Skip to content

Commit 0de91c8

Browse files
committed
Auto merge of #12591 - epage:spec, r=weihanglo
Prepare for partial-version package specs ### What does this PR try to resolve? These are refactorings, test expansions, and cleanups I saw as I was preparing to implement support for `[email protected]` as proposed in #12425. I figured these changes stand on their own so I separated them out. One further change I considered was that `foo@0` will suggest `foo` in a "did you mean" message. This is a big off *but* most likely any fix for this would be undone by the work to support `[email protected]`, so I held off on it. ### How should we test and review this PR? Each change is broken down into an individual commit
2 parents 5aca9af + a78bba7 commit 0de91c8

File tree

6 files changed

+146
-35
lines changed

6 files changed

+146
-35
lines changed

src/bin/cargo/commands/install.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ fn parse_semver_flag(v: &str) -> CargoResult<VersionReq> {
261261
// requirement, add a note to the warning
262262
if v.parse::<VersionReq>().is_ok() {
263263
msg.push_str(&format!(
264-
"\n\n tip: if you want to specify semver range, \
264+
"\n\n tip: if you want to specify SemVer range, \
265265
add an explicit qualifier, like '^{}'",
266266
v
267267
));

src/cargo/util/semver_ext.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,10 @@ impl std::str::FromStr for PartialVersion {
143143
let version_req = match semver::VersionReq::parse(value) {
144144
// Exclude semver operators like `^` and pre-release identifiers
145145
Ok(req) if value.chars().all(|c| c.is_ascii_digit() || c == '.') => req,
146-
Err(_) if value.contains('+') => {
146+
_ if value.contains('+') => {
147147
anyhow::bail!("unexpected build field, expected a version like \"1.32\"")
148148
}
149-
Err(_) if value.contains('-') => {
149+
_ if value.contains('-') => {
150150
anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"")
151151
}
152152
_ => anyhow::bail!("expected a version like \"1.32\""),

src/cargo/util/to_semver.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ impl<'a> ToSemver for &'a str {
1515
fn to_semver(self) -> CargoResult<Version> {
1616
match Version::parse(self.trim()) {
1717
Ok(v) => Ok(v),
18-
Err(..) => Err(anyhow::format_err!("cannot parse '{}' as a semver", self)),
18+
Err(..) => Err(anyhow::format_err!(
19+
"cannot parse '{}' as a SemVer version",
20+
self
21+
)),
1922
}
2023
}
2124
}

tests/testsuite/install_upgrade.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,9 @@ fn ambiguous_version_no_longer_allowed() {
230230
cargo_process("install foo --version=1.0")
231231
.with_stderr(
232232
"\
233-
[ERROR] invalid value '1.0' for '--version <VERSION>': cannot parse '1.0' as a semver
233+
[ERROR] invalid value '1.0' for '--version <VERSION>': cannot parse '1.0' as a SemVer version
234234
235-
tip: if you want to specify semver range, add an explicit qualifier, like '^1.0'
235+
tip: if you want to specify SemVer range, add an explicit qualifier, like '^1.0'
236236
237237
For more information, try '--help'.
238238
",

tests/testsuite/pkgid.rs

Lines changed: 104 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,31 @@ use cargo_test_support::project;
44
use cargo_test_support::registry::Package;
55

66
#[cargo_test]
7-
fn simple() {
8-
Package::new("bar", "0.1.0").publish();
7+
fn local() {
98
let p = project()
109
.file(
1110
"Cargo.toml",
1211
r#"
12+
[workspace]
13+
members = ["bar"]
14+
1315
[package]
1416
name = "foo"
1517
version = "0.1.0"
1618
edition = "2018"
17-
18-
[dependencies]
19-
bar = "0.1.0"
2019
"#,
2120
)
2221
.file("src/main.rs", "fn main() {}")
22+
.file(
23+
"bar/Cargo.toml",
24+
r#"
25+
[package]
26+
name = "bar"
27+
version = "0.1.0"
28+
edition = "2018"
29+
"#,
30+
)
31+
.file("bar/src/main.rs", "fn main() {}")
2332
.build();
2433

2534
p.cargo("generate-lockfile").run();
@@ -28,16 +37,38 @@ fn simple() {
2837
.with_stdout(format!("file://[..]{}#0.1.0", p.root().to_str().unwrap()))
2938
.run();
3039

31-
p.cargo("pkgid bar")
32-
.with_stdout("https://github.com/rust-lang/crates.io-index#[email protected]")
40+
// Bad file URL.
41+
p.cargo("pkgid ./Cargo.toml")
42+
.with_status(101)
43+
.with_stderr(
44+
"\
45+
error: invalid package ID specification: `./Cargo.toml`
46+
47+
Caused by:
48+
package ID specification `./Cargo.toml` looks like a file path, maybe try file://[..]/Cargo.toml
49+
",
50+
)
51+
.run();
52+
53+
// Bad file URL with similar name.
54+
p.cargo("pkgid './bar'")
55+
.with_status(101)
56+
.with_stderr(
57+
"\
58+
error: invalid package ID specification: `./bar`
59+
60+
<tab>Did you mean `bar`?
61+
62+
Caused by:
63+
package ID specification `./bar` looks like a file path, maybe try file://[..]/bar
64+
",
65+
)
3366
.run();
3467
}
3568

3669
#[cargo_test]
37-
fn suggestion_bad_pkgid() {
70+
fn registry() {
3871
Package::new("crates-io", "0.1.0").publish();
39-
Package::new("two-ver", "0.1.0").publish();
40-
Package::new("two-ver", "0.2.0").publish();
4172
let p = project()
4273
.file(
4374
"Cargo.toml",
@@ -49,16 +80,18 @@ fn suggestion_bad_pkgid() {
4980
5081
[dependencies]
5182
crates-io = "0.1.0"
52-
two-ver = "0.1.0"
53-
two-ver2 = { package = "two-ver", version = "0.2.0" }
5483
"#,
5584
)
56-
.file("src/lib.rs", "")
85+
.file("src/main.rs", "fn main() {}")
5786
.file("cratesio", "")
5887
.build();
5988

6089
p.cargo("generate-lockfile").run();
6190

91+
p.cargo("pkgid crates-io")
92+
.with_stdout("https://github.com/rust-lang/crates.io-index#[email protected]")
93+
.run();
94+
6295
// Bad URL.
6396
p.cargo("pkgid https://example.com/crates-io")
6497
.with_status(101)
@@ -83,45 +116,87 @@ error: package ID specification `crates_io` did not match any packages
83116
",
84117
)
85118
.run();
119+
}
86120

87-
// Bad version.
88-
p.cargo("pkgid two-ver:0.3.0")
121+
#[cargo_test]
122+
fn multiple_versions() {
123+
Package::new("two-ver", "0.1.0").publish();
124+
Package::new("two-ver", "0.2.0").publish();
125+
let p = project()
126+
.file(
127+
"Cargo.toml",
128+
r#"
129+
[package]
130+
name = "foo"
131+
version = "0.1.0"
132+
edition = "2018"
133+
134+
[dependencies]
135+
two-ver = "0.1.0"
136+
two-ver2 = { package = "two-ver", version = "0.2.0" }
137+
"#,
138+
)
139+
.file("src/lib.rs", "")
140+
.file("cratesio", "")
141+
.build();
142+
143+
p.cargo("generate-lockfile").run();
144+
145+
p.cargo("pkgid two-ver:0.2.0")
146+
.with_stdout("https://github.com/rust-lang/crates.io-index#[email protected]")
147+
.run();
148+
149+
// Incomplete version.
150+
p.cargo("pkgid two-ver@0")
89151
.with_status(101)
90152
.with_stderr(
91153
"\
92-
error: package ID specification `[email protected]` did not match any packages
93-
Did you mean one of these?
154+
error: invalid package ID specification: `two-ver@0`
94155
95-
96-
156+
<tab>Did you mean `two-ver`?
157+
158+
Caused by:
159+
cannot parse '0' as a SemVer version
97160
",
98161
)
99162
.run();
100163

101-
// Bad file URL.
102-
p.cargo("pkgid ./Cargo.toml")
164+
// Incomplete version.
165+
p.cargo("pkgid [email protected]")
103166
.with_status(101)
104167
.with_stderr(
105168
"\
106-
error: invalid package ID specification: `./Cargo.toml`
169+
error: invalid package ID specification: `[email protected]`
107170
108171
Caused by:
109-
package ID specification `./Cargo.toml` looks like a file path, maybe try file://[..]/Cargo.toml
172+
cannot parse '0.2' as a SemVer version
110173
",
111174
)
112175
.run();
113176

114-
// Bad file URL with similar name.
115-
p.cargo("pkgid './cratesio'")
177+
// Ambiguous.
178+
p.cargo("pkgid two-ver")
116179
.with_status(101)
117180
.with_stderr(
118181
"\
119-
error: invalid package ID specification: `./cratesio`
182+
error: There are multiple `two-ver` packages in your project, and the specification `two-ver` is ambiguous.
183+
Please re-run this command with `-p <spec>` where `<spec>` is one of the following:
184+
185+
186+
",
187+
)
188+
.run();
120189

121-
<tab>Did you mean `crates-io`?
190+
// Bad version.
191+
p.cargo("pkgid two-ver:0.3.0")
192+
.with_status(101)
193+
.with_stderr(
194+
"\
195+
error: package ID specification `[email protected]` did not match any packages
196+
Did you mean one of these?
122197
123-
Caused by:
124-
package ID specification `./cratesio` looks like a file path, maybe try file://[..]/cratesio
198+
199+
125200
",
126201
)
127202
.run();

tests/testsuite/rust_version.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,39 @@ Caused by:
5757
.run();
5858
}
5959

60+
#[cargo_test]
61+
fn rust_version_good_pre_release() {
62+
project()
63+
.file(
64+
"Cargo.toml",
65+
r#"
66+
[package]
67+
name = "foo"
68+
version = "0.0.1"
69+
authors = []
70+
rust-version = "1.43.0-beta.1"
71+
[[bin]]
72+
name = "foo"
73+
"#,
74+
)
75+
.file("src/main.rs", "fn main() {}")
76+
.build()
77+
.cargo("check")
78+
.with_status(101)
79+
.with_stderr(
80+
"\
81+
error: failed to parse manifest at `[..]`
82+
83+
Caused by:
84+
TOML parse error at line 6, column 28
85+
|
86+
6 | rust-version = \"1.43.0-beta.1\"
87+
| ^^^^^^^^^^^^^^^
88+
unexpected prerelease field, expected a version like \"1.32\"",
89+
)
90+
.run();
91+
}
92+
6093
#[cargo_test]
6194
fn rust_version_bad_pre_release() {
6295
project()

0 commit comments

Comments
 (0)