From d312e27e8b63371eece000cfc145f32432aff619 Mon Sep 17 00:00:00 2001 From: Ian Alexander Date: Wed, 8 Oct 2025 20:03:54 -0400 Subject: [PATCH] cmd/go: use local state object in pkg `modcmd` This commit modifies `modcmd.runDownload` to construct a new modload.State object using the new constructor instead of the current global `modload.LoaderState` variable. This commit is part of the overall effort to eliminate global modloader state. [git-generate] cd src/cmd/go/internal/modcmd rf ' add download.go:/func runDownload\(/-0 var moduleLoaderState *modload.State ex { import "cmd/go/internal/modload"; modload.LoaderState -> moduleLoaderState } add runDownload://+0 moduleLoaderState := modload.NewState() add runEdit://+0 moduleLoaderState := modload.NewState() add runGraph://+0 moduleLoaderState := modload.NewState() add runInit://+0 moduleLoaderState := modload.NewState() add runTidy://+0 moduleLoaderState := modload.NewState() add runVendor://+0 moduleLoaderState := modload.NewState() add runVerify://+0 moduleLoaderState := modload.NewState() add runWhy://+0 moduleLoaderState := modload.NewState() rm download.go:/var moduleLoaderState \*modload.State/ ' Change-Id: Id69deba173032a4d6da228eae28e38bd87176db5 Reviewed-on: https://go-review.googlesource.com/c/go/+/711125 Reviewed-by: Michael Matloob Reviewed-by: Michael Matloob LUCI-TryBot-Result: Go LUCI --- src/cmd/go/internal/modcmd/download.go | 41 +++++++++++++------------- src/cmd/go/internal/modcmd/edit.go | 3 +- src/cmd/go/internal/modcmd/graph.go | 11 +++---- src/cmd/go/internal/modcmd/init.go | 5 ++-- src/cmd/go/internal/modcmd/tidy.go | 11 +++---- src/cmd/go/internal/modcmd/vendor.go | 7 +++-- src/cmd/go/internal/modcmd/verify.go | 11 +++---- src/cmd/go/internal/modcmd/why.go | 15 +++++----- 8 files changed, 56 insertions(+), 48 deletions(-) diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index 1b2f850d1b..7544e221d5 100644 --- a/src/cmd/go/internal/modcmd/download.go +++ b/src/cmd/go/internal/modcmd/download.go @@ -109,18 +109,19 @@ type ModuleJSON struct { } func runDownload(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile(modload.LoaderState) + moduleLoaderState := modload.NewState() + modload.InitWorkfile(moduleLoaderState) // Check whether modules are enabled and whether we're in a module. - modload.LoaderState.ForceUseModules = true + moduleLoaderState.ForceUseModules = true modload.ExplicitWriteGoMod = true haveExplicitArgs := len(args) > 0 - if modload.HasModRoot(modload.LoaderState) || modload.WorkFilePath(modload.LoaderState) != "" { - modload.LoadModFile(modload.LoaderState, ctx) // to fill MainModules + if modload.HasModRoot(moduleLoaderState) || modload.WorkFilePath(moduleLoaderState) != "" { + modload.LoadModFile(moduleLoaderState, ctx) // to fill MainModules if haveExplicitArgs { - for _, mainModule := range modload.LoaderState.MainModules.Versions() { + for _, mainModule := range moduleLoaderState.MainModules.Versions() { targetAtUpgrade := mainModule.Path + "@upgrade" targetAtPatch := mainModule.Path + "@patch" for _, arg := range args { @@ -130,14 +131,14 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { } } } - } else if modload.WorkFilePath(modload.LoaderState) != "" { + } else if modload.WorkFilePath(moduleLoaderState) != "" { // TODO(#44435): Think about what the correct query is to download the // right set of modules. Also see code review comment at // https://go-review.googlesource.com/c/go/+/359794/comments/ce946a80_6cf53992. args = []string{"all"} } else { - mainModule := modload.LoaderState.MainModules.Versions()[0] - modFile := modload.LoaderState.MainModules.ModFile(mainModule) + mainModule := moduleLoaderState.MainModules.Versions()[0] + modFile := moduleLoaderState.MainModules.ModFile(mainModule) if modFile.Go == nil || gover.Compare(modFile.Go.Version, gover.ExplicitIndirectVersion) < 0 { if len(modFile.Require) > 0 { args = []string{"all"} @@ -153,12 +154,12 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // However, we also need to load the full module graph, to ensure that // we have downloaded enough of the module graph to run 'go list all', // 'go mod graph', and similar commands. - _, err := modload.LoadModGraph(modload.LoaderState, ctx, "") + _, err := modload.LoadModGraph(moduleLoaderState, ctx, "") if err != nil { // TODO(#64008): call base.Fatalf instead of toolchain.SwitchOrFatal // here, since we can only reach this point with an outdated toolchain // if the go.mod file is inconsistent. - toolchain.SwitchOrFatal(modload.LoaderState, ctx, err) + toolchain.SwitchOrFatal(moduleLoaderState, ctx, err) } for _, m := range modFile.Require { @@ -169,7 +170,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { } if len(args) == 0 { - if modload.HasModRoot(modload.LoaderState) { + if modload.HasModRoot(moduleLoaderState) { os.Stderr.WriteString("go: no module dependencies to download\n") } else { base.Errorf("go: no modules specified (see 'go help mod download')") @@ -177,14 +178,14 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { base.Exit() } - if *downloadReuse != "" && modload.HasModRoot(modload.LoaderState) { + if *downloadReuse != "" && modload.HasModRoot(moduleLoaderState) { base.Fatalf("go mod download -reuse cannot be used inside a module") } var mods []*ModuleJSON type token struct{} sem := make(chan token, runtime.GOMAXPROCS(0)) - infos, infosErr := modload.ListModules(modload.LoaderState, ctx, args, 0, *downloadReuse) + infos, infosErr := modload.ListModules(moduleLoaderState, ctx, args, 0, *downloadReuse) // There is a bit of a chicken-and-egg problem here: ideally we need to know // which Go version to switch to download the requested modules, but if we @@ -211,7 +212,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // toolchain version) or only one module (as is used by the Go Module Proxy). if infosErr != nil { - sw := toolchain.NewSwitcher(modload.LoaderState) + sw := toolchain.NewSwitcher(moduleLoaderState) sw.Error(infosErr) if sw.NeedSwitch() { sw.Switch(ctx) @@ -220,7 +221,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // when we can. } - if !haveExplicitArgs && modload.WorkFilePath(modload.LoaderState) == "" { + if !haveExplicitArgs && modload.WorkFilePath(moduleLoaderState) == "" { // 'go mod download' is sometimes run without arguments to pre-populate the // module cache. In modules that aren't at go 1.17 or higher, it may fetch // modules that aren't needed to build packages in the main module. This is @@ -231,7 +232,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // TODO(#64008): In the future, report an error if go.mod or go.sum need to // be updated after loading the build list. This may require setting // the mode to "mod" or "readonly" depending on haveExplicitArgs. - if err := modload.WriteGoMod(modload.LoaderState, ctx, modload.WriteOpts{}); err != nil { + if err := modload.WriteGoMod(moduleLoaderState, ctx, modload.WriteOpts{}); err != nil { base.Fatal(err) } } @@ -291,8 +292,8 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // with no arguments we download the module pattern "all", // which may include dependencies that are normally pruned out // of the individual modules in the workspace. - if haveExplicitArgs || modload.WorkFilePath(modload.LoaderState) != "" { - sw := toolchain.NewSwitcher(modload.LoaderState) + if haveExplicitArgs || modload.WorkFilePath(moduleLoaderState) != "" { + sw := toolchain.NewSwitcher(moduleLoaderState) // Add errors to the Switcher in deterministic order so that they will be // logged deterministically. for _, m := range mods { @@ -347,8 +348,8 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // // Don't save sums for 'go mod download' without arguments unless we're in // workspace mode; see comment above. - if haveExplicitArgs || modload.WorkFilePath(modload.LoaderState) != "" { - if err := modload.WriteGoMod(modload.LoaderState, ctx, modload.WriteOpts{}); err != nil { + if haveExplicitArgs || modload.WorkFilePath(moduleLoaderState) != "" { + if err := modload.WriteGoMod(moduleLoaderState, ctx, modload.WriteOpts{}); err != nil { base.Error(err) } } diff --git a/src/cmd/go/internal/modcmd/edit.go b/src/cmd/go/internal/modcmd/edit.go index d5774e98d7..2e0d1a6dd8 100644 --- a/src/cmd/go/internal/modcmd/edit.go +++ b/src/cmd/go/internal/modcmd/edit.go @@ -209,6 +209,7 @@ func init() { } func runEdit(ctx context.Context, cmd *base.Command, args []string) { + moduleLoaderState := modload.NewState() anyFlags := *editModule != "" || *editGo != "" || *editToolchain != "" || @@ -232,7 +233,7 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) { if len(args) == 1 { gomod = args[0] } else { - gomod = modload.ModFilePath(modload.LoaderState) + gomod = modload.ModFilePath(moduleLoaderState) } if *editModule != "" { diff --git a/src/cmd/go/internal/modcmd/graph.go b/src/cmd/go/internal/modcmd/graph.go index 2a1bad0e0e..467da99b22 100644 --- a/src/cmd/go/internal/modcmd/graph.go +++ b/src/cmd/go/internal/modcmd/graph.go @@ -52,23 +52,24 @@ func init() { } func runGraph(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile(modload.LoaderState) + moduleLoaderState := modload.NewState() + modload.InitWorkfile(moduleLoaderState) if len(args) > 0 { base.Fatalf("go: 'go mod graph' accepts no arguments") } - modload.LoaderState.ForceUseModules = true - modload.LoaderState.RootMode = modload.NeedRoot + moduleLoaderState.ForceUseModules = true + moduleLoaderState.RootMode = modload.NeedRoot goVersion := graphGo.String() if goVersion != "" && gover.Compare(gover.Local(), goVersion) < 0 { - toolchain.SwitchOrFatal(modload.LoaderState, ctx, &gover.TooNewError{ + toolchain.SwitchOrFatal(moduleLoaderState, ctx, &gover.TooNewError{ What: "-go flag", GoVersion: goVersion, }) } - mg, err := modload.LoadModGraph(modload.LoaderState, ctx, goVersion) + mg, err := modload.LoadModGraph(moduleLoaderState, ctx, goVersion) if err != nil { base.Fatal(err) } diff --git a/src/cmd/go/internal/modcmd/init.go b/src/cmd/go/internal/modcmd/init.go index 32eb5d06f9..e8db3d005f 100644 --- a/src/cmd/go/internal/modcmd/init.go +++ b/src/cmd/go/internal/modcmd/init.go @@ -35,6 +35,7 @@ func init() { } func runInit(ctx context.Context, cmd *base.Command, args []string) { + moduleLoaderState := modload.NewState() if len(args) > 1 { base.Fatalf("go: 'go mod init' accepts at most one argument") } @@ -43,6 +44,6 @@ func runInit(ctx context.Context, cmd *base.Command, args []string) { modPath = args[0] } - modload.LoaderState.ForceUseModules = true - modload.CreateModFile(modload.LoaderState, ctx, modPath) // does all the hard work + moduleLoaderState.ForceUseModules = true + modload.CreateModFile(moduleLoaderState, ctx, modPath) // does all the hard work } diff --git a/src/cmd/go/internal/modcmd/tidy.go b/src/cmd/go/internal/modcmd/tidy.go index fb66bbcda3..3ac0109625 100644 --- a/src/cmd/go/internal/modcmd/tidy.go +++ b/src/cmd/go/internal/modcmd/tidy.go @@ -105,6 +105,7 @@ func (f *goVersionFlag) Set(s string) error { } func runTidy(ctx context.Context, cmd *base.Command, args []string) { + moduleLoaderState := modload.NewState() if len(args) > 0 { base.Fatalf("go: 'go mod tidy' accepts no arguments") } @@ -119,18 +120,18 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) { // those packages. In order to make 'go test' reproducible for the packages // that are in 'all' but outside of the main module, we must explicitly // request that their test dependencies be included. - modload.LoaderState.ForceUseModules = true - modload.LoaderState.RootMode = modload.NeedRoot + moduleLoaderState.ForceUseModules = true + moduleLoaderState.RootMode = modload.NeedRoot goVersion := tidyGo.String() if goVersion != "" && gover.Compare(gover.Local(), goVersion) < 0 { - toolchain.SwitchOrFatal(modload.LoaderState, ctx, &gover.TooNewError{ + toolchain.SwitchOrFatal(moduleLoaderState, ctx, &gover.TooNewError{ What: "-go flag", GoVersion: goVersion, }) } - modload.LoadPackages(modload.LoaderState, ctx, modload.PackageOpts{ + modload.LoadPackages(moduleLoaderState, ctx, modload.PackageOpts{ TidyGoVersion: tidyGo.String(), Tags: imports.AnyTags(), Tidy: true, @@ -141,6 +142,6 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) { LoadTests: true, AllowErrors: tidyE, SilenceMissingStdImports: true, - Switcher: toolchain.NewSwitcher(modload.LoaderState), + Switcher: toolchain.NewSwitcher(moduleLoaderState), }, "all") } diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index f864d466bd..ef44ce41c0 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -66,11 +66,12 @@ func init() { } func runVendor(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile(modload.LoaderState) - if modload.WorkFilePath(modload.LoaderState) != "" { + moduleLoaderState := modload.NewState() + modload.InitWorkfile(moduleLoaderState) + if modload.WorkFilePath(moduleLoaderState) != "" { base.Fatalf("go: 'go mod vendor' cannot be run in workspace mode. Run 'go work vendor' to vendor the workspace or set 'GOWORK=off' to exit workspace mode.") } - RunVendor(modload.LoaderState, ctx, vendorE, vendorO, args) + RunVendor(moduleLoaderState, ctx, vendorE, vendorO, args) } func RunVendor(loaderstate *modload.State, ctx context.Context, vendorE bool, vendorO string, args []string) { diff --git a/src/cmd/go/internal/modcmd/verify.go b/src/cmd/go/internal/modcmd/verify.go index 358d7dd203..e40a05ed53 100644 --- a/src/cmd/go/internal/modcmd/verify.go +++ b/src/cmd/go/internal/modcmd/verify.go @@ -44,20 +44,21 @@ func init() { } func runVerify(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile(modload.LoaderState) + moduleLoaderState := modload.NewState() + modload.InitWorkfile(moduleLoaderState) if len(args) != 0 { // NOTE(rsc): Could take a module pattern. base.Fatalf("go: verify takes no arguments") } - modload.LoaderState.ForceUseModules = true - modload.LoaderState.RootMode = modload.NeedRoot + moduleLoaderState.ForceUseModules = true + moduleLoaderState.RootMode = modload.NeedRoot // Only verify up to GOMAXPROCS zips at once. type token struct{} sem := make(chan token, runtime.GOMAXPROCS(0)) - mg, err := modload.LoadModGraph(modload.LoaderState, ctx, "") + mg, err := modload.LoadModGraph(moduleLoaderState, ctx, "") if err != nil { base.Fatal(err) } @@ -71,7 +72,7 @@ func runVerify(ctx context.Context, cmd *base.Command, args []string) { errsChans[i] = errsc mod := mod // use a copy to avoid data races go func() { - errsc <- verifyMod(modload.LoaderState, ctx, mod) + errsc <- verifyMod(moduleLoaderState, ctx, mod) <-sem }() } diff --git a/src/cmd/go/internal/modcmd/why.go b/src/cmd/go/internal/modcmd/why.go index d0ec244465..407a19d5c2 100644 --- a/src/cmd/go/internal/modcmd/why.go +++ b/src/cmd/go/internal/modcmd/why.go @@ -63,9 +63,10 @@ func init() { } func runWhy(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile(modload.LoaderState) - modload.LoaderState.ForceUseModules = true - modload.LoaderState.RootMode = modload.NeedRoot + moduleLoaderState := modload.NewState() + modload.InitWorkfile(moduleLoaderState) + moduleLoaderState.ForceUseModules = true + moduleLoaderState.RootMode = modload.NeedRoot modload.ExplicitWriteGoMod = true // don't write go.mod in ListModules loadOpts := modload.PackageOpts{ @@ -83,13 +84,13 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) { } } - mods, err := modload.ListModules(modload.LoaderState, ctx, args, 0, "") + mods, err := modload.ListModules(moduleLoaderState, ctx, args, 0, "") if err != nil { base.Fatal(err) } byModule := make(map[string][]string) - _, pkgs := modload.LoadPackages(modload.LoaderState, ctx, loadOpts, "all") + _, pkgs := modload.LoadPackages(moduleLoaderState, ctx, loadOpts, "all") for _, path := range pkgs { m := modload.PackageModule(path) if m.Path != "" { @@ -120,9 +121,9 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) { } } else { // Resolve to packages. - matches, _ := modload.LoadPackages(modload.LoaderState, ctx, loadOpts, args...) + matches, _ := modload.LoadPackages(moduleLoaderState, ctx, loadOpts, args...) - modload.LoadPackages(modload.LoaderState, ctx, loadOpts, "all") // rebuild graph, from main module (not from named packages) + modload.LoadPackages(moduleLoaderState, ctx, loadOpts, "all") // rebuild graph, from main module (not from named packages) sep := "" for _, m := range matches { -- 2.52.0