@@ -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) ?,
@@ -481,9 +448,14 @@ where
481448 let mut ssh_agent_attempts = Vec :: new ( ) ;
482449 let mut any_attempts = false ;
483450 let mut tried_sshkey = false ;
451+ let mut url_attempt = None ;
484452
453+ let orig_url = url;
485454 let mut res = f ( & mut |url, username, allowed| {
486455 any_attempts = true ;
456+ if url != orig_url {
457+ url_attempt = Some ( url. to_string ( ) ) ;
458+ }
487459 // libgit2's "USERNAME" authentication actually means that it's just
488460 // asking us for a username to keep going. This is currently only really
489461 // used for SSH authentication and isn't really an authentication type.
@@ -615,47 +587,83 @@ where
615587 }
616588 }
617589 }
618-
619- if res . is_ok ( ) || !any_attempts {
620- return res . map_err ( From :: from ) ;
621- }
590+ let mut err = match res {
591+ Ok ( e ) => return Ok ( e ) ,
592+ Err ( e ) => e ,
593+ } ;
622594
623595 // In the case of an authentication failure (where we tried something) then
624596 // we try to give a more helpful error message about precisely what we
625597 // tried.
626- let res = res . map_err ( anyhow :: Error :: from ) . chain_err ( || {
598+ if any_attempts {
627599 let mut msg = "failed to authenticate when downloading \
628600 repository"
629601 . to_string ( ) ;
602+
603+ if let Some ( attempt) = & url_attempt {
604+ if url != attempt {
605+ msg. push_str ( ": " ) ;
606+ msg. push_str ( attempt) ;
607+ }
608+ }
609+ msg. push_str ( "\n " ) ;
630610 if !ssh_agent_attempts. is_empty ( ) {
631611 let names = ssh_agent_attempts
632612 . iter ( )
633613 . map ( |s| format ! ( "`{}`" , s) )
634614 . collect :: < Vec < _ > > ( )
635615 . join ( ", " ) ;
636616 msg. push_str ( & format ! (
637- "\n attempted ssh-agent authentication, but \
638- none of the usernames {} succeeded ",
617+ "\n * attempted ssh-agent authentication, but \
618+ no usernames succeeded: {} ",
639619 names
640620 ) ) ;
641621 }
642622 if let Some ( failed_cred_helper) = cred_helper_bad {
643623 if failed_cred_helper {
644624 msg. push_str (
645- "\n attempted to find username/password via \
625+ "\n * attempted to find username/password via \
646626 git's `credential.helper` support, but failed",
647627 ) ;
648628 } else {
649629 msg. push_str (
650- "\n attempted to find username/password via \
630+ "\n * attempted to find username/password via \
651631 `credential.helper`, but maybe the found \
652632 credentials were incorrect",
653633 ) ;
654634 }
655635 }
656- msg
657- } ) ?;
658- Ok ( res)
636+ msg. push_str ( "\n \n " ) ;
637+ msg. push_str ( "if the git CLI succeeds then `net.git-fetch-with-cli` may help here\n " ) ;
638+ msg. push_str ( "https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli" ) ;
639+ err = err. context ( msg) ;
640+
641+ // Otherwise if we didn't even get to the authentication phase them we may
642+ // have failed to set up a connection, in these cases hint on the
643+ // `net.git-fetch-with-cli` configuration option.
644+ } else if let Some ( e) = err. downcast_ref :: < git2:: Error > ( ) {
645+ match e. class ( ) {
646+ ErrorClass :: Net
647+ | ErrorClass :: Ssl
648+ | ErrorClass :: Submodule
649+ | ErrorClass :: FetchHead
650+ | ErrorClass :: Ssh
651+ | ErrorClass :: Callback
652+ | ErrorClass :: Http => {
653+ let mut msg = "network failure seems to have happened\n " . to_string ( ) ;
654+ msg. push_str (
655+ "if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n " ,
656+ ) ;
657+ msg. push_str (
658+ "https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli" ,
659+ ) ;
660+ err = err. context ( msg) ;
661+ }
662+ _ => { }
663+ }
664+ }
665+
666+ Err ( err)
659667}
660668
661669fn reset ( repo : & git2:: Repository , obj : & git2:: Object < ' _ > , config : & Config ) -> CargoResult < ( ) > {
0 commit comments