Skip to content

Commit 19337f2

Browse files
authored
[Collections] Update models to support version-specific manifests (#3226)
Motivation: Package collection models should support version-specific manifests. Modifications: - Update JSON and API models to have a dictionary of manifests by tools version. Each manifest contains package name, products, and targets. - Move collection format spec to this repo to be closer to the source. * 'minimumPlatformVersions' should also be part of 'Manifest' * Wire up JSON model validator * Validate manifest tools version * Add defaultToolsVersion * Fix cli tool, update docs
1 parent 7f91029 commit 19337f2

19 files changed

+1066
-443
lines changed

Fixtures/Collections/JSON/good.json

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,31 @@
2121
"versions": [
2222
{
2323
"version": "0.1.0",
24-
"packageName": "PackageOne",
25-
"targets": [
26-
{
27-
"name": "Foo",
28-
"moduleName": "Foo"
29-
}
30-
],
31-
"products": [
32-
{
33-
"name": "Foo",
34-
"type": {
35-
"library": ["automatic"]
36-
},
37-
"targets": ["Foo"]
24+
"manifests": {
25+
"5.1": {
26+
"toolsVersion": "5.1",
27+
"packageName": "PackageOne",
28+
"targets": [
29+
{
30+
"name": "Foo",
31+
"moduleName": "Foo"
32+
}
33+
],
34+
"products": [
35+
{
36+
"name": "Foo",
37+
"type": {
38+
"library": ["automatic"]
39+
},
40+
"targets": ["Foo"]
41+
}
42+
],
43+
"minimumPlatformVersions": [
44+
{ "name": "macOS", "version": "10.15" }
45+
]
3846
}
39-
],
40-
"toolsVersion": "5.1",
41-
"minimumPlatformVersions": [
42-
{ "name": "macOS", "version": "10.15" }
43-
],
47+
},
48+
"defaultToolsVersion": "5.1",
4449
"verifiedCompatibility": [
4550
{
4651
"platform": { "name": "macOS" },
@@ -69,43 +74,53 @@
6974
"versions": [
7075
{
7176
"version": "2.1.0",
72-
"packageName": "PackageTwo",
73-
"targets": [
74-
{
75-
"name": "Bar",
76-
"moduleName": "Bar"
77-
}
78-
],
79-
"products": [
80-
{
81-
"name": "Bar",
82-
"type": {
83-
"library": ["automatic"]
84-
},
85-
"targets": ["Bar"]
77+
"manifests": {
78+
"5.2": {
79+
"toolsVersion": "5.2",
80+
"packageName": "PackageTwo",
81+
"targets": [
82+
{
83+
"name": "Bar",
84+
"moduleName": "Bar"
85+
}
86+
],
87+
"products": [
88+
{
89+
"name": "Bar",
90+
"type": {
91+
"library": ["automatic"]
92+
},
93+
"targets": ["Bar"]
94+
}
95+
]
8696
}
87-
],
88-
"toolsVersion": "5.2"
97+
},
98+
"defaultToolsVersion": "5.2"
8999
},
90100
{
91101
"version": "1.8.3",
92-
"packageName": "PackageTwo",
93-
"targets": [
94-
{
95-
"name": "Bar",
96-
"moduleName": "Bar"
102+
"manifests": {
103+
"5.0": {
104+
"toolsVersion": "5.0",
105+
"packageName": "PackageTwo",
106+
"targets": [
107+
{
108+
"name": "Bar",
109+
"moduleName": "Bar"
110+
}
111+
],
112+
"products": [
113+
{
114+
"name": "Bar",
115+
"type": {
116+
"library": ["automatic"]
117+
},
118+
"targets": ["Bar"]
119+
}
120+
]
97121
}
98-
],
99-
"products": [
100-
{
101-
"name": "Bar",
102-
"type": {
103-
"library": ["automatic"]
104-
},
105-
"targets": ["Bar"]
106-
}
107-
],
108-
"toolsVersion": "5.0"
122+
},
123+
"defaultToolsVersion": "5.0"
109124
}
110125
]
111126
}

Fixtures/Collections/JSON/good_signed.json

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,31 @@
2121
"versions": [
2222
{
2323
"version": "0.1.0",
24-
"packageName": "PackageOne",
25-
"targets": [
26-
{
27-
"name": "Foo",
28-
"moduleName": "Foo"
29-
}
30-
],
31-
"products": [
32-
{
33-
"name": "Foo",
34-
"type": {
35-
"library": ["automatic"]
36-
},
37-
"targets": ["Foo"]
24+
"manifests": {
25+
"5.1": {
26+
"toolsVersion": "5.1",
27+
"packageName": "PackageOne",
28+
"targets": [
29+
{
30+
"name": "Foo",
31+
"moduleName": "Foo"
32+
}
33+
],
34+
"products": [
35+
{
36+
"name": "Foo",
37+
"type": {
38+
"library": ["automatic"]
39+
},
40+
"targets": ["Foo"]
41+
}
42+
],
43+
"minimumPlatformVersions": [
44+
{ "name": "macOS", "version": "10.15" }
45+
]
3846
}
39-
],
40-
"toolsVersion": "5.1",
41-
"minimumPlatformVersions": [
42-
{ "name": "macOS", "version": "10.15" }
43-
],
47+
},
48+
"defaultToolsVersion": "5.1",
4449
"verifiedCompatibility": [
4550
{
4651
"platform": { "name": "macOS" },
@@ -69,43 +74,53 @@
6974
"versions": [
7075
{
7176
"version": "2.1.0",
72-
"packageName": "PackageTwo",
73-
"targets": [
74-
{
75-
"name": "Bar",
76-
"moduleName": "Bar"
77-
}
78-
],
79-
"products": [
80-
{
81-
"name": "Bar",
82-
"type": {
83-
"library": ["automatic"]
84-
},
85-
"targets": ["Bar"]
77+
"manifests": {
78+
"5.2": {
79+
"toolsVersion": "5.2",
80+
"packageName": "PackageTwo",
81+
"targets": [
82+
{
83+
"name": "Bar",
84+
"moduleName": "Bar"
85+
}
86+
],
87+
"products": [
88+
{
89+
"name": "Bar",
90+
"type": {
91+
"library": ["automatic"]
92+
},
93+
"targets": ["Bar"]
94+
}
95+
]
8696
}
87-
],
88-
"toolsVersion": "5.2"
97+
},
98+
"defaultToolsVersion": "5.2"
8999
},
90100
{
91101
"version": "1.8.3",
92-
"packageName": "PackageTwo",
93-
"targets": [
94-
{
95-
"name": "Bar",
96-
"moduleName": "Bar"
102+
"manifests": {
103+
"5.0": {
104+
"toolsVersion": "5.0",
105+
"packageName": "PackageTwo",
106+
"targets": [
107+
{
108+
"name": "Bar",
109+
"moduleName": "Bar"
110+
}
111+
],
112+
"products": [
113+
{
114+
"name": "Bar",
115+
"type": {
116+
"library": ["automatic"]
117+
},
118+
"targets": ["Bar"]
119+
}
120+
]
97121
}
98-
],
99-
"products": [
100-
{
101-
"name": "Bar",
102-
"type": {
103-
"library": ["automatic"]
104-
},
105-
"targets": ["Bar"]
106-
}
107-
],
108-
"toolsVersion": "5.0"
122+
},
123+
"defaultToolsVersion": "5.0"
109124
}
110125
]
111126
}

Sources/Commands/SwiftPackageCollectionsTool.swift

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,18 @@ import TSCUtility
1919
private enum CollectionsError: Swift.Error {
2020
case invalidArgument(String)
2121
case invalidVersionString(String)
22+
case unsigned
2223
}
2324

2425
extension CollectionsError: CustomStringConvertible {
2526
var description: String {
2627
switch self {
2728
case .invalidArgument(let argumentName):
28-
return "invalid argument '\(argumentName)'"
29+
return "Invalid argument '\(argumentName)'"
2930
case .invalidVersionString(let versionString):
30-
return "invalid version string '\(versionString)'"
31+
return "Invalid version string '\(versionString)'"
32+
case .unsigned:
33+
return "The collection is not signed. If you would still like to add it please rerun 'add' with '--trust-unsigned'."
3134
}
3235
}
3336
}
@@ -100,23 +103,28 @@ public struct SwiftPackageCollectionsTool: ParsableCommand {
100103
@Option(name: .long, help: "Sort order for the added collection")
101104
var order: Int?
102105

103-
@Option(name: .long, help: "Trust the collection even if it is unsigned")
104-
var trustUnsigned: Bool?
106+
@Flag(name: .long, help: "Trust the collection even if it is unsigned")
107+
var trustUnsigned: Bool = false
105108

106109
mutating func run() throws {
107110
guard let collectionUrl = URL(string: collectionUrl) else {
108111
throw CollectionsError.invalidArgument("collectionUrl")
109112
}
110113

111114
let source = PackageCollectionsModel.CollectionSource(type: .json, url: collectionUrl)
112-
let collection = try with { collections in
113-
try tsc_await {
114-
collections.addCollection(
115-
source,
116-
order: order,
117-
trustConfirmationProvider: trustUnsigned.map { userTrusted in { _, callback in callback(userTrusted) } },
118-
callback: $0
119-
) }
115+
let collection: PackageCollectionsModel.Collection = try with { collections in
116+
do {
117+
let userTrusted = self.trustUnsigned
118+
return try tsc_await {
119+
collections.addCollection(
120+
source,
121+
order: order,
122+
trustConfirmationProvider: { _, callback in callback(userTrusted) },
123+
callback: $0
124+
) }
125+
} catch PackageCollectionError.trustConfirmationRequired, PackageCollectionError.untrusted {
126+
throw CollectionsError.unsigned
127+
}
120128
}
121129

122130
print("Added \"\(collection.name)\" to your package collections.")
@@ -210,19 +218,31 @@ public struct SwiftPackageCollectionsTool: ParsableCommand {
210218
guard let version = version else {
211219
return nil
212220
}
221+
guard let defaultManifest = version.defaultManifest else {
222+
return nil
223+
}
213224

214-
let modules = version.targets.compactMap { $0.moduleName }.joined(separator: ", ")
215-
let products = optionalRow("Products", version.products.isEmpty ? nil : version.products.compactMap { $0.name }.joined(separator: ", "))
225+
let manifests = version.manifests.values.filter { $0.toolsVersion != version.defaultToolsVersion }.map { printManifest($0) }.joined(separator: "\n")
216226
let compatibility = optionalRow(
217227
"Verified Compatibility (Platform, Swift Version)",
218228
version.verifiedCompatibility?.map { "(\($0.platform.name), \($0.swiftVersion.rawValue))" }.joined(separator: ", ")
219229
)
220230
let license = optionalRow("License", version.license?.type.description)
221-
231+
222232
return """
223233
\(version.version)
224-
Package Name: \(version.packageName)
225-
Modules: \(modules)\(products)\(compatibility)\(license)
234+
\(printManifest(defaultManifest))\(manifests)\(compatibility)\(license)
235+
"""
236+
}
237+
238+
private func printManifest(_ manifest: PackageCollectionsModel.Package.Version.Manifest) -> String {
239+
let modules = manifest.targets.compactMap { $0.moduleName }.joined(separator: ", ")
240+
let products = optionalRow("Products", manifest.products.isEmpty ? nil : manifest.products.compactMap { $0.name }.joined(separator: ", "), indentationLevel: 3)
241+
242+
return """
243+
Tools Version: \(manifest.toolsVersion.description)
244+
Package Name: \(manifest.packageName)
245+
Modules: \(modules)\(products)
226246
"""
227247
}
228248

0 commit comments

Comments
 (0)