]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: inject vendor dir into builder struct
authorIan Alexander <jitsu@google.com>
Fri, 10 Oct 2025 01:01:05 +0000 (21:01 -0400)
committerIan Alexander <jitsu@google.com>
Fri, 24 Oct 2025 14:21:16 +0000 (07:21 -0700)
This change adds a new field to the Builder struct to store a function
to retrieve the current vendor directory.  This allows us to delay the
determination of the vendor directory until later, which is currently
necessary to successful interaction with the module loader state.
This behavior will be changed in a future CL and the Builder field
will then be removed.

In addition, a new method to get the vendor dir from the module loader
state is added that will return the empty string instead of panicing.

This commit is part of the overall effort to eliminate global
modloader state.

Change-Id: Ib0165edb9502d98ddfa986acf5579c1b746a026f
Reviewed-on: https://go-review.googlesource.com/c/go/+/711133
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

12 files changed:
src/cmd/go/internal/bug/bug.go
src/cmd/go/internal/envcmd/env.go
src/cmd/go/internal/list/list.go
src/cmd/go/internal/modload/init.go
src/cmd/go/internal/run/run.go
src/cmd/go/internal/test/test.go
src/cmd/go/internal/tool/tool.go
src/cmd/go/internal/vet/vet.go
src/cmd/go/internal/work/action.go
src/cmd/go/internal/work/build.go
src/cmd/go/internal/work/exec.go
src/cmd/go/scriptcmds_test.go

index ccd8dee95e69b3b851ac29b08a29a576bace4296..637673f7ebd33dbffb13ef277b7d4541986fb89b 100644 (file)
@@ -106,7 +106,7 @@ func printEnvDetails(loaderstate *modload.State, w io.Writer) {
 func printGoEnv(loaderstate *modload.State, w io.Writer) {
        env := envcmd.MkEnv()
        env = append(env, envcmd.ExtraEnvVars(loaderstate)...)
-       env = append(env, envcmd.ExtraEnvVarsCostly()...)
+       env = append(env, envcmd.ExtraEnvVarsCostly(loaderstate)...)
        envcmd.PrintEnv(w, env, false)
 }
 
index 517722a4265eddd3e283cd2807fc8f9758562ea2..aaadc2fde1e322351a65e31fbf202b9de6cd7128 100644 (file)
@@ -211,8 +211,8 @@ func ExtraEnvVars(loaderstate *modload.State) []cfg.EnvVar {
 
 // ExtraEnvVarsCostly returns environment variables that should not leak into child processes
 // but are costly to evaluate.
-func ExtraEnvVarsCostly() []cfg.EnvVar {
-       b := work.NewBuilder("")
+func ExtraEnvVarsCostly(loaderstate *modload.State) []cfg.EnvVar {
+       b := work.NewBuilder("", loaderstate.VendorDirOrEmpty)
        defer func() {
                if err := b.Close(); err != nil {
                        base.Fatal(err)
@@ -337,7 +337,7 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
        }
        if needCostly {
                work.BuildInit(modload.LoaderState)
-               env = append(env, ExtraEnvVarsCostly()...)
+               env = append(env, ExtraEnvVarsCostly(modload.LoaderState)...)
        }
 
        if len(args) > 0 {
index 454efd31947d0475805b35687f5298afda028801..200aca007d235696d6dc8a25046a06244142b999 100644 (file)
@@ -713,7 +713,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
        // Do we need to run a build to gather information?
        needStale := (listJson && listJsonFields.needAny("Stale", "StaleReason")) || strings.Contains(*listFmt, ".Stale")
        if needStale || *listExport || *listCompiled {
-               b := work.NewBuilder("")
+               b := work.NewBuilder("", modload.LoaderState.VendorDirOrEmpty)
                if *listE {
                        b.AllowErrors = true
                }
index 12f52381b045e74566f1ec3d685d40cb6e821df6..274589cbfdb0f8ab7e1e4d165ef1517d89b6b353 100644 (file)
@@ -183,17 +183,25 @@ func (mms *MainModuleSet) InGorootSrc(m module.Version) bool {
 }
 
 func (mms *MainModuleSet) mustGetSingleMainModule(loaderstate *State) module.Version {
+       mm, err := mms.getSingleMainModule(loaderstate)
+       if err != nil {
+               panic(err)
+       }
+       return mm
+}
+
+func (mms *MainModuleSet) getSingleMainModule(loaderstate *State) (module.Version, error) {
        if mms == nil || len(mms.versions) == 0 {
-               panic("internal error: mustGetSingleMainModule called in context with no main modules")
+               return module.Version{}, errors.New("internal error: mustGetSingleMainModule called in context with no main modules")
        }
        if len(mms.versions) != 1 {
                if inWorkspaceMode(loaderstate) {
-                       panic("internal error: mustGetSingleMainModule called in workspace mode")
+                       return module.Version{}, errors.New("internal error: mustGetSingleMainModule called in workspace mode")
                } else {
-                       panic("internal error: multiple main modules present outside of workspace mode")
+                       return module.Version{}, errors.New("internal error: multiple main modules present outside of workspace mode")
                }
        }
-       return mms.versions[0]
+       return mms.versions[0], nil
 }
 
 func (mms *MainModuleSet) GetSingleIndexOrNil(loaderstate *State) *modFileIndex {
@@ -627,18 +635,38 @@ func Enabled(loaderstate *State) bool {
        return loaderstate.modRoots != nil || cfg.ModulesEnabled
 }
 
-func VendorDir(loaderstate *State) string {
-       if inWorkspaceMode(loaderstate) {
-               return filepath.Join(filepath.Dir(WorkFilePath(loaderstate)), "vendor")
+func (s *State) vendorDir() (string, error) {
+       if inWorkspaceMode(s) {
+               return filepath.Join(filepath.Dir(WorkFilePath(s)), "vendor"), nil
+       }
+       mainModule, err := s.MainModules.getSingleMainModule(s)
+       if err != nil {
+               return "", err
        }
        // 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(loaderstate))
+       modRoot := s.MainModules.ModRoot(mainModule)
        if modRoot == "" {
-               panic("vendor directory does not exist when in single module mode outside of a module")
+               return "", errors.New("vendor directory does not exist when in single module mode outside of a module")
+       }
+       return filepath.Join(modRoot, "vendor"), nil
+}
+
+func (s *State) VendorDirOrEmpty() string {
+       dir, err := s.vendorDir()
+       if err != nil {
+               return ""
+       }
+       return dir
+}
+
+func VendorDir(loaderstate *State) string {
+       dir, err := loaderstate.vendorDir()
+       if err != nil {
+               panic(err)
        }
-       return filepath.Join(modRoot, "vendor")
+       return dir
 }
 
 func inWorkspaceMode(loaderstate *State) bool {
index b6d76514b032d8a0353b9c4eafd0d41316cf3834..c39fcab200b9698649fe7f7252857ad989e99ab3 100644 (file)
@@ -85,7 +85,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
        }
 
        work.BuildInit(modload.LoaderState)
-       b := work.NewBuilder("")
+       b := work.NewBuilder("", modload.LoaderState.VendorDirOrEmpty)
        defer func() {
                if err := b.Close(); err != nil {
                        base.Fatal(err)
index 70207cfbd13267a48db90207a859eb1dac45417c..ba1b0681c56abcbe6b82b7d66c0c1640c94dd0c6 100644 (file)
@@ -854,7 +854,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
                }
        }
 
-       b := work.NewBuilder("")
+       b := work.NewBuilder("", modload.LoaderState.VendorDirOrEmpty)
        defer func() {
                if err := b.Close(); err != nil {
                        base.Fatal(err)
index 75a8fab78ad31b2725330fb526999592d6d4bd1f..7ffc50fc87a4e40a078e5423ff73742ce6178d0f 100644 (file)
@@ -337,7 +337,7 @@ func buildAndRunModtool(loaderstate *modload.State, ctx context.Context, toolNam
 
 func buildAndRunTool(loaderstate *modload.State, ctx context.Context, tool string, args []string, runTool work.ActorFunc) {
        work.BuildInit(loaderstate)
-       b := work.NewBuilder("")
+       b := work.NewBuilder("", loaderstate.VendorDirOrEmpty)
        defer func() {
                if err := b.Close(); err != nil {
                        base.Fatal(err)
index c5ba3ae110d8c3005f555bc62f3c54c284130a6e..0e3689f0c137f5a745853d5347183fc77e72877f 100644 (file)
@@ -224,7 +224,7 @@ func run(ctx context.Context, cmd *base.Command, args []string) {
                base.Fatalf("no packages to %s", cmd.Name())
        }
 
-       b := work.NewBuilder("")
+       b := work.NewBuilder("", modload.LoaderState.VendorDirOrEmpty)
        defer func() {
                if err := b.Close(); err != nil {
                        base.Fatal(err)
index 1c6d253be2eead1c80ef9b434d62b90be9fb11f8..0bff1e5e489ca2572ee7108ff57377f3b32e5be5 100644 (file)
@@ -40,6 +40,7 @@ import (
 // build packages in parallel, and the builder is shared.
 type Builder struct {
        WorkDir            string                    // the temporary work directory (ends in filepath.Separator)
+       getVendorDir       func() string             // TODO(jitsu): remove this after we eliminate global module state
        actionCache        map[cacheKey]*Action      // a cache of already-constructed actions
        flagCache          map[[2]string]bool        // a cache of supported compiler flags
        gccCompilerIDCache map[string]cache.ActionID // cache for gccCompilerID
@@ -275,8 +276,9 @@ const (
 // and arranges for it to be removed in case of an unclean exit.
 // The caller must Close the builder explicitly to clean up the WorkDir
 // before a clean exit.
-func NewBuilder(workDir string) *Builder {
+func NewBuilder(workDir string, getVendorDir func() string) *Builder {
        b := new(Builder)
+       b.getVendorDir = getVendorDir
 
        b.actionCache = make(map[cacheKey]*Action)
        b.gccToolIDCache = make(map[string]string)
index d5687956b4124f62a5544dfd6806a851eb0bcc1f..59f1df473436608dd4f8a45718c7b8ecca87f83c 100644 (file)
@@ -461,7 +461,7 @@ var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs }
 func runBuild(ctx context.Context, cmd *base.Command, args []string) {
        modload.InitWorkfile(modload.LoaderState)
        BuildInit(modload.LoaderState)
-       b := NewBuilder("")
+       b := NewBuilder("", modload.LoaderState.VendorDirOrEmpty)
        defer func() {
                if err := b.Close(); err != nil {
                        base.Fatal(err)
@@ -783,7 +783,7 @@ func InstallPackages(loaderstate *modload.State, ctx context.Context, patterns [
        }
        base.ExitIfErrors()
 
-       b := NewBuilder("")
+       b := NewBuilder("", loaderstate.VendorDirOrEmpty)
        defer func() {
                if err := b.Close(); err != nil {
                        base.Fatal(err)
index eb012d26109f57c12385c421fba6dcb2d99d39b1..7e571c6efbd26a19207d563f9afb416ce0c769a9 100644 (file)
@@ -2260,7 +2260,7 @@ func (b *Builder) ccompile(loaderstate *modload.State, a *Action, outfile string
                        } 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(loaderstate)
+                               from = b.getVendorDir()
                                toPath = "vendor"
                        } else {
                                from = m.Dir
@@ -3383,7 +3383,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
        }
        srcs := []string{src}
 
-       p := load.GoFilesPackage(modload.LoaderState, context.TODO(), load.PackageOpts{}, srcs)
+       p := load.GoFilesPackage(modload.NewState(), 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
index ced8d880e9ae3afc00aadc573bea90476f477854..8195e830caa31b9767a65033e1fb11f9067e410f 100644 (file)
@@ -54,7 +54,8 @@ func scriptCC(cmdExec script.Cmd) script.Cmd {
                        Args:    "args...",
                },
                func(s *script.State, args ...string) (script.WaitFunc, error) {
-                       b := work.NewBuilder(s.Getwd())
+                       fakeVendorDirProvider := func() string { return "" }
+                       b := work.NewBuilder(s.Getwd(), fakeVendorDirProvider)
                        wait, err := cmdExec.Run(s, append(b.GccCmd(".", ""), args...)...)
                        if err != nil {
                                return wait, err