Skip to content

Commit 20cdc5c

Browse files
committed
refactor(cli): rewrite rustup target with clap-derive
1 parent 48c798c commit 20cdc5c

7 files changed

+103
-100
lines changed

src/cli/rustup_mode.rs

Lines changed: 90 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ enum RustupSubcmd {
144144
#[command(subcommand)]
145145
subcmd: ToolchainSubcmd,
146146
},
147+
148+
/// Modify a toolchain's supported targets
149+
Target {
150+
#[command(subcommand)]
151+
subcmd: TargetSubcmd,
152+
},
147153
}
148154

149155
#[derive(Debug, Subcommand)]
@@ -249,6 +255,45 @@ struct UninstallOpts {
249255
toolchain: Vec<ResolvableToolchainName>,
250256
}
251257

258+
#[derive(Debug, Subcommand)]
259+
#[command(arg_required_else_help = true, subcommand_required = true)]
260+
enum TargetSubcmd {
261+
/// List installed and available targets
262+
List {
263+
#[arg(
264+
long,
265+
help = OFFICIAL_TOOLCHAIN_ARG_HELP,
266+
)]
267+
toolchain: Option<PartialToolchainDesc>,
268+
269+
/// List only installed targets
270+
#[arg(long)]
271+
installed: bool,
272+
},
273+
274+
/// Add a target to a Rust toolchain
275+
#[command(alias = "install")]
276+
Add {
277+
/// List of targets to install; "all" installs all available targets
278+
#[arg(required = true, num_args = 1..)]
279+
target: Vec<String>,
280+
281+
#[arg(long, help = OFFICIAL_TOOLCHAIN_ARG_HELP)]
282+
toolchain: Option<PartialToolchainDesc>,
283+
},
284+
285+
/// Remove a target from a Rust toolchain
286+
#[command(alias = "uninstall")]
287+
Remove {
288+
/// List of targets to uninstall
289+
#[arg(required = true, num_args = 1..)]
290+
target: Vec<String>,
291+
292+
#[arg(long, help = OFFICIAL_TOOLCHAIN_ARG_HELP)]
293+
toolchain: Option<PartialToolchainDesc>,
294+
},
295+
}
296+
252297
impl Rustup {
253298
fn dispatch(self, cfg: &mut Cfg) -> Result<utils::ExitCode> {
254299
match self.subcmd {
@@ -285,6 +330,14 @@ impl Rustup {
285330
},
286331
RustupSubcmd::Check => check_updates(cfg),
287332
RustupSubcmd::Default { toolchain } => default_(cfg, toolchain),
333+
RustupSubcmd::Target { subcmd } => match subcmd {
334+
TargetSubcmd::List {
335+
toolchain,
336+
installed,
337+
} => handle_epipe(target_list(cfg, toolchain, installed)),
338+
TargetSubcmd::Add { target, toolchain } => target_add(cfg, target, toolchain),
339+
TargetSubcmd::Remove { target, toolchain } => target_remove(cfg, target, toolchain),
340+
},
288341
}
289342
}
290343
}
@@ -362,18 +415,10 @@ pub fn main() -> Result<utils::ExitCode> {
362415
Some(s) => match s {
363416
("dump-testament", _) => common::dump_testament()?,
364417
(
365-
"show" | "update" | "install" | "uninstall" | "toolchain" | "check" | "default",
418+
"show" | "update" | "install" | "uninstall" | "toolchain" | "check" | "default"
419+
| "target",
366420
_,
367421
) => Rustup::from_arg_matches(&matches)?.dispatch(cfg)?,
368-
("target", c) => match c.subcommand() {
369-
Some(s) => match s {
370-
("list", m) => handle_epipe(target_list(cfg, m))?,
371-
("add", m) => target_add(cfg, m)?,
372-
("remove", m) => target_remove(cfg, m)?,
373-
_ => unreachable!(),
374-
},
375-
None => unreachable!(),
376-
},
377422
("component", c) => match c.subcommand() {
378423
Some(s) => match s {
379424
("list", m) => handle_epipe(component_list(cfg, m))?,
@@ -470,63 +515,6 @@ pub(crate) fn cli() -> Command {
470515
.about("Dump information about the build")
471516
.hide(true), // Not for users, only CI
472517
)
473-
.subcommand(
474-
Command::new("target")
475-
.about("Modify a toolchain's supported targets")
476-
.subcommand_required(true)
477-
.arg_required_else_help(true)
478-
.subcommand(
479-
Command::new("list")
480-
.about("List installed and available targets")
481-
.arg(
482-
Arg::new("toolchain")
483-
.help(OFFICIAL_TOOLCHAIN_ARG_HELP)
484-
.long("toolchain")
485-
.value_parser(partial_toolchain_desc_parser)
486-
.num_args(1),
487-
)
488-
.arg(
489-
Arg::new("installed")
490-
.long("installed")
491-
.help("List only installed targets")
492-
.action(ArgAction::SetTrue),
493-
),
494-
)
495-
.subcommand(
496-
Command::new("add")
497-
.about("Add a target to a Rust toolchain")
498-
.alias("install")
499-
.arg(Arg::new("target").required(true).num_args(1..).help(
500-
"List of targets to install; \
501-
\"all\" installs all available targets",
502-
))
503-
.arg(
504-
Arg::new("toolchain")
505-
.help(OFFICIAL_TOOLCHAIN_ARG_HELP)
506-
.long("toolchain")
507-
.num_args(1)
508-
.value_parser(partial_toolchain_desc_parser),
509-
),
510-
)
511-
.subcommand(
512-
Command::new("remove")
513-
.about("Remove a target from a Rust toolchain")
514-
.alias("uninstall")
515-
.arg(
516-
Arg::new("target")
517-
.help("List of targets to uninstall")
518-
.required(true)
519-
.num_args(1..),
520-
)
521-
.arg(
522-
Arg::new("toolchain")
523-
.help(OFFICIAL_TOOLCHAIN_ARG_HELP)
524-
.long("toolchain")
525-
.num_args(1)
526-
.value_parser(partial_toolchain_desc_parser),
527-
),
528-
),
529-
)
530518
.subcommand(
531519
Command::new("component")
532520
.about("Modify a toolchain's installed components")
@@ -1176,27 +1164,30 @@ fn show_rustup_home(cfg: &Cfg) -> Result<utils::ExitCode> {
11761164
Ok(utils::ExitCode(0))
11771165
}
11781166

1179-
fn target_list(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
1180-
let toolchain = explicit_desc_or_dir_toolchain(cfg, m)?;
1167+
fn target_list(
1168+
cfg: &Cfg,
1169+
toolchain: Option<PartialToolchainDesc>,
1170+
installed_only: bool,
1171+
) -> Result<utils::ExitCode> {
1172+
let toolchain = explicit_desc_or_dir_toolchain(cfg, toolchain)?;
11811173
// downcasting required because the toolchain files can name any toolchain
11821174
let distributable = (&toolchain).try_into()?;
1183-
common::list_targets(distributable, m.get_flag("installed"))
1175+
common::list_targets(distributable, installed_only)
11841176
}
11851177

1186-
fn target_add(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
1187-
let toolchain = explicit_desc_or_dir_toolchain(cfg, m)?;
1178+
fn target_add(
1179+
cfg: &Cfg,
1180+
mut targets: Vec<String>,
1181+
toolchain: Option<PartialToolchainDesc>,
1182+
) -> Result<utils::ExitCode> {
1183+
let toolchain = explicit_desc_or_dir_toolchain(cfg, toolchain)?;
11881184
// XXX: long term move this error to cli ? the normal .into doesn't work
11891185
// because Result here is the wrong sort and expression type ascription
11901186
// isn't a feature yet.
11911187
// list_components *and* add_component would both be inappropriate for
11921188
// custom toolchains.
11931189
let distributable = DistributableToolchain::try_from(&toolchain)?;
11941190
let components = distributable.components()?;
1195-
let mut targets: Vec<_> = m
1196-
.get_many::<String>("target")
1197-
.unwrap()
1198-
.map(ToOwned::to_owned)
1199-
.collect();
12001191

12011192
if targets.contains(&"all".to_string()) {
12021193
if targets.len() != 1 {
@@ -1234,12 +1225,16 @@ fn target_add(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
12341225
Ok(utils::ExitCode(0))
12351226
}
12361227

1237-
fn target_remove(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
1238-
let toolchain = explicit_desc_or_dir_toolchain(cfg, m)?;
1228+
fn target_remove(
1229+
cfg: &Cfg,
1230+
targets: Vec<String>,
1231+
toolchain: Option<PartialToolchainDesc>,
1232+
) -> Result<utils::ExitCode> {
1233+
let toolchain = explicit_desc_or_dir_toolchain(cfg, toolchain)?;
12391234
let distributable = DistributableToolchain::try_from(&toolchain)?;
12401235

1241-
for target in m.get_many::<String>("target").unwrap() {
1242-
let target = TargetTriple::new(target);
1236+
for target in targets {
1237+
let target = TargetTriple::new(&target);
12431238
let default_target = cfg.get_default_host_triple()?;
12441239
if target == default_target {
12451240
warn!("after removing the default host target, proc-macros and build scripts might no longer build");
@@ -1266,15 +1261,15 @@ fn target_remove(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
12661261
}
12671262

12681263
fn component_list(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
1269-
let toolchain = explicit_desc_or_dir_toolchain(cfg, m)?;
1264+
let toolchain = explicit_desc_or_dir_toolchain_old(cfg, m)?;
12701265
// downcasting required because the toolchain files can name any toolchain
12711266
let distributable = (&toolchain).try_into()?;
12721267
common::list_components(distributable, m.get_flag("installed"))?;
12731268
Ok(utils::ExitCode(0))
12741269
}
12751270

12761271
fn component_add(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
1277-
let toolchain = explicit_desc_or_dir_toolchain(cfg, m)?;
1272+
let toolchain = explicit_desc_or_dir_toolchain_old(cfg, m)?;
12781273
let distributable = DistributableToolchain::try_from(&toolchain)?;
12791274
let target = get_target(m, &distributable);
12801275

@@ -1294,7 +1289,7 @@ fn get_target(m: &ArgMatches, distributable: &DistributableToolchain<'_>) -> Opt
12941289
}
12951290

12961291
fn component_remove(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
1297-
let toolchain = explicit_desc_or_dir_toolchain(cfg, m)?;
1292+
let toolchain = explicit_desc_or_dir_toolchain_old(cfg, m)?;
12981293
let distributable = DistributableToolchain::try_from(&toolchain)?;
12991294
let target = get_target(m, &distributable);
13001295

@@ -1308,13 +1303,21 @@ fn component_remove(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
13081303

13091304
// Make *sure* only to use this for a subcommand whose "toolchain" argument
13101305
// has .value_parser(partial_toolchain_desc_parser), or it will panic.
1311-
fn explicit_desc_or_dir_toolchain<'a>(cfg: &'a Cfg, m: &ArgMatches) -> Result<Toolchain<'a>> {
1306+
// FIXME: Delete this.
1307+
fn explicit_desc_or_dir_toolchain_old<'a>(cfg: &'a Cfg, m: &ArgMatches) -> Result<Toolchain<'a>> {
13121308
let toolchain = m
13131309
.get_one::<PartialToolchainDesc>("toolchain")
13141310
.map(Into::into);
13151311
explicit_or_dir_toolchain2(cfg, toolchain)
13161312
}
13171313

1314+
fn explicit_desc_or_dir_toolchain(
1315+
cfg: &Cfg,
1316+
toolchain: Option<PartialToolchainDesc>,
1317+
) -> Result<Toolchain<'_>> {
1318+
explicit_or_dir_toolchain2(cfg, toolchain.map(|it| (&it).into()))
1319+
}
1320+
13181321
fn explicit_or_dir_toolchain2(
13191322
cfg: &Cfg,
13201323
toolchain: Option<ResolvableToolchainName>,
@@ -1458,7 +1461,7 @@ const DOCS_DATA: &[(&str, &str, &str)] = &[
14581461
];
14591462

14601463
fn doc(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
1461-
let toolchain = explicit_desc_or_dir_toolchain(cfg, m)?;
1464+
let toolchain = explicit_desc_or_dir_toolchain_old(cfg, m)?;
14621465

14631466
if let Ok(distributable) = DistributableToolchain::try_from(&toolchain) {
14641467
if let [_] = distributable
@@ -1522,7 +1525,7 @@ fn man(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
15221525

15231526
let command = m.get_one::<String>("command").unwrap();
15241527

1525-
let toolchain = explicit_desc_or_dir_toolchain(cfg, m)?;
1528+
let toolchain = explicit_desc_or_dir_toolchain_old(cfg, m)?;
15261529
let mut path = toolchain.path().to_path_buf();
15271530
path.push("share");
15281531
path.push("man");

tests/suite/cli-ui/rustup/rustup_help_cmd_stdout.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ The Rust toolchain installer
99
Usage: rustup[EXE] [OPTIONS] [+toolchain] [COMMAND]
1010
1111
Commands:
12-
target Modify a toolchain's supported targets
1312
component Modify a toolchain's installed components
1413
override Modify toolchain overrides for directories
1514
run Run a command with an environment configured for a given toolchain
@@ -24,6 +23,7 @@ Commands:
2423
check Check for updates to Rust toolchains and rustup
2524
default Set the default toolchain
2625
toolchain Modify or query the installed toolchains
26+
target Modify a toolchain's supported targets
2727
help Print this message or the help of the given subcommand(s)
2828
2929
Arguments:

tests/suite/cli-ui/rustup/rustup_help_flag_stdout.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ The Rust toolchain installer
99
Usage: rustup[EXE] [OPTIONS] [+toolchain] [COMMAND]
1010
1111
Commands:
12-
target Modify a toolchain's supported targets
1312
component Modify a toolchain's installed components
1413
override Modify toolchain overrides for directories
1514
run Run a command with an environment configured for a given toolchain
@@ -24,6 +23,7 @@ Commands:
2423
check Check for updates to Rust toolchains and rustup
2524
default Set the default toolchain
2625
toolchain Modify or query the installed toolchains
26+
target Modify a toolchain's supported targets
2727
help Print this message or the help of the given subcommand(s)
2828
2929
Arguments:

tests/suite/cli-ui/rustup/rustup_only_options_stdout.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ The Rust toolchain installer
99
Usage: rustup[EXE] [OPTIONS] [+toolchain] [COMMAND]
1010
1111
Commands:
12-
target Modify a toolchain's supported targets
1312
component Modify a toolchain's installed components
1413
override Modify toolchain overrides for directories
1514
run Run a command with an environment configured for a given toolchain
@@ -24,6 +23,7 @@ Commands:
2423
check Check for updates to Rust toolchains and rustup
2524
default Set the default toolchain
2625
toolchain Modify or query the installed toolchains
26+
target Modify a toolchain's supported targets
2727
help Print this message or the help of the given subcommand(s)
2828
2929
Arguments:

tests/suite/cli-ui/rustup/rustup_target_cmd_add_cmd_help_flag_stdout.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
bin.name = "rustup"
2-
args = ["target","add","--help"]
2+
args = ["target", "add", "--help"]
33
stdout = """
44
...
55
Add a target to a Rust toolchain
66
7-
Usage: rustup[EXE] target add [OPTIONS] <target>...
7+
Usage: rustup[EXE] target add [OPTIONS] <TARGET>...
88
99
Arguments:
10-
<target>... List of targets to install; \"all\" installs all available targets
10+
<TARGET>... List of targets to install; \"all\" installs all available targets
1111
1212
Options:
13-
--toolchain <toolchain> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
13+
--toolchain <TOOLCHAIN> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
1414
information see `rustup help toolchain`
1515
-h, --help Print help
1616
"""

tests/suite/cli-ui/rustup/rustup_target_cmd_list_cmd_help_flag_stdout.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
bin.name = "rustup"
2-
args = ["target","list","--help"]
2+
args = ["target", "list", "--help"]
33
stdout = """
44
...
55
List installed and available targets
66
77
Usage: rustup[EXE] target list [OPTIONS]
88
99
Options:
10-
--toolchain <toolchain> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
10+
--toolchain <TOOLCHAIN> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
1111
information see `rustup help toolchain`
1212
--installed List only installed targets
1313
-h, --help Print help

tests/suite/cli-ui/rustup/rustup_target_cmd_remove_cmd_help_flag_stdout.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
bin.name = "rustup"
2-
args = ["target","remove","--help"]
2+
args = ["target", "remove", "--help"]
33
stdout = """
44
...
55
Remove a target from a Rust toolchain
66
7-
Usage: rustup[EXE] target remove [OPTIONS] <target>...
7+
Usage: rustup[EXE] target remove [OPTIONS] <TARGET>...
88
99
Arguments:
10-
<target>... List of targets to uninstall
10+
<TARGET>... List of targets to uninstall
1111
1212
Options:
13-
--toolchain <toolchain> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
13+
--toolchain <TOOLCHAIN> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
1414
information see `rustup help toolchain`
1515
-h, --help Print help
1616
"""

0 commit comments

Comments
 (0)