@@ -15,18 +15,27 @@ import TSCBasic
15
15
public struct PackageCollections : PackageCollectionsProtocol {
16
16
private let configuration : Configuration
17
17
private let storage : Storage
18
- private let providers : [ PackageCollectionsModel . CollectionSourceType : PackageCollectionProvider ]
18
+ private let collectionProviders : [ PackageCollectionsModel . CollectionSourceType : PackageCollectionProvider ]
19
+ private let metadataProvider : PackageMetadataProvider
19
20
20
- init ( configuration: Configuration , storage: Storage , providers: [ PackageCollectionsModel . CollectionSourceType : PackageCollectionProvider ] ) {
21
+ init ( configuration: Configuration ,
22
+ storage: Storage ,
23
+ collectionProviders: [ PackageCollectionsModel . CollectionSourceType : PackageCollectionProvider ] ,
24
+ metadataProvider: PackageMetadataProvider ) {
21
25
self . configuration = configuration
22
26
self . storage = storage
23
- self . providers = providers
27
+ self . collectionProviders = collectionProviders
28
+ self . metadataProvider = metadataProvider
24
29
}
25
30
31
+ // MARK: - Profiles
32
+
26
33
public func listProfiles( callback: @escaping ( Result < [ PackageCollectionsModel . Profile ] , Error > ) -> Void ) {
27
34
self . storage. collectionsProfiles. listProfiles ( callback: callback)
28
35
}
29
36
37
+ // MARK: - Collections
38
+
30
39
public func listCollections( identifiers: Set < PackageCollectionsModel . CollectionIdentifier > ? = nil ,
31
40
in profile: PackageCollectionsModel . Profile ? = nil ,
32
41
callback: @escaping ( Result < [ PackageCollectionsModel . Collection ] , Error > ) -> Void ) {
@@ -60,28 +69,6 @@ public struct PackageCollections: PackageCollectionsProtocol {
60
69
}
61
70
}
62
71
63
- public func findPackages(
64
- _ query: String ,
65
- collections: Set < PackageCollectionsModel . CollectionIdentifier > ? = nil ,
66
- profile: PackageCollectionsModel . Profile ? = nil ,
67
- callback: @escaping ( Result < PackageCollectionsModel . PackageSearchResult , Error > ) -> Void
68
- ) {
69
- let profile = profile ?? . default
70
-
71
- self . storage. collectionsProfiles. listSources ( in: profile) { result in
72
- switch result {
73
- case . failure( let error) :
74
- callback ( . failure( error) )
75
- case . success( let sources) :
76
- let identifiers = sources. map { . init( from: $0) } . filter { collections? . contains ( $0) ?? true }
77
- if identifiers. isEmpty {
78
- return callback ( . success( PackageCollectionsModel . PackageSearchResult ( items: [ ] ) ) )
79
- }
80
- self . storage. collections. searchPackages ( identifiers: identifiers, query: query, callback: callback)
81
- }
82
- }
83
- }
84
-
85
72
public func refreshCollections( in profile: PackageCollectionsModel . Profile ? = nil ,
86
73
callback: @escaping ( Result < [ PackageCollectionsModel . CollectionSource ] , Error > ) -> Void ) {
87
74
let profile = profile ?? . default
@@ -179,7 +166,7 @@ public struct PackageCollections: PackageCollectionsProtocol {
179
166
self . storage. collections. get ( identifier: . init( from: source) ) { result in
180
167
switch result {
181
168
case . failure:
182
- guard let provider = self . providers [ source. type] else {
169
+ guard let provider = self . collectionProviders [ source. type] else {
183
170
return callback ( . failure( UnknownProvider ( source. type) ) )
184
171
}
185
172
provider. get ( source, callback: callback)
@@ -189,6 +176,63 @@ public struct PackageCollections: PackageCollectionsProtocol {
189
176
}
190
177
}
191
178
179
+ // MARK: - Packages
180
+
181
+ public func findPackages(
182
+ _ query: String ,
183
+ collections: Set < PackageCollectionsModel . CollectionIdentifier > ? = nil ,
184
+ profile: PackageCollectionsModel . Profile ? = nil ,
185
+ callback: @escaping ( Result < PackageCollectionsModel . PackageSearchResult , Error > ) -> Void
186
+ ) {
187
+ let profile = profile ?? . default
188
+
189
+ self . storage. collectionsProfiles. listSources ( in: profile) { result in
190
+ switch result {
191
+ case . failure( let error) :
192
+ callback ( . failure( error) )
193
+ case . success( let sources) :
194
+ let identifiers = sources. map { . init( from: $0) } . filter { collections? . contains ( $0) ?? true }
195
+ if identifiers. isEmpty {
196
+ return callback ( . success( PackageCollectionsModel . PackageSearchResult ( items: [ ] ) ) )
197
+ }
198
+ self . storage. collections. searchPackages ( identifiers: identifiers, query: query, callback: callback)
199
+ }
200
+ }
201
+ }
202
+
203
+ // MARK: - Package Metadata
204
+
205
+ public func getPackageMetadata( _ reference: PackageReference ,
206
+ profile: PackageCollectionsModel . Profile ? = nil ,
207
+ callback: @escaping ( Result < PackageCollectionsModel . PackageMetadata , Error > ) -> Void ) {
208
+ let profile = profile ?? . default
209
+
210
+ // first find in storage
211
+ self . findPackage ( identifier: reference. identity, profile: profile) { result in
212
+ switch result {
213
+ case . failure( let error) :
214
+ callback ( . failure( error) )
215
+ case . success( let packageSearchResult) :
216
+ // then try to get more metadata from provider (optional)
217
+ self . metadataProvider. get ( reference: reference) { result in
218
+ switch result {
219
+ case . failure( let error) :
220
+ callback ( . failure( error) )
221
+ case . success( let basicMetadata) :
222
+ // finally merge the results
223
+ let metadata = PackageCollectionsModel . PackageMetadata (
224
+ package : Self . mergedPackageMetadata ( package : packageSearchResult. package , basicMetadata: basicMetadata) ,
225
+ collections: packageSearchResult. collections
226
+ )
227
+ callback ( . success( metadata) )
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+
234
+ // MARK: - Targets
235
+
192
236
public func listTargets(
193
237
collections: Set < PackageCollectionsModel . CollectionIdentifier > ? = nil ,
194
238
in profile: PackageCollectionsModel . Profile ? = nil ,
@@ -229,12 +273,7 @@ public struct PackageCollections: PackageCollectionsProtocol {
229
273
}
230
274
}
231
275
232
- // FIXME:
233
- public func getPackageMetadata( _ reference: PackageReference ,
234
- profile: PackageCollectionsModel . Profile ? = nil ,
235
- callback: @escaping ( Result < PackageCollectionsModel . PackageMetadata , Error > ) -> Void ) {
236
- fatalError ( " not implemented " )
237
- }
276
+ // MARK: - Private
238
277
239
278
// Fetch the collection from the network and store it in local storage
240
279
// This helps avoid network access in normal operations
@@ -245,7 +284,7 @@ public struct PackageCollections: PackageCollectionsProtocol {
245
284
if let errors = source. validate ( ) {
246
285
return callback ( . failure( MultipleErrors ( errors) ) )
247
286
}
248
- guard let provider = self . providers [ source. type] else {
287
+ guard let provider = self . collectionProviders [ source. type] else {
249
288
return callback ( . failure( UnknownProvider ( source. type) ) )
250
289
}
251
290
provider. get ( source) { result in
@@ -258,6 +297,27 @@ public struct PackageCollections: PackageCollectionsProtocol {
258
297
}
259
298
}
260
299
300
+ func findPackage(
301
+ identifier: PackageReference . PackageIdentity ,
302
+ profile: PackageCollectionsModel . Profile ? = nil ,
303
+ callback: @escaping ( Result < PackageCollectionsModel . PackageSearchResult . Item , Error > ) -> Void
304
+ ) {
305
+ let profile = profile ?? . default
306
+
307
+ self . storage. collectionsProfiles. listSources ( in: profile) { result in
308
+ switch result {
309
+ case . failure( let error) :
310
+ callback ( . failure( error) )
311
+ case . success( let sources) :
312
+ let identifiers = sources. map { PackageCollectionsModel . CollectionIdentifier ( from: $0) }
313
+ if identifiers. isEmpty {
314
+ return callback ( . failure( NotFoundError ( " \( identifier) " ) ) )
315
+ }
316
+ self . storage. collections. findPackage ( identifier: identifier, collectionIdentifiers: identifiers, callback: callback)
317
+ }
318
+ }
319
+ }
320
+
261
321
private func targetListResultFromCollections( _ collections: [ PackageCollectionsModel . Collection ] ) -> PackageCollectionsModel . TargetListResult {
262
322
var packageCollections = [ PackageReference : ( package : PackageCollectionsModel . Collection . Package , collections: Set < PackageCollectionsModel . CollectionIdentifier > ) ] ( )
263
323
var targetsPackages = [ String : ( target: PackageCollectionsModel . PackageTarget , packages: Set < PackageReference > ) ] ( )
@@ -285,15 +345,43 @@ public struct PackageCollections: PackageCollectionsProtocol {
285
345
. compactMap { packageCollections [ $0] }
286
346
. map { pair -> PackageCollectionsModel . TargetListResult . Package in
287
347
let versions = pair. package . versions. map { PackageCollectionsModel . TargetListResult. PackageVersion ( version: $0. version, packageName: $0. packageName) }
288
- return PackageCollectionsModel . TargetListResult . Package ( repository: pair. package . repository,
289
- description: pair. package . summary,
290
- versions: versions,
291
- collections: Array ( pair. collections) )
348
+ return . init ( repository: pair. package . repository,
349
+ description: pair. package . summary,
350
+ versions: versions,
351
+ collections: Array ( pair. collections) )
292
352
}
293
353
294
354
return PackageCollectionsModel . TargetListItem ( target: pair. target, packages: targetPackages)
295
355
}
296
356
}
357
+
358
+ internal static func mergedPackageMetadata( package : PackageCollectionsModel . Collection . Package ,
359
+ basicMetadata: PackageCollectionsModel . PackageBasicMetadata ? ) -> PackageCollectionsModel . Package {
360
+ var versions = package . versions. map { packageVersion -> PackageCollectionsModel . Package . Version in
361
+ . init( version: packageVersion. version,
362
+ packageName: packageVersion. packageName,
363
+ targets: packageVersion. targets,
364
+ products: packageVersion. products,
365
+ toolsVersion: packageVersion. toolsVersion,
366
+ verifiedPlatforms: packageVersion. verifiedPlatforms,
367
+ verifiedSwiftVersions: packageVersion. verifiedSwiftVersions,
368
+ license: packageVersion. license)
369
+ }
370
+
371
+ // uses TSCUtility.Version comparator
372
+ versions. sort ( by: { lhs, rhs in lhs. version > rhs. version } )
373
+ let latestVersion = versions. first
374
+
375
+ return . init(
376
+ repository: package . repository,
377
+ description: basicMetadata? . description ?? package . summary,
378
+ versions: versions,
379
+ latestVersion: latestVersion,
380
+ watchersCount: basicMetadata? . watchersCount,
381
+ readmeURL: basicMetadata? . readmeURL ?? package . readmeURL,
382
+ authors: basicMetadata? . authors
383
+ )
384
+ }
297
385
}
298
386
299
387
private struct UnknownProvider : Error {
0 commit comments