(140820778) Darwin SearchPaths without expanding tilde produce non-tilde-based paths (#1069)

This commit is contained in:
Jeremy Schonfeld 2024-12-04 12:52:55 -08:00 committed by GitHub
parent 4f6c892548
commit db104087d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 32 deletions

View File

@ -57,41 +57,11 @@ extension FileManager.SearchPathDomainMask {
} }
} }
#if FOUNDATION_FRAMEWORK
@_cdecl("_NSSearchPathsForDirectoryInDomain")
func _NSSearchPaths(for directory: FileManager.SearchPathDirectory, in domain: FileManager.SearchPathDomainMask, expandTilde: Bool) -> [String] {
_SearchPathURLs(for: directory, in: domain, expandTilde: expandTilde).map(\.path)
}
#endif
func _SearchPathURLs(for directory: FileManager.SearchPathDirectory, in domain: FileManager.SearchPathDomainMask, expandTilde: Bool) -> some Sequence<URL> { func _SearchPathURLs(for directory: FileManager.SearchPathDirectory, in domain: FileManager.SearchPathDomainMask, expandTilde: Bool) -> some Sequence<URL> {
#if canImport(Darwin) #if canImport(Darwin)
let basic = _DarwinSearchPathsSequence(directory: directory, domainMask: domain.intersection(.valid)).lazy.map { _DarwinSearchPaths(for: directory, in: domain, expandTilde: expandTilde).map {
if expandTilde { URL(filePath: $0, directoryHint: .isDirectory)
return URL(filePath: $0.expandingTildeInPath, directoryHint: .isDirectory)
} else {
return URL(filePath: $0, directoryHint: .isDirectory)
}
} }
#if os(macOS) && FOUNDATION_FRAMEWORK
// NSSharedUserDomainMask is basically just a wrapper around NSUserDomainMask.
let compatibleSharedUserDomainMask = domain != .allDomainsMask && (domain.rawValue & 16) != 0
if domain.contains(._sharedUserDomainMask) || compatibleSharedUserDomainMask {
var result = Array(basic)
for path in _DarwinSearchPathsSequence(directory: directory, domainMask: .userDomainMask) {
let expandedURL = URL(filePath: expandTilde ? path.replacingTildeWithRealHomeDirectory : path, directoryHint: .isDirectory)
// Avoid duplicates, which would occur with (NSUserDomainMask | NSSharedUserDomainMask) in non-sandboxed apps.
if !result.contains(expandedURL) {
// Insert this path after NSUserDomainMask and before any of the more general paths.
let insertionIndex = domain.contains(.userDomainMask) ? 1 : 0
result.insert(expandedURL, at: insertionIndex)
}
}
return result
}
#endif
return Array(basic)
#else #else
var result = Set<URL>() var result = Set<URL>()
var domain = domain.intersection(.valid) var domain = domain.intersection(.valid)
@ -109,3 +79,37 @@ func _SearchPathURLs(for directory: FileManager.SearchPathDirectory, in domain:
return result return result
#endif #endif
} }
#if canImport(Darwin)
#if FOUNDATION_FRAMEWORK
@_cdecl("_NSSearchPathsForDirectoryInDomain")
#endif
func _DarwinSearchPaths(for directory: FileManager.SearchPathDirectory, in domain: FileManager.SearchPathDomainMask, expandTilde: Bool) -> [String] {
let basic = _DarwinSearchPathsSequence(directory: directory, domainMask: domain.intersection(.valid)).lazy.map {
if expandTilde {
$0.expandingTildeInPath
} else {
$0
}
}
#if os(macOS) && FOUNDATION_FRAMEWORK
// NSSharedUserDomainMask is basically just a wrapper around NSUserDomainMask.
let compatibleSharedUserDomainMask = domain != .allDomainsMask && (domain.rawValue & 16) != 0
if domain.contains(._sharedUserDomainMask) || compatibleSharedUserDomainMask {
var result = Array(basic)
for path in _DarwinSearchPathsSequence(directory: directory, domainMask: .userDomainMask) {
let expandedPath = expandTilde ? path.replacingTildeWithRealHomeDirectory : path
// Avoid duplicates, which would occur with (NSUserDomainMask | NSSharedUserDomainMask) in non-sandboxed apps.
if !result.contains(expandedPath) {
// Insert this path after NSUserDomainMask and before any of the more general paths.
let insertionIndex = domain.contains(.userDomainMask) ? 1 : 0
result.insert(expandedPath, at: insertionIndex)
}
}
return result
}
#endif
return Array(basic)
}
#endif

View File

@ -1049,6 +1049,16 @@ final class FileManagerTests : XCTestCase {
XCTAssertEqual(FileManager.default.homeDirectory(forUser: UUID().uuidString), fallbackPath) XCTAssertEqual(FileManager.default.homeDirectory(forUser: UUID().uuidString), fallbackPath)
#endif #endif
} }
func testSearchPathsWithoutExpandingTilde() throws {
#if !canImport(Darwin)
throw XCTSkip("This test is not applicable for this platform")
#else
for path in _DarwinSearchPaths(for: .libraryDirectory, in: .userDomainMask, expandTilde: false) {
XCTAssertTrue(path.starts(with: "~/"), "Path '\(path)' did not start with ~/ as expected")
}
#endif
}
func testWindowsDirectoryCreationCrash() throws { func testWindowsDirectoryCreationCrash() throws {
try FileManagerPlayground { try FileManagerPlayground {