diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index 4ec3f6951e6..b4937fa6f6f 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -261,7 +261,7 @@ fn parse_semver_flag(v: &str) -> CargoResult { // requirement, add a note to the warning if v.parse::().is_ok() { msg.push_str(&format!( - "\n\n tip: if you want to specify semver range, \ + "\n\n tip: if you want to specify SemVer range, \ add an explicit qualifier, like '^{}'", v )); diff --git a/src/cargo/util/semver_ext.rs b/src/cargo/util/semver_ext.rs index 5efa1d2f173..cddaa97c9cd 100644 --- a/src/cargo/util/semver_ext.rs +++ b/src/cargo/util/semver_ext.rs @@ -143,10 +143,10 @@ impl std::str::FromStr for PartialVersion { let version_req = match semver::VersionReq::parse(value) { // Exclude semver operators like `^` and pre-release identifiers Ok(req) if value.chars().all(|c| c.is_ascii_digit() || c == '.') => req, - Err(_) if value.contains('+') => { + _ if value.contains('+') => { anyhow::bail!("unexpected build field, expected a version like \"1.32\"") } - Err(_) if value.contains('-') => { + _ if value.contains('-') => { anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"") } _ => anyhow::bail!("expected a version like \"1.32\""), diff --git a/src/cargo/util/to_semver.rs b/src/cargo/util/to_semver.rs index 25da9dfb975..3cc9e5706ac 100644 --- a/src/cargo/util/to_semver.rs +++ b/src/cargo/util/to_semver.rs @@ -15,7 +15,10 @@ impl<'a> ToSemver for &'a str { fn to_semver(self) -> CargoResult { match Version::parse(self.trim()) { Ok(v) => Ok(v), - Err(..) => Err(anyhow::format_err!("cannot parse '{}' as a semver", self)), + Err(..) => Err(anyhow::format_err!( + "cannot parse '{}' as a SemVer version", + self + )), } } } diff --git a/tests/testsuite/install_upgrade.rs b/tests/testsuite/install_upgrade.rs index 100fe1fde11..580117f5cdc 100644 --- a/tests/testsuite/install_upgrade.rs +++ b/tests/testsuite/install_upgrade.rs @@ -230,9 +230,9 @@ fn ambiguous_version_no_longer_allowed() { cargo_process("install foo --version=1.0") .with_stderr( "\ -[ERROR] invalid value '1.0' for '--version ': cannot parse '1.0' as a semver +[ERROR] invalid value '1.0' for '--version ': cannot parse '1.0' as a SemVer version - tip: if you want to specify semver range, add an explicit qualifier, like '^1.0' + tip: if you want to specify SemVer range, add an explicit qualifier, like '^1.0' For more information, try '--help'. ", diff --git a/tests/testsuite/pkgid.rs b/tests/testsuite/pkgid.rs index 3e3e4692a63..1857f43b185 100644 --- a/tests/testsuite/pkgid.rs +++ b/tests/testsuite/pkgid.rs @@ -4,22 +4,31 @@ use cargo_test_support::project; use cargo_test_support::registry::Package; #[cargo_test] -fn simple() { - Package::new("bar", "0.1.0").publish(); +fn local() { let p = project() .file( "Cargo.toml", r#" + [workspace] + members = ["bar"] + [package] name = "foo" version = "0.1.0" edition = "2018" - - [dependencies] - bar = "0.1.0" "#, ) .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2018" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") .build(); p.cargo("generate-lockfile").run(); @@ -28,16 +37,38 @@ fn simple() { .with_stdout(format!("file://[..]{}#0.1.0", p.root().to_str().unwrap())) .run(); - p.cargo("pkgid bar") - .with_stdout("https://github.com/rust-lang/crates.io-index#bar@0.1.0") + // Bad file URL. + p.cargo("pkgid ./Cargo.toml") + .with_status(101) + .with_stderr( + "\ +error: invalid package ID specification: `./Cargo.toml` + +Caused by: + package ID specification `./Cargo.toml` looks like a file path, maybe try file://[..]/Cargo.toml +", + ) + .run(); + + // Bad file URL with similar name. + p.cargo("pkgid './bar'") + .with_status(101) + .with_stderr( + "\ +error: invalid package ID specification: `./bar` + +Did you mean `bar`? + +Caused by: + package ID specification `./bar` looks like a file path, maybe try file://[..]/bar +", + ) .run(); } #[cargo_test] -fn suggestion_bad_pkgid() { +fn registry() { Package::new("crates-io", "0.1.0").publish(); - Package::new("two-ver", "0.1.0").publish(); - Package::new("two-ver", "0.2.0").publish(); let p = project() .file( "Cargo.toml", @@ -49,16 +80,18 @@ fn suggestion_bad_pkgid() { [dependencies] crates-io = "0.1.0" - two-ver = "0.1.0" - two-ver2 = { package = "two-ver", version = "0.2.0" } "#, ) - .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") .file("cratesio", "") .build(); p.cargo("generate-lockfile").run(); + p.cargo("pkgid crates-io") + .with_stdout("https://github.com/rust-lang/crates.io-index#crates-io@0.1.0") + .run(); + // Bad URL. p.cargo("pkgid https://example.com/crates-io") .with_status(101) @@ -83,45 +116,87 @@ error: package ID specification `crates_io` did not match any packages ", ) .run(); +} - // Bad version. - p.cargo("pkgid two-ver:0.3.0") +#[cargo_test] +fn multiple_versions() { + Package::new("two-ver", "0.1.0").publish(); + Package::new("two-ver", "0.2.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + two-ver = "0.1.0" + two-ver2 = { package = "two-ver", version = "0.2.0" } + "#, + ) + .file("src/lib.rs", "") + .file("cratesio", "") + .build(); + + p.cargo("generate-lockfile").run(); + + p.cargo("pkgid two-ver:0.2.0") + .with_stdout("https://github.com/rust-lang/crates.io-index#two-ver@0.2.0") + .run(); + + // Incomplete version. + p.cargo("pkgid two-ver@0") .with_status(101) .with_stderr( "\ -error: package ID specification `two-ver@0.3.0` did not match any packages -Did you mean one of these? +error: invalid package ID specification: `two-ver@0` - two-ver@0.1.0 - two-ver@0.2.0 +Did you mean `two-ver`? + +Caused by: + cannot parse '0' as a SemVer version ", ) .run(); - // Bad file URL. - p.cargo("pkgid ./Cargo.toml") + // Incomplete version. + p.cargo("pkgid two-ver@0.2") .with_status(101) .with_stderr( "\ -error: invalid package ID specification: `./Cargo.toml` +error: invalid package ID specification: `two-ver@0.2` Caused by: - package ID specification `./Cargo.toml` looks like a file path, maybe try file://[..]/Cargo.toml + cannot parse '0.2' as a SemVer version ", ) .run(); - // Bad file URL with similar name. - p.cargo("pkgid './cratesio'") + // Ambiguous. + p.cargo("pkgid two-ver") .with_status(101) .with_stderr( "\ -error: invalid package ID specification: `./cratesio` +error: There are multiple `two-ver` packages in your project, and the specification `two-ver` is ambiguous. +Please re-run this command with `-p ` where `` is one of the following: + two-ver@0.1.0 + two-ver@0.2.0 +", + ) + .run(); -Did you mean `crates-io`? + // Bad version. + p.cargo("pkgid two-ver:0.3.0") + .with_status(101) + .with_stderr( + "\ +error: package ID specification `two-ver@0.3.0` did not match any packages +Did you mean one of these? -Caused by: - package ID specification `./cratesio` looks like a file path, maybe try file://[..]/cratesio + two-ver@0.1.0 + two-ver@0.2.0 ", ) .run(); diff --git a/tests/testsuite/rust_version.rs b/tests/testsuite/rust_version.rs index 4f65dcdc6c8..21321b7c579 100644 --- a/tests/testsuite/rust_version.rs +++ b/tests/testsuite/rust_version.rs @@ -57,6 +57,39 @@ Caused by: .run(); } +#[cargo_test] +fn rust_version_good_pre_release() { + project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + rust-version = "1.43.0-beta.1" + [[bin]] + name = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build() + .cargo("check") + .with_status(101) + .with_stderr( + "\ +error: failed to parse manifest at `[..]` + +Caused by: + TOML parse error at line 6, column 28 + | + 6 | rust-version = \"1.43.0-beta.1\" + | ^^^^^^^^^^^^^^^ + unexpected prerelease field, expected a version like \"1.32\"", + ) + .run(); +} + #[cargo_test] fn rust_version_bad_pre_release() { project()