github.com/anthonymayer/glide@v0.0.0-20160224162501-bff8b50d232e/dependency/delete.go (about)

     1  package dependency
     2  
     3  import (
     4  	"errors"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/Masterminds/glide/cfg"
    10  	"github.com/Masterminds/glide/msg"
    11  	gpath "github.com/Masterminds/glide/path"
    12  )
    13  
    14  // DeleteUnused removes packages from vendor/ that are no longer used.
    15  //
    16  // TODO: This should work off of a Lock file, not glide.yaml.
    17  func DeleteUnused(conf *cfg.Config) error {
    18  	vpath, err := gpath.Vendor()
    19  	if err != nil {
    20  		return err
    21  	}
    22  	if vpath == "" {
    23  		return errors.New("Vendor not set")
    24  	}
    25  
    26  	// Build directory tree of what to keep.
    27  	var pkgList []string
    28  	for _, dep := range conf.Imports {
    29  		pkgList = append(pkgList, dep.Name)
    30  	}
    31  
    32  	var searchPath string
    33  	var markForDelete []string
    34  	// Callback function for filepath.Walk to delete packages not in yaml file.
    35  	fn := func(path string, info os.FileInfo, err error) error {
    36  		// Bubble up the error
    37  		if err != nil {
    38  			return err
    39  		}
    40  
    41  		if info.IsDir() == false || path == searchPath || path == vpath {
    42  			return nil
    43  		}
    44  
    45  		localPath := strings.TrimPrefix(path, searchPath)
    46  		keep := false
    47  
    48  		// First check if the path has a prefix that's a specific package. If
    49  		// so we keep it to keep the package.
    50  		for _, name := range pkgList {
    51  			if strings.HasPrefix(localPath, name) {
    52  				keep = true
    53  			}
    54  		}
    55  
    56  		// If a package is, for example, github.com/Masterminds/glide the
    57  		// previous look will not mark the directories github.com or
    58  		// github.com/Masterminds to keep. Here we see if these names prefix
    59  		// and packages we know about to mark as keepers.
    60  		if keep == false {
    61  			for _, name := range pkgList {
    62  				if strings.HasPrefix(name, localPath) {
    63  					keep = true
    64  				}
    65  			}
    66  		}
    67  
    68  		// If the parent directory has already been marked for delete this
    69  		// directory doesn't need to be marked.
    70  		for _, markedDirectory := range markForDelete {
    71  			if strings.HasPrefix(path, markedDirectory) {
    72  				return nil
    73  			}
    74  		}
    75  
    76  		// Remove the directory if we are not keeping it.
    77  		if keep == false {
    78  			// Mark for deletion
    79  			markForDelete = append(markForDelete, path)
    80  		}
    81  
    82  		return nil
    83  	}
    84  
    85  	// Walk vendor directory
    86  	searchPath = vpath + string(os.PathSeparator)
    87  	err = filepath.Walk(searchPath, fn)
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	// Perform the actual delete.
    93  	for _, path := range markForDelete {
    94  		localPath := strings.TrimPrefix(path, searchPath)
    95  		msg.Info("Removing unused package: %s\n", localPath)
    96  		rerr := os.RemoveAll(path)
    97  		if rerr != nil {
    98  			return rerr
    99  		}
   100  	}
   101  
   102  	return nil
   103  }