Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions src/cargo/sources/git/oxide.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use tracing::debug;
pub fn with_retry_and_progress(
repo_path: &std::path::Path,
gctx: &GlobalContext,
repo_remote_url: &str,
cb: &(
dyn Fn(
&std::path::Path,
Expand Down Expand Up @@ -54,7 +55,7 @@ pub fn with_retry_and_progress(
*urls.borrow_mut() = Some(url.to_owned());
},
);
amend_authentication_hints(res, urls.get_mut().take())
amend_authentication_hints(res, repo_remote_url, urls.get_mut().take())
});
translate_progress_to_bar(&mut progress_bar, root, is_shallow)?;
thread.join().expect("no panic in scoped thread")
Expand Down Expand Up @@ -180,6 +181,7 @@ fn translate_progress_to_bar(

fn amend_authentication_hints(
res: Result<(), crate::sources::git::fetch::Error>,
remote_url: &str,
last_url_for_authentication: Option<gix::bstr::BString>,
) -> CargoResult<()> {
let Err(err) = res else { return Ok(()) };
Expand All @@ -189,6 +191,7 @@ fn amend_authentication_hints(
) => Some(err),
_ => None,
};

if let Some(e) = e {
let auth_message = match e {
gix::protocol::handshake::Error::Credentials(_) => {
Expand All @@ -203,10 +206,14 @@ fn amend_authentication_hints(
.into()
}
gix::protocol::handshake::Error::Transport(_) => {
let msg = concat!(
"network failure seems to have happened\n",
"if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n",
"https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli"
let msg = format!(
concat!(
"network failure seems to have happened\n",
"if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n",
"https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli",
"{}"
),
super::utils::note_github_pull_request(remote_url).unwrap_or_default()
);
return Err(anyhow::Error::from(err).context(msg));
}
Expand Down
42 changes: 36 additions & 6 deletions src/cargo/sources/git/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -798,12 +798,14 @@ where
| ErrorClass::FetchHead
| ErrorClass::Ssh
| ErrorClass::Http => {
let mut msg = "network failure seems to have happened\n".to_string();
msg.push_str(
"if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n",
);
msg.push_str(
"https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli",
let msg = format!(
concat!(
"network failure seems to have happened\n",
"if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n",
"https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli",
"{}"
),
note_github_pull_request(url).unwrap_or_default()
);
err = err.context(msg);
}
Expand Down Expand Up @@ -1142,6 +1144,7 @@ fn fetch_with_gitoxide(
let res = oxide::with_retry_and_progress(
git2_repo.path(),
gctx,
remote_url,
&|repo_path,
should_interrupt,
mut progress,
Expand Down Expand Up @@ -1589,6 +1592,33 @@ fn is_github(url: &Url) -> bool {
url.host_str() == Some("github.com")
}

// Give some messages on GitHub PR URL given as is
pub(crate) fn note_github_pull_request(url: &str) -> Option<String> {
if let Ok(url) = url.parse::<Url>()
&& is_github(&url)
{
let path_segments = url
.path_segments()
.map(|p| p.into_iter().collect::<Vec<_>>())
.unwrap_or_default();
if let [owner, repo, "pull", pr_number, ..] = path_segments[..] {
let repo_url = format!("https://github.com/{owner}/{repo}.git");
let rev = format!("refs/pull/{pr_number}/head");
return Some(format!(
concat!(
"\n\nnote: GitHub url {} is not a repository. \n",
"help: Replace the dependency with \n",
" `git = \"{}\" rev = \"{}\"` \n",
" to specify pull requests as dependencies' revision."
),
url, repo_url, rev
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: prefer inline arg like git = "{repo_url}"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, but format! does not capture variables when the format string is expanded from a macro (in this case, concat!). I'd prefer readability of concat! over iteration of push_string(format!(...)) s.

));
}
}

None
}

/// Whether a `rev` looks like a commit hash (ASCII hex digits).
fn looks_like_commit_hash(rev: &str) -> bool {
rev.len() >= 7 && rev.chars().all(|ch| ch.is_ascii_hexdigit())
Expand Down
41 changes: 41 additions & 0 deletions tests/testsuite/bad_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2259,6 +2259,47 @@ Caused by:
.run();
}

#[cargo_test(public_network_test)]
fn github_pull_request_url() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.0"
edition = "2015"
authors = []
[dependencies.bar]
git = "https://github.com/rust-lang/does-not-exist/pull/123"
"#,
)
.file("src/lib.rs", "")
.build();

p.cargo("check -v")
.with_status(101)
.with_stderr_data(str![[r#"
[UPDATING] git repository `https://github.com/rust-lang/does-not-exist/pull/123`
...
[ERROR] failed to get `bar` as a dependency of package `foo v0.0.0 ([ROOT]/foo)`
Caused by:
failed to load source for dependency `bar`
Caused by:
Unable to update https://github.com/rust-lang/does-not-exist/pull/123
...
[NOTE] GitHub url https://github.com/rust-lang/does-not-exist/pull/123 is not a repository.
[HELP] Replace the dependency with
`git = "https://github.com/rust-lang/does-not-exist.git" rev = "refs/pull/123/head"`
to specify pull requests as dependencies' revision.
...
"#]])
.run();
}

#[cargo_test]
fn fragment_in_git_url() {
let p = project()
Expand Down
57 changes: 57 additions & 0 deletions tests/testsuite/patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,63 @@ fn patch_to_git() {
.run();
}

#[cargo_test(public_network_test)]
fn patch_to_git_pull_request() {
Package::new("bar", "0.1.0").publish();

let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[dependencies]
bar = "0.1"
[patch.crates-io]
bar = { git = 'https://github.com/rust-lang/does-not-exist/pull/123' }
"#,
)
.file(
"src/lib.rs",
"extern crate bar; pub fn foo() { bar::bar(); }",
)
.build();

p.cargo("check -v")
.with_status(101)
.with_stderr_data(format!(
r#"[UPDATING] git repository `https://github.com/rust-lang/does-not-exist/pull/123`
...
[ERROR] failed to load source for dependency `bar`
Caused by:
Unable to update https://github.com/rust-lang/does-not-exist/pull/123
Caused by:
failed to clone into: [ROOT]/home/.cargo/git/db/123-[HASH]
Caused by:
network failure seems to have happened
if a proxy or similar is necessary `net.git-fetch-with-cli` may help here
https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli
[NOTE] GitHub url https://github.com/rust-lang/does-not-exist/pull/123 is not a repository.
[HELP] Replace the dependency with
`git = "https://github.com/rust-lang/does-not-exist.git" rev = "refs/pull/123/head"`
to specify pull requests as dependencies' revision.
Caused by:
...
"#
))
.run();
}

#[cargo_test]
fn unused() {
Package::new("bar", "0.1.0").publish();
Expand Down