Skip to content

Commit

Permalink
Fix issue that it is not possible to remove a remote package (#803)
Browse files Browse the repository at this point in the history
Resolves #802

Issue:

- Package references's setter implementation only allowed appending new elements and didn't support removing them as the `packageReferences` array is shared between both `localPackages` and `remotePackages`.

Changes:

- It checks that only the references are kept that are not part of the current type. 
- This is done by getting the object of the reference and checking the type of this reference.
- Unit test was added to verify removal case

Notes:

- To correctly remove a package, there's a few other objects and references that need to be removed _(not just the element from `packageReferences`)_
  • Loading branch information
kevin-kp authored Nov 27, 2023
1 parent 447c159 commit 338e983
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 16 deletions.
29 changes: 13 additions & 16 deletions Sources/XcodeProj/Objects/Project/PBXProject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,7 @@ public final class PBXProject: PBXObject {
/// Remote Swift packages.
public var remotePackages: [XCRemoteSwiftPackageReference] {
set {
var finalReferences: [PBXObjectReference] = packageReferences ?? []
let newReferences = newValue.references()
for reference in newReferences {
if !finalReferences.contains(reference) {
finalReferences.append(reference)
}
}
packageReferences = finalReferences
setPackageReferences(newValue)
}
get {
packageReferences?.objects() ?? []
Expand All @@ -154,20 +147,24 @@ public final class PBXProject: PBXObject {
/// Local Swift packages.
public var localPackages: [XCLocalSwiftPackageReference] {
set {
var finalReferences: [PBXObjectReference] = packageReferences ?? []
let newReferences = newValue.references()
for reference in newReferences {
if !finalReferences.contains(reference) {
finalReferences.append(reference)
}
}
packageReferences = finalReferences
setPackageReferences(newValue)
}
get {
packageReferences?.objects() ?? []
}
}

private func setPackageReferences<T: PBXContainerItem>(_ packages: [T]) {
let newReferences = packages.references()
var finalReferences: [PBXObjectReference] = packageReferences?.filter { !($0.getObject() is T) } ?? []
for reference in newReferences {
if !finalReferences.contains(reference) {
finalReferences.append(reference)
}
}
packageReferences = finalReferences
}

/// Sets the attributes for the given target.
///
/// - Parameters:
Expand Down
40 changes: 40 additions & 0 deletions Tests/XcodeProjTests/Objects/Project/PBXProjectTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,46 @@ final class PBXProjectTests: XCTestCase {
PBXProjError.frameworksBuildPhaseNotFound(targetName: target.name))
}

func test_removeRemotePackage() throws {
// Given
let objects = PBXObjects(objects: [])

let buildPhase = PBXFrameworksBuildPhase(
files: [],
inputFileListPaths: nil,
outputFileListPaths: nil, buildActionMask: PBXBuildPhase.defaultBuildActionMask,
runOnlyForDeploymentPostprocessing: true
)
let target = PBXNativeTarget(name: "Target",
buildConfigurationList: nil,
buildPhases: [buildPhase])
objects.add(object: target)

let configurationList = XCConfigurationList.fixture()
let mainGroup = PBXGroup.fixture()
objects.add(object: configurationList)
objects.add(object: mainGroup)

let project = PBXProject(name: "Project",
buildConfigurationList: configurationList,
compatibilityVersion: "0",
mainGroup: mainGroup,
targets: [target])

objects.add(object: project)

let _ = try project.addSwiftPackage(repositoryURL: "url",
productName: "Product",
versionRequirement: .branch("main"),
targetName: "Target")

// When
project.remotePackages.removeFirst()

// Then
XCTAssert(project.remotePackages.isEmpty)
}

func test_addSwiftPackage() throws {
// Given
let objects = PBXObjects(objects: [])
Expand Down

0 comments on commit 338e983

Please sign in to comment.