Skip to content

Fix argument parsing for volta run to properly handle flags#1857

Merged
rwjblue merged 1 commit intovolta-cli:mainfrom
charlespierce:volta_run_args
Aug 16, 2024
Merged

Fix argument parsing for volta run to properly handle flags#1857
rwjblue merged 1 commit intovolta-cli:mainfrom
charlespierce:volta_run_args

Conversation

@charlespierce
Copy link
Copy Markdown
Contributor

Fixes #1852

Info

Clap's parsing for variable-length argument lists has precedence rules for what happens when a potential vararg overlaps with a known flag value (see https://docs.rs/clap/latest/clap/struct.Arg.html#method.allow_hyphen_values):

  1. If we are already in a list of variable args, the args take precedence and any potential flags are ignored (flags are treated as part of the vararg)
  2. If we are not already in a list of variable args, then known flags take precedence and are parsed as such, rather than starting the vararg list

As a result of this precedence, with volta run set up to have args be separate from command, we could run into parsing issues with commands that have flags that overlap with Volta's. For example:

volta run node -h

When parsing this, Clap would see node as the command, and then it would parse -h as Volta's -h (help) flag and print Volta's help. This is because the variable-length args hadn't started yet (we hadn't run into any unknown positional arguments), so Clap treated -h as a known flag with higher precedence. This is exactly the opposite of what we actually want for volta run

Instead, what we want is that everything after the command argument should be treated as part of the arguments to the command; regardless of whether the flag overlaps with Volta's flags.

To achieve that, we combine command and args into a single vararg, so that by virtue of having a command in the first place, the vararg has started parsing and Clap will treat any flags as more argument values, rather than as flags.

Changes

  • Updated the command definition of Run to have command_and_args as a single list instead of a value and a list.
  • Pulled the command and args out inside of Command::run so that they can still be passed to execute_tool in the same manner as before

Tested

  • Ran volta run node -h and verified that it correctly runs node -h, rather than showing the help output for volta run
  • Ran volta run node to make sure the arg processing is handled correctly when there are no additional arguments.
  • Ran volta run to validate that Clap shows a "missing required argument" message rather than creating a Run instance with an empty command_and_args vector.

Note

Clap's parsing for variable-length argument lists has precedence rules for what
happens when a potential vararg overlaps with a known flag value (see https://docs.rs/clap/latest/clap/struct.Arg.html#method.allow_hyphen_values):

1. If we are already in a list of variable args, the args take precedence and any
   potential flags are ignored (flags are treated as part of the vararg)
2. If we are _not_ already in a list of variable args, then known flags take
   precedence and are parsed as such, rather than starting the vararg list

As a result of this precedence, with `volta run` set up to have `args` be
separate from `command`, we could run into parsing issues with commands that have
flags that overlap with Volta's. For example:

```
volta run node -h
```

When parsing this, Clap would see `node` as the `command`, and then it would
parse `-h` as _Volta's_ `-h` (help) flag and print Volta's help. This is because
the variable-length `args` hadn't started yet (we hadn't run into any unknown
positional arguments), so Clap treated `-h` as a known flag with higher
precedence. This is exactly the opposite of what we actually want for `volta run`

Instead, what we want is that everything after the `command` argument should
be treated as part of the arguments to the command; regardless of whether the
flag overlaps with Volta's flags.

To achieve that, we combine `command` and `args` into a _single_ vararg, so that
by virtue of having a command in the first place, the vararg has started parsing
and Clap will treat any flags as more argument values, rather than as flags.
Copy link
Copy Markdown
Contributor

@rwjblue rwjblue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good sleuthing!!

@rwjblue rwjblue merged commit 1942724 into volta-cli:main Aug 16, 2024
@charlespierce charlespierce deleted the volta_run_args branch August 16, 2024 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Volta doesn't pass certain arguments to the globally installed npm package

2 participants