Skip to content

Commit 9033d81

Browse files
authored
Add PackageRegistryManager (#3787)
* Add scopeAndName property to PackageIdentity * Use PackageIdentity.Scope instead of String where applicable * Add RegistryManager * Add SourceArchiver that uses tar command * Update Workspace initialization to configure registryManager * Add and adapt tests
1 parent 85189ac commit 9033d81

File tree

14 files changed

+731
-75
lines changed

14 files changed

+731
-75
lines changed

Sources/Commands/SwiftPackageRegistryTool.swift

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import Foundation
2424
import PackageRegistry
2525

2626
private enum RegistryConfigurationError: Swift.Error {
27-
case missingScope(String? = nil)
27+
case missingScope(PackageIdentity.Scope? = nil)
2828
case invalidURL(String)
2929
}
3030

@@ -90,6 +90,8 @@ public struct SwiftPackageRegistryTool: ParsableCommand {
9090
throw RegistryConfigurationError.invalidURL(self.url)
9191
}
9292

93+
let scope = try scope.map(PackageIdentity.Scope.init(validating:))
94+
9395
// TODO: Require login if password is specified
9496

9597
let set: (inout RegistryConfiguration) throws -> Void = { configuration in
@@ -125,6 +127,8 @@ public struct SwiftPackageRegistryTool: ParsableCommand {
125127
var scope: String?
126128

127129
func run(_ swiftTool: SwiftTool) throws {
130+
let scope = try scope.map(PackageIdentity.Scope.init(validating:))
131+
128132
let unset: (inout RegistryConfiguration) throws -> Void = { configuration in
129133
if let scope = scope {
130134
guard let _ = configuration.scopedRegistries[scope] else {
@@ -148,23 +152,3 @@ public struct SwiftPackageRegistryTool: ParsableCommand {
148152
}
149153
}
150154
}
151-
152-
// MARK: -
153-
154-
155-
private extension SwiftTool {
156-
func getRegistriesConfig() throws -> Workspace.Configuration.Registries {
157-
let localRegistriesFile = try Workspace.DefaultLocations.registriesConfigurationFile(forRootPackage: self.getPackageRoot())
158-
159-
let workspace = try getActiveWorkspace()
160-
let sharedRegistriesFile = workspace.location.sharedConfigurationDirectory.map {
161-
Workspace.DefaultLocations.registriesConfigurationFile(at: $0)
162-
}
163-
164-
return try .init(
165-
localRegistriesFile: localRegistriesFile,
166-
sharedRegistriesFile: sharedRegistriesFile,
167-
fileSystem: localFileSystem
168-
)
169-
}
170-
}

Sources/Commands/SwiftTool.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,21 @@ public class SwiftTool {
495495
return newPath
496496
}
497497

498+
func getRegistriesConfig(sharedConfigurationDirectory: AbsolutePath? = nil) throws -> Workspace.Configuration.Registries {
499+
let localRegistriesFile = try Workspace.DefaultLocations.registriesConfigurationFile(forRootPackage: self.getPackageRoot())
500+
501+
let sharedConfigurationDirectory = try sharedConfigurationDirectory ?? self.getSharedConfigurationDirectory()
502+
let sharedRegistriesFile = sharedConfigurationDirectory.map {
503+
Workspace.DefaultLocations.registriesConfigurationFile(at: $0)
504+
}
505+
506+
return try .init(
507+
localRegistriesFile: localRegistriesFile,
508+
sharedRegistriesFile: sharedRegistriesFile,
509+
fileSystem: localFileSystem
510+
)
511+
}
512+
498513
func getAuthorizationProvider() throws -> AuthorizationProvider? {
499514
var providers = [AuthorizationProvider]()
500515

@@ -609,6 +624,7 @@ public class SwiftTool {
609624
sharedConfigurationDirectory: sharedConfigurationDirectory
610625
),
611626
mirrors: self.getMirrorsConfig(sharedConfigurationDirectory: sharedConfigurationDirectory).mirrors,
627+
registries: try self.getRegistriesConfig(sharedConfigurationDirectory: sharedConfigurationDirectory).configuration,
612628
authorizationProvider: self.getAuthorizationProvider(),
613629
customManifestLoader: self.getManifestLoader(), // FIXME: doe we really need to customize it?
614630
customRepositoryProvider: provider, // FIXME: doe we really need to customize it?

Sources/PackageDescription/PackageDependency.swift

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11+
import Foundation
12+
1113
// MARK: - file system
1214

1315
extension Package {
@@ -27,7 +29,7 @@ extension Package {
2729
public enum Kind {
2830
case fileSystem(name: String?, path: String)
2931
case sourceControl(name: String?, location: String, requirement: SourceControlRequirement)
30-
case registry(identity: String, requirement: RegistryRequirement)
32+
case registry(id: String, requirement: RegistryRequirement)
3133
}
3234

3335
@available(_PackageDescription, introduced: 5.6)
@@ -81,7 +83,7 @@ extension Package {
8183
case .revision(let revision):
8284
return .revisionItem(revision)
8385
}
84-
case .registry(identity: _, requirement: let requirement):
86+
case .registry(id: _, requirement: let requirement):
8587
switch requirement {
8688
case .exact(let version):
8789
return .exactItem(version)
@@ -121,8 +123,8 @@ extension Package {
121123
self.init(kind: .sourceControl(name: name, location: location, requirement: requirement))
122124
}
123125

124-
convenience init(identity: String, requirement: RegistryRequirement) {
125-
self.init(kind: .registry(identity: identity, requirement: requirement))
126+
convenience init(id: String, requirement: RegistryRequirement) {
127+
self.init(kind: .registry(id: id, requirement: requirement))
126128
}
127129
}
128130
}
@@ -459,17 +461,17 @@ extension Package.Dependency {
459461
/// The following example allows the Swift Package Manager to select a version
460462
/// like a `1.2.3`, `1.2.4`, or `1.3.0`, but not `2.0.0`.
461463
///
462-
/// .package(identity: "scope.name", from: "1.2.3"),
464+
/// .package(id: "scope.name", from: "1.2.3"),
463465
///
464466
/// - Parameters:
465-
/// - identity: The identity of the package.
467+
/// - id: The identity of the package.
466468
/// - version: The minimum version requirement.
467469
@available(_PackageDescription, introduced: 999)
468470
public static func package(
469-
identity: String,
471+
id: String,
470472
from version: Version
471473
) -> Package.Dependency {
472-
return .package(identity: identity, .upToNextMajor(from: version))
474+
return .package(id: id, .upToNextMajor(from: version))
473475
}
474476

475477
/// Adds a package dependency that uses the exact version requirement.
@@ -483,17 +485,17 @@ extension Package.Dependency {
483485
///
484486
/// The following example instruct the Swift Package Manager to use version `1.2.3`.
485487
///
486-
/// .package(identity: "scope.name", exact: "1.2.3"),
488+
/// .package(id: "scope.name", exact: "1.2.3"),
487489
///
488490
/// - Parameters:
489-
/// - identity: The identity of the package.
491+
/// - id: The identity of the package.
490492
/// - version: The minimum version requirement.
491493
@available(_PackageDescription, introduced: 999)
492494
public static func package(
493-
identity: String,
495+
id: String,
494496
exact version: Version
495497
) -> Package.Dependency {
496-
return .package(identity: identity, requirement: .exact(version))
498+
return .package(id: id, requirement: .exact(version))
497499
}
498500

499501
/// Adds a package dependency starting with a specific minimum version, up to
@@ -502,17 +504,17 @@ extension Package.Dependency {
502504
/// The following example allows the Swift Package Manager to pick
503505
/// versions `1.2.3`, `1.2.4`, `1.2.5`, but not `1.2.6`.
504506
///
505-
/// .package(identity: "scope.name", "1.2.3"..<"1.2.6"),
507+
/// .package(id: "scope.name", "1.2.3"..<"1.2.6"),
506508
///
507509
/// - Parameters:
508-
/// - identity: The identity of the package.
510+
/// - id: The identity of the package.
509511
/// - range: The custom version range requirement.
510512
@available(_PackageDescription, introduced: 999)
511513
public static func package(
512-
identity: String,
514+
id: String,
513515
_ range: Range<Version>
514516
) -> Package.Dependency {
515-
return .package(identity: identity, requirement: .range(range))
517+
return .package(id: id, requirement: .range(range))
516518
}
517519

518520
/// Adds a package dependency starting with a specific minimum version, going
@@ -521,14 +523,14 @@ extension Package.Dependency {
521523
/// The following example allows the Swift Package Manager to pick
522524
/// versions 1.2.3, 1.2.4, 1.2.5, as well as 1.2.6.
523525
///
524-
/// .package(identity: "scope.name", "1.2.3"..."1.2.6"),
526+
/// .package(id: "scope.name", "1.2.3"..."1.2.6"),
525527
///
526528
/// - Parameters:
527-
/// - identity: The identity of the package.
529+
/// - id: The identity of the package.
528530
/// - range: The closed version range requirement.
529531
@available(_PackageDescription, introduced: 999)
530532
public static func package(
531-
identity: String,
533+
id: String,
532534
_ range: ClosedRange<Version>
533535
) -> Package.Dependency {
534536
// Increase upperbound's patch version by one.
@@ -537,16 +539,21 @@ extension Package.Dependency {
537539
upper.major, upper.minor, upper.patch + 1,
538540
prereleaseIdentifiers: upper.prereleaseIdentifiers,
539541
buildMetadataIdentifiers: upper.buildMetadataIdentifiers)
540-
return .package(identity: identity, range.lowerBound ..< upperBound)
542+
return .package(id: id, range.lowerBound ..< upperBound)
541543
}
542544

543545
// intentionally private to hide enum detail
544546
@available(_PackageDescription, introduced: 999)
545547
private static func package(
546-
identity: String,
548+
id: String,
547549
requirement: Package.Dependency.RegistryRequirement
548550
) -> Package.Dependency {
549-
return .init(identity: identity, requirement: requirement)
551+
let pattern = #"\A[a-zA-Z\d](?:[a-zA-Z\d]|-(?=[a-zA-Z\d])){0,38}\.[a-zA-Z0-9](?:[a-zA-Z0-9]|[-_](?=[a-zA-Z0-9])){0,99}\z"#
552+
if id.range(of: pattern, options: .regularExpression) == nil {
553+
errors.append("Invalid package identifier: \(id)")
554+
}
555+
556+
return .init(id: id, requirement: requirement)
550557
}
551558
}
552559

Sources/PackageModel/PackageIdentity.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ public struct PackageIdentity: CustomStringConvertible {
6363
public static func plain(_ value: String) -> PackageIdentity {
6464
PackageIdentity(value)
6565
}
66+
67+
// TODO: formalize package registry identifier
68+
public var scopeAndName: (Scope, Name)? {
69+
let components = description.split(separator: ".", maxSplits: 1, omittingEmptySubsequences: true)
70+
guard components.count == 2,
71+
let scope = Scope(components.first),
72+
let name = Name(components.last)
73+
else { return nil }
74+
75+
return (scope, name)
76+
}
6677
}
6778

6879
extension PackageIdentity: Equatable, Comparable {
@@ -149,6 +160,11 @@ extension PackageIdentity {
149160
self = scope
150161
}
151162

163+
fileprivate init?(_ substring: String.SubSequence?) {
164+
guard let substring = substring else { return nil }
165+
self.init(String(substring))
166+
}
167+
152168
// MARK: - Equatable & Comparable
153169

154170
private func compare(to other: Scope) -> ComparisonResult {
@@ -226,6 +242,11 @@ extension PackageIdentity {
226242
self = name
227243
}
228244

245+
fileprivate init?(_ substring: String.SubSequence?) {
246+
guard let substring = substring else { return nil }
247+
self.init(String(substring))
248+
}
249+
229250
// MARK: - Equatable & Comparable
230251

231252
private func compare(to other: Name) -> ComparisonResult {

Sources/PackageRegistry/CMakeLists.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@
77
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
88

99
add_library(PackageRegistry
10-
RegistryConfiguration.swift)
10+
Registry.swift
11+
RegistryConfiguration.swift
12+
RegistryManager.swift
13+
SourceArchiver.swift)
1114
target_link_libraries(PackageRegistry PUBLIC
12-
TSCBasic
15+
Basics
1316
PackageLoading
1417
PackageModel
18+
TSCBasic
1519
TSCUtility)
1620
# NOTE(compnerd) workaround for CMake not setting up include flags yet
1721
set_target_properties(PackageRegistry PROPERTIES
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2021 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 struct Foundation.URL
12+
13+
public struct Registry: Hashable, Codable {
14+
public var url: Foundation.URL
15+
16+
public init(url: Foundation.URL) {
17+
self.url = url
18+
}
19+
}

Sources/PackageRegistry/RegistryConfiguration.swift

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,17 @@
99
*/
1010

1111
import Foundation
12+
import PackageModel
1213

1314
public struct RegistryConfiguration: Hashable {
14-
public typealias Scope = String
15-
16-
public struct Registry: Hashable {
17-
public var url: Foundation.URL
18-
19-
public init(url: Foundation.URL) {
20-
self.url = url
21-
}
22-
}
23-
24-
public enum Version: Int {
15+
public enum Version: Int, Codable {
2516
case v1 = 1
2617
}
2718

2819
public static let version: Version = .v1
2920

3021
public var defaultRegistry: Registry?
31-
public var scopedRegistries: [Scope: Registry]
22+
public var scopedRegistries: [PackageIdentity.Scope: Registry]
3223

3324
public init() {
3425
self.defaultRegistry = nil
@@ -48,6 +39,10 @@ public struct RegistryConfiguration: Hashable {
4839
self.scopedRegistries[scope] = registry
4940
}
5041
}
42+
43+
public func registry(for scope: PackageIdentity.Scope) -> Registry? {
44+
return scopedRegistries[scope] ?? defaultRegistry
45+
}
5146
}
5247

5348
// MARK: - Codable
@@ -83,9 +78,10 @@ extension RegistryConfiguration: Codable {
8378

8479
self.defaultRegistry = try nestedContainer.decodeIfPresent(Registry.self, forKey: .default)
8580

86-
var scopedRegistries: [Scope: Registry] = [:]
81+
var scopedRegistries: [PackageIdentity.Scope: Registry] = [:]
8782
for key in nestedContainer.allKeys where key != .default {
88-
scopedRegistries[key.stringValue] = try nestedContainer.decode(Registry.self, forKey: key)
83+
let scope = try PackageIdentity.Scope(validating: key.stringValue)
84+
scopedRegistries[scope] = try nestedContainer.decode(Registry.self, forKey: key)
8985
}
9086
self.scopedRegistries = scopedRegistries
9187
case nil:
@@ -103,11 +99,8 @@ extension RegistryConfiguration: Codable {
10399
try nestedContainer.encodeIfPresent(defaultRegistry, forKey: .default)
104100

105101
for (scope, registry) in scopedRegistries {
106-
let key = ScopeCodingKey(stringValue: scope)
102+
let key = ScopeCodingKey(stringValue: scope.description)
107103
try nestedContainer.encode(registry, forKey: key)
108104
}
109105
}
110106
}
111-
112-
extension RegistryConfiguration.Version: Codable {}
113-
extension RegistryConfiguration.Registry: Codable {}

0 commit comments

Comments
 (0)