1
0
mirror of https://github.com/golang/go synced 2024-09-29 16:24:28 -06:00

cmd/go: add -C flag

The -C flag is like tar -C or make -C: it changes to the named directory
early in command startup, before anything else happens.

Fixes #50332.

Change-Id: I8e4546f69044cb3a028d4d26dfba482b08cb845d
Reviewed-on: https://go-review.googlesource.com/c/go/+/421436
Reviewed-by: Bryan Mills <bcmills@google.com>
Auto-Submit: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
This commit is contained in:
Russ Cox 2022-08-05 13:09:20 -04:00 committed by Gopher Robot
parent fb4f7fdb26
commit 2af48cbb7d
24 changed files with 136 additions and 9 deletions

View File

@ -57,12 +57,13 @@ import (
)
var (
unexported bool // -u flag
matchCase bool // -c flag
showAll bool // -all flag
showCmd bool // -cmd flag
showSrc bool // -src flag
short bool // -short flag
unexported bool // -u flag
matchCase bool // -c flag
chdir string // -C flag
showAll bool // -all flag
showCmd bool // -cmd flag
showSrc bool // -src flag
short bool // -short flag
)
// usage is a replacement usage function for the flags package.
@ -96,6 +97,7 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) {
flagSet.Usage = usage
unexported = false
matchCase = false
flagSet.StringVar(&chdir, "C", "", "change to `dir` before running command")
flagSet.BoolVar(&unexported, "u", false, "show unexported symbols as well as exported")
flagSet.BoolVar(&matchCase, "c", false, "symbol matching honors case (paths not affected)")
flagSet.BoolVar(&showAll, "all", false, "show all documentation for package")
@ -103,6 +105,11 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) {
flagSet.BoolVar(&showSrc, "src", false, "show source code for symbol")
flagSet.BoolVar(&short, "short", false, "one-line representation for each symbol")
flagSet.Parse(args)
if chdir != "" {
if err := os.Chdir(chdir); err != nil {
return err
}
}
var paths []string
var symbol, method string
// Loop until something is printed.

View File

@ -100,6 +100,10 @@
// The build flags are shared by the build, clean, get, install, list, run,
// and test commands:
//
// -C dir
// Change to dir before running the command.
// Any files named on the command line are interpreted after
// changing directories.
// -a
// force rebuilding of packages that are already up-to-date.
// -n
@ -1233,6 +1237,8 @@
// referred to indirectly. For the full set of modules available to a build,
// use 'go list -m -json all'.
//
// Edit also provides the -C, -n, and -x build flags.
//
// See https://golang.org/ref/mod#go-mod-edit for more about 'go mod edit'.
//
// # Print module requirement graph
@ -1797,7 +1803,7 @@
//
// Usage:
//
// go vet [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]
// go vet [-C dir] [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]
//
// Vet runs the Go vet command on the packages named by the import paths.
//
@ -1806,6 +1812,7 @@
// For a list of checkers and their flags, see 'go tool vet help'.
// For details of a specific checker such as 'printf', see 'go tool vet help printf'.
//
// The -C flag changes to dir before running the 'go vet' command.
// The -n flag prints commands that would be executed.
// The -x flag prints commands as they are executed.
//

49
src/cmd/go/chdir_test.go Normal file
View File

@ -0,0 +1,49 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"cmd/go/internal/base"
"os"
"strings"
"testing"
)
func TestChdir(t *testing.T) {
// We want -C to apply to every go subcommand.
// Test that every command either has a -C flag registered
// or has CustomFlags set. In the latter case, the command
// must be explicitly tested in TestScript/chdir.
script, err := os.ReadFile("testdata/script/chdir.txt")
if err != nil {
t.Fatal(err)
}
var walk func(string, *base.Command)
walk = func(name string, cmd *base.Command) {
if len(cmd.Commands) > 0 {
for _, sub := range cmd.Commands {
walk(name+" "+sub.Name(), sub)
}
return
}
if !cmd.Runnable() {
return
}
if cmd.CustomFlags {
if !strings.Contains(string(script), "# "+name+"\n") {
t.Errorf("%s has custom flags, not tested in testdata/script/chdir.txt", name)
}
return
}
f := cmd.Flag.Lookup("C")
if f == nil {
t.Errorf("%s has no -C flag", name)
} else if f.Usage != "AddChdirFlag" {
t.Errorf("%s has -C flag but not from AddChdirFlag", name)
}
}
walk("go", base.Go)
}

View File

@ -6,6 +6,7 @@ package base
import (
"flag"
"os"
"cmd/go/internal/cfg"
"cmd/go/internal/fsys"
@ -57,6 +58,13 @@ func AddBuildFlagsNX(flags *flag.FlagSet) {
flags.BoolVar(&cfg.BuildX, "x", false, "")
}
// AddChdirFlag adds the -C flag to the flag set.
func AddChdirFlag(flags *flag.FlagSet) {
// The usage message is never printed, but it's used in chdir_test.go
// to identify that the -C flag is from AddChdirFlag.
flags.Func("C", "AddChdirFlag", os.Chdir)
}
// AddModFlag adds the -mod build flag to the flag set.
func AddModFlag(flags *flag.FlagSet) {
flags.Var(explicitStringFlag{value: &cfg.BuildMod, explicit: &cfg.BuildModExplicit}, "mod", "")

View File

@ -37,6 +37,7 @@ The report includes useful system information.
func init() {
CmdBug.Flag.BoolVar(&cfg.BuildV, "v", false, "")
base.AddChdirFlag(&CmdBug.Flag)
}
func runBug(ctx context.Context, cmd *base.Command, args []string) {

View File

@ -57,6 +57,7 @@ For more about environment variables, see 'go help environment'.
func init() {
CmdEnv.Run = runEnv // break init cycle
base.AddChdirFlag(&CmdEnv.Flag)
}
var (

View File

@ -21,6 +21,7 @@ import (
func init() {
base.AddBuildFlagsNX(&CmdFmt.Flag)
base.AddChdirFlag(&CmdFmt.Flag)
base.AddModFlag(&CmdFmt.Flag)
base.AddModCommonFlags(&CmdFmt.Flag)
}

View File

@ -84,6 +84,7 @@ func init() {
// TODO(jayconrod): https://golang.org/issue/35849 Apply -x to other 'go mod' commands.
cmdDownload.Flag.BoolVar(&cfg.BuildX, "x", false, "")
base.AddChdirFlag(&cmdDownload.Flag)
base.AddModCommonFlags(&cmdDownload.Flag)
}

View File

@ -127,6 +127,8 @@ Note that this only describes the go.mod file itself, not other modules
referred to indirectly. For the full set of modules available to a build,
use 'go list -m -json all'.
Edit also provides the -C, -n, and -x build flags.
See https://golang.org/ref/mod#go-mod-edit for more about 'go mod edit'.
`,
}
@ -157,8 +159,9 @@ func init() {
cmdEdit.Flag.Var(flagFunc(flagRetract), "retract", "")
cmdEdit.Flag.Var(flagFunc(flagDropRetract), "dropretract", "")
base.AddModCommonFlags(&cmdEdit.Flag)
base.AddBuildFlagsNX(&cmdEdit.Flag)
base.AddChdirFlag(&cmdEdit.Flag)
base.AddModCommonFlags(&cmdEdit.Flag)
}
func runEdit(ctx context.Context, cmd *base.Command, args []string) {

View File

@ -41,6 +41,7 @@ var (
func init() {
cmdGraph.Flag.Var(&graphGo, "go", "")
base.AddChdirFlag(&cmdGraph.Flag)
base.AddModCommonFlags(&cmdGraph.Flag)
}

View File

@ -34,6 +34,7 @@ See https://golang.org/ref/mod#go-mod-init for more about 'go mod init'.
}
func init() {
base.AddChdirFlag(&cmdInit.Flag)
base.AddModCommonFlags(&cmdInit.Flag)
}

View File

@ -64,6 +64,7 @@ func init() {
cmdTidy.Flag.BoolVar(&tidyE, "e", false, "")
cmdTidy.Flag.Var(&tidyGo, "go", "")
cmdTidy.Flag.Var(&tidyCompat, "compat", "")
base.AddChdirFlag(&cmdTidy.Flag)
base.AddModCommonFlags(&cmdTidy.Flag)
}

View File

@ -61,6 +61,7 @@ func init() {
cmdVendor.Flag.BoolVar(&cfg.BuildV, "v", false, "")
cmdVendor.Flag.BoolVar(&vendorE, "e", false, "")
cmdVendor.Flag.StringVar(&vendorO, "o", "", "")
base.AddChdirFlag(&cmdVendor.Flag)
base.AddModCommonFlags(&cmdVendor.Flag)
}

View File

@ -38,6 +38,7 @@ See https://golang.org/ref/mod#go-mod-verify for more about 'go mod verify'.
}
func init() {
base.AddChdirFlag(&cmdVerify.Flag)
base.AddModCommonFlags(&cmdVerify.Flag)
}

View File

@ -58,6 +58,7 @@ var (
func init() {
cmdWhy.Run = runWhy // break init cycle
base.AddChdirFlag(&cmdWhy.Flag)
base.AddModCommonFlags(&cmdWhy.Flag)
}

View File

@ -48,6 +48,7 @@ func isGccgoTool(tool string) bool {
}
func init() {
base.AddChdirFlag(&CmdTool.Flag)
CmdTool.Flag.BoolVar(&toolN, "n", false, "")
}

View File

@ -44,6 +44,7 @@ See also: go doc runtime/debug.BuildInfo.
}
func init() {
base.AddChdirFlag(&CmdVersion.Flag)
CmdVersion.Run = runVersion // break init cycle
}

View File

@ -25,7 +25,7 @@ func init() {
var CmdVet = &base.Command{
CustomFlags: true,
UsageLine: "go vet [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]",
UsageLine: "go vet [-C dir] [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]",
Short: "report likely mistakes in packages",
Long: `
Vet runs the Go vet command on the packages named by the import paths.
@ -35,6 +35,7 @@ For more about specifying packages, see 'go help packages'.
For a list of checkers and their flags, see 'go tool vet help'.
For details of a specific checker such as 'printf', see 'go tool vet help printf'.
The -C flag changes to dir before running the 'go vet' command.
The -n flag prints commands that would be executed.
The -x flag prints commands as they are executed.

View File

@ -58,6 +58,10 @@ will be written to that directory.
The build flags are shared by the build, clean, get, install, list, run,
and test commands:
-C dir
Change to dir before running the command.
Any files named on the command line are interpreted after
changing directories.
-a
force rebuilding of packages that are already up-to-date.
-n
@ -282,6 +286,7 @@ const (
// install, list, run, and test commands.
func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) {
base.AddBuildFlagsNX(&cmd.Flag)
base.AddChdirFlag(&cmd.Flag)
cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "")
cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "")
if mask&OmitVFlag == 0 {

View File

@ -109,6 +109,7 @@ func init() {
cmdEdit.Flag.Var(flagFunc(flagEditworkDropUse), "dropuse", "")
cmdEdit.Flag.Var(flagFunc(flagEditworkReplace), "replace", "")
cmdEdit.Flag.Var(flagFunc(flagEditworkDropReplace), "dropreplace", "")
base.AddChdirFlag(&cmdEdit.Flag)
}
func runEditwork(ctx context.Context, cmd *base.Command, args []string) {

View File

@ -34,6 +34,7 @@ for more information.
}
func init() {
base.AddChdirFlag(&cmdInit.Flag)
base.AddModCommonFlags(&cmdInit.Flag)
}

View File

@ -41,6 +41,7 @@ for more information.
}
func init() {
base.AddChdirFlag(&cmdSync.Flag)
base.AddModCommonFlags(&cmdSync.Flag)
}

View File

@ -43,6 +43,7 @@ var useR = cmdUse.Flag.Bool("r", false, "")
func init() {
cmdUse.Run = runUse // break init cycle
base.AddChdirFlag(&cmdUse.Flag)
base.AddModCommonFlags(&cmdUse.Flag)
}

31
src/cmd/go/testdata/script/chdir.txt vendored Normal file
View File

@ -0,0 +1,31 @@
env OLD=$PWD
# basic -C functionality
cd $GOROOT/src/math
go list -C ../strings
stdout strings
! go list -C ../nonexist
stderr 'chdir.*nonexist'
# check for -C in subcommands with custom flag parsing
# cmd/go/chdir_test.go handles the normal ones more directly.
# go doc
go doc -C ../strings HasPrefix
# go env
go env -C $OLD/custom GOMOD
stdout 'custom[\\/]go.mod'
! go env -C ../nonexist
stderr '^invalid value "../nonexist" for flag -C: chdir ../nonexist:.*$'
# go test
go test -n -C ../strings
stderr 'strings\.test'
# go vet
go vet -n -C ../strings
stderr strings_test
-- custom/go.mod --
module m