From 0c3015191f085fe4941da677d1a7787379bc57d9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 22 May 2023 12:26:15 -0400 Subject: [PATCH] cmd/go: add mod edit -toolchain and work edit -toolchain We have added a new toolchain directive in go.mod and go.work. This CL adds support in mod edit and work edit for changing the toolchain line. For #57001. Change-Id: I36a960796630a359b8a587877cb9548c299d5c87 Reviewed-on: https://go-review.googlesource.com/c/go/+/497296 TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills Run-TryBot: Russ Cox --- src/cmd/go/alldocs.go | 24 +++--- src/cmd/go/internal/modcmd/edit.go | 76 ++++++++++++------- src/cmd/go/internal/workcmd/edit.go | 57 +++++++++----- src/cmd/go/testdata/script/mod_edit_go.txt | 5 +- .../go/testdata/script/mod_edit_toolchain.txt | 18 +++++ src/cmd/go/testdata/script/work_edit.txt | 4 + .../testdata/script/work_edit_toolchain.txt | 20 +++++ 7 files changed, 147 insertions(+), 57 deletions(-) create mode 100644 src/cmd/go/testdata/script/mod_edit_toolchain.txt create mode 100644 src/cmd/go/testdata/script/work_edit_toolchain.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 455a0f7536..6a1cb8b810 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1210,6 +1210,8 @@ // // The -go=version flag sets the expected Go language version. // +// The -toolchain=name flag sets the Go toolchain to use. +// // The -print flag prints the final go.mod in its text format instead of // writing it back to go.mod. // @@ -1222,12 +1224,13 @@ // } // // type GoMod struct { -// Module ModPath -// Go string -// Require []Require -// Exclude []Module -// Replace []Replace -// Retract []Retract +// Module ModPath +// Go string +// Toolchain string +// Require []Require +// Exclude []Module +// Replace []Replace +// Retract []Retract // } // // type ModPath struct { @@ -1523,6 +1526,8 @@ // // The -go=version flag sets the expected Go language version. // +// The -toolchain=name flag sets the Go toolchain to use. +// // The -print flag prints the final go.work in its text format instead of // writing it back to go.mod. // @@ -1530,9 +1535,10 @@ // writing it back to go.mod. The JSON output corresponds to these Go types: // // type GoWork struct { -// Go string -// Use []Use -// Replace []Replace +// Go string +// Toolchain string +// Use []Use +// Replace []Replace // } // // type Use struct { diff --git a/src/cmd/go/internal/modcmd/edit.go b/src/cmd/go/internal/modcmd/edit.go index 2b63af5855..bd22649172 100644 --- a/src/cmd/go/internal/modcmd/edit.go +++ b/src/cmd/go/internal/modcmd/edit.go @@ -79,6 +79,8 @@ and the changes are applied in the order given. The -go=version flag sets the expected Go language version. +The -toolchain=name flag sets the Go toolchain to use. + The -print flag prints the final go.mod in its text format instead of writing it back to go.mod. @@ -91,12 +93,13 @@ writing it back to go.mod. The JSON output corresponds to these Go types: } type GoMod struct { - Module ModPath - Go string - Require []Require - Exclude []Module - Replace []Replace - Retract []Retract + Module ModPath + Go string + Toolchain string + Require []Require + Exclude []Module + Replace []Replace + Retract []Retract } type ModPath struct { @@ -135,12 +138,13 @@ See https://golang.org/ref/mod#go-mod-edit for more about 'go mod edit'. } var ( - editFmt = cmdEdit.Flag.Bool("fmt", false, "") - editGo = cmdEdit.Flag.String("go", "", "") - editJSON = cmdEdit.Flag.Bool("json", false, "") - editPrint = cmdEdit.Flag.Bool("print", false, "") - editModule = cmdEdit.Flag.String("module", "", "") - edits []func(*modfile.File) // edits specified in flags + editFmt = cmdEdit.Flag.Bool("fmt", false, "") + editGo = cmdEdit.Flag.String("go", "", "") + editToolchain = cmdEdit.Flag.String("toolchain", "", "") + editJSON = cmdEdit.Flag.Bool("json", false, "") + editPrint = cmdEdit.Flag.Bool("print", false, "") + editModule = cmdEdit.Flag.String("module", "", "") + edits []func(*modfile.File) // edits specified in flags ) type flagFunc func(string) @@ -166,13 +170,13 @@ func init() { } func runEdit(ctx context.Context, cmd *base.Command, args []string) { - anyFlags := - *editModule != "" || - *editGo != "" || - *editJSON || - *editPrint || - *editFmt || - len(edits) > 0 + anyFlags := *editModule != "" || + *editGo != "" || + *editToolchain != "" || + *editJSON || + *editPrint || + *editFmt || + len(edits) > 0 if !anyFlags { base.Fatalf("go: no flags specified (see 'go help mod edit').") @@ -198,11 +202,16 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) { } } - if *editGo != "" { + if *editGo != "" && *editGo != "none" { if !modfile.GoVersionRE.MatchString(*editGo) { base.Fatalf(`go mod: invalid -go option; expecting something like "-go %s"`, gover.Local()) } } + if *editToolchain != "" && *editToolchain != "none" { + if !modfile.ToolchainRE.MatchString(*editToolchain) { + base.Fatalf(`go mod: invalid -toolchain option; expecting something like "-toolchain go%s"`, gover.Local()) + } + } data, err := lockedfile.Read(gomod) if err != nil { @@ -218,11 +227,20 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) { modFile.AddModuleStmt(*editModule) } - if *editGo != "" { + if *editGo == "none" { + modFile.DropGoStmt() + } else if *editGo != "" { if err := modFile.AddGoStmt(*editGo); err != nil { base.Fatalf("go: internal error: %v", err) } } + if *editToolchain == "none" { + modFile.DropToolchainStmt() + } else if *editToolchain != "" { + if err := modFile.AddToolchainStmt(*editToolchain); err != nil { + base.Fatalf("go: internal error: %v", err) + } + } if len(edits) > 0 { for _, edit := range edits { @@ -460,12 +478,13 @@ func flagDropRetract(arg string) { // fileJSON is the -json output data structure. type fileJSON struct { - Module editModuleJSON - Go string `json:",omitempty"` - Require []requireJSON - Exclude []module.Version - Replace []replaceJSON - Retract []retractJSON + Module editModuleJSON + Go string `json:",omitempty"` + Toolchain string `json:",omitempty"` + Require []requireJSON + Exclude []module.Version + Replace []replaceJSON + Retract []retractJSON } type editModuleJSON struct { @@ -502,6 +521,9 @@ func editPrintJSON(modFile *modfile.File) { if modFile.Go != nil { f.Go = modFile.Go.Version } + if modFile.Toolchain != nil { + f.Toolchain = modFile.Toolchain.Name + } for _, r := range modFile.Require { f.Require = append(f.Require, requireJSON{Path: r.Mod.Path, Version: r.Mod.Version, Indirect: r.Indirect}) } diff --git a/src/cmd/go/internal/workcmd/edit.go b/src/cmd/go/internal/workcmd/edit.go index e4254782a8..4157e521d7 100644 --- a/src/cmd/go/internal/workcmd/edit.go +++ b/src/cmd/go/internal/workcmd/edit.go @@ -58,6 +58,8 @@ editing flags may be repeated, and the changes are applied in the order given. The -go=version flag sets the expected Go language version. +The -toolchain=name flag sets the Go toolchain to use. + The -print flag prints the final go.work in its text format instead of writing it back to go.mod. @@ -65,9 +67,10 @@ The -json flag prints the final go.work file in JSON format instead of writing it back to go.mod. The JSON output corresponds to these Go types: type GoWork struct { - Go string - Use []Use - Replace []Replace + Go string + Toolchain string + Use []Use + Replace []Replace } type Use struct { @@ -91,11 +94,12 @@ for more information. } var ( - editFmt = cmdEdit.Flag.Bool("fmt", false, "") - editGo = cmdEdit.Flag.String("go", "", "") - editJSON = cmdEdit.Flag.Bool("json", false, "") - editPrint = cmdEdit.Flag.Bool("print", false, "") - workedits []func(file *modfile.WorkFile) // edits specified in flags + editFmt = cmdEdit.Flag.Bool("fmt", false, "") + editGo = cmdEdit.Flag.String("go", "", "") + editToolchain = cmdEdit.Flag.String("toolchain", "", "") + editJSON = cmdEdit.Flag.Bool("json", false, "") + editPrint = cmdEdit.Flag.Bool("print", false, "") + workedits []func(file *modfile.WorkFile) // edits specified in flags ) type flagFunc func(string) @@ -128,23 +132,27 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { modload.InitWorkfile() gowork = modload.WorkFilePath() } + if gowork == "" { + base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)") + } - if *editGo != "" { + if *editGo != "" && *editGo != "none" { if !modfile.GoVersionRE.MatchString(*editGo) { - base.Fatalf(`go mod: invalid -go option; expecting something like "-go %s"`, gover.Local()) + base.Fatalf(`go work: invalid -go option; expecting something like "-go %s"`, gover.Local()) } } - - if gowork == "" { - base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)") + if *editToolchain != "" && *editToolchain != "none" { + if !modfile.ToolchainRE.MatchString(*editToolchain) { + base.Fatalf(`go work: invalid -toolchain option; expecting something like "-toolchain go%s"`, gover.Local()) + } } - anyFlags := - *editGo != "" || - *editJSON || - *editPrint || - *editFmt || - len(workedits) > 0 + anyFlags := *editGo != "" || + *editToolchain != "" || + *editJSON || + *editPrint || + *editFmt || + len(workedits) > 0 if !anyFlags { base.Fatalf("go: no flags specified (see 'go help work edit').") @@ -155,11 +163,20 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("go: errors parsing %s:\n%s", base.ShortPath(gowork), err) } - if *editGo != "" { + if *editGo == "none" { + workFile.DropGoStmt() + } else if *editGo != "" { if err := workFile.AddGoStmt(*editGo); err != nil { base.Fatalf("go: internal error: %v", err) } } + if *editToolchain == "none" { + workFile.DropToolchainStmt() + } else if *editToolchain != "" { + if err := workFile.AddToolchainStmt(*editToolchain); err != nil { + base.Fatalf("go: internal error: %v", err) + } + } if len(workedits) > 0 { for _, edit := range workedits { diff --git a/src/cmd/go/testdata/script/mod_edit_go.txt b/src/cmd/go/testdata/script/mod_edit_go.txt index 7e9740fec4..ec04f40f52 100644 --- a/src/cmd/go/testdata/script/mod_edit_go.txt +++ b/src/cmd/go/testdata/script/mod_edit_go.txt @@ -1,4 +1,4 @@ -# Test support for go mod -edit to set language version. +# Test support for go mod edit -go to set language version. env GO111MODULE=on ! go build @@ -13,6 +13,9 @@ go mod edit -go=1.8 ! go build stderr 'type aliases requires' +# go=none should drop the line +go mod edit -go=none +! grep go go.mod -- go.mod -- module m diff --git a/src/cmd/go/testdata/script/mod_edit_toolchain.txt b/src/cmd/go/testdata/script/mod_edit_toolchain.txt new file mode 100644 index 0000000000..525e4dd54a --- /dev/null +++ b/src/cmd/go/testdata/script/mod_edit_toolchain.txt @@ -0,0 +1,18 @@ +# Test support for go mod edit -toolchain to set toolchain to use + +env GOTOOLCHAIN=local +env GO111MODULE=on + +! grep toolchain go.mod +go mod edit -toolchain=go1.9 +grep 'toolchain go1.9' go.mod + +go mod edit -toolchain=local +grep 'toolchain local' go.mod + +go mod edit -toolchain=none +! grep toolchain go.mod + +-- go.mod -- +module m +go 1.8 diff --git a/src/cmd/go/testdata/script/work_edit.txt b/src/cmd/go/testdata/script/work_edit.txt index ad5de6286d..c67696dd6e 100644 --- a/src/cmd/go/testdata/script/work_edit.txt +++ b/src/cmd/go/testdata/script/work_edit.txt @@ -6,6 +6,10 @@ cmpenv go.work go.work.want_initial go work edit -use n cmpenv go.work go.work.want_use_n +grep go go.work +go work edit -go none +! grep go go.work + go work edit -go 1.18 cmp go.work go.work.want_go_118 diff --git a/src/cmd/go/testdata/script/work_edit_toolchain.txt b/src/cmd/go/testdata/script/work_edit_toolchain.txt new file mode 100644 index 0000000000..a171296707 --- /dev/null +++ b/src/cmd/go/testdata/script/work_edit_toolchain.txt @@ -0,0 +1,20 @@ +# Test support for go work edit -toolchain to set toolchain to use + +env GOTOOLCHAIN=local +env GO111MODULE=on + +! grep toolchain go.work +go work edit -toolchain=go1.9 +grep 'toolchain go1.9' go.work + +go work edit -toolchain=local +grep 'toolchain local' go.work + +go work edit -toolchain=none +! grep toolchain go.work + +-- go.work -- +go 1.8 +use . +-- go.mod -- +module m -- 2.48.1