diff --git a/Package.swift b/Package.swift index 577105b..d94e4ec 100644 --- a/Package.swift +++ b/Package.swift @@ -22,7 +22,7 @@ let formatterTestsTargetName = formatterTargetName + "Tests" let package = Package( name: packageName, platforms: [ - .macOS(.v10_15) + .macOS(.v13) ], products: [ .library( diff --git a/Sources/DBXCResultParser/Constants.swift b/Sources/DBXCResultParser/Constants.swift index cc53ee3..fe826c4 100644 --- a/Sources/DBXCResultParser/Constants.swift +++ b/Sources/DBXCResultParser/Constants.swift @@ -9,56 +9,4 @@ import Foundation struct Constants { private static let packageName = "DBXCResultParser" - - private static var cachesDirectory: URL { - get throws { - guard let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else { - throw Error.noCachesDirectory - } - - return cachesDirectory - } - } - - private static var appCachesDirectory: URL { - get throws { - let appCachesDirectory = try cachesDirectory.appendingPathComponent(packageName, isDirectory: true) - if !FileManager.default.fileExists(atPath: appCachesDirectory.path) { - try FileManager.default.createDirectory(at: appCachesDirectory, - withIntermediateDirectories: true, - attributes: nil) - } - return appCachesDirectory - } - } - - static var actionsInvocationRecord: URL { - get throws { - try appCachesDirectory - .appendingPathComponent("ActionsInvocationRecord", isDirectory: false) - .appendingPathExtension("json") - } - } - - static var actionTestPlanRunSummaries: URL { - get throws { - try appCachesDirectory - .appendingPathComponent("ActionTestPlanRunSummaries", isDirectory: false) - .appendingPathExtension("json") - } - } - - static var actionTestSummary: URL { - get throws { - try appCachesDirectory - .appendingPathComponent("ActionTestSummary", isDirectory: false) - .appendingPathExtension("json") - } - } -} - -extension Constants { - enum Error: Swift.Error { - case noCachesDirectory - } } diff --git a/Sources/DBXCResultParser/Models/DTO/DTO+Helpers.swift b/Sources/DBXCResultParser/Models/DTO/DTO+Helpers.swift index 0a55dd4..74dbfae 100644 --- a/Sources/DBXCResultParser/Models/DTO/DTO+Helpers.swift +++ b/Sources/DBXCResultParser/Models/DTO/DTO+Helpers.swift @@ -9,10 +9,10 @@ import Foundation extension ActionsInvocationRecordDTO { init(from xcresultPath: URL) throws { - let filePath = try Constants.actionsInvocationRecord - try DBShell.execute("xcrun xcresulttool get --path \(xcresultPath.relativePath) --format json > \(filePath.relativePath)") - let data = try Data(contentsOf: filePath) - try FileManager.default.removeItem(atPath: filePath.relativePath) + let result = try DBShell + .execute("xcrun xcresulttool get --path \(xcresultPath.relativePath) --format json") + .trimmingPrefix { $0 != "{" } // xcodebuild may produce unwanted output prior to json + let data = try result.data(using: .utf8) ?! UnwrapError.valueIsNil self = try JSONDecoder().decode(ActionsInvocationRecordDTO.self, from: data) } } @@ -20,10 +20,10 @@ extension ActionsInvocationRecordDTO { extension ActionTestPlanRunSummariesDTO { init(from xcresultPath: URL, refId: String? = nil) throws { let refId = try (refId ?? ActionsInvocationRecordDTO(from: xcresultPath).testsRefId) - let filePath = try Constants.actionTestPlanRunSummaries - try DBShell.execute("xcrun xcresulttool get --path \(xcresultPath.relativePath) --format json --id \(refId) > \(filePath.relativePath)") - let data = try Data(contentsOf: filePath) - try FileManager.default.removeItem(atPath: filePath.relativePath) + let result = try DBShell + .execute("xcrun xcresulttool get --path \(xcresultPath.relativePath) --format json --id \(refId)") + .trimmingPrefix { $0 != "{" } // xcodebuild may produce unwanted output prior to json + let data = try result.data(using: .utf8) ?! UnwrapError.valueIsNil self = try JSONDecoder().decode(ActionTestPlanRunSummariesDTO.self, from: data) } } @@ -31,20 +31,30 @@ extension ActionTestPlanRunSummariesDTO { extension ActionTestSummaryDTO { init(from xcresultPath: URL, refId: String? = nil) throws { let refId = try (refId ?? ActionsInvocationRecordDTO(from: xcresultPath).testsRefId) - let filePath = try Constants.actionTestSummary - try DBShell.execute("xcrun xcresulttool get --path \(xcresultPath.relativePath) --format json --id \(refId) > \(filePath.relativePath)") - let data = try Data(contentsOf: filePath) - try FileManager.default.removeItem(atPath: filePath.relativePath) + let result = try DBShell.execute("xcrun xcresulttool get --path \(xcresultPath.relativePath) --format json --id \(refId)") + let data = try result.data(using: .utf8) ?! UnwrapError.valueIsNil self = try JSONDecoder().decode(ActionTestSummaryDTO.self, from: data) } } extension Array where Element == CoverageDTO { init(from xcresultPath: URL) throws { - let tempFilePath = try Constants.actionsInvocationRecord - try DBShell.execute("xcrun xccov view --report --only-targets --json \(xcresultPath.relativePath) > \(tempFilePath.relativePath)") - let data = try Data(contentsOf: tempFilePath) - try FileManager.default.removeItem(atPath: tempFilePath.relativePath) + let result = try DBShell.execute("xcrun xccov view --report --only-targets --json \(xcresultPath.relativePath)") + let data = try result.data(using: .utf8) ?! UnwrapError.valueIsNil self = try JSONDecoder().decode(Array.self, from: data) } } + +infix operator ?!: NilCoalescingPrecedence + +/// Throws the right hand side error if the left hand side optional is `nil`. +func ?!(value: T?, error: @autoclosure () -> Error) throws -> T { + guard let value = value else { + throw error() + } + return value +} + +enum UnwrapError: Swift.Error { + case valueIsNil +}