Skip to content

Commit 035b0c0

Browse files
committed
[Workspace] Diagnose duplicate root packages
<rdar://problem/47031631>
1 parent c924e56 commit 035b0c0

File tree

5 files changed

+61
-4
lines changed

5 files changed

+61
-4
lines changed

Sources/TestSupport/TestWorkspace.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ public final class TestWorkspace {
3838
toolsVersion: ToolsVersion = ToolsVersion.currentToolsVersion,
3939
skipUpdate: Bool = false
4040
) throws {
41-
precondition(Set(roots.map({$0.name})).count == roots.count, "Root packages should be unique")
4241
self.sandbox = sandbox
4342
self.fs = fs
4443
self.config = SwiftPMConfig(path: sandbox.appending(component: "swiftpm"), fs: fs)
@@ -155,7 +154,7 @@ public final class TestWorkspace {
155154
}
156155

157156
public func rootPaths(for packages: [String]) -> [AbsolutePath] {
158-
return packages.map({ rootsDir.appending(component: $0) })
157+
return packages.map({ rootsDir.appending(RelativePath($0)) })
159158
}
160159

161160
public struct PackageDependency {

Sources/Workspace/Diagnostics.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,4 +443,16 @@ public enum WorkspaceDiagnostics {
443443
}
444444
)
445445
}
446+
447+
public struct DuplicateRoots: DiagnosticData {
448+
public static let id = DiagnosticID(
449+
type: DuplicateRoots.self,
450+
name: "org.swift.diags.workspace.\(DuplicateRoots.self)",
451+
description: {
452+
$0 <<< "found multiple top-level packages named" <<< { "'" + $0.name + "'" }
453+
}
454+
)
455+
456+
let name: String
457+
}
446458
}

Sources/Workspace/Workspace.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,9 +665,18 @@ extension Workspace {
665665
packages: [AbsolutePath],
666666
diagnostics: DiagnosticsEngine
667667
) -> [Manifest] {
668-
return packages.compactMap({ package -> Manifest? in
669-
loadManifest(packagePath: package, url: package.asString, diagnostics: diagnostics)
668+
let rootManifests = packages.compactMap({ package -> Manifest? in
669+
loadManifest(packagePath: package, url: package.asString, diagnostics: diagnostics)
670670
})
671+
672+
// Check for duplicate root packages.
673+
let duplicateRoots = rootManifests.spm_findDuplicateElements(by: \.name)
674+
if !duplicateRoots.isEmpty {
675+
diagnostics.emit(data: WorkspaceDiagnostics.DuplicateRoots(name: duplicateRoots[0][0].name))
676+
return []
677+
}
678+
679+
return rootManifests
671680
}
672681
}
673682

Tests/WorkspaceTests/WorkspaceTests.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,42 @@ final class WorkspaceTests: XCTestCase {
225225
}
226226
}
227227

228+
func testDuplicateRootPackages() throws {
229+
let sandbox = AbsolutePath("/tmp/ws/")
230+
let fs = InMemoryFileSystem()
231+
232+
let workspace = try TestWorkspace(
233+
sandbox: sandbox,
234+
fs: fs,
235+
roots: [
236+
TestPackage(
237+
name: "Foo",
238+
targets: [
239+
TestTarget(name: "Foo", dependencies: []),
240+
],
241+
products: [],
242+
dependencies: []
243+
),
244+
TestPackage(
245+
name: "Foo",
246+
path: "Nested/Foo",
247+
targets: [
248+
TestTarget(name: "Foo", dependencies: []),
249+
],
250+
products: [],
251+
dependencies: []
252+
),
253+
],
254+
packages: []
255+
)
256+
257+
workspace.checkPackageGraph(roots: ["Foo", "Nested/Foo"]) { (graph, diagnostics) in
258+
DiagnosticsEngineTester(diagnostics) { result in
259+
result.check(diagnostic: .equal("found multiple top-level packages named 'Foo'"), behavior: .error)
260+
}
261+
}
262+
}
263+
228264
/// Test that the remote repository is not resolved when a root package with same name is already present.
229265
func testRootAsDependency1() throws {
230266
let sandbox = AbsolutePath("/tmp/ws/")

Tests/WorkspaceTests/XCTestManifests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ extension WorkspaceTests {
5252
("testDependencyManifestsOrder", testDependencyManifestsOrder),
5353
("testDependencyResolutionWithEdit", testDependencyResolutionWithEdit),
5454
("testDependencySwitchWithSameIdentity", testDependencySwitchWithSameIdentity),
55+
("testDuplicateRootPackages", testDuplicateRootPackages),
5556
("testEditDependency", testEditDependency),
5657
("testForceResolveToResolvedVersions", testForceResolveToResolvedVersions),
5758
("testGraphRootDependencies", testGraphRootDependencies),

0 commit comments

Comments
 (0)