Skip to content

Commit 893db8c

Browse files
committed
Auto merge of #8166 - kornelski:net-cli, r=alexcrichton
Hint git-fetch-with-cli on git errors Our team has struggled with making Cargo git dependencies work in CI, until learning about this setting. Cargo doesn't have a dedicated system for error hints like `rustc`, so I've stuffed the hint into the error message.
2 parents c7eddc1 + 4fd4835 commit 893db8c

File tree

2 files changed

+118
-3
lines changed

2 files changed

+118
-3
lines changed

src/cargo/sources/git/utils.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::util::paths;
44
use crate::util::process_builder::process;
55
use crate::util::{network, Config, IntoUrl, Progress};
66
use curl::easy::{Easy, List};
7-
use git2::{self, ObjectType};
7+
use git2::{self, ErrorClass, ObjectType};
88
use log::{debug, info};
99
use serde::ser;
1010
use serde::Serialize;
@@ -97,10 +97,43 @@ impl GitRemote {
9797
reference: &GitReference,
9898
cargo_config: &Config,
9999
) -> CargoResult<(GitDatabase, GitRevision)> {
100+
let format_error = |e: anyhow::Error, operation| {
101+
let may_be_libgit_fault = e
102+
.chain()
103+
.filter_map(|e| e.downcast_ref::<git2::Error>())
104+
.any(|e| match e.class() {
105+
ErrorClass::Net
106+
| ErrorClass::Ssl
107+
| ErrorClass::Submodule
108+
| ErrorClass::FetchHead
109+
| ErrorClass::Ssh
110+
| ErrorClass::Callback
111+
| ErrorClass::Http => true,
112+
_ => false,
113+
});
114+
let uses_cli = cargo_config
115+
.net_config()
116+
.ok()
117+
.and_then(|config| config.git_fetch_with_cli)
118+
.unwrap_or(false);
119+
let msg = if !uses_cli && may_be_libgit_fault {
120+
format!(
121+
r"failed to {} into: {}
122+
If your environment requires git authentication or proxying, try enabling `git-fetch-with-cli`
123+
https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli",
124+
operation,
125+
into.display()
126+
)
127+
} else {
128+
format!("failed to {} into: {}", operation, into.display())
129+
};
130+
e.context(msg)
131+
};
132+
100133
let mut repo_and_rev = None;
101134
if let Ok(mut repo) = git2::Repository::open(into) {
102135
self.fetch_into(&mut repo, cargo_config)
103-
.chain_err(|| format!("failed to fetch into {}", into.display()))?;
136+
.map_err(|e| format_error(e, "fetch"))?;
104137
if let Ok(rev) = reference.resolve(&repo) {
105138
repo_and_rev = Some((repo, rev));
106139
}
@@ -110,7 +143,7 @@ impl GitRemote {
110143
None => {
111144
let repo = self
112145
.clone_into(into, cargo_config)
113-
.chain_err(|| format!("failed to clone into: {}", into.display()))?;
146+
.map_err(|e| format_error(e, "clone"))?;
114147
let rev = reference.resolve(&repo)?;
115148
(repo, rev)
116149
}

tests/testsuite/git_auth.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,85 @@ Caused by:
265265
.run();
266266
t.join().ok().unwrap();
267267
}
268+
269+
#[cargo_test]
270+
fn net_err_suggests_fetch_with_cli() {
271+
let p = project()
272+
.file(
273+
"Cargo.toml",
274+
r#"
275+
[package]
276+
name = "foo"
277+
version = "0.0.0"
278+
authors = []
279+
280+
[dependencies]
281+
foo = { git = "ssh://needs-proxy.invalid/git" }
282+
"#,
283+
)
284+
.file("src/lib.rs", "")
285+
.build();
286+
287+
p.cargo("build -v")
288+
.with_status(101)
289+
.with_stderr(
290+
"\
291+
[UPDATING] git repository `ssh://needs-proxy.invalid/git`
292+
warning: spurious network error[..]
293+
warning: spurious network error[..]
294+
[ERROR] failed to get `foo` as a dependency of package `foo v0.0.0 [..]`
295+
296+
Caused by:
297+
failed to load source for dependency `foo`
298+
299+
Caused by:
300+
Unable to update ssh://needs-proxy.invalid/git
301+
302+
Caused by:
303+
failed to clone into: [..]
304+
If your environment requires git authentication or proxying, try enabling `git-fetch-with-cli`
305+
https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli
306+
307+
Caused by:
308+
failed to resolve address for needs-proxy.invalid[..]
309+
",
310+
)
311+
.run();
312+
313+
p.change_file(
314+
".cargo/config",
315+
"
316+
[net]
317+
git-fetch-with-cli = true
318+
",
319+
);
320+
321+
p.cargo("build -v")
322+
.with_status(101)
323+
.with_stderr(
324+
"\
325+
[UPDATING] git repository `ssh://needs-proxy.invalid/git`
326+
[RUNNING] `git fetch[..]
327+
[ERROR] failed to get `foo` as a dependency of package `foo v0.0.0 [..]`
328+
329+
Caused by:
330+
failed to load source for dependency `foo`
331+
332+
Caused by:
333+
Unable to update ssh://needs-proxy.invalid/git
334+
335+
Caused by:
336+
failed to fetch into: [..]
337+
338+
Caused by:
339+
[..]process didn't exit successfully[..]
340+
--- stderr
341+
ssh: Could not resolve hostname[..]
342+
fatal: [..]
343+
344+
Please make sure you have the correct access rights
345+
and the repository exists.
346+
[..]",
347+
)
348+
.run();
349+
}

0 commit comments

Comments
 (0)