@@ -51,125 +51,8 @@ impl PrepareFetch {
51
51
P : crate :: Progress ,
52
52
P :: SubProgress : ' static ,
53
53
{
54
- use crate :: bstr:: { BStr , ByteVec } ;
54
+ use crate :: bstr:: ByteVec ;
55
55
use crate :: remote:: fetch:: RefLogMessage ;
56
- use git_ref:: transaction:: { LogChange , RefLog } ;
57
-
58
- fn write_remote_to_local_config_file (
59
- remote : & mut crate :: Remote < ' _ > ,
60
- remote_name : String ,
61
- ) -> Result < git_config:: File < ' static > , Error > {
62
- let mut metadata = git_config:: file:: Metadata :: from ( git_config:: Source :: Local ) ;
63
- let config_path = remote. repo . git_dir ( ) . join ( "config" ) ;
64
- metadata. path = Some ( config_path. clone ( ) ) ;
65
- let mut config =
66
- git_config:: File :: from_paths_metadata ( Some ( metadata) , Default :: default ( ) ) ?. expect ( "one file to load" ) ;
67
- remote. save_as_to ( remote_name, & mut config) ?;
68
- std:: fs:: write ( config_path, config. to_bstring ( ) ) ?;
69
- Ok ( config)
70
- }
71
-
72
- fn replace_changed_local_config_file ( repo : & mut Repository , mut config : git_config:: File < ' static > ) {
73
- let repo_config = git_features:: threading:: OwnShared :: make_mut ( & mut repo. config . resolved ) ;
74
- let ids_to_remove: Vec < _ > = repo_config
75
- . sections_and_ids ( )
76
- . filter_map ( |( s, id) | {
77
- matches ! ( s. meta( ) . source, git_config:: Source :: Local | git_config:: Source :: Api ) . then ( || id)
78
- } )
79
- . collect ( ) ;
80
- for id in ids_to_remove {
81
- repo_config. remove_section_by_id ( id) ;
82
- }
83
- crate :: config:: overrides:: apply ( & mut config, & repo. options . config_overrides , git_config:: Source :: Api )
84
- . expect ( "applied once and can be applied again" ) ;
85
- repo_config. append ( config) ;
86
- repo. reread_values_and_clear_caches ( )
87
- . expect ( "values could be read once and can be read again" ) ;
88
- }
89
-
90
- /// HEAD cannot be written by means of refspec by design, so we have to do it manually here. Also create the pointed-to ref
91
- /// if we have to, as it might not have been naturally included in the ref-specs.
92
- fn update_head (
93
- repo : & Repository ,
94
- remote_refs : & [ git_protocol:: fetch:: Ref ] ,
95
- reflog_message : & BStr ,
96
- ) -> Result < ( ) , Error > {
97
- use git_ref:: transaction:: { PreviousValue , RefEdit } ;
98
- use git_ref:: Target ;
99
- use std:: convert:: TryInto ;
100
- let ( head_peeled_id, head_ref) = match remote_refs. iter ( ) . find_map ( |r| match r {
101
- git_protocol:: fetch:: Ref :: Symbolic {
102
- full_ref_name,
103
- target,
104
- object,
105
- } if full_ref_name == "HEAD" => Some ( ( object, Some ( target) ) ) ,
106
- git_protocol:: fetch:: Ref :: Direct { full_ref_name, object } if full_ref_name == "HEAD" => {
107
- Some ( ( object, None ) )
108
- }
109
- _ => None ,
110
- } ) {
111
- Some ( t) => t,
112
- None => return Ok ( ( ) ) ,
113
- } ;
114
-
115
- let name: git_ref:: FullName = "HEAD" . try_into ( ) . expect ( "valid" ) ;
116
- let reflog_message = || LogChange {
117
- mode : RefLog :: AndReference ,
118
- force_create_reflog : false ,
119
- message : reflog_message. to_owned ( ) ,
120
- } ;
121
- match head_ref {
122
- Some ( referent) => {
123
- let referent: git_ref:: FullName = referent. try_into ( ) . map_err ( |err| Error :: InvalidHeadRef {
124
- head_ref_name : referent. to_owned ( ) ,
125
- source : err,
126
- } ) ?;
127
- repo. edit_references ( [
128
- RefEdit {
129
- change : git_ref:: transaction:: Change :: Update {
130
- log : reflog_message ( ) ,
131
- expected : PreviousValue :: Any ,
132
- new : Target :: Peeled ( head_peeled_id. to_owned ( ) ) ,
133
- } ,
134
- name : referent. clone ( ) ,
135
- deref : false ,
136
- } ,
137
- RefEdit {
138
- change : git_ref:: transaction:: Change :: Update {
139
- log : reflog_message ( ) ,
140
- expected : PreviousValue :: Any ,
141
- new : Target :: Symbolic ( referent) ,
142
- } ,
143
- name : name. clone ( ) ,
144
- deref : false ,
145
- } ,
146
- ] ) ?;
147
- let mut log = reflog_message ( ) ;
148
- log. mode = RefLog :: Only ;
149
- repo. edit_reference ( RefEdit {
150
- change : git_ref:: transaction:: Change :: Update {
151
- log,
152
- expected : PreviousValue :: Any ,
153
- new : Target :: Peeled ( head_peeled_id. to_owned ( ) ) ,
154
- } ,
155
- name,
156
- deref : false ,
157
- } ) ?;
158
- }
159
- None => {
160
- repo. edit_reference ( RefEdit {
161
- change : git_ref:: transaction:: Change :: Update {
162
- log : reflog_message ( ) ,
163
- expected : PreviousValue :: Any ,
164
- new : Target :: Peeled ( head_peeled_id. to_owned ( ) ) ,
165
- } ,
166
- name,
167
- deref : false ,
168
- } ) ?;
169
- }
170
- } ;
171
- Ok ( ( ) )
172
- }
173
56
174
57
let repo = self
175
58
. repo
@@ -197,7 +80,7 @@ impl PrepareFetch {
197
80
remote = f ( remote) ?;
198
81
}
199
82
200
- let config = write_remote_to_local_config_file ( & mut remote, remote_name. clone ( ) ) ?;
83
+ let config = util :: write_remote_to_local_config_file ( & mut remote, remote_name. clone ( ) ) ?;
201
84
202
85
// Add HEAD after the remote was written to config, we need it to know what to checkout later, and assure
203
86
// the ref that HEAD points to is present no matter what.
@@ -226,8 +109,8 @@ impl PrepareFetch {
226
109
} )
227
110
. receive ( should_interrupt) ?;
228
111
229
- replace_changed_local_config_file ( repo, config) ;
230
- update_head ( repo, & outcome. ref_map . remote_refs , reflog_message. as_ref ( ) ) ?;
112
+ util :: replace_changed_local_config_file ( repo, config) ;
113
+ util :: update_head ( repo, & outcome. ref_map . remote_refs , reflog_message. as_ref ( ) ) ?;
231
114
232
115
Ok ( ( self . repo . take ( ) . expect ( "still present" ) , outcome) )
233
116
}
@@ -300,3 +183,126 @@ impl From<PrepareFetch> for Repository {
300
183
prep. persist ( )
301
184
}
302
185
}
186
+
187
+ mod util {
188
+ use super :: Error ;
189
+ use crate :: bstr:: BStr ;
190
+ use crate :: Repository ;
191
+ use git_ref:: transaction:: { LogChange , RefLog } ;
192
+
193
+ pub fn write_remote_to_local_config_file (
194
+ remote : & mut crate :: Remote < ' _ > ,
195
+ remote_name : String ,
196
+ ) -> Result < git_config:: File < ' static > , Error > {
197
+ let mut metadata = git_config:: file:: Metadata :: from ( git_config:: Source :: Local ) ;
198
+ let config_path = remote. repo . git_dir ( ) . join ( "config" ) ;
199
+ metadata. path = Some ( config_path. clone ( ) ) ;
200
+ let mut config =
201
+ git_config:: File :: from_paths_metadata ( Some ( metadata) , Default :: default ( ) ) ?. expect ( "one file to load" ) ;
202
+ remote. save_as_to ( remote_name, & mut config) ?;
203
+ std:: fs:: write ( config_path, config. to_bstring ( ) ) ?;
204
+ Ok ( config)
205
+ }
206
+
207
+ pub fn replace_changed_local_config_file ( repo : & mut Repository , mut config : git_config:: File < ' static > ) {
208
+ let repo_config = git_features:: threading:: OwnShared :: make_mut ( & mut repo. config . resolved ) ;
209
+ let ids_to_remove: Vec < _ > = repo_config
210
+ . sections_and_ids ( )
211
+ . filter_map ( |( s, id) | {
212
+ matches ! ( s. meta( ) . source, git_config:: Source :: Local | git_config:: Source :: Api ) . then ( || id)
213
+ } )
214
+ . collect ( ) ;
215
+ for id in ids_to_remove {
216
+ repo_config. remove_section_by_id ( id) ;
217
+ }
218
+ crate :: config:: overrides:: apply ( & mut config, & repo. options . config_overrides , git_config:: Source :: Api )
219
+ . expect ( "applied once and can be applied again" ) ;
220
+ repo_config. append ( config) ;
221
+ repo. reread_values_and_clear_caches ( )
222
+ . expect ( "values could be read once and can be read again" ) ;
223
+ }
224
+
225
+ /// HEAD cannot be written by means of refspec by design, so we have to do it manually here. Also create the pointed-to ref
226
+ /// if we have to, as it might not have been naturally included in the ref-specs.
227
+ pub fn update_head (
228
+ repo : & Repository ,
229
+ remote_refs : & [ git_protocol:: fetch:: Ref ] ,
230
+ reflog_message : & BStr ,
231
+ ) -> Result < ( ) , Error > {
232
+ use git_ref:: transaction:: { PreviousValue , RefEdit } ;
233
+ use git_ref:: Target ;
234
+ use std:: convert:: TryInto ;
235
+ let ( head_peeled_id, head_ref) = match remote_refs. iter ( ) . find_map ( |r| match r {
236
+ git_protocol:: fetch:: Ref :: Symbolic {
237
+ full_ref_name,
238
+ target,
239
+ object,
240
+ } if full_ref_name == "HEAD" => Some ( ( object, Some ( target) ) ) ,
241
+ git_protocol:: fetch:: Ref :: Direct { full_ref_name, object } if full_ref_name == "HEAD" => {
242
+ Some ( ( object, None ) )
243
+ }
244
+ _ => None ,
245
+ } ) {
246
+ Some ( t) => t,
247
+ None => return Ok ( ( ) ) ,
248
+ } ;
249
+
250
+ let name: git_ref:: FullName = "HEAD" . try_into ( ) . expect ( "valid" ) ;
251
+ let reflog_message = || LogChange {
252
+ mode : RefLog :: AndReference ,
253
+ force_create_reflog : false ,
254
+ message : reflog_message. to_owned ( ) ,
255
+ } ;
256
+ match head_ref {
257
+ Some ( referent) => {
258
+ let referent: git_ref:: FullName = referent. try_into ( ) . map_err ( |err| Error :: InvalidHeadRef {
259
+ head_ref_name : referent. to_owned ( ) ,
260
+ source : err,
261
+ } ) ?;
262
+ repo. edit_references ( [
263
+ RefEdit {
264
+ change : git_ref:: transaction:: Change :: Update {
265
+ log : reflog_message ( ) ,
266
+ expected : PreviousValue :: Any ,
267
+ new : Target :: Peeled ( head_peeled_id. to_owned ( ) ) ,
268
+ } ,
269
+ name : referent. clone ( ) ,
270
+ deref : false ,
271
+ } ,
272
+ RefEdit {
273
+ change : git_ref:: transaction:: Change :: Update {
274
+ log : reflog_message ( ) ,
275
+ expected : PreviousValue :: Any ,
276
+ new : Target :: Symbolic ( referent) ,
277
+ } ,
278
+ name : name. clone ( ) ,
279
+ deref : false ,
280
+ } ,
281
+ ] ) ?;
282
+ let mut log = reflog_message ( ) ;
283
+ log. mode = RefLog :: Only ;
284
+ repo. edit_reference ( RefEdit {
285
+ change : git_ref:: transaction:: Change :: Update {
286
+ log,
287
+ expected : PreviousValue :: Any ,
288
+ new : Target :: Peeled ( head_peeled_id. to_owned ( ) ) ,
289
+ } ,
290
+ name,
291
+ deref : false ,
292
+ } ) ?;
293
+ }
294
+ None => {
295
+ repo. edit_reference ( RefEdit {
296
+ change : git_ref:: transaction:: Change :: Update {
297
+ log : reflog_message ( ) ,
298
+ expected : PreviousValue :: Any ,
299
+ new : Target :: Peeled ( head_peeled_id. to_owned ( ) ) ,
300
+ } ,
301
+ name,
302
+ deref : false ,
303
+ } ) ?;
304
+ }
305
+ } ;
306
+ Ok ( ( ) )
307
+ }
308
+ }
0 commit comments