@@ -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,28 @@ 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+ var droppedTailing : Bool = false
530+ var substring = path [ path. startIndex..< path. endIndex]
531+ while substring. count > 1 && substring. utf8. last == UInt8 ( ascii: " \\ " ) {
532+ substring = substring. dropLast ( )
533+ droppedTailing = true
534+ }
535+ // Don't drop the trailing slash is we only have <drive>: left
536+ if hasDrive && substring. count == 2 && droppedTailing {
537+ self . string = Self . repr ( path) + " \\ "
538+ } else {
539+ self . string = Self . repr ( String ( substring) )
524540 }
525541 }
526542
@@ -544,7 +560,7 @@ private struct WindowsPath: Path, Sendable {
544560 self . init ( string: " . " )
545561 } else {
546562 let realpath : String = Self . repr ( path)
547- // Treat a relative path as an invalid relative path...
563+ // Treat an absolute path as an invalid relative path
548564 if Self . isAbsolutePath ( realpath) || realpath. first == " \\ " {
549565 throw PathValidationError . invalidRelativePath ( path)
550566 }
@@ -568,6 +584,7 @@ private struct WindowsPath: Path, Sendable {
568584 _ = string. withCString ( encodedAs: UTF16 . self) { root in
569585 name. withCString ( encodedAs: UTF16 . self) { path in
570586 PathAllocCombine ( root, path, ULONG ( PATHCCH_ALLOW_LONG_PATHS . rawValue) , & result)
587+ _ = PathCchStripPrefix ( result, wcslen ( result) )
571588 }
572589 }
573590 defer { LocalFree ( result) }
@@ -579,6 +596,7 @@ private struct WindowsPath: Path, Sendable {
579596 _ = string. withCString ( encodedAs: UTF16 . self) { root in
580597 relativePath. string. withCString ( encodedAs: UTF16 . self) { path in
581598 PathAllocCombine ( root, path, ULONG ( PATHCCH_ALLOW_LONG_PATHS . rawValue) , & result)
599+ _ = PathCchStripPrefix ( result, wcslen ( result) )
582600 }
583601 }
584602 defer { LocalFree ( result) }
@@ -965,8 +983,7 @@ extension AbsolutePath {
965983 preconditionFailure ( " invalid relative path computed from \( pathString) " )
966984 }
967985 }
968-
969- assert ( AbsolutePath ( base, result) == self )
986+ assert ( AbsolutePath ( base, result) == self , " \( AbsolutePath ( base, result) ) != \( self ) " )
970987 return result
971988 }
972989
0 commit comments