Skip to content

Package ID specification urls must contain a host #9188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 9, 2021
71 changes: 25 additions & 46 deletions src/cargo/core/package_id_spec.rs
Original file line number Diff line number Diff line change
@@ -38,27 +38,31 @@ 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",
/// ];
/// for spec in specs {
/// assert!(PackageIdSpec::parse(spec).is_ok());
/// }
pub fn parse(spec: &str) -> CargoResult<PackageIdSpec> {
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<Item = PackageId>,
{
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(
4 changes: 4 additions & 0 deletions src/doc/man/cargo-pkgid.md
Original file line number Diff line number Diff line change
@@ -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}}
4 changes: 4 additions & 0 deletions src/doc/man/generated_txt/cargo-pkgid.txt
Original file line number Diff line number Diff line change
@@ -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)

4 changes: 4 additions & 0 deletions src/doc/src/commands/cargo-pkgid.md
Original file line number Diff line number Diff line change
@@ -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)
10 changes: 10 additions & 0 deletions src/etc/man/cargo-pkgid.1
Original file line number Diff line number Diff line change
@@ -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)
29 changes: 29 additions & 0 deletions tests/testsuite/pkgid.rs
Original file line number Diff line number Diff line change
@@ -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`
<tab>Did you mean `crates-io`?
Caused by:
package ID specification `./cratesio` looks like a file path, maybe try file://[..]/cratesio
",
)
.run();