// UpdateImports iterates over the imported packages and updates them. // // Params: // // - force (bool): force packages to update (default false) // - conf (*cfg.Config): The configuration // - packages([]string): The packages to update. Default is all. func UpdateImports(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { cfg := p.Get("conf", nil).(*cfg.Config) force := p.Get("force", true).(bool) plist := p.Get("packages", []string{}).([]string) home := p.Get("home", "").(string) cache := p.Get("cache", false).(bool) cacheGopath := p.Get("cacheGopath", false).(bool) useGopath := p.Get("useGopath", false).(bool) pkgs := list2map(plist) restrict := len(pkgs) > 0 cwd, err := VendorPath(c) if err != nil { return false, err } if len(cfg.Imports) == 0 { Info("No dependencies found. Nothing updated.\n") return false, nil } for _, dep := range cfg.Imports { if restrict && !pkgs[dep.Name] { Debug("===> Skipping %q", dep.Name) // Even though skipping check if the package exists and has VCS info // needed for other operations. dest := filepath.Join(cwd, filepath.FromSlash(dep.Name)) if _, err := os.Stat(dest); os.IsNotExist(err) { Warn("Package %s not checked out to vendor/ folder", dep.Name) Error("Unable to generate accurate glide.lock because %s is missing", dep.Name) } else { empty, err := isDirectoryEmpty(dest) _, err2 := v.DetectVcsFromFS(dest) if err != nil || empty == true { Warn("Package %s not checked out to vendor/ folder. Directory empty", dep.Name) Error("Unable to generate accurate glide.lock because %s is missing", dep.Name) continue } else if empty == false && err2 == v.ErrCannotDetectVCS { Warn("%s appears to be a vendored package missing version control data", dep.Name) Error("Unable to generate accurate glide.lock because %s version control data is missing", dep.Name) } } continue } // Hack: The updateCache global keeps us from re-updating the same // dependencies when we're recursing. We cache here to prevent // flattening from causing unnecessary updates. updateCache[dep.Name] = true if err := VcsUpdate(dep, cwd, home, force, cache, cacheGopath, useGopath); err != nil { Warn("Update failed for %s: %s\n", dep.Name, err) } } return true, nil }
// VcsVersion set the VCS version for a checkout. func VcsVersion(dep *Dependency, vend string) error { // If there is no refernece configured there is nothing to set. if dep.Reference == "" { return nil } cwd := path.Join(vend, dep.Name) // When the directory is not empty and has no VCS directory it's // a vendored files situation. empty, err := isDirectoryEmpty(cwd) if err != nil { return err } _, err = v.DetectVcsFromFS(cwd) if empty == false && err == v.ErrCannotDetectVCS { Warn("%s appears to be a vendored package. Unable to set new version. Consider the '--update-vendored' flag.\n", dep.Name) } else { Info("Setting version for %s.\n", dep.Name) repo, err := dep.GetRepo(cwd) if err != nil { return err } if err := repo.UpdateVersion(dep.Reference); err != nil { Error("Failed to set version to %s: %s\n", dep.Reference, err) return err } } return nil }
func repoRoot(pth string) (string, error) { _, err := vcs.DetectVcsFromFS(pth) if err == vcs.ErrCannotDetectVCS { if pth == "/" { return pth, err } return repoRoot(path.Dir(pth)) } if err != nil { return pth, fmt.Errorf("Error while detecting repo root for %v: %v", pth, err) } return pth, nil }
// VendoredSetup is a command that does the setup for vendored directories. // If enabled (via update) it marks vendored directories that are being updated // and removed the old code. This should be a prefix to UpdateImports and // VendoredCleanUp should be a suffix to UpdateImports. func VendoredSetup(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { update := p.Get("update", true).(bool) cfg := p.Get("conf", nil).(*Config) if update != true { return cfg, nil } vend, err := VendorPath(c) if err != nil { return cfg, err } for _, dep := range cfg.Imports { cwd := path.Join(vend, dep.Name) // When the directory is not empty and has no VCS directory it's // a vendored files situation. empty, err := isDirectoryEmpty(cwd) if err != nil { Error("Error with the directory %s\n", cwd) continue } _, err = vcs.DetectVcsFromFS(cwd) if empty == false && err == vcs.ErrCannotDetectVCS { Info("Updating vendored package %s\n", dep.Name) // Remove old directory. cmd.UpdateImports will retrieve the version // and cmd.SetReference will set the version. err = os.RemoveAll(cwd) if err != nil { Error("Unable to update vendored dependency %s.\n", dep.Name) } else { dep.UpdateAsVendored = true } } } return cfg, nil }
func main() { yml, err := ioutil.ReadFile("glide.lock") if err != nil && os.IsNotExist(err) { fmt.Println("glide.lock file not found. Please run glide up to generate it.") os.Exit(1) } if err != nil { fmt.Println(err) os.Exit(2) } l, err := cfg.LockfileFromYaml(yml) if err != nil { fmt.Println("Unable to parse glide.lock file.") os.Exit(1) } for _, d := range l.Imports { dir := filepath.Join("vendor", filepath.FromSlash(d.Name)) t, err := vcs.DetectVcsFromFS(dir) if err != nil { fmt.Println(err) continue } p := filepath.Join(dir, "."+string(t)) if _, err = os.Stat(p); os.IsNotExist(err) { fmt.Println("VCS data not present for", d.Name) continue } fmt.Println("Removing VCS data for", d.Name) err = os.RemoveAll(p) if err != nil { fmt.Println(err) } } }
// VcsUpdate updates to a particular checkout based on the VCS setting. func VcsUpdate(dep *Dependency, vend string, force bool) error { Info("Fetching updates for %s.\n", dep.Name) if filterArchOs(dep) { Info("%s is not used for %s/%s.\n", dep.Name, runtime.GOOS, runtime.GOARCH) return nil } dest := path.Join(vend, dep.Name) // If destination doesn't exist we need to perform an initial checkout. if _, err := os.Stat(dest); os.IsNotExist(err) { if err = VcsGet(dep, dest); err != nil { Warn("Unable to checkout %s\n", dep.Name) return err } } else { // At this point we have a directory for the package. // When the directory is not empty and has no VCS directory it's // a vendored files situation. empty, err := isDirectoryEmpty(dest) if err != nil { return err } _, err = v.DetectVcsFromFS(dest) if empty == false && err == v.ErrCannotDetectVCS { Warn("%s appears to be a vendored package. Unable to update. Consider the '--update-vendored' flag.\n", dep.Name) } else { repo, err := dep.GetRepo(dest) // Tried to checkout a repo to a path that does not work. Either the // type or endpoint has changed. Force is being passed in so the old // location can be removed and replaced with the new one. // Warning, any changes in the old location will be deleted. // TODO: Put dirty checking in on the existing local checkout. if (err == v.ErrWrongVCS || err == v.ErrWrongRemote) && force == true { var newRemote string if len(dep.Repository) > 0 { newRemote = dep.Repository } else { newRemote = "https://" + dep.Name } Warn("Replacing %s with contents from %s\n", dep.Name, newRemote) rerr := os.RemoveAll(dest) if rerr != nil { return rerr } if err = VcsGet(dep, dest); err != nil { Warn("Unable to checkout %s\n", dep.Name) return err } } else if err != nil { return err } else { if err := repo.Update(); err != nil { Warn("Download failed.\n") return err } } } } return nil }
// VcsVersion set the VCS version for a checkout. func VcsVersion(dep *yaml.Dependency, vend string) error { // If there is no refernece configured there is nothing to set. if dep.Reference == "" { return nil } cwd := path.Join(vend, dep.Name) // When the directory is not empty and has no VCS directory it's // a vendored files situation. empty, err := isDirectoryEmpty(cwd) if err != nil { return err } _, err = v.DetectVcsFromFS(cwd) if empty == false && err == v.ErrCannotDetectVCS { Warn("%s appears to be a vendored package. Unable to set new version. Consider the '--update-vendored' flag.\n", dep.Name) } else { repo, err := dep.GetRepo(cwd) if err != nil { return err } ver := dep.Reference // Referenes in Git can begin with a ^ which is similar to semver. // If there is a ^ prefix we assume it's a semver constraint rather than // part of the git/VCS commit id. if repo.IsReference(ver) && !strings.HasPrefix(ver, "^") { Info("Setting version for %s to %s.\n", dep.Name, ver) } else { // Create the constraing first to make sure it's valid before // working on the repo. constraint, err := semver.NewConstraint(ver) // Make sure the constriant is valid. At this point it's not a valid // reference so if it's not a valid constrint we can exit early. if err != nil { Warn("The reference '%s' is not valid\n", ver) return err } // Get the tags and branches (in that order) refs, err := getAllVcsRefs(repo) if err != nil { return err } // Convert and filter the list to semver.Version instances semvers := getSemVers(refs) // Sort semver list sort.Sort(sort.Reverse(semver.Collection(semvers))) found := false for _, v := range semvers { if constraint.Check(v) { found = true // If the constrint passes get the original reference ver = v.Original() break } } if found { Info("Detected semantic version. Setting version for %s to %s.\n", dep.Name, ver) } else { Warn("Unable to find semantic version for constraint %s %s\n", dep.Name, ver) } } if err := repo.UpdateVersion(ver); err != nil { Error("Failed to set version to %s: %s\n", dep.Reference, err) return err } } return nil }
// VcsUpdate updates to a particular checkout based on the VCS setting. func VcsUpdate(dep *yaml.Dependency, vend, home string, force, cache, cacheGopath, skipGopath bool) error { Info("Fetching updates for %s.\n", dep.Name) if filterArchOs(dep) { Info("%s is not used for %s/%s.\n", dep.Name, runtime.GOOS, runtime.GOARCH) return nil } dest := path.Join(vend, dep.Name) // If destination doesn't exist we need to perform an initial checkout. if _, err := os.Stat(dest); os.IsNotExist(err) { if err = VcsGet(dep, dest, home, cache, cacheGopath, skipGopath); err != nil { Warn("Unable to checkout %s\n", dep.Name) return err } } else { // At this point we have a directory for the package. // When the directory is not empty and has no VCS directory it's // a vendored files situation. empty, err := isDirectoryEmpty(dest) if err != nil { return err } _, err = v.DetectVcsFromFS(dest) if empty == false && err == v.ErrCannotDetectVCS { Warn("%s appears to be a vendored package. Unable to update. Consider the '--update-vendored' flag.\n", dep.Name) } else { repo, err := dep.GetRepo(dest) // Tried to checkout a repo to a path that does not work. Either the // type or endpoint has changed. Force is being passed in so the old // location can be removed and replaced with the new one. // Warning, any changes in the old location will be deleted. // TODO: Put dirty checking in on the existing local checkout. if (err == v.ErrWrongVCS || err == v.ErrWrongRemote) && force == true { var newRemote string if len(dep.Repository) > 0 { newRemote = dep.Repository } else { newRemote = "https://" + dep.Name } Warn("Replacing %s with contents from %s\n", dep.Name, newRemote) rerr := os.RemoveAll(dest) if rerr != nil { return rerr } if err = VcsGet(dep, dest, home, cache, cacheGopath, skipGopath); err != nil { Warn("Unable to checkout %s\n", dep.Name) return err } } else if err != nil { return err } else { // Check if the current version is a tag or commit id. If it is // and that version is already checked out we can skip updating // which is faster than going out to the Internet to perform // an update. if dep.Reference != "" { version, err := repo.Version() if err != nil { return err } ib, err := isBranch(dep.Reference, repo) if err != nil { return err } // If the current version equals the ref and it's not a // branch it's a tag or commit id so we can skip // performing an update. if version == dep.Reference && !ib { Info("%s is already set to version %s. Skipping update.", dep.Name, dep.Reference) return nil } } if err := repo.Update(); err != nil { Warn("Download failed.\n") return err } } } } return nil }
// VcsUpdate updates to a particular checkout based on the VCS setting. func VcsUpdate(dep *cfg.Dependency, vend string, inst *Installer) error { // If the dependency has already been pinned we can skip it. This is a // faster path so we don't need to resolve it again. if dep.Pin != "" { msg.Debug("Dependency %s has already been pinned. Fetching updates skipped.", dep.Name) return nil } msg.Info("Fetching updates for %s.\n", dep.Name) if filterArchOs(dep) { msg.Info("%s is not used for %s/%s.\n", dep.Name, runtime.GOOS, runtime.GOARCH) return nil } dest := filepath.Join(vend, dep.Name) // If destination doesn't exist we need to perform an initial checkout. if _, err := os.Stat(dest); os.IsNotExist(err) { if err = VcsGet(dep, dest, inst.Home, inst.UseCache, inst.UseCacheGopath, inst.UseGopath); err != nil { msg.Warn("Unable to checkout %s\n", dep.Name) return err } } else { // At this point we have a directory for the package. // When the directory is not empty and has no VCS directory it's // a vendored files situation. empty, err := gpath.IsDirectoryEmpty(dest) if err != nil { return err } _, err = v.DetectVcsFromFS(dest) if inst.UpdateVendored == false && empty == false && err == v.ErrCannotDetectVCS { msg.Warn("%s appears to be a vendored package. Unable to update. Consider the '--update-vendored' flag.\n", dep.Name) } else { if inst.UpdateVendored == true && empty == false && err == v.ErrCannotDetectVCS { // A vendored package, no repo, and updating the vendored packages // has been opted into. msg.Info("%s is a vendored package. Updating.", dep.Name) err = os.RemoveAll(dest) if err != nil { msg.Error("Unable to update vendored dependency %s.\n", dep.Name) return err } else { dep.UpdateAsVendored = true } if err = VcsGet(dep, dest, inst.Home, inst.UseCache, inst.UseCacheGopath, inst.UseGopath); err != nil { msg.Warn("Unable to checkout %s\n", dep.Name) return err } return nil } repo, err := dep.GetRepo(dest) // Tried to checkout a repo to a path that does not work. Either the // type or endpoint has changed. Force is being passed in so the old // location can be removed and replaced with the new one. // Warning, any changes in the old location will be deleted. // TODO: Put dirty checking in on the existing local checkout. if (err == v.ErrWrongVCS || err == v.ErrWrongRemote) && inst.Force == true { var newRemote string if len(dep.Repository) > 0 { newRemote = dep.Repository } else { newRemote = "https://" + dep.Name } msg.Warn("Replacing %s with contents from %s\n", dep.Name, newRemote) rerr := os.RemoveAll(dest) if rerr != nil { return rerr } if err = VcsGet(dep, dest, inst.Home, inst.UseCache, inst.UseCacheGopath, inst.UseGopath); err != nil { msg.Warn("Unable to checkout %s\n", dep.Name) return err } } else if err != nil { return err } else if repo.IsDirty() { return fmt.Errorf("%s contains uncommited changes. Skipping update", dep.Name) } else { // Check if the current version is a tag or commit id. If it is // and that version is already checked out we can skip updating // which is faster than going out to the Internet to perform // an update. if dep.Reference != "" { version, err := repo.Version() if err != nil { return err } ib, err := isBranch(dep.Reference, repo) if err != nil { return err } // If the current version equals the ref and it's not a // branch it's a tag or commit id so we can skip // performing an update. if version == dep.Reference && !ib { msg.Info("%s is already set to version %s. Skipping update.", dep.Name, dep.Reference) return nil } } if err := repo.Update(); err != nil { msg.Warn("Download failed.\n") return err } } } } return nil }
// VcsUpdate updates to a particular checkout based on the VCS setting. func VcsUpdate(dep *cfg.Dependency, force bool, updated *UpdateTracker) error { // If the dependency has already been pinned we can skip it. This is a // faster path so we don't need to resolve it again. if dep.Pin != "" { msg.Debug("Dependency %s has already been pinned. Fetching updates skipped.", dep.Name) return nil } if updated.Check(dep.Name) { msg.Debug("%s was already updated, skipping.", dep.Name) return nil } updated.Add(dep.Name) if filterArchOs(dep) { msg.Info("%s is not used for %s/%s.\n", dep.Name, runtime.GOOS, runtime.GOARCH) return nil } key, err := cp.Key(dep.Remote()) if err != nil { msg.Die("Cache key generation error: %s", err) } location := cp.Location() dest := filepath.Join(location, "src", key) // If destination doesn't exist we need to perform an initial checkout. if _, err := os.Stat(dest); os.IsNotExist(err) { msg.Info("--> Fetching %s.", dep.Name) if err = VcsGet(dep); err != nil { msg.Warn("Unable to checkout %s\n", dep.Name) return err } } else { // At this point we have a directory for the package. msg.Info("--> Fetching updates for %s.", dep.Name) // When the directory is not empty and has no VCS directory it's // a vendored files situation. empty, err := gpath.IsDirectoryEmpty(dest) if err != nil { return err } _, err = v.DetectVcsFromFS(dest) if empty == true && err == v.ErrCannotDetectVCS { msg.Warn("Cached version of %s is an empty directory. Fetching a new copy of the dependency.", dep.Name) msg.Debug("Removing empty directory %s", dest) err := os.RemoveAll(dest) if err != nil { return err } if err = VcsGet(dep); err != nil { msg.Warn("Unable to checkout %s\n", dep.Name) return err } } else { repo, err := dep.GetRepo(dest) // Tried to checkout a repo to a path that does not work. Either the // type or endpoint has changed. Force is being passed in so the old // location can be removed and replaced with the new one. // Warning, any changes in the old location will be deleted. // TODO: Put dirty checking in on the existing local checkout. if (err == v.ErrWrongVCS || err == v.ErrWrongRemote) && force == true { newRemote := dep.Remote() msg.Warn("Replacing %s with contents from %s\n", dep.Name, newRemote) rerr := os.RemoveAll(dest) if rerr != nil { return rerr } if err = VcsGet(dep); err != nil { msg.Warn("Unable to checkout %s\n", dep.Name) return err } repo, err = dep.GetRepo(dest) if err != nil { return err } } else if err != nil { return err } else if repo.IsDirty() { return fmt.Errorf("%s contains uncommitted changes. Skipping update", dep.Name) } ver := dep.Reference if ver == "" { ver = defaultBranch(repo) } // Check if the current version is a tag or commit id. If it is // and that version is already checked out we can skip updating // which is faster than going out to the Internet to perform // an update. if ver != "" { version, err := repo.Version() if err != nil { return err } ib, err := isBranch(ver, repo) if err != nil { return err } // If the current version equals the ref and it's not a // branch it's a tag or commit id so we can skip // performing an update. if version == ver && !ib { msg.Debug("%s is already set to version %s. Skipping update.", dep.Name, dep.Reference) return nil } } if err := repo.Update(); err != nil { msg.Warn("Download failed.\n") return err } } } return nil }
// VcsVersion set the VCS version for a checkout. func VcsVersion(dep *cfg.Dependency) error { // If the dependency has already been pinned we can skip it. This is a // faster path so we don't need to resolve it again. if dep.Pin != "" { msg.Debug("Dependency %s has already been pinned. Setting version skipped.", dep.Name) return nil } key, err := cp.Key(dep.Remote()) if err != nil { msg.Die("Cache key generation error: %s", err) } location := cp.Location() cwd := filepath.Join(location, "src", key) // If there is no reference configured there is nothing to set. if dep.Reference == "" { // Before exiting update the pinned version repo, err := dep.GetRepo(cwd) if err != nil { return err } dep.Pin, err = repo.Version() if err != nil { return err } return nil } // When the directory is not empty and has no VCS directory it's // a vendored files situation. empty, err := gpath.IsDirectoryEmpty(cwd) if err != nil { return err } _, err = v.DetectVcsFromFS(cwd) if empty == false && err == v.ErrCannotDetectVCS { return fmt.Errorf("Cache directory missing VCS information for %s", dep.Name) } repo, err := dep.GetRepo(cwd) if err != nil { return err } ver := dep.Reference // References in Git can begin with a ^ which is similar to semver. // If there is a ^ prefix we assume it's a semver constraint rather than // part of the git/VCS commit id. if repo.IsReference(ver) && !strings.HasPrefix(ver, "^") { msg.Info("--> Setting version for %s to %s.\n", dep.Name, ver) } else { // Create the constraint first to make sure it's valid before // working on the repo. constraint, err := semver.NewConstraint(ver) // Make sure the constriant is valid. At this point it's not a valid // reference so if it's not a valid constrint we can exit early. if err != nil { msg.Warn("The reference '%s' is not valid\n", ver) return err } // Get the tags and branches (in that order) refs, err := getAllVcsRefs(repo) if err != nil { return err } // Convert and filter the list to semver.Version instances semvers := getSemVers(refs) // Sort semver list sort.Sort(sort.Reverse(semver.Collection(semvers))) found := false for _, v := range semvers { if constraint.Check(v) { found = true // If the constrint passes get the original reference ver = v.Original() break } } if found { msg.Info("--> Detected semantic version. Setting version for %s to %s.", dep.Name, ver) } else { msg.Warn("--> Unable to find semantic version for constraint %s %s", dep.Name, ver) } } if err := repo.UpdateVersion(ver); err != nil { return err } dep.Pin, err = repo.Version() if err != nil { return err } return nil }