forked from Masterminds/glide
/
delete.go
110 lines (91 loc) · 2.52 KB
/
delete.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
package cmd
import (
"errors"
"os"
"path/filepath"
"strings"
"github.com/Masterminds/cookoo"
"github.com/Masterminds/glide/yaml"
)
// DeleteUnusedPackages removes packages from vendor/ that are no longer used.
func DeleteUnusedPackages(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
// Conditional opt-in to removed unused dependencies.
optIn := p.Get("optIn", false).(bool)
if optIn != true {
return nil, nil
}
vpath, err := VendorPath(c)
if err != nil {
return nil, err
}
if vpath == "" {
return false, errors.New("Vendor not set")
}
// Build directory tree of what to keep.
cfg := p.Get("conf", nil).(*yaml.Config)
var pkgList []string
for _, dep := range cfg.Imports {
pkgList = append(pkgList, dep.Name)
}
// Callback function for filepath.Walk to delete packages not in yaml file.
var searchPath string
var markForDelete []string
fn := func(path string, info os.FileInfo, err error) error {
// Bubble up the error
if err != nil {
return err
}
if info.IsDir() == false || path == searchPath || path == vpath {
return nil
}
localPath := strings.TrimPrefix(path, searchPath)
keep := false
// First check if the path has a prefix that's a specific package. If
// so we keep it to keep the package.
for _, name := range pkgList {
if strings.HasPrefix(localPath, name) {
keep = true
}
}
// If a package is, for example, github.com/Masterminds/glide the
// previous look will not mark the directories github.com or
// github.com/Masterminds to keep. Here we see if these names prefix
// and packages we know about to mark as keepers.
if keep == false {
for _, name := range pkgList {
if strings.HasPrefix(name, localPath) {
keep = true
}
}
}
// If the parent directory has already been marked for delete this
// directory doesn't need to be marked.
for _, markedDirectory := range markForDelete {
if strings.HasPrefix(path, markedDirectory) {
return nil
}
}
// Remove the directory if we are not keeping it.
if keep == false {
// Mark for deletion
markForDelete = append(markForDelete, path)
}
return nil
}
// Walk vendor directory
searchPath = vpath + "/"
err = filepath.Walk(searchPath, fn)
if err != nil {
return false, err
}
// Perform the actual delete.
for _, path := range markForDelete {
localPath := strings.TrimPrefix(path, searchPath)
Info("Removing unused package: %s\n", localPath)
rerr := os.RemoveAll(path)
if rerr != nil {
return false, rerr
}
}
return nil, nil
}