summaryrefslogtreecommitdiff
path: root/src/cmd/vendor/golang.org/x/mod/modfile/rule.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/vendor/golang.org/x/mod/modfile/rule.go')
-rw-r--r--src/cmd/vendor/golang.org/x/mod/modfile/rule.go26
1 files changed, 25 insertions, 1 deletions
diff --git a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go
index 6bcde8fabe..c20aef1566 100644
--- a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go
+++ b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go
@@ -1387,13 +1387,21 @@ func (f *File) DropRetract(vi VersionInterval) error {
func (f *File) SortBlocks() {
f.removeDups() // otherwise sorting is unsafe
+ // semanticSortForExcludeVersionV is the Go version (plus leading "v") at which
+ // lines in exclude blocks start to use semantic sort instead of lexicographic sort.
+ // See go.dev/issue/60028.
+ const semanticSortForExcludeVersionV = "v1.21"
+ useSemanticSortForExclude := f.Go != nil && semver.Compare("v"+f.Go.Version, semanticSortForExcludeVersionV) >= 0
+
for _, stmt := range f.Syntax.Stmt {
block, ok := stmt.(*LineBlock)
if !ok {
continue
}
less := lineLess
- if block.Token[0] == "retract" {
+ if block.Token[0] == "exclude" && useSemanticSortForExclude {
+ less = lineExcludeLess
+ } else if block.Token[0] == "retract" {
less = lineRetractLess
}
sort.SliceStable(block.Line, func(i, j int) bool {
@@ -1496,6 +1504,22 @@ func lineLess(li, lj *Line) bool {
return len(li.Token) < len(lj.Token)
}
+// lineExcludeLess reports whether li should be sorted before lj for lines in
+// an "exclude" block.
+func lineExcludeLess(li, lj *Line) bool {
+ if len(li.Token) != 2 || len(lj.Token) != 2 {
+ // Not a known exclude specification.
+ // Fall back to sorting lexicographically.
+ return lineLess(li, lj)
+ }
+ // An exclude specification has two tokens: ModulePath and Version.
+ // Compare module path by string order and version by semver rules.
+ if pi, pj := li.Token[0], lj.Token[0]; pi != pj {
+ return pi < pj
+ }
+ return semver.Compare(li.Token[1], lj.Token[1]) < 0
+}
+
// lineRetractLess returns whether li should be sorted before lj for lines in
// a "retract" block. It treats each line as a version interval. Single versions
// are compared as if they were intervals with the same low and high version.