// Install installs the dependencies from a Lockfile. func (i *Installer) Install(lock *cfg.Lockfile, conf *cfg.Config) (*cfg.Config, error) { cwd, err := gpath.Vendor() if err != nil { return conf, err } // Create a config setup based on the Lockfile data to process with // existing commands. newConf := &cfg.Config{} newConf.Name = conf.Name newConf.Imports = make(cfg.Dependencies, len(lock.Imports)) for k, v := range lock.Imports { newConf.Imports[k] = cfg.DependencyFromLock(v) } newConf.DevImports = make(cfg.Dependencies, len(lock.DevImports)) for k, v := range lock.DevImports { newConf.DevImports[k] = cfg.DependencyFromLock(v) } newConf.DeDupe() if len(newConf.Imports) == 0 { msg.Info("No dependencies found. Nothing installed.\n") return newConf, nil } msg.Info("Downloading dependencies. Please wait...") LazyConcurrentUpdate(newConf.Imports, cwd, i, newConf) LazyConcurrentUpdate(newConf.DevImports, cwd, i, newConf) return newConf, nil }
// VendoredCleanup cleans up vendored codebases after an update. // // This should _only_ be run for installations that do not want VCS repos inside // of the vendor/ directory. func VendoredCleanup(conf *cfg.Config) error { vend, err := gpath.Vendor() if err != nil { return err } for _, dep := range conf.Imports { if dep.UpdateAsVendored == true { msg.Info("Cleaning up vendored package %s\n", dep.Name) // Remove the VCS directory cwd := filepath.Join(vend, dep.Name) repo, err := dep.GetRepo(cwd) if err != nil { msg.Err("Error cleaning up %s:%s", dep.Name, err) continue } t := repo.Vcs() err = os.RemoveAll(cwd + string(os.PathSeparator) + "." + string(t)) if err != nil { msg.Err("Error cleaning up VCS dir for %s:%s", dep.Name, err) } } } return nil }
// SetReference is a command to set the VCS reference (commit id, tag, etc) for // a project. func SetReference(conf *cfg.Config, resolveTest bool) error { cwd, err := gpath.Vendor() if err != nil { return err } if len(conf.Imports) == 0 && len(conf.DevImports) == 0 { msg.Info("No references set.\n") return nil } done := make(chan struct{}, concurrentWorkers) in := make(chan *cfg.Dependency, concurrentWorkers) var wg sync.WaitGroup for i := 0; i < concurrentWorkers; i++ { go func(ch <-chan *cfg.Dependency) { for { select { case dep := <-ch: if err := VcsVersion(dep, cwd); err != nil { msg.Err("Failed to set version on %s to %s: %s\n", dep.Name, dep.Reference, err) } wg.Done() case <-done: return } } }(in) } for _, dep := range conf.Imports { if !conf.HasIgnore(dep.Name) { wg.Add(1) in <- dep } } if resolveTest { for _, dep := range conf.DevImports { if !conf.HasIgnore(dep.Name) { wg.Add(1) in <- dep } } } wg.Wait() // Close goroutines setting the version for i := 0; i < concurrentWorkers; i++ { done <- struct{}{} } // close(done) // close(in) return nil }
// VendorPath returns the path to the location to put vendor packages func (i *Installer) VendorPath() string { if i.Vendor != "" { return i.Vendor } vp, err := gpath.Vendor() if err != nil { return filepath.FromSlash("./vendor") } return vp }
// Install installs the dependencies from a Lockfile. func (i *Installer) Install(lock *cfg.Lockfile, conf *cfg.Config) (*cfg.Config, error) { cwd, err := gpath.Vendor() if err != nil { return conf, err } // Create a config setup based on the Lockfile data to process with // existing commands. newConf := &cfg.Config{} newConf.Name = conf.Name newConf.Imports = make(cfg.Dependencies, len(lock.Imports)) for k, v := range lock.Imports { newConf.Imports[k] = &cfg.Dependency{ Name: v.Name, Reference: v.Version, Repository: v.Repository, VcsType: v.VcsType, Subpackages: v.Subpackages, Arch: v.Arch, Os: v.Os, } } newConf.DevImports = make(cfg.Dependencies, len(lock.DevImports)) for k, v := range lock.DevImports { newConf.DevImports[k] = &cfg.Dependency{ Name: v.Name, Reference: v.Version, Repository: v.Repository, VcsType: v.VcsType, Subpackages: v.Subpackages, Arch: v.Arch, Os: v.Os, } } newConf.DeDupe() if len(newConf.Imports) == 0 { msg.Info("No dependencies found. Nothing installed.\n") return newConf, nil } msg.Info("Downloading dependencies. Please wait...") ConcurrentUpdate(newConf.Imports, cwd, i, newConf) ConcurrentUpdate(newConf.DevImports, cwd, i, newConf) return newConf, nil }
// allPackages gets a list of all packages required to satisfy the given deps. func allPackages(deps []*cfg.Dependency, res *dependency.Resolver) ([]string, error) { if len(deps) == 0 { return []string{}, nil } vdir, err := gpath.Vendor() if err != nil { return []string{}, err } vdir += string(os.PathSeparator) ll, err := res.ResolveAll(deps) if err != nil { return []string{}, err } for i := 0; i < len(ll); i++ { ll[i] = strings.TrimPrefix(ll[i], vdir) } return ll, nil }
// Rebuild rebuilds '.a' files for a project. // // Prior to Go 1.4, this could substantially reduce time on incremental compiles. // It remains to be seen whether this is tremendously beneficial to modern Go // programs. func Rebuild() { conf := EnsureConfig() vpath, err := gpath.Vendor() if err != nil { msg.Die("Could not get vendor path: %s", err) } msg.Info("Building dependencies.\n") if len(conf.Imports) == 0 { msg.Info("No dependencies found. Nothing built.\n") return } for _, dep := range conf.Imports { if err := buildDep(dep, vpath); err != nil { msg.Warn("Failed to build %s: %s\n", dep.Name, err) } } }
// Rebuild rebuilds '.a' files for a project. // // Prior to Go 1.4, this could substantially reduce time on incremental compiles. // It remains to be seen whether this is tremendously beneficial to modern Go // programs. func Rebuild() { msg.Warn("The rebuild command is deprecated and will be removed in a future version") msg.Warn("Use the go install command instead") conf := EnsureConfig() vpath, err := gpath.Vendor() if err != nil { msg.Die("Could not get vendor path: %s", err) } msg.Info("Building dependencies.\n") if len(conf.Imports) == 0 { msg.Info("No dependencies found. Nothing built.\n") return } for _, dep := range conf.Imports { if err := buildDep(dep, vpath); err != nil { msg.Warn("Failed to build %s: %s\n", dep.Name, err) } } }
// DeleteUnused removes packages from vendor/ that are no longer used. // // TODO: This should work off of a Lock file, not glide.yaml. func DeleteUnused(conf *cfg.Config) error { vpath, err := gpath.Vendor() if err != nil { return err } if vpath == "" { return errors.New("Vendor not set") } // Build directory tree of what to keep. var pkgList []string for _, dep := range conf.Imports { pkgList = append(pkgList, dep.Name) } var searchPath string var markForDelete []string // Callback function for filepath.Walk to delete packages not in yaml file. 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 + string(os.PathSeparator) err = filepath.Walk(searchPath, fn) if err != nil { return err } // Perform the actual delete. for _, path := range markForDelete { localPath := strings.TrimPrefix(path, searchPath) msg.Info("Removing unused package: %s\n", localPath) rerr := os.RemoveAll(path) if rerr != nil { return rerr } } return nil }