Skip to content
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

Allow selecting toolchains to uninstall with glob pattern #2540

Closed
wants to merge 9 commits into from
28 changes: 25 additions & 3 deletions src/cli/rustup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::process::Command;
use std::str::FromStr;

use clap::{App, AppSettings, Arg, ArgGroup, ArgMatches, Shell, SubCommand};
use regex::Regex;

use super::common;
use super::errors::*;
Expand Down Expand Up @@ -404,6 +405,12 @@ pub fn cli() -> App<'static, 'static> {
SubCommand::with_name("uninstall")
.about("Uninstall a toolchain")
.alias("remove")
.arg(
Arg::with_name("regex")
.help("Use a regular expression to select the toolchains to uninstall")
.long("regex")
.takes_value(false),
kinnison marked this conversation as resolved.
Show resolved Hide resolved
)
camelid marked this conversation as resolved.
Show resolved Hide resolved
.arg(
Arg::with_name("toolchain")
.help(TOOLCHAIN_ARG_HELP)
Expand Down Expand Up @@ -1312,10 +1319,25 @@ fn toolchain_link(cfg: &Cfg, m: &ArgMatches<'_>) -> Result<utils::ExitCode> {
}

fn toolchain_remove(cfg: &mut Cfg, m: &ArgMatches<'_>) -> Result<utils::ExitCode> {
for toolchain in m.values_of("toolchain").unwrap() {
let toolchain = cfg.get_toolchain(toolchain, false)?;
toolchain.remove()?;
if m.is_present("regex") {
assert!(
m.values_of("toolchain").unwrap().len() == 1,
"exactly one regex filter must be supplied"
);
camelid marked this conversation as resolved.
Show resolved Hide resolved

let regex = Regex::from_str(m.values_of("toolchain").unwrap().next().unwrap())
.expect("invalid regex");
camelid marked this conversation as resolved.
Show resolved Hide resolved

for toolchain in cfg.get_toolchains_from_regex(regex)? {
toolchain.remove()?;
}
} else {
for toolchain in m.values_of("toolchain").unwrap() {
let toolchain = cfg.get_toolchain(toolchain, false)?;
toolchain.remove()?;
}
}

Ok(utils::ExitCode(0))
}

Expand Down
33 changes: 23 additions & 10 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use std::borrow::Cow;
use std::fmt::{self, Display};
use std::io;
use std::iter;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use std::sync::Arc;

use pgp::{Deserializable, SignedPublicKey};
use regex::Regex;
use serde::Deserialize;

use crate::dist::download::DownloadCfg;
Expand Down Expand Up @@ -362,6 +364,14 @@ impl Cfg {
Toolchain::from(self, name)
}

pub fn get_toolchains_from_regex(&self, regex: Regex) -> Result<Vec<Toolchain<'_>>> {
camelid marked this conversation as resolved.
Show resolved Hide resolved
Ok(self
.list_toolchains_iter()?
.filter(|toolchain| regex.is_match(toolchain))
.map(|toolchain| Toolchain::from(self, &toolchain).unwrap())
.collect())
}

pub fn verify_toolchain(&self, name: &str) -> Result<Toolchain<'_>> {
let toolchain = self.get_toolchain(name, false)?;
toolchain.verify()?;
Expand Down Expand Up @@ -694,18 +704,21 @@ impl Cfg {
}

pub fn list_toolchains(&self) -> Result<Vec<String>> {
if utils::is_directory(&self.toolchains_dir) {
let mut toolchains: Vec<_> = utils::read_dir("toolchains", &self.toolchains_dir)?
.filter_map(io::Result::ok)
.filter(|e| e.file_type().map(|f| !f.is_file()).unwrap_or(false))
.filter_map(|e| e.file_name().into_string().ok())
.collect();

utils::toolchain_sort(&mut toolchains);
let mut toolchains: Vec<_> = self.list_toolchains_iter()?.collect();
utils::toolchain_sort(&mut toolchains);
Ok(toolchains)
}

Ok(toolchains)
fn list_toolchains_iter(&self) -> Result<Box<dyn Iterator<Item = String>>> {
camelid marked this conversation as resolved.
Show resolved Hide resolved
if utils::is_directory(&self.toolchains_dir) {
Ok(Box::new(
utils::read_dir("toolchains", &self.toolchains_dir)?
.filter_map(io::Result::ok)
.filter(|e| e.file_type().map(|f| !f.is_file()).unwrap_or(false))
.filter_map(|e| e.file_name().into_string().ok()),
))
} else {
Ok(Vec::new())
Ok(Box::new(iter::empty()))
}
}

Expand Down