diff --git a/Package.swift b/Package.swift index 656f635..6726780 100644 --- a/Package.swift +++ b/Package.swift @@ -12,12 +12,14 @@ let package = Package( .package(url: "https://github.com/Swinject/Swinject.git", from: "2.8.1"), .package(url: "https://github.com/Swinject/SwinjectAutoregistration", from: "2.8.1"), .package(url: "https://github.com/jakeheis/SwiftCLI", exact: "6.0.3"), + .package(url: "https://github.com/raptorxcz/xcbeautify", revision: "1bd38b6a64bb447c264fbdfc1b453bf8065b8ec6"), ], targets: [ .target(name: "SwiftTools", dependencies: [ "Swinject", "SwinjectAutoregistration", "SwiftCLI", + .product(name: "XcbeautifyLib", package: "xcbeautify"), ]), .testTarget( name: "SwiftToolsTests", diff --git a/Sources/SwiftTools/Build/Domain/BuildInteractor.swift b/Sources/SwiftTools/Build/Domain/BuildInteractor.swift index b658a61..07d42da 100644 --- a/Sources/SwiftTools/Build/Domain/BuildInteractor.swift +++ b/Sources/SwiftTools/Build/Domain/BuildInteractor.swift @@ -47,7 +47,7 @@ final class BuildInteractorImpl: BuildInteractor { func test(with arguments: TestArguments) throws { let arguments = try makeArguments(from: arguments) - try shellService.execute(arguments: arguments) + try shellService.executeWithXCBeautify(arguments: arguments) } func testWithLog(with arguments: TestArguments) throws -> String { diff --git a/Sources/SwiftTools/Common/Shell/Platform/ShellService.swift b/Sources/SwiftTools/Common/Shell/Platform/ShellService.swift index f49d50d..6f18a5d 100644 --- a/Sources/SwiftTools/Common/Shell/Platform/ShellService.swift +++ b/Sources/SwiftTools/Common/Shell/Platform/ShellService.swift @@ -6,10 +6,12 @@ // import SwiftCLI +import XcbeautifyLib public protocol ShellService { func execute(arguments: [String]) throws func executeWithResult(arguments: [String]) throws -> String + func executeWithXCBeautify(arguments: [String]) throws } final class ShellServiceImpl: ShellService { @@ -58,4 +60,33 @@ final class ShellServiceImpl: ShellService { return captureStream } } + + func executeWithXCBeautify(arguments: [String]) throws { + let printStream = WriteStream.stdout + let parser = XcbeautifyLib.Parser( + colored: true, + renderer: .terminal, + preserveUnbeautifiedLines: true, + additionalLines: { nil } + ) + let outputStream = makeBeautifyStream(outputStream: printStream, parser: parser) + + let command = arguments.joined(separator: " ") + let task = Task(executable: "/bin/bash", arguments: ["-c", command], stdout: outputStream) + let exitCode = task.runSync() + + guard exitCode == 0 else { + throw ToolsError(description: "shell command: '\(command)' failed with error") + } + } + + private func makeBeautifyStream(outputStream: WritableStream, parser: XcbeautifyLib.Parser) -> ProcessingStream { + return LineStream { line in + if let formatted = parser.parse(line: line) { + outputStream.write(formatted) + } else { + outputStream.write(line) + } + } + } } diff --git a/Tests/SwiftToolsTests/Build/Domain/BuildInteractorTests.swift b/Tests/SwiftToolsTests/Build/Domain/BuildInteractorTests.swift index 4231698..08c290b 100644 --- a/Tests/SwiftToolsTests/Build/Domain/BuildInteractorTests.swift +++ b/Tests/SwiftToolsTests/Build/Domain/BuildInteractorTests.swift @@ -62,8 +62,8 @@ final class BuildInteractorTests: XCTestCase { try sut.test(with: argumetns) - XCTAssertEqual(shellServiceSpy.execute.count, 1) - XCTAssertEqual(shellServiceSpy.execute.last?.arguments[safe: 4], "\"platform=iOS Simulator,id=40164398-DEA8-4D73-8813-CF7B2AC49090\"") + XCTAssertEqual(shellServiceSpy.executeWithXCBeautify.count, 1) + XCTAssertEqual(shellServiceSpy.executeWithXCBeautify.last?.arguments[safe: 4], "\"platform=iOS Simulator,id=40164398-DEA8-4D73-8813-CF7B2AC49090\"") } func test_givenBuildDestinationsAndmacOSPlatform_whenTest_thenParseCorrectDestination() throws { @@ -71,17 +71,12 @@ final class BuildInteractorTests: XCTestCase { try sut.test(with: argumetns) - XCTAssertEqual(shellServiceSpy.execute.count, 1) - XCTAssertEqual(shellServiceSpy.execute.last?.arguments[safe: 4], "\"platform=macOS,variant=Mac Catalyst,id=B717F26A-6C7A-5DE6-A1D0-9D0374071FD0\"") + XCTAssertEqual(shellServiceSpy.executeWithXCBeautify.count, 1) + XCTAssertEqual(shellServiceSpy.executeWithXCBeautify.last?.arguments[safe: 4], "\"platform=macOS,variant=Mac Catalyst,id=B717F26A-6C7A-5DE6-A1D0-9D0374071FD0\"") } } final class ShellServiceSpy: ShellService { - enum SpyError: Error { - case spyError - } - typealias ThrowBlock = () throws -> Void - struct Execute { let arguments: [String] } @@ -90,11 +85,17 @@ final class ShellServiceSpy: ShellService { let arguments: [String] } + struct ExecuteWithXCBeautify { + let arguments: [String] + } + + var executeThrowBlock: (() throws -> Void)? + var executeWithResultThrowBlock: (() throws -> Void)? + var executeWithResultReturn: String + var executeWithXCBeautifyThrowBlock: (() throws -> Void)? var execute = [Execute]() - var executeThrowBlock: ThrowBlock? var executeWithResult = [ExecuteWithResult]() - var executeWithResultThrowBlock: ThrowBlock? - var executeWithResultReturn: String + var executeWithXCBeautify = [ExecuteWithXCBeautify]() init(executeWithResultReturn: String) { self.executeWithResultReturn = executeWithResultReturn @@ -112,6 +113,12 @@ final class ShellServiceSpy: ShellService { try executeWithResultThrowBlock?() return executeWithResultReturn } + + func executeWithXCBeautify(arguments: [String]) throws { + let item = ExecuteWithXCBeautify(arguments: arguments) + executeWithXCBeautify.append(item) + try executeWithXCBeautifyThrowBlock?() + } } final class PrintServiceSpy: PrintService {