Skip to content

Commit 29da97c

Browse files
committed
changed an api to use Task instead of async/await
1 parent fb29b40 commit 29da97c

File tree

2 files changed

+40
-14
lines changed

2 files changed

+40
-14
lines changed

Sources/Basics/TemporaryFile.swift

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,28 @@ import TSCLibc
2929
/// If `body` has a return value, that value is also used as the
3030
/// return value for the `withTemporaryDirectory` function.
3131
/// The cleanup block should be called when the temporary directory is no longer needed.
32-
///
32+
/// - Returns: `Task<Result, Error>` which can be used
3333
/// - Throws: `MakeDirectoryError` and rethrows all errors from `body`.
3434
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
3535
public func withTemporaryDirectory<Result>(
3636
dir: AbsolutePath? = nil,
3737
prefix: String = "TemporaryDirectory",
38-
_ body: (AbsolutePath, @escaping (AbsolutePath) -> Void) async throws -> Result
39-
) async throws -> Result {
38+
_ body: @escaping (AbsolutePath, @escaping (AbsolutePath) -> Void) async throws -> Result
39+
) throws -> Task<Result, Error> {
4040
let temporaryDirectory = try createTemporaryDirectory(dir: dir, prefix: prefix)
41-
return try await body(temporaryDirectory) { path in
42-
_ = try? FileManager.default.removeItem(atPath: path.pathString)
41+
42+
let task: Task<Result, Error> = Task {
43+
try await withTaskCancellationHandler {
44+
try await body(temporaryDirectory) { path in
45+
_ = try? FileManager.default.removeItem(atPath: path.pathString)
46+
}
47+
} onCancel: {
48+
_ = try? FileManager.default.removeItem(atPath: temporaryDirectory.pathString)
49+
}
50+
4351
}
52+
53+
return task
4454
}
4555

4656
/// Creates a temporary directory and evaluates a closure with the directory path as an argument.
@@ -63,10 +73,10 @@ public func withTemporaryDirectory<Result>(
6373
public func withTemporaryDirectory<Result>(
6474
dir: AbsolutePath? = nil,
6575
prefix: String = "TemporaryDirectory",
66-
removeTreeOnDeinit: Bool = false ,
67-
_ body: (AbsolutePath) async throws -> Result
68-
) async throws -> Result {
69-
try await withTemporaryDirectory(dir: dir, prefix: prefix) { path, cleanup in
76+
removeTreeOnDeinit: Bool = false,
77+
_ body: @escaping (AbsolutePath) async throws -> Result
78+
) throws -> Task<Result, Error> {
79+
try withTemporaryDirectory(dir: dir, prefix: prefix) { path, cleanup in
7080
defer { if removeTreeOnDeinit { cleanup(path) } }
7181
return try await body(path)
7282
}

Tests/BasicsTests/TemporaryFileTests.swift

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class TemporaryAsyncFileTests: XCTestCase {
2929

3030
XCTAssertTrue(localFileSystem.isDirectory(tempDirPath))
3131
return tempDirPath
32-
}
32+
}.value
3333
XCTAssertFalse(localFileSystem.isDirectory(path1))
3434

3535
// Test temp directory is not removed when its not empty.
@@ -45,7 +45,7 @@ class TemporaryAsyncFileTests: XCTestCase {
4545

4646
try localFileSystem.writeFileContents(filePath, bytes: ByteString())
4747
return tempDirPath
48-
}
48+
}.value
4949
XCTAssertTrue(localFileSystem.isDirectory(path2))
5050
// Cleanup.
5151
try FileManager.default.removeItem(atPath: path2.pathString)
@@ -63,7 +63,7 @@ class TemporaryAsyncFileTests: XCTestCase {
6363

6464
try localFileSystem.writeFileContents(filePath, bytes: ByteString())
6565
return tempDirPath
66-
}
66+
}.value
6767
XCTAssertFalse(localFileSystem.isDirectory(path3))
6868
}
6969

@@ -81,10 +81,26 @@ class TemporaryAsyncFileTests: XCTestCase {
8181
// Their paths should be different.
8282
XCTAssertTrue(pathOne != pathTwo)
8383
return pathTwo
84-
}
84+
}.value
8585
return (pathOne, pathTwo)
86-
}
86+
}.value
8787
XCTAssertFalse(localFileSystem.isDirectory(pathOne))
8888
XCTAssertFalse(localFileSystem.isDirectory(pathTwo))
8989
}
90+
91+
func testCancelOfTask() async throws {
92+
let task: Task<AbsolutePath, Error> = try withTemporaryDirectory { path in
93+
94+
try await Task.sleep(nanoseconds: 1_000_000_000)
95+
XCTAssertTrue(Task.isCancelled)
96+
XCTAssertFalse(localFileSystem.isDirectory(path))
97+
return path
98+
}
99+
task.cancel()
100+
do {
101+
// The correct path is to throw an error here
102+
let result = try await task.value
103+
XCTAssertFalse(localFileSystem.isDirectory(result))
104+
} catch {}
105+
}
90106
}

0 commit comments

Comments
 (0)