Skip to content

cmd/go: support a -C flag value to not use any current directory #56868

@mvdan

Description

@mvdan

cmd/go uses the current directory for a number of things:

  • Walking parent directories to find the current module
  • Walking parent directories to find the current workspace
  • Resolving relative package paths, like . or ./foo

However, in some cases, we do not need any of those. For example:

  • When querying global config settings, like go env -json GOROOT GOCACHE GOPROXY
  • When querying the default build context, like go list -f={{context.ReleaseTags}} runtime
  • When querying information about the standard library, like go list -json runtime

On one hand, finding the current module and workspace for these three commands is wasteful. On the other, it can be actively harmful. For example, if the current directory or any of its parents has a go.mod with broken syntax, then any of the three commands above may fail. In our fork of cmd/go/script_test.go, we had to make calls like these inside a temporary directory to work around the problem: rogpeppe/go-internal#188

Using a temporary directory is also far from ideal. It still walks the parent directories, which is still wasteful. And it could still break in some (hopefully rare) edge cases, like if /tmp/go.mod existed and had broken syntax.

One possible solution would be to manually turn off the search for "current module" and "current workspace". For the latter, it seems that we can use GOWORK=off. For the former, I don't seem to be able to find an "off" setting. There's GO111MODULE=off, but I don't really want GOPATH mode either, and I believe this mode will disappear at some point anyway.

Moreover, turning off the search for these two files may be enough today, but in the future cmd/go may use the current directory to look for more files, just like go.work was introduced recently. So I really want a general option to mean "do not use the current directory to alter your behavior in any way".

Luckily, in #50332 we gained a global "chdir" option. I propose that it gain a special value, -C=off, to mean just that. The process would still have a current directory, and it would still make direct accesses to the filesystem (e.g. to look inside GOROOT or to read the GOENV file), but any major feature relying on the current directory would be disabled or fail. For example:

  • There would never be a current or main module
  • There would never be a current or main workspace
  • Relative package paths, like go list . or go list ./foo, would fail

I realise that this is likely a complex set of changes for the innards of cmd/go, as the current directory is likely used in many places. I also realise that it likely does not make sense to use some commands like go build -C=off. So perhaps we could start by only supporting this mode in go env and go list: two commands often used by Go tools to get the information they need.

cc @myitcv @rogpeppe

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Accepted

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions