1
1
use std:: ffi:: OsStr ;
2
2
use std:: fs:: { self , File , OpenOptions } ;
3
3
use std:: io:: { self , Read , Write } ;
4
- use std:: path:: { Component , Path , PathBuf } ;
4
+ use std:: path:: { Component , Path , PathBuf , Prefix } ;
5
5
use std:: process:: { Child , Command , Stdio } ;
6
6
use std:: time:: SystemTime ;
7
7
use std:: { env, mem} ;
@@ -263,6 +263,37 @@ pub fn path_to_str(path: &impl AsRef<Path>) -> Result<&str> {
263
263
path. to_str ( ) . with_context ( || format ! ( "invalid unicode in path: {}" , path. display( ) ) )
264
264
}
265
265
266
+ pub fn patch_path ( path : PathBuf ) -> PathBuf {
267
+ if cfg ! ( windows) {
268
+ fn patch_drive ( drive_letter : u8 ) -> char {
269
+ drive_letter. to_ascii_uppercase ( ) as char
270
+ }
271
+
272
+ let mut components = path. components ( ) ;
273
+ match components. next ( ) {
274
+ Some ( Component :: Prefix ( prefix) ) => {
275
+ let prefix = match prefix. kind ( ) {
276
+ Prefix :: Disk ( drive_letter) => {
277
+ format ! ( r"{}:" , patch_drive( drive_letter) )
278
+ }
279
+ Prefix :: VerbatimDisk ( drive_letter) => {
280
+ format ! ( r"\\?\{}:" , patch_drive( drive_letter) )
281
+ }
282
+ _ => return path,
283
+ } ;
284
+
285
+ let mut path = PathBuf :: default ( ) ;
286
+ path. push ( prefix) ;
287
+ path. extend ( components) ;
288
+ path
289
+ }
290
+ _ => path,
291
+ }
292
+ } else {
293
+ path
294
+ }
295
+ }
296
+
266
297
/// Returns the absolute version of a path. Like
267
298
/// [`std::path::Path::canonicalize`], but doesn't resolve symlinks.
268
299
pub fn resolve_path ( path : impl AsRef < Path > ) -> Result < PathBuf > {
@@ -274,8 +305,6 @@ pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
274
305
275
306
// initialize root
276
307
if cfg ! ( windows) {
277
- use std:: path:: Prefix ;
278
-
279
308
fn get_drive_letter ( path : impl AsRef < Path > ) -> Option < u8 > {
280
309
let path = path. as_ref ( ) ;
281
310
let mut components = path. components ( ) ;
@@ -292,7 +321,7 @@ pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
292
321
}
293
322
294
323
fn get_drive_path ( drive_letter : u8 ) -> PathBuf {
295
- format ! ( r"{}:\" , drive_letter as char ) . into ( )
324
+ format ! ( r"{}:\" , drive_letter. to_ascii_uppercase ( ) as char ) . into ( )
296
325
}
297
326
298
327
fn get_drive_relative ( drive_letter : u8 ) -> Result < PathBuf > {
@@ -312,23 +341,25 @@ pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
312
341
match components. peek ( ) {
313
342
Some ( Component :: Prefix ( prefix) ) => match prefix. kind ( ) {
314
343
Prefix :: Disk ( drive_letter) => {
315
- let disk = components. next ( ) . unwrap ( ) ;
344
+ components. next ( ) ;
316
345
if components. peek ( ) == Some ( & Component :: RootDir ) {
317
- let root = components. next ( ) . unwrap ( ) ;
318
- stack. push ( disk) ;
319
- stack. push ( root) ;
346
+ components. next ( ) ;
347
+ base_path = get_drive_path ( drive_letter) ;
320
348
} else {
321
349
base_path = get_drive_relative ( drive_letter) ?;
322
- stack. extend ( base_path. components ( ) ) ;
323
350
}
351
+
352
+ stack. extend ( base_path. components ( ) ) ;
324
353
}
325
354
Prefix :: VerbatimDisk ( drive_letter) => {
326
355
components. next ( ) ;
327
356
if components. peek ( ) == Some ( & Component :: RootDir ) {
328
357
components. next ( ) ;
358
+ base_path = get_drive_path ( drive_letter) ;
359
+ } else {
360
+ bail ! ( "illegal path: {}" , path. display( ) ) ;
329
361
}
330
362
331
- base_path = get_drive_path ( drive_letter) ;
332
363
stack. extend ( base_path. components ( ) ) ;
333
364
}
334
365
_ => bail ! ( "invalid path: {}" , path. display( ) ) ,
0 commit comments