// VcsUpdate updates to a particular checkout based on the VCS setting. func VcsUpdate(dep *cfg.Dependency, dest, home string, cache, cacheGopath, useGopath, force, updateVendored bool) 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 } // 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, 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 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 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, home, cache, cacheGopath, 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) && 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, home, cache, cacheGopath, 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 }