From: Ian Alexander Date: Thu, 21 Aug 2025 01:59:08 +0000 (-0400) Subject: cmd/go: inject State parameter into `run.runRun` X-Git-Tag: go1.26rc1~614 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=5b29875c8e;p=gostls13.git cmd/go: inject State parameter into `run.runRun` This command modifies the call tree starting at `run.runRun` to inject a `State` parameter to every function that is currently using the global `modload.LoaderState` variable. By explicilty passing a `State` parameter, we can begin to eliminate the usage of the global `modload.LoaderState`. This commit is part of the overall effort to eliminate global modloader state. [git-generate] cd src/cmd/go/internal/run rf 'inject modload.LoaderState runRun' cd .. ./rf-cleanup.zsh Change-Id: I337323c087ed4e43af28973fad27152791eefbc2 Reviewed-on: https://go-review.googlesource.com/c/go/+/698063 TryBot-Bypass: Ian Alexander Reviewed-by: Michael Matloob Reviewed-by: Michael Matloob --- diff --git a/src/cmd/go/internal/bug/bug.go b/src/cmd/go/internal/bug/bug.go index 4ff45d2d88..4e9ae1e9b4 100644 --- a/src/cmd/go/internal/bug/bug.go +++ b/src/cmd/go/internal/bug/bug.go @@ -21,6 +21,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/envcmd" + "cmd/go/internal/modload" "cmd/go/internal/web" "cmd/go/internal/work" ) @@ -44,7 +45,7 @@ func runBug(ctx context.Context, cmd *base.Command, args []string) { if len(args) > 0 { base.Fatalf("go: bug takes no arguments") } - work.BuildInit() + work.BuildInit(modload.LoaderState) var buf strings.Builder buf.WriteString(bugHeader) diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go index c6f311e026..1c05977de5 100644 --- a/src/cmd/go/internal/clean/clean.go +++ b/src/cmd/go/internal/clean/clean.go @@ -120,7 +120,7 @@ func init() { } func runClean(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() + modload.InitWorkfile(modload.LoaderState) if len(args) > 0 { cacheFlag := "" switch { @@ -142,13 +142,13 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) { // either the flags and arguments explicitly imply a package, // or no other target (such as a cache) was requested to be cleaned. cleanPkg := len(args) > 0 || cleanI || cleanR - if (!modload.Enabled() || modload.HasModRoot()) && + if (!modload.Enabled(modload.LoaderState) || modload.HasModRoot(modload.LoaderState)) && !cleanCache && !cleanModcache && !cleanTestcache && !cleanFuzzcache { cleanPkg = true } if cleanPkg { - for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) { + for _, pkg := range load.PackagesAndErrors(modload.LoaderState, ctx, load.PackageOpts{}, args) { clean(pkg) } } diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 6ad6954dd5..13708ae170 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -191,14 +191,14 @@ func findEnv(env []cfg.EnvVar, name string) string { // ExtraEnvVars returns environment variables that should not leak into child processes. func ExtraEnvVars() []cfg.EnvVar { gomod := "" - modload.Init() - if modload.HasModRoot() { + modload.Init(modload.LoaderState) + if modload.HasModRoot(modload.LoaderState) { gomod = modload.ModFilePath() - } else if modload.Enabled() { + } else if modload.Enabled(modload.LoaderState) { gomod = os.DevNull } - modload.InitWorkfile() - gowork := modload.WorkFilePath() + modload.InitWorkfile(modload.LoaderState) + gowork := modload.WorkFilePath(modload.LoaderState) // As a special case, if a user set off explicitly, report that in GOWORK. if cfg.Getenv("GOWORK") == "off" { gowork = "off" @@ -336,7 +336,7 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) { } } if needCostly { - work.BuildInit() + work.BuildInit(modload.LoaderState) env = append(env, ExtraEnvVarsCostly()...) } diff --git a/src/cmd/go/internal/fmtcmd/fmt.go b/src/cmd/go/internal/fmtcmd/fmt.go index 83fba9661a..a42e775305 100644 --- a/src/cmd/go/internal/fmtcmd/fmt.go +++ b/src/cmd/go/internal/fmtcmd/fmt.go @@ -59,8 +59,8 @@ func runFmt(ctx context.Context, cmd *base.Command, args []string) { baseGofmtArgs := len(gofmtArgs) baseGofmtArgLen := gofmtArgLen - for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) { - if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main { + for _, pkg := range load.PackagesAndErrors(modload.LoaderState, ctx, load.PackageOpts{}, args) { + if modload.Enabled(modload.LoaderState) && pkg.Module != nil && !pkg.Module.Main { if !printed { fmt.Fprintf(os.Stderr, "go: not formatting packages in dependency modules\n") printed = true @@ -70,7 +70,7 @@ func runFmt(ctx context.Context, cmd *base.Command, args []string) { if pkg.Error != nil { if _, ok := errors.AsType[*load.NoGoError](pkg.Error); ok { // Skip this error, as we will format all files regardless. - } else if _, ok := errors.AsType[*load.EmbedError](pkg.Error); ok && len(pkg.InternalAllGoFiles()) > 0 { + } else if _, ok := errors.AsType[*load.EmbedError](pkg.Error); ok && len(pkg.InternalAllGoFiles()) > 0 { // Skip this error, as we will format all files regardless. } else { base.Errorf("%v", pkg.Error) diff --git a/src/cmd/go/internal/generate/generate.go b/src/cmd/go/internal/generate/generate.go index 0f4b4a972e..4250916b8d 100644 --- a/src/cmd/go/internal/generate/generate.go +++ b/src/cmd/go/internal/generate/generate.go @@ -182,7 +182,7 @@ func init() { } func runGenerate(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() + modload.InitWorkfile(modload.LoaderState) if generateRunFlag != "" { var err error @@ -204,8 +204,8 @@ func runGenerate(ctx context.Context, cmd *base.Command, args []string) { // Even if the arguments are .go files, this loop suffices. printed := false pkgOpts := load.PackageOpts{IgnoreImports: true} - for _, pkg := range load.PackagesAndErrors(ctx, pkgOpts, args) { - if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main { + for _, pkg := range load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, args) { + if modload.Enabled(modload.LoaderState) && pkg.Module != nil && !pkg.Module.Main { if !printed { fmt.Fprintf(os.Stderr, "go: not generating in packages in dependency modules\n") printed = true diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index bee7dc8053..0bf86ae004 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -419,7 +419,7 @@ func (v *jsonFlag) needAny(fields ...string) bool { var nl = []byte{'\n'} func runList(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() + modload.InitWorkfile(modload.LoaderState) if *listFmt != "" && listJson { base.Fatalf("go list -f cannot be used with -json") @@ -427,11 +427,11 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { if *listReuse != "" && !*listM { base.Fatalf("go list -reuse cannot be used without -m") } - if *listReuse != "" && modload.HasModRoot() { + if *listReuse != "" && modload.HasModRoot(modload.LoaderState) { base.Fatalf("go list -reuse cannot be used inside a module") } - work.BuildInit() + work.BuildInit(modload.LoaderState) out := newTrackingWriter(os.Stdout) defer out.w.Flush() @@ -496,12 +496,12 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { } } - modload.Init() + modload.Init(modload.LoaderState) if *listRetracted { if cfg.BuildMod == "vendor" { base.Fatalf("go list -retracted cannot be used when vendoring is enabled") } - if !modload.Enabled() { + if !modload.Enabled(modload.LoaderState) { base.Fatalf("go list -retracted can only be used in module-aware mode") } } @@ -525,11 +525,11 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("go list -test cannot be used with -m") } - if modload.Init(); !modload.Enabled() { + if modload.Init(modload.LoaderState); !modload.Enabled(modload.LoaderState) { base.Fatalf("go: list -m cannot be used with GO111MODULE=off") } - modload.LoadModFile(ctx) // Sets cfg.BuildMod as a side-effect. + modload.LoadModFile(modload.LoaderState, ctx) // Sets cfg.BuildMod as a side-effect. if cfg.BuildMod == "vendor" { const actionDisabledFormat = "go: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)" @@ -613,7 +613,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { SuppressBuildInfo: !*listExport && !listJsonFields.needAny("Stale", "StaleReason"), SuppressEmbedFiles: !*listExport && !listJsonFields.needAny("EmbedFiles", "TestEmbedFiles", "XTestEmbedFiles"), } - pkgs := load.PackagesAndErrors(ctx, pkgOpts, args) + pkgs := load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, args) if !*listE { w := 0 for _, pkg := range pkgs { @@ -727,7 +727,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { b.NeedExport = *listExport b.NeedCompiledGoFiles = *listCompiled if cfg.BuildCover { - load.PrepareForCoverageBuild(pkgs) + load.PrepareForCoverageBuild(modload.LoaderState, pkgs) } a := &work.Action{} // TODO: Use pkgsFilter? diff --git a/src/cmd/go/internal/load/flag.go b/src/cmd/go/internal/load/flag.go index 55bdab0135..86a922bc10 100644 --- a/src/cmd/go/internal/load/flag.go +++ b/src/cmd/go/internal/load/flag.go @@ -6,6 +6,7 @@ package load import ( "cmd/go/internal/base" + "cmd/go/internal/modload" "cmd/internal/quoted" "fmt" "strings" @@ -63,7 +64,7 @@ func (f *PerPackageFlag) set(v, cwd string) error { return fmt.Errorf("parameter may not start with quote character %c", v[0]) } pattern := strings.TrimSpace(v[:i]) - match = MatchPackage(pattern, cwd) + match = MatchPackage(modload.LoaderState, pattern, cwd) v = v[i+1:] } flags, err := quoted.Split(v) diff --git a/src/cmd/go/internal/load/godebug.go b/src/cmd/go/internal/load/godebug.go index c795d42f11..817cc4faeb 100644 --- a/src/cmd/go/internal/load/godebug.go +++ b/src/cmd/go/internal/load/godebug.go @@ -45,12 +45,12 @@ func ParseGoDebug(text string) (key, value string, err error) { // defaultGODEBUG returns the default GODEBUG setting for the main package p. // When building a test binary, directives, testDirectives, and xtestDirectives // list additional directives from the package under test. -func defaultGODEBUG(p *Package, directives, testDirectives, xtestDirectives []build.Directive) string { +func defaultGODEBUG(loaderstate *modload.State, p *Package, directives, testDirectives, xtestDirectives []build.Directive) string { if p.Name != "main" { return "" } - goVersion := modload.LoaderState.MainModules.GoVersion() - if modload.LoaderState.RootMode == modload.NoRoot && p.Module != nil { + goVersion := loaderstate.MainModules.GoVersion(loaderstate) + if loaderstate.RootMode == modload.NoRoot && p.Module != nil { // This is go install pkg@version or go run pkg@version. // Use the Go version from the package. // If there isn't one, then assume Go 1.20, @@ -73,7 +73,7 @@ func defaultGODEBUG(p *Package, directives, testDirectives, xtestDirectives []bu } // Add directives from main module go.mod. - for _, g := range modload.LoaderState.MainModules.Godebugs() { + for _, g := range loaderstate.MainModules.Godebugs(loaderstate) { if m == nil { m = make(map[string]string) } diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index a894affc84..cfaece2072 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -686,8 +686,8 @@ const ( ) // LoadPackage does Load import, but without a parent package load context -func LoadPackage(ctx context.Context, opts PackageOpts, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package { - p, err := loadImport(ctx, opts, nil, path, srcDir, nil, stk, importPos, mode) +func LoadPackage(loaderstate *modload.State, ctx context.Context, opts PackageOpts, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package { + p, err := loadImport(loaderstate, ctx, opts, nil, path, srcDir, nil, stk, importPos, mode) if err != nil { base.Fatalf("internal error: loadImport of %q with nil parent returned an error", path) } @@ -703,7 +703,7 @@ func LoadPackage(ctx context.Context, opts PackageOpts, path, srcDir string, stk // The returned PackageError, if any, describes why parent is not allowed // to import the named package, with the error referring to importPos. // The PackageError can only be non-nil when parent is not nil. -func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) { +func loadImport(loaderstate *modload.State, ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) { ctx, span := trace.StartSpan(ctx, "modload.loadImport "+path) defer span.Done() @@ -718,9 +718,9 @@ func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDi parentRoot = parent.Root parentIsStd = parent.Standard } - bp, loaded, err := loadPackageData(ctx, path, parentPath, srcDir, parentRoot, parentIsStd, mode) + bp, loaded, err := loadPackageData(loaderstate, ctx, path, parentPath, srcDir, parentRoot, parentIsStd, mode) if loaded && pre != nil && !opts.IgnoreImports { - pre.preloadImports(ctx, opts, bp.Imports, bp) + pre.preloadImports(loaderstate, ctx, opts, bp.Imports, bp) } if bp == nil { p := &Package{ @@ -771,7 +771,7 @@ func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDi // Load package. // loadPackageData may return bp != nil even if an error occurs, // in order to return partial information. - p.load(ctx, opts, path, stk, importPos, bp, err) + p.load(loaderstate, ctx, opts, path, stk, importPos, bp, err) if !cfg.ModulesEnabled && path != cleanImport(path) { p.Error = &PackageError{ @@ -784,7 +784,7 @@ func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDi } // Checked on every import because the rules depend on the code doing the importing. - if perr := disallowInternal(ctx, srcDir, parent, parentPath, p, stk); perr != nil { + if perr := disallowInternal(loaderstate, ctx, srcDir, parent, parentPath, p, stk); perr != nil { perr.setPos(importPos) return p, perr } @@ -838,7 +838,7 @@ func extractFirstImport(importPos []token.Position) *token.Position { // // loadPackageData returns a boolean, loaded, which is true if this is the // first time the package was loaded. Callers may preload imports in this case. -func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) { +func loadPackageData(loaderstate *modload.State, ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) { ctx, span := trace.StartSpan(ctx, "load.loadPackageData "+path) defer span.Done() @@ -883,7 +883,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo r.path = newPath r.dir = dir } else if cfg.ModulesEnabled { - r.dir, r.path, r.err = modload.Lookup(parentPath, parentIsStd, path) + r.dir, r.path, r.err = modload.Lookup(loaderstate, parentPath, parentIsStd, path) } else if build.IsLocalImport(path) { r.dir = filepath.Join(parentDir, path) r.path = dirToImportPath(r.dir) @@ -892,7 +892,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo // find out the key to use in packageCache without the // overhead of repeated calls to buildContext.Import. // The code is also needed in a few other places anyway. - r.path = resolveImportPath(path, parentPath, parentDir, parentRoot, parentIsStd) + r.path = resolveImportPath(loaderstate, path, parentPath, parentDir, parentRoot, parentIsStd) } else if mode&ResolveModule != 0 { r.path = moduleImportPath(path, parentPath, parentDir, parentRoot) } @@ -921,7 +921,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo } else { buildContext.GOPATH = "" // Clear GOPATH so packages are imported as pure module packages } - modroot := modload.PackageModRoot(ctx, r.path) + modroot := modload.PackageModRoot(loaderstate, ctx, r.path) if modroot == "" && str.HasPathPrefix(r.dir, cfg.GOROOTsrc) { modroot = cfg.GOROOTsrc gorootSrcCmd := filepath.Join(cfg.GOROOTsrc, "cmd") @@ -942,7 +942,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo if cfg.ModulesEnabled { // Override data.p.Root, since ImportDir sets it to $GOPATH, if // the module is inside $GOPATH/src. - if info := modload.PackageModuleInfo(ctx, path); info != nil { + if info := modload.PackageModuleInfo(loaderstate, ctx, path); info != nil { data.p.Root = info.Dir } } @@ -989,7 +989,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo if cfg.GOBIN != "" { data.p.BinDir = cfg.GOBIN } else if cfg.ModulesEnabled { - data.p.BinDir = modload.BinDir() + data.p.BinDir = modload.BinDir(loaderstate) } } @@ -1068,7 +1068,7 @@ func newPreload() *preload { // preloadMatches loads data for package paths matched by patterns. // When preloadMatches returns, some packages may not be loaded yet, but // loadPackageData and loadImport are always safe to call. -func (pre *preload) preloadMatches(ctx context.Context, opts PackageOpts, matches []*search.Match) { +func (pre *preload) preloadMatches(loaderstate *modload.State, ctx context.Context, opts PackageOpts, matches []*search.Match) { for _, m := range matches { for _, pkg := range m.Pkgs { select { @@ -1077,10 +1077,10 @@ func (pre *preload) preloadMatches(ctx context.Context, opts PackageOpts, matche case pre.sema <- struct{}{}: go func(pkg string) { mode := 0 // don't use vendoring or module import resolution - bp, loaded, err := loadPackageData(ctx, pkg, "", base.Cwd(), "", false, mode) + bp, loaded, err := loadPackageData(loaderstate, ctx, pkg, "", base.Cwd(), "", false, mode) <-pre.sema if bp != nil && loaded && err == nil && !opts.IgnoreImports { - pre.preloadImports(ctx, opts, bp.Imports, bp) + pre.preloadImports(loaderstate, ctx, opts, bp.Imports, bp) } }(pkg) } @@ -1091,7 +1091,7 @@ func (pre *preload) preloadMatches(ctx context.Context, opts PackageOpts, matche // preloadImports queues a list of imports for preloading. // When preloadImports returns, some packages may not be loaded yet, // but loadPackageData and loadImport are always safe to call. -func (pre *preload) preloadImports(ctx context.Context, opts PackageOpts, imports []string, parent *build.Package) { +func (pre *preload) preloadImports(loaderstate *modload.State, ctx context.Context, opts PackageOpts, imports []string, parent *build.Package) { parentIsStd := parent.Goroot && parent.ImportPath != "" && search.IsStandardImportPath(parent.ImportPath) for _, path := range imports { if path == "C" || path == "unsafe" { @@ -1102,10 +1102,10 @@ func (pre *preload) preloadImports(ctx context.Context, opts PackageOpts, import return case pre.sema <- struct{}{}: go func(path string) { - bp, loaded, err := loadPackageData(ctx, path, parent.ImportPath, parent.Dir, parent.Root, parentIsStd, ResolveImport) + bp, loaded, err := loadPackageData(loaderstate, ctx, path, parent.ImportPath, parent.Dir, parent.Root, parentIsStd, ResolveImport) <-pre.sema if bp != nil && loaded && err == nil && !opts.IgnoreImports { - pre.preloadImports(ctx, opts, bp.Imports, bp) + pre.preloadImports(loaderstate, ctx, opts, bp.Imports, bp) } }(path) } @@ -1160,12 +1160,12 @@ func ResolveImportPath(parent *Package, path string) (found string) { parentRoot = parent.Root parentIsStd = parent.Standard } - return resolveImportPath(path, parentPath, parentDir, parentRoot, parentIsStd) + return resolveImportPath(modload.LoaderState, path, parentPath, parentDir, parentRoot, parentIsStd) } -func resolveImportPath(path, parentPath, parentDir, parentRoot string, parentIsStd bool) (found string) { +func resolveImportPath(loaderstate *modload.State, path, parentPath, parentDir, parentRoot string, parentIsStd bool) (found string) { if cfg.ModulesEnabled { - if _, p, e := modload.Lookup(parentPath, parentIsStd, path); e == nil { + if _, p, e := modload.Lookup(loaderstate, parentPath, parentIsStd, path); e == nil { return p } return path @@ -1463,7 +1463,7 @@ func reusePackage(p *Package, stk *ImportStack) *Package { // is allowed to import p. // If the import is allowed, disallowInternal returns the original package p. // If not, it returns a new package containing just an appropriate error. -func disallowInternal(ctx context.Context, srcDir string, importer *Package, importerPath string, p *Package, stk *ImportStack) *PackageError { +func disallowInternal(loaderstate *modload.State, ctx context.Context, srcDir string, importer *Package, importerPath string, p *Package, stk *ImportStack) *PackageError { // golang.org/s/go14internal: // An import of a path containing the element “internal” // is disallowed if the importing code is outside the tree @@ -1552,7 +1552,7 @@ func disallowInternal(ctx context.Context, srcDir string, importer *Package, imp // directory containing them. // If the directory is outside the main modules, this will resolve to ".", // which is not a prefix of any valid module. - importerPath, _ = modload.LoaderState.MainModules.DirImportPath(ctx, importer.Dir) + importerPath, _ = loaderstate.MainModules.DirImportPath(loaderstate, ctx, importer.Dir) } parentOfInternal := p.ImportPath[:i] if str.HasPathPrefix(importerPath, parentOfInternal) { @@ -1771,7 +1771,7 @@ func (p *Package) DefaultExecName() string { // load populates p using information from bp, err, which should // be the result of calling build.Context.Import. // stk contains the import stack, not including path itself. -func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) { +func (p *Package) load(loaderstate *modload.State, ctx context.Context, opts PackageOpts, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) { p.copyBuild(opts, bp) // The localPrefix is the path we interpret ./ imports relative to, @@ -1835,7 +1835,7 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk * elem = full } if p.Internal.Build.BinDir == "" && cfg.ModulesEnabled { - p.Internal.Build.BinDir = modload.BinDir() + p.Internal.Build.BinDir = modload.BinDir(loaderstate) } if p.Internal.Build.BinDir != "" { // Install to GOBIN or bin of GOPATH entry. @@ -1973,9 +1973,9 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk * pkgPath = "command-line-arguments" } if cfg.ModulesEnabled { - p.Module = modload.PackageModuleInfo(ctx, pkgPath) + p.Module = modload.PackageModuleInfo(loaderstate, ctx, pkgPath) } - p.DefaultGODEBUG = defaultGODEBUG(p, nil, nil, nil) + p.DefaultGODEBUG = defaultGODEBUG(loaderstate, p, nil, nil, nil) if !opts.SuppressEmbedFiles { p.EmbedFiles, p.Internal.Embed, err = resolveEmbed(p.Dir, p.EmbedPatterns) @@ -2026,7 +2026,7 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk * if path == "C" { continue } - p1, err := loadImport(ctx, opts, nil, path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport) + p1, err := loadImport(loaderstate, ctx, opts, nil, path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport) if err != nil && p.Error == nil { p.Error = err p.Incomplete = true @@ -2813,7 +2813,7 @@ func TestPackageList(ctx context.Context, opts PackageOpts, roots []*Package) [] } walkTest := func(root *Package, path string) { var stk ImportStack - p1, err := loadImport(ctx, opts, nil, path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport) + p1, err := loadImport(modload.LoaderState, ctx, opts, nil, path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport) if err != nil && root.Error == nil { // Assign error importing the package to the importer. root.Error = err @@ -2840,16 +2840,16 @@ func TestPackageList(ctx context.Context, opts PackageOpts, roots []*Package) [] // dependencies (like sync/atomic for coverage). // TODO(jayconrod): delete this function and set flags automatically // in LoadImport instead. -func LoadImportWithFlags(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) { - p, err := loadImport(context.TODO(), PackageOpts{}, nil, path, srcDir, parent, stk, importPos, mode) +func LoadImportWithFlags(loaderstate *modload.State, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) { + p, err := loadImport(loaderstate, context.TODO(), PackageOpts{}, nil, path, srcDir, parent, stk, importPos, mode) setToolFlags(p) return p, err } // LoadPackageWithFlags is the same as LoadImportWithFlags but without a parent. // It's then guaranteed to not return an error -func LoadPackageWithFlags(path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package { - p := LoadPackage(context.TODO(), PackageOpts{}, path, srcDir, stk, importPos, mode) +func LoadPackageWithFlags(loaderstate *modload.State, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package { + p := LoadPackage(loaderstate, context.TODO(), PackageOpts{}, path, srcDir, stk, importPos, mode) setToolFlags(p) return p } @@ -2899,7 +2899,7 @@ type PackageOpts struct { // // To obtain a flat list of packages, use PackageList. // To report errors loading packages, use ReportPackageErrors. -func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) []*Package { +func PackagesAndErrors(loaderstate *modload.State, ctx context.Context, opts PackageOpts, patterns []string) []*Package { ctx, span := trace.StartSpan(ctx, "load.PackagesAndErrors") defer span.Done() @@ -2911,7 +2911,7 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) // We need to test whether the path is an actual Go file and not a // package path or pattern ending in '.go' (see golang.org/issue/34653). if fi, err := fsys.Stat(p); err == nil && !fi.IsDir() { - pkgs := []*Package{GoFilesPackage(ctx, opts, patterns)} + pkgs := []*Package{GoFilesPackage(loaderstate, ctx, opts, patterns)} setPGOProfilePath(pkgs) return pkgs } @@ -2919,13 +2919,13 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) } var matches []*search.Match - if modload.Init(); cfg.ModulesEnabled { + if modload.Init(loaderstate); cfg.ModulesEnabled { modOpts := modload.PackageOpts{ ResolveMissingImports: true, LoadTests: opts.ModResolveTests, SilencePackageErrors: true, } - matches, _ = modload.LoadPackages(ctx, modOpts, patterns...) + matches, _ = modload.LoadPackages(loaderstate, ctx, modOpts, patterns...) } else { matches = search.ImportPaths(patterns) } @@ -2938,7 +2938,7 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) pre := newPreload() defer pre.flush() - pre.preloadMatches(ctx, opts, matches) + pre.preloadMatches(loaderstate, ctx, opts, matches) for _, m := range matches { for _, pkg := range m.Pkgs { @@ -2952,7 +2952,7 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) // a literal and also a non-literal pattern. mode |= cmdlinePkgLiteral } - p, perr := loadImport(ctx, opts, pre, pkg, base.Cwd(), nil, &stk, nil, mode) + p, perr := loadImport(loaderstate, ctx, opts, pre, pkg, base.Cwd(), nil, &stk, nil, mode) if perr != nil { base.Fatalf("internal error: loadImport of %q with nil parent returned an error", pkg) } @@ -3243,8 +3243,8 @@ func setToolFlags(pkgs ...*Package) { // GoFilesPackage creates a package for building a collection of Go files // (typically named on the command line). The target is named p.a for // package p or named after the first Go file for package main. -func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Package { - modload.Init() +func GoFilesPackage(loaderstate *modload.State, ctx context.Context, opts PackageOpts, gofiles []string) *Package { + modload.Init(loaderstate) for _, f := range gofiles { if !strings.HasSuffix(f, ".go") { @@ -3289,7 +3289,7 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa ctxt.ReadDir = func(string) ([]fs.FileInfo, error) { return dirent, nil } if cfg.ModulesEnabled { - modload.ImportFromFiles(ctx, gofiles) + modload.ImportFromFiles(loaderstate, ctx, gofiles) } var err error @@ -3305,7 +3305,7 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa pkg := new(Package) pkg.Internal.Local = true pkg.Internal.CmdlineFiles = true - pkg.load(ctx, opts, "command-line-arguments", &stk, nil, bp, err) + pkg.load(loaderstate, ctx, opts, "command-line-arguments", &stk, nil, bp, err) if !cfg.ModulesEnabled { pkg.Internal.LocalPrefix = dirToImportPath(dir) } @@ -3319,7 +3319,7 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa if cfg.GOBIN != "" { pkg.Target = filepath.Join(cfg.GOBIN, exe) } else if cfg.ModulesEnabled { - pkg.Target = filepath.Join(modload.BinDir(), exe) + pkg.Target = filepath.Join(modload.BinDir(loaderstate), exe) } } @@ -3347,11 +3347,11 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa // module, but its go.mod file (if it has one) must not contain directives that // would cause it to be interpreted differently if it were the main module // (replace, exclude). -func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args []string) ([]*Package, error) { - if !modload.LoaderState.ForceUseModules { +func PackagesAndErrorsOutsideModule(loaderstate *modload.State, ctx context.Context, opts PackageOpts, args []string) ([]*Package, error) { + if !loaderstate.ForceUseModules { panic("modload.ForceUseModules must be true") } - if modload.LoaderState.RootMode != modload.NoRoot { + if loaderstate.RootMode != modload.NoRoot { panic("modload.RootMode must be NoRoot") } @@ -3404,12 +3404,12 @@ func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args allowed = nil } noneSelected := func(path string) (version string) { return "none" } - qrs, err := modload.QueryPackages(ctx, patterns[0], version, noneSelected, allowed) + qrs, err := modload.QueryPackages(loaderstate, ctx, patterns[0], version, noneSelected, allowed) if err != nil { return nil, fmt.Errorf("%s: %w", args[0], err) } rootMod := qrs[0].Mod - deprecation, err := modload.CheckDeprecation(ctx, rootMod) + deprecation, err := modload.CheckDeprecation(loaderstate, ctx, rootMod) if err != nil { return nil, fmt.Errorf("%s: %w", args[0], err) } @@ -3438,12 +3438,12 @@ func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args // Since we are in NoRoot mode, the build list initially contains only // the dummy command-line-arguments module. Add a requirement on the // module that provides the packages named on the command line. - if _, err := modload.EditBuildList(ctx, nil, []module.Version{rootMod}); err != nil { + if _, err := modload.EditBuildList(loaderstate, ctx, nil, []module.Version{rootMod}); err != nil { return nil, fmt.Errorf("%s: %w", args[0], err) } // Load packages for all arguments. - pkgs := PackagesAndErrors(ctx, opts, patterns) + pkgs := PackagesAndErrors(loaderstate, ctx, opts, patterns) // Check that named packages are all provided by the same module. for _, pkg := range pkgs { @@ -3471,14 +3471,14 @@ func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args } // EnsureImport ensures that package p imports the named package. -func EnsureImport(p *Package, pkg string) { +func EnsureImport(loaderstate *modload.State, p *Package, pkg string) { for _, d := range p.Internal.Imports { if d.Name == pkg { return } } - p1, err := LoadImportWithFlags(pkg, p.Dir, p, &ImportStack{}, nil, 0) + p1, err := LoadImportWithFlags(loaderstate, pkg, p.Dir, p, &ImportStack{}, nil, 0) if err != nil { base.Fatalf("load %s: %v", pkg, err) } @@ -3494,7 +3494,7 @@ func EnsureImport(p *Package, pkg string) { // "go test -cover"). It walks through the packages being built (and // dependencies) and marks them for coverage instrumentation when // appropriate, and possibly adding additional deps where needed. -func PrepareForCoverageBuild(pkgs []*Package) { +func PrepareForCoverageBuild(loaderstate *modload.State, pkgs []*Package) { var match []func(*Package) bool matchMainModAndCommandLine := func(p *Package) bool { @@ -3507,7 +3507,7 @@ func PrepareForCoverageBuild(pkgs []*Package) { // the specific packages selected by the user-specified pattern(s). match = make([]func(*Package) bool, len(cfg.BuildCoverPkg)) for i := range cfg.BuildCoverPkg { - match[i] = MatchPackage(cfg.BuildCoverPkg[i], base.Cwd()) + match[i] = MatchPackage(loaderstate, cfg.BuildCoverPkg[i], base.Cwd()) } } else { // Without -coverpkg, instrument only packages in the main module @@ -3519,10 +3519,10 @@ func PrepareForCoverageBuild(pkgs []*Package) { // Visit the packages being built or installed, along with all of // their dependencies, and mark them to be instrumented, taking // into account the matchers we've set up in the sequence above. - SelectCoverPackages(PackageList(pkgs), match, "build") + SelectCoverPackages(loaderstate, PackageList(pkgs), match, "build") } -func SelectCoverPackages(roots []*Package, match []func(*Package) bool, op string) []*Package { +func SelectCoverPackages(loaderstate *modload.State, roots []*Package, match []func(*Package) bool, op string) []*Package { var warntag string var includeMain bool switch op { @@ -3602,7 +3602,7 @@ func SelectCoverPackages(roots []*Package, match []func(*Package) bool, op strin // Force import of sync/atomic into package if atomic mode. if cfg.BuildCoverMode == "atomic" { - EnsureImport(p, "sync/atomic") + EnsureImport(loaderstate, p, "sync/atomic") } } diff --git a/src/cmd/go/internal/load/search.go b/src/cmd/go/internal/load/search.go index 51c8cc0932..09e32a4f46 100644 --- a/src/cmd/go/internal/load/search.go +++ b/src/cmd/go/internal/load/search.go @@ -14,7 +14,7 @@ import ( ) // MatchPackage(pattern, cwd)(p) reports whether package p matches pattern in the working directory cwd. -func MatchPackage(pattern, cwd string) func(*Package) bool { +func MatchPackage(loaderstate *modload.State, pattern, cwd string) func(*Package) bool { switch { case search.IsRelativePath(pattern): // Split pattern into leading pattern-free directory path @@ -54,13 +54,13 @@ func MatchPackage(pattern, cwd string) func(*Package) bool { return func(p *Package) bool { return p.Standard } case pattern == "cmd": return func(p *Package) bool { return p.Standard && strings.HasPrefix(p.ImportPath, "cmd/") } - case pattern == "tool" && modload.Enabled(): + case pattern == "tool" && modload.Enabled(loaderstate): return func(p *Package) bool { - return modload.LoaderState.MainModules.Tools()[p.ImportPath] + return loaderstate.MainModules.Tools()[p.ImportPath] } - case pattern == "work" && modload.Enabled(): + case pattern == "work" && modload.Enabled(loaderstate): return func(p *Package) bool { - return p.Module != nil && modload.LoaderState.MainModules.Contains(p.Module.Path) + return p.Module != nil && loaderstate.MainModules.Contains(p.Module.Path) } default: diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index 9849ee138a..9019545b4b 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -24,6 +24,7 @@ import ( "unicode/utf8" "cmd/go/internal/fsys" + "cmd/go/internal/modload" "cmd/go/internal/str" "cmd/go/internal/trace" ) @@ -106,7 +107,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p defer pre.flush() allImports := append([]string{}, p.TestImports...) allImports = append(allImports, p.XTestImports...) - pre.preloadImports(ctx, opts, allImports, p.Internal.Build) + pre.preloadImports(modload.LoaderState, ctx, opts, allImports, p.Internal.Build) var ptestErr, pxtestErr *PackageError var imports, ximports []*Package @@ -116,7 +117,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p stk.Push(ImportInfo{Pkg: p.ImportPath + " (test)"}) rawTestImports := str.StringList(p.TestImports) for i, path := range p.TestImports { - p1, err := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport) + p1, err := loadImport(modload.LoaderState, ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport) if err != nil && ptestErr == nil { ptestErr = err incomplete = true @@ -145,7 +146,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p var pxtestIncomplete bool rawXTestImports := str.StringList(p.XTestImports) for i, path := range p.XTestImports { - p1, err := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport) + p1, err := loadImport(modload.LoaderState, ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport) if err != nil && pxtestErr == nil { pxtestErr = err } @@ -292,7 +293,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p } pb := p.Internal.Build - pmain.DefaultGODEBUG = defaultGODEBUG(pmain, pb.Directives, pb.TestDirectives, pb.XTestDirectives) + pmain.DefaultGODEBUG = defaultGODEBUG(modload.LoaderState, pmain, pb.Directives, pb.TestDirectives, pb.XTestDirectives) if pmain.Internal.BuildInfo == nil || pmain.DefaultGODEBUG != p.DefaultGODEBUG { // Either we didn't generate build info for the package under test (because it wasn't package main), or // the DefaultGODEBUG used to build the test main package is different from the DefaultGODEBUG @@ -321,7 +322,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p if dep == ptest.ImportPath { pmain.Internal.Imports = append(pmain.Internal.Imports, ptest) } else { - p1, err := loadImport(ctx, opts, pre, dep, "", nil, &stk, nil, 0) + p1, err := loadImport(modload.LoaderState, ctx, opts, pre, dep, "", nil, &stk, nil, 0) if err != nil && pmain.Error == nil { pmain.Error = err pmain.Incomplete = true diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index 8df11bfa59..f4ed4b4583 100644 --- a/src/cmd/go/internal/modcmd/download.go +++ b/src/cmd/go/internal/modcmd/download.go @@ -109,15 +109,15 @@ type ModuleJSON struct { } func runDownload(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() + modload.InitWorkfile(modload.LoaderState) // Check whether modules are enabled and whether we're in a module. modload.LoaderState.ForceUseModules = true modload.ExplicitWriteGoMod = true haveExplicitArgs := len(args) > 0 - if modload.HasModRoot() || modload.WorkFilePath() != "" { - modload.LoadModFile(ctx) // to fill MainModules + if modload.HasModRoot(modload.LoaderState) || modload.WorkFilePath(modload.LoaderState) != "" { + modload.LoadModFile(modload.LoaderState, ctx) // to fill MainModules if haveExplicitArgs { for _, mainModule := range modload.LoaderState.MainModules.Versions() { @@ -130,7 +130,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { } } } - } else if modload.WorkFilePath() != "" { + } else if modload.WorkFilePath(modload.LoaderState) != "" { // 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. @@ -169,7 +169,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { } if len(args) == 0 { - if modload.HasModRoot() { + if modload.HasModRoot(modload.LoaderState) { os.Stderr.WriteString("go: no module dependencies to download\n") } else { base.Errorf("go: no modules specified (see 'go help mod download')") @@ -177,7 +177,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { base.Exit() } - if *downloadReuse != "" && modload.HasModRoot() { + if *downloadReuse != "" && modload.HasModRoot(modload.LoaderState) { base.Fatalf("go mod download -reuse cannot be used inside a module") } @@ -220,7 +220,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // when we can. } - if !haveExplicitArgs && modload.WorkFilePath() == "" { + if !haveExplicitArgs && modload.WorkFilePath(modload.LoaderState) == "" { // '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 @@ -291,7 +291,7 @@ 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() != "" { + if haveExplicitArgs || modload.WorkFilePath(modload.LoaderState) != "" { var sw toolchain.Switcher // Add errors to the Switcher in deterministic order so that they will be // logged deterministically. @@ -347,7 +347,7 @@ 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() != "" { + if haveExplicitArgs || modload.WorkFilePath(modload.LoaderState) != "" { if err := modload.WriteGoMod(ctx, modload.WriteOpts{}); err != nil { base.Error(err) } diff --git a/src/cmd/go/internal/modcmd/graph.go b/src/cmd/go/internal/modcmd/graph.go index 5f47260e18..3bc6009b57 100644 --- a/src/cmd/go/internal/modcmd/graph.go +++ b/src/cmd/go/internal/modcmd/graph.go @@ -52,7 +52,7 @@ func init() { } func runGraph(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() + modload.InitWorkfile(modload.LoaderState) if len(args) > 0 { base.Fatalf("go: 'go mod graph' accepts no arguments") diff --git a/src/cmd/go/internal/modcmd/tidy.go b/src/cmd/go/internal/modcmd/tidy.go index 0314dcef25..c693bd52a3 100644 --- a/src/cmd/go/internal/modcmd/tidy.go +++ b/src/cmd/go/internal/modcmd/tidy.go @@ -130,7 +130,7 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) { }) } - modload.LoadPackages(ctx, modload.PackageOpts{ + modload.LoadPackages(modload.LoaderState, ctx, modload.PackageOpts{ TidyGoVersion: tidyGo.String(), Tags: imports.AnyTags(), Tidy: true, diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index df673e885c..8d9672d536 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -66,8 +66,8 @@ func init() { } func runVendor(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() - if modload.WorkFilePath() != "" { + modload.InitWorkfile(modload.LoaderState) + if modload.WorkFilePath(modload.LoaderState) != "" { 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(ctx, vendorE, vendorO, args) @@ -88,7 +88,7 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string) AllowErrors: vendorE, SilenceMissingStdImports: true, } - _, pkgs := modload.LoadPackages(ctx, loadOpts, "all") + _, pkgs := modload.LoadPackages(modload.LoaderState, ctx, loadOpts, "all") var vdir string switch { @@ -97,7 +97,7 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string) case vendorO != "": vdir = filepath.Join(base.Cwd(), vendorO) default: - vdir = filepath.Join(modload.VendorDir()) + vdir = filepath.Join(modload.VendorDir(modload.LoaderState)) } if err := os.RemoveAll(vdir); err != nil { base.Fatal(err) @@ -116,8 +116,8 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string) includeAllReplacements := false includeGoVersions := false isExplicit := map[module.Version]bool{} - gv := modload.LoaderState.MainModules.GoVersion() - if gover.Compare(gv, "1.14") >= 0 && (modload.FindGoWork(base.Cwd()) != "" || modload.ModFile().Go != nil) { + gv := modload.LoaderState.MainModules.GoVersion(modload.LoaderState) + if gover.Compare(gv, "1.14") >= 0 && (modload.FindGoWork(modload.LoaderState, base.Cwd()) != "" || modload.ModFile().Go != nil) { // If the Go version is at least 1.14, annotate all explicit 'require' and // 'replace' targets found in the go.mod file so that we can perform a // stronger consistency check when -mod=vendor is set. @@ -162,7 +162,7 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string) replacementWritten := make(map[module.Version]bool) for _, m := range vendorMods { - replacement := modload.Replacement(m) + replacement := modload.Replacement(modload.LoaderState, m) line := moduleLine(m, replacement) replacementWritten[m] = true io.WriteString(w, line) @@ -215,7 +215,7 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string) continue } replacementWritten[r.Old] = true - rNew := modload.Replacement(r.Old) + rNew := modload.Replacement(modload.LoaderState, r.Old) if rNew == (module.Version{}) { // There is no replacement. Don't try to write it. continue @@ -269,7 +269,7 @@ func moduleLine(m, r module.Version) string { } func vendorPkg(vdir, pkg string) { - src, realPath, _ := modload.Lookup("", false, pkg) + src, realPath, _ := modload.Lookup(modload.LoaderState, "", false, pkg) if src == "" { base.Errorf("internal error: no pkg for %s\n", pkg) return @@ -315,7 +315,7 @@ func vendorPkg(vdir, pkg string) { } } var embedPatterns []string - if gover.Compare(modload.LoaderState.MainModules.GoVersion(), "1.22") >= 0 { + if gover.Compare(modload.LoaderState.MainModules.GoVersion(modload.LoaderState), "1.22") >= 0 { embedPatterns = bp.EmbedPatterns } else { // Maintain the behavior of https://github.com/golang/go/issues/63473 @@ -431,7 +431,7 @@ func matchPotentialSourceFile(dir string, info fs.DirEntry) bool { return false } if info.Name() == "go.mod" || info.Name() == "go.sum" { - if gv := modload.LoaderState.MainModules.GoVersion(); gover.Compare(gv, "1.17") >= 0 { + if gv := modload.LoaderState.MainModules.GoVersion(modload.LoaderState); gover.Compare(gv, "1.17") >= 0 { // As of Go 1.17, we strip go.mod and go.sum files from dependency modules. // Otherwise, 'go' commands invoked within the vendor subtree may misidentify // an arbitrary directory within the vendor tree as a module root. diff --git a/src/cmd/go/internal/modcmd/verify.go b/src/cmd/go/internal/modcmd/verify.go index 8de444ff06..d8227bcd54 100644 --- a/src/cmd/go/internal/modcmd/verify.go +++ b/src/cmd/go/internal/modcmd/verify.go @@ -44,7 +44,7 @@ func init() { } func runVerify(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() + modload.InitWorkfile(modload.LoaderState) if len(args) != 0 { // NOTE(rsc): Could take a module pattern. diff --git a/src/cmd/go/internal/modcmd/why.go b/src/cmd/go/internal/modcmd/why.go index 62a5387ed8..b37d9fded0 100644 --- a/src/cmd/go/internal/modcmd/why.go +++ b/src/cmd/go/internal/modcmd/why.go @@ -63,7 +63,7 @@ func init() { } func runWhy(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() + modload.InitWorkfile(modload.LoaderState) modload.LoaderState.ForceUseModules = true modload.LoaderState.RootMode = modload.NeedRoot modload.ExplicitWriteGoMod = true // don't write go.mod in ListModules @@ -89,7 +89,7 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) { } byModule := make(map[string][]string) - _, pkgs := modload.LoadPackages(ctx, loadOpts, "all") + _, pkgs := modload.LoadPackages(modload.LoaderState, ctx, loadOpts, "all") for _, path := range pkgs { m := modload.PackageModule(path) if m.Path != "" { @@ -120,9 +120,9 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) { } } else { // Resolve to packages. - matches, _ := modload.LoadPackages(ctx, loadOpts, args...) + matches, _ := modload.LoadPackages(modload.LoaderState, ctx, loadOpts, args...) - modload.LoadPackages(ctx, loadOpts, "all") // rebuild graph, from main module (not from named packages) + modload.LoadPackages(modload.LoaderState, ctx, loadOpts, "all") // rebuild graph, from main module (not from named packages) sep := "" for _, m := range matches { diff --git a/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go b/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go index 16cc145705..9d59d1a8ea 100644 --- a/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go +++ b/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go @@ -94,7 +94,7 @@ func TestZipSums(t *testing.T) { cfg.GOPROXY = "direct" cfg.GOSUMDB = "off" - modload.Init() + modload.Init(modload.LoaderState) // Shard tests by downloading only every nth module when shard flags are set. // This makes it easier to test small groups of modules quickly. We avoid diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 5017f878ed..141e1708fa 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -307,14 +307,14 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // Allow looking up modules for import paths when outside of a module. // 'go get' is expected to do this, unlike other commands. - modload.AllowMissingModuleImports() + modload.AllowMissingModuleImports(modload.LoaderState) // 'go get' no longer builds or installs packages, so there's nothing to do // if there's no go.mod file. // TODO(#40775): make modload.Init return ErrNoModRoot instead of exiting. // We could handle that here by printing a different message. - modload.Init() - if !modload.HasModRoot() { + modload.Init(modload.LoaderState) + if !modload.HasModRoot(modload.LoaderState) { base.Fatalf("go: go.mod file not found in current directory or any parent directory.\n" + "\t'go get' is no longer supported outside a module.\n" + "\tTo build and install a command, use 'go install' with a version,\n" + @@ -424,9 +424,9 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { newReqs := reqsFromGoMod(modload.ModFile()) r.reportChanges(oldReqs, newReqs) - if gowork := modload.FindGoWork(base.Cwd()); gowork != "" { + if gowork := modload.FindGoWork(modload.LoaderState, base.Cwd()); gowork != "" { wf, err := modload.ReadWorkFile(gowork) - if err == nil && modload.UpdateWorkGoVersion(wf, modload.LoaderState.MainModules.GoVersion()) { + if err == nil && modload.UpdateWorkGoVersion(wf, modload.LoaderState.MainModules.GoVersion(modload.LoaderState)) { modload.WriteWorkFile(gowork, wf) } } @@ -448,7 +448,7 @@ func updateTools(ctx context.Context, queries []*query, opts *modload.WriteOpts) patterns = append(patterns, q.pattern) } - matches, _ := modload.LoadPackages(ctx, pkgOpts, patterns...) + matches, _ := modload.LoadPackages(modload.LoaderState, ctx, pkgOpts, patterns...) for i, m := range matches { if queries[i].version == "none" { opts.DropTools = append(opts.DropTools, m.Pkgs...) @@ -574,7 +574,7 @@ func newResolver(ctx context.Context, queries []*query) *resolver { buildListVersion: initialVersion, initialVersion: initialVersion, nonesByPath: map[string]*query{}, - workspace: loadWorkspace(modload.FindGoWork(base.Cwd())), + workspace: loadWorkspace(modload.FindGoWork(modload.LoaderState, base.Cwd())), } for _, q := range queries { @@ -645,7 +645,7 @@ func (r *resolver) noneForPath(mPath string) (nq *query, found bool) { // allowed versions. func (r *resolver) queryModule(ctx context.Context, mPath, query string, selected func(string) string) (module.Version, error) { current := r.initialSelected(mPath) - rev, err := modload.Query(ctx, mPath, query, current, r.checkAllowedOr(query, selected)) + rev, err := modload.Query(modload.LoaderState, ctx, mPath, query, current, r.checkAllowedOr(query, selected)) if err != nil { return module.Version{}, err } @@ -655,7 +655,7 @@ func (r *resolver) queryModule(ctx context.Context, mPath, query string, selecte // queryPackages wraps modload.QueryPackage, substituting r.checkAllowedOr to // decide allowed versions. func (r *resolver) queryPackages(ctx context.Context, pattern, query string, selected func(string) string) (pkgMods []module.Version, err error) { - results, err := modload.QueryPackages(ctx, pattern, query, selected, r.checkAllowedOr(query, selected)) + results, err := modload.QueryPackages(modload.LoaderState, ctx, pattern, query, selected, r.checkAllowedOr(query, selected)) if len(results) > 0 { pkgMods = make([]module.Version, 0, len(results)) for _, qr := range results { @@ -668,7 +668,7 @@ func (r *resolver) queryPackages(ctx context.Context, pattern, query string, sel // queryPattern wraps modload.QueryPattern, substituting r.checkAllowedOr to // decide allowed versions. func (r *resolver) queryPattern(ctx context.Context, pattern, query string, selected func(string) string) (pkgMods []module.Version, mod module.Version, err error) { - results, modOnly, err := modload.QueryPattern(ctx, pattern, query, selected, r.checkAllowedOr(query, selected)) + results, modOnly, err := modload.QueryPattern(modload.LoaderState, ctx, pattern, query, selected, r.checkAllowedOr(query, selected)) if len(results) > 0 { pkgMods = make([]module.Version, 0, len(results)) for _, qr := range results { @@ -721,7 +721,7 @@ func (r *resolver) queryNone(ctx context.Context, q *query) { if !q.isWildcard() { q.pathOnce(q.pattern, func() pathSet { - hasModRoot := modload.HasModRoot() + hasModRoot := modload.HasModRoot(modload.LoaderState) if hasModRoot && modload.LoaderState.MainModules.Contains(q.pattern) { v := module.Version{Path: q.pattern} // The user has explicitly requested to downgrade their own module to @@ -746,7 +746,7 @@ func (r *resolver) queryNone(ctx context.Context, q *query) { continue } q.pathOnce(curM.Path, func() pathSet { - if modload.HasModRoot() && curM.Version == "" && modload.LoaderState.MainModules.Contains(curM.Path) { + if modload.HasModRoot(modload.LoaderState) && curM.Version == "" && modload.LoaderState.MainModules.Contains(curM.Path) { return errSet(&modload.QueryMatchesMainModulesError{MainModules: []module.Version{curM}, Pattern: q.pattern, Query: q.version}) } return pathSet{mod: module.Version{Path: curM.Path, Version: "none"}} @@ -766,7 +766,7 @@ func (r *resolver) performLocalQueries(ctx context.Context) { // Absolute paths like C:\foo and relative paths like ../foo... are // restricted to matching packages in the main module. - pkgPattern, mainModule := modload.LoaderState.MainModules.DirImportPath(ctx, q.pattern) + pkgPattern, mainModule := modload.LoaderState.MainModules.DirImportPath(modload.LoaderState, ctx, q.pattern) if pkgPattern == "." { modload.MustHaveModRoot() versions := modload.LoaderState.MainModules.Versions() @@ -1275,13 +1275,13 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack return nil } - _, pkgs := modload.LoadPackages(ctx, opts, patterns...) + _, pkgs := modload.LoadPackages(modload.LoaderState, ctx, opts, patterns...) for _, pkgPath := range pkgs { const ( parentPath = "" parentIsStd = false ) - _, _, err := modload.Lookup(parentPath, parentIsStd, pkgPath) + _, _, err := modload.Lookup(modload.LoaderState, parentPath, parentIsStd, pkgPath) if err == nil { continue } @@ -1651,7 +1651,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin AllowErrors: true, SilenceNoGoErrors: true, } - matches, pkgs := modload.LoadPackages(ctx, pkgOpts, pkgPatterns...) + matches, pkgs := modload.LoadPackages(modload.LoaderState, ctx, pkgOpts, pkgPatterns...) for _, m := range matches { if len(m.Errs) > 0 { base.SetExitStatus(1) @@ -1659,7 +1659,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin } } for _, pkg := range pkgs { - if dir, _, err := modload.Lookup("", false, pkg); err != nil { + if dir, _, err := modload.Lookup(modload.LoaderState, "", false, pkg); err != nil { if dir != "" && errors.Is(err, imports.ErrNoGo) { // Since dir is non-empty, we must have located source files // associated with either the package or its test — ErrNoGo must @@ -1690,7 +1690,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin } } - reqs := modload.LoadModFile(ctx) + reqs := modload.LoadModFile(modload.LoaderState, ctx) for m := range relevantMods { if reqs.IsDirect(m.Path) { relevantMods[m] |= direct @@ -1714,7 +1714,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin for i := range retractions { i := i r.work.Add(func() { - err := modload.CheckRetractions(ctx, retractions[i].m) + err := modload.CheckRetractions(modload.LoaderState, ctx, retractions[i].m) if _, ok := errors.AsType[*modload.ModuleRetractedError](err); ok { retractions[i].message = err.Error() } @@ -1735,7 +1735,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin for i := range deprecations { i := i r.work.Add(func() { - deprecation, err := modload.CheckDeprecation(ctx, deprecations[i].m) + deprecation, err := modload.CheckDeprecation(modload.LoaderState, ctx, deprecations[i].m) if err != nil || deprecation == "" { return } @@ -1765,7 +1765,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin i := i m := r.buildList[i] mActual := m - if mRepl := modload.Replacement(m); mRepl.Path != "" { + if mRepl := modload.Replacement(modload.LoaderState, m); mRepl.Path != "" { mActual = mRepl } old := module.Version{Path: m.Path, Version: r.initialVersion[m.Path]} @@ -1773,7 +1773,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin continue } oldActual := old - if oldRepl := modload.Replacement(old); oldRepl.Path != "" { + if oldRepl := modload.Replacement(modload.LoaderState, old); oldRepl.Path != "" { oldActual = oldRepl } if mActual == oldActual || mActual.Version == "" || !modfetch.HaveSum(oldActual) { @@ -1986,7 +1986,7 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi } } - changed, err := modload.EditBuildList(ctx, additions, resolved) + changed, err := modload.EditBuildList(modload.LoaderState, ctx, additions, resolved) if err != nil { if errors.Is(err, gover.ErrTooNew) { toolchain.SwitchOrFatal(ctx, err) diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go index 59f3023ffc..7076bbadce 100644 --- a/src/cmd/go/internal/modget/query.go +++ b/src/cmd/go/internal/modget/query.go @@ -184,7 +184,7 @@ func (q *query) validate() error { if q.pattern == "all" { // If there is no main module, "all" is not meaningful. - if !modload.HasModRoot() { + if !modload.HasModRoot(modload.LoaderState) { return fmt.Errorf(`cannot match "all": %v`, modload.ErrNoModRoot) } if !versionOkForMainModule(q.version) { diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index a8ab82d1ec..5b1b643d27 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -51,8 +51,8 @@ func findStandardImportPath(path string) string { // a given package. If modules are not enabled or if the package is in the // standard library or if the package was not successfully loaded with // LoadPackages or ImportFromFiles, nil is returned. -func PackageModuleInfo(ctx context.Context, pkgpath string) *modinfo.ModulePublic { - if isStandardImportPath(pkgpath) || !Enabled() { +func PackageModuleInfo(loaderstate *State, ctx context.Context, pkgpath string) *modinfo.ModulePublic { + if isStandardImportPath(pkgpath) || !Enabled(loaderstate) { return nil } m, ok := findModule(loaded, pkgpath) @@ -60,23 +60,23 @@ func PackageModuleInfo(ctx context.Context, pkgpath string) *modinfo.ModulePubli return nil } - rs := LoadModFile(ctx) - return moduleInfo(ctx, rs, m, 0, nil) + rs := LoadModFile(loaderstate, ctx) + return moduleInfo(loaderstate, ctx, rs, m, 0, nil) } // PackageModRoot returns the module root directory for the module that provides // a given package. If modules are not enabled or if the package is in the // standard library or if the package was not successfully loaded with // LoadPackages or ImportFromFiles, the empty string is returned. -func PackageModRoot(ctx context.Context, pkgpath string) string { - if isStandardImportPath(pkgpath) || !Enabled() || cfg.BuildMod == "vendor" { +func PackageModRoot(loaderstate *State, ctx context.Context, pkgpath string) string { + if isStandardImportPath(pkgpath) || !Enabled(loaderstate) || cfg.BuildMod == "vendor" { return "" } m, ok := findModule(loaded, pkgpath) if !ok { return "" } - root, _, err := fetch(ctx, m) + root, _, err := fetch(loaderstate, ctx, m) if err != nil { return "" } @@ -84,26 +84,26 @@ func PackageModRoot(ctx context.Context, pkgpath string) string { } func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic { - if !Enabled() { + if !Enabled(LoaderState) { return nil } if path, vers, found := strings.Cut(path, "@"); found { m := module.Version{Path: path, Version: vers} - return moduleInfo(ctx, nil, m, 0, nil) + return moduleInfo(LoaderState, ctx, nil, m, 0, nil) } - rs := LoadModFile(ctx) + rs := LoadModFile(LoaderState, ctx) var ( v string ok bool ) if rs.pruning == pruned { - v, ok = rs.rootSelected(path) + v, ok = rs.rootSelected(LoaderState, path) } if !ok { - mg, err := rs.Graph(ctx) + mg, err := rs.Graph(LoaderState, ctx) if err != nil { base.Fatal(err) } @@ -119,7 +119,7 @@ func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic { } } - return moduleInfo(ctx, rs, module.Version{Path: path, Version: v}, 0, nil) + return moduleInfo(LoaderState, ctx, rs, module.Version{Path: path, Version: v}, 0, nil) } // addUpdate fills in m.Update if an updated version is available. @@ -128,7 +128,7 @@ func addUpdate(ctx context.Context, m *modinfo.ModulePublic) { return } - info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed) + info, err := Query(LoaderState, ctx, m.Path, "upgrade", m.Version, CheckAllowed) if _, ok := errors.AsType[*NoMatchingVersionError](err); ok || errors.Is(err, fs.ErrNotExist) || errors.Is(err, ErrDisallowed) { @@ -221,7 +221,7 @@ func addVersions(ctx context.Context, m *modinfo.ModulePublic, listRetracted boo if listRetracted { allowed = CheckExclusions } - v, origin, err := versions(ctx, m.Path, allowed) + v, origin, err := versions(LoaderState, ctx, m.Path, allowed) if err != nil && m.Error == nil { m.Error = &modinfo.ModuleError{Err: err.Error()} } @@ -231,12 +231,12 @@ func addVersions(ctx context.Context, m *modinfo.ModulePublic, listRetracted boo // addRetraction fills in m.Retracted if the module was retracted by its author. // m.Error is set if there's an error loading retraction information. -func addRetraction(ctx context.Context, m *modinfo.ModulePublic) { +func addRetraction(loaderstate *State, ctx context.Context, m *modinfo.ModulePublic) { if m.Version == "" { return } - err := CheckRetractions(ctx, module.Version{Path: m.Path, Version: m.Version}) + err := CheckRetractions(loaderstate, ctx, module.Version{Path: m.Path, Version: m.Version}) if err == nil { return } else if _, ok := errors.AsType[*NoMatchingVersionError](err); ok || errors.Is(err, fs.ErrNotExist) { @@ -263,7 +263,7 @@ func addRetraction(ctx context.Context, m *modinfo.ModulePublic) { // addDeprecation fills in m.Deprecated if the module was deprecated by its // author. m.Error is set if there's an error loading deprecation information. func addDeprecation(ctx context.Context, m *modinfo.ModulePublic) { - deprecation, err := CheckDeprecation(ctx, module.Version{Path: m.Path, Version: m.Version}) + deprecation, err := CheckDeprecation(LoaderState, ctx, module.Version{Path: m.Path, Version: m.Version}) if _, ok := errors.AsType[*NoMatchingVersionError](err); ok || errors.Is(err, fs.ErrNotExist) { // Ignore "no matching version" and "not found" errors. // This means the proxy has no matching version or no versions at all. @@ -287,8 +287,8 @@ func addDeprecation(ctx context.Context, m *modinfo.ModulePublic) { // moduleInfo returns information about module m, loaded from the requirements // in rs (which may be nil to indicate that m was not loaded from a requirement // graph). -func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode ListMode, reuse map[module.Version]*modinfo.ModulePublic) *modinfo.ModulePublic { - if m.Version == "" && LoaderState.MainModules.Contains(m.Path) { +func moduleInfo(loaderstate *State, ctx context.Context, rs *Requirements, m module.Version, mode ListMode, reuse map[module.Version]*modinfo.ModulePublic) *modinfo.ModulePublic { + if m.Version == "" && loaderstate.MainModules.Contains(m.Path) { info := &modinfo.ModulePublic{ Path: m.Path, Version: m.Version, @@ -299,7 +299,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li } else { panic("internal error: GoVersion not set for main module") } - if modRoot := LoaderState.MainModules.ModRoot(m); modRoot != "" { + if modRoot := loaderstate.MainModules.ModRoot(m); modRoot != "" { info.Dir = modRoot info.GoMod = modFilePath(modRoot) } @@ -322,7 +322,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li } checksumOk := func(suffix string) bool { - return rs == nil || m.Version == "" || !mustHaveSums() || + return rs == nil || m.Version == "" || !mustHaveSums(loaderstate) || modfetch.HaveSum(module.Version{Path: m.Path, Version: m.Version + suffix}) } @@ -330,7 +330,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li if m.Version != "" { if old := reuse[mod]; old != nil { - if err := checkReuse(ctx, mod, old.Origin); err == nil { + if err := checkReuse(loaderstate, ctx, mod, old.Origin); err == nil { *m = *old m.Query = "" m.Dir = "" @@ -338,7 +338,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li } } - if q, err := Query(ctx, m.Path, m.Version, "", nil); err != nil { + if q, err := Query(loaderstate, ctx, m.Path, m.Version, "", nil); err != nil { m.Error = &modinfo.ModuleError{Err: err.Error()} } else { m.Version = q.Version @@ -349,7 +349,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li if m.GoVersion == "" && checksumOk("/go.mod") { // Load the go.mod file to determine the Go version, since it hasn't // already been populated from rawGoVersion. - if summary, err := rawGoModSummary(mod); err == nil && summary.goVersion != "" { + if summary, err := rawGoModSummary(loaderstate, mod); err == nil && summary.goVersion != "" { m.GoVersion = summary.goVersion } } @@ -377,7 +377,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li } if mode&ListRetracted != 0 { - addRetraction(ctx, m) + addRetraction(loaderstate, ctx, m) } } } @@ -389,7 +389,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li return info } - r := Replacement(m) + r := Replacement(loaderstate, m) if r.Path == "" { if cfg.BuildMod == "vendor" { // It's tempting to fill in the "Dir" field to point within the vendor @@ -418,7 +418,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li if filepath.IsAbs(r.Path) { info.Replace.Dir = r.Path } else { - info.Replace.Dir = filepath.Join(replaceRelativeTo(), r.Path) + info.Replace.Dir = filepath.Join(replaceRelativeTo(loaderstate), r.Path) } info.Replace.GoMod = filepath.Join(info.Replace.Dir, "go.mod") } diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index cf64ee1dc2..54ec4d23eb 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -104,21 +104,21 @@ func mustHaveGoRoot(roots []module.Version) { // // If vendoring is in effect, the caller must invoke initVendor on the returned // *Requirements before any other method. -func newRequirements(pruning modPruning, rootModules []module.Version, direct map[string]bool) *Requirements { +func newRequirements(loaderstate *State, pruning modPruning, rootModules []module.Version, direct map[string]bool) *Requirements { mustHaveGoRoot(rootModules) if pruning != workspace { - if LoaderState.workFilePath != "" { + if loaderstate.workFilePath != "" { panic("in workspace mode, but pruning is not workspace in newRequirements") } } if pruning != workspace { - if LoaderState.workFilePath != "" { + if loaderstate.workFilePath != "" { panic("in workspace mode, but pruning is not workspace in newRequirements") } for i, m := range rootModules { - if m.Version == "" && LoaderState.MainModules.Contains(m.Path) { + if m.Version == "" && loaderstate.MainModules.Contains(m.Path) { panic(fmt.Sprintf("newRequirements called with untrimmed build list: rootModules[%v] is a main module", i)) } if m.Path == "" || m.Version == "" { @@ -162,10 +162,10 @@ func (rs *Requirements) String() string { // initVendor initializes rs.graph from the given list of vendored module // dependencies, overriding the graph that would normally be loaded from module // requirements. -func (rs *Requirements) initVendor(vendorList []module.Version) { +func (rs *Requirements) initVendor(loaderstate *State, vendorList []module.Version) { rs.graphOnce.Do(func() { - roots := LoaderState.MainModules.Versions() - if inWorkspaceMode() { + roots := loaderstate.MainModules.Versions() + if inWorkspaceMode(loaderstate) { // Use rs.rootModules to pull in the go and toolchain roots // from the go.work file and preserve the invariant that all // of rs.rootModules are in mg.g. @@ -176,7 +176,7 @@ func (rs *Requirements) initVendor(vendorList []module.Version) { } if rs.pruning == pruned { - mainModule := LoaderState.MainModules.mustGetSingleMainModule() + mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate) // The roots of a single pruned module should already include every module in the // vendor list, because the vendored modules are the same as those needed // for graph pruning. @@ -184,7 +184,7 @@ func (rs *Requirements) initVendor(vendorList []module.Version) { // Just to be sure, we'll double-check that here. inconsistent := false for _, m := range vendorList { - if v, ok := rs.rootSelected(m.Path); !ok || v != m.Version { + if v, ok := rs.rootSelected(loaderstate, m.Path); !ok || v != m.Version { base.Errorf("go: vendored module %v should be required explicitly in go.mod", m) inconsistent = true } @@ -208,15 +208,15 @@ func (rs *Requirements) initVendor(vendorList []module.Version) { // graph, but still distinguishes between direct and indirect // dependencies. vendorMod := module.Version{Path: "vendor/modules.txt", Version: ""} - if inWorkspaceMode() { - for _, m := range LoaderState.MainModules.Versions() { - reqs, _ := rootsFromModFile(m, LoaderState.MainModules.ModFile(m), omitToolchainRoot) + if inWorkspaceMode(loaderstate) { + for _, m := range loaderstate.MainModules.Versions() { + reqs, _ := rootsFromModFile(loaderstate, m, loaderstate.MainModules.ModFile(m), omitToolchainRoot) mg.g.Require(m, append(reqs, vendorMod)) } mg.g.Require(vendorMod, vendorList) } else { - mainModule := LoaderState.MainModules.mustGetSingleMainModule() + mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate) mg.g.Require(mainModule, append(rs.rootModules, vendorMod)) mg.g.Require(vendorMod, vendorList) } @@ -227,8 +227,8 @@ func (rs *Requirements) initVendor(vendorList []module.Version) { } // GoVersion returns the Go language version for the Requirements. -func (rs *Requirements) GoVersion() string { - v, _ := rs.rootSelected("go") +func (rs *Requirements) GoVersion(loaderstate *State) string { + v, _ := rs.rootSelected(loaderstate, "go") if v == "" { panic("internal error: missing go version in modload.Requirements") } @@ -238,8 +238,8 @@ func (rs *Requirements) GoVersion() string { // rootSelected returns the version of the root dependency with the given module // path, or the zero module.Version and ok=false if the module is not a root // dependency. -func (rs *Requirements) rootSelected(path string) (version string, ok bool) { - if LoaderState.MainModules.Contains(path) { +func (rs *Requirements) rootSelected(loaderstate *State, path string) (version string, ok bool) { + if loaderstate.MainModules.Contains(path) { return "", true } if v, ok := rs.maxRootVersion[path]; ok { @@ -252,9 +252,9 @@ func (rs *Requirements) rootSelected(path string) (version string, ok bool) { // of the same module or a requirement on any version of the main module. // Redundant requirements should be pruned, but they may influence version // selection. -func (rs *Requirements) hasRedundantRoot() bool { +func (rs *Requirements) hasRedundantRoot(loaderstate *State) bool { for i, m := range rs.rootModules { - if LoaderState.MainModules.Contains(m.Path) || (i > 0 && m.Path == rs.rootModules[i-1].Path) { + if loaderstate.MainModules.Contains(m.Path) || (i > 0 && m.Path == rs.rootModules[i-1].Path) { return true } } @@ -269,9 +269,9 @@ func (rs *Requirements) hasRedundantRoot() bool { // // If the requirements of any relevant module fail to load, Graph also // returns a non-nil error of type *mvs.BuildListError. -func (rs *Requirements) Graph(ctx context.Context) (*ModuleGraph, error) { +func (rs *Requirements) Graph(loaderstate *State, ctx context.Context) (*ModuleGraph, error) { rs.graphOnce.Do(func() { - mg, mgErr := readModGraph(ctx, rs.pruning, rs.rootModules, nil) + mg, mgErr := readModGraph(loaderstate, ctx, rs.pruning, rs.rootModules, nil) rs.graph.Store(&cachedGraph{mg, mgErr}) }) cached := rs.graph.Load() @@ -307,7 +307,7 @@ var readModGraphDebugOnce sync.Once // // Unlike LoadModGraph, readModGraph does not attempt to diagnose or update // inconsistent roots. -func readModGraph(ctx context.Context, pruning modPruning, roots []module.Version, unprune map[module.Version]bool) (*ModuleGraph, error) { +func readModGraph(loaderstate *State, ctx context.Context, pruning modPruning, roots []module.Version, unprune map[module.Version]bool) (*ModuleGraph, error) { mustHaveGoRoot(roots) if pruning == pruned { // Enable diagnostics for lazy module loading @@ -333,10 +333,10 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio } var graphRoots []module.Version - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { graphRoots = roots } else { - graphRoots = LoaderState.MainModules.Versions() + graphRoots = loaderstate.MainModules.Versions() } var ( mu sync.Mutex // guards mg.g and hasError during loading @@ -347,10 +347,10 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio ) if pruning != workspace { - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { panic("pruning is not workspace in workspace mode") } - mg.g.Require(LoaderState.MainModules.mustGetSingleMainModule(), roots) + mg.g.Require(loaderstate.MainModules.mustGetSingleMainModule(loaderstate), roots) } type dedupKey struct { @@ -367,7 +367,7 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio // m's go.mod file indicates that it supports graph pruning. loadOne := func(m module.Version) (*modFileSummary, error) { return mg.loadCache.Do(m, func() (*modFileSummary, error) { - summary, err := goModSummary(m) + summary, err := goModSummary(loaderstate, m) mu.Lock() if err == nil { @@ -527,12 +527,12 @@ func (mg *ModuleGraph) findError() error { return nil } -func (mg *ModuleGraph) allRootsSelected() bool { +func (mg *ModuleGraph) allRootsSelected(loaderstate *State) bool { var roots []module.Version - if inWorkspaceMode() { - roots = LoaderState.MainModules.Versions() + if inWorkspaceMode(loaderstate) { + roots = loaderstate.MainModules.Versions() } else { - roots, _ = mg.g.RequiredBy(LoaderState.MainModules.mustGetSingleMainModule()) + roots, _ = mg.g.RequiredBy(loaderstate.MainModules.mustGetSingleMainModule(loaderstate)) } for _, m := range roots { if mg.Selected(m.Path) != m.Version { @@ -553,13 +553,13 @@ func (mg *ModuleGraph) allRootsSelected() bool { // LoadModGraph need only be called if LoadPackages is not, // typically in commands that care about modules but no particular package. func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) { - rs, err := loadModFile(ctx, nil) + rs, err := loadModFile(LoaderState, ctx, nil) if err != nil { return nil, err } if goVersion != "" { - v, _ := rs.rootSelected("go") + v, _ := rs.rootSelected(LoaderState, "go") if gover.Compare(v, gover.GoStrictVersion) >= 0 && gover.Compare(goVersion, v) < 0 { return nil, fmt.Errorf("requested Go version %s cannot load module graph (requires Go >= %s)", goVersion, v) } @@ -569,13 +569,13 @@ func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) { // Use newRequirements instead of convertDepth because convertDepth // also updates roots; here, we want to report the unmodified roots // even though they may seem inconsistent. - rs = newRequirements(unpruned, rs.rootModules, rs.direct) + rs = newRequirements(LoaderState, unpruned, rs.rootModules, rs.direct) } - return rs.Graph(ctx) + return rs.Graph(LoaderState, ctx) } - rs, mg, err := expandGraph(ctx, rs) + rs, mg, err := expandGraph(LoaderState, ctx, rs) if err != nil { return nil, err } @@ -594,22 +594,22 @@ func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) { // from those roots and any error encountered while loading that graph. // expandGraph returns non-nil requirements and a non-nil graph regardless of // errors. On error, the roots might not be updated to be consistent. -func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleGraph, error) { - mg, mgErr := rs.Graph(ctx) +func expandGraph(loaderstate *State, ctx context.Context, rs *Requirements) (*Requirements, *ModuleGraph, error) { + mg, mgErr := rs.Graph(loaderstate, ctx) if mgErr != nil { // Without the graph, we can't update the roots: we don't know which // versions of transitive dependencies would be selected. return rs, mg, mgErr } - if !mg.allRootsSelected() { + if !mg.allRootsSelected(loaderstate) { // The roots of rs are not consistent with the rest of the graph. Update // them. In an unpruned module this is a no-op for the build list as a whole — // it just promotes what were previously transitive requirements to be // roots — but in a pruned module it may pull in previously-irrelevant // transitive dependencies. - newRS, rsErr := updateRoots(ctx, rs.direct, rs, nil, nil, false) + newRS, rsErr := updateRoots(loaderstate, ctx, rs.direct, rs, nil, nil, false) if rsErr != nil { // Failed to update roots, perhaps because of an error in a transitive // dependency needed for the update. Return the original Requirements @@ -617,7 +617,7 @@ func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleG return rs, mg, rsErr } rs = newRS - mg, mgErr = rs.Graph(ctx) + mg, mgErr = rs.Graph(loaderstate, ctx) } return rs, mg, mgErr @@ -639,16 +639,16 @@ func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleG // On success, EditBuildList reports whether the selected version of any module // in the build list may have been changed (possibly to or from "none") as a // result. -func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (changed bool, err error) { - rs, changed, err := editRequirements(ctx, LoadModFile(ctx), add, mustSelect) +func EditBuildList(loaderstate *State, ctx context.Context, add, mustSelect []module.Version) (changed bool, err error) { + rs, changed, err := editRequirements(loaderstate, ctx, LoadModFile(loaderstate, ctx), add, mustSelect) if err != nil { return false, err } - LoaderState.requirements = rs + loaderstate.requirements = rs return changed, nil } -func overrideRoots(ctx context.Context, rs *Requirements, replace []module.Version) *Requirements { +func overrideRoots(loaderstate *State, ctx context.Context, rs *Requirements, replace []module.Version) *Requirements { drop := make(map[string]bool) for _, m := range replace { drop[m.Path] = true @@ -661,7 +661,7 @@ func overrideRoots(ctx context.Context, rs *Requirements, replace []module.Versi } roots = append(roots, replace...) gover.ModSort(roots) - return newRequirements(rs.pruning, roots, rs.direct) + return newRequirements(loaderstate, rs.pruning, roots, rs.direct) } // A ConstraintError describes inconsistent constraints in EditBuildList @@ -765,28 +765,28 @@ func (c Conflict) String() string { // tidyRoots trims the root dependencies to the minimal requirements needed to // both retain the same versions of all packages in pkgs and satisfy the // graph-pruning invariants (if applicable). -func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Requirements, error) { - mainModule := LoaderState.MainModules.mustGetSingleMainModule() +func tidyRoots(loaderstate *State, ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Requirements, error) { + mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate) if rs.pruning == unpruned { - return tidyUnprunedRoots(ctx, mainModule, rs, pkgs) + return tidyUnprunedRoots(loaderstate, ctx, mainModule, rs, pkgs) } - return tidyPrunedRoots(ctx, mainModule, rs, pkgs) + return tidyPrunedRoots(loaderstate, ctx, mainModule, rs, pkgs) } -func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { +func updateRoots(loaderstate *State, ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { switch rs.pruning { case unpruned: - return updateUnprunedRoots(ctx, direct, rs, add) + return updateUnprunedRoots(loaderstate, ctx, direct, rs, add) case pruned: - return updatePrunedRoots(ctx, direct, rs, pkgs, add, rootsImported) + return updatePrunedRoots(loaderstate, ctx, direct, rs, pkgs, add, rootsImported) case workspace: - return updateWorkspaceRoots(ctx, direct, rs, add) + return updateWorkspaceRoots(loaderstate, ctx, direct, rs, add) default: panic(fmt.Sprintf("unsupported pruning mode: %v", rs.pruning)) } } -func updateWorkspaceRoots(ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) { +func updateWorkspaceRoots(loaderstate *State, ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) { if len(add) != 0 { // add should be empty in workspace mode because workspace mode implies // -mod=readonly, which in turn implies no new requirements. The code path @@ -797,7 +797,7 @@ func updateWorkspaceRoots(ctx context.Context, direct map[string]bool, rs *Requi // return an error. panic("add is not empty") } - return newRequirements(workspace, rs.rootModules, direct), nil + return newRequirements(loaderstate, workspace, rs.rootModules, direct), nil } // tidyPrunedRoots returns a minimal set of root requirements that maintains the @@ -816,16 +816,16 @@ func updateWorkspaceRoots(ctx context.Context, direct map[string]bool, rs *Requi // To ensure that the loading process eventually converges, the caller should // add any needed roots from the tidy root set (without removing existing untidy // roots) until the set of roots has converged. -func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requirements, pkgs []*loadPkg) (*Requirements, error) { +func tidyPrunedRoots(loaderstate *State, ctx context.Context, mainModule module.Version, old *Requirements, pkgs []*loadPkg) (*Requirements, error) { var ( roots []module.Version pathIsRoot = map[string]bool{mainModule.Path: true} ) - if v, ok := old.rootSelected("go"); ok { + if v, ok := old.rootSelected(loaderstate, "go"); ok { roots = append(roots, module.Version{Path: "go", Version: v}) pathIsRoot["go"] = true } - if v, ok := old.rootSelected("toolchain"); ok { + if v, ok := old.rootSelected(loaderstate, "toolchain"); ok { roots = append(roots, module.Version{Path: "toolchain", Version: v}) pathIsRoot["toolchain"] = true } @@ -847,7 +847,7 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir if !pkg.flags.has(pkgInAll) { continue } - if pkg.fromExternalModule() && !pathIsRoot[pkg.mod.Path] { + if pkg.fromExternalModule(loaderstate) && !pathIsRoot[pkg.mod.Path] { roots = append(roots, pkg.mod) pathIsRoot[pkg.mod.Path] = true } @@ -855,11 +855,11 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir queued[pkg] = true } gover.ModSort(roots) - tidy := newRequirements(pruned, roots, old.direct) + tidy := newRequirements(loaderstate, pruned, roots, old.direct) for len(queue) > 0 { roots = tidy.rootModules - mg, err := tidy.Graph(ctx) + mg, err := tidy.Graph(loaderstate, ctx) if err != nil { return nil, err } @@ -892,12 +892,12 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir if len(roots) > len(tidy.rootModules) { gover.ModSort(roots) - tidy = newRequirements(pruned, roots, tidy.direct) + tidy = newRequirements(loaderstate, pruned, roots, tidy.direct) } } roots = tidy.rootModules - _, err := tidy.Graph(ctx) + _, err := tidy.Graph(loaderstate, ctx) if err != nil { return nil, err } @@ -921,7 +921,7 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir pkg := pkg q.Add(func() { skipModFile := true - _, _, _, _, err := importFromModules(ctx, pkg.path, tidy, nil, skipModFile) + _, _, _, _, err := importFromModules(loaderstate, ctx, pkg.path, tidy, nil, skipModFile) if _, ok := errors.AsType[*AmbiguousImportError](err); ok { disambiguateRoot.Store(pkg.mod, true) } @@ -938,8 +938,8 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir if len(roots) > len(tidy.rootModules) { module.Sort(roots) - tidy = newRequirements(pruned, roots, tidy.direct) - _, err = tidy.Graph(ctx) + tidy = newRequirements(loaderstate, pruned, roots, tidy.direct) + _, err = tidy.Graph(loaderstate, ctx) if err != nil { return nil, err } @@ -999,7 +999,7 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir // // (See https://golang.org/design/36460-lazy-module-loading#invariants for more // detail.) -func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { +func updatePrunedRoots(loaderstate *State, ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { roots := rs.rootModules rootsUpgraded := false @@ -1009,7 +1009,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem // either pkgInAll or pkgIsRoot is included as a root.” needSort := false for _, pkg := range pkgs { - if !pkg.fromExternalModule() { + if !pkg.fromExternalModule(loaderstate) { // pkg was not loaded from a module dependency, so we don't need // to do anything special to maintain that dependency. continue @@ -1058,7 +1058,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem continue } - if _, ok := rs.rootSelected(pkg.mod.Path); ok { + if _, ok := rs.rootSelected(loaderstate, pkg.mod.Path); ok { // It is possible that the main module's go.mod file is incomplete or // otherwise erroneous — for example, perhaps the author forgot to 'git // add' their updated go.mod file after adding a new package import, or @@ -1094,7 +1094,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem } for _, m := range add { - if v, ok := rs.rootSelected(m.Path); !ok || gover.ModCompare(m.Path, v, m.Version) < 0 { + if v, ok := rs.rootSelected(loaderstate, m.Path); !ok || gover.ModCompare(m.Path, v, m.Version) < 0 { roots = append(roots, m) rootsUpgraded = true needSort = true @@ -1111,7 +1111,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem // We've added or upgraded one or more roots, so load the full module // graph so that we can update those roots to be consistent with other // requirements. - if mustHaveCompleteRequirements() { + if mustHaveCompleteRequirements(loaderstate) { // Our changes to the roots may have moved dependencies into or out of // the graph-pruning horizon, which could in turn change the selected // versions of other modules. (For pruned modules adding or removing an @@ -1119,9 +1119,9 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem return rs, errGoModDirty } - rs = newRequirements(pruned, roots, direct) + rs = newRequirements(loaderstate, pruned, roots, direct) var err error - mg, err = rs.Graph(ctx) + mg, err = rs.Graph(loaderstate, ctx) if err != nil { return rs, err } @@ -1135,20 +1135,20 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem // We've already loaded the full module graph, which includes the // requirements of all of the root modules — even the transitive // requirements, if they are unpruned! - mg, _ = rs.Graph(ctx) + mg, _ = rs.Graph(loaderstate, ctx) } else if cfg.BuildMod == "vendor" { // We can't spot-check the requirements of other modules because we // don't in general have their go.mod files available in the vendor // directory. (Fortunately this case is impossible, because mg.graph is // always non-nil in vendor mode!) panic("internal error: rs.graph is unexpectedly nil with -mod=vendor") - } else if !spotCheckRoots(ctx, rs, spotCheckRoot) { + } else if !spotCheckRoots(loaderstate, ctx, rs, spotCheckRoot) { // We spot-checked the explicit requirements of the roots that are // relevant to the packages we've loaded. Unfortunately, they're // inconsistent in some way; we need to load the full module graph // so that we can fix the roots properly. var err error - mg, err = rs.Graph(ctx) + mg, err = rs.Graph(loaderstate, ctx) if err != nil { return rs, err } @@ -1158,7 +1158,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem roots = make([]module.Version, 0, len(rs.rootModules)) rootsUpgraded = false inRootPaths := make(map[string]bool, len(rs.rootModules)+1) - for _, mm := range LoaderState.MainModules.Versions() { + for _, mm := range loaderstate.MainModules.Versions() { inRootPaths[mm.Path] = true } for _, m := range rs.rootModules { @@ -1184,7 +1184,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem var v string if mg == nil { - v, _ = rs.rootSelected(m.Path) + v, _ = rs.rootSelected(loaderstate, m.Path) } else { v = mg.Selected(m.Path) } @@ -1218,12 +1218,12 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem // preserve its cached ModuleGraph (if any). return rs, nil } - return newRequirements(pruned, roots, direct), nil + return newRequirements(loaderstate, pruned, roots, direct), nil } // spotCheckRoots reports whether the versions of the roots in rs satisfy the // explicit requirements of the modules in mods. -func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Version]bool) bool { +func spotCheckRoots(loaderstate *State, ctx context.Context, rs *Requirements, mods map[module.Version]bool) bool { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -1235,14 +1235,14 @@ func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Versi return } - summary, err := goModSummary(m) + summary, err := goModSummary(loaderstate, m) if err != nil { cancel() return } for _, r := range summary.require { - if v, ok := rs.rootSelected(r.Path); ok && gover.ModCompare(r.Path, v, r.Version) < 0 { + if v, ok := rs.rootSelected(loaderstate, r.Path); ok && gover.ModCompare(r.Path, v, r.Version) < 0 { cancel() return } @@ -1264,7 +1264,7 @@ func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Versi // the selected version of every module that provided or lexically could have // provided a package in pkgs, and includes the selected version of every such // module in direct as a root. -func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, old *Requirements, pkgs []*loadPkg) (*Requirements, error) { +func tidyUnprunedRoots(loaderstate *State, ctx context.Context, mainModule module.Version, old *Requirements, pkgs []*loadPkg) (*Requirements, error) { var ( // keep is a set of modules that provide packages or are needed to // disambiguate imports. @@ -1292,16 +1292,16 @@ func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, old *Requ // without its sum. See #47738. altMods = map[string]string{} ) - if v, ok := old.rootSelected("go"); ok { + if v, ok := old.rootSelected(loaderstate, "go"); ok { keep = append(keep, module.Version{Path: "go", Version: v}) keptPath["go"] = true } - if v, ok := old.rootSelected("toolchain"); ok { + if v, ok := old.rootSelected(loaderstate, "toolchain"); ok { keep = append(keep, module.Version{Path: "toolchain", Version: v}) keptPath["toolchain"] = true } for _, pkg := range pkgs { - if !pkg.fromExternalModule() { + if !pkg.fromExternalModule(loaderstate) { continue } if m := pkg.mod; !keptPath[m.Path] { @@ -1350,7 +1350,7 @@ func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, old *Requ } } - return newRequirements(unpruned, min, old.direct), nil + return newRequirements(loaderstate, unpruned, min, old.direct), nil } // updateUnprunedRoots returns a set of root requirements that includes the selected @@ -1367,8 +1367,8 @@ func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, old *Requ // by a dependency in add. // 4. Every version in add is selected at its given version unless upgraded by // (the dependencies of) an existing root or another module in add. -func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) { - mg, err := rs.Graph(ctx) +func updateUnprunedRoots(loaderstate *State, ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) { + mg, err := rs.Graph(loaderstate, ctx) if err != nil { // We can't ignore errors in the module graph even if the user passed the -e // flag to try to push past them. If we can't load the complete module @@ -1376,7 +1376,7 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir return rs, err } - if mustHaveCompleteRequirements() { + if mustHaveCompleteRequirements(loaderstate) { // Instead of actually updating the requirements, just check that no updates // are needed. if rs == nil { @@ -1396,7 +1396,7 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir } } for mPath := range direct { - if _, ok := rs.rootSelected(mPath); !ok { + if _, ok := rs.rootSelected(loaderstate, mPath); !ok { // Module m is supposed to be listed explicitly, but isn't. // // Note that this condition is also detected (and logged with more @@ -1435,7 +1435,7 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir // This is only for convenience and clarity for end users: in an unpruned module, // the choice of explicit vs. implicit dependency has no impact on MVS // selection (for itself or any other module). - keep := append(mg.BuildList()[LoaderState.MainModules.Len():], add...) + keep := append(mg.BuildList()[loaderstate.MainModules.Len():], add...) for _, m := range keep { if direct[m.Path] && !inRootPaths[m.Path] { rootPaths = append(rootPaths, m.Path) @@ -1444,14 +1444,14 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir } var roots []module.Version - for _, mainModule := range LoaderState.MainModules.Versions() { + for _, mainModule := range loaderstate.MainModules.Versions() { min, err := mvs.Req(mainModule, rootPaths, &mvsReqs{roots: keep}) if err != nil { return rs, err } roots = append(roots, min...) } - if LoaderState.MainModules.Len() > 1 { + if loaderstate.MainModules.Len() > 1 { gover.ModSort(roots) } if rs.pruning == unpruned && slices.Equal(roots, rs.rootModules) && maps.Equal(direct, rs.direct) { @@ -1460,12 +1460,12 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir return rs, nil } - return newRequirements(unpruned, roots, direct), nil + return newRequirements(loaderstate, unpruned, roots, direct), nil } // convertPruning returns a version of rs with the given pruning behavior. // If rs already has the given pruning, convertPruning returns rs unmodified. -func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) (*Requirements, error) { +func convertPruning(loaderstate *State, ctx context.Context, rs *Requirements, pruning modPruning) (*Requirements, error) { if rs.pruning == pruning { return rs, nil } else if rs.pruning == workspace || pruning == workspace { @@ -1477,7 +1477,7 @@ func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) ( // pruned module graph are a superset of the roots of an unpruned one, so // we don't need to add any new roots — we just need to drop the ones that // are redundant, which is exactly what updateUnprunedRoots does. - return updateUnprunedRoots(ctx, rs.direct, rs, nil) + return updateUnprunedRoots(loaderstate, ctx, rs.direct, rs, nil) } // We are converting an unpruned module to a pruned one. @@ -1487,9 +1487,9 @@ func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) ( // root set! “Include the transitive dependencies of every module in the build // list” is exactly what happens in a pruned module if we promote every module // in the build list to a root. - mg, err := rs.Graph(ctx) + mg, err := rs.Graph(loaderstate, ctx) if err != nil { return rs, err } - return newRequirements(pruned, mg.BuildList()[LoaderState.MainModules.Len():], rs.direct), nil + return newRequirements(loaderstate, pruned, mg.BuildList()[loaderstate.MainModules.Len():], rs.direct), nil } diff --git a/src/cmd/go/internal/modload/edit.go b/src/cmd/go/internal/modload/edit.go index 96d864545d..72d0f75422 100644 --- a/src/cmd/go/internal/modload/edit.go +++ b/src/cmd/go/internal/modload/edit.go @@ -42,7 +42,7 @@ import ( // If pruning is enabled, the roots of the edited requirements include an // explicit entry for each module path in tryUpgrade, mustSelect, and the roots // of rs, unless the selected version for the module path is "none". -func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSelect []module.Version) (edited *Requirements, changed bool, err error) { +func editRequirements(loaderstate *State, ctx context.Context, rs *Requirements, tryUpgrade, mustSelect []module.Version) (edited *Requirements, changed bool, err error) { if rs.pruning == workspace { panic("editRequirements cannot edit workspace requirements") } @@ -82,7 +82,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel } if rootPruning != rs.pruning { - rs, err = convertPruning(ctx, rs, rootPruning) + rs, err = convertPruning(loaderstate, ctx, rs, rootPruning) if err != nil { return orig, false, err } @@ -100,13 +100,13 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel // dependencies, so we need to treat everything in the build list as // potentially relevant — that is, as what would be a “root” in a module // with graph pruning enabled. - mg, err := rs.Graph(ctx) + mg, err := rs.Graph(loaderstate, ctx) if err != nil { // If we couldn't load the graph, we don't know what its requirements were // to begin with, so we can't edit those requirements in a coherent way. return orig, false, err } - bl := mg.BuildList()[LoaderState.MainModules.Len():] + bl := mg.BuildList()[loaderstate.MainModules.Len():] selectedRoot = make(map[string]string, len(bl)) for _, m := range bl { selectedRoot[m.Path] = m.Version @@ -224,7 +224,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel // of every root. The upgraded roots are in addition to the original // roots, so we will have enough information to trace a path to each // conflict we discover from one or more of the original roots. - mg, upgradedRoots, err := extendGraph(ctx, rootPruning, roots, selectedRoot) + mg, upgradedRoots, err := extendGraph(loaderstate, ctx, rootPruning, roots, selectedRoot) if err != nil { if mg == nil { return orig, false, err @@ -391,7 +391,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel // the edit. We want to make sure we consider keeping it as-is, // even if it wouldn't normally be included. (For example, it might // be a pseudo-version or pre-release.) - origMG, _ := orig.Graph(ctx) + origMG, _ := orig.Graph(loaderstate, ctx) origV := origMG.Selected(m.Path) if conflict.Err != nil && origV == m.Version { @@ -415,7 +415,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel rejectedRoot[m] = true prev := m for { - prev, err = previousVersion(ctx, prev) + prev, err = previousVersion(loaderstate, ctx, prev) if gover.ModCompare(m.Path, m.Version, origV) > 0 && (gover.ModCompare(m.Path, prev.Version, origV) < 0 || err != nil) { // previousVersion skipped over origV. Insert it into the order. prev.Version = origV @@ -515,13 +515,13 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel // The modules in mustSelect are always promoted to be explicit. for _, m := range mustSelect { - if m.Version != "none" && !LoaderState.MainModules.Contains(m.Path) { + if m.Version != "none" && !loaderstate.MainModules.Contains(m.Path) { rootPaths = append(rootPaths, m.Path) } } for _, m := range roots { - if v, ok := rs.rootSelected(m.Path); ok && (v == m.Version || rs.direct[m.Path]) { + if v, ok := rs.rootSelected(loaderstate, m.Path); ok && (v == m.Version || rs.direct[m.Path]) { // m.Path was formerly a root, and either its version hasn't changed or // we believe that it provides a package directly imported by a package // or test in the main module. For now we'll assume that it is still @@ -532,7 +532,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel } } - roots, err = mvs.Req(LoaderState.MainModules.mustGetSingleMainModule(), rootPaths, &mvsReqs{roots: roots}) + roots, err = mvs.Req(loaderstate.MainModules.mustGetSingleMainModule(loaderstate), rootPaths, &mvsReqs{roots: roots}) if err != nil { return nil, false, err } @@ -563,7 +563,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel direct[m.Path] = true } } - edited = newRequirements(rootPruning, roots, direct) + edited = newRequirements(loaderstate, rootPruning, roots, direct) // If we ended up adding a dependency that upgrades our go version far enough // to activate pruning, we must convert the edited Requirements in order to @@ -578,7 +578,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel // those two modules will never be downgraded due to a conflict with any other // constraint. if rootPruning == unpruned { - if v, ok := edited.rootSelected("go"); ok && pruningForGoVersion(v) == pruned { + if v, ok := edited.rootSelected(loaderstate, "go"); ok && pruningForGoVersion(v) == pruned { // Since we computed the edit with the unpruned graph, and the pruned // graph is a strict subset of the unpruned graph, this conversion // preserves the exact (edited) build list that we already computed. @@ -587,7 +587,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel // the graph. 'go get' will check for that sort of transition and log a // message reminding the user how to clean up this mess we're about to // make. 😅 - edited, err = convertPruning(ctx, edited, pruned) + edited, err = convertPruning(loaderstate, ctx, edited, pruned) if err != nil { return orig, false, err } @@ -607,9 +607,9 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel // The extended graph is useful for diagnosing version conflicts: for each // selected module version, it can provide a complete path of requirements from // some root to that version. -func extendGraph(ctx context.Context, rootPruning modPruning, roots []module.Version, selectedRoot map[string]string) (mg *ModuleGraph, upgradedRoot map[module.Version]bool, err error) { +func extendGraph(loaderstate *State, ctx context.Context, rootPruning modPruning, roots []module.Version, selectedRoot map[string]string) (mg *ModuleGraph, upgradedRoot map[module.Version]bool, err error) { for { - mg, err = readModGraph(ctx, rootPruning, roots, upgradedRoot) + mg, err = readModGraph(loaderstate, ctx, rootPruning, roots, upgradedRoot) // We keep on going even if err is non-nil until we reach a steady state. // (Note that readModGraph returns a non-nil *ModuleGraph even in case of // errors.) The caller may be able to fix the errors by adjusting versions, diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index 392fe3edd7..a2a98289b0 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -262,7 +262,7 @@ func (e *invalidImportError) Unwrap() error { // (https://go.dev/issue/56222) for modules with 'go' versions between 1.17 and // 1.20, preventing unnecessary go.sum churn and network access in those // modules. -func importFromModules(ctx context.Context, path string, rs *Requirements, mg *ModuleGraph, skipModFile bool) (m module.Version, modroot, dir string, altMods []module.Version, err error) { +func importFromModules(loaderstate *State, ctx context.Context, path string, rs *Requirements, mg *ModuleGraph, skipModFile bool) (m module.Version, modroot, dir string, altMods []module.Version, err error) { invalidf := func(format string, args ...interface{}) (module.Version, string, string, []module.Version, error) { return module.Version{}, "", "", nil, &invalidImportError{ importPath: path, @@ -299,12 +299,12 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // Is the package in the standard library? pathIsStd := search.IsStandardImportPath(path) if pathIsStd && modindex.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) { - for _, mainModule := range LoaderState.MainModules.Versions() { - if LoaderState.MainModules.InGorootSrc(mainModule) { - if dir, ok, err := dirInModule(path, LoaderState.MainModules.PathPrefix(mainModule), LoaderState.MainModules.ModRoot(mainModule), true); err != nil { - return module.Version{}, LoaderState.MainModules.ModRoot(mainModule), dir, nil, err + for _, mainModule := range loaderstate.MainModules.Versions() { + if loaderstate.MainModules.InGorootSrc(mainModule) { + if dir, ok, err := dirInModule(path, loaderstate.MainModules.PathPrefix(mainModule), loaderstate.MainModules.ModRoot(mainModule), true); err != nil { + return module.Version{}, loaderstate.MainModules.ModRoot(mainModule), dir, nil, err } else if ok { - return mainModule, LoaderState.MainModules.ModRoot(mainModule), dir, nil, nil + return mainModule, loaderstate.MainModules.ModRoot(mainModule), dir, nil, nil } } } @@ -321,10 +321,10 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // Everything must be in the main modules or the main module's or workspace's vendor directory. if cfg.BuildMod == "vendor" { var mainErr error - for _, mainModule := range LoaderState.MainModules.Versions() { - modRoot := LoaderState.MainModules.ModRoot(mainModule) + for _, mainModule := range loaderstate.MainModules.Versions() { + modRoot := loaderstate.MainModules.ModRoot(mainModule) if modRoot != "" { - dir, mainOK, err := dirInModule(path, LoaderState.MainModules.PathPrefix(mainModule), modRoot, true) + dir, mainOK, err := dirInModule(path, loaderstate.MainModules.PathPrefix(mainModule), modRoot, true) if mainErr == nil { mainErr = err } @@ -336,8 +336,8 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M } } - if HasModRoot() { - vendorDir := VendorDir() + if HasModRoot(loaderstate) { + vendorDir := VendorDir(loaderstate) dir, inVendorDir, _ := dirInModule(path, "", vendorDir, false) if inVendorDir { readVendorList(vendorDir) @@ -345,13 +345,13 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // vendor/modules.txt does not exist or the user manually added directories to the vendor directory. // Go 1.23 and later require vendored packages to be present in modules.txt to be imported. _, ok := vendorPkgModule[path] - if ok || (gover.Compare(LoaderState.MainModules.GoVersion(), gover.ExplicitModulesTxtImportVersion) < 0) { + if ok || (gover.Compare(loaderstate.MainModules.GoVersion(loaderstate), gover.ExplicitModulesTxtImportVersion) < 0) { mods = append(mods, vendorPkgModule[path]) dirs = append(dirs, dir) roots = append(roots, vendorDir) } else { subCommand := "mod" - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { subCommand = "work" } fmt.Fprintf(os.Stderr, "go: ignoring package %s which exists in the vendor directory but is missing from vendor/modules.txt. To sync the vendor directory run go %s vendor.\n", path, subCommand) @@ -399,7 +399,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M ok bool ) if mg == nil { - v, ok = rs.rootSelected(prefix) + v, ok = rs.rootSelected(loaderstate, prefix) } else { v, ok = mg.Selected(prefix), true } @@ -408,7 +408,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M } m := module.Version{Path: prefix, Version: v} - root, isLocal, err := fetch(ctx, m) + root, isLocal, err := fetch(loaderstate, ctx, m) if err != nil { if _, ok := errors.AsType[*sumMissingError](err); ok { // We are missing a sum needed to fetch a module in the build list. @@ -471,8 +471,8 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // If the module graph is pruned and this is a test-only dependency // of a package in "all", we didn't necessarily load that file // when we read the module graph, so do it now to be sure. - if !skipModFile && cfg.BuildMod != "vendor" && mods[0].Path != "" && !LoaderState.MainModules.Contains(mods[0].Path) { - if _, err := goModSummary(mods[0]); err != nil { + if !skipModFile && cfg.BuildMod != "vendor" && mods[0].Path != "" && !loaderstate.MainModules.Contains(mods[0].Path) { + if _, err := goModSummary(loaderstate, mods[0]); err != nil { return module.Version{}, "", "", nil, err } } @@ -483,7 +483,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // We checked the full module graph and still didn't find the // requested package. var queryErr error - if !HasModRoot() { + if !HasModRoot(loaderstate) { queryErr = ErrNoModRoot } return module.Version{}, "", "", nil, &ImportMissingError{Path: path, QueryErr: queryErr, isStd: pathIsStd} @@ -491,7 +491,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // So far we've checked the root dependencies. // Load the full module graph and try again. - mg, err = rs.Graph(ctx) + mg, err = rs.Graph(loaderstate, ctx) if err != nil { // We might be missing one or more transitive (implicit) dependencies from // the module graph, so we can't return an ImportMissingError here — one @@ -507,12 +507,12 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // // Unlike QueryPattern, queryImport prefers to add a replaced version of a // module *before* checking the proxies for a version to add. -func queryImport(ctx context.Context, path string, rs *Requirements) (module.Version, error) { +func queryImport(loaderstate *State, ctx context.Context, path string, rs *Requirements) (module.Version, error) { // To avoid spurious remote fetches, try the latest replacement for each // module (golang.org/issue/26241). var mods []module.Version - if LoaderState.MainModules != nil { // TODO(#48912): Ensure MainModules exists at this point, and remove the check. - for mp, mv := range LoaderState.MainModules.HighestReplaced() { + if loaderstate.MainModules != nil { // TODO(#48912): Ensure MainModules exists at this point, and remove the check. + for mp, mv := range loaderstate.MainModules.HighestReplaced() { if !maybeInModule(path, mp) { continue } @@ -528,7 +528,7 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver mv = module.ZeroPseudoVersion("v0") } } - mg, err := rs.Graph(ctx) + mg, err := rs.Graph(loaderstate, ctx) if err != nil { return module.Version{}, err } @@ -547,7 +547,7 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver return len(mods[i].Path) > len(mods[j].Path) }) for _, m := range mods { - root, isLocal, err := fetch(ctx, m) + root, isLocal, err := fetch(loaderstate, ctx, m) if err != nil { if _, ok := errors.AsType[*sumMissingError](err); ok { return module.Version{}, &ImportMissingSumError{importPath: path} @@ -567,7 +567,7 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver // The package path is not valid to fetch remotely, // so it can only exist in a replaced module, // and we know from the above loop that it is not. - replacement := Replacement(mods[0]) + replacement := Replacement(loaderstate, mods[0]) return module.Version{}, &PackageNotInModuleError{ Mod: mods[0], Query: "latest", @@ -607,12 +607,12 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver // and return m, dir, ImportMissingError. fmt.Fprintf(os.Stderr, "go: finding module for package %s\n", path) - mg, err := rs.Graph(ctx) + mg, err := rs.Graph(loaderstate, ctx) if err != nil { return module.Version{}, err } - candidates, err := QueryPackages(ctx, path, "latest", mg.Selected, CheckAllowed) + candidates, err := QueryPackages(loaderstate, ctx, path, "latest", mg.Selected, CheckAllowed) if err != nil { if errors.Is(err, fs.ErrNotExist) { // Return "cannot find module providing package […]" instead of whatever @@ -747,15 +747,15 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile // // The isLocal return value reports whether the replacement, // if any, is local to the filesystem. -func fetch(ctx context.Context, mod module.Version) (dir string, isLocal bool, err error) { - if modRoot := LoaderState.MainModules.ModRoot(mod); modRoot != "" { +func fetch(loaderstate *State, ctx context.Context, mod module.Version) (dir string, isLocal bool, err error) { + if modRoot := loaderstate.MainModules.ModRoot(mod); modRoot != "" { return modRoot, true, nil } - if r := Replacement(mod); r.Path != "" { + if r := Replacement(loaderstate, mod); r.Path != "" { if r.Version == "" { dir = r.Path if !filepath.IsAbs(dir) { - dir = filepath.Join(replaceRelativeTo(), dir) + dir = filepath.Join(replaceRelativeTo(loaderstate), dir) } // Ensure that the replacement directory actually exists: // dirInModule does not report errors for missing modules, @@ -780,7 +780,7 @@ func fetch(ctx context.Context, mod module.Version) (dir string, isLocal bool, e mod = r } - if mustHaveSums() && !modfetch.HaveSum(mod) { + if mustHaveSums(loaderstate) && !modfetch.HaveSum(mod) { return "", false, module.VersionError(mod, &sumMissingError{}) } @@ -790,8 +790,8 @@ func fetch(ctx context.Context, mod module.Version) (dir string, isLocal bool, e // mustHaveSums reports whether we require that all checksums // needed to load or build packages are already present in the go.sum file. -func mustHaveSums() bool { - return HasModRoot() && cfg.BuildMod == "readonly" && !inWorkspaceMode() +func mustHaveSums(loaderstate *State) bool { + return HasModRoot(loaderstate) && cfg.BuildMod == "readonly" && !inWorkspaceMode(loaderstate) } type sumMissingError struct { diff --git a/src/cmd/go/internal/modload/import_test.go b/src/cmd/go/internal/modload/import_test.go index f6b8bb9099..a5c4b837a0 100644 --- a/src/cmd/go/internal/modload/import_test.go +++ b/src/cmd/go/internal/modload/import_test.go @@ -69,12 +69,12 @@ func TestQueryImport(t *testing.T) { LoaderState.RootMode = NoRoot ctx := context.Background() - rs := LoadModFile(ctx) + rs := LoadModFile(LoaderState, ctx) for _, tt := range importTests { t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) { // Note that there is no build list, so Import should always fail. - m, err := queryImport(ctx, tt.path, rs) + m, err := queryImport(LoaderState, ctx, tt.path, rs) if tt.err == "" { if err != nil { diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 31fe632773..2075152886 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -64,7 +64,7 @@ func EnterModule(ctx context.Context, enterModroot string) { modfetch.Reset() LoaderState.modRoots = []string{enterModroot} - LoadModFile(ctx) + LoadModFile(LoaderState, ctx) } // EnterWorkspace enters workspace mode from module mode, applying the updated requirements to the main @@ -73,9 +73,9 @@ func EnterModule(ctx context.Context, enterModroot string) { // EnterWorkspace will modify the global state they depend on in a non-thread-safe way. func EnterWorkspace(ctx context.Context) (exit func(), err error) { // Find the identity of the main module that will be updated before we reset modload state. - mm := LoaderState.MainModules.mustGetSingleMainModule() + mm := LoaderState.MainModules.mustGetSingleMainModule(LoaderState) // Get the updated modfile we will use for that module. - _, _, updatedmodfile, err := UpdateGoModFromReqs(ctx, WriteOpts{}) + _, _, updatedmodfile, err := UpdateGoModFromReqs(LoaderState, ctx, WriteOpts{}) if err != nil { return nil, err } @@ -85,12 +85,12 @@ func EnterWorkspace(ctx context.Context) (exit func(), err error) { LoaderState.ForceUseModules = true // Load in workspace mode. - InitWorkfile() - LoadModFile(ctx) + InitWorkfile(LoaderState) + LoadModFile(LoaderState, ctx) // Update the content of the previous main module, and recompute the requirements. *LoaderState.MainModules.ModFile(mm) = *updatedmodfile - LoaderState.requirements = requirementsFromModFiles(ctx, LoaderState.MainModules.workFile, slices.Collect(maps.Values(LoaderState.MainModules.modFiles)), nil) + LoaderState.requirements = requirementsFromModFiles(LoaderState, ctx, LoaderState.MainModules.workFile, slices.Collect(maps.Values(LoaderState.MainModules.modFiles)), nil) return func() { setState(oldstate) @@ -182,12 +182,12 @@ func (mms *MainModuleSet) InGorootSrc(m module.Version) bool { return mms.inGorootSrc[m] } -func (mms *MainModuleSet) mustGetSingleMainModule() module.Version { +func (mms *MainModuleSet) mustGetSingleMainModule(loaderstate *State) module.Version { if mms == nil || len(mms.versions) == 0 { panic("internal error: mustGetSingleMainModule called in context with no main modules") } if len(mms.versions) != 1 { - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { panic("internal error: mustGetSingleMainModule called in workspace mode") } else { panic("internal error: multiple main modules present outside of workspace mode") @@ -196,14 +196,14 @@ func (mms *MainModuleSet) mustGetSingleMainModule() module.Version { return mms.versions[0] } -func (mms *MainModuleSet) GetSingleIndexOrNil() *modFileIndex { +func (mms *MainModuleSet) GetSingleIndexOrNil(loaderstate *State) *modFileIndex { if mms == nil { return nil } if len(mms.versions) == 0 { return nil } - return mms.indices[mms.mustGetSingleMainModule()] + return mms.indices[mms.mustGetSingleMainModule(loaderstate)] } func (mms *MainModuleSet) Index(m module.Version) *modFileIndex { @@ -246,12 +246,12 @@ func (mms *MainModuleSet) HighestReplaced() map[string]string { // GoVersion returns the go version set on the single module, in module mode, // or the go.work file in workspace mode. -func (mms *MainModuleSet) GoVersion() string { - if inWorkspaceMode() { +func (mms *MainModuleSet) GoVersion(loaderstate *State) string { + if inWorkspaceMode(loaderstate) { return gover.FromGoWork(mms.workFile) } if mms != nil && len(mms.versions) == 1 { - f := mms.ModFile(mms.mustGetSingleMainModule()) + f := mms.ModFile(mms.mustGetSingleMainModule(loaderstate)) if f == nil { // Special case: we are outside a module, like 'go run x.go'. // Assume the local Go version. @@ -266,15 +266,15 @@ func (mms *MainModuleSet) GoVersion() string { // Godebugs returns the godebug lines set on the single module, in module mode, // or on the go.work file in workspace mode. // The caller must not modify the result. -func (mms *MainModuleSet) Godebugs() []*modfile.Godebug { - if inWorkspaceMode() { +func (mms *MainModuleSet) Godebugs(loaderstate *State) []*modfile.Godebug { + if inWorkspaceMode(loaderstate) { if mms.workFile != nil { return mms.workFile.Godebug } return nil } if mms != nil && len(mms.versions) == 1 { - f := mms.ModFile(mms.mustGetSingleMainModule()) + f := mms.ModFile(mms.mustGetSingleMainModule(loaderstate)) if f == nil { // Special case: we are outside a module, like 'go run x.go'. return nil @@ -315,16 +315,16 @@ const ( // To make permanent changes to the require statements // in go.mod, edit it before loading. func ModFile() *modfile.File { - Init() - modFile := LoaderState.MainModules.ModFile(LoaderState.MainModules.mustGetSingleMainModule()) + Init(LoaderState) + modFile := LoaderState.MainModules.ModFile(LoaderState.MainModules.mustGetSingleMainModule(LoaderState)) if modFile == nil { - die() + die(LoaderState) } return modFile } -func BinDir() string { - Init() +func BinDir(loaderstate *State) string { + Init(loaderstate) if cfg.GOBIN != "" { return cfg.GOBIN } @@ -337,13 +337,13 @@ func BinDir() string { // InitWorkfile initializes the workFilePath variable for commands that // operate in workspace mode. It should not be called by other commands, // for example 'go mod tidy', that don't operate in workspace mode. -func InitWorkfile() { +func InitWorkfile(loaderstate *State) { // Initialize fsys early because we need overlay to read go.work file. fips140.Init() if err := fsys.Init(); err != nil { base.Fatal(err) } - LoaderState.workFilePath = FindGoWork(base.Cwd()) + loaderstate.workFilePath = FindGoWork(loaderstate, base.Cwd()) } // FindGoWork returns the name of the go.work file for this command, @@ -351,8 +351,8 @@ func InitWorkfile() { // Most code should use Init and Enabled rather than use this directly. // It is exported mainly for Go toolchain switching, which must process // the go.work very early at startup. -func FindGoWork(wd string) string { - if LoaderState.RootMode == NoRoot { +func FindGoWork(loaderstate *State, wd string) string { + if loaderstate.RootMode == NoRoot { return "" } @@ -371,8 +371,8 @@ func FindGoWork(wd string) string { // WorkFilePath returns the absolute path of the go.work file, or "" if not in // workspace mode. WorkFilePath must be called after InitWorkfile. -func WorkFilePath() string { - return LoaderState.workFilePath +func WorkFilePath(loaderstate *State) string { + return loaderstate.workFilePath } // Reset clears all the initialized, cached state about the use of modules, @@ -451,11 +451,11 @@ var LoaderState = NewState() // current module (if any), sets environment variables for Git subprocesses, and // configures the cfg, codehost, load, modfetch, and search packages for use // with modules. -func Init() { - if LoaderState.initialized { +func Init(loaderstate *State) { + if loaderstate.initialized { return } - LoaderState.initialized = true + loaderstate.initialized = true fips140.Init() @@ -468,11 +468,11 @@ func Init() { default: base.Fatalf("go: unknown environment setting GO111MODULE=%s", env) case "auto": - mustUseModules = LoaderState.ForceUseModules + mustUseModules = loaderstate.ForceUseModules case "on", "": mustUseModules = true case "off": - if LoaderState.ForceUseModules { + if loaderstate.ForceUseModules { base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'") } mustUseModules = false @@ -496,15 +496,15 @@ func Init() { if os.Getenv("GCM_INTERACTIVE") == "" { os.Setenv("GCM_INTERACTIVE", "never") } - if LoaderState.modRoots != nil { + if loaderstate.modRoots != nil { // modRoot set before Init was called ("go mod init" does this). // No need to search for go.mod. - } else if LoaderState.RootMode == NoRoot { + } else if loaderstate.RootMode == NoRoot { if cfg.ModFile != "" && !base.InGOFLAGS("-modfile") { base.Fatalf("go: -modfile cannot be used with commands that ignore the current module") } - LoaderState.modRoots = nil - } else if LoaderState.workFilePath != "" { + loaderstate.modRoots = nil + } else if loaderstate.workFilePath != "" { // We're in workspace mode, which implies module mode. if cfg.ModFile != "" { base.Fatalf("go: -modfile cannot be used in workspace mode") @@ -514,7 +514,7 @@ func Init() { if cfg.ModFile != "" { base.Fatalf("go: cannot find main module, but -modfile was set.\n\t-modfile cannot be used to set the module root directory.") } - if LoaderState.RootMode == NeedRoot { + if loaderstate.RootMode == NeedRoot { base.Fatal(ErrNoModRoot) } if !mustUseModules { @@ -529,14 +529,14 @@ func Init() { // It's a bit of a peculiar thing to disallow but quite mysterious // when it happens. See golang.org/issue/26708. fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in system temp root %v\n", os.TempDir()) - if LoaderState.RootMode == NeedRoot { + if loaderstate.RootMode == NeedRoot { base.Fatal(ErrNoModRoot) } if !mustUseModules { return } } else { - LoaderState.modRoots = []string{modRoot} + loaderstate.modRoots = []string{modRoot} } } if cfg.ModFile != "" && !strings.HasSuffix(cfg.ModFile, ".mod") { @@ -545,13 +545,13 @@ func Init() { // We're in module mode. Set any global variables that need to be set. cfg.ModulesEnabled = true - setDefaultBuildMod() + setDefaultBuildMod(loaderstate) list := filepath.SplitList(cfg.BuildContext.GOPATH) if len(list) > 0 && list[0] != "" { gopath = list[0] if _, err := fsys.Stat(filepath.Join(gopath, "go.mod")); err == nil { fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in $GOPATH %v\n", gopath) - if LoaderState.RootMode == NeedRoot { + if loaderstate.RootMode == NeedRoot { base.Fatal(ErrNoModRoot) } if !mustUseModules { @@ -622,49 +622,49 @@ func FindGoMod(wd string) string { // If modules are enabled but there is no main module, Enabled returns true // and then the first use of module information will call die // (usually through MustModRoot). -func Enabled() bool { - Init() - return LoaderState.modRoots != nil || cfg.ModulesEnabled +func Enabled(loaderstate *State) bool { + Init(loaderstate) + return loaderstate.modRoots != nil || cfg.ModulesEnabled } -func VendorDir() string { - if inWorkspaceMode() { - return filepath.Join(filepath.Dir(WorkFilePath()), "vendor") +func VendorDir(loaderstate *State) string { + if inWorkspaceMode(loaderstate) { + return filepath.Join(filepath.Dir(WorkFilePath(loaderstate)), "vendor") } // Even if -mod=vendor, we could be operating with no mod root (and thus no // vendor directory). As long as there are no dependencies that is expected // to work. See script/vendor_outside_module.txt. - modRoot := LoaderState.MainModules.ModRoot(LoaderState.MainModules.mustGetSingleMainModule()) + modRoot := loaderstate.MainModules.ModRoot(loaderstate.MainModules.mustGetSingleMainModule(loaderstate)) if modRoot == "" { panic("vendor directory does not exist when in single module mode outside of a module") } return filepath.Join(modRoot, "vendor") } -func inWorkspaceMode() bool { - if !LoaderState.initialized { +func inWorkspaceMode(loaderstate *State) bool { + if !loaderstate.initialized { panic("inWorkspaceMode called before modload.Init called") } - if !Enabled() { + if !Enabled(loaderstate) { return false } - return LoaderState.workFilePath != "" + return loaderstate.workFilePath != "" } // HasModRoot reports whether a main module or main modules are present. // HasModRoot may return false even if Enabled returns true: for example, 'get' // does not require a main module. -func HasModRoot() bool { - Init() - return LoaderState.modRoots != nil +func HasModRoot(loaderstate *State) bool { + Init(loaderstate) + return loaderstate.modRoots != nil } // MustHaveModRoot checks that a main module or main modules are present, // and calls base.Fatalf if there are no main modules. func MustHaveModRoot() { - Init() - if !HasModRoot() { - die() + Init(LoaderState) + if !HasModRoot(LoaderState) { + die(LoaderState) } } @@ -686,11 +686,11 @@ func modFilePath(modRoot string) string { return filepath.Join(modRoot, "go.mod") } -func die() { +func die(loaderstate *State) { if cfg.Getenv("GO111MODULE") == "off" { base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'") } - if !inWorkspaceMode() { + if !inWorkspaceMode(loaderstate) { if dir, name := findAltConfig(base.Cwd()); dir != "" { rel, err := filepath.Rel(base.Cwd(), dir) if err != nil { @@ -711,7 +711,7 @@ func die() { type noMainModulesError struct{} func (e noMainModulesError) Error() string { - if inWorkspaceMode() { + if inWorkspaceMode(LoaderState) { return "no modules were found in the current workspace; see 'go help work'" } return "go.mod file not found in current directory or any parent directory; see 'go help modules'" @@ -868,33 +868,33 @@ func UpdateWorkFile(wf *modfile.WorkFile) { // other, but unlike LoadModGraph does not load the full module graph or check // it for global consistency. Most callers outside of the modload package should // use LoadModGraph instead. -func LoadModFile(ctx context.Context) *Requirements { - rs, err := loadModFile(ctx, nil) +func LoadModFile(loaderstate *State, ctx context.Context) *Requirements { + rs, err := loadModFile(loaderstate, ctx, nil) if err != nil { base.Fatal(err) } return rs } -func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) { - if LoaderState.requirements != nil { - return LoaderState.requirements, nil +func loadModFile(loaderstate *State, ctx context.Context, opts *PackageOpts) (*Requirements, error) { + if loaderstate.requirements != nil { + return loaderstate.requirements, nil } - Init() + Init(loaderstate) var workFile *modfile.WorkFile - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { var err error - workFile, LoaderState.modRoots, err = LoadWorkFile(LoaderState.workFilePath) + workFile, loaderstate.modRoots, err = LoadWorkFile(loaderstate.workFilePath) if err != nil { return nil, err } - for _, modRoot := range LoaderState.modRoots { + for _, modRoot := range loaderstate.modRoots { sumFile := strings.TrimSuffix(modFilePath(modRoot), ".mod") + ".sum" modfetch.WorkspaceGoSumFiles = append(modfetch.WorkspaceGoSumFiles, sumFile) } - modfetch.GoSumFile = LoaderState.workFilePath + ".sum" - } else if len(LoaderState.modRoots) == 0 { + modfetch.GoSumFile = loaderstate.workFilePath + ".sum" + } else if len(loaderstate.modRoots) == 0 { // We're in module mode, but not inside a module. // // Commands like 'go build', 'go run', 'go list' have no go.mod file to @@ -913,25 +913,25 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) // // See golang.org/issue/32027. } else { - modfetch.GoSumFile = strings.TrimSuffix(modFilePath(LoaderState.modRoots[0]), ".mod") + ".sum" + modfetch.GoSumFile = strings.TrimSuffix(modFilePath(loaderstate.modRoots[0]), ".mod") + ".sum" } - if len(LoaderState.modRoots) == 0 { + if len(loaderstate.modRoots) == 0 { // TODO(#49228): Instead of creating a fake module with an empty modroot, // make MainModules.Len() == 0 mean that we're in module mode but not inside // any module. mainModule := module.Version{Path: "command-line-arguments"} - LoaderState.MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, nil) + loaderstate.MainModules = makeMainModules(loaderstate, []module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, nil) var ( goVersion string pruning modPruning roots []module.Version direct = map[string]bool{"go": true} ) - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { // Since we are in a workspace, the Go version for the synthetic // "command-line-arguments" module must not exceed the Go version // for the workspace. - goVersion = LoaderState.MainModules.GoVersion() + goVersion = loaderstate.MainModules.GoVersion(loaderstate) pruning = workspace roots = []module.Version{ mainModule, @@ -947,26 +947,26 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) } } rawGoVersion.Store(mainModule, goVersion) - LoaderState.requirements = newRequirements(pruning, roots, direct) + loaderstate.requirements = newRequirements(loaderstate, pruning, roots, direct) if cfg.BuildMod == "vendor" { // For issue 56536: Some users may have GOFLAGS=-mod=vendor set. // Make sure it behaves as though the fake module is vendored // with no dependencies. - LoaderState.requirements.initVendor(nil) + loaderstate.requirements.initVendor(loaderstate, nil) } - return LoaderState.requirements, nil + return loaderstate.requirements, nil } var modFiles []*modfile.File var mainModules []module.Version var indices []*modFileIndex var errs []error - for _, modroot := range LoaderState.modRoots { + for _, modroot := range loaderstate.modRoots { gomod := modFilePath(modroot) var fixed bool - data, f, err := ReadModFile(gomod, fixVersion(ctx, &fixed)) + data, f, err := ReadModFile(gomod, fixVersion(loaderstate, ctx, &fixed)) if err != nil { - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { if tooNew, ok := err.(*gover.TooNewError); ok && !strings.HasPrefix(cfg.CmdName, "work ") { // Switching to a newer toolchain won't help - the go.work has the wrong version. // Report this more specific error, unless we are a command like 'go work use' @@ -981,7 +981,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) errs = append(errs, err) continue } - if inWorkspaceMode() && !strings.HasPrefix(cfg.CmdName, "work ") { + if inWorkspaceMode(loaderstate) && !strings.HasPrefix(cfg.CmdName, "work ") { // Refuse to use workspace if its go version is too old. // Disable this check if we are a workspace command like work use or work sync, // which will fix the problem. @@ -993,7 +993,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) } } - if !inWorkspaceMode() { + if !inWorkspaceMode(loaderstate) { ok := true for _, g := range f.Godebug { if err := CheckGodebug("godebug", g.Key, g.Value); err != nil { @@ -1022,45 +1022,45 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) return nil, errors.Join(errs...) } - LoaderState.MainModules = makeMainModules(mainModules, LoaderState.modRoots, modFiles, indices, workFile) - setDefaultBuildMod() // possibly enable automatic vendoring - rs := requirementsFromModFiles(ctx, workFile, modFiles, opts) + loaderstate.MainModules = makeMainModules(loaderstate, mainModules, loaderstate.modRoots, modFiles, indices, workFile) + setDefaultBuildMod(loaderstate) // possibly enable automatic vendoring + rs := requirementsFromModFiles(loaderstate, ctx, workFile, modFiles, opts) if cfg.BuildMod == "vendor" { - readVendorList(VendorDir()) - versions := LoaderState.MainModules.Versions() + readVendorList(VendorDir(loaderstate)) + versions := loaderstate.MainModules.Versions() indexes := make([]*modFileIndex, 0, len(versions)) modFiles := make([]*modfile.File, 0, len(versions)) modRoots := make([]string, 0, len(versions)) for _, m := range versions { - indexes = append(indexes, LoaderState.MainModules.Index(m)) - modFiles = append(modFiles, LoaderState.MainModules.ModFile(m)) - modRoots = append(modRoots, LoaderState.MainModules.ModRoot(m)) + indexes = append(indexes, loaderstate.MainModules.Index(m)) + modFiles = append(modFiles, loaderstate.MainModules.ModFile(m)) + modRoots = append(modRoots, loaderstate.MainModules.ModRoot(m)) } - checkVendorConsistency(indexes, modFiles, modRoots) - rs.initVendor(vendorList) + checkVendorConsistency(loaderstate, indexes, modFiles, modRoots) + rs.initVendor(loaderstate, vendorList) } - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { // We don't need to update the mod file so return early. - LoaderState.requirements = rs + loaderstate.requirements = rs return rs, nil } - mainModule := LoaderState.MainModules.mustGetSingleMainModule() + mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate) - if rs.hasRedundantRoot() { + if rs.hasRedundantRoot(loaderstate) { // If any module path appears more than once in the roots, we know that the // go.mod file needs to be updated even though we have not yet loaded any // transitive dependencies. var err error - rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false) + rs, err = updateRoots(loaderstate, ctx, rs.direct, rs, nil, nil, false) if err != nil { return nil, err } } - if LoaderState.MainModules.Index(mainModule).goVersion == "" && rs.pruning != workspace { + if loaderstate.MainModules.Index(mainModule).goVersion == "" && rs.pruning != workspace { // TODO(#45551): Do something more principled instead of checking // cfg.CmdName directly here. if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" { @@ -1069,8 +1069,8 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) if opts != nil && opts.TidyGoVersion != "" { v = opts.TidyGoVersion } - addGoStmt(LoaderState.MainModules.ModFile(mainModule), mainModule, v) - rs = overrideRoots(ctx, rs, []module.Version{{Path: "go", Version: v}}) + addGoStmt(loaderstate.MainModules.ModFile(mainModule), mainModule, v) + rs = overrideRoots(loaderstate, ctx, rs, []module.Version{{Path: "go", Version: v}}) // We need to add a 'go' version to the go.mod file, but we must assume // that its existing contents match something between Go 1.11 and 1.16. @@ -1079,7 +1079,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) // requirements to support pruning. if gover.Compare(v, gover.ExplicitIndirectVersion) >= 0 { var err error - rs, err = convertPruning(ctx, rs, pruned) + rs, err = convertPruning(loaderstate, ctx, rs, pruned) if err != nil { return nil, err } @@ -1089,8 +1089,8 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) } } - LoaderState.requirements = rs - return LoaderState.requirements, nil + loaderstate.requirements = rs + return loaderstate.requirements, nil } func errWorkTooOld(gomod string, wf *modfile.WorkFile, goVers string) error { @@ -1126,7 +1126,7 @@ func CheckReservedModulePath(path string) error { func CreateModFile(ctx context.Context, modPath string) { modRoot := base.Cwd() LoaderState.modRoots = []string{modRoot} - Init() + Init(LoaderState) modFilePath := modFilePath(modRoot) if _, err := fsys.Stat(modFilePath); err == nil { base.Fatalf("go: %s already exists", modFilePath) @@ -1162,16 +1162,16 @@ func CreateModFile(ctx context.Context, modPath string) { fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath) modFile := new(modfile.File) modFile.AddModuleStmt(modPath) - LoaderState.MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}, nil) + LoaderState.MainModules = makeMainModules(LoaderState, []module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}, nil) addGoStmt(modFile, modFile.Module.Mod, gover.Local()) // Add the go directive before converted module requirements. - rs := requirementsFromModFiles(ctx, nil, []*modfile.File{modFile}, nil) - rs, err := updateRoots(ctx, rs.direct, rs, nil, nil, false) + rs := requirementsFromModFiles(LoaderState, ctx, nil, []*modfile.File{modFile}, nil) + rs, err := updateRoots(LoaderState, ctx, rs.direct, rs, nil, nil, false) if err != nil { base.Fatal(err) } LoaderState.requirements = rs - if err := commitRequirements(ctx, WriteOpts{}); err != nil { + if err := commitRequirements(LoaderState, ctx, WriteOpts{}); err != nil { base.Fatal(err) } @@ -1206,7 +1206,7 @@ func CreateModFile(ctx context.Context, modPath string) { // and does nothing for versions that already appear to be canonical. // // The VersionFixer sets 'fixed' if it ever returns a non-canonical version. -func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer { +func fixVersion(loaderstate *State, ctx context.Context, fixed *bool) modfile.VersionFixer { return func(path, vers string) (resolved string, err error) { defer func() { if err == nil && resolved != vers { @@ -1239,7 +1239,7 @@ func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer { return vers, nil } - info, err := Query(ctx, path, vers, "", nil) + info, err := Query(loaderstate, ctx, path, vers, "", nil) if err != nil { return "", err } @@ -1254,8 +1254,8 @@ func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer { // // This function affects the default cfg.BuildMod when outside of a module, // so it can only be called prior to Init. -func AllowMissingModuleImports() { - if LoaderState.initialized { +func AllowMissingModuleImports(loaderstate *State) { + if loaderstate.initialized { panic("AllowMissingModuleImports after Init") } allowMissingModuleImports = true @@ -1263,7 +1263,7 @@ func AllowMissingModuleImports() { // makeMainModules creates a MainModuleSet and associated variables according to // the given main modules. -func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex, workFile *modfile.WorkFile) *MainModuleSet { +func makeMainModules(loaderstate *State, ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex, workFile *modfile.WorkFile) *MainModuleSet { for _, m := range ms { if m.Version != "" { panic("mainModulesCalled with module.Version with non empty Version field: " + fmt.Sprintf("%#v", m)) @@ -1338,7 +1338,7 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile continue } var newV module.Version = r.New - if WorkFilePath() != "" && newV.Version == "" && !filepath.IsAbs(newV.Path) { + if WorkFilePath(loaderstate) != "" && newV.Version == "" && !filepath.IsAbs(newV.Path) { // Since we are in a workspace, we may be loading replacements from // multiple go.mod files. Relative paths in those replacement are // relative to the go.mod file, not the workspace, so the same string @@ -1380,14 +1380,14 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile // requirementsFromModFiles returns the set of non-excluded requirements from // the global modFile. -func requirementsFromModFiles(ctx context.Context, workFile *modfile.WorkFile, modFiles []*modfile.File, opts *PackageOpts) *Requirements { +func requirementsFromModFiles(loaderstate *State, ctx context.Context, workFile *modfile.WorkFile, modFiles []*modfile.File, opts *PackageOpts) *Requirements { var roots []module.Version direct := map[string]bool{} var pruning modPruning - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { pruning = workspace - roots = make([]module.Version, len(LoaderState.MainModules.Versions()), 2+len(LoaderState.MainModules.Versions())) - copy(roots, LoaderState.MainModules.Versions()) + roots = make([]module.Version, len(loaderstate.MainModules.Versions()), 2+len(loaderstate.MainModules.Versions())) + copy(roots, loaderstate.MainModules.Versions()) goVersion := gover.FromGoWork(workFile) var toolchain string if workFile.Toolchain != nil { @@ -1396,16 +1396,16 @@ func requirementsFromModFiles(ctx context.Context, workFile *modfile.WorkFile, m roots = appendGoAndToolchainRoots(roots, goVersion, toolchain, direct) direct = directRequirements(modFiles) } else { - pruning = pruningForGoVersion(LoaderState.MainModules.GoVersion()) + pruning = pruningForGoVersion(loaderstate.MainModules.GoVersion(loaderstate)) if len(modFiles) != 1 { panic(fmt.Errorf("requirementsFromModFiles called with %v modfiles outside workspace mode", len(modFiles))) } modFile := modFiles[0] - roots, direct = rootsFromModFile(LoaderState.MainModules.mustGetSingleMainModule(), modFile, withToolchainRoot) + roots, direct = rootsFromModFile(loaderstate, loaderstate.MainModules.mustGetSingleMainModule(loaderstate), modFile, withToolchainRoot) } gover.ModSort(roots) - rs := newRequirements(pruning, roots, direct) + rs := newRequirements(loaderstate, pruning, roots, direct) return rs } @@ -1428,7 +1428,7 @@ func directRequirements(modFiles []*modfile.File) map[string]bool { return direct } -func rootsFromModFile(m module.Version, modFile *modfile.File, addToolchainRoot addToolchainRoot) (roots []module.Version, direct map[string]bool) { +func rootsFromModFile(loaderstate *State, m module.Version, modFile *modfile.File, addToolchainRoot addToolchainRoot) (roots []module.Version, direct map[string]bool) { direct = make(map[string]bool) padding := 2 // Add padding for the toolchain and go version, added upon return. if !addToolchainRoot { @@ -1436,7 +1436,7 @@ func rootsFromModFile(m module.Version, modFile *modfile.File, addToolchainRoot } roots = make([]module.Version, 0, padding+len(modFile.Require)) for _, r := range modFile.Require { - if index := LoaderState.MainModules.Index(m); index != nil && index.exclude[r.Mod] { + if index := loaderstate.MainModules.Index(m); index != nil && index.exclude[r.Mod] { if cfg.BuildMod == "mod" { fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) } else { @@ -1477,9 +1477,9 @@ func appendGoAndToolchainRoots(roots []module.Version, goVersion, toolchain stri // setDefaultBuildMod sets a default value for cfg.BuildMod if the -mod flag // wasn't provided. setDefaultBuildMod may be called multiple times. -func setDefaultBuildMod() { +func setDefaultBuildMod(loaderstate *State) { if cfg.BuildModExplicit { - if inWorkspaceMode() && cfg.BuildMod != "readonly" && cfg.BuildMod != "vendor" { + if inWorkspaceMode(loaderstate) && cfg.BuildMod != "readonly" && cfg.BuildMod != "vendor" { switch cfg.CmdName { case "work sync", "mod graph", "mod verify", "mod why": // These commands run with BuildMod set to mod, but they don't take the @@ -1514,7 +1514,7 @@ func setDefaultBuildMod() { cfg.BuildMod = "readonly" return } - if LoaderState.modRoots == nil { + if loaderstate.modRoots == nil { if allowMissingModuleImports { cfg.BuildMod = "mod" } else { @@ -1523,29 +1523,29 @@ func setDefaultBuildMod() { return } - if len(LoaderState.modRoots) >= 1 { + if len(loaderstate.modRoots) >= 1 { var goVersion string var versionSource string - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { versionSource = "go.work" - if wfg := LoaderState.MainModules.WorkFile().Go; wfg != nil { + if wfg := loaderstate.MainModules.WorkFile().Go; wfg != nil { goVersion = wfg.Version } } else { versionSource = "go.mod" - index := LoaderState.MainModules.GetSingleIndexOrNil() + index := loaderstate.MainModules.GetSingleIndexOrNil(loaderstate) if index != nil { goVersion = index.goVersion } } vendorDir := "" - if LoaderState.workFilePath != "" { - vendorDir = filepath.Join(filepath.Dir(LoaderState.workFilePath), "vendor") + if loaderstate.workFilePath != "" { + vendorDir = filepath.Join(filepath.Dir(loaderstate.workFilePath), "vendor") } else { - if len(LoaderState.modRoots) != 1 { - panic(fmt.Errorf("outside workspace mode, but have %v modRoots", LoaderState.modRoots)) + if len(loaderstate.modRoots) != 1 { + panic(fmt.Errorf("outside workspace mode, but have %v modRoots", loaderstate.modRoots)) } - vendorDir = filepath.Join(LoaderState.modRoots[0], "vendor") + vendorDir = filepath.Join(loaderstate.modRoots[0], "vendor") } if fi, err := fsys.Stat(vendorDir); err == nil && fi.IsDir() { if goVersion != "" { @@ -1613,8 +1613,8 @@ func modulesTextIsForWorkspace(vendorDir string) (bool, error) { return false, nil } -func mustHaveCompleteRequirements() bool { - return cfg.BuildMod != "mod" && !inWorkspaceMode() +func mustHaveCompleteRequirements(loaderstate *State) bool { + return cfg.BuildMod != "mod" && !inWorkspaceMode(loaderstate) } // addGoStmt adds a go directive to the go.mod file if it does not already @@ -1809,21 +1809,21 @@ type WriteOpts struct { // WriteGoMod writes the current build list back to go.mod. func WriteGoMod(ctx context.Context, opts WriteOpts) error { - LoaderState.requirements = LoadModFile(ctx) - return commitRequirements(ctx, opts) + LoaderState.requirements = LoadModFile(LoaderState, ctx) + return commitRequirements(LoaderState, ctx, opts) } var errNoChange = errors.New("no update needed") // UpdateGoModFromReqs returns a modified go.mod file using the current // requirements. It does not commit these changes to disk. -func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []byte, modFile *modfile.File, err error) { - if LoaderState.MainModules.Len() != 1 || LoaderState.MainModules.ModRoot(LoaderState.MainModules.Versions()[0]) == "" { +func UpdateGoModFromReqs(loaderstate *State, ctx context.Context, opts WriteOpts) (before, after []byte, modFile *modfile.File, err error) { + if loaderstate.MainModules.Len() != 1 || loaderstate.MainModules.ModRoot(loaderstate.MainModules.Versions()[0]) == "" { // We aren't in a module, so we don't have anywhere to write a go.mod file. return nil, nil, nil, errNoChange } - mainModule := LoaderState.MainModules.mustGetSingleMainModule() - modFile = LoaderState.MainModules.ModFile(mainModule) + mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate) + modFile = loaderstate.MainModules.ModFile(mainModule) if modFile == nil { // command-line-arguments has no .mod file to write. return nil, nil, nil, errNoChange @@ -1836,7 +1836,7 @@ func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []b var list []*modfile.Require toolchain := "" goVersion := "" - for _, m := range LoaderState.requirements.rootModules { + for _, m := range loaderstate.requirements.rootModules { if m.Path == "go" { goVersion = m.Version continue @@ -1847,7 +1847,7 @@ func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []b } list = append(list, &modfile.Require{ Mod: m, - Indirect: !LoaderState.requirements.direct[m.Path], + Indirect: !loaderstate.requirements.direct[m.Path], }) } @@ -1917,13 +1917,13 @@ func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []b // go.mod or go.sum are out of date in a semantically significant way. // // In workspace mode, commitRequirements only writes changes to go.work.sum. -func commitRequirements(ctx context.Context, opts WriteOpts) (err error) { - if inWorkspaceMode() { +func commitRequirements(loaderstate *State, ctx context.Context, opts WriteOpts) (err error) { + if inWorkspaceMode(loaderstate) { // go.mod files aren't updated in workspace mode, but we still want to // update the go.work.sum file. - return modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums), mustHaveCompleteRequirements()) + return modfetch.WriteGoSum(ctx, keepSums(loaderstate, ctx, loaded, loaderstate.requirements, addBuildListZipSums), mustHaveCompleteRequirements(loaderstate)) } - _, updatedGoMod, modFile, err := UpdateGoModFromReqs(ctx, opts) + _, updatedGoMod, modFile, err := UpdateGoModFromReqs(loaderstate, ctx, opts) if err != nil { if errors.Is(err, errNoChange) { return nil @@ -1931,7 +1931,7 @@ func commitRequirements(ctx context.Context, opts WriteOpts) (err error) { return err } - index := LoaderState.MainModules.GetSingleIndexOrNil() + index := loaderstate.MainModules.GetSingleIndexOrNil(loaderstate) dirty := index.modFileIsDirty(modFile) || len(opts.DropTools) > 0 || len(opts.AddTools) > 0 if dirty && cfg.BuildMod != "mod" { // If we're about to fail due to -mod=readonly, @@ -1945,15 +1945,15 @@ func commitRequirements(ctx context.Context, opts WriteOpts) (err error) { // Don't write go.mod, but write go.sum in case we added or trimmed sums. // 'go mod init' shouldn't write go.sum, since it will be incomplete. if cfg.CmdName != "mod init" { - if err := modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { + if err := modfetch.WriteGoSum(ctx, keepSums(loaderstate, ctx, loaded, loaderstate.requirements, addBuildListZipSums), mustHaveCompleteRequirements(loaderstate)); err != nil { return err } } return nil } - mainModule := LoaderState.MainModules.mustGetSingleMainModule() - modFilePath := modFilePath(LoaderState.MainModules.ModRoot(mainModule)) + mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate) + modFilePath := modFilePath(loaderstate.MainModules.ModRoot(mainModule)) if fsys.Replaced(modFilePath) { if dirty { return errors.New("updates to go.mod needed, but go.mod is part of the overlay specified with -overlay") @@ -1962,13 +1962,13 @@ func commitRequirements(ctx context.Context, opts WriteOpts) (err error) { } defer func() { // At this point we have determined to make the go.mod file on disk equal to new. - LoaderState.MainModules.SetIndex(mainModule, indexModFile(updatedGoMod, modFile, mainModule, false)) + loaderstate.MainModules.SetIndex(mainModule, indexModFile(updatedGoMod, modFile, mainModule, false)) // Update go.sum after releasing the side lock and refreshing the index. // 'go mod init' shouldn't write go.sum, since it will be incomplete. if cfg.CmdName != "mod init" { if err == nil { - err = modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums), mustHaveCompleteRequirements()) + err = modfetch.WriteGoSum(ctx, keepSums(loaderstate, ctx, loaded, loaderstate.requirements, addBuildListZipSums), mustHaveCompleteRequirements(loaderstate)) } } }() @@ -2011,7 +2011,7 @@ func commitRequirements(ctx context.Context, opts WriteOpts) (err error) { // including any go.mod files needed to reconstruct the MVS result // or identify go versions, // in addition to the checksums for every module in keepMods. -func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums) map[module.Version]bool { +func keepSums(loaderstate *State, ctx context.Context, ld *loader, rs *Requirements, which whichSums) map[module.Version]bool { // Every module in the full module graph contributes its requirements, // so in order to ensure that the build list itself is reproducible, // we need sums for every go.mod in the graph (regardless of whether @@ -2024,12 +2024,12 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums // ambiguous import errors the next time we load the package. keepModSumsForZipSums := true if ld == nil { - if gover.Compare(LoaderState.MainModules.GoVersion(), gover.TidyGoModSumVersion) < 0 && cfg.BuildMod != "mod" { + if gover.Compare(loaderstate.MainModules.GoVersion(loaderstate), gover.TidyGoModSumVersion) < 0 && cfg.BuildMod != "mod" { keepModSumsForZipSums = false } } else { keepPkgGoModSums := true - if gover.Compare(ld.requirements.GoVersion(), gover.TidyGoModSumVersion) < 0 && (ld.Tidy || cfg.BuildMod != "mod") { + if gover.Compare(ld.requirements.GoVersion(loaderstate), gover.TidyGoModSumVersion) < 0 && (ld.Tidy || cfg.BuildMod != "mod") { keepPkgGoModSums = false keepModSumsForZipSums = false } @@ -2047,21 +2047,21 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums // minor, so we maintain the previous (buggy) behavior in 'go mod tidy' to // avoid introducing unnecessary churn. if keepPkgGoModSums { - r := resolveReplacement(pkg.mod) + r := resolveReplacement(loaderstate, pkg.mod) keep[modkey(r)] = true } if rs.pruning == pruned && pkg.mod.Path != "" { - if v, ok := rs.rootSelected(pkg.mod.Path); ok && v == pkg.mod.Version { + if v, ok := rs.rootSelected(loaderstate, pkg.mod.Path); ok && v == pkg.mod.Version { // pkg was loaded from a root module, and because the main module has // a pruned module graph we do not check non-root modules for // conflicts for packages that can be found in roots. So we only need // the checksums for the root modules that may contain pkg, not all // possible modules. for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { - if v, ok := rs.rootSelected(prefix); ok && v != "none" { + if v, ok := rs.rootSelected(loaderstate, prefix); ok && v != "none" { m := module.Version{Path: prefix, Version: v} - r := resolveReplacement(m) + r := resolveReplacement(loaderstate, m) keep[r] = true } } @@ -2069,11 +2069,11 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums } } - mg, _ := rs.Graph(ctx) + mg, _ := rs.Graph(loaderstate, ctx) for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { if v := mg.Selected(prefix); v != "none" { m := module.Version{Path: prefix, Version: v} - r := resolveReplacement(m) + r := resolveReplacement(loaderstate, m) keep[r] = true } } @@ -2085,27 +2085,27 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums // Save sums for the root modules (or their replacements), but don't // incur the cost of loading the graph just to find and retain the sums. for _, m := range rs.rootModules { - r := resolveReplacement(m) + r := resolveReplacement(loaderstate, m) keep[modkey(r)] = true if which == addBuildListZipSums { keep[r] = true } } } else { - mg, _ := rs.Graph(ctx) + mg, _ := rs.Graph(loaderstate, ctx) mg.WalkBreadthFirst(func(m module.Version) { if _, ok := mg.RequiredBy(m); ok { // The requirements from m's go.mod file are present in the module graph, // so they are relevant to the MVS result regardless of whether m was // actually selected. - r := resolveReplacement(m) + r := resolveReplacement(loaderstate, m) keep[modkey(r)] = true } }) if which == addBuildListZipSums { for _, m := range mg.BuildList() { - r := resolveReplacement(m) + r := resolveReplacement(loaderstate, m) if keepModSumsForZipSums { keep[modkey(r)] = true // we need the go version from the go.mod file to do anything useful with the zipfile } diff --git a/src/cmd/go/internal/modload/list.go b/src/cmd/go/internal/modload/list.go index 803bab49ae..bd28d7596e 100644 --- a/src/cmd/go/internal/modload/list.go +++ b/src/cmd/go/internal/modload/list.go @@ -69,7 +69,7 @@ func ListModules(ctx context.Context, args []string, mode ListMode, reuseFile st } } - rs, mods, err := listModules(ctx, LoadModFile(ctx), args, mode, reuse) + rs, mods, err := listModules(ctx, LoadModFile(LoaderState, ctx), args, mode, reuse) type token struct{} sem := make(chan token, runtime.GOMAXPROCS(0)) @@ -88,7 +88,7 @@ func ListModules(ctx context.Context, args []string, mode ListMode, reuseFile st addVersions(ctx, m, mode&ListRetractedVersions != 0) } if mode&ListRetracted != 0 { - addRetraction(ctx, m) + addRetraction(LoaderState, ctx, m) } if mode&ListDeprecated != 0 { addDeprecation(ctx, m) @@ -117,7 +117,7 @@ func ListModules(ctx context.Context, args []string, mode ListMode, reuseFile st // but in general list -u is looking up other checksums in the checksum database // that won't be necessary later, so it makes sense not to write the go.sum back out. if !ExplicitWriteGoMod && mode&ListU == 0 { - err = commitRequirements(ctx, WriteOpts{}) + err = commitRequirements(LoaderState, ctx, WriteOpts{}) } } return mods, err @@ -130,7 +130,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List if gover.IsToolchain(m.Path) { continue } - ms = append(ms, moduleInfo(ctx, rs, m, mode, reuse)) + ms = append(ms, moduleInfo(LoaderState, ctx, rs, m, mode, reuse)) } return rs, ms, nil } @@ -145,25 +145,25 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List } if arg == "all" || strings.Contains(arg, "...") { needFullGraph = true - if !HasModRoot() { + if !HasModRoot(LoaderState) { base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot) } continue } if path, vers, found := strings.Cut(arg, "@"); found { if vers == "upgrade" || vers == "patch" { - if _, ok := rs.rootSelected(path); !ok || rs.pruning == unpruned { + if _, ok := rs.rootSelected(LoaderState, path); !ok || rs.pruning == unpruned { needFullGraph = true - if !HasModRoot() { + if !HasModRoot(LoaderState) { base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot) } } } continue } - if _, ok := rs.rootSelected(arg); !ok || rs.pruning == unpruned { + if _, ok := rs.rootSelected(LoaderState, arg); !ok || rs.pruning == unpruned { needFullGraph = true - if mode&ListVersions == 0 && !HasModRoot() { + if mode&ListVersions == 0 && !HasModRoot(LoaderState) { base.Fatalf("go: cannot match %q without -versions or an explicit version: %v", arg, ErrNoModRoot) } } @@ -171,7 +171,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List var mg *ModuleGraph if needFullGraph { - rs, mg, mgErr = expandGraph(ctx, rs) + rs, mg, mgErr = expandGraph(LoaderState, ctx, rs) } matchedModule := map[module.Version]bool{} @@ -179,7 +179,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List if path, vers, found := strings.Cut(arg, "@"); found { var current string if mg == nil { - current, _ = rs.rootSelected(path) + current, _ = rs.rootSelected(LoaderState, path) } else { current = mg.Selected(path) } @@ -198,7 +198,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List // specific revision or used 'go list -retracted'. allowed = nil } - info, err := queryReuse(ctx, path, vers, current, allowed, reuse) + info, err := queryReuse(LoaderState, ctx, path, vers, current, allowed, reuse) if err != nil { var origin *codehost.Origin if info != nil { @@ -217,7 +217,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List // *Requirements instead. var noRS *Requirements - mod := moduleInfo(ctx, noRS, module.Version{Path: path, Version: info.Version}, mode, reuse) + mod := moduleInfo(LoaderState, ctx, noRS, module.Version{Path: path, Version: info.Version}, mode, reuse) if vers != mod.Version { mod.Query = vers } @@ -237,7 +237,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List var v string if mg == nil { var ok bool - v, ok = rs.rootSelected(arg) + v, ok = rs.rootSelected(LoaderState, arg) if !ok { // We checked rootSelected(arg) in the earlier args loop, so if there // is no such root we should have loaded a non-nil mg. @@ -251,7 +251,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List continue } if v != "none" { - mods = append(mods, moduleInfo(ctx, rs, module.Version{Path: arg, Version: v}, mode, reuse)) + mods = append(mods, moduleInfo(LoaderState, ctx, rs, module.Version{Path: arg, Version: v}, mode, reuse)) } else if cfg.BuildMod == "vendor" { // In vendor mode, we can't determine whether a missing module is “a // known dependency” because the module graph is incomplete. @@ -292,7 +292,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List fetchedMods := make([]*modinfo.ModulePublic, len(matches)) for i, m := range matches { q.Add(func() { - fetchedMods[i] = moduleInfo(ctx, rs, m, mode, reuse) + fetchedMods[i] = moduleInfo(LoaderState, ctx, rs, m, mode, reuse) }) } <-q.Idle() diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 0d661eb2e7..ad3b80bfd9 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -250,7 +250,7 @@ type PackageOpts struct { // LoadPackages identifies the set of packages matching the given patterns and // loads the packages in the import graph rooted at that set. -func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (matches []*search.Match, loadedPackages []string) { +func LoadPackages(loaderstate *State, ctx context.Context, opts PackageOpts, patterns ...string) (matches []*search.Match, loadedPackages []string) { if opts.Tags == nil { opts.Tags = imports.Tags() } @@ -271,11 +271,11 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma case m.IsLocal(): // Evaluate list of file system directories on first iteration. if m.Dirs == nil { - matchModRoots := LoaderState.modRoots + matchModRoots := loaderstate.modRoots if opts.MainModule != (module.Version{}) { - matchModRoots = []string{LoaderState.MainModules.ModRoot(opts.MainModule)} + matchModRoots = []string{loaderstate.MainModules.ModRoot(opts.MainModule)} } - matchLocalDirs(ctx, matchModRoots, m, rs) + matchLocalDirs(loaderstate, ctx, matchModRoots, m, rs) } // Make a copy of the directory list and translate to import paths. @@ -286,7 +286,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // the loader iterations. m.Pkgs = m.Pkgs[:0] for _, dir := range m.Dirs { - pkg, err := resolveLocalPackage(ctx, dir, rs) + pkg, err := resolveLocalPackage(loaderstate, ctx, dir, rs) if err != nil { if !m.IsLiteral() && (err == errPkgIsBuiltin || err == errPkgIsGorootSrc) { continue // Don't include "builtin" or GOROOT/src in wildcard patterns. @@ -294,8 +294,8 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // If we're outside of a module, ensure that the failure mode // indicates that. - if !HasModRoot() { - die() + if !HasModRoot(loaderstate) { + die(loaderstate) } if ld != nil { @@ -311,7 +311,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma case strings.Contains(m.Pattern(), "..."): m.Errs = m.Errs[:0] - mg, err := rs.Graph(ctx) + mg, err := rs.Graph(loaderstate, ctx) if err != nil { // The module graph is (or may be) incomplete — perhaps we failed to // load the requirements of some module. This is an error in matching @@ -321,26 +321,26 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // necessarily prevent us from loading the packages we could find. m.Errs = append(m.Errs, err) } - matchPackages(ctx, m, opts.Tags, includeStd, mg.BuildList()) + matchPackages(loaderstate, ctx, m, opts.Tags, includeStd, mg.BuildList()) case m.Pattern() == "work": - matchModules := LoaderState.MainModules.Versions() + matchModules := loaderstate.MainModules.Versions() if opts.MainModule != (module.Version{}) { matchModules = []module.Version{opts.MainModule} } - matchPackages(ctx, m, opts.Tags, omitStd, matchModules) + matchPackages(loaderstate, ctx, m, opts.Tags, omitStd, matchModules) case m.Pattern() == "all": if ld == nil { // The initial roots are the packages and tools in the main module. // loadFromRoots will expand that to "all". m.Errs = m.Errs[:0] - matchModules := LoaderState.MainModules.Versions() + matchModules := loaderstate.MainModules.Versions() if opts.MainModule != (module.Version{}) { matchModules = []module.Version{opts.MainModule} } - matchPackages(ctx, m, opts.Tags, omitStd, matchModules) - for tool := range LoaderState.MainModules.Tools() { + matchPackages(loaderstate, ctx, m, opts.Tags, omitStd, matchModules) + for tool := range loaderstate.MainModules.Tools() { m.Pkgs = append(m.Pkgs, tool) } } else { @@ -355,7 +355,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma } case m.Pattern() == "tool": - for tool := range LoaderState.MainModules.Tools() { + for tool := range loaderstate.MainModules.Tools() { m.Pkgs = append(m.Pkgs, tool) } default: @@ -364,12 +364,12 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma } } - initialRS, err := loadModFile(ctx, &opts) + initialRS, err := loadModFile(loaderstate, ctx, &opts) if err != nil { base.Fatal(err) } - ld := loadFromRoots(ctx, loaderParams{ + ld := loadFromRoots(loaderstate, ctx, loaderParams{ PackageOpts: opts, requirements: initialRS, @@ -404,7 +404,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma if opts.Tidy { if cfg.BuildV { - mg, _ := ld.requirements.Graph(ctx) + mg, _ := ld.requirements.Graph(loaderstate, ctx) for _, m := range initialRS.rootModules { var unused bool if ld.requirements.pruning == unpruned { @@ -416,7 +416,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // m is unused if it was dropped from the roots. If it is still present // as a transitive dependency, that transitive dependency is not needed // by any package or test in the main module. - _, ok := ld.requirements.rootSelected(m.Path) + _, ok := ld.requirements.rootSelected(loaderstate, m.Path) unused = !ok } if unused { @@ -425,9 +425,9 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma } } - keep := keepSums(ctx, ld, ld.requirements, loadedZipSumsOnly) + keep := keepSums(loaderstate, ctx, ld, ld.requirements, loadedZipSumsOnly) compatVersion := ld.TidyCompatibleVersion - goVersion := ld.requirements.GoVersion() + goVersion := ld.requirements.GoVersion(loaderstate) if compatVersion == "" { if gover.Compare(goVersion, gover.GoStrictVersion) < 0 { compatVersion = gover.Prev(goVersion) @@ -444,10 +444,10 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma compatVersion = goVersion } if compatPruning := pruningForGoVersion(compatVersion); compatPruning != ld.requirements.pruning { - compatRS := newRequirements(compatPruning, ld.requirements.rootModules, ld.requirements.direct) - ld.checkTidyCompatibility(ctx, compatRS, compatVersion) + compatRS := newRequirements(loaderstate, compatPruning, ld.requirements.rootModules, ld.requirements.direct) + ld.checkTidyCompatibility(loaderstate, ctx, compatRS, compatVersion) - for m := range keepSums(ctx, ld, compatRS, loadedZipSumsOnly) { + for m := range keepSums(loaderstate, ctx, ld, compatRS, loadedZipSumsOnly) { keep[m] = true } } @@ -455,8 +455,8 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma if opts.TidyDiff { cfg.BuildMod = "readonly" loaded = ld - LoaderState.requirements = loaded.requirements - currentGoMod, updatedGoMod, _, err := UpdateGoModFromReqs(ctx, WriteOpts{}) + loaderstate.requirements = loaded.requirements + currentGoMod, updatedGoMod, _, err := UpdateGoModFromReqs(loaderstate, ctx, WriteOpts{}) if err != nil { base.Fatal(err) } @@ -466,7 +466,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // Dropping compatibility for 1.16 may result in a strictly smaller go.sum. // Update the keep map with only the loaded.requirements. if gover.Compare(compatVersion, "1.16") > 0 { - keep = keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums) + keep = keepSums(loaderstate, ctx, loaded, loaderstate.requirements, addBuildListZipSums) } currentGoSum, tidyGoSum := modfetch.TidyGoSum(keep) goSumDiff := diff.Diff("current/go.sum", currentGoSum, "tidy/go.sum", tidyGoSum) @@ -490,7 +490,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // loaded.requirements, but here we may have also loaded (and want to // preserve checksums for) additional entities from compatRS, which are // only needed for compatibility with ld.TidyCompatibleVersion. - if err := modfetch.WriteGoSum(ctx, keep, mustHaveCompleteRequirements()); err != nil { + if err := modfetch.WriteGoSum(ctx, keep, mustHaveCompleteRequirements(loaderstate)); err != nil { base.Fatal(err) } } @@ -505,7 +505,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // to call WriteGoMod itself) or if ResolveMissingImports is false (the // command wants to examine the package graph as-is). loaded = ld - LoaderState.requirements = loaded.requirements + loaderstate.requirements = loaded.requirements for _, pkg := range ld.pkgs { if !pkg.isTest() { @@ -515,7 +515,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma sort.Strings(loadedPackages) if !ExplicitWriteGoMod && opts.ResolveMissingImports { - if err := commitRequirements(ctx, WriteOpts{}); err != nil { + if err := commitRequirements(loaderstate, ctx, WriteOpts{}); err != nil { base.Fatal(err) } } @@ -525,7 +525,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // matchLocalDirs is like m.MatchDirs, but tries to avoid scanning directories // outside of the standard library and active modules. -func matchLocalDirs(ctx context.Context, modRoots []string, m *search.Match, rs *Requirements) { +func matchLocalDirs(loaderstate *State, ctx context.Context, modRoots []string, m *search.Match, rs *Requirements) { if !m.IsLocal() { panic(fmt.Sprintf("internal error: resolveLocalDirs on non-local pattern %s", m.Pattern())) } @@ -543,10 +543,10 @@ func matchLocalDirs(ctx context.Context, modRoots []string, m *search.Match, rs } modRoot := findModuleRoot(absDir) - if !slices.Contains(modRoots, modRoot) && search.InDir(absDir, cfg.GOROOTsrc) == "" && pathInModuleCache(ctx, absDir, rs) == "" { + if !slices.Contains(modRoots, modRoot) && search.InDir(absDir, cfg.GOROOTsrc) == "" && pathInModuleCache(loaderstate, ctx, absDir, rs) == "" { m.Dirs = []string{} scope := "main module or its selected dependencies" - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { scope = "modules listed in go.work or their selected dependencies" } m.AddError(fmt.Errorf("directory prefix %s does not contain %s", base.ShortPath(absDir), scope)) @@ -558,7 +558,7 @@ func matchLocalDirs(ctx context.Context, modRoots []string, m *search.Match, rs } // resolveLocalPackage resolves a filesystem path to a package path. -func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (string, error) { +func resolveLocalPackage(loaderstate *State, ctx context.Context, dir string, rs *Requirements) (string, error) { var absDir string if filepath.IsAbs(dir) { absDir = filepath.Clean(dir) @@ -596,13 +596,13 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str } } - for _, mod := range LoaderState.MainModules.Versions() { - modRoot := LoaderState.MainModules.ModRoot(mod) + for _, mod := range loaderstate.MainModules.Versions() { + modRoot := loaderstate.MainModules.ModRoot(mod) if modRoot != "" && absDir == modRoot { if absDir == cfg.GOROOTsrc { return "", errPkgIsGorootSrc } - return LoaderState.MainModules.PathPrefix(mod), nil + return loaderstate.MainModules.PathPrefix(mod), nil } } @@ -611,8 +611,8 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str // It's not strictly necessary but helpful to keep the checks. var pkgNotFoundErr error pkgNotFoundLongestPrefix := "" - for _, mainModule := range LoaderState.MainModules.Versions() { - modRoot := LoaderState.MainModules.ModRoot(mainModule) + for _, mainModule := range loaderstate.MainModules.Versions() { + modRoot := loaderstate.MainModules.ModRoot(mainModule) if modRoot != "" && str.HasFilePathPrefix(absDir, modRoot) && !strings.Contains(absDir[len(modRoot):], "@") { suffix := filepath.ToSlash(str.TrimFilePathPrefix(absDir, modRoot)) if pkg, found := strings.CutPrefix(suffix, "vendor/"); found { @@ -620,14 +620,14 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str return "", fmt.Errorf("without -mod=vendor, directory %s has no package path", absDir) } - readVendorList(VendorDir()) + readVendorList(VendorDir(loaderstate)) if _, ok := vendorPkgModule[pkg]; !ok { return "", fmt.Errorf("directory %s is not a package listed in vendor/modules.txt", absDir) } return pkg, nil } - mainModulePrefix := LoaderState.MainModules.PathPrefix(mainModule) + mainModulePrefix := loaderstate.MainModules.PathPrefix(mainModule) if mainModulePrefix == "" { pkg := suffix if pkg == "builtin" { @@ -668,13 +668,13 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str return pkg, nil } - pkg := pathInModuleCache(ctx, absDir, rs) + pkg := pathInModuleCache(loaderstate, ctx, absDir, rs) if pkg == "" { dirstr := fmt.Sprintf("directory %s", base.ShortPath(absDir)) if dirstr == "directory ." { dirstr = "current directory" } - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { if mr := findModuleRoot(absDir); mr != "" { return "", fmt.Errorf("%s is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using:\n\tgo work use %s", dirstr, base.ShortPath(mr)) } @@ -693,17 +693,17 @@ var ( // pathInModuleCache returns the import path of the directory dir, // if dir is in the module cache copy of a module in our build list. -func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string { +func pathInModuleCache(loaderstate *State, ctx context.Context, dir string, rs *Requirements) string { tryMod := func(m module.Version) (string, bool) { if gover.IsToolchain(m.Path) { return "", false } var root string var err error - if repl := Replacement(m); repl.Path != "" && repl.Version == "" { + if repl := Replacement(loaderstate, m); repl.Path != "" && repl.Version == "" { root = repl.Path if !filepath.IsAbs(root) { - root = filepath.Join(replaceRelativeTo(), root) + root = filepath.Join(replaceRelativeTo(loaderstate), root) } } else if repl.Path != "" { root, err = modfetch.DownloadDir(ctx, repl) @@ -728,7 +728,7 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string if rs.pruning == pruned { for _, m := range rs.rootModules { - if v, _ := rs.rootSelected(m.Path); v != m.Version { + if v, _ := rs.rootSelected(loaderstate, m.Path); v != m.Version { continue // m is a root, but we have a higher root for the same path. } if importPath, ok := tryMod(m); ok { @@ -747,7 +747,7 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string // versions of root modules may differ from what we already checked above. // Re-check those paths too. - mg, _ := rs.Graph(ctx) + mg, _ := rs.Graph(loaderstate, ctx) var importPath string for _, m := range mg.BuildList() { var found bool @@ -766,8 +766,8 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string // // TODO(bcmills): Silencing errors seems off. Take a closer look at this and // figure out what the error-reporting actually ought to be. -func ImportFromFiles(ctx context.Context, gofiles []string) { - rs := LoadModFile(ctx) +func ImportFromFiles(loaderstate *State, ctx context.Context, gofiles []string) { + rs := LoadModFile(loaderstate, ctx) tags := imports.Tags() imports, testImports, err := imports.ScanFiles(gofiles, tags) @@ -775,7 +775,7 @@ func ImportFromFiles(ctx context.Context, gofiles []string) { base.Fatal(err) } - loaded = loadFromRoots(ctx, loaderParams{ + loaded = loadFromRoots(loaderstate, ctx, loaderParams{ PackageOpts: PackageOpts{ Tags: tags, ResolveMissingImports: true, @@ -788,10 +788,10 @@ func ImportFromFiles(ctx context.Context, gofiles []string) { return roots }, }) - LoaderState.requirements = loaded.requirements + loaderstate.requirements = loaded.requirements if !ExplicitWriteGoMod { - if err := commitRequirements(ctx, WriteOpts{}); err != nil { + if err := commitRequirements(loaderstate, ctx, WriteOpts{}); err != nil { base.Fatal(err) } } @@ -799,11 +799,11 @@ func ImportFromFiles(ctx context.Context, gofiles []string) { // DirImportPath returns the effective import path for dir, // provided it is within a main module, or else returns ".". -func (mms *MainModuleSet) DirImportPath(ctx context.Context, dir string) (path string, m module.Version) { - if !HasModRoot() { +func (mms *MainModuleSet) DirImportPath(loaderstate *State, ctx context.Context, dir string) (path string, m module.Version) { + if !HasModRoot(loaderstate) { return ".", module.Version{} } - LoadModFile(ctx) // Sets targetPrefix. + LoadModFile(loaderstate, ctx) // Sets targetPrefix. if !filepath.IsAbs(dir) { dir = filepath.Join(base.Cwd(), dir) @@ -820,7 +820,7 @@ func (mms *MainModuleSet) DirImportPath(ctx context.Context, dir string) (path s return mms.PathPrefix(v), v } if str.HasFilePathPrefix(dir, modRoot) { - pathPrefix := LoaderState.MainModules.PathPrefix(v) + pathPrefix := loaderstate.MainModules.PathPrefix(v) if pathPrefix > longestPrefix { longestPrefix = pathPrefix longestPrefixVersion = v @@ -853,13 +853,13 @@ func PackageModule(path string) module.Version { // the package at path as imported from the package in parentDir. // Lookup requires that one of the Load functions in this package has already // been called. -func Lookup(parentPath string, parentIsStd bool, path string) (dir, realPath string, err error) { +func Lookup(loaderstate *State, parentPath string, parentIsStd bool, path string) (dir, realPath string, err error) { if path == "" { panic("Lookup called with empty package path") } if parentIsStd { - path = loaded.stdVendor(parentPath, path) + path = loaded.stdVendor(loaderstate, parentPath, path) } pkg, ok := loaded.pkgCache.Get(path) if !ok { @@ -957,11 +957,11 @@ func (ld *loader) exitIfErrors(ctx context.Context) { // goVersion reports the Go version that should be used for the loader's // requirements: ld.TidyGoVersion if set, or ld.requirements.GoVersion() // otherwise. -func (ld *loader) goVersion() string { +func (ld *loader) goVersion(loaderstate *State) string { if ld.TidyGoVersion != "" { return ld.TidyGoVersion } - return ld.requirements.GoVersion() + return ld.requirements.GoVersion(loaderstate) } // A loadPkg records information about a single loaded package. @@ -1064,11 +1064,11 @@ func (pkg *loadPkg) isTest() bool { // fromExternalModule reports whether pkg was loaded from a module other than // the main module. -func (pkg *loadPkg) fromExternalModule() bool { +func (pkg *loadPkg) fromExternalModule(loaderstate *State) bool { if pkg.mod.Path == "" { return false // loaded from the standard library, not a module } - return !LoaderState.MainModules.Contains(pkg.mod.Path) + return !loaderstate.MainModules.Contains(pkg.mod.Path) } var errMissing = errors.New("cannot find package") @@ -1079,7 +1079,7 @@ var errMissing = errors.New("cannot find package") // The set of root packages is returned by the params.listRoots function, and // expanded to the full set of packages by tracing imports (and possibly tests) // as needed. -func loadFromRoots(ctx context.Context, params loaderParams) *loader { +func loadFromRoots(loaderstate *State, ctx context.Context, params loaderParams) *loader { ld := &loader{ loaderParams: params, work: par.NewQueue(runtime.GOMAXPROCS(0)), @@ -1095,7 +1095,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { // spot-checks in modules that do not maintain the expanded go.mod // requirements needed for graph pruning. var err error - ld.requirements, _, err = expandGraph(ctx, ld.requirements) + ld.requirements, _, err = expandGraph(loaderstate, ctx, ld.requirements) if err != nil { ld.error(err) } @@ -1103,11 +1103,11 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { ld.exitIfErrors(ctx) updateGoVersion := func() { - goVersion := ld.goVersion() + goVersion := ld.goVersion(loaderstate) if ld.requirements.pruning != workspace { var err error - ld.requirements, err = convertPruning(ctx, ld.requirements, pruningForGoVersion(goVersion)) + ld.requirements, err = convertPruning(loaderstate, ctx, ld.requirements, pruningForGoVersion(goVersion)) if err != nil { ld.error(err) ld.exitIfErrors(ctx) @@ -1141,7 +1141,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { // set of root packages does not change then we can select the correct // versions of all transitive imports on the first try and complete // loading in a single iteration. - changedBuildList := ld.preloadRootModules(ctx, rootPkgs) + changedBuildList := ld.preloadRootModules(loaderstate, ctx, rootPkgs) if changedBuildList { // The build list has changed, so the set of root packages may have also // changed. Start over to pick up the changes. (Preloading roots is much @@ -1154,7 +1154,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { inRoots := map[*loadPkg]bool{} for _, path := range rootPkgs { - root := ld.pkg(ctx, path, pkgIsRoot) + root := ld.pkg(loaderstate, ctx, path, pkgIsRoot) if !inRoots[root] { ld.roots = append(ld.roots, root) inRoots[root] = true @@ -1170,7 +1170,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { ld.buildStacks() - changed, err := ld.updateRequirements(ctx) + changed, err := ld.updateRequirements(loaderstate, ctx) if err != nil { ld.error(err) break @@ -1184,12 +1184,12 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { continue } - if !ld.ResolveMissingImports || (!HasModRoot() && !allowMissingModuleImports) { + if !ld.ResolveMissingImports || (!HasModRoot(loaderstate) && !allowMissingModuleImports) { // We've loaded as much as we can without resolving missing imports. break } - modAddedBy, err := ld.resolveMissingImports(ctx) + modAddedBy, err := ld.resolveMissingImports(loaderstate, ctx) if err != nil { ld.error(err) break @@ -1216,7 +1216,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { // iteration so we don't need to also update it here. (That would waste time // computing a "direct" map that we'll have to recompute later anyway.) direct := ld.requirements.direct - rs, err := updateRoots(ctx, direct, ld.requirements, noPkgs, toAdd, ld.AssumeRootsImported) + rs, err := updateRoots(loaderstate, ctx, direct, ld.requirements, noPkgs, toAdd, ld.AssumeRootsImported) if err != nil { // If an error was found in a newly added module, report the package // import stack instead of the module requirement stack. Packages @@ -1244,7 +1244,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { // Tidy the build list, if applicable, before we report errors. // (The process of tidying may remove errors from irrelevant dependencies.) if ld.Tidy { - rs, err := tidyRoots(ctx, ld.requirements, ld.pkgs) + rs, err := tidyRoots(loaderstate, ctx, ld.requirements, ld.pkgs) if err != nil { ld.error(err) } else { @@ -1252,8 +1252,8 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { // Attempt to switch to the requested Go version. We have been using its // pruning and semantics all along, but there may have been — and may // still be — requirements on higher versions in the graph. - tidy := overrideRoots(ctx, rs, []module.Version{{Path: "go", Version: ld.TidyGoVersion}}) - mg, err := tidy.Graph(ctx) + tidy := overrideRoots(loaderstate, ctx, rs, []module.Version{{Path: "go", Version: ld.TidyGoVersion}}) + mg, err := tidy.Graph(loaderstate, ctx) if err != nil { ld.error(err) } @@ -1285,7 +1285,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { if m.Path == "go" && ld.TidyGoVersion != "" { continue } - if v, ok := ld.requirements.rootSelected(m.Path); !ok || v != m.Version { + if v, ok := ld.requirements.rootSelected(loaderstate, m.Path); !ok || v != m.Version { ld.error(fmt.Errorf("internal error: a requirement on %v is needed but was not added during package loading (selected %s)", m, v)) } } @@ -1334,7 +1334,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { ld.error(fmt.Errorf("%s: %w", pkg.stackText(), pkg.err)) } - ld.checkMultiplePaths() + ld.checkMultiplePaths(loaderstate) return ld } @@ -1357,7 +1357,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { // The "changed" return value reports whether the update changed the selected // version of any module that either provided a loaded package or may now // provide a package that was previously unresolved. -func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err error) { +func (ld *loader) updateRequirements(loaderstate *State, ctx context.Context) (changed bool, err error) { rs := ld.requirements // direct contains the set of modules believed to provide packages directly @@ -1390,16 +1390,16 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err } } } - if pkg.mod.Version != "" || !LoaderState.MainModules.Contains(pkg.mod.Path) { + if pkg.mod.Version != "" || !loaderstate.MainModules.Contains(pkg.mod.Path) { continue } for _, dep := range pkg.imports { - if !dep.fromExternalModule() { + if !dep.fromExternalModule(loaderstate) { continue } - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { // In workspace mode / workspace pruning mode, the roots are the main modules // rather than the main module's direct dependencies. The check below on the selected // roots does not apply. @@ -1412,7 +1412,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err // of the vendor directory anyway. continue } - if mg, err := rs.Graph(ctx); err != nil { + if mg, err := rs.Graph(loaderstate, ctx); err != nil { return false, err } else if _, ok := mg.RequiredBy(dep.mod); !ok { // dep.mod is not an explicit dependency, but needs to be. @@ -1424,7 +1424,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err } } } else if pkg.err == nil && cfg.BuildMod != "mod" { - if v, ok := rs.rootSelected(dep.mod.Path); !ok || v != dep.mod.Version { + if v, ok := rs.rootSelected(loaderstate, dep.mod.Path); !ok || v != dep.mod.Version { // dep.mod is not an explicit dependency, but needs to be. // Because we are not in "mod" mode, we will not be able to update it. // Instead, mark the importing package with an error. @@ -1490,21 +1490,21 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err // roots can only increase and the set of roots can only expand. The set // of extant root paths is finite and the set of versions of each path is // finite, so the iteration *must* reach a stable fixed-point. - tidy, err := tidyRoots(ctx, rs, ld.pkgs) + tidy, err := tidyRoots(loaderstate, ctx, rs, ld.pkgs) if err != nil { return false, err } addRoots = tidy.rootModules } - rs, err = updateRoots(ctx, direct, rs, ld.pkgs, addRoots, ld.AssumeRootsImported) + rs, err = updateRoots(loaderstate, ctx, direct, rs, ld.pkgs, addRoots, ld.AssumeRootsImported) if err != nil { // We don't actually know what even the root requirements are supposed to be, // so we can't proceed with loading. Return the error to the caller return false, err } - if rs.GoVersion() != ld.requirements.GoVersion() { + if rs.GoVersion(loaderstate) != ld.requirements.GoVersion(loaderstate) { // A change in the selected Go version may or may not affect the set of // loaded packages, but in some cases it can change the meaning of the "all" // pattern, the level of pruning in the module graph, and even the set of @@ -1515,12 +1515,12 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err // The roots of the module graph have changed in some way (not just the // "direct" markings). Check whether the changes affected any of the loaded // packages. - mg, err := rs.Graph(ctx) + mg, err := rs.Graph(loaderstate, ctx) if err != nil { return false, err } for _, pkg := range ld.pkgs { - if pkg.fromExternalModule() && mg.Selected(pkg.mod.Path) != pkg.mod.Version { + if pkg.fromExternalModule(loaderstate) && mg.Selected(pkg.mod.Path) != pkg.mod.Version { changed = true break } @@ -1540,7 +1540,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err // // In some sense, we can think of this as ‘upgraded the module providing // pkg.path from "none" to a version higher than "none"’. - if _, _, _, _, err = importFromModules(ctx, pkg.path, rs, nil, ld.skipImportModFiles); err == nil { + if _, _, _, _, err = importFromModules(loaderstate, ctx, pkg.path, rs, nil, ld.skipImportModFiles); err == nil { changed = true break } @@ -1558,7 +1558,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err // The newly-resolved packages are added to the addedModuleFor map, and // resolveMissingImports returns a map from each new module version to // the first missing package that module would resolve. -func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[module.Version]*loadPkg, err error) { +func (ld *loader) resolveMissingImports(loaderstate *State, ctx context.Context) (modAddedBy map[module.Version]*loadPkg, err error) { type pkgMod struct { pkg *loadPkg mod *module.Version @@ -1582,11 +1582,11 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod var mod module.Version ld.work.Add(func() { var err error - mod, err = queryImport(ctx, pkg.path, ld.requirements) + mod, err = queryImport(loaderstate, ctx, pkg.path, ld.requirements) if err != nil { if ime, ok := errors.AsType[*ImportMissingError](err); ok { for curstack := pkg.stack; curstack != nil; curstack = curstack.stack { - if LoaderState.MainModules.Contains(curstack.mod.Path) { + if loaderstate.MainModules.Contains(curstack.mod.Path) { ime.ImportingMainModule = curstack.mod break } @@ -1658,7 +1658,7 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod // ld.work queue, and its test (if requested) will also be populated once // imports have been resolved. When ld.work goes idle, all transitive imports of // the requested package (and its test, if requested) will have been loaded. -func (ld *loader) pkg(ctx context.Context, path string, flags loadPkgFlags) *loadPkg { +func (ld *loader) pkg(loaderstate *State, ctx context.Context, path string, flags loadPkgFlags) *loadPkg { if flags.has(pkgImportsLoaded) { panic("internal error: (*loader).pkg called with pkgImportsLoaded flag set") } @@ -1667,20 +1667,20 @@ func (ld *loader) pkg(ctx context.Context, path string, flags loadPkgFlags) *loa pkg := &loadPkg{ path: path, } - ld.applyPkgFlags(ctx, pkg, flags) + ld.applyPkgFlags(loaderstate, ctx, pkg, flags) - ld.work.Add(func() { ld.load(ctx, pkg) }) + ld.work.Add(func() { ld.load(loaderstate, ctx, pkg) }) return pkg }) - ld.applyPkgFlags(ctx, pkg, flags) + ld.applyPkgFlags(loaderstate, ctx, pkg, flags) return pkg } // applyPkgFlags updates pkg.flags to set the given flags and propagate the // (transitive) effects of those flags, possibly loading or enqueueing further // packages as a result. -func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkgFlags) { +func (ld *loader) applyPkgFlags(loaderstate *State, ctx context.Context, pkg *loadPkg, flags loadPkgFlags) { if flags == 0 { return } @@ -1708,7 +1708,7 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg // so it's ok if we call it more than is strictly necessary. wantTest := false switch { - case ld.allPatternIsRoot && LoaderState.MainModules.Contains(pkg.mod.Path): + case ld.allPatternIsRoot && loaderstate.MainModules.Contains(pkg.mod.Path): // We are loading the "all" pattern, which includes packages imported by // tests in the main module. This package is in the main module, so we // need to identify the imports of its test even if LoadTests is not set. @@ -1729,13 +1729,13 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg if wantTest { var testFlags loadPkgFlags - if LoaderState.MainModules.Contains(pkg.mod.Path) || (ld.allClosesOverTests && new.has(pkgInAll)) { + if loaderstate.MainModules.Contains(pkg.mod.Path) || (ld.allClosesOverTests && new.has(pkgInAll)) { // Tests of packages in the main module are in "all", in the sense that // they cause the packages they import to also be in "all". So are tests // of packages in "all" if "all" closes over test dependencies. testFlags |= pkgInAll } - ld.pkgTest(ctx, pkg, testFlags) + ld.pkgTest(loaderstate, ctx, pkg, testFlags) } } @@ -1743,13 +1743,13 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg // We have just marked pkg with pkgInAll, or we have just loaded its // imports, or both. Now is the time to propagate pkgInAll to the imports. for _, dep := range pkg.imports { - ld.applyPkgFlags(ctx, dep, pkgInAll) + ld.applyPkgFlags(loaderstate, ctx, dep, pkgInAll) } } if new.has(pkgFromRoot) && !old.has(pkgFromRoot|pkgImportsLoaded) { for _, dep := range pkg.imports { - ld.applyPkgFlags(ctx, dep, pkgFromRoot) + ld.applyPkgFlags(loaderstate, ctx, dep, pkgFromRoot) } } } @@ -1757,7 +1757,7 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg // preloadRootModules loads the module requirements needed to identify the // selected version of each module providing a package in rootPkgs, // adding new root modules to the module graph if needed. -func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (changedBuildList bool) { +func (ld *loader) preloadRootModules(loaderstate *State, ctx context.Context, rootPkgs []string) (changedBuildList bool) { needc := make(chan map[module.Version]bool, 1) needc <- map[module.Version]bool{} for _, path := range rootPkgs { @@ -1768,12 +1768,12 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch // If the main module is tidy and the package is in "all" — or if we're // lucky — we can identify all of its imports without actually loading the // full module graph. - m, _, _, _, err := importFromModules(ctx, path, ld.requirements, nil, ld.skipImportModFiles) + m, _, _, _, err := importFromModules(loaderstate, ctx, path, ld.requirements, nil, ld.skipImportModFiles) if err != nil { if _, ok := errors.AsType[*ImportMissingError](err); ok && ld.ResolveMissingImports { // This package isn't provided by any selected module. // If we can find it, it will be a new root dependency. - m, err = queryImport(ctx, path, ld.requirements) + m, err = queryImport(loaderstate, ctx, path, ld.requirements) } if err != nil { // We couldn't identify the root module containing this package. @@ -1786,7 +1786,7 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch return } - v, ok := ld.requirements.rootSelected(m.Path) + v, ok := ld.requirements.rootSelected(loaderstate, m.Path) if !ok || v != m.Version { // We found the requested package in m, but m is not a root, so // loadModGraph will not load its requirements. We need to promote the @@ -1814,7 +1814,7 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch } gover.ModSort(toAdd) - rs, err := updateRoots(ctx, ld.requirements.direct, ld.requirements, nil, toAdd, ld.AssumeRootsImported) + rs, err := updateRoots(loaderstate, ctx, ld.requirements.direct, ld.requirements, nil, toAdd, ld.AssumeRootsImported) if err != nil { // We are missing some root dependency, and for some reason we can't load // enough of the module dependency graph to add the missing root. Package @@ -1836,11 +1836,11 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch } // load loads an individual package. -func (ld *loader) load(ctx context.Context, pkg *loadPkg) { +func (ld *loader) load(loaderstate *State, ctx context.Context, pkg *loadPkg) { var mg *ModuleGraph if ld.requirements.pruning == unpruned { var err error - mg, err = ld.requirements.Graph(ctx) + mg, err = ld.requirements.Graph(loaderstate, ctx) if err != nil { // We already checked the error from Graph in loadFromRoots and/or // updateRequirements, so we ignored the error on purpose and we should @@ -1855,17 +1855,17 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) { } var modroot string - pkg.mod, modroot, pkg.dir, pkg.altMods, pkg.err = importFromModules(ctx, pkg.path, ld.requirements, mg, ld.skipImportModFiles) - if LoaderState.MainModules.Tools()[pkg.path] { + pkg.mod, modroot, pkg.dir, pkg.altMods, pkg.err = importFromModules(loaderstate, ctx, pkg.path, ld.requirements, mg, ld.skipImportModFiles) + if loaderstate.MainModules.Tools()[pkg.path] { // Tools declared by main modules are always in "all". // We apply the package flags before returning so that missing // tool dependencies report an error https://go.dev/issue/70582 - ld.applyPkgFlags(ctx, pkg, pkgInAll) + ld.applyPkgFlags(loaderstate, ctx, pkg, pkgInAll) } if pkg.dir == "" { return } - if LoaderState.MainModules.Contains(pkg.mod.Path) { + if loaderstate.MainModules.Contains(pkg.mod.Path) { // Go ahead and mark pkg as in "all". This provides the invariant that a // package that is *only* imported by other packages in "all" is always // marked as such before loading its imports. @@ -1875,7 +1875,7 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) { // about (by reducing churn on the flag bits of dependencies), and costs // essentially nothing (these atomic flag ops are essentially free compared // to scanning source code for imports). - ld.applyPkgFlags(ctx, pkg, pkgInAll) + ld.applyPkgFlags(loaderstate, ctx, pkg, pkgInAll) } if ld.AllowPackage != nil { if err := ld.AllowPackage(ctx, pkg.path, pkg.mod); err != nil { @@ -1907,13 +1907,13 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) { if pkg.inStd { // Imports from packages in "std" and "cmd" should resolve using // GOROOT/src/vendor even when "std" is not the main module. - path = ld.stdVendor(pkg.path, path) + path = ld.stdVendor(loaderstate, pkg.path, path) } - pkg.imports = append(pkg.imports, ld.pkg(ctx, path, importFlags)) + pkg.imports = append(pkg.imports, ld.pkg(loaderstate, ctx, path, importFlags)) } pkg.testImports = testImports - ld.applyPkgFlags(ctx, pkg, pkgImportsLoaded) + ld.applyPkgFlags(loaderstate, ctx, pkg, pkgImportsLoaded) } // pkgTest locates the test of pkg, creating it if needed, and updates its state @@ -1921,7 +1921,7 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) { // // pkgTest requires that the imports of pkg have already been loaded (flagged // with pkgImportsLoaded). -func (ld *loader) pkgTest(ctx context.Context, pkg *loadPkg, testFlags loadPkgFlags) *loadPkg { +func (ld *loader) pkgTest(loaderstate *State, ctx context.Context, pkg *loadPkg, testFlags loadPkgFlags) *loadPkg { if pkg.isTest() { panic("pkgTest called on a test package") } @@ -1936,7 +1936,7 @@ func (ld *loader) pkgTest(ctx context.Context, pkg *loadPkg, testFlags loadPkgFl err: pkg.err, inStd: pkg.inStd, } - ld.applyPkgFlags(ctx, pkg.test, testFlags) + ld.applyPkgFlags(loaderstate, ctx, pkg.test, testFlags) createdTest = true }) @@ -1949,14 +1949,14 @@ func (ld *loader) pkgTest(ctx context.Context, pkg *loadPkg, testFlags loadPkgFl } for _, path := range pkg.testImports { if pkg.inStd { - path = ld.stdVendor(test.path, path) + path = ld.stdVendor(loaderstate, test.path, path) } - test.imports = append(test.imports, ld.pkg(ctx, path, importFlags)) + test.imports = append(test.imports, ld.pkg(loaderstate, ctx, path, importFlags)) } pkg.testImports = nil - ld.applyPkgFlags(ctx, test, pkgImportsLoaded) + ld.applyPkgFlags(loaderstate, ctx, test, pkgImportsLoaded) } else { - ld.applyPkgFlags(ctx, test, testFlags) + ld.applyPkgFlags(loaderstate, ctx, test, testFlags) } return test @@ -1964,7 +1964,7 @@ func (ld *loader) pkgTest(ctx context.Context, pkg *loadPkg, testFlags loadPkgFl // stdVendor returns the canonical import path for the package with the given // path when imported from the standard-library package at parentPath. -func (ld *loader) stdVendor(parentPath, path string) string { +func (ld *loader) stdVendor(loaderstate *State, parentPath, path string) string { if p, _, ok := fips140.ResolveImport(path); ok { return p } @@ -1973,14 +1973,14 @@ func (ld *loader) stdVendor(parentPath, path string) string { } if str.HasPathPrefix(parentPath, "cmd") { - if !ld.VendorModulesInGOROOTSrc || !LoaderState.MainModules.Contains("cmd") { + if !ld.VendorModulesInGOROOTSrc || !loaderstate.MainModules.Contains("cmd") { vendorPath := pathpkg.Join("cmd", "vendor", path) if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil { return vendorPath } } - } else if !ld.VendorModulesInGOROOTSrc || !LoaderState.MainModules.Contains("std") || str.HasPathPrefix(parentPath, "vendor") { + } else if !ld.VendorModulesInGOROOTSrc || !loaderstate.MainModules.Contains("std") || str.HasPathPrefix(parentPath, "vendor") { // If we are outside of the 'std' module, resolve imports from within 'std' // to the vendor directory. // @@ -2026,7 +2026,7 @@ func (ld *loader) computePatternAll() (all []string) { // or as a replacement for another module, but not both at the same time. // // (See https://golang.org/issue/26607 and https://golang.org/issue/34650.) -func (ld *loader) checkMultiplePaths() { +func (ld *loader) checkMultiplePaths(loaderstate *State) { mods := ld.requirements.rootModules if cached := ld.requirements.graph.Load(); cached != nil { if mg := cached.mg; mg != nil { @@ -2036,7 +2036,7 @@ func (ld *loader) checkMultiplePaths() { firstPath := map[module.Version]string{} for _, mod := range mods { - src := resolveReplacement(mod) + src := resolveReplacement(loaderstate, mod) if prev, ok := firstPath[src]; !ok { firstPath[src] = mod.Path } else if prev != mod.Path { @@ -2047,8 +2047,8 @@ func (ld *loader) checkMultiplePaths() { // checkTidyCompatibility emits an error if any package would be loaded from a // different module under rs than under ld.requirements. -func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements, compatVersion string) { - goVersion := rs.GoVersion() +func (ld *loader) checkTidyCompatibility(loaderstate *State, ctx context.Context, rs *Requirements, compatVersion string) { + goVersion := rs.GoVersion(loaderstate) suggestUpgrade := false suggestEFlag := false suggestFixes := func() { @@ -2065,7 +2065,7 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements, fmt.Fprintln(os.Stderr) goFlag := "" - if goVersion != LoaderState.MainModules.GoVersion() { + if goVersion != loaderstate.MainModules.GoVersion(loaderstate) { goFlag = " -go=" + goVersion } @@ -2094,7 +2094,7 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements, fmt.Fprintf(os.Stderr, "For information about 'go mod tidy' compatibility, see:\n\thttps://go.dev/ref/mod#graph-pruning\n") } - mg, err := rs.Graph(ctx) + mg, err := rs.Graph(loaderstate, ctx) if err != nil { ld.error(fmt.Errorf("error loading go %s module graph: %w", compatVersion, err)) ld.switchIfErrors(ctx) @@ -2132,7 +2132,7 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements, pkg := pkg ld.work.Add(func() { - mod, _, _, _, err := importFromModules(ctx, pkg.path, rs, mg, ld.skipImportModFiles) + mod, _, _, _, err := importFromModules(loaderstate, ctx, pkg.path, rs, mg, ld.skipImportModFiles) if mod != pkg.mod { mismatches := <-mismatchMu mismatches[pkg] = mismatch{mod: mod, err: err} diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 3fdbdc7010..20feb8fcac 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -142,7 +142,7 @@ func CheckAllowed(ctx context.Context, m module.Version) error { if err := CheckExclusions(ctx, m); err != nil { return err } - if err := CheckRetractions(ctx, m); err != nil { + if err := CheckRetractions(LoaderState, ctx, m); err != nil { return err } return nil @@ -172,7 +172,7 @@ func (e *excludedError) Is(err error) bool { return err == ErrDisallowed } // CheckRetractions returns an error if module m has been retracted by // its author. -func CheckRetractions(ctx context.Context, m module.Version) (err error) { +func CheckRetractions(loaderstate *State, ctx context.Context, m module.Version) (err error) { defer func() { if err == nil { return @@ -193,7 +193,7 @@ func CheckRetractions(ctx context.Context, m module.Version) (err error) { // Cannot be retracted. return nil } - if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" { + if repl := Replacement(loaderstate, module.Version{Path: m.Path}); repl.Path != "" { // All versions of the module were replaced. // Don't load retractions, since we'd just load the replacement. return nil @@ -210,11 +210,11 @@ func CheckRetractions(ctx context.Context, m module.Version) (err error) { // We load the raw file here: the go.mod file may have a different module // path that we expect if the module or its repository was renamed. // We still want to apply retractions to other aliases of the module. - rm, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) + rm, err := queryLatestVersionIgnoringRetractions(loaderstate, ctx, m.Path) if err != nil { return err } - summary, err := rawGoModSummary(rm) + summary, err := rawGoModSummary(loaderstate, rm) if err != nil && !errors.Is(err, gover.ErrTooNew) { return err } @@ -300,7 +300,7 @@ func ShortMessage(message, emptyDefault string) string { // // CheckDeprecation returns an error if the message can't be loaded. // CheckDeprecation returns "", nil if there is no deprecation message. -func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string, err error) { +func CheckDeprecation(loaderstate *State, ctx context.Context, m module.Version) (deprecation string, err error) { defer func() { if err != nil { err = fmt.Errorf("loading deprecation for %s: %w", m.Path, err) @@ -312,17 +312,17 @@ func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string // Don't look up deprecation. return "", nil } - if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" { + if repl := Replacement(loaderstate, module.Version{Path: m.Path}); repl.Path != "" { // All versions of the module were replaced. // We'll look up deprecation separately for the replacement. return "", nil } - latest, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) + latest, err := queryLatestVersionIgnoringRetractions(loaderstate, ctx, m.Path) if err != nil { return "", err } - summary, err := rawGoModSummary(latest) + summary, err := rawGoModSummary(loaderstate, latest) if err != nil && !errors.Is(err, gover.ErrTooNew) { return "", err } @@ -342,28 +342,28 @@ func replacement(mod module.Version, replace map[module.Version]module.Version) // Replacement returns the replacement for mod, if any. If the path in the // module.Version is relative it's relative to the single main module outside // workspace mode, or the workspace's directory in workspace mode. -func Replacement(mod module.Version) module.Version { - r, foundModRoot, _ := replacementFrom(mod) - return canonicalizeReplacePath(r, foundModRoot) +func Replacement(loaderstate *State, mod module.Version) module.Version { + r, foundModRoot, _ := replacementFrom(loaderstate, mod) + return canonicalizeReplacePath(loaderstate, r, foundModRoot) } // replacementFrom returns the replacement for mod, if any, the modroot of the replacement if it appeared in a go.mod, // and the source of the replacement. The replacement is relative to the go.work or go.mod file it appears in. -func replacementFrom(mod module.Version) (r module.Version, modroot string, fromFile string) { +func replacementFrom(loaderstate *State, mod module.Version) (r module.Version, modroot string, fromFile string) { foundFrom, found, foundModRoot := "", module.Version{}, "" - if LoaderState.MainModules == nil { + if loaderstate.MainModules == nil { return module.Version{}, "", "" - } else if LoaderState.MainModules.Contains(mod.Path) && mod.Version == "" { + } else if loaderstate.MainModules.Contains(mod.Path) && mod.Version == "" { // Don't replace the workspace version of the main module. return module.Version{}, "", "" } - if _, r, ok := replacement(mod, LoaderState.MainModules.WorkFileReplaceMap()); ok { - return r, "", LoaderState.workFilePath + if _, r, ok := replacement(mod, loaderstate.MainModules.WorkFileReplaceMap()); ok { + return r, "", loaderstate.workFilePath } - for _, v := range LoaderState.MainModules.Versions() { - if index := LoaderState.MainModules.Index(v); index != nil { + for _, v := range loaderstate.MainModules.Versions() { + if index := loaderstate.MainModules.Index(v); index != nil { if from, r, ok := replacement(mod, index.replace); ok { - modRoot := LoaderState.MainModules.ModRoot(v) + modRoot := loaderstate.MainModules.ModRoot(v) if foundModRoot != "" && foundFrom != from && found != r { base.Errorf("conflicting replacements found for %v in workspace modules defined by %v and %v", mod, modFilePath(foundModRoot), modFilePath(modRoot)) @@ -376,21 +376,21 @@ func replacementFrom(mod module.Version) (r module.Version, modroot string, from return found, foundModRoot, modFilePath(foundModRoot) } -func replaceRelativeTo() string { - if workFilePath := WorkFilePath(); workFilePath != "" { +func replaceRelativeTo(loaderstate *State) string { + if workFilePath := WorkFilePath(loaderstate); workFilePath != "" { return filepath.Dir(workFilePath) } - return LoaderState.MainModules.ModRoot(LoaderState.MainModules.mustGetSingleMainModule()) + return loaderstate.MainModules.ModRoot(loaderstate.MainModules.mustGetSingleMainModule(loaderstate)) } // canonicalizeReplacePath ensures that relative, on-disk, replaced module paths // are relative to the workspace directory (in workspace mode) or to the module's // directory (in module mode, as they already are). -func canonicalizeReplacePath(r module.Version, modRoot string) module.Version { +func canonicalizeReplacePath(loaderstate *State, r module.Version, modRoot string) module.Version { if filepath.IsAbs(r.Path) || r.Version != "" || modRoot == "" { return r } - workFilePath := WorkFilePath() + workFilePath := WorkFilePath(loaderstate) if workFilePath == "" { return r } @@ -407,8 +407,8 @@ func canonicalizeReplacePath(r module.Version, modRoot string) module.Version { // for m: either m itself, or the replacement for m (iff m is replaced). // It also returns the modroot of the module providing the replacement if // one was found. -func resolveReplacement(m module.Version) module.Version { - if r := Replacement(m); r.Path != "" { +func resolveReplacement(loaderstate *State, m module.Version) module.Version { + if r := Replacement(loaderstate, m); r.Path != "" { return r } return m @@ -573,12 +573,12 @@ type retraction struct { // module versions. // // The caller must not modify the returned summary. -func goModSummary(m module.Version) (*modFileSummary, error) { - if m.Version == "" && !inWorkspaceMode() && LoaderState.MainModules.Contains(m.Path) { +func goModSummary(loaderstate *State, m module.Version) (*modFileSummary, error) { + if m.Version == "" && !inWorkspaceMode(loaderstate) && loaderstate.MainModules.Contains(m.Path) { panic("internal error: goModSummary called on a main module") } if gover.IsToolchain(m.Path) { - return rawGoModSummary(m) + return rawGoModSummary(loaderstate, m) } if cfg.BuildMod == "vendor" { @@ -586,7 +586,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) { module: module.Version{Path: m.Path}, } - readVendorList(VendorDir()) + readVendorList(VendorDir(loaderstate)) if vendorVersion[m.Path] != m.Version { // This module is not vendored, so packages cannot be loaded from it and // it cannot be relevant to the build. @@ -601,15 +601,15 @@ func goModSummary(m module.Version) (*modFileSummary, error) { return summary, nil } - actual := resolveReplacement(m) - if mustHaveSums() && actual.Version != "" { + actual := resolveReplacement(loaderstate, m) + if mustHaveSums(loaderstate) && actual.Version != "" { key := module.Version{Path: actual.Path, Version: actual.Version + "/go.mod"} if !modfetch.HaveSum(key) { suggestion := fmt.Sprintf(" for go.mod file; to add it:\n\tgo mod download %s", m.Path) return nil, module.VersionError(actual, &sumMissingError{suggestion: suggestion}) } } - summary, err := rawGoModSummary(actual) + summary, err := rawGoModSummary(loaderstate, actual) if err != nil { return nil, err } @@ -641,8 +641,8 @@ func goModSummary(m module.Version) (*modFileSummary, error) { } } - for _, mainModule := range LoaderState.MainModules.Versions() { - if index := LoaderState.MainModules.Index(mainModule); index != nil && len(index.exclude) > 0 { + for _, mainModule := range loaderstate.MainModules.Versions() { + if index := loaderstate.MainModules.Index(mainModule); index != nil && len(index.exclude) > 0 { // Drop any requirements on excluded versions. // Don't modify the cached summary though, since we might need the raw // summary separately. @@ -676,7 +676,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) { // rawGoModSummary cannot be used on the main module outside of workspace mode. // The modFileSummary can still be used for retractions and deprecations // even if a TooNewError is returned. -func rawGoModSummary(m module.Version) (*modFileSummary, error) { +func rawGoModSummary(loaderstate *State, m module.Version) (*modFileSummary, error) { if gover.IsToolchain(m.Path) { if m.Path == "go" && gover.Compare(m.Version, gover.GoStrictVersion) >= 0 { // Declare that go 1.21.3 requires toolchain 1.21.3, @@ -686,7 +686,7 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) { } return &modFileSummary{module: m}, nil } - if m.Version == "" && !inWorkspaceMode() && LoaderState.MainModules.Contains(m.Path) { + if m.Version == "" && !inWorkspaceMode(loaderstate) && loaderstate.MainModules.Contains(m.Path) { // Calling rawGoModSummary implies that we are treating m as a module whose // requirements aren't the roots of the module graph and can't be modified. // @@ -694,22 +694,22 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) { // are the roots of the module graph and we expect them to be kept consistent. panic("internal error: rawGoModSummary called on a main module") } - if m.Version == "" && inWorkspaceMode() && m.Path == "command-line-arguments" { + if m.Version == "" && inWorkspaceMode(loaderstate) && m.Path == "command-line-arguments" { // "go work sync" calls LoadModGraph to make sure the module graph is valid. // If there are no modules in the workspace, we synthesize an empty // command-line-arguments module, which rawGoModData cannot read a go.mod for. return &modFileSummary{module: m}, nil - } else if m.Version == "" && inWorkspaceMode() && LoaderState.MainModules.Contains(m.Path) { + } else if m.Version == "" && inWorkspaceMode(loaderstate) && loaderstate.MainModules.Contains(m.Path) { // When go get uses EnterWorkspace to check that the workspace loads properly, // it will update the contents of the workspace module's modfile in memory. To use the updated // contents of the modfile when doing the load, don't read from disk and instead // recompute a summary using the updated contents of the modfile. - if mf := LoaderState.MainModules.ModFile(m); mf != nil { - return summaryFromModFile(m, LoaderState.MainModules.modFiles[m]) + if mf := loaderstate.MainModules.ModFile(m); mf != nil { + return summaryFromModFile(m, loaderstate.MainModules.modFiles[m]) } } return rawGoModSummaryCache.Do(m, func() (*modFileSummary, error) { - name, data, err := rawGoModData(m) + name, data, err := rawGoModData(loaderstate, m) if err != nil { return nil, err } @@ -781,15 +781,15 @@ var rawGoModSummaryCache par.ErrCache[module.Version, *modFileSummary] // // Unlike rawGoModSummary, rawGoModData does not cache its results in memory. // Use rawGoModSummary instead unless you specifically need these bytes. -func rawGoModData(m module.Version) (name string, data []byte, err error) { +func rawGoModData(loaderstate *State, m module.Version) (name string, data []byte, err error) { if m.Version == "" { dir := m.Path if !filepath.IsAbs(dir) { - if inWorkspaceMode() && LoaderState.MainModules.Contains(m.Path) { - dir = LoaderState.MainModules.ModRoot(m) + if inWorkspaceMode(loaderstate) && loaderstate.MainModules.Contains(m.Path) { + dir = loaderstate.MainModules.ModRoot(m) } else { // m is a replacement module with only a file path. - dir = filepath.Join(replaceRelativeTo(), dir) + dir = filepath.Join(replaceRelativeTo(loaderstate), dir) } } name = filepath.Join(dir, "go.mod") @@ -825,12 +825,12 @@ func rawGoModData(m module.Version) (name string, data []byte, err error) { // // If the queried latest version is replaced, // queryLatestVersionIgnoringRetractions returns the replacement. -func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (latest module.Version, err error) { +func queryLatestVersionIgnoringRetractions(loaderstate *State, ctx context.Context, path string) (latest module.Version, err error) { return latestVersionIgnoringRetractionsCache.Do(path, func() (module.Version, error) { ctx, span := trace.StartSpan(ctx, "queryLatestVersionIgnoringRetractions "+path) defer span.Done() - if repl := Replacement(module.Version{Path: path}); repl.Path != "" { + if repl := Replacement(loaderstate, module.Version{Path: path}); repl.Path != "" { // All versions of the module were replaced. // No need to query. return repl, nil @@ -840,12 +840,12 @@ func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (la // Ignore exclusions from the main module's go.mod. const ignoreSelected = "" var allowAll AllowedFunc - rev, err := Query(ctx, path, "latest", ignoreSelected, allowAll) + rev, err := Query(loaderstate, ctx, path, "latest", ignoreSelected, allowAll) if err != nil { return module.Version{}, err } latest := module.Version{Path: path, Version: rev.Version} - if repl := resolveReplacement(latest); repl.Path != "" { + if repl := resolveReplacement(loaderstate, latest); repl.Path != "" { latest = repl } return latest, nil diff --git a/src/cmd/go/internal/modload/mvs.go b/src/cmd/go/internal/modload/mvs.go index 97e6fe44dd..32afc866fb 100644 --- a/src/cmd/go/internal/modload/mvs.go +++ b/src/cmd/go/internal/modload/mvs.go @@ -53,7 +53,7 @@ func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { return nil, nil } - summary, err := goModSummary(mod) + summary, err := goModSummary(LoaderState, mod) if err != nil { return nil, err } @@ -79,11 +79,11 @@ func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) { return m, nil } -func versions(ctx context.Context, path string, allowed AllowedFunc) (versions []string, origin *codehost.Origin, err error) { +func versions(loaderstate *State, ctx context.Context, path string, allowed AllowedFunc) (versions []string, origin *codehost.Origin, err error) { // Note: modfetch.Lookup and repo.Versions are cached, // so there's no need for us to add extra caching here. err = modfetch.TryProxies(func(proxy string) error { - repo, err := lookupRepo(ctx, proxy, path) + repo, err := lookupRepo(loaderstate, ctx, proxy, path) if err != nil { return err } @@ -111,12 +111,12 @@ func versions(ctx context.Context, path string, allowed AllowedFunc) (versions [ // // Since the version of a main module is not found in the version list, // it has no previous version. -func previousVersion(ctx context.Context, m module.Version) (module.Version, error) { - if m.Version == "" && LoaderState.MainModules.Contains(m.Path) { +func previousVersion(loaderstate *State, ctx context.Context, m module.Version) (module.Version, error) { + if m.Version == "" && loaderstate.MainModules.Contains(m.Path) { return module.Version{Path: m.Path, Version: "none"}, nil } - list, _, err := versions(ctx, m.Path, CheckAllowed) + list, _, err := versions(loaderstate, ctx, m.Path, CheckAllowed) if err != nil { if errors.Is(err, os.ErrNotExist) { return module.Version{Path: m.Path, Version: "none"}, nil @@ -132,5 +132,5 @@ func previousVersion(ctx context.Context, m module.Version) (module.Version, err func (*mvsReqs) Previous(m module.Version) (module.Version, error) { // TODO(golang.org/issue/38714): thread tracing context through MVS. - return previousVersion(context.TODO(), m) + return previousVersion(LoaderState, context.TODO(), m) } diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index b37a244fbb..17a0aef21a 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -80,19 +80,19 @@ import ( // // Query often returns a non-nil *RevInfo with a non-nil error, // to provide an info.Origin that can allow the error to be cached. -func Query(ctx context.Context, path, query, current string, allowed AllowedFunc) (*modfetch.RevInfo, error) { +func Query(loaderstate *State, ctx context.Context, path, query, current string, allowed AllowedFunc) (*modfetch.RevInfo, error) { ctx, span := trace.StartSpan(ctx, "modload.Query "+path) defer span.Done() - return queryReuse(ctx, path, query, current, allowed, nil) + return queryReuse(loaderstate, ctx, path, query, current, allowed, nil) } // queryReuse is like Query but also takes a map of module info that can be reused // if the validation criteria in Origin are met. -func queryReuse(ctx context.Context, path, query, current string, allowed AllowedFunc, reuse map[module.Version]*modinfo.ModulePublic) (*modfetch.RevInfo, error) { +func queryReuse(loaderstate *State, ctx context.Context, path, query, current string, allowed AllowedFunc, reuse map[module.Version]*modinfo.ModulePublic) (*modfetch.RevInfo, error) { var info *modfetch.RevInfo err := modfetch.TryProxies(func(proxy string) (err error) { - info, err = queryProxy(ctx, proxy, path, query, current, allowed, reuse) + info, err = queryProxy(loaderstate, ctx, proxy, path, query, current, allowed, reuse) return err }) return info, err @@ -100,9 +100,9 @@ func queryReuse(ctx context.Context, path, query, current string, allowed Allowe // checkReuse checks whether a revision of a given module // for a given module may be reused, according to the information in origin. -func checkReuse(ctx context.Context, m module.Version, old *codehost.Origin) error { +func checkReuse(loaderstate *State, ctx context.Context, m module.Version, old *codehost.Origin) error { return modfetch.TryProxies(func(proxy string) error { - repo, err := lookupRepo(ctx, proxy, m.Path) + repo, err := lookupRepo(loaderstate, ctx, proxy, m.Path) if err != nil { return err } @@ -197,7 +197,7 @@ func (queryDisabledError) Error() string { return fmt.Sprintf("cannot query module due to -mod=%s\n\t(%s)", cfg.BuildMod, cfg.BuildModReason) } -func queryProxy(ctx context.Context, proxy, path, query, current string, allowed AllowedFunc, reuse map[module.Version]*modinfo.ModulePublic) (*modfetch.RevInfo, error) { +func queryProxy(loaderstate *State, ctx context.Context, proxy, path, query, current string, allowed AllowedFunc, reuse map[module.Version]*modinfo.ModulePublic) (*modfetch.RevInfo, error) { ctx, span := trace.StartSpan(ctx, "modload.queryProxy "+path+" "+query) defer span.Done() @@ -211,7 +211,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed allowed = func(context.Context, module.Version) error { return nil } } - if LoaderState.MainModules.Contains(path) && (query == "upgrade" || query == "patch") { + if loaderstate.MainModules.Contains(path) && (query == "upgrade" || query == "patch") { m := module.Version{Path: path} if err := allowed(ctx, m); err != nil { return nil, fmt.Errorf("internal error: main module version is not allowed: %w", err) @@ -223,7 +223,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed return nil, fmt.Errorf("can't query specific version (%q) of standard-library module %q", query, path) } - repo, err := lookupRepo(ctx, proxy, path) + repo, err := lookupRepo(loaderstate, ctx, proxy, path) if err != nil { return nil, err } @@ -296,7 +296,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed return &clone } - releases, prereleases, err := qm.filterVersions(ctx, versions.List) + releases, prereleases, err := qm.filterVersions(loaderstate, ctx, versions.List) if err != nil { return revWithOrigin(nil), err } @@ -569,7 +569,7 @@ func (qm *queryMatcher) allowsVersion(ctx context.Context, v string) bool { // // If the allowed predicate returns an error not equivalent to ErrDisallowed, // filterVersions returns that error. -func (qm *queryMatcher) filterVersions(ctx context.Context, versions []string) (releases, prereleases []string, err error) { +func (qm *queryMatcher) filterVersions(loaderstate *State, ctx context.Context, versions []string) (releases, prereleases []string, err error) { needIncompatible := qm.preferIncompatible var lastCompatible string @@ -602,7 +602,7 @@ func (qm *queryMatcher) filterVersions(ctx context.Context, versions []string) ( // ignore any version with a higher (+incompatible) major version. (See // https://golang.org/issue/34165.) Note that we even prefer a // compatible pre-release over an incompatible release. - ok, err := versionHasGoMod(ctx, module.Version{Path: qm.path, Version: lastCompatible}) + ok, err := versionHasGoMod(loaderstate, ctx, module.Version{Path: qm.path, Version: lastCompatible}) if err != nil { return nil, nil, err } @@ -639,11 +639,11 @@ type QueryResult struct { // QueryPackages is like QueryPattern, but requires that the pattern match at // least one package and omits the non-package result (if any). -func QueryPackages(ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) ([]QueryResult, error) { - pkgMods, modOnly, err := QueryPattern(ctx, pattern, query, current, allowed) +func QueryPackages(loaderstate *State, ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) ([]QueryResult, error) { + pkgMods, modOnly, err := QueryPattern(loaderstate, ctx, pattern, query, current, allowed) if len(pkgMods) == 0 && err == nil { - replacement := Replacement(modOnly.Mod) + replacement := Replacement(loaderstate, modOnly.Mod) return nil, &PackageNotInModuleError{ Mod: modOnly.Mod, Replacement: replacement, @@ -670,7 +670,7 @@ func QueryPackages(ctx context.Context, pattern, query string, current func(stri // // QueryPattern always returns at least one QueryResult (which may be only // modOnly) or a non-nil error. -func QueryPattern(ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) (pkgMods []QueryResult, modOnly *QueryResult, err error) { +func QueryPattern(loaderstate *State, ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) (pkgMods []QueryResult, modOnly *QueryResult, err error) { ctx, span := trace.StartSpan(ctx, "modload.QueryPattern "+pattern+" "+query) defer span.Done() @@ -693,15 +693,15 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin } match = func(mod module.Version, roots []string, isLocal bool) *search.Match { m := search.NewMatch(pattern) - matchPackages(ctx, m, imports.AnyTags(), omitStd, []module.Version{mod}) + matchPackages(loaderstate, ctx, m, imports.AnyTags(), omitStd, []module.Version{mod}) return m } } else { match = func(mod module.Version, roots []string, isLocal bool) *search.Match { m := search.NewMatch(pattern) prefix := mod.Path - if LoaderState.MainModules.Contains(mod.Path) { - prefix = LoaderState.MainModules.PathPrefix(module.Version{Path: mod.Path}) + if loaderstate.MainModules.Contains(mod.Path) { + prefix = loaderstate.MainModules.PathPrefix(module.Version{Path: mod.Path}) } for _, root := range roots { if _, ok, err := dirInModule(pattern, prefix, root, isLocal); err != nil { @@ -715,8 +715,8 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin } var mainModuleMatches []module.Version - for _, mainModule := range LoaderState.MainModules.Versions() { - m := match(mainModule, LoaderState.modRoots, true) + for _, mainModule := range loaderstate.MainModules.Versions() { + m := match(mainModule, loaderstate.modRoots, true) if len(m.Pkgs) > 0 { if query != "upgrade" && query != "patch" { return nil, nil, &QueryMatchesPackagesInMainModuleError{ @@ -756,7 +756,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin var ( results []QueryResult - candidateModules = modulePrefixesExcludingTarget(base) + candidateModules = modulePrefixesExcludingTarget(loaderstate, base) ) if len(candidateModules) == 0 { if modOnly != nil { @@ -783,7 +783,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin pathCurrent := current(path) r.Mod.Path = path - r.Rev, err = queryProxy(ctx, proxy, path, query, pathCurrent, allowed, nil) + r.Rev, err = queryProxy(loaderstate, ctx, proxy, path, query, pathCurrent, allowed, nil) if err != nil { return r, err } @@ -791,7 +791,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if gover.IsToolchain(r.Mod.Path) { return r, nil } - root, isLocal, err := fetch(ctx, r.Mod) + root, isLocal, err := fetch(loaderstate, ctx, r.Mod) if err != nil { return r, err } @@ -801,7 +801,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if err := firstError(m); err != nil { return r, err } - replacement := Replacement(r.Mod) + replacement := Replacement(loaderstate, r.Mod) return r, &PackageNotInModuleError{ Mod: r.Mod, Replacement: replacement, @@ -812,7 +812,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin return r, nil } - allResults, err := queryPrefixModules(ctx, candidateModules, queryModule) + allResults, err := queryPrefixModules(loaderstate, ctx, candidateModules, queryModule) results = allResults[:0] for _, r := range allResults { if len(r.Packages) == 0 { @@ -838,11 +838,11 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin // itself, sorted by descending length. Prefixes that are not valid module paths // but are valid package paths (like "m" or "example.com/.gen") are included, // since they might be replaced. -func modulePrefixesExcludingTarget(path string) []string { +func modulePrefixesExcludingTarget(loaderstate *State, path string) []string { prefixes := make([]string, 0, strings.Count(path, "/")+1) mainModulePrefixes := make(map[string]bool) - for _, m := range LoaderState.MainModules.Versions() { + for _, m := range loaderstate.MainModules.Versions() { mainModulePrefixes[m.Path] = true } @@ -863,7 +863,7 @@ func modulePrefixesExcludingTarget(path string) []string { return prefixes } -func queryPrefixModules(ctx context.Context, candidateModules []string, queryModule func(ctx context.Context, path string) (QueryResult, error)) (found []QueryResult, err error) { +func queryPrefixModules(loaderstate *State, ctx context.Context, candidateModules []string, queryModule func(ctx context.Context, path string) (QueryResult, error)) (found []QueryResult, err error) { ctx, span := trace.StartSpan(ctx, "modload.queryPrefixModules") defer span.Done() @@ -905,7 +905,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod case *PackageNotInModuleError: // Given the option, prefer to attribute “package not in module” // to modules other than the main one. - if noPackage == nil || LoaderState.MainModules.Contains(noPackage.Mod.Path) { + if noPackage == nil || loaderstate.MainModules.Contains(noPackage.Mod.Path) { noPackage = rErr } case *NoMatchingVersionError: @@ -1096,8 +1096,8 @@ func (e *PackageNotInModuleError) ImportPath() string { // go.mod with different content. Second, if we don't fetch the .zip, then // we don't need to verify it in go.sum. This makes 'go list -m -u' faster // and simpler. -func versionHasGoMod(_ context.Context, m module.Version) (bool, error) { - _, data, err := rawGoModData(m) +func versionHasGoMod(loaderstate *State, _ context.Context, m module.Version) (bool, error) { + _, data, err := rawGoModData(loaderstate, m) if err != nil { return false, err } @@ -1117,7 +1117,7 @@ type versionRepo interface { var _ versionRepo = modfetch.Repo(nil) -func lookupRepo(ctx context.Context, proxy, path string) (repo versionRepo, err error) { +func lookupRepo(loaderstate *State, ctx context.Context, proxy, path string) (repo versionRepo, err error) { if path != "go" && path != "toolchain" { err = module.CheckPath(path) } @@ -1127,9 +1127,9 @@ func lookupRepo(ctx context.Context, proxy, path string) (repo versionRepo, err repo = emptyRepo{path: path, err: err} } - if LoaderState.MainModules == nil { + if loaderstate.MainModules == nil { return repo, err - } else if _, ok := LoaderState.MainModules.HighestReplaced()[path]; ok { + } else if _, ok := loaderstate.MainModules.HighestReplaced()[path]; ok { return &replacementRepo{repo: repo}, nil } @@ -1239,7 +1239,7 @@ func (rr *replacementRepo) Stat(ctx context.Context, rev string) (*modfetch.RevI } } - if r := Replacement(module.Version{Path: path, Version: v}); r.Path == "" { + if r := Replacement(LoaderState, module.Version{Path: path, Version: v}); r.Path == "" { return info, err } return rr.replacementStat(v) diff --git a/src/cmd/go/internal/modload/query_test.go b/src/cmd/go/internal/modload/query_test.go index 93f8f0d00d..b4487eebb0 100644 --- a/src/cmd/go/internal/modload/query_test.go +++ b/src/cmd/go/internal/modload/query_test.go @@ -182,7 +182,7 @@ func TestQuery(t *testing.T) { t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.query+"/"+tt.current+"/"+allow, func(t *testing.T) { t.Parallel() - info, err := Query(ctx, tt.path, tt.query, tt.current, allowed) + info, err := Query(LoaderState, ctx, tt.path, tt.query, tt.current, allowed) if tt.err != "" { if err == nil { t.Errorf("Query(_, %q, %q, %q, %v) = %v, want error %q", tt.path, tt.query, tt.current, allow, info.Version, tt.err) diff --git a/src/cmd/go/internal/modload/search.go b/src/cmd/go/internal/modload/search.go index 205db3e8f7..9951e68ee8 100644 --- a/src/cmd/go/internal/modload/search.go +++ b/src/cmd/go/internal/modload/search.go @@ -41,7 +41,7 @@ const ( // matchPackages is like m.MatchPackages, but uses a local variable (rather than // a global) for tags, can include or exclude packages in the standard library, // and is restricted to the given list of modules. -func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, filter stdFilter, modules []module.Version) { +func matchPackages(loaderstate *State, ctx context.Context, m *search.Match, tags map[string]bool, filter stdFilter, modules []module.Version) { ctx, span := trace.StartSpan(ctx, "modload.matchPackages") defer span.Done() @@ -74,7 +74,7 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f ) q := par.NewQueue(runtime.GOMAXPROCS(0)) - ignorePatternsMap := parseIgnorePatterns(ctx, treeCanMatch, modules) + ignorePatternsMap := parseIgnorePatterns(loaderstate, ctx, treeCanMatch, modules) walkPkgs := func(root, importPathRoot string, prune pruning) { _, span := trace.StartSpan(ctx, "walkPkgs "+root) defer span.Done() @@ -171,13 +171,13 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f } if cfg.BuildMod == "vendor" { - for _, mod := range LoaderState.MainModules.Versions() { - if modRoot := LoaderState.MainModules.ModRoot(mod); modRoot != "" { - walkPkgs(modRoot, LoaderState.MainModules.PathPrefix(mod), pruneGoMod|pruneVendor) + for _, mod := range loaderstate.MainModules.Versions() { + if modRoot := loaderstate.MainModules.ModRoot(mod); modRoot != "" { + walkPkgs(modRoot, loaderstate.MainModules.PathPrefix(mod), pruneGoMod|pruneVendor) } } - if HasModRoot() { - walkPkgs(VendorDir(), "", pruneVendor) + if HasModRoot(loaderstate) { + walkPkgs(VendorDir(loaderstate), "", pruneVendor) } return } @@ -191,16 +191,16 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f root, modPrefix string isLocal bool ) - if LoaderState.MainModules.Contains(mod.Path) { - if LoaderState.MainModules.ModRoot(mod) == "" { + if loaderstate.MainModules.Contains(mod.Path) { + if loaderstate.MainModules.ModRoot(mod) == "" { continue // If there is no main module, we can't search in it. } - root = LoaderState.MainModules.ModRoot(mod) - modPrefix = LoaderState.MainModules.PathPrefix(mod) + root = loaderstate.MainModules.ModRoot(mod) + modPrefix = loaderstate.MainModules.PathPrefix(mod) isLocal = true } else { var err error - root, isLocal, err = fetch(ctx, mod) + root, isLocal, err = fetch(loaderstate, ctx, mod) if err != nil { m.AddError(err) continue @@ -286,17 +286,17 @@ func walkFromIndex(index *modindex.Module, importPathRoot string, isMatch, treeC func MatchInModule(ctx context.Context, pattern string, m module.Version, tags map[string]bool) *search.Match { match := search.NewMatch(pattern) if m == (module.Version{}) { - matchPackages(ctx, match, tags, includeStd, nil) + matchPackages(LoaderState, ctx, match, tags, includeStd, nil) } - LoadModFile(ctx) // Sets Target, needed by fetch and matchPackages. + LoadModFile(LoaderState, ctx) // Sets Target, needed by fetch and matchPackages. if !match.IsLiteral() { - matchPackages(ctx, match, tags, omitStd, []module.Version{m}) + matchPackages(LoaderState, ctx, match, tags, omitStd, []module.Version{m}) return match } - root, isLocal, err := fetch(ctx, m) + root, isLocal, err := fetch(LoaderState, ctx, m) if err != nil { match.Errs = []error{err} return match @@ -322,7 +322,7 @@ func MatchInModule(ctx context.Context, pattern string, m module.Version, tags m // parseIgnorePatterns collects all ignore patterns associated with the // provided list of modules. // It returns a map of module root -> *search.IgnorePatterns. -func parseIgnorePatterns(ctx context.Context, treeCanMatch func(string) bool, modules []module.Version) map[string]*search.IgnorePatterns { +func parseIgnorePatterns(loaderstate *State, ctx context.Context, treeCanMatch func(string) bool, modules []module.Version) map[string]*search.IgnorePatterns { ignorePatternsMap := make(map[string]*search.IgnorePatterns) for _, mod := range modules { if gover.IsToolchain(mod.Path) || !treeCanMatch(mod.Path) { @@ -330,12 +330,12 @@ func parseIgnorePatterns(ctx context.Context, treeCanMatch func(string) bool, mo } var modRoot string var ignorePatterns []string - if LoaderState.MainModules.Contains(mod.Path) { - modRoot = LoaderState.MainModules.ModRoot(mod) + if loaderstate.MainModules.Contains(mod.Path) { + modRoot = loaderstate.MainModules.ModRoot(mod) if modRoot == "" { continue } - modIndex := LoaderState.MainModules.Index(mod) + modIndex := loaderstate.MainModules.Index(mod) if modIndex == nil { continue } @@ -344,11 +344,11 @@ func parseIgnorePatterns(ctx context.Context, treeCanMatch func(string) bool, mo // Skip getting ignore patterns for vendored modules because they // do not have go.mod files. var err error - modRoot, _, err = fetch(ctx, mod) + modRoot, _, err = fetch(loaderstate, ctx, mod) if err != nil { continue } - summary, err := goModSummary(mod) + summary, err := goModSummary(loaderstate, mod) if err != nil { continue } diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go index d3f055acf6..bf0c4e4037 100644 --- a/src/cmd/go/internal/modload/vendor.go +++ b/src/cmd/go/internal/modload/vendor.go @@ -140,10 +140,10 @@ func readVendorList(vendorDir string) { // checkVendorConsistency verifies that the vendor/modules.txt file matches (if // go 1.14) or at least does not contradict (go 1.13 or earlier) the // requirements and replacements listed in the main module's go.mod file. -func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, modRoots []string) { +func checkVendorConsistency(loaderstate *State, indexes []*modFileIndex, modFiles []*modfile.File, modRoots []string) { // readVendorList only needs the main module to get the directory // the vendor directory is in. - readVendorList(VendorDir()) + readVendorList(VendorDir(loaderstate)) if len(modFiles) < 1 { // We should never get here if there are zero modfiles. Either @@ -154,7 +154,7 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m } pre114 := false - if !inWorkspaceMode() { // workspace mode was added after Go 1.14 + if !inWorkspaceMode(loaderstate) { // workspace mode was added after Go 1.14 if len(indexes) != 1 { panic(fmt.Errorf("not in workspace mode but number of indexes is %v, not 1", len(indexes))) } @@ -215,8 +215,8 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m continue // Don't print the same error more than once } seenrep[r.Old] = true - rNew, modRoot, replacementSource := replacementFrom(r.Old) - rNewCanonical := canonicalizeReplacePath(rNew, modRoot) + rNew, modRoot, replacementSource := replacementFrom(loaderstate, r.Old) + rNewCanonical := canonicalizeReplacePath(loaderstate, rNew, modRoot) vr := vendorMeta[r.Old].Replacement if vr == (module.Version{}) { if rNewCanonical == (module.Version{}) { @@ -236,8 +236,8 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m for _, modFile := range modFiles { checkReplace(modFile.Replace) } - if LoaderState.MainModules.workFile != nil { - checkReplace(LoaderState.MainModules.workFile.Replace) + if loaderstate.MainModules.workFile != nil { + checkReplace(loaderstate.MainModules.workFile.Replace) } for _, mod := range vendorList { @@ -252,7 +252,7 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m } if !foundRequire { article := "" - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { article = "a " } vendErrorf(mod, "is marked as explicit in vendor/modules.txt, but not explicitly required in %vgo.mod", article) @@ -262,9 +262,9 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m } for _, mod := range vendorReplaced { - r := Replacement(mod) + r := Replacement(loaderstate, mod) replacementSource := "go.mod" - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { replacementSource = "the workspace" } if r == (module.Version{}) { @@ -276,9 +276,9 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m if vendErrors.Len() > 0 { subcmd := "mod" - if inWorkspaceMode() { + if inWorkspaceMode(loaderstate) { subcmd = "work" } - base.Fatalf("go: inconsistent vendoring in %s:%s\n\n\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo %s vendor", filepath.Dir(VendorDir()), vendErrors, subcmd) + base.Fatalf("go: inconsistent vendoring in %s:%s\n\n\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo %s vendor", filepath.Dir(VendorDir(loaderstate)), vendErrors, subcmd) } } diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index d922dcdd66..b6d76514b0 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -78,13 +78,13 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { // for -race and -msan. modload.LoaderState.ForceUseModules = true modload.LoaderState.RootMode = modload.NoRoot - modload.AllowMissingModuleImports() - modload.Init() + modload.AllowMissingModuleImports(modload.LoaderState) + modload.Init(modload.LoaderState) } else { - modload.InitWorkfile() + modload.InitWorkfile(modload.LoaderState) } - work.BuildInit() + work.BuildInit(modload.LoaderState) b := work.NewBuilder("") defer func() { if err := b.Close(); err != nil { @@ -107,18 +107,18 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("go: cannot run *_test.go files (%s)", file) } } - p = load.GoFilesPackage(ctx, pkgOpts, files) + p = load.GoFilesPackage(modload.LoaderState, ctx, pkgOpts, files) } else if len(args) > 0 && !strings.HasPrefix(args[0], "-") { arg := args[0] var pkgs []*load.Package if strings.Contains(arg, "@") && !build.IsLocalImport(arg) && !filepath.IsAbs(arg) { var err error - pkgs, err = load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args[:1]) + pkgs, err = load.PackagesAndErrorsOutsideModule(modload.LoaderState, ctx, pkgOpts, args[:1]) if err != nil { base.Fatal(err) } } else { - pkgs = load.PackagesAndErrors(ctx, pkgOpts, args[:1]) + pkgs = load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, args[:1]) } if len(pkgs) == 0 { @@ -140,7 +140,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { load.CheckPackageErrors([]*load.Package{p}) if cfg.BuildCover { - load.PrepareForCoverageBuild([]*load.Package{p}) + load.PrepareForCoverageBuild(modload.LoaderState, []*load.Package{p}) } p.Internal.OmitDebug = true @@ -166,7 +166,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { p.Internal.ExeName = p.DefaultExecName() } - a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p) + a1 := b.LinkAction(modload.LoaderState, work.ModeBuild, work.ModeBuild, p) a1.CacheExecutable = true a := &work.Action{Mode: "go run", Actor: work.ActorFunc(buildRunProgram), Args: cmdArgs, Deps: []*work.Action{a1}} b.Do(ctx, a) diff --git a/src/cmd/go/internal/telemetrystats/telemetrystats.go b/src/cmd/go/internal/telemetrystats/telemetrystats.go index d5b642240f..9586324551 100644 --- a/src/cmd/go/internal/telemetrystats/telemetrystats.go +++ b/src/cmd/go/internal/telemetrystats/telemetrystats.go @@ -24,7 +24,7 @@ func Increment() { func incrementConfig() { if !modload.WillBeEnabled() { counter.Inc("go/mode:gopath") - } else if workfile := modload.FindGoWork(base.Cwd()); workfile != "" { + } else if workfile := modload.FindGoWork(modload.LoaderState, base.Cwd()); workfile != "" { counter.Inc("go/mode:workspace") } else { counter.Inc("go/mode:module") diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index e225929add..5e5d79a39f 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -683,7 +683,7 @@ var defaultVetFlags = []string{ func runTest(ctx context.Context, cmd *base.Command, args []string) { pkgArgs, testArgs = testFlags(args) - modload.InitWorkfile() // The test command does custom flag processing; initialize workspaces after that. + modload.InitWorkfile(modload.LoaderState) // The test command does custom flag processing; initialize workspaces after that. if cfg.DebugTrace != "" { var close func() error @@ -704,13 +704,13 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { work.FindExecCmd() // initialize cached result - work.BuildInit() + work.BuildInit(modload.LoaderState) work.VetFlags = testVet.flags work.VetExplicit = testVet.explicit work.VetTool = base.Tool("vet") pkgOpts := load.PackageOpts{ModResolveTests: true} - pkgs = load.PackagesAndErrors(ctx, pkgOpts, pkgArgs) + pkgs = load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, pkgArgs) // We *don't* call load.CheckPackageErrors here because we want to report // loading errors as per-package test setup errors later. if len(pkgs) == 0 { @@ -741,7 +741,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { if !mainMods.Contains(m.Path) { base.Fatalf("cannot use -fuzz flag on package outside the main module") } - } else if pkgs[0].Standard && modload.Enabled() { + } else if pkgs[0].Standard && modload.Enabled(modload.LoaderState) { // Because packages in 'std' and 'cmd' are part of the standard library, // they are only treated as part of a module in 'go mod' subcommands and // 'go get'. However, we still don't want to accidentally corrupt their @@ -867,13 +867,13 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { if cfg.BuildCoverPkg != nil { match := make([]func(*load.Package) bool, len(cfg.BuildCoverPkg)) for i := range cfg.BuildCoverPkg { - match[i] = load.MatchPackage(cfg.BuildCoverPkg[i], base.Cwd()) + match[i] = load.MatchPackage(modload.LoaderState, cfg.BuildCoverPkg[i], base.Cwd()) } // Select for coverage all dependencies matching the -coverpkg // patterns. plist := load.TestPackageList(ctx, pkgOpts, pkgs) - testCoverPkgs = load.SelectCoverPackages(plist, match, "test") + testCoverPkgs = load.SelectCoverPackages(modload.LoaderState, plist, match, "test") if len(testCoverPkgs) > 0 { // create a new singleton action that will collect up the // meta-data files from all of the packages mentioned in @@ -981,7 +981,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { // happens we'll wind up building the Q compile action // before updating its deps to include sync/atomic). if cfg.BuildCoverMode == "atomic" && p.ImportPath != "sync/atomic" { - load.EnsureImport(p, "sync/atomic") + load.EnsureImport(modload.LoaderState, p, "sync/atomic") } // Tag the package for static meta-data generation if no // test files (this works only with the new coverage @@ -1221,7 +1221,7 @@ func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts, } } - a := b.LinkAction(work.ModeBuild, work.ModeBuild, pmain) + a := b.LinkAction(modload.LoaderState, work.ModeBuild, work.ModeBuild, pmain) a.Target = testDir + testBinary + cfg.ExeSuffix if cfg.Goos == "windows" { // There are many reserved words on Windows that, diff --git a/src/cmd/go/internal/tool/tool.go b/src/cmd/go/internal/tool/tool.go index e25c06a8f0..e95b07d8c8 100644 --- a/src/cmd/go/internal/tool/tool.go +++ b/src/cmd/go/internal/tool/tool.go @@ -161,8 +161,8 @@ func listTools(ctx context.Context) { fmt.Println(name) } - modload.InitWorkfile() - modload.LoadModFile(ctx) + modload.InitWorkfile(modload.LoaderState) + modload.LoadModFile(modload.LoaderState, ctx) modTools := slices.Sorted(maps.Keys(modload.LoaderState.MainModules.Tools())) for _, tool := range modTools { fmt.Println(tool) @@ -252,8 +252,8 @@ func loadBuiltinTool(toolName string) string { } func loadModTool(ctx context.Context, name string) string { - modload.InitWorkfile() - modload.LoadModFile(ctx) + modload.InitWorkfile(modload.LoaderState) + modload.LoadModFile(modload.LoaderState, ctx) matches := []string{} for tool := range modload.LoaderState.MainModules.Tools() { @@ -336,7 +336,7 @@ func buildAndRunModtool(ctx context.Context, toolName, tool string, args []strin } func buildAndRunTool(ctx context.Context, tool string, args []string, runTool work.ActorFunc) { - work.BuildInit() + work.BuildInit(modload.LoaderState) b := work.NewBuilder("") defer func() { if err := b.Close(); err != nil { @@ -345,11 +345,11 @@ func buildAndRunTool(ctx context.Context, tool string, args []string, runTool wo }() pkgOpts := load.PackageOpts{MainOnly: true} - p := load.PackagesAndErrors(ctx, pkgOpts, []string{tool})[0] + p := load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, []string{tool})[0] p.Internal.OmitDebug = true p.Internal.ExeName = p.DefaultExecName() - a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p) + a1 := b.LinkAction(modload.LoaderState, work.ModeBuild, work.ModeBuild, p) a1.CacheExecutable = true a := &work.Action{Mode: "go tool", Actor: runTool, Args: args, Deps: []*work.Action{a1}} b.Do(ctx, a) diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go index 4f46b19c12..d54277ed1b 100644 --- a/src/cmd/go/internal/toolchain/select.go +++ b/src/cmd/go/internal/toolchain/select.go @@ -355,7 +355,7 @@ func Exec(gotoolchain string) { modload.Reset() modload.LoaderState.ForceUseModules = true modload.LoaderState.RootMode = modload.NoRoot - modload.Init() + modload.Init(modload.LoaderState) // Download and unpack toolchain module into module cache. // Note that multiple go commands might be doing this at the same time, @@ -529,7 +529,7 @@ func raceSafeCopy(old, new string) error { // The toolchain line overrides the version line func modGoToolchain() (file, goVers, toolchain string) { wd := base.UncachedCwd() - file = modload.FindGoWork(wd) + file = modload.FindGoWork(modload.LoaderState, wd) // $GOWORK can be set to a file that does not yet exist, if we are running 'go work init'. // Do not try to load the file in that case if _, err := os.Stat(file); err != nil { @@ -694,7 +694,7 @@ func maybeSwitchForGoInstallVersion(minVers string) { // Set up modules without an explicit go.mod, to download go.mod. modload.LoaderState.ForceUseModules = true modload.LoaderState.RootMode = modload.NoRoot - modload.Init() + modload.Init(modload.LoaderState) defer modload.Reset() // See internal/load.PackagesAndErrorsOutsideModule @@ -705,7 +705,7 @@ func maybeSwitchForGoInstallVersion(minVers string) { allowed = nil } noneSelected := func(path string) (version string) { return "none" } - _, err := modload.QueryPackages(ctx, path, version, noneSelected, allowed) + _, err := modload.QueryPackages(modload.LoaderState, ctx, path, version, noneSelected, allowed) if errors.Is(err, gover.ErrTooNew) { // Run early switch, same one go install or go run would eventually do, // if it understood all the command-line flags. diff --git a/src/cmd/go/internal/vet/vet.go b/src/cmd/go/internal/vet/vet.go index a2625b2118..e274348bd6 100644 --- a/src/cmd/go/internal/vet/vet.go +++ b/src/cmd/go/internal/vet/vet.go @@ -123,7 +123,7 @@ func run(ctx context.Context, cmd *base.Command, args []string) { // The vet/fix commands do custom flag processing; // initialize workspaces after that. - modload.InitWorkfile() + modload.InitWorkfile(modload.LoaderState) if cfg.DebugTrace != "" { var close func() error @@ -142,7 +142,7 @@ func run(ctx context.Context, cmd *base.Command, args []string) { ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command")) defer span.Done() - work.BuildInit() + work.BuildInit(modload.LoaderState) // Flag theory: // @@ -217,7 +217,7 @@ func run(ctx context.Context, cmd *base.Command, args []string) { work.VetFlags = toolFlags pkgOpts := load.PackageOpts{ModResolveTests: true} - pkgs := load.PackagesAndErrors(ctx, pkgOpts, pkgArgs) + pkgs := load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, pkgArgs) load.CheckPackageErrors(pkgs) if len(pkgs) == 0 { base.Fatalf("no packages to %s", cmd.Name()) diff --git a/src/cmd/go/internal/work/action.go b/src/cmd/go/internal/work/action.go index 3636f642e2..f1f3bcea38 100644 --- a/src/cmd/go/internal/work/action.go +++ b/src/cmd/go/internal/work/action.go @@ -28,6 +28,7 @@ import ( "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/modload" "cmd/go/internal/str" "cmd/go/internal/trace" "cmd/internal/buildid" @@ -392,7 +393,7 @@ func (b *Builder) NewObjdir() string { // at shlibpath. For the native toolchain this list is stored, newline separated, in // an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the // .go_export section. -func readpkglist(shlibpath string) (pkgs []*load.Package) { +func readpkglist(loaderstate *modload.State, shlibpath string) (pkgs []*load.Package) { var stk load.ImportStack if cfg.BuildToolchainName == "gccgo" { f, err := elf.Open(shlibpath) @@ -412,7 +413,7 @@ func readpkglist(shlibpath string) (pkgs []*load.Package) { for _, line := range bytes.Split(data, []byte{'\n'}) { if path, found := bytes.CutPrefix(line, pkgpath); found { path = bytes.TrimSuffix(path, []byte{';'}) - pkgs = append(pkgs, load.LoadPackageWithFlags(string(path), base.Cwd(), &stk, nil, 0)) + pkgs = append(pkgs, load.LoadPackageWithFlags(loaderstate, string(path), base.Cwd(), &stk, nil, 0)) } } } else { @@ -423,7 +424,7 @@ func readpkglist(shlibpath string) (pkgs []*load.Package) { scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes)) for scanner.Scan() { t := scanner.Text() - pkgs = append(pkgs, load.LoadPackageWithFlags(t, base.Cwd(), &stk, nil, 0)) + pkgs = append(pkgs, load.LoadPackageWithFlags(loaderstate, t, base.Cwd(), &stk, nil, 0)) } } return @@ -445,7 +446,7 @@ func (b *Builder) cacheAction(mode string, p *load.Package, f func() *Action) *A // AutoAction returns the "right" action for go build or go install of p. func (b *Builder) AutoAction(mode, depMode BuildMode, p *load.Package) *Action { if p.Name == "main" { - return b.LinkAction(mode, depMode, p) + return b.LinkAction(modload.LoaderState, mode, depMode, p) } return b.CompileAction(mode, depMode, p) } @@ -913,7 +914,7 @@ func (b *Builder) vetAction(mode, depMode BuildMode, p *load.Package) *Action { // LinkAction returns the action for linking p into an executable // and possibly installing the result (according to mode). // depMode is the action (build or install) to use when compiling dependencies. -func (b *Builder) LinkAction(mode, depMode BuildMode, p *load.Package) *Action { +func (b *Builder) LinkAction(loaderstate *modload.State, mode, depMode BuildMode, p *load.Package) *Action { // Construct link action. a := b.cacheAction("link", p, func() *Action { a := &Action{ @@ -948,7 +949,7 @@ func (b *Builder) LinkAction(mode, depMode BuildMode, p *load.Package) *Action { } a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix a.built = a.Target - b.addTransitiveLinkDeps(a, a1, "") + b.addTransitiveLinkDeps(loaderstate, a, a1, "") // Sequence the build of the main package (a1) strictly after the build // of all other dependencies that go into the link. It is likely to be after @@ -1034,7 +1035,7 @@ func (b *Builder) installAction(a1 *Action, mode BuildMode) *Action { // makes sure those are present in a.Deps. // If shlib is non-empty, then a corresponds to the build and installation of shlib, // so any rebuild of shlib should not be added as a dependency. -func (b *Builder) addTransitiveLinkDeps(a, a1 *Action, shlib string) { +func (b *Builder) addTransitiveLinkDeps(loaderstate *modload.State, a, a1 *Action, shlib string) { // Expand Deps to include all built packages, for the linker. // Use breadth-first search to find rebuilt-for-test packages // before the standard ones. @@ -1075,7 +1076,7 @@ func (b *Builder) addTransitiveLinkDeps(a, a1 *Action, shlib string) { // we'll end up building an overall library or executable that depends at runtime // on other libraries that are out-of-date, which is clearly not good either. // We call it ModeBuggyInstall to make clear that this is not right. - a.Deps = append(a.Deps, b.linkSharedAction(ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil)) + a.Deps = append(a.Deps, b.linkSharedAction(loaderstate, ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil)) } } } @@ -1116,21 +1117,21 @@ func (b *Builder) buildmodeShared(mode, depMode BuildMode, args []string, pkgs [ if err != nil { base.Fatalf("%v", err) } - return b.linkSharedAction(mode, depMode, name, a1) + return b.linkSharedAction(modload.LoaderState, mode, depMode, name, a1) } // linkSharedAction takes a grouping action a1 corresponding to a list of built packages // and returns an action that links them together into a shared library with the name shlib. // If a1 is nil, shlib should be an absolute path to an existing shared library, // and then linkSharedAction reads that library to find out the package list. -func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Action) *Action { +func (b *Builder) linkSharedAction(loaderstate *modload.State, mode, depMode BuildMode, shlib string, a1 *Action) *Action { fullShlib := shlib shlib = filepath.Base(shlib) a := b.cacheAction("build-shlib "+shlib, nil, func() *Action { if a1 == nil { // TODO(rsc): Need to find some other place to store config, // not in pkg directory. See golang.org/issue/22196. - pkgs := readpkglist(fullShlib) + pkgs := readpkglist(loaderstate, fullShlib) a1 = &Action{ Mode: "shlib packages", } @@ -1173,7 +1174,7 @@ func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Ac } } var stk load.ImportStack - p := load.LoadPackageWithFlags(pkg, base.Cwd(), &stk, nil, 0) + p := load.LoadPackageWithFlags(loaderstate, pkg, base.Cwd(), &stk, nil, 0) if p.Error != nil { base.Fatalf("load %s: %v", pkg, p.Error) } @@ -1201,7 +1202,7 @@ func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Ac add(a, dep, true) } } - b.addTransitiveLinkDeps(a, a1, shlib) + b.addTransitiveLinkDeps(loaderstate, a, a1, shlib) return a }) diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index fdb483d46f..45acbe85c2 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -459,8 +459,8 @@ func oneMainPkg(pkgs []*load.Package) []*load.Package { var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs } func runBuild(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() - BuildInit() + modload.InitWorkfile(modload.LoaderState) + BuildInit(modload.LoaderState) b := NewBuilder("") defer func() { if err := b.Close(); err != nil { @@ -468,7 +468,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { } }() - pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{AutoVCS: true}, args) + pkgs := load.PackagesAndErrors(modload.LoaderState, ctx, load.PackageOpts{AutoVCS: true}, args) load.CheckPackageErrors(pkgs) explicitO := len(cfg.BuildO) > 0 @@ -503,7 +503,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { } if cfg.BuildCover { - load.PrepareForCoverageBuild(pkgs) + load.PrepareForCoverageBuild(modload.LoaderState, pkgs) } if cfg.BuildO != "" { @@ -694,10 +694,10 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) { } } - modload.InitWorkfile() - BuildInit() - pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{AutoVCS: true}, args) - if cfg.ModulesEnabled && !modload.HasModRoot() { + modload.InitWorkfile(modload.LoaderState) + BuildInit(modload.LoaderState) + pkgs := load.PackagesAndErrors(modload.LoaderState, ctx, load.PackageOpts{AutoVCS: true}, args) + if cfg.ModulesEnabled && !modload.HasModRoot(modload.LoaderState) { haveErrors := false allMissingErrors := true for _, pkg := range pkgs { @@ -722,7 +722,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) { load.CheckPackageErrors(pkgs) if cfg.BuildCover { - load.PrepareForCoverageBuild(pkgs) + load.PrepareForCoverageBuild(modload.LoaderState, pkgs) } InstallPackages(ctx, args, pkgs) @@ -861,9 +861,9 @@ func InstallPackages(ctx context.Context, patterns []string, pkgs []*load.Packag func installOutsideModule(ctx context.Context, args []string) { modload.LoaderState.ForceUseModules = true modload.LoaderState.RootMode = modload.NoRoot - modload.AllowMissingModuleImports() - modload.Init() - BuildInit() + modload.AllowMissingModuleImports(modload.LoaderState) + modload.Init(modload.LoaderState) + BuildInit(modload.LoaderState) // Load packages. Ignore non-main packages. // Print a warning if an argument contains "..." and matches no main packages. @@ -872,7 +872,7 @@ func installOutsideModule(ctx context.Context, args []string) { // TODO(golang.org/issue/40276): don't report errors loading non-main packages // matched by a pattern. pkgOpts := load.PackageOpts{MainOnly: true} - pkgs, err := load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args) + pkgs, err := load.PackagesAndErrorsOutsideModule(modload.LoaderState, ctx, pkgOpts, args) if err != nil { base.Fatal(err) } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 703b4367db..eb012d2610 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -2193,7 +2193,7 @@ func (noToolchain) cc(b *Builder, a *Action, ofile, cfile string) error { // gcc runs the gcc C compiler to create an object from a single C file. func (b *Builder) gcc(a *Action, workdir, out string, flags []string, cfile string) error { p := a.Package - return b.ccompile(a, out, flags, cfile, b.GccCmd(p.Dir, workdir)) + return b.ccompile(modload.LoaderState, a, out, flags, cfile, b.GccCmd(p.Dir, workdir)) } // gas runs the gcc c compiler to create an object file from a single C assembly file. @@ -2207,23 +2207,23 @@ func (b *Builder) gas(a *Action, workdir, out string, flags []string, sfile stri return fmt.Errorf("package using cgo has Go assembly file %s", sfile) } } - return b.ccompile(a, out, flags, sfile, b.GccCmd(p.Dir, workdir)) + return b.ccompile(modload.LoaderState, a, out, flags, sfile, b.GccCmd(p.Dir, workdir)) } // gxx runs the g++ C++ compiler to create an object from a single C++ file. func (b *Builder) gxx(a *Action, workdir, out string, flags []string, cxxfile string) error { p := a.Package - return b.ccompile(a, out, flags, cxxfile, b.GxxCmd(p.Dir, workdir)) + return b.ccompile(modload.LoaderState, a, out, flags, cxxfile, b.GxxCmd(p.Dir, workdir)) } // gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file. func (b *Builder) gfortran(a *Action, workdir, out string, flags []string, ffile string) error { p := a.Package - return b.ccompile(a, out, flags, ffile, b.gfortranCmd(p.Dir, workdir)) + return b.ccompile(modload.LoaderState, a, out, flags, ffile, b.gfortranCmd(p.Dir, workdir)) } // ccompile runs the given C or C++ compiler and creates an object from a single source file. -func (b *Builder) ccompile(a *Action, outfile string, flags []string, file string, compiler []string) error { +func (b *Builder) ccompile(loaderstate *modload.State, a *Action, outfile string, flags []string, file string, compiler []string) error { p := a.Package sh := b.Shell(a) file = mkAbs(p.Dir, file) @@ -2260,7 +2260,7 @@ func (b *Builder) ccompile(a *Action, outfile string, flags []string, file strin } else if m.Dir == "" { // The module is in the vendor directory. Replace the entire vendor // directory path, because the module's Dir is not filled in. - from = modload.VendorDir() + from = modload.VendorDir(loaderstate) toPath = "vendor" } else { from = m.Dir @@ -2310,7 +2310,7 @@ func (b *Builder) ccompile(a *Action, outfile string, flags []string, file strin } } if len(newFlags) < len(flags) { - return b.ccompile(a, outfile, newFlags, file, compiler) + return b.ccompile(loaderstate, a, outfile, newFlags, file, compiler) } } @@ -3383,7 +3383,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) { } srcs := []string{src} - p := load.GoFilesPackage(context.TODO(), load.PackageOpts{}, srcs) + p := load.GoFilesPackage(modload.LoaderState, context.TODO(), load.PackageOpts{}, srcs) if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, nil, "", false, "", srcs); e != nil { return "32", nil diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index e4e83dc8f9..a2954ab91a 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -50,14 +50,14 @@ func makeCfgChangedEnv() []string { return slices.Clip(env) } -func BuildInit() { +func BuildInit(loaderstate *modload.State) { if buildInitStarted { base.Fatalf("go: internal error: work.BuildInit called more than once") } buildInitStarted = true base.AtExit(closeBuilders) - modload.Init() + modload.Init(loaderstate) instrumentInit() buildModeInit() cfgChangedEnv = makeCfgChangedEnv() diff --git a/src/cmd/go/internal/workcmd/edit.go b/src/cmd/go/internal/workcmd/edit.go index 18730436ca..3778e70b68 100644 --- a/src/cmd/go/internal/workcmd/edit.go +++ b/src/cmd/go/internal/workcmd/edit.go @@ -143,8 +143,8 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { if len(args) == 1 { gowork = args[0] } else { - modload.InitWorkfile() - gowork = modload.WorkFilePath() + modload.InitWorkfile(modload.LoaderState) + gowork = modload.WorkFilePath(modload.LoaderState) } if gowork == "" { base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)") diff --git a/src/cmd/go/internal/workcmd/init.go b/src/cmd/go/internal/workcmd/init.go index 52185391c1..20fef91d5e 100644 --- a/src/cmd/go/internal/workcmd/init.go +++ b/src/cmd/go/internal/workcmd/init.go @@ -44,11 +44,11 @@ func init() { } func runInit(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() + modload.InitWorkfile(modload.LoaderState) modload.LoaderState.ForceUseModules = true - gowork := modload.WorkFilePath() + gowork := modload.WorkFilePath(modload.LoaderState) if gowork == "" { gowork = filepath.Join(base.Cwd(), "go.work") } diff --git a/src/cmd/go/internal/workcmd/sync.go b/src/cmd/go/internal/workcmd/sync.go index 640771d8f7..c58cd55cee 100644 --- a/src/cmd/go/internal/workcmd/sync.go +++ b/src/cmd/go/internal/workcmd/sync.go @@ -49,8 +49,8 @@ func init() { func runSync(ctx context.Context, cmd *base.Command, args []string) { modload.LoaderState.ForceUseModules = true - modload.InitWorkfile() - if modload.WorkFilePath() == "" { + modload.InitWorkfile(modload.LoaderState) + if modload.WorkFilePath(modload.LoaderState) == "" { base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)") } @@ -73,7 +73,7 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) { } for _, m := range mms.Versions() { opts.MainModule = m - _, pkgs := modload.LoadPackages(ctx, opts, "all") + _, pkgs := modload.LoadPackages(modload.LoaderState, ctx, opts, "all") opts.MainModule = module.Version{} // reset var ( @@ -91,7 +91,7 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) { mustSelectFor[m] = mustSelect } - workFilePath := modload.WorkFilePath() // save go.work path because EnterModule clobbers it. + workFilePath := modload.WorkFilePath(modload.LoaderState) // save go.work path because EnterModule clobbers it. var goV string for _, m := range mms.Versions() { @@ -114,12 +114,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(ctx, nil, mustSelectFor[m]) + changed, err := modload.EditBuildList(modload.LoaderState, ctx, nil, mustSelectFor[m]) if err != nil { continue } if changed { - modload.LoadPackages(ctx, modload.PackageOpts{ + modload.LoadPackages(modload.LoaderState, ctx, modload.PackageOpts{ Tags: imports.AnyTags(), Tidy: true, VendorModulesInGOROOTSrc: true, @@ -131,7 +131,7 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) { }, "all") modload.WriteGoMod(ctx, modload.WriteOpts{}) } - goV = gover.Max(goV, modload.LoaderState.MainModules.GoVersion()) + goV = gover.Max(goV, modload.LoaderState.MainModules.GoVersion(modload.LoaderState)) } wf, err := modload.ReadWorkFile(workFilePath) diff --git a/src/cmd/go/internal/workcmd/use.go b/src/cmd/go/internal/workcmd/use.go index 2842163517..ca8de22cca 100644 --- a/src/cmd/go/internal/workcmd/use.go +++ b/src/cmd/go/internal/workcmd/use.go @@ -62,8 +62,8 @@ func init() { func runUse(ctx context.Context, cmd *base.Command, args []string) { modload.LoaderState.ForceUseModules = true - modload.InitWorkfile() - gowork := modload.WorkFilePath() + modload.InitWorkfile(modload.LoaderState) + gowork := modload.WorkFilePath(modload.LoaderState) if gowork == "" { base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)") } diff --git a/src/cmd/go/internal/workcmd/vendor.go b/src/cmd/go/internal/workcmd/vendor.go index f9f0cc0898..36c1f7b522 100644 --- a/src/cmd/go/internal/workcmd/vendor.go +++ b/src/cmd/go/internal/workcmd/vendor.go @@ -46,8 +46,8 @@ func init() { } func runVendor(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() - if modload.WorkFilePath() == "" { + modload.InitWorkfile(modload.LoaderState) + if modload.WorkFilePath(modload.LoaderState) == "" { base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)") }