Skip to content

Commit 2806270

Browse files
committed
feat(yank): Support foo@version like cargo-add
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.
1 parent b3f6772 commit 2806270

File tree

2 files changed

+140
-5
lines changed

2 files changed

+140
-5
lines changed

src/bin/cargo/commands/yank.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ pub fn cli() -> App {
1010
.arg(
1111
opt("version", "The version to yank or un-yank")
1212
.alias("vers")
13-
.value_name("VERSION")
14-
.required(true),
13+
.value_name("VERSION"),
1514
)
1615
.arg(opt(
1716
"undo",
@@ -28,14 +27,37 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
2827

2928
let registry = args.registry(config)?;
3029

30+
let (krate, version) = resolve_crate(args.value_of("crate"), args.value_of("version"))?;
31+
if version.is_none() {
32+
return Err(anyhow::format_err!("`--version` is required").into());
33+
}
34+
3135
ops::yank(
3236
config,
33-
args.value_of("crate").map(|s| s.to_string()),
34-
args.value_of("version").map(|s| s.to_string()),
37+
krate.map(|s| s.to_string()),
38+
version.map(|s| s.to_string()),
3539
args.value_of("token").map(|s| s.to_string()),
3640
args.value_of("index").map(|s| s.to_string()),
3741
args.is_present("undo"),
3842
registry,
3943
)?;
4044
Ok(())
4145
}
46+
47+
fn resolve_crate<'k>(
48+
mut krate: Option<&'k str>,
49+
mut version: Option<&'k str>,
50+
) -> crate::CargoResult<(Option<&'k str>, Option<&'k str>)> {
51+
if let Some((k, v)) = krate.and_then(|k| k.split_once('@')) {
52+
if version.is_some() {
53+
anyhow::bail!("cannot specify both `@{v}` and `--version`");
54+
}
55+
if k.is_empty() {
56+
// by convention, arguments starting with `@` are response files
57+
anyhow::bail!("missing crate name for `@{v}`");
58+
}
59+
krate = Some(k);
60+
version = Some(v);
61+
}
62+
Ok((krate, version))
63+
}

tests/testsuite/yank.rs

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn setup(name: &str, version: &str) {
1313
}
1414

1515
#[cargo_test]
16-
fn simple() {
16+
fn explicit_version() {
1717
registry::init();
1818
setup("foo", "0.0.1");
1919

@@ -46,3 +46,116 @@ Caused by:
4646
)
4747
.run();
4848
}
49+
50+
#[cargo_test]
51+
fn inline_version() {
52+
registry::init();
53+
setup("foo", "0.0.1");
54+
55+
let p = project()
56+
.file(
57+
"Cargo.toml",
58+
r#"
59+
[project]
60+
name = "foo"
61+
version = "0.0.1"
62+
authors = []
63+
license = "MIT"
64+
description = "foo"
65+
"#,
66+
)
67+
.file("src/main.rs", "fn main() {}")
68+
.build();
69+
70+
p.cargo("yank [email protected] --token sekrit").run();
71+
72+
p.cargo("yank --undo [email protected] --token sekrit")
73+
.with_status(101)
74+
.with_stderr(
75+
" Updating `[..]` index
76+
77+
error: failed to undo a yank from the registry at file:///[..]
78+
79+
Caused by:
80+
EOF while parsing a value at line 1 column 0",
81+
)
82+
.run();
83+
}
84+
85+
#[cargo_test]
86+
fn version_required() {
87+
registry::init();
88+
setup("foo", "0.0.1");
89+
90+
let p = project()
91+
.file(
92+
"Cargo.toml",
93+
r#"
94+
[project]
95+
name = "foo"
96+
version = "0.0.1"
97+
authors = []
98+
license = "MIT"
99+
description = "foo"
100+
"#,
101+
)
102+
.file("src/main.rs", "fn main() {}")
103+
.build();
104+
105+
p.cargo("yank foo --token sekrit")
106+
.with_status(101)
107+
.with_stderr("error: `--version` is required")
108+
.run();
109+
}
110+
111+
#[cargo_test]
112+
fn inline_version_without_name() {
113+
registry::init();
114+
setup("foo", "0.0.1");
115+
116+
let p = project()
117+
.file(
118+
"Cargo.toml",
119+
r#"
120+
[project]
121+
name = "foo"
122+
version = "0.0.1"
123+
authors = []
124+
license = "MIT"
125+
description = "foo"
126+
"#,
127+
)
128+
.file("src/main.rs", "fn main() {}")
129+
.build();
130+
131+
p.cargo("yank @0.0.1 --token sekrit")
132+
.with_status(101)
133+
.with_stderr("error: missing crate name for `@0.0.1`")
134+
.run();
135+
}
136+
137+
#[cargo_test]
138+
fn inline_and_explicit_version() {
139+
registry::init();
140+
setup("foo", "0.0.1");
141+
142+
let p = project()
143+
.file(
144+
"Cargo.toml",
145+
r#"
146+
[project]
147+
name = "foo"
148+
version = "0.0.1"
149+
authors = []
150+
license = "MIT"
151+
description = "foo"
152+
"#,
153+
)
154+
.file("src/main.rs", "fn main() {}")
155+
.build();
156+
157+
p.cargo("yank [email protected] --version 0.0.1 --token sekrit")
158+
.with_status(101)
159+
.with_stderr("error: cannot specify both `@0.0.1` and `--version`")
160+
.run();
161+
}

0 commit comments

Comments
 (0)