1
0
mirror of https://github.com/golang/go synced 2024-11-23 16:40:03 -07:00

cmd/go/internal/modload: document mvsReqs.Max

The version "" denotes the main module, which has no version. The
mvs.Reqs interface documentation hints this is allowed, but it's not
obvious from the implementation in modload.mvsReqs.Max.

Also, replace a related TODO with a comment in mvs.Downgrade.

Fixes #39042

Change-Id: I11e10908c9b3d8c2283eaa5c04bd8e1b936851fd
Reviewed-on: https://go-review.googlesource.com/c/go/+/234003
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Jay Conrod 2020-05-14 15:03:26 -04:00
parent f8662a5a96
commit 8be0de1e7e
2 changed files with 24 additions and 5 deletions

View File

@ -157,6 +157,12 @@ func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
return r.modFileToList(f), nil return r.modFileToList(f), nil
} }
// Max returns the maximum of v1 and v2 according to semver.Compare.
//
// As a special case, the version "" is considered higher than all other
// versions. The main module (also known as the target) has no version and must
// be chosen over other versions of the same module in the module dependency
// graph.
func (*mvsReqs) Max(v1, v2 string) string { func (*mvsReqs) Max(v1, v2 string) string {
if v1 != "" && semver.Compare(v1, v2) == -1 { if v1 != "" && semver.Compare(v1, v2) == -1 {
return v2 return v2

View File

@ -115,7 +115,21 @@ func (e *BuildListError) Error() string {
} }
// BuildList returns the build list for the target module. // BuildList returns the build list for the target module.
// The first element is the target itself, with the remainder of the list sorted by path. //
// target is the root vertex of a module requirement graph. For cmd/go, this is
// typically the main module, but note that this algorithm is not intended to
// be Go-specific: module paths and versions are treated as opaque values.
//
// reqs describes the module requirement graph and provides an opaque method
// for comparing versions.
//
// BuildList traverses the graph and returns a list containing the highest
// version for each visited module. The first element of the returned list is
// target itself; reqs.Max requires target.Version to compare higher than all
// other versions, so no other version can be selected. The remaining elements
// of the list are sorted by path.
//
// See https://research.swtch.com/vgo-mvs for details.
func BuildList(target module.Version, reqs Reqs) ([]module.Version, error) { func BuildList(target module.Version, reqs Reqs) ([]module.Version, error) {
return buildList(target, reqs, nil) return buildList(target, reqs, nil)
} }
@ -220,10 +234,9 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m
// The final list is the minimum version of each module found in the graph. // The final list is the minimum version of each module found in the graph.
if v := min[target.Path]; v != target.Version { if v := min[target.Path]; v != target.Version {
// TODO(jayconrod): there is a special case in modload.mvsReqs.Max // target.Version will be "" for modload, the main client of MVS.
// that prevents us from selecting a newer version of a module // "" denotes the main module, which has no version. However, MVS treats
// when the module has no version. This may only be the case for target. // version strings as opaque, so "" is not a special value here.
// Should we always panic when target has a version?
// See golang.org/issue/31491, golang.org/issue/29773. // See golang.org/issue/31491, golang.org/issue/29773.
panic(fmt.Sprintf("mistake: chose version %q instead of target %+v", v, target)) // TODO: Don't panic. panic(fmt.Sprintf("mistake: chose version %q instead of target %+v", v, target)) // TODO: Don't panic.
} }