зеркало из https://github.com/golang/dep.git
Merge pull request #1884 from sdboyer/discard-version-unifier
gps: Remove versionTypeUnion
This commit is contained in:
Коммит
6211c75ddb
|
@ -4,8 +4,8 @@
|
|||
[[projects]]
|
||||
name = "github.com/sdboyer/deptest"
|
||||
packages = ["."]
|
||||
revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf"
|
||||
version = "v1.0.0"
|
||||
revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f"
|
||||
version = "v0.8.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/sdboyer/deptestdos"
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
[[projects]]
|
||||
name = "github.com/sdboyer/deptest"
|
||||
packages = ["."]
|
||||
revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf"
|
||||
version = "v1.0.0"
|
||||
revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f"
|
||||
version = "v0.8.1"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
|
|
2
cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/final/Gopkg.lock
сгенерированный
поставляемый
2
cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/final/Gopkg.lock
сгенерированный
поставляемый
|
@ -2,10 +2,10 @@
|
|||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/sdboyer/deptest"
|
||||
packages = ["."]
|
||||
revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f"
|
||||
version = "v0.8.1"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
[[projects]]
|
||||
name = "github.com/sdboyer/deptest"
|
||||
packages = ["."]
|
||||
revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf"
|
||||
version = "v1.0.0"
|
||||
revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f"
|
||||
version = "v0.8.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/sdboyer/deptestdos"
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
[[projects]]
|
||||
name = "github.com/sdboyer/deptest"
|
||||
packages = ["."]
|
||||
revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf"
|
||||
version = "v1.0.0"
|
||||
revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f"
|
||||
version = "v0.8.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/sdboyer/deptestdos"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{
|
||||
"importpath": "github.com/sdboyer/deptestdos",
|
||||
"repository": "https://github.com/sdboyer/deptestdos",
|
||||
"revision": "5c607206be5decd28e6263ffffdcee067266015eXXX",
|
||||
"revision": "5c607206be5decd28e6263ffffdcee067266015e",
|
||||
"branch": "master"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -169,12 +169,6 @@ func (c semverConstraint) typedString() string {
|
|||
|
||||
func (c semverConstraint) Matches(v Version) bool {
|
||||
switch tv := v.(type) {
|
||||
case versionTypeUnion:
|
||||
for _, elem := range tv {
|
||||
if c.Matches(elem) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
case semVersion:
|
||||
return c.c.Matches(tv.sv) == nil
|
||||
case versionPair:
|
||||
|
@ -194,12 +188,6 @@ func (c semverConstraint) Intersect(c2 Constraint) Constraint {
|
|||
switch tc := c2.(type) {
|
||||
case anyConstraint:
|
||||
return c
|
||||
case versionTypeUnion:
|
||||
for _, elem := range tc {
|
||||
if rc := c.Intersect(elem); rc != none {
|
||||
return rc
|
||||
}
|
||||
}
|
||||
case semverConstraint:
|
||||
rc := c.c.Intersect(tc.c)
|
||||
if !semver.IsNone(rc) {
|
||||
|
|
|
@ -697,183 +697,6 @@ func TestSemverConstraint_ImpliedCaret(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Test that certain types of cross-version comparisons work when they are
|
||||
// expressed as a version union (but that others don't).
|
||||
func TestVersionUnion(t *testing.T) {
|
||||
rev := Revision("flooboofoobooo")
|
||||
v1 := NewBranch("master")
|
||||
v2 := NewBranch("test")
|
||||
v3 := NewVersion("1.0.0").Pair(rev)
|
||||
v4 := NewVersion("1.0.1")
|
||||
v5 := NewVersion("v2.0.5").Pair(Revision("notamatch"))
|
||||
|
||||
uv1 := versionTypeUnion{v1, v4, rev}
|
||||
uv2 := versionTypeUnion{v2, v3}
|
||||
|
||||
if uv1.MatchesAny(none) {
|
||||
t.Errorf("Union can't match none")
|
||||
}
|
||||
if none.MatchesAny(uv1) {
|
||||
t.Errorf("Union can't match none")
|
||||
}
|
||||
|
||||
if !uv1.MatchesAny(any) {
|
||||
t.Errorf("Union must match any")
|
||||
}
|
||||
if !any.MatchesAny(uv1) {
|
||||
t.Errorf("Union must match any")
|
||||
}
|
||||
|
||||
// Basic matching
|
||||
if !uv1.Matches(v4) {
|
||||
t.Errorf("Union should match on branch to branch")
|
||||
}
|
||||
if !v4.Matches(uv1) {
|
||||
t.Errorf("Union should reverse-match on branch to branch")
|
||||
}
|
||||
|
||||
if !uv1.Matches(v3) {
|
||||
t.Errorf("Union should match on rev to paired rev")
|
||||
}
|
||||
if !v3.Matches(uv1) {
|
||||
t.Errorf("Union should reverse-match on rev to paired rev")
|
||||
}
|
||||
|
||||
if uv1.Matches(v2) {
|
||||
t.Errorf("Union should not match on anything in disjoint unpaired")
|
||||
}
|
||||
if v2.Matches(uv1) {
|
||||
t.Errorf("Union should not reverse-match on anything in disjoint unpaired")
|
||||
}
|
||||
|
||||
if uv1.Matches(v5) {
|
||||
t.Errorf("Union should not match on anything in disjoint pair")
|
||||
}
|
||||
if v5.Matches(uv1) {
|
||||
t.Errorf("Union should not reverse-match on anything in disjoint pair")
|
||||
}
|
||||
|
||||
if !uv1.Matches(uv2) {
|
||||
t.Errorf("Union should succeed on matching comparison to other union with some overlap")
|
||||
}
|
||||
|
||||
// MatchesAny - repeat Matches for safety, but add more, too
|
||||
if !uv1.MatchesAny(v4) {
|
||||
t.Errorf("Union should match on branch to branch")
|
||||
}
|
||||
if !v4.MatchesAny(uv1) {
|
||||
t.Errorf("Union should reverse-match on branch to branch")
|
||||
}
|
||||
|
||||
if !uv1.MatchesAny(v3) {
|
||||
t.Errorf("Union should match on rev to paired rev")
|
||||
}
|
||||
if !v3.MatchesAny(uv1) {
|
||||
t.Errorf("Union should reverse-match on rev to paired rev")
|
||||
}
|
||||
|
||||
if uv1.MatchesAny(v2) {
|
||||
t.Errorf("Union should not match on anything in disjoint unpaired")
|
||||
}
|
||||
if v2.MatchesAny(uv1) {
|
||||
t.Errorf("Union should not reverse-match on anything in disjoint unpaired")
|
||||
}
|
||||
|
||||
if uv1.MatchesAny(v5) {
|
||||
t.Errorf("Union should not match on anything in disjoint pair")
|
||||
}
|
||||
if v5.MatchesAny(uv1) {
|
||||
t.Errorf("Union should not reverse-match on anything in disjoint pair")
|
||||
}
|
||||
|
||||
c1, _ := NewSemverConstraint("~1.0.0")
|
||||
c2, _ := NewSemverConstraint("~2.0.0")
|
||||
if !uv1.MatchesAny(c1) {
|
||||
t.Errorf("Union should have some overlap due to containing 1.0.1 version")
|
||||
}
|
||||
if !c1.MatchesAny(uv1) {
|
||||
t.Errorf("Union should have some overlap due to containing 1.0.1 version")
|
||||
}
|
||||
|
||||
if uv1.MatchesAny(c2) {
|
||||
t.Errorf("Union should have no overlap with ~2.0.0 semver range")
|
||||
}
|
||||
if c2.MatchesAny(uv1) {
|
||||
t.Errorf("Union should have no overlap with ~2.0.0 semver range")
|
||||
}
|
||||
|
||||
if !uv1.MatchesAny(uv2) {
|
||||
t.Errorf("Union should succeed on MatchAny against other union with some overlap")
|
||||
}
|
||||
|
||||
// Intersect - repeat all previous
|
||||
if uv1.Intersect(v4) != v4 {
|
||||
t.Errorf("Union intersection on contained version should return that version")
|
||||
}
|
||||
if v4.Intersect(uv1) != v4 {
|
||||
t.Errorf("Union reverse-intersection on contained version should return that version")
|
||||
}
|
||||
|
||||
if uv1.Intersect(v3) != rev {
|
||||
t.Errorf("Union intersection on paired version w/matching rev should return rev, got %s", uv1.Intersect(v3))
|
||||
}
|
||||
if v3.Intersect(uv1) != rev {
|
||||
t.Errorf("Union reverse-intersection on paired version w/matching rev should return rev, got %s", v3.Intersect(uv1))
|
||||
}
|
||||
|
||||
if uv1.Intersect(v2) != none {
|
||||
t.Errorf("Union should not intersect with anything in disjoint unpaired")
|
||||
}
|
||||
if v2.Intersect(uv1) != none {
|
||||
t.Errorf("Union should not reverse-intersect with anything in disjoint unpaired")
|
||||
}
|
||||
|
||||
if uv1.Intersect(v5) != none {
|
||||
t.Errorf("Union should not intersect with anything in disjoint pair")
|
||||
}
|
||||
if v5.Intersect(uv1) != none {
|
||||
t.Errorf("Union should not reverse-intersect with anything in disjoint pair")
|
||||
}
|
||||
|
||||
if uv1.Intersect(c1) != v4 {
|
||||
t.Errorf("Union intersecting with semver range should return 1.0.1 version, got %s", uv1.Intersect(c1))
|
||||
}
|
||||
if c1.Intersect(uv1) != v4 {
|
||||
t.Errorf("Union reverse-intersecting with semver range should return 1.0.1 version, got %s", c1.Intersect(uv1))
|
||||
}
|
||||
|
||||
if uv1.Intersect(c2) != none {
|
||||
t.Errorf("Union intersecting with non-overlapping semver range should return none, got %s", uv1.Intersect(c2))
|
||||
}
|
||||
if c2.Intersect(uv1) != none {
|
||||
t.Errorf("Union reverse-intersecting with non-overlapping semver range should return none, got %s", uv1.Intersect(c2))
|
||||
}
|
||||
|
||||
if uv1.Intersect(uv2) != rev {
|
||||
t.Errorf("Unions should intersect down to rev, but got %s", uv1.Intersect(uv2))
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionUnionPanicOnType(t *testing.T) {
|
||||
// versionTypeUnions need to panic if Type() gets called
|
||||
defer func() {
|
||||
if err := recover(); err == nil {
|
||||
t.Error("versionTypeUnion did not panic on Type() call")
|
||||
}
|
||||
}()
|
||||
_ = versionTypeUnion{}.Type()
|
||||
}
|
||||
|
||||
func TestVersionUnionPanicOnString(t *testing.T) {
|
||||
// versionStringUnions need to panic if String() gets called
|
||||
defer func() {
|
||||
if err := recover(); err == nil {
|
||||
t.Error("versionStringUnion did not panic on String() call")
|
||||
}
|
||||
}()
|
||||
_ = versionTypeUnion{}.String()
|
||||
}
|
||||
|
||||
func TestTypedConstraintString(t *testing.T) {
|
||||
// Also tests typedVersionString(), as this nests down into that
|
||||
rev := Revision("flooboofoobooo")
|
||||
|
@ -944,8 +767,6 @@ func TestConstraintsIdentical(t *testing.T) {
|
|||
{Revision("test"), Revision("test"), true},
|
||||
{Revision("test"), Revision("test2"), false},
|
||||
{testSemverConstraint(t, "v2.10.7"), testSemverConstraint(t, "v2.10.7"), true},
|
||||
{versionTypeUnion{NewVersion("test"), NewBranch("branch")},
|
||||
versionTypeUnion{NewBranch("branch"), NewVersion("test")}, true},
|
||||
} {
|
||||
if test.eq != test.a.identical(test.b) {
|
||||
want := "identical"
|
||||
|
|
|
@ -80,7 +80,7 @@ func (s *solver) check(a atomWithPackages, pkgonly bool) error {
|
|||
// the constraints established by the current solution.
|
||||
func (s *solver) checkAtomAllowable(pa atom) error {
|
||||
constraint := s.sel.getConstraint(pa.id)
|
||||
if s.vUnify.matches(pa.id, constraint, pa.v) {
|
||||
if constraint.Matches(pa.v) {
|
||||
return nil
|
||||
}
|
||||
// TODO(sdboyer) collect constraint failure reason (wait...aren't we, below?)
|
||||
|
@ -88,7 +88,7 @@ func (s *solver) checkAtomAllowable(pa atom) error {
|
|||
deps := s.sel.getDependenciesOn(pa.id)
|
||||
var failparent []dependency
|
||||
for _, dep := range deps {
|
||||
if !s.vUnify.matches(pa.id, dep.dep.Constraint, pa.v) {
|
||||
if !dep.dep.Constraint.Matches(pa.v) {
|
||||
s.fail(dep.depender.id)
|
||||
failparent = append(failparent, dep)
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ func (s *solver) checkDepsConstraintsAllowable(a atomWithPackages, cdep complete
|
|||
constraint := s.sel.getConstraint(dep.Ident)
|
||||
// Ensure the constraint expressed by the dep has at least some possible
|
||||
// intersection with the intersection of existing constraints.
|
||||
if s.vUnify.matchesAny(dep.Ident, constraint, dep.Constraint) {
|
||||
if constraint.MatchesAny(dep.Constraint) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -159,7 +159,7 @@ func (s *solver) checkDepsConstraintsAllowable(a atomWithPackages, cdep complete
|
|||
var failsib []dependency
|
||||
var nofailsib []dependency
|
||||
for _, sibling := range siblings {
|
||||
if !s.vUnify.matchesAny(dep.Ident, sibling.dep.Constraint, dep.Constraint) {
|
||||
if !sibling.dep.Constraint.MatchesAny(dep.Constraint) {
|
||||
s.fail(sibling.depender.id)
|
||||
failsib = append(failsib, sibling)
|
||||
} else {
|
||||
|
@ -181,7 +181,7 @@ func (s *solver) checkDepsConstraintsAllowable(a atomWithPackages, cdep complete
|
|||
func (s *solver) checkDepsDisallowsSelected(a atomWithPackages, cdep completeDep) error {
|
||||
dep := cdep.workingConstraint
|
||||
selected, exists := s.sel.selected(dep.Ident)
|
||||
if exists && !s.vUnify.matches(dep.Ident, dep.Constraint, selected.a.v) {
|
||||
if exists && !dep.Constraint.Matches(selected.a.v) {
|
||||
s.fail(dep.Ident)
|
||||
|
||||
return &constraintNotAllowedFailure{
|
||||
|
|
|
@ -16,8 +16,6 @@ type selection struct {
|
|||
// ProjectRoots to the particular case variant that has currently been
|
||||
// selected.
|
||||
foldRoots map[string]ProjectRoot
|
||||
// The versoinUnifier in use for this solve run.
|
||||
vu *versionUnifier
|
||||
}
|
||||
|
||||
type selected struct {
|
||||
|
@ -159,7 +157,7 @@ func (s *selection) getConstraint(id ProjectIdentifier) Constraint {
|
|||
// Start with the open set
|
||||
var ret Constraint = any
|
||||
for _, dep := range deps {
|
||||
ret = s.vu.intersect(id, ret, dep.dep.Constraint)
|
||||
ret = ret.Intersect(dep.dep.Constraint)
|
||||
}
|
||||
|
||||
return ret
|
||||
|
|
|
@ -847,8 +847,8 @@ var basicFixtures = map[string]basicFixture{
|
|||
"foo 1.0.1 foorev", // mkrevlock drops the 1.0.1
|
||||
),
|
||||
r: mksolution(
|
||||
"foo 1.0.1 foorev",
|
||||
"bar 1.0.1",
|
||||
"foo 1.0.2",
|
||||
"bar 1.0.2",
|
||||
),
|
||||
},
|
||||
"lock to branch on old rev keeps old rev": {
|
||||
|
|
|
@ -127,10 +127,6 @@ type solver struct {
|
|||
// names a SourceManager operates on.
|
||||
b sourceBridge
|
||||
|
||||
// A versionUnifier, to facilitate cross-type version comparison and set
|
||||
// operations.
|
||||
vUnify *versionUnifier
|
||||
|
||||
// A stack containing projects and packages that are currently "selected" -
|
||||
// that is, they have passed all satisfiability checks, and are part of the
|
||||
// current solution.
|
||||
|
@ -305,15 +301,11 @@ func Prepare(params SolveParameters, sm SourceManager) (Solver, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.vUnify = &versionUnifier{
|
||||
b: s.b,
|
||||
}
|
||||
|
||||
// Initialize stacks and queues
|
||||
s.sel = &selection{
|
||||
deps: make(map[ProjectRoot][]dependency),
|
||||
foldRoots: make(map[string]ProjectRoot),
|
||||
vu: s.vUnify,
|
||||
}
|
||||
s.unsel = &unselected{
|
||||
sl: make([]bimodalIdentifier, 0),
|
||||
|
@ -447,7 +439,6 @@ func (s *solver) Solve(ctx context.Context) (Solution, error) {
|
|||
|
||||
// Set up a metrics object
|
||||
s.mtr = newMetrics()
|
||||
s.vUnify.mtr = s.mtr
|
||||
|
||||
// Prime the queues with the root project
|
||||
if err := s.selectRoot(); err != nil {
|
||||
|
@ -1007,35 +998,9 @@ func (s *solver) getLockVersionIfValid(id ProjectIdentifier) (Version, error) {
|
|||
constraint := s.sel.getConstraint(id)
|
||||
v := lp.Version()
|
||||
if !constraint.Matches(v) {
|
||||
var found bool
|
||||
if tv, ok := v.(Revision); ok {
|
||||
// If we only have a revision from the root's lock, allow matching
|
||||
// against other versions that have that revision
|
||||
for _, pv := range s.vUnify.pairRevision(id, tv) {
|
||||
if constraint.Matches(pv) {
|
||||
v = pv
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
//} else if _, ok := constraint.(Revision); ok {
|
||||
//// If the current constraint is itself a revision, and the lock gave
|
||||
//// an unpaired version, see if they match up
|
||||
////
|
||||
//if u, ok := v.(UnpairedVersion); ok {
|
||||
//pv := s.sm.pairVersion(id, u)
|
||||
//if constraint.Matches(pv) {
|
||||
//v = pv
|
||||
//found = true
|
||||
//}
|
||||
//}
|
||||
}
|
||||
|
||||
if !found {
|
||||
// No match found, which means we're going to be breaking the lock
|
||||
// Still return the invalid version so that is included in the trace
|
||||
s.b.breakLock()
|
||||
}
|
||||
// No match found, which means we're going to be breaking the lock
|
||||
// Still return the invalid version so that is included in the trace
|
||||
s.b.breakLock()
|
||||
}
|
||||
|
||||
return v, nil
|
||||
|
|
|
@ -140,8 +140,6 @@ func (r Revision) Type() VersionType {
|
|||
// version is the same Revision as itself.
|
||||
func (r Revision) Matches(v Version) bool {
|
||||
switch tv := v.(type) {
|
||||
case versionTypeUnion:
|
||||
return tv.Matches(r)
|
||||
case Revision:
|
||||
return r == tv
|
||||
case versionPair:
|
||||
|
@ -159,8 +157,6 @@ func (r Revision) MatchesAny(c Constraint) bool {
|
|||
return true
|
||||
case noneConstraint:
|
||||
return false
|
||||
case versionTypeUnion:
|
||||
return tc.MatchesAny(r)
|
||||
case Revision:
|
||||
return r == tc
|
||||
case versionPair:
|
||||
|
@ -179,8 +175,6 @@ func (r Revision) Intersect(c Constraint) Constraint {
|
|||
return r
|
||||
case noneConstraint:
|
||||
return none
|
||||
case versionTypeUnion:
|
||||
return tc.Intersect(r)
|
||||
case Revision:
|
||||
if r == tc {
|
||||
return r
|
||||
|
@ -230,8 +224,6 @@ func (v branchVersion) Type() VersionType {
|
|||
|
||||
func (v branchVersion) Matches(v2 Version) bool {
|
||||
switch tv := v2.(type) {
|
||||
case versionTypeUnion:
|
||||
return tv.Matches(v)
|
||||
case branchVersion:
|
||||
return v.name == tv.name
|
||||
case versionPair:
|
||||
|
@ -248,8 +240,6 @@ func (v branchVersion) MatchesAny(c Constraint) bool {
|
|||
return true
|
||||
case noneConstraint:
|
||||
return false
|
||||
case versionTypeUnion:
|
||||
return tc.MatchesAny(v)
|
||||
case branchVersion:
|
||||
return v.name == tc.name
|
||||
case versionPair:
|
||||
|
@ -267,8 +257,6 @@ func (v branchVersion) Intersect(c Constraint) Constraint {
|
|||
return v
|
||||
case noneConstraint:
|
||||
return none
|
||||
case versionTypeUnion:
|
||||
return tc.Intersect(v)
|
||||
case branchVersion:
|
||||
if v.name == tc.name {
|
||||
return v
|
||||
|
@ -328,8 +316,6 @@ func (v plainVersion) Type() VersionType {
|
|||
|
||||
func (v plainVersion) Matches(v2 Version) bool {
|
||||
switch tv := v2.(type) {
|
||||
case versionTypeUnion:
|
||||
return tv.Matches(v)
|
||||
case plainVersion:
|
||||
return v == tv
|
||||
case versionPair:
|
||||
|
@ -346,8 +332,6 @@ func (v plainVersion) MatchesAny(c Constraint) bool {
|
|||
return true
|
||||
case noneConstraint:
|
||||
return false
|
||||
case versionTypeUnion:
|
||||
return tc.MatchesAny(v)
|
||||
case plainVersion:
|
||||
return v == tc
|
||||
case versionPair:
|
||||
|
@ -365,8 +349,6 @@ func (v plainVersion) Intersect(c Constraint) Constraint {
|
|||
return v
|
||||
case noneConstraint:
|
||||
return none
|
||||
case versionTypeUnion:
|
||||
return tc.Intersect(v)
|
||||
case plainVersion:
|
||||
if v == tc {
|
||||
return v
|
||||
|
@ -428,8 +410,6 @@ func (v semVersion) Type() VersionType {
|
|||
|
||||
func (v semVersion) Matches(v2 Version) bool {
|
||||
switch tv := v2.(type) {
|
||||
case versionTypeUnion:
|
||||
return tv.Matches(v)
|
||||
case semVersion:
|
||||
return v.sv.Equal(tv.sv)
|
||||
case versionPair:
|
||||
|
@ -446,8 +426,6 @@ func (v semVersion) MatchesAny(c Constraint) bool {
|
|||
return true
|
||||
case noneConstraint:
|
||||
return false
|
||||
case versionTypeUnion:
|
||||
return tc.MatchesAny(v)
|
||||
case semVersion:
|
||||
return v.sv.Equal(tc.sv)
|
||||
case semverConstraint:
|
||||
|
@ -467,8 +445,6 @@ func (v semVersion) Intersect(c Constraint) Constraint {
|
|||
return v
|
||||
case noneConstraint:
|
||||
return none
|
||||
case versionTypeUnion:
|
||||
return tc.Intersect(v)
|
||||
case semVersion:
|
||||
if v.sv.Equal(tc.sv) {
|
||||
return v
|
||||
|
@ -537,8 +513,6 @@ func (v versionPair) Unpair() UnpairedVersion {
|
|||
|
||||
func (v versionPair) Matches(v2 Version) bool {
|
||||
switch tv2 := v2.(type) {
|
||||
case versionTypeUnion:
|
||||
return tv2.Matches(v)
|
||||
case versionPair:
|
||||
return v.r == tv2.r
|
||||
case Revision:
|
||||
|
@ -571,8 +545,6 @@ func (v versionPair) Intersect(c2 Constraint) Constraint {
|
|||
return v
|
||||
case noneConstraint:
|
||||
return none
|
||||
case versionTypeUnion:
|
||||
return tc.Intersect(v)
|
||||
case versionPair:
|
||||
if v.r == tc.r {
|
||||
return v.r
|
||||
|
|
|
@ -1,302 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gps
|
||||
|
||||
import "github.com/golang/dep/gps/internal/pb"
|
||||
|
||||
// versionUnifier facilitates cross-type version comparison and set operations.
|
||||
type versionUnifier struct {
|
||||
b sourceBridge
|
||||
mtr *metrics
|
||||
}
|
||||
|
||||
// pairVersion takes an UnpairedVersion and attempts to pair it with an
|
||||
// underlying Revision in the context of the provided ProjectIdentifier by
|
||||
// consulting the canonical version list.
|
||||
func (vu versionUnifier) pairVersion(id ProjectIdentifier, v UnpairedVersion) PairedVersion {
|
||||
vl, err := vu.b.listVersions(id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
vu.mtr.push("b-pair-version")
|
||||
// doing it like this is a bit sloppy
|
||||
for _, v2 := range vl {
|
||||
if p, ok := v2.(PairedVersion); ok {
|
||||
if p.Matches(v) {
|
||||
vu.mtr.pop()
|
||||
return p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vu.mtr.pop()
|
||||
return nil
|
||||
}
|
||||
|
||||
// pairRevision takes a Revision and attempts to pair it with all possible
|
||||
// versionsby consulting the canonical version list of the provided
|
||||
// ProjectIdentifier.
|
||||
func (vu versionUnifier) pairRevision(id ProjectIdentifier, r Revision) []Version {
|
||||
vl, err := vu.b.listVersions(id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
vu.mtr.push("b-pair-rev")
|
||||
p := []Version{r}
|
||||
// doing it like this is a bit sloppy
|
||||
for _, v2 := range vl {
|
||||
if pv, ok := v2.(PairedVersion); ok {
|
||||
if pv.Matches(r) {
|
||||
p = append(p, pv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vu.mtr.pop()
|
||||
return p
|
||||
}
|
||||
|
||||
// matches performs a typical match check between the provided version and
|
||||
// constraint. If that basic check fails and the provided version is incomplete
|
||||
// (e.g. an unpaired version or bare revision), it will attempt to gather more
|
||||
// information on one or the other and re-perform the comparison.
|
||||
func (vu versionUnifier) matches(id ProjectIdentifier, c Constraint, v Version) bool {
|
||||
if c.Matches(v) {
|
||||
return true
|
||||
}
|
||||
|
||||
vu.mtr.push("b-matches")
|
||||
// This approach is slightly wasteful, but just SO much less verbose, and
|
||||
// more easily understood.
|
||||
vtu := vu.createTypeUnion(id, v)
|
||||
|
||||
var uc Constraint
|
||||
if cv, ok := c.(Version); ok {
|
||||
uc = vu.createTypeUnion(id, cv)
|
||||
} else {
|
||||
uc = c
|
||||
}
|
||||
|
||||
vu.mtr.pop()
|
||||
return uc.Matches(vtu)
|
||||
}
|
||||
|
||||
// matchesAny is the authoritative version of Constraint.MatchesAny.
|
||||
func (vu versionUnifier) matchesAny(id ProjectIdentifier, c1, c2 Constraint) bool {
|
||||
if c1.MatchesAny(c2) {
|
||||
return true
|
||||
}
|
||||
|
||||
vu.mtr.push("b-matches-any")
|
||||
// This approach is slightly wasteful, but just SO much less verbose, and
|
||||
// more easily understood.
|
||||
var uc1, uc2 Constraint
|
||||
if v1, ok := c1.(Version); ok {
|
||||
uc1 = vu.createTypeUnion(id, v1)
|
||||
} else {
|
||||
uc1 = c1
|
||||
}
|
||||
|
||||
if v2, ok := c2.(Version); ok {
|
||||
uc2 = vu.createTypeUnion(id, v2)
|
||||
} else {
|
||||
uc2 = c2
|
||||
}
|
||||
|
||||
vu.mtr.pop()
|
||||
return uc1.MatchesAny(uc2)
|
||||
}
|
||||
|
||||
// intersect is the authoritative version of Constraint.Intersect.
|
||||
func (vu versionUnifier) intersect(id ProjectIdentifier, c1, c2 Constraint) Constraint {
|
||||
rc := c1.Intersect(c2)
|
||||
if rc != none {
|
||||
return rc
|
||||
}
|
||||
|
||||
vu.mtr.push("b-intersect")
|
||||
// This approach is slightly wasteful, but just SO much less verbose, and
|
||||
// more easily understood.
|
||||
var uc1, uc2 Constraint
|
||||
if v1, ok := c1.(Version); ok {
|
||||
uc1 = vu.createTypeUnion(id, v1)
|
||||
} else {
|
||||
uc1 = c1
|
||||
}
|
||||
|
||||
if v2, ok := c2.(Version); ok {
|
||||
uc2 = vu.createTypeUnion(id, v2)
|
||||
} else {
|
||||
uc2 = c2
|
||||
}
|
||||
|
||||
vu.mtr.pop()
|
||||
return uc1.Intersect(uc2)
|
||||
}
|
||||
|
||||
// createTypeUnion creates a versionTypeUnion for the provided version.
|
||||
//
|
||||
// This union may (and typically will) end up being nothing more than the single
|
||||
// input version, but creating a versionTypeUnion guarantees that 'local'
|
||||
// constraint checks (direct method calls) are authoritative.
|
||||
func (vu versionUnifier) createTypeUnion(id ProjectIdentifier, v Version) versionTypeUnion {
|
||||
switch tv := v.(type) {
|
||||
case Revision:
|
||||
return versionTypeUnion(vu.pairRevision(id, tv))
|
||||
case PairedVersion:
|
||||
return versionTypeUnion(vu.pairRevision(id, tv.Revision()))
|
||||
case UnpairedVersion:
|
||||
pv := vu.pairVersion(id, tv)
|
||||
if pv == nil {
|
||||
return versionTypeUnion{tv}
|
||||
}
|
||||
|
||||
return versionTypeUnion(vu.pairRevision(id, pv.Revision()))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// versionTypeUnion represents a set of versions that are, within the scope of
|
||||
// this solver run, equivalent.
|
||||
//
|
||||
// The simple case here is just a pair - a normal version plus its underlying
|
||||
// revision - but if a tag or branch point at the same rev, then we consider
|
||||
// them equivalent. Again, however, this equivalency is short-lived; it must be
|
||||
// re-assessed during every solver run.
|
||||
//
|
||||
// The union members are treated as being OR'd together: all constraint
|
||||
// operations attempt each member, and will take the most open/optimistic
|
||||
// answer.
|
||||
//
|
||||
// This technically does allow tags to match branches - something we otherwise
|
||||
// try hard to avoid - but because the original input constraint never actually
|
||||
// changes (and is never written out in the Solution), there's no harmful case
|
||||
// of a user suddenly riding a branch when they expected a fixed tag.
|
||||
type versionTypeUnion []Version
|
||||
|
||||
// This should generally not be called, but is required for the interface. If it
|
||||
// is called, we have a bigger problem (the type has escaped the solver); thus,
|
||||
// panic.
|
||||
func (vtu versionTypeUnion) String() string {
|
||||
panic("versionTypeUnion should never be turned into a string; it is solver internal-only")
|
||||
}
|
||||
|
||||
// This should generally not be called, but is required for the interface. If it
|
||||
// is called, we have a bigger problem (the type has escaped the solver); thus,
|
||||
// panic.
|
||||
func (vtu versionTypeUnion) ImpliedCaretString() string {
|
||||
panic("versionTypeUnion should never be turned into a string; it is solver internal-only")
|
||||
}
|
||||
|
||||
func (vtu versionTypeUnion) typedString() string {
|
||||
panic("versionTypeUnion should never be turned into a string; it is solver internal-only")
|
||||
}
|
||||
|
||||
// This should generally not be called, but is required for the interface. If it
|
||||
// is called, we have a bigger problem (the type has escaped the solver); thus,
|
||||
// panic.
|
||||
func (vtu versionTypeUnion) Type() VersionType {
|
||||
panic("versionTypeUnion should never need to answer a Type() call; it is solver internal-only")
|
||||
}
|
||||
|
||||
// Matches takes a version, and returns true if that version matches any version
|
||||
// contained in the union.
|
||||
//
|
||||
// This DOES allow tags to match branches, albeit indirectly through a revision.
|
||||
func (vtu versionTypeUnion) Matches(v Version) bool {
|
||||
vtu2, otherIs := v.(versionTypeUnion)
|
||||
|
||||
for _, v1 := range vtu {
|
||||
if otherIs {
|
||||
for _, v2 := range vtu2 {
|
||||
if v1.Matches(v2) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} else if v1.Matches(v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// MatchesAny returns true if any of the contained versions (which are also
|
||||
// constraints) in the union successfully MatchAny with the provided
|
||||
// constraint.
|
||||
func (vtu versionTypeUnion) MatchesAny(c Constraint) bool {
|
||||
vtu2, otherIs := c.(versionTypeUnion)
|
||||
|
||||
for _, v1 := range vtu {
|
||||
if otherIs {
|
||||
for _, v2 := range vtu2 {
|
||||
if v1.MatchesAny(v2) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} else if v1.MatchesAny(c) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Intersect takes a constraint, and attempts to intersect it with all the
|
||||
// versions contained in the union until one returns non-none. If that never
|
||||
// happens, then none is returned.
|
||||
//
|
||||
// In order to avoid weird version floating elsewhere in the solver, the union
|
||||
// always returns the input constraint. (This is probably obviously correct, but
|
||||
// is still worth noting.)
|
||||
func (vtu versionTypeUnion) Intersect(c Constraint) Constraint {
|
||||
vtu2, otherIs := c.(versionTypeUnion)
|
||||
|
||||
for _, v1 := range vtu {
|
||||
if otherIs {
|
||||
for _, v2 := range vtu2 {
|
||||
if rc := v1.Intersect(v2); rc != none {
|
||||
return rc
|
||||
}
|
||||
}
|
||||
} else if rc := v1.Intersect(c); rc != none {
|
||||
return rc
|
||||
}
|
||||
}
|
||||
|
||||
return none
|
||||
}
|
||||
|
||||
func (vtu versionTypeUnion) identical(c Constraint) bool {
|
||||
vtu2, ok := c.(versionTypeUnion)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if len(vtu) != len(vtu2) {
|
||||
return false
|
||||
}
|
||||
used := make([]bool, len(vtu))
|
||||
outter:
|
||||
for _, v := range vtu {
|
||||
for i, v2 := range vtu2 {
|
||||
if used[i] {
|
||||
continue
|
||||
}
|
||||
if v.identical(v2) {
|
||||
used[i] = true
|
||||
continue outter
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (vtu versionTypeUnion) copyTo(*pb.Constraint) {
|
||||
panic("versionTypeUnion should never be serialized; it is solver internal-only")
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gps
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/dep/gps/pkgtree"
|
||||
)
|
||||
|
||||
type lvFixBridge []Version
|
||||
|
||||
var lvfb1 lvFixBridge
|
||||
|
||||
func init() {
|
||||
rev1 := Revision("revision-one")
|
||||
rev2 := Revision("revision-two")
|
||||
rev3 := Revision("revision-three")
|
||||
|
||||
lvfb1 = lvFixBridge{
|
||||
NewBranch("master").Pair(rev1),
|
||||
NewBranch("test").Pair(rev2),
|
||||
NewVersion("1.0.0").Pair(rev1),
|
||||
NewVersion("1.0.1").Pair("other1"),
|
||||
NewVersion("v2.0.5").Pair(rev3),
|
||||
NewVersion("2.0.5.2").Pair(rev3),
|
||||
newDefaultBranch("unwrapped").Pair(rev3),
|
||||
NewVersion("20.0.5.2").Pair(rev1),
|
||||
NewVersion("v1.5.5-beta.4").Pair("other2"),
|
||||
NewVersion("v3.0.1-alpha.1").Pair(rev2),
|
||||
}
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) listVersions(ProjectIdentifier) ([]Version, error) {
|
||||
return lb, nil
|
||||
}
|
||||
|
||||
func TestCreateTyepUnion(t *testing.T) {
|
||||
vu := versionUnifier{
|
||||
b: lvfb1,
|
||||
mtr: newMetrics(),
|
||||
}
|
||||
|
||||
rev1 := Revision("revision-one")
|
||||
rev2 := Revision("revision-two")
|
||||
id := mkPI("irrelevant")
|
||||
|
||||
vtu := vu.createTypeUnion(id, rev1)
|
||||
if len(vtu) != 4 {
|
||||
t.Fatalf("wanted a type union with four elements, got %v: \n%#v", len(vtu), vtu)
|
||||
}
|
||||
|
||||
vtu = vu.createTypeUnion(id, NewBranch("master"))
|
||||
if len(vtu) != 4 {
|
||||
t.Fatalf("wanted a type union with four elements, got %v: \n%#v", len(vtu), vtu)
|
||||
}
|
||||
|
||||
vtu = vu.createTypeUnion(id, Revision("notexist"))
|
||||
if len(vtu) != 1 {
|
||||
t.Fatalf("wanted a type union with one elements, got %v: \n%#v", len(vtu), vtu)
|
||||
}
|
||||
|
||||
vtu = vu.createTypeUnion(id, rev2)
|
||||
if len(vtu) != 3 {
|
||||
t.Fatalf("wanted a type union with three elements, got %v: \n%#v", len(vtu), vtu)
|
||||
}
|
||||
|
||||
vtu = vu.createTypeUnion(id, nil)
|
||||
if vtu != nil {
|
||||
t.Fatalf("wanted a nil return on nil input, got %#v", vtu)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypeUnionIntersect(t *testing.T) {
|
||||
vu := versionUnifier{
|
||||
b: lvfb1,
|
||||
mtr: newMetrics(),
|
||||
}
|
||||
|
||||
rev1 := Revision("revision-one")
|
||||
rev2 := Revision("revision-two")
|
||||
rev3 := Revision("revision-three")
|
||||
id := mkPI("irrelevant")
|
||||
|
||||
c, _ := NewSemverConstraint("^2.0.0")
|
||||
gotc := vu.intersect(id, rev2, c)
|
||||
if gotc != none {
|
||||
t.Fatalf("wanted empty set from intersect, got %#v", gotc)
|
||||
}
|
||||
|
||||
gotc = vu.intersect(id, c, rev1)
|
||||
if gotc != none {
|
||||
t.Fatalf("wanted empty set from intersect, got %#v", gotc)
|
||||
}
|
||||
|
||||
gotc = vu.intersect(id, c, rev3)
|
||||
if gotc != NewVersion("v2.0.5").Pair(rev3) {
|
||||
t.Fatalf("wanted v2.0.5, got %s from intersect", gotc.typedString())
|
||||
}
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) SourceExists(ProjectIdentifier) (bool, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) SyncSourceFor(ProjectIdentifier) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) RevisionPresentIn(ProjectIdentifier, Revision) (bool, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) ListPackages(ProjectIdentifier, Version) (pkgtree.PackageTree, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) GetManifestAndLock(ProjectIdentifier, Version, ProjectAnalyzer) (Manifest, Lock, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) ExportProject(ProjectIdentifier, Version, string) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) DeduceProjectRoot(ip string) (ProjectRoot, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) verifyRootDir(path string) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) vendorCodeExists(ProjectIdentifier) (bool, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (lb lvFixBridge) breakLock() {
|
||||
panic("not implemented")
|
||||
}
|
Загрузка…
Ссылка в новой задаче