@@ -3,7 +3,7 @@ use crate::util::errors::{CargoResult, CargoResultExt};
3
3
use crate :: util:: paths;
4
4
use crate :: util:: process_builder:: process;
5
5
use crate :: util:: { network, Config , IntoUrl , Progress } ;
6
- use anyhow:: anyhow;
6
+ use anyhow:: { anyhow, Context } ;
7
7
use curl:: easy:: List ;
8
8
use git2:: { self , ErrorClass , ObjectType } ;
9
9
use log:: { debug, info} ;
@@ -85,46 +85,13 @@ impl GitRemote {
85
85
locked_rev : Option < git2:: Oid > ,
86
86
cargo_config : & Config ,
87
87
) -> 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
-
121
88
// If we have a previous instance of `GitDatabase` then fetch into that
122
89
// if we can. If that can successfully load our revision then we've
123
90
// populated the database with the latest version of `reference`, so
124
91
// return that database and the rev we resolve to.
125
92
if let Some ( mut db) = db {
126
93
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 ( ) ) ) ?;
128
95
match locked_rev {
129
96
Some ( rev) => {
130
97
if db. contains ( rev) {
@@ -148,7 +115,7 @@ impl GitRemote {
148
115
paths:: create_dir_all ( into) ?;
149
116
let mut repo = init ( into, true ) ?;
150
117
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 ( ) ) ) ?;
152
119
let rev = match locked_rev {
153
120
Some ( rev) => rev,
154
121
None => reference. resolve ( & repo) ?,
@@ -481,9 +448,14 @@ where
481
448
let mut ssh_agent_attempts = Vec :: new ( ) ;
482
449
let mut any_attempts = false ;
483
450
let mut tried_sshkey = false ;
451
+ let mut url_attempt = None ;
484
452
453
+ let orig_url = url;
485
454
let mut res = f ( & mut |url, username, allowed| {
486
455
any_attempts = true ;
456
+ if url != orig_url {
457
+ url_attempt = Some ( url. to_string ( ) ) ;
458
+ }
487
459
// libgit2's "USERNAME" authentication actually means that it's just
488
460
// asking us for a username to keep going. This is currently only really
489
461
// used for SSH authentication and isn't really an authentication type.
@@ -615,47 +587,83 @@ where
615
587
}
616
588
}
617
589
}
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
+ } ;
622
594
623
595
// In the case of an authentication failure (where we tried something) then
624
596
// we try to give a more helpful error message about precisely what we
625
597
// tried.
626
- let res = res . map_err ( anyhow :: Error :: from ) . chain_err ( || {
598
+ if any_attempts {
627
599
let mut msg = "failed to authenticate when downloading \
628
600
repository"
629
601
. 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 " ) ;
630
610
if !ssh_agent_attempts. is_empty ( ) {
631
611
let names = ssh_agent_attempts
632
612
. iter ( )
633
613
. map ( |s| format ! ( "`{}`" , s) )
634
614
. collect :: < Vec < _ > > ( )
635
615
. join ( ", " ) ;
636
616
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: {} ",
639
619
names
640
620
) ) ;
641
621
}
642
622
if let Some ( failed_cred_helper) = cred_helper_bad {
643
623
if failed_cred_helper {
644
624
msg. push_str (
645
- "\n attempted to find username/password via \
625
+ "\n * attempted to find username/password via \
646
626
git's `credential.helper` support, but failed",
647
627
) ;
648
628
} else {
649
629
msg. push_str (
650
- "\n attempted to find username/password via \
630
+ "\n * attempted to find username/password via \
651
631
`credential.helper`, but maybe the found \
652
632
credentials were incorrect",
653
633
) ;
654
634
}
655
635
}
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)
659
667
}
660
668
661
669
fn reset ( repo : & git2:: Repository , obj : & git2:: Object < ' _ > , config : & Config ) -> CargoResult < ( ) > {
0 commit comments