-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
122 lines (104 loc) · 2.75 KB
/
main.go
File metadata and controls
122 lines (104 loc) · 2.75 KB
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
package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"path/filepath"
"time"
"github.com/dotcommander/repoclean/internal/cleanup"
)
func main() {
path := flag.String("path", ".", "directory to scan")
maxDepth := flag.Int("max-depth", 5, "maximum directory depth")
staleDays := flag.Int("stale-days", 90, "days before a file is considered stale")
report := flag.Bool("report", false, "output human-readable cleanup plan instead of JSON")
findings := flag.Bool("findings", false, "output findings-focused view grouped by signal")
execMode := flag.Bool("exec", false, "output shell commands for automated execution")
apply := flag.Bool("apply", false, "dry-run: show commands that would execute (add --confirm to run)")
confirm := flag.Bool("confirm", false, "actually execute commands (requires --apply)")
missing := flag.Bool("missing", false, "check repo completeness (missing LICENSE, CI, etc.)")
flag.Parse()
absPath, err := filepath.Abs(*path)
if err != nil {
log.Fatalf("repoclean: resolve path: %v", err)
}
cfg := cleanup.Config{
Path: absPath,
MaxDepth: *maxDepth,
StaleDays: *staleDays,
}
cfg.Rules = cleanup.LoadRules()
start := time.Now()
files, err := cleanup.Walk(cfg)
if err != nil {
log.Fatalf("repoclean: walk: %v", err)
}
if elapsed := time.Since(start); elapsed > 5*time.Second {
log.Printf("repoclean: walk took %v (large repo?)", elapsed)
}
if *missing {
cr := cleanup.CheckCompleteness(files)
cr.Path = absPath
printMissing(cr)
return
}
if err := cleanup.Enrich(files, cfg); err != nil {
log.Printf("repoclean: enrich warning: %v", err)
}
if err := cleanup.Classify(files); err != nil {
log.Printf("repoclean: classify warning: %v", err)
}
cleanup.FindDuplicates(files)
cleanup.EmitFindings(files)
result := cleanup.Categorize(files, cfg)
result.Path = absPath
if *confirm && !*apply {
log.Fatal("repoclean: --confirm requires --apply")
}
if *apply {
cmds := buildCommands(result)
if len(cmds) == 0 {
fmt.Println("nothing to clean up")
return
}
if *confirm {
if err := runCommands(cmds, absPath); err != nil {
log.Fatalf("repoclean: apply: %v", err)
}
} else {
dryRun(cmds)
}
return
}
if *execMode {
printExec(result)
return
}
if *findings {
printFindings(files)
return
}
if *report {
printReport(result)
return
}
out, err := json.MarshalIndent(result, "", " ")
if err != nil {
log.Fatalf("repoclean: marshal: %v", err)
}
fmt.Println(string(out))
}
func fmtSize(kb int64) string {
b := float64(kb) * 1024
const unit = 1024
if b < unit {
return fmt.Sprintf("%dB", int64(b))
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f%cB", b/float64(div), "KMGTPE"[exp])
}