Skip to content

Commit 9f4d4ec

Browse files
Restore Target‐Based Resolution (#3006)
* Reverted 27f444f (leaving conflicts marked). * Resolved conflicts. * Added failing test. * Fixed cache. * Patched other potentential issue. * Revert "Resolved conflicts." This reverts commit bcf41e7. * Revert "Reverted 27f444f (leaving conflicts marked)." This reverts commit 4a0abc0.
1 parent 04347a5 commit 9f4d4ec

File tree

8 files changed

+71
-7
lines changed

8 files changed

+71
-7
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// swift-tools-version:4.0
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "SRP",
7+
products: [
8+
.library(name: "SRP", targets: ["SRP"]),
9+
],
10+
dependencies: [
11+
.package(url: "https://github.com/IBM-Swift/BlueCryptor.git", from: "0.8.16"),
12+
.package(url: "https://github.com/lorentey/BigInt.git", from: "3.0.0"),
13+
],
14+
targets: [
15+
.target(name: "SRP", dependencies: ["Cryptor", "BigInt"], path: "Sources"),
16+
.testTarget(name: "SRPTests", dependencies: ["Cryptor", "SRP"]),
17+
],
18+
swiftLanguageVersions: [4]
19+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Reduced from https://github.com/Bouke/SRP/tree/b166838d4cf9218933c03151d62e50772460f95e, which was tripping rdar://problem/65284674.

Fixtures/DependencyResolution/Regressions/SRP/Sources/SRP/SRP.swift

Whitespace-only changes.

Fixtures/DependencyResolution/Regressions/SRP/Tests/SRPTests/SRPTests.swift

Whitespace-only changes.

Sources/PackageGraph/RepositoryPackageContainer.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public class RepositoryPackageContainer: BasePackageContainer, CustomStringConve
8787
let _reversedVersions: [Version]
8888

8989
/// The cached dependency information.
90-
private var dependenciesCache: [String: (Manifest, [RepositoryPackageConstraint])] = [:]
90+
private var dependenciesCache: [String: [ProductFilter: (Manifest, [RepositoryPackageConstraint])]] = [:]
9191
private var dependenciesCacheLock = Lock()
9292

9393
init(
@@ -157,7 +157,7 @@ public class RepositoryPackageContainer: BasePackageContainer, CustomStringConve
157157

158158
public override func getDependencies(at version: Version, productFilter: ProductFilter) throws -> [RepositoryPackageConstraint] {
159159
do {
160-
return try cachedDependencies(forIdentifier: version.description) {
160+
return try cachedDependencies(forIdentifier: version.description, productFilter: productFilter) {
161161
let tag = knownVersions[version]!
162162
let revision = try repository.resolveRevision(tag: tag)
163163
return try getDependencies(at: revision, version: version, productFilter: productFilter)
@@ -170,7 +170,7 @@ public class RepositoryPackageContainer: BasePackageContainer, CustomStringConve
170170

171171
public override func getDependencies(at revision: String, productFilter: ProductFilter) throws -> [RepositoryPackageConstraint] {
172172
do {
173-
return try cachedDependencies(forIdentifier: revision) {
173+
return try cachedDependencies(forIdentifier: revision, productFilter: productFilter) {
174174
// resolve the revision identifier and return its dependencies.
175175
let revision = try repository.resolveRevision(identifier: revision)
176176
return try getDependencies(at: revision, productFilter: productFilter)
@@ -203,14 +203,15 @@ public class RepositoryPackageContainer: BasePackageContainer, CustomStringConve
203203

204204
private func cachedDependencies(
205205
forIdentifier identifier: String,
206+
productFilter: ProductFilter,
206207
getDependencies: () throws -> (Manifest, [RepositoryPackageConstraint])
207208
) throws -> (Manifest, [RepositoryPackageConstraint]) {
208209
return try dependenciesCacheLock.withLock {
209-
if let result = dependenciesCache[identifier] {
210+
if let result = dependenciesCache[identifier, default: [:]][productFilter] {
210211
return result
211212
}
212213
let result = try getDependencies()
213-
dependenciesCache[identifier] = result
214+
dependenciesCache[identifier, default: [:]][productFilter] = result
214215
return result
215216
}
216217
}

Sources/SPMTestSupport/misc.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,20 @@ public func executeSwiftRun(
164164
return try SwiftPMProduct.SwiftRun.execute(args, packagePath: packagePath, env: env)
165165
}
166166

167+
@discardableResult
168+
public func executeSwiftPackage(
169+
_ packagePath: AbsolutePath,
170+
configuration: Configuration = .Debug,
171+
extraArgs: [String] = [],
172+
Xcc: [String] = [],
173+
Xld: [String] = [],
174+
Xswiftc: [String] = [],
175+
env: [String: String]? = nil
176+
) throws -> (stdout: String, stderr: String) {
177+
let args = swiftArgs(configuration: configuration, extraArgs: extraArgs, Xcc: Xcc, Xld: Xld, Xswiftc: Xswiftc)
178+
return try SwiftPMProduct.SwiftPackage.execute(args, packagePath: packagePath, env: env)
179+
}
180+
167181
private func swiftArgs(
168182
configuration: Configuration,
169183
extraArgs: [String],

Sources/Workspace/Workspace.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,14 +1240,28 @@ extension Workspace {
12401240
var loadedManifests = [String: Manifest]()
12411241

12421242
// Compute the transitive closure of available dependencies.
1243-
let allManifests = try! topologicalSort(inputManifests.map({ KeyedPair(($0, ProductFilter.everything), key: $0.name)})) { node in
1243+
struct NameAndFilter: Hashable { // Just because a raw tuple cannot be hashable.
1244+
let name: String
1245+
let filter: ProductFilter
1246+
}
1247+
let allManifestsWithPossibleDuplicates = try! topologicalSort(inputManifests.map({ KeyedPair(($0, ProductFilter.everything), key: NameAndFilter(name: $0.name, filter: .everything)) })) { node in
12441248
return node.item.0.dependenciesRequired(for: node.item.1).compactMap({ dependency in
12451249
let url = config.mirrors.effectiveURL(forURL: dependency.url)
12461250
let manifest = loadedManifests[url] ?? loadManifest(forURL: url, diagnostics: diagnostics)
12471251
loadedManifests[url] = manifest
1248-
return manifest.flatMap({ KeyedPair(($0, dependency.productFilter), key: $0.name) })
1252+
return manifest.flatMap({ KeyedPair(($0, dependency.productFilter), key: NameAndFilter(name: $0.name, filter: dependency.productFilter)) })
12491253
})
12501254
}
1255+
var deduplication: Set<String> = []
1256+
var allManifests: [KeyedPair<(Manifest, ProductFilter), NameAndFilter>] = []
1257+
for node in allManifestsWithPossibleDuplicates {
1258+
if deduplication.contains(node.item.0.name) {
1259+
continue // A duplicate.
1260+
} else {
1261+
allManifests.append(node)
1262+
deduplication.insert(node.item.0.name)
1263+
}
1264+
}
12511265

12521266
let allDependencyManifests = allManifests.map({ $0.item }).filter({ !root.manifests.contains($0.0) })
12531267
let deps = allDependencyManifests.map({ ($0, state.dependencies[forURL: $0.url]!, $1) })

Tests/FunctionalTests/DependencyResolutionTests.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,19 @@ class DependencyResolutionTests: XCTestCase {
6565
XCTAssertEqual(output, "♣︎K\n♣︎Q\n♣︎J\n♣︎10\n♣︎9\n♣︎8\n♣︎7\n♣︎6\n♣︎5\n♣︎4\n")
6666
}
6767
}
68+
69+
func testRepositoryCacheDoesNotDerailResolution() throws {
70+
// From rdar://problem/65284674
71+
// RepositoryPackageContainer used to erroneously cache dependencies based only on version,
72+
// storing the result of the first product filter and then continually returning it for other filters too.
73+
// This lead to corrupt graph states.
74+
guard Resources.havePD4Runtime else {
75+
throw XCTSkip("PackageDescription v4 is unavailable; this test requires the compiler script instead of a self‐hosted build.")
76+
}
77+
78+
fixture(name: "DependencyResolution/Regressions/SRP") { prefix in
79+
let (output, error) = try executeSwiftPackage(prefix, extraArgs: ["resolve"])
80+
XCTAssert(error.isEmpty, output + error)
81+
}
82+
}
6883
}

0 commit comments

Comments
 (0)