Skip to content

Commit efeba46

Browse files
committed
[PackageGraph] Fix crash when there is a cycle in root package
<rdar://problem/39954169> [SR-7597]: Running 'swift build' crashes with segmentation fault when dependency name equals project's name
1 parent 24e01f1 commit efeba46

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

Sources/PackageGraph/PackageGraphLoader.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ public struct PackageGraphLoader {
107107
// Detect cycles in manifest dependencies.
108108
if let cycle = findCycle(inputManifests, successors: successors) {
109109
diagnostics.emit(PackageGraphError.cycleDetected(cycle))
110-
allManifests = inputManifests
110+
// Break the cycle so we can build a partial package graph.
111+
allManifests = inputManifests.filter({ $0 != cycle.cycle[0] })
111112
} else {
112113
// Sort all manifests toplogically.
113114
allManifests = try! topologicalSort(inputManifests, successors: successors)

Tests/PackageGraphTests/PackageGraphTests.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,32 @@ class PackageGraphTests: XCTestCase {
169169
XCTAssertEqual(diagnostics.diagnostics[0].localizedDescription, "cyclic dependency declaration found: Foo -> Bar -> Baz -> Bar")
170170
}
171171

172+
func testCycle2() throws {
173+
let fs = InMemoryFileSystem(emptyFiles:
174+
"/Foo/Sources/Foo/source.swift",
175+
"/Bar/Sources/Bar/source.swift",
176+
"/Baz/Sources/Baz/source.swift"
177+
)
178+
179+
let diagnostics = DiagnosticsEngine()
180+
_ = loadPackageGraph(root: "/Foo", fs: fs, diagnostics: diagnostics,
181+
manifests: [
182+
Manifest.createV4Manifest(
183+
name: "Foo",
184+
path: "/Foo",
185+
url: "/Foo",
186+
dependencies: [
187+
PackageDependencyDescription(url: "/Foo", requirement: .upToNextMajor(from: "1.0.0"))
188+
],
189+
targets: [
190+
TargetDescription(name: "Foo"),
191+
]),
192+
]
193+
)
194+
195+
XCTAssertEqual(diagnostics.diagnostics[0].localizedDescription, "cyclic dependency declaration found: Foo -> Foo")
196+
}
197+
172198
// Make sure there is no error when we reference Test targets in a package and then
173199
// use it as a dependency to another package. SR-2353
174200
func testTestTargetDeclInExternalPackage() throws {

Tests/PackageGraphTests/XCTestManifests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ extension DependencyResolverTests {
2323
extension PackageGraphTests {
2424
static let __allTests = [
2525
("testBasic", testBasic),
26+
("testCycle2", testCycle2),
2627
("testCycle", testCycle),
2728
("testDuplicateInterPackageTargetNames", testDuplicateInterPackageTargetNames),
2829
("testDuplicateModules", testDuplicateModules),

0 commit comments

Comments
 (0)