@@ -12,7 +12,9 @@ pub enum Error {
12
12
#[ error( transparent) ]
13
13
Fetch ( #[ from] crate :: remote:: fetch:: Error ) ,
14
14
#[ error( transparent) ]
15
- RemoteConfiguration ( #[ from] crate :: remote:: init:: Error ) ,
15
+ RemoteInit ( #[ from] crate :: remote:: init:: Error ) ,
16
+ #[ error( "Custom configuration of remote to clone from failed" ) ]
17
+ RemoteConfiguration ( #[ source] Box < dyn std:: error:: Error + Send + Sync > ) ,
16
18
#[ error( "Default remote configured at `clone.defaultRemoteName` is invalid" ) ]
17
19
RemoteName ( #[ from] crate :: remote:: name:: Error ) ,
18
20
#[ error( "Failed to load repo-local git configuration before writing" ) ]
@@ -24,7 +26,7 @@ pub enum Error {
24
26
#[ error( "The remote HEAD points to a reference named {head_ref_name:?} which is invalid." ) ]
25
27
InvalidHeadRef {
26
28
source : git_validate:: refname:: Error ,
27
- head_ref_name : crate :: bstr :: BString ,
29
+ head_ref_name : BString ,
28
30
} ,
29
31
#[ error( "Failed to update HEAD with values from remote" ) ]
30
32
HeadUpdate ( #[ from] crate :: reference:: edit:: Error ) ,
@@ -51,6 +53,7 @@ impl PrepareFetch {
51
53
P : crate :: Progress ,
52
54
P :: SubProgress : ' static ,
53
55
{
56
+ use crate :: remote;
54
57
use crate :: { bstr:: ByteVec , remote:: fetch:: RefLogMessage } ;
55
58
56
59
let repo = self
@@ -64,36 +67,39 @@ impl PrepareFetch {
64
67
. config
65
68
. resolved
66
69
. string_by_key ( "clone.defaultRemoteName" )
67
- . map ( |n| crate :: remote:: name:: validated ( n. into_owned ( ) ) )
70
+ . map ( |n| remote:: name:: validated ( n. into_owned ( ) ) )
68
71
. unwrap_or_else ( || Ok ( "origin" . into ( ) ) ) ?,
69
72
} ;
70
73
71
74
let mut remote = repo
72
75
. remote_at ( self . url . clone ( ) ) ?
73
76
. with_refspecs (
74
77
Some ( format ! ( "+refs/heads/*:refs/remotes/{remote_name}/*" ) . as_str ( ) ) ,
75
- crate :: remote:: Direction :: Fetch ,
78
+ remote:: Direction :: Fetch ,
76
79
)
77
80
. expect ( "valid static spec" ) ;
78
81
if let Some ( f) = self . configure_remote . as_mut ( ) {
79
- remote = f ( remote) ?;
82
+ remote = f ( remote) . map_err ( |err| Error :: RemoteConfiguration ( err ) ) ?;
80
83
}
81
84
82
85
let config = util:: write_remote_to_local_config_file ( & mut remote, remote_name. clone ( ) ) ?;
83
86
84
87
// Add HEAD after the remote was written to config, we need it to know what to checkout later, and assure
85
88
// the ref that HEAD points to is present no matter what.
86
- remote. fetch_specs . push (
87
- git_refspec:: parse (
88
- format ! ( "HEAD:refs/remotes/{remote_name}/HEAD" ) . as_str ( ) . into ( ) ,
89
- git_refspec:: parse:: Operation :: Fetch ,
90
- )
91
- . expect ( "valid" )
92
- . to_owned ( ) ,
93
- ) ;
94
- let pending_pack: crate :: remote:: fetch:: Prepare < ' _ , ' _ , _ , _ > = remote
95
- . connect ( crate :: remote:: Direction :: Fetch , progress) ?
96
- . prepare_fetch ( self . fetch_options . clone ( ) ) ?;
89
+ let head_refspec = git_refspec:: parse (
90
+ format ! ( "HEAD:refs/remotes/{remote_name}/HEAD" ) . as_str ( ) . into ( ) ,
91
+ git_refspec:: parse:: Operation :: Fetch ,
92
+ )
93
+ . expect ( "valid" )
94
+ . to_owned ( ) ;
95
+ let pending_pack: remote:: fetch:: Prepare < ' _ , ' _ , _ , _ > =
96
+ remote. connect ( remote:: Direction :: Fetch , progress) ?. prepare_fetch ( {
97
+ let mut opts = self . fetch_options . clone ( ) ;
98
+ if !opts. extra_refspecs . contains ( & head_refspec) {
99
+ opts. extra_refspecs . push ( head_refspec)
100
+ }
101
+ opts
102
+ } ) ?;
97
103
if pending_pack. ref_map ( ) . object_hash != repo. object_hash ( ) {
98
104
unimplemented ! ( "configure repository to expect a different object hash as advertised by the server" )
99
105
}
@@ -148,10 +154,13 @@ impl PrepareFetch {
148
154
///
149
155
/// The passed in `remote` will be un-named and pre-configured to be a default remote as we know it from git-clone.
150
156
/// It is not yet present in the configuration of the repository,
151
- /// but each change it will eventually be written to the configuration prior to performing a the fetch operation.
157
+ /// but each change it will eventually be written to the configuration prior to performing a the fetch operation,
158
+ /// _all changes done in `f()` will be persisted_.
159
+ ///
160
+ /// It can also be used to configure additional options, like those for fetching tags.
152
161
pub fn configure_remote (
153
162
mut self ,
154
- f : impl FnMut ( crate :: Remote < ' _ > ) -> Result < crate :: Remote < ' _ > , crate :: remote :: init :: Error > + ' static ,
163
+ f : impl FnMut ( crate :: Remote < ' _ > ) -> Result < crate :: Remote < ' _ > , Box < dyn std :: error :: Error + Send + Sync > > + ' static ,
155
164
) -> Self {
156
165
self . configure_remote = Some ( Box :: new ( f) ) ;
157
166
self
0 commit comments