diff --git a/src/bin/cargo/commands/yank.rs b/src/bin/cargo/commands/yank.rs index fea6cbf31b6..ceaffb915ca 100644 --- a/src/bin/cargo/commands/yank.rs +++ b/src/bin/cargo/commands/yank.rs @@ -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)) +} diff --git a/src/doc/man/cargo-yank.md b/src/doc/man/cargo-yank.md index 36922386f89..3b9185d6a65 100644 --- a/src/doc/man/cargo-yank.md +++ b/src/doc/man/cargo-yank.md @@ -6,6 +6,7 @@ cargo-yank - Remove a pushed crate from the index ## SYNOPSIS +`cargo yank` [_options_] _crate_@_version_\ `cargo yank` [_options_] `--version` _version_ [_crate_] ## DESCRIPTION @@ -64,7 +65,7 @@ Undo a yank, putting a version back into the index. 1. Yank a crate from the index: - cargo yank --version 1.0.7 foo + cargo yank foo@1.0.7 ## SEE ALSO {{man "cargo" 1}}, {{man "cargo-login" 1}}, {{man "cargo-publish" 1}} diff --git a/src/doc/man/generated_txt/cargo-yank.txt b/src/doc/man/generated_txt/cargo-yank.txt index a56d41bc703..8ad8ca81c77 100644 --- a/src/doc/man/generated_txt/cargo-yank.txt +++ b/src/doc/man/generated_txt/cargo-yank.txt @@ -4,6 +4,7 @@ NAME cargo-yank - Remove a pushed crate from the index SYNOPSIS + cargo yank [options] crate@version cargo yank [options] --version version [crate] DESCRIPTION @@ -104,7 +105,7 @@ EXIT STATUS EXAMPLES 1. Yank a crate from the index: - cargo yank --version 1.0.7 foo + cargo yank foo@1.0.7 SEE ALSO cargo(1), cargo-login(1), cargo-publish(1) diff --git a/src/doc/src/commands/cargo-yank.md b/src/doc/src/commands/cargo-yank.md index d31c162ea0c..21c68d14ade 100644 --- a/src/doc/src/commands/cargo-yank.md +++ b/src/doc/src/commands/cargo-yank.md @@ -6,6 +6,7 @@ cargo-yank - Remove a pushed crate from the index ## SYNOPSIS +`cargo yank` [_options_] _crate_@_version_\ `cargo yank` [_options_] `--version` _version_ [_crate_] ## DESCRIPTION @@ -140,7 +141,7 @@ details on environment variables that Cargo reads. 1. Yank a crate from the index: - cargo yank --version 1.0.7 foo + cargo yank foo@1.0.7 ## SEE ALSO [cargo(1)](cargo.html), [cargo-login(1)](cargo-login.html), [cargo-publish(1)](cargo-publish.html) diff --git a/src/etc/man/cargo-yank.1 b/src/etc/man/cargo-yank.1 index 7fe705bb351..ac6dfc70882 100644 --- a/src/etc/man/cargo-yank.1 +++ b/src/etc/man/cargo-yank.1 @@ -6,6 +6,8 @@ .SH "NAME" cargo\-yank \- Remove a pushed crate from the index .SH "SYNOPSIS" +\fBcargo yank\fR [\fIoptions\fR] \fIcrate\fR@\fIversion\fR +.br \fBcargo yank\fR [\fIoptions\fR] \fB\-\-version\fR \fIversion\fR [\fIcrate\fR] .SH "DESCRIPTION" The yank command removes a previously published crate's version from the @@ -139,7 +141,7 @@ details on environment variables that Cargo reads. .sp .RS 4 .nf -cargo yank \-\-version 1.0.7 foo +cargo yank foo@1.0.7 .fi .RE .RE diff --git a/tests/testsuite/yank.rs b/tests/testsuite/yank.rs index 259c5946566..3447aac2885 100644 --- a/tests/testsuite/yank.rs +++ b/tests/testsuite/yank.rs @@ -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(); +}