]> git.proxmox.com Git - cargo.git/commitdiff
feat(yank): Support `foo@version` like cargo-add
authorEd Page <eopage@gmail.com>
Tue, 19 Apr 2022 21:44:39 +0000 (16:44 -0500)
committerEd Page <eopage@gmail.com>
Tue, 19 Apr 2022 22:00:42 +0000 (17:00 -0500)
In #10472, cargo-add was merged with support for an inline version
syntax of `foo@version`.  That also served as the change proposal for
extending that syntax to `cargo yank` for convinience and consistency.

The major difference is that `cargo-add` is specifying a version-req
while `cargo-yank` is specifying a version.

This doesn't use the full `pkgid` syntax because that allows syntax that
is unsupported here.

This doesn't use `cargo-add`s parser because that is for version reqs.

src/bin/cargo/commands/yank.rs
tests/testsuite/yank.rs

index fea6cbf31b66b591bcf24ae223fd2f4f66fdcae6..ceaffb915ca2fff06db095c9b5319ca37d4a1365 100644 (file)
@@ -10,8 +10,7 @@ pub fn cli() -> App {
         .arg(
             opt("version", "The version to yank or un-yank")
                 .alias("vers")
-                .value_name("VERSION")
-                .required(true),
+                .value_name("VERSION"),
         )
         .arg(opt(
             "undo",
@@ -28,10 +27,15 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
 
     let registry = args.registry(config)?;
 
+    let (krate, version) = resolve_crate(args.value_of("crate"), args.value_of("version"))?;
+    if version.is_none() {
+        return Err(anyhow::format_err!("`--version` is required").into());
+    }
+
     ops::yank(
         config,
-        args.value_of("crate").map(|s| s.to_string()),
-        args.value_of("version").map(|s| s.to_string()),
+        krate.map(|s| s.to_string()),
+        version.map(|s| s.to_string()),
         args.value_of("token").map(|s| s.to_string()),
         args.value_of("index").map(|s| s.to_string()),
         args.is_present("undo"),
@@ -39,3 +43,21 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
     )?;
     Ok(())
 }
+
+fn resolve_crate<'k>(
+    mut krate: Option<&'k str>,
+    mut version: Option<&'k str>,
+) -> crate::CargoResult<(Option<&'k str>, Option<&'k str>)> {
+    if let Some((k, v)) = krate.and_then(|k| k.split_once('@')) {
+        if version.is_some() {
+            anyhow::bail!("cannot specify both `@{v}` and `--version`");
+        }
+        if k.is_empty() {
+            // by convention, arguments starting with `@` are response files
+            anyhow::bail!("missing crate name for `@{v}`");
+        }
+        krate = Some(k);
+        version = Some(v);
+    }
+    Ok((krate, version))
+}
index 259c5946566f44cfef3255627f36037467912ad4..3447aac2885331dae6e1b91f4276fe5b424edd2b 100644 (file)
@@ -13,7 +13,7 @@ fn setup(name: &str, version: &str) {
 }
 
 #[cargo_test]
-fn simple() {
+fn explicit_version() {
     registry::init();
     setup("foo", "0.0.1");
 
@@ -46,3 +46,116 @@ Caused by:
         )
         .run();
 }
+
+#[cargo_test]
+fn inline_version() {
+    registry::init();
+    setup("foo", "0.0.1");
+
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                [project]
+                name = "foo"
+                version = "0.0.1"
+                authors = []
+                license = "MIT"
+                description = "foo"
+            "#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+
+    p.cargo("yank foo@0.0.1 --token sekrit").run();
+
+    p.cargo("yank --undo foo@0.0.1 --token sekrit")
+        .with_status(101)
+        .with_stderr(
+            "    Updating `[..]` index
+      Unyank foo@0.0.1
+error: failed to undo a yank from the registry at file:///[..]
+
+Caused by:
+  EOF while parsing a value at line 1 column 0",
+        )
+        .run();
+}
+
+#[cargo_test]
+fn version_required() {
+    registry::init();
+    setup("foo", "0.0.1");
+
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                [project]
+                name = "foo"
+                version = "0.0.1"
+                authors = []
+                license = "MIT"
+                description = "foo"
+            "#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+
+    p.cargo("yank foo --token sekrit")
+        .with_status(101)
+        .with_stderr("error: `--version` is required")
+        .run();
+}
+
+#[cargo_test]
+fn inline_version_without_name() {
+    registry::init();
+    setup("foo", "0.0.1");
+
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                [project]
+                name = "foo"
+                version = "0.0.1"
+                authors = []
+                license = "MIT"
+                description = "foo"
+            "#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+
+    p.cargo("yank @0.0.1 --token sekrit")
+        .with_status(101)
+        .with_stderr("error: missing crate name for `@0.0.1`")
+        .run();
+}
+
+#[cargo_test]
+fn inline_and_explicit_version() {
+    registry::init();
+    setup("foo", "0.0.1");
+
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                [project]
+                name = "foo"
+                version = "0.0.1"
+                authors = []
+                license = "MIT"
+                description = "foo"
+            "#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+
+    p.cargo("yank foo@0.0.1 --version 0.0.1 --token sekrit")
+        .with_status(101)
+        .with_stderr("error: cannot specify both `@0.0.1` and `--version`")
+        .run();
+}