diff --git a/Package.swift b/Package.swift index 8ebc98ba..4c6e4ab2 100644 --- a/Package.swift +++ b/Package.swift @@ -18,6 +18,7 @@ let targets: [PackageDescription.Target] = [ dependencies: ["CSystem"], path: "Sources/System", swiftSettings: [ + .define("SYSTEM_PACKAGE"), .define("ENABLE_MOCKING", .when(configuration: .debug)) ]), .target( diff --git a/Sources/System/FilePath/FilePathComponentView.swift b/Sources/System/FilePath/FilePathComponentView.swift index 7b5394bb..5a4a8dc6 100644 --- a/Sources/System/FilePath/FilePathComponentView.swift +++ b/Sources/System/FilePath/FilePathComponentView.swift @@ -40,6 +40,30 @@ extension FilePath { } } + #if SYSTEM_PACKAGE + /// View the non-root components that make up this path. + public var components: ComponentView { + get { ComponentView(self) } + _modify { + // RRC's empty init means that we can't guarantee that the yielded + // view will restore our root. So copy it out first. + // + // TODO(perf): Small-form root (especially on Unix). Have Root + // always copy out (not worth ref counting). Make sure that we're + // not needlessly sliding values around or triggering a COW + let rootStr = self.root?._systemString ?? SystemString() + var comp = ComponentView(self) + self = FilePath() + defer { + self = comp._path + if root?._slice.elementsEqual(rootStr) != true { + self.root = Root(rootStr) + } + } + yield &comp + } + } + #else /// View the non-root components that make up this path. public var components: ComponentView { __consuming get { ComponentView(self) } @@ -62,6 +86,7 @@ extension FilePath { yield &comp } } + #endif } // @available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) diff --git a/Sources/System/FilePath/FilePathString.swift b/Sources/System/FilePath/FilePathString.swift index 842367c1..9f43a9c0 100644 --- a/Sources/System/FilePath/FilePathString.swift +++ b/Sources/System/FilePath/FilePathString.swift @@ -32,10 +32,15 @@ extension FilePath { /// The pointer passed as an argument to `body` is valid /// only during the execution of this method. /// Don't try to store the pointer for later use. + @_alwaysEmitIntoClient public func withPlatformString( _ body: (UnsafePointer) throws -> Result ) rethrows -> Result { - try _withPlatformString(body) + #if !os(Windows) + return try withCString(body) + #else + return try _withPlatformString(body) + #endif } } @@ -412,7 +417,7 @@ extension FilePath { #if os(Windows) fatalError("FilePath.withCString() unsupported on Windows ") #else - return try withPlatformString(body) + return try _withPlatformString(body) #endif } } diff --git a/Sources/System/Internals/Mocking.swift b/Sources/System/Internals/Mocking.swift index b1ca4856..4c74b6a4 100644 --- a/Sources/System/Internals/Mocking.swift +++ b/Sources/System/Internals/Mocking.swift @@ -146,13 +146,20 @@ private func originalSyscallName(_ function: String) -> String { private func mockImpl( name: String, + path: UnsafePointer?, _ args: [AnyHashable] ) -> CInt { + precondition(mockingEnabled) let origName = originalSyscallName(name) guard let driver = currentMockingDriver else { fatalError("Mocking requested from non-mocking context") } - driver.trace.add(Trace.Entry(name: origName, args)) + var mockArgs: Array = [] + if let p = path { + mockArgs.append(String(_errorCorrectingPlatformString: p)) + } + mockArgs.append(contentsOf: args) + driver.trace.add(Trace.Entry(name: origName, mockArgs)) switch driver.forceErrno { case .none: break @@ -170,21 +177,20 @@ private func mockImpl( } internal func _mock( - name: String = #function, _ args: AnyHashable... + name: String = #function, path: UnsafePointer? = nil, _ args: AnyHashable... ) -> CInt { - precondition(mockingEnabled) - return mockImpl(name: name, args) + return mockImpl(name: name, path: path, args) } internal func _mockInt( - name: String = #function, _ args: AnyHashable... + name: String = #function, path: UnsafePointer? = nil, _ args: AnyHashable... ) -> Int { - Int(mockImpl(name: name, args)) + Int(mockImpl(name: name, path: path, args)) } internal func _mockOffT( - name: String = #function, _ args: AnyHashable... + name: String = #function, path: UnsafePointer? = nil, _ args: AnyHashable... ) -> _COffT { - _COffT(mockImpl(name: name, args)) + _COffT(mockImpl(name: name, path: path, args)) } #endif // ENABLE_MOCKING diff --git a/Sources/System/Internals/Syscalls.swift b/Sources/System/Internals/Syscalls.swift index a755928e..ecfdc843 100644 --- a/Sources/System/Internals/Syscalls.swift +++ b/Sources/System/Internals/Syscalls.swift @@ -26,7 +26,7 @@ internal func system_open( ) -> CInt { #if ENABLE_MOCKING if mockingEnabled { - return _mock(String(_errorCorrectingPlatformString: path), oflag) + return _mock(path: path, oflag) } #endif return open(path, oflag) @@ -38,7 +38,7 @@ internal func system_open( ) -> CInt { #if ENABLE_MOCKING if mockingEnabled { - return _mock(String(_errorCorrectingPlatformString: path), oflag, mode) + return _mock(path: path, oflag, mode) } #endif return open(path, oflag, mode) diff --git a/Tests/SystemTests/XCTestManifests.swift b/Tests/SystemTests/XCTestManifests.swift index abbfe070..68eb9e82 100644 --- a/Tests/SystemTests/XCTestManifests.swift +++ b/Tests/SystemTests/XCTestManifests.swift @@ -17,6 +17,7 @@ extension FileDescriptorTest { // to regenerate. static let __allTests__FileDescriptorTest = [ ("testConstants", testConstants), + ("testStandardDescriptors", testStandardDescriptors), ] } @@ -26,6 +27,7 @@ extension FileOperationsTest { // to regenerate. static let __allTests__FileOperationsTest = [ ("testAdHocOpen", testAdHocOpen), + ("testGithubIssues", testGithubIssues), ("testHelpers", testHelpers), ("testSyscalls", testSyscalls), ] @@ -38,7 +40,6 @@ extension FilePathComponentsTest { static let __allTests__FilePathComponentsTest = [ ("testAdHocRRC", testAdHocRRC), ("testCases", testCases), - ("testConcatenation", testConcatenation), ("testSeparatorNormalization", testSeparatorNormalization), ] }