Skip to content

Commit

Permalink
refactor(cli): rewrite rustup component with clap-derive
Browse files Browse the repository at this point in the history
  • Loading branch information
rami3l committed Jan 22, 2024
1 parent daf7f97 commit 38547fd
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 86 deletions.
164 changes: 91 additions & 73 deletions src/cli/rustup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ enum RustupSubcmd {
#[command(subcommand)]
subcmd: TargetSubcmd,
},

/// Modify a toolchain's installed components
Component {
#[command(subcommand)]
subcmd: ComponentSubcmd,
},
}

#[derive(Debug, Subcommand)]
Expand Down Expand Up @@ -293,6 +299,44 @@ enum TargetSubcmd {
},
}

#[derive(Debug, Subcommand)]
#[command(arg_required_else_help = true, subcommand_required = true)]
enum ComponentSubcmd {
/// List installed and available components
List {
#[arg(long, help = OFFICIAL_TOOLCHAIN_ARG_HELP)]
toolchain: Option<PartialToolchainDesc>,

/// List only installed components
#[arg(long)]
installed: bool,
},

/// Add a component to a Rust toolchain
Add {
#[arg(required = true, num_args = 1..)]
component: Vec<String>,

#[arg(long, help = OFFICIAL_TOOLCHAIN_ARG_HELP)]
toolchain: Option<PartialToolchainDesc>,

#[arg(long)]
target: Option<String>,
},

/// Remove a component from a Rust toolchain
Remove {
#[arg(required = true, num_args = 1..)]
component: Vec<String>,

#[arg(long, help = OFFICIAL_TOOLCHAIN_ARG_HELP)]
toolchain: Option<PartialToolchainDesc>,

#[arg(long)]
target: Option<String>,
},
}

impl Rustup {
fn dispatch(self, cfg: &mut Cfg) -> Result<utils::ExitCode> {
match self.subcmd {
Expand Down Expand Up @@ -337,6 +381,22 @@ impl Rustup {
TargetSubcmd::Add { target, toolchain } => target_add(cfg, target, toolchain),
TargetSubcmd::Remove { target, toolchain } => target_remove(cfg, target, toolchain),
},
RustupSubcmd::Component { subcmd } => match subcmd {
ComponentSubcmd::List {
toolchain,
installed,
} => handle_epipe(component_list(cfg, toolchain, installed)),
ComponentSubcmd::Add {
component,
toolchain,
target,
} => component_add(cfg, component, toolchain, target.as_deref()),
ComponentSubcmd::Remove {
component,
toolchain,
target,
} => component_remove(cfg, component, toolchain, target.as_deref()),
},
}
}
}
Expand Down Expand Up @@ -415,18 +475,9 @@ pub fn main() -> Result<utils::ExitCode> {
("dump-testament", _) => common::dump_testament()?,
(
"show" | "update" | "install" | "uninstall" | "toolchain" | "check" | "default"
| "target",
| "target" | "component",
_,
) => Rustup::from_arg_matches(&matches)?.dispatch(cfg)?,
("component", c) => match c.subcommand() {
Some(s) => match s {
("list", m) => handle_epipe(component_list(cfg, m))?,
("add", m) => component_add(cfg, m)?,
("remove", m) => component_remove(cfg, m)?,
_ => unreachable!(),
},
None => unreachable!(),
},
("override", c) => match c.subcommand() {
Some(s) => match s {
("list", _) => handle_epipe(common::list_overrides(cfg))?,
Expand Down Expand Up @@ -513,55 +564,6 @@ pub(crate) fn cli() -> Command {
.about("Dump information about the build")
.hide(true), // Not for users, only CI
)
.subcommand(
Command::new("component")
.about("Modify a toolchain's installed components")
.subcommand_required(true)
.arg_required_else_help(true)
.subcommand(
Command::new("list")
.about("List installed and available components")
.arg(
Arg::new("toolchain")
.help(OFFICIAL_TOOLCHAIN_ARG_HELP)
.long("toolchain")
.num_args(1)
.value_parser(partial_toolchain_desc_parser),
)
.arg(
Arg::new("installed")
.long("installed")
.help("List only installed components")
.action(ArgAction::SetTrue),
),
)
.subcommand(
Command::new("add")
.about("Add a component to a Rust toolchain")
.arg(Arg::new("component").required(true).num_args(1..))
.arg(
Arg::new("toolchain")
.help(OFFICIAL_TOOLCHAIN_ARG_HELP)
.long("toolchain")
.num_args(1)
.value_parser(partial_toolchain_desc_parser),
)
.arg(Arg::new("target").long("target").num_args(1)),
)
.subcommand(
Command::new("remove")
.about("Remove a component from a Rust toolchain")
.arg(Arg::new("component").required(true).num_args(1..))
.arg(
Arg::new("toolchain")
.help(OFFICIAL_TOOLCHAIN_ARG_HELP)
.long("toolchain")
.num_args(1)
.value_parser(partial_toolchain_desc_parser),
)
.arg(Arg::new("target").long("target").num_args(1)),
),
)
.subcommand(
Command::new("override")
.about("Modify toolchain overrides for directories")
Expand Down Expand Up @@ -1298,25 +1300,34 @@ fn target_remove(
Ok(utils::ExitCode(0))
}

fn component_list(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
let toolchain = explicit_desc_or_dir_toolchain_old(cfg, m)?;
fn component_list(
cfg: &Cfg,
toolchain: Option<PartialToolchainDesc>,
installed_only: bool,
) -> Result<utils::ExitCode> {
let toolchain = explicit_desc_or_dir_toolchain(cfg, toolchain)?;
// downcasting required because the toolchain files can name any toolchain
let distributable = (&toolchain).try_into()?;

if m.get_flag("installed") {
if installed_only {
common::list_installed_components(distributable)?;
} else {
common::list_components(distributable)?;
}
Ok(utils::ExitCode(0))
}

fn component_add(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
let toolchain = explicit_desc_or_dir_toolchain_old(cfg, m)?;
fn component_add(
cfg: &Cfg,
components: Vec<String>,
toolchain: Option<PartialToolchainDesc>,
target: Option<&str>,
) -> Result<utils::ExitCode> {
let toolchain = explicit_desc_or_dir_toolchain(cfg, toolchain)?;
let distributable = DistributableToolchain::try_from(&toolchain)?;
let target = get_target(m, &distributable);
let target = get_target(target, &distributable);

for component in m.get_many::<String>("component").unwrap() {
for component in &components {
let new_component = Component::new_with_target(component, false)
.unwrap_or_else(|| Component::new(component.to_string(), target.clone(), true));
distributable.add_component(new_component)?;
Expand All @@ -1325,19 +1336,26 @@ fn component_add(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
Ok(utils::ExitCode(0))
}

fn get_target(m: &ArgMatches, distributable: &DistributableToolchain<'_>) -> Option<TargetTriple> {
m.get_one::<String>("target")
.map(|s| &**s)
fn get_target(
target: Option<&str>,
distributable: &DistributableToolchain<'_>,
) -> Option<TargetTriple> {
target
.map(TargetTriple::new)
.or_else(|| Some(distributable.desc().target.clone()))
}

fn component_remove(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
let toolchain = explicit_desc_or_dir_toolchain_old(cfg, m)?;
fn component_remove(
cfg: &Cfg,
components: Vec<String>,
toolchain: Option<PartialToolchainDesc>,
target: Option<&str>,
) -> Result<utils::ExitCode> {
let toolchain = explicit_desc_or_dir_toolchain(cfg, toolchain)?;
let distributable = DistributableToolchain::try_from(&toolchain)?;
let target = get_target(m, &distributable);
let target = get_target(target, &distributable);

for component in m.get_many::<String>("component").unwrap() {
for component in &components {
let new_component = Component::new_with_target(component, false)
.unwrap_or_else(|| Component::new(component.to_string(), target.clone(), true));
distributable.remove_component(new_component)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ stdout = """
...
Add a component to a Rust toolchain
Usage: rustup[EXE] component add [OPTIONS] <component>...
Usage: rustup[EXE] component add [OPTIONS] <COMPONENT>...
Arguments:
<component>...
<COMPONENT>...
Options:
--toolchain <toolchain> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
--toolchain <TOOLCHAIN> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
information see `rustup help toolchain`
--target <target>
--target <TARGET>
-h, --help Print help
"""
stderr = ""
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
bin.name = "rustup"
args = ["component","list","--help"]
args = ["component", "list", "--help"]
stdout = """
...
List installed and available components
Usage: rustup[EXE] component list [OPTIONS]
Options:
--toolchain <toolchain> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
--toolchain <TOOLCHAIN> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
information see `rustup help toolchain`
--installed List only installed components
-h, --help Print help
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ stdout = """
...
Remove a component from a Rust toolchain
Usage: rustup[EXE] component remove [OPTIONS] <component>...
Usage: rustup[EXE] component remove [OPTIONS] <COMPONENT>...
Arguments:
<component>...
<COMPONENT>...
Options:
--toolchain <toolchain> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
--toolchain <TOOLCHAIN> Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more
information see `rustup help toolchain`
--target <target>
--target <TARGET>
-h, --help Print help
"""
stderr = ""
2 changes: 1 addition & 1 deletion tests/suite/cli-ui/rustup/rustup_help_cmd_stdout.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ The Rust toolchain installer
Usage: rustup[EXE] [OPTIONS] [+toolchain] [COMMAND]
Commands:
component Modify a toolchain's installed components
override Modify toolchain overrides for directories
run Run a command with an environment configured for a given toolchain
which Display which binary will be run for a given command
Expand All @@ -24,6 +23,7 @@ Commands:
default Set the default toolchain
toolchain Modify or query the installed toolchains
target Modify a toolchain's supported targets
component Modify a toolchain's installed components
help Print this message or the help of the given subcommand(s)
Arguments:
Expand Down
2 changes: 1 addition & 1 deletion tests/suite/cli-ui/rustup/rustup_help_flag_stdout.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ The Rust toolchain installer
Usage: rustup[EXE] [OPTIONS] [+toolchain] [COMMAND]
Commands:
component Modify a toolchain's installed components
override Modify toolchain overrides for directories
run Run a command with an environment configured for a given toolchain
which Display which binary will be run for a given command
Expand All @@ -24,6 +23,7 @@ Commands:
default Set the default toolchain
toolchain Modify or query the installed toolchains
target Modify a toolchain's supported targets
component Modify a toolchain's installed components
help Print this message or the help of the given subcommand(s)
Arguments:
Expand Down
2 changes: 1 addition & 1 deletion tests/suite/cli-ui/rustup/rustup_only_options_stdout.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ The Rust toolchain installer
Usage: rustup[EXE] [OPTIONS] [+toolchain] [COMMAND]
Commands:
component Modify a toolchain's installed components
override Modify toolchain overrides for directories
run Run a command with an environment configured for a given toolchain
which Display which binary will be run for a given command
Expand All @@ -24,6 +23,7 @@ Commands:
default Set the default toolchain
toolchain Modify or query the installed toolchains
target Modify a toolchain's supported targets
component Modify a toolchain's installed components
help Print this message or the help of the given subcommand(s)
Arguments:
Expand Down

0 comments on commit 38547fd

Please sign in to comment.