Skip to content

Commit d193adb

Browse files
authored
Merge pull request golang#210 from sdboyer/paired-lv
Convert ListVersions() to return []PairedVersion
2 parents df000f6 + 22be9f3 commit d193adb

14 files changed

+657
-412
lines changed

bridge.go

Lines changed: 18 additions & 261 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,29 @@ import (
99
"github.com/sdboyer/gps/pkgtree"
1010
)
1111

12-
// sourceBridges provide an adapter to SourceManagers that tailor operations
13-
// for a single solve run.
12+
// sourceBridge is an adapter to SourceManagers that tailor operations for a
13+
// single solve run.
1414
type sourceBridge interface {
1515
// sourceBridge includes all the methods in the SourceManager interface except
1616
// for Release().
1717
SourceExists(ProjectIdentifier) (bool, error)
1818
SyncSourceFor(ProjectIdentifier) error
19-
ListVersions(ProjectIdentifier) ([]Version, error)
2019
RevisionPresentIn(ProjectIdentifier, Revision) (bool, error)
2120
ListPackages(ProjectIdentifier, Version) (pkgtree.PackageTree, error)
2221
GetManifestAndLock(ProjectIdentifier, Version, ProjectAnalyzer) (Manifest, Lock, error)
2322
ExportProject(ProjectIdentifier, Version, string) error
2423
DeduceProjectRoot(ip string) (ProjectRoot, error)
2524

25+
//sourceExists(ProjectIdentifier) (bool, error)
26+
//syncSourceFor(ProjectIdentifier) error
27+
listVersions(ProjectIdentifier) ([]Version, error)
28+
//revisionPresentIn(ProjectIdentifier, Revision) (bool, error)
29+
//listPackages(ProjectIdentifier, Version) (pkgtree.PackageTree, error)
30+
//getManifestAndLock(ProjectIdentifier, Version, ProjectAnalyzer) (Manifest, Lock, error)
31+
//exportProject(ProjectIdentifier, Version, string) error
32+
//deduceProjectRoot(ip string) (ProjectRoot, error)
2633
verifyRootDir(path string) error
27-
pairRevision(id ProjectIdentifier, r Revision) []Version
28-
pairVersion(id ProjectIdentifier, v UnpairedVersion) PairedVersion
29-
vendorCodeExists(id ProjectIdentifier) (bool, error)
30-
matches(id ProjectIdentifier, c Constraint, v Version) bool
31-
matchesAny(id ProjectIdentifier, c1, c2 Constraint) bool
32-
intersect(id ProjectIdentifier, c1, c2 Constraint) Constraint
34+
vendorCodeExists(ProjectIdentifier) (bool, error)
3335
breakLock()
3436
}
3537

@@ -50,9 +52,6 @@ type bridge struct {
5052
// held by the solver that it ends up being easier and saner to do this.
5153
s *solver
5254

53-
// Whether to sort version lists for downgrade.
54-
down bool
55-
5655
// Simple, local cache of the root's PackageTree
5756
crp *struct {
5857
ptree pkgtree.PackageTree
@@ -62,11 +61,14 @@ type bridge struct {
6261
// Map of project root name to their available version list. This cache is
6362
// layered on top of the proper SourceManager's cache; the only difference
6463
// is that this keeps the versions sorted in the direction required by the
65-
// current solve run
64+
// current solve run.
6665
vlists map[ProjectIdentifier][]Version
6766

6867
// Indicates whether lock breaking has already been run
6968
lockbroken int32
69+
70+
// Whether to sort version lists for downgrade.
71+
down bool
7072
}
7173

7274
// Global factory func to create a bridge. This exists solely to allow tests to
@@ -91,19 +93,19 @@ func (b *bridge) GetManifestAndLock(id ProjectIdentifier, v Version, an ProjectA
9193
return m, l, e
9294
}
9395

94-
func (b *bridge) ListVersions(id ProjectIdentifier) ([]Version, error) {
96+
func (b *bridge) listVersions(id ProjectIdentifier) ([]Version, error) {
9597
if vl, exists := b.vlists[id]; exists {
9698
return vl, nil
9799
}
98100

99101
b.s.mtr.push("b-list-versions")
100-
vl, err := b.sm.ListVersions(id)
101-
// TODO(sdboyer) cache errors, too?
102+
pvl, err := b.sm.ListVersions(id)
102103
if err != nil {
103104
b.s.mtr.pop()
104105
return nil, err
105106
}
106107

108+
vl := hidePair(pvl)
107109
if b.down {
108110
SortForDowngrade(vl)
109111
} else {
@@ -140,149 +142,6 @@ func (b *bridge) vendorCodeExists(id ProjectIdentifier) (bool, error) {
140142
return false, nil
141143
}
142144

143-
func (b *bridge) pairVersion(id ProjectIdentifier, v UnpairedVersion) PairedVersion {
144-
vl, err := b.ListVersions(id)
145-
if err != nil {
146-
return nil
147-
}
148-
149-
b.s.mtr.push("b-pair-version")
150-
// doing it like this is a bit sloppy
151-
for _, v2 := range vl {
152-
if p, ok := v2.(PairedVersion); ok {
153-
if p.Matches(v) {
154-
b.s.mtr.pop()
155-
return p
156-
}
157-
}
158-
}
159-
160-
b.s.mtr.pop()
161-
return nil
162-
}
163-
164-
func (b *bridge) pairRevision(id ProjectIdentifier, r Revision) []Version {
165-
vl, err := b.ListVersions(id)
166-
if err != nil {
167-
return nil
168-
}
169-
170-
b.s.mtr.push("b-pair-rev")
171-
p := []Version{r}
172-
// doing it like this is a bit sloppy
173-
for _, v2 := range vl {
174-
if pv, ok := v2.(PairedVersion); ok {
175-
if pv.Matches(r) {
176-
p = append(p, pv)
177-
}
178-
}
179-
}
180-
181-
b.s.mtr.pop()
182-
return p
183-
}
184-
185-
// matches performs a typical match check between the provided version and
186-
// constraint. If that basic check fails and the provided version is incomplete
187-
// (e.g. an unpaired version or bare revision), it will attempt to gather more
188-
// information on one or the other and re-perform the comparison.
189-
func (b *bridge) matches(id ProjectIdentifier, c Constraint, v Version) bool {
190-
if c.Matches(v) {
191-
return true
192-
}
193-
194-
b.s.mtr.push("b-matches")
195-
// This approach is slightly wasteful, but just SO much less verbose, and
196-
// more easily understood.
197-
vtu := b.vtu(id, v)
198-
199-
var uc Constraint
200-
if cv, ok := c.(Version); ok {
201-
uc = b.vtu(id, cv)
202-
} else {
203-
uc = c
204-
}
205-
206-
b.s.mtr.pop()
207-
return uc.Matches(vtu)
208-
}
209-
210-
// matchesAny is the authoritative version of Constraint.MatchesAny.
211-
func (b *bridge) matchesAny(id ProjectIdentifier, c1, c2 Constraint) bool {
212-
if c1.MatchesAny(c2) {
213-
return true
214-
}
215-
216-
b.s.mtr.push("b-matches-any")
217-
// This approach is slightly wasteful, but just SO much less verbose, and
218-
// more easily understood.
219-
var uc1, uc2 Constraint
220-
if v1, ok := c1.(Version); ok {
221-
uc1 = b.vtu(id, v1)
222-
} else {
223-
uc1 = c1
224-
}
225-
226-
if v2, ok := c2.(Version); ok {
227-
uc2 = b.vtu(id, v2)
228-
} else {
229-
uc2 = c2
230-
}
231-
232-
b.s.mtr.pop()
233-
return uc1.MatchesAny(uc2)
234-
}
235-
236-
// intersect is the authoritative version of Constraint.Intersect.
237-
func (b *bridge) intersect(id ProjectIdentifier, c1, c2 Constraint) Constraint {
238-
rc := c1.Intersect(c2)
239-
if rc != none {
240-
return rc
241-
}
242-
243-
b.s.mtr.push("b-intersect")
244-
// This approach is slightly wasteful, but just SO much less verbose, and
245-
// more easily understood.
246-
var uc1, uc2 Constraint
247-
if v1, ok := c1.(Version); ok {
248-
uc1 = b.vtu(id, v1)
249-
} else {
250-
uc1 = c1
251-
}
252-
253-
if v2, ok := c2.(Version); ok {
254-
uc2 = b.vtu(id, v2)
255-
} else {
256-
uc2 = c2
257-
}
258-
259-
b.s.mtr.pop()
260-
return uc1.Intersect(uc2)
261-
}
262-
263-
// vtu creates a versionTypeUnion for the provided version.
264-
//
265-
// This union may (and typically will) end up being nothing more than the single
266-
// input version, but creating a versionTypeUnion guarantees that 'local'
267-
// constraint checks (direct method calls) are authoritative.
268-
func (b *bridge) vtu(id ProjectIdentifier, v Version) versionTypeUnion {
269-
switch tv := v.(type) {
270-
case Revision:
271-
return versionTypeUnion(b.pairRevision(id, tv))
272-
case PairedVersion:
273-
return versionTypeUnion(b.pairRevision(id, tv.Underlying()))
274-
case UnpairedVersion:
275-
pv := b.pairVersion(id, tv)
276-
if pv == nil {
277-
return versionTypeUnion{tv}
278-
}
279-
280-
return versionTypeUnion(b.pairRevision(id, pv.Underlying()))
281-
}
282-
283-
return nil
284-
}
285-
286145
// listPackages lists all the packages contained within the given project at a
287146
// particular version.
288147
//
@@ -358,105 +217,3 @@ func (b *bridge) SyncSourceFor(id ProjectIdentifier) error {
358217
// by the solver, and the metrics design is for wall time on a single thread
359218
return b.sm.SyncSourceFor(id)
360219
}
361-
362-
// versionTypeUnion represents a set of versions that are, within the scope of
363-
// this solver run, equivalent.
364-
//
365-
// The simple case here is just a pair - a normal version plus its underlying
366-
// revision - but if a tag or branch point at the same rev, then we consider
367-
// them equivalent. Again, however, this equivalency is short-lived; it must be
368-
// re-assessed during every solver run.
369-
//
370-
// The union members are treated as being OR'd together: all constraint
371-
// operations attempt each member, and will take the most open/optimistic
372-
// answer.
373-
//
374-
// This technically does allow tags to match branches - something we otherwise
375-
// try hard to avoid - but because the original input constraint never actually
376-
// changes (and is never written out in the Solution), there's no harmful case
377-
// of a user suddenly riding a branch when they expected a fixed tag.
378-
type versionTypeUnion []Version
379-
380-
// This should generally not be called, but is required for the interface. If it
381-
// is called, we have a bigger problem (the type has escaped the solver); thus,
382-
// panic.
383-
func (vtu versionTypeUnion) String() string {
384-
panic("versionTypeUnion should never be turned into a string; it is solver internal-only")
385-
}
386-
387-
// This should generally not be called, but is required for the interface. If it
388-
// is called, we have a bigger problem (the type has escaped the solver); thus,
389-
// panic.
390-
func (vtu versionTypeUnion) Type() VersionType {
391-
panic("versionTypeUnion should never need to answer a Type() call; it is solver internal-only")
392-
}
393-
394-
// Matches takes a version, and returns true if that version matches any version
395-
// contained in the union.
396-
//
397-
// This DOES allow tags to match branches, albeit indirectly through a revision.
398-
func (vtu versionTypeUnion) Matches(v Version) bool {
399-
vtu2, otherIs := v.(versionTypeUnion)
400-
401-
for _, v1 := range vtu {
402-
if otherIs {
403-
for _, v2 := range vtu2 {
404-
if v1.Matches(v2) {
405-
return true
406-
}
407-
}
408-
} else if v1.Matches(v) {
409-
return true
410-
}
411-
}
412-
413-
return false
414-
}
415-
416-
// MatchesAny returns true if any of the contained versions (which are also
417-
// constraints) in the union successfully MatchAny with the provided
418-
// constraint.
419-
func (vtu versionTypeUnion) MatchesAny(c Constraint) bool {
420-
vtu2, otherIs := c.(versionTypeUnion)
421-
422-
for _, v1 := range vtu {
423-
if otherIs {
424-
for _, v2 := range vtu2 {
425-
if v1.MatchesAny(v2) {
426-
return true
427-
}
428-
}
429-
} else if v1.MatchesAny(c) {
430-
return true
431-
}
432-
}
433-
434-
return false
435-
}
436-
437-
// Intersect takes a constraint, and attempts to intersect it with all the
438-
// versions contained in the union until one returns non-none. If that never
439-
// happens, then none is returned.
440-
//
441-
// In order to avoid weird version floating elsewhere in the solver, the union
442-
// always returns the input constraint. (This is probably obviously correct, but
443-
// is still worth noting.)
444-
func (vtu versionTypeUnion) Intersect(c Constraint) Constraint {
445-
vtu2, otherIs := c.(versionTypeUnion)
446-
447-
for _, v1 := range vtu {
448-
if otherIs {
449-
for _, v2 := range vtu2 {
450-
if rc := v1.Intersect(v2); rc != none {
451-
return rc
452-
}
453-
}
454-
} else if rc := v1.Intersect(c); rc != none {
455-
return rc
456-
}
457-
}
458-
459-
return none
460-
}
461-
462-
func (vtu versionTypeUnion) _private() {}

0 commit comments

Comments
 (0)