@@ -10,7 +10,7 @@ use gix_object::bstr::ByteSlice;
1010use gix_path:: RelativePath ;
1111
1212use crate :: {
13- file:: { loose, loose :: iter:: SortedLoosePaths } ,
13+ file:: loose:: { self , iter:: SortedLoosePaths } ,
1414 store_impl:: { file, packed} ,
1515 BStr , FullName , Namespace , Reference ,
1616} ;
@@ -85,36 +85,48 @@ impl<'p> LooseThenPacked<'p, '_> {
8585 }
8686
8787 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)
11589 }
11690}
11791
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+
118130impl Iterator for LooseThenPacked < ' _ , ' _ > {
119131 type Item = Result < Reference , Error > ;
120132
@@ -210,6 +222,11 @@ impl Platform<'_> {
210222 self . store
211223 . iter_prefixed_packed ( prefix, self . packed . as_ref ( ) . map ( |b| & * * * b) )
212224 }
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+ }
213230}
214231
215232impl file:: Store {
@@ -254,6 +271,10 @@ pub(crate) enum IterInfo<'a> {
254271 /// If `true`, we will convert decomposed into precomposed unicode.
255272 precompose_unicode : bool ,
256273 } ,
274+ PseudoRefs {
275+ base : & ' a Path ,
276+ precompose_unicode : bool ,
277+ } ,
257278}
258279
259280impl < ' a > IterInfo < ' a > {
@@ -263,6 +284,7 @@ impl<'a> IterInfo<'a> {
263284 IterInfo :: PrefixAndBase { prefix, .. } => Some ( gix_path:: into_bstr ( * prefix) ) ,
264285 IterInfo :: BaseAndIterRoot { prefix, .. } => Some ( gix_path:: into_bstr ( prefix. clone ( ) ) ) ,
265286 IterInfo :: ComputedIterationRoot { prefix, .. } => Some ( prefix. clone ( ) ) ,
287+ IterInfo :: PseudoRefs { .. } => None ,
266288 }
267289 }
268290
@@ -271,24 +293,35 @@ impl<'a> IterInfo<'a> {
271293 IterInfo :: Base {
272294 base,
273295 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) ,
275297 IterInfo :: BaseAndIterRoot {
276298 base,
277299 iter_root,
278300 prefix : _,
279301 precompose_unicode,
280- } => SortedLoosePaths :: at ( & iter_root, base. into ( ) , None , precompose_unicode) ,
302+ } => SortedLoosePaths :: at ( & iter_root, base. into ( ) , None , None , false , precompose_unicode) ,
281303 IterInfo :: PrefixAndBase {
282304 base,
283305 prefix,
284306 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) ,
286308 IterInfo :: ComputedIterationRoot {
287309 iter_root,
288310 base,
289311 prefix,
290312 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) ,
292325 }
293326 . peekable ( )
294327 }
@@ -354,6 +387,20 @@ impl file::Store {
354387 }
355388 }
356389
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+
357404 /// As [`iter(…)`](file::Store::iter()), but filters by `prefix`, i.e. `refs/heads/` or
358405 /// `refs/heads/feature-`.
359406 /// Note that if a prefix isn't using a trailing `/`, like in `refs/heads/foo`, it will effectively
0 commit comments