Skip to content

Commit ce61e27

Browse files
committed
explicitly marked Sendable
1 parent 8bbfdba commit ce61e27

5 files changed

Lines changed: 61 additions & 59 deletions

File tree

Sources/quickpkg/ArchiveExtractor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22

3-
struct ArchiveExtractor {
3+
struct ArchiveExtractor: Sendable {
44
let executor: ShellExecutor
55
let logger: Logger
66

Sources/quickpkg/PackageBuilder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22

3-
struct PackageBuilder {
3+
struct PackageBuilder: Sendable {
44
let executor: ShellExecutor
55
let logger: Logger
66

Sources/quickpkg/PlistHandler.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22

3-
struct PlistHandler {
3+
struct PlistHandler: Sendable {
44
/// Extract the first plist from mixed output (like hdiutil which returns text + plist)
55
static func extractFirstPlist(from data: Data) throws -> Data {
66
guard let string = String(data: data, encoding: .utf8) else {

Sources/quickpkg/QuickPkg.swift

Lines changed: 58 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -107,69 +107,68 @@ struct QuickPkg: AsyncParsableCommand {
107107
let dmgManager = DMGManager(executor: executor, logger: logger)
108108
let archiveExtractor = ArchiveExtractor(executor: executor, logger: logger)
109109

110-
// Clean up mounted DMGs when done
111-
defer {
112-
if clean {
113-
Task {
114-
await dmgManager.detachAll()
115-
}
116-
}
117-
}
110+
// Capture clean flag for use in async cleanup
111+
let shouldClean = clean
118112

119113
// Find the application
120114
let appURL: URL
121-
switch inputType {
122-
case .app:
123-
guard FileManager.default.fileExists(atPath: path) else {
124-
throw QuickPkgError.fileNotFound(path)
125-
}
126-
appURL = url
115+
do {
116+
switch inputType {
117+
case .app:
118+
guard FileManager.default.fileExists(atPath: path) else {
119+
throw QuickPkgError.fileNotFound(path)
120+
}
121+
appURL = url
127122

128-
case .dmg:
129-
guard FileManager.default.fileExists(atPath: path) else {
130-
throw QuickPkgError.fileNotFound(path)
131-
}
132-
let mountPoints = try await dmgManager.attach(url)
133-
let apps = findApplications(in: mountPoints)
134-
guard !apps.isEmpty else {
135-
throw QuickPkgError.noApplicationFound
136-
}
137-
guard apps.count == 1 else {
138-
throw QuickPkgError.multipleApplicationsFound(apps.map(\.path))
139-
}
140-
appURL = apps[0]
123+
case .dmg:
124+
guard FileManager.default.fileExists(atPath: path) else {
125+
throw QuickPkgError.fileNotFound(path)
126+
}
127+
let mountPoints = try await dmgManager.attach(url)
128+
let apps = findApplications(in: mountPoints)
129+
guard !apps.isEmpty else {
130+
throw QuickPkgError.noApplicationFound
131+
}
132+
guard apps.count == 1 else {
133+
throw QuickPkgError.multipleApplicationsFound(apps.map(\.path))
134+
}
135+
appURL = apps[0]
141136

142-
case .zip:
143-
guard FileManager.default.fileExists(atPath: path) else {
144-
throw QuickPkgError.fileNotFound(path)
145-
}
146-
let extractDir = tempDir.path.appendingPathComponent("unarchive")
147-
try FileManager.default.createDirectory(at: extractDir, withIntermediateDirectories: true)
148-
try await archiveExtractor.extractZip(url, to: extractDir)
149-
let apps = findApplications(in: [extractDir])
150-
guard !apps.isEmpty else {
151-
throw QuickPkgError.noApplicationFound
152-
}
153-
guard apps.count == 1 else {
154-
throw QuickPkgError.multipleApplicationsFound(apps.map(\.path))
155-
}
156-
appURL = apps[0]
137+
case .zip:
138+
guard FileManager.default.fileExists(atPath: path) else {
139+
throw QuickPkgError.fileNotFound(path)
140+
}
141+
let extractDir = tempDir.path.appendingPathComponent("unarchive")
142+
try FileManager.default.createDirectory(at: extractDir, withIntermediateDirectories: true)
143+
try await archiveExtractor.extractZip(url, to: extractDir)
144+
let apps = findApplications(in: [extractDir])
145+
guard !apps.isEmpty else {
146+
throw QuickPkgError.noApplicationFound
147+
}
148+
guard apps.count == 1 else {
149+
throw QuickPkgError.multipleApplicationsFound(apps.map(\.path))
150+
}
151+
appURL = apps[0]
157152

158-
case .xip:
159-
guard FileManager.default.fileExists(atPath: path) else {
160-
throw QuickPkgError.fileNotFound(path)
161-
}
162-
let extractDir = tempDir.path.appendingPathComponent("unarchive")
163-
try FileManager.default.createDirectory(at: extractDir, withIntermediateDirectories: true)
164-
try await archiveExtractor.extractXip(url, to: extractDir)
165-
let apps = findApplications(in: [extractDir])
166-
guard !apps.isEmpty else {
167-
throw QuickPkgError.noApplicationFound
168-
}
169-
guard apps.count == 1 else {
170-
throw QuickPkgError.multipleApplicationsFound(apps.map(\.path))
153+
case .xip:
154+
guard FileManager.default.fileExists(atPath: path) else {
155+
throw QuickPkgError.fileNotFound(path)
156+
}
157+
let extractDir = tempDir.path.appendingPathComponent("unarchive")
158+
try FileManager.default.createDirectory(at: extractDir, withIntermediateDirectories: true)
159+
try await archiveExtractor.extractXip(url, to: extractDir)
160+
let apps = findApplications(in: [extractDir])
161+
guard !apps.isEmpty else {
162+
throw QuickPkgError.noApplicationFound
163+
}
164+
guard apps.count == 1 else {
165+
throw QuickPkgError.multipleApplicationsFound(apps.map(\.path))
166+
}
167+
appURL = apps[0]
171168
}
172-
appURL = apps[0]
169+
} catch {
170+
if shouldClean { await dmgManager.detachAll() }
171+
throw error
173172
}
174173

175174
logger.log("Found application: \(appURL.path)", level: 1)
@@ -180,6 +179,9 @@ struct QuickPkg: AsyncParsableCommand {
180179
let payloadAppURL = payloadDir.appendingPathComponent(appURL.lastPathComponent)
181180
try FileManager.default.copyItem(at: appURL, to: payloadAppURL)
182181

182+
// Detach DMG now that we've copied the app
183+
if shouldClean { await dmgManager.detachAll() }
184+
183185
// Extract metadata from app
184186
let metadata = try AppMetadata(from: payloadAppURL)
185187
logger.log("Name: \(metadata.name), ID: \(metadata.identifier), Version: \(metadata.version)", level: 1)

0 commit comments

Comments
 (0)