@@ -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) ?,
@@ -473,9 +440,14 @@ where
473
440
let mut ssh_agent_attempts = Vec :: new ( ) ;
474
441
let mut any_attempts = false ;
475
442
let mut tried_sshkey = false ;
443
+ let mut url_attempt = None ;
476
444
445
+ let orig_url = url;
477
446
let mut res = f ( & mut |url, username, allowed| {
478
447
any_attempts = true ;
448
+ if url != orig_url {
449
+ url_attempt = Some ( url. to_string ( ) ) ;
450
+ }
479
451
// libgit2's "USERNAME" authentication actually means that it's just
480
452
// asking us for a username to keep going. This is currently only really
481
453
// used for SSH authentication and isn't really an authentication type.
@@ -607,47 +579,83 @@ where
607
579
}
608
580
}
609
581
}
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
+ } ;
614
586
615
587
// In the case of an authentication failure (where we tried something) then
616
588
// we try to give a more helpful error message about precisely what we
617
589
// tried.
618
- let res = res . map_err ( anyhow :: Error :: from ) . chain_err ( || {
590
+ if any_attempts {
619
591
let mut msg = "failed to authenticate when downloading \
620
592
repository"
621
593
. 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 " ) ;
622
602
if !ssh_agent_attempts. is_empty ( ) {
623
603
let names = ssh_agent_attempts
624
604
. iter ( )
625
605
. map ( |s| format ! ( "`{}`" , s) )
626
606
. collect :: < Vec < _ > > ( )
627
607
. join ( ", " ) ;
628
608
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: {} ",
631
611
names
632
612
) ) ;
633
613
}
634
614
if let Some ( failed_cred_helper) = cred_helper_bad {
635
615
if failed_cred_helper {
636
616
msg. push_str (
637
- "\n attempted to find username/password via \
617
+ "\n * attempted to find username/password via \
638
618
git's `credential.helper` support, but failed",
639
619
) ;
640
620
} else {
641
621
msg. push_str (
642
- "\n attempted to find username/password via \
622
+ "\n * attempted to find username/password via \
643
623
`credential.helper`, but maybe the found \
644
624
credentials were incorrect",
645
625
) ;
646
626
}
647
627
}
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)
651
659
}
652
660
653
661
fn reset ( repo : & git2:: Repository , obj : & git2:: Object < ' _ > , config : & Config ) -> CargoResult < ( ) > {
0 commit comments