@@ -102,7 +102,7 @@ struct AWSLambdaPackager: CommandPlugin {
102102 )
103103 let productPath = buildOutputPath. appending ( product. name)
104104 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)
106106 }
107107 builtProducts [ . init( product) ] = productPath
108108 }
@@ -132,7 +132,7 @@ struct AWSLambdaPackager: CommandPlugin {
132132 parameters: parameters
133133 )
134134 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)
136136 }
137137 results [ . init( product) ] = artifact. path
138138 }
@@ -197,14 +197,14 @@ struct AWSLambdaPackager: CommandPlugin {
197197 print ( " \( executable. string) \( arguments. joined ( separator: " " ) ) " )
198198 }
199199
200- let sync = DispatchGroup ( )
201200 var output = " "
201+ let outputSync = DispatchGroup ( )
202202 let outputQueue = DispatchQueue ( label: " AWSLambdaPackager.output " )
203203 let outputHandler = { ( data: Data ? ) in
204204 dispatchPrecondition ( condition: . onQueue( outputQueue) )
205205
206- sync . enter ( )
207- defer { sync . leave ( ) }
206+ outputSync . enter ( )
207+ defer { outputSync . leave ( ) }
208208
209209 guard let _output = data. flatMap ( { String ( data: $0, encoding: . utf8) ? . trimmingCharacters ( in: CharacterSet ( [ " \n " ] ) ) } ) , !_output. isEmpty else {
210210 return
@@ -216,34 +216,36 @@ struct AWSLambdaPackager: CommandPlugin {
216216 output += _output
217217 }
218218
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) } }
223221
224222 let process = Process ( )
225- process. standardOutput = stdoutPipe
226- process. standardError = stderrPipe
223+ process. standardOutput = pipe
224+ process. standardError = pipe
227225 process. executableURL = URL ( fileURLWithPath: executable. string)
228226 process. arguments = arguments
229227 if let workingDirectory = customWorkingDirectory {
230228 process. currentDirectoryURL = URL ( fileURLWithPath: workingDirectory. string)
231229 }
232230 process. terminationHandler = { _ in
233231 outputQueue. async {
234- outputHandler ( try ? stdoutPipe. fileHandleForReading. readToEnd ( ) )
235- outputHandler ( try ? stderrPipe. fileHandleForReading. readToEnd ( ) )
232+ outputHandler ( try ? pipe. fileHandleForReading. readToEnd ( ) )
236233 }
237234 }
238235
239236 try process. run ( )
240237 process. waitUntilExit ( )
241238
242239 // wait for output to be full processed
243- sync . wait ( )
240+ outputSync . wait ( )
244241
245242 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)
247249 }
248250
249251 return output
@@ -282,7 +284,7 @@ private struct Configuration: CustomStringConvertible {
282284 if let outputPath = outputPathArgument. first {
283285 var isDirectory : ObjCBool = false
284286 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) ' " )
286288 }
287289 self . outputDirectory = Path ( outputPath)
288290 } else {
@@ -293,7 +295,7 @@ private struct Configuration: CustomStringConvertible {
293295 let products = try context. package . products ( named: productsArgument)
294296 for product in products {
295297 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" )
297299 }
298300 }
299301 self . products = products
@@ -304,7 +306,7 @@ private struct Configuration: CustomStringConvertible {
304306
305307 if let buildConfigurationName = configurationArgument. first {
306308 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) ' " )
308310 }
309311 self . buildConfiguration = buildConfiguration
310312 } else {
@@ -338,18 +340,6 @@ private struct Configuration: CustomStringConvertible {
338340 }
339341}
340342
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-
353343private enum ProcessLogLevel : Int , Comparable {
354344 case silent = 0
355345 case output = 1
@@ -360,21 +350,33 @@ private enum ProcessLogLevel: Int, Comparable {
360350 }
361351}
362352
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) "
372375 }
373- return executable
374376 }
375377}
376378
377- struct LambdaProduct : Hashable {
379+ private struct LambdaProduct : Hashable {
378380 let underlying : Product
379381
380382 init ( _ underlying: Product ) {
@@ -393,3 +395,17 @@ struct LambdaProduct: Hashable {
393395 lhs. underlying. id == rhs. underlying. id
394396 }
395397}
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