Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit 12a1b64

Browse files
committed
internal/gps: update prune functions to use in-memory filesystemState
This commit update prune functions to use filesystemState instead of repeated walks over the filesyste. strip_vendor functions still walk the filesystem and will be updated in a later commit. Signed-off-by: Ibrahim AshShohail <[email protected]>
1 parent c460889 commit 12a1b64

6 files changed

+384
-329
lines changed

hack/lint.bash

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ set -e
99
PKGS=$(go list ./... | grep -vF /vendor/)
1010
go vet $PKGS
1111
golint $PKGS
12-
megacheck -unused.exported -ignore "github.com/golang/dep/internal/test/test.go:U1000 github.com/golang/dep/internal/gps/prune.go:U1000" $PKGS
12+
megacheck -unused.exported -ignore "github.com/golang/dep/internal/test/test.go:U1000" $PKGS

internal/gps/prune.go

+111-143
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type PruneOptions uint8
1818

1919
const (
2020
// PruneNestedVendorDirs indicates if nested vendor directories should be pruned.
21-
PruneNestedVendorDirs = 1 << iota
21+
PruneNestedVendorDirs PruneOptions = 1 << iota
2222
// PruneUnusedPackages indicates if unused Go packages should be pruned.
2323
PruneUnusedPackages
2424
// PruneNonGoFiles indicates if non-Go files should be pruned.
@@ -57,12 +57,13 @@ var (
5757
// on the PruneOptions passed.
5858
//
5959
// A Lock must be passed if PruneUnusedPackages is toggled on.
60-
func Prune(baseDir string, options PruneOptions, l Lock, logger *log.Logger) error {
60+
func Prune(baseDir string, l Lock, options PruneOptions, logger *log.Logger) error {
6161
// TODO(ibrasho) allow passing specific options per project
62+
6263
for _, lp := range l.Projects() {
6364
projectDir := filepath.Join(baseDir, string(lp.Ident().ProjectRoot))
64-
err := PruneProject(projectDir, lp, options, logger)
65-
if err != nil {
65+
66+
if err := PruneProject(projectDir, lp, options, logger); err != nil {
6667
return err
6768
}
6869
}
@@ -73,28 +74,31 @@ func Prune(baseDir string, options PruneOptions, l Lock, logger *log.Logger) err
7374
// PruneProject remove excess files according to the options passed, from
7475
// the lp directory in baseDir.
7576
func PruneProject(baseDir string, lp LockedProject, options PruneOptions, logger *log.Logger) error {
76-
projectDir := filepath.Join(baseDir, string(lp.Ident().ProjectRoot))
77+
fs, err := deriveFilesystemState(baseDir)
78+
if err != nil {
79+
return errors.Wrap(err, "could not derive filesystem state")
80+
}
7781

7882
if (options & PruneNestedVendorDirs) != 0 {
79-
if err := pruneNestedVendorDirs(projectDir); err != nil {
83+
if err := pruneNestedVendorDirs(baseDir); err != nil {
8084
return err
8185
}
8286
}
8387

8488
if (options & PruneUnusedPackages) != 0 {
85-
if err := pruneUnusedPackages(lp, projectDir, logger); err != nil {
89+
if err := pruneUnusedPackages(lp, fs, logger); err != nil {
8690
return errors.Wrap(err, "failed to prune unused packages")
8791
}
8892
}
8993

9094
if (options & PruneNonGoFiles) != 0 {
91-
if err := pruneNonGoFiles(projectDir, logger); err != nil {
95+
if err := pruneNonGoFiles(fs, logger); err != nil {
9296
return errors.Wrap(err, "failed to prune non-Go files")
9397
}
9498
}
9599

96100
if (options & PruneGoTestFiles) != 0 {
97-
if err := pruneGoTestFiles(projectDir, logger); err != nil {
101+
if err := pruneGoTestFiles(fs, logger); err != nil {
98102
return errors.Wrap(err, "failed to prune Go test files")
99103
}
100104
}
@@ -107,152 +111,141 @@ func pruneNestedVendorDirs(baseDir string) error {
107111
return filepath.Walk(baseDir, stripVendor)
108112
}
109113

110-
// pruneUnusedPackages deletes unimported packages found within baseDir.
114+
// pruneVendorDirs deletes all nested vendor directories within baseDir.
115+
// func pruneVendorDirs(fs filesystemState, logger *log.Logger) error {
116+
// toDelete := collectNestedVendorDirs(fs)
117+
118+
// for _, path := range toDelete {
119+
// logger.Printf(" * %s", path)
120+
121+
// if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
122+
// return err
123+
// }
124+
// }
125+
126+
// return nil
127+
// }
128+
129+
// func collectNestedVendorDirs(fs filesystemState) []string {
130+
// toDelete := make([]string, 0, len(fs.dirs)/4)
131+
132+
// for _, dir := range fs.dirs {
133+
// if filepath.Base(dir)
134+
// toDelete = append(toDelete, dir)
135+
// }
136+
137+
// for _, link := range fs.links {
138+
// toDelete = append(toDelete)
139+
// }
140+
141+
// return files
142+
// }
143+
144+
// pruneUnusedPackages deletes unimported packages found in fs.
111145
// Determining whether packages are imported or not is based on the passed LockedProject.
112-
func pruneUnusedPackages(lp LockedProject, projectDir string, logger *log.Logger) error {
146+
func pruneUnusedPackages(lp LockedProject, fs filesystemState, logger *log.Logger) error {
113147
pr := string(lp.Ident().ProjectRoot)
114-
logger.Printf("Calculating unused packages in %s to prune.\n", pr)
148+
unusedPackages := calculateUnusedPackages(lp, fs)
115149

116-
unusedPackages, err := calculateUnusedPackages(lp, projectDir)
117-
if err != nil {
118-
return errors.Wrapf(err, "could not calculate unused packages in %s", pr)
119-
}
150+
logger.Printf("Found %d unused packages in %s:\n", len(unusedPackages), pr)
120151

121-
logger.Printf("Found the following unused packages in %s:\n", pr)
122152
for pkg := range unusedPackages {
123153
logger.Printf(" * %s\n", filepath.Join(pr, pkg))
124154
}
125155

126-
unusedPackagesFiles, err := collectUnusedPackagesFiles(projectDir, unusedPackages)
127-
if err != nil {
128-
return errors.Wrapf(err, "could not collect unused packages' files in %s", pr)
129-
}
156+
toDelete := collectUnusedPackagesFiles(fs, unusedPackages)
157+
158+
logger.Printf("Deleting %d files in unused packages:", len(toDelete))
130159

131-
if err := deleteFiles(unusedPackagesFiles); err != nil {
132-
return errors.Wrapf(err, "")
160+
for _, path := range toDelete {
161+
logger.Printf(" * %s\n", path)
162+
163+
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
164+
return err
165+
}
133166
}
134167

135168
return nil
136169
}
137170

138171
// calculateUnusedPackages generates a list of unused packages in lp.
139-
func calculateUnusedPackages(lp LockedProject, projectDir string) (map[string]struct{}, error) {
140-
// TODO(ibrasho): optimize this...
172+
func calculateUnusedPackages(lp LockedProject, fs filesystemState) map[string]struct{} {
141173
unused := make(map[string]struct{})
142174
imported := make(map[string]struct{})
175+
143176
for _, pkg := range lp.Packages() {
144177
imported[pkg] = struct{}{}
145178
}
146179

147-
err := filepath.Walk(projectDir, func(path string, info os.FileInfo, err error) error {
148-
if err != nil {
149-
return err
150-
}
151-
152-
// Ignore anything that's not a directory.
153-
if !info.IsDir() {
154-
return nil
155-
}
180+
// Add the root package if it's not imported.
181+
if _, ok := imported["."]; !ok {
182+
unused["."] = struct{}{}
183+
}
156184

157-
pkg, err := filepath.Rel(projectDir, path)
158-
if err != nil {
159-
return errors.Wrap(err, "unexpected error while calculating unused packages")
160-
}
185+
for _, dirPath := range fs.dirs {
186+
pkg := filepath.ToSlash(dirPath)
161187

162-
pkg = filepath.ToSlash(pkg)
163188
if _, ok := imported[pkg]; !ok {
164189
unused[pkg] = struct{}{}
165190
}
191+
}
166192

167-
return nil
168-
})
169-
170-
return unused, err
193+
return unused
171194
}
172195

173-
// collectUnusedPackagesFiles returns a slice of all files in the unused packages in projectDir.
174-
func collectUnusedPackagesFiles(projectDir string, unusedPackages map[string]struct{}) ([]string, error) {
196+
// collectUnusedPackagesFiles returns a slice of all files in the unused packages based on fs.
197+
func collectUnusedPackagesFiles(fs filesystemState, unusedPackages map[string]struct{}) []string {
175198
// TODO(ibrasho): is this useful?
176199
files := make([]string, 0, len(unusedPackages))
177200

178-
err := filepath.Walk(projectDir, func(path string, info os.FileInfo, err error) error {
179-
if err != nil {
180-
return err
201+
for _, path := range fs.files {
202+
// Keep perserved files.
203+
if isPreservedFile(filepath.Base(path)) {
204+
continue
181205
}
182206

183-
// Ignore directories.
184-
if info.IsDir() {
185-
return nil
186-
}
207+
pkg := filepath.ToSlash(filepath.Dir(path))
187208

188-
// Ignore perserved files.
189-
if isPreservedFile(info.Name()) {
190-
return nil
191-
}
192-
193-
pkg, err := filepath.Rel(projectDir, filepath.Dir(path))
194-
if err != nil {
195-
return errors.Wrap(err, "unexpected error while calculating unused packages")
196-
}
197-
198-
pkg = filepath.ToSlash(pkg)
199209
if _, ok := unusedPackages[pkg]; ok {
200-
files = append(files, path)
210+
files = append(files, filepath.Join(fs.root, path))
201211
}
212+
}
202213

203-
return nil
204-
})
205-
206-
return files, err
214+
return files
207215
}
208216

209-
// pruneNonGoFiles delete all non-Go files existing within baseDir.
217+
// pruneNonGoFiles delete all non-Go files existing in fs.
210218
// Files with names that are prefixed by any entry in preservedNonGoFiles
211219
// are not deleted.
212-
func pruneNonGoFiles(baseDir string, logger *log.Logger) error {
213-
files, err := collectNonGoFiles(baseDir, logger)
214-
if err != nil {
215-
return errors.Wrap(err, "could not collect non-Go files")
216-
}
217-
218-
if err := deleteFiles(files); err != nil {
219-
return errors.Wrap(err, "could not prune Go test files")
220-
}
221-
222-
return nil
223-
}
224-
225-
// collectNonGoFiles returns a slice containing all non-Go files in baseDir.
226-
// Files meeting the checks in isPreservedFile are not returned.
227-
func collectNonGoFiles(baseDir string, logger *log.Logger) ([]string, error) {
228-
files := make([]string, 0)
229-
230-
err := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
231-
if err != nil {
232-
return err
220+
func pruneNonGoFiles(fs filesystemState, logger *log.Logger) error {
221+
// TODO(ibrasho) detemine a sane capacity
222+
toDelete := make([]string, 0, len(fs.files)/4)
223+
224+
for _, path := range fs.files {
225+
// Ignore Go files.
226+
if strings.HasSuffix(path, ".go") {
227+
continue
233228
}
234229

235-
// Ignore directories.
236-
if info.IsDir() {
237-
return nil
230+
// Ignore perserved files.
231+
if isPreservedFile(filepath.Base(path)) {
232+
continue
238233
}
239234

240-
// Ignore all Go files.
241-
if strings.HasSuffix(info.Name(), ".go") {
242-
return nil
243-
}
235+
toDelete = append(toDelete, filepath.Join(fs.root, path))
236+
}
244237

245-
// Ignore perserved files.
246-
if isPreservedFile(info.Name()) {
247-
return nil
248-
}
238+
logger.Printf("Deleting %d non-Go files:\n", len(toDelete))
249239

250-
files = append(files, path)
240+
for _, path := range toDelete {
241+
logger.Printf(" * %s\n", path)
251242

252-
return nil
253-
})
243+
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
244+
return err
245+
}
246+
}
254247

255-
return files, err
248+
return nil
256249
}
257250

258251
// isPreservedFile checks if the file name indicates that the file should be
@@ -275,51 +268,26 @@ func isPreservedFile(name string) bool {
275268
return false
276269
}
277270

278-
// pruneGoTestFiles deletes all Go test files (*_test.go) within baseDir.
279-
func pruneGoTestFiles(baseDir string, logger *log.Logger) error {
280-
files, err := collectGoTestFiles(baseDir)
281-
if err != nil {
282-
return errors.Wrap(err, "could not collect Go test files")
283-
}
284-
285-
if err := deleteFiles(files); err != nil {
286-
return errors.Wrap(err, "could not prune Go test files")
287-
}
288-
289-
return nil
290-
}
291-
292-
// collectGoTestFiles returns a slice contains all Go test files (any files
293-
// prefixed with _test.go) in baseDir.
294-
func collectGoTestFiles(baseDir string) ([]string, error) {
295-
files := make([]string, 0)
271+
// pruneGoTestFiles deletes all Go test files (*_test.go) in fs.
272+
func pruneGoTestFiles(fs filesystemState, logger *log.Logger) error {
273+
// TODO(ibrasho) detemine a sane capacity
274+
toDelete := make([]string, 0, len(fs.files)/2)
296275

297-
err := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
298-
if err != nil {
299-
return err
300-
}
301-
302-
// Ignore directories.
303-
if info.IsDir() {
304-
return nil
305-
}
306-
307-
// Ignore any files that is not a Go test file.
308-
if strings.HasSuffix(info.Name(), "_test.go") {
309-
files = append(files, path)
276+
for _, path := range fs.files {
277+
if strings.HasSuffix(path, "_test.go") {
278+
toDelete = append(toDelete, filepath.Join(fs.root, path))
310279
}
280+
}
311281

312-
return nil
313-
})
282+
logger.Printf("Deleting %d Go test files:\n", len(toDelete))
314283

315-
return files, err
316-
}
284+
for _, path := range toDelete {
285+
logger.Printf(" * %s\n", path)
317286

318-
func deleteFiles(paths []string) error {
319-
for _, path := range paths {
320-
if err := os.Remove(path); err != nil {
287+
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
321288
return err
322289
}
323290
}
291+
324292
return nil
325293
}

0 commit comments

Comments
 (0)