Skip to content

Commit e7bea8f

Browse files
dmitshurgopherbot
authored andcommitted
modfile: use semantic sort for exclude blocks
For golang/go#60028. Change-Id: I4c7a726a900fc7c4b34816eba5cfd0361c45315f Reviewed-on: https://go-review.googlesource.com/c/mod/+/492990 Run-TryBot: Dmitri Shuralyov <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Auto-Submit: Dmitri Shuralyov <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Bryan Mills <[email protected]>
1 parent ad6fd61 commit e7bea8f

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

modfile/rule.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1387,13 +1387,21 @@ func (f *File) DropRetract(vi VersionInterval) error {
13871387
func (f *File) SortBlocks() {
13881388
f.removeDups() // otherwise sorting is unsafe
13891389

1390+
// semanticSortForExcludeVersionV is the Go version (plus leading "v") at which
1391+
// lines in exclude blocks start to use semantic sort instead of lexicographic sort.
1392+
// See go.dev/issue/60028.
1393+
const semanticSortForExcludeVersionV = "v1.21"
1394+
useSemanticSortForExclude := f.Go != nil && semver.Compare("v"+f.Go.Version, semanticSortForExcludeVersionV) >= 0
1395+
13901396
for _, stmt := range f.Syntax.Stmt {
13911397
block, ok := stmt.(*LineBlock)
13921398
if !ok {
13931399
continue
13941400
}
13951401
less := lineLess
1396-
if block.Token[0] == "retract" {
1402+
if block.Token[0] == "exclude" && useSemanticSortForExclude {
1403+
less = lineExcludeLess
1404+
} else if block.Token[0] == "retract" {
13971405
less = lineRetractLess
13981406
}
13991407
sort.SliceStable(block.Line, func(i, j int) bool {
@@ -1496,6 +1504,22 @@ func lineLess(li, lj *Line) bool {
14961504
return len(li.Token) < len(lj.Token)
14971505
}
14981506

1507+
// lineExcludeLess reports whether li should be sorted before lj for lines in
1508+
// an "exclude" block.
1509+
func lineExcludeLess(li, lj *Line) bool {
1510+
if len(li.Token) != 2 || len(lj.Token) != 2 {
1511+
// Not a known exclude specification.
1512+
// Fall back to sorting lexicographically.
1513+
return lineLess(li, lj)
1514+
}
1515+
// An exclude specification has two tokens: ModulePath and Version.
1516+
// Compare module path by string order and version by semver rules.
1517+
if pi, pj := li.Token[0], lj.Token[0]; pi != pj {
1518+
return pi < pj
1519+
}
1520+
return semver.Compare(li.Token[1], lj.Token[1]) < 0
1521+
}
1522+
14991523
// lineRetractLess returns whether li should be sorted before lj for lines in
15001524
// a "retract" block. It treats each line as a version interval. Single versions
15011525
// are compared as if they were intervals with the same low and high version.

modfile/rule_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,52 @@ var sortBlocksTests = []struct {
12241224
`,
12251225
false,
12261226
},
1227+
// Exclude blocks are sorted using semver in ascending order
1228+
// in go.mod files that opt in to Go version 1.21 or newer.
1229+
{
1230+
`sort_exclude_go121_semver`,
1231+
`module m
1232+
go 1.21
1233+
exclude (
1234+
b.example/m v0.9.0
1235+
a.example/m v1.0.0
1236+
b.example/m v0.10.0
1237+
c.example/m v1.1.0
1238+
b.example/m v0.11.0
1239+
)`,
1240+
`module m
1241+
go 1.21
1242+
exclude (
1243+
a.example/m v1.0.0
1244+
b.example/m v0.9.0
1245+
b.example/m v0.10.0
1246+
b.example/m v0.11.0
1247+
c.example/m v1.1.0
1248+
)
1249+
`,
1250+
true,
1251+
},
1252+
{
1253+
`sort_exclude_!go121_lexicographically`, // Maintain the previous (less featureful) behavior to avoid unnecessary churn.
1254+
`module m
1255+
exclude (
1256+
b.example/m v0.9.0
1257+
a.example/m v1.0.0
1258+
b.example/m v0.10.0
1259+
c.example/m v1.1.0
1260+
b.example/m v0.11.0
1261+
)`,
1262+
`module m
1263+
exclude (
1264+
a.example/m v1.0.0
1265+
b.example/m v0.10.0
1266+
b.example/m v0.11.0
1267+
b.example/m v0.9.0
1268+
c.example/m v1.1.0
1269+
)
1270+
`,
1271+
true,
1272+
},
12271273
}
12281274

12291275
var addRetractValidateVersionTests = []struct {

0 commit comments

Comments
 (0)