Skip to content

Commit

Permalink
Add minimumXcodeGenVersion option
Browse files Browse the repository at this point in the history
If XcodeGen's version is less than this version validation will fail.
  • Loading branch information
brentleyjones committed Jul 19, 2018
1 parent fed7e14 commit a69cae6
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 14 deletions.
1 change: 1 addition & 0 deletions Docs/ProjectSpec.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Note that target names can also be changed by adding a `name` property to a targ

### Options

- [ ] **minimumXcodeGenVersion**: **String** - The minimum version of XcodeGen required.
- [ ] **carthageBuildPath**: **String** - The path to the carthage build directory. Defaults to `Carthage/Build`. This is used when specifying target carthage dependencies
- [ ] **carthageExecutablePath**: **String** - The path to the carthage executable. Defaults to `carthage`. You can specify when you use custom built or locally installed Carthage using [Mint](https://github.com/yonaskolb/Mint), for example.
- [ ] **createIntermediateGroups**: **Bool** - If this is specified and set to `true`, then intermediate groups will be created for every path component between the folder containing the source and next existing group it finds or the base path. For example, when enabled if a source path is specified as `Vendor/Foo/Hello.swift`, the group `Vendor` will created as a parent of the `Foo` group.
Expand Down
7 changes: 7 additions & 0 deletions Sources/ProjectSpec/SpecOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import xcproj

public struct SpecOptions: Equatable {

public var minimumXcodeGenVersion: Version?
public var carthageBuildPath: String?
public var carthageExecutablePath: String?
public var createIntermediateGroups: Bool
Expand Down Expand Up @@ -45,6 +46,7 @@ public struct SpecOptions: Equatable {
}

public init(
minimumXcodeGenVersion: Version? = nil,
carthageBuildPath: String? = nil,
carthageExecutablePath: String? = nil,
createIntermediateGroups: Bool = false,
Expand All @@ -60,6 +62,7 @@ public struct SpecOptions: Equatable {
defaultConfig: String? = nil,
transitivelyLinkDependencies: Bool = false
) {
self.minimumXcodeGenVersion = minimumXcodeGenVersion
self.carthageBuildPath = carthageBuildPath
self.carthageExecutablePath = carthageExecutablePath
self.createIntermediateGroups = createIntermediateGroups
Expand All @@ -80,6 +83,10 @@ public struct SpecOptions: Equatable {
extension SpecOptions: JSONObjectConvertible {

public init(jsonDictionary: JSONDictionary) throws {
if let string: String = jsonDictionary.json(atKeyPath: "minimumXcodeGenVersion") {
minimumXcodeGenVersion = try Version(string)
}

carthageBuildPath = jsonDictionary.json(atKeyPath: "carthageBuildPath")
carthageExecutablePath = jsonDictionary.json(atKeyPath: "carthageExecutablePath")
bundleIdPrefix = jsonDictionary.json(atKeyPath: "bundleIdPrefix")
Expand Down
6 changes: 5 additions & 1 deletion Sources/ProjectSpec/SpecValidation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import PathKit

extension Project {

public func validate() throws {
public func validate(xcodeGenVersion: Version) throws {

var errors: [SpecValidationError.ValidationError] = []

if let minimumXcodeGenVersion = options.minimumXcodeGenVersion, xcodeGenVersion < minimumXcodeGenVersion {
errors.append(.invalidXcodeGenVersion(version: xcodeGenVersion, minimumVersion: minimumXcodeGenVersion))
}

func validateSettings(_ settings: Settings) -> [SpecValidationError.ValidationError] {
var errors: [SpecValidationError.ValidationError] = []
Expand Down
3 changes: 3 additions & 0 deletions Sources/ProjectSpec/SpecValidationError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public struct SpecValidationError: Error, CustomStringConvertible {
public var errors: [ValidationError]

public enum ValidationError: Error, CustomStringConvertible {
case invalidXcodeGenVersion(version: Version, minimumVersion: Version)
case invalidTargetDependency(target: String, dependency: String)
case invalidTargetSource(target: String, source: String)
case invalidTargetConfigFile(target: String, configFile: String, config: String)
Expand All @@ -23,6 +24,8 @@ public struct SpecValidationError: Error, CustomStringConvertible {

public var description: String {
switch self {
case let .invalidXcodeGenVersion(version, minimumVersion):
return "XcodeGen version is \(version), but minimum required version specified as \(minimumVersion)"
case let .invalidTargetDependency(target, dependency):
return "Target \(target.quoted) has invalid dependency: \(dependency.quoted)"
case let .invalidTargetConfigFile(target, configFile, config):
Expand Down
2 changes: 1 addition & 1 deletion Sources/XcodeGen/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func generate(spec: String, project: String, isQuiet: Bool, justVersion: Bool) {
do {
logger.info("⚙️ Generating project...")
let projectGenerator = ProjectGenerator(project: project)
let xcodeProject = try projectGenerator.generateXcodeProject()
let xcodeProject = try projectGenerator.generateXcodeProject(xcodeGenVersion: version)

logger.info("⚙️ Writing project...")

Expand Down
4 changes: 2 additions & 2 deletions Sources/XcodeGenKit/ProjectGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public class ProjectGenerator {
return project.configs.first { $0.type == .release }!
}

public func generateXcodeProject() throws -> XcodeProj {
try project.validate()
public func generateXcodeProject(xcodeGenVersion: Version) throws -> XcodeProj {
try project.validate(xcodeGenVersion: xcodeGenVersion)
let pbxProjGenerator = PBXProjGenerator(project: project)
let pbxProject = try pbxProjGenerator.generate()
let workspace = try generateWorkspace()
Expand Down
8 changes: 4 additions & 4 deletions Tests/XcodeGenKitTests/GeneratorHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import Yams

extension Project {

func generateXcodeProject(file: String = #file, line: Int = #line) throws -> XcodeProj {
func generateXcodeProject(xcodeGenVersion: Version = try! Version("1.11.0"), file: String = #file, line: Int = #line) throws -> XcodeProj {
return try doThrowing(file: file, line: line) {
let generator = ProjectGenerator(project: self)
return try generator.generateXcodeProject()
return try generator.generateXcodeProject(xcodeGenVersion: xcodeGenVersion)
}
}

func generatePbxProj(file: String = #file, line: Int = #line) throws -> PBXProj {
func generatePbxProj(xcodeGenVersion: Version = try! Version("1.11.0"), file: String = #file, line: Int = #line) throws -> PBXProj {
return try doThrowing(file: file, line: line) {
let xcodeProject = try generateXcodeProject().pbxproj
let xcodeProject = try generateXcodeProject(xcodeGenVersion: xcodeGenVersion).pbxproj
try xcodeProject.validate()
return xcodeProject
}
Expand Down
4 changes: 2 additions & 2 deletions Tests/XcodeGenKitTests/ProjectFixtureTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ class ProjectFixtureTests: XCTestCase {
}
}

fileprivate func generateXcodeProject(specPath: Path, projectPath: Path, file: String = #file, line: Int = #line) throws -> XcodeProj {
fileprivate func generateXcodeProject(xcodeGenVersion: Version = try! Version("1.11.0"), specPath: Path, projectPath: Path, file: String = #file, line: Int = #line) throws -> XcodeProj {
let project = try Project(path: specPath)
let generator = ProjectGenerator(project: project)
let xcodeProject = try generator.generateXcodeProject()
let xcodeProject = try generator.generateXcodeProject(xcodeGenVersion: xcodeGenVersion)
let oldProject = try XcodeProj(path: projectPath)
let pbxProjPath = projectPath + XcodeProj.pbxprojPath(projectPath)
let oldProjectString: String = try pbxProjPath.read()
Expand Down
19 changes: 15 additions & 4 deletions Tests/XcodeGenKitTests/ProjectSpecTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ class ProjectSpecTests: XCTestCase {
configSettings: ["invalidConfig": [:]],
groups: ["invalidSettingGroup"]
)

$0.it("fails with invalid XcodeGen version") {
let minimumVersion = try! Version("1.11.1")
var project = baseProject
project.options = SpecOptions(minimumXcodeGenVersion: minimumVersion)

try expectValidationError(xcodeGenVersion: try! Version("1.11.0"), project, .invalidXcodeGenVersion(version: try! Version("1.11.0"), minimumVersion: minimumVersion))
try expectValidationError(xcodeGenVersion: try! Version("1.10.99"), project, .invalidXcodeGenVersion(version: try! Version("1.10.99"), minimumVersion: minimumVersion))
try expectValidationError(xcodeGenVersion: try! Version("0.99"), project, .invalidXcodeGenVersion(version: try! Version("0.99"), minimumVersion: minimumVersion))
}

$0.it("fails with invalid project") {
var project = baseProject
project.settings = invalidSettings
Expand All @@ -98,7 +109,7 @@ class ProjectSpecTests: XCTestCase {
project.options = SpecOptions(disabledValidations: [.missingConfigs])
let configPath = fixturePath + "test.xcconfig"
project.configFiles = ["missingConfiguration": configPath.string]
try project.validate()
try project.validate(xcodeGenVersion: try Version("1.11.0"))
}

$0.it("fails with invalid target") {
Expand Down Expand Up @@ -154,7 +165,7 @@ class ProjectSpecTests: XCTestCase {
platform: .iOS,
sources: [.init(path: "generated.swift", optional: true)]
)]
try project.validate()
try project.validate(xcodeGenVersion: try Version("1.11.0"))
}

$0.it("validates missing default configurations") {
Expand All @@ -166,9 +177,9 @@ class ProjectSpecTests: XCTestCase {
}
}

fileprivate func expectValidationError(_ project: Project, _ expectedError: SpecValidationError.ValidationError, file: String = #file, line: Int = #line) throws {
fileprivate func expectValidationError(xcodeGenVersion: Version = try! Version("1.11.0"), _ project: Project, _ expectedError: SpecValidationError.ValidationError, file: String = #file, line: Int = #line) throws {
do {
try project.validate()
try project.validate(xcodeGenVersion: xcodeGenVersion)
} catch let error as SpecValidationError {
if !error.errors
.contains(where: { $0.description == expectedError.description }) {
Expand Down

0 comments on commit a69cae6

Please sign in to comment.