Skip to content
Open
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
29 changes: 29 additions & 0 deletions Sources/XcodeProj/Utils/ReferenceGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,35 @@ final class ReferenceGenerator: ReferenceGenerating {
}

fixReference(for: synchronizedRootGroup, identifiers: identifiers)

// Generate references for exception sets
if let exceptions = synchronizedRootGroup.exceptions {
try exceptions.forEach { exception in
try generateExceptionSetReferences(exception, identifiers: identifiers)
}
}
}

/// Generates the reference for an exception set object.
///
/// - Parameters:
/// - exceptionSet: exception set instance.
/// - identifiers: list of identifiers.
private func generateExceptionSetReferences(_ exceptionSet: PBXFileSystemSynchronizedExceptionSet,
identifiers: [String]) throws {
var identifiers = identifiers

if let buildFileException = exceptionSet as? PBXFileSystemSynchronizedBuildFileExceptionSet {
if let target = buildFileException.target {
identifiers.append(target.reference.value)
}
fixReference(for: buildFileException, identifiers: identifiers)
} else if let buildPhaseException = exceptionSet as? PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet {
if let buildPhase = buildPhaseException.buildPhase {
identifiers.append(buildPhase.reference.value)
}
fixReference(for: buildPhaseException, identifiers: identifiers)
}
}

/// Generates the reference for a configuration list object.
Expand Down
62 changes: 60 additions & 2 deletions Tests/XcodeProjTests/Utils/ReferenceGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,63 @@ class ReferenceGeneratorTests: XCTestCase {

XCTAssert(!syncedGroup.reference.temporary)
}

func test_projectWithFilesystemSynchronizedRootGroupWithExceptions_convertsReferencesToPermanent() throws {
let project = PBXProj(rootObject: nil, objectVersion: 0, archiveVersion: 0, classes: [:], objects: [])
let pbxProject = project.makeProject()

let target = project.makeTarget()
pbxProject.targets.append(target)

let buildFileException = PBXFileSystemSynchronizedBuildFileExceptionSet(
target: target,
membershipExceptions: ["Info.plist"],
publicHeaders: nil,
privateHeaders: nil,
additionalCompilerFlagsByRelativePath: nil,
attributesByRelativePath: nil
)
project.add(object: buildFileException)

let syncedGroup = project.makeSynchronizedRootGroup(exceptions: [buildFileException])
target.fileSystemSynchronizedGroups = [syncedGroup]

let referenceGenerator = ReferenceGenerator(outputSettings: PBXOutputSettings())
try referenceGenerator.generateReferences(proj: project)

XCTAssert(!syncedGroup.reference.temporary, "Synced group reference should not be temporary")
XCTAssert(!buildFileException.reference.temporary, "Build file exception reference should not be temporary")
XCTAssertFalse(buildFileException.reference.value.hasPrefix("TEMP_"), "Build file exception reference should not have TEMP_ prefix")
}

func test_projectWithFilesystemSynchronizedRootGroupWithBuildPhaseException_convertsReferencesToPermanent() throws {
let project = PBXProj(rootObject: nil, objectVersion: 0, archiveVersion: 0, classes: [:], objects: [])
let pbxProject = project.makeProject()

let target = project.makeTarget()
pbxProject.targets.append(target)

let buildPhase = PBXSourcesBuildPhase()
project.add(object: buildPhase)
target.buildPhases.append(buildPhase)

let buildPhaseException = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet(
buildPhase: buildPhase,
membershipExceptions: ["ExcludedFile.swift"],
attributesByRelativePath: nil
)
project.add(object: buildPhaseException)

let syncedGroup = project.makeSynchronizedRootGroup(exceptions: [buildPhaseException])
target.fileSystemSynchronizedGroups = [syncedGroup]

let referenceGenerator = ReferenceGenerator(outputSettings: PBXOutputSettings())
try referenceGenerator.generateReferences(proj: project)

XCTAssert(!syncedGroup.reference.temporary, "Synced group reference should not be temporary")
XCTAssert(!buildPhaseException.reference.temporary, "Build phase exception reference should not be temporary")
XCTAssertFalse(buildPhaseException.reference.value.hasPrefix("TEMP_"), "Build phase exception reference should not have TEMP_ prefix")
}
}

private extension PBXProj {
Expand Down Expand Up @@ -192,11 +249,12 @@ private extension PBXProj {
return target
}

func makeSynchronizedRootGroup() -> PBXFileSystemSynchronizedRootGroup {
func makeSynchronizedRootGroup(exceptions: [PBXFileSystemSynchronizedExceptionSet] = []) -> PBXFileSystemSynchronizedRootGroup {
let syncedGroup = PBXFileSystemSynchronizedRootGroup(
sourceTree: .group,
path: "SyncedPath",
name: "SyncedGroup"
name: "SyncedGroup",
exceptions: exceptions
)
add(object: syncedGroup)
rootObject!.mainGroup.children.append(syncedGroup)
Expand Down