@@ -2,18 +2,59 @@ package cmd
22
33import (
44 "fmt"
5+ "os"
56
67 "github.com/seqra/opentaint/internal/output"
78 "github.com/seqra/opentaint/internal/utils"
89 "github.com/spf13/cobra"
910)
1011
1112var (
12- pruneDryRun bool
13- pruneYes bool
14- pruneIncLogs bool
13+ pruneDryRun bool
14+ pruneYes bool
15+ pruneAll bool
16+ pruneArtifacts bool
17+ pruneRules bool
18+ pruneJDK bool
19+ pruneModels bool
20+ pruneLogs bool
21+ pruneInstall bool
1522)
1623
24+ // resolveCategories maps CLI flags to a PruneCategory bitmask.
25+ // Returns an error if --all is combined with specific flags.
26+ func resolveCategories () (utils.PruneCategory , error ) {
27+ specific := pruneArtifacts || pruneRules || pruneJDK || pruneModels || pruneLogs || pruneInstall
28+ if pruneAll && specific {
29+ return 0 , fmt .Errorf ("--all cannot be combined with specific category flags (--artifacts, --rules, --jdk, --models, --logs, --install)" )
30+ }
31+ if pruneAll {
32+ return utils .PruneCategoriesAll , nil
33+ }
34+ if ! specific {
35+ return utils .PruneCategoriesDefault , nil
36+ }
37+
38+ flagMap := []struct {
39+ flag * bool
40+ cat utils.PruneCategory
41+ }{
42+ {& pruneArtifacts , utils .PruneCategoryArtifacts },
43+ {& pruneRules , utils .PruneCategoryRules },
44+ {& pruneJDK , utils .PruneCategoryJDK },
45+ {& pruneModels , utils .PruneCategoryModels },
46+ {& pruneLogs , utils .PruneCategoryLogs },
47+ {& pruneInstall , utils .PruneCategoryInstall },
48+ }
49+ var cats utils.PruneCategory
50+ for _ , f := range flagMap {
51+ if * f .flag {
52+ cats |= f .cat
53+ }
54+ }
55+ return cats , nil
56+ }
57+
1758var pruneCmd = & cobra.Command {
1859 Use : "prune" ,
1960 Short : "Remove stale downloaded artifacts from ~/.opentaint" ,
@@ -22,16 +63,59 @@ var pruneCmd = &cobra.Command{
2263Identifies artifacts that are no longer needed:
2364- Old versions of analyzer JARs, autobuilder JARs, and rules
2465- Downloaded JDK/JRE versions that don't match the current version
25- - Redundant downloads when bundled artifacts are available
26- - Stale install-tier artifacts (~/.opentaint/install/) after a opentaint upgrade
66+ - Cached project models and staging directories
67+
68+ Use category flags to prune selectively:
69+ --artifacts Stale analyzer and autobuilder JARs
70+ --rules Stale rules directories
71+ --jdk Old JDK/JRE versions
72+ --models Cached project models and staging directories
73+ --logs Project log files
74+ --install Install-tier lib and JRE artifacts (requires re-download)
2775
28- By default, log files are kept. Use --include-logs to also prune them from project cache directories.` ,
76+ Without category flags, prunes: artifacts + rules + jdk + models.
77+ With --all: prunes everything including logs and install-tier.` ,
2978 Run : func (cmd * cobra.Command , args []string ) {
30- result , err := utils .ScanForStaleArtifacts (pruneIncLogs )
79+ categories , err := resolveCategories ()
80+ if err != nil {
81+ out .FatalErr (err )
82+ }
83+
84+ // Acquire global prune lock
85+ pruneLockPath , err := utils .PruneLockPath ()
86+ if err != nil {
87+ out .Fatalf ("Failed to resolve prune lock path: %s" , err )
88+ }
89+ pruneLock , err := utils .TryLock (pruneLockPath , utils.LockMeta {
90+ PID : os .Getpid (),
91+ Command : "prune" ,
92+ })
93+ if err == utils .ErrLocked {
94+ out .Fatal ("Another prune is already running" )
95+ }
96+ if err != nil {
97+ out .Fatalf ("Failed to acquire prune lock: %s" , err )
98+ }
99+ defer pruneLock .Unlock ()
100+
101+ result , err := utils .ScanForStaleArtifacts (categories )
31102 if err != nil {
32103 out .Fatalf ("Failed to scan for stale artifacts: %s" , err )
33104 }
34105
106+ // Display skipped projects
107+ if len (result .Skipped ) > 0 {
108+ sb := out .Section ("Skipped (compilation in progress)" )
109+ for _ , s := range result .Skipped {
110+ if s .Meta .PID != 0 {
111+ sb .Text (fmt .Sprintf ("%s (locked by PID %d)" , s .Path , s .Meta .PID ))
112+ } else {
113+ sb .Text (fmt .Sprintf ("%s (locked)" , s .Path ))
114+ }
115+ }
116+ sb .Render ()
117+ }
118+
35119 if result .TotalCount == 0 {
36120 out .Print ("No stale artifacts found. Nothing to prune." )
37121 return
@@ -70,5 +154,11 @@ func init() {
70154
71155 pruneCmd .Flags ().BoolVar (& pruneDryRun , "dry-run" , false , "Show what would be deleted without deleting" )
72156 pruneCmd .Flags ().BoolVar (& pruneYes , "yes" , false , "Skip interactive confirmation" )
73- pruneCmd .Flags ().BoolVar (& pruneIncLogs , "include-logs" , false , "Also prune log files" )
157+ pruneCmd .Flags ().BoolVar (& pruneAll , "all" , false , "Prune everything including logs and install-tier artifacts" )
158+ pruneCmd .Flags ().BoolVar (& pruneArtifacts , "artifacts" , false , "Prune stale analyzer and autobuilder JARs" )
159+ pruneCmd .Flags ().BoolVar (& pruneRules , "rules" , false , "Prune stale rules directories" )
160+ pruneCmd .Flags ().BoolVar (& pruneJDK , "jdk" , false , "Prune old JDK/JRE versions" )
161+ pruneCmd .Flags ().BoolVar (& pruneModels , "models" , false , "Prune cached project models and staging directories" )
162+ pruneCmd .Flags ().BoolVar (& pruneLogs , "logs" , false , "Prune project log files" )
163+ pruneCmd .Flags ().BoolVar (& pruneInstall , "install" , false , "Prune install-tier lib and JRE artifacts (requires re-download on next run)" )
74164}
0 commit comments