@@ -10,7 +10,7 @@ use gix_object::bstr::ByteSlice;
10
10
use gix_path:: RelativePath ;
11
11
12
12
use crate :: {
13
- file:: { loose, loose :: iter:: SortedLoosePaths } ,
13
+ file:: loose:: { self , iter:: SortedLoosePaths } ,
14
14
store_impl:: { file, packed} ,
15
15
BStr , FullName , Namespace , Reference ,
16
16
} ;
@@ -85,36 +85,48 @@ impl<'p> LooseThenPacked<'p, '_> {
85
85
}
86
86
87
87
fn convert_loose ( & mut self , res : std:: io:: Result < ( PathBuf , FullName ) > ) -> Result < Reference , Error > {
88
- let ( refpath, name) = res. map_err ( Error :: Traversal ) ?;
89
- std:: fs:: File :: open ( & refpath)
90
- . and_then ( |mut f| {
91
- self . buf . clear ( ) ;
92
- f. read_to_end ( & mut self . buf )
93
- } )
94
- . map_err ( |err| Error :: ReadFileContents {
95
- source : err,
96
- path : refpath. to_owned ( ) ,
97
- } ) ?;
98
- loose:: Reference :: try_from_path ( name, & self . buf )
99
- . map_err ( |err| {
100
- let relative_path = refpath
101
- . strip_prefix ( self . git_dir )
102
- . ok ( )
103
- . or_else ( || {
104
- self . common_dir
105
- . and_then ( |common_dir| refpath. strip_prefix ( common_dir) . ok ( ) )
106
- } )
107
- . expect ( "one of our bases contains the path" ) ;
108
- Error :: ReferenceCreation {
109
- source : err,
110
- relative_path : relative_path. into ( ) ,
111
- }
112
- } )
113
- . map ( Into :: into)
114
- . map ( |r| self . strip_namespace ( r) )
88
+ convert_loose ( & mut self . buf , self . git_dir , self . common_dir , self . namespace , res)
115
89
}
116
90
}
117
91
92
+ pub ( crate ) fn convert_loose (
93
+ buf : & mut Vec < u8 > ,
94
+ git_dir : & Path ,
95
+ common_dir : Option < & Path > ,
96
+ namespace : Option < & Namespace > ,
97
+ res : std:: io:: Result < ( PathBuf , FullName ) > ,
98
+ ) -> Result < Reference , Error > {
99
+ let ( refpath, name) = res. map_err ( Error :: Traversal ) ?;
100
+ std:: fs:: File :: open ( & refpath)
101
+ . and_then ( |mut f| {
102
+ buf. clear ( ) ;
103
+ f. read_to_end ( buf)
104
+ } )
105
+ . map_err ( |err| Error :: ReadFileContents {
106
+ source : err,
107
+ path : refpath. to_owned ( ) ,
108
+ } ) ?;
109
+ loose:: Reference :: try_from_path ( name, buf)
110
+ . map_err ( |err| {
111
+ let relative_path = refpath
112
+ . strip_prefix ( git_dir)
113
+ . ok ( )
114
+ . or_else ( || common_dir. and_then ( |common_dir| refpath. strip_prefix ( common_dir) . ok ( ) ) )
115
+ . expect ( "one of our bases contains the path" ) ;
116
+ Error :: ReferenceCreation {
117
+ source : err,
118
+ relative_path : relative_path. into ( ) ,
119
+ }
120
+ } )
121
+ . map ( Into :: into)
122
+ . map ( |mut r : Reference | {
123
+ if let Some ( namespace) = namespace {
124
+ r. strip_namespace ( namespace) ;
125
+ }
126
+ r
127
+ } )
128
+ }
129
+
118
130
impl Iterator for LooseThenPacked < ' _ , ' _ > {
119
131
type Item = Result < Reference , Error > ;
120
132
@@ -210,6 +222,11 @@ impl Platform<'_> {
210
222
self . store
211
223
. iter_prefixed_packed ( prefix, self . packed . as_ref ( ) . map ( |b| & * * * b) )
212
224
}
225
+
226
+ /// Return an iterator over the pseudo references
227
+ pub fn psuedo_refs ( & self ) -> std:: io:: Result < LooseThenPacked < ' _ , ' _ > > {
228
+ self . store . iter_pseudo_refs ( )
229
+ }
213
230
}
214
231
215
232
impl file:: Store {
@@ -254,6 +271,10 @@ pub(crate) enum IterInfo<'a> {
254
271
/// If `true`, we will convert decomposed into precomposed unicode.
255
272
precompose_unicode : bool ,
256
273
} ,
274
+ PseudoRefs {
275
+ base : & ' a Path ,
276
+ precompose_unicode : bool ,
277
+ } ,
257
278
}
258
279
259
280
impl < ' a > IterInfo < ' a > {
@@ -263,6 +284,7 @@ impl<'a> IterInfo<'a> {
263
284
IterInfo :: PrefixAndBase { prefix, .. } => Some ( gix_path:: into_bstr ( * prefix) ) ,
264
285
IterInfo :: BaseAndIterRoot { prefix, .. } => Some ( gix_path:: into_bstr ( prefix. clone ( ) ) ) ,
265
286
IterInfo :: ComputedIterationRoot { prefix, .. } => Some ( prefix. clone ( ) ) ,
287
+ IterInfo :: PseudoRefs { .. } => None ,
266
288
}
267
289
}
268
290
@@ -271,24 +293,35 @@ impl<'a> IterInfo<'a> {
271
293
IterInfo :: Base {
272
294
base,
273
295
precompose_unicode,
274
- } => SortedLoosePaths :: at ( & base. join ( "refs" ) , base. into ( ) , None , precompose_unicode) ,
296
+ } => SortedLoosePaths :: at ( & base. join ( "refs" ) , base. into ( ) , None , None , false , precompose_unicode) ,
275
297
IterInfo :: BaseAndIterRoot {
276
298
base,
277
299
iter_root,
278
300
prefix : _,
279
301
precompose_unicode,
280
- } => SortedLoosePaths :: at ( & iter_root, base. into ( ) , None , precompose_unicode) ,
302
+ } => SortedLoosePaths :: at ( & iter_root, base. into ( ) , None , None , false , precompose_unicode) ,
281
303
IterInfo :: PrefixAndBase {
282
304
base,
283
305
prefix,
284
306
precompose_unicode,
285
- } => SortedLoosePaths :: at ( & base. join ( prefix) , base. into ( ) , None , precompose_unicode) ,
307
+ } => SortedLoosePaths :: at ( & base. join ( prefix) , base. into ( ) , None , None , false , precompose_unicode) ,
286
308
IterInfo :: ComputedIterationRoot {
287
309
iter_root,
288
310
base,
289
311
prefix,
290
312
precompose_unicode,
291
- } => SortedLoosePaths :: at ( & iter_root, base. into ( ) , Some ( prefix. into_owned ( ) ) , precompose_unicode) ,
313
+ } => SortedLoosePaths :: at (
314
+ & iter_root,
315
+ base. into ( ) ,
316
+ Some ( prefix. into_owned ( ) ) ,
317
+ None ,
318
+ false ,
319
+ precompose_unicode,
320
+ ) ,
321
+ IterInfo :: PseudoRefs {
322
+ base,
323
+ precompose_unicode,
324
+ } => SortedLoosePaths :: at ( base, base. into ( ) , None , Some ( "HEAD" . into ( ) ) , true , precompose_unicode) ,
292
325
}
293
326
. peekable ( )
294
327
}
@@ -354,6 +387,20 @@ impl file::Store {
354
387
}
355
388
}
356
389
390
+ /// Return an iterator over all pseudo references, loose or `packed`, sorted by their name.
391
+ ///
392
+ /// Errors are returned similarly to what would happen when loose and packed refs where iterated by themselves.
393
+ pub fn iter_pseudo_refs < ' p > ( & ' _ self ) -> std:: io:: Result < LooseThenPacked < ' p , ' _ > > {
394
+ self . iter_from_info (
395
+ IterInfo :: PseudoRefs {
396
+ base : self . git_dir ( ) ,
397
+ precompose_unicode : self . precompose_unicode ,
398
+ } ,
399
+ None ,
400
+ None ,
401
+ )
402
+ }
403
+
357
404
/// As [`iter(…)`](file::Store::iter()), but filters by `prefix`, i.e. `refs/heads/` or
358
405
/// `refs/heads/feature-`.
359
406
/// Note that if a prefix isn't using a trailing `/`, like in `refs/heads/foo`, it will effectively
0 commit comments