diff --git a/analyzer.go b/analyzer.go index cbc77f0382..aed9aa9305 100644 --- a/analyzer.go +++ b/analyzer.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" - "github.com/Masterminds/semver" "github.com/sdboyer/gps" ) @@ -37,7 +36,6 @@ func (a analyzer) DeriveManifestAndLock(path string, n gps.ProjectRoot) (gps.Man return m, nil, nil } -func (a analyzer) Info() (string, *semver.Version) { - v, _ := semver.NewVersion("v0.0.1") - return "dep", v +func (a analyzer) Info() (string, int) { + return "dep", 1 } diff --git a/cmd/dep/ensure.go b/cmd/dep/ensure.go index 0246df12bd..b16b4cbdf4 100644 --- a/cmd/dep/ensure.go +++ b/cmd/dep/ensure.go @@ -18,6 +18,7 @@ import ( "github.com/golang/dep" "github.com/pkg/errors" "github.com/sdboyer/gps" + "github.com/sdboyer/gps/pkgtree" ) const ensureShortHelp = `Ensure a dependency is safely vendored in the project` @@ -123,7 +124,7 @@ func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error { params.Trace = true params.TraceLogger = log.New(os.Stderr, "", 0) } - params.RootPackageTree, err = gps.ListPackages(p.AbsRoot, string(p.ImportRoot)) + params.RootPackageTree, err = pkgtree.ListPackages(p.AbsRoot, string(p.ImportRoot)) if err != nil { return errors.Wrap(err, "ensure ListPackage for project") } diff --git a/cmd/dep/hash_in.go b/cmd/dep/hash_in.go index b76f8fe889..45e2da09f1 100644 --- a/cmd/dep/hash_in.go +++ b/cmd/dep/hash_in.go @@ -11,6 +11,7 @@ import ( "github.com/golang/dep" "github.com/pkg/errors" "github.com/sdboyer/gps" + "github.com/sdboyer/gps/pkgtree" ) func (cmd *hashinCommand) Name() string { return "hash-inputs" } @@ -42,7 +43,7 @@ func (hashinCommand) Run(ctx *dep.Ctx, args []string) error { return errors.Wrap(err, "determineProjectRoot") } - params.RootPackageTree, err = gps.ListPackages(p.AbsRoot, cpr) + params.RootPackageTree, err = pkgtree.ListPackages(p.AbsRoot, cpr) if err != nil { return errors.Wrap(err, "gps.ListPackages") } diff --git a/cmd/dep/init.go b/cmd/dep/init.go index 3e2e4069dd..8037845955 100644 --- a/cmd/dep/init.go +++ b/cmd/dep/init.go @@ -15,6 +15,7 @@ import ( "github.com/golang/dep" "github.com/pkg/errors" "github.com/sdboyer/gps" + "github.com/sdboyer/gps/pkgtree" ) const initShortHelp = `Initialize a new project with manifest and lock files` @@ -89,7 +90,7 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error { return errors.Wrap(err, "determineProjectRoot") } vlogf("Finding dependencies for %q...", cpr) - pkgT, err := gps.ListPackages(root, cpr) + pkgT, err := pkgtree.ListPackages(root, cpr) if err != nil { return errors.Wrap(err, "gps.ListPackages") } @@ -214,7 +215,7 @@ type projectData struct { ondisk map[gps.ProjectRoot]gps.Version // projects that were found on disk } -func getProjectData(ctx *dep.Ctx, pkgT gps.PackageTree, cpr string, sm *gps.SourceMgr) (projectData, error) { +func getProjectData(ctx *dep.Ctx, pkgT pkgtree.PackageTree, cpr string, sm *gps.SourceMgr) (projectData, error) { constraints := make(gps.ProjectConstraints) dependencies := make(map[gps.ProjectRoot][]string) packages := make(map[string]bool) @@ -285,7 +286,7 @@ func getProjectData(ctx *dep.Ctx, pkgT gps.PackageTree, cpr string, sm *gps.Sour ) // cache of PackageTrees, so we don't parse projects more than once - ptrees := make(map[gps.ProjectRoot]gps.PackageTree) + ptrees := make(map[gps.ProjectRoot]pkgtree.PackageTree) // depth-first traverser var dft func(string) error @@ -339,7 +340,7 @@ func getProjectData(ctx *dep.Ctx, pkgT gps.PackageTree, cpr string, sm *gps.Sour ondisk[pr] = v } - ptree, err = gps.ListPackages(r, string(pr)) + ptree, err = pkgtree.ListPackages(r, string(pr)) if err != nil { // Any error here other than an a nonexistent dir (which // can't happen because we covered that case above) is diff --git a/cmd/dep/remove.go b/cmd/dep/remove.go index 7a9c6ff5fb..87615608d7 100644 --- a/cmd/dep/remove.go +++ b/cmd/dep/remove.go @@ -14,6 +14,7 @@ import ( "github.com/golang/dep" "github.com/pkg/errors" "github.com/sdboyer/gps" + "github.com/sdboyer/gps/pkgtree" ) const removeShortHelp = `Remove a dependency from the project` @@ -61,7 +62,7 @@ func (cmd *removeCommand) Run(ctx *dep.Ctx, args []string) error { return errors.Wrap(err, "determineProjectRoot") } - pkgT, err := gps.ListPackages(p.AbsRoot, cpr) + pkgT, err := pkgtree.ListPackages(p.AbsRoot, cpr) if err != nil { return errors.Wrap(err, "gps.ListPackages") } diff --git a/cmd/dep/status.go b/cmd/dep/status.go index f1e55858b3..3e683af612 100644 --- a/cmd/dep/status.go +++ b/cmd/dep/status.go @@ -17,6 +17,7 @@ import ( "github.com/golang/dep" "github.com/sdboyer/gps" + "github.com/sdboyer/gps/pkgtree" ) const statusShortHelp = `Report the status of the project's dependencies` @@ -203,7 +204,7 @@ func runStatusAll(out outputter, p *dep.Project, sm *gps.SourceMgr) error { // While the network churns on ListVersions() requests, statically analyze // code from the current project. - ptree, err := gps.ListPackages(p.AbsRoot, string(p.ImportRoot)) + ptree, err := pkgtree.ListPackages(p.AbsRoot, string(p.ImportRoot)) if err != nil { return fmt.Errorf("analysis of local packages failed: %v", err) } @@ -368,7 +369,7 @@ func formatVersion(v gps.Version) string { return v.String() } -func collectConstraints(ptree gps.PackageTree, p *dep.Project, sm *gps.SourceMgr) map[string][]gps.Constraint { +func collectConstraints(ptree pkgtree.PackageTree, p *dep.Project, sm *gps.SourceMgr) map[string][]gps.Constraint { // TODO return map[string][]gps.Constraint{} } diff --git a/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/lock.json b/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/lock.json index bab94e010b..4af31ffe93 100644 --- a/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/lock.json +++ b/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/lock.json @@ -1,5 +1,5 @@ { - "memo": "63510efb9632ec69c1164ce396d7ebea4ad3884b4fa508373da17226d5a39739", + "memo": "4b36ae008ef4be09dee7e2ae00606d44fd75f4310fd0d0ef6e744690290569de", "projects": [ { "name": "github.com/sdboyer/deptest", diff --git a/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/lock.json b/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/lock.json index 7836faf3c7..21f628ed00 100644 --- a/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/lock.json +++ b/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/lock.json @@ -1,5 +1,5 @@ { - "memo": "1a99b419931283cb086167ddfb2e8322df12e2648e139eb27a42904360e962ad", + "memo": "e7725ea56516a42a641aaaf5d48754258d9f3c59949cb8a0e8a21b1ab6e07179", "projects": [ { "name": "github.com/sdboyer/deptest", diff --git a/cmd/dep/testdata/harness_tests/ensure/override/case1/final/lock.json b/cmd/dep/testdata/harness_tests/ensure/override/case1/final/lock.json index 9f0acd1845..71cd0988aa 100644 --- a/cmd/dep/testdata/harness_tests/ensure/override/case1/final/lock.json +++ b/cmd/dep/testdata/harness_tests/ensure/override/case1/final/lock.json @@ -1,5 +1,5 @@ { - "memo": "70b47774699956441e395f458714b8e5800b54bebc73b046678245b9e1cfdc3b", + "memo": "8bca9526e654e56e05d9075d1f33fa5b649bf6d58aa7d71ca39e7fbea8468e07", "projects": [ { "name": "github.com/sdboyer/deptest", diff --git a/cmd/dep/testdata/harness_tests/ensure/update/case1/final/lock.json b/cmd/dep/testdata/harness_tests/ensure/update/case1/final/lock.json index c36607c20e..f54aca1056 100644 --- a/cmd/dep/testdata/harness_tests/ensure/update/case1/final/lock.json +++ b/cmd/dep/testdata/harness_tests/ensure/update/case1/final/lock.json @@ -1,5 +1,5 @@ { - "memo": "3ee7126505b016d4b9140dc3521b931380fd9d61fd1d1e6612d6b5b56b21baad", + "memo": "1b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb", "projects": [ { "name": "github.com/sdboyer/deptest", diff --git a/cmd/dep/testdata/harness_tests/ensure/update/case2/testcase.json b/cmd/dep/testdata/harness_tests/ensure/update/case2/testcase.json index 5be759213e..dd86dd72fc 100644 --- a/cmd/dep/testdata/harness_tests/ensure/update/case2/testcase.json +++ b/cmd/dep/testdata/harness_tests/ensure/update/case2/testcase.json @@ -2,5 +2,6 @@ "commands": [ ["init"], ["ensure", "-n", "-update", "github.com/sdboyer/deptest"] - ] + ], + "vendor-final": [] } diff --git a/cmd/dep/testdata/harness_tests/init/case2/final/lock.json b/cmd/dep/testdata/harness_tests/init/case2/final/lock.json index 85a2364c75..876df85036 100644 --- a/cmd/dep/testdata/harness_tests/init/case2/final/lock.json +++ b/cmd/dep/testdata/harness_tests/init/case2/final/lock.json @@ -1,5 +1,5 @@ { - "memo": "1792d407a795640a2b821b350f481bc48852535ed17c98cae2cbe2912a9c3e36", + "memo": "88d2718cda70cce45158f953d2c6ead79c1db38e67e9704aff72be8fddb096e7", "projects": [ { "name": "github.com/sdboyer/deptest", diff --git a/cmd/dep/testdata/harness_tests/init/skip-hidden/final/lock.json b/cmd/dep/testdata/harness_tests/init/skip-hidden/final/lock.json index bab94e010b..4af31ffe93 100644 --- a/cmd/dep/testdata/harness_tests/init/skip-hidden/final/lock.json +++ b/cmd/dep/testdata/harness_tests/init/skip-hidden/final/lock.json @@ -1,5 +1,5 @@ { - "memo": "63510efb9632ec69c1164ce396d7ebea4ad3884b4fa508373da17226d5a39739", + "memo": "4b36ae008ef4be09dee7e2ae00606d44fd75f4310fd0d0ef6e744690290569de", "projects": [ { "name": "github.com/sdboyer/deptest", diff --git a/cmd/dep/testdata/harness_tests/remove/force/case1/final/lock.json b/cmd/dep/testdata/harness_tests/remove/force/case1/final/lock.json index d5c096f360..309f43cbe6 100644 --- a/cmd/dep/testdata/harness_tests/remove/force/case1/final/lock.json +++ b/cmd/dep/testdata/harness_tests/remove/force/case1/final/lock.json @@ -1,5 +1,5 @@ { - "memo": "1792d407a795640a2b821b350f481bc48852535ed17c98cae2cbe2912a9c3e36", + "memo": "88d2718cda70cce45158f953d2c6ead79c1db38e67e9704aff72be8fddb096e7", "projects": [ { "name": "github.com/sdboyer/deptest", diff --git a/cmd/dep/testdata/harness_tests/remove/specific/case1/final/lock.json b/cmd/dep/testdata/harness_tests/remove/specific/case1/final/lock.json index c5e7e1919a..8563f21501 100644 --- a/cmd/dep/testdata/harness_tests/remove/specific/case1/final/lock.json +++ b/cmd/dep/testdata/harness_tests/remove/specific/case1/final/lock.json @@ -1,5 +1,5 @@ { - "memo": "1a90a1bc14e6c5302e5c936186412f7e61e380a3b82afc54ea387f3a237843f8", + "memo": "d414dbf5fc668c1085effa68372d02e54b23d058cc66f9fd19ba094c6a946d9b", "projects": [ { "name": "github.com/sdboyer/deptest", diff --git a/cmd/dep/testdata/harness_tests/remove/specific/case2/final/lock.json b/cmd/dep/testdata/harness_tests/remove/specific/case2/final/lock.json index 37ee11680e..1764a031d8 100644 --- a/cmd/dep/testdata/harness_tests/remove/specific/case2/final/lock.json +++ b/cmd/dep/testdata/harness_tests/remove/specific/case2/final/lock.json @@ -1,5 +1,5 @@ { - "memo": "ffb96eabfbb48ff1ae4f1ad2145a9e765f1e6aef7a3fbfd36a84ad875fcb3585", + "memo": "38d8431865759ee3bf28fbdfc464f98ee8b56319394ec717df45e9969544cfca", "projects": [ { "name": "github.com/sdboyer/deptest", diff --git a/cmd/dep/testdata/harness_tests/remove/unused/case1/final/lock.json b/cmd/dep/testdata/harness_tests/remove/unused/case1/final/lock.json index c5e7e1919a..8563f21501 100644 --- a/cmd/dep/testdata/harness_tests/remove/unused/case1/final/lock.json +++ b/cmd/dep/testdata/harness_tests/remove/unused/case1/final/lock.json @@ -1,5 +1,5 @@ { - "memo": "1a90a1bc14e6c5302e5c936186412f7e61e380a3b82afc54ea387f3a237843f8", + "memo": "d414dbf5fc668c1085effa68372d02e54b23d058cc66f9fd19ba094c6a946d9b", "projects": [ { "name": "github.com/sdboyer/deptest", diff --git a/lock.json b/lock.json index f27282a743..070f270f20 100644 --- a/lock.json +++ b/lock.json @@ -1,5 +1,5 @@ { - "memo": "fc012dfb266db9deec4121dd38069e2556ba66a5514939662da94fac1251996e", + "memo": "31a7162c06758e4619ed89b91e1f48bf94ad14f394bbee79299ed0bb5150e409", "projects": [ { "name": "github.com/Masterminds/semver", @@ -11,8 +11,8 @@ }, { "name": "github.com/Masterminds/vcs", - "version": "v1.8.0", - "revision": "fbe9fb6ad5b5f35b3e82a7c21123cfc526cbf895", + "version": "v1.11.0", + "revision": "795e20f901c3d561de52811fb3488a2cb2c8588b", "packages": [ "." ] @@ -35,10 +35,13 @@ }, { "name": "github.com/sdboyer/gps", - "version": "v0.14.1", - "revision": "287edec9f4ca516577cc3ac9744068a34c4c7b08", + "version": "v0.15.0", + "revision": "b0f646b744e74543c094023d05339ffb82458e35", "packages": [ - "." + ".", + "internal", + "internal/fs", + "pkgtree" ] } ] diff --git a/manifest.json b/manifest.json index 2c5403aa3c..fdbed6a4d1 100644 --- a/manifest.json +++ b/manifest.json @@ -10,7 +10,7 @@ "version": ">=0.8.0, <1.0.0" }, "github.com/sdboyer/gps": { - "version": ">=0.14.0, <1.0.0" + "version": ">=0.15.0, <1.0.0" } } } diff --git a/vendor/github.com/Masterminds/vcs/.travis.yml b/vendor/github.com/Masterminds/vcs/.travis.yml index 5c50c4a1cf..47bd9491e9 100644 --- a/vendor/github.com/Masterminds/vcs/.travis.yml +++ b/vendor/github.com/Masterminds/vcs/.travis.yml @@ -1,10 +1,9 @@ language: go go: - - 1.3 - - 1.4 - - 1.5 - 1.6 + - 1.7 + - 1.8 - tip before_script: @@ -17,6 +16,10 @@ before_script: # - http://docs.travis-ci.com/user/workers/standard-infrastructure/ sudo: false +script: + - make setup + - make test + notifications: webhooks: urls: diff --git a/vendor/github.com/Masterminds/vcs/CHANGELOG.md b/vendor/github.com/Masterminds/vcs/CHANGELOG.md index 6362674264..4ac3e69202 100644 --- a/vendor/github.com/Masterminds/vcs/CHANGELOG.md +++ b/vendor/github.com/Masterminds/vcs/CHANGELOG.md @@ -1,3 +1,43 @@ +# 1.11.0 (2017-03-23) + +## Added +- #65: Exposed CmdFromDir function (thanks @erizocosmico) + +## Changed +- #69: Updated testing for Go 1.8 + +## Fixed +- #64: Testing fatal error if bzr not installed (thanks @kevinburke) + +# 1.10.2 (2017-01-24) + +## Fixed +- #63: Remove extra quotes in submodule export (thanks @dt) + +# 1.10.1 (2017-01-18) + +## Fixed +- #62: Added windows testing via appveyor and fixed issues under windows. + +# 1.10.0 (2017-01-09) + +## Added +- #60: Handle Git submodules (thanks @sdboyer) +- #61: Add gometalinter to testing + +# 1.9.0 (2016-11-18) + +## Added +- #50: Auto-detect remotes with file:// prefix. +- #59: Testing against Go 1.7 + +## Changed +- Removed auto-detection for Google Code as the service is deprecated +- Added auto-detection of git.openstack.org + +## Fixed +- #53: Git not fetching tags off branch + # 1.8.0 (2016-06-29) ## Added diff --git a/vendor/github.com/Masterminds/vcs/Makefile b/vendor/github.com/Masterminds/vcs/Makefile new file mode 100644 index 0000000000..5d722c2f4b --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/Makefile @@ -0,0 +1,41 @@ +.PHONY: setup +setup: + go get -u gopkg.in/alecthomas/gometalinter.v1 + gometalinter.v1 --install + +.PHONY: test +test: validate lint + @echo "==> Running tests" + go test -v + +.PHONY: validate +validate: +# misspell finds the work adresář (used in bzr.go) as a mispelling of +# address. It finds adres. An issue has been filed at +# https://github.com/client9/misspell/issues/99. In the meantime adding +# adres to the ignore list. + @echo "==> Running static validations" + @gometalinter.v1 \ + --disable-all \ + --linter "misspell:misspell -i adres -j 1 {path}/*.go:PATH:LINE:COL:MESSAGE" \ + --enable deadcode \ + --severity deadcode:error \ + --enable gofmt \ + --enable gosimple \ + --enable ineffassign \ + --enable misspell \ + --enable vet \ + --tests \ + --vendor \ + --deadline 60s \ + ./... || exit_code=1 + +.PHONY: lint +lint: + @echo "==> Running linters" + @gometalinter.v1 \ + --disable-all \ + --enable golint \ + --vendor \ + --deadline 60s \ + ./... || : diff --git a/vendor/github.com/Masterminds/vcs/README.md b/vendor/github.com/Masterminds/vcs/README.md index cdb981fd28..a11268513b 100644 --- a/vendor/github.com/Masterminds/vcs/README.md +++ b/vendor/github.com/Masterminds/vcs/README.md @@ -4,6 +4,8 @@ Manage repos in varying version control systems with ease through a common interface. [![Build Status](https://travis-ci.org/Masterminds/vcs.svg)](https://travis-ci.org/Masterminds/vcs) [![GoDoc](https://godoc.org/github.com/Masterminds/vcs?status.png)](https://godoc.org/github.com/Masterminds/vcs) [![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/vcs)](https://goreportcard.com/report/github.com/Masterminds/vcs) +[![Build status](https://ci.appveyor.com/api/projects/status/vg3cjc561q2trobm?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/vcs) + ## Quick Usage diff --git a/vendor/github.com/Masterminds/vcs/appveyor.yml b/vendor/github.com/Masterminds/vcs/appveyor.yml new file mode 100644 index 0000000000..c0c9170fa7 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/appveyor.yml @@ -0,0 +1,26 @@ + +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\Masterminds\vcs +shallow_clone: true + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +install: + - go version + - go env + - choco install -y bzr + - set PATH=C:\Program Files (x86)\Bazaar;%PATH% + - bzr --version + +build_script: + - go install -v ./... + +test_script: + - go test -v + +deploy: off diff --git a/vendor/github.com/Masterminds/vcs/bzr.go b/vendor/github.com/Masterminds/vcs/bzr.go index e8f55b67c1..8343d3ce70 100644 --- a/vendor/github.com/Masterminds/vcs/bzr.go +++ b/vendor/github.com/Masterminds/vcs/bzr.go @@ -39,7 +39,7 @@ func NewBzrRepo(remote, local string) (*BzrRepo, error) { // http://bazaar.launchpad.net/~mattfarina/govcstestbzrrepo/trunk/. Notice // the change from https to http and the path chance. // Here we set the remote to be the local one if none is passed in. - if err == nil && r.CheckLocal() == true && remote == "" { + if err == nil && r.CheckLocal() && remote == "" { c := exec.Command("bzr", "info") c.Dir = local c.Env = envForDir(c.Dir) @@ -226,11 +226,7 @@ func (s *BzrRepo) Tags() ([]string, error) { // commit id or tag. func (s *BzrRepo) IsReference(r string) bool { _, err := s.RunFromDir("bzr", "revno", "-r", r) - if err == nil { - return true - } - - return false + return err == nil } // IsDirty returns if the checkout has been modified from the checked @@ -308,21 +304,14 @@ func (s *BzrRepo) Ping() bool { // an error is returned. Launchpad returns a 404 for a codebase that // does not exist. Otherwise it returns a JSON object describing it. _, er := get("https://api.launchpad.net/1.0/" + try) - if er == nil { - return true - } - return false + return er == nil } } // This is the same command that Go itself uses but it's not fast (or fast // enough by my standards). A faster method would be useful. _, err = s.run("bzr", "info", s.Remote()) - if err != nil { - return false - } - - return true + return err == nil } // ExportDir exports the current revision to the passed in directory. @@ -340,6 +329,7 @@ func (s *BzrRepo) ExportDir(dir string) error { // https://bazaar.launchpad.net/~bzr-pqm/bzr/bzr.dev/files/head:/po/ func (s *BzrRepo) isUnableToCreateDir(err error) bool { msg := err.Error() + if strings.HasPrefix(msg, fmt.Sprintf("Parent directory of %s does not exist.", s.LocalPath())) || strings.HasPrefix(msg, fmt.Sprintf("Nadřazený adresář %s neexistuje.", s.LocalPath())) || strings.HasPrefix(msg, fmt.Sprintf("El directorio padre de %s no existe.", s.LocalPath())) || diff --git a/vendor/github.com/Masterminds/vcs/bzr_test.go b/vendor/github.com/Masterminds/vcs/bzr_test.go index e12c6d30b2..4b2e50ec60 100644 --- a/vendor/github.com/Masterminds/vcs/bzr_test.go +++ b/vendor/github.com/Masterminds/vcs/bzr_test.go @@ -31,7 +31,7 @@ func TestBzr(t *testing.T) { repo, err := NewBzrRepo("https://launchpad.net/govcstestbzrrepo", tempDir+"/govcstestbzrrepo") if err != nil { - t.Error(err) + t.Fatal(err) } if repo.Vcs() != Bzr { @@ -55,7 +55,7 @@ func TestBzr(t *testing.T) { } // Verify Bzr repo is a Bzr repo - if repo.CheckLocal() == false { + if !repo.CheckLocal() { t.Error("Problem checking out repo or Bzr CheckLocal is not working") } @@ -75,7 +75,7 @@ func TestBzr(t *testing.T) { t.Error(nrerr) } // Verify the right oject is returned. It will check the local repo type. - if nrepo.CheckLocal() == false { + if !nrepo.CheckLocal() { t.Error("Wrong version returned from NewRepo") } @@ -164,15 +164,15 @@ func TestBzr(t *testing.T) { t.Error("Bzr is incorrectly returning branches") } - if repo.IsReference("1.0.0") != true { + if !repo.IsReference("1.0.0") { t.Error("Bzr is reporting a reference is not one") } - if repo.IsReference("foo") == true { - t.Error("Bzr is reporting a non-existant reference is one") + if repo.IsReference("foo") { + t.Error("Bzr is reporting a non-existent reference is one") } - if repo.IsDirty() == true { + if repo.IsDirty() { t.Error("Bzr incorrectly reporting dirty") } @@ -227,7 +227,7 @@ func TestBzr(t *testing.T) { _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) if err != nil { - if found := os.IsNotExist(err); found == false { + if found := os.IsNotExist(err); !found { t.Errorf("Error checking exported metadata in Bzr: %s", err) } } else { @@ -250,7 +250,7 @@ func TestBzrCheckLocal(t *testing.T) { }() repo, _ := NewBzrRepo("", tempDir) - if repo.CheckLocal() == true { + if repo.CheckLocal() { t.Error("Bzr CheckLocal does not identify non-Bzr location") } diff --git a/vendor/github.com/Masterminds/vcs/errors.go b/vendor/github.com/Masterminds/vcs/errors.go index ea8c5fc30d..be7097040d 100644 --- a/vendor/github.com/Masterminds/vcs/errors.go +++ b/vendor/github.com/Masterminds/vcs/errors.go @@ -5,7 +5,7 @@ import "errors" // The vcs package provides ways to work with errors that hide the underlying // implementation details but make them accessible if needed. For basic errors // that do not have underlying implementation specific details or the underlying -// details are likely not necessairy there are errors for comparison. +// details are not necessary there are errors for comparison. // // For example: // diff --git a/vendor/github.com/Masterminds/vcs/git.go b/vendor/github.com/Masterminds/vcs/git.go index eb4b86e9e1..c9e17ca750 100644 --- a/vendor/github.com/Masterminds/vcs/git.go +++ b/vendor/github.com/Masterminds/vcs/git.go @@ -33,7 +33,7 @@ func NewGitRepo(remote, local string) (*GitRepo, error) { // Make sure the local Git repo is configured the same as the remote when // A remote value was passed in. - if err == nil && r.CheckLocal() == true { + if err == nil && r.CheckLocal() { c := exec.Command("git", "config", "--get", "remote.origin.url") c.Dir = local c.Env = envForDir(c.Dir) @@ -70,7 +70,7 @@ func (s GitRepo) Vcs() Type { // Get is used to perform an initial clone of a repository. func (s *GitRepo) Get() error { - out, err := s.run("git", "clone", s.Remote(), s.LocalPath()) + out, err := s.run("git", "clone", "--recursive", s.Remote(), s.LocalPath()) // There are some windows cases where Git cannot create the parent directory, // if it does not already exist, to the location it's trying to create the @@ -131,7 +131,7 @@ func (s *GitRepo) Init() error { // Update performs an Git fetch and pull to an existing checkout. func (s *GitRepo) Update() error { // Perform a fetch to make sure everything is up to date. - out, err := s.RunFromDir("git", "fetch", s.RemoteLocation) + out, err := s.RunFromDir("git", "fetch", "--tags", s.RemoteLocation) if err != nil { return NewRemoteError("Unable to update repository", err, string(out)) } @@ -143,7 +143,7 @@ func (s *GitRepo) Update() error { return NewLocalError("Unable to update repository", err, "") } - if detached == true { + if detached { return nil } @@ -151,7 +151,8 @@ func (s *GitRepo) Update() error { if err != nil { return NewRemoteError("Unable to update repository", err, string(out)) } - return nil + + return s.defendAgainstSubmodules() } // UpdateVersion sets the version of a package currently checked out via Git. @@ -160,6 +161,30 @@ func (s *GitRepo) UpdateVersion(version string) error { if err != nil { return NewLocalError("Unable to update checked out version", err, string(out)) } + + return s.defendAgainstSubmodules() +} + +// defendAgainstSubmodules tries to keep repo state sane in the event of +// submodules. Or nested submodules. What a great idea, submodules. +func (s *GitRepo) defendAgainstSubmodules() error { + // First, update them to whatever they should be, if there should happen to be any. + out, err := s.RunFromDir("git", "submodule", "update", "--init", "--recursive") + if err != nil { + return NewLocalError("Unexpected error while defensively updating submodules", err, string(out)) + } + // Now, do a special extra-aggressive clean in case changing versions caused + // one or more submodules to go away. + out, err = s.RunFromDir("git", "clean", "-x", "-d", "-f", "-f") + if err != nil { + return NewLocalError("Unexpected error while defensively cleaning up after possible derelict submodule directories", err, string(out)) + } + // Then, repeat just in case there are any nested submodules that went away. + out, err = s.RunFromDir("git", "submodule", "foreach", "--recursive", "git", "clean", "-x", "-d", "-f", "-f") + if err != nil { + return NewLocalError("Unexpected error while defensively cleaning up after possible derelict nested submodule directories", err, string(out)) + } + return nil } @@ -255,11 +280,7 @@ func (s *GitRepo) IsReference(r string) bool { // not been checked out yet. This next step should pickup the other // possible references. _, err = s.RunFromDir("git", "show-ref", r) - if err == nil { - return true - } - - return false + return err == nil } // IsDirty returns if the checkout has been modified from the checked @@ -339,11 +360,7 @@ func (s *GitRepo) Ping() bool { // remote needs to be different. c.Env = mergeEnvLists([]string{"GIT_TERMINAL_PROMPT=0"}, os.Environ()) _, err := c.CombinedOutput() - if err != nil { - return false - } - - return true + return err == nil } // ExportDir exports the current revision to the passed in directory. @@ -354,11 +371,25 @@ func (s *GitRepo) ExportDir(dir string) error { dir = dir + string(os.PathSeparator) } + // checkout-index on some systems, such as some Windows cases, does not + // create the parent directory to export into if it does not exist. Explicitly + // creating it. + err := os.MkdirAll(dir, 0755) + if err != nil { + return NewLocalError("Unable to create directory", err, "") + } + out, err := s.RunFromDir("git", "checkout-index", "-f", "-a", "--prefix="+dir) s.log(out) if err != nil { return NewLocalError("Unable to export source", err, string(out)) } + // and now, the horror of submodules + out, err = s.RunFromDir("git", "submodule", "foreach", "--recursive", "git checkout-index -f -a --prefix=\""+filepath.Join(dir, "$path")+string(filepath.Separator)+"\"") + s.log(out) + if err != nil { + return NewLocalError("Error while exporting submodule sources", err, string(out)) + } return nil } diff --git a/vendor/github.com/Masterminds/vcs/git_test.go b/vendor/github.com/Masterminds/vcs/git_test.go index 80eae55ae2..7c6e093399 100644 --- a/vendor/github.com/Masterminds/vcs/git_test.go +++ b/vendor/github.com/Masterminds/vcs/git_test.go @@ -1,6 +1,7 @@ package vcs import ( + "fmt" "io/ioutil" "path/filepath" "time" @@ -53,7 +54,7 @@ func TestGit(t *testing.T) { } // Verify Git repo is a Git repo - if repo.CheckLocal() == false { + if !repo.CheckLocal() { t.Error("Problem checking out repo or Git CheckLocal is not working") } @@ -73,7 +74,7 @@ func TestGit(t *testing.T) { t.Error(nrerr) } // Verify the right oject is returned. It will check the local repo type. - if nrepo.CheckLocal() == false { + if !nrepo.CheckLocal() { t.Error("Wrong version returned from NewRepo") } @@ -153,8 +154,23 @@ func TestGit(t *testing.T) { if err != nil { t.Error(err) } - if tags[0] != "1.0.0" { - t.Error("Git tags is not reporting the correct version") + + var hasRelTag bool + var hasOffMasterTag bool + + for _, tv := range tags { + if tv == "1.0.0" { + hasRelTag = true + } else if tv == "off-master-tag" { + hasOffMasterTag = true + } + } + + if !hasRelTag { + t.Error("Git tags unable to find release tag on master") + } + if !hasOffMasterTag { + t.Error("Git tags did not fetch tags not on master") } tags, err = repo.TagsFromCommit("74dd547545b7df4aa285bcec1b54e2b76f726395") @@ -177,20 +193,20 @@ func TestGit(t *testing.T) { if err != nil { t.Error(err) } - // The branches should be HEAD, master, and test. - if branches[2] != "test" { + // The branches should be HEAD, master, other, and test. + if branches[3] != "test" { t.Error("Git is incorrectly returning branches") } - if repo.IsReference("1.0.0") != true { + if !repo.IsReference("1.0.0") { t.Error("Git is reporting a reference is not one") } - if repo.IsReference("foo") == true { - t.Error("Git is reporting a non-existant reference is one") + if repo.IsReference("foo") { + t.Error("Git is reporting a non-existent reference is one") } - if repo.IsDirty() == true { + if repo.IsDirty() { t.Error("Git incorrectly reporting dirty") } @@ -245,7 +261,7 @@ func TestGit(t *testing.T) { _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) if err != nil { - if found := os.IsNotExist(err); found == false { + if found := os.IsNotExist(err); !found { t.Errorf("Error checking exported metadata in Git: %s", err) } } else { @@ -268,7 +284,7 @@ func TestGitCheckLocal(t *testing.T) { }() repo, _ := NewGitRepo("", tempDir) - if repo.CheckLocal() == true { + if repo.CheckLocal() { t.Error("Git CheckLocal does not identify non-Git location") } @@ -341,3 +357,128 @@ func TestGitInit(t *testing.T) { t.Error(err) } } + +func TestGitSubmoduleHandling(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-git-submodule-tests") + if err != nil { + t.Fatal(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + dumplocal := func(err error) string { + if terr, ok := err.(*LocalError); ok { + return fmt.Sprintf("msg: %s\norig: %s\nout: %s", terr.Error(), terr.Original(), terr.Out()) + } + return err.Error() + } + + subdirExists := func(dir ...string) bool { + _, err := os.Stat(filepath.Join(append([]string{tempDir}, dir...)...)) + return err == nil + } + + // Initial clone should get version with two submodules, each of which have + // their own submodule + repo, err := NewGitRepo("https://github.com/sdboyer/subm", tempDir) + if err != nil { + t.Fatal(dumplocal(err)) + } + err = repo.Get() + if err != nil { + t.Fatalf("unable to clone Git repo. Err was %s", dumplocal(err)) + } + + // Verify we are on the right version. + v, err := repo.Version() + if v != "18e3a5f6fc7f6d577e732e7a5ab2caf990efbf8f" { + t.Fatalf("did not start from expected rev, tests could fail - bailing out (got %s)", v) + } + if err != nil { + t.Fatal(dumplocal(err)) + } + + if !subdirExists("subm1", ".git") { + t.Fatal("subm1 submodule does not exist on initial clone/checkout") + } + if !subdirExists("subm1", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm1 does not exist on initial clone/checkout") + } + + if !subdirExists("subm-again", ".git") { + t.Fatal("subm-again submodule does not exist on initial clone/checkout") + } + if !subdirExists("subm-again", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm-again does not exist on initial clone/checkout") + } + + // Now switch to version with no submodules, make sure they all go away + err = repo.UpdateVersion("e677f82015f72ac1c8fafa66b5463163b3597af2") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if subdirExists("subm1") { + t.Fatal("checking out version without submodule did not clean up immediate submodules") + } + if subdirExists("subm1", "dep-test") { + t.Fatal("checking out version without submodule did not clean up nested submodules") + } + if subdirExists("subm-again") { + t.Fatal("checking out version without submodule did not clean up immediate submodules") + } + if subdirExists("subm-again", "dep-test") { + t.Fatal("checking out version without submodule did not clean up nested submodules") + } + + err = repo.UpdateVersion("aaf7aa1bc4c3c682cc530eca8f80417088ee8540") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if !subdirExists("subm1", ".git") { + t.Fatal("checking out version with immediate submodule did not set up git subrepo") + } + + err = repo.UpdateVersion("6cc4669af468f3b4f16e7e96275ad01ade5b522f") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if !subdirExists("subm1", "dep-test", ".git") { + t.Fatal("checking out version with nested submodule did not set up nested git subrepo") + } + + err = repo.UpdateVersion("aaf7aa1bc4c3c682cc530eca8f80417088ee8540") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if subdirExists("subm1", "dep-test") { + t.Fatal("rolling back to version without nested submodule did not clean up the nested submodule") + } + + err = repo.UpdateVersion("18e3a5f6fc7f6d577e732e7a5ab2caf990efbf8f") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if !subdirExists("subm1", ".git") { + t.Fatal("subm1 submodule does not exist after switch from other commit") + } + if !subdirExists("subm1", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm1 does not exist after switch from other commit") + } + + if !subdirExists("subm-again", ".git") { + t.Fatal("subm-again submodule does not exist after switch from other commit") + } + if !subdirExists("subm-again", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm-again does not exist after switch from other commit") + } + +} diff --git a/vendor/github.com/Masterminds/vcs/hg.go b/vendor/github.com/Masterminds/vcs/hg.go index df41cd6259..5000a6d9da 100644 --- a/vendor/github.com/Masterminds/vcs/hg.go +++ b/vendor/github.com/Masterminds/vcs/hg.go @@ -32,7 +32,7 @@ func NewHgRepo(remote, local string) (*HgRepo, error) { // Make sure the local Hg repo is configured the same as the remote when // A remote value was passed in. - if err == nil && r.CheckLocal() == true { + if err == nil && r.CheckLocal() { // An Hg repo was found so test that the URL there matches // the repo passed in here. c := exec.Command("hg", "paths") @@ -207,11 +207,7 @@ func (s *HgRepo) Tags() ([]string, error) { // commit id, branch, or tag. func (s *HgRepo) IsReference(r string) bool { _, err := s.RunFromDir("hg", "log", "-r", r) - if err == nil { - return true - } - - return false + return err == nil } // IsDirty returns if the checkout has been modified from the checked @@ -305,11 +301,7 @@ func (s *HgRepo) TagsFromCommit(id string) ([]string, error) { // Ping returns if remote location is accessible. func (s *HgRepo) Ping() bool { _, err := s.run("hg", "identify", s.Remote()) - if err != nil { - return false - } - - return true + return err == nil } // ExportDir exports the current revision to the passed in directory. diff --git a/vendor/github.com/Masterminds/vcs/hg_test.go b/vendor/github.com/Masterminds/vcs/hg_test.go index b8aa39a114..6b19f72809 100644 --- a/vendor/github.com/Masterminds/vcs/hg_test.go +++ b/vendor/github.com/Masterminds/vcs/hg_test.go @@ -55,7 +55,7 @@ func TestHg(t *testing.T) { } // Verify Hg repo is a Hg repo - if repo.CheckLocal() == false { + if !repo.CheckLocal() { t.Error("Problem checking out repo or Hg CheckLocal is not working") } @@ -75,7 +75,7 @@ func TestHg(t *testing.T) { t.Error(nrerr) } // Verify the right oject is returned. It will check the local repo type. - if nrepo.CheckLocal() == false { + if !nrepo.CheckLocal() { t.Error("Wrong version returned from NewRepo") } @@ -166,19 +166,19 @@ func TestHg(t *testing.T) { t.Error("Hg is incorrectly returning branches") } - if repo.IsReference("1.0.0") != true { + if !repo.IsReference("1.0.0") { t.Error("Hg is reporting a reference is not one") } - if repo.IsReference("test") != true { + if !repo.IsReference("test") { t.Error("Hg is reporting a reference is not one") } - if repo.IsReference("foo") == true { - t.Error("Hg is reporting a non-existant reference is one") + if repo.IsReference("foo") { + t.Error("Hg is reporting a non-existent reference is one") } - if repo.IsDirty() == true { + if repo.IsDirty() { t.Error("Hg incorrectly reporting dirty") } @@ -231,7 +231,7 @@ func TestHg(t *testing.T) { _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) if err != nil { - if found := os.IsNotExist(err); found == false { + if found := os.IsNotExist(err); !found { t.Errorf("Error checking exported metadata in Hg: %s", err) } } else { @@ -254,7 +254,7 @@ func TestHgCheckLocal(t *testing.T) { }() repo, _ := NewHgRepo("", tempDir) - if repo.CheckLocal() == true { + if repo.CheckLocal() { t.Error("Hg CheckLocal does not identify non-Hg location") } diff --git a/vendor/github.com/Masterminds/vcs/repo.go b/vendor/github.com/Masterminds/vcs/repo.go index 1298a5f927..356dad6f9f 100644 --- a/vendor/github.com/Masterminds/vcs/repo.go +++ b/vendor/github.com/Masterminds/vcs/repo.go @@ -130,6 +130,10 @@ type Repo interface { // RunFromDir executes a command from repo's directory. RunFromDir(cmd string, args ...string) ([]byte, error) + // CmdFromDir creates a new command that will be executed from repo's + // directory. + CmdFromDir(cmd string, args ...string) *exec.Cmd + // ExportDir exports the current revision to the passed in directory. ExportDir(string) error } @@ -220,10 +224,15 @@ func (b base) run(cmd string, args ...string) ([]byte, error) { return out, err } -func (b *base) RunFromDir(cmd string, args ...string) ([]byte, error) { +func (b *base) CmdFromDir(cmd string, args ...string) *exec.Cmd { c := exec.Command(cmd, args...) c.Dir = b.local c.Env = envForDir(c.Dir) + return c +} + +func (b *base) RunFromDir(cmd string, args ...string) ([]byte, error) { + c := b.CmdFromDir(cmd, args...) out, err := c.CombinedOutput() return out, err } diff --git a/vendor/github.com/Masterminds/vcs/repo_test.go b/vendor/github.com/Masterminds/vcs/repo_test.go index d61f6cbea9..8c083b3fc4 100644 --- a/vendor/github.com/Masterminds/vcs/repo_test.go +++ b/vendor/github.com/Masterminds/vcs/repo_test.go @@ -46,7 +46,7 @@ func TestTypeSwitch(t *testing.T) { } }() - repo, err := NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir+"/VCSTestRepo") + repo, err := NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir+string(os.PathSeparator)+"VCSTestRepo") if err != nil { t.Error(err) } @@ -55,7 +55,7 @@ func TestTypeSwitch(t *testing.T) { t.Errorf("Unable to checkout SVN repo for repo switching tests. Err was %s", err) } - _, err = NewRepo("https://github.com/Masterminds/VCSTestRepo", tempDir+"/VCSTestRepo") + _, err = NewRepo("https://github.com/Masterminds/VCSTestRepo", tempDir+string(os.PathSeparator)+"VCSTestRepo") if err != ErrWrongVCS { t.Errorf("Not detecting repo switch from SVN to Git") } @@ -63,12 +63,12 @@ func TestTypeSwitch(t *testing.T) { func TestDepInstalled(t *testing.T) { i := depInstalled("git") - if i != true { + if !i { t.Error("depInstalled not finding installed dep.") } i = depInstalled("thisreallyisntinstalled") - if i != false { + if i { t.Error("depInstalled finding not installed dep.") } } diff --git a/vendor/github.com/Masterminds/vcs/svn.go b/vendor/github.com/Masterminds/vcs/svn.go index 888ae09553..913f90a8f0 100644 --- a/vendor/github.com/Masterminds/vcs/svn.go +++ b/vendor/github.com/Masterminds/vcs/svn.go @@ -6,6 +6,7 @@ import ( "os" "os/exec" "path/filepath" + "runtime" "strings" "time" ) @@ -33,7 +34,7 @@ func NewSvnRepo(remote, local string) (*SvnRepo, error) { // Make sure the local SVN repo is configured the same as the remote when // A remote value was passed in. - if err == nil && r.CheckLocal() == true { + if err == nil && r.CheckLocal() { // An SVN repo was found so test that the URL there matches // the repo passed in here. out, err := exec.Command("svn", "info", local).CombinedOutput() @@ -76,6 +77,8 @@ func (s *SvnRepo) Get() error { remote := s.Remote() if strings.HasPrefix(remote, "/") { remote = "file://" + remote + } else if runtime.GOOS == "windows" && filepath.VolumeName(remote) != "" { + remote = "file:///" + remote } out, err := s.run("svn", "checkout", remote, s.LocalPath()) if err != nil { @@ -139,6 +142,9 @@ func (s *SvnRepo) Version() (string, error) { } out, err := s.RunFromDir("svn", "info", "--xml") + if err != nil { + return "", NewLocalError("Unable to retrieve checked out version", err, string(out)) + } s.log(out) infos := &Info{} err = xml.Unmarshal(out, &infos) @@ -180,8 +186,8 @@ func (s *SvnRepo) Date() (time.Time, error) { if err != nil { return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out)) } - const longForm = "2006-01-02T15:04:05.000000Z\n" - t, err := time.Parse(longForm, string(out)) + const longForm = "2006-01-02T15:04:05.000000Z" + t, err := time.Parse(longForm, strings.TrimSpace(string(out))) if err != nil { return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out)) } @@ -190,14 +196,24 @@ func (s *SvnRepo) Date() (time.Time, error) { // CheckLocal verifies the local location is an SVN repo. func (s *SvnRepo) CheckLocal() bool { - sep := fmt.Sprintf("%c", os.PathSeparator) - psplit := strings.Split(s.LocalPath(), sep) - for i := 0; i < len(psplit); i++ { - path := fmt.Sprintf("%s%s", sep, filepath.Join(psplit[0:(len(psplit)-(i))]...)) - if _, err := os.Stat(filepath.Join(path, ".svn")); err == nil { + pth, err := filepath.Abs(s.LocalPath()) + if err != nil { + s.log(err.Error()) + return false + } + + if _, err := os.Stat(filepath.Join(pth, ".svn")); err == nil { + return true + } + + oldpth := pth + for oldpth != pth { + pth = filepath.Dir(pth) + if _, err := os.Stat(filepath.Join(pth, ".svn")); err == nil { return true } } + return false } @@ -261,6 +277,9 @@ func (s *SvnRepo) CommitInfo(id string) (*CommitInfo, error) { } out, err := s.RunFromDir("svn", "info", "-r", id, "--xml") + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } infos := &Info{} err = xml.Unmarshal(out, &infos) if err != nil { @@ -323,11 +342,7 @@ func (s *SvnRepo) TagsFromCommit(id string) ([]string, error) { // Ping returns if remote location is accessible. func (s *SvnRepo) Ping() bool { _, err := s.run("svn", "--non-interactive", "info", s.Remote()) - if err != nil { - return false - } - - return true + return err == nil } // ExportDir exports the current revision to the passed in directory. @@ -346,11 +361,7 @@ func (s *SvnRepo) ExportDir(dir string) error { // where the parent directory of the VCS local path doesn't exist. func (s *SvnRepo) isUnableToCreateDir(err error) bool { msg := err.Error() - if strings.HasPrefix(msg, "E000002") { - return true - } - - return false + return strings.HasPrefix(msg, "E000002") } // detectRemoteFromInfoCommand finds the remote url from the `svn info` diff --git a/vendor/github.com/Masterminds/vcs/svn_test.go b/vendor/github.com/Masterminds/vcs/svn_test.go index d242f3eedd..93fc139ab9 100644 --- a/vendor/github.com/Masterminds/vcs/svn_test.go +++ b/vendor/github.com/Masterminds/vcs/svn_test.go @@ -28,7 +28,7 @@ func TestSvn(t *testing.T) { } }() - repo, err := NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir+"/VCSTestRepo") + repo, err := NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir+string(os.PathSeparator)+"VCSTestRepo") if err != nil { t.Error(err) } @@ -41,7 +41,7 @@ func TestSvn(t *testing.T) { if repo.Remote() != "https://github.com/Masterminds/VCSTestRepo/trunk" { t.Error("Remote not set properly") } - if repo.LocalPath() != tempDir+"/VCSTestRepo" { + if repo.LocalPath() != tempDir+string(os.PathSeparator)+"VCSTestRepo" { t.Error("Local disk location not set properly") } @@ -54,7 +54,7 @@ func TestSvn(t *testing.T) { } // Verify SVN repo is a SVN repo - if repo.CheckLocal() == false { + if !repo.CheckLocal() { t.Error("Problem checking out repo or SVN CheckLocal is not working") } @@ -167,15 +167,15 @@ func TestSvn(t *testing.T) { t.Error("Svn is incorrectly returning branches") } - if repo.IsReference("r4") != true { + if !repo.IsReference("r4") { t.Error("Svn is reporting a reference is not one") } - if repo.IsReference("55") == true { - t.Error("Svn is reporting a non-existant reference is one") + if repo.IsReference("55") { + t.Error("Svn is reporting a non-existent reference is one") } - if repo.IsDirty() == true { + if repo.IsDirty() { t.Error("Svn incorrectly reporting dirty") } @@ -230,7 +230,7 @@ func TestSvn(t *testing.T) { _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) if err != nil { - if found := os.IsNotExist(err); found == false { + if found := os.IsNotExist(err); !found { t.Errorf("Error checking exported metadata in Svn: %s", err) } } else { @@ -253,7 +253,7 @@ func TestSvnCheckLocal(t *testing.T) { }() repo, _ := NewSvnRepo("", tempDir) - if repo.CheckLocal() == true { + if repo.CheckLocal() { t.Error("SVN CheckLocal does not identify non-SVN location") } @@ -300,8 +300,8 @@ func TestSvnPing(t *testing.T) { func TestSvnInit(t *testing.T) { tempDir, err := ioutil.TempDir("", "go-vcs-svn-tests") - remoteDir := tempDir + "/remoteDir" - localDir := tempDir + "/localDir" + remoteDir := tempDir + string(os.PathSeparator) + "remoteDir" + localDir := tempDir + string(os.PathSeparator) + "localDir" if err != nil { t.Error(err) } diff --git a/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go b/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go index f965132b03..09f6e22ebe 100644 --- a/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go +++ b/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go @@ -2,12 +2,20 @@ package vcs import ( "os" + "runtime" + "strings" ) // DetectVcsFromFS detects the type from the local path. // Is there a better way to do this? func DetectVcsFromFS(vcsPath string) (Type, error) { + // There are cases under windows that a path could start with a / and it needs + // to be stripped. For example, a path such as /C:\foio\bar. + if runtime.GOOS == "windows" && strings.HasPrefix(vcsPath, "/") { + vcsPath = strings.TrimPrefix(vcsPath, "/") + } + // When the local directory to the package doesn't exist // it's not yet downloaded so we can't detect the type // locally. @@ -15,20 +23,20 @@ func DetectVcsFromFS(vcsPath string) (Type, error) { return "", ErrCannotDetectVCS } - seperator := string(os.PathSeparator) + separator := string(os.PathSeparator) // Walk through each of the different VCS types to see if // one can be detected. Do this is order of guessed popularity. - if _, err := os.Stat(vcsPath + seperator + ".git"); err == nil { + if _, err := os.Stat(vcsPath + separator + ".git"); err == nil { return Git, nil } - if _, err := os.Stat(vcsPath + seperator + ".svn"); err == nil { + if _, err := os.Stat(vcsPath + separator + ".svn"); err == nil { return Svn, nil } - if _, err := os.Stat(vcsPath + seperator + ".hg"); err == nil { + if _, err := os.Stat(vcsPath + separator + ".hg"); err == nil { return Hg, nil } - if _, err := os.Stat(vcsPath + seperator + ".bzr"); err == nil { + if _, err := os.Stat(vcsPath + separator + ".bzr"); err == nil { return Bzr, nil } diff --git a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go index 0567af8b19..6689f957f1 100644 --- a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go +++ b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go @@ -55,16 +55,10 @@ var vcsList = []*vcsInfo{ vcs: Git, pattern: `^(go\.googlesource\.com/[A-Za-z0-9_.\-]+/?)$`, }, - // TODO: Once Google Code becomes fully deprecated this can be removed. { - host: "code.google.com", - addCheck: checkGoogle, - pattern: `^(code\.google\.com/[pr]/(?P[a-z0-9\-]+)(\.(?P[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`, - }, - // Alternative Google setup. This is the previous structure but it still works... until Google Code goes away. - { - addCheck: checkURL, - pattern: `^([a-z0-9_\-.]+)\.googlecode\.com/(?Pgit|hg|svn)(/.*)?$`, + host: "git.openstack.org", + vcs: Git, + pattern: `^(git\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)$`, }, // If none of the previous detect the type they will fall to this looking for the type in a generic sense // by the extension to the path. @@ -158,6 +152,11 @@ func detectVcsFromURL(vcsURL string) (Type, error) { } } + // Detect file schemes + if u.Scheme == "file" { + return DetectVcsFromFS(u.Path) + } + if u.Host == "" { return "", ErrCannotDetectVCS } @@ -267,37 +266,6 @@ func checkBitbucket(i map[string]string, ul *url.URL) (Type, error) { } -// Google supports Git, Hg, and Svn. The SVN style is only -// supported through their legacy setup at .googlecode.com. -// I wonder if anyone is actually using SVN support. -func checkGoogle(i map[string]string, u *url.URL) (Type, error) { - - // To figure out which of the VCS types is used in Google Code you need - // to parse a web page and find it. Ugh. I mean... ugh. - var hack = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`) - - d, err := get(expand(i, "https://code.google.com/p/{project}/source/checkout?repo={repo}")) - if err != nil { - return "", err - } - - if m := hack.FindSubmatch(d); m != nil { - if vcs := string(m[1]); vcs != "" { - if vcs == "svn" { - // While Google supports SVN it can only be used with the legacy - // urls of .googlecode.com. I considered creating a new - // error for this problem but Google Code is going away and there - // is support for the legacy structure. - return "", ErrCannotDetectVCS - } - - return Type(vcs), nil - } - } - - return "", ErrCannotDetectVCS -} - // Expect a type key on i with the exact type detected from the regex. func checkURL(i map[string]string, u *url.URL) (Type, error) { return Type(i["type"]), nil diff --git a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go index e97bba8297..938cb0ebc5 100644 --- a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go +++ b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go @@ -1,6 +1,10 @@ package vcs import ( + "io/ioutil" + "os" + "os/exec" + "runtime" "strings" "testing" ) @@ -24,8 +28,6 @@ func TestVCSLookup(t *testing.T) { "https://hub.jazz.net/git/user1/pkgname": {work: true, t: Git}, "https://hub.jazz.net/git/user1/pkgname/subpkg/subpkg/subpkg": {work: true, t: Git}, "https://hubs.jazz.net/git/user1/pkgname": {work: false, t: Git}, - "http://farbtastic.googlecode.com/svn/": {work: true, t: Svn}, - "http://farbtastic.googlecode.com/svn/trunk": {work: true, t: Svn}, "https://example.com/foo/bar.git": {work: true, t: Git}, "https://example.com/foo/bar.svn": {work: true, t: Svn}, "https://example.com/foo/bar/baz.bzr": {work: true, t: Bzr}, @@ -33,6 +35,7 @@ func TestVCSLookup(t *testing.T) { "https://gopkg.in/tomb.v1": {work: true, t: Git}, "https://golang.org/x/net": {work: true, t: Git}, "https://speter.net/go/exp/math/dec/inf": {work: true, t: Git}, + "https://git.openstack.org/foo/bar": {work: true, t: Git}, "git@github.com:Masterminds/vcs.git": {work: true, t: Git}, "git@example.com:foo.git": {work: true, t: Git}, "ssh://hg@bitbucket.org/mattfarina/testhgrepo": {work: true, t: Hg}, @@ -47,15 +50,15 @@ func TestVCSLookup(t *testing.T) { for u, c := range urlList { ty, _, err := detectVcsFromRemote(u) - if err == nil && c.work == false { + if err == nil && !c.work { t.Errorf("Error detecting VCS from URL(%s)", u) } - if err == ErrCannotDetectVCS && c.work == true { + if err == ErrCannotDetectVCS && c.work { t.Errorf("Error detecting VCS from URL(%s)", u) } - if err != nil && c.work == true { + if err != nil && c.work { t.Errorf("Error detecting VCS from URL(%s): %s", u, err) } @@ -63,16 +66,52 @@ func TestVCSLookup(t *testing.T) { err != ErrCannotDetectVCS && !strings.HasSuffix(err.Error(), "Not Found") && !strings.HasSuffix(err.Error(), "Access Denied") && - c.work == false { + !c.work { t.Errorf("Unexpected error returned (%s): %s", u, err) } - if c.work == true && ty != c.t { + if c.work && ty != c.t { t.Errorf("Incorrect VCS type returned(%s)", u) } } } +func TestVCSFileLookup(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-file-lookup-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + _, err = exec.Command("git", "init", tempDir).CombinedOutput() + if err != nil { + t.Error(err) + } + + // On Windows it should be file:// followed by /C:\for\bar. That / before + // the drive needs to be included in testing. + var pth string + if runtime.GOOS == "windows" { + pth = "file:///" + tempDir + } else { + pth = "file://" + tempDir + } + ty, _, err := detectVcsFromRemote(pth) + + if err != nil { + t.Errorf("Unable to detect file:// path: %s", err) + } + + if ty != Git { + t.Errorf("Detected wrong type from file:// path. Found type %v", ty) + } +} + func TestNotFound(t *testing.T) { _, _, err := detectVcsFromRemote("https://mattfarina.com/notfound") if err == nil || !strings.HasSuffix(err.Error(), " Not Found") { diff --git a/vendor/github.com/sdboyer/gps/CONTRIBUTING.md b/vendor/github.com/sdboyer/gps/CONTRIBUTING.md index 3ff03b36eb..0ed6f9e28a 100644 --- a/vendor/github.com/sdboyer/gps/CONTRIBUTING.md +++ b/vendor/github.com/sdboyer/gps/CONTRIBUTING.md @@ -56,3 +56,12 @@ The changes themselves should generally conform to the following guidelines: * New or changed logic should be accompanied by tests. * Maintainable, table-based tests are strongly preferred, even if it means writing a new testing harness to execute them. + +## Setting up your development environment + +In order to run `gps`'s tests, you'll need to inflate `gps`'s dependencies using +`glide`. Install `[glide](https://github.com/Masterminds/glide)`, and then download +and install `gps`'s dependencies by running `glide install` from the repo base. + +Also, you'll need to have working copies of `git`, `hg`, and `bzr` to run all of +`gps`'s tests. diff --git a/vendor/github.com/sdboyer/gps/README.md b/vendor/github.com/sdboyer/gps/README.md index ea287cc29e..0f956b2c1f 100644 --- a/vendor/github.com/sdboyer/gps/README.md +++ b/vendor/github.com/sdboyer/gps/README.md @@ -10,7 +10,7 @@ GoDoc

--- +--- `gps` is the Go Packaging Solver. It is an engine for tackling dependency management problems in Go. It is trivial - [about 35 lines of @@ -28,8 +28,10 @@ way. It is a distillation of the ideas behind language package managers like [cargo](https://crates.io/) (and others) into a library, artisanally handcrafted with ❤️ for Go's specific requirements. -`gps` is [on track](https://github.com/Masterminds/glide/issues/565) to become -the engine behind [glide](https://glide.sh). It also powers the [experimental, eventually-official Go tooling](https://github.com/golang/dep). +`gps` was [on track](https://github.com/Masterminds/glide/issues/565) to become +the engine behind [glide](https://glide.sh); however, those efforts have been +discontinued in favor of gps powering the [experimental, eventually-official +Go tooling](https://github.com/golang/dep). The wiki has a [general introduction to the `gps` approach](https://github.com/sdboyer/gps/wiki/Introduction-to-gps), as well diff --git a/vendor/github.com/sdboyer/gps/appveyor.yml b/vendor/github.com/sdboyer/gps/appveyor.yml index 8c6b1fd60d..5605fb8e14 100644 --- a/vendor/github.com/sdboyer/gps/appveyor.yml +++ b/vendor/github.com/sdboyer/gps/appveyor.yml @@ -19,7 +19,7 @@ build_script: - C:\gopath\bin\glide install test_script: - - go test + - go test . ./internal/... ./pkgtree/... - go build example.go deploy: off diff --git a/vendor/github.com/sdboyer/gps/bridge.go b/vendor/github.com/sdboyer/gps/bridge.go index 222b372039..ded26eee2e 100644 --- a/vendor/github.com/sdboyer/gps/bridge.go +++ b/vendor/github.com/sdboyer/gps/bridge.go @@ -6,7 +6,7 @@ import ( "path/filepath" "sync/atomic" - "github.com/Masterminds/semver" + "github.com/sdboyer/gps/pkgtree" ) // sourceBridges provide an adapter to SourceManagers that tailor operations @@ -45,7 +45,7 @@ type bridge struct { // Simple, local cache of the root's PackageTree crp *struct { - ptree PackageTree + ptree pkgtree.PackageTree err error } @@ -81,7 +81,7 @@ func (b *bridge) GetManifestAndLock(id ProjectIdentifier, v Version) (Manifest, return m, l, e } -func (b *bridge) AnalyzerInfo() (string, *semver.Version) { +func (b *bridge) AnalyzerInfo() (string, int) { return b.sm.AnalyzerInfo() } @@ -282,7 +282,7 @@ func (b *bridge) vtu(id ProjectIdentifier, v Version) versionTypeUnion { // // The root project is handled separately, as the source manager isn't // responsible for that code. -func (b *bridge) ListPackages(id ProjectIdentifier, v Version) (PackageTree, error) { +func (b *bridge) ListPackages(id ProjectIdentifier, v Version) (pkgtree.PackageTree, error) { if b.s.rd.isRoot(id.ProjectRoot) { return b.s.rd.rpt, nil } diff --git a/vendor/github.com/sdboyer/gps/circle.yml b/vendor/github.com/sdboyer/gps/circle.yml index 8be1609360..70ed51535b 100644 --- a/vendor/github.com/sdboyer/gps/circle.yml +++ b/vendor/github.com/sdboyer/gps/circle.yml @@ -7,7 +7,9 @@ dependencies: pre: - wget https://github.com/Masterminds/glide/releases/download/0.10.1/glide-0.10.1-linux-amd64.tar.gz - tar -vxz -C $HOME/bin --strip=1 -f glide-0.10.1-linux-amd64.tar.gz + - sudo apt-get install bzr subversion override: + - mkdir -p $HOME/.go_workspace/src - glide --home $HOME/.glide -y glide.yaml install --cache - mkdir -p $RD - rsync -azC --delete ./ $RD @@ -18,6 +20,11 @@ test: pre: - go vet override: - - cd $RD && go test -v -coverprofile=coverage.txt -covermode=atomic + - | + cd $RD && \ + echo 'mode: atomic' > coverage.txt && \ + go list ./... | grep -v "/vendor/" | \ + xargs -n1 -I% sh -c 'set -e; go test -covermode=atomic -coverprofile=coverage.out % ; tail -n +2 coverage.out >> coverage.txt' && \ + rm coverage.out - cd $RD && go build example.go - cd $RD && bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/sdboyer/gps/cmd.go b/vendor/github.com/sdboyer/gps/cmd.go index 995c866397..eabda0f994 100644 --- a/vendor/github.com/sdboyer/gps/cmd.go +++ b/vendor/github.com/sdboyer/gps/cmd.go @@ -4,7 +4,10 @@ import ( "bytes" "fmt" "os/exec" + "sync" "time" + + "github.com/Masterminds/vcs" ) // monitoredCmd wraps a cmd and will keep monitoring the process until it @@ -38,8 +41,13 @@ func (c *monitoredCmd) run() error { select { case <-ticker.C: if c.hasTimedOut() { - if err := c.cmd.Process.Kill(); err != nil { - return &killCmdError{err} + // On windows it is apparently (?) possible for the process + // pointer to become nil without Run() having returned (and + // thus, passing through the done channel). Guard against this. + if c.cmd.Process != nil { + if err := c.cmd.Process.Kill(); err != nil { + return &killCmdError{err} + } } return &timeoutError{c.timeout} @@ -52,8 +60,8 @@ func (c *monitoredCmd) run() error { func (c *monitoredCmd) hasTimedOut() bool { t := time.Now().Add(-c.timeout) - return c.stderr.lastActivity.Before(t) && - c.stdout.lastActivity.Before(t) + return c.stderr.lastActivity().Before(t) && + c.stdout.lastActivity().Before(t) } func (c *monitoredCmd) combinedOutput() ([]byte, error) { @@ -67,8 +75,9 @@ func (c *monitoredCmd) combinedOutput() ([]byte, error) { // activityBuffer is a buffer that keeps track of the last time a Write // operation was performed on it. type activityBuffer struct { - buf *bytes.Buffer - lastActivity time.Time + sync.Mutex + buf *bytes.Buffer + lastActivityStamp time.Time } func newActivityBuffer() *activityBuffer { @@ -78,10 +87,18 @@ func newActivityBuffer() *activityBuffer { } func (b *activityBuffer) Write(p []byte) (int, error) { - b.lastActivity = time.Now() + b.Lock() + b.lastActivityStamp = time.Now() + defer b.Unlock() return b.buf.Write(p) } +func (b *activityBuffer) lastActivity() time.Time { + b.Lock() + defer b.Unlock() + return b.lastActivityStamp +} + type timeoutError struct { timeout time.Duration } @@ -97,3 +114,13 @@ type killCmdError struct { func (e killCmdError) Error() string { return fmt.Sprintf("error killing command after timeout: %s", e.err) } + +func runFromCwd(cmd string, args ...string) ([]byte, error) { + c := newMonitoredCmd(exec.Command(cmd, args...), 2*time.Minute) + return c.combinedOutput() +} + +func runFromRepoDir(repo vcs.Repo, cmd string, args ...string) ([]byte, error) { + c := newMonitoredCmd(repo.CmdFromDir(cmd, args...), 2*time.Minute) + return c.combinedOutput() +} diff --git a/vendor/github.com/sdboyer/gps/deduce.go b/vendor/github.com/sdboyer/gps/deduce.go index 1ae97a2395..b14b16f77d 100644 --- a/vendor/github.com/sdboyer/gps/deduce.go +++ b/vendor/github.com/sdboyer/gps/deduce.go @@ -48,10 +48,9 @@ func validateVCSScheme(scheme, typ string) bool { // Regexes for the different known import path flavors var ( - // This regex allowed some usernames that github currently disallows. They - // may have allowed them in the past; keeping it in case we need to revert. - //ghRegex = regexp.MustCompile(`^(?Pgithub\.com/([A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`) - ghRegex = regexp.MustCompile(`^(?Pgithub\.com(/[A-Za-z0-9][-A-Za-z0-9]*[A-Za-z0-9]/[A-Za-z0-9_.\-]+))((?:/[A-Za-z0-9_.\-]+)*)$`) + // This regex allows some usernames that github currently disallows. They + // have allowed them in the past. + ghRegex = regexp.MustCompile(`^(?Pgithub\.com(/[A-Za-z0-9][-A-Za-z0-9]*/[A-Za-z0-9_.\-]+))((?:/[A-Za-z0-9_.\-]+)*)$`) gpinNewRegex = regexp.MustCompile(`^(?Pgopkg\.in(?:(/[a-zA-Z0-9][-a-zA-Z0-9]+)?)(/[a-zA-Z][-.a-zA-Z0-9]*)\.((?:v0|v[1-9][0-9]*)(?:\.0|\.[1-9][0-9]*){0,2}(?:-unstable)?)(?:\.git)?)((?:/[a-zA-Z0-9][-.a-zA-Z0-9]*)*)$`) //gpinOldRegex = regexp.MustCompile(`^(?Pgopkg\.in/(?:([a-z0-9][-a-z0-9]+)/)?((?:v0|v[1-9][0-9]*)(?:\.0|\.[1-9][0-9]*){0,2}(-unstable)?)/([a-zA-Z][-a-zA-Z0-9]*)(?:\.git)?)((?:/[a-zA-Z][-a-zA-Z0-9]*)*)$`) bbRegex = regexp.MustCompile(`^(?Pbitbucket\.org(?P/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))((?:/[A-Za-z0-9_.\-]+)*)$`) @@ -655,7 +654,7 @@ func (sm *SourceMgr) deduceFromPath(path string) (deductionFuture, error) { defer close(c) // make sure the metadata future is finished (without errors), thus // guaranteeing that ru and vcs will be populated - _, err := root() + _, err = root() if err != nil { return } @@ -683,7 +682,6 @@ func (sm *SourceMgr) deduceFromPath(path string) (deductionFuture, error) { return src, ident, err } } - return deductionFuture{ rslow: true, root: root, diff --git a/vendor/github.com/sdboyer/gps/deduce_test.go b/vendor/github.com/sdboyer/gps/deduce_test.go index ead3a82969..5044538400 100644 --- a/vendor/github.com/sdboyer/gps/deduce_test.go +++ b/vendor/github.com/sdboyer/gps/deduce_test.go @@ -77,15 +77,31 @@ var pathDeductionFixtures = map[string][]pathDeductionFixture{ root: "github.com/sdboyer/gps", mb: maybeGitSource{url: mkurl("https://github.com/sdboyer/gps")}, }, + { + in: "github.com/sdboyer-/gps/foo", + root: "github.com/sdboyer-/gps", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://github.com/sdboyer-/gps")}, + maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer-/gps")}, + maybeGitSource{url: mkurl("git://github.com/sdboyer-/gps")}, + maybeGitSource{url: mkurl("http://github.com/sdboyer-/gps")}, + }, + }, + { + in: "github.com/a/gps/foo", + root: "github.com/a/gps", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://github.com/a/gps")}, + maybeGitSource{url: mkurl("ssh://git@github.com/a/gps")}, + maybeGitSource{url: mkurl("git://github.com/a/gps")}, + maybeGitSource{url: mkurl("http://github.com/a/gps")}, + }, + }, // some invalid github username patterns { in: "github.com/-sdboyer/gps/foo", rerr: errors.New("github.com/-sdboyer/gps/foo is not a valid path for a source on github.com"), }, - { - in: "github.com/sdboyer-/gps/foo", - rerr: errors.New("github.com/sdboyer-/gps/foo is not a valid path for a source on github.com"), - }, { in: "github.com/sdbo.yer/gps/foo", rerr: errors.New("github.com/sdbo.yer/gps/foo is not a valid path for a source on github.com"), @@ -467,98 +483,102 @@ var pathDeductionFixtures = map[string][]pathDeductionFixture{ func TestDeduceFromPath(t *testing.T) { for typ, fixtures := range pathDeductionFixtures { - var deducer pathDeducer - switch typ { - case "github": - deducer = githubDeducer{regexp: ghRegex} - case "gopkg.in": - deducer = gopkginDeducer{regexp: gpinNewRegex} - case "jazz": - deducer = jazzDeducer{regexp: jazzRegex} - case "bitbucket": - deducer = bitbucketDeducer{regexp: bbRegex} - case "launchpad": - deducer = launchpadDeducer{regexp: lpRegex} - case "git.launchpad": - deducer = launchpadGitDeducer{regexp: glpRegex} - case "apache": - deducer = apacheDeducer{regexp: apacheRegex} - case "vcsext": - deducer = vcsExtensionDeducer{regexp: vcsExtensionRegex} - default: - // Should just be the vanity imports, which we do elsewhere - continue - } - - var printmb func(mb maybeSource) string - printmb = func(mb maybeSource) string { - switch tmb := mb.(type) { - case maybeSources: - var buf bytes.Buffer - fmt.Fprintf(&buf, "%v maybeSources:", len(tmb)) - for _, elem := range tmb { - fmt.Fprintf(&buf, "\n\t\t%s", printmb(elem)) - } - return buf.String() - case maybeGitSource: - return fmt.Sprintf("%T: %s", tmb, ufmt(tmb.url)) - case maybeBzrSource: - return fmt.Sprintf("%T: %s", tmb, ufmt(tmb.url)) - case maybeHgSource: - return fmt.Sprintf("%T: %s", tmb, ufmt(tmb.url)) - case maybeGopkginSource: - return fmt.Sprintf("%T: %s (v%v) %s ", tmb, tmb.opath, tmb.major, ufmt(tmb.url)) + t.Run(typ, func(t *testing.T) { + var deducer pathDeducer + switch typ { + case "github": + deducer = githubDeducer{regexp: ghRegex} + case "gopkg.in": + deducer = gopkginDeducer{regexp: gpinNewRegex} + case "jazz": + deducer = jazzDeducer{regexp: jazzRegex} + case "bitbucket": + deducer = bitbucketDeducer{regexp: bbRegex} + case "launchpad": + deducer = launchpadDeducer{regexp: lpRegex} + case "git.launchpad": + deducer = launchpadGitDeducer{regexp: glpRegex} + case "apache": + deducer = apacheDeducer{regexp: apacheRegex} + case "vcsext": + deducer = vcsExtensionDeducer{regexp: vcsExtensionRegex} default: - t.Errorf("Unknown maybeSource type: %T", mb) - t.FailNow() + // Should just be the vanity imports, which we do elsewhere + t.Log("skipping") + t.SkipNow() } - return "" - } - for _, fix := range fixtures { - u, in, uerr := normalizeURI(fix.in) - if uerr != nil { - if fix.rerr == nil { - t.Errorf("(in: %s) bad input URI %s", fix.in, uerr) + var printmb func(mb maybeSource, t *testing.T) string + printmb = func(mb maybeSource, t *testing.T) string { + switch tmb := mb.(type) { + case maybeSources: + var buf bytes.Buffer + fmt.Fprintf(&buf, "%v maybeSources:", len(tmb)) + for _, elem := range tmb { + fmt.Fprintf(&buf, "\n\t\t%s", printmb(elem, t)) + } + return buf.String() + case maybeGitSource: + return fmt.Sprintf("%T: %s", tmb, ufmt(tmb.url)) + case maybeBzrSource: + return fmt.Sprintf("%T: %s", tmb, ufmt(tmb.url)) + case maybeHgSource: + return fmt.Sprintf("%T: %s", tmb, ufmt(tmb.url)) + case maybeGopkginSource: + return fmt.Sprintf("%T: %s (v%v) %s ", tmb, tmb.opath, tmb.major, ufmt(tmb.url)) + default: + t.Errorf("Unknown maybeSource type: %T", mb) } - continue + return "" } - root, rerr := deducer.deduceRoot(in) - if fix.rerr != nil { - if rerr == nil { - t.Errorf("(in: %s, %T) Expected error on deducing root, got none:\n\t(WNT) %s", in, deducer, fix.rerr) - } else if fix.rerr.Error() != rerr.Error() { - t.Errorf("(in: %s, %T) Got unexpected error on deducing root:\n\t(GOT) %s\n\t(WNT) %s", in, deducer, rerr, fix.rerr) - } - } else if rerr != nil { - t.Errorf("(in: %s, %T) Got unexpected error on deducing root:\n\t(GOT) %s", in, deducer, rerr) - } else if root != fix.root { - t.Errorf("(in: %s, %T) Deducer did not return expected root:\n\t(GOT) %s\n\t(WNT) %s", in, deducer, root, fix.root) - } + for _, fix := range fixtures { + t.Run(fix.in, func(t *testing.T) { + u, in, uerr := normalizeURI(fix.in) + if uerr != nil { + if fix.rerr == nil { + t.Errorf("bad input URI %s", uerr) + } + t.SkipNow() + } - mb, mberr := deducer.deduceSource(in, u) - if fix.srcerr != nil { - if mberr == nil { - t.Errorf("(in: %s, %T) Expected error on deducing source, got none:\n\t(WNT) %s", in, deducer, fix.srcerr) - } else if fix.srcerr.Error() != mberr.Error() { - t.Errorf("(in: %s, %T) Got unexpected error on deducing source:\n\t(GOT) %s\n\t(WNT) %s", in, deducer, mberr, fix.srcerr) - } - } else if mberr != nil { - // don't complain the fix already expected an rerr - if fix.rerr == nil { - t.Errorf("(in: %s, %T) Got unexpected error on deducing source:\n\t(GOT) %s", in, deducer, mberr) - } - } else if !reflect.DeepEqual(mb, fix.mb) { - if mb == nil { - t.Errorf("(in: %s, %T) Deducer returned source maybes, but none expected:\n\t(GOT) (none)\n\t(WNT) %s", in, deducer, printmb(fix.mb)) - } else if fix.mb == nil { - t.Errorf("(in: %s, %T) Deducer returned source maybes, but none expected:\n\t(GOT) %s\n\t(WNT) (none)", in, deducer, printmb(mb)) - } else { - t.Errorf("(in: %s, %T) Deducer did not return expected source:\n\t(GOT) %s\n\t(WNT) %s", in, deducer, printmb(mb), printmb(fix.mb)) - } + root, rerr := deducer.deduceRoot(in) + if fix.rerr != nil { + if rerr == nil { + t.Errorf("Expected error on deducing root, got none:\n\t(WNT) %s", fix.rerr) + } else if fix.rerr.Error() != rerr.Error() { + t.Errorf("Got unexpected error on deducing root:\n\t(GOT) %s\n\t(WNT) %s", rerr, fix.rerr) + } + } else if rerr != nil { + t.Errorf("Got unexpected error on deducing root:\n\t(GOT) %s", rerr) + } else if root != fix.root { + t.Errorf("Deducer did not return expected root:\n\t(GOT) %s\n\t(WNT) %s", root, fix.root) + } + + mb, mberr := deducer.deduceSource(in, u) + if fix.srcerr != nil { + if mberr == nil { + t.Errorf("Expected error on deducing source, got none:\n\t(WNT) %s", fix.srcerr) + } else if fix.srcerr.Error() != mberr.Error() { + t.Errorf("Got unexpected error on deducing source:\n\t(GOT) %s\n\t(WNT) %s", mberr, fix.srcerr) + } + } else if mberr != nil { + // don't complain the fix already expected an rerr + if fix.rerr == nil { + t.Errorf("Got unexpected error on deducing source:\n\t(GOT) %s", mberr) + } + } else if !reflect.DeepEqual(mb, fix.mb) { + if mb == nil { + t.Errorf("Deducer returned source maybes, but none expected:\n\t(GOT) (none)\n\t(WNT) %s", printmb(fix.mb, t)) + } else if fix.mb == nil { + t.Errorf("Deducer returned source maybes, but none expected:\n\t(GOT) %s\n\t(WNT) (none)", printmb(mb, t)) + } else { + t.Errorf("Deducer did not return expected source:\n\t(GOT) %s\n\t(WNT) %s", printmb(mb, t), printmb(fix.mb, t)) + } + } + }) } - } + }) } } @@ -577,30 +597,32 @@ func TestVanityDeduction(t *testing.T) { for _, fix := range vanities { go func(fix pathDeductionFixture) { defer wg.Done() - pr, err := sm.DeduceProjectRoot(fix.in) - if err != nil { - t.Errorf("(in: %s) Unexpected err on deducing project root: %s", fix.in, err) - return - } else if string(pr) != fix.root { - t.Errorf("(in: %s) Deducer did not return expected root:\n\t(GOT) %s\n\t(WNT) %s", fix.in, pr, fix.root) - } + t.Run(fmt.Sprintf("%s", fix.in), func(t *testing.T) { + pr, err := sm.DeduceProjectRoot(fix.in) + if err != nil { + t.Errorf("Unexpected err on deducing project root: %s", err) + return + } else if string(pr) != fix.root { + t.Errorf("Deducer did not return expected root:\n\t(GOT) %s\n\t(WNT) %s", pr, fix.root) + } - ft, err := sm.deducePathAndProcess(fix.in) - if err != nil { - t.Errorf("(in: %s) Unexpected err on deducing source: %s", fix.in, err) - return - } + ft, err := sm.deducePathAndProcess(fix.in) + if err != nil { + t.Errorf("Unexpected err on deducing source: %s", err) + return + } - _, ident, err := ft.srcf() - if err != nil { - t.Errorf("(in: %s) Unexpected err on executing source future: %s", fix.in, err) - return - } + _, ident, err := ft.srcf() + if err != nil { + t.Errorf("Unexpected err on executing source future: %s", err) + return + } - ustr := fix.mb.(maybeGitSource).url.String() - if ident != ustr { - t.Errorf("(in: %s) Deduced repo ident does not match fixture:\n\t(GOT) %s\n\t(WNT) %s", fix.in, ident, ustr) - } + ustr := fix.mb.(maybeGitSource).url.String() + if ident != ustr { + t.Errorf("Deduced repo ident does not match fixture:\n\t(GOT) %s\n\t(WNT) %s", ident, ustr) + } + }) }(fix) } @@ -620,27 +642,3 @@ func ufmt(u *url.URL) string { return fmt.Sprintf("host=%q, path=%q, opaque=%q, scheme=%q, user=%#v, pass=%#v, rawpath=%q, rawq=%q, frag=%q", u.Host, u.Path, u.Opaque, u.Scheme, user, pass, u.RawPath, u.RawQuery, u.Fragment) } - -func TestIsStdLib(t *testing.T) { - fix := []struct { - ip string - is bool - }{ - {"appengine", true}, - {"net/http", true}, - {"github.com/anything", false}, - {"foo", true}, - } - - for _, f := range fix { - r := doIsStdLib(f.ip) - if r != f.is { - if r { - t.Errorf("%s was marked stdlib but should not have been", f.ip) - } else { - t.Errorf("%s was not marked stdlib but should have been", f.ip) - - } - } - } -} diff --git a/vendor/github.com/sdboyer/gps/example.go b/vendor/github.com/sdboyer/gps/example.go index 61dcdb7885..dd1225454b 100644 --- a/vendor/github.com/sdboyer/gps/example.go +++ b/vendor/github.com/sdboyer/gps/example.go @@ -10,8 +10,8 @@ import ( "path/filepath" "strings" - "github.com/Masterminds/semver" "github.com/sdboyer/gps" + "github.com/sdboyer/gps/pkgtree" ) // This is probably the simplest possible implementation of gps. It does the @@ -36,7 +36,7 @@ func main() { TraceLogger: log.New(os.Stdout, "", 0), } // Perform static analysis on the current project to find all of its imports. - params.RootPackageTree, _ = gps.ListPackages(root, importroot) + params.RootPackageTree, _ = pkgtree.ListPackages(root, importroot) // Set up a SourceManager. This manages interaction with sources (repositories). tempdir, _ := ioutil.TempDir("", "gps-repocache") @@ -66,7 +66,6 @@ func (a NaiveAnalyzer) DeriveManifestAndLock(path string, n gps.ProjectRoot) (gp // Reports the name and version of the analyzer. This is used internally as part // of gps' hashing memoization scheme. -func (a NaiveAnalyzer) Info() (name string, version *semver.Version) { - v, _ := semver.NewVersion("v0.0.1") - return "example-analyzer", v +func (a NaiveAnalyzer) Info() (name string, version int) { + return "example-analyzer", 1 } diff --git a/vendor/github.com/sdboyer/gps/glide.lock b/vendor/github.com/sdboyer/gps/glide.lock index 282a4e9cd4..8d45a7837f 100644 --- a/vendor/github.com/sdboyer/gps/glide.lock +++ b/vendor/github.com/sdboyer/gps/glide.lock @@ -1,19 +1,10 @@ -hash: 2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e -updated: 2016-06-06T22:10:37.696580463-04:00 +hash: ca4079cea0bcb746c052c89611d05eb5649440191bcad12afde0ac4c4a00fb97 +updated: 2017-03-09T21:12:59.686448539+01:00 imports: - name: github.com/armon/go-radix version: 4239b77079c7b5d1243b7b4736304ce8ddb6f0f2 -- name: github.com/hashicorp/go-immutable-radix - version: 8e8ed81f8f0bf1bdd829593fdd5c29922c1ea990 -- name: github.com/hashicorp/golang-lru - version: a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4 - name: github.com/Masterminds/semver version: 94ad6eaf8457cf85a68c9b53fa42e9b1b8683783 - vcs: git - name: github.com/Masterminds/vcs version: abd1ea7037d3652ef9833a164b627f49225e1131 - vcs: git -- name: github.com/termie/go-shutil - version: bcacb06fecaeec8dc42af03c87c6949f4a05c74c - vcs: git -devImports: [] +testImports: [] diff --git a/vendor/github.com/sdboyer/gps/glide.yaml b/vendor/github.com/sdboyer/gps/glide.yaml index 5e379faf04..7f9f8799cd 100644 --- a/vendor/github.com/sdboyer/gps/glide.yaml +++ b/vendor/github.com/sdboyer/gps/glide.yaml @@ -3,6 +3,8 @@ owners: - name: Sam Boyer email: tech@samboyer.org dependencies: +- package: github.com/Masterminds/vcs + version: abd1ea7037d3652ef9833a164b627f49225e1131 - package: github.com/Masterminds/semver branch: 2.x - package: github.com/termie/go-shutil diff --git a/vendor/github.com/sdboyer/gps/hash.go b/vendor/github.com/sdboyer/gps/hash.go index 1cedb260f8..f6e5d07e23 100644 --- a/vendor/github.com/sdboyer/gps/hash.go +++ b/vendor/github.com/sdboyer/gps/hash.go @@ -5,7 +5,10 @@ import ( "crypto/sha256" "io" "sort" + "strconv" "strings" + + "github.com/sdboyer/gps/pkgtree" ) // string headers used to demarcate sections in hash input creation @@ -103,7 +106,7 @@ func (s *solver) writeHashingInputs(w io.Writer) { writeString(hhAnalyzer) an, av := s.b.AnalyzerInfo() writeString(an) - writeString(av.String()) + writeString(strconv.Itoa(av)) } // bytes.Buffer wrapper that injects newlines after each call to Write(). @@ -127,7 +130,7 @@ func HashingInputsAsString(s Solver) string { return (*bytes.Buffer)(buf).String() } -type sortPackageOrErr []PackageOrErr +type sortPackageOrErr []pkgtree.PackageOrErr func (s sortPackageOrErr) Len() int { return len(s) } func (s sortPackageOrErr) Swap(i, j int) { s[i], s[j] = s[j], s[i] } diff --git a/vendor/github.com/sdboyer/gps/hash_test.go b/vendor/github.com/sdboyer/gps/hash_test.go index 5ff324ed88..84f3618df1 100644 --- a/vendor/github.com/sdboyer/gps/hash_test.go +++ b/vendor/github.com/sdboyer/gps/hash_test.go @@ -40,7 +40,7 @@ func TestHashInputs(t *testing.T) { hhOverrides, hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", } for _, v := range elems { h.Write([]byte(v)) @@ -93,7 +93,7 @@ func TestHashInputsReqsIgs(t *testing.T) { hhOverrides, hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", } for _, v := range elems { h.Write([]byte(v)) @@ -138,7 +138,7 @@ func TestHashInputsReqsIgs(t *testing.T) { hhOverrides, hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", } for _, v := range elems { h.Write([]byte(v)) @@ -177,7 +177,7 @@ func TestHashInputsReqsIgs(t *testing.T) { hhOverrides, hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", } for _, v := range elems { h.Write([]byte(v)) @@ -232,7 +232,7 @@ func TestHashInputsOverrides(t *testing.T) { "car", hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", }, }, { @@ -263,7 +263,7 @@ func TestHashInputsOverrides(t *testing.T) { "car", hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", }, }, { @@ -293,7 +293,7 @@ func TestHashInputsOverrides(t *testing.T) { "car", hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", }, }, { @@ -321,7 +321,7 @@ func TestHashInputsOverrides(t *testing.T) { "car", hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", }, }, { @@ -353,7 +353,7 @@ func TestHashInputsOverrides(t *testing.T) { "b-foobranch", hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", }, }, { @@ -381,7 +381,7 @@ func TestHashInputsOverrides(t *testing.T) { "b-foobranch", hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", }, }, { @@ -411,7 +411,7 @@ func TestHashInputsOverrides(t *testing.T) { "b-foobranch", hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", }, }, { @@ -442,7 +442,7 @@ func TestHashInputsOverrides(t *testing.T) { "b-foobranch", hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", }, }, { @@ -474,7 +474,7 @@ func TestHashInputsOverrides(t *testing.T) { "b-foobranch", hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", }, }, { @@ -508,7 +508,7 @@ func TestHashInputsOverrides(t *testing.T) { "b-foobranch", hhAnalyzer, "depspec-sm-builtin", - "1.0.0", + "1", }, }, } diff --git a/vendor/github.com/sdboyer/gps/types.go b/vendor/github.com/sdboyer/gps/identifier.go similarity index 92% rename from vendor/github.com/sdboyer/gps/types.go rename to vendor/github.com/sdboyer/gps/identifier.go index 7b0478e6de..7406ce96d2 100644 --- a/vendor/github.com/sdboyer/gps/types.go +++ b/vendor/github.com/sdboyer/gps/identifier.go @@ -163,16 +163,6 @@ type ProjectProperties struct { Constraint Constraint } -// Package represents a Go package. It contains a subset of the information -// go/build.Package does. -type Package struct { - Name string // Package name, as declared in the package statement - ImportPath string // Full import path, including the prefix provided to ListPackages() - CommentPath string // Import path given in the comment on the package statement - Imports []string // Imports from all go and cgo files - TestImports []string // Imports from all go test files (in go/build parlance: both TestImports and XTestImports) -} - // bimodalIdentifiers are used to track work to be done in the unselected queue. type bimodalIdentifier struct { id ProjectIdentifier diff --git a/vendor/github.com/sdboyer/gps/util.go b/vendor/github.com/sdboyer/gps/internal/fs/fs.go similarity index 79% rename from vendor/github.com/sdboyer/gps/util.go rename to vendor/github.com/sdboyer/gps/internal/fs/fs.go index 45d3dff708..cec090d72c 100644 --- a/vendor/github.com/sdboyer/gps/util.go +++ b/vendor/github.com/sdboyer/gps/internal/fs/fs.go @@ -1,7 +1,7 @@ -package gps +package fs import ( - "fmt" + "errors" "io" "io/ioutil" "os" @@ -10,10 +10,10 @@ import ( "syscall" ) -// renameWithFallback attempts to rename a file or directory, but falls back to +// RenameWithFallback attempts to rename a file or directory, but falls back to // copying in the event of a cross-link device error. If the fallback copy // succeeds, src is still removed, emulating normal rename behavior. -func renameWithFallback(src, dest string) error { +func RenameWithFallback(src, dest string) error { fi, err := os.Stat(src) if err != nil { return err @@ -36,9 +36,9 @@ func renameWithFallback(src, dest string) error { var cerr error if terr.Err == syscall.EXDEV { if fi.IsDir() { - cerr = copyDir(src, dest) + cerr = CopyDir(src, dest) } else { - cerr = copyFile(src, dest) + cerr = CopyFile(src, dest) } } else if runtime.GOOS == "windows" { // In windows it can drop down to an operating system call that @@ -49,9 +49,9 @@ func renameWithFallback(src, dest string) error { // See https://msdn.microsoft.com/en-us/library/cc231199.aspx if ok && noerr == 0x11 { if fi.IsDir() { - cerr = copyDir(src, dest) + cerr = CopyDir(src, dest) } else { - cerr = copyFile(src, dest) + cerr = CopyFile(src, dest) } } } else { @@ -65,10 +65,15 @@ func renameWithFallback(src, dest string) error { return os.RemoveAll(src) } -// copyDir recursively copies a directory tree, attempting to preserve permissions. +var ( + errSrcNotDir = errors.New("source is not a directory") + errDestExist = errors.New("destination already exists") +) + +// CopyDir recursively copies a directory tree, attempting to preserve permissions. // Source directory must exist, destination directory must *not* exist. // Symlinks are ignored and skipped. -func copyDir(src string, dst string) (err error) { +func CopyDir(src string, dst string) (err error) { src = filepath.Clean(src) dst = filepath.Clean(dst) @@ -77,7 +82,7 @@ func copyDir(src string, dst string) (err error) { return err } if !si.IsDir() { - return fmt.Errorf("source is not a directory") + return errSrcNotDir } _, err = os.Stat(dst) @@ -85,7 +90,7 @@ func copyDir(src string, dst string) (err error) { return } if err == nil { - return fmt.Errorf("destination already exists") + return errDestExist } err = os.MkdirAll(dst, si.Mode()) @@ -103,14 +108,14 @@ func copyDir(src string, dst string) (err error) { dstPath := filepath.Join(dst, entry.Name()) if entry.IsDir() { - err = copyDir(srcPath, dstPath) + err = CopyDir(srcPath, dstPath) if err != nil { return } } else { // This will include symlinks, which is what we want in all cases // where gps is copying things. - err = copyFile(srcPath, dstPath) + err = CopyFile(srcPath, dstPath) if err != nil { return } @@ -120,12 +125,12 @@ func copyDir(src string, dst string) (err error) { return } -// copyFile copies the contents of the file named src to the file named +// CopyFile copies the contents of the file named src to the file named // by dst. The file will be created if it does not already exist. If the // destination file exists, all it's contents will be replaced by the contents // of the source file. The file mode will be copied from the source and // the copied data is synced/flushed to stable storage. -func copyFile(src, dst string) (err error) { +func CopyFile(src, dst string) (err error) { in, err := os.Open(src) if err != nil { return @@ -163,3 +168,4 @@ func copyFile(src, dst string) (err error) { return } + diff --git a/vendor/github.com/sdboyer/gps/util_test.go b/vendor/github.com/sdboyer/gps/internal/fs/fs_test.go similarity index 95% rename from vendor/github.com/sdboyer/gps/util_test.go rename to vendor/github.com/sdboyer/gps/internal/fs/fs_test.go index 036edbf742..04f3204754 100644 --- a/vendor/github.com/sdboyer/gps/util_test.go +++ b/vendor/github.com/sdboyer/gps/internal/fs/fs_test.go @@ -1,4 +1,4 @@ -package gps +package fs import ( "fmt" @@ -46,7 +46,7 @@ func TestCopyDir(t *testing.T) { srcf.Close() destdir := filepath.Join(dir, "dest") - if err := copyDir(srcdir, destdir); err != nil { + if err := CopyDir(srcdir, destdir); err != nil { t.Fatal(err) } @@ -102,7 +102,7 @@ func TestCopyFile(t *testing.T) { srcf.Close() destf := filepath.Join(dir, "destf") - if err := copyFile(srcf.Name(), destf); err != nil { + if err := CopyFile(srcf.Name(), destf); err != nil { t.Fatal(err) } diff --git a/vendor/github.com/sdboyer/gps/internal/internal.go b/vendor/github.com/sdboyer/gps/internal/internal.go new file mode 100644 index 0000000000..fd141d5a67 --- /dev/null +++ b/vendor/github.com/sdboyer/gps/internal/internal.go @@ -0,0 +1,19 @@ +// Package internal provides support for gps own packages. +package internal + +import "strings" + +// IsStdLib is a reference to internal implementation. +// It is stored as a var so that tests can swap it out. Ugh globals, ugh. +var IsStdLib = doIsStdLib + +// This was lovingly lifted from src/cmd/go/pkg.go in Go's code +// (isStandardImportPath). +func doIsStdLib(path string) bool { + i := strings.Index(path, "/") + if i < 0 { + i = len(path) + } + + return !strings.Contains(path[:i], ".") +} diff --git a/vendor/github.com/sdboyer/gps/internal/internal_test.go b/vendor/github.com/sdboyer/gps/internal/internal_test.go new file mode 100644 index 0000000000..c13ad3b7da --- /dev/null +++ b/vendor/github.com/sdboyer/gps/internal/internal_test.go @@ -0,0 +1,28 @@ +package internal + +import "testing" + +func TestIsStdLib(t *testing.T) { + fix := []struct { + ip string + is bool + }{ + {"appengine", true}, + {"net/http", true}, + {"github.com/anything", false}, + {"foo", true}, + } + + for _, f := range fix { + r := doIsStdLib(f.ip) + if r != f.is { + if r { + t.Errorf("%s was marked stdlib but should not have been", f.ip) + } else { + t.Errorf("%s was not marked stdlib but should have been", f.ip) + + } + } + } +} + diff --git a/vendor/github.com/sdboyer/gps/lock_test.go b/vendor/github.com/sdboyer/gps/lock_test.go index a65179be89..d49fccf22a 100644 --- a/vendor/github.com/sdboyer/gps/lock_test.go +++ b/vendor/github.com/sdboyer/gps/lock_test.go @@ -37,40 +37,42 @@ func TestLockedProjectsEq(t *testing.T) { NewLockedProject(mkPI("github.com/sdboyer/gps"), Revision("278a227dfc3d595a33a77ff3f841fd8ca1bc8cd0"), []string{"gps"}), } - fix := []struct { + fix := map[string]struct { l1, l2 int shouldeq bool err string }{ - {0, 0, true, "lp does not eq self"}, - {0, 5, false, "should not eq with different rev"}, - {0, 6, false, "should not eq with different version"}, - {5, 5, true, "should eq with same rev"}, - {0, 1, false, "should not eq when other pkg list is empty"}, - {0, 2, false, "should not eq when other pkg list is longer"}, - {2, 4, false, "should not eq when pkg lists are out of order"}, - {0, 3, false, "should not eq totally different lp"}, - {7, 7, true, "should eq with only rev"}, - {5, 7, false, "should not eq when only rev matches"}, + "with self": {0, 0, true, "lp does not eq self"}, + "with different revision": {0, 5, false, "should not eq with different rev"}, + "with different versions": {0, 6, false, "should not eq with different version"}, + "with same revsion": {5, 5, true, "should eq with same rev"}, + "with empty pkg": {0, 1, false, "should not eq when other pkg list is empty"}, + "with long pkg list": {0, 2, false, "should not eq when other pkg list is longer"}, + "with different orders": {2, 4, false, "should not eq when pkg lists are out of order"}, + "with different lp": {0, 3, false, "should not eq totally different lp"}, + "with only rev": {7, 7, true, "should eq with only rev"}, + "when only rev matches": {5, 7, false, "should not eq when only rev matches"}, } - for _, f := range fix { - if f.shouldeq { - if !lps[f.l1].Eq(lps[f.l2]) { - t.Error(f.err) - } - if !lps[f.l2].Eq(lps[f.l1]) { - t.Error(f.err + (" (reversed)")) - } - } else { - if lps[f.l1].Eq(lps[f.l2]) { - t.Error(f.err) - } - if lps[f.l2].Eq(lps[f.l1]) { - t.Error(f.err + (" (reversed)")) - } + for k, f := range fix { + t.Run(k, func(t *testing.T) { + if f.shouldeq { + if !lps[f.l1].Eq(lps[f.l2]) { + t.Error(f.err) + } + if !lps[f.l2].Eq(lps[f.l1]) { + t.Error(f.err + (" (reversed)")) + } + } else { + if lps[f.l1].Eq(lps[f.l2]) { + t.Error(f.err) + } + if lps[f.l2].Eq(lps[f.l1]) { + t.Error(f.err + (" (reversed)")) + } - } + } + }) } } diff --git a/vendor/github.com/sdboyer/gps/manager_test.go b/vendor/github.com/sdboyer/gps/manager_test.go index 57027e6802..db566620ca 100644 --- a/vendor/github.com/sdboyer/gps/manager_test.go +++ b/vendor/github.com/sdboyer/gps/manager_test.go @@ -26,8 +26,8 @@ func (naiveAnalyzer) DeriveManifestAndLock(string, ProjectRoot) (Manifest, Lock, return nil, nil, nil } -func (a naiveAnalyzer) Info() (name string, version *semver.Version) { - return "naive-analyzer", sv("v0.0.1") +func (a naiveAnalyzer) Info() (name string, version int) { + return "naive-analyzer", 1 } func sv(s string) *semver.Version { @@ -350,6 +350,7 @@ func TestGetSources(t *testing.T) { if testing.Short() { t.Skip("Skipping source setup test in short mode") } + requiresBins(t, "git", "hg", "bzr") sm, clean := mkNaiveSM(t) @@ -363,6 +364,8 @@ func TestGetSources(t *testing.T) { wg.Add(3) for _, pi := range pil { go func(lpi ProjectIdentifier) { + defer wg.Done() + nn := lpi.normalizedSource() src, err := sm.getSourceFor(lpi) if err != nil { @@ -395,8 +398,6 @@ func TestGetSources(t *testing.T) { } else if src == src4 { t.Errorf("(src %q) explicit http source should create a new src", nn) } - - wg.Done() }(pi) } @@ -850,3 +851,17 @@ func TestSignalHandling(t *testing.T) { } clean() } + +func TestUnreachableSource(t *testing.T) { + // If a git remote is unreachable (maybe the server is only accessible behind a VPN, or + // something), we should return a clear error, not a panic. + + sm, clean := mkNaiveSM(t) + defer clean() + + id := mkPI("golang.org/notareal/repo").normalize() + _, err := sm.ListVersions(id) + if err == nil { + t.Error("expected err when listing versions of a bogus source, but got nil") + } +} diff --git a/vendor/github.com/sdboyer/gps/maybe_source.go b/vendor/github.com/sdboyer/gps/maybe_source.go index d59962aedc..5e74ce95c0 100644 --- a/vendor/github.com/sdboyer/gps/maybe_source.go +++ b/vendor/github.com/sdboyer/gps/maybe_source.go @@ -50,9 +50,9 @@ type sourceFailures []sourceSetupFailure func (sf sourceFailures) Error() string { var buf bytes.Buffer - fmt.Fprintf(&buf, "No valid source could be created:\n") + fmt.Fprintf(&buf, "no valid source could be created:") for _, e := range sf { - fmt.Fprintf(&buf, "\t%s", e.Error()) + fmt.Fprintf(&buf, "\n\t%s", e.Error()) } return buf.String() @@ -67,7 +67,7 @@ func (m maybeGitSource) try(cachedir string, an ProjectAnalyzer) (source, string path := filepath.Join(cachedir, "sources", sanitizer.Replace(ustr)) r, err := vcs.NewGitRepo(ustr, path) if err != nil { - return nil, "", err + return nil, ustr, unwrapVcsErr(err) } src := &gitSource{ @@ -75,7 +75,7 @@ func (m maybeGitSource) try(cachedir string, an ProjectAnalyzer) (source, string an: an, dc: newMetaCache(), crepo: &repo{ - r: r, + r: &gitRepo{r}, rpath: path, }, }, @@ -85,7 +85,7 @@ func (m maybeGitSource) try(cachedir string, an ProjectAnalyzer) (source, string if !r.CheckLocal() { _, err = src.listVersions() if err != nil { - return nil, "", err + return nil, ustr, unwrapVcsErr(err) } } @@ -112,7 +112,7 @@ func (m maybeGopkginSource) try(cachedir string, an ProjectAnalyzer) (source, st ustr := m.url.String() r, err := vcs.NewGitRepo(ustr, path) if err != nil { - return nil, "", err + return nil, ustr, unwrapVcsErr(err) } src := &gopkginSource{ @@ -121,7 +121,7 @@ func (m maybeGopkginSource) try(cachedir string, an ProjectAnalyzer) (source, st an: an, dc: newMetaCache(), crepo: &repo{ - r: r, + r: &gitRepo{r}, rpath: path, }, }, @@ -133,7 +133,7 @@ func (m maybeGopkginSource) try(cachedir string, an ProjectAnalyzer) (source, st if !r.CheckLocal() { _, err = src.listVersions() if err != nil { - return nil, "", err + return nil, ustr, unwrapVcsErr(err) } } @@ -149,10 +149,10 @@ func (m maybeBzrSource) try(cachedir string, an ProjectAnalyzer) (source, string path := filepath.Join(cachedir, "sources", sanitizer.Replace(ustr)) r, err := vcs.NewBzrRepo(ustr, path) if err != nil { - return nil, "", err + return nil, ustr, unwrapVcsErr(err) } if !r.Ping() { - return nil, "", fmt.Errorf("Remote repository at %s does not exist, or is inaccessible", ustr) + return nil, ustr, fmt.Errorf("remote repository at %s does not exist, or is inaccessible", ustr) } src := &bzrSource{ @@ -164,7 +164,7 @@ func (m maybeBzrSource) try(cachedir string, an ProjectAnalyzer) (source, string f: existsUpstream, }, crepo: &repo{ - r: r, + r: &bzrRepo{r}, rpath: path, }, }, @@ -183,10 +183,10 @@ func (m maybeHgSource) try(cachedir string, an ProjectAnalyzer) (source, string, path := filepath.Join(cachedir, "sources", sanitizer.Replace(ustr)) r, err := vcs.NewHgRepo(ustr, path) if err != nil { - return nil, "", err + return nil, ustr, unwrapVcsErr(err) } if !r.Ping() { - return nil, "", fmt.Errorf("Remote repository at %s does not exist, or is inaccessible", ustr) + return nil, ustr, fmt.Errorf("remote repository at %s does not exist, or is inaccessible", ustr) } src := &hgSource{ @@ -198,7 +198,7 @@ func (m maybeHgSource) try(cachedir string, an ProjectAnalyzer) (source, string, f: existsUpstream, }, crepo: &repo{ - r: r, + r: &hgRepo{r}, rpath: path, }, }, diff --git a/vendor/github.com/sdboyer/gps/metrics.go b/vendor/github.com/sdboyer/gps/metrics.go index bd5629ea35..ee4c0ab9e4 100644 --- a/vendor/github.com/sdboyer/gps/metrics.go +++ b/vendor/github.com/sdboyer/gps/metrics.go @@ -62,11 +62,10 @@ func (m *metrics) dump(l *log.Logger) { fmt.Fprintf(w, "\t%s:\t%v\t\n", nd.n, nd.d) } fmt.Fprintf(w, "\n\tTOTAL:\t%v\t\n", tot) - - l.Println("\nSolver wall times by segment:") w.Flush() - fmt.Println((&buf).String()) + l.Println("\nSolver wall times by segment:") + l.Println((&buf).String()) } type ndpair struct { diff --git a/vendor/github.com/sdboyer/gps/analysis.go b/vendor/github.com/sdboyer/gps/pkgtree/pkgtree.go similarity index 88% rename from vendor/github.com/sdboyer/gps/analysis.go rename to vendor/github.com/sdboyer/gps/pkgtree/pkgtree.go index e5f0fe3cec..5717f0b267 100644 --- a/vendor/github.com/sdboyer/gps/analysis.go +++ b/vendor/github.com/sdboyer/gps/pkgtree/pkgtree.go @@ -1,4 +1,4 @@ -package gps +package pkgtree import ( "fmt" @@ -14,35 +14,14 @@ import ( "unicode" ) -var ( - osList []string - archList []string - ignoreTags = []string{} //[]string{"appengine", "ignore"} //TODO: appengine is a special case for now: https://github.com/tools/godep/issues/353 -) - -func init() { - // The supported systems are listed in - // https://github.com/golang/go/blob/master/src/go/build/syslist.go - // The lists are not exported, so we need to duplicate them here. - osListString := "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows" - osList = strings.Split(osListString, " ") - - archListString := "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc s390 s390x sparc sparc64" - archList = strings.Split(archListString, " ") -} - -// Stored as a var so that tests can swap it out. Ugh globals, ugh. -var isStdLib = doIsStdLib - -// This was lovingly lifted from src/cmd/go/pkg.go in Go's code -// (isStandardImportPath). -func doIsStdLib(path string) bool { - i := strings.Index(path, "/") - if i < 0 { - i = len(path) - } - - return !strings.Contains(path[:i], ".") +// Package represents a Go package. It contains a subset of the information +// go/build.Package does. +type Package struct { + Name string // Package name, as declared in the package statement + ImportPath string // Full import path, including the prefix provided to ListPackages() + CommentPath string // Import path given in the comment on the package statement + Imports []string // Imports from all go and cgo files + TestImports []string // Imports from all go test files (in go/build parlance: both TestImports and XTestImports) } // ListPackages reports Go package information about all directories in the tree @@ -112,13 +91,15 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { // would have an err with the same path as is called this time, as only // then will filepath.Walk have attempted to descend into the directory // and encountered an error. - _, err = os.Open(wp) + var f *os.File + f, err = os.Open(wp) if err != nil { if os.IsPermission(err) { return filepath.SkipDir } return err } + f.Close() // Compute the import path. Run the result through ToSlash(), so that // windows file paths are normalized to slashes, as is expected of @@ -304,45 +285,6 @@ func (e *LocalImportsError) Error() string { } } -// A PackageTree represents the results of recursively parsing a tree of -// packages, starting at the ImportRoot. The results of parsing the files in the -// directory identified by each import path - a Package or an error - are stored -// in the Packages map, keyed by that import path. -type PackageTree struct { - ImportRoot string - Packages map[string]PackageOrErr -} - -// dup copies the PackageTree. -// -// This is really only useful as a defensive measure to prevent external state -// mutations. -func (t PackageTree) dup() PackageTree { - t2 := PackageTree{ - ImportRoot: t.ImportRoot, - Packages: map[string]PackageOrErr{}, - } - - for path, poe := range t.Packages { - poe2 := PackageOrErr{ - Err: poe.Err, - P: poe.P, - } - if len(poe.P.Imports) > 0 { - poe2.P.Imports = make([]string, len(poe.P.Imports)) - copy(poe2.P.Imports, poe.P.Imports) - } - if len(poe.P.TestImports) > 0 { - poe2.P.TestImports = make([]string, len(poe.P.TestImports)) - copy(poe2.P.TestImports, poe.P.TestImports) - } - - t2.Packages[path] = poe2 - } - - return t2 -} - type wm struct { err error ex map[string]bool @@ -356,15 +298,6 @@ type PackageOrErr struct { Err error } -// ReachMap maps a set of import paths (keys) to the sets of transitively -// reachable tree-internal packages, and all the tree-external packages -// reachable through those internal packages. -// -// See PackageTree.ToReachMap() for more information. -type ReachMap map[string]struct { - Internal, External []string -} - // ProblemImportError describes the reason that a particular import path is // not safely importable. type ProblemImportError struct { @@ -393,6 +326,20 @@ func (e *ProblemImportError) Error() string { } } +// Helper func to create an error when a package is missing. +func missingPkgErr(pkg string) error { + return fmt.Errorf("no package exists at %q", pkg) +} + +// A PackageTree represents the results of recursively parsing a tree of +// packages, starting at the ImportRoot. The results of parsing the files in the +// directory identified by each import path - a Package or an error - are stored +// in the Packages map, keyed by that import path. +type PackageTree struct { + ImportRoot string + Packages map[string]PackageOrErr +} + // ToReachMap looks through a PackageTree and computes the list of external // import statements (that is, import statements pointing to packages that are // not logical children of PackageTree.ImportRoot) that are transitively @@ -525,9 +472,34 @@ func (t PackageTree) ToReachMap(main, tests, backprop bool, ignore map[string]bo return wmToReach(workmap, backprop) } -// Helper func to create an error when a package is missing. -func missingPkgErr(pkg string) error { - return fmt.Errorf("no package exists at %q", pkg) +// Copy copies the PackageTree. +// +// This is really only useful as a defensive measure to prevent external state +// mutations. +func (t PackageTree) Copy() PackageTree { + t2 := PackageTree{ + ImportRoot: t.ImportRoot, + Packages: map[string]PackageOrErr{}, + } + + for path, poe := range t.Packages { + poe2 := PackageOrErr{ + Err: poe.Err, + P: poe.P, + } + if len(poe.P.Imports) > 0 { + poe2.P.Imports = make([]string, len(poe.P.Imports)) + copy(poe2.P.Imports, poe.P.Imports) + } + if len(poe.P.TestImports) > 0 { + poe2.P.TestImports = make([]string, len(poe.P.TestImports)) + copy(poe2.P.TestImports, poe.P.TestImports) + } + + t2.Packages[path] = poe2 + } + + return t2 } // wmToReach takes an internal "workmap" constructed by @@ -857,64 +829,6 @@ func wmToReach(workmap map[string]wm, backprop bool) (ReachMap, map[string]*Prob return rm, errmap } -// FlattenAll flattens a reachmap into a sorted, deduplicated list of all the -// external imports named by its contained packages. -// -// If stdlib is true, then stdlib imports are excluded from the result. -func (rm ReachMap) FlattenAll(stdlib bool) []string { - return rm.flatten(func(pkg string) bool { return true }, stdlib) -} - -// Flatten flattens a reachmap into a sorted, deduplicated list of all the -// external imports named by its contained packages, but excludes imports coming -// from packages with disallowed patterns in their names: any path element with -// a leading dot, a leading underscore, with the name "testdata". -// -// If stdlib is true, then stdlib imports are excluded from the result. -func (rm ReachMap) Flatten(stdlib bool) []string { - f := func(pkg string) bool { - // Eliminate import paths with any elements having leading dots, leading - // underscores, or testdata. If these are internally reachable (which is - // a no-no, but possible), any external imports will have already been - // pulled up through ExternalReach. The key here is that we don't want - // to treat such packages as themselves being sources. - for _, elem := range strings.Split(pkg, "/") { - if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { - return false - } - } - return true - } - - return rm.flatten(f, stdlib) -} - -func (rm ReachMap) flatten(filter func(string) bool, stdlib bool) []string { - exm := make(map[string]struct{}) - for pkg, ie := range rm { - if filter(pkg) { - for _, ex := range ie.External { - if !stdlib && isStdLib(ex) { - continue - } - exm[ex] = struct{}{} - } - } - } - - if len(exm) == 0 { - return []string{} - } - - ex := make([]string, 0, len(exm)) - for p := range exm { - ex = append(ex, p) - } - - sort.Strings(ex) - return ex -} - // eqOrSlashedPrefix checks to see if the prefix is either equal to the string, // or that it is a prefix and the next char in the string is "/". func eqOrSlashedPrefix(s, prefix string) bool { diff --git a/vendor/github.com/sdboyer/gps/analysis_test.go b/vendor/github.com/sdboyer/gps/pkgtree/pkgtree_test.go similarity index 92% rename from vendor/github.com/sdboyer/gps/analysis_test.go rename to vendor/github.com/sdboyer/gps/pkgtree/pkgtree_test.go index 47adb6a745..2dce984286 100644 --- a/vendor/github.com/sdboyer/gps/analysis_test.go +++ b/vendor/github.com/sdboyer/gps/pkgtree/pkgtree_test.go @@ -1,4 +1,4 @@ -package gps +package pkgtree import ( "fmt" @@ -12,8 +12,26 @@ import ( "runtime" "strings" "testing" + + "github.com/sdboyer/gps/internal" + "github.com/sdboyer/gps/internal/fs" ) +// Stores a reference to original IsStdLib, so we could restore overridden version. +var doIsStdLib = internal.IsStdLib + +func init() { + overrideIsStdLib() +} + +// sets the IsStdLib func to always return false, otherwise it would identify +// pretty much all of our fixtures as being stdlib and skip everything. +func overrideIsStdLib() { + internal.IsStdLib = func(path string) bool { + return false + } +} + // PackageTree.ToReachMap() uses an easily separable algorithm, wmToReach(), // to turn a discovered set of packages and their imports into a proper pair of // internal and external reach maps. @@ -434,24 +452,26 @@ func TestWorkmapToReach(t *testing.T) { for name, fix := range table { // Avoid erroneous errors by initializing the fixture's error map if // needed - if fix.em == nil { - fix.em = make(map[string]*ProblemImportError) - } + t.Run(name, func(t *testing.T) { + if fix.em == nil { + fix.em = make(map[string]*ProblemImportError) + } - rm, em := wmToReach(fix.workmap, fix.backprop) - if !reflect.DeepEqual(rm, fix.rm) { - //t.Error(pretty.Sprintf("wmToReach(%q): Did not get expected reach map:\n\t(GOT): %s\n\t(WNT): %s", name, rm, fix.rm)) - t.Errorf("wmToReach(%q): Did not get expected reach map:\n\t(GOT): %s\n\t(WNT): %s", name, rm, fix.rm) - } - if !reflect.DeepEqual(em, fix.em) { - //t.Error(pretty.Sprintf("wmToReach(%q): Did not get expected error map:\n\t(GOT): %# v\n\t(WNT): %# v", name, em, fix.em)) - t.Errorf("wmToReach(%q): Did not get expected error map:\n\t(GOT): %v\n\t(WNT): %v", name, em, fix.em) - } + rm, em := wmToReach(fix.workmap, fix.backprop) + if !reflect.DeepEqual(rm, fix.rm) { + //t.Error(pretty.Sprintf("wmToReach(%q): Did not get expected reach map:\n\t(GOT): %s\n\t(WNT): %s", name, rm, fix.rm)) + t.Errorf("Did not get expected reach map:\n\t(GOT): %s\n\t(WNT): %s", rm, fix.rm) + } + if !reflect.DeepEqual(em, fix.em) { + //t.Error(pretty.Sprintf("wmToReach(%q): Did not get expected error map:\n\t(GOT): %# v\n\t(WNT): %# v", name, em, fix.em)) + t.Errorf("Did not get expected error map:\n\t(GOT): %v\n\t(WNT): %v", em, fix.em) + } + }) } } func TestListPackagesNoDir(t *testing.T) { - out, err := ListPackages(filepath.Join(getwd(t), "_testdata", "notexist"), "notexist") + out, err := ListPackages(filepath.Join(getTestdataRootDir(t), "notexist"), "notexist") if err == nil { t.Error("ListPackages should have errored on pointing to a nonexistent dir") } @@ -461,7 +481,7 @@ func TestListPackagesNoDir(t *testing.T) { } func TestListPackages(t *testing.T) { - srcdir := filepath.Join(getwd(t), "_testdata", "src") + srcdir := filepath.Join(getTestdataRootDir(t), "src") j := func(s ...string) string { return filepath.Join(srcdir, filepath.Join(s...)) } @@ -1236,59 +1256,60 @@ func TestListPackages(t *testing.T) { } for name, fix := range table { - if _, err := os.Stat(fix.fileRoot); err != nil { - t.Errorf("listPackages(%q): error on fileRoot %s: %s", name, fix.fileRoot, err) - continue - } - - out, err := ListPackages(fix.fileRoot, fix.importRoot) - - if err != nil && fix.err == nil { - t.Errorf("listPackages(%q): Received error but none expected: %s", name, err) - } else if fix.err != nil && err == nil { - t.Errorf("listPackages(%q): Error expected but none received", name) - } else if fix.err != nil && err != nil { - if !reflect.DeepEqual(fix.err, err) { - t.Errorf("listPackages(%q): Did not receive expected error:\n\t(GOT): %s\n\t(WNT): %s", name, err, fix.err) + t.Run(name, func(t *testing.T) { + if _, err := os.Stat(fix.fileRoot); err != nil { + t.Errorf("error on fileRoot %s: %s", fix.fileRoot, err) } - } - if fix.out.ImportRoot != "" && fix.out.Packages != nil { - if !reflect.DeepEqual(out, fix.out) { - if fix.out.ImportRoot != out.ImportRoot { - t.Errorf("listPackages(%q): Expected ImportRoot %s, got %s", name, fix.out.ImportRoot, out.ImportRoot) - } + out, err := ListPackages(fix.fileRoot, fix.importRoot) - // overwrite the out one to see if we still have a real problem - out.ImportRoot = fix.out.ImportRoot + if err != nil && fix.err == nil { + t.Errorf("Received error but none expected: %s", err) + } else if fix.err != nil && err == nil { + t.Errorf("Error expected but none received") + } else if fix.err != nil && err != nil { + if !reflect.DeepEqual(fix.err, err) { + t.Errorf("Did not receive expected error:\n\t(GOT): %s\n\t(WNT): %s", err, fix.err) + } + } + if fix.out.ImportRoot != "" && fix.out.Packages != nil { if !reflect.DeepEqual(out, fix.out) { - if len(fix.out.Packages) < 2 { - t.Errorf("listPackages(%q): Did not get expected PackageOrErrs:\n\t(GOT): %#v\n\t(WNT): %#v", name, out, fix.out) - } else { - seen := make(map[string]bool) - for path, perr := range fix.out.Packages { - seen[path] = true - if operr, exists := out.Packages[path]; !exists { - t.Errorf("listPackages(%q): Expected PackageOrErr for path %s was missing from output:\n\t%s", name, path, perr) - } else { - if !reflect.DeepEqual(perr, operr) { - t.Errorf("listPackages(%q): PkgOrErr for path %s was not as expected:\n\t(GOT): %#v\n\t(WNT): %#v", name, path, operr, perr) + if fix.out.ImportRoot != out.ImportRoot { + t.Errorf("Expected ImportRoot %s, got %s", fix.out.ImportRoot, out.ImportRoot) + } + + // overwrite the out one to see if we still have a real problem + out.ImportRoot = fix.out.ImportRoot + + if !reflect.DeepEqual(out, fix.out) { + if len(fix.out.Packages) < 2 { + t.Errorf("Did not get expected PackageOrErrs:\n\t(GOT): %#v\n\t(WNT): %#v", out, fix.out) + } else { + seen := make(map[string]bool) + for path, perr := range fix.out.Packages { + seen[path] = true + if operr, exists := out.Packages[path]; !exists { + t.Errorf("Expected PackageOrErr for path %s was missing from output:\n\t%s", path, perr) + } else { + if !reflect.DeepEqual(perr, operr) { + t.Errorf("PkgOrErr for path %s was not as expected:\n\t(GOT): %#v\n\t(WNT): %#v", path, operr, perr) + } } } - } - for path, operr := range out.Packages { - if seen[path] { - continue - } + for path, operr := range out.Packages { + if seen[path] { + continue + } - t.Errorf("listPackages(%q): Got PackageOrErr for path %s, but none was expected:\n\t%s", name, path, operr) + t.Errorf("Got PackageOrErr for path %s, but none was expected:\n\t%s", path, operr) + } } } } } - } + }) } } @@ -1313,9 +1334,9 @@ func TestListPackagesNoPerms(t *testing.T) { } defer os.RemoveAll(tmp) - srcdir := filepath.Join(getwd(t), "_testdata", "src", "ren") + srcdir := filepath.Join(getTestdataRootDir(t), "src", "ren") workdir := filepath.Join(tmp, "ren") - copyDir(srcdir, workdir) + fs.CopyDir(srcdir, workdir) // chmod the simple dir and m1p/b.go file so they can't be read err = os.Chmod(filepath.Join(workdir, "simple"), 0) @@ -1382,186 +1403,9 @@ func TestListPackagesNoPerms(t *testing.T) { } } -func TestFlattenReachMap(t *testing.T) { - // There's enough in the 'varied' test case to test most of what matters - vptree, err := ListPackages(filepath.Join(getwd(t), "_testdata", "src", "github.com", "example", "varied"), "github.com/example/varied") - if err != nil { - t.Fatalf("listPackages failed on varied test case: %s", err) - } - - var expect []string - var name string - var ignore map[string]bool - var stdlib, main, tests bool - - validate := func() { - rm, em := vptree.ToReachMap(main, tests, true, ignore) - if len(em) != 0 { - t.Errorf("Should not have any error pkgs from ToReachMap, got %s", em) - } - result := rm.Flatten(stdlib) - if !reflect.DeepEqual(expect, result) { - t.Errorf("Wrong imports in %q case:\n\t(GOT): %s\n\t(WNT): %s", name, result, expect) - } - } - - all := []string{ - "encoding/binary", - "github.com/Masterminds/semver", - "github.com/sdboyer/gps", - "go/parser", - "hash", - "net/http", - "os", - "sort", - } - - // helper to rewrite expect, except for a couple packages - // - // this makes it easier to see what we're taking out on each test - except := func(not ...string) { - expect = make([]string, len(all)-len(not)) - - drop := make(map[string]bool) - for _, npath := range not { - drop[npath] = true - } - - k := 0 - for _, path := range all { - if !drop[path] { - expect[k] = path - k++ - } - } - } - - // everything on - name = "simple" - except() - stdlib, main, tests = true, true, true - validate() - - // turning off stdlib should cut most things, but we need to override the - // function - isStdLib = doIsStdLib - name = "no stdlib" - stdlib = false - except("encoding/binary", "go/parser", "hash", "net/http", "os", "sort") - validate() - // Restore stdlib func override - overrideIsStdLib() - - // stdlib back in; now exclude tests, which should just cut one - name = "no tests" - stdlib, tests = true, false - except("encoding/binary") - validate() - - // Now skip main, which still just cuts out one - name = "no main" - main, tests = false, true - except("net/http") - validate() - - // No test and no main, which should be additive - name = "no test, no main" - main, tests = false, false - except("net/http", "encoding/binary") - validate() - - // now, the ignore tests. turn main and tests back on - main, tests = true, true - - // start with non-matching - name = "non-matching ignore" - ignore = map[string]bool{ - "nomatch": true, - } - except() - validate() - - // should have the same effect as ignoring main - name = "ignore the root" - ignore = map[string]bool{ - "github.com/example/varied": true, - } - except("net/http") - validate() - - // now drop a more interesting one - name = "ignore simple" - ignore = map[string]bool{ - "github.com/example/varied/simple": true, - } - // we get github.com/sdboyer/gps from m1p, too, so it should still be there - except("go/parser") - validate() - - // now drop two - name = "ignore simple and namemismatch" - ignore = map[string]bool{ - "github.com/example/varied/simple": true, - "github.com/example/varied/namemismatch": true, - } - except("go/parser", "github.com/Masterminds/semver") - validate() - - // make sure tests and main play nice with ignore - name = "ignore simple and namemismatch, and no tests" - tests = false - except("go/parser", "github.com/Masterminds/semver", "encoding/binary") - validate() - name = "ignore simple and namemismatch, and no main" - main, tests = false, true - except("go/parser", "github.com/Masterminds/semver", "net/http") - validate() - name = "ignore simple and namemismatch, and no main or tests" - main, tests = false, false - except("go/parser", "github.com/Masterminds/semver", "net/http", "encoding/binary") - validate() - - main, tests = true, true - - // ignore two that should knock out gps - name = "ignore both importers" - ignore = map[string]bool{ - "github.com/example/varied/simple": true, - "github.com/example/varied/m1p": true, - } - except("sort", "github.com/sdboyer/gps", "go/parser") - validate() - - // finally, directly ignore some external packages - name = "ignore external" - ignore = map[string]bool{ - "github.com/sdboyer/gps": true, - "go/parser": true, - "sort": true, - } - except("sort", "github.com/sdboyer/gps", "go/parser") - validate() - - // The only thing varied *doesn't* cover is disallowed path patterns - ptree, err := ListPackages(filepath.Join(getwd(t), "_testdata", "src", "disallow"), "disallow") - if err != nil { - t.Fatalf("ListPackages failed on disallow test case: %s", err) - } - - rm, em := ptree.ToReachMap(false, false, true, nil) - if len(em) != 0 { - t.Errorf("Should not have any error packages from ToReachMap, got %s", em) - } - result := rm.Flatten(true) - expect = []string{"github.com/sdboyer/gps", "hash", "sort"} - if !reflect.DeepEqual(expect, result) { - t.Errorf("Wrong imports in %q case:\n\t(GOT): %s\n\t(WNT): %s", name, result, expect) - } -} - func TestToReachMap(t *testing.T) { // There's enough in the 'varied' test case to test most of what matters - vptree, err := ListPackages(filepath.Join(getwd(t), "_testdata", "src", "github.com", "example", "varied"), "github.com/example/varied") + vptree, err := ListPackages(filepath.Join(getTestdataRootDir(t), "src", "github.com", "example", "varied"), "github.com/example/varied") if err != nil { t.Fatalf("ListPackages failed on varied test case: %s", err) } @@ -1823,9 +1667,186 @@ func TestToReachMap(t *testing.T) { validate() } +func TestFlattenReachMap(t *testing.T) { + // There's enough in the 'varied' test case to test most of what matters + vptree, err := ListPackages(filepath.Join(getTestdataRootDir(t), "src", "github.com", "example", "varied"), "github.com/example/varied") + if err != nil { + t.Fatalf("listPackages failed on varied test case: %s", err) + } + + var expect []string + var name string + var ignore map[string]bool + var stdlib, main, tests bool + + validate := func() { + rm, em := vptree.ToReachMap(main, tests, true, ignore) + if len(em) != 0 { + t.Errorf("Should not have any error pkgs from ToReachMap, got %s", em) + } + result := rm.Flatten(stdlib) + if !reflect.DeepEqual(expect, result) { + t.Errorf("Wrong imports in %q case:\n\t(GOT): %s\n\t(WNT): %s", name, result, expect) + } + } + + all := []string{ + "encoding/binary", + "github.com/Masterminds/semver", + "github.com/sdboyer/gps", + "go/parser", + "hash", + "net/http", + "os", + "sort", + } + + // helper to rewrite expect, except for a couple packages + // + // this makes it easier to see what we're taking out on each test + except := func(not ...string) { + expect = make([]string, len(all)-len(not)) + + drop := make(map[string]bool) + for _, npath := range not { + drop[npath] = true + } + + k := 0 + for _, path := range all { + if !drop[path] { + expect[k] = path + k++ + } + } + } + + // everything on + name = "simple" + except() + stdlib, main, tests = true, true, true + validate() + + // turning off stdlib should cut most things, but we need to override the + // function + internal.IsStdLib = doIsStdLib + name = "no stdlib" + stdlib = false + except("encoding/binary", "go/parser", "hash", "net/http", "os", "sort") + validate() + // restore stdlib func override + overrideIsStdLib() + + // stdlib back in; now exclude tests, which should just cut one + name = "no tests" + stdlib, tests = true, false + except("encoding/binary") + validate() + + // Now skip main, which still just cuts out one + name = "no main" + main, tests = false, true + except("net/http") + validate() + + // No test and no main, which should be additive + name = "no test, no main" + main, tests = false, false + except("net/http", "encoding/binary") + validate() + + // now, the ignore tests. turn main and tests back on + main, tests = true, true + + // start with non-matching + name = "non-matching ignore" + ignore = map[string]bool{ + "nomatch": true, + } + except() + validate() + + // should have the same effect as ignoring main + name = "ignore the root" + ignore = map[string]bool{ + "github.com/example/varied": true, + } + except("net/http") + validate() + + // now drop a more interesting one + name = "ignore simple" + ignore = map[string]bool{ + "github.com/example/varied/simple": true, + } + // we get github.com/sdboyer/gps from m1p, too, so it should still be there + except("go/parser") + validate() + + // now drop two + name = "ignore simple and namemismatch" + ignore = map[string]bool{ + "github.com/example/varied/simple": true, + "github.com/example/varied/namemismatch": true, + } + except("go/parser", "github.com/Masterminds/semver") + validate() + + // make sure tests and main play nice with ignore + name = "ignore simple and namemismatch, and no tests" + tests = false + except("go/parser", "github.com/Masterminds/semver", "encoding/binary") + validate() + name = "ignore simple and namemismatch, and no main" + main, tests = false, true + except("go/parser", "github.com/Masterminds/semver", "net/http") + validate() + name = "ignore simple and namemismatch, and no main or tests" + main, tests = false, false + except("go/parser", "github.com/Masterminds/semver", "net/http", "encoding/binary") + validate() + + main, tests = true, true + + // ignore two that should knock out gps + name = "ignore both importers" + ignore = map[string]bool{ + "github.com/example/varied/simple": true, + "github.com/example/varied/m1p": true, + } + except("sort", "github.com/sdboyer/gps", "go/parser") + validate() + + // finally, directly ignore some external packages + name = "ignore external" + ignore = map[string]bool{ + "github.com/sdboyer/gps": true, + "go/parser": true, + "sort": true, + } + except("sort", "github.com/sdboyer/gps", "go/parser") + validate() + + // The only thing varied *doesn't* cover is disallowed path patterns + ptree, err := ListPackages(filepath.Join(getTestdataRootDir(t), "src", "disallow"), "disallow") + if err != nil { + t.Fatalf("ListPackages failed on disallow test case: %s", err) + } + + rm, em := ptree.ToReachMap(false, false, true, nil) + if len(em) != 0 { + t.Errorf("Should not have any error packages from ToReachMap, got %s", em) + } + result := rm.Flatten(true) + expect = []string{"github.com/sdboyer/gps", "hash", "sort"} + if !reflect.DeepEqual(expect, result) { + t.Errorf("Wrong imports in %q case:\n\t(GOT): %s\n\t(WNT): %s", name, result, expect) + } +} + // Verify that we handle import cycles correctly - drop em all func TestToReachMapCycle(t *testing.T) { - ptree, err := ListPackages(filepath.Join(getwd(t), "_testdata", "src", "cycle"), "cycle") + ptree, err := ListPackages(filepath.Join(getTestdataRootDir(t), "src", "cycle"), "cycle") if err != nil { t.Fatalf("ListPackages failed on cycle test case: %s", err) } @@ -1845,10 +1866,10 @@ func TestToReachMapCycle(t *testing.T) { } } -func getwd(t *testing.T) string { +func getTestdataRootDir(t *testing.T) string { cwd, err := os.Getwd() if err != nil { t.Fatal(err) } - return cwd + return filepath.Join(cwd, "..", "_testdata") } diff --git a/vendor/github.com/sdboyer/gps/pkgtree/reachmap.go b/vendor/github.com/sdboyer/gps/pkgtree/reachmap.go new file mode 100644 index 0000000000..5d1f155907 --- /dev/null +++ b/vendor/github.com/sdboyer/gps/pkgtree/reachmap.go @@ -0,0 +1,75 @@ +package pkgtree + +import ( + "sort" + "strings" + + "github.com/sdboyer/gps/internal" +) + +// ReachMap maps a set of import paths (keys) to the sets of transitively +// reachable tree-internal packages, and all the tree-external packages +// reachable through those internal packages. +// +// See PackageTree.ToReachMap() for more information. +type ReachMap map[string]struct { + Internal, External []string +} + +// FlattenAll flattens a reachmap into a sorted, deduplicated list of all the +// external imports named by its contained packages. +// +// If stdlib is false, then stdlib imports are excluded from the result. +func (rm ReachMap) FlattenAll(stdlib bool) []string { + return rm.flatten(func(pkg string) bool { return true }, stdlib) +} + +// Flatten flattens a reachmap into a sorted, deduplicated list of all the +// external imports named by its contained packages, but excludes imports coming +// from packages with disallowed patterns in their names: any path element with +// a leading dot, a leading underscore, with the name "testdata". +// +// If stdlib is false, then stdlib imports are excluded from the result. +func (rm ReachMap) Flatten(stdlib bool) []string { + f := func(pkg string) bool { + // Eliminate import paths with any elements having leading dots, leading + // underscores, or testdata. If these are internally reachable (which is + // a no-no, but possible), any external imports will have already been + // pulled up through ExternalReach. The key here is that we don't want + // to treat such packages as themselves being sources. + for _, elem := range strings.Split(pkg, "/") { + if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { + return false + } + } + return true + } + + return rm.flatten(f, stdlib) +} + +func (rm ReachMap) flatten(filter func(string) bool, stdlib bool) []string { + exm := make(map[string]struct{}) + for pkg, ie := range rm { + if filter(pkg) { + for _, ex := range ie.External { + if !stdlib && internal.IsStdLib(ex) { + continue + } + exm[ex] = struct{}{} + } + } + } + + if len(exm) == 0 { + return []string{} + } + + ex := make([]string, 0, len(exm)) + for p := range exm { + ex = append(ex, p) + } + + sort.Strings(ex) + return ex +} \ No newline at end of file diff --git a/vendor/github.com/sdboyer/gps/result_test.go b/vendor/github.com/sdboyer/gps/result_test.go index ee6ab359f4..1cf9273266 100644 --- a/vendor/github.com/sdboyer/gps/result_test.go +++ b/vendor/github.com/sdboyer/gps/result_test.go @@ -44,6 +44,7 @@ func TestWriteDepTree(t *testing.T) { if testing.Short() { t.Skip("Skipping dep tree writing test in short mode") } + requiresBins(t, "git", "hg", "bzr") tmp, err := ioutil.TempDir("", "writetree") if err != nil { diff --git a/vendor/github.com/sdboyer/gps/rootdata.go b/vendor/github.com/sdboyer/gps/rootdata.go index 3a4696c602..79d838216b 100644 --- a/vendor/github.com/sdboyer/gps/rootdata.go +++ b/vendor/github.com/sdboyer/gps/rootdata.go @@ -4,6 +4,8 @@ import ( "sort" "github.com/armon/go-radix" + "github.com/sdboyer/gps/internal" + "github.com/sdboyer/gps/pkgtree" ) // rootdata holds static data and constraining rules from the root project for @@ -39,10 +41,10 @@ type rootdata struct { rl safeLock // A defensively copied instance of params.RootPackageTree - rpt PackageTree + rpt pkgtree.PackageTree } -// rootImportList returns a list of the unique imports from the root data. +// externalImportList returns a list of the unique imports from the root data. // Ignores and requires are taken into consideration, stdlib is excluded, and // errors within the local set of package are not backpropagated. func (rd rootdata) externalImportList() []string { @@ -50,7 +52,7 @@ func (rd rootdata) externalImportList() []string { all := rm.Flatten(false) reach := make([]string, 0, len(all)) for _, r := range all { - if !isStdLib(r) { + if !internal.IsStdLib(r) { reach = append(reach, r) } } @@ -112,7 +114,7 @@ func (rd rootdata) getApplicableConstraints() []workingConstraint { // Walk all dep import paths we have to consider and mark the corresponding // wc entry in the trie, if any for _, im := range rd.externalImportList() { - if isStdLib(im) { + if internal.IsStdLib(im) { continue } diff --git a/vendor/github.com/sdboyer/gps/rootdata_test.go b/vendor/github.com/sdboyer/gps/rootdata_test.go index c0ad5c3951..e3126322bc 100644 --- a/vendor/github.com/sdboyer/gps/rootdata_test.go +++ b/vendor/github.com/sdboyer/gps/rootdata_test.go @@ -204,11 +204,13 @@ func TestGetApplicableConstraints(t *testing.T) { } for _, fix := range table { - fix.mut() - - got := rd.getApplicableConstraints() - if !reflect.DeepEqual(fix.result, got) { - t.Errorf("(fix: %q) unexpected applicable constraint set:\n\t(GOT): %+v\n\t(WNT): %+v", fix.name, got, fix.result) - } + t.Run(fix.name, func(t *testing.T) { + fix.mut() + + got := rd.getApplicableConstraints() + if !reflect.DeepEqual(fix.result, got) { + t.Errorf("unexpected applicable constraint set:\n\t(GOT): %+v\n\t(WNT): %+v", got, fix.result) + } + }) } } diff --git a/vendor/github.com/sdboyer/gps/solve_basic_test.go b/vendor/github.com/sdboyer/gps/solve_basic_test.go index 956692782a..575bfa54a0 100644 --- a/vendor/github.com/sdboyer/gps/solve_basic_test.go +++ b/vendor/github.com/sdboyer/gps/solve_basic_test.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/Masterminds/semver" + "github.com/sdboyer/gps/pkgtree" ) var regfrom = regexp.MustCompile(`^(\w*) from (\w*) ([0-9\.\*]*)`) @@ -371,7 +372,7 @@ type pident struct { type specfix interface { name() string rootmanifest() RootManifest - rootTree() PackageTree + rootTree() pkgtree.PackageTree specs() []depspec maxTries() int solution() map[ProjectIdentifier]LockedProject @@ -439,7 +440,7 @@ func (f basicFixture) rootmanifest() RootManifest { } } -func (f basicFixture) rootTree() PackageTree { +func (f basicFixture) rootTree() pkgtree.PackageTree { var imp, timp []string for _, dep := range f.ds[0].deps { imp = append(imp, string(dep.Ident.ProjectRoot)) @@ -449,11 +450,11 @@ func (f basicFixture) rootTree() PackageTree { } n := string(f.ds[0].n) - pt := PackageTree{ + pt := pkgtree.PackageTree{ ImportRoot: n, - Packages: map[string]PackageOrErr{ + Packages: map[string]pkgtree.PackageOrErr{ string(n): { - P: Package{ + P: pkgtree.Package{ ImportPath: n, Name: n, Imports: imp, @@ -1350,7 +1351,7 @@ func init() { } // reachMaps contain externalReach()-type data for a given depspec fixture's -// universe of proejcts, packages, and versions. +// universe of projects, packages, and versions. type reachMap map[pident]map[string][]string type depspecSourceManager struct { @@ -1404,8 +1405,8 @@ func (sm *depspecSourceManager) GetManifestAndLock(id ProjectIdentifier, v Versi return nil, nil, fmt.Errorf("Project %s at version %s could not be found", id.errString(), v) } -func (sm *depspecSourceManager) AnalyzerInfo() (string, *semver.Version) { - return "depspec-sm-builtin", sv("v1.0.0") +func (sm *depspecSourceManager) AnalyzerInfo() (string, int) { + return "depspec-sm-builtin", 1 } func (sm *depspecSourceManager) ExternalReach(id ProjectIdentifier, v Version) (map[string][]string, error) { @@ -1416,15 +1417,15 @@ func (sm *depspecSourceManager) ExternalReach(id ProjectIdentifier, v Version) ( return nil, fmt.Errorf("No reach data for %s at version %s", id.errString(), v) } -func (sm *depspecSourceManager) ListPackages(id ProjectIdentifier, v Version) (PackageTree, error) { +func (sm *depspecSourceManager) ListPackages(id ProjectIdentifier, v Version) (pkgtree.PackageTree, error) { pid := pident{n: ProjectRoot(id.normalizedSource()), v: v} if r, exists := sm.rm[pid]; exists { - return PackageTree{ + return pkgtree.PackageTree{ ImportRoot: string(pid.n), - Packages: map[string]PackageOrErr{ + Packages: map[string]pkgtree.PackageOrErr{ string(pid.n): { - P: Package{ + P: pkgtree.Package{ ImportPath: string(pid.n), Name: string(pid.n), Imports: r[string(pid.n)], @@ -1440,11 +1441,11 @@ func (sm *depspecSourceManager) ListPackages(id ProjectIdentifier, v Version) (P uv := pv.Unpair() for pid, r := range sm.rm { if uv.Matches(pid.v) { - return PackageTree{ + return pkgtree.PackageTree{ ImportRoot: string(pid.n), - Packages: map[string]PackageOrErr{ + Packages: map[string]pkgtree.PackageOrErr{ string(pid.n): { - P: Package{ + P: pkgtree.Package{ ImportPath: string(pid.n), Name: string(pid.n), Imports: r[string(pid.n)], @@ -1456,7 +1457,7 @@ func (sm *depspecSourceManager) ListPackages(id ProjectIdentifier, v Version) (P } } - return PackageTree{}, fmt.Errorf("Project %s at version %s could not be found", pid.n, v) + return pkgtree.PackageTree{}, fmt.Errorf("Project %s at version %s could not be found", pid.n, v) } func (sm *depspecSourceManager) ListVersions(id ProjectIdentifier) (pi []Version, err error) { @@ -1545,7 +1546,7 @@ func (b *depspecBridge) verifyRootDir(path string) error { return nil } -func (b *depspecBridge) ListPackages(id ProjectIdentifier, v Version) (PackageTree, error) { +func (b *depspecBridge) ListPackages(id ProjectIdentifier, v Version) (pkgtree.PackageTree, error) { return b.sm.(fixSM).ListPackages(id, v) } @@ -1600,195 +1601,3 @@ func (dummyLock) InputHash() []byte { func (dummyLock) Projects() []LockedProject { return nil } - -// We've borrowed this bestiary from pub's tests: -// https://github.com/dart-lang/pub/blob/master/test/version_solver_test.dart - -// TODO(sdboyer) finish converting all of these - -/* -func basicGraph() { - testResolve("circular dependency", { - "myapp 1.0.0": { - "foo": "1.0.0" - }, - "foo 1.0.0": { - "bar": "1.0.0" - }, - "bar 1.0.0": { - "foo": "1.0.0" - } - }, result: { - "myapp from root": "1.0.0", - "foo": "1.0.0", - "bar": "1.0.0" - }); - -} - -func withLockFile() { - -} - -func rootDependency() { - testResolve("with root source", { - "myapp 1.0.0": { - "foo": "1.0.0" - }, - "foo 1.0.0": { - "myapp from root": ">=1.0.0" - } - }, result: { - "myapp from root": "1.0.0", - "foo": "1.0.0" - }); - - testResolve("with different source", { - "myapp 1.0.0": { - "foo": "1.0.0" - }, - "foo 1.0.0": { - "myapp": ">=1.0.0" - } - }, result: { - "myapp from root": "1.0.0", - "foo": "1.0.0" - }); - - testResolve("with wrong version", { - "myapp 1.0.0": { - "foo": "1.0.0" - }, - "foo 1.0.0": { - "myapp": "<1.0.0" - } - }, error: couldNotSolve); -} - -func unsolvable() { - - testResolve("mismatched descriptions", { - "myapp 0.0.0": { - "foo": "1.0.0", - "bar": "1.0.0" - }, - "foo 1.0.0": { - "shared-x": "1.0.0" - }, - "bar 1.0.0": { - "shared-y": "1.0.0" - }, - "shared-x 1.0.0": {}, - "shared-y 1.0.0": {} - }, error: descriptionMismatch("shared", "foo", "bar")); - - testResolve("mismatched sources", { - "myapp 0.0.0": { - "foo": "1.0.0", - "bar": "1.0.0" - }, - "foo 1.0.0": { - "shared": "1.0.0" - }, - "bar 1.0.0": { - "shared from mock2": "1.0.0" - }, - "shared 1.0.0": {}, - "shared 1.0.0 from mock2": {} - }, error: sourceMismatch("shared", "foo", "bar")); - - - - // This is a regression test for #18300. - testResolve("...", { - "myapp 0.0.0": { - "angular": "any", - "collection": "any" - }, - "analyzer 0.12.2": {}, - "angular 0.10.0": { - "di": ">=0.0.32 <0.1.0", - "collection": ">=0.9.1 <1.0.0" - }, - "angular 0.9.11": { - "di": ">=0.0.32 <0.1.0", - "collection": ">=0.9.1 <1.0.0" - }, - "angular 0.9.10": { - "di": ">=0.0.32 <0.1.0", - "collection": ">=0.9.1 <1.0.0" - }, - "collection 0.9.0": {}, - "collection 0.9.1": {}, - "di 0.0.37": {"analyzer": ">=0.13.0 <0.14.0"}, - "di 0.0.36": {"analyzer": ">=0.13.0 <0.14.0"} - }, error: noVersion(["analyzer", "di"]), maxTries: 2); -} - -func badSource() { - testResolve("fail if the root package has a bad source in dep", { - "myapp 0.0.0": { - "foo from bad": "any" - }, - }, error: unknownSource("myapp", "foo", "bad")); - - testResolve("fail if the root package has a bad source in dev dep", { - "myapp 0.0.0": { - "(dev) foo from bad": "any" - }, - }, error: unknownSource("myapp", "foo", "bad")); - - testResolve("fail if all versions have bad source in dep", { - "myapp 0.0.0": { - "foo": "any" - }, - "foo 1.0.0": { - "bar from bad": "any" - }, - "foo 1.0.1": { - "baz from bad": "any" - }, - "foo 1.0.3": { - "bang from bad": "any" - }, - }, error: unknownSource("foo", "bar", "bad"), maxTries: 3); - - testResolve("ignore versions with bad source in dep", { - "myapp 1.0.0": { - "foo": "any" - }, - "foo 1.0.0": { - "bar": "any" - }, - "foo 1.0.1": { - "bar from bad": "any" - }, - "foo 1.0.3": { - "bar from bad": "any" - }, - "bar 1.0.0": {} - }, result: { - "myapp from root": "1.0.0", - "foo": "1.0.0", - "bar": "1.0.0" - }, maxTries: 3); -} - -func backtracking() { - testResolve("circular dependency on older version", { - "myapp 0.0.0": { - "a": ">=1.0.0" - }, - "a 1.0.0": {}, - "a 2.0.0": { - "b": "1.0.0" - }, - "b 1.0.0": { - "a": "1.0.0" - } - }, result: { - "myapp from root": "0.0.0", - "a": "1.0.0" - }, maxTries: 2); -} -*/ diff --git a/vendor/github.com/sdboyer/gps/solve_bimodal_test.go b/vendor/github.com/sdboyer/gps/solve_bimodal_test.go index 3ee7493f2c..48f63a404b 100644 --- a/vendor/github.com/sdboyer/gps/solve_bimodal_test.go +++ b/vendor/github.com/sdboyer/gps/solve_bimodal_test.go @@ -4,6 +4,8 @@ import ( "fmt" "path/filepath" "strings" + + "github.com/sdboyer/gps/pkgtree" ) // dsp - "depspec with packages" @@ -285,6 +287,33 @@ var bimodalFixtures = map[string]bimodalFixture{ "a 1.0.0", ), }, + "project cycle involving root with backtracking": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "a ~1.0.0"), + pkg("root", "a", "b"), + pkg("root/foo"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "root/foo"), + ), + dsp(mkDepspec("a 1.0.1"), + pkg("a", "root/foo"), + ), + dsp(mkDepspec("b 1.0.0", "a 1.0.0"), + pkg("b", "a"), + ), + dsp(mkDepspec("b 1.0.1", "a 1.0.0"), + pkg("b", "a"), + ), + dsp(mkDepspec("b 1.0.2", "a 1.0.0"), + pkg("b", "a"), + ), + }, + r: mksolution( + "a 1.0.0", + "b 1.0.2", + ), + }, "project cycle not involving root": { ds: []depspec{ dsp(mkDepspec("root 0.0.0", "a ~1.0.0"), @@ -975,7 +1004,7 @@ type tpkg struct { type bimodalFixture struct { // name of this fixture datum n string - // bimodal project. first is always treated as root project + // bimodal project; first is always treated as root project ds []depspec // results; map of name/version pairs r map[ProjectIdentifier]LockedProject @@ -1034,16 +1063,16 @@ func (f bimodalFixture) rootmanifest() RootManifest { return m } -func (f bimodalFixture) rootTree() PackageTree { - pt := PackageTree{ +func (f bimodalFixture) rootTree() pkgtree.PackageTree { + pt := pkgtree.PackageTree{ ImportRoot: string(f.ds[0].n), - Packages: map[string]PackageOrErr{}, + Packages: map[string]pkgtree.PackageOrErr{}, } for _, pkg := range f.ds[0].pkgs { elems := strings.Split(pkg.path, "/") - pt.Packages[pkg.path] = PackageOrErr{ - P: Package{ + pt.Packages[pkg.path] = pkgtree.PackageOrErr{ + P: pkgtree.Package{ ImportPath: pkg.path, Name: elems[len(elems)-1], // TODO(sdboyer) ugh, tpkg type has no space for supporting test @@ -1080,17 +1109,17 @@ func newbmSM(bmf bimodalFixture) *bmSourceManager { return sm } -func (sm *bmSourceManager) ListPackages(id ProjectIdentifier, v Version) (PackageTree, error) { +func (sm *bmSourceManager) ListPackages(id ProjectIdentifier, v Version) (pkgtree.PackageTree, error) { for k, ds := range sm.specs { // Cheat for root, otherwise we blow up b/c version is empty if id.normalizedSource() == string(ds.n) && (k == 0 || ds.v.Matches(v)) { - ptree := PackageTree{ + ptree := pkgtree.PackageTree{ ImportRoot: id.normalizedSource(), - Packages: make(map[string]PackageOrErr), + Packages: make(map[string]pkgtree.PackageOrErr), } for _, pkg := range ds.pkgs { - ptree.Packages[pkg.path] = PackageOrErr{ - P: Package{ + ptree.Packages[pkg.path] = pkgtree.PackageOrErr{ + P: pkgtree.Package{ ImportPath: pkg.path, Name: filepath.Base(pkg.path), Imports: pkg.imports, @@ -1102,7 +1131,7 @@ func (sm *bmSourceManager) ListPackages(id ProjectIdentifier, v Version) (Packag } } - return PackageTree{}, fmt.Errorf("Project %s at version %s could not be found", id.errString(), v) + return pkgtree.PackageTree{}, fmt.Errorf("Project %s at version %s could not be found", id.errString(), v) } func (sm *bmSourceManager) GetManifestAndLock(id ProjectIdentifier, v Version) (Manifest, Lock, error) { @@ -1126,36 +1155,25 @@ func (sm *bmSourceManager) GetManifestAndLock(id ProjectIdentifier, v Version) ( // Note that it does not do things like stripping out stdlib packages - these // maps are intended for use in SM fixtures, and that's a higher-level // responsibility within the system. -func computeBimodalExternalMap(ds []depspec) map[pident]map[string][]string { +func computeBimodalExternalMap(specs []depspec) map[pident]map[string][]string { // map of project name+version -> map of subpkg name -> external pkg list rm := make(map[pident]map[string][]string) - // algorithm adapted from externalReach() - for _, d := range ds { - // Keeps a list of all internal and external reaches for packages within - // a given root. We create one on each pass through, rather than doing - // them all at once, because the depspec set may (read: is expected to) - // have multiple versions of the same base project, and each of those - // must be calculated independently. - workmap := make(map[string]wm) - - for _, pkg := range d.pkgs { - w := wm{ - ex: make(map[string]bool), - in: make(map[string]bool), - } - - for _, imp := range pkg.imports { - if !eqOrSlashedPrefix(imp, string(d.n)) { - w.ex[imp] = true - } else { - w.in[imp] = true - } + for _, ds := range specs { + ptree := pkgtree.PackageTree{ + ImportRoot: string(ds.n), + Packages: make(map[string]pkgtree.PackageOrErr), + } + for _, pkg := range ds.pkgs { + ptree.Packages[pkg.path] = pkgtree.PackageOrErr{ + P: pkgtree.Package{ + ImportPath: pkg.path, + Name: filepath.Base(pkg.path), + Imports: pkg.imports, + }, } - workmap[pkg.path] = w } - - reachmap, em := wmToReach(workmap, true) + reachmap, em := ptree.ToReachMap(false, true, true, nil) if len(em) > 0 { panic(fmt.Sprintf("pkgs with errors in reachmap processing: %s", em)) } @@ -1164,7 +1182,7 @@ func computeBimodalExternalMap(ds []depspec) map[pident]map[string][]string { for ip, ie := range reachmap { drm[ip] = ie.External } - rm[pident{n: d.n, v: d.v}] = drm + rm[pident{n: ds.n, v: ds.v}] = drm } return rm diff --git a/vendor/github.com/sdboyer/gps/solve_test.go b/vendor/github.com/sdboyer/gps/solve_test.go index 9b203f0c4a..8fc4161b96 100644 --- a/vendor/github.com/sdboyer/gps/solve_test.go +++ b/vendor/github.com/sdboyer/gps/solve_test.go @@ -7,12 +7,15 @@ import ( "io/ioutil" "log" "math/rand" - "os" "reflect" "sort" "strconv" "strings" "testing" + "unicode" + + "github.com/sdboyer/gps/internal" + "github.com/sdboyer/gps/pkgtree" ) var fixtorun string @@ -44,18 +47,36 @@ func overrideMkBridge() { // sets the isStdLib func to always return false, otherwise it would identify // pretty much all of our fixtures as being stdlib and skip everything func overrideIsStdLib() { - isStdLib = func(path string) bool { + internal.IsStdLib = func(path string) bool { return false } } -var stderrlog = log.New(os.Stderr, "", 0) +type testlogger struct { + *testing.T +} + +func (t testlogger) Write(b []byte) (n int, err error) { + str := string(b) + if len(str) == 0 { + return 0, nil + } -func fixSolve(params SolveParameters, sm SourceManager) (Solution, error) { - if testing.Verbose() { - params.Trace = true - params.TraceLogger = stderrlog + for _, part := range strings.Split(str, "\n") { + str := strings.TrimRightFunc(part, unicode.IsSpace) + if len(str) != 0 { + t.T.Log(str) + } } + return len(b), err +} + +func fixSolve(params SolveParameters, sm SourceManager, t *testing.T) (Solution, error) { + // Trace unconditionally; by passing the trace through t.Log(), the testing + // system will decide whether or not to actually show the output (based on + // -v, or selectively on test failure). + params.Trace = true + params.TraceLogger = log.New(testlogger{T: t}, "", 0) s, err := Prepare(params, sm) if err != nil { @@ -82,19 +103,14 @@ func TestBasicSolves(t *testing.T) { sort.Strings(names) for _, n := range names { - solveBasicsAndCheck(basicFixtures[n], t) - if testing.Verbose() { - // insert a line break between tests - stderrlog.Println("") - } + t.Run(n, func(t *testing.T) { + solveBasicsAndCheck(basicFixtures[n], t) + }) } } } func solveBasicsAndCheck(fix basicFixture, t *testing.T) (res Solution, err error) { - if testing.Verbose() { - stderrlog.Printf("[[fixture %q]]", fix.n) - } sm := newdepspecSM(fix.ds, nil) params := SolveParameters{ @@ -111,7 +127,7 @@ func solveBasicsAndCheck(fix basicFixture, t *testing.T) (res Solution, err erro params.Lock = fix.l } - res, err = fixSolve(params, sm) + res, err = fixSolve(params, sm, t) return fixtureSolveSimpleChecks(fix, res, err, t) } @@ -133,19 +149,14 @@ func TestBimodalSolves(t *testing.T) { sort.Strings(names) for _, n := range names { - solveBimodalAndCheck(bimodalFixtures[n], t) - if testing.Verbose() { - // insert a line break between tests - stderrlog.Println("") - } + t.Run(n, func(t *testing.T) { + solveBimodalAndCheck(bimodalFixtures[n], t) + }) } } } func solveBimodalAndCheck(fix bimodalFixture, t *testing.T) (res Solution, err error) { - if testing.Verbose() { - stderrlog.Printf("[[fixture %q]]", fix.n) - } sm := newbmSM(fix) params := SolveParameters{ @@ -161,7 +172,7 @@ func solveBimodalAndCheck(fix bimodalFixture, t *testing.T) (res Solution, err e params.Lock = fix.l } - res, err = fixSolve(params, sm) + res, err = fixSolve(params, sm, t) return fixtureSolveSimpleChecks(fix, res, err, t) } @@ -288,7 +299,7 @@ func TestRootLockNoVersionPairMatching(t *testing.T) { Lock: l2, } - res, err := fixSolve(params, sm) + res, err := fixSolve(params, sm, t) fixtureSolveSimpleChecks(fix, res, err, t) } @@ -325,7 +336,7 @@ func TestBadSolveOpts(t *testing.T) { t.Error("Prepare should have given error on empty import root, but gave:", err) } - params.RootPackageTree = PackageTree{ + params.RootPackageTree = pkgtree.PackageTree{ ImportRoot: pn, } _, err = Prepare(params, sm) @@ -335,11 +346,11 @@ func TestBadSolveOpts(t *testing.T) { t.Error("Prepare should have given error on empty import root, but gave:", err) } - params.RootPackageTree = PackageTree{ + params.RootPackageTree = pkgtree.PackageTree{ ImportRoot: pn, - Packages: map[string]PackageOrErr{ + Packages: map[string]pkgtree.PackageOrErr{ pn: { - P: Package{ + P: pkgtree.Package{ ImportPath: pn, Name: pn, }, diff --git a/vendor/github.com/sdboyer/gps/solver.go b/vendor/github.com/sdboyer/gps/solver.go index 95c913c72f..3d3d8240b2 100644 --- a/vendor/github.com/sdboyer/gps/solver.go +++ b/vendor/github.com/sdboyer/gps/solver.go @@ -8,8 +8,27 @@ import ( "strings" "github.com/armon/go-radix" + "github.com/sdboyer/gps/internal" + "github.com/sdboyer/gps/pkgtree" ) +var ( + osList []string + archList []string + ignoreTags = []string{} //[]string{"appengine", "ignore"} //TODO: appengine is a special case for now: https://github.com/tools/godep/issues/353 +) + +func init() { + // The supported systems are listed in + // https://github.com/golang/go/blob/master/src/go/build/syslist.go + // The lists are not exported, so we need to duplicate them here. + osListString := "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows" + osList = strings.Split(osListString, " ") + + archListString := "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc s390 s390x sparc sparc64" + archList = strings.Split(archListString, " ") +} + var rootRev = Revision("") // SolveParameters hold all arguments to a solver run. @@ -38,7 +57,7 @@ type SolveParameters struct { // // The ImportRoot property must be a non-empty string, and at least one // element must be present in the Packages map. - RootPackageTree PackageTree + RootPackageTree pkgtree.PackageTree // The root manifest. This contains all the dependency constraints // associated with normal Manifests, as well as the particular controls @@ -157,7 +176,7 @@ func (params SolveParameters) toRootdata() (rootdata, error) { ig: params.Manifest.IgnoredPackages(), req: params.Manifest.RequiredPackages(), ovr: params.Manifest.Overrides(), - rpt: params.RootPackageTree.dup(), + rpt: params.RootPackageTree.Copy(), chng: make(map[ProjectRoot]struct{}), rlm: make(map[ProjectRoot]LockedProject), chngall: params.ChangeAll, @@ -579,7 +598,7 @@ func (s *solver) intersectConstraintsWithImports(deps []workingConstraint, reach dmap := make(map[ProjectRoot]completeDep) for _, rp := range reach { // If it's a stdlib-shaped package, skip it. - if isStdLib(rp) { + if internal.IsStdLib(rp) { continue } @@ -1152,6 +1171,12 @@ func (s *solver) unselectLast() (atomWithPackages, bool) { } for _, dep := range deps { + // Skip popping if the dep is the root project, which can occur if + // there's a project-level import cycle. (This occurs frequently with + // e.g. kubernetes and docker) + if s.rd.isRoot(dep.Ident.ProjectRoot) { + continue + } s.sel.popDep(dep.Ident) // if no parents/importers, remove from unselected queue diff --git a/vendor/github.com/sdboyer/gps/source.go b/vendor/github.com/sdboyer/gps/source.go index 2ee2ec5cf4..075c8cfd48 100644 --- a/vendor/github.com/sdboyer/gps/source.go +++ b/vendor/github.com/sdboyer/gps/source.go @@ -5,6 +5,8 @@ import ( "os" "path/filepath" "sync" + + "github.com/sdboyer/gps/pkgtree" ) // sourceExistence values represent the extent to which a project "exists." @@ -48,7 +50,7 @@ type source interface { checkExistence(sourceExistence) bool exportVersionTo(Version, string) error getManifestAndLock(ProjectRoot, Version) (Manifest, Lock, error) - listPackages(ProjectRoot, Version) (PackageTree, error) + listPackages(ProjectRoot, Version) (pkgtree.PackageTree, error) listVersions() ([]Version, error) revisionPresentIn(Revision) (bool, error) } @@ -56,7 +58,7 @@ type source interface { type sourceMetaCache struct { //Version string // TODO(sdboyer) use this infos map[Revision]projectInfo - ptrees map[Revision]PackageTree + ptrees map[Revision]pkgtree.PackageTree vMap map[UnpairedVersion]Revision rMap map[Revision][]UnpairedVersion // TODO(sdboyer) mutexes. actually probably just one, b/c complexity @@ -79,7 +81,7 @@ type existence struct { func newMetaCache() *sourceMetaCache { return &sourceMetaCache{ infos: make(map[Revision]projectInfo), - ptrees: make(map[Revision]PackageTree), + ptrees: make(map[Revision]pkgtree.PackageTree), vMap: make(map[UnpairedVersion]Revision), rMap: make(map[Revision][]UnpairedVersion), } @@ -353,7 +355,7 @@ func (bs *baseVCSSource) syncLocal() error { return bs.syncerr } -func (bs *baseVCSSource) listPackages(pr ProjectRoot, v Version) (ptree PackageTree, err error) { +func (bs *baseVCSSource) listPackages(pr ProjectRoot, v Version) (ptree pkgtree.PackageTree, err error) { if err = bs.ensureCacheExistence(); err != nil { return } @@ -390,7 +392,7 @@ func (bs *baseVCSSource) listPackages(pr ProjectRoot, v Version) (ptree PackageT } if err == nil { - ptree, err = ListPackages(bs.crepo.r.LocalPath(), string(pr)) + ptree, err = pkgtree.ListPackages(bs.crepo.r.LocalPath(), string(pr)) // TODO(sdboyer) cache errs? if err == nil { bs.dc.ptrees[r] = ptree diff --git a/vendor/github.com/sdboyer/gps/source_manager.go b/vendor/github.com/sdboyer/gps/source_manager.go index 2ed04deeb8..2c10d15861 100644 --- a/vendor/github.com/sdboyer/gps/source_manager.go +++ b/vendor/github.com/sdboyer/gps/source_manager.go @@ -11,7 +11,7 @@ import ( "sync/atomic" "time" - "github.com/Masterminds/semver" + "github.com/sdboyer/gps/pkgtree" ) // Used to compute a friendly filepath from a URL-shaped input @@ -45,7 +45,7 @@ type SourceManager interface { // ListPackages parses the tree of the Go packages at or below root of the // provided ProjectIdentifier, at the provided version. - ListPackages(ProjectIdentifier, Version) (PackageTree, error) + ListPackages(ProjectIdentifier, Version) (pkgtree.PackageTree, error) // GetManifestAndLock returns manifest and lock information for the provided // root import path. @@ -61,7 +61,7 @@ type SourceManager interface { // AnalyzerInfo reports the name and version of the logic used to service // GetManifestAndLock(). - AnalyzerInfo() (name string, version *semver.Version) + AnalyzerInfo() (name string, version int) // DeduceRootProject takes an import path and deduces the corresponding // project/source root. @@ -77,7 +77,7 @@ type ProjectAnalyzer interface { DeriveManifestAndLock(path string, importRoot ProjectRoot) (Manifest, Lock, error) // Report the name and version of this ProjectAnalyzer. - Info() (name string, version *semver.Version) + Info() (name string, version int) } // SourceMgr is the default SourceManager for gps. @@ -312,7 +312,7 @@ func (sm *SourceMgr) doRelease() { } // AnalyzerInfo reports the name and version of the injected ProjectAnalyzer. -func (sm *SourceMgr) AnalyzerInfo() (name string, version *semver.Version) { +func (sm *SourceMgr) AnalyzerInfo() (name string, version int) { return sm.an.Info() } @@ -344,9 +344,9 @@ func (sm *SourceMgr) GetManifestAndLock(id ProjectIdentifier, v Version) (Manife // ListPackages parses the tree of the Go packages at and below the ProjectRoot // of the given ProjectIdentifier, at the given version. -func (sm *SourceMgr) ListPackages(id ProjectIdentifier, v Version) (PackageTree, error) { +func (sm *SourceMgr) ListPackages(id ProjectIdentifier, v Version) (pkgtree.PackageTree, error) { if atomic.CompareAndSwapInt32(&sm.releasing, 1, 1) { - return PackageTree{}, smIsReleased{} + return pkgtree.PackageTree{}, smIsReleased{} } atomic.AddInt32(&sm.opcount, 1) sm.glock.RLock() @@ -357,7 +357,7 @@ func (sm *SourceMgr) ListPackages(id ProjectIdentifier, v Version) (PackageTree, src, err := sm.getSourceFor(id) if err != nil { - return PackageTree{}, err + return pkgtree.PackageTree{}, err } return src.listPackages(id.ProjectRoot, v) diff --git a/vendor/github.com/sdboyer/gps/source_test.go b/vendor/github.com/sdboyer/gps/source_test.go index db4f1d6e22..d3c84bbf61 100644 --- a/vendor/github.com/sdboyer/gps/source_test.go +++ b/vendor/github.com/sdboyer/gps/source_test.go @@ -3,6 +3,7 @@ package gps import ( "io/ioutil" "net/url" + "os/exec" "reflect" "sync" "testing" @@ -13,6 +14,7 @@ func TestGitSourceInteractions(t *testing.T) { if testing.Short() { t.Skip("Skipping git source version fetching test in short mode") } + requiresBins(t, "git") cpath, err := ioutil.TempDir("", "smcache") if err != nil { @@ -113,6 +115,7 @@ func TestGopkginSourceInteractions(t *testing.T) { if testing.Short() { t.Skip("Skipping gopkg.in source version fetching test in short mode") } + requiresBins(t, "git") cpath, err := ioutil.TempDir("", "smcache") if err != nil { @@ -252,6 +255,7 @@ func TestBzrSourceInteractions(t *testing.T) { if testing.Short() { t.Skip("Skipping bzr source version fetching test in short mode") } + requiresBins(t, "bzr") cpath, err := ioutil.TempDir("", "smcache") if err != nil { @@ -361,6 +365,7 @@ func TestHgSourceInteractions(t *testing.T) { if testing.Short() { t.Skip("Skipping hg source version fetching test in short mode") } + requiresBins(t, "hg") cpath, err := ioutil.TempDir("", "smcache") if err != nil { @@ -481,3 +486,13 @@ func TestHgSourceInteractions(t *testing.T) { <-donech rf() } + +// Fail a test if the specified binaries aren't installed. +func requiresBins(t *testing.T, bins ...string) { + for _, b := range bins { + _, err := exec.LookPath(b) + if err != nil { + t.Fatalf("%s is not installed", b) + } + } +} diff --git a/vendor/github.com/sdboyer/gps/trace.go b/vendor/github.com/sdboyer/gps/trace.go index 97858ac816..c12100d928 100644 --- a/vendor/github.com/sdboyer/gps/trace.go +++ b/vendor/github.com/sdboyer/gps/trace.go @@ -4,6 +4,8 @@ import ( "fmt" "strconv" "strings" + + "github.com/sdboyer/gps/pkgtree" ) const ( @@ -104,7 +106,7 @@ func (s *solver) traceFinish(sol solution, err error) { } // traceSelectRoot is called just once, when the root project is selected -func (s *solver) traceSelectRoot(ptree PackageTree, cdeps []completeDep) { +func (s *solver) traceSelectRoot(ptree pkgtree.PackageTree, cdeps []completeDep) { if s.tl == nil { return } diff --git a/vendor/github.com/sdboyer/gps/vcs_repo.go b/vendor/github.com/sdboyer/gps/vcs_repo.go new file mode 100644 index 0000000000..d2e992a49e --- /dev/null +++ b/vendor/github.com/sdboyer/gps/vcs_repo.go @@ -0,0 +1,314 @@ +package gps + +import ( + "bytes" + "encoding/xml" + "io/ioutil" + "os" + "path/filepath" + "runtime" + "strings" + "time" + + "github.com/Masterminds/vcs" +) + +// original implementation of these methods come from +// https://github.com/Masterminds/vcs + +type gitRepo struct { + *vcs.GitRepo +} + +func (r *gitRepo) Get() error { + out, err := runFromCwd("git", "clone", "--recursive", r.Remote(), r.LocalPath()) + + // There are some windows cases where Git cannot create the parent directory, + // if it does not already exist, to the location it's trying to create the + // repo. Catch that error and try to handle it. + if err != nil && r.isUnableToCreateDir(err) { + basePath := filepath.Dir(filepath.FromSlash(r.LocalPath())) + if _, err := os.Stat(basePath); os.IsNotExist(err) { + err = os.MkdirAll(basePath, 0755) + if err != nil { + return vcs.NewLocalError("unable to create directory", err, "") + } + + out, err = runFromCwd("git", "clone", r.Remote(), r.LocalPath()) + if err != nil { + return vcs.NewRemoteError("unable to get repository", err, string(out)) + } + return err + } + } else if err != nil { + return vcs.NewRemoteError("unable to get repository", err, string(out)) + } + + return nil +} + +func (r *gitRepo) Update() error { + // Perform a fetch to make sure everything is up to date. + out, err := runFromRepoDir(r, "git", "fetch", "--tags", r.RemoteLocation) + if err != nil { + return vcs.NewRemoteError("unable to update repository", err, string(out)) + } + + // When in a detached head state, such as when an individual commit is checked + // out do not attempt a pull. It will cause an error. + detached, err := r.isDetachedHead() + if err != nil { + return vcs.NewLocalError("unable to update repository", err, "") + } + + if detached { + return nil + } + + out, err = runFromRepoDir(r, "git", "pull") + if err != nil { + return vcs.NewRemoteError("unable to update repository", err, string(out)) + } + + return r.defendAgainstSubmodules() +} + +// defendAgainstSubmodules tries to keep repo state sane in the event of +// submodules. Or nested submodules. What a great idea, submodules. +func (r *gitRepo) defendAgainstSubmodules() error { + // First, update them to whatever they should be, if there should happen to be any. + out, err := runFromRepoDir(r, "git", "submodule", "update", "--init", "--recursive") + if err != nil { + return vcs.NewLocalError("unexpected error while defensively updating submodules", err, string(out)) + } + + // Now, do a special extra-aggressive clean in case changing versions caused + // one or more submodules to go away. + out, err = runFromRepoDir(r, "git", "clean", "-x", "-d", "-f", "-f") + if err != nil { + return vcs.NewLocalError("unexpected error while defensively cleaning up after possible derelict submodule directories", err, string(out)) + } + + // Then, repeat just in case there are any nested submodules that went away. + out, err = runFromRepoDir(r, "git", "submodule", "foreach", "--recursive", "git", "clean", "-x", "-d", "-f", "-f") + if err != nil { + return vcs.NewLocalError("unexpected error while defensively cleaning up after possible derelict nested submodule directories", err, string(out)) + } + + return nil +} + +// isUnableToCreateDir checks for an error in the command to see if an error +// where the parent directory of the VCS local path doesn't exist. This is +// done in a multi-lingual manner. +func (r *gitRepo) isUnableToCreateDir(err error) bool { + msg := err.Error() + if strings.HasPrefix(msg, "could not create work tree dir") || + strings.HasPrefix(msg, "不能创建工作区目录") || + strings.HasPrefix(msg, "no s'ha pogut crear el directori d'arbre de treball") || + strings.HasPrefix(msg, "impossible de créer le répertoire de la copie de travail") || + strings.HasPrefix(msg, "kunde inte skapa arbetskatalogen") || + (strings.HasPrefix(msg, "Konnte Arbeitsverzeichnis") && strings.Contains(msg, "nicht erstellen")) || + (strings.HasPrefix(msg, "작업 디렉터리를") && strings.Contains(msg, "만들 수 없습니다")) { + return true + } + + return false +} + +// isDetachedHead will detect if git repo is in "detached head" state. +func (r *gitRepo) isDetachedHead() (bool, error) { + p := filepath.Join(r.LocalPath(), ".git", "HEAD") + contents, err := ioutil.ReadFile(p) + if err != nil { + return false, err + } + + contents = bytes.TrimSpace(contents) + if bytes.HasPrefix(contents, []byte("ref: ")) { + return false, nil + } + + return true, nil +} + +type bzrRepo struct { + *vcs.BzrRepo +} + +func (r *bzrRepo) Get() error { + basePath := filepath.Dir(filepath.FromSlash(r.LocalPath())) + if _, err := os.Stat(basePath); os.IsNotExist(err) { + err = os.MkdirAll(basePath, 0755) + if err != nil { + return vcs.NewLocalError("unable to create directory", err, "") + } + } + + out, err := runFromCwd("bzr", "branch", r.Remote(), r.LocalPath()) + if err != nil { + return vcs.NewRemoteError("unable to get repository", err, string(out)) + } + + return nil +} + +func (r *bzrRepo) Update() error { + out, err := runFromRepoDir(r, "bzr", "pull") + if err != nil { + return vcs.NewRemoteError("unable to update repository", err, string(out)) + } + + out, err = runFromRepoDir(r, "bzr", "update") + if err != nil { + return vcs.NewRemoteError("unable to update repository", err, string(out)) + } + + return nil +} + +type hgRepo struct { + *vcs.HgRepo +} + +func (r *hgRepo) Get() error { + out, err := runFromCwd("hg", "clone", r.Remote(), r.LocalPath()) + if err != nil { + return vcs.NewRemoteError("unable to get repository", err, string(out)) + } + + return nil +} + +func (r *hgRepo) Update() error { + return r.UpdateVersion(``) +} + +func (r *hgRepo) UpdateVersion(version string) error { + out, err := runFromRepoDir(r, "hg", "pull") + if err != nil { + return vcs.NewRemoteError("unable to update checked out version", err, string(out)) + } + + if len(strings.TrimSpace(version)) > 0 { + out, err = runFromRepoDir(r, "hg", "update", version) + } else { + out, err = runFromRepoDir(r, "hg", "update") + } + + if err != nil { + return vcs.NewRemoteError("unable to update checked out version", err, string(out)) + } + + return nil +} + +type svnRepo struct { + *vcs.SvnRepo +} + +func (r *svnRepo) Get() error { + remote := r.Remote() + if strings.HasPrefix(remote, "/") { + remote = "file://" + remote + } else if runtime.GOOS == "windows" && filepath.VolumeName(remote) != "" { + remote = "file:///" + remote + } + + out, err := runFromCwd("svn", "checkout", remote, r.LocalPath()) + if err != nil { + return vcs.NewRemoteError("unable to get repository", err, string(out)) + } + + return nil +} + +func (r *svnRepo) Update() error { + out, err := runFromRepoDir(r, "svn", "update") + if err != nil { + return vcs.NewRemoteError("unable to update repository", err, string(out)) + } + + return err +} + +func (r *svnRepo) UpdateVersion(version string) error { + out, err := runFromRepoDir(r, "svn", "update", "-r", version) + if err != nil { + return vcs.NewRemoteError("unable to update checked out version", err, string(out)) + } + + return nil +} + +func (r *svnRepo) CommitInfo(id string) (*vcs.CommitInfo, error) { + // There are cases where Svn log doesn't return anything for HEAD or BASE. + // svn info does provide details for these but does not have elements like + // the commit message. + if id == "HEAD" || id == "BASE" { + type commit struct { + Revision string `xml:"revision,attr"` + } + + type info struct { + Commit commit `xml:"entry>commit"` + } + + out, err := runFromRepoDir(r, "svn", "info", "-r", id, "--xml") + if err != nil { + return nil, vcs.NewLocalError("unable to retrieve commit information", err, string(out)) + } + + infos := new(info) + err = xml.Unmarshal(out, &infos) + if err != nil { + return nil, vcs.NewLocalError("unable to retrieve commit information", err, string(out)) + } + + id = infos.Commit.Revision + if id == "" { + return nil, vcs.ErrRevisionUnavailable + } + } + + out, err := runFromRepoDir(r, "svn", "log", "-r", id, "--xml") + if err != nil { + return nil, vcs.NewRemoteError("unable to retrieve commit information", err, string(out)) + } + + type logentry struct { + Author string `xml:"author"` + Date string `xml:"date"` + Msg string `xml:"msg"` + } + + type log struct { + XMLName xml.Name `xml:"log"` + Logs []logentry `xml:"logentry"` + } + + logs := new(log) + err = xml.Unmarshal(out, &logs) + if err != nil { + return nil, vcs.NewLocalError("unable to retrieve commit information", err, string(out)) + } + + if len(logs.Logs) == 0 { + return nil, vcs.ErrRevisionUnavailable + } + + ci := &vcs.CommitInfo{ + Commit: id, + Author: logs.Logs[0].Author, + Message: logs.Logs[0].Msg, + } + + if len(logs.Logs[0].Date) > 0 { + ci.Date, err = time.Parse(time.RFC3339Nano, logs.Logs[0].Date) + if err != nil { + return nil, vcs.NewLocalError("unable to retrieve commit information", err, string(out)) + } + } + + return ci, nil +} diff --git a/vendor/github.com/sdboyer/gps/vcs_repo_test.go b/vendor/github.com/sdboyer/gps/vcs_repo_test.go new file mode 100644 index 0000000000..722edb3483 --- /dev/null +++ b/vendor/github.com/sdboyer/gps/vcs_repo_test.go @@ -0,0 +1,308 @@ +package gps + +import ( + "io/ioutil" + "os" + "testing" + "time" + + "github.com/Masterminds/vcs" +) + +// original implementation of these test files come from +// https://github.com/Masterminds/vcs test files + +func TestSvnRepo(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + tempDir, err := ioutil.TempDir("", "go-vcs-svn-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + rep, err := vcs.NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir+string(os.PathSeparator)+"VCSTestRepo") + if err != nil { + t.Error(err) + } + repo := &svnRepo{rep} + + // Do an initial checkout. + err = repo.Get() + if err != nil { + t.Errorf("Unable to checkout SVN repo. Err was %s", err) + } + + // Verify SVN repo is a SVN repo + if !repo.CheckLocal() { + t.Error("Problem checking out repo or SVN CheckLocal is not working") + } + + // Update the version to a previous version. + err = repo.UpdateVersion("r2") + if err != nil { + t.Errorf("Unable to update SVN repo version. Err was %s", err) + } + + // Use Version to verify we are on the right version. + v, err := repo.Version() + if v != "2" { + t.Error("Error checking checked SVN out version") + } + if err != nil { + t.Error(err) + } + + // Perform an update which should take up back to the latest version. + err = repo.Update() + if err != nil { + t.Error(err) + } + + // Make sure we are on a newer version because of the update. + v, err = repo.Version() + if v == "2" { + t.Error("Error with version. Still on old version. Update failed") + } + if err != nil { + t.Error(err) + } + + ci, err := repo.CommitInfo("2") + if err != nil { + t.Error(err) + } + if ci.Commit != "2" { + t.Error("Svn.CommitInfo wrong commit id") + } + if ci.Author != "matt.farina" { + t.Error("Svn.CommitInfo wrong author") + } + if ci.Message != "Update README.md" { + t.Error("Svn.CommitInfo wrong message") + } + ti, err := time.Parse(time.RFC3339Nano, "2015-07-29T13:46:20.000000Z") + if err != nil { + t.Error(err) + } + if !ti.Equal(ci.Date) { + t.Error("Svn.CommitInfo wrong date") + } + + _, err = repo.CommitInfo("555555555") + if err != vcs.ErrRevisionUnavailable { + t.Error("Svn didn't return expected ErrRevisionUnavailable") + } +} + +func TestHgRepo(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + tempDir, err := ioutil.TempDir("", "go-vcs-hg-tests") + if err != nil { + t.Error(err) + } + + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + rep, err := vcs.NewHgRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir+"/testhgrepo") + if err != nil { + t.Error(err) + } + + repo := &hgRepo{rep} + + // Do an initial clone. + err = repo.Get() + if err != nil { + t.Errorf("Unable to clone Hg repo. Err was %s", err) + } + + // Verify Hg repo is a Hg repo + if !repo.CheckLocal() { + t.Error("Problem checking out repo or Hg CheckLocal is not working") + } + + // Set the version using the short hash. + err = repo.UpdateVersion("a5494ba2177f") + if err != nil { + t.Errorf("Unable to update Hg repo version. Err was %s", err) + } + + // Use Version to verify we are on the right version. + v, err := repo.Version() + if v != "a5494ba2177ff9ef26feb3c155dfecc350b1a8ef" { + t.Errorf("Error checking checked out Hg version: %s", v) + } + if err != nil { + t.Error(err) + } + + // Perform an update. + err = repo.Update() + if err != nil { + t.Error(err) + } + + v, err = repo.Version() + if v != "9c6ccbca73e8a1351c834f33f57f1f7a0329ad35" { + t.Errorf("Error checking checked out Hg version: %s", v) + } + if err != nil { + t.Error(err) + } +} + +func TestGitRepo(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + tempDir, err := ioutil.TempDir("", "go-vcs-git-tests") + if err != nil { + t.Error(err) + } + + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + rep, err := vcs.NewGitRepo("https://github.com/Masterminds/VCSTestRepo", tempDir+"/VCSTestRepo") + if err != nil { + t.Error(err) + } + + repo := &gitRepo{rep} + + // Do an initial clone. + err = repo.Get() + if err != nil { + t.Errorf("Unable to clone Git repo. Err was %s", err) + } + + // Verify Git repo is a Git repo + if !repo.CheckLocal() { + t.Error("Problem checking out repo or Git CheckLocal is not working") + } + + // Perform an update. + err = repo.Update() + if err != nil { + t.Error(err) + } + + v, err := repo.Current() + if err != nil { + t.Errorf("Error trying Git Current: %s", err) + } + if v != "master" { + t.Errorf("Current failed to detect Git on tip of master. Got version: %s", v) + } + + // Set the version using the short hash. + err = repo.UpdateVersion("806b07b") + if err != nil { + t.Errorf("Unable to update Git repo version. Err was %s", err) + } + + // Once a ref has been checked out the repo is in a detached head state. + // Trying to pull in an update in this state will cause an error. Update + // should cleanly handle this. Pulling on a branch (tested elsewhere) and + // skipping that here. + err = repo.Update() + if err != nil { + t.Error(err) + } + + // Use Version to verify we are on the right version. + v, err = repo.Version() + if v != "806b07b08faa21cfbdae93027904f80174679402" { + t.Error("Error checking checked out Git version") + } + if err != nil { + t.Error(err) + } +} + +func TestBzrRepo(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests") + if err != nil { + t.Error(err) + } + + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + rep, err := vcs.NewBzrRepo("https://launchpad.net/govcstestbzrrepo", tempDir+"/govcstestbzrrepo") + if err != nil { + t.Fatal(err) + } + + repo := &bzrRepo{rep} + + // Do an initial clone. + err = repo.Get() + if err != nil { + t.Errorf("Unable to clone Bzr repo. Err was %s", err) + } + + // Verify Bzr repo is a Bzr repo + if !repo.CheckLocal() { + t.Error("Problem checking out repo or Bzr CheckLocal is not working") + } + + v, err := repo.Current() + if err != nil { + t.Errorf("Error trying Bzr Current: %s", err) + } + if v != "-1" { + t.Errorf("Current failed to detect Bzr on tip of branch. Got version: %s", v) + } + + err = repo.UpdateVersion("2") + if err != nil { + t.Errorf("Unable to update Bzr repo version. Err was %s", err) + } + + // Use Version to verify we are on the right version. + v, err = repo.Version() + if v != "2" { + t.Error("Error checking checked out Bzr version") + } + if err != nil { + t.Error(err) + } + + v, err = repo.Current() + if err != nil { + t.Errorf("Error trying Bzr Current: %s", err) + } + if v != "2" { + t.Errorf("Current failed to detect Bzr on rev 2 of branch. Got version: %s", v) + } +} diff --git a/vendor/github.com/sdboyer/gps/vcs_source.go b/vendor/github.com/sdboyer/gps/vcs_source.go index 3663a97c56..940dd82ec8 100644 --- a/vendor/github.com/sdboyer/gps/vcs_source.go +++ b/vendor/github.com/sdboyer/gps/vcs_source.go @@ -11,6 +11,7 @@ import ( "github.com/Masterminds/semver" "github.com/Masterminds/vcs" + "github.com/sdboyer/gps/internal/fs" ) // Kept here as a reference in case it does become important to implement a @@ -50,20 +51,20 @@ func (s *gitSource) exportVersionTo(v Version, to string) error { // Back up original index idx, bak := filepath.Join(r.LocalPath(), ".git", "index"), filepath.Join(r.LocalPath(), ".git", "origindex") - err := renameWithFallback(idx, bak) + err := fs.RenameWithFallback(idx, bak) if err != nil { return err } // could have an err here...but it's hard to imagine how? - defer renameWithFallback(bak, idx) + defer fs.RenameWithFallback(bak, idx) vstr := v.String() if rv, ok := v.(PairedVersion); ok { vstr = rv.Underlying().String() } - out, err := r.RunFromDir("git", "read-tree", vstr) + out, err := runFromRepoDir(r, "git", "read-tree", vstr) if err != nil { return fmt.Errorf("%s: %s", out, err) } @@ -79,7 +80,7 @@ func (s *gitSource) exportVersionTo(v Version, to string) error { // though we have a bunch of housekeeping to do to set up, then tear // down, the sparse checkout controls, as well as restore the original // index and HEAD. - out, err = r.RunFromDir("git", "checkout-index", "-a", "--prefix="+to) + out, err = runFromRepoDir(r, "git", "checkout-index", "-a", "--prefix="+to) if err != nil { return fmt.Errorf("%s: %s", out, err) } @@ -170,7 +171,7 @@ func (s *gitSource) doListVersions() (vlist []Version, err error) { s.crepo.synced = true s.crepo.mut.RLock() - out, err = r.RunFromDir("git", "show-ref", "--dereference") + out, err = runFromRepoDir(r, "git", "show-ref", "--dereference") s.crepo.mut.RUnlock() if err != nil { // TODO(sdboyer) More-er proper-er error @@ -385,6 +386,22 @@ type bzrSource struct { baseVCSSource } +func (s *bzrSource) update() error { + r := s.crepo.r + + out, err := runFromRepoDir(r, "bzr", "pull") + if err != nil { + return vcs.NewRemoteError("Unable to update repository", err, string(out)) + } + + out, err = runFromRepoDir(r, "bzr", "update") + if err != nil { + return vcs.NewRemoteError("Unable to update repository", err, string(out)) + } + + return nil +} + func (s *bzrSource) listVersions() (vlist []Version, err error) { s.baseVCSSource.lvmut.Lock() defer s.baseVCSSource.lvmut.Unlock() @@ -411,7 +428,7 @@ func (s *bzrSource) listVersions() (vlist []Version, err error) { // didn't create it if !s.crepo.synced { s.crepo.mut.Lock() - err = r.Update() + err = s.update() s.crepo.mut.Unlock() if err != nil { return @@ -422,7 +439,7 @@ func (s *bzrSource) listVersions() (vlist []Version, err error) { var out []byte // Now, list all the tags - out, err = r.RunFromDir("bzr", "tags", "--show-ids", "-v") + out, err = runFromRepoDir(r, "bzr", "tags", "--show-ids", "-v") if err != nil { return nil, fmt.Errorf("%s: %s", err, string(out)) } @@ -430,7 +447,7 @@ func (s *bzrSource) listVersions() (vlist []Version, err error) { all := bytes.Split(bytes.TrimSpace(out), []byte("\n")) var branchrev []byte - branchrev, err = r.RunFromDir("bzr", "version-info", "--custom", "--template={revision_id}", "--revision=branch:.") + branchrev, err = runFromRepoDir(r, "bzr", "version-info", "--custom", "--template={revision_id}", "--revision=branch:.") br := string(branchrev) if err != nil { return nil, fmt.Errorf("%s: %s", err, br) @@ -473,6 +490,22 @@ type hgSource struct { baseVCSSource } +func (s *hgSource) update() error { + r := s.crepo.r + + out, err := runFromRepoDir(r, "hg", "pull") + if err != nil { + return vcs.NewLocalError("Unable to update checked out version", err, string(out)) + } + + out, err = runFromRepoDir(r, "hg", "update") + if err != nil { + return vcs.NewLocalError("Unable to update checked out version", err, string(out)) + } + + return nil +} + func (s *hgSource) listVersions() (vlist []Version, err error) { s.baseVCSSource.lvmut.Lock() defer s.baseVCSSource.lvmut.Unlock() @@ -499,7 +532,7 @@ func (s *hgSource) listVersions() (vlist []Version, err error) { // didn't create it if !s.crepo.synced { s.crepo.mut.Lock() - err = unwrapVcsErr(r.Update()) + err = unwrapVcsErr(s.update()) s.crepo.mut.Unlock() if err != nil { return @@ -511,7 +544,7 @@ func (s *hgSource) listVersions() (vlist []Version, err error) { var out []byte // Now, list all the tags - out, err = r.RunFromDir("hg", "tags", "--debug", "--verbose") + out, err = runFromRepoDir(r, "hg", "tags", "--debug", "--verbose") if err != nil { return nil, fmt.Errorf("%s: %s", err, string(out)) } @@ -545,7 +578,7 @@ func (s *hgSource) listVersions() (vlist []Version, err error) { // bookmarks next, because the presence of the magic @ bookmark has to // determine how we handle the branches var magicAt bool - out, err = r.RunFromDir("hg", "bookmarks", "--debug") + out, err = runFromRepoDir(r, "hg", "bookmarks", "--debug") if err != nil { // better nothing than partial and misleading return nil, fmt.Errorf("%s: %s", err, string(out)) @@ -578,7 +611,7 @@ func (s *hgSource) listVersions() (vlist []Version, err error) { } } - out, err = r.RunFromDir("hg", "branches", "-c", "--debug") + out, err = runFromRepoDir(r, "hg", "branches", "-c", "--debug") if err != nil { // better nothing than partial and misleading return nil, fmt.Errorf("%s: %s", err, string(out)) @@ -653,7 +686,7 @@ func (r *repo) exportVersionTo(v Version, to string) error { // TODO(sdboyer) this is a simplistic approach and relying on the tools // themselves might make it faster, but git's the overwhelming case (and has // its own method) so fine for now - return copyDir(r.rpath, to) + return fs.CopyDir(r.rpath, to) } // This func copied from Masterminds/vcs so we can exec our own commands