-
-
Notifications
You must be signed in to change notification settings - Fork 649
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move CLI flag extraction into ArgSplitter #21943
Conversation
This creates a new empty release notes file for 2.26, since we're cutting the `2.25.x` branch (pantsbuild#21911) and starting the 2.26.x series.
e4d7389
to
6bfac2e
Compare
@@ -116,7 +116,7 @@ def __init__(self, flags: Tuple[str, ...], arg_scope: str): | |||
self.flags = flags | |||
self.arg_scope = arg_scope | |||
scope = f"scope {self.arg_scope}" if self.arg_scope else "global scope" | |||
msg = f"Unknown flags {', '.join(self.flags)} on {scope}" | |||
msg = f"Unknown {pluralize(len(self.flags), 'flag')} {', '.join(self.flags)} on {scope}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noticed this while debugging, and it's not worth a separate PR.
@@ -26,7 +56,8 @@ pub struct PantsCommand { | |||
pub goals: Vec<String>, // Requested known goals. | |||
pub unknown_goals: Vec<String>, // Any requested but unknown goals. | |||
pub specs: Vec<String>, // What to run against, e.g. targets or files/dirs. | |||
pub passthru: Vec<String>, // Any remaining args specified after a -- separator. | |||
pub(crate) flags: Vec<Flag>, // Option values set via flag. | |||
pub passthru: Option<Vec<String>>, // Any remaining args specified after a -- separator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will do a future pass on visibility, some of these pub
may be able to be pub(crate)
. But I wanted to get this bugfix in first.
@@ -90,7 +123,7 @@ impl ArgSplitter { | |||
// changes to plugins (as they can introduce new goals) or changes on the filesystem. | |||
// We might want to deprecate this behavior and consistently assume that these are goals, | |||
// since the user can always add a `./` prefix to override. | |||
while let Some(arg) = unconsumed_args.pop() { | |||
while let Some(arg) = unconsumed_args.next() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reversing-and-popping method of iterating was needlessly confusing.
} | ||
passthru = Some(remainder); | ||
} else if arg.starts_with("--") { | ||
let mut components = arg.splitn(2, '='); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is moved here from the old Args
impl.
} | ||
|
||
#[test] | ||
fn test_bool() { | ||
let args = mk_args([ | ||
"-c=swallow", | ||
"--unladen-capacity=swallow", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old Args
implementation happened to support arbitrary short flags, and we tested that, but the OptionsParser itself didn't support those, so this is not taking away any capability of Pants itself, just an overeagerness of the previous implementation.
@@ -372,41 +379,6 @@ fn test_nonexistent_optional_fromfile() { | |||
assert!(args.get_string(&option_id!("foo")).unwrap().is_none()); | |||
} | |||
|
|||
#[test] | |||
fn test_passthrough_args() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now get these from ArgSplitter
(and it is tested there).
// Now get the PantsCommand based on the expanded aliases. | ||
// For historical reasons, getting the SplitArgs (for goals and specs) is done | ||
// in ArgSplitter, in a separate pass from getting the Args (for CLI flags). | ||
// TODO: Combine the two passes? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODONE!
@@ -563,22 +570,18 @@ impl OptionParser { | |||
|
|||
let alias_map = cli_alias::create_alias_map(known_scopes_to_flags, &alias_strings)?; | |||
|
|||
// Step #4: Read any spec_files from alias-expanded args, env, config and rcfiles. | |||
|
|||
// Add the args reader back in, after expanding aliases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We no longer need to hang on to the args reader. We just insert one, remove it, and reinsert a new one again.
static ref SCOPE_NAME_RE: Regex = Regex::new(r"^(?:[a-z0-9_])+(?:-(?:[a-z0-9_])+)*$").unwrap(); | ||
} | ||
|
||
pub(crate) fn is_valid_scope_name(name: &str) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now parse flags in the ArgSplitter, which has a list of known scopes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense.
I'm a bit surprised we didn't catch the negative specs bug earlier with an integration test or similar? What do you think about adding some sort of higher level "target selection" integration test?
I tried to automatically cherry-pick this change back to each relevant milestone, so that it is available in those older releases of Pants. ❌ 2.24.xI was unable to cherry-pick this PR to 2.24.x, likely due to merge-conflicts. Steps to Cherry-Pick locallyTo resolve:
Please note that I cannot re-run CI if a job fails. Please work with your PR approver(s) to re-run CI if necessary. ✔️ 2.25.xSuccessfully opened #21950. When you're done manually cherry-picking, please remove the Thanks again for your contributions! |
…1950) Previously, for legacy reasons, we had a separate pass for processing flags, while the ArgSplitter dealt with finding goals and specs. This turned out to be not just a code redundancy issue, but it caused a bug: #21930 . This PR cleans up the redundancy and smooths out some ragged legacy edges in the Rust options parser: - Employs uniform terminology: Now all CLI args (specs, goals, flags) are referred to as `args`, while args that set option values are referred to as `flags`. Previously we used `flags` and `args` somewhat interchangeably to refer to the latter, but also `args` to refer to the former. This clears up the ambiguity. - Notably, the `Arg` struct is now called `Flag`, and lives in `flags.rs`. - Gets rid of the previous `Args` struct and its logic, reusing its name to now be just a simple holder of arg strings prior to parsing. - Moves the flag-gathering logic, previously in the old `Args`, into `ArgSplitter`. - Modify tests appropriately. Including removing testing of arbitrary short (`-f`) flags, which happened to work before, even though we only officially support a known small set of such flags (`-v`, `-h`, `-l`). - Regression test for #21930. - Make passthru args an Option, so we can distinguish between `pants ...` and `pants ... --` (i.e., no passthru separator vs a passthru separator with no args after it). Co-authored-by: Benjy Weinberger <[email protected]> Co-authored-by: Huon Wilson <[email protected]>
We fix directly in 2.24.x, as we can't cherrypick the more comprehensive #21943 due to its reliance on a whole stack of changes that we don't want in 2.24.x
Previously, for legacy reasons, we had a separate pass for
processing flags, while the ArgSplitter dealt with finding
goals and specs. This turned out to be not just a code
redundancy issue, but it caused a bug: #21930 .
This PR cleans up the redundancy and smooths out
some ragged legacy edges in the Rust options parser:
(specs, goals, flags) are referred to as
args
,while args that set option values are referred to
as
flags
. Previously we usedflags
andargs
somewhat interchangeably to refer to the latter,
but also
args
to refer to the former. This clearsup the ambiguity.
Arg
struct is now calledFlag
, andlives in
flags.rs
.Args
struct and its logic,reusing its name to now be just a simple holder of
arg strings prior to parsing.
Args
,into
ArgSplitter
.of arbitrary short (
-f
) flags, which happened to workbefore, even though we only officially support a known
small set of such flags (
-v
,-h
,-l
).-
#21930.pants ...
andpants ... --
(i.e., no passthru separator vsa passthru separator with no args after it).