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 {
if v1 != "" && semver.Compare(v1, v2) == -1 {
return v2
}
// 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) {
return buildList(target, reqs, nil)
}
// The final list is the minimum version of each module found in the graph.
if v := min[target.Path]; v != target.Version {
- // TODO(jayconrod): there is a special case in modload.mvsReqs.Max
- // that prevents us from selecting a newer version of a module
- // when the module has no version. This may only be the case for target.
- // Should we always panic when target has a version?
+ // target.Version will be "" for modload, the main client of MVS.
+ // "" denotes the main module, which has no version. However, MVS treats
+ // version strings as opaque, so "" is not a special value here.
// 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.
}