@@ -102,7 +102,7 @@ struct AWSLambdaPackager: CommandPlugin {
102
102
)
103
103
let productPath = buildOutputPath. appending ( product. name)
104
104
guard FileManager . default. fileExists ( atPath: productPath. string) else {
105
- throw Errors . productExecutableNotFound ( " could not find executable for ' \( product. name) ', expected at ' \( productPath ) ' " )
105
+ throw Errors . productExecutableNotFound ( product. name)
106
106
}
107
107
builtProducts [ . init( product) ] = productPath
108
108
}
@@ -132,7 +132,7 @@ struct AWSLambdaPackager: CommandPlugin {
132
132
parameters: parameters
133
133
)
134
134
guard let artifact = result. executableArtifact ( for: product) else {
135
- throw Errors . unknownExecutable ( " no executable artifacts found for \( product. name) " )
135
+ throw Errors . productExecutableNotFound ( product. name)
136
136
}
137
137
results [ . init( product) ] = artifact. path
138
138
}
@@ -197,14 +197,14 @@ struct AWSLambdaPackager: CommandPlugin {
197
197
print ( " \( executable. string) \( arguments. joined ( separator: " " ) ) " )
198
198
}
199
199
200
- let sync = DispatchGroup ( )
201
200
var output = " "
201
+ let outputSync = DispatchGroup ( )
202
202
let outputQueue = DispatchQueue ( label: " AWSLambdaPackager.output " )
203
203
let outputHandler = { ( data: Data ? ) in
204
204
dispatchPrecondition ( condition: . onQueue( outputQueue) )
205
205
206
- sync . enter ( )
207
- defer { sync . leave ( ) }
206
+ outputSync . enter ( )
207
+ defer { outputSync . leave ( ) }
208
208
209
209
guard let _output = data. flatMap ( { String ( data: $0, encoding: . utf8) ? . trimmingCharacters ( in: CharacterSet ( [ " \n " ] ) ) } ) , !_output. isEmpty else {
210
210
return
@@ -216,34 +216,36 @@ struct AWSLambdaPackager: CommandPlugin {
216
216
output += _output
217
217
}
218
218
219
- let stdoutPipe = Pipe ( )
220
- stdoutPipe. fileHandleForReading. readabilityHandler = { fileHandle in outputQueue. async { outputHandler ( fileHandle. availableData) } }
221
- let stderrPipe = Pipe ( )
222
- stderrPipe. fileHandleForReading. readabilityHandler = { fileHandle in outputQueue. async { outputHandler ( fileHandle. availableData) } }
219
+ let pipe = Pipe ( )
220
+ pipe. fileHandleForReading. readabilityHandler = { fileHandle in outputQueue. async { outputHandler ( fileHandle. availableData) } }
223
221
224
222
let process = Process ( )
225
- process. standardOutput = stdoutPipe
226
- process. standardError = stderrPipe
223
+ process. standardOutput = pipe
224
+ process. standardError = pipe
227
225
process. executableURL = URL ( fileURLWithPath: executable. string)
228
226
process. arguments = arguments
229
227
if let workingDirectory = customWorkingDirectory {
230
228
process. currentDirectoryURL = URL ( fileURLWithPath: workingDirectory. string)
231
229
}
232
230
process. terminationHandler = { _ in
233
231
outputQueue. async {
234
- outputHandler ( try ? stdoutPipe. fileHandleForReading. readToEnd ( ) )
235
- outputHandler ( try ? stderrPipe. fileHandleForReading. readToEnd ( ) )
232
+ outputHandler ( try ? pipe. fileHandleForReading. readToEnd ( ) )
236
233
}
237
234
}
238
235
239
236
try process. run ( )
240
237
process. waitUntilExit ( )
241
238
242
239
// wait for output to be full processed
243
- sync . wait ( )
240
+ outputSync . wait ( )
244
241
245
242
if process. terminationStatus != 0 {
246
- throw Errors . processFailed ( process. terminationStatus)
243
+ // print output on failure and if not already printed
244
+ if logLevel < . output {
245
+ print ( output)
246
+ fflush ( stdout)
247
+ }
248
+ throw Errors . processFailed ( [ executable. string] + arguments, process. terminationStatus)
247
249
}
248
250
249
251
return output
@@ -282,7 +284,7 @@ private struct Configuration: CustomStringConvertible {
282
284
if let outputPath = outputPathArgument. first {
283
285
var isDirectory : ObjCBool = false
284
286
guard FileManager . default. fileExists ( atPath: outputPath, isDirectory: & isDirectory) , isDirectory. boolValue else {
285
- throw Errors . invalidArgument ( " invalid output directory \( outputPath) " )
287
+ throw Errors . invalidArgument ( " invalid output directory ' \( outputPath) ' " )
286
288
}
287
289
self . outputDirectory = Path ( outputPath)
288
290
} else {
@@ -293,7 +295,7 @@ private struct Configuration: CustomStringConvertible {
293
295
let products = try context. package . products ( named: productsArgument)
294
296
for product in products {
295
297
guard product is ExecutableProduct else {
296
- throw Errors . invalidArgument ( " product named \( product. name) is not an executable product " )
298
+ throw Errors . invalidArgument ( " product named ' \( product. name) ' is not an executable product" )
297
299
}
298
300
}
299
301
self . products = products
@@ -304,7 +306,7 @@ private struct Configuration: CustomStringConvertible {
304
306
305
307
if let buildConfigurationName = configurationArgument. first {
306
308
guard let buildConfiguration = PackageManager . BuildConfiguration ( rawValue: buildConfigurationName) else {
307
- throw Errors . invalidArgument ( " invalid build configuration named \( buildConfigurationName) " )
309
+ throw Errors . invalidArgument ( " invalid build configuration named ' \( buildConfigurationName) ' " )
308
310
}
309
311
self . buildConfiguration = buildConfiguration
310
312
} else {
@@ -338,18 +340,6 @@ private struct Configuration: CustomStringConvertible {
338
340
}
339
341
}
340
342
341
- private enum Errors : Error {
342
- case invalidArgument( String )
343
- case unsupportedPlatform( String )
344
- case unknownProduct( String )
345
- case unknownExecutable( String )
346
- case buildError( String )
347
- case productExecutableNotFound( String )
348
- case failedWritingDockerfile
349
- case processFailed( Int32 )
350
- case invalidProcessOutput
351
- }
352
-
353
343
private enum ProcessLogLevel : Int , Comparable {
354
344
case silent = 0
355
345
case output = 1
@@ -360,21 +350,33 @@ private enum ProcessLogLevel: Int, Comparable {
360
350
}
361
351
}
362
352
363
- extension PackageManager . BuildResult {
364
- // find the executable produced by the build
365
- func executableArtifact( for product: Product ) -> PackageManager . BuildResult . BuiltArtifact ? {
366
- let executables = self . builtArtifacts. filter { $0. kind == . executable && $0. path. lastComponent == product. name }
367
- guard !executables. isEmpty else {
368
- return nil
369
- }
370
- guard executables. count == 1 , let executable = executables. first else {
371
- return nil
353
+ private enum Errors : Error , CustomStringConvertible {
354
+ case invalidArgument( String )
355
+ case unsupportedPlatform( String )
356
+ case unknownProduct( String )
357
+ case productExecutableNotFound( String )
358
+ case failedWritingDockerfile
359
+ case processFailed( [ String ] , Int32 )
360
+
361
+ var description : String {
362
+ switch self {
363
+ case . invalidArgument( let description) :
364
+ return description
365
+ case . unsupportedPlatform( let description) :
366
+ return description
367
+ case . unknownProduct( let description) :
368
+ return description
369
+ case . productExecutableNotFound( let product) :
370
+ return " product executable not found ' \( product) ' "
371
+ case . failedWritingDockerfile:
372
+ return " failed writing dockerfile "
373
+ case . processFailed( let arguments, let code) :
374
+ return " \( arguments. joined ( separator: " " ) ) failed with code \( code) "
372
375
}
373
- return executable
374
376
}
375
377
}
376
378
377
- struct LambdaProduct : Hashable {
379
+ private struct LambdaProduct : Hashable {
378
380
let underlying : Product
379
381
380
382
init ( _ underlying: Product ) {
@@ -393,3 +395,17 @@ struct LambdaProduct: Hashable {
393
395
lhs. underlying. id == rhs. underlying. id
394
396
}
395
397
}
398
+
399
+ extension PackageManager . BuildResult {
400
+ // find the executable produced by the build
401
+ func executableArtifact( for product: Product ) -> PackageManager . BuildResult . BuiltArtifact ? {
402
+ let executables = self . builtArtifacts. filter { $0. kind == . executable && $0. path. lastComponent == product. name }
403
+ guard !executables. isEmpty else {
404
+ return nil
405
+ }
406
+ guard executables. count == 1 , let executable = executables. first else {
407
+ return nil
408
+ }
409
+ return executable
410
+ }
411
+ }
0 commit comments