Skip to content

Commit ce948f4

Browse files
authored
util: provide a better error message for invalid SSH URLs (#15185)
### What does this PR try to resolve? It's very common for users to attempt to use the pseudo-URLs that GitHub or other providers provide in the form `[email protected]:rust-lang/rust.git` as a source in Cargo.toml, which are the default format accepted by OpenSSH. Unfortunately, these are not actually URLs, and unsurprisingly, the `url` crate doesn't accept them. However, our error message is unhelpful and looks like this: invalid url `[email protected]:rust-lang/rust.git`: relative URL without a base This is technically true, but we can do better. The user actually wants to write a real SSH URL, so if the non-URL starts with `git@`, let's rewrite it into a real URL for them to help them and include that in the error message. `git@` is the prefix used by all major forges, as well as the default configuration for do-it-yourself implementations like Gitolite. While other options are possible, they are much less common, and this is an extremely easy and cheap heuristic that does not necessitate complicated parsing, but which we can change in the future should that be necessary. This also avoids the problem where users try to turn the pseudo-URL into a real URL by just prepending `ssh://`, which causes an error message about the invalid port number due to the colon which they have not changed. Since they can just copy and paste the proposed answer, they'll be less likely to attempt this invalid approach. Fixes #13549 ### How should we test and review this PR? 1. `cargo init pkg1` 2. `cd pkg1` 3. Edit `Cargo.toml` to add the dependency line `bytes = { git = "[email protected]:tokio-rs/bytes.git", tag = "v1.10.0" }`. 4. Run `cargo build` 5. Notice that the error suggests a URL to try. 6. Replace the Git URL with the suggested URL. 7. Run `cargo build`. 8. Notice that the package compiles cleanly. ### Additional information N/A
2 parents 26f5f3f + 7cd8890 commit ce948f4

File tree

2 files changed

+15
-3
lines changed

2 files changed

+15
-3
lines changed

src/cargo/util/into_url.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,18 @@ pub trait IntoUrl {
1212

1313
impl<'a> IntoUrl for &'a str {
1414
fn into_url(self) -> CargoResult<Url> {
15-
Url::parse(self).map_err(|s| anyhow::format_err!("invalid url `{}`: {}", self, s))
15+
Url::parse(self).map_err(|s| {
16+
if self.starts_with("git@") {
17+
anyhow::format_err!(
18+
"invalid url `{}`: {}; try using `{}` instead",
19+
self,
20+
s,
21+
format_args!("ssh://{}", self.replacen(':', "/", 1))
22+
)
23+
} else {
24+
anyhow::format_err!("invalid url `{}`: {}", self, s)
25+
}
26+
})
1627
}
1728
}
1829

tests/testsuite/git.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ this is dep1 this is dep2
528528
#[cargo_test]
529529
fn cargo_compile_with_short_ssh_git() {
530530
let url = "[email protected]:a/dep";
531+
let well_formed_url = "ssh://[email protected]/a/dep";
531532

532533
let p = project()
533534
.file(
@@ -565,9 +566,9 @@ fn cargo_compile_with_short_ssh_git() {
565566
[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`
566567
567568
Caused by:
568-
invalid url `{}`: relative URL without a base
569+
invalid url `{}`: relative URL without a base; try using `{}` instead
569570
",
570-
url
571+
url, well_formed_url
571572
))
572573
.run();
573574
}

0 commit comments

Comments
 (0)