@@ -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