Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Sources/RswiftCore/CallInformation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ public struct CallInformation {
let scriptOutputFiles: [String]
let lastRunURL: URL

private let buildProductsDirURL: URL
private let developerDirURL: URL
private let sourceRootURL: URL
private let sdkRootURL: URL
private let platformURL: URL
let buildProductsDirURL: URL
let developerDirURL: URL
let sourceRootURL: URL
let sdkRootURL: URL
let platformURL: URL

public init(
outputURL: URL,
Expand Down
61 changes: 61 additions & 0 deletions Sources/RswiftCore/EnvironmentValidation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// EnvironmentValidation.swift
// Commander
//
// Created by Tom Lokhorst on 2018-12-12.
//

import Foundation

public func validateRswiftEnvironment(
outputURL: URL,
sourceRootPath: String,
scriptInputFiles: [String],
scriptOutputFiles: [String],
lastRunURL: URL,
podsRoot: String?,
commandLineArguments: [String]) -> [String]
{
var errors: [String] = []
var outputIsDirectory = false

if outputURL.pathExtension != "swift" {
outputIsDirectory = true

var error = "Output path must specify a file, it should not be a directory."
if FileManager.default.directoryExists(atPath: outputURL.path) {
let rswiftGeneratedFile = outputURL.appendingPathComponent("R.generated.swift").path
let commandParts = commandLineArguments
.map { $0.replacingOccurrences(of: podsRoot ?? "", with: "$PODS_ROOT") }
.map { $0.replacingOccurrences(of: outputURL.path, with: rswiftGeneratedFile) }
.map { $0.replacingOccurrences(of: sourceRootPath, with: "$SRCROOT") }
.map { $0.contains(" ") ? "\"\($0)\"" : $0 }
error += "\nExample: " + commandParts.joined(separator: " ")
}

errors.append(error)
}

if !scriptInputFiles.contains(lastRunURL.path) {
errors.append("Build phase Intput Files does not contain '$TEMP_DIR/\(lastRunURL.lastPathComponent)'.")
}

if !scriptOutputFiles.contains(outputURL.path) {
var prettyPath = outputURL.path.replacingOccurrences(of: sourceRootPath, with: "$SRCROOT")
if outputIsDirectory {
prettyPath += "/R.generated.swift"
}
errors.append("Build phase Output Files do not contain '\(prettyPath)'.")
}

return errors
}

extension FileManager {
func directoryExists(atPath path: String) -> Bool {
var isDir: ObjCBool = false
let exists = fileExists(atPath: path, isDirectory: &isDir)

return exists && isDir.boolValue
}
}
15 changes: 0 additions & 15 deletions Sources/RswiftCore/RswiftCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@ import XcodeEdit
public struct RswiftCore {

static public func run(_ callInformation: CallInformation) throws {
guard callInformation.scriptInputFiles.contains(callInformation.lastRunURL.path) else {
fail("Missing '$(TEMP_DIR)/\(callInformation.lastRunURL.lastPathComponent)' from Input Files. See upgrading to R.swift 5.0: http://bit.ly/2PsO9IF")
exit(EXIT_FAILURE)
}

guard callInformation.outputURL.pathExtension == "swift" else {
fail("Output path must be a specific Swift file, folders are not allowed anymore. See upgrading to R.swift 5.0: http://bit.ly/2PsO9IF")
exit(EXIT_FAILURE)
}

guard callInformation.scriptOutputFiles.contains(callInformation.outputURL.path) else {
fail("Build phase output files do not contain '\(callInformation.outputURL.path)'. See upgrading to R.swift 5.0: http://bit.ly/2PsO9IF")
exit(EXIT_FAILURE)
}

do {
let xcodeproj = try Xcodeproj(url: callInformation.xcodeprojURL)
let ignoreFile = (try? IgnoreFile(ignoreFileURL: callInformation.rswiftIgnoreURL)) ?? IgnoreFile()
Expand Down
2 changes: 1 addition & 1 deletion Sources/RswiftCore/Util/ErrorOutput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public func warn(_ warning: String) {
print("warning: [R.swift] \(warning)")
}

func fail(_ error: String) {
public func fail(_ error: String) {
print("error: [R.swift] \(error)")
}
38 changes: 28 additions & 10 deletions Sources/rswift/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@ let generate = command(

let processInfo = ProcessInfo()

// Touch last run file
do {
let tempDirPath = try ProcessInfo().environmentVariable(name: EnvironmentKeys.tempDir)
let lastRunFile = URL(fileURLWithPath: tempDirPath).appendingPathComponent(Rswift.lastRunFile)
try Date().description.write(to: lastRunFile, atomically: true, encoding: .utf8)
} catch {
warn("Failed to write out to '\(Rswift.lastRunFile)', this might cause Xcode to not run the R.swift build phase: \(error)")
}

let xcodeprojPath = try processInfo.environmentVariable(name: EnvironmentKeys.xcodeproj)
let targetName = try processInfo.environmentVariable(name: EnvironmentKeys.target)
let bundleIdentifier = try processInfo.environmentVariable(name: EnvironmentKeys.bundleIdentifier)
Expand All @@ -105,6 +114,8 @@ let generate = command(
.filter { !$0.isEmpty }
.map { Module.custom(name: $0) }

let lastRunURL = URL(fileURLWithPath: tempDir).appendingPathComponent(Rswift.lastRunFile)

let scriptInputFileCountString = try processInfo.environmentVariable(name: EnvironmentKeys.scriptInputFileCount)
guard let scriptInputFileCount = Int(scriptInputFileCountString) else {
throw ArgumentError.invalidType(value: scriptInputFileCountString, type: "Int", argument: EnvironmentKeys.scriptInputFileCount)
Expand All @@ -121,6 +132,22 @@ let generate = command(
.map(EnvironmentKeys.scriptOutputFile)
.map(processInfo.environmentVariable)

let errors = validateRswiftEnvironment(
outputURL: outputURL,
sourceRootPath: sourceRootPath,
scriptInputFiles: scriptInputFiles,
scriptOutputFiles: scriptOutputFiles,
lastRunURL: lastRunURL,
podsRoot: processInfo.environment["PODS_ROOT"],
commandLineArguments: CommandLine.arguments)
guard errors.isEmpty else {
for error in errors {
fail(error)
}
warn("For updating to R.swift 5.0, read our migration guide: https://github.com/mac-cain13/R.swift/blob/master/Documentation/Migration.md")
exit(EXIT_FAILURE)
}

let callInformation = CallInformation(
outputURL: outputURL,
rswiftIgnoreURL: rswiftIgnoreURL,
Expand All @@ -135,7 +162,7 @@ let generate = command(

scriptInputFiles: scriptInputFiles,
scriptOutputFiles: scriptOutputFiles,
lastRunURL: URL(fileURLWithPath: tempDir).appendingPathComponent(Rswift.lastRunFile),
lastRunURL: lastRunURL,

buildProductsDirURL: URL(fileURLWithPath: buildProductsDirPath),
developerDirURL: URL(fileURLWithPath: developerDirPath),
Expand All @@ -147,15 +174,6 @@ let generate = command(
try RswiftCore.run(callInformation)
}

// Touch last run file
do {
let tempDirPath = try ProcessInfo().environmentVariable(name: EnvironmentKeys.tempDir)
let lastRunFile = URL(fileURLWithPath: tempDirPath).appendingPathComponent(Rswift.lastRunFile)
try Date().description.write(to: lastRunFile, atomically: true, encoding: .utf8)
} catch {
warn("Failed to write out to '\(Rswift.lastRunFile)', this might cause Xcode to not run the R.swift build phase: \(error)")
}

// Start parsing the launch arguments
let group = Group()
group.addCommand("generate", "Generates R.generated.swift file", generate)
Expand Down