Skip to content

Commit 90ff0b7

Browse files
authored
Refactor SwiftPMConfig (#3002)
* Make Mirror type fileprivate * Move JSONSerializable conformance into separate extension * Make DependencyMirrors.Error public Conform to CustomStringConvertible in extension * Update SwiftPMConfig implementation to more closely match PinsStore * Add test coverage for SwiftPMConfig * Rename mirroredURL to effectiveURL * Add documentation comments for SwiftPMConfig * Remove unnecessary calls to SwiftPMConfig.load Rename load to restoreState * Create DependencyMirrors collection subtype on SwiftPMConfig * Pass instances of DependencyMirrors instead of SwiftPMConfig to APIs Move SwiftPMConfig type to Workspace module Move DependencyMirrors type to PackageGraph module * Update CMakeLists.txt files * Rename SwiftPMConfig to Workspace.Configuration
1 parent ef31656 commit 90ff0b7

20 files changed

+418
-222
lines changed

Sources/Commands/SwiftPackageTool.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,6 @@ extension SwiftPackageTool.Config {
644644

645645
func run(_ swiftTool: SwiftTool) throws {
646646
let config = try swiftTool.getSwiftPMConfig()
647-
try config.load()
648647

649648
if packageURL != nil {
650649
swiftTool.diagnostics.emit(
@@ -656,7 +655,8 @@ extension SwiftPackageTool.Config {
656655
throw ExitCode.failure
657656
}
658657

659-
try config.set(mirrorURL: mirrorURL, forURL: originalURL)
658+
config.mirrors.set(mirrorURL: mirrorURL, forURL: originalURL)
659+
try config.saveState()
660660
}
661661
}
662662

@@ -678,7 +678,6 @@ extension SwiftPackageTool.Config {
678678

679679
func run(_ swiftTool: SwiftTool) throws {
680680
let config = try swiftTool.getSwiftPMConfig()
681-
try config.load()
682681

683682
if packageURL != nil {
684683
swiftTool.diagnostics.emit(
@@ -690,7 +689,8 @@ extension SwiftPackageTool.Config {
690689
throw ExitCode.failure
691690
}
692691

693-
try config.unset(originalOrMirrorURL: originalOrMirrorURL)
692+
try config.mirrors.unset(originalOrMirrorURL: originalOrMirrorURL)
693+
try config.saveState()
694694
}
695695
}
696696

@@ -709,7 +709,6 @@ extension SwiftPackageTool.Config {
709709

710710
func run(_ swiftTool: SwiftTool) throws {
711711
let config = try swiftTool.getSwiftPMConfig()
712-
try config.load()
713712

714713
if packageURL != nil {
715714
swiftTool.diagnostics.emit(
@@ -721,7 +720,7 @@ extension SwiftPackageTool.Config {
721720
throw ExitCode.failure
722721
}
723722

724-
if let mirror = config.getMirror(forURL: originalURL) {
723+
if let mirror = config.mirrors.getMirror(forURL: originalURL) {
725724
print(mirror)
726725
} else {
727726
stderrStream <<< "not found\n"

Sources/Commands/SwiftTool.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,11 +411,11 @@ public class SwiftTool {
411411
return try getPackageRoot().appending(components: ".swiftpm", "config")
412412
}
413413

414-
func getSwiftPMConfig() throws -> SwiftPMConfig {
414+
func getSwiftPMConfig() throws -> Workspace.Configuration {
415415
return try _swiftpmConfig.get()
416416
}
417-
private lazy var _swiftpmConfig: Result<SwiftPMConfig, Swift.Error> = {
418-
return Result(catching: { SwiftPMConfig(path: try configFilePath()) })
417+
private lazy var _swiftpmConfig: Result<Workspace.Configuration, Swift.Error> = {
418+
return Result(catching: { try Workspace.Configuration(path: try configFilePath()) })
419419
}()
420420

421421
func resolvedNetrcFilePath() -> AbsolutePath? {

Sources/PackageGraph/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
add_library(PackageGraph
1010
BoundVersion.swift
1111
CheckoutState.swift
12+
DependencyMirrors.swift
1213
DependencyResolutionNode.swift
1314
DependencyResolver.swift
1415
Diagnostics.swift
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2018 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import Foundation
12+
13+
import TSCBasic
14+
import TSCUtility
15+
16+
/// A collection of dependency mirrors.
17+
public final class DependencyMirrors {
18+
19+
/// A dependency mirror error.
20+
public enum Error: Swift.Error {
21+
/// No mirror was found for the specified URL.
22+
case mirrorNotFound
23+
}
24+
25+
private var storage: [String: String]
26+
27+
private init(_ mirrors: [Mirror]) {
28+
self.storage = Dictionary(mirrors.map({ ($0.original, $0.mirror) }), uniquingKeysWith: { first, _ in first })
29+
}
30+
31+
/// Sets a mirror URL for the given URL.
32+
public func set(mirrorURL: String, forURL url: String) {
33+
storage[url] = mirrorURL
34+
}
35+
36+
/// Unsets a mirror for the given URL.
37+
/// - Parameter originalOrMirrorURL: The original URL or the mirrored URL
38+
/// - Throws: `Error.mirrorNotFound` if no mirror exists for the provided URL.
39+
public func unset(originalOrMirrorURL: String) throws {
40+
if storage.keys.contains(originalOrMirrorURL) {
41+
storage[originalOrMirrorURL] = nil
42+
} else if let mirror = storage.first(where: { $0.value == originalOrMirrorURL }) {
43+
storage[mirror.key] = nil
44+
} else {
45+
throw Error.mirrorNotFound
46+
}
47+
}
48+
49+
/// Returns the mirrored URL for a package dependency URL.
50+
/// - Parameter url: The original URL
51+
/// - Returns: The mirrored URL, if one exists.
52+
public func getMirror(forURL url: String) -> String? {
53+
return storage[url]
54+
}
55+
56+
/// Returns the effective URL for a package dependency URL.
57+
/// - Parameter url: The original URL
58+
/// - Returns: The mirrored URL if it exists, otherwise the original URL.
59+
public func effectiveURL(forURL url: String) -> String {
60+
return getMirror(forURL: url) ?? url
61+
}
62+
}
63+
64+
extension DependencyMirrors: Collection {
65+
public typealias Index = Dictionary<String, String>.Index
66+
public typealias Element = String
67+
68+
public var startIndex: Index {
69+
storage.startIndex
70+
}
71+
72+
public var endIndex: Index {
73+
storage.endIndex
74+
}
75+
76+
public subscript(index: Index) -> Element {
77+
storage[index].value
78+
}
79+
80+
public func index(after index: Index) -> Index {
81+
storage.index(after: index)
82+
}
83+
}
84+
85+
extension DependencyMirrors: ExpressibleByDictionaryLiteral {
86+
public convenience init(dictionaryLiteral elements: (String, String)...) {
87+
self.init(elements.map { Mirror(original: $0.0, mirror: $0.1) })
88+
}
89+
}
90+
91+
extension DependencyMirrors: JSONMappable, JSONSerializable {
92+
public convenience init(json: JSON) throws {
93+
self.init(try [Mirror](json: json))
94+
}
95+
96+
public func toJSON() -> JSON {
97+
let mirrors = storage.map { Mirror(original: $0.key, mirror: $0.value) }
98+
return .array(mirrors.sorted(by: { $0.original < $1.mirror }).map { $0.toJSON() })
99+
}
100+
}
101+
102+
extension DependencyMirrors.Error: CustomStringConvertible {
103+
public var description: String {
104+
switch self {
105+
case .mirrorNotFound:
106+
return "mirror not found"
107+
}
108+
}
109+
}
110+
111+
// MARK: -
112+
113+
/// An individual repository mirror.
114+
private struct Mirror {
115+
/// The original repository path.
116+
let original: String
117+
118+
/// The mirrored repository path.
119+
let mirror: String
120+
121+
init(original: String, mirror: String) {
122+
self.original = original
123+
self.mirror = mirror
124+
}
125+
}
126+
127+
extension Mirror: JSONMappable, JSONSerializable {
128+
init(json: JSON) throws {
129+
self.original = try json.get("original")
130+
self.mirror = try json.get("mirror")
131+
}
132+
133+
func toJSON() -> JSON {
134+
.init([
135+
"original": original,
136+
"mirror": mirror
137+
])
138+
}
139+
}

Sources/PackageGraph/LocalPackageContainer.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public class LocalPackageContainer: BasePackageContainer {
5151
}
5252

5353
public override func getUnversionedDependencies(productFilter: ProductFilter) throws -> [PackageContainerConstraint] {
54-
return try loadManifest().dependencyConstraints(productFilter: productFilter, config: config)
54+
return try loadManifest().dependencyConstraints(productFilter: productFilter, mirrors: mirrors)
5555
}
5656

5757
public override func getUpdatedIdentifier(at boundVersion: BoundVersion) throws -> Identifier {
@@ -62,7 +62,7 @@ public class LocalPackageContainer: BasePackageContainer {
6262

6363
public init(
6464
_ identifier: Identifier,
65-
config: SwiftPMConfig,
65+
mirrors: DependencyMirrors,
6666
manifestLoader: ManifestLoaderProtocol,
6767
toolsVersionLoader: ToolsVersionLoaderProtocol,
6868
currentToolsVersion: ToolsVersion,
@@ -72,7 +72,7 @@ public class LocalPackageContainer: BasePackageContainer {
7272
self.fs = fs
7373
super.init(
7474
identifier,
75-
config: config,
75+
mirrors: mirrors,
7676
manifestLoader: manifestLoader,
7777
toolsVersionLoader: toolsVersionLoader,
7878
currentToolsVersion: currentToolsVersion

Sources/PackageGraph/PackageContainer.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public class BasePackageContainer: PackageContainer {
141141

142142
public let identifier: Identifier
143143

144-
let config: SwiftPMConfig
144+
let mirrors: DependencyMirrors
145145

146146
/// The manifest loader.
147147
let manifestLoader: ManifestLoaderProtocol
@@ -182,13 +182,13 @@ public class BasePackageContainer: PackageContainer {
182182

183183
init(
184184
_ identifier: Identifier,
185-
config: SwiftPMConfig,
185+
mirrors: DependencyMirrors,
186186
manifestLoader: ManifestLoaderProtocol,
187187
toolsVersionLoader: ToolsVersionLoaderProtocol,
188188
currentToolsVersion: ToolsVersion
189189
) {
190190
self.identifier = identifier
191-
self.config = config
191+
self.mirrors = mirrors
192192
self.manifestLoader = manifestLoader
193193
self.toolsVersionLoader = toolsVersionLoader
194194
self.currentToolsVersion = currentToolsVersion

Sources/PackageGraph/PackageGraph+Loading.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ extension PackageGraph {
1919
/// Load the package graph for the given package path.
2020
public static func load(
2121
root: PackageGraphRoot,
22-
config: SwiftPMConfig = SwiftPMConfig(),
22+
mirrors: DependencyMirrors = [:],
2323
additionalFileRules: [FileRuleDescription] = [],
2424
externalManifests: [Manifest],
2525
requiredDependencies: Set<PackageReference> = [],
@@ -42,7 +42,7 @@ extension PackageGraph {
4242
let manifestMap = Dictionary(uniqueKeysWithValues: manifestMapSequence)
4343
let successors: (GraphLoadingNode) -> [GraphLoadingNode] = { node in
4444
node.requiredDependencies().compactMap({ dependency in
45-
let url = config.mirroredURL(forURL: dependency.url)
45+
let url = mirrors.effectiveURL(forURL: dependency.url)
4646
return manifestMap[PackageReference.computeIdentity(packageURL: url)].map { manifest in
4747
GraphLoadingNode(manifest: manifest, productFilter: dependency.productFilter)
4848
}
@@ -129,7 +129,7 @@ extension PackageGraph {
129129
// Resolve dependencies and create resolved packages.
130130
let resolvedPackages = createResolvedPackages(
131131
allManifests: allManifests,
132-
config: config,
132+
mirrors: mirrors,
133133
manifestToPackage: manifestToPackage,
134134
rootManifestSet: rootManifestSet,
135135
unsafeAllowedPackages: unsafeAllowedPackages,
@@ -187,7 +187,7 @@ private func checkAllDependenciesAreUsed(_ rootPackages: [ResolvedPackage], _ di
187187
/// Create resolved packages from the loaded packages.
188188
private func createResolvedPackages(
189189
allManifests: [GraphLoadingNode],
190-
config: SwiftPMConfig,
190+
mirrors: DependencyMirrors,
191191
manifestToPackage: [Manifest: Package],
192192
// FIXME: This shouldn't be needed once <rdar://problem/33693433> is fixed.
193193
rootManifestSet: Set<Manifest>,
@@ -228,7 +228,7 @@ private func createResolvedPackages(
228228
}
229229

230230
// Otherwise, look it up by its identity.
231-
let url = config.mirroredURL(forURL: dependency.url)
231+
let url = mirrors.effectiveURL(forURL: dependency.url)
232232
let resolvedPackage = packageMapByIdentity[PackageReference.computeIdentity(packageURL: url)]
233233

234234
// We check that the explicit package dependency name matches the package name.
@@ -359,10 +359,10 @@ private func createResolvedPackages(
359359
// explicitly reference the package containing the product, or for the product, package and
360360
// dependency to share the same name. We don't check this in manifest loading for root-packages so
361361
// we can provide a more detailed diagnostic here.
362-
let referencedPackageURL = config.mirroredURL(forURL: product.packageBuilder.package.manifest.url)
362+
let referencedPackageURL = mirrors.effectiveURL(forURL: product.packageBuilder.package.manifest.url)
363363
let referencedPackageIdentity = PackageReference.computeIdentity(packageURL: referencedPackageURL)
364364
let packageDependency = packageBuilder.package.manifest.dependencies.first { package in
365-
let packageURL = config.mirroredURL(forURL: package.url)
365+
let packageURL = mirrors.effectiveURL(forURL: package.url)
366366
let packageIdentity = PackageReference.computeIdentity(packageURL: packageURL)
367367
return packageIdentity == referencedPackageIdentity
368368
}!

Sources/PackageGraph/PackageGraphRoot.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ public struct PackageGraphRootInput {
2222
/// Top level dependencies to the graph.
2323
public let dependencies: [PackageDependencyDescription]
2424

25+
/// Dependency mirrors for the graph.
26+
public let mirrors: DependencyMirrors
27+
2528
/// Create a package graph root.
26-
public init(packages: [AbsolutePath], dependencies: [PackageDependencyDescription] = []) {
29+
public init(packages: [AbsolutePath], dependencies: [PackageDependencyDescription] = [], mirrors: DependencyMirrors = [:]) {
2730
self.packages = packages
2831
self.dependencies = dependencies
32+
self.mirrors = mirrors
2933
}
3034
}
3135

@@ -67,13 +71,13 @@ public struct PackageGraphRoot {
6771
}
6872

6973
/// Returns the constraints imposed by root manifests + dependencies.
70-
public func constraints(config: SwiftPMConfig) -> [RepositoryPackageConstraint] {
74+
public func constraints(mirrors: DependencyMirrors) -> [RepositoryPackageConstraint] {
7175
let constraints = packageRefs.map({
7276
RepositoryPackageConstraint(container: $0, requirement: .unversioned, products: .everything)
7377
})
7478
return constraints + dependencies.map({
7579
RepositoryPackageConstraint(
76-
container: $0.createPackageRef(config: config),
80+
container: $0.createPackageRef(mirrors: mirrors),
7781
requirement: $0.requirement.toConstraintRequirement(),
7882
products: $0.productFilter
7983
)

Sources/PackageGraph/PackageModel+Extensions.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import SourceControl
1313

1414
extension PackageDependencyDescription {
1515
/// Create the package reference object for the dependency.
16-
public func createPackageRef(config: SwiftPMConfig) -> PackageReference {
17-
let effectiveURL = config.mirroredURL(forURL: url)
16+
public func createPackageRef(mirrors: DependencyMirrors) -> PackageReference {
17+
let effectiveURL = mirrors.effectiveURL(forURL: url)
1818

1919
// FIXME: The identity of a package dependency is currently based on
2020
// on a name computed from the package's effective URL. This
@@ -35,10 +35,10 @@ extension PackageDependencyDescription {
3535

3636
extension Manifest {
3737
/// Constructs constraints of the dependencies in the raw package.
38-
public func dependencyConstraints(productFilter: ProductFilter, config: SwiftPMConfig) -> [RepositoryPackageConstraint] {
38+
public func dependencyConstraints(productFilter: ProductFilter, mirrors: DependencyMirrors) -> [RepositoryPackageConstraint] {
3939
return dependenciesRequired(for: productFilter).map({
4040
return RepositoryPackageConstraint(
41-
container: $0.createPackageRef(config: config),
41+
container: $0.createPackageRef(mirrors: mirrors),
4242
requirement: $0.requirement.toConstraintRequirement(),
4343
products: $0.productFilter)
4444
})

0 commit comments

Comments
 (0)