Skip to content

Commit 347880c

Browse files
committed
simplify package collections model
motivation: simpler is nicer changes: * dedupe collection.package and package, and collection.package.version and pacakge.version as they ended up very similar * add keywords to package and package basic metadata * adjust code & tests
1 parent 9acfcfe commit 347880c

18 files changed

+876
-849
lines changed

Sources/PackageCollections/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ add_library(PackageCollections
1717
Providers/JSONPackageCollectionProvider.swift
1818
Providers/PackageCollectionProvider.swift
1919
Providers/PackageMetadataProvider.swift
20+
Storage/FilePackageCollectionsSourcesStorage.swift
2021
Storage/PackageCollectionsSourcesStorage.swift
2122
Storage/PackageCollectionsStorage.swift
23+
Storage/SQLitePackageCollectionsStorage.swift
2224
API.swift
2325
PackageCollections.swift
2426
PackageCollections+Configuration.swift

Sources/PackageCollections/Model/Collection.swift

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -141,74 +141,3 @@ extension PackageCollectionsModel.CollectionIdentifier: Codable {
141141
}
142142
}
143143
}
144-
145-
// FIXME: add minimumPlatformVersions
146-
extension PackageCollectionsModel.Collection {
147-
/// A representation of package metadata
148-
public struct Package: Equatable, Codable {
149-
public typealias Version = PackageVersion
150-
151-
/// Package reference
152-
public let reference: PackageReference
153-
154-
/// Package's repository address
155-
public let repository: RepositorySpecifier
156-
157-
/// A summary about the package
158-
public let summary: String?
159-
160-
/// Published versions of the package
161-
public let versions: [Version]
162-
163-
/// URL of the package's README
164-
public let readmeURL: URL?
165-
166-
/// Initializes a `Package`
167-
init(
168-
repository: RepositorySpecifier,
169-
summary: String?,
170-
versions: [Version],
171-
readmeURL: URL?
172-
) {
173-
self.reference = .init(repository: repository)
174-
self.repository = repository
175-
self.summary = summary
176-
self.versions = versions
177-
self.readmeURL = readmeURL
178-
}
179-
}
180-
}
181-
182-
extension PackageCollectionsModel.Collection {
183-
/// A representation of package version
184-
public struct PackageVersion: Equatable, Codable {
185-
public typealias Target = PackageCollectionsModel.PackageTarget
186-
public typealias Product = PackageCollectionsModel.PackageProduct
187-
188-
/// The version
189-
public let version: TSCUtility.Version
190-
191-
/// The package name
192-
public let packageName: String
193-
194-
// Custom instead of `PackageModel.Target` because we don't need the additional details
195-
/// The package version's targets
196-
public let targets: [Target]
197-
198-
// Custom instead of `PackageModel.Product` because of the simplified `Target`
199-
/// The package version's products
200-
public let products: [Product]
201-
202-
/// The package version's Swift tools version
203-
public let toolsVersion: ToolsVersion
204-
205-
/// The package version's supported platforms verified to work
206-
public let verifiedPlatforms: [PackageModel.Platform]?
207-
208-
/// The package version's Swift versions verified to work
209-
public let verifiedSwiftVersions: [SwiftLanguageVersion]?
210-
211-
/// The package version's license
212-
public let license: PackageCollectionsModel.License?
213-
}
214-
}

Sources/PackageCollections/Model/Package.swift

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import SourceControl
1515

1616
extension PackageCollectionsModel {
1717
/// Package metadata
18-
public struct Package: Equatable {
18+
public struct Package: Codable, Equatable {
1919
/// Package reference
2020
public let reference: PackageReference
2121

@@ -25,6 +25,9 @@ extension PackageCollectionsModel {
2525
/// Package description
2626
public let description: String?
2727

28+
/// Keywords for the package
29+
public let keywords: [String]?
30+
2831
/// Published versions of the package
2932
public let versions: [Version]
3033

@@ -67,6 +70,7 @@ extension PackageCollectionsModel {
6770
init(
6871
repository: RepositorySpecifier,
6972
description: String?,
73+
keywords: [String]?,
7074
versions: [Version],
7175
latestVersion: Version?,
7276
watchersCount: Int?,
@@ -76,6 +80,7 @@ extension PackageCollectionsModel {
7680
self.reference = .init(repository: repository)
7781
self.repository = repository
7882
self.description = description
83+
self.keywords = keywords
7984
self.versions = versions
8085
self.latestVersion = latestVersion
8186
self.watchersCount = watchersCount
@@ -88,9 +93,9 @@ extension PackageCollectionsModel {
8893
// FIXME: add minimumPlatformVersions
8994
extension PackageCollectionsModel.Package {
9095
/// A representation of package version
91-
public struct Version: Equatable {
92-
public typealias Target = PackageCollectionsModel.PackageTarget
93-
public typealias Product = PackageCollectionsModel.PackageProduct
96+
public struct Version: Codable, Equatable {
97+
public typealias Target = PackageCollectionsModel.Target
98+
public typealias Product = PackageCollectionsModel.Product
9499

95100
/// The version
96101
public let version: TSCUtility.Version
@@ -122,7 +127,7 @@ extension PackageCollectionsModel.Package {
122127

123128
extension PackageCollectionsModel {
124129
/// A representation of package target
125-
public struct PackageTarget: Equatable, Hashable, Codable {
130+
public struct Target: Equatable, Hashable, Codable {
126131
/// The target name
127132
public let name: String
128133

@@ -133,15 +138,15 @@ extension PackageCollectionsModel {
133138

134139
extension PackageCollectionsModel {
135140
/// A representation of package product
136-
public struct PackageProduct: Equatable, Codable {
141+
public struct Product: Equatable, Codable {
137142
/// The product name
138143
public let name: String
139144

140145
/// The product type
141146
public let type: ProductType
142147

143148
/// The product's targets
144-
public let targets: [PackageTarget]
149+
public let targets: [Target]
145150
}
146151
}
147152

Sources/PackageCollections/Model/Search.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ extension PackageCollectionsModel {
1818
public struct Item {
1919
// Merged package metadata from across collections
2020
/// The matching package
21-
public let package: PackageCollectionsModel.Collection.Package
21+
public let package: PackageCollectionsModel.Package
2222

2323
/// Package collections that contain the package
2424
public let collections: [PackageCollectionsModel.CollectionIdentifier]

Sources/PackageCollections/Model/TargetListResult.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ extension PackageCollectionsModel {
1717
public typealias TargetListResult = [TargetListItem]
1818

1919
public struct TargetListItem {
20-
public typealias Target = PackageCollectionsModel.PackageTarget
2120
public typealias Package = PackageCollectionsModel.TargetListResult.Package
2221

2322
/// Target

Sources/PackageCollections/PackageCollections.swift

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,44 @@ import TSCBasic
1414
// TODO: is there a better name? this conflicts with the module name which is okay in this case but not ideal in Swift
1515
public struct PackageCollections: PackageCollectionsProtocol {
1616
private let configuration: Configuration
17-
private let storage: Storage
17+
private let storageContainer: (storage: Storage, owned: Bool)
1818
private let collectionProviders: [PackageCollectionsModel.CollectionSourceType: PackageCollectionProvider]
1919
private let metadataProvider: PackageMetadataProvider
2020

21-
init(configuration: Configuration,
21+
private var storage: Storage {
22+
self.storageContainer.storage
23+
}
24+
25+
// initialize with defaults
26+
public init(configuration: Configuration = .init()) {
27+
let storage = Storage(sources: FilePackageCollectionsSourcesStorage(),
28+
collections: SQLitePackageCollectionsStorage())
29+
let collectionProviders = [PackageCollectionsModel.CollectionSourceType.json: JSONPackageCollectionProvider()]
30+
let metadataProvider = GitHubPackageMetadataProvider()
31+
32+
self.configuration = configuration
33+
self.storageContainer = (storage, true)
34+
self.collectionProviders = collectionProviders
35+
self.metadataProvider = metadataProvider
36+
}
37+
38+
// internal initializer for testing
39+
init(configuration: Configuration = .init(),
2240
storage: Storage,
2341
collectionProviders: [PackageCollectionsModel.CollectionSourceType: PackageCollectionProvider],
2442
metadataProvider: PackageMetadataProvider) {
2543
self.configuration = configuration
26-
self.storage = storage
44+
self.storageContainer = (storage, false)
2745
self.collectionProviders = collectionProviders
2846
self.metadataProvider = metadataProvider
2947
}
3048

49+
public func shutdown() throws {
50+
if self.storageContainer.owned {
51+
try self.storageContainer.storage.close()
52+
}
53+
}
54+
3155
// MARK: - Collections
3256

3357
public func listCollections(identifiers: Set<PackageCollectionsModel.CollectionIdentifier>? = nil,
@@ -279,8 +303,8 @@ public struct PackageCollections: PackageCollectionsProtocol {
279303
}
280304

281305
private func targetListResultFromCollections(_ collections: [PackageCollectionsModel.Collection]) -> PackageCollectionsModel.TargetListResult {
282-
var packageCollections = [PackageReference: (package: PackageCollectionsModel.Collection.Package, collections: Set<PackageCollectionsModel.CollectionIdentifier>)]()
283-
var targetsPackages = [String: (target: PackageCollectionsModel.PackageTarget, packages: Set<PackageReference>)]()
306+
var packageCollections = [PackageReference: (package: PackageCollectionsModel.Package, collections: Set<PackageCollectionsModel.CollectionIdentifier>)]()
307+
var targetsPackages = [String: (target: PackageCollectionsModel.Target, packages: Set<PackageReference>)]()
284308

285309
collections.forEach { collection in
286310
collection.packages.forEach { package in
@@ -306,7 +330,7 @@ public struct PackageCollections: PackageCollectionsProtocol {
306330
.map { pair -> PackageCollectionsModel.TargetListResult.Package in
307331
let versions = pair.package.versions.map { PackageCollectionsModel.TargetListResult.PackageVersion(version: $0.version, packageName: $0.packageName) }
308332
return .init(repository: pair.package.repository,
309-
description: pair.package.summary,
333+
description: pair.package.description,
310334
versions: versions,
311335
collections: Array(pair.collections))
312336
}
@@ -315,7 +339,7 @@ public struct PackageCollections: PackageCollectionsProtocol {
315339
}
316340
}
317341

318-
internal static func mergedPackageMetadata(package: PackageCollectionsModel.Collection.Package,
342+
internal static func mergedPackageMetadata(package: PackageCollectionsModel.Package,
319343
basicMetadata: PackageCollectionsModel.PackageBasicMetadata?) -> PackageCollectionsModel.Package {
320344
var versions = package.versions.map { packageVersion -> PackageCollectionsModel.Package.Version in
321345
.init(version: packageVersion.version,
@@ -334,7 +358,8 @@ public struct PackageCollections: PackageCollectionsProtocol {
334358

335359
return .init(
336360
repository: package.repository,
337-
description: basicMetadata?.description ?? package.summary,
361+
description: basicMetadata?.description ?? package.description,
362+
keywords: basicMetadata?.keywords ?? package.keywords,
338363
versions: versions,
339364
latestVersion: latestVersion,
340365
watchersCount: basicMetadata?.watchersCount,

Sources/PackageCollections/Providers/GitHubPackageMetadataProvider.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider {
4242

4343
func get(_ reference: PackageReference, callback: @escaping (Result<PackageCollectionsModel.PackageBasicMetadata, Error>) -> Void) {
4444
guard reference.kind == .remote else {
45-
return callback(.failure(Errors.unprocessable(reference)))
45+
return callback(.failure(Errors.invalidReferenceType(reference)))
4646
}
4747
guard let baseURL = self.apiURL(reference.path) else {
48-
return callback(.failure(Errors.unprocessable(reference)))
48+
return callback(.failure(Errors.invalidGitUrl(reference.path)))
4949
}
5050

5151
let metadataURL = baseURL
@@ -103,6 +103,7 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider {
103103

104104
callback(.success(.init(
105105
description: metadata.description,
106+
keywords: metadata.topics,
106107
versions: tags.compactMap { TSCUtility.Version(string: $0.name) },
107108
watchersCount: metadata.watchersCount,
108109
readmeURL: readme?.downloadURL,
@@ -154,7 +155,8 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider {
154155
}
155156

156157
enum Errors: Error, Equatable {
157-
case unprocessable(PackageReference)
158+
case invalidReferenceType(PackageReference)
159+
case invalidGitUrl(String)
158160
case invalidResponse(URL)
159161
}
160162
}
@@ -164,6 +166,7 @@ extension GitHubPackageMetadataProvider {
164166
let name: String
165167
let fullName: String
166168
let description: String?
169+
let topics: [String]?
167170
let isPrivate: Bool
168171
let isFork: Bool
169172
let defaultBranch: String
@@ -181,6 +184,7 @@ extension GitHubPackageMetadataProvider {
181184
case name
182185
case fullName = "full_name"
183186
case description
187+
case topics
184188
case isPrivate = "private"
185189
case isFork = "fork"
186190
case defaultBranch = "default_branch"

Sources/PackageCollections/Providers/JSONPackageCollectionProvider.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,17 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider {
9393
return .failure(Errors.invalidJSON(error))
9494
}
9595

96-
let packages = collection.packages.map { package -> PackageCollectionsModel.Collection.Package in
97-
let versions = package.versions.compactMap { version -> PackageCollectionsModel.Collection.Package.Version? in
96+
let packages = collection.packages.map { package -> PackageCollectionsModel.Package in
97+
let versions = package.versions.compactMap { version -> PackageCollectionsModel.Package.Version? in
9898
// note this filters out / ignores missing / bad data in attempt to make the most out of the provided set
9999
guard let parsedVersion = TSCUtility.Version(string: version.version) else {
100100
return nil
101101
}
102102
guard let toolsVersion = ToolsVersion(string: version.toolsVersion) else {
103103
return nil
104104
}
105-
let targets = version.targets.map { PackageCollectionsModel.PackageTarget(name: $0.name, moduleName: $0.moduleName) }
106-
let products = version.products.compactMap { PackageCollectionsModel.PackageProduct(from: $0, packageTargets: targets) }
105+
let targets = version.targets.map { PackageCollectionsModel.Target(name: $0.name, moduleName: $0.moduleName) }
106+
let products = version.products.compactMap { PackageCollectionsModel.Product(from: $0, packageTargets: targets) }
107107
let verifiedPlatforms: [PackageModel.Platform]? = version.verifiedPlatforms?.compactMap { PackageModel.Platform(from: $0) }
108108
let verifiedSwiftVersions = version.verifiedSwiftVersions?.compactMap { SwiftLanguageVersion(string: $0) }
109109
let license = version.license.flatMap { PackageCollectionsModel.License(from: $0) }
@@ -117,9 +117,13 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider {
117117
license: license)
118118
}
119119
return .init(repository: RepositorySpecifier(url: package.url),
120-
summary: package.description,
120+
description: package.description,
121+
keywords: package.keywords,
121122
versions: versions,
122-
readmeURL: package.readmeURL.flatMap { Foundation.URL(string: $0) })
123+
latestVersion: versions.last!,
124+
watchersCount: nil,
125+
readmeURL: package.readmeURL.flatMap { Foundation.URL(string: $0) },
126+
authors: nil)
123127
}
124128
return .success(.init(source: source,
125129
name: collection.name,
@@ -227,8 +231,8 @@ extension JSONPackageCollectionProvider.CollectionV1 {
227231

228232
// MARK: - Extensions for mapping from JSON to PackageCollectionsModel
229233

230-
extension PackageCollectionsModel.PackageProduct {
231-
fileprivate init?(from: JSONPackageCollectionProvider.CollectionV1.Product, packageTargets: [PackageCollectionsModel.PackageTarget]) {
234+
extension PackageCollectionsModel.Product {
235+
fileprivate init?(from: JSONPackageCollectionProvider.CollectionV1.Product, packageTargets: [PackageCollectionsModel.Target]) {
232236
let targets = packageTargets.filter { from.targets.map { $0.lowercased() }.contains($0.name.lowercased()) }
233237
self = .init(name: from.name, type: from.type, targets: targets)
234238
}

Sources/PackageCollections/Providers/PackageMetadataProvider.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ protocol PackageMetadataProvider {
2626
extension PackageCollectionsModel {
2727
struct PackageBasicMetadata: Equatable {
2828
let description: String?
29+
let keywords: [String]?
2930
let versions: [TSCUtility.Version]
3031
let watchersCount: Int?
3132
let readmeURL: Foundation.URL?

0 commit comments

Comments
 (0)