Skip to content

Commit 408a97b

Browse files
committed
Merge remote-tracking branch 'origin/main' into release/5.10
2 parents a412f79 + dafbae5 commit 408a97b

File tree

8 files changed

+665
-28
lines changed

8 files changed

+665
-28
lines changed

Sources/PackageGraph/PubGrub/ContainerProvider.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ final class ContainerProvider {
6262
completion: @escaping (Result<PubGrubPackageContainer, Error>) -> Void
6363
) {
6464
// Return the cached container, if available.
65-
if let container = self.containersCache[package], package.equalsIncludingLocation(container.package) {
65+
if let container = self.containersCache[comparingLocation: package] {
6666
return completion(.success(container))
6767
}
6868

6969
if let prefetchSync = self.prefetches[package] {
7070
// If this container is already being prefetched, wait for that to complete
7171
prefetchSync.notify(queue: .sharedConcurrent) {
72-
if let container = self.containersCache[package], package.equalsIncludingLocation(container.package) {
72+
if let container = self.containersCache[comparingLocation: package] {
7373
// should be in the cache once prefetch completed
7474
return completion(.success(container))
7575
} else {
@@ -125,3 +125,12 @@ final class ContainerProvider {
125125
}
126126
}
127127
}
128+
129+
extension ThreadSafeKeyValueStore where Key == PackageReference, Value == PubGrubPackageContainer {
130+
subscript(comparingLocation package: PackageReference) -> PubGrubPackageContainer? {
131+
if let container = self[package], container.package.equalsIncludingLocation(package) {
132+
return container
133+
}
134+
return .none
135+
}
136+
}

Sources/PackageModel/PackageIdentity.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ public struct CanonicalPackageLocation: Equatable, CustomStringConvertible {
424424
}
425425

426426
/// Similar to `CanonicalPackageLocation` but differentiates based on the scheme.
427-
public struct CanonicalPackageURL: CustomStringConvertible {
427+
public struct CanonicalPackageURL: Equatable, CustomStringConvertible {
428428
public let description: String
429429
public let scheme: String?
430430

Sources/PackageModel/PackageReference.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,24 @@ extension PackageReference: Equatable {
161161

162162
// TODO: consider rolling into Equatable
163163
public func equalsIncludingLocation(_ other: PackageReference) -> Bool {
164-
return self.identity == other.identity && self.canonicalLocation == other.canonicalLocation
164+
if self.identity != other.identity {
165+
return false
166+
}
167+
if self.canonicalLocation != other.canonicalLocation {
168+
return false
169+
}
170+
switch (self.kind, other.kind) {
171+
case (.remoteSourceControl(let lurl), .remoteSourceControl(let rurl)):
172+
return lurl.canonicalURL == rurl.canonicalURL
173+
default:
174+
return true
175+
}
176+
}
177+
}
178+
179+
extension SourceControlURL {
180+
var canonicalURL: CanonicalPackageURL {
181+
CanonicalPackageURL(self.absoluteString)
165182
}
166183
}
167184

Sources/Workspace/ManagedDependency.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ extension Workspace {
196196

197197
// When loading manifests in Workspace, there are cases where we must also compare the location
198198
// as it may attempt to load manifests for dependencies that have the same identity but from a different location
199-
// (e.g. dependency is changed to a fork with the same identity)
199+
// (e.g. dependency is changed to a fork with the same identity)
200200
public subscript(comparingLocation package: PackageReference) -> ManagedDependency? {
201201
if let dependency = self.dependencies[package.identity], dependency.packageRef.equalsIncludingLocation(package) {
202202
return dependency

Sources/Workspace/Workspace+Dependencies.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -859,9 +859,8 @@ extension Workspace {
859859
// a required dependency that is already loaded (managed) should be represented in the pins store.
860860
// also comparing location as it may have changed at this point
861861
if requiredDependencies.contains(where: { $0.equalsIncludingLocation(dependency.packageRef) }) {
862-
let pin = pinsStore.pins[dependency.packageRef.identity]
863862
// if pin not found, or location is different (it may have changed at this point) pin it
864-
if !(pin?.packageRef.equalsIncludingLocation(dependency.packageRef) ?? false) {
863+
if pinsStore.pins[comparingLocation: dependency.packageRef] == .none {
865864
pinsStore.pin(dependency)
866865
}
867866
} else if let pin = pinsStore.pins[dependency.packageRef.identity] {

Sources/Workspace/Workspace+Manifests.swift

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ extension Workspace {
198198
}
199199
}
200200

201+
let topLevelDependencies = root.packages.flatMap { $1.manifest.dependencies.map(\.packageRef) }
202+
201203
var requiredIdentities: OrderedCollections.OrderedSet<PackageReference> = []
202204
_ = transitiveClosure(inputNodes) { node in
203205
node.manifest.dependenciesRequired(for: node.productFilter).compactMap { dependency in
@@ -209,17 +211,28 @@ extension Workspace {
209211
if existing.canonicalLocation == package.canonicalLocation {
210212
// same literal location is fine
211213
if existing.locationString != package.locationString {
212-
let preferred = [existing, package].sorted(by: {
213-
$0.locationString > $1.locationString
214-
}).first! // safe
215-
observabilityScope.emit(debug: """
216-
similar variants of package '\(package.identity)' \
217-
found at '\(package.locationString)' and '\(existing.locationString)'. \
218-
using preferred variant '\(preferred.locationString)'
219-
""")
220-
if preferred.locationString != existing.locationString {
221-
requiredIdentities.remove(existing)
222-
requiredIdentities.insert(preferred, at: index)
214+
// we prefer the top level dependencies
215+
if topLevelDependencies.contains(where: {
216+
$0.locationString == existing.locationString
217+
}) {
218+
observabilityScope.emit(debug: """
219+
similar variants of package '\(package.identity)' \
220+
found at '\(package.locationString)' and '\(existing.locationString)'. \
221+
using preferred root variant '\(existing.locationString)'
222+
""")
223+
} else {
224+
let preferred = [existing, package].sorted(by: {
225+
$0.locationString > $1.locationString
226+
}).first! // safe
227+
observabilityScope.emit(debug: """
228+
similar variants of package '\(package.identity)' \
229+
found at '\(package.locationString)' and '\(existing.locationString)'. \
230+
using preferred variant '\(preferred.locationString)'
231+
""")
232+
if preferred.locationString != existing.locationString {
233+
requiredIdentities.remove(existing)
234+
requiredIdentities.insert(preferred, at: index)
235+
}
223236
}
224237
}
225238
} else {

Sources/Workspace/Workspace+Pinning.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,16 @@ extension Workspace {
3030
for dependency in requiredDependencies {
3131
if let managedDependency = self.state.dependencies[comparingLocation: dependency] {
3232
dependenciesToPin.append(managedDependency)
33+
} else if let managedDependency = self.state.dependencies[dependency.identity] {
34+
observabilityScope
35+
.emit(
36+
info: "required dependency '\(dependency.identity)' from '\(dependency.locationString)' was not found in managed dependencies, using alternative location '\(managedDependency.packageRef.locationString)' instead"
37+
)
38+
dependenciesToPin.append(ManagedDependency(packageRef: dependency, state: managedDependency.state, subpath: managedDependency.subpath))
3339
} else {
3440
observabilityScope
3541
.emit(
36-
warning: "required dependency \(dependency.identity) (\(dependency.locationString)) was not found in managed dependencies and will not be recorded in resolved file"
42+
warning: "required dependency '\(dependency.identity)' from '\(dependency.locationString)' was not found in managed dependencies and will not be recorded in resolved file"
3743
)
3844
}
3945
}
@@ -49,8 +55,8 @@ extension Workspace {
4955
needsUpdate = true
5056
} else {
5157
for dependency in dependenciesToPin {
52-
if let pin = storedPinStore.pins.first(where: { $0.value.packageRef.equalsIncludingLocation(dependency.packageRef) }) {
53-
if pin.value.state != PinsStore.Pin(dependency)?.state {
58+
if let pin = storedPinStore.pins[comparingLocation: dependency.packageRef] {
59+
if pin.state != PinsStore.Pin(dependency)?.state {
5460
needsUpdate = true
5561
break
5662
}
@@ -180,3 +186,12 @@ extension PinsStore.PinState {
180186
}
181187
}
182188
}
189+
190+
extension PinsStore.Pins {
191+
subscript(comparingLocation package: PackageReference) -> PinsStore.Pin? {
192+
if let pin = self[package.identity], pin.packageRef.equalsIncludingLocation(package) {
193+
return pin
194+
}
195+
return .none
196+
}
197+
}

0 commit comments

Comments
 (0)