@@ -34,7 +34,7 @@ pub trait PathExt {
3434#[ cfg( target_family = "windows" ) ]
3535fn format_prefix ( prefix : & str ) -> Result < String > {
3636 match prefix {
37- "" => eyre :: bail! ( "Error: got empty windows prefix" ) ,
37+ "" => Ok ( "" . to_owned ( ) ) ,
3838 _ => Ok ( format ! ( "/mnt/{}" , prefix. to_lowercase( ) ) ) ,
3939 }
4040}
@@ -196,13 +196,28 @@ fn _canonicalize(path: &Path) -> Result<PathBuf> {
196196 }
197197}
198198
199+ fn is_wsl_absolute ( path : & str ) -> bool {
200+ if !cfg ! ( target_os = "windows" ) {
201+ return false ;
202+ }
203+ let path = path. strip_prefix ( "/mnt/" ) . unwrap_or ( path) ;
204+ let maybe_drive = path. split_once ( '/' ) . map_or ( path, |x| x. 0 ) ;
205+
206+ maybe_drive. len ( ) == 1 && matches ! ( maybe_drive. chars( ) . next( ) , Some ( 'a' ..='z' ) )
207+ }
208+
199209// Fix for issue #581. target_dir must be absolute.
200210pub fn absolute_path ( path : impl AsRef < Path > ) -> Result < PathBuf > {
201- Ok ( if path. as_ref ( ) . is_absolute ( ) {
202- path. as_ref ( ) . to_path_buf ( )
203- } else {
204- env:: current_dir ( ) ?. join ( path)
205- } )
211+ let as_ref = path. as_ref ( ) ;
212+ Ok (
213+ if as_ref. is_absolute ( )
214+ || cfg ! ( target_family = "windows" ) && is_wsl_absolute ( as_ref. to_utf8 ( ) ?)
215+ {
216+ as_ref. to_path_buf ( )
217+ } else {
218+ env:: current_dir ( ) ?. join ( path)
219+ } ,
220+ )
206221}
207222
208223/// Pretty format a file path. Also removes the path prefix from a command if wanted
@@ -319,9 +334,22 @@ mod tests {
319334 assert ! ( p!( "C:" ) . join( ".." ) . as_posix_relative( ) . is_err( ) ) ;
320335 }
321336
337+ #[ test]
338+ #[ cfg( target_family = "windows" ) ]
339+ fn is_absolute_wslpath ( ) {
340+ assert ! ( is_wsl_absolute( "/mnt/c/Users" ) ) ;
341+ assert ! ( is_wsl_absolute( "/mnt/c" ) ) ;
342+ assert ! ( is_wsl_absolute( "/mnt/z/Users" ) ) ;
343+ assert ! ( !is_wsl_absolute( "/mnt" ) ) ;
344+ assert ! ( !is_wsl_absolute( "/mnt/cc" ) ) ;
345+ assert ! ( !is_wsl_absolute( "/mnt/zc" ) ) ;
346+ }
347+
322348 #[ test]
323349 #[ cfg( target_family = "windows" ) ]
324350 fn as_posix_with_drive ( ) {
351+ use regex:: Regex ;
352+
325353 result_eq ( p ! ( r"C:\" ) . as_posix_absolute ( ) , Ok ( "/mnt/c" . to_owned ( ) ) ) ;
326354 result_eq (
327355 p ! ( r"C:\Users" ) . as_posix_absolute ( ) ,
@@ -336,6 +364,17 @@ mod tests {
336364 p ! ( r"\\.\C:\Users" ) . as_posix_absolute ( ) ,
337365 Ok ( "/mnt/c/Users" . to_owned ( ) ) ,
338366 ) ;
367+
368+ result_eq (
369+ p ! ( r"/mnt/c/Users" ) . as_posix_absolute ( ) ,
370+ Ok ( "/mnt/c/Users" . to_owned ( ) ) ,
371+ ) ;
372+ result_eq ( p ! ( r"/mnt/c" ) . as_posix_absolute ( ) , Ok ( "/mnt/c" . to_owned ( ) ) ) ;
373+
374+ let regex = Regex :: new ( "/mnt/[A-Za-z]/mnt" ) . unwrap ( ) ;
375+ let result = p ! ( r"/mnt" ) . as_posix_absolute ( ) ;
376+ assert ! ( result. is_ok( ) ) ;
377+ assert ! ( regex. is_match( & result. unwrap( ) ) ) ;
339378 }
340379
341380 #[ test]
0 commit comments