Skip to content

Commit 836fca8

Browse files
authored
Improve tmpdir management (#147)
- We now have a single tmpdir "root" that can be recreated at launch to clean up old stragglers - The location of this tmpdir root can be controlled by `XTL_TMPDIR` or `TMPDIR`. In general the path is `$TMPDIR/sh.xtool`. With this change it should be possible to `export XTL_TMPDIR=/var/tmp` if `/tmp` doesn't have enough space, which fixes #23.
1 parent 41f81b2 commit 836fca8

File tree

11 files changed

+141
-73
lines changed

11 files changed

+141
-73
lines changed

Package.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,14 @@ let package = Package(
9090
],
9191
exclude: ["openapi-generator-config.yaml", "patch.js"]
9292
),
93+
// common utilities shared across xtool targets
94+
.target(name: "XUtils"),
9395
.target(
9496
name: "XKit",
9597
dependencies: [
9698
"DeveloperAPI",
9799
"CXKit",
100+
"XUtils",
98101
.byName(name: "XADI", condition: .when(platforms: [.linux])),
99102
.product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"),
100103
.product(name: "Dependencies", package: "swift-dependencies"),
@@ -165,6 +168,7 @@ let package = Package(
165168
.target(
166169
name: "PackLib",
167170
dependencies: [
171+
"XUtils",
168172
.product(name: "Yams", package: "Yams"),
169173
.product(name: "XcodeGenKit", package: "XcodeGen", condition: .when(platforms: [.macOS])),
170174
]

Sources/PackLib/Foundation+Utils.swift

Lines changed: 0 additions & 56 deletions
This file was deleted.

Sources/PackLib/PackSchema.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Foundation
22
import Yams
3+
import XUtils
34

45
public struct PackSchemaBase: Codable, Sendable {
56
public enum Version: Int, Codable, Sendable {

Sources/PackLib/Packer.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Foundation
2+
import XUtils
23

34
public struct Packer: Sendable {
45
public let buildSettings: BuildSettings

Sources/PackLib/Planner.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Foundation
2+
import XUtils
23

34
public struct Planner: Sendable {
45
public var buildSettings: BuildSettings
@@ -213,7 +214,7 @@ public struct Planner: Sendable {
213214
}
214215

215216
private func dumpDependencies() async throws -> PackageDependency {
216-
let tempDir = try TemporaryDirectory(name: "xtool-dump-\(UUID().uuidString)")
217+
let tempDir = try TemporaryDirectory(name: "xtool-dump")
217218
let tempFileURL = tempDir.url.appendingPathComponent("dump.json")
218219

219220
// SwiftPM sometimes prints extraneous data to stdout, so ask

Sources/XKit/Integration/IntegratedInstaller.swift

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Foundation
22
import SwiftyMobileDevice
33
import ConcurrencyExtras
44
import Dependencies
5+
import XUtils
56

67
extension LockdownClient {
78
static let installerLabel = "xtool"
@@ -54,9 +55,6 @@ public actor IntegratedInstaller {
5455

5556
private var appInstaller: AppInstaller?
5657

57-
private let tempDir = FileManager.default.temporaryDirectoryShim
58-
.appendingPathComponent("sh.xtool.Staging")
59-
6058
private var stage: String?
6159

6260
private nonisolated let updateTask = LockIsolated<Task<Void, Never>?>(nil)
@@ -206,12 +204,9 @@ public actor IntegratedInstaller {
206204
public func install(app: URL) async throws -> String {
207205
try await self.updateStage(to: "Unpacking app", initialProgress: nil)
208206

209-
if FileManager.default.fileExists(atPath: tempDir.path) {
210-
try? FileManager.default.removeItem(at: tempDir)
211-
}
212-
213-
try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
214-
defer { try? FileManager.default.removeItem(at: tempDir) }
207+
let _tempDir = try TemporaryDirectory(name: "staging")
208+
let tempDir = _tempDir.url
209+
defer { withExtendedLifetime(_tempDir) {} }
215210

216211
switch app.pathExtension {
217212
case "ipa":
@@ -235,7 +230,7 @@ public actor IntegratedInstaller {
235230

236231
try await self.updateProgress(to: 1)
237232

238-
let payload = self.tempDir.appendingPathComponent("Payload")
233+
let payload = tempDir.appendingPathComponent("Payload")
239234
guard let appDir = payload.implicitContents.first(where: { $0.pathExtension == "app" })
240235
else { throw Error.appExtractionFailed }
241236

Sources/XToolSupport/DevCommand.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import ArgumentParser
33
import PackLib
44
import XKit
55
import Dependencies
6+
import XUtils
67

78
struct PackOperation {
89
struct BuildOptions: ParsableArguments {
@@ -136,12 +137,8 @@ struct DevBuildCommand: AsyncParsableCommand {
136137
if ipa {
137138
@Dependency(\.zipCompressor) var compressor
138139
finalURL = url.deletingPathExtension().appendingPathExtension("ipa")
139-
let tmpDir = try TemporaryDirectory(name: "sh.xtool.tmp")
140-
let payloadDir = tmpDir.url.appendingPathComponent("Payload", isDirectory: true)
141-
try FileManager.default.createDirectory(
142-
at: payloadDir,
143-
withIntermediateDirectories: true
144-
)
140+
let tmpDir = try TemporaryDirectory(name: "Payload")
141+
let payloadDir = tmpDir.url
145142
try FileManager.default.moveItem(at: url, to: payloadDir.appendingPathComponent(url.lastPathComponent))
146143
let ipaURL = try await compressor.compress(directory: payloadDir) { progress in
147144
if let progress {

Sources/XToolSupport/SDKCommand.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Version
44
import ArgumentParser
55
import Dependencies
66
import PackLib
7+
import XUtils
78

89
struct SDKCommand: AsyncParsableCommand {
910
static let configuration = CommandConfiguration(

Sources/XToolSupport/XTool.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import Foundation
22
import XKit
33
import ArgumentParser
4+
import XUtils
45

56
public enum XTool {
67
public static func run(arguments: [String]? = nil) async throws {
8+
TemporaryDirectory.prepare()
79
await XToolCommand.cancellableMain(arguments)
810
}
911
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Foundation
2+
3+
extension Data {
4+
// AsyncBytes is Darwin-only :/
5+
6+
package init(reading fileHandle: FileHandle) async throws {
7+
#if canImport(Darwin)
8+
self = try await fileHandle.bytes.reduce(into: Data()) { $0.append($1) }
9+
#else
10+
self = try fileHandle.readToEnd() ?? Data()
11+
#endif
12+
}
13+
14+
package init(reading file: URL) async throws {
15+
#if canImport(Darwin)
16+
self = try await file.resourceBytes.reduce(into: Data()) { $0.append($1) }
17+
#else
18+
try self.init(contentsOf: file)
19+
#endif
20+
}
21+
}
22+
23+
package func stderrPrint(_ message: String, terminator: String = "\n") {
24+
try? FileHandle.standardError.write(contentsOf: Data("\(message)\(terminator)".utf8))
25+
}

0 commit comments

Comments
 (0)