Skip to content

Commit 5b7ed39

Browse files
committed
update collections APIs to use package identity
motivation: adoption of SE-0292 package registry chnages: * migrate APIs that take PackageRefernec to take PackageIdentity * adjust and update tests rdar://83073308 rdar://82954076
1 parent ac5d561 commit 5b7ed39

14 files changed

+185
-178
lines changed

Sources/Commands/SwiftPackageCollectionsTool.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ public struct SwiftPackageCollectionsTool: ParsableCommand {
196196
try JSONEncoder.makeWithDefaults().print(results.items)
197197
} else {
198198
results.items.forEach {
199-
print("\($0.package.repository.url): \($0.package.summary ?? "")")
199+
print("\($0.package.identity): \($0.package.summary ?? "")")
200200
}
201201
}
202202

@@ -208,7 +208,7 @@ public struct SwiftPackageCollectionsTool: ParsableCommand {
208208
try JSONEncoder.makeWithDefaults().print(packages)
209209
} else {
210210
packages.forEach {
211-
print("\($0.repository.url): \($0.summary ?? "")")
211+
print("\($0.identity): \($0.summary ?? "")")
212212
}
213213
}
214214
}
@@ -314,7 +314,7 @@ public struct SwiftPackageCollectionsTool: ParsableCommand {
314314
let description = optionalRow("Description", collection.overview)
315315
let keywords = optionalRow("Keywords", collection.keywords?.joined(separator: ", "))
316316
let createdAt = optionalRow("Created At", DateFormatter().string(from: collection.createdAt))
317-
let packages = collection.packages.map { "\($0.repository.url)" }.joined(separator: "\n\(indent(levels: 2))")
317+
let packages = collection.packages.map { "\($0.identity)" }.joined(separator: "\n\(indent(levels: 2))")
318318

319319
if jsonOptions.json {
320320
try JSONEncoder.makeWithDefaults().print(collection)

Sources/PackageCollections/Model/Package.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ import SourceControl
1717
extension PackageCollectionsModel {
1818
/// Package metadata
1919
public struct Package: Codable, Equatable {
20-
/// Package reference
21-
public let reference: PackageReference
20+
/// Package identity
21+
public let identity: PackageIdentity
2222

23-
/// Package's repository address
24-
public let repository: RepositorySpecifier
23+
/// Package location
24+
public let location: String
2525

2626
/// Package description
2727
public let summary: String?
@@ -85,7 +85,8 @@ extension PackageCollectionsModel {
8585

8686
/// Initializes a `Package`
8787
init(
88-
repository: RepositorySpecifier,
88+
identity: PackageIdentity,
89+
location: String,
8990
summary: String?,
9091
keywords: [String]?,
9192
versions: [Version],
@@ -95,8 +96,8 @@ extension PackageCollectionsModel {
9596
authors: [Author]?,
9697
languages: Set<String>?
9798
) {
98-
self.reference = .init(repository: repository)
99-
self.repository = repository
99+
self.identity = identity
100+
self.location = location
100101
self.summary = summary
101102
self.keywords = keywords
102103
self.versions = versions
@@ -271,6 +272,6 @@ extension PackageCollectionsModel.Package.Version {
271272

272273
extension Model.Package {
273274
var displayName: String {
274-
self.latestVersion?.packageName ?? self.reference.identity.description
275+
self.latestVersion?.packageName ?? self.identity.description
275276
}
276277
}

Sources/PackageCollections/Model/TargetListResult.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ extension PackageCollectionsModel.TargetListResult {
3333
public struct Package: Hashable, Encodable {
3434
public typealias Version = PackageCollectionsModel.TargetListResult.PackageVersion
3535

36-
/// Package's repository address
37-
public let repository: RepositorySpecifier
36+
/// Package's identity
37+
public let identity: PackageIdentity
38+
39+
/// Package's location
40+
public let location: String
3841

3942
/// Package description
4043
public let summary: String?

Sources/PackageCollections/PackageCollections.swift

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -314,26 +314,26 @@ public struct PackageCollections: PackageCollectionsProtocol {
314314
case .failure(let error):
315315
callback(.failure(error))
316316
case .success(let collections):
317-
var packageCollections = [PackageReference: (package: Model.Package, collections: Set<Model.CollectionIdentifier>)]()
317+
var packageCollections = [PackageIdentity: (package: Model.Package, collections: Set<Model.CollectionIdentifier>)]()
318318
// Use package data from the most recently processed collection
319319
collections.sorted(by: { $0.lastProcessedAt > $1.lastProcessedAt }).forEach { collection in
320320
collection.packages.forEach { package in
321-
var entry = packageCollections.removeValue(forKey: package.reference)
321+
var entry = packageCollections.removeValue(forKey: package.identity)
322322
if entry == nil {
323323
entry = (package, .init())
324324
}
325325

326326
if var entry = entry {
327327
entry.collections.insert(collection.identifier)
328-
packageCollections[package.reference] = entry
328+
packageCollections[package.identity] = entry
329329
}
330330
}
331331
}
332332

333333
let result = PackageCollectionsModel.PackageSearchResult(
334334
items: packageCollections.sorted { $0.value.package.displayName < $1.value.package.displayName }
335335
.map { entry in
336-
.init(package: entry.value.package, collections: Array(entry.value.collections))
336+
.init(package: entry.value.package, collections: Array(entry.value.collections))
337337
}
338338
)
339339
callback(.success(result))
@@ -343,32 +343,46 @@ public struct PackageCollections: PackageCollectionsProtocol {
343343

344344
// MARK: - Package Metadata
345345

346+
@available(*, deprecated, message: "user identity based API instead")
346347
public func getPackageMetadata(_ reference: PackageReference,
347348
callback: @escaping (Result<PackageCollectionsModel.PackageMetadata, Error>) -> Void) {
348349
self.getPackageMetadata(reference, collections: nil, callback: callback)
349350
}
350351

352+
@available(*, deprecated, message: "user identity based API instead")
351353
public func getPackageMetadata(_ reference: PackageReference,
352354
collections: Set<PackageCollectionsModel.CollectionIdentifier>?,
353355
callback: @escaping (Result<PackageCollectionsModel.PackageMetadata, Error>) -> Void) {
356+
self.getPackageMetadata(reference.identity, collections: nil, callback: callback)
357+
}
358+
359+
public func getPackageMetadata(_ identity: PackageIdentity,
360+
callback: @escaping (Result<PackageCollectionsModel.PackageMetadata, Error>) -> Void) {
361+
self.getPackageMetadata(identity, collections: nil, callback: callback)
362+
}
363+
364+
public func getPackageMetadata(_ identity: PackageIdentity,
365+
collections: Set<PackageCollectionsModel.CollectionIdentifier>?,
366+
callback: @escaping (Result<PackageCollectionsModel.PackageMetadata, Error>) -> Void) {
354367
guard Self.isSupportedPlatform else {
355368
return callback(.failure(PackageCollectionError.unsupportedPlatform))
356369
}
357370

358371
// first find in storage
359-
self.findPackage(reference: reference, collections: collections) { result in
372+
self.findPackage(identity: identity, collections: collections) { result in
360373
switch result {
361374
case .failure(let error):
362375
callback(.failure(error))
363376
case .success(let packageSearchResult):
377+
364378
// then try to get more metadata from provider (optional)
365-
let authTokenType = self.metadataProvider.getAuthTokenType(for: reference)
379+
let authTokenType = self.metadataProvider.getAuthTokenType(for: packageSearchResult.package.location)
366380
let isAuthTokenConfigured = authTokenType.flatMap { self.configuration.authTokens()?[$0] } != nil
367381

368-
self.metadataProvider.get(reference) { result in
382+
self.metadataProvider.get(identity: packageSearchResult.package.identity, location: packageSearchResult.package.location) { result in
369383
switch result {
370384
case .failure(let error):
371-
self.diagnosticsEngine?.emit(warning: "Failed fetching information about \(reference) from \(self.metadataProvider.name): \(error)")
385+
self.diagnosticsEngine?.emit(warning: "Failed fetching information about \(identity) from \(self.metadataProvider.name): \(error)")
372386

373387
let provider: PackageMetadataProviderContext?
374388
switch error {
@@ -517,7 +531,7 @@ public struct PackageCollections: PackageCollectionsProtocol {
517531
}
518532
}
519533

520-
func findPackage(reference: PackageReference,
534+
func findPackage(identity: PackageIdentity,
521535
collections: Set<PackageCollectionsModel.CollectionIdentifier>?,
522536
callback: @escaping (Result<PackageCollectionsModel.PackageSearchResult.Item, Error>) -> Void) {
523537
self.storage.sources.list { result in
@@ -530,17 +544,17 @@ public struct PackageCollections: PackageCollectionsProtocol {
530544
collectionIdentifiers = collectionIdentifiers.filter { collections.contains($0) }
531545
}
532546
if collectionIdentifiers.isEmpty {
533-
return callback(.failure(NotFoundError("\(reference)")))
547+
return callback(.failure(NotFoundError("\(identity)")))
534548
}
535-
self.storage.collections.findPackage(identifier: reference.identity, collectionIdentifiers: collectionIdentifiers) { findPackageResult in
549+
self.storage.collections.findPackage(identifier: identity, collectionIdentifiers: collectionIdentifiers) { findPackageResult in
536550
switch findPackageResult {
537551
case .failure(let error):
538552
callback(.failure(error))
539553
case .success(let packagesCollections):
540554
// A package identity can be associated with multiple repository URLs
541-
let matches = packagesCollections.packages.filter { $0.reference.canonicalLocation == reference.canonicalLocation }
555+
let matches = packagesCollections.packages.filter { $0.identity == identity }
542556
guard let package = matches.first else {
543-
return callback(.failure(NotFoundError("\(reference)")))
557+
return callback(.failure(NotFoundError("\(identity)")))
544558
}
545559
callback(.success(.init(package: package, collections: packagesCollections.collections)))
546560
}
@@ -550,22 +564,22 @@ public struct PackageCollections: PackageCollectionsProtocol {
550564
}
551565

552566
private func targetListResultFromCollections(_ collections: [Model.Collection]) -> Model.TargetListResult {
553-
var packageCollections = [PackageReference: (package: Model.Package, collections: Set<Model.CollectionIdentifier>)]()
554-
var targetsPackages = [String: (target: Model.Target, packages: Set<PackageReference>)]()
567+
var packageCollections = [PackageIdentity: (package: Model.Package, collections: Set<Model.CollectionIdentifier>)]()
568+
var targetsPackages = [String: (target: Model.Target, packages: Set<PackageIdentity>)]()
555569

556570
collections.forEach { collection in
557571
collection.packages.forEach { package in
558572
// Avoid copy-on-write: remove entry from dictionary before mutating
559-
var entry = packageCollections.removeValue(forKey: package.reference) ?? (package, .init())
573+
var entry = packageCollections.removeValue(forKey: package.identity) ?? (package, .init())
560574
entry.collections.insert(collection.identifier)
561-
packageCollections[package.reference] = entry
575+
packageCollections[package.identity] = entry
562576

563577
package.versions.forEach { version in
564578
version.manifests.values.forEach { manifest in
565579
manifest.targets.forEach { target in
566580
// Avoid copy-on-write: remove entry from dictionary before mutating
567581
var entry = targetsPackages.removeValue(forKey: target.name) ?? (target: target, packages: .init())
568-
entry.packages.insert(package.reference)
582+
entry.packages.insert(package.identity)
569583
targetsPackages[target.name] = entry
570584
}
571585
}
@@ -586,7 +600,8 @@ public struct PackageCollections: PackageCollectionsProtocol {
586600
)
587601
}
588602
}
589-
return .init(repository: pair.package.repository,
603+
return .init(identity: pair.package.identity,
604+
location: pair.package.location,
590605
summary: pair.package.summary,
591606
versions: versions,
592607
collections: Array(pair.collections))
@@ -614,7 +629,8 @@ public struct PackageCollections: PackageCollectionsProtocol {
614629
versions.sort(by: >)
615630

616631
return Model.Package(
617-
repository: package.repository,
632+
identity: package.identity,
633+
location: package.location,
618634
summary: basicMetadata?.summary ?? package.summary,
619635
keywords: basicMetadata?.keywords ?? package.keywords,
620636
versions: versions,
@@ -634,9 +650,3 @@ private struct UnknownProvider: Error {
634650
self.sourceType = sourceType
635651
}
636652
}
637-
638-
private extension PackageReference {
639-
var canonicalLocation: String {
640-
(self.location.hasSuffix(".git") ? String(self.location.dropLast(4)) : self.location).lowercased()
641-
}
642-
}

Sources/PackageCollections/Providers/GitHubPackageMetadataProvider.swift

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,12 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider {
4949
try self.cache?.close()
5050
}
5151

52-
func get(_ reference: PackageReference, callback: @escaping (Result<Model.PackageBasicMetadata, Error>) -> Void) {
53-
guard reference.kind == .remote else {
54-
return callback(.failure(Errors.invalidReferenceType(reference)))
55-
}
56-
guard let baseURL = Self.apiURL(reference.location) else {
57-
return callback(.failure(Errors.invalidGitURL(reference.location)))
52+
func get(identity: PackageIdentity, location: String, callback: @escaping (Result<Model.PackageBasicMetadata, Error>) -> Void) {
53+
guard let baseURL = Self.apiURL(location) else {
54+
return callback(.failure(Errors.invalidGitURL(location)))
5855
}
5956

60-
if let cached = try? self.cache?.get(key: reference.identity.description) {
57+
if let cached = try? self.cache?.get(key: identity.description) {
6158
if cached.dispatchTime + DispatchTimeInterval.seconds(self.configuration.cacheTTLInSeconds) > DispatchTime.now() {
6259
return callback(.success(cached.package))
6360
}
@@ -157,9 +154,9 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider {
157154
)
158155

159156
do {
160-
try self.cache?.put(key: reference.identity.description, value: CacheValue(package: model, timestamp: DispatchTime.now()), replace: true)
157+
try self.cache?.put(key: identity.description, value: CacheValue(package: model, timestamp: DispatchTime.now()), replace: true)
161158
} catch {
162-
self.diagnosticsEngine?.emit(.warning("Failed to save GitHub metadata for package \(reference) to cache: \(error)"))
159+
self.diagnosticsEngine?.emit(.warning("Failed to save GitHub metadata for package \(identity) to cache: \(error)"))
163160
}
164161

165162
callback(.success(model))
@@ -170,13 +167,13 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider {
170167
}
171168
}
172169

173-
func getAuthTokenType(for reference: PackageReference) -> AuthTokenType? {
174-
guard reference.kind == .remote, let baseURL = Self.apiURL(reference.location) else {
170+
func getAuthTokenType(for location: String) -> AuthTokenType? {
171+
guard let baseURL = Self.apiURL(location) else {
175172
return nil
176173
}
177174

178175
return baseURL.host.flatMap { host in
179-
self.getAuthTokenType(for: host)
176+
self.getAuthTokenType(forHost: host)
180177
}
181178
}
182179

@@ -206,7 +203,7 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider {
206203
options.validResponseCodes = validResponseCodes
207204
options.authorizationProvider = { url in
208205
url.host.flatMap { host in
209-
let tokenType = self.getAuthTokenType(for: host)
206+
let tokenType = self.getAuthTokenType(forHost: host)
210207
return self.configuration.authTokens()?[tokenType].flatMap { token in
211208
"token \(token)"
212209
}
@@ -215,7 +212,8 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider {
215212
return options
216213
}
217214

218-
private func getAuthTokenType(for host: String) -> AuthTokenType {
215+
216+
private func getAuthTokenType(forHost host: String) -> AuthTokenType {
219217
let host = host.hasPrefix(Self.apiHostPrefix) ? String(host.dropFirst(Self.apiHostPrefix.count)) : host
220218
return .github(host)
221219
}

Sources/PackageCollections/Providers/JSONPackageCollectionProvider.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider {
259259
serializationOkay = false
260260
}
261261

262-
return .init(repository: RepositorySpecifier(url: package.url.absoluteString),
262+
return .init(identity: .init(url: package.url.absoluteString),
263+
location: package.url.absoluteString,
263264
summary: package.summary,
264265
keywords: package.keywords,
265266
versions: versions,

Sources/PackageCollections/Providers/PackageMetadataProvider.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,16 @@ protocol PackageMetadataProvider: Closable {
2323
/// Retrieves metadata for a package at the given repository address.
2424
///
2525
/// - Parameters:
26-
/// - reference: The package's reference
26+
/// - identity: The package's identity
27+
/// - location: The package's location
2728
/// - callback: The closure to invoke when result becomes available
28-
func get(_ reference: PackageReference, callback: @escaping (Result<PackageCollectionsModel.PackageBasicMetadata, Error>) -> Void)
29+
func get(identity: PackageIdentity, location: String, callback: @escaping (Result<PackageCollectionsModel.PackageBasicMetadata, Error>) -> Void)
2930

3031
/// Returns `AuthTokenType` for a package.
3132
///
3233
/// - Parameters:
33-
/// - reference: The package's reference
34-
func getAuthTokenType(for reference: PackageReference) -> AuthTokenType?
34+
/// - location: The package's location
35+
func getAuthTokenType(for location: String) -> AuthTokenType?
3536
}
3637

3738
extension Model {

0 commit comments

Comments
 (0)