@@ -2022,24 +2022,28 @@ extension URL {
20222022
20232023#if !NO_FILESYSTEM
20242024 private static func isDirectory( _ path: String ) -> Bool {
2025- #if !FOUNDATION_FRAMEWORK
2025+ #if os(Windows)
2026+ let path = path. replacing ( . _slash, with: . _backslash)
2027+ #endif
2028+ #if !FOUNDATION_FRAMEWORK
20262029 var isDirectory : Bool = false
20272030 _ = FileManager . default. fileExists ( atPath: path, isDirectory: & isDirectory)
20282031 return isDirectory
2029- #else
2032+ #else
20302033 var isDirectory : ObjCBool = false
20312034 _ = FileManager . default. fileExists ( atPath: path, isDirectory: & isDirectory)
20322035 return isDirectory. boolValue
2033- #endif
2036+ #endif
20342037 }
20352038#endif // !NO_FILESYSTEM
20362039
20372040 /// Checks if a file path is absolute and standardizes the inputted file path on Windows
2041+ /// Assumes the path only contains `/` as the path separator
20382042 internal static func isAbsolute( standardizing filePath: inout String ) -> Bool {
20392043 #if os(Windows)
20402044 var isAbsolute = false
20412045 let utf8 = filePath. utf8
2042- if utf8. first == . _backslash {
2046+ if utf8. first == . _slash {
20432047 // Either an absolute path or a UNC path
20442048 isAbsolute = true
20452049 } else if utf8. count >= 3 {
@@ -2052,18 +2056,18 @@ extension URL {
20522056 isAbsolute = (
20532057 first. isAlpha
20542058 && ( second == . _colon || second == . _pipe)
2055- && third == . _backslash
2059+ && third == . _slash
20562060 )
20572061
20582062 if isAbsolute {
2059- // Standardize to "\ [drive-letter]:\ ..."
2063+ // Standardize to "/ [drive-letter]:/ ..."
20602064 if second == . _pipe {
20612065 var filePathArray = Array ( utf8)
20622066 filePathArray [ 1 ] = . _colon
2063- filePathArray. insert ( . _backslash , at: 0 )
2067+ filePathArray. insert ( . _slash , at: 0 )
20642068 filePath = String ( decoding: filePathArray, as: UTF8 . self)
20652069 } else {
2066- filePath = " \\ " + filePath
2070+ filePath = " / " + filePath
20672071 }
20682072 }
20692073 }
@@ -2107,10 +2111,9 @@ extension URL {
21072111 }
21082112
21092113 #if os(Windows)
2110- let slash = UInt8 ( ascii : " \\ " )
2111- var filePath = path. replacing ( UInt8 ( ascii : " / " ) , with: slash )
2114+ // Convert any "\" to "/" before storing the URL parse info
2115+ var filePath = path. replacing ( . _backslash , with: . _slash )
21122116 #else
2113- let slash = UInt8 ( ascii: " / " )
21142117 var filePath = path
21152118 #endif
21162119
@@ -2122,41 +2125,31 @@ extension URL {
21222125 }
21232126 #endif
21242127
2125- func absoluteFilePath( ) -> String {
2126- guard !isAbsolute, let baseURL else {
2127- return filePath
2128- }
2129- let basePath = baseURL. path ( )
2130- #if os(Windows)
2131- let urlPath = filePath. replacing ( UInt8 ( ascii: " \\ " ) , with: UInt8 ( ascii: " / " ) )
2132- return URL . fileSystemPath ( for: basePath. merging ( relativePath: urlPath) ) . replacing ( UInt8 ( ascii: " / " ) , with: UInt8 ( ascii: " \\ " ) )
2133- #else
2134- return URL . fileSystemPath ( for: basePath. merging ( relativePath: filePath) )
2135- #endif
2136- }
2137-
21382128 let isDirectory : Bool
21392129 switch directoryHint {
21402130 case . isDirectory:
21412131 isDirectory = true
21422132 case . notDirectory:
2133+ filePath = filePath. _droppingTrailingSlashes
21432134 isDirectory = false
21442135 case . checkFileSystem:
21452136 #if !NO_FILESYSTEM
2137+ func absoluteFilePath( ) -> String {
2138+ guard !isAbsolute, let baseURL else {
2139+ return filePath
2140+ }
2141+ let absolutePath = baseURL. path ( ) . merging ( relativePath: filePath)
2142+ return URL . fileSystemPath ( for: absolutePath)
2143+ }
21462144 isDirectory = URL . isDirectory ( absoluteFilePath ( ) )
21472145 #else
2148- isDirectory = filePath. utf8. last == slash
2146+ isDirectory = filePath. utf8. last == . _slash
21492147 #endif
21502148 case . inferFromPath:
2151- isDirectory = filePath. utf8. last == slash
2149+ isDirectory = filePath. utf8. last == . _slash
21522150 }
21532151
2154- #if os(Windows)
2155- // Convert any "\" back to "/" before storing the URL parse info
2156- filePath = filePath. replacing ( UInt8 ( ascii: " \\ " ) , with: UInt8 ( ascii: " / " ) )
2157- #endif
2158-
2159- if !filePath. isEmpty && filePath. utf8. last != UInt8 ( ascii: " / " ) && isDirectory {
2152+ if isDirectory && !filePath. isEmpty && filePath. utf8. last != . _slash {
21602153 filePath += " / "
21612154 }
21622155 var components = URLComponents ( )
@@ -2434,6 +2427,9 @@ extension URL {
24342427 guard var filePath = path else {
24352428 return nil
24362429 }
2430+ #if os(Windows)
2431+ filePath = filePath. replacing ( . _backslash, with: . _slash)
2432+ #endif
24372433 guard URL . isAbsolute ( standardizing: & filePath) else {
24382434 return nil
24392435 }
0 commit comments