Skip to content

Commit 4016af7

Browse files
committed
Add better support for nested recursive aliases.
1 parent 6e525e0 commit 4016af7

File tree

1 file changed

+52
-8
lines changed

1 file changed

+52
-8
lines changed

src/cli.rs

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,20 +180,22 @@ fn parse_subcommand(
180180
result: &mut Args,
181181
target_list: &TargetList,
182182
config: &CargoConfig,
183-
parent: Option<&str>,
183+
seen: &mut Vec<String>,
184184
) -> Result<()> {
185-
if parent == Some(&arg) {
185+
if seen.iter().position(|x| x == &arg).is_some() {
186+
let chain = seen.join(" -> ");
186187
MessageInfo::default().fatal(
187-
format_args!("alias {arg} has unresolvable recursive definition: {arg} -> {arg}"),
188+
format_args!("alias {arg} has unresolvable recursive definition: {chain} -> {arg}"),
188189
shell::ERROR_CODE,
189190
);
190191
}
191192
let subcommand = Subcommand::from(arg.as_ref());
192193
if subcommand == Subcommand::Other {
193194
if let Some(alias) = config.alias(&arg)? {
195+
seen.push(arg);
194196
let mut iter = alias.iter().cloned();
195197
while let Some(subarg) = iter.next() {
196-
parse_arg(subarg, result, target_list, config, &mut iter, Some(&arg))?;
198+
parse_arg(subarg, result, target_list, config, seen, &mut iter)?;
197199
}
198200
return Ok(());
199201
}
@@ -212,8 +214,8 @@ fn parse_arg(
212214
result: &mut Args,
213215
target_list: &TargetList,
214216
config: &CargoConfig,
217+
seen: &mut Vec<String>,
215218
iter: &mut impl Iterator<Item = String>,
216-
parent_subcommand: Option<&str>,
217219
) -> Result<()> {
218220
if arg.is_empty() {
219221
return Ok(());
@@ -310,7 +312,7 @@ fn parse_arg(
310312
}
311313
}
312314
} else if (!arg.starts_with('-') || arg == "--list") && result.subcommand.is_none() {
313-
parse_subcommand(arg, result, target_list, config, parent_subcommand)?;
315+
parse_subcommand(arg, result, target_list, config, seen)?;
314316
} else {
315317
result.all.push(arg.clone());
316318
}
@@ -321,8 +323,9 @@ fn parse_arg(
321323
pub fn parse(target_list: &TargetList, config: &CargoConfig) -> Result<Args> {
322324
let mut result = Args::default();
323325
let mut args = env::args().skip(1);
326+
let mut seen = vec![];
324327
while let Some(arg) = args.next() {
325-
parse_arg(arg, &mut result, target_list, config, &mut args, None)?;
328+
parse_arg(arg, &mut result, target_list, config, &mut seen, &mut args)?;
326329
}
327330

328331
Ok(result)
@@ -334,6 +337,12 @@ mod tests {
334337
use crate::rustc;
335338
use crate::shell::Verbosity;
336339

340+
macro_rules! s {
341+
($s:literal) => {
342+
$s.to_owned()
343+
};
344+
}
345+
337346
#[test]
338347
fn is_verbose_test() {
339348
assert!(!is_verbose("b"));
@@ -346,6 +355,23 @@ mod tests {
346355
assert!(!is_verbose("-version"));
347356
}
348357

358+
#[test]
359+
fn test_nested_alias() {
360+
let mut args = Args::default();
361+
let target_list =
362+
rustc::target_list(&mut Verbosity::Quiet.into()).expect("failed to get target list");
363+
let config = CargoConfig::new(None);
364+
365+
parse_subcommand(
366+
"g".to_owned(),
367+
&mut args,
368+
&target_list,
369+
&config,
370+
&mut vec![s!("x"), s!("y"), s!("z"), s!("a"), s!("e"), s!("f")],
371+
)
372+
.ok();
373+
}
374+
349375
#[test]
350376
#[should_panic]
351377
fn test_recursive_alias() {
@@ -359,7 +385,25 @@ mod tests {
359385
&mut args,
360386
&target_list,
361387
&config,
362-
Some("recursive"),
388+
&mut vec![s!("recursive")],
389+
)
390+
.ok();
391+
}
392+
393+
#[test]
394+
#[should_panic]
395+
fn test_nested_recursive_alias() {
396+
let mut args = Args::default();
397+
let target_list =
398+
rustc::target_list(&mut Verbosity::Quiet.into()).expect("failed to get target list");
399+
let config = CargoConfig::new(None);
400+
401+
parse_subcommand(
402+
"y".to_owned(),
403+
&mut args,
404+
&target_list,
405+
&config,
406+
&mut vec![s!("x"), s!("y"), s!("z"), s!("a")],
363407
)
364408
.ok();
365409
}

0 commit comments

Comments
 (0)