Skip to content

Commit 524ff58

Browse files
authored
rdar://107033737 (Expose PackageVersionMetadata from PackageSearchClient) (#6374)
This exposes all of the version-specific metadata, not just the readme URL. For convenience, this is still flattened and only the metadata for the latest version is available, but I have also added a `latestVersion` property if we are taking metadata from a specific version to indicate where it is from. (cherry picked from commit 8c6d925)
1 parent d8f7a4b commit 524ff58

File tree

1 file changed

+150
-10
lines changed

1 file changed

+150
-10
lines changed

Sources/PackageMetadata/PackageMetadata.swift

Lines changed: 150 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,60 @@ public struct Package {
3030
case sourceControl(url: URL)
3131
}
3232

33+
public struct Resource: Sendable {
34+
public let name: String
35+
public let type: String
36+
public let checksum: String?
37+
public let signing: Signing?
38+
}
39+
40+
public struct Signing: Sendable {
41+
public let signatureBase64Encoded: String
42+
public let signatureFormat: String
43+
}
44+
45+
public struct Author: Sendable {
46+
public let name: String
47+
public let email: String?
48+
public let description: String?
49+
public let organization: Organization?
50+
public let url: URL?
51+
}
52+
53+
public struct Organization: Sendable {
54+
public let name: String
55+
public let email: String?
56+
public let description: String?
57+
public let url: URL?
58+
}
59+
3360
public let identity: PackageIdentity
3461
public let location: String?
3562
public let branches: [String]
3663
public let versions: [Version]
37-
public let readmeURL: URL?
3864
public let source: Source
3965

40-
fileprivate init(identity: PackageIdentity, location: String? = nil, branches: [String] = [], versions: [Version], readmeURL: URL? = nil, source: Source) {
66+
// Per version metadata based on the latest version that we include here for convenience.
67+
public let licenseURL: URL?
68+
public let readmeURL: URL?
69+
public let repositoryURLs: [URL]?
70+
public let resources: [Resource]
71+
public let author: Author?
72+
public let description: String?
73+
public let latestVersion: Version?
74+
75+
fileprivate init(identity: PackageIdentity, location: String? = nil, branches: [String] = [], versions: [Version], licenseURL: URL? = nil, readmeURL: URL? = nil, repositoryURLs: [URL]?, resources: [Resource], author: Author?, description: String?, latestVersion: Version? = nil, source: Source) {
4176
self.identity = identity
4277
self.location = location
4378
self.branches = branches
4479
self.versions = versions
80+
self.licenseURL = licenseURL
4581
self.readmeURL = readmeURL
82+
self.repositoryURLs = repositoryURLs
83+
self.resources = resources
84+
self.author = author
85+
self.description = description
86+
self.latestVersion = latestVersion
4687
self.source = source
4788
}
4889
}
@@ -78,19 +119,37 @@ public struct PackageSearchClient {
78119
}
79120
return nil
80121
}
81-
82-
private func getReadMeURL(
122+
123+
private struct Metadata {
124+
public let licenseURL: URL?
125+
public let readmeURL: URL?
126+
public let repositoryURLs: [URL]?
127+
public let resources: [Package.Resource]
128+
public let author: Package.Author?
129+
public let description: String?
130+
}
131+
132+
private func getVersionMetadata(
83133
package: PackageIdentity,
84134
version: Version,
85-
callback: @escaping (Result<URL?, Error>) -> Void
135+
callback: @escaping (Result<Metadata, Error>) -> Void
86136
) {
87137
self.registryClient.getPackageVersionMetadata(
88138
package: package,
89139
version: version,
90140
observabilityScope: observabilityScope,
91141
callbackQueue: DispatchQueue.sharedConcurrent
92142
) { result in
93-
callback(result.tryMap { metadata in metadata.readmeURL })
143+
callback(result.tryMap { metadata in
144+
Metadata(
145+
licenseURL: metadata.licenseURL,
146+
readmeURL: metadata.readmeURL,
147+
repositoryURLs: metadata.repositoryURLs,
148+
resources: metadata.resources.map { .init($0) },
149+
author: metadata.author.map { .init($0) },
150+
description: metadata.description
151+
)
152+
})
94153
}
95154
}
96155

@@ -108,7 +167,13 @@ public struct PackageSearchClient {
108167
Package(identity: $0.package.identity,
109168
location: $0.package.location,
110169
versions: $0.package.versions.map { $0.version },
170+
licenseURL: nil,
111171
readmeURL: $0.package.readmeURL,
172+
repositoryURLs: nil,
173+
resources: [],
174+
author: nil,
175+
description: nil,
176+
latestVersion: nil, // this only makes sense in connection with providing versioned metadata
112177
source: .indexAndCollections(collections: $0.collections, indexes: $0.indexes)
113178
)
114179
}
@@ -146,7 +211,13 @@ public struct PackageSearchClient {
146211
location: url.absoluteString,
147212
branches: branches,
148213
versions: versions,
214+
licenseURL: nil,
149215
readmeURL: self.guessReadMeURL(baseURL: url, defaultBranch: try repository.getDefaultBranch()),
216+
repositoryURLs: nil,
217+
resources: [],
218+
author: nil,
219+
description: nil,
220+
latestVersion: nil, // this only makes sense in connection with providing versioned metadata
150221
source: .sourceControl(url: url))
151222
return callback(.success([package]))
152223
}
@@ -171,25 +242,52 @@ public struct PackageSearchClient {
171242

172243
// See if the latest package version has readmeURL set
173244
if let version = versions.first {
174-
self.getReadMeURL(package: identity, version: version) { result in
245+
self.getVersionMetadata(package: identity, version: version) { result in
246+
let licenseURL: URL?
175247
let readmeURL: URL?
176-
if case .success(.some(let readmeURLForVersion)) = result {
177-
readmeURL = readmeURLForVersion
248+
let repositoryURLs: [URL]?
249+
let resources: [Package.Resource]
250+
let author: Package.Author?
251+
let description: String?
252+
if case .success(let metadata) = result {
253+
licenseURL = metadata.licenseURL
254+
readmeURL = metadata.readmeURL
255+
repositoryURLs = metadata.repositoryURLs
256+
resources = metadata.resources
257+
author = metadata.author
258+
description = metadata.description
178259
} else {
260+
licenseURL = nil
179261
readmeURL = self.guessReadMeURL(alternateLocations: metadata.alternateLocations)
262+
repositoryURLs = nil
263+
resources = []
264+
author = nil
265+
description = nil
180266
}
181-
267+
182268
return callback(.success([Package(identity: identity,
183269
versions: metadata.versions,
270+
licenseURL: licenseURL,
184271
readmeURL: readmeURL,
272+
repositoryURLs: repositoryURLs,
273+
resources: resources,
274+
author: author,
275+
description: description,
276+
latestVersion: version,
185277
source: .registry(url: metadata.registry.url)
186278
)]))
187279
}
188280
} else {
189281
let readmeURL: URL? = self.guessReadMeURL(alternateLocations: metadata.alternateLocations)
190282
return callback(.success([Package(identity: identity,
191283
versions: metadata.versions,
284+
licenseURL: nil,
192285
readmeURL: readmeURL,
286+
repositoryURLs: nil,
287+
resources: [],
288+
author: nil,
289+
description: nil,
290+
latestVersion: nil, // this only makes sense in connection with providing versioned metadata
193291
source: .registry(url: metadata.registry.url)
194292
)]))
195293
}
@@ -240,3 +338,45 @@ public struct PackageSearchClient {
240338
}
241339
}
242340
}
341+
342+
fileprivate extension Package.Signing {
343+
init(_ signing: RegistryClient.PackageVersionMetadata.Signing) {
344+
self.init(
345+
signatureBase64Encoded: signing.signatureBase64Encoded,
346+
signatureFormat: signing.signatureFormat
347+
)
348+
}
349+
}
350+
351+
fileprivate extension Package.Resource {
352+
init(_ resource: RegistryClient.PackageVersionMetadata.Resource) {
353+
self.init(
354+
name: resource.name,
355+
type: resource.type,
356+
checksum: resource.checksum,
357+
signing: resource.signing.map { .init($0) })
358+
}
359+
}
360+
361+
fileprivate extension Package.Author {
362+
init(_ author: RegistryClient.PackageVersionMetadata.Author) {
363+
self.init(
364+
name: author.name,
365+
email: author.email,
366+
description: author.description,
367+
organization: author.organization.map { .init($0) },
368+
url: author.url
369+
)
370+
}
371+
}
372+
373+
fileprivate extension Package.Organization {
374+
init(_ organization: RegistryClient.PackageVersionMetadata.Organization) {
375+
self.init(
376+
name: organization.name,
377+
email: organization.email,
378+
description: organization.description,
379+
url: organization.url
380+
)
381+
}
382+
}

0 commit comments

Comments
 (0)