Skip to content

Commit 22c81c7

Browse files
committed
fix(git): convert SCP-like submodule URLs to ssh:// format
PR rust-lang#16246 introduced a regression where submodules using SCP-like URLs fail because `child_remote_url.into_url()` requires WHATWG-parsable URLs. This commit fixes the issue by detecting SCP-like URLs in `absolute_submodule_url()` and converting them to the equivalent `ssh://` format. Signed-off-by: Cibil Pankiras <cibil.pankiras@egym.com>
1 parent e26896f commit 22c81c7

2 files changed

Lines changed: 26 additions & 14 deletions

File tree

src/cargo/sources/git/utils.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -511,8 +511,9 @@ impl CheckoutGuard {
511511
/// (`git@github.com:rust-lang/cargo.git` is not a valid WHATWG URL)
512512
///
513513
/// To overcome these, this patch always tries [`Url::parse`] first to normalize
514-
/// the path. If it couldn't, append the relative path as the last resort and
515-
/// pray the remote git service supports non-normalized URLs.
514+
/// the path. If it couldn't, append the relative path and/or convert SCP-like URLs
515+
/// to ssh:// format as the last resorts and pray the remote git service supports
516+
/// non-normalized URLs.
516517
///
517518
/// See also rust-lang/cargo#12404 and rust-lang/cargo#12295.
518519
///
@@ -546,6 +547,15 @@ fn absolute_submodule_url<'s>(base_url: &str, submodule_url: &'s str) -> CargoRe
546547
Cow::from(submodule_url)
547548
};
548549

550+
let absolute_url = match gix::url::parse(gix::bstr::BStr::new(absolute_url.as_ref().as_bytes()))
551+
{
552+
Ok(mut url) if url.serialize_alternative_form && url.scheme == gix::url::Scheme::Ssh => {
553+
url.serialize_alternative_form = false;
554+
Cow::from(url.to_bstring().to_string())
555+
}
556+
_ => absolute_url,
557+
};
558+
549559
Ok(absolute_url)
550560
}
551561

@@ -1623,7 +1633,7 @@ mod tests {
16231633
(
16241634
"ssh://git@gitub.com/rust-lang/cargo",
16251635
"git@github.com:rust-lang/cargo.git",
1626-
"git@github.com:rust-lang/cargo.git",
1636+
"ssh://git@github.com/rust-lang/cargo.git",
16271637
),
16281638
(
16291639
"ssh://git@gitub.com/rust-lang/cargo",
@@ -1668,37 +1678,37 @@ mod tests {
16681678
(
16691679
"git@github.com:rust-lang/cargo.git",
16701680
"./",
1671-
"git@github.com:rust-lang/cargo.git/./",
1681+
"ssh://git@github.com/rust-lang/cargo.git/./",
16721682
),
16731683
(
16741684
"git@github.com:rust-lang/cargo.git",
16751685
"../",
1676-
"git@github.com:rust-lang/cargo.git/../",
1686+
"ssh://git@github.com/rust-lang/cargo.git/../",
16771687
),
16781688
(
16791689
"git@github.com:rust-lang/cargo.git",
16801690
"./foo",
1681-
"git@github.com:rust-lang/cargo.git/./foo",
1691+
"ssh://git@github.com/rust-lang/cargo.git/./foo",
16821692
),
16831693
(
16841694
"git@github.com:rust-lang/cargo.git/",
16851695
"./foo",
1686-
"git@github.com:rust-lang/cargo.git/./foo",
1696+
"ssh://git@github.com/rust-lang/cargo.git/./foo",
16871697
),
16881698
(
16891699
"git@github.com:rust-lang/cargo.git",
16901700
"../foo",
1691-
"git@github.com:rust-lang/cargo.git/../foo",
1701+
"ssh://git@github.com/rust-lang/cargo.git/../foo",
16921702
),
16931703
(
16941704
"git@github.com:rust-lang/cargo.git/",
16951705
"../foo",
1696-
"git@github.com:rust-lang/cargo.git/../foo",
1706+
"ssh://git@github.com/rust-lang/cargo.git/../foo",
16971707
),
16981708
(
16991709
"git@github.com:rust-lang/cargo.git",
17001710
"../foo/bar/../baz",
1701-
"git@github.com:rust-lang/cargo.git/../foo/bar/../baz",
1711+
"ssh://git@github.com/rust-lang/cargo.git/../foo/bar/../baz",
17021712
),
17031713
];
17041714

tests/testsuite/git.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4421,12 +4421,14 @@ fn dep_with_scp_like_submodule_url() {
44214421
.file("src/lib.rs", "extern crate dep1;")
44224422
.build();
44234423

4424-
// since Cargo can't parse SCP-like URL, it will fail earlier with invalid
4425-
// URL error before reaching the non-existing SSH server.
4424+
// With the SCP-like URL fix, Cargo converts `git@github.com:foo/bar.git`
4425+
// to `ssh://git@github.com/foo/bar.git` and tries to fetch, which fails
4426+
// with other errors like authentication failure or SSH server not reachable.
44264427
p.cargo("fetch")
44274428
.with_status(101)
44284429
.with_stderr_data(str![[r#"
44294430
[UPDATING] git repository `[ROOTURL]/dep1`
4431+
[UPDATING] git submodule `ssh://git@github.com/foo/bar.git`
44304432
[ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([ROOT]/foo)`
44314433
44324434
Caused by:
@@ -4439,8 +4441,8 @@ Caused by:
44394441
failed to update submodule `submod`
44404442
44414443
Caused by:
4442-
invalid url `git@github.com:foo/bar.git`: relative URL without a base; try using `ssh://git@github.com/foo/bar.git` instead
4443-
4444+
failed to fetch submodule `submod` from ssh://git@github.com/foo/bar.git
4445+
...
44444446
"#]])
44454447
.run();
44464448
}

0 commit comments

Comments
 (0)