Skip to content

Commit 3e343ce

Browse files
committed
refactor ManagedDependencies
motivation: ManagedDependencies are based on location instead of on identity, refactor them to be based on identity as part of the transition to identity based logic changes: * transition ManagedDependencies underlying hashmap to be based on identity * update the ManagedDependencies edit state to include the "basedOn" property which is only relevant to that state * update calls ites to use package identity instead of location when reading/writing managed depedencies * refactor related call-sites to handle edited state more safely and correctly * add code comments to explain some of the more subtle business logic * adjust tests where needed
1 parent 18c097d commit 3e343ce

File tree

11 files changed

+429
-361
lines changed

11 files changed

+429
-361
lines changed

Sources/PackageGraph/PackageGraph+Loading.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extension PackageGraph {
2222
root: PackageGraphRoot,
2323
identityResolver: IdentityResolver,
2424
additionalFileRules: [FileRuleDescription] = [],
25-
externalManifests: [Manifest],
25+
externalManifests: OrderedDictionary<PackageIdentity, Manifest>,
2626
requiredDependencies: Set<PackageReference> = [],
2727
unsafeAllowedPackages: Set<PackageReference> = [],
2828
binaryArtifacts: [BinaryArtifact] = [],
@@ -35,11 +35,11 @@ extension PackageGraph {
3535
let observabilityScope = ObservabilitySystem.topScope.makeChildScope(description: "Loading Package Graph")
3636

3737
// Create a map of the manifests, keyed by their identity.
38-
let rootManifestsMap = root.manifests
39-
let externalManifestsMap = try externalManifests.map{ (try identityResolver.resolveIdentity(for: $0.packageKind), $0) }
40-
let manifestMap = rootManifestsMap.merging(externalManifestsMap, uniquingKeysWith: { lhs, rhs in
41-
return lhs
42-
})
38+
var manifestMap = externalManifests
39+
// prefer roots
40+
root.manifests.forEach {
41+
manifestMap[$0.key] = $0.value
42+
}
4343

4444
let successors: (GraphLoadingNode) -> [GraphLoadingNode] = { node in
4545
node.requiredDependencies().compactMap{ dependency in

Sources/PackageModel/PackageIdentity.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public struct PackageIdentity: CustomStringConvertible {
4646
}
4747

4848
/// Creates a package identity from a URL.
49-
/// - Parameter url: The package's URL.
49+
/// - Parameter urlString: The package's URL.
5050
// FIXME: deprecate this
5151
public init(urlString: String) {
5252
self.description = Self.provider.init(urlString).description

Sources/PackageModel/PackageReference.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,16 @@ public struct PackageReference: Encodable {
115115
}
116116

117117
extension PackageReference: Equatable {
118+
// TODO: consider location as well?
118119
public static func ==(lhs: PackageReference, rhs: PackageReference) -> Bool {
119120
return lhs.identity == rhs.identity
120121
}
121122
}
122123

123124
extension PackageReference: Hashable {
125+
// TODO: consider location as well?
124126
public func hash(into hasher: inout Hasher) {
125-
hasher.combine(identity)
127+
hasher.combine(self.identity)
126128
}
127129
}
128130

Sources/SPMTestSupport/MockWorkspace.swift

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ public final class MockWorkspace {
405405

406406
public func set(
407407
pins: [PackageReference: CheckoutState] = [:],
408-
managedDependencies: [ManagedDependency] = [],
408+
managedDependencies: [Workspace.ManagedDependency] = [],
409409
managedArtifacts: [Workspace.ManagedArtifact] = []
410410
) throws {
411411
let workspace = try self.getOrCreateWorkspace()
@@ -426,7 +426,7 @@ public final class MockWorkspace {
426426
workspace.state.artifacts.add(artifact)
427427
}
428428

429-
try workspace.state.saveState()
429+
try workspace.state.save()
430430
}
431431

432432
public func resetState() throws {
@@ -447,24 +447,32 @@ public final class MockWorkspace {
447447
}
448448

449449
public struct ManagedDependencyResult {
450-
public let managedDependencies: ManagedDependencies
450+
public let managedDependencies: Workspace.ManagedDependencies
451451

452-
public init(_ managedDependencies: ManagedDependencies) {
452+
public init(_ managedDependencies: Workspace.ManagedDependencies) {
453453
self.managedDependencies = managedDependencies
454454
}
455455

456456
public func check(notPresent name: String, file: StaticString = #file, line: UInt = #line) {
457-
let dependency = self.managedDependencies[forNameOrIdentity: name]
458-
XCTAssert(dependency == nil, "Unexpectedly found \(name) in managed dependencies", file: file, line: line)
457+
self.check(notPresent: .plain(name), file: file, line: line)
458+
}
459+
460+
public func check(notPresent dependencyId: PackageIdentity, file: StaticString = #file, line: UInt = #line) {
461+
let dependency = self.managedDependencies[dependencyId]
462+
XCTAssertNil(dependency, "Unexpectedly found \(dependencyId) in managed dependencies", file: file, line: line)
459463
}
460464

461465
public func checkEmpty(file: StaticString = #file, line: UInt = #line) {
462466
XCTAssertEqual(self.managedDependencies.count, 0, file: file, line: line)
463467
}
464468

465469
public func check(dependency name: String, at state: State, file: StaticString = #file, line: UInt = #line) {
466-
guard let dependency = managedDependencies[forNameOrIdentity: name] else {
467-
XCTFail("\(name) does not exists", file: file, line: line)
470+
self.check(dependency: .plain(name), at: state, file: file, line: line)
471+
}
472+
473+
public func check(dependency dependencyId: PackageIdentity, at state: State, file: StaticString = #file, line: UInt = #line) {
474+
guard let dependency = managedDependencies[dependencyId] else {
475+
XCTFail("\(dependencyId) does not exists", file: file, line: line)
468476
return
469477
}
470478
switch state {
@@ -478,8 +486,9 @@ public final class MockWorkspace {
478486
XCTAssertEqual(dependency.checkoutState?.branch, branch, file: file, line: line)
479487
}
480488
case .edited(let path):
481-
if dependency.state != .edited(path) {
489+
guard case .edited(_, unmanagedPath: path) = dependency.state else {
482490
XCTFail("Expected edited dependency; found '\(dependency.state)' instead", file: file, line: line)
491+
return
483492
}
484493
case .local:
485494
if dependency.state != .local {
@@ -757,8 +766,8 @@ extension CheckoutState {
757766
}
758767
}
759768

760-
fileprivate extension PackageReference.Kind {
761-
var displayName: String {
769+
extension PackageReference.Kind {
770+
fileprivate var displayName: String {
762771
switch self {
763772
case .root:
764773
return "root"
@@ -771,3 +780,12 @@ fileprivate extension PackageReference.Kind {
771780
}
772781
}
773782
}
783+
784+
extension Workspace.ManagedDependency {
785+
fileprivate var checkoutState: CheckoutState? {
786+
if case .checkout(let checkoutState) = state {
787+
return checkoutState
788+
}
789+
return .none
790+
}
791+
}

Sources/SPMTestSupport/misc.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,10 @@ public func loadPackageGraph(
229229
useXCBuildFileRules: Bool = false
230230
) throws -> PackageGraph {
231231
let rootManifests = manifests.filter { $0.packageKind.isRoot }.spm_createDictionary{ ($0.path, $0) }
232-
let externalManifests = manifests.filter { !$0.packageKind.isRoot }
232+
let externalManifests = try manifests.filter { !$0.packageKind.isRoot }.reduce(into: OrderedDictionary<PackageIdentity, Manifest>()) { partial, item in
233+
partial[try identityResolver.resolveIdentity(for: item.packageKind)] = item
234+
}
235+
233236
let packages = Array(rootManifests.keys)
234237
let input = PackageGraphRootInput(packages: packages)
235238
let graphRoot = PackageGraphRoot(input: input, manifests: rootManifests, explicitProduct: explicitProduct)

0 commit comments

Comments
 (0)