Skip to content

Commit

Permalink
cmd/go: set go.work path using GOWORK, and remove -workfile flag
Browse files Browse the repository at this point in the history
This change removes the -workfile flag and allows the go.work file path
to be set using GOWORK (which was previously read-only). This removes
the potential discrepancy and confusion between the flag and environment
variable.

GOWORK will still return the actual path of the go.work file found if it
is set to '' or 'auto'. GOWORK will return 'off' if it is set to 'off'.

For #45713
Fixes #51171

Change-Id: I72eed65d47c63c81433f2b54158d514daeaa1ab3
Reviewed-on: https://go-review.googlesource.com/c/go/+/385995
Trust: Michael Matloob <[email protected]>
Run-TryBot: Michael Matloob <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Bryan Mills <[email protected]>
  • Loading branch information
matloob committed Feb 16, 2022
1 parent 293ecd8 commit 5d8d387
Show file tree
Hide file tree
Showing 27 changed files with 80 additions and 86 deletions.
4 changes: 2 additions & 2 deletions doc/go1.18.html
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ <h3 id="go-command">Go command</h3>
<p><!-- https://golang.org/issue/45713 -->
The <code>go</code> command now supports a "Workspace" mode. If a
<code>go.work</code> file is found in the working directory or a
parent directory, or one is specified using the <code>-workfile</code>
flag, it will put the <code>go</code> command into workspace mode.
parent directory, or one is specified using the <code>GOWORK</code>
environment variable, it will put the <code>go</code> command into workspace mode.
In workspace mode, the <code>go.work</code> file will be used to
determine the set of main modules used as the roots for module
resolution, instead of using the normally-found <code>go.mod</code>
Expand Down
16 changes: 8 additions & 8 deletions src/cmd/go/alldocs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 0 additions & 7 deletions src/cmd/go/internal/base/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,6 @@ func AddModFlag(flags *flag.FlagSet) {
flags.Var(explicitStringFlag{value: &cfg.BuildMod, explicit: &cfg.BuildModExplicit}, "mod", "")
}

// AddWorkfileFlag adds the workfile flag to the flag set. It enables workspace
// mode for commands that support it by resetting the cfg.WorkFile variable
// to "" (equivalent to auto) rather than off.
func AddWorkfileFlag(flags *flag.FlagSet) {
flags.Var(explicitStringFlag{value: &cfg.WorkFile, explicit: &cfg.WorkFileExplicit}, "workfile", "")
}

// AddModCommonFlags adds the module-related flags common to build commands
// and 'go mod' subcommands.
func AddModCommonFlags(flags *flag.FlagSet) {
Expand Down
6 changes: 2 additions & 4 deletions src/cmd/go/internal/cfg/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ var (
BuildWork bool // -work flag
BuildX bool // -x flag

ModCacheRW bool // -modcacherw flag
ModFile string // -modfile flag
WorkFile string // -workfile flag
WorkFileExplicit bool // whether -workfile was set explicitly
ModCacheRW bool // -modcacherw flag
ModFile string // -modfile flag

CmdName string // "build", "install", "list", "mod tidy", etc.

Expand Down
4 changes: 4 additions & 0 deletions src/cmd/go/internal/envcmd/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ func ExtraEnvVars() []cfg.EnvVar {
}
modload.InitWorkfile()
gowork := modload.WorkFilePath()
// As a special case, if a user set off explicitly, report that in GOWORK.
if cfg.Getenv("GOWORK") == "off" {
gowork = "off"
}
return []cfg.EnvVar{
{Name: "GOMOD", Value: gomod},
{Name: "GOWORK", Value: gowork},
Expand Down
8 changes: 8 additions & 0 deletions src/cmd/go/internal/help/helpdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,14 @@ General-purpose environment variables:
GOVCS
Lists version control commands that may be used with matching servers.
See 'go help vcs'.
GOWORK
In module aware mode, use the given go.work file as a workspace file.
By default or when GOWORK is "auto", the go command searches for a
file named go.work in the current directory and then containing directories
until one is found. If a valid go.work file is found, the modules
specified will collectively be used as the main modules. If GOWORK
is "off", or a go.work file is not found in "auto" mode, workspace
mode is disabled.
Environment variables for use with cgo:
Expand Down
1 change: 0 additions & 1 deletion src/cmd/go/internal/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,6 @@ For more about modules, see https://golang.org/ref/mod.
func init() {
CmdList.Run = runList // break init cycle
work.AddBuildFlags(CmdList, work.DefaultBuildFlags)
base.AddWorkfileFlag(&CmdList.Flag)
}

var (
Expand Down
1 change: 0 additions & 1 deletion src/cmd/go/internal/modcmd/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ func init() {
// TODO(jayconrod): https://golang.org/issue/35849 Apply -x to other 'go mod' commands.
cmdDownload.Flag.BoolVar(&cfg.BuildX, "x", false, "")
base.AddModCommonFlags(&cmdDownload.Flag)
base.AddWorkfileFlag(&cmdDownload.Flag)
}

type moduleJSON struct {
Expand Down
1 change: 0 additions & 1 deletion src/cmd/go/internal/modcmd/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ var (
func init() {
cmdGraph.Flag.Var(&graphGo, "go", "")
base.AddModCommonFlags(&cmdGraph.Flag)
base.AddWorkfileFlag(&cmdGraph.Flag)
}

func runGraph(ctx context.Context, cmd *base.Command, args []string) {
Expand Down
1 change: 0 additions & 1 deletion src/cmd/go/internal/modcmd/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ See https://golang.org/ref/mod#go-mod-verify for more about 'go mod verify'.

func init() {
base.AddModCommonFlags(&cmdVerify.Flag)
base.AddWorkfileFlag(&cmdVerify.Flag)
}

func runVerify(ctx context.Context, cmd *base.Command, args []string) {
Expand Down
1 change: 0 additions & 1 deletion src/cmd/go/internal/modcmd/why.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ var (
func init() {
cmdWhy.Run = runWhy // break init cycle
base.AddModCommonFlags(&cmdWhy.Flag)
base.AddWorkfileFlag(&cmdWhy.Flag)
}

func runWhy(ctx context.Context, cmd *base.Command, args []string) {
Expand Down
10 changes: 5 additions & 5 deletions src/cmd/go/internal/modload/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,16 +288,16 @@ func BinDir() string {
// 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() {
switch cfg.WorkFile {
switch gowork := cfg.Getenv("GOWORK"); gowork {
case "off":
workFilePath = ""
case "", "auto":
workFilePath = findWorkspaceFile(base.Cwd())
default:
if !filepath.IsAbs(cfg.WorkFile) {
base.Fatalf("the path provided to -workfile must be an absolute path")
if !filepath.IsAbs(gowork) {
base.Fatalf("the path provided to GOWORK must be an absolute path")
}
workFilePath = cfg.WorkFile
workFilePath = gowork
}
}

Expand Down Expand Up @@ -1109,7 +1109,7 @@ func setDefaultBuildMod() {
if inWorkspaceMode() && cfg.BuildMod != "readonly" {
base.Fatalf("go: -mod may only be set to readonly when in workspace mode, but it is set to %q"+
"\n\tRemove the -mod flag to use the default readonly value,"+
"\n\tor set -workfile=off to disable workspace mode.", cfg.BuildMod)
"\n\tor set GOWORK=off to disable workspace mode.", cfg.BuildMod)
}
// Don't override an explicit '-mod=' argument.
return
Expand Down
1 change: 0 additions & 1 deletion src/cmd/go/internal/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ func init() {
CmdRun.Run = runRun // break init loop

work.AddBuildFlags(CmdRun, work.DefaultBuildFlags)
base.AddWorkfileFlag(&CmdRun.Flag)
CmdRun.Flag.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "")
}

Expand Down
1 change: 0 additions & 1 deletion src/cmd/go/internal/test/testflag.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (

func init() {
work.AddBuildFlags(CmdTest, work.OmitVFlag)
base.AddWorkfileFlag(&CmdTest.Flag)

cf := CmdTest.Flag
cf.BoolVar(&testC, "c", false, "")
Expand Down
9 changes: 0 additions & 9 deletions src/cmd/go/internal/work/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,6 @@ and test commands:
directory, but it is not accessed. When -modfile is specified, an
alternate go.sum file is also used: its path is derived from the
-modfile flag by trimming the ".mod" extension and appending ".sum".
-workfile file
in module aware mode, use the given go.work file as a workspace file.
By default or when -workfile is "auto", the go command searches for a
file named go.work in the current directory and then containing directories
until one is found. If a valid go.work file is found, the modules
specified will collectively be used as the main modules. If -workfile
is "off", or a go.work file is not found in "auto" mode, workspace
mode is disabled.
-overlay file
read a JSON config file that provides an overlay for build operations.
The file is a JSON struct with a single field, named 'Replace', that
Expand Down Expand Up @@ -217,7 +209,6 @@ func init() {

AddBuildFlags(CmdBuild, DefaultBuildFlags)
AddBuildFlags(CmdInstall, DefaultBuildFlags)
base.AddWorkfileFlag(&CmdBuild.Flag)
}

// Note that flags consulted by other parts of the code
Expand Down
4 changes: 1 addition & 3 deletions src/cmd/go/internal/workcmd/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ func init() {
cmdEdit.Flag.Var(flagFunc(flagEditworkDropUse), "dropuse", "")
cmdEdit.Flag.Var(flagFunc(flagEditworkReplace), "replace", "")
cmdEdit.Flag.Var(flagFunc(flagEditworkDropReplace), "dropreplace", "")

base.AddWorkfileFlag(&cmdEdit.Flag)
}

func runEditwork(ctx context.Context, cmd *base.Command, args []string) {
Expand All @@ -137,7 +135,7 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) {
}

if gowork == "" {
base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using -workfile flag)")
base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
}

anyFlags :=
Expand Down
6 changes: 0 additions & 6 deletions src/cmd/go/internal/workcmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,13 @@ current go version will also be listed in the go.work file.

func init() {
base.AddModCommonFlags(&cmdInit.Flag)
base.AddWorkfileFlag(&cmdInit.Flag)
}

func runInit(ctx context.Context, cmd *base.Command, args []string) {
modload.InitWorkfile()

modload.ForceUseModules = true

// TODO(matloob): support using the -workfile path
// To do that properly, we'll have to make the module directories
// make dirs relative to workFile path before adding the paths to
// the directory entries

workFile := modload.WorkFilePath()
if workFile == "" {
workFile = filepath.Join(base.Cwd(), "go.work")
Expand Down
3 changes: 1 addition & 2 deletions src/cmd/go/internal/workcmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,13 @@ that in each workspace module.

func init() {
base.AddModCommonFlags(&cmdSync.Flag)
base.AddWorkfileFlag(&cmdSync.Flag)
}

func runSync(ctx context.Context, cmd *base.Command, args []string) {
modload.ForceUseModules = true
modload.InitWorkfile()
if modload.WorkFilePath() == "" {
base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using -workfile flag)")
base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
}

workGraph := modload.LoadModGraph(ctx, "")
Expand Down
3 changes: 1 addition & 2 deletions src/cmd/go/internal/workcmd/use.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ func init() {
cmdUse.Run = runUse // break init cycle

base.AddModCommonFlags(&cmdUse.Flag)
base.AddWorkfileFlag(&cmdUse.Flag)
}

func runUse(ctx context.Context, cmd *base.Command, args []string) {
Expand All @@ -53,7 +52,7 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
gowork = modload.WorkFilePath()

if gowork == "" {
base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using -workfile flag)")
base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
}
workFile, err := modload.ReadWorkFile(gowork)
if err != nil {
Expand Down
8 changes: 6 additions & 2 deletions src/cmd/go/testdata/script/work.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ stdout 'example.com/b'
go list -mod=readonly all
! go list -mod=mod all
stderr '^go: -mod may only be set to readonly when in workspace mode'
go list -mod=mod -workfile=off all
env GOWORK=off
go list -mod=mod all
env GOWORK=

# Test that duplicates in the use list return an error
cp go.work go.work.backup
Expand All @@ -53,7 +55,9 @@ go run example.com/d
# This exercises the code that determines which module command-line-arguments
# belongs to.
go list ./b/main.go
go build -n -workfile=off -o foo foo.go
env GOWORK=off
go build -n -o foo foo.go
env GOWORK=
go build -n -o foo foo.go

-- go.work.dup --
Expand Down
3 changes: 2 additions & 1 deletion src/cmd/go/testdata/script/work_edit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ cmp stdout go.work.want_print
go work edit -json -go 1.19 -use b -dropuse c -replace '[email protected] = ../z' -dropreplace x.1 -dropreplace [email protected]
cmp stdout go.work.want_json

go work edit -print -fmt -workfile $GOPATH/src/unformatted
env GOWORK=$GOPATH/src/unformatted
go work edit -print -fmt
cmp stdout formatted

-- m/go.mod --
Expand Down
4 changes: 4 additions & 0 deletions src/cmd/go/testdata/script/work_env.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ cd src
go env GOWORK
stdout 'go.work'

env GOWORK='off'
go env GOWORK
stdout 'off'

! go env -w GOWORK=off
stderr '^go: GOWORK cannot be modified$'

Expand Down
24 changes: 24 additions & 0 deletions src/cmd/go/testdata/script/work_gowork.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
env GOWORK=stop.work
! go list a # require absolute path
! stderr panic
env GOWORK=doesnotexist
! go list a
! stderr panic

env GOWORK=$GOPATH/src/stop.work
go list -n a
go build -n a
go test -n a

-- stop.work --
go 1.18

use ./a
-- a/a.go --
package a
-- a/a_test.go --
package a
-- a/go.mod --
module a

go 1.18
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# Test that the workfile flag is used by go work init.
# Test that the GOWORK environment variable flag is used by go work init.

! exists go.work
go work init
exists go.work

go work init -workfile=$GOPATH/src/foo/foo.work
env GOWORK=$GOPATH/src/foo/foo.work
! exists foo/foo.work
go work init
exists foo/foo.work

env GOWORK=
cd foo/bar
! go work init
stderr 'already exists'
Expand Down
10 changes: 5 additions & 5 deletions src/cmd/go/testdata/script/work_nowork.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
! go work use
stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using -workfile flag\)$'
stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'

! go work use .
stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using -workfile flag\)$'
stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'

! go work edit
stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using -workfile flag\)$'
stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'

! go work edit -go=1.18
stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using -workfile flag\)$'
stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'

! go work sync
stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using -workfile flag\)$'
stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'

-- go.mod --
module example
Expand Down
Loading

0 comments on commit 5d8d387

Please sign in to comment.