@@ -289,6 +289,7 @@ quick_error! {
289
289
Utf8Conversion ( what: & ' static str , err: git_features:: path:: Utf8Error ) {
290
290
display( "Ill-formed UTF-8 in {}" , what)
291
291
context( what: & ' static str , err: git_features:: path:: Utf8Error ) -> ( what, err)
292
+ source( err)
292
293
}
293
294
UsernameConversion ( err: std:: str :: Utf8Error ) {
294
295
display( "Ill-formed UTF-8 in username" )
@@ -334,10 +335,10 @@ impl<'a> From<Cow<'a, [u8]>> for Path<'a> {
334
335
}
335
336
}
336
337
337
- impl Path < ' _ > {
338
- /// Interpolates path value
338
+ impl < ' a > Path < ' a > {
339
+ /// Interpolates this path into a file system path.
339
340
///
340
- /// Path value can be given a string that begins with `~/` or `~user/` or `%(prefix)/`
341
+ /// If this path starts with `~/` or `~user/` or `%(prefix)/`
341
342
/// - `~/` is expanded to the value of `$HOME` on unix based systems. On windows, `SHGetKnownFolderPath` is used.
342
343
/// See also [dirs](https://crates.io/crates/dirs).
343
344
/// - `~user/` to the specified user’s home directory, e.g `~alice` might get expanded to `/home/alice` on linux.
@@ -346,51 +347,50 @@ impl Path<'_> {
346
347
/// optionally provided by the caller through `git_install_dir`.
347
348
///
348
349
/// Any other, non-empty path value is returned unchanged and error is returned in case of an empty path value.
349
- pub fn interpolate ( self , git_install_dir : Option < & std:: path:: Path > ) -> Result < Self , PathError > {
350
+ pub fn interpolate ( self , git_install_dir : Option < & std:: path:: Path > ) -> Result < Cow < ' a , std :: path :: Path > , PathError > {
350
351
if self . is_empty ( ) {
351
352
return Err ( PathError :: Missing { what : "path" } ) ;
352
353
}
353
354
354
355
const PREFIX : & [ u8 ] = b"%(prefix)/" ;
355
- const SLASH : u8 = b'/' ;
356
356
if self . starts_with ( PREFIX ) {
357
357
let mut expanded = git_features:: path:: into_bytes ( git_install_dir. ok_or ( PathError :: Missing {
358
358
what : "git install dir" ,
359
359
} ) ?)
360
360
. context ( "git install dir" ) ?
361
361
. into_owned ( ) ;
362
- let ( _prefix, val) = self . split_at ( PREFIX . len ( ) - 1 ) ;
362
+ let ( _prefix, val) = self . split_at ( PREFIX . len ( ) - "/" . len ( ) ) ;
363
363
expanded. extend ( val) ;
364
- Ok ( Path {
365
- value : Cow :: Owned ( expanded) ,
366
- } )
364
+ Ok ( git_features :: path :: from_byte_vec ( expanded )
365
+ . context ( "prefix- expanded path" ) ?
366
+ . into ( ) )
367
367
} else if self . starts_with ( b"~/" ) {
368
368
let home_path = dirs:: home_dir ( ) . ok_or ( PathError :: Missing { what : "home dir" } ) ?;
369
369
let mut expanded = git_features:: path:: into_bytes ( home_path)
370
370
. context ( "home dir" ) ?
371
371
. into_owned ( ) ;
372
- let ( _prefix, val) = self . split_at ( SLASH . len ( ) ) ;
372
+ let ( _prefix, val) = self . split_at ( "~" . len ( ) ) ;
373
373
expanded. extend ( val) ;
374
374
let expanded = git_features:: path:: convert:: to_unix_separators ( expanded) ;
375
- Ok ( Path { value : expanded } )
376
- } else if self . starts_with ( b"~" ) && self . contains ( & SLASH ) {
377
- self . interpolate_user ( SLASH )
375
+ Ok ( git_features :: path :: from_bytes ( expanded ) . context ( "tilde expanded path" ) ? )
376
+ } else if self . starts_with ( b"~" ) && self . contains ( & b'/' ) {
377
+ self . interpolate_user ( )
378
378
} else {
379
- Ok ( self )
379
+ Ok ( git_features :: path :: from_bytes ( self . value ) . context ( "unexpanded path" ) ? )
380
380
}
381
381
}
382
382
383
383
#[ cfg( target_os = "windows" ) ]
384
- fn interpolate_user ( self , _slash : u8 ) -> Result < Self , PathError > {
384
+ fn interpolate_user ( self ) -> Result < Self , PathError > {
385
385
Err ( PathError :: UserInterpolationUnsupported )
386
386
}
387
387
388
388
#[ cfg( not( target_os = "windows" ) ) ]
389
- fn interpolate_user ( self , slash : u8 ) -> Result < Self , PathError > {
390
- let ( _prefix, val) = self . split_at ( slash . len ( ) ) ;
389
+ fn interpolate_user ( self ) -> Result < Cow < ' a , std :: path :: Path > , PathError > {
390
+ let ( _prefix, val) = self . split_at ( '/' . len ( ) ) ;
391
391
let i = val
392
392
. iter ( )
393
- . position ( |& e| e == slash )
393
+ . position ( |& e| e == b'/' )
394
394
. ok_or ( PathError :: Missing { what : "/" } ) ?;
395
395
let ( username, val) = val. split_at ( i) ;
396
396
let username = std:: str:: from_utf8 ( username) ?;
@@ -400,9 +400,9 @@ impl Path<'_> {
400
400
. dir ;
401
401
let mut expanded = home. as_bytes ( ) . to_owned ( ) ;
402
402
expanded. extend ( val) ;
403
- Ok ( Path {
404
- value : Cow :: Owned ( expanded) ,
405
- } )
403
+ Ok ( git_features :: path :: from_byte_vec ( expanded )
404
+ . context ( "tilded user expanded path" ) ?
405
+ . into ( ) )
406
406
}
407
407
}
408
408
@@ -1553,24 +1553,24 @@ mod path {
1553
1553
fn prefix_interpolated ( ) {
1554
1554
let val = Cow :: Borrowed ( & b"%(prefix)/foo/bar" [ ..] ) ;
1555
1555
let git_install_dir = "/tmp/git" ;
1556
- let expected = format ! ( "{}/foo/bar" , git_install_dir) ;
1556
+ let expected = & std :: path :: PathBuf :: from ( format ! ( "{}/foo/bar" , git_install_dir) ) ;
1557
1557
assert_eq ! (
1558
1558
& * Path :: from( val)
1559
1559
. interpolate( Some ( std:: path:: Path :: new( git_install_dir) ) )
1560
1560
. unwrap( ) ,
1561
- expected. as_bytes ( )
1561
+ expected
1562
1562
) ;
1563
1563
}
1564
1564
1565
1565
#[ test]
1566
1566
fn disabled_prefix_interpoldation ( ) {
1567
- let path = & b "./%(prefix)/foo/bar"[ .. ] ;
1567
+ let path = "./%(prefix)/foo/bar" ;
1568
1568
let git_install_dir = "/tmp/git" ;
1569
1569
assert_eq ! (
1570
- & * Path :: from( Cow :: Borrowed ( path) )
1570
+ & * Path :: from( Cow :: Borrowed ( path. as_bytes ( ) ) )
1571
1571
. interpolate( Some ( std:: path:: Path :: new( git_install_dir) ) )
1572
1572
. unwrap( ) ,
1573
- path
1573
+ std :: path:: Path :: new ( path )
1574
1574
) ;
1575
1575
}
1576
1576
@@ -1587,7 +1587,7 @@ mod path {
1587
1587
let expected = format ! ( "{}/foo/bar" , home) ;
1588
1588
assert_eq ! (
1589
1589
Path :: from( Cow :: Borrowed ( path) ) . interpolate( None ) . unwrap( ) . as_ref( ) ,
1590
- expected . as_bytes ( )
1590
+ std :: path :: Path :: new ( & expected )
1591
1591
) ;
1592
1592
}
1593
1593
@@ -1609,7 +1609,7 @@ mod path {
1609
1609
let expected = format ! ( "{}/foo/bar" , home) ;
1610
1610
assert_eq ! (
1611
1611
& * Path :: from( Cow :: Borrowed ( path. as_bytes( ) ) ) . interpolate( None ) . unwrap( ) ,
1612
- expected . as_bytes ( )
1612
+ std :: path :: Path :: new ( & expected )
1613
1613
) ;
1614
1614
}
1615
1615
}
0 commit comments