From da5599dd5fb1b36f6db56ca1f7caf06104d9fa82 Mon Sep 17 00:00:00 2001 From: Matt Farina Date: Thu, 21 Jan 2016 11:41:10 -0500 Subject: [PATCH] Removing cookoo and the cmd directory. Hope this goes well. --- Makefile | 3 +- cmd/cache.go | 114 ----- cmd/cache_test.go | 21 - cmd/delete.go | 110 ----- cmd/flatten.go | 479 -------------------- cmd/gb.go | 79 ---- cmd/get_imports.go | 882 ------------------------------------ cmd/get_imports_test.go | 8 - cmd/godeps.go | 108 ----- cmd/gpm.go | 110 ----- cmd/guess_deps.go | 171 ------- cmd/install.go | 142 ------ cmd/link_package.go | 50 -- cmd/mkdir.go | 23 - cmd/msg.go | 100 ---- cmd/msg_windows.go | 64 --- cmd/novendor.go | 134 ------ cmd/print_name.go | 17 - cmd/rebuild.go | 99 ---- cmd/semver.go | 48 -- cmd/tree.go | 331 -------------- cmd/tree_test.go | 23 - cmd/util.go | 215 --------- cmd/util_test.go | 42 -- cmd/vendor_path.go | 44 -- cmd/vendor_path_test.go | 28 -- cmd/vendored.go | 65 --- cmd/yaml.go | 196 -------- cmd/yaml_test.go | 124 ----- dependency/resolver.go | 3 + dependency/resolver_test.go | 7 +- glide.go | 55 +-- glide.lock | 10 +- glide.yaml | 4 - glide_test.go | 5 +- 35 files changed, 13 insertions(+), 3901 deletions(-) delete mode 100644 cmd/cache.go delete mode 100644 cmd/cache_test.go delete mode 100644 cmd/delete.go delete mode 100644 cmd/flatten.go delete mode 100644 cmd/gb.go delete mode 100644 cmd/get_imports.go delete mode 100644 cmd/get_imports_test.go delete mode 100644 cmd/godeps.go delete mode 100644 cmd/gpm.go delete mode 100644 cmd/guess_deps.go delete mode 100644 cmd/install.go delete mode 100644 cmd/link_package.go delete mode 100644 cmd/mkdir.go delete mode 100644 cmd/msg.go delete mode 100644 cmd/msg_windows.go delete mode 100644 cmd/novendor.go delete mode 100644 cmd/print_name.go delete mode 100644 cmd/rebuild.go delete mode 100644 cmd/semver.go delete mode 100644 cmd/tree.go delete mode 100644 cmd/tree_test.go delete mode 100644 cmd/util.go delete mode 100644 cmd/util_test.go delete mode 100644 cmd/vendor_path.go delete mode 100644 cmd/vendor_path_test.go delete mode 100644 cmd/vendored.go delete mode 100644 cmd/yaml.go delete mode 100644 cmd/yaml_test.go diff --git a/Makefile b/Makefile index 1cc1e21d..7adc2808 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ install: build install -m 755 ./glide ${DESTDIR}/usr/local/bin/glide test: - go test . ./cmd ./gb ./path ./action ./tree ./util ./godep ./gpm + go test . ./gb ./path ./action ./tree ./util ./godep ./gpm ./cfg ./dependency ./importer ./msg ./repo clean: rm -f ./glide.test @@ -18,7 +18,6 @@ clean: bootstrap: mkdir ./vendor - git clone https://github.com/Masterminds/cookoo vendor/github.com/Masterminds/cookoo git clone https://github.com/Masterminds/vcs vendor/github.com/Masterminds/vcs git clone https://gopkg.in/yaml.v2 vendor/gopkg.in/yaml.v2 git clone https://github.com/codegangsta/cli vendor/github.com/codegangsta/cli diff --git a/cmd/cache.go b/cmd/cache.go deleted file mode 100644 index bbb9c7b5..00000000 --- a/cmd/cache.go +++ /dev/null @@ -1,114 +0,0 @@ -package cmd - -import ( - "encoding/json" - "errors" - "io/ioutil" - "net/url" - "os" - "path/filepath" - "strings" - "time" - - "github.com/Masterminds/cookoo" -) - -var cacheEnabled = true - -var errCacheDisabled = errors.New("Cache disabled") - -// EnsureCacheDir Creates the $HOME/.glide/cache directory (unless home is -// specified to be different) if it does not exist. -func EnsureCacheDir(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - home := p.Get("home", "").(string) - if home == "" { - cacheEnabled = false - Warn("Unable to locate home directory") - return false, nil - } - err := os.MkdirAll(filepath.Join(home, "cache", "info"), os.ModeDir|os.ModePerm) - if err != nil { - cacheEnabled = false - Warn("Error creating Glide directory %s", home) - } - return false, nil -} - -// Pass in a repo location and get a cache key from it. -func cacheCreateKey(repo string) (string, error) { - - // A url needs a scheme. A git repo such as - // git@github.com:Masterminds/cookoo.git reworked to the url parser. - c := strings.Contains(repo, "://") - if !c { - repo = "ssh://" + repo - } - - u, err := url.Parse(repo) - if err != nil { - return "", err - } - - if !c { - u.Scheme = "" - } - - var key string - if u.Scheme != "" { - key = u.Scheme + "-" - } - if u.User != nil && u.User.Username() != "" { - key = key + u.User.Username() + "-" - } - key = key + u.Host - if u.Path != "" { - key = key + strings.Replace(u.Path, "/", "-", -1) - } - - key = strings.Replace(key, ":", "-", -1) - - return key, nil -} - -type cacheRepoInfo struct { - DefaultBranch string `json:"default-branch"` - LastUpdate string `json:"last-update"` -} - -func saveCacheRepoData(key string, data cacheRepoInfo, location string) error { - if !cacheEnabled { - return errCacheDisabled - } - data.LastUpdate = time.Now().String() - d, err := json.Marshal(data) - if err != nil { - return err - } - - p := filepath.Join(location, "cache", "info", key+".json") - f, err := os.Create(p) - if err != nil { - return err - } - defer f.Close() - - _, err = f.Write(d) - return err -} - -func cacheRepoData(key, location string) (*cacheRepoInfo, error) { - if !cacheEnabled { - return &cacheRepoInfo{}, errCacheDisabled - } - c := &cacheRepoInfo{} - p := filepath.Join(location, "cache", "info", key+".json") - f, err := ioutil.ReadFile(p) - if err != nil { - return &cacheRepoInfo{}, err - } - err = json.Unmarshal(f, c) - if err != nil { - return &cacheRepoInfo{}, err - } - return c, nil -} diff --git a/cmd/cache_test.go b/cmd/cache_test.go deleted file mode 100644 index 6104434d..00000000 --- a/cmd/cache_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package cmd - -import "testing" - -func TestCacheCreateKey(t *testing.T) { - tests := map[string]string{ - "https://github.com/foo/bar": "https-github.com-foo-bar", - "git@github.com:foo/bar": "git-github.com-foo-bar", - } - - for k, v := range tests { - key, err := cacheCreateKey(k) - if err != nil { - t.Errorf("Cache key generation err: %s", err) - continue - } - if key != v { - t.Errorf("Expected cache key %s for %s but got %s", v, k, key) - } - } -} diff --git a/cmd/delete.go b/cmd/delete.go deleted file mode 100644 index 202377ae..00000000 --- a/cmd/delete.go +++ /dev/null @@ -1,110 +0,0 @@ -package cmd - -import ( - "errors" - "os" - "path/filepath" - "strings" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" -) - -// DeleteUnusedPackages removes packages from vendor/ that are no longer used. -func DeleteUnusedPackages(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - // Conditional opt-in to removed unused dependencies. - optIn := p.Get("optIn", false).(bool) - if optIn != true { - return nil, nil - } - - vpath, err := VendorPath(c) - if err != nil { - return nil, err - } - if vpath == "" { - return false, errors.New("Vendor not set") - } - - // Build directory tree of what to keep. - cfg := p.Get("conf", nil).(*cfg.Config) - var pkgList []string - for _, dep := range cfg.Imports { - pkgList = append(pkgList, dep.Name) - } - - // Callback function for filepath.Walk to delete packages not in yaml file. - var searchPath string - - var markForDelete []string - - 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 false, err - } - - // Perform the actual delete. - for _, path := range markForDelete { - localPath := strings.TrimPrefix(path, searchPath) - Info("Removing unused package: %s\n", localPath) - rerr := os.RemoveAll(path) - if rerr != nil { - return false, rerr - } - } - - return nil, nil -} diff --git a/cmd/flatten.go b/cmd/flatten.go deleted file mode 100644 index 9ae94f74..00000000 --- a/cmd/flatten.go +++ /dev/null @@ -1,479 +0,0 @@ -package cmd - -import ( - "io/ioutil" - "os" - "path" - "path/filepath" - "strings" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" - "github.com/Masterminds/glide/util" - "github.com/Masterminds/semver" -) - -// Flatten recurses through all dependent packages and flattens to a top level. -// -// Flattening involves determining a tree's dependencies and flattening them -// into a single large list. -// -// Params: -// - packages ([]string): The packages to read. If this is empty, it reads all -// packages. -// - force (bool): force vcs updates. -// - conf (*cfg.Config): The configuration. -// -// Returns: -// -func Flatten(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - conf := p.Get("conf", &cfg.Config{}).(*cfg.Config) - skip := p.Get("skip", false).(bool) - home := p.Get("home", "").(string) - cache := p.Get("cache", false).(bool) - cacheGopath := p.Get("cacheGopath", false).(bool) - useGopath := p.Get("useGopath", false).(bool) - - if skip { - Warn("Skipping lockfile generation because full dependency tree is not being calculated") - return conf, nil - } - packages := p.Get("packages", []string{}).([]string) - - // Operate on a clone of the conf so any changes don't impact later operations. - // This is a deep clone so dependencies are also cloned. - confcopy := conf.Clone() - - // Generate a hash of the conf for later use in lockfile generation. - hash, err := conf.Hash() - if err != nil { - return conf, err - } - - // When packages are passed around with a #version on the end it needs - // to be stripped. - for k, v := range packages { - parts := strings.Split(v, "#") - packages[k] = parts[0] - } - - force := p.Get("force", true).(bool) - vend, _ := VendorPath(c) - - // If no packages are supplied, we do them all. - if len(packages) == 0 { - packages = make([]string, len(confcopy.Imports)) - for i, v := range confcopy.Imports { - packages[i] = v.Name - } - } - - // Build an initial dependency map. - deps := make(map[string]*cfg.Dependency, len(confcopy.Imports)) - for _, imp := range confcopy.Imports { - deps[imp.Name] = imp - } - - f := &flattening{confcopy, vend, vend, deps, packages} - - // The assumption here is that once something has been scanned once in a - // run, there is no need to scan it again. - scanned := map[string]bool{} - err = recFlatten(f, force, home, cache, cacheGopath, useGopath, scanned) - if err != nil { - return confcopy, err - } - err = confcopy.DeDupe() - if err != nil { - return confcopy, err - } - flattenSetRefs(f) - Info("Project relies on %d dependencies.", len(deps)) - - c.Put("Lockfile", cfg.LockfileFromMap(deps, hash)) - - exportFlattenedDeps(confcopy, deps) - - return confcopy, err -} - -func exportFlattenedDeps(conf *cfg.Config, in map[string]*cfg.Dependency) { - out := make([]*cfg.Dependency, len(in)) - i := 0 - for _, v := range in { - out[i] = v - i++ - } - conf.Imports = out -} - -type flattening struct { - conf *cfg.Config - // Top vendor path, e.g. project/vendor - top string - // Current path - curr string - // Built list of dependencies - deps map[string]*cfg.Dependency - // Dependencies that need to be scanned. - scan []string -} - -// Hack: Cache record of updates so we don't have to keep doing git pulls. -var updateCache = map[string]bool{} - -// refFlatten recursively flattens the vendor tree. -func recFlatten(f *flattening, force bool, home string, cache, cacheGopath, useGopath bool, scanned map[string]bool) error { - Debug("---> Inspecting %s for changes (%d packages).\n", f.curr, len(f.scan)) - for _, imp := range f.scan { - Debug("----> Scanning %s", imp) - base := filepath.Join(f.top, filepath.FromSlash(imp)) - mod := []string{} - if m, ok := mergeGlide(base, imp, f); ok { - mod = m - } else if m, ok = mergeGodep(base, imp, f); ok { - mod = m - } else if m, ok = mergeGPM(base, imp, f); ok { - mod = m - } else if m, ok = mergeGb(base, imp, f); ok { - mod = m - } else if m, ok = mergeGuess(base, imp, f, scanned); ok { - mod = m - } - - if len(mod) > 0 { - Debug("----> Updating all dependencies for %q (%d)", imp, len(mod)) - flattenGlideUp(f, base, home, force, cache, cacheGopath, useGopath) - f2 := &flattening{ - conf: f.conf, - top: f.top, - curr: base, - deps: f.deps, - scan: mod} - recFlatten(f2, force, home, cache, cacheGopath, useGopath, scanned) - } - } - - return nil -} - -// flattenGlideUp does a glide update in the middle of a flatten operation. -// -// While this is expensive, it is also necessary to make sure we have the -// correct version of all dependencies. We might be able to simplify by -// marking packages dirty when they are added. -func flattenGlideUp(f *flattening, base, home string, force, cache, cacheGopath, useGopath bool) error { - //vdir := path.Join(base, "vendor") - for _, imp := range f.deps { - // If the top package name in the glide.yaml file is present in the deps - // skip it because we already have it. - if imp.Name == f.conf.Name { - continue - } - wd := filepath.Join(f.top, filepath.FromSlash(imp.Name)) - - if updateCache[imp.Name] { - Debug("----> Already updated %s", imp.Name) - continue - } - - Debug("Getting project %s (%s)\n", imp.Name, wd) - - if err := VcsUpdate(imp, f.top, home, force, cache, cacheGopath, useGopath); err != nil { - // We can still go on just fine even if this fails. - Warn("Skipped getting %s: %s\n", imp.Name, err) - continue - } - updateCache[imp.Name] = true - - // If a revision has been set use it. - err := VcsVersion(imp, f.top) - if err != nil { - Warn("Problem setting version on %s: %s\n", imp.Name, err) - } - } - - return nil -} - -// Set the references for all packages after a flatten is completed. -func flattenSetRefs(f *flattening) { - Debug("Setting final version for %d dependencies.", len(f.deps)) - for _, imp := range f.deps { - if err := VcsVersion(imp, f.top); err != nil { - Warn("Problem setting version on %s: %s (flatten)\n", imp.Name, err) - } - } -} - -func mergeGlide(dir, name string, f *flattening) ([]string, bool) { - deps := f.deps - vend := f.top - gp := path.Join(dir, "glide.yaml") - if _, err := os.Stat(gp); err != nil { - return []string{}, false - } - - yml, err := ioutil.ReadFile(gp) - if err != nil { - Warn("Found glide file %q, but can't read: %s", gp, err) - return []string{}, false - } - - conf, err := cfg.ConfigFromYaml(yml) - if err != nil { - Warn("Found glide file %q, but can't use it: %s", gp, err) - return []string{}, false - } - - Info("Found glide.yaml in %s", gp) - - return mergeDeps(deps, conf.Imports, vend, f), true -} - -// listGodep appends Godeps entries to the deps. -// -// It returns true if any dependencies were found (even if not added because -// they are duplicates). -func mergeGodep(dir, name string, f *flattening) ([]string, bool) { - deps := f.deps - vend := f.top - Debug("Looking in %s/Godeps/ for a Godeps.json file.\n", dir) - d, err := parseGodepGodeps(dir) - if err != nil { - Warn("Looking for Godeps: %s\n", err) - return []string{}, false - } else if len(d) == 0 { - return []string{}, false - } - - Info("Found Godeps.json file for %q", name) - return mergeDeps(deps, d, vend, f), true -} - -// listGb merges GB dependencies into the deps. -func mergeGb(dir, pkg string, f *flattening) ([]string, bool) { - deps := f.deps - vend := f.top - Debug("Looking in %s/vendor/ for a manifest file.\n", dir) - d, err := parseGbManifest(dir) - if err != nil || len(d) == 0 { - return []string{}, false - } - Info("Found gb manifest file for %q", pkg) - return mergeDeps(deps, d, vend, f), true -} - -// mergeGPM merges GPM Godeps files into deps. -func mergeGPM(dir, pkg string, f *flattening) ([]string, bool) { - deps := f.deps - vend := f.top - d, err := parseGPMGodeps(dir) - if err != nil || len(d) == 0 { - return []string{}, false - } - Info("Found GPM file for %q", pkg) - return mergeDeps(deps, d, vend, f), true -} - -// mergeGuess guesses dependencies and merges. -// -// This always returns true because it always handles the job of searching -// for dependencies. So generally it should be the last merge strategy -// that you try. -func mergeGuess(dir, pkg string, f *flattening, scanned map[string]bool) ([]string, bool) { - deps := f.deps - Info("Scanning %s for dependencies.", pkg) - buildContext, err := util.GetBuildContext() - if err != nil { - Warn("Could not scan package %q: %s", pkg, err) - return []string{}, false - } - - res := []string{} - - if _, err := os.Stat(dir); err != nil { - Warn("Directory is missing: %s", dir) - return res, true - } - - d := walkDeps(buildContext, dir, pkg) - for _, oname := range d { - if _, ok := scanned[oname]; ok { - //Info("===> Scanned %s already. Skipping", name) - continue - } - Debug("=> Scanning %s", oname) - name, _ := NormalizeName(oname) - //if _, ok := deps[name]; ok { - //scanned[oname] = true - //Debug("====> Seen %s already. Skipping", name) - //continue - //} - if f.conf.HasIgnore(name) { - Debug("==> Skipping %s because it is on the ignore list", name) - continue - } - - found := findPkg(buildContext, name, dir) - switch found.PType { - case ptypeUnknown: - Info("==> Unknown %s (%s)", name, oname) - Debug("✨☆ Undownloaded dependency: %s", name) - repo := util.GetRootFromPackage(name) - nd := &cfg.Dependency{ - Name: name, - Repository: "https://" + repo, - } - deps[name] = nd - res = append(res, name) - case ptypeGoroot, ptypeCgo: - scanned[oname] = true - // Why do we break rather than continue? - break - default: - // We're looking for dependencies that might exist in $GOPATH - // but not be on vendor. We add any that are on $GOPATH. - if _, ok := deps[name]; !ok { - Debug("✨☆ GOPATH dependency: %s", name) - nd := &cfg.Dependency{Name: name} - deps[name] = nd - res = append(res, name) - } - scanned[oname] = true - } - } - - return res, true -} - -// mergeDeps merges any dependency array into deps. -func mergeDeps(orig map[string]*cfg.Dependency, add []*cfg.Dependency, vend string, f *flattening) []string { - mod := []string{} - for _, dd := range add { - if f.conf.HasIgnore(dd.Name) { - Debug("Skipping %s because it is on the ignore list", dd.Name) - } else if existing, ok := orig[dd.Name]; !ok { - // Add it unless it's already there. - orig[dd.Name] = dd - Debug("Adding %s to the scan list", dd.Name) - mod = append(mod, dd.Name) - } else if existing.Reference == "" && dd.Reference != "" { - // If a nested dep has finer dependency references than outside, - // set the reference. - existing.Reference = dd.Reference - mod = append(mod, dd.Name) - } else if dd.Reference != "" && existing.Reference != "" && dd.Reference != existing.Reference { - // Check if one is a version and the other is a constraint. If the - // version is in the constraint use that. - dest := filepath.Join(vend, filepath.FromSlash(dd.Name)) - repo, err := existing.GetRepo(dest) - if err != nil { - Warn("Unable to access repo for %s\n", existing.Name) - Info("Keeping %s %s", existing.Name, existing.Reference) - continue - } - - eIsRef := repo.IsReference(existing.Reference) - ddIsRef := repo.IsReference(dd.Reference) - - // Both are references and different ones. - if eIsRef && ddIsRef { - Warn("Conflict: %s ref is %s, but also asked for %s\n", existing.Name, existing.Reference, dd.Reference) - Info("Keeping %s %s", existing.Name, existing.Reference) - } else if eIsRef { - // Test ddIsRef is a constraint and if eIsRef is a semver - // within that - con, err := semver.NewConstraint(dd.Reference) - if err != nil { - Warn("Version issue for %s: '%s' is neither a reference or semantic version constraint\n", dd.Name, dd.Reference) - Info("Keeping %s %s", existing.Name, existing.Reference) - continue - } - - ver, err := semver.NewVersion(existing.Reference) - if err != nil { - // The existing version is not a semantic version. - Warn("Conflict: %s version is %s, but also asked for %s\n", existing.Name, existing.Reference, dd.Reference) - Info("Keeping %s %s", existing.Name, existing.Reference) - continue - } - - if con.Check(ver) { - Info("Keeping %s %s because it fits constraint '%s'", existing.Name, existing.Reference, dd.Reference) - } else { - Warn("Conflict: %s version is %s but does not meet constraint '%s'\n", existing.Name, existing.Reference, dd.Reference) - Info("Keeping %s %s", existing.Name, existing.Reference) - } - - } else if ddIsRef { - // Test eIsRef is a constraint and if ddIsRef is a semver - // within that - con, err := semver.NewConstraint(existing.Reference) - if err != nil { - Warn("Version issue for %s: '%s' is neither a reference or semantic version constraint\n", existing.Name, existing.Reference) - Info("Keeping %s %s", existing.Name, existing.Reference) - continue - } - - ver, err := semver.NewVersion(dd.Reference) - if err != nil { - // The dd version is not a semantic version. - Warn("Conflict: %s version is %s, but also asked for %s\n", existing.Name, existing.Reference, dd.Reference) - Info("Keeping %s %s", existing.Name, existing.Reference) - continue - } - - if con.Check(ver) { - // Use the specific version if noted instead of the existing - // constraint. - existing.Reference = dd.Reference - mod = append(mod, dd.Name) - Info("Using %s %s because it fits constraint '%s'", existing.Name, dd.Reference, existing.Reference) - } else { - Warn("Conflict: %s semantic version constraint is %s but '%s' does not meet the constraint\n", existing.Name, existing.Reference, dd.Reference) - Info("Keeping %s %s", existing.Name, existing.Reference) - } - } else { - // Neither is a vcs reference and both could be semantic version - // constraints that are different. - - _, err := semver.NewConstraint(dd.Reference) - if err != nil { - // dd.Reference is not a reference or a valid constraint. - Warn("Version %s %s is not a reference or valid semantic version constraint\n", dd.Name, dd.Reference) - Info("Keeping %s %s", existing.Name, existing.Reference) - continue - } - - _, err = semver.NewConstraint(existing.Reference) - if err != nil { - // existing.Reference is not a reference or a valid constraint. - // We really should never end up here. - Warn("Version %s %s is not a reference or valid semantic version constraint\n", existing.Name, existing.Reference) - - existing.Reference = dd.Reference - mod = append(mod, dd.Name) - Info("Using %s %s because it is a valid version", existing.Name, existing.Reference) - continue - } - - // Both versions are constraints. Try to merge them. - // If either comparison has an || skip merging. That's complicated. - ddor := strings.Index(dd.Reference, "||") - eor := strings.Index(existing.Reference, "||") - if ddor == -1 && eor == -1 { - // Add the comparisons together. - newRef := existing.Reference + ", " + dd.Reference - existing.Reference = newRef - mod = append(mod, dd.Name) - Info("Combining %s semantic version constraints %s and %s", existing.Name, existing.Reference, dd.Reference) - } else { - Warn("Conflict: %s version is %s, but also asked for %s\n", existing.Name, existing.Reference, dd.Reference) - Info("Keeping %s %s", existing.Name, existing.Reference) - } - } - } - } - return mod -} diff --git a/cmd/gb.go b/cmd/gb.go deleted file mode 100644 index e74e6b6d..00000000 --- a/cmd/gb.go +++ /dev/null @@ -1,79 +0,0 @@ -package cmd - -import ( - "encoding/json" - "os" - "path/filepath" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" - "github.com/Masterminds/glide/gb" -) - -func HasGbManifest(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - dir := cookoo.GetString("dir", "", p) - path := filepath.Join(dir, "vendor", "manifest") - _, err := os.Stat(path) - return err == nil, nil -} - -// GbManifest -// -// Params: -// - dir (string): The directory where the manifest file is located. -// Returns: -// -func GbManifest(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - dir := cookoo.GetString("dir", ".", p) - return parseGbManifest(dir) -} - -func parseGbManifest(dir string) ([]*cfg.Dependency, error) { - path := filepath.Join(dir, "vendor", "manifest") - if fi, err := os.Stat(path); err != nil || fi.IsDir() { - return []*cfg.Dependency{}, nil - } - - Info("Found GB manifest file.\n") - buf := []*cfg.Dependency{} - file, err := os.Open(path) - if err != nil { - return buf, err - } - defer file.Close() - - man := gb.Manifest{} - - dec := json.NewDecoder(file) - if err := dec.Decode(&man); err != nil { - return buf, err - } - - seen := map[string]bool{} - - for _, d := range man.Dependencies { - pkg, sub := NormalizeName(d.Importpath) - if _, ok := seen[pkg]; ok { - if len(sub) == 0 { - continue - } - for _, dep := range buf { - if dep.Name == pkg { - dep.Subpackages = append(dep.Subpackages, sub) - } - } - } else { - seen[pkg] = true - dep := &cfg.Dependency{ - Name: pkg, - Reference: d.Revision, - Repository: d.Repository, - } - if len(sub) > 0 { - dep.Subpackages = []string{sub} - } - buf = append(buf, dep) - } - } - return buf, nil -} diff --git a/cmd/get_imports.go b/cmd/get_imports.go deleted file mode 100644 index 8613914d..00000000 --- a/cmd/get_imports.go +++ /dev/null @@ -1,882 +0,0 @@ -package cmd - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "os/exec" - "path/filepath" - "sort" - "sync" - //"log" - - "os" - "runtime" - "strings" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" - "github.com/Masterminds/glide/util" - "github.com/Masterminds/semver" - v "github.com/Masterminds/vcs" -) - -// Used for the fan out/in pattern used with VCS calls. -var concurrentWorkers = 20 - -//func init() { -// Uncomment the line below and the log import to see the output -// from the vcs commands executed for each project. -//v.Logger = log.New(os.Stdout, "go-vcs", log.LstdFlags) -//} - -// GetAll gets zero or more repos. -// -// This takes a package name, normalizes it, finds the repo, and installs it. -// It's the workhorse behind `glide get`. -// -// Params: -// - packages ([]string): Package names to get. -// - verbose (bool): default false -// -// Returns: -// - []*Dependency: A list of constructed dependencies. -func GetAll(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - names := p.Get("packages", []string{}).([]string) - conf := p.Get("conf", nil).(*cfg.Config) - insecure := p.Get("insecure", false).(bool) - - Info("Preparing to install %d package.", len(names)) - - deps := []*cfg.Dependency{} - for _, name := range names { - var version string - parts := strings.Split(name, "#") - if len(parts) > 1 { - name = parts[0] - version = parts[1] - } - - root := util.GetRootFromPackage(name) - if len(root) == 0 { - return nil, fmt.Errorf("Package name is required for %q.", name) - } - - if conf.HasDependency(root) { - Warn("Package %q is already in glide.yaml. Skipping", root) - continue - } - - if conf.HasIgnore(root) { - Warn("Package %q is set to be ignored in glide.yaml. Skipping", root) - continue - } - - dep := &cfg.Dependency{ - Name: root, - } - - if version != "" { - dep.Reference = version - } - - // When retriving from an insecure location set the repo to the - // insecure location. - if insecure { - dep.Repository = "http://" + root - } - - subpkg := strings.TrimPrefix(name, root) - if len(subpkg) > 0 && subpkg != "/" { - dep.Subpackages = []string{subpkg} - } - - if dep.Reference != "" { - Info("Importing %s with the version %s", dep.Name, dep.Reference) - } else { - Info("Importing %s", dep.Name) - } - - conf.Imports = append(conf.Imports, dep) - - deps = append(deps, dep) - - } - - Info("Walking the dependency tree to calculate versions") - return deps, nil -} - -// 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 -} - -// SetReference is a command to set the VCS reference (commit id, tag, etc) for -// a project. -func SetReference(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - conf := p.Get("conf", nil).(*cfg.Config) - cwd, err := VendorPath(c) - if err != nil { - return false, err - } - - if len(conf.Imports) == 0 { - Info("No references set.\n") - return false, nil - } - // - // for _, dep := range conf.Imports { - // if err := VcsVersion(dep, cwd); err != nil { - // Warn("Failed to set version on %s to %s: %s\n", dep.Name, dep.Reference, err) - // } - // } - - 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 { - Warn("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 { - 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 true, nil -} - -// filterArchOs indicates a dependency should be filtered out because it is -// the wrong GOOS or GOARCH. -func filterArchOs(dep *cfg.Dependency) bool { - found := false - if len(dep.Arch) > 0 { - for _, a := range dep.Arch { - if a == runtime.GOARCH { - found = true - } - } - // If it's not found, it should be filtered out. - if !found { - return true - } - } - - found = false - if len(dep.Os) > 0 { - for _, o := range dep.Os { - if o == runtime.GOOS { - found = true - } - } - if !found { - return true - } - - } - - return false -} - -// VcsExists checks if the directory has a local VCS checkout. -func VcsExists(dep *cfg.Dependency, dest string) bool { - repo, err := dep.GetRepo(dest) - if err != nil { - return false - } - - return repo.CheckLocal() -} - -// VcsGet figures out how to fetch a dependency, and then gets it. -// -// VcsGet installs into the dest. -func VcsGet(dep *cfg.Dependency, dest, home string, cache, cacheGopath, useGopath bool) error { - // When not skipping the $GOPATH look in it for a copy of the package - if useGopath { - // Check if the $GOPATH has a viable version to use and if so copy to vendor - gps := Gopaths() - for _, p := range gps { - d := filepath.Join(p, "src", filepath.FromSlash(dep.Name)) - if _, err := os.Stat(d); err == nil { - empty, err := isDirectoryEmpty(d) - if empty || err != nil { - continue - } - - repo, err := dep.GetRepo(d) - if err != nil { - continue - } - - // Dirty repos have uncomitted changes. - if repo.IsDirty() { - continue - } - - // Having found a repo we copy it to vendor and update it. - Debug("Found %s in GOPATH at %s. Copying to %s", dep.Name, d, dest) - err = copyDir(d, dest) - if err != nil { - return err - } - - // Update the repo in the vendor directory - Debug("Updating %s, now in the vendor path at %s", dep.Name, dest) - repo, err = dep.GetRepo(dest) - if err != nil { - return err - } - err = repo.Update() - if err != nil { - return err - } - - // If there is no reference set on the dep we try to checkout - // the default branch. - if dep.Reference == "" { - db := defaultBranch(repo, home) - if db != "" { - err = repo.UpdateVersion(db) - if err != nil { - Debug("Attempting to set the version on %s to %s failed. Error %s", dep.Name, db, err) - } - } - } - return nil - } - } - } - - // When opting in to cache in the GOPATH attempt to do put a copy there. - if cacheGopath { - - // Since we didn't find an existing copy in the GOPATHs try to clone there. - gp := Gopath() - if gp != "" { - d := filepath.Join(gp, "src", filepath.FromSlash(dep.Name)) - if _, err := os.Stat(d); os.IsNotExist(err) { - // Empty directory so we checkout out the code here. - Debug("Retrieving %s to %s before copying to vendor", dep.Name, d) - repo, err := dep.GetRepo(d) - if err != nil { - return err - } - repo.Get() - - branch := findCurrentBranch(repo) - if branch != "" { - // we know the default branch so we can store it in the cache - var loc string - if dep.Repository != "" { - loc = dep.Repository - } else { - loc = "https://" + dep.Name - } - key, err := cacheCreateKey(loc) - if err == nil { - Debug("Saving default branch for %s", repo.Remote()) - c := cacheRepoInfo{DefaultBranch: branch} - err = saveCacheRepoData(key, c, home) - if err == errCacheDisabled { - Debug("Unable to cache default branch because caching is disabled") - } - } - } - - Debug("Copying %s from GOPATH at %s to %s", dep.Name, d, dest) - err = copyDir(d, dest) - if err != nil { - return err - } - - return nil - } - } - } - - // If opting in to caching attempt to put it in the cache folder - if cache { - // Check if the cache has a viable version and try to use that. - var loc string - if dep.Repository != "" { - loc = dep.Repository - } else { - loc = "https://" + dep.Name - } - key, err := cacheCreateKey(loc) - if err == nil { - d := filepath.Join(home, "cache", "src", key) - - repo, err := dep.GetRepo(d) - if err != nil { - return err - } - // If the directory does not exist this is a first cache. - if _, err = os.Stat(d); os.IsNotExist(err) { - Debug("Adding %s to the cache for the first time", dep.Name) - err = repo.Get() - if err != nil { - return err - } - branch := findCurrentBranch(repo) - if branch != "" { - // we know the default branch so we can store it in the cache - var loc string - if dep.Repository != "" { - loc = dep.Repository - } else { - loc = "https://" + dep.Name - } - key, err := cacheCreateKey(loc) - if err == nil { - Debug("Saving default branch for %s", repo.Remote()) - c := cacheRepoInfo{DefaultBranch: branch} - err = saveCacheRepoData(key, c, home) - if err == errCacheDisabled { - Debug("Unable to cache default branch because caching is disabled") - } else if err != nil { - Debug("Error saving %s to cache. Error: %s", repo.Remote(), err) - } - } - } - - } else { - Debug("Updating %s in the cache", dep.Name) - err = repo.Update() - if err != nil { - return err - } - } - - Debug("Copying %s from the cache to %s", dep.Name, dest) - err = copyDir(d, dest) - if err != nil { - return err - } - - return nil - } else { - Warn("Cache key generation error: %s", err) - } - } - - // If unable to cache pull directly into the vendor/ directory. - repo, err := dep.GetRepo(dest) - if err != nil { - return err - } - - gerr := repo.Get() - - // Attempt to cache the default branch - branch := findCurrentBranch(repo) - if branch != "" { - // we know the default branch so we can store it in the cache - var loc string - if dep.Repository != "" { - loc = dep.Repository - } else { - loc = "https://" + dep.Name - } - key, err := cacheCreateKey(loc) - if err == nil { - Debug("Saving default branch for %s", repo.Remote()) - c := cacheRepoInfo{DefaultBranch: branch} - err = saveCacheRepoData(key, c, home) - if err == errCacheDisabled { - Debug("Unable to cache default branch because caching is disabled") - } else if err != nil { - Debug("Error saving %s to cache - Error: %s", repo.Remote(), err) - } - } - } - - return gerr -} - -// VcsUpdate updates to a particular checkout based on the VCS setting. -func VcsUpdate(dep *cfg.Dependency, vend, home string, force, cache, cacheGopath, useGopath 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 := filepath.Join(vend, filepath.FromSlash(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, useGopath); 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 updatingVendored == false && 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 { - - if updatingVendored == true && empty == false && err == v.ErrCannotDetectVCS { - // A vendored package, no repo, and updating the vendored packages - // has been opted into. - Info("%s is a vendored package. Updating.", dep.Name) - err = os.RemoveAll(dest) - if err != nil { - 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 { - 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 - } - - 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 { - 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 { - 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 -} - -// VcsVersion set the VCS version for a checkout. -func VcsVersion(dep *cfg.Dependency, vend string) error { - cwd := filepath.Join(vend, filepath.FromSlash(dep.Name)) - - // If there is no refernece 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 := 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 - } - dep.Pin, err = repo.Version() - if err != nil { - return err - } - } - - return nil -} - -// VcsLastCommit gets the last commit ID from the given dependency. -func VcsLastCommit(dep *cfg.Dependency, vend string) (string, error) { - cwd := filepath.Join(vend, filepath.FromSlash(dep.Name)) - repo, err := dep.GetRepo(cwd) - if err != nil { - return "", err - } - - if repo.CheckLocal() == false { - return "", fmt.Errorf("%s is not a VCS repo\n", dep.Name) - } - - version, err := repo.Version() - if err != nil { - return "", err - } - - return version, nil -} - -// Some repos will have multiple branches in them (e.g. Git) while others -// (e.g. Svn) will not. -func defaultBranch(repo v.Repo, home string) string { - - // Svn and Bzr use different locations (paths or entire locations) - // for branches so we won't have a default branch. - if repo.Vcs() == v.Svn || repo.Vcs() == v.Bzr { - return "" - } - - // Check the cache for a value. - key, kerr := cacheCreateKey(repo.Remote()) - var d cacheRepoInfo - if kerr == nil { - d, err := cacheRepoData(key, home) - if err == nil { - if d.DefaultBranch != "" { - return d.DefaultBranch - } - } - } - - // If we don't have it in the store try some APIs - r := repo.Remote() - u, err := url.Parse(r) - if err != nil { - return "" - } - if u.Scheme == "" { - // Where there is no scheme we try urls like git@github.com:foo/bar - r = strings.Replace(r, ":", "/", -1) - r = "ssh://" + r - u, err = url.Parse(r) - if err != nil { - return "" - } - u.Scheme = "" - } - if u.Host == "github.com" { - parts := strings.Split(u.Path, "/") - if len(parts) != 2 { - return "" - } - api := fmt.Sprintf("https://api.github.com/repos/%s/%s", parts[0], parts[1]) - resp, err := http.Get(api) - if err != nil { - return "" - } - defer resp.Body.Close() - if resp.StatusCode >= 300 || resp.StatusCode < 200 { - return "" - } - body, err := ioutil.ReadAll(resp.Body) - var data interface{} - err = json.Unmarshal(body, &data) - if err != nil { - return "" - } - gh := data.(map[string]interface{}) - db := gh["default_branch"].(string) - if kerr == nil { - d.DefaultBranch = db - err := saveCacheRepoData(key, d, home) - if err == errCacheDisabled { - Debug("Unable to cache default branch because caching is disabled") - } else if err != nil { - Debug("Error saving %s to cache. Error: %s", repo.Remote(), err) - } - } - return db - } - - if u.Host == "bitbucket.org" { - parts := strings.Split(u.Path, "/") - if len(parts) != 2 { - return "" - } - api := fmt.Sprintf("https://bitbucket.org/api/1.0/repositories/%s/%s/main-branch/", parts[0], parts[1]) - resp, err := http.Get(api) - if err != nil { - return "" - } - defer resp.Body.Close() - if resp.StatusCode >= 300 || resp.StatusCode < 200 { - return "" - } - body, err := ioutil.ReadAll(resp.Body) - var data interface{} - err = json.Unmarshal(body, &data) - if err != nil { - return "" - } - bb := data.(map[string]interface{}) - db := bb["name"].(string) - if kerr == nil { - d.DefaultBranch = db - err := saveCacheRepoData(key, d, home) - if err == errCacheDisabled { - Debug("Unable to cache default branch because caching is disabled") - } else if err != nil { - Debug("Error saving %s to cache. Error: %s", repo.Remote(), err) - } - } - return db - } - - return "" -} - -// From a local repo find out the current branch name if there is one. -func findCurrentBranch(repo v.Repo) string { - Debug("Attempting to find current branch for %s", repo.Remote()) - // Svn and Bzr don't have default branches. - if repo.Vcs() == v.Svn || repo.Vcs() == v.Bzr { - return "" - } - - if repo.Vcs() == v.Git { - c := exec.Command("git", "symbolic-ref", "--short", "HEAD") - c.Dir = repo.LocalPath() - c.Env = envForDir(c.Dir) - out, err := c.CombinedOutput() - if err != nil { - Debug("Unable to find current branch for %s, error: %s", repo.Remote(), err) - return "" - } - return strings.TrimSpace(string(out)) - } - - if repo.Vcs() == v.Hg { - c := exec.Command("hg", "branch") - c.Dir = repo.LocalPath() - c.Env = envForDir(c.Dir) - out, err := c.CombinedOutput() - if err != nil { - Debug("Unable to find current branch for %s, error: %s", repo.Remote(), err) - return "" - } - return strings.TrimSpace(string(out)) - } - - return "" -} - -// list2map takes a list of packages names and creates a map of normalized names. -func list2map(in []string) map[string]bool { - out := make(map[string]bool, len(in)) - for _, v := range in { - v, _ := NormalizeName(v) - out[v] = true - } - return out -} - -func envForDir(dir string) []string { - env := os.Environ() - return mergeEnvLists([]string{"PWD=" + dir}, env) -} - -func mergeEnvLists(in, out []string) []string { -NextVar: - for _, inkv := range in { - k := strings.SplitAfterN(inkv, "=", 2)[0] - for i, outkv := range out { - if strings.HasPrefix(outkv, k) { - out[i] = inkv - continue NextVar - } - } - out = append(out, inkv) - } - return out -} diff --git a/cmd/get_imports_test.go b/cmd/get_imports_test.go deleted file mode 100644 index b072ed40..00000000 --- a/cmd/get_imports_test.go +++ /dev/null @@ -1,8 +0,0 @@ -package cmd - -import "github.com/Masterminds/cookoo" - -func SilenceLogs(c cookoo.Context) { - p := cookoo.NewParamsWithValues(map[string]interface{}{"quiet": true}) - BeQuiet(c, p) -} diff --git a/cmd/godeps.go b/cmd/godeps.go deleted file mode 100644 index ac122923..00000000 --- a/cmd/godeps.go +++ /dev/null @@ -1,108 +0,0 @@ -package cmd - -import ( - "encoding/json" - "os" - "path/filepath" - "strings" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" - "github.com/Masterminds/glide/util" -) - -// This file contains commands for working with Godep. - -// The Godeps struct from Godep. -// -// https://raw.githubusercontent.com/tools/godep/master/dep.go -// -// We had to copy this because it's in the package main for Godep. -type Godeps struct { - ImportPath string - GoVersion string - Packages []string `json:",omitempty"` // Arguments to save, if any. - Deps []GodepDependency - - outerRoot string -} - -// GodepDependency is a modified version of Godep's Dependency struct. -// It drops all of the unexported fields. -type GodepDependency struct { - ImportPath string - Comment string `json:",omitempty"` // Description of commit, if present. - Rev string // VCS-specific commit ID. -} - -// HasGodepGodeps is a command to detect if a package contains a Godeps.json file. -func HasGodepGodeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - dir := cookoo.GetString("dir", "", p) - path := filepath.Join(dir, "Godeps", "Godeps.json") - _, err := os.Stat(path) - return err == nil, nil -} - -// ParseGodepGodeps parses the Godep Godeps.json file. -// -// Params: -// - dir (string): the project's directory -// -// Returns an []*cfg.Dependency -func ParseGodepGodeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - dir := cookoo.GetString("dir", "", p) - return parseGodepGodeps(dir) -} -func parseGodepGodeps(dir string) ([]*cfg.Dependency, error) { - path := filepath.Join(dir, "Godeps", "Godeps.json") - if _, err := os.Stat(path); err != nil { - return []*cfg.Dependency{}, nil - } - Info("Found Godeps.json file.\n") - - buf := []*cfg.Dependency{} - - godeps := new(Godeps) - - // Get a handle to the file. - file, err := os.Open(path) - if err != nil { - return buf, err - } - defer file.Close() - - dec := json.NewDecoder(file) - if err := dec.Decode(godeps); err != nil { - return buf, err - } - - // Info("Importing %d packages from %s.\n", len(godeps.Deps), godeps.ImportPath) - seen := map[string]bool{} - - for _, d := range godeps.Deps { - // Info("Adding package %s\n", d.ImportPath) - pkg := util.GetRootFromPackage(d.ImportPath) - sub := strings.TrimPrefix(d.ImportPath, pkg) - sub = strings.TrimPrefix(sub, "/") - if _, ok := seen[pkg]; ok { - if len(sub) == 0 { - continue - } - // Modify existing dep with additional subpackages. - for _, dep := range buf { - if dep.Name == pkg { - dep.Subpackages = append(dep.Subpackages, sub) - } - } - } else { - seen[pkg] = true - dep := &cfg.Dependency{Name: pkg, Reference: d.Rev} - if len(sub) > 0 { - dep.Subpackages = []string{sub} - } - buf = append(buf, dep) - } - } - - return buf, nil -} diff --git a/cmd/gpm.go b/cmd/gpm.go deleted file mode 100644 index eef097f6..00000000 --- a/cmd/gpm.go +++ /dev/null @@ -1,110 +0,0 @@ -package cmd - -import ( - "bufio" - "os" - "path/filepath" - "strings" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" -) - -// This file contains commands for working with GPM/GVP. - -// HasGPMGodeps indicates whether a Godeps file exists. -func HasGPMGodeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - dir := cookoo.GetString("dir", "", p) - path := filepath.Join(dir, "Godeps") - _, err := os.Stat(path) - return err == nil, nil -} - -// GPMGodeps parses a GPM-flavored Godeps file. -// -// Params -// - dir (string): Directory root. -// -// Returns an []*cfg.Dependency -func GPMGodeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - dir := cookoo.GetString("dir", "", p) - return parseGPMGodeps(dir) -} -func parseGPMGodeps(dir string) ([]*cfg.Dependency, error) { - path := filepath.Join(dir, "Godeps") - if i, err := os.Stat(path); err != nil { - return []*cfg.Dependency{}, nil - } else if i.IsDir() { - Info("Godeps is a directory. This is probably a Godep project.\n") - return []*cfg.Dependency{}, nil - } - Info("Found Godeps file.\n") - - buf := []*cfg.Dependency{} - - file, err := os.Open(path) - if err != nil { - return buf, err - } - scanner := bufio.NewScanner(file) - for scanner.Scan() { - parts, ok := parseGodepsLine(scanner.Text()) - if ok { - dep := &cfg.Dependency{Name: parts[0]} - if len(parts) > 1 { - dep.Reference = parts[1] - } - buf = append(buf, dep) - } - } - if err := scanner.Err(); err != nil { - Warn("Scan failed: %s\n", err) - return buf, err - } - - return buf, nil -} - -// GPMGodepsGit reads a Godeps-Git file for gpm-git. -func GPMGodepsGit(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - dir := cookoo.GetString("dir", "", p) - path := filepath.Join(dir, "Godeps-Git") - if _, err := os.Stat(path); err != nil { - return []*cfg.Dependency{}, nil - } - Info("Found Godeps-Git file.\n") - - buf := []*cfg.Dependency{} - - file, err := os.Open(path) - if err != nil { - return buf, err - } - scanner := bufio.NewScanner(file) - for scanner.Scan() { - parts, ok := parseGodepsLine(scanner.Text()) - if ok { - dep := &cfg.Dependency{Name: parts[1], Repository: parts[0]} - if len(parts) > 2 { - dep.Reference = parts[2] - } - buf = append(buf, dep) - } - } - if err := scanner.Err(); err != nil { - Warn("Scan failed: %s\n", err) - return buf, err - } - - return buf, nil -} - -func parseGodepsLine(line string) ([]string, bool) { - line = strings.TrimSpace(line) - - if len(line) == 0 || strings.HasPrefix(line, "#") { - return []string{}, false - } - - return strings.Fields(line), true -} diff --git a/cmd/guess_deps.go b/cmd/guess_deps.go deleted file mode 100644 index 25c833bc..00000000 --- a/cmd/guess_deps.go +++ /dev/null @@ -1,171 +0,0 @@ -package cmd - -import ( - "os" - "path/filepath" - "sort" - "strings" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" - "github.com/Masterminds/glide/dependency" - "github.com/Masterminds/glide/util" -) - -// GuessDeps tries to get the dependencies for the current directory. -// -// Params -// - dirname (string): Directory to use as the base. Default: "." -// - skipImport (book): Whether to skip importing from Godep, GPM, and gb -func GuessDeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - buildContext, err := util.GetBuildContext() - if err != nil { - return nil, err - } - base := p.Get("dirname", ".").(string) - skipImport := p.Get("skipImport", false).(bool) - name := guessPackageName(buildContext, base) - - Info("Generating a YAML configuration file and guessing the dependencies") - - config := new(cfg.Config) - - // Get the name of the top level package - config.Name = name - - // Import by looking at other package managers and looking over the - // entire directory structure. - - // Attempt to import from other package managers. - if !skipImport { - Info("Attempting to import from other package managers (use --skip-import to skip)") - deps := []*cfg.Dependency{} - absBase, err := filepath.Abs(base) - if err != nil { - return nil, err - } - - if d, ok := guessImportGodep(absBase); ok { - Info("Importing Godep configuration") - Warn("Godep uses commit id versions. Consider using Semantic Versions with Glide") - deps = d - } else if d, ok := guessImportGPM(absBase); ok { - Info("Importing GPM configuration") - deps = d - } else if d, ok := guessImportGB(absBase); ok { - Info("Importing GB configuration") - deps = d - } - - for _, i := range deps { - Info("Found imported reference to %s\n", i.Name) - config.Imports = append(config.Imports, i) - } - } - - // Resolve dependencies by looking at the tree. - r, err := dependency.NewResolver(base) - if err != nil { - return nil, err - } - - h := &dependency.DefaultMissingPackageHandler{Missing: []string{}, Gopath: []string{}} - r.Handler = h - - sortable, err := r.ResolveLocal(false) - if err != nil { - return nil, err - } - - sort.Strings(sortable) - - vpath := r.VendorDir - if !strings.HasSuffix(vpath, string(os.PathSeparator)) { - vpath = vpath + string(os.PathSeparator) - } - - for _, pa := range sortable { - n := strings.TrimPrefix(pa, vpath) - root := util.GetRootFromPackage(n) - - if !config.HasDependency(root) { - Info("Found reference to %s\n", n) - d := &cfg.Dependency{ - Name: root, - } - subpkg := strings.TrimPrefix(n, root) - if len(subpkg) > 0 && subpkg != "/" { - d.Subpackages = []string{subpkg} - } - config.Imports = append(config.Imports, d) - } else { - subpkg := strings.TrimPrefix(n, root) - if len(subpkg) > 0 && subpkg != "/" { - subpkg = strings.TrimPrefix(subpkg, "/") - d := config.Imports.Get(root) - f := false - for _, v := range d.Subpackages { - if v == subpkg { - f = true - } - } - if !f { - Info("Adding sub-package %s to %s\n", subpkg, root) - d.Subpackages = append(d.Subpackages, subpkg) - } - } - } - } - - return config, nil -} - -// Attempt to guess at the package name at the top level. When unable to detect -// a name goes to default of "main". -// -// DEPRECATED. Use BuildCtxt.PackageName(base) -func guessPackageName(b *util.BuildCtxt, base string) string { - cwd, err := os.Getwd() - if err != nil { - return "main" - } - - pkg, err := b.Import(base, cwd, 0) - if err != nil { - // There may not be any top level Go source files but the project may - // still be within the GOPATH. - if strings.HasPrefix(base, b.GOPATH) { - p := strings.TrimPrefix(base, b.GOPATH) - return strings.Trim(p, string(os.PathSeparator)) - } - } - - return pkg.ImportPath -} - -func guessImportGodep(dir string) ([]*cfg.Dependency, bool) { - d, err := parseGodepGodeps(dir) - if err != nil || len(d) == 0 { - return []*cfg.Dependency{}, false - } - - return d, true -} - -func guessImportGPM(dir string) ([]*cfg.Dependency, bool) { - d, err := parseGPMGodeps(dir) - if err != nil || len(d) == 0 { - return []*cfg.Dependency{}, false - } - - return d, true -} - -func guessImportGB(dir string) ([]*cfg.Dependency, bool) { - d, err := parseGbManifest(dir) - if err != nil || len(d) == 0 { - return []*cfg.Dependency{}, false - } - - return d, true -} diff --git a/cmd/install.go b/cmd/install.go deleted file mode 100644 index ea4b86a6..00000000 --- a/cmd/install.go +++ /dev/null @@ -1,142 +0,0 @@ -package cmd - -import ( - "io/ioutil" - "os" - "sync" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" -) - -// LockFileExists checks if a lock file exists. If not it jumps to the update -// command. -func LockFileExists(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - fname := p.Get("filename", "glide.lock").(string) - if _, err := os.Stat(fname); err != nil { - Info("Lock file (glide.lock) does not exist. Performing update.") - return false, &cookoo.Reroute{"update"} - } - - return true, nil -} - -// LoadLockFile loads the lock file to the context and checks if it is correct -// for the loaded cfg file. -func LoadLockFile(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - fname := p.Get("filename", "glide.lock").(string) - conf := p.Get("conf", nil).(*cfg.Config) - - yml, err := ioutil.ReadFile(fname) - if err != nil { - return nil, err - } - lock, err := cfg.LockfileFromYaml(yml) - if err != nil { - return nil, err - } - - hash, err := conf.Hash() - if err != nil { - return nil, err - } - - if hash != lock.Hash { - Warn("Lock file may be out of date. Hash check of YAML failed. You may need to run 'update'") - } - - return lock, nil -} - -// Install installs the dependencies from a Lockfile. -func Install(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - lock := p.Get("lock", nil).(*cfg.Lockfile) - conf := p.Get("conf", nil).(*cfg.Config) - force := p.Get("force", true).(bool) - home := p.Get("home", "").(string) - cache := p.Get("cache", false).(bool) - cacheGopath := p.Get("cacheGopath", false).(bool) - useGopath := p.Get("useGopath", false).(bool) - - cwd, err := VendorPath(c) - if err != nil { - return false, 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 { - Info("No dependencies found. Nothing installed.\n") - return false, nil - } - - // for _, dep := range newConf.Imports { - // if err := VcsUpdate(dep, cwd, home, force, cache, cacheGopath, useGopath); err != nil { - // Warn("Update failed for %s: %s\n", dep.Name, err) - // } - // } - - 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 := VcsUpdate(dep, cwd, home, force, cache, cacheGopath, useGopath); err != nil { - Warn("Update failed for %s: %s\n", dep.Name, err) - } - wg.Done() - case <-done: - return - } - } - }(in) - } - - for _, dep := range newConf.Imports { - wg.Add(1) - in <- dep - } - - wg.Wait() - // Close goroutines setting the version - for i := 0; i < concurrentWorkers; i++ { - done <- struct{}{} - } - - return newConf, nil -} diff --git a/cmd/link_package.go b/cmd/link_package.go deleted file mode 100644 index 214b0944..00000000 --- a/cmd/link_package.go +++ /dev/null @@ -1,50 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "path" - "strings" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" -) - -// LinkPackage creates a symlink to the project within the GOPATH. -func LinkPackage(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - conf := c.Get("cfg", "").(*cfg.Config) - pname := p.Get("path", conf.Name).(string) - - // Per issue #10, this may be nicer to work with in cases where repos are - // moved. - //here := "../.." - depth := strings.Count(pname, "/") - here := "../.." + strings.Repeat("/..", depth) - - gopath := Gopath() - if gopath == "" { - return nil, fmt.Errorf("$GOPATH appears to be unset") - } - if len(pname) == 0 { - return nil, fmt.Errorf("glide.yaml is missing 'package:'") - } - - base := path.Dir(pname) - if base != "." { - dir := fmt.Sprintf("%s/src/%s", gopath, base) - if err := os.MkdirAll(dir, os.ModeDir|0755); err != nil { - return nil, fmt.Errorf("Failed to make directory %s: %s", dir, err) - } - } - - ldest := fmt.Sprintf("%s/src/%s", gopath, pname) - if err := os.Symlink(here, ldest); err != nil { - if os.IsExist(err) { - Info("Link to %s already exists. Skipping.\n", ldest) - } else { - return nil, fmt.Errorf("Failed to create symlink from %s to %s: %s", gopath, ldest, err) - } - } - - return ldest, nil -} diff --git a/cmd/mkdir.go b/cmd/mkdir.go deleted file mode 100644 index d4788451..00000000 --- a/cmd/mkdir.go +++ /dev/null @@ -1,23 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - - "github.com/Masterminds/cookoo" -) - -// Mkdir creates the src directory within the GOPATH. -func Mkdir(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - - target := p.Get("dir", "").(string) - if len(target) == 0 { - return nil, fmt.Errorf("Vendor path appears to be unset") - } - - if err := os.MkdirAll(target, os.ModeDir|0755); err != nil { - return false, fmt.Errorf("Failed to make directory %s: %s", target, err) - } - - return true, nil -} diff --git a/cmd/msg.go b/cmd/msg.go deleted file mode 100644 index a6dcc143..00000000 --- a/cmd/msg.go +++ /dev/null @@ -1,100 +0,0 @@ -// +build !windows - -package cmd - -import ( - "fmt" - "os" - "strings" - "sync" -) - -// These contanstants map to color codes for shell scripts making them -// human readable. -const ( - Blue = "0;34" - Red = "0;31" - Green = "0;32" - Yellow = "0;33" - Cyan = "0;36" - Pink = "1;35" -) - -var outputLock sync.Mutex - -// Color returns a string in a certain color. The first argument is a string -// containing the color code or a constant from the table above mapped to a code. -// -// The following will print the string "Foo" in yellow: -// fmt.Print(Color(Yellow, "Foo")) -func Color(code, msg string) string { - if NoColor { - return msg - } - return fmt.Sprintf("\033[%sm%s\033[m", code, msg) -} - -// Info logs information -func Info(msg string, args ...interface{}) { - if Quiet { - return - } - i := fmt.Sprint(Color(Green, "[INFO] ")) - Msg(i+msg, args...) -} - -// Debug logs debug information -func Debug(msg string, args ...interface{}) { - if Quiet || !IsDebugging { - return - } - i := fmt.Sprint("[DEBUG] ") - Msg(i+msg, args...) -} - -// Warn logs a warning -func Warn(msg string, args ...interface{}) { - i := fmt.Sprint(Color(Yellow, "[WARN] ")) - ErrMsg(i+msg, args...) -} - -// Error logs and error. -func Error(msg string, args ...interface{}) { - i := fmt.Sprint(Color(Red, "[ERROR] ")) - ErrMsg(i+msg, args...) -} - -// ErrMsg sends a message to Stderr -func ErrMsg(msg string, args ...interface{}) { - outputLock.Lock() - defer outputLock.Unlock() - - // If messages don't have a newline on the end we add one. - e := "" - if !strings.HasSuffix(msg, "\n") { - e = "\n" - } - if len(args) == 0 { - fmt.Fprint(os.Stderr, msg+e) - } else { - fmt.Fprintf(os.Stderr, msg+e, args...) - } -} - -// Msg prints a message with optional arguments, that can be printed, of -// varying types. -func Msg(msg string, args ...interface{}) { - outputLock.Lock() - defer outputLock.Unlock() - - // If messages don't have a newline on the end we add one. - e := "" - if !strings.HasSuffix(msg, "\n") { - e = "\n" - } - if len(args) == 0 { - fmt.Fprint(os.Stderr, msg+e) - } else { - fmt.Fprintf(os.Stderr, msg+e, args...) - } -} diff --git a/cmd/msg_windows.go b/cmd/msg_windows.go deleted file mode 100644 index 6774ebd8..00000000 --- a/cmd/msg_windows.go +++ /dev/null @@ -1,64 +0,0 @@ -// +build windows - -package cmd - -import ( - "fmt" - "os" - "strings" -) - -// Info logs information -func Info(msg string, args ...interface{}) { - if Quiet { - return - } - fmt.Print("[INFO] ") - Msg(msg, args...) -} - -// Debug logs debug information -func Debug(msg string, args ...interface{}) { - if Quiet || !IsDebugging { - return - } - fmt.Print("[DEBUG] ") - Msg(msg, args...) -} - -// Warn logs a warning -func Warn(msg string, args ...interface{}) { - fmt.Fprint(os.Stderr, "[WARN] ") - ErrMsg(msg, args...) -} - -// Error logs and error. -func Error(msg string, args ...interface{}) { - fmt.Fprint(os.Stderr, "[ERROR] ") - ErrMsg(msg, args...) -} - -// ErrMsg sends a message to Stderr -func ErrMsg(msg string, args ...interface{}) { - if len(args) == 0 { - fmt.Fprint(os.Stderr, msg) - return - } - fmt.Fprintf(os.Stderr, msg, args...) -} - -// Msg prints a message with optional arguments, that can be printed, of -// varying types. -func Msg(msg string, args ...interface{}) { - if len(args) == 0 { - fmt.Print(msg) - return - } - fmt.Printf(msg, args...) - - // Get rid of the annoying fact that messages need \n at the end, but do - // it in a backward compatible way. - if !strings.HasSuffix(msg, "\n") { - fmt.Println("") - } -} diff --git a/cmd/novendor.go b/cmd/novendor.go deleted file mode 100644 index b0adcd3d..00000000 --- a/cmd/novendor.go +++ /dev/null @@ -1,134 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/Masterminds/cookoo" -) - -// NoVendor takes a path and returns all subpaths that are not vendor directories. -// -// It is not recursive. -// -// If the given path is a file, it returns that path unaltered. -// -// If the given path is a directory, it scans all of the immediate children, -// and returns all of the go files and directories that are not vendor. -func NoVendor(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - path := p.Get("path", ".").(string) - gonly := p.Get("onlyGo", true).(bool) - - return noVend(path, gonly) -} - -// Take a list of paths and print a single string with space-separated paths. -func PathString(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - paths := p.Get("paths", []string{}).([]string) - s := strings.Join(paths, " ") - fmt.Println(s) - return nil, nil -} - -// noVend takes a directory and returns a list of Go-like files or directories, -// provided the directory is not a vendor directory. -// -// If onlyGo is true, this will filter out all directories that do not contain -// ".go" files. -func noVend(path string, onlyGo bool) ([]string, error) { - - info, err := os.Stat(path) - if err != nil { - return []string{}, err - } - - if !info.IsDir() { - return []string{path}, nil - } - - res := []string{} - f, err := os.Open(path) - if err != nil { - return res, err - } - - fis, err := f.Readdir(0) - if err != nil { - return res, err - } - - cur := false - - for _, fi := range fis { - if exclude(fi) { - continue - } - - full := filepath.Join(path, fi.Name()) - if fi.IsDir() && !isVend(fi) { - p := "./" + full + "/..." - res = append(res, p) - } else if !fi.IsDir() && isGoish(fi) { - //res = append(res, full) - cur = true - } - } - - // Filter out directories that do not contain Go code - if onlyGo { - res = hasGoSource(res) - } - - if cur { - res = append(res, ".") - } - - return res, nil -} - -func hasGoSource(dirs []string) []string { - buf := []string{} - for _, d := range dirs { - d := filepath.Dir(d) - found := false - walker := func(p string, fi os.FileInfo, err error) error { - // Dumb optimization - if found { - return nil - } - - // If the file ends with .go, report a match. - if strings.ToLower(filepath.Ext(p)) == ".go" { - found = true - } - - return nil - } - filepath.Walk(d, walker) - - if found { - buf = append(buf, "./"+d+"/...") - } - } - return buf -} - -func isVend(fi os.FileInfo) bool { - return fi.Name() == "vendor" -} - -func exclude(fi os.FileInfo) bool { - if strings.HasPrefix(fi.Name(), "_") { - return true - } - if strings.HasPrefix(fi.Name(), ".") { - return true - } - return false -} - -func isGoish(fi os.FileInfo) bool { - return filepath.Ext(fi.Name()) == ".go" -} diff --git a/cmd/print_name.go b/cmd/print_name.go deleted file mode 100644 index 6a6d26d3..00000000 --- a/cmd/print_name.go +++ /dev/null @@ -1,17 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" -) - -// PrintName prints the name of the project. -// -// This comes from Config.Name. -func PrintName(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - conf := p.Get("conf", nil).(*cfg.Config) - fmt.Println(conf.Name) - return nil, nil -} diff --git a/cmd/rebuild.go b/cmd/rebuild.go deleted file mode 100644 index 07a14499..00000000 --- a/cmd/rebuild.go +++ /dev/null @@ -1,99 +0,0 @@ -package cmd - -import ( - "os" - "os/exec" - "path" - "path/filepath" - "strings" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" -) - -// Rebuild runs 'go build' in a directory. -// -// Params: -// - conf: the *cfg.Config. -// -func Rebuild(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - conf := p.Get("conf", nil).(*cfg.Config) - vpath, err := VendorPath(c) - if err != nil { - return nil, err - } - - Info("Building dependencies.\n") - - if len(conf.Imports) == 0 { - Info("No dependencies found. Nothing built.\n") - return true, nil - } - - for _, dep := range conf.Imports { - if err := buildDep(c, dep, vpath); err != nil { - Warn("Failed to build %s: %s\n", dep.Name, err) - } - } - - return true, nil -} - -func buildDep(c cookoo.Context, dep *cfg.Dependency, vpath string) error { - if len(dep.Subpackages) == 0 { - buildPath(c, dep.Name) - } - - for _, pkg := range dep.Subpackages { - if pkg == "**" || pkg == "..." { - //Info("Building all packages in %s\n", dep.Name) - buildPath(c, path.Join(dep.Name, "...")) - } else { - paths, err := resolvePackages(vpath, dep.Name, pkg) - if err != nil { - Warn("Error resolving packages: %s", err) - } - buildPaths(c, paths) - } - } - - return nil -} - -func resolvePackages(vpath, pkg, subpkg string) ([]string, error) { - sdir, _ := os.Getwd() - if err := os.Chdir(filepath.Join(vpath, filepath.FromSlash(pkg), filepath.FromSlash(subpkg))); err != nil { - return []string{}, err - } - defer os.Chdir(sdir) - p, err := filepath.Glob(filepath.Join(vpath, filepath.FromSlash(pkg), filepath.FromSlash(subpkg))) - if err != nil { - return []string{}, err - } - for k, v := range p { - nv := strings.TrimPrefix(v, vpath) - p[k] = strings.TrimPrefix(nv, string(filepath.Separator)) - } - return p, nil -} - -func buildPaths(c cookoo.Context, paths []string) error { - for _, path := range paths { - if err := buildPath(c, path); err != nil { - return err - } - } - - return nil -} - -func buildPath(c cookoo.Context, path string) error { - Info("Running go build %s\n", path) - // . in a filepath.Join is removed so it needs to be prepended separately. - p := "." + string(filepath.Separator) + filepath.Join("vendor", filepath.FromSlash(path)) - out, err := exec.Command("go", "install", p).CombinedOutput() - if err != nil { - Warn("Failed to run 'go install' for %s: %s", path, string(out)) - } - return err -} diff --git a/cmd/semver.go b/cmd/semver.go deleted file mode 100644 index 566f431e..00000000 --- a/cmd/semver.go +++ /dev/null @@ -1,48 +0,0 @@ -package cmd - -import ( - "github.com/Masterminds/semver" - "github.com/Masterminds/vcs" -) - -// Filter a list of versions to only included semantic versions. The response -// is a mapping of the original version to the semantic version. -func getSemVers(refs []string) []*semver.Version { - sv := []*semver.Version{} - for _, r := range refs { - v, err := semver.NewVersion(r) - if err == nil { - sv = append(sv, v) - } - } - - return sv -} - -// Get all the references for a repo. This includes the tags and branches. -func getAllVcsRefs(repo vcs.Repo) ([]string, error) { - tags, err := repo.Tags() - if err != nil { - return []string{}, err - } - - branches, err := repo.Branches() - if err != nil { - return []string{}, err - } - - return append(branches, tags...), nil -} - -func isBranch(branch string, repo vcs.Repo) (bool, error) { - branches, err := repo.Branches() - if err != nil { - return false, err - } - for _, b := range branches { - if b == branch { - return true, nil - } - } - return false, nil -} diff --git a/cmd/tree.go b/cmd/tree.go deleted file mode 100644 index 252405e0..00000000 --- a/cmd/tree.go +++ /dev/null @@ -1,331 +0,0 @@ -package cmd - -import ( - "container/list" - "fmt" - "os" - "path/filepath" - "sort" - "strings" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/dependency" - "github.com/Masterminds/glide/msg" - "github.com/Masterminds/glide/util" -) - -// Tree prints a tree representing dependencies. -func Tree(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - buildContext, err := util.GetBuildContext() - if err != nil { - return nil, err - } - showcore := p.Get("showcore", false).(bool) - basedir := p.Get("dir", ".").(string) - myName := guessPackageName(buildContext, basedir) - - if basedir == "." { - var err error - basedir, err = os.Getwd() - if err != nil { - Error("Could not get working directory") - return nil, err - } - } - - fmt.Println(myName) - l := list.New() - l.PushBack(myName) - displayTree(buildContext, basedir, myName, 1, showcore, l) - return nil, nil -} - -// ListDeps lists all of the dependencies of the current project. -// -// Params: -// - dir (string): basedir -// - deep (bool): whether to do a deep scan or a shallow scan -// -// Returns: -// -func ListDeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - basedir := p.Get("dir", ".").(string) - deep := p.Get("deep", true).(bool) - - basedir, err := filepath.Abs(basedir) - if err != nil { - return nil, err - } - - r, err := dependency.NewResolver(basedir) - if err != nil { - return nil, err - } - h := &dependency.DefaultMissingPackageHandler{Missing: []string{}, Gopath: []string{}} - r.Handler = h - - sortable, err := r.ResolveLocal(deep) - if err != nil { - return nil, err - } - - sort.Strings(sortable) - - fmt.Println("INSTALLED packages:") - for _, k := range sortable { - v, err := filepath.Rel(basedir, k) - if err != nil { - msg.Warn("Failed to Rel path: %s", err) - v = k - } - fmt.Printf("\t%s\n", v) - } - - if len(h.Missing) > 0 { - fmt.Println("\nMISSING packages:") - for _, pkg := range h.Missing { - fmt.Printf("\t%s\n", pkg) - } - } - if len(h.Gopath) > 0 { - fmt.Println("\nGOPATH packages:") - for _, pkg := range h.Gopath { - fmt.Printf("\t%s\n", pkg) - } - } - - return nil, nil -} - -func listDeps(b *util.BuildCtxt, info map[string]*pinfo, name, path string) { - found := findPkg(b, name, path) - switch found.PType { - case ptypeUnknown: - info[name] = found - break - case ptypeGoroot, ptypeCgo: - break - default: - info[name] = found - for _, i := range walkDeps(b, found.Path, found.Name) { - // Only walk the deps that are not already found to avoid - // infinite recursion. - if _, f := info[found.Name]; f == false { - listDeps(b, info, i, found.Path) - } - } - } -} - -func displayTree(b *util.BuildCtxt, basedir, myName string, level int, core bool, l *list.List) { - deps := walkDeps(b, basedir, myName) - for _, name := range deps { - found := findPkg(b, name, basedir) - if found.PType == ptypeUnknown { - msg := "glide get " + found.Name - fmt.Printf("\t%s\t(%s)\n", found.Name, msg) - continue - } - if !core && found.PType == ptypeGoroot || found.PType == ptypeCgo { - continue - } - fmt.Print(strings.Repeat("\t", level)) - - f := findInList(found.Name, l) - if f == true { - fmt.Printf("(Recursion) %s (%s)\n", found.Name, found.Path) - } else { - // Every branch in the tree is a copy to handle all the branches - cl := copyList(l) - cl.PushBack(found.Name) - fmt.Printf("%s (%s)\n", found.Name, found.Path) - displayTree(b, found.Path, found.Name, level+1, core, cl) - } - } -} - -type ptype int8 - -const ( - ptypeUnknown ptype = iota - ptypeLocal - ptypeVendor - ptypeGopath - ptypeGoroot - ptypeCgo -) - -func ptypeString(t ptype) string { - switch t { - case ptypeLocal: - return "local" - case ptypeVendor: - return "vendored" - case ptypeGopath: - return "gopath" - case ptypeGoroot: - return "core" - case ptypeCgo: - return "cgo" - default: - return "missing" - } -} - -type pinfo struct { - Name, Path string - PType ptype - Vendored bool -} - -func findPkg(b *util.BuildCtxt, name, cwd string) *pinfo { - var fi os.FileInfo - var err error - var p string - - info := &pinfo{ - Name: name, - } - - // Recurse backward to scan other vendor/ directories - // If the cwd isn't an absolute path walking upwards looking for vendor/ - // folders can get into an infinate loop. - abs, err := filepath.Abs(cwd) - if err != nil { - abs = cwd - } - if abs != "." { - - // Previously there was a check on the loop that wd := "/". The path - // "/" is a POSIX path so this fails on Windows. Now the check is to - // make sure the same wd isn't seen twice. When the same wd happens - // more than once it's the beginning of looping on the same location - // which is the top level. - pwd := "" - for wd := abs; wd != pwd; wd = filepath.Dir(wd) { - pwd = wd - - // Don't look for packages outside the GOPATH - // Note, the GOPATH may or may not end with the path separator. - // The output of filepath.Dir does not the the path separator on the - // end so we need to test both. - if wd == b.GOPATH || wd+string(os.PathSeparator) == b.GOPATH { - break - } - p = filepath.Join(wd, "vendor", filepath.FromSlash(name)) - if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) { - info.Path = p - info.PType = ptypeVendor - info.Vendored = true - return info - } - } - } - // Check $GOPATH - for _, r := range filepath.SplitList(b.GOPATH) { - p = filepath.Join(r, "src", filepath.FromSlash(name)) - if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) { - info.Path = p - info.PType = ptypeGopath - return info - } - } - - // Check $GOROOT - for _, r := range filepath.SplitList(b.GOROOT) { - p = filepath.Join(r, "src", filepath.FromSlash(name)) - if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) { - info.Path = p - info.PType = ptypeGoroot - return info - } - } - - // Finally, if this is "C", we're dealing with cgo - if name == "C" { - info.PType = ptypeCgo - } - - return info -} - -func isLink(fi os.FileInfo) bool { - return fi.Mode()&os.ModeSymlink == os.ModeSymlink -} - -func walkDeps(b *util.BuildCtxt, base, myName string) []string { - externalDeps := []string{} - filepath.Walk(base, func(path string, fi os.FileInfo, err error) error { - if excludeSubtree(path, fi) { - if fi.IsDir() { - return filepath.SkipDir - } - return nil - } - - pkg, err := b.ImportDir(path, 0) - if err != nil { - if !strings.HasPrefix(err.Error(), "no buildable Go source") { - Warn("Error: %s (%s)", err, path) - // Not sure if we should return here. - //return err - } - } - - if pkg.Goroot { - return nil - } - - for _, imp := range pkg.Imports { - //if strings.HasPrefix(imp, myName) { - ////Info("Skipping %s because it is a subpackage of %s", imp, myName) - //continue - //} - if imp == myName { - continue - } - externalDeps = append(externalDeps, imp) - } - - return nil - }) - return externalDeps -} - -func excludeSubtree(path string, fi os.FileInfo) bool { - top := filepath.Base(path) - - if !fi.IsDir() && !isLink(fi) { - return true - } - - // Provisionally, we'll skip vendor. We definitely - // should skip testdata. - if top == "vendor" || top == "testdata" { - return true - } - - // Skip anything that starts with _ - if strings.HasPrefix(top, "_") || (strings.HasPrefix(top, ".") && top != ".") { - return true - } - return false -} - -func copyList(l *list.List) *list.List { - n := list.New() - for e := l.Front(); e != nil; e = e.Next() { - n.PushBack(e.Value.(string)) - } - return n -} - -func findInList(n string, l *list.List) bool { - for e := l.Front(); e != nil; e = e.Next() { - if e.Value.(string) == n { - return true - } - } - - return false -} diff --git a/cmd/tree_test.go b/cmd/tree_test.go deleted file mode 100644 index afa66677..00000000 --- a/cmd/tree_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package cmd - -import ( - "container/list" - "testing" -) - -func TestFindInTree(t *testing.T) { - l := list.New() - l.PushBack("github.com/Masterminds/glide") - l.PushBack("github.com/Masterminds/vcs") - l.PushBack("github.com/Masterminds/semver") - - f := findInList("foo", l) - if f != false { - t.Error("findInList found true instead of false") - } - - f = findInList("github.com/Masterminds/vcs", l) - if f != true { - t.Error("findInList found false instead of true") - } -} diff --git a/cmd/util.go b/cmd/util.go deleted file mode 100644 index 67441735..00000000 --- a/cmd/util.go +++ /dev/null @@ -1,215 +0,0 @@ -package cmd - -import ( - "fmt" - "io" - "os" - "os/exec" - "path/filepath" - "strings" - - "github.com/Masterminds/cookoo" -) - -// Quiet, when set to true, can suppress Info and Debug messages. -var Quiet = false -var IsDebugging = false -var NoColor = false - -// BeQuiet supresses Info and Debug messages. -func BeQuiet(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - Quiet = p.Get("quiet", false).(bool) - IsDebugging = p.Get("debug", false).(bool) - return Quiet, nil -} - -// CheckColor turns off the colored output (and uses plain text output) for -// logging depending on the value of the "no-color" flag. -func CheckColor(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - NoColor = p.Get("no-color", false).(bool) - return NoColor, nil -} - -// ReadyToGlide fails if the environment is not sufficient for using glide. -// -// Most importantly, it fails if glide.yaml is not present in the current -// working directory. -func ReadyToGlide(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - fname := p.Get("filename", "glide.yaml").(string) - if _, err := os.Stat(fname); err != nil { - cwd, _ := os.Getwd() - return false, fmt.Errorf("%s is missing from %s", fname, cwd) - } - return true, nil -} - -// VersionGuard ensures that the Go version is correct. -func VersionGuard(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - // 6l was removed in 1.5, when vendoring was introduced. - cmd := exec.Command("go", "tool", "6l") - var out string - if _, err := cmd.CombinedOutput(); err == nil { - Warn("You must install the Go 1.5 or greater toolchain to work with Glide.\n") - } - if os.Getenv("GO15VENDOREXPERIMENT") != "1" { - Warn("To use Glide, you must set GO15VENDOREXPERIMENT=1\n") - } - - // Verify the setup isn't for the old version of glide. That is, this is - // no longer assuming the _vendor directory as the GOPATH. Inform of - // the change. - if _, err := os.Stat("_vendor/"); err == nil { - Warn(`Your setup appears to be for the previous version of Glide. -Previously, vendor packages were stored in _vendor/src/ and -_vendor was set as your GOPATH. As of Go 1.5 the go tools -recognize the vendor directory as a location for these -files. Glide has embraced this. Please remove the _vendor -directory or move the _vendor/src/ directory to vendor/.` + "\n") - } - - return out, nil -} - -// CowardMode checks that the environment is setup before continuing on. If not -// setup and error is returned. -func CowardMode(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - gopath := Gopath() - if gopath == "" { - return false, fmt.Errorf("No GOPATH is set.\n") - } - - _, err := os.Stat(filepath.Join(gopath, "src")) - if err != nil { - Error("Could not find %s/src. The GOPATH does not appear to be properly setup.\n", gopath) - Info("As of Glide 0.5/Go 1.5, this is required.\n") - return false, err - } - - return true, nil -} - -// Check if a directory is empty or not. -func isDirectoryEmpty(dir string) (bool, error) { - f, err := os.Open(dir) - if err != nil { - return false, err - } - defer f.Close() - - _, err = f.Readdir(1) - - if err == io.EOF { - return true, nil - } - - return false, err -} - -// Gopath gets GOPATH from environment and return the most relevant path. -// -// A GOPATH can contain a colon-separated list of paths. This retrieves the -// GOPATH and returns only the FIRST ("most relevant") path. -// -// This should be used carefully. If, for example, you are looking for a package, -// you may be better off using Gopaths. -func Gopath() string { - gopaths := Gopaths() - if len(gopaths) == 0 { - return "" - } - return gopaths[0] -} - -// Gopaths retrieves the Gopath as a list when there is more than one path -// listed in the Gopath. -func Gopaths() []string { - p := os.Getenv("GOPATH") - p = strings.Trim(p, string(filepath.ListSeparator)) - return filepath.SplitList(p) -} - -func fileExist(name string) (bool, error) { - _, err := os.Stat(name) - if err == nil { - return true, nil - } - if os.IsNotExist(err) { - return false, nil - } - return true, err -} - -// We copy the directory here rather than jumping out to a shell so we can -// support multiple operating systems. -func copyDir(source string, dest string) error { - - // get properties of source dir - si, err := os.Stat(source) - if err != nil { - return err - } - - err = os.MkdirAll(dest, si.Mode()) - if err != nil { - return err - } - - d, _ := os.Open(source) - - objects, err := d.Readdir(-1) - - for _, obj := range objects { - - sp := filepath.Join(source, obj.Name()) - - dp := filepath.Join(dest, obj.Name()) - - if obj.IsDir() { - err = copyDir(sp, dp) - if err != nil { - return err - } - } else { - // perform copy - err = copyFile(sp, dp) - if err != nil { - return err - } - } - - } - return nil -} - -func copyFile(source string, dest string) error { - ln, err := os.Readlink(source) - if err == nil { - return os.Symlink(ln, dest) - } - s, err := os.Open(source) - if err != nil { - return err - } - - defer s.Close() - - d, err := os.Create(dest) - if err != nil { - return err - } - - defer d.Close() - - _, err = io.Copy(d, s) - if err != nil { - return err - } - - si, err := os.Stat(source) - if err != nil { - return err - } - err = os.Chmod(dest, si.Mode()) - - return err -} diff --git a/cmd/util_test.go b/cmd/util_test.go deleted file mode 100644 index 89a041a8..00000000 --- a/cmd/util_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package cmd - -import ( - "io/ioutil" - "os" - "testing" -) - -func TestisDirectoryEmpty(t *testing.T) { - tempDir, err := ioutil.TempDir("", "empty-dir-test") - if err != nil { - t.Error(err) - } - defer func() { - err = os.RemoveAll(tempDir) - if err != nil { - t.Error(err) - } - }() - - empty, err := isDirectoryEmpty(tempDir) - if err != nil { - t.Error(err) - } - if empty == false { - t.Error("isDirectoryEmpty reporting false on empty directory") - } - - data := "foo bar baz" - err = ioutil.WriteFile(tempDir+"/foo", []byte(data), 0644) - if err != nil { - t.Error(err) - } - - empty, err = isDirectoryEmpty(tempDir) - if err != nil { - t.Error(err) - } - if empty == true { - t.Error("isDirectoryEmpty reporting true on non-empty directory") - } -} diff --git a/cmd/vendor_path.go b/cmd/vendor_path.go deleted file mode 100644 index 0b3dc75e..00000000 --- a/cmd/vendor_path.go +++ /dev/null @@ -1,44 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/Masterminds/cookoo" -) - -// Return the path to the vendor directory. -func VendorPath(c cookoo.Context) (string, error) { - vendor := c.Get("VendorDir", "vendor").(string) - filename := c.Get("yaml", "glide.yaml").(string) - cwd, err := os.Getwd() - if err != nil { - return "", err - } - - // Find the directory that contains glide.yaml - yamldir, err := glideWD(cwd, filename) - if err != nil { - return cwd, err - } - - gopath := filepath.Join(yamldir, vendor) - - return gopath, nil -} - -func glideWD(dir, filename string) (string, error) { - fullpath := filepath.Join(dir, filename) - - if _, err := os.Stat(fullpath); err == nil { - return dir, nil - } - - base := filepath.Dir(dir) - if base == dir { - return "", fmt.Errorf("Cannot resolve parent of %s", base) - } - - return glideWD(base, filename) -} diff --git a/cmd/vendor_path_test.go b/cmd/vendor_path_test.go deleted file mode 100644 index 258b8b5d..00000000 --- a/cmd/vendor_path_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package cmd - -import ( - "os" - "path/filepath" - "testing" -) - -func TestGlideWD(t *testing.T) { - cwd, _ := os.Getwd() - filename := "glide.yaml" - found, err := glideWD(cwd, filename) - if err != nil { - t.Errorf("Failed to get Glide directory: %s", err) - } - - if found != filepath.Dir(cwd) { - t.Errorf("Expected %s to match %s", found, filepath.Base(cwd)) - } - - // This should fail - cwd = "/No/Such/Dir" - found, err = glideWD(cwd, filename) - if err == nil { - t.Errorf("Expected to get an error on a non-existent directory, not %s", found) - } - -} diff --git a/cmd/vendored.go b/cmd/vendored.go deleted file mode 100644 index 6dfbda08..00000000 --- a/cmd/vendored.go +++ /dev/null @@ -1,65 +0,0 @@ -package cmd - -import ( - "os" - "path/filepath" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" -) - -// If we are updating the vendored dependencies. That is those stored in the -// local project VCS. -var updatingVendored = false - -// 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", false).(bool) - conf := p.Get("conf", nil).(*cfg.Config) - - updatingVendored = update - - return conf, nil -} - -// VendoredCleanUp is a command that cleans up vendored codebases after an update. -// If enabled (via update) it removes the VCS info from updated vendored -// packages. This should be a suffix to UpdateImports and VendoredSetup should -// be a prefix to UpdateImports. -func VendoredCleanUp(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - update := p.Get("update", true).(bool) - if update != true { - return false, nil - } - conf := p.Get("conf", nil).(*cfg.Config) - - vend, err := VendorPath(c) - if err != nil { - return false, err - } - - for _, dep := range conf.Imports { - if dep.UpdateAsVendored == true { - Info("Cleaning up vendored package %s\n", dep.Name) - - // Remove the VCS directory - cwd := filepath.Join(vend, filepath.FromSlash(dep.Name)) - repo, err := dep.GetRepo(cwd) - if err != nil { - Error("Error cleaning up %s:%s", dep.Name, err) - continue - } - t := repo.Vcs() - err = os.RemoveAll(cwd + string(os.PathSeparator) + "." + string(t)) - if err != nil { - Error("Error cleaning up VCS dir for %s:%s", dep.Name, err) - } - } - - } - - return true, nil -} diff --git a/cmd/yaml.go b/cmd/yaml.go deleted file mode 100644 index f05a1e93..00000000 --- a/cmd/yaml.go +++ /dev/null @@ -1,196 +0,0 @@ -package cmd - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" - "github.com/Masterminds/glide/util" -) - -// ParseYaml parses the glide.yaml format and returns a Configuration object. -// -// Params: -// - filename (string): YAML filename as a string -// -// Returns: -// - *cfg.Config: The configuration. -func ParseYaml(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - fname := p.Get("filename", "glide.yaml").(string) - //conf := new(Config) - yml, err := ioutil.ReadFile(fname) - if err != nil { - return nil, err - } - conf, err := cfg.ConfigFromYaml(yml) - if err != nil { - return nil, err - } - - return conf, nil -} - -// ParseYamlString parses a YAML string. This is similar but different to -// ParseYaml that parses an external file. -// -// Params: -// - yaml (string): YAML as a string. -// -// Returns: -// - *cfg.Config: The configuration. -func ParseYamlString(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - yamlString := p.Get("yaml", "").(string) - - conf, err := cfg.ConfigFromYaml([]byte(yamlString)) - if err != nil { - return nil, err - } - - return conf, nil -} - -// GuardYaml protects the glide yaml file from being overwritten. -func GuardYaml(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - fname := p.Get("filename", "glide.yaml").(string) - if _, err := os.Stat(fname); err == nil { - cwd, _ := os.Getwd() - return false, fmt.Errorf("Cowardly refusing to overwrite %s in %s", fname, cwd) - } - - return true, nil -} - -// WriteYaml writes the config as YAML. -// -// Params: -// - conf: A *cfg.Config to render. -// - out (io.Writer): An output stream to write to. Default is os.Stdout. -// - filename (string): If set, the file will be opened and the content will be written to it. -func WriteYaml(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - conf := p.Get("conf", nil).(*cfg.Config) - toStdout := p.Get("toStdout", true).(bool) - - data, err := conf.Marshal() - if err != nil { - return nil, err - } - - var out io.Writer - if nn, ok := p.Has("filename"); ok && len(nn.(string)) > 0 { - file, err := os.Create(nn.(string)) - if err != nil { - } - defer file.Close() - out = io.Writer(file) - //fmt.Fprint(out, yml) - out.Write(data) - } else if toStdout { - out = p.Get("out", os.Stdout).(io.Writer) - //fmt.Fprint(out, yml) - out.Write(data) - } - - // Otherwise we supress output. - return true, nil -} - -// WriteLock writes the lock as YAML. -// -// Params: -// - lockfile: A *cfg.Lockfile to render. -// - out (io.Writer): An output stream to write to. Default is os.Stdout. -func WriteLock(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - skip := p.Get("skip", false).(bool) - if skip { - return false, nil - } - - lockfile := p.Get("lockfile", nil).(*cfg.Lockfile) - - Info("Writing glide.lock file") - - data, err := lockfile.Marshal() - if err != nil { - return nil, err - } - - var out io.Writer - file, err := os.Create("glide.lock") - if err != nil { - return false, err - } - defer file.Close() - out = io.Writer(file) - out.Write(data) - - return true, nil -} - -// AddDependencies adds a list of *Dependency objects to the given *cfg.Config. -// -// This is used to merge in packages from other sources or config files. -func AddDependencies(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { - deps := p.Get("dependencies", []*cfg.Dependency{}).([]*cfg.Dependency) - config := p.Get("conf", nil).(*cfg.Config) - - // Make a set of existing package names for quick comparison. - pkgSet := make(map[string]bool, len(config.Imports)) - for _, p := range config.Imports { - pkgSet[p.Name] = true - } - - // If a dep is not already present, add it. - for _, dep := range deps { - if _, ok := pkgSet[dep.Name]; ok { - Warn("Package %s is already in glide.yaml. Skipping.\n", dep.Name) - continue - } - config.Imports = append(config.Imports, dep) - } - - return true, nil -} - -// NormalizeName takes a package name and normalizes it to the top level package. -// -// For example, golang.org/x/crypto/ssh becomes golang.org/x/crypto. 'ssh' is -// returned as extra data. -func NormalizeName(name string) (string, string) { - - // Fastpath check if a name in the GOROOT. There is an issue when a pkg - // is in the GOROOT and GetRootFromPackage tries to look it up because it - // expects remote names. - b, err := util.GetBuildContext() - if err == nil { - p := filepath.Join(b.GOROOT, "src", filepath.FromSlash(name)) - if _, err := os.Stat(p); err == nil { - return name, "" - } - } - - root := util.GetRootFromPackage(name) - extra := strings.TrimPrefix(name, root) - if len(extra) > 0 && extra != "/" { - extra = strings.TrimPrefix(extra, "/") - } else { - // If extra is / (which is what it would be here) we want to return "" - extra = "" - } - - return root, extra - - // parts := strings.SplitN(name, "/", 4) - // extra := "" - // if len(parts) < 3 { - // return name, extra - // } - // if len(parts) == 4 { - // extra = parts[3] - // } - // return strings.Join(parts[0:3], "/"), extra -} diff --git a/cmd/yaml_test.go b/cmd/yaml_test.go deleted file mode 100644 index a1e3e6b2..00000000 --- a/cmd/yaml_test.go +++ /dev/null @@ -1,124 +0,0 @@ -package cmd - -import ( - "testing" - - "github.com/Masterminds/cookoo" - "github.com/Masterminds/glide/cfg" -) - -var yamlFile = ` -package: fake/testing -import: - - package: github.com/kylelemons/go-gypsy - subpackages: - - yaml - # Intentionally left spaces at end of next line. - - package: github.com/Masterminds/convert - repo: git@github.com:Masterminds/convert.git - ref: a9949121a2e2192ca92fa6dddfeaaa4a4412d955 - subpackages: - - color - - nautical - - radial - os: - - linux - arch: - - i386 - - arm - - package: github.com/Masterminds/structable - -devimport: - - package: github.com/kylelemons/go-gypsy -` - -func TestFromYaml(t *testing.T) { - reg, router, cxt := cookoo.Cookoo() - - reg.Route("t", "Testing"). - Does(ParseYamlString, "cfg").Using("yaml").WithDefault(yamlFile) - - if err := router.HandleRequest("t", cxt, false); err != nil { - t.Errorf("Failed to parse YAML: %s", err) - } - - conf := cxt.Get("cfg", nil).(*cfg.Config) - - if conf.Name != "fake/testing" { - t.Errorf("Expected name to be 'fake/teting', not '%s'", conf.Name) - } - - if len(conf.Imports) != 3 { - t.Errorf("Expected 3 imports, got %d", len(conf.Imports)) - } - - if conf.Imports.Get("github.com/Masterminds/convert") == nil { - t.Error("Expected Imports.Get to return Dependency") - } - - if conf.Imports.Get("github.com/doesnot/exist") != nil { - t.Error("Execpted Imports.Get to return nil") - } - - var imp *cfg.Dependency - for _, d := range conf.Imports { - if d.Name == "github.com/Masterminds/convert" { - imp = d - } - } - - if imp == nil { - t.Errorf("Expected the convert package, got nothing") - } - - if len(imp.Subpackages) != 3 { - t.Errorf("Expected 3 subpackages. got %d", len(imp.Subpackages)) - } - - if imp.Subpackages[0] != "color" { - t.Errorf("Expected first subpackage to be 'color', got '%s'", imp.Subpackages[0]) - } - - if len(imp.Os) != 1 { - t.Errorf("Expected Os: SOMETHING") - } else if imp.Os[0] != "linux" { - t.Errorf("Expected Os: linux") - } - - if len(imp.Arch) != 2 { - t.Error("Expected two Archs.") - } else if imp.Arch[0] != "i386" { - t.Errorf("Expected arch 1 to be i386, got %s.", imp.Arch[0]) - } else if imp.Arch[1] != "arm" { - t.Error("Expected arch 2 to be arm.") - } - - if imp.Repository != "git@github.com:Masterminds/convert.git" { - t.Errorf("Got wrong repo %s on %s", imp.Repository, imp.Name) - } - if imp.Reference != "a9949121a2e2192ca92fa6dddfeaaa4a4412d955" { - t.Errorf("Got wrong reference.") - } - - if len(conf.DevImports) != 1 { - t.Errorf("Expected one dev import.") - } - -} - -func TestNormalizeName(t *testing.T) { - packages := map[string]string{ - "github.com/Masterminds/cookoo/web/io/foo": "github.com/Masterminds/cookoo", - "golang.org/x/crypto/ssh": "golang.org/x/crypto", - //"technosophos.me/x/totally/fake/package": "technosophos.me/x/totally", - "incomplete/example": "incomplete/example", - "net": "net", - } - for start, expected := range packages { - if finish, extra := NormalizeName(start); expected != finish { - t.Errorf("Expected '%s', got '%s'", expected, finish) - } else if start != finish && start != finish+"/"+extra { - t.Errorf("Expected %s to end with %s", finish, extra) - } - } -} diff --git a/dependency/resolver.go b/dependency/resolver.go index ba751e65..7c2b0d29 100644 --- a/dependency/resolver.go +++ b/dependency/resolver.go @@ -150,6 +150,9 @@ func NewResolver(basedir string) (*Resolver, error) { seen: map[string]bool{}, alreadyQ: map[string]bool{}, findCache: map[string]*PkgInfo{}, + + // The config instance here should really be replaced with a real one. + Config: &cfg.Config{}, } // TODO: Make sure the build context is correctly set up. Especially in diff --git a/dependency/resolver_test.go b/dependency/resolver_test.go index 46268f22..0edb764d 100644 --- a/dependency/resolver_test.go +++ b/dependency/resolver_test.go @@ -21,7 +21,6 @@ func TestResolveLocalShallow(t *testing.T) { } expect := []string{ - "github.com/Masterminds/cookoo", "github.com/Masterminds/semver", "github.com/Masterminds/vcs", "gopkg.in/yaml.v2", @@ -53,8 +52,8 @@ func TestResolveLocalDeep(t *testing.T) { t.Fatalf("Failed to resolve: %s", err) } - if len(l) < 8 { - t.Errorf("Expected at least 8 deps, got %d: %s", len(l)) + if len(l) < 4 { + t.Errorf("Expected at least 4 deps, got %d: %s", len(l)) } } @@ -79,8 +78,8 @@ func TestResolveAll(t *testing.T) { // These are build dependencies of Glide, so we know they are here. deps := []*cfg.Dependency{ &cfg.Dependency{Name: "github.com/codegangsta/cli"}, - &cfg.Dependency{Name: "github.com/Masterminds/cookoo"}, &cfg.Dependency{Name: "github.com/Masterminds/semver"}, + &cfg.Dependency{Name: "github.com/Masterminds/vcs"}, &cfg.Dependency{Name: "gopkg.in/yaml.v2"}, } diff --git a/glide.go b/glide.go index e9f2b5cd..97e0dfb0 100644 --- a/glide.go +++ b/glide.go @@ -43,7 +43,6 @@ import ( gpath "github.com/Masterminds/glide/path" "github.com/Masterminds/glide/repo" - "github.com/Masterminds/cookoo" "github.com/codegangsta/cli" "fmt" @@ -76,8 +75,6 @@ no longer exist. var VendorDir = "vendor" func main() { - _, router, cxt := cookoo.Cookoo() - app := cli.NewApp() app.Name = "glide" app.Usage = usage @@ -112,12 +109,12 @@ func main() { action.Plugin(command, os.Args) } app.Before = startup - app.Commands = commands(cxt, router) + app.Commands = commands() app.Run(os.Args) } -func commands(cxt cookoo.Context, router *cookoo.Router) []cli.Command { +func commands() []cli.Command { return []cli.Command{ { Name: "create", @@ -206,14 +203,6 @@ func commands(cxt cookoo.Context, router *cookoo.Router) []cli.Command { packages := []string(c.Args()) insecure := c.Bool("insecure") action.Get(packages, inst, insecure) - - cxt.Put("skipFlatten", !c.Bool("no-recursive")) - // FIXME: Are these used anywhere? - if c.Bool("import") { - cxt.Put("importGodeps", true) - cxt.Put("importGPM", true) - cxt.Put("importGb", true) - } }, }, { @@ -395,27 +384,6 @@ Example: } action.Install(installer) - - // Was used by nested update. - cxt.Put("skipFlatten", c.Bool("no-recursive")) - cxt.Put("deleteFlatten", c.Bool("delete-flatten")) - - // Not sure what this is for - cxt.Put("toPath", c.String("file")) - - // This is never used here, but was used by Update. - cxt.Put("toStdout", false) - - // This is never set to true, apparently. - if c.Bool("import") { - cxt.Put("importGodeps", true) - cxt.Put("importGPM", true) - cxt.Put("importGb", true) - } - - // This is a bug. Install should never limit which packages are - // installed. - cxt.Put("packages", []string(c.Args())) }, }, { @@ -493,25 +461,6 @@ Example: } action.Update(installer) - - cxt.Put("deleteOptIn", c.Bool("delete")) - cxt.Put("forceUpdate", c.Bool("force")) - cxt.Put("skipFlatten", c.Bool("no-recursive")) - cxt.Put("deleteFlatten", c.Bool("delete-flatten")) - cxt.Put("toPath", c.String("file")) - cxt.Put("toStdout", false) - cxt.Put("useCache", c.Bool("cache")) - cxt.Put("cacheGopath", c.Bool("cache-gopath")) - cxt.Put("useGopath", c.Bool("use-gopath")) - if c.Bool("import") { - cxt.Put("importGodeps", true) - cxt.Put("importGPM", true) - cxt.Put("importGb", true) - } - cxt.Put("updateVendoredDeps", c.Bool("update-vendored")) - - cxt.Put("packages", []string(c.Args())) - //setupHandler(c, "update", cxt, router) }, }, { diff --git a/glide.lock b/glide.lock index f17306aa..3ff76ad1 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,8 @@ -hash: 1fdfb16656a1b4a1664afdc9e2a5fc8040165bc5b6e85812df2affceacb7fbc8 -updated: 2016-01-20T12:21:03.062084202-05:00 +hash: 4cf59f8e61ae7034d3296c0c7528aaf8784800008814fb02410cbb3ea9b34175 +updated: 2016-01-21T11:19:37.465408253-05:00 imports: - name: github.com/codegangsta/cli - version: b5232bb2934f606f9f27a1305f1eea224e8e8b88 -- name: github.com/Masterminds/cookoo - version: 78aa11ce75e257c51be7ea945edb84cf19c4a6de - subpackages: - - . + version: c31a7975863e7810c92e2e288a9ab074f9a88f29 - name: github.com/Masterminds/semver version: 513f3dcb3ecfb1248831fb5cb06a23a3cd5935dc - name: github.com/Masterminds/vcs diff --git a/glide.yaml b/glide.yaml index c888aa0e..611d71c2 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,10 +1,6 @@ package: github.com/Masterminds/glide import: - package: gopkg.in/yaml.v2 -- package: github.com/Masterminds/cookoo - version: ^1.2.0 - subpackages: - - . - package: github.com/Masterminds/vcs version: ^1.2.0 - package: github.com/codegangsta/cli diff --git a/glide_test.go b/glide_test.go index 9e0a8383..1c50468f 100644 --- a/glide_test.go +++ b/glide_test.go @@ -2,13 +2,10 @@ package main import ( "testing" - - "github.com/Masterminds/cookoo" ) func TestCommandsNonEmpty(t *testing.T) { - _, router, ctx := cookoo.Cookoo() - commands := commands(ctx, router) + commands := commands() if len(commands) == 0 { t.Fail() }