diff --git a/cmd/dep/ensure.go b/cmd/dep/ensure.go index dd558b9047..55549c514b 100644 --- a/cmd/dep/ensure.go +++ b/cmd/dep/ensure.go @@ -6,13 +6,11 @@ package main import ( "bytes" - "encoding/hex" "flag" "fmt" "go/build" "log" "path/filepath" - "strconv" "strings" "github.com/golang/dep" @@ -297,79 +295,13 @@ func getProjectConstraint(arg string, sm gps.SourceManager) (gps.ProjectConstrai } pi := gps.ProjectIdentifier{ProjectRoot: pr, Source: source} - c, err := deduceConstraint(versionStr, pi, sm) + c, err := sm.DeduceConstraint(versionStr, pi) if err != nil { return emptyPC, err } return gps.ProjectConstraint{Ident: pi, Constraint: c}, nil } -// deduceConstraint tries to puzzle out what kind of version is given in a string - -// semver, a revision, or as a fallback, a plain tag -func deduceConstraint(s string, pi gps.ProjectIdentifier, sm gps.SourceManager) (gps.Constraint, error) { - if s == "" { - // Find the default branch - versions, err := sm.ListVersions(pi) - if err != nil { - return nil, errors.Wrapf(err, "list versions for %s(%s)", pi.ProjectRoot, pi.Source) // means repo does not exist - } - - gps.SortPairedForUpgrade(versions) - for _, v := range versions { - if v.Type() == gps.IsBranch { - return v.Unpair(), nil - } - } - } - - // always semver if we can - c, err := gps.NewSemverConstraintIC(s) - if err == nil { - return c, nil - } - - slen := len(s) - if slen == 40 { - if _, err = hex.DecodeString(s); err == nil { - // Whether or not it's intended to be a SHA1 digest, this is a - // valid byte sequence for that, so go with Revision. This - // covers git and hg - return gps.Revision(s), nil - } - } - // Next, try for bzr, which has a three-component GUID separated by - // dashes. There should be two, but the email part could contain - // internal dashes - if strings.Count(s, "-") >= 2 { - // Work from the back to avoid potential confusion from the email - i3 := strings.LastIndex(s, "-") - // Skip if - is last char, otherwise this would panic on bounds err - if slen == i3+1 { - return gps.NewVersion(s), nil - } - - i2 := strings.LastIndex(s[:i3], "-") - if _, err = strconv.ParseUint(s[i2+1:i3], 10, 64); err == nil { - // Getting this far means it'd pretty much be nuts if it's not a - // bzr rev, so don't bother parsing the email. - return gps.Revision(s), nil - } - } - - // call out to network and get the package's versions - versions, err := sm.ListVersions(pi) - if err != nil { - return nil, errors.Wrapf(err, "list versions for %s(%s)", pi.ProjectRoot, pi.Source) // means repo does not exist - } - - for _, version := range versions { - if s == version.String() { - return version.Unpair(), nil - } - } - return nil, errors.Errorf("%s is not a valid version for the package %s(%s)", s, pi.ProjectRoot, pi.Source) -} - func checkErrors(m map[string]pkgtree.PackageOrErr) error { noGoErrors, pkgErrors := 0, 0 for _, poe := range m { diff --git a/cmd/dep/ensure_test.go b/cmd/dep/ensure_test.go index 478e686e13..0bff840c54 100644 --- a/cmd/dep/ensure_test.go +++ b/cmd/dep/ensure_test.go @@ -38,7 +38,7 @@ func TestDeduceConstraint(t *testing.T) { pi := gps.ProjectIdentifier{ProjectRoot: "github.com/sdboyer/deptest"} for str, want := range constraints { - got, err := deduceConstraint(str, pi, sm) + got, err := sm.DeduceConstraint(str, pi) h.Must(err) wantT := reflect.TypeOf(want) @@ -68,7 +68,7 @@ func TestDeduceConstraint_InvalidInput(t *testing.T) { pi := gps.ProjectIdentifier{ProjectRoot: "github.com/sdboyer/deptest"} for _, str := range constraints { - _, err := deduceConstraint(str, pi, sm) + _, err := sm.DeduceConstraint(str, pi) if err == nil { t.Errorf("expected %s to produce an error", str) } diff --git a/cmd/dep/glide_importer.go b/cmd/dep/glide_importer.go index c53ff391ea..e717adbdfc 100644 --- a/cmd/dep/glide_importer.go +++ b/cmd/dep/glide_importer.go @@ -206,7 +206,7 @@ func (g *glideImporter) buildProjectConstraint(pkg glidePackage) (pc gps.Project } pc.Ident = gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(pkg.Name), Source: pkg.Repository} - pc.Constraint, err = deduceConstraint(pkg.Reference, pc.Ident, g.sm) + pc.Constraint, err = g.sm.DeduceConstraint(pkg.Reference, pc.Ident) f := fb.NewConstraintFeedback(pc, fb.DepTypeImported) f.LogFeedback(g.logger) diff --git a/cmd/dep/godep_importer.go b/cmd/dep/godep_importer.go index 101582f7b6..ead09f220b 100644 --- a/cmd/dep/godep_importer.go +++ b/cmd/dep/godep_importer.go @@ -158,7 +158,7 @@ func (g *godepImporter) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, e // create a project constraint func (g *godepImporter) buildProjectConstraint(pkg godepPackage) (pc gps.ProjectConstraint, err error) { pc.Ident = gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(pkg.ImportPath)} - pc.Constraint, err = deduceConstraint(pkg.Comment, pc.Ident, g.sm) + pc.Constraint, err = g.sm.DeduceConstraint(pkg.Comment, pc.Ident) f := fb.NewConstraintFeedback(pc, fb.DepTypeImported) f.LogFeedback(g.logger) diff --git a/internal/gps/solve_basic_test.go b/internal/gps/solve_basic_test.go index 2728c44145..a96344b61c 100644 --- a/internal/gps/solve_basic_test.go +++ b/internal/gps/solve_basic_test.go @@ -5,12 +5,15 @@ package gps import ( + "encoding/hex" "fmt" "regexp" + "strconv" "strings" "github.com/Masterminds/semver" "github.com/golang/dep/internal/gps/pkgtree" + "github.com/pkg/errors" ) var regfrom = regexp.MustCompile(`^(\w*) from (\w*) ([0-9\.\*]*)`) @@ -1550,6 +1553,72 @@ func (sm *depspecSourceManager) ignore() map[string]bool { return sm.ig } +// DeduceConstraint tries to puzzle out what kind of version is given in a string - +// semver, a revision, or as a fallback, a plain tag +func (sm *depspecSourceManager) DeduceConstraint(s string, pi ProjectIdentifier) (Constraint, error) { + if s == "" { + // Find the default branch + versions, err := sm.ListVersions(pi) + if err != nil { + return nil, errors.Wrapf(err, "list versions for %s(%s)", pi.ProjectRoot, pi.Source) // means repo does not exist + } + + SortPairedForUpgrade(versions) + for _, v := range versions { + if v.Type() == IsBranch { + return v.Unpair(), nil + } + } + } + + // always semver if we can + c, err := NewSemverConstraintIC(s) + if err == nil { + return c, nil + } + + slen := len(s) + if slen == 40 { + if _, err = hex.DecodeString(s); err == nil { + // Whether or not it's intended to be a SHA1 digest, this is a + // valid byte sequence for that, so go with Revision. This + // covers git and hg + return Revision(s), nil + } + } + // Next, try for bzr, which has a three-component GUID separated by + // dashes. There should be two, but the email part could contain + // internal dashes + if strings.Count(s, "-") >= 2 { + // Work from the back to avoid potential confusion from the email + i3 := strings.LastIndex(s, "-") + // Skip if - is last char, otherwise this would panic on bounds err + if slen == i3+1 { + return NewVersion(s), nil + } + + i2 := strings.LastIndex(s[:i3], "-") + if _, err = strconv.ParseUint(s[i2+1:i3], 10, 64); err == nil { + // Getting this far means it'd pretty much be nuts if it's not a + // bzr rev, so don't bother parsing the email. + return Revision(s), nil + } + } + + // call out to network and get the package's versions + versions, err := sm.ListVersions(pi) + if err != nil { + return nil, errors.Wrapf(err, "list versions for %s(%s)", pi.ProjectRoot, pi.Source) // means repo does not exist + } + + for _, version := range versions { + if s == version.String() { + return version.Unpair(), nil + } + } + return nil, errors.Errorf("%s is not a valid version for the package %s(%s)", s, pi.ProjectRoot, pi.Source) +} + type depspecBridge struct { *bridge } diff --git a/internal/gps/source_manager.go b/internal/gps/source_manager.go index 6f60c6dad6..af7bdb10a5 100644 --- a/internal/gps/source_manager.go +++ b/internal/gps/source_manager.go @@ -6,17 +6,20 @@ package gps import ( "context" + "encoding/hex" "fmt" "os" "os/signal" "path/filepath" "runtime" + "strconv" "strings" "sync" "sync/atomic" "time" "github.com/golang/dep/internal/gps/pkgtree" + "github.com/pkg/errors" "github.com/sdboyer/constext" ) @@ -72,6 +75,10 @@ type SourceManager interface { // no longer safe to call methods against it; all method calls will // immediately result in errors. Release() + + // DeduceConstraint tries to puzzle out what kind of version is given in a string - + // semver, a revision, or as a fallback, a plain tag + DeduceConstraint(s string, pi ProjectIdentifier) (Constraint, error) } // A ProjectAnalyzer is responsible for analyzing a given path for Manifest and @@ -455,6 +462,72 @@ func (sm *SourceMgr) DeduceProjectRoot(ip string) (ProjectRoot, error) { return ProjectRoot(pd.root), err } +// DeduceConstraint tries to puzzle out what kind of version is given in a string - +// semver, a revision, or as a fallback, a plain tag +func (sm *SourceMgr) DeduceConstraint(s string, pi ProjectIdentifier) (Constraint, error) { + if s == "" { + // Find the default branch + versions, err := sm.ListVersions(pi) + if err != nil { + return nil, errors.Wrapf(err, "list versions for %s(%s)", pi.ProjectRoot, pi.Source) // means repo does not exist + } + + SortPairedForUpgrade(versions) + for _, v := range versions { + if v.Type() == IsBranch { + return v.Unpair(), nil + } + } + } + + // always semver if we can + c, err := NewSemverConstraintIC(s) + if err == nil { + return c, nil + } + + slen := len(s) + if slen == 40 { + if _, err = hex.DecodeString(s); err == nil { + // Whether or not it's intended to be a SHA1 digest, this is a + // valid byte sequence for that, so go with Revision. This + // covers git and hg + return Revision(s), nil + } + } + // Next, try for bzr, which has a three-component GUID separated by + // dashes. There should be two, but the email part could contain + // internal dashes + if strings.Count(s, "-") >= 2 { + // Work from the back to avoid potential confusion from the email + i3 := strings.LastIndex(s, "-") + // Skip if - is last char, otherwise this would panic on bounds err + if slen == i3+1 { + return NewVersion(s), nil + } + + i2 := strings.LastIndex(s[:i3], "-") + if _, err = strconv.ParseUint(s[i2+1:i3], 10, 64); err == nil { + // Getting this far means it'd pretty much be nuts if it's not a + // bzr rev, so don't bother parsing the email. + return Revision(s), nil + } + } + + // call out to network and get the package's versions + versions, err := sm.ListVersions(pi) + if err != nil { + return nil, errors.Wrapf(err, "list versions for %s(%s)", pi.ProjectRoot, pi.Source) // means repo does not exist + } + + for _, version := range versions { + if s == version.String() { + return version.Unpair(), nil + } + } + return nil, errors.Errorf("%s is not a valid version for the package %s(%s)", s, pi.ProjectRoot, pi.Source) +} + type timeCount struct { count int start time.Time