Skip to content

Commit 8c6d925

Browse files
authored
rdar://107033737 (Expose PackageVersionMetadata from PackageSearchClient) (#6351)
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.
1 parent 638cc86 commit 8c6d925

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
}
@@ -80,11 +121,20 @@ public struct PackageSearchClient {
80121
}
81122
return nil
82123
}
83-
84-
private func getReadMeURL(
124+
125+
private struct Metadata {
126+
public let licenseURL: URL?
127+
public let readmeURL: URL?
128+
public let repositoryURLs: [URL]?
129+
public let resources: [Package.Resource]
130+
public let author: Package.Author?
131+
public let description: String?
132+
}
133+
134+
private func getVersionMetadata(
85135
package: PackageIdentity,
86136
version: Version,
87-
callback: @escaping (Result<URL?, Error>) -> Void
137+
callback: @escaping (Result<Metadata, Error>) -> Void
88138
) {
89139
self.registryClient.getPackageVersionMetadata(
90140
package: package,
@@ -93,7 +143,16 @@ public struct PackageSearchClient {
93143
observabilityScope: observabilityScope,
94144
callbackQueue: DispatchQueue.sharedConcurrent
95145
) { result in
96-
callback(result.tryMap { metadata in metadata.readmeURL })
146+
callback(result.tryMap { metadata in
147+
Metadata(
148+
licenseURL: metadata.licenseURL,
149+
readmeURL: metadata.readmeURL,
150+
repositoryURLs: metadata.repositoryURLs,
151+
resources: metadata.resources.map { .init($0) },
152+
author: metadata.author.map { .init($0) },
153+
description: metadata.description
154+
)
155+
})
97156
}
98157
}
99158

@@ -111,7 +170,13 @@ public struct PackageSearchClient {
111170
Package(identity: $0.package.identity,
112171
location: $0.package.location,
113172
versions: $0.package.versions.map { $0.version },
173+
licenseURL: nil,
114174
readmeURL: $0.package.readmeURL,
175+
repositoryURLs: nil,
176+
resources: [],
177+
author: nil,
178+
description: nil,
179+
latestVersion: nil, // this only makes sense in connection with providing versioned metadata
115180
source: .indexAndCollections(collections: $0.collections, indexes: $0.indexes)
116181
)
117182
}
@@ -149,7 +214,13 @@ public struct PackageSearchClient {
149214
location: url.absoluteString,
150215
branches: branches,
151216
versions: versions,
217+
licenseURL: nil,
152218
readmeURL: self.guessReadMeURL(baseURL: url, defaultBranch: try repository.getDefaultBranch()),
219+
repositoryURLs: nil,
220+
resources: [],
221+
author: nil,
222+
description: nil,
223+
latestVersion: nil, // this only makes sense in connection with providing versioned metadata
153224
source: .sourceControl(url: url))
154225
return callback(.success([package]))
155226
}
@@ -174,25 +245,52 @@ public struct PackageSearchClient {
174245

175246
// See if the latest package version has readmeURL set
176247
if let version = versions.first {
177-
self.getReadMeURL(package: identity, version: version) { result in
248+
self.getVersionMetadata(package: identity, version: version) { result in
249+
let licenseURL: URL?
178250
let readmeURL: URL?
179-
if case .success(.some(let readmeURLForVersion)) = result {
180-
readmeURL = readmeURLForVersion
251+
let repositoryURLs: [URL]?
252+
let resources: [Package.Resource]
253+
let author: Package.Author?
254+
let description: String?
255+
if case .success(let metadata) = result {
256+
licenseURL = metadata.licenseURL
257+
readmeURL = metadata.readmeURL
258+
repositoryURLs = metadata.repositoryURLs
259+
resources = metadata.resources
260+
author = metadata.author
261+
description = metadata.description
181262
} else {
263+
licenseURL = nil
182264
readmeURL = self.guessReadMeURL(alternateLocations: metadata.alternateLocations)
265+
repositoryURLs = nil
266+
resources = []
267+
author = nil
268+
description = nil
183269
}
184-
270+
185271
return callback(.success([Package(identity: identity,
186272
versions: metadata.versions,
273+
licenseURL: licenseURL,
187274
readmeURL: readmeURL,
275+
repositoryURLs: repositoryURLs,
276+
resources: resources,
277+
author: author,
278+
description: description,
279+
latestVersion: version,
188280
source: .registry(url: metadata.registry.url)
189281
)]))
190282
}
191283
} else {
192284
let readmeURL: URL? = self.guessReadMeURL(alternateLocations: metadata.alternateLocations)
193285
return callback(.success([Package(identity: identity,
194286
versions: metadata.versions,
287+
licenseURL: nil,
195288
readmeURL: readmeURL,
289+
repositoryURLs: nil,
290+
resources: [],
291+
author: nil,
292+
description: nil,
293+
latestVersion: nil, // this only makes sense in connection with providing versioned metadata
196294
source: .registry(url: metadata.registry.url)
197295
)]))
198296
}
@@ -243,3 +341,45 @@ public struct PackageSearchClient {
243341
}
244342
}
245343
}
344+
345+
fileprivate extension Package.Signing {
346+
init(_ signing: RegistryClient.PackageVersionMetadata.Signing) {
347+
self.init(
348+
signatureBase64Encoded: signing.signatureBase64Encoded,
349+
signatureFormat: signing.signatureFormat
350+
)
351+
}
352+
}
353+
354+
fileprivate extension Package.Resource {
355+
init(_ resource: RegistryClient.PackageVersionMetadata.Resource) {
356+
self.init(
357+
name: resource.name,
358+
type: resource.type,
359+
checksum: resource.checksum,
360+
signing: resource.signing.map { .init($0) })
361+
}
362+
}
363+
364+
fileprivate extension Package.Author {
365+
init(_ author: RegistryClient.PackageVersionMetadata.Author) {
366+
self.init(
367+
name: author.name,
368+
email: author.email,
369+
description: author.description,
370+
organization: author.organization.map { .init($0) },
371+
url: author.url
372+
)
373+
}
374+
}
375+
376+
fileprivate extension Package.Organization {
377+
init(_ organization: RegistryClient.PackageVersionMetadata.Organization) {
378+
self.init(
379+
name: organization.name,
380+
email: organization.email,
381+
description: organization.description,
382+
url: organization.url
383+
)
384+
}
385+
}

0 commit comments

Comments
 (0)