Skip to content

Commit b7cd543

Browse files
committed
Support additional dependencies in forced resolution mode
rdar://115630439
1 parent 21c6684 commit b7cd543

File tree

2 files changed

+59
-15
lines changed

2 files changed

+59
-15
lines changed

Sources/Workspace/Workspace+Manifests.swift

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,24 @@ extension Workspace {
408408
automaticallyAddManagedDependencies: Bool = false,
409409
observabilityScope: ObservabilityScope
410410
) throws -> DependencyManifests {
411+
let prepopulateManagedDependencies: ([PackageReference]) throws -> Void = { refs in
412+
// pre-populate managed dependencies if we are asked to do so (this happens when resolving to a resolved
413+
// file)
414+
if automaticallyAddManagedDependencies {
415+
try refs.forEach { ref in
416+
// Since we are creating managed dependencies based on the resolved file in this mode, but local
417+
// packages aren't part of that file, they will be missing from it. So we're eagerly adding them
418+
// here, but explicitly don't add any that are overridden by a root with the same identity since
419+
// that would lead to loading the given package twice, once as a root and once as a dependency
420+
// which violates various assumptions.
421+
if case .fileSystem = ref.kind, !root.manifests.keys.contains(ref.identity) {
422+
try self.state.dependencies.add(.fileSystem(packageRef: ref))
423+
}
424+
}
425+
observabilityScope.trap { try self.state.save() }
426+
}
427+
}
428+
411429
// Utility Just because a raw tuple cannot be hashable.
412430
struct Key: Hashable {
413431
let identity: PackageIdentity
@@ -442,6 +460,7 @@ extension Workspace {
442460

443461
// Load root dependencies manifests (in parallel)
444462
let rootDependencies = root.dependencies.map(\.packageRef)
463+
try prepopulateManagedDependencies(rootDependencies)
445464
let rootDependenciesManifests = try temp_await { self.loadManagedManifests(
446465
for: rootDependencies,
447466
observabilityScope: observabilityScope,
@@ -473,21 +492,7 @@ extension Workspace {
473492
let dependenciesRequired = pair.item.dependenciesRequired(for: pair.key.productFilter)
474493
let dependenciesToLoad = dependenciesRequired.map(\.packageRef)
475494
.filter { !loadedManifests.keys.contains($0.identity) }
476-
// pre-populate managed dependencies if we are asked to do so (this happens when resolving to a resolved
477-
// file)
478-
if automaticallyAddManagedDependencies {
479-
try dependenciesToLoad.forEach { ref in
480-
// Since we are creating managed dependencies based on the resolved file in this mode, but local
481-
// packages aren't part of that file, they will be missing from it. So we're eagerly adding them
482-
// here, but explicitly don't add any that are overridden by a root with the same identity since
483-
// that would lead to loading the given package twice, once as a root and once as a dependency
484-
// which violates various assumptions.
485-
if case .fileSystem = ref.kind, !root.manifests.keys.contains(ref.identity) {
486-
try self.state.dependencies.add(.fileSystem(packageRef: ref))
487-
}
488-
}
489-
observabilityScope.trap { try self.state.save() }
490-
}
495+
try prepopulateManagedDependencies(dependenciesToLoad)
491496
let dependenciesManifests = try temp_await { self.loadManagedManifests(
492497
for: dependenciesToLoad,
493498
observabilityScope: observabilityScope,

Tests/WorkspaceTests/WorkspaceTests.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5225,6 +5225,45 @@ final class WorkspaceTests: XCTestCase {
52255225
}
52265226
}
52275227

5228+
func testForceResolveToResolvedVersionsLocalPackageInAdditionalDependencies() throws {
5229+
let sandbox = AbsolutePath("/tmp/ws/")
5230+
let fs = InMemoryFileSystem()
5231+
5232+
let workspace = try MockWorkspace(
5233+
sandbox: sandbox,
5234+
fileSystem: fs,
5235+
roots: [
5236+
MockPackage(
5237+
name: "Root",
5238+
targets: [
5239+
MockTarget(name: "Root"),
5240+
],
5241+
products: [],
5242+
dependencies: []
5243+
),
5244+
],
5245+
packages: [
5246+
MockPackage(
5247+
name: "Foo",
5248+
targets: [
5249+
MockTarget(name: "Foo"),
5250+
],
5251+
products: [
5252+
MockProduct(name: "Foo", targets: ["Foo"]),
5253+
],
5254+
versions: [nil]
5255+
),
5256+
]
5257+
)
5258+
5259+
try workspace.checkPackageGraph(roots: ["Root"], dependencies: [.fileSystem(path: workspace.packagesDir.appending(component: "Foo"))], forceResolvedVersions: true) { _, diagnostics in
5260+
XCTAssertNoDiagnostics(diagnostics)
5261+
}
5262+
workspace.checkManagedDependencies { result in
5263+
result.check(dependency: "foo", at: .local)
5264+
}
5265+
}
5266+
52285267
// This verifies that the simplest possible loading APIs are available for package clients.
52295268
func testSimpleAPI() throws {
52305269
try testWithTemporaryDirectory { path in

0 commit comments

Comments
 (0)