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

Commit

Permalink
internal/gps: add pruneProject func
Browse files Browse the repository at this point in the history
Signed-off-by: Ibrahim AshShohail <[email protected]>
  • Loading branch information
ibrasho committed Sep 2, 2017
1 parent e4c3218 commit 9bd639a
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 305 deletions.
235 changes: 83 additions & 152 deletions internal/gps/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"sort"
"strings"

"github.com/golang/dep/internal/fs"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -58,17 +57,29 @@ var (
//
// A Lock must be passed if PruneUnusedPackages is toggled on.
func Prune(baseDir string, options PruneOptions, l Lock, logger *log.Logger) error {
// TODO(ibrasho) allow passing specific options per project
for _, lp := range l.Projects() {
projectDir := filepath.Join(baseDir, string(lp.Ident().ProjectRoot))
err := pruneProject(projectDir, lp, options, logger)
if err != nil {
return err
}
}

return nil
}

// pruneProject remove excess files according to the options passed, from
// the lp directory in baseDir.
func pruneProject(baseDir string, lp LockedProject, options PruneOptions, logger *log.Logger) error {
if (options & PruneNestedVendorDirs) != 0 {
if err := pruneNestedVendorDirs(baseDir); err != nil {
return err
}
}

if (options & PruneUnusedPackages) != 0 {
if l == nil {
return errors.New("pruning unused packages requires passing a non-nil Lock")
}
if err := pruneUnusedPackages(baseDir, l, logger); err != nil {
if err := pruneUnusedPackages(baseDir, lp, logger); err != nil {
return errors.Wrap(err, "failed to prune unused packages")
}
}
Expand All @@ -85,39 +96,25 @@ func Prune(baseDir string, options PruneOptions, l Lock, logger *log.Logger) err
}
}

// Delete all empty directories.
if err := pruneEmptyDirs(baseDir, logger); err != nil {
return errors.Wrap(err, "failed to prune empty dirs")
}

return nil
}

// pruneNestedVendorDirs deletes all nested vendor directories within baseDir.
func pruneNestedVendorDirs(baseDir string) error {
return filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
return nil
}

// Ignore the base vendor directory.
if path == baseDir {
return nil
}

if err := filepath.Walk(path, stripVendor); err != nil {
return err
}

// Don't walk into directories again.
return filepath.SkipDir
})
return filepath.Walk(baseDir, stripVendor)
}

// pruneUnusedPackages deletes unimported packages found within baseDir.
// Determining whether packages are imported or not is based on the passed Lock.
func pruneUnusedPackages(baseDir string, l Lock, logger *log.Logger) error {
unused, err := calculateUnusedPackages(baseDir, l, logger)
func pruneUnusedPackages(baseDir string, lp LockedProject, logger *log.Logger) error {
if logger != nil {
logger.Printf("Calculating unused packages in %s to prune.\n", lp.Ident().ProjectRoot)
logger.Println("Checking the following packages:")
}

var unused []string

err := filepath.Walk(baseDir, findUnusedPackages(lp, unused, baseDir, logger))
if err != nil {
return err
}
Expand Down Expand Up @@ -148,20 +145,45 @@ func pruneUnusedPackages(baseDir string, l Lock, logger *log.Logger) error {
return nil
}

// calculateUnusedPackages generates a list of unused packages existing within
// baseDir depending on the imported packages found in the passed Lock.
func calculateUnusedPackages(baseDir string, l Lock, logger *log.Logger) ([]string, error) {
imported := calculateImportedPackages(l)
sort.Strings(imported)

var unused []string
// pruneNonGoFiles delete all non-Go files existing within baseDir.
// Files with names that are prefixed by any entry in preservedNonGoFiles
// are not deleted.
func pruneNonGoFiles(baseDir string, logger *log.Logger) error {
var files []string

if logger != nil {
logger.Println("Calculating unused packages to prune.")
logger.Println("Checking the following packages:")
err := filepath.Walk(baseDir, findNonGoFiles(files))
if err != nil {
return errors.Wrap(err, "could not prune non-Go files")
}

err := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
return deleteFiles(files)
}

// pruneGoTestFiles deletes all Go test files (*_test.go) within baseDir.
func pruneGoTestFiles(baseDir string, logger *log.Logger) error {
filesCh := make(chan string)

var err error
go func() {
if walkErr := filepath.Walk(baseDir, findGoTestsFile(filesCh)); err != nil {
err = errors.Wrap(walkErr, "could not prune Go test files")
close(filesCh)
}
}()

go func() {
err = deleteFilesCh(filesCh)
}()

return err
}

// findUnusedPackages generates a list of unused packages in lp.
func findUnusedPackages(lp LockedProject, unused []string, baseDir string, logger *log.Logger) filepath.WalkFunc {
imported := lp.Packages()
sort.Strings(imported)

return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
Expand All @@ -176,8 +198,7 @@ func calculateUnusedPackages(baseDir string, l Lock, logger *log.Logger) ([]stri
logger.Printf(" %s", pkg)
}

// If pkg is not a parent of an imported package, add it to the
// unused list.
// If pkg is not a parent of an imported package, add it to the unused list.
i := sort.Search(len(imported), func(i int) bool {
return pkg <= imported[i]
})
Expand All @@ -186,44 +207,14 @@ func calculateUnusedPackages(baseDir string, l Lock, logger *log.Logger) ([]stri
}

return nil
})

return unused, err
}

// calculateImportedPackages generates a list of imported packages from
// the passed Lock.
func calculateImportedPackages(l Lock) []string {
var imported []string

for _, project := range l.Projects() {
projectRoot := string(project.Ident().ProjectRoot)
for _, pkg := range project.Packages() {
imported = append(imported, filepath.Join(projectRoot, pkg))
}
}
return imported
}

// pruneNonGoFiles delete all non-Go files existing within baseDir.
// Files with names that are prefixed by any entry in preservedNonGoFiles
// are not deleted.
func pruneNonGoFiles(baseDir string, logger *log.Logger) error {
files, err := calculateNonGoFiles(baseDir)
if err != nil {
return errors.Wrap(err, "could not prune non-Go files")
}

return deleteFiles(files)
}

// calculateNonGoFiles returns a list of all non-Go files within baseDir.
// Files with names that are prefixed by any entry in preservedNonGoFiles
// are not deleted.
func calculateNonGoFiles(baseDir string) ([]string, error) {
var files []string

err := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
// findNonGoFiles returns a WalkFunc that appends all non-Go files to the
// passed slice.
// Files passing the checks in isPreservedNonGoFile are not appended.
func findNonGoFiles(files []string) filepath.WalkFunc {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
Expand All @@ -243,13 +234,13 @@ func calculateNonGoFiles(baseDir string) ([]string, error) {
}

return nil
})

return files, err
}
}

// isPreservedNonGoFile checks if the file name idicates that the file should be
// preserved. It assumes the file is not a Go file (doesn't have a .go suffix).
// It checks if the file name contains one of the prefixes in licenseFilePrefixes
// or contains one of the legalFileSubstrings entries.
func isPreservedNonGoFile(name string) bool {
name = strings.ToLower(name)

Expand All @@ -268,22 +259,10 @@ func isPreservedNonGoFile(name string) bool {
return false
}

// pruneGoTestFiles deletes all Go test files (*_test.go) within baseDir.
func pruneGoTestFiles(baseDir string, logger *log.Logger) error {
files, err := calculateGoTestFiles(baseDir)
if err != nil {
return errors.Wrap(err, "could not prune Go test files")
}

return deleteFiles(files)
}

// calculateGoTestFiles walks over baseDir and returns a list of all
// Go test files (any file that has the name *_test.go).
func calculateGoTestFiles(baseDir string) ([]string, error) {
var files []string

err := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
// findGoTestsFile returns a WalkFunc that appends Go test files (any files
// prefixed with _test.go) to the passed slice.
func findGoTestsFile(filesCh chan string) filepath.WalkFunc {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
Expand All @@ -294,73 +273,25 @@ func calculateGoTestFiles(baseDir string) ([]string, error) {
}

// Ignore any files that is not a Go test file.
if !strings.HasSuffix(info.Name(), "_test.go") {
return nil
if strings.HasSuffix(info.Name(), "_test.go") {
filesCh <- path
}

files = append(files, path)

return nil
})

return files, err
}

// pruneEmptyDirs delete all empty directories within baseDir.
func pruneEmptyDirs(baseDir string, logger *log.Logger) error {
empty, err := calculateEmptyDirs(baseDir)
if err != nil {
return err
}

if logger != nil {
logger.Println("Deleting empty directories:")
}
}

for _, dir := range empty {
if logger != nil {
logger.Printf(" %s\n", strings.TrimPrefix(dir, baseDir+string(os.PathSeparator)))
}
if err := os.Remove(dir); err != nil {
func deleteFiles(paths []string) error {
for _, path := range paths {
if err := os.Remove(path); err != nil {
return err
}
}

return nil
}

// calculateEmptyDirs walks over baseDir and returns a slice of empty directory paths.
func calculateEmptyDirs(baseDir string) ([]string, error) {
var empty []string

err := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil
}

if baseDir == path {
return nil
}

if !info.IsDir() {
return nil
}

nonEmpty, err := fs.IsNonEmptyDir(path)
if err != nil {
return err
} else if !nonEmpty {
empty = append(empty, path)
}

return nil
})

return empty, err
}

func deleteFiles(paths []string) error {
for _, path := range paths {
func deleteFilesCh(paths chan string) error {
for path := range paths {
if err := os.Remove(path); err != nil {
return err
}
Expand Down
Loading

0 comments on commit 9bd639a

Please sign in to comment.