Make it possible to uninstall multiple packages
authorFredrik Larsson <nossralf@gmail.com>
Sun, 10 Sep 2017 18:41:12 +0000 (20:41 +0200)
committerFredrik Larsson <nossralf@gmail.com>
Sat, 28 Oct 2017 12:53:57 +0000 (14:53 +0200)
src/bin/uninstall.rs
src/cargo/ops/cargo_install.rs

index 2adf2d04156ea094916fab0a54f54d18abf1fbe0..3774f0c31fb9597f609e338899cc5642e6d8cc33 100644 (file)
@@ -13,14 +13,14 @@ pub struct Options {
     #[serde(rename = "flag_Z")]
     flag_z: Vec<String>,
 
-    arg_spec: String,
+    arg_spec: Vec<String>,
 }
 
 pub const USAGE: &'static str = "
 Remove a Rust binary
 
 Usage:
-    cargo uninstall [options] <spec>
+    cargo uninstall [options] <spec>...
     cargo uninstall (-h | --help)
 
 Options:
@@ -49,7 +49,9 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
                      &options.flag_z)?;
 
     let root = options.flag_root.as_ref().map(|s| &s[..]);
-    ops::uninstall(root, &options.arg_spec, &options.flag_bin, config)?;
+    let specs = options.arg_spec.iter().map(|s| &s[..]).collect::<Vec<_>>();
+
+    ops::uninstall(root, specs, &options.flag_bin, config)?;
     Ok(())
 }
 
index 4c88e8951f7b79df46223ee43c75ef1a034bcffe..01189bc61ee46005fad82aa70635641ba10f0e9e 100644 (file)
@@ -557,10 +557,53 @@ pub fn install_list(dst: Option<&str>, config: &Config) -> CargoResult<()> {
 }
 
 pub fn uninstall(root: Option<&str>,
-                 spec: &str,
+                 specs: Vec<&str>,
                  bins: &[String],
                  config: &Config) -> CargoResult<()> {
     let root = resolve_root(root, config)?;
+    let scheduled_error = if specs.len() == 1 {
+        uninstall_one(root, specs[0], bins, config)?;
+        false
+    } else {
+        let mut succeeded = vec![];
+        let mut failed = vec![];
+        for spec in specs {
+            let root = root.clone();
+            match uninstall_one(root, spec, bins, config) {
+                Ok(()) => succeeded.push(spec),
+                Err(e) => {
+                    ::handle_error(e, &mut config.shell());
+                    failed.push(spec)
+                }
+            }
+        }
+
+        let mut summary = vec![];
+        if !succeeded.is_empty() {
+            summary.push(format!("Successfully uninstalled {}!", succeeded.join(", ")));
+        }
+        if !failed.is_empty() {
+            summary.push(format!("Failed to uninstall {} (see error(s) above).", failed.join(", ")));
+        }
+
+        if !succeeded.is_empty() || !failed.is_empty() {
+            config.shell().status("\nSummary:", summary.join(" "))?;
+        }
+
+        !failed.is_empty()
+    };
+
+    if scheduled_error {
+        bail!("some packages failed to uninstall");
+    }
+
+    Ok(())
+}
+
+pub fn uninstall_one(root: Filesystem,
+                     spec: &str,
+                     bins: &[String],
+                     config: &Config) -> CargoResult<()> {
     let crate_metadata = metadata(config, &root)?;
     let mut metadata = read_crate_list(&crate_metadata)?;
     let mut to_remove = Vec::new();