@@ -7,9 +7,9 @@ use std::{
7
7
} ;
8
8
9
9
use crate :: {
10
- file:: { loose, loose:: iter:: SortedLoosePaths , path_to_name } ,
10
+ file:: { loose, loose:: iter:: SortedLoosePaths } ,
11
11
store_impl:: { file, packed} ,
12
- BString , FullName , Namespace , Reference ,
12
+ BStr , FullName , Namespace , Reference ,
13
13
} ;
14
14
15
15
/// An iterator stepping through sorted input of loose references and packed references, preferring loose refs over otherwise
@@ -195,10 +195,9 @@ impl Platform<'_> {
195
195
self . store . iter_packed ( self . packed . as_ref ( ) . map ( |b| & * * * b) )
196
196
}
197
197
198
- /// As [`iter(…)`][file::Store::iter()], but filters by `prefix`, i.e. "refs/heads".
199
- ///
200
- /// Please note that "refs/heads" or "refs\\heads" is equivalent to "refs/heads/"
201
- pub fn prefixed ( & self , prefix : & Path ) -> std:: io:: Result < LooseThenPacked < ' _ , ' _ > > {
198
+ /// As [`iter(…)`][file::Store::iter()], but filters by `prefix`, i.e. "refs/heads/" or
199
+ /// "refs/heads/feature-".
200
+ pub fn prefixed ( & self , prefix : Cow < ' _ , BStr > ) -> std:: io:: Result < LooseThenPacked < ' _ , ' _ > > {
202
201
self . store
203
202
. iter_prefixed_packed ( prefix, self . packed . as_ref ( ) . map ( |b| & * * * b) )
204
203
}
@@ -242,22 +241,19 @@ pub(crate) enum IterInfo<'a> {
242
241
/// The top-level directory as boundary of all references, used to create their short-names after iteration
243
242
base : & ' a Path ,
244
243
/// The original prefix
245
- prefix : Cow < ' a , Path > ,
246
- /// The remainder of the prefix that wasn't a valid path
247
- remainder : Option < BString > ,
244
+ prefix : Cow < ' a , BStr > ,
248
245
/// If `true`, we will convert decomposed into precomposed unicode.
249
246
precompose_unicode : bool ,
250
247
} ,
251
248
}
252
249
253
250
impl < ' a > IterInfo < ' a > {
254
- fn prefix ( & self ) -> Option < & Path > {
251
+ fn prefix ( & self ) -> Option < Cow < ' _ , BStr > > {
255
252
match self {
256
253
IterInfo :: Base { .. } => None ,
257
- IterInfo :: PrefixAndBase { prefix, .. } => Some ( * prefix) ,
258
- IterInfo :: ComputedIterationRoot { prefix, .. } | IterInfo :: BaseAndIterRoot { prefix, .. } => {
259
- prefix. as_ref ( ) . into ( )
260
- }
254
+ IterInfo :: PrefixAndBase { prefix, .. } => Some ( gix_path:: into_bstr ( * prefix) ) ,
255
+ IterInfo :: BaseAndIterRoot { prefix, .. } => Some ( gix_path:: into_bstr ( prefix. clone ( ) ) ) ,
256
+ IterInfo :: ComputedIterationRoot { prefix, .. } => Some ( prefix. clone ( ) ) ,
261
257
}
262
258
}
263
259
@@ -281,48 +277,37 @@ impl<'a> IterInfo<'a> {
281
277
IterInfo :: ComputedIterationRoot {
282
278
iter_root,
283
279
base,
284
- prefix : _,
285
- remainder,
280
+ prefix,
286
281
precompose_unicode,
287
- } => SortedLoosePaths :: at ( & iter_root, base. into ( ) , remainder , precompose_unicode) ,
282
+ } => SortedLoosePaths :: at ( & iter_root, base. into ( ) , Some ( prefix . into_owned ( ) ) , precompose_unicode) ,
288
283
}
289
284
. peekable ( )
290
285
}
291
286
292
- fn from_prefix ( base : & ' a Path , prefix : Cow < ' a , Path > , precompose_unicode : bool ) -> std:: io:: Result < Self > {
293
- if prefix. is_absolute ( ) {
287
+ fn from_prefix ( base : & ' a Path , prefix : Cow < ' a , BStr > , precompose_unicode : bool ) -> std:: io:: Result < Self > {
288
+ let prefix_path = gix_path:: from_bstring ( prefix. as_ref ( ) ) ;
289
+ if prefix_path. is_absolute ( ) {
294
290
return Err ( std:: io:: Error :: new (
295
291
std:: io:: ErrorKind :: InvalidInput ,
296
- "prefix must be a relative path, like 'refs/heads'" ,
292
+ "prefix must be a relative path, like 'refs/heads/ '" ,
297
293
) ) ;
298
294
}
299
295
use std:: path:: Component :: * ;
300
- if prefix . components ( ) . any ( |c| matches ! ( c, CurDir | ParentDir ) ) {
296
+ if prefix_path . components ( ) . any ( |c| matches ! ( c, CurDir | ParentDir ) ) {
301
297
return Err ( std:: io:: Error :: new (
302
298
std:: io:: ErrorKind :: InvalidInput ,
303
299
"Refusing to handle prefixes with relative path components" ,
304
300
) ) ;
305
301
}
306
- let iter_root = base. join ( prefix . as_ref ( ) ) ;
307
- if iter_root . is_dir ( ) {
302
+ let iter_root = base. join ( & prefix_path ) ;
303
+ if prefix . ends_with ( b"/" ) {
308
304
Ok ( IterInfo :: BaseAndIterRoot {
309
305
base,
310
306
iter_root,
311
- prefix,
307
+ prefix : prefix_path . into ( ) ,
312
308
precompose_unicode,
313
309
} )
314
310
} else {
315
- let filename_prefix = iter_root
316
- . file_name ( )
317
- . map ( ToOwned :: to_owned)
318
- . map ( |p| {
319
- gix_path:: try_into_bstr ( PathBuf :: from ( p) )
320
- . map ( std:: borrow:: Cow :: into_owned)
321
- . map_err ( |_| {
322
- std:: io:: Error :: new ( std:: io:: ErrorKind :: InvalidInput , "prefix contains ill-formed UTF-8" )
323
- } )
324
- } )
325
- . transpose ( ) ?;
326
311
let iter_root = iter_root
327
312
. parent ( )
328
313
. expect ( "a parent is always there unless empty" )
@@ -331,7 +316,6 @@ impl<'a> IterInfo<'a> {
331
316
base,
332
317
prefix,
333
318
iter_root,
334
- remainder : filename_prefix,
335
319
precompose_unicode,
336
320
} )
337
321
}
@@ -374,30 +358,28 @@ impl file::Store {
374
358
}
375
359
}
376
360
377
- /// As [`iter(…)`][file::Store::iter()], but filters by `prefix`, i.e. "refs/heads".
378
- ///
379
- /// Please note that "refs/heads" or "refs\\heads" is equivalent to "refs/heads/"
361
+ /// As [`iter(…)`][file::Store::iter()], but filters by `prefix`, i.e. "refs/heads/" or
362
+ /// "refs/heads/feature-".
380
363
pub fn iter_prefixed_packed < ' s , ' p > (
381
364
& ' s self ,
382
- prefix : & Path ,
365
+ prefix : Cow < ' _ , BStr > ,
383
366
packed : Option < & ' p packed:: Buffer > ,
384
367
) -> std:: io:: Result < LooseThenPacked < ' p , ' s > > {
385
368
match self . namespace . as_ref ( ) {
386
369
None => {
387
- let git_dir_info = IterInfo :: from_prefix ( self . git_dir ( ) , prefix. into ( ) , self . precompose_unicode ) ?;
370
+ let git_dir_info = IterInfo :: from_prefix ( self . git_dir ( ) , prefix. clone ( ) , self . precompose_unicode ) ?;
388
371
let common_dir_info = self
389
372
. common_dir ( )
390
- . map ( |base| IterInfo :: from_prefix ( base, prefix. into ( ) , self . precompose_unicode ) )
373
+ . map ( |base| IterInfo :: from_prefix ( base, prefix, self . precompose_unicode ) )
391
374
. transpose ( ) ?;
392
375
self . iter_from_info ( git_dir_info, common_dir_info, packed)
393
376
}
394
377
Some ( namespace) => {
395
- let prefix = namespace. to_owned ( ) . into_namespaced_prefix ( prefix) ;
396
- let git_dir_info =
397
- IterInfo :: from_prefix ( self . git_dir ( ) , prefix. clone ( ) . into ( ) , self . precompose_unicode ) ?;
378
+ let prefix = namespace. to_owned ( ) . into_namespaced_prefix ( prefix. as_ref ( ) ) ;
379
+ let git_dir_info = IterInfo :: from_prefix ( self . git_dir ( ) , prefix. clone ( ) , self . precompose_unicode ) ?;
398
380
let common_dir_info = self
399
381
. common_dir ( )
400
- . map ( |base| IterInfo :: from_prefix ( base, prefix. into ( ) , self . precompose_unicode ) )
382
+ . map ( |base| IterInfo :: from_prefix ( base, prefix, self . precompose_unicode ) )
401
383
. transpose ( ) ?;
402
384
self . iter_from_info ( git_dir_info, common_dir_info, packed)
403
385
}
@@ -416,7 +398,7 @@ impl file::Store {
416
398
iter_packed : match packed {
417
399
Some ( packed) => Some (
418
400
match git_dir_info. prefix ( ) {
419
- Some ( prefix) => packed. iter_prefixed ( path_to_name ( prefix) . into_owned ( ) ) ,
401
+ Some ( prefix) => packed. iter_prefixed ( prefix. into_owned ( ) ) ,
420
402
None => packed. iter ( ) ,
421
403
}
422
404
. map_err ( |err| std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , err) ) ?
0 commit comments