Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate package manifest parsing errors #86

Merged
merged 7 commits into from
Aug 19, 2020
Merged
45 changes: 26 additions & 19 deletions Sources/SwiftToolchain/Toolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ enum ToolchainError: Error, CustomStringConvertible {
case noExecutableProduct
case failedToBuild(product: String)
case failedToBuildTestBundle
case missingPackage
case missingPackageManifest
case processFailed(output: [UInt8])
case invalidVersion(version: String)

var description: String {
Expand All @@ -44,11 +45,19 @@ enum ToolchainError: Error, CustomStringConvertible {
return "Failed to build executable product \(product)"
case .failedToBuildTestBundle:
return "Failed to build the test bundle"
case .missingPackage:
case .missingPackageManifest:
return """
The `Package.swift` manifest file could not be found. Please navigate to a directory that \
contains `Package.swift` and restart.
"""
case let .processFailed(output: output):
if let description = ByteString(output).validDescription {
return """
Process failed with following output:
\(description)
"""
}
return "Process failed with no text output"
case let .invalidVersion(version):
return "Invalid version \(version)"
}
Expand All @@ -61,17 +70,19 @@ public final class Toolchain {

private let version: String
private let swiftPath: AbsolutePath
private let package: Package?
private let package: Result<Package, Error>

public init(
for versionSpec: String? = nil,
_ fileSystem: FileSystem,
_ terminal: TerminalController
) throws {
(swiftPath, version) = try fileSystem.inferSwiftPath(from: versionSpec, terminal)
let (swiftPath, version) = try fileSystem.inferSwiftPath(from: versionSpec, terminal)
self.swiftPath = swiftPath
self.version = version
self.fileSystem = fileSystem
self.terminal = terminal
package = try? Package(with: swiftPath, terminal)
package = Result { try Package(with: swiftPath, terminal) }
}

private func inferBinPath() throws -> AbsolutePath {
Expand All @@ -86,9 +97,8 @@ public final class Toolchain {
}

private func inferDevProduct(hint: String?) throws -> String? {
guard let package = package else {
throw ToolchainError.missingPackage
}
let package = try self.package.get()

var candidateProducts = package.products
.filter { $0.type.library == nil }
.map(\.name)
Expand Down Expand Up @@ -125,8 +135,8 @@ public final class Toolchain {
}

private func inferManifestDirectory() throws -> AbsolutePath {
guard package != nil, var cwd = fileSystem.currentWorkingDirectory else {
throw ToolchainError.missingPackage
guard (try? package.get()) != nil, var cwd = fileSystem.currentWorkingDirectory else {
throw ToolchainError.missingPackageManifest
}

repeat {
Expand All @@ -138,13 +148,11 @@ public final class Toolchain {
cwd = cwd.parentDirectory
} while !cwd.isRoot

throw ToolchainError.missingPackage
throw ToolchainError.missingPackageManifest
}

public func inferSourcesPaths() throws -> [AbsolutePath] {
guard let package = package else {
throw ToolchainError.missingPackage
}
let package = try self.package.get()

let targetPaths = package.targets.compactMap { target -> String? in
guard let path = target.path else {
Expand Down Expand Up @@ -177,8 +185,9 @@ public final class Toolchain {
guard let product = try inferDevProduct(hint: product)
else { throw ToolchainError.noExecutableProduct }

if let package = package,
let jsKit = package.dependencies?.first(where: { $0.name == "JavaScriptKit" }),
let package = try self.package.get()

if let jsKit = package.dependencies?.first(where: { $0.name == "JavaScriptKit" }),
jsKit.requirement.revision != ["c90e82f"] {
let version = jsKit.requirement.revision.flatMap { " (\($0[0]))" } ?? ""

Expand Down Expand Up @@ -221,9 +230,7 @@ public final class Toolchain {

/// Returns an absolute path to the resulting test bundle
public func buildTestBundle(isRelease: Bool) throws -> AbsolutePath {
guard let package = package else {
throw ToolchainError.missingPackage
}
let package = try self.package.get()
let binPath = try inferBinPath()
let testBundlePath = binPath.appending(component: "\(package.name)PackageTests.xctest")
terminal.logLookup("- test bundle to run: ", testBundlePath.pathString)
Expand Down