this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cmd/cue: add -C flag, like `go` and `git`

cmd/cue gains a -C flag that changes the working directory before any
other processing. -C must be the first argument and accepts either
"-C dir" or "-C=dir". This mirrors the flag added to cmd/go in
https://go.dev/cl/421436, and follows the same constraint that -C must
precede the subcommand.

Note that other tools like `git` allow the -C flag to come after other
flags even though it affects all flags, and even multiple -C flags.
We don't support these for now as they seem unnecessary.

Fixes #1918

Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: I4ee255d08ea507bd771481af6932b0ebb34e3b6b
Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1236314
Reviewed-by: Paul Jolly <paul@myitcv.io>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

+117 -9
+2
cmd/cue/cmd/flags.go
··· 27 27 flagAllErrors flagName = "all-errors" 28 28 flagAllMajor flagName = "all-major" 29 29 flagAllVersions flagName = "all-versions" 30 + flagChdir flagName = "chdir" 30 31 flagCheck flagName = "check" 31 32 flagDeps flagName = "deps" 32 33 flagDiff flagName = "diff" ··· 93 94 f.BoolP(string(flagIgnore), "i", false, 94 95 "proceed in the presence of errors") 95 96 f.BoolP(string(flagAllErrors), "E", false, "print all available errors") 97 + f.VarP(chdirFlag{}, string(flagChdir), "C", "change working directory before running command (must be the first flag)") 96 98 97 99 f.String(string(flagCpuProfile), "", "write a CPU profile to the specified file before exiting") 98 100 f.MarkHidden(string(flagCpuProfile))
+51
cmd/cue/cmd/root.go
··· 22 22 "os" 23 23 "runtime" 24 24 "runtime/pprof" 25 + "strings" 25 26 "sync" 26 27 "testing" 27 28 "time" ··· 233 234 // The API could also be made clearer if we want to keep cmd public, 234 235 // such as not leaking *cobra.Command via embedding. 235 236 237 + // handleChdirFlag consumes a leading -C flag from args, if any, and changes 238 + // the working directory accordingly. The flag must be the first argument, in 239 + // one of the forms "-C dir", "-C=dir", "--chdir dir", or "--chdir=dir". Modeled 240 + // on cmd/go's handling of -C; see https://go.dev/cl/421436. 241 + // 242 + // Any -C left in args is rejected later by cobra via [chdirFlag.Set], which 243 + // covers both repeated -C flags and -C following another flag. 244 + func handleChdirFlag(args []string) ([]string, error) { 245 + if len(args) == 0 { 246 + return args, nil 247 + } 248 + a := args[0] 249 + var dir string 250 + switch { 251 + case a == "-C" || a == "--chdir": 252 + if len(args) < 2 { 253 + // Let cobra report the missing argument. 254 + return args, nil 255 + } 256 + dir = args[1] 257 + args = args[2:] 258 + case strings.HasPrefix(a, "-C=") || strings.HasPrefix(a, "--chdir="): 259 + _, dir, _ = strings.Cut(a, "=") 260 + args = args[1:] 261 + default: 262 + return args, nil 263 + } 264 + if err := os.Chdir(dir); err != nil { 265 + return args, err 266 + } 267 + return args, nil 268 + } 269 + 270 + // chdirFlag is a [pflag.Value] that always rejects assignment. The actual -C 271 + // handling happens in [handleChdirFlag] before cobra parses; cobra only sees 272 + // -C if it appears after another argument or is repeated, both of which are 273 + // errors. 274 + type chdirFlag struct{} 275 + 276 + func (chdirFlag) String() string { return "" } 277 + func (chdirFlag) Type() string { return "string" } 278 + func (chdirFlag) Set(string) error { 279 + return fmt.Errorf("must be the first argument") 280 + } 281 + 236 282 // New creates the top-level command. 237 283 // The returned error is always nil, and is a historical artifact. 238 284 func New(args []string) (*Command, error) { 285 + args, err := handleChdirFlag(args) 286 + if err != nil { 287 + fmt.Fprintf(os.Stderr, "%v\n", err) 288 + os.Exit(1) 289 + } 239 290 // Each call to New resets rootWorkingDir, to support [os.Chdir] calls in between. 240 291 rootWorkingDir = sync.OnceValue(func() string { 241 292 wd, err := os.Getwd()
+52
cmd/cue/cmd/testdata/script/chdir.txtar
··· 1 + # Verify that the top-level -C flag changes the working directory before 2 + # running the requested subcommand. Mirrors the behavior of cmd/go's -C flag. 3 + 4 + exec cue -C sub export 5 + cmp stdout expect-stdout 6 + 7 + exec cue -C=sub export 8 + cmp stdout expect-stdout 9 + 10 + exec cue --chdir sub export 11 + cmp stdout expect-stdout 12 + 13 + # -C must be the first argument; placing it after a subcommand fails. 14 + ! exec cue export -C sub 15 + cmp stderr stderr-not-first 16 + 17 + # -C must come before any other global flag, too. 18 + # Note that the "invalid argument" part of the error is unfortunate, 19 + # but avoiding that with cobra and pflag is cumbersome. 20 + ! exec cue -E -C sub export 21 + cmp stderr stderr-not-first 22 + 23 + # -C may only be given once. 24 + ! exec cue -C sub -C nested export 25 + cmp stderr stderr-repeated 26 + 27 + # -C must be followed by an argument. 28 + ! exec cue -C 29 + cmp stderr stderr-missing-arg 30 + 31 + # -C must point to an existing directory. 32 + # Note that the underlying OS error message varies on Windows. 33 + ! exec cue -C nonexistent export 34 + [unix] cmp stderr stderr-bad-dir-unix 35 + [windows] stderr 'chdir nonexistent:' 36 + 37 + -- expect-stdout -- 38 + { 39 + "foo": 42 40 + } 41 + -- stderr-not-first -- 42 + invalid argument "sub" for "-C, --chdir" flag: must be the first argument 43 + -- stderr-repeated -- 44 + invalid argument "nested" for "-C, --chdir" flag: must be the first argument 45 + -- stderr-missing-arg -- 46 + flag needs an argument: 'C' in -C 47 + -- stderr-bad-dir-unix -- 48 + chdir nonexistent: no such file or directory 49 + -- sub/x.cue -- 50 + package x 51 + 52 + foo: 42
+8 -6
cmd/cue/cmd/testdata/script/help_cmd.txtar
··· 172 172 -T, --inject-vars inject system variables in tags (default true) 173 173 174 174 Global Flags: 175 - -E, --all-errors print all available errors 176 - -i, --ignore proceed in the presence of errors 177 - -s, --simplify simplify output 175 + -E, --all-errors print all available errors 176 + -C, --chdir string change working directory before running command (must be the first flag) 177 + -i, --ignore proceed in the presence of errors 178 + -s, --simplify simplify output 178 179 179 180 Use "cue cmd [command] --help" for more information about a command. 180 181 -- cue-help-cmd-hello.stdout -- ··· 184 185 cue cmd hello [flags] 185 186 186 187 Global Flags: 187 - -E, --all-errors print all available errors 188 - -i, --ignore proceed in the presence of errors 189 - -s, --simplify simplify output 188 + -E, --all-errors print all available errors 189 + -C, --chdir string change working directory before running command (must be the first flag) 190 + -i, --ignore proceed in the presence of errors 191 + -s, --simplify simplify output
+4 -3
cmd/cue/cmd/testdata/script/help_cmd_flags.txtar
··· 142 142 -T, --inject-vars inject system variables in tags (default true) 143 143 144 144 Global Flags: 145 - -E, --all-errors print all available errors 146 - -i, --ignore proceed in the presence of errors 147 - -s, --simplify simplify output 145 + -E, --all-errors print all available errors 146 + -C, --chdir string change working directory before running command (must be the first flag) 147 + -i, --ignore proceed in the presence of errors 148 + -s, --simplify simplify output