Skip to content

Commit

Permalink
feat(yank): Support foo@version like cargo-add
Browse files Browse the repository at this point in the history
In rust-lang#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.
  • Loading branch information
epage authored and Hezuikn committed Sep 22, 2022
1 parent 7aa7513 commit 1a4472c
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 5 deletions.
30 changes: 26 additions & 4 deletions src/bin/cargo/commands/yank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -28,14 +27,37 @@ 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"),
registry,
)?;
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))
}
115 changes: 114 additions & 1 deletion tests/testsuite/yank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn setup(name: &str, version: &str) {
}

#[cargo_test]
fn simple() {
fn explicit_version() {
registry::init();
setup("foo", "0.0.1");

Expand Down Expand Up @@ -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();
}

0 comments on commit 1a4472c

Please # to comment.