Skip to content

Commit 53e43db

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 callsites to use package identity instead of location when reading/writing managed depedencies * refactor related call-sites to handle edited state more safely and correctly * adjust tests where needed
1 parent 6f8a435 commit 53e43db

File tree

7 files changed

+450
-405
lines changed

7 files changed

+450
-405
lines changed

Sources/SPMTestSupport/MockWorkspace.swift

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,8 @@ public final class MockWorkspace {
378378

379379
public func set(
380380
pins: [PackageReference: CheckoutState] = [:],
381-
managedDependencies: [ManagedDependency] = [],
382-
managedArtifacts: [ManagedArtifact] = []
381+
managedDependencies: [Workspace.ManagedDependency] = [],
382+
managedArtifacts: [Workspace.ManagedArtifact] = []
383383
) throws {
384384
let workspace = try self.getOrCreateWorkspace()
385385
let pinsStore = try workspace.pinsStore.load()
@@ -420,24 +420,32 @@ public final class MockWorkspace {
420420
}
421421

422422
public struct ManagedDependencyResult {
423-
public let managedDependencies: ManagedDependencies
423+
public let managedDependencies: Workspace.ManagedDependencies
424424

425-
public init(_ managedDependencies: ManagedDependencies) {
425+
public init(_ managedDependencies: Workspace.ManagedDependencies) {
426426
self.managedDependencies = managedDependencies
427427
}
428428

429429
public func check(notPresent name: String, file: StaticString = #file, line: UInt = #line) {
430-
let dependency = self.managedDependencies[forNameOrIdentity: name]
431-
XCTAssert(dependency == nil, "Unexpectedly found \(name) in managed dependencies", file: file, line: line)
430+
self.check(notPresent: .plain(name), file: file, line: line)
431+
}
432+
433+
public func check(notPresent dependencyId: PackageIdentity, file: StaticString = #file, line: UInt = #line) {
434+
let dependency = self.managedDependencies[dependencyId]
435+
XCTAssertNil(dependency, "Unexpectedly found \(dependencyId) in managed dependencies", file: file, line: line)
432436
}
433437

434438
public func checkEmpty(file: StaticString = #file, line: UInt = #line) {
435439
XCTAssertEqual(self.managedDependencies.count, 0, file: file, line: line)
436440
}
437441

438442
public func check(dependency name: String, at state: State, file: StaticString = #file, line: UInt = #line) {
439-
guard let dependency = managedDependencies[forNameOrIdentity: name] else {
440-
XCTFail("\(name) does not exists", file: file, line: line)
443+
self.check(dependency: .plain(name), at: state, file: file, line: line)
444+
}
445+
446+
public func check(dependency dependencyId: PackageIdentity, at state: State, file: StaticString = #file, line: UInt = #line) {
447+
guard let dependency = managedDependencies[dependencyId] else {
448+
XCTFail("\(dependencyId) does not exists", file: file, line: line)
441449
return
442450
}
443451
switch state {
@@ -451,8 +459,9 @@ public final class MockWorkspace {
451459
XCTAssertEqual(dependency.checkoutState?.branch, branch, file: file, line: line)
452460
}
453461
case .edited(let path):
454-
if dependency.state != .edited(path) {
462+
guard case .edited(_, unmanagedPath: path) = dependency.state else {
455463
XCTFail("Expected edited dependency; found '\(dependency.state)' instead", file: file, line: line)
464+
return
456465
}
457466
case .local:
458467
if dependency.state != .local {
@@ -463,9 +472,9 @@ public final class MockWorkspace {
463472
}
464473

465474
public struct ManagedArtifactResult {
466-
public let managedArtifacts: ManagedArtifacts
475+
public let managedArtifacts: Workspace.ManagedArtifacts
467476

468-
public init(_ managedArtifacts: ManagedArtifacts) {
477+
public init(_ managedArtifacts: Workspace.ManagedArtifacts) {
469478
self.managedArtifacts = managedArtifacts
470479
}
471480

@@ -486,7 +495,7 @@ public final class MockWorkspace {
486495
public func check(
487496
packageName: String,
488497
targetName: String,
489-
source: ManagedArtifact.Source,
498+
source: Workspace.ManagedArtifact.Source,
490499
path: AbsolutePath,
491500
file: StaticString = #file,
492501
line: UInt = #line
@@ -718,3 +727,12 @@ extension CheckoutState {
718727
}
719728
}
720729
}
730+
731+
extension Workspace.ManagedDependency {
732+
public var checkoutState: CheckoutState? {
733+
if case .checkout(let checkoutState) = state {
734+
return checkoutState
735+
}
736+
return nil
737+
}
738+
}

Sources/Workspace/ManagedArtifact.swift

Lines changed: 91 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -14,83 +14,83 @@ import SourceControl
1414
import TSCBasic
1515
import TSCUtility
1616

17-
/// A downloaded artifact managed by the workspace.
18-
public struct ManagedArtifact {
19-
/// The package reference.
20-
public let packageRef: PackageReference
21-
22-
/// The name of the binary target the artifact corresponds to.
23-
public let targetName: String
24-
25-
/// The source of the artifact (local or remote).
26-
public let source: Source
27-
28-
/// The path of the artifact on disk
29-
public let path: AbsolutePath
30-
31-
public init(
32-
packageRef: PackageReference,
33-
targetName: String,
34-
source: Source,
35-
path: AbsolutePath
36-
) {
37-
self.packageRef = packageRef
38-
self.targetName = targetName
39-
self.source = source
40-
self.path = path
41-
}
17+
extension Workspace {
18+
/// A downloaded artifact managed by the workspace.
19+
public struct ManagedArtifact {
20+
/// The package reference.
21+
public let packageRef: PackageReference
22+
23+
/// The name of the binary target the artifact corresponds to.
24+
public let targetName: String
25+
26+
/// The source of the artifact (local or remote).
27+
public let source: Source
28+
29+
/// The path of the artifact on disk
30+
public let path: AbsolutePath
31+
32+
public init(
33+
packageRef: PackageReference,
34+
targetName: String,
35+
source: Source,
36+
path: AbsolutePath
37+
) {
38+
self.packageRef = packageRef
39+
self.targetName = targetName
40+
self.source = source
41+
self.path = path
42+
}
4243

43-
/// Create an artifact downloaded from a remote url.
44-
public static func remote(
45-
packageRef: PackageReference,
46-
targetName: String,
47-
url: String,
48-
checksum: String,
49-
path: AbsolutePath
50-
) -> ManagedArtifact {
51-
return ManagedArtifact(
52-
packageRef: packageRef,
53-
targetName: targetName,
54-
source: .remote(url: url, checksum: checksum),
55-
path: path
56-
)
57-
}
44+
/// Create an artifact downloaded from a remote url.
45+
public static func remote(
46+
packageRef: PackageReference,
47+
targetName: String,
48+
url: String,
49+
checksum: String,
50+
path: AbsolutePath
51+
) -> ManagedArtifact {
52+
return ManagedArtifact(
53+
packageRef: packageRef,
54+
targetName: targetName,
55+
source: .remote(url: url, checksum: checksum),
56+
path: path
57+
)
58+
}
5859

59-
/// Create an artifact present locally on the filesystem.
60-
public static func local(
61-
packageRef: PackageReference,
62-
targetName: String,
63-
path: AbsolutePath
64-
) -> ManagedArtifact {
65-
return ManagedArtifact(
66-
packageRef: packageRef,
67-
targetName: targetName,
68-
source: .local,
69-
path: path
70-
)
71-
}
60+
/// Create an artifact present locally on the filesystem.
61+
public static func local(
62+
packageRef: PackageReference,
63+
targetName: String,
64+
path: AbsolutePath
65+
) -> ManagedArtifact {
66+
return ManagedArtifact(
67+
packageRef: packageRef,
68+
targetName: targetName,
69+
source: .local,
70+
path: path
71+
)
72+
}
7273

73-
/// Represents the source of the artifact.
74-
public enum Source: Equatable {
74+
/// Represents the source of the artifact.
75+
public enum Source: Equatable {
7576

76-
/// Represents a remote artifact, with the url it was downloaded from, its checksum, and its path relative to
77-
/// the workspace artifacts path.
78-
case remote(url: String, checksum: String)
77+
/// Represents a remote artifact, with the url it was downloaded from, its checksum, and its path relative to
78+
/// the workspace artifacts path.
79+
case remote(url: String, checksum: String)
7980

80-
/// Represents a locally available artifact, with its path relative to its package.
81-
case local
81+
/// Represents a locally available artifact, with its path relative to its package.
82+
case local
83+
}
8284
}
8385
}
8486

85-
// MARK: - CustomStringConvertible
86-
87-
extension ManagedArtifact: CustomStringConvertible {
87+
extension Workspace.ManagedArtifact: CustomStringConvertible {
8888
public var description: String {
8989
return "<ManagedArtifact: \(self.packageRef.name).\(self.targetName) \(self.source) \(self.path)>"
9090
}
9191
}
9292

93-
extension ManagedArtifact.Source: CustomStringConvertible {
93+
extension Workspace.ManagedArtifact.Source: CustomStringConvertible {
9494
public var description: String {
9595
switch self {
9696
case .local:
@@ -101,42 +101,42 @@ extension ManagedArtifact.Source: CustomStringConvertible {
101101
}
102102
}
103103

104-
// MARK: -
104+
// MARK: - ManagedArtifacts
105105

106-
/// A collection of managed artifacts which have been downloaded.
107-
public final class ManagedArtifacts {
106+
extension Workspace {
107+
/// A collection of managed artifacts which have been downloaded.
108+
public final class ManagedArtifacts {
108109

109-
/// A mapping from package url, to target name, to ManagedArtifact.
110-
private var artifactMap: [String: [String: ManagedArtifact]]
110+
/// A mapping from package url, to target name, to ManagedArtifact.
111+
private var artifactMap: [String: [String: ManagedArtifact]]
111112

112-
internal var artifacts: AnyCollection<ManagedArtifact> {
113-
AnyCollection(artifactMap.values.lazy.flatMap({ $0.values }))
114-
}
113+
internal var artifacts: AnyCollection<ManagedArtifact> {
114+
AnyCollection(artifactMap.values.lazy.flatMap({ $0.values }))
115+
}
115116

116-
init(artifactMap: [String: [String: ManagedArtifact]] = [:]) {
117-
self.artifactMap = artifactMap
118-
}
117+
init(artifactMap: [String: [String: ManagedArtifact]] = [:]) {
118+
self.artifactMap = artifactMap
119+
}
119120

120-
public subscript(packageURL packageURL: String, targetName targetName: String) -> ManagedArtifact? {
121-
artifactMap[packageURL]?[targetName]
122-
}
121+
public subscript(packageURL packageURL: String, targetName targetName: String) -> ManagedArtifact? {
122+
artifactMap[packageURL]?[targetName]
123+
}
123124

124-
public subscript(packageName packageName: String, targetName targetName: String) -> ManagedArtifact? {
125-
artifacts.first(where: { $0.packageRef.name == packageName && $0.targetName == targetName })
126-
}
125+
public subscript(packageName packageName: String, targetName targetName: String) -> ManagedArtifact? {
126+
artifacts.first(where: { $0.packageRef.name == packageName && $0.targetName == targetName })
127+
}
127128

128-
public func add(_ artifact: ManagedArtifact) {
129-
artifactMap[artifact.packageRef.location, default: [:]][artifact.targetName] = artifact
130-
}
129+
public func add(_ artifact: ManagedArtifact) {
130+
artifactMap[artifact.packageRef.location, default: [:]][artifact.targetName] = artifact
131+
}
131132

132-
public func remove(packageURL: String, targetName: String) {
133-
artifactMap[packageURL]?[targetName] = nil
133+
public func remove(packageURL: String, targetName: String) {
134+
artifactMap[packageURL]?[targetName] = nil
135+
}
134136
}
135137
}
136138

137-
// MARK: - Collection
138-
139-
extension ManagedArtifacts: Collection {
139+
extension Workspace.ManagedArtifacts: Collection {
140140
public var startIndex: AnyIndex {
141141
artifacts.startIndex
142142
}
@@ -145,7 +145,7 @@ extension ManagedArtifacts: Collection {
145145
artifacts.endIndex
146146
}
147147

148-
public subscript(index: AnyIndex) -> ManagedArtifact {
148+
public subscript(index: AnyIndex) -> Workspace.ManagedArtifact {
149149
artifacts[index]
150150
}
151151

@@ -154,9 +154,7 @@ extension ManagedArtifacts: Collection {
154154
}
155155
}
156156

157-
// MARK: - CustomStringConvertible
158-
159-
extension ManagedArtifacts: CustomStringConvertible {
157+
extension Workspace.ManagedArtifacts: CustomStringConvertible {
160158
public var description: String {
161159
"<ManagedArtifacts: \(Array(artifacts))>"
162160
}

0 commit comments

Comments
 (0)