mirror of
https://github.com/golang/go.git
synced 2026-06-28 03:40:37 +00:00
cmd/go: loosen go work sync version requirements
In go work sync, we may resolve lower versions of modules for the workspace than what we would in an individual module because replace directives in the workspace can hide requirements that would bump versions up. If we try to force those versions for each module we'll run into a conflict. Instead, make the new requirements additive so it only bumps the versions up. We still have the issue that we originally resolve the modules using the workspace's replaces but later apply the requirements using the modules, but that's unavoidable so we just have to work around it. The important thing is that we now don't throw away the error and silently avoid changing the go.mod file. Additionally, in the case there are errors, we'll check for them ahead of time and only write out the synced go.mod files if there were no errors. Fixes #65363 Change-Id: I25bd98719eb5de0530d50eba3ccf4b2a6a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/762602 Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Michael Matloob <matloob@google.com> TryBot-Bypass: Michael Matloob <matloob@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
parent
a221442229
commit
8191cd8868
4 changed files with 115 additions and 17 deletions
|
|
@ -59,7 +59,7 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
|
|||
if err != nil {
|
||||
toolchain.SwitchOrFatal(moduleLoader, ctx, err)
|
||||
}
|
||||
mustSelectFor := map[module.Version][]module.Version{}
|
||||
addFor := map[module.Version][]module.Version{}
|
||||
|
||||
mms := moduleLoader.MainModules
|
||||
|
||||
|
|
@ -78,22 +78,23 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
|
|||
opts.MainModule = module.Version{} // reset
|
||||
|
||||
var (
|
||||
mustSelect []module.Version
|
||||
inMustSelect = map[module.Version]bool{}
|
||||
addReq []module.Version
|
||||
inAddReq = map[module.Version]bool{}
|
||||
)
|
||||
for _, pkg := range pkgs {
|
||||
if r := moduleLoader.PackageModule(pkg); r.Version != "" && !inMustSelect[r] {
|
||||
if r := moduleLoader.PackageModule(pkg); r.Version != "" && !inAddReq[r] {
|
||||
// r has a known version, so force that version.
|
||||
mustSelect = append(mustSelect, r)
|
||||
inMustSelect[r] = true
|
||||
addReq = append(addReq, r)
|
||||
inAddReq[r] = true
|
||||
}
|
||||
}
|
||||
gover.ModSort(mustSelect) // ensure determinism
|
||||
mustSelectFor[m] = mustSelect
|
||||
gover.ModSort(addReq) // ensure determinism
|
||||
addFor[m] = addReq
|
||||
}
|
||||
|
||||
workFilePath := modload.WorkFilePath(moduleLoader) // save go.work path because EnterModule clobbers it.
|
||||
workFilePath := modload.WorkFilePath(moduleLoader)
|
||||
|
||||
var loaders []*modload.Loader
|
||||
var goV string
|
||||
for _, m := range mms.Versions() {
|
||||
if mms.ModRoot(m) == "" && m.Path == "command-line-arguments" {
|
||||
|
|
@ -103,9 +104,9 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
|
|||
continue
|
||||
}
|
||||
|
||||
// Use EnterModule to reset the global state in modload to be in
|
||||
// single-module mode using the modroot of m.
|
||||
modload.EnterModule(moduleLoader, ctx, mms.ModRoot(m))
|
||||
// Use EnterModule to make a loader with a single work module.
|
||||
loader := modload.NewLoader()
|
||||
modload.EnterModule(loader, ctx, mms.ModRoot(m))
|
||||
|
||||
// Edit the build list in the same way that 'go get' would if we
|
||||
// requested the relevant module versions explicitly.
|
||||
|
|
@ -115,12 +116,12 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
|
|||
// so we don't write some go.mods with the "before" toolchain
|
||||
// and others with the "after" toolchain. If nothing else, that
|
||||
// discrepancy could show up in auto-recorded toolchain lines.
|
||||
changed, err := modload.EditBuildList(moduleLoader, ctx, nil, mustSelectFor[m])
|
||||
changed, err := modload.EditBuildList(loader, ctx, addFor[m], nil)
|
||||
if err != nil {
|
||||
continue
|
||||
base.Fatal(err)
|
||||
}
|
||||
if changed {
|
||||
modload.LoadPackages(moduleLoader, ctx, modload.PackageOpts{
|
||||
modload.LoadPackages(loader, ctx, modload.PackageOpts{
|
||||
Tags: imports.AnyTags(),
|
||||
Tidy: true,
|
||||
VendorModulesInGOROOTSrc: true,
|
||||
|
|
@ -130,9 +131,17 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
|
|||
SilenceMissingStdImports: true,
|
||||
SilencePackageErrors: true,
|
||||
}, "all")
|
||||
modload.WriteGoMod(moduleLoader, ctx, modload.WriteOpts{})
|
||||
// Run UpdateGoModFromReqs before we run WriteGoMod so we can catch errors in it early.
|
||||
if _, _, _, err := modload.UpdateGoModFromReqs(loader, ctx, modload.WriteOpts{}); err != nil {
|
||||
base.Fatal(err)
|
||||
}
|
||||
loaders = append(loaders, loader)
|
||||
}
|
||||
goV = gover.Max(goV, moduleLoader.MainModules.GoVersion(moduleLoader))
|
||||
goV = gover.Max(goV, loader.MainModules.GoVersion(loader))
|
||||
}
|
||||
base.ExitIfErrors()
|
||||
for _, loader := range loaders {
|
||||
modload.WriteGoMod(loader, ctx, modload.WriteOpts{})
|
||||
}
|
||||
|
||||
wf, err := modload.ReadWorkFile(workFilePath)
|
||||
|
|
|
|||
12
src/cmd/go/testdata/mod/example.com_syncreplace_v1.0.0.txt
vendored
Normal file
12
src/cmd/go/testdata/mod/example.com_syncreplace_v1.0.0.txt
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
-- .mod --
|
||||
module example.com/syncreplace
|
||||
|
||||
go 1.27
|
||||
|
||||
require rsc.io/quote v1.0.0
|
||||
-- syncreplace.go --
|
||||
package syncreplace
|
||||
|
||||
import _ "rsc.io/quote"
|
||||
-- .info --
|
||||
{"Version":"v1.0.0"}
|
||||
12
src/cmd/go/testdata/mod/example.com_syncreplace_v1.1.0.txt
vendored
Normal file
12
src/cmd/go/testdata/mod/example.com_syncreplace_v1.1.0.txt
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
-- .mod --
|
||||
module example.com/syncreplace
|
||||
|
||||
go 1.27
|
||||
|
||||
require rsc.io/quote v1.1.0
|
||||
-- syncreplace.go --
|
||||
package syncreplace
|
||||
|
||||
import _ "rsc.io/quote"
|
||||
-- .info --
|
||||
{"Version":"v1.1.0"}
|
||||
65
src/cmd/go/testdata/script/work_sync_replace.txt
vendored
Normal file
65
src/cmd/go/testdata/script/work_sync_replace.txt
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
go work sync
|
||||
|
||||
cmp a/go.mod a/go.mod.want
|
||||
cmp b/go.mod b/go.mod.want
|
||||
-- go.work --
|
||||
go 1.27
|
||||
|
||||
use (
|
||||
./a
|
||||
./b
|
||||
)
|
||||
-- a/go.mod --
|
||||
module example.com/a
|
||||
|
||||
go 1.27
|
||||
|
||||
replace example.com/syncreplace v1.1.0 => example.com/syncreplace v1.0.0
|
||||
|
||||
require (
|
||||
example.com/syncreplace v1.1.0
|
||||
rsc.io/quote v1.0.0
|
||||
)
|
||||
-- a/go.mod.want --
|
||||
module example.com/a
|
||||
|
||||
go 1.27
|
||||
|
||||
replace example.com/syncreplace v1.1.0 => example.com/syncreplace v1.0.0
|
||||
|
||||
require (
|
||||
example.com/syncreplace v1.1.0
|
||||
rsc.io/quote v1.0.0
|
||||
)
|
||||
-- a/a.go --
|
||||
package a
|
||||
|
||||
import (
|
||||
_ "example.com/syncreplace"
|
||||
_ "rsc.io/quote"
|
||||
)
|
||||
-- b/go.mod --
|
||||
module example.com/b
|
||||
|
||||
go 1.27
|
||||
|
||||
require (
|
||||
example.com/syncreplace v1.1.0
|
||||
rsc.io/quote v1.0.0
|
||||
)
|
||||
-- b/go.mod.want --
|
||||
module example.com/b
|
||||
|
||||
go 1.27
|
||||
|
||||
require (
|
||||
example.com/syncreplace v1.1.0
|
||||
rsc.io/quote v1.1.0
|
||||
)
|
||||
-- b/b.go --
|
||||
package b
|
||||
|
||||
import (
|
||||
_ "example.com/syncreplace"
|
||||
_ "rsc.io/quote"
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue