diff --git a/src/cargo/core/package_id_spec.rs b/src/cargo/core/package_id_spec.rs index daa3c73ee74..6049e981fa9 100644 --- a/src/cargo/core/package_id_spec.rs +++ b/src/cargo/core/package_id_spec.rs @@ -38,12 +38,9 @@ impl PackageIdSpec { /// use cargo::core::PackageIdSpec; /// /// let specs = vec![ + /// "https://crates.io/foo", /// "https://crates.io/foo#1.2.3", /// "https://crates.io/foo#bar:1.2.3", - /// "crates.io/foo", - /// "crates.io/foo#1.2.3", - /// "crates.io/foo#bar", - /// "crates.io/foo#bar:1.2.3", /// "foo", /// "foo:1.2.3", /// ]; @@ -51,14 +48,21 @@ impl PackageIdSpec { /// assert!(PackageIdSpec::parse(spec).is_ok()); /// } pub fn parse(spec: &str) -> CargoResult { - if spec.contains('/') { + if spec.contains("://") { if let Ok(url) = spec.into_url() { return PackageIdSpec::from_url(url); } - if !spec.contains("://") { - if let Ok(url) = Url::parse(&format!("cargo://{}", spec)) { - return PackageIdSpec::from_url(url); - } + } else if spec.contains('/') || spec.contains('\\') { + let abs = std::env::current_dir().unwrap_or_default().join(spec); + if abs.exists() { + let maybe_url = Url::from_file_path(abs) + .map_or_else(|_| "a file:// URL".to_string(), |url| url.to_string()); + bail!( + "package ID specification `{}` looks like a file path, \ + maybe try {}", + spec, + maybe_url + ); } } let mut parts = spec.splitn(2, ':'); @@ -80,8 +84,11 @@ impl PackageIdSpec { where I: IntoIterator, { - let spec = PackageIdSpec::parse(spec) - .chain_err(|| anyhow::format_err!("invalid package ID specification: `{}`", spec))?; + let i: Vec<_> = i.into_iter().collect(); + let spec = PackageIdSpec::parse(spec).chain_err(|| { + let suggestion = lev_distance::closest_msg(spec, i.iter(), |id| id.name().as_str()); + anyhow::format_err!("invalid package ID specification: `{}`{}", spec, suggestion) + })?; spec.query(i) } @@ -275,11 +282,7 @@ impl fmt::Display for PackageIdSpec { let mut printed_name = false; match self.url { Some(ref url) => { - if url.scheme() == "cargo" { - write!(f, "{}{}", url.host().unwrap(), url.path())?; - } else { - write!(f, "{}", url)?; - } + write!(f, "{}", url)?; if url.path_segments().unwrap().next_back().unwrap() != &*self.name { printed_name = true; write!(f, "#{}", self.name)?; @@ -333,51 +336,27 @@ mod tests { } ok( - "https://crates.io/foo#1.2.3", - PackageIdSpec { - name: InternedString::new("foo"), - version: Some("1.2.3".to_semver().unwrap()), - url: Some(Url::parse("https://crates.io/foo").unwrap()), - }, - ); - ok( - "https://crates.io/foo#bar:1.2.3", - PackageIdSpec { - name: InternedString::new("bar"), - version: Some("1.2.3".to_semver().unwrap()), - url: Some(Url::parse("https://crates.io/foo").unwrap()), - }, - ); - ok( - "crates.io/foo", + "https://crates.io/foo", PackageIdSpec { name: InternedString::new("foo"), version: None, - url: Some(Url::parse("cargo://crates.io/foo").unwrap()), + url: Some(Url::parse("https://crates.io/foo").unwrap()), }, ); ok( - "crates.io/foo#1.2.3", + "https://crates.io/foo#1.2.3", PackageIdSpec { name: InternedString::new("foo"), version: Some("1.2.3".to_semver().unwrap()), - url: Some(Url::parse("cargo://crates.io/foo").unwrap()), - }, - ); - ok( - "crates.io/foo#bar", - PackageIdSpec { - name: InternedString::new("bar"), - version: None, - url: Some(Url::parse("cargo://crates.io/foo").unwrap()), + url: Some(Url::parse("https://crates.io/foo").unwrap()), }, ); ok( - "crates.io/foo#bar:1.2.3", + "https://crates.io/foo#bar:1.2.3", PackageIdSpec { name: InternedString::new("bar"), version: Some("1.2.3".to_semver().unwrap()), - url: Some(Url::parse("cargo://crates.io/foo").unwrap()), + url: Some(Url::parse("https://crates.io/foo").unwrap()), }, ); ok( diff --git a/src/doc/man/cargo-pkgid.md b/src/doc/man/cargo-pkgid.md index 12f8cacc8c4..1fb9a60efc7 100644 --- a/src/doc/man/cargo-pkgid.md +++ b/src/doc/man/cargo-pkgid.md @@ -81,5 +81,9 @@ Get the package ID for the given package instead of the current package. cargo pkgid https://github.com/rust-lang/crates.io-index#foo +4. Retrieve package specification for `foo` from a local package: + + cargo pkgid file:///path/to/local/package#foo + ## SEE ALSO {{man "cargo" 1}}, {{man "cargo-generate-lockfile" 1}}, {{man "cargo-metadata" 1}} diff --git a/src/doc/man/generated_txt/cargo-pkgid.txt b/src/doc/man/generated_txt/cargo-pkgid.txt index eab8edebbea..cee20fc122b 100644 --- a/src/doc/man/generated_txt/cargo-pkgid.txt +++ b/src/doc/man/generated_txt/cargo-pkgid.txt @@ -137,6 +137,10 @@ EXAMPLES cargo pkgid https://github.com/rust-lang/crates.io-index#foo + 4. Retrieve package specification for foo from a local package: + + cargo pkgid file:///path/to/local/package#foo + SEE ALSO cargo(1), cargo-generate-lockfile(1), cargo-metadata(1) diff --git a/src/doc/src/commands/cargo-pkgid.md b/src/doc/src/commands/cargo-pkgid.md index e899d9c9d84..c380738c943 100644 --- a/src/doc/src/commands/cargo-pkgid.md +++ b/src/doc/src/commands/cargo-pkgid.md @@ -163,5 +163,9 @@ details on environment variables that Cargo reads. cargo pkgid https://github.com/rust-lang/crates.io-index#foo +4. Retrieve package specification for `foo` from a local package: + + cargo pkgid file:///path/to/local/package#foo + ## SEE ALSO [cargo(1)](cargo.html), [cargo-generate-lockfile(1)](cargo-generate-lockfile.html), [cargo-metadata(1)](cargo-metadata.html) diff --git a/src/etc/man/cargo-pkgid.1 b/src/etc/man/cargo-pkgid.1 index 27b3cd71a8c..4ee1046dd43 100644 --- a/src/etc/man/cargo-pkgid.1 +++ b/src/etc/man/cargo-pkgid.1 @@ -207,5 +207,15 @@ cargo pkgid https://github.com/rust\-lang/crates.io\-index#foo .fi .RE .RE +.sp +.RS 4 +\h'-04' 4.\h'+01'Retrieve package specification for \fBfoo\fR from a local package: +.sp +.RS 4 +.nf +cargo pkgid file:///path/to/local/package#foo +.fi +.RE +.RE .SH "SEE ALSO" \fBcargo\fR(1), \fBcargo\-generate\-lockfile\fR(1), \fBcargo\-metadata\fR(1) diff --git a/tests/testsuite/pkgid.rs b/tests/testsuite/pkgid.rs index 93ee9eeddfb..5cd4cd41b17 100644 --- a/tests/testsuite/pkgid.rs +++ b/tests/testsuite/pkgid.rs @@ -54,6 +54,7 @@ fn suggestion_bad_pkgid() { "#, ) .file("src/lib.rs", "") + .file("cratesio", "") .build(); p.cargo("generate-lockfile").run(); @@ -93,6 +94,34 @@ Did you mean one of these? two-ver:0.1.0 two-ver:0.2.0 +", + ) + .run(); + + // 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 simliar name. + p.cargo("pkgid './cratesio'") + .with_status(101) + .with_stderr( + "\ +error: invalid package ID specification: `./cratesio` + +Did you mean `crates-io`? + +Caused by: + package ID specification `./cratesio` looks like a file path, maybe try file://[..]/cratesio ", ) .run();