-
Notifications
You must be signed in to change notification settings - Fork 1
/
clean.go
158 lines (139 loc) · 3.48 KB
/
clean.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package main
import (
"flag"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
)
const Version = "1.3"
const HelpText = `NAME
clean - The quick little project cleaner.
SYNOPSIS
clean [options] [dir]
DESCRIPTION
Recursively cleans compiled output files within a directory. Specify language
modes using [options]; if omitted all language modes are cleaned. Specify a
directory [dir]; if omitted the current directory is used.
For sake of speed, certain directories are never cleaned such as Python
virtual envs, node_modules, or any hidden/dot directories.
Source code at: https://github.com/vsalvino/clean
OPTIONS
`
func main() {
// Parse command line options.
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), HelpText)
flag.PrintDefaults()
}
var c_a bool = false
var c_cc = flag.Bool(
"cc", false, "Clean compiled output (.exe, .dll, .o, .out, .so) etc.")
var c_ed = flag.Bool(
"ed", false, "Clean editor cruft (Emacs backups, etc.)")
var c_py = flag.Bool(
"py", false, "Clean Python __pycache__ directories.")
var c_x = flag.String(
"x", "", "Clean files ending with provided extension (e.g. \".elc\").")
var ver = flag.Bool(
"version", false, "Print version and exit.")
flag.Parse()
var dir string = flag.Arg(0)
var err error
// Print version if specified.
if *ver {
fmt.Printf("clean version %s", Version)
os.Exit(0)
}
// If no flags provided, use all.
c_a = !(*c_cc || *c_ed || *c_py || *c_x != "")
// Process provided directory.
if dir == "" {
// If dir is not provided, get working directory.
dir, err = os.Getwd()
} else {
// Get absolute path of what the user provided.
dir, err = filepath.Abs(dir)
}
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// Walk the path and clean files.
err = filepath.WalkDir(
dir,
func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
// Check if dir/file needs cleaned.
n := d.Name()
var delete bool = false
if *c_py || c_a {
// Python.
if n == "__pycache__" ||
strings.HasSuffix(n, ".pyc") {
delete = true
}
}
if *c_ed || c_a {
// Emacs backups.
if strings.HasSuffix(n, "~") ||
(strings.HasPrefix(n, "#") && strings.HasSuffix(n, "#")) {
delete = true
}
}
if *c_cc || c_a {
// Compiled output.
if strings.HasSuffix(n, ".app") ||
strings.HasSuffix(n, ".dll") ||
strings.HasSuffix(n, ".dylib") ||
strings.HasSuffix(n, ".exe") ||
strings.HasSuffix(n, ".idb") ||
strings.HasSuffix(n, ".ko") ||
strings.HasSuffix(n, ".o") ||
strings.HasSuffix(n, ".obj") ||
strings.HasSuffix(n, ".out") ||
strings.HasSuffix(n, ".pdb") ||
strings.HasSuffix(n, ".so") ||
strings.HasSuffix(n, ".test") {
delete = true
}
}
if *c_x != "" {
if strings.HasSuffix(n, *c_x) {
delete = true
}
}
// Remove the file if so.
if delete {
fmt.Printf("Remove %s\n", path)
err = os.RemoveAll(path)
if err != nil {
fmt.Printf(" Error: %s\n", err)
}
// If we just deleted a directory, do not try to walk it.
if d.IsDir() {
return filepath.SkipDir
}
}
// Do not walk dirs we don't care about, unless it was the provided
// root dir.
if d.IsDir() && path != dir {
if strings.HasPrefix(n, ".") ||
n == "env" ||
n == "venv" ||
n == "pyenv" ||
n == "node_modules" {
return filepath.SkipDir
}
}
return nil
},
)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}