@@ -2022,24 +2022,28 @@ extension URL {
2022
2022
2023
2023
#if !NO_FILESYSTEM
2024
2024
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
2026
2029
var isDirectory : Bool = false
2027
2030
_ = FileManager . default. fileExists ( atPath: path, isDirectory: & isDirectory)
2028
2031
return isDirectory
2029
- #else
2032
+ #else
2030
2033
var isDirectory : ObjCBool = false
2031
2034
_ = FileManager . default. fileExists ( atPath: path, isDirectory: & isDirectory)
2032
2035
return isDirectory. boolValue
2033
- #endif
2036
+ #endif
2034
2037
}
2035
2038
#endif // !NO_FILESYSTEM
2036
2039
2037
2040
/// 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
2038
2042
internal static func isAbsolute( standardizing filePath: inout String ) -> Bool {
2039
2043
#if os(Windows)
2040
2044
var isAbsolute = false
2041
2045
let utf8 = filePath. utf8
2042
- if utf8. first == . _backslash {
2046
+ if utf8. first == . _slash {
2043
2047
// Either an absolute path or a UNC path
2044
2048
isAbsolute = true
2045
2049
} else if utf8. count >= 3 {
@@ -2052,18 +2056,18 @@ extension URL {
2052
2056
isAbsolute = (
2053
2057
first. isAlpha
2054
2058
&& ( second == . _colon || second == . _pipe)
2055
- && third == . _backslash
2059
+ && third == . _slash
2056
2060
)
2057
2061
2058
2062
if isAbsolute {
2059
- // Standardize to "\ [drive-letter]:\ ..."
2063
+ // Standardize to "/ [drive-letter]:/ ..."
2060
2064
if second == . _pipe {
2061
2065
var filePathArray = Array ( utf8)
2062
2066
filePathArray [ 1 ] = . _colon
2063
- filePathArray. insert ( . _backslash , at: 0 )
2067
+ filePathArray. insert ( . _slash , at: 0 )
2064
2068
filePath = String ( decoding: filePathArray, as: UTF8 . self)
2065
2069
} else {
2066
- filePath = " \\ " + filePath
2070
+ filePath = " / " + filePath
2067
2071
}
2068
2072
}
2069
2073
}
@@ -2107,10 +2111,9 @@ extension URL {
2107
2111
}
2108
2112
2109
2113
#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 )
2112
2116
#else
2113
- let slash = UInt8 ( ascii: " / " )
2114
2117
var filePath = path
2115
2118
#endif
2116
2119
@@ -2122,41 +2125,31 @@ extension URL {
2122
2125
}
2123
2126
#endif
2124
2127
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
-
2138
2128
let isDirectory : Bool
2139
2129
switch directoryHint {
2140
2130
case . isDirectory:
2141
2131
isDirectory = true
2142
2132
case . notDirectory:
2133
+ filePath = filePath. _droppingTrailingSlashes
2143
2134
isDirectory = false
2144
2135
case . checkFileSystem:
2145
2136
#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
+ }
2146
2144
isDirectory = URL . isDirectory ( absoluteFilePath ( ) )
2147
2145
#else
2148
- isDirectory = filePath. utf8. last == slash
2146
+ isDirectory = filePath. utf8. last == . _slash
2149
2147
#endif
2150
2148
case . inferFromPath:
2151
- isDirectory = filePath. utf8. last == slash
2149
+ isDirectory = filePath. utf8. last == . _slash
2152
2150
}
2153
2151
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 {
2160
2153
filePath += " / "
2161
2154
}
2162
2155
var components = URLComponents ( )
@@ -2434,6 +2427,9 @@ extension URL {
2434
2427
guard var filePath = path else {
2435
2428
return nil
2436
2429
}
2430
+ #if os(Windows)
2431
+ filePath = filePath. replacing ( . _backslash, with: . _slash)
2432
+ #endif
2437
2433
guard URL . isAbsolute ( standardizing: & filePath) else {
2438
2434
return nil
2439
2435
}
0 commit comments