Skip to content

Commit

Permalink
Add ability to initialize scheme without a blueprint identifier (#612)
Browse files Browse the repository at this point in the history
* Add ability to initialize scheme without a blueprint identifier

* Add test for serialization

* Update changelog

Co-authored-by: Pedro Piñera Buendía <pedro@ppinera.es>
  • Loading branch information
daltonclaybrook and Pedro Piñera Buendía committed Jun 17, 2021
1 parent 3bfa83f commit 5115e42
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Fixed

- Adding group set incorrect parent in case of complex path [#614](https://github.com/tuist/XcodeProj/pull/614) by [@avdyushin](https://github.com/avdyushin)
- **Breaking** Fixed issue where some schemes could not be deserialized because a buildable reference did not contain a blueprint identifier [#612](https://github.com/tuist/XcodeProj/pull/612) by [@daltonclaybrook](https://github.com/daltonclaybrook)
- Added the `com.apple.product-type.driver-extension` and `com.apple.product-type.system-extension` PBXProductType [#618](https://github.com/tuist/XcodeProj/pull/618) by [@vgorloff](https://github.com/vgorloff).

### Changed
Expand Down
33 changes: 33 additions & 0 deletions Fixtures/Schemes/NoBlueprintID.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme LastUpgradeVersion = "9999" version = "1.3">
<BuildAction parallelizeBuildables = "YES" buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry buildForTesting = "YES" buildForRunning = "YES" buildForProfiling = "YES" buildForArchiving = "YES" buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BuildableName = "'lib$(TARGET_NAME)'"
BlueprintName = "NoBlueprintID"
ReferencedContainer = "container:NoBlueprintID.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "NO">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BuildableName = "'$(TARGET_NAME)'"
BlueprintName = "NoBlueprintIDTests"
ReferencedContainer = "container:NoBlueprintID.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
</Scheme>
41 changes: 21 additions & 20 deletions Sources/XcodeProj/Scheme/XCScheme+BuildableReference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ extension XCScheme {
blueprint = .reference(object.reference)
}

private var blueprint: Blueprint
public var blueprintIdentifier: String {
blueprint.string
private var blueprint: Blueprint?
public var blueprintIdentifier: String? {
blueprint?.string
}

public var buildableName: String
Expand All @@ -35,24 +35,24 @@ extension XCScheme {
// MARK: - Init

public init(referencedContainer: String,
blueprint: PBXObject,
blueprint: PBXObject?,
buildableName: String,
blueprintName: String,
buildableIdentifier: String = "primary") {
self.referencedContainer = referencedContainer
self.blueprint = .reference(blueprint.reference)
self.blueprint = blueprint.map { Blueprint.reference($0.reference) }
self.buildableName = buildableName
self.buildableIdentifier = buildableIdentifier
self.blueprintName = blueprintName
}

public init(referencedContainer: String,
blueprintIdentifier: String,
blueprintIdentifier: String?,
buildableName: String,
blueprintName: String,
buildableIdentifier: String = "primary") {
self.referencedContainer = referencedContainer
self.blueprint = .string(blueprintIdentifier)
self.blueprint = blueprintIdentifier.map(Blueprint.string)
self.buildableName = buildableName
self.buildableIdentifier = buildableIdentifier
self.blueprintName = blueprintName
Expand All @@ -64,9 +64,6 @@ extension XCScheme {
guard let buildableIdentifier = element.attributes["BuildableIdentifier"] else {
throw XCSchemeError.missing(property: "BuildableIdentifier")
}
guard let blueprintIdentifier = element.attributes["BlueprintIdentifier"] else {
throw XCSchemeError.missing(property: "BlueprintIdentifier")
}
guard let buildableName = element.attributes["BuildableName"] else {
throw XCSchemeError.missing(property: "BuildableName")
}
Expand All @@ -77,22 +74,26 @@ extension XCScheme {
throw XCSchemeError.missing(property: "ReferencedContainer")
}
self.buildableIdentifier = buildableIdentifier
blueprint = .string(blueprintIdentifier)
let blueprintIdentifier = element.attributes["BlueprintIdentifier"]
self.blueprint = blueprintIdentifier.map(Blueprint.string)
self.buildableName = buildableName
self.blueprintName = blueprintName
self.referencedContainer = referencedContainer
}

func xmlElement() -> AEXMLElement {
AEXMLElement(name: "BuildableReference",
value: nil,
attributes: [
"BuildableIdentifier": buildableIdentifier,
"BlueprintIdentifier": blueprint.string,
"BuildableName": buildableName,
"BlueprintName": blueprintName,
"ReferencedContainer": referencedContainer,
])
var attributes: [String: String] = [
"BuildableIdentifier": buildableIdentifier,
"BuildableName": buildableName,
"BlueprintName": blueprintName,
"ReferencedContainer": referencedContainer,
]
if let blueprintIdentifier = blueprint?.string {
attributes["BlueprintIdentifier"] = blueprintIdentifier
}
return AEXMLElement(name: "BuildableReference",
value: nil,
attributes: attributes)
}

// MARK: - Equatable
Expand Down
18 changes: 18 additions & 0 deletions Tests/XcodeProjTests/Scheme/XCSchemeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,19 @@ final class XCSchemeIntegrationTests: XCTestCase {
XCTAssertNotEqual(runnableA1, remoteRunnableA1)
}

func test_schemeWithoutBlueprintIdentifier_canBeCreated() {
let subject = try? XCScheme(path: noBlueprintIDPath)
XCTAssertNotNil(subject)
}

func test_schemeWithoutBlueprintIdentifier_serializesWithoutBlueprintIdentifier() throws {
let subject = try XCScheme(path: noBlueprintIDPath)
let buildable = try XCTUnwrap(subject.buildAction?.buildActionEntries.first?.buildableReference)
let buildableXML = buildable.xmlElement()
XCTAssertNotNil(buildableXML.attributes["BlueprintName"])
XCTAssertNil(buildableXML.attributes["BlueprintIdentifier"])
}

func test_buildAction_runPostActionsOnFailure() throws {
// Given / When
let subject = try XCScheme(path: runPostActionsOnFailureSchemePath)
Expand Down Expand Up @@ -545,6 +558,11 @@ final class XCSchemeIntegrationTests: XCTestCase {
fixturesPath() + "Schemes/MinimalInformation.xcscheme"
}

/// Path to a scheme with a buildable reference that contains no blueprint identifier
private var noBlueprintIDPath: Path {
fixturesPath() + "Schemes/NoBlueprintID.xcscheme"
}

private var watchAppSchemePath: Path {
fixturesPath() + "iOS/AppWithExtensions/AppWithExtensions.xcodeproj/xcshareddata/xcschemes/WatchApp.xcscheme"
}
Expand Down

0 comments on commit 5115e42

Please sign in to comment.