Read options after the path or URL and refuse a second argument (closes #196)
check / check (push) Waiting to run
check / check (push) Waiting to run
Every command read options only up to its first argument, and check, fetch, freshen, list and export dropped everything after it, so `check DIR --require-signature FPR` passed an unsigned manifest. Options are now read wherever they appear, as urfave/cli v3 does by default, and `--` still ends them. Those five commands refuse a second argument, naming it. TestFlagAfterArgumentIsArgument asserted the defect (`gen DIR -v` read `-v` as a path); a test that `gen -- -x` reads `-x` as a path replaces it. Model: opus-5-5
This commit was merged in pull request #197.
This commit is contained in:
+24
-22
@@ -48,6 +48,10 @@ func manifestTempPath(out string) string {
|
||||
// errUnknownCommand indicates an unrecognized command argument.
|
||||
var errUnknownCommand = errors.New("unknown command")
|
||||
|
||||
// errUnexpectedArgument indicates a second argument to a command that takes
|
||||
// one.
|
||||
var errUnexpectedArgument = errors.New("unexpected argument")
|
||||
|
||||
// CLIApp is the main CLI application container. It holds configuration,
|
||||
// I/O streams, and filesystem abstraction to enable testing and flexibility.
|
||||
//
|
||||
@@ -154,13 +158,14 @@ func commonFlags() []cli.Flag {
|
||||
}
|
||||
}
|
||||
|
||||
// stopOnFirstArg returns the StopOnNthArg setting every command uses: flags
|
||||
// are read only before the command's first argument, and everything after it
|
||||
// is an argument, as with urfave/cli v2. So `mfer gen d -v` names a path "-v".
|
||||
func stopOnFirstArg() *int {
|
||||
n := 1
|
||||
// refuseExtraArgs is the ArgValidator of the commands that take one
|
||||
// argument: it refuses a second one, naming it.
|
||||
func refuseExtraArgs(_ context.Context, cmd *cli.Command) error {
|
||||
if cmd.Args().Len() > 1 {
|
||||
return fmt.Errorf("%w %q", errUnexpectedArgument, cmd.Args().Get(1))
|
||||
}
|
||||
|
||||
return &n
|
||||
return nil
|
||||
}
|
||||
|
||||
// requireSignatureFlag returns the --require-signature flag taken by the
|
||||
@@ -186,11 +191,10 @@ func includePermissionsFlag() *cli.BoolFlag {
|
||||
|
||||
func (mfa *CLIApp) generateCommand() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: cmdGenerate,
|
||||
Aliases: []string{"gen"},
|
||||
Usage: "Generate manifest file",
|
||||
ArgsUsage: "[path ...]",
|
||||
StopOnNthArg: stopOnFirstArg(),
|
||||
Name: cmdGenerate,
|
||||
Aliases: []string{"gen"},
|
||||
Usage: "Generate manifest file",
|
||||
ArgsUsage: "[path ...]",
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
mfa.setVerbosity(cmd)
|
||||
mfa.printBanner()
|
||||
@@ -252,7 +256,7 @@ func (mfa *CLIApp) checkCommand() *cli.Command {
|
||||
Name: cmdCheck,
|
||||
Usage: "Validate files using manifest file",
|
||||
ArgsUsage: manifestArgsUsage,
|
||||
StopOnNthArg: stopOnFirstArg(),
|
||||
ArgValidator: refuseExtraArgs,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
mfa.setVerbosity(cmd)
|
||||
mfa.printBanner()
|
||||
@@ -286,7 +290,7 @@ func (mfa *CLIApp) freshenCommand() *cli.Command {
|
||||
Name: cmdFreshen,
|
||||
Usage: "Update manifest with changed, new, and removed files",
|
||||
ArgsUsage: manifestArgsUsage,
|
||||
StopOnNthArg: stopOnFirstArg(),
|
||||
ArgValidator: refuseExtraArgs,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
mfa.setVerbosity(cmd)
|
||||
mfa.printBanner()
|
||||
@@ -337,7 +341,7 @@ func (mfa *CLIApp) exportCommand() *cli.Command {
|
||||
Name: cmdExport,
|
||||
Usage: "Export manifest contents as JSON",
|
||||
ArgsUsage: "[manifest file or URL]",
|
||||
StopOnNthArg: stopOnFirstArg(),
|
||||
ArgValidator: refuseExtraArgs,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
mfa.setVerbosity(cmd)
|
||||
|
||||
@@ -348,9 +352,8 @@ func (mfa *CLIApp) exportCommand() *cli.Command {
|
||||
|
||||
func (mfa *CLIApp) versionCommand() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: cmdVersion,
|
||||
Usage: "Show version",
|
||||
StopOnNthArg: stopOnFirstArg(),
|
||||
Name: cmdVersion,
|
||||
Usage: "Show version",
|
||||
Action: func(context.Context, *cli.Command) error {
|
||||
mfa.printVersion()
|
||||
|
||||
@@ -365,7 +368,7 @@ func (mfa *CLIApp) listCommand() *cli.Command {
|
||||
Aliases: []string{"ls"},
|
||||
Usage: "List files in manifest",
|
||||
ArgsUsage: manifestArgsUsage,
|
||||
StopOnNthArg: stopOnFirstArg(),
|
||||
ArgValidator: refuseExtraArgs,
|
||||
Action: mfa.listManifestOperation,
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
@@ -386,7 +389,7 @@ func (mfa *CLIApp) fetchCommand() *cli.Command {
|
||||
Name: cmdFetch,
|
||||
Usage: "fetch manifest and referenced files",
|
||||
ArgsUsage: "URL",
|
||||
StopOnNthArg: stopOnFirstArg(),
|
||||
ArgValidator: refuseExtraArgs,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
mfa.setVerbosity(cmd)
|
||||
mfa.printBanner()
|
||||
@@ -445,9 +448,8 @@ func (mfa *CLIApp) run(args []string) {
|
||||
Writer: mfa.Stdout,
|
||||
// v3 writes its "Incorrect Usage" line to ErrWriter; v2 wrote it to
|
||||
// stdout, before the help, so it stays on stdout.
|
||||
ErrWriter: mfa.Stdout,
|
||||
Flags: commonFlags(),
|
||||
StopOnNthArg: stopOnFirstArg(),
|
||||
ErrWriter: mfa.Stdout,
|
||||
Flags: commonFlags(),
|
||||
Action: func(_ context.Context, cmd *cli.Command) error {
|
||||
if cmd.Args().Len() > 0 {
|
||||
return fmt.Errorf("%w %q", errUnknownCommand, cmd.Args().First())
|
||||
|
||||
Reference in New Issue
Block a user