@@ -3,7 +3,7 @@ use crate::util::errors::{CargoResult, CargoResultExt};
33use crate :: util:: paths;
44use crate :: util:: process_builder:: process;
55use crate :: util:: { network, Config , IntoUrl , Progress } ;
6- use anyhow:: anyhow;
6+ use anyhow:: { anyhow, Context } ;
77use curl:: easy:: List ;
88use git2:: { self , ErrorClass , ObjectType } ;
99use log:: { debug, info} ;
@@ -85,46 +85,13 @@ impl GitRemote {
8585 locked_rev : Option < git2:: Oid > ,
8686 cargo_config : & Config ,
8787 ) -> CargoResult < ( GitDatabase , git2:: Oid ) > {
88- let format_error = |e : anyhow:: Error , operation| {
89- let may_be_libgit_fault = e
90- . chain ( )
91- . filter_map ( |e| e. downcast_ref :: < git2:: Error > ( ) )
92- . any ( |e| match e. class ( ) {
93- ErrorClass :: Net
94- | ErrorClass :: Ssl
95- | ErrorClass :: Submodule
96- | ErrorClass :: FetchHead
97- | ErrorClass :: Ssh
98- | ErrorClass :: Callback
99- | ErrorClass :: Http => true ,
100- _ => false ,
101- } ) ;
102- let uses_cli = cargo_config
103- . net_config ( )
104- . ok ( )
105- . and_then ( |config| config. git_fetch_with_cli )
106- . unwrap_or ( false ) ;
107- let msg = if !uses_cli && may_be_libgit_fault {
108- format ! (
109- r"failed to {} into: {}
110- If your environment requires git authentication or proxying, try enabling `git-fetch-with-cli`
111- https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli" ,
112- operation,
113- into. display( )
114- )
115- } else {
116- format ! ( "failed to {} into: {}" , operation, into. display( ) )
117- } ;
118- e. context ( msg)
119- } ;
120-
12188 // If we have a previous instance of `GitDatabase` then fetch into that
12289 // if we can. If that can successfully load our revision then we've
12390 // populated the database with the latest version of `reference`, so
12491 // return that database and the rev we resolve to.
12592 if let Some ( mut db) = db {
12693 fetch ( & mut db. repo , self . url . as_str ( ) , reference, cargo_config)
127- . map_err ( |e| format_error ( e , " fetch" ) ) ?;
94+ . context ( format ! ( "failed to fetch into: {}" , into . display ( ) ) ) ?;
12895 match locked_rev {
12996 Some ( rev) => {
13097 if db. contains ( rev) {
@@ -148,7 +115,7 @@ impl GitRemote {
148115 paths:: create_dir_all ( into) ?;
149116 let mut repo = init ( into, true ) ?;
150117 fetch ( & mut repo, self . url . as_str ( ) , reference, cargo_config)
151- . map_err ( |e| format_error ( e , " clone" ) ) ?;
118+ . context ( format ! ( "failed to clone into: {}" , into . display ( ) ) ) ?;
152119 let rev = match locked_rev {
153120 Some ( rev) => rev,
154121 None => reference. resolve ( & repo) ?,
@@ -473,9 +440,14 @@ where
473440 let mut ssh_agent_attempts = Vec :: new ( ) ;
474441 let mut any_attempts = false ;
475442 let mut tried_sshkey = false ;
443+ let mut url_attempt = None ;
476444
445+ let orig_url = url;
477446 let mut res = f ( & mut |url, username, allowed| {
478447 any_attempts = true ;
448+ if url != orig_url {
449+ url_attempt = Some ( url. to_string ( ) ) ;
450+ }
479451 // libgit2's "USERNAME" authentication actually means that it's just
480452 // asking us for a username to keep going. This is currently only really
481453 // used for SSH authentication and isn't really an authentication type.
@@ -607,47 +579,83 @@ where
607579 }
608580 }
609581 }
610-
611- if res . is_ok ( ) || !any_attempts {
612- return res . map_err ( From :: from ) ;
613- }
582+ let mut err = match res {
583+ Ok ( e ) => return Ok ( e ) ,
584+ Err ( e ) => e ,
585+ } ;
614586
615587 // In the case of an authentication failure (where we tried something) then
616588 // we try to give a more helpful error message about precisely what we
617589 // tried.
618- let res = res . map_err ( anyhow :: Error :: from ) . chain_err ( || {
590+ if any_attempts {
619591 let mut msg = "failed to authenticate when downloading \
620592 repository"
621593 . to_string ( ) ;
594+
595+ if let Some ( attempt) = & url_attempt {
596+ if url != attempt {
597+ msg. push_str ( ": " ) ;
598+ msg. push_str ( attempt) ;
599+ }
600+ }
601+ msg. push_str ( "\n " ) ;
622602 if !ssh_agent_attempts. is_empty ( ) {
623603 let names = ssh_agent_attempts
624604 . iter ( )
625605 . map ( |s| format ! ( "`{}`" , s) )
626606 . collect :: < Vec < _ > > ( )
627607 . join ( ", " ) ;
628608 msg. push_str ( & format ! (
629- "\n attempted ssh-agent authentication, but \
630- none of the usernames {} succeeded ",
609+ "\n * attempted ssh-agent authentication, but \
610+ no usernames succeeded: {} ",
631611 names
632612 ) ) ;
633613 }
634614 if let Some ( failed_cred_helper) = cred_helper_bad {
635615 if failed_cred_helper {
636616 msg. push_str (
637- "\n attempted to find username/password via \
617+ "\n * attempted to find username/password via \
638618 git's `credential.helper` support, but failed",
639619 ) ;
640620 } else {
641621 msg. push_str (
642- "\n attempted to find username/password via \
622+ "\n * attempted to find username/password via \
643623 `credential.helper`, but maybe the found \
644624 credentials were incorrect",
645625 ) ;
646626 }
647627 }
648- msg
649- } ) ?;
650- Ok ( res)
628+ msg. push_str ( "\n \n " ) ;
629+ msg. push_str ( "if the git CLI succeeds then `net.git-fetch-with-cli` may help here\n " ) ;
630+ msg. push_str ( "https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli" ) ;
631+ err = err. context ( msg) ;
632+
633+ // Otherwise if we didn't even get to the authentication phase them we may
634+ // have failed to set up a connection, in these cases hint on the
635+ // `net.git-fetch-with-cli` configuration option.
636+ } else if let Some ( e) = err. downcast_ref :: < git2:: Error > ( ) {
637+ match e. class ( ) {
638+ ErrorClass :: Net
639+ | ErrorClass :: Ssl
640+ | ErrorClass :: Submodule
641+ | ErrorClass :: FetchHead
642+ | ErrorClass :: Ssh
643+ | ErrorClass :: Callback
644+ | ErrorClass :: Http => {
645+ let mut msg = "network failure seems to have happened\n " . to_string ( ) ;
646+ msg. push_str (
647+ "if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n " ,
648+ ) ;
649+ msg. push_str (
650+ "https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli" ,
651+ ) ;
652+ err = err. context ( msg) ;
653+ }
654+ _ => { }
655+ }
656+ }
657+
658+ Err ( err)
651659}
652660
653661fn reset ( repo : & git2:: Repository , obj : & git2:: Object < ' _ > , config : & Config ) -> CargoResult < ( ) > {
0 commit comments