mirror of
https://github.com/golang/go.git
synced 2026-06-27 03:11:23 +00:00
cmd/go: simplify go.mod to have at most two require sections
This change simplifies go.mod files to have at most two require blocks (one for direct and one for indirect dependencies) when the go version is 1.27 or higher. Fixes #56471. Change-Id: I71bb41511575d02697945eb0fab787391018e652 Reviewed-on: https://go-review.googlesource.com/c/go/+/739061 Reviewed-by: Michael Matloob <matloob@golang.org> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
parent
f3f3d0859a
commit
21e3cdefc3
6 changed files with 217 additions and 12 deletions
|
|
@ -6,7 +6,7 @@ require (
|
|||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83
|
||||
golang.org/x/arch v0.23.1-0.20260109160903-657d90bd6695
|
||||
golang.org/x/build v0.0.0-20260122183339-3ba88df37c64
|
||||
golang.org/x/mod v0.35.0
|
||||
golang.org/x/mod v0.36.1-0.20260513122029-343ee60345a1
|
||||
golang.org/x/sync v0.20.0
|
||||
golang.org/x/sys v0.44.0
|
||||
golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ golang.org/x/arch v0.23.1-0.20260109160903-657d90bd6695 h1:q45HsUyFzBjBk4mHGgUew
|
|||
golang.org/x/arch v0.23.1-0.20260109160903-657d90bd6695/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||
golang.org/x/build v0.0.0-20260122183339-3ba88df37c64 h1:BNhBATNmH/VtzGolB+ksQPPvn6ZyffiR8TmKenqNo+A=
|
||||
golang.org/x/build v0.0.0-20260122183339-3ba88df37c64/go.mod h1:3QmSbNil8ZWqC94m80Glej1v8b92gYzPIQPTtSa0c+4=
|
||||
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
|
||||
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
|
||||
golang.org/x/mod v0.36.1-0.20260513122029-343ee60345a1 h1:C0TwvxhsI0bHc1TbK4QEa5PCMrHiST7y/lpX4MVW3KM=
|
||||
golang.org/x/mod v0.36.1-0.20260513122029-343ee60345a1/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
||||
|
|
|
|||
|
|
@ -1989,8 +1989,10 @@ func UpdateGoModFromReqs(ld *Loader, ctx context.Context, opts WriteOpts) (befor
|
|||
// Update require blocks.
|
||||
if gover.Compare(goVersion, gover.SeparateIndirectVersion) < 0 {
|
||||
modFile.SetRequire(list)
|
||||
} else {
|
||||
} else if gover.Compare(goVersion, gover.SimplifyRequireVersion) < 0 {
|
||||
modFile.SetRequireSeparateIndirect(list)
|
||||
} else {
|
||||
modFile.SetRequireAtMostTwo(list)
|
||||
}
|
||||
modFile.Cleanup()
|
||||
after, err = modFile.Format()
|
||||
|
|
|
|||
155
src/cmd/go/testdata/script/mod_simplify_require.txt
vendored
Normal file
155
src/cmd/go/testdata/script/mod_simplify_require.txt
vendored
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
# If go.mod has go 1.27 or higher, multiple require blocks should be
|
||||
# consolidated. Even those with comments.
|
||||
|
||||
cp go.mod.127 go.mod
|
||||
go mod tidy
|
||||
cmp go.mod go.mod.127tidy
|
||||
|
||||
# If go.mod has go 1.26, blocks with comments should be preserved.
|
||||
cp go.mod.126 go.mod
|
||||
go mod tidy
|
||||
cmp go.mod go.mod.126tidy
|
||||
|
||||
-- go.mod.127 --
|
||||
module example.com/m
|
||||
|
||||
go 1.27
|
||||
|
||||
require example.com/a v1.0.0
|
||||
|
||||
// Block comment
|
||||
require (
|
||||
example.com/b v1.0.0
|
||||
)
|
||||
|
||||
// Another block comment
|
||||
require (
|
||||
example.com/d v1.0.0 // an inline comment
|
||||
example.com/c v1.0.0 // indirect
|
||||
)
|
||||
|
||||
// A third block comment
|
||||
require (
|
||||
example.com/e v1.0.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
example.com/a v1.0.0 => ./a
|
||||
example.com/b v1.0.0 => ./b
|
||||
example.com/c v1.0.0 => ./c
|
||||
example.com/d v1.0.0 => ./d
|
||||
example.com/e v1.0.0 => ./e
|
||||
)
|
||||
-- go.mod.127tidy --
|
||||
module example.com/m
|
||||
|
||||
go 1.27
|
||||
|
||||
// Block comment
|
||||
//
|
||||
// Another block comment
|
||||
require (
|
||||
example.com/a v1.0.0
|
||||
example.com/b v1.0.0
|
||||
example.com/d v1.0.0 // an inline comment
|
||||
)
|
||||
|
||||
// A third block comment
|
||||
require (
|
||||
example.com/c v1.0.0 // indirect
|
||||
example.com/e v1.0.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
example.com/a v1.0.0 => ./a
|
||||
example.com/b v1.0.0 => ./b
|
||||
example.com/c v1.0.0 => ./c
|
||||
example.com/d v1.0.0 => ./d
|
||||
example.com/e v1.0.0 => ./e
|
||||
)
|
||||
-- go.mod.126 --
|
||||
module example.com/m
|
||||
|
||||
go 1.26
|
||||
|
||||
require example.com/a v1.0.0
|
||||
|
||||
// Block comment
|
||||
require (
|
||||
example.com/b v1.0.0
|
||||
example.com/d v1.0.0
|
||||
)
|
||||
|
||||
require example.com/c v1.0.0 // indirect
|
||||
|
||||
replace (
|
||||
example.com/a v1.0.0 => ./a
|
||||
example.com/b v1.0.0 => ./b
|
||||
example.com/c v1.0.0 => ./c
|
||||
example.com/d v1.0.0 => ./d
|
||||
example.com/e v1.0.0 => ./e
|
||||
)
|
||||
-- go.mod.126tidy --
|
||||
module example.com/m
|
||||
|
||||
go 1.26
|
||||
|
||||
require example.com/a v1.0.0
|
||||
|
||||
// Block comment
|
||||
require (
|
||||
example.com/b v1.0.0
|
||||
example.com/d v1.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
example.com/c v1.0.0 // indirect
|
||||
example.com/e v1.0.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
example.com/a v1.0.0 => ./a
|
||||
example.com/b v1.0.0 => ./b
|
||||
example.com/c v1.0.0 => ./c
|
||||
example.com/d v1.0.0 => ./d
|
||||
example.com/e v1.0.0 => ./e
|
||||
)
|
||||
-- m.go --
|
||||
package m
|
||||
import _ "example.com/a"
|
||||
import _ "example.com/b"
|
||||
import _ "example.com/d"
|
||||
|
||||
-- a/go.mod --
|
||||
module example.com/a
|
||||
go 1.26
|
||||
require example.com/c v1.0.0
|
||||
require example.com/e v1.0.0
|
||||
-- a/a.go --
|
||||
package a
|
||||
import _ "example.com/c"
|
||||
import _ "example.com/e"
|
||||
|
||||
-- b/go.mod --
|
||||
module example.com/b
|
||||
go 1.26
|
||||
-- b/b.go --
|
||||
package b
|
||||
|
||||
-- c/go.mod --
|
||||
module example.com/c
|
||||
go 1.26
|
||||
-- c/c.go --
|
||||
package c
|
||||
|
||||
-- d/go.mod --
|
||||
module example.com/d
|
||||
go 1.26
|
||||
-- d/d.go --
|
||||
package d
|
||||
|
||||
-- e/go.mod --
|
||||
module example.com/e
|
||||
go 1.26
|
||||
-- e/e.go --
|
||||
package e
|
||||
62
src/cmd/vendor/golang.org/x/mod/modfile/rule.go
generated
vendored
62
src/cmd/vendor/golang.org/x/mod/modfile/rule.go
generated
vendored
|
|
@ -327,6 +327,7 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parse
|
|||
}
|
||||
|
||||
var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))?([a-z]+[0-9]+)?$`)
|
||||
|
||||
var laxGoVersionRE = lazyregexp.New(`^v?(([1-9][0-9]*)\.(0|[1-9][0-9]*))([^0-9].*)$`)
|
||||
|
||||
// Toolchains must be named beginning with `go1`,
|
||||
|
|
@ -1272,6 +1273,17 @@ func (f *File) SetRequire(req []*Require) {
|
|||
// SetRequireSeparateIndirect will split it into a direct-only and indirect-only
|
||||
// block. This aids in the transition to separate blocks.
|
||||
func (f *File) SetRequireSeparateIndirect(req []*Require) {
|
||||
f.setRequireSeparateIndirect(req, false)
|
||||
}
|
||||
|
||||
// SetRequireAtMostTwo is like SetRequireSeparateIndirect but it aggressively
|
||||
// consolidates all requirements into at most two blocks (one direct, one indirect).
|
||||
// It ignores existing blocks and comments when deciding where to place requirements.
|
||||
func (f *File) SetRequireAtMostTwo(req []*Require) {
|
||||
f.setRequireSeparateIndirect(req, true)
|
||||
}
|
||||
|
||||
func (f *File) setRequireSeparateIndirect(req []*Require, simplify bool) {
|
||||
// hasComments returns whether a line or block has comments
|
||||
// other than "indirect".
|
||||
hasComments := func(c Comments) bool {
|
||||
|
|
@ -1304,6 +1316,17 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
|
|||
}
|
||||
|
||||
// Examine existing require lines and blocks.
|
||||
need := make(map[string]*Require)
|
||||
for _, r := range req {
|
||||
need[r.Mod.Path] = r
|
||||
}
|
||||
lineIndirect := make(map[*Line]bool)
|
||||
for _, r := range f.Require {
|
||||
if n := need[r.Mod.Path]; n != nil {
|
||||
lineIndirect[r.Syntax] = n.Indirect
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
// We may insert new requirements into the last uncommented
|
||||
// direct-only and indirect-only blocks. We may also move requirements
|
||||
|
|
@ -1321,7 +1344,9 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
|
|||
|
||||
// Track the block each requirement belongs to (if any) so we can
|
||||
// move them later.
|
||||
lineToBlock = make(map[*Line]*LineBlock)
|
||||
lineToBlock = make(map[*Line]*LineBlock)
|
||||
directBlockComments []Comment
|
||||
indirectBlockComments []Comment
|
||||
)
|
||||
for i, stmt := range f.Syntax.Stmt {
|
||||
switch stmt := stmt.(type) {
|
||||
|
|
@ -1364,6 +1389,24 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
|
|||
if allIndirect {
|
||||
lastIndirectIndex = i
|
||||
}
|
||||
if simplify {
|
||||
anyDirect := false
|
||||
for _, line := range stmt.Line {
|
||||
if ind, ok := lineIndirect[line]; ok && !ind {
|
||||
anyDirect = true
|
||||
break
|
||||
}
|
||||
}
|
||||
target := &directBlockComments
|
||||
if !anyDirect && len(stmt.Line) > 0 {
|
||||
target = &indirectBlockComments
|
||||
}
|
||||
if len(*target) > 0 && len(stmt.Comments.Before) > 0 {
|
||||
*target = append(*target, Comment{Token: "//"})
|
||||
}
|
||||
*target = append(*target, stmt.Comments.Before...)
|
||||
stmt.Comments.Before = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1422,6 +1465,15 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
|
|||
lastIndirectBlock = ensureBlock(lastIndirectIndex)
|
||||
}
|
||||
|
||||
if simplify {
|
||||
if len(directBlockComments) > 0 {
|
||||
lastDirectBlock.Comments.Before = append(lastDirectBlock.Comments.Before, directBlockComments...)
|
||||
}
|
||||
if len(indirectBlockComments) > 0 {
|
||||
lastIndirectBlock.Comments.Before = append(lastIndirectBlock.Comments.Before, indirectBlockComments...)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete requirements we don't want anymore.
|
||||
// Update versions and indirect comments on requirements we want to keep.
|
||||
// If a requirement is in last{Direct,Indirect}Block with the wrong
|
||||
|
|
@ -1430,10 +1482,6 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
|
|||
// correct block.
|
||||
//
|
||||
// Some blocks may be empty after this. Cleanup will remove them.
|
||||
need := make(map[string]*Require)
|
||||
for _, r := range req {
|
||||
need[r.Mod.Path] = r
|
||||
}
|
||||
have := make(map[string]*Require)
|
||||
for _, r := range f.Require {
|
||||
path := r.Mod.Path
|
||||
|
|
@ -1446,10 +1494,10 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) {
|
|||
r.setVersion(need[path].Mod.Version)
|
||||
r.setIndirect(need[path].Indirect)
|
||||
if need[path].Indirect &&
|
||||
(oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastDirectBlock) {
|
||||
(simplify || oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastDirectBlock) {
|
||||
moveReq(r, lastIndirectBlock)
|
||||
} else if !need[path].Indirect &&
|
||||
(oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastIndirectBlock) {
|
||||
(simplify || oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastIndirectBlock) {
|
||||
moveReq(r, lastDirectBlock)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
src/cmd/vendor/modules.txt
vendored
2
src/cmd/vendor/modules.txt
vendored
|
|
@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm
|
|||
# golang.org/x/build v0.0.0-20260122183339-3ba88df37c64
|
||||
## explicit; go 1.24.9
|
||||
golang.org/x/build/relnote
|
||||
# golang.org/x/mod v0.35.0
|
||||
# golang.org/x/mod v0.36.1-0.20260513122029-343ee60345a1
|
||||
## explicit; go 1.25.0
|
||||
golang.org/x/mod/internal/lazyregexp
|
||||
golang.org/x/mod/modfile
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue