Skip to content

Commit 0f377e0

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 70975dc commit 0f377e0

File tree

10 files changed

+434
-362
lines changed

10 files changed

+434
-362
lines changed

Sources/PackageGraph/PackageGraph+Loading.swift

Lines changed: 14 additions & 5 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] = [],
@@ -36,10 +36,19 @@ extension PackageGraph {
3636

3737
// Create a map of the manifests, keyed by their identity.
3838
let rootManifestsMap = root.manifests
39-
let externalManifestsMap = externalManifests.map{ (identityResolver.resolveIdentity(for: $0.packageLocation), $0) }
40-
let manifestMap = rootManifestsMap.merging(externalManifestsMap, uniquingKeysWith: { lhs, rhs in
41-
return lhs
42-
})
39+
//let externalManifestsMap = externalManifests.map{ (identityResolver.resolveIdentity(for: $0.packageLocation), $0) }
40+
//let manifestMap = rootManifestsMap.merging(externalManifests, uniquingKeysWith: { lhs, rhs in
41+
// return lhs
42+
//})
43+
44+
// prefer roots
45+
var manifestMap = rootManifestsMap
46+
externalManifests.forEach {
47+
if !manifestMap.keys.contains($0.key) {
48+
manifestMap[$0.key] = $0.value
49+
}
50+
}
51+
4352

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

Sources/PackageModel/PackageReference.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,20 @@ public struct PackageReference: Codable {
7171

7272
extension PackageReference: Equatable {
7373
public static func ==(lhs: PackageReference, rhs: PackageReference) -> Bool {
74-
return lhs.identity == rhs.identity
74+
return lhs.identity == rhs.identity //&& lhs.location == rhs.location
7575
}
7676
}
7777

7878
extension PackageReference: Hashable {
7979
public func hash(into hasher: inout Hasher) {
80-
hasher.combine(identity)
80+
hasher.combine(self.identity)
81+
//hasher.combine(self.location)
8182
}
8283
}
8384

8485
extension PackageReference: CustomStringConvertible {
8586
public var description: String {
86-
return "\(identity)\(self.location.isEmpty ? "" : "[\(self.location)]")"
87+
return "\(self.identity)\(self.location.isEmpty ? "" : "[\(self.location)]")"
8788
}
8889
}
8990

Sources/SPMTestSupport/MockWorkspace.swift

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ public final class MockWorkspace {
413413

414414
public func set(
415415
pins: [PackageReference: CheckoutState] = [:],
416-
managedDependencies: [ManagedDependency] = [],
416+
managedDependencies: [Workspace.ManagedDependency] = [],
417417
managedArtifacts: [Workspace.ManagedArtifact] = []
418418
) throws {
419419
let workspace = try self.getOrCreateWorkspace()
@@ -434,7 +434,7 @@ public final class MockWorkspace {
434434
workspace.state.artifacts.add(artifact)
435435
}
436436

437-
try workspace.state.saveState()
437+
try workspace.state.save()
438438
}
439439

440440
public func resetState() throws {
@@ -455,24 +455,32 @@ public final class MockWorkspace {
455455
}
456456

457457
public struct ManagedDependencyResult {
458-
public let managedDependencies: ManagedDependencies
458+
public let managedDependencies: Workspace.ManagedDependencies
459459

460-
public init(_ managedDependencies: ManagedDependencies) {
460+
public init(_ managedDependencies: Workspace.ManagedDependencies) {
461461
self.managedDependencies = managedDependencies
462462
}
463463

464464
public func check(notPresent name: String, file: StaticString = #file, line: UInt = #line) {
465-
let dependency = self.managedDependencies[forNameOrIdentity: name]
466-
XCTAssert(dependency == nil, "Unexpectedly found \(name) in managed dependencies", file: file, line: line)
465+
self.check(notPresent: .plain(name), file: file, line: line)
466+
}
467+
468+
public func check(notPresent dependencyId: PackageIdentity, file: StaticString = #file, line: UInt = #line) {
469+
let dependency = self.managedDependencies[dependencyId]
470+
XCTAssertNil(dependency, "Unexpectedly found \(dependencyId) in managed dependencies", file: file, line: line)
467471
}
468472

469473
public func checkEmpty(file: StaticString = #file, line: UInt = #line) {
470474
XCTAssertEqual(self.managedDependencies.count, 0, file: file, line: line)
471475
}
472476

473477
public func check(dependency name: String, at state: State, file: StaticString = #file, line: UInt = #line) {
474-
guard let dependency = managedDependencies[forNameOrIdentity: name] else {
475-
XCTFail("\(name) does not exists", file: file, line: line)
478+
self.check(dependency: .plain(name), at: state, file: file, line: line)
479+
}
480+
481+
public func check(dependency dependencyId: PackageIdentity, at state: State, file: StaticString = #file, line: UInt = #line) {
482+
guard let dependency = managedDependencies[dependencyId] else {
483+
XCTFail("\(dependencyId) does not exists", file: file, line: line)
476484
return
477485
}
478486
switch state {
@@ -486,8 +494,9 @@ public final class MockWorkspace {
486494
XCTAssertEqual(dependency.checkoutState?.branch, branch, file: file, line: line)
487495
}
488496
case .edited(let path):
489-
if dependency.state != .edited(path) {
497+
guard case .edited(_, unmanagedPath: path) = dependency.state else {
490498
XCTFail("Expected edited dependency; found '\(dependency.state)' instead", file: file, line: line)
499+
return
491500
}
492501
case .local:
493502
if dependency.state != .local {
@@ -764,3 +773,12 @@ extension CheckoutState {
764773
}
765774
}
766775
}
776+
777+
extension Workspace.ManagedDependency {
778+
public var checkoutState: CheckoutState? {
779+
if case .checkout(let checkoutState) = state {
780+
return checkoutState
781+
}
782+
return nil
783+
}
784+
}

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 == .root }.spm_createDictionary{ ($0.path, $0) }
232-
let externalManifests = manifests.filter { $0.packageKind != .root }
232+
let externalManifests = manifests.filter { $0.packageKind != .root }.reduce(into: OrderedDictionary<PackageIdentity, Manifest>()) { partial, item in
233+
partial[identityResolver.resolveIdentity(for: item.packageLocation)] = 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)