@@ -88,7 +88,7 @@ public struct AbsolutePath: Hashable, Sendable {
8888 }
8989 defer { LocalFree ( pwszResult) }
9090
91- self . init ( String ( decodingCString: pwszResult, as: UTF16 . self) )
91+ try self . init ( validating : String ( decodingCString: pwszResult, as: UTF16 . self) )
9292#else
9393 try self . init ( basePath, RelativePath ( validating: str) )
9494#endif
@@ -515,12 +515,27 @@ private struct WindowsPath: Path, Sendable {
515515 }
516516
517517 init ( string: String ) {
518- if string. first? . isASCII ?? false , string. first? . isLetter ?? false , string. first? . isLowercase ?? false ,
518+ let path : String
519+ let hasDrive : Bool
520+ if string. first? . isASCII ?? false , string. first? . isLetter ?? false ,
519521 string. count > 1 , string [ string. index ( string. startIndex, offsetBy: 1 ) ] == " : "
520522 {
521- self . string = " \( string. first!. uppercased ( ) ) \( string. dropFirst ( 1 ) ) "
523+ hasDrive = true
524+ path = " \( string. first!. uppercased ( ) ) \( string. dropFirst ( 1 ) ) "
522525 } else {
523- self . string = string
526+ hasDrive = false
527+ path = string
528+ }
529+ // There seems to be many assumptions around paths and trailing '\'
530+ var substring = path [ path. startIndex..< path. endIndex]
531+ while substring. count > 1 && substring. utf8. last == UInt8 ( ascii: " \\ " ) {
532+ substring = substring. dropLast ( )
533+ }
534+ // Don't use stripped substring is we only have <drive>: left
535+ if hasDrive && substring. count == 2 {
536+ self . string = Self . repr ( path)
537+ } else {
538+ self . string = Self . repr ( String ( substring) )
524539 }
525540 }
526541
@@ -544,7 +559,7 @@ private struct WindowsPath: Path, Sendable {
544559 self . init ( string: " . " )
545560 } else {
546561 let realpath : String = Self . repr ( path)
547- // Treat a relative path as an invalid relative path...
562+ // Treat an absolute path as an invalid relative path
548563 if Self . isAbsolutePath ( realpath) || realpath. first == " \\ " {
549564 throw PathValidationError . invalidRelativePath ( path)
550565 }
@@ -568,6 +583,7 @@ private struct WindowsPath: Path, Sendable {
568583 _ = string. withCString ( encodedAs: UTF16 . self) { root in
569584 name. withCString ( encodedAs: UTF16 . self) { path in
570585 PathAllocCombine ( root, path, ULONG ( PATHCCH_ALLOW_LONG_PATHS . rawValue) , & result)
586+ _ = PathCchStripPrefix ( result, wcslen ( result) )
571587 }
572588 }
573589 defer { LocalFree ( result) }
@@ -579,6 +595,7 @@ private struct WindowsPath: Path, Sendable {
579595 _ = string. withCString ( encodedAs: UTF16 . self) { root in
580596 relativePath. string. withCString ( encodedAs: UTF16 . self) { path in
581597 PathAllocCombine ( root, path, ULONG ( PATHCCH_ALLOW_LONG_PATHS . rawValue) , & result)
598+ _ = PathCchStripPrefix ( result, wcslen ( result) )
582599 }
583600 }
584601 defer { LocalFree ( result) }
@@ -965,8 +982,7 @@ extension AbsolutePath {
965982 preconditionFailure ( " invalid relative path computed from \( pathString) " )
966983 }
967984 }
968-
969- assert ( AbsolutePath ( base, result) == self )
985+ assert ( AbsolutePath ( base, result) == self , " \( AbsolutePath ( base, result) ) != \( self ) " )
970986 return result
971987 }
972988
0 commit comments