Skip to content

Commit bb7f9e7

Browse files
committed
[PubGrub] Note that selected package version is backed by a provided library
First step on the path to remove `ProvidedLibraryPackageContainer` and `PackageReference.providedLibrary` and fix a problem where a package backed by a provided library has to be always treated as "new" or "updated" by `precomputeResolution` which triggers full resolution.
1 parent 04b26ea commit bb7f9e7

File tree

7 files changed

+38
-85
lines changed

7 files changed

+38
-85
lines changed

Sources/PackageGraph/BoundVersion.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import struct PackageModel.ProvidedLibrary
1314
import struct TSCUtility.Version
1415

1516
/// A bound version for a package within an assignment.
@@ -22,7 +23,7 @@ public enum BoundVersion: Equatable, Hashable {
2223
case excluded
2324

2425
/// The version of the package to include.
25-
case version(Version)
26+
case version(Version, library: ProvidedLibrary? = nil)
2627

2728
/// The package assignment is unversioned.
2829
case unversioned
@@ -36,7 +37,7 @@ extension BoundVersion: CustomStringConvertible {
3637
switch self {
3738
case .excluded:
3839
return "excluded"
39-
case .version(let version):
40+
case .version(let version, _):
4041
return version.description
4142
case .unversioned:
4243
return "unversioned"

Sources/PackageGraph/Resolution/PubGrub/PubGrubDependencyResolver.swift

+16-19
Original file line numberDiff line numberDiff line change
@@ -231,35 +231,32 @@ public struct PubGrubDependencyResolver {
231231
continue
232232
}
233233

234-
var package = assignment.term.node.package
234+
let package = assignment.term.node.package
235235

236236
let boundVersion: BoundVersion
237237
switch assignment.term.requirement {
238238
case .exact(let version):
239-
boundVersion = .version(version)
239+
if let library = package.matchingPrebuiltLibrary(in: availableLibraries),
240+
version == library.version
241+
{
242+
boundVersion = .version(version, library: library)
243+
} else {
244+
boundVersion = .version(version)
245+
}
240246
case .range, .any, .empty, .ranges:
241247
throw InternalError("unexpected requirement value for assignment \(assignment.term)")
242248
}
243249

244-
if let library = package.matchingPrebuiltLibrary(in: availableLibraries),
245-
boundVersion == .version(library.version)
246-
{
247-
guard case .remoteSourceControl(let url) = package.kind else {
248-
throw InternalError("Matched provided library against invalid package: \(package)")
249-
}
250-
251-
package = .providedLibrary(
252-
identity: package.identity,
253-
origin: url,
254-
path: library.location
255-
)
256-
}
257-
258250
let products = assignment.term.node.productFilter
259251

260-
// TODO: replace with async/await when available
261-
let container = try temp_await { self.provider.getContainer(for: package, completion: $0) }
262-
let updatePackage = try container.underlying.loadPackageReference(at: boundVersion)
252+
let updatePackage: PackageReference
253+
if case .version(_, let library) = boundVersion, library != nil {
254+
updatePackage = package
255+
} else {
256+
// TODO: replace with async/await when available
257+
let container = try temp_await { self.provider.getContainer(for: package, completion: $0) }
258+
updatePackage = try container.underlying.loadPackageReference(at: boundVersion)
259+
}
263260

264261
if var existing = flattenedAssignments[updatePackage] {
265262
guard existing.binding == boundVersion else {

Sources/PackageModel/InstalledLibrariesSupport/LibraryMetadata.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import Basics
1414
import struct TSCUtility.Version
1515

16-
public struct ProvidedLibrary {
16+
public struct ProvidedLibrary: Hashable {
1717
public let location: AbsolutePath
1818
public let metadata: LibraryMetadata
1919

@@ -22,8 +22,8 @@ public struct ProvidedLibrary {
2222
}
2323
}
2424

25-
public struct LibraryMetadata: Decodable {
26-
public enum Identity: Equatable, Decodable {
25+
public struct LibraryMetadata: Hashable, Decodable {
26+
public enum Identity: Hashable, Decodable {
2727
case packageIdentity(scope: String, name: String)
2828
case sourceControl(url: SourceControlURL)
2929
}

Sources/Workspace/PackageContainer/SourceControlPackageContainer.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ internal final class SourceControlPackageContainer: PackageContainer, CustomStri
354354
let revision: Revision
355355
var version: Version?
356356
switch boundVersion {
357-
case .version(let v):
357+
case .version(let v, _):
358358
guard let tag = try self.knownVersions()[v] else {
359359
throw StringError("unknown tag \(v)")
360360
}

Sources/Workspace/Workspace+Dependencies.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,7 @@ extension Workspace {
10961096
packageStateChanges[binding.package.identity] = (binding.package, .added(newState))
10971097
}
10981098

1099-
case .version(let version):
1099+
case .version(let version, _):
11001100
let stateChange: PackageStateChange
11011101
switch currentDependency?.state {
11021102
case .sourceControlCheckout(.version(version, _)),

Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class DependencyResolverRealWorldPerfTests: XCTestCasePerf {
6969
switch resolver.solve(constraints: graph.constraints) {
7070
case .success(let result):
7171
let result: [(container: PackageReference, version: Version)] = result.compactMap {
72-
guard case .version(let version) = $0.boundVersion else {
72+
guard case .version(let version, _) = $0.boundVersion else {
7373
XCTFail("Unexpected result")
7474
return nil
7575
}

Tests/PackageGraphTests/PubgrubTests.swift

+13-58
Original file line numberDiff line numberDiff line change
@@ -2046,16 +2046,12 @@ final class PubGrubTestsBasicGraphs: XCTestCase {
20462046
let result = resolver.solve(constraints: dependencies1)
20472047
print(try result.get())
20482048
AssertResult(result, [
2049-
(
2050-
"foo",
2051-
.providedLibrary(.init("https://example.com/org/foo"), .init("/foo")),
2052-
.version(.init(stringLiteral: "1.0.0"))
2053-
),
2049+
("foo", .version(.init(stringLiteral: "1.0.0"), library: availableLibraries.first!)),
20542050
])
20552051

20562052
let result2 = resolver.solve(constraints: dependencies2)
20572053
AssertResult(result2, [
2058-
("foo", fooRef.kind, .version(.init(stringLiteral: "1.2.0"))),
2054+
("foo", .version(.init(stringLiteral: "1.2.0"))),
20592055
])
20602056
}
20612057

@@ -2114,16 +2110,8 @@ final class PubGrubTestsBasicGraphs: XCTestCase {
21142110

21152111
let result = resolver.solve(constraints: dependencies)
21162112
AssertResult(result, [
2117-
(
2118-
"foo",
2119-
.providedLibrary(.init("https://example.com/org/foo"), .init("/foo")),
2120-
.version(.init(stringLiteral: "1.1.0"))
2121-
),
2122-
(
2123-
"target",
2124-
.localSourceControl("/target"),
2125-
.version(.init(stringLiteral: "2.0.0"))
2126-
),
2113+
("foo", .version(.init(stringLiteral: "1.1.0"), library: availableLibraries.first!)),
2114+
("target", .version(.init(stringLiteral: "2.0.0"))),
21272115
])
21282116
}
21292117

@@ -2167,8 +2155,8 @@ final class PubGrubTestsBasicGraphs: XCTestCase {
21672155

21682156
let result = resolver.solve(constraints: dependencies)
21692157
AssertResult(result, [
2170-
("foo", fooRef.kind, .version(.init(stringLiteral: "1.1.0"))),
2171-
("bar", .localSourceControl("/bar"), .version(.init(stringLiteral: "1.0.0"))),
2158+
("foo", .version(.init(stringLiteral: "1.1.0"))),
2159+
("bar", .version(.init(stringLiteral: "1.0.0"))),
21722160
])
21732161
}
21742162
}
@@ -3312,22 +3300,6 @@ private func AssertBindings(
33123300
_ packages: [(identity: PackageIdentity, version: BoundVersion)],
33133301
file: StaticString = #file,
33143302
line: UInt = #line
3315-
) {
3316-
AssertBindings(
3317-
bindings,
3318-
packages.map {
3319-
(identity: $0, kind: nil, version: $1)
3320-
},
3321-
file: file,
3322-
line: line
3323-
)
3324-
}
3325-
3326-
private func AssertBindings(
3327-
_ bindings: [DependencyResolverBinding],
3328-
_ packages: [(identity: PackageIdentity, kind: PackageReference.Kind?, version: BoundVersion)],
3329-
file: StaticString = #file,
3330-
line: UInt = #line
33313303
) {
33323304
if bindings.count > packages.count {
33333305
let unexpectedBindings = bindings
@@ -3346,15 +3318,7 @@ private func AssertBindings(
33463318
}
33473319
for package in packages {
33483320
guard let binding = bindings.first(where: {
3349-
if $0.package.identity != package.identity {
3350-
return false
3351-
}
3352-
3353-
if let kind = package.kind, $0.package.kind != kind {
3354-
return false
3355-
}
3356-
3357-
return true
3321+
$0.package.identity == package.identity
33583322
}) else {
33593323
XCTFail("No binding found for \(package.identity).", file: file, line: line)
33603324
continue
@@ -3376,21 +3340,12 @@ private func AssertResult(
33763340
_ packages: [(identifier: String, version: BoundVersion)],
33773341
file: StaticString = #file,
33783342
line: UInt = #line
3379-
) {
3380-
AssertResult(result, packages.map { ($0, nil, $1) }, file: file, line: line)
3381-
}
3382-
3383-
private func AssertResult(
3384-
_ result: Result<[DependencyResolverBinding], Error>,
3385-
_ packages: [(identifier: String, kind: PackageReference.Kind?, version: BoundVersion)],
3386-
file: StaticString = #file,
3387-
line: UInt = #line
33883343
) {
33893344
switch result {
33903345
case .success(let bindings):
33913346
AssertBindings(
33923347
bindings,
3393-
packages.map { (PackageIdentity($0.identifier), $0.kind, $0.version) },
3348+
packages.map { (PackageIdentity($0.identifier), $0.version) },
33943349
file: file,
33953350
line: line
33963351
)
@@ -3440,7 +3395,7 @@ public class MockContainer: PackageContainer {
34403395
public func toolsVersionsAppropriateVersionsDescending() throws -> [Version] {
34413396
var versions: [Version] = []
34423397
for version in self._versions.reversed() {
3443-
guard case .version(let v) = version else { continue }
3398+
guard case .version(let v, _) = version else { continue }
34443399
versions.append(v)
34453400
}
34463401
return versions
@@ -3449,7 +3404,7 @@ public class MockContainer: PackageContainer {
34493404
public func versionsAscending() throws -> [Version] {
34503405
var versions: [Version] = []
34513406
for version in self._versions {
3452-
guard case .version(let v) = version else { continue }
3407+
guard case .version(let v, _) = version else { continue }
34533408
versions.append(v)
34543409
}
34553410
return versions
@@ -3516,7 +3471,7 @@ public class MockContainer: PackageContainer {
35163471
self._versions.append(version)
35173472
self._versions = self._versions
35183473
.sorted(by: { lhs, rhs -> Bool in
3519-
guard case .version(let lv) = lhs, case .version(let rv) = rhs else {
3474+
guard case .version(let lv, _) = lhs, case .version(let rv, _) = rhs else {
35203475
return true
35213476
}
35223477
return lv < rv
@@ -3571,7 +3526,7 @@ public class MockContainer: PackageContainer {
35713526
let versions = dependencies.keys.compactMap(Version.init(_:))
35723527
self._versions = versions
35733528
.sorted()
3574-
.map(BoundVersion.version)
3529+
.map { .version($0) }
35753530
}
35763531
}
35773532

@@ -3742,7 +3697,7 @@ class DependencyGraphBuilder {
37423697
let container = self
37433698
.containers[packageReference.identity.description] ?? MockContainer(package: packageReference)
37443699

3745-
if case .version(let v) = version {
3700+
if case .version(let v, _) = version {
37463701
container.versionsToolsVersions[v] = toolsVersion ?? container.toolsVersion
37473702
}
37483703

0 commit comments

Comments
 (0)