Skip to content

Commit 4e791bb

Browse files
committed
Add a fast way to look up the package in which a particular target or product is defined.
1 parent 5e59c9f commit 4e791bb

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

Sources/PackageGraph/PackageGraph.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
4+
Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See http://swift.org/LICENSE.txt for license information
@@ -79,6 +79,18 @@ public struct PackageGraph {
7979
return rootPackages.contains(package)
8080
}
8181

82+
/// Returns the package that contains the target, or nil if the target isn't in the graph.
83+
public func package(for target: ResolvedTarget) -> ResolvedPackage? {
84+
return self.targetsToPackages[target]
85+
}
86+
private let targetsToPackages: [ResolvedTarget: ResolvedPackage]
87+
88+
/// Returns the package that contains the product, or nil if the product isn't in the graph.
89+
public func package(for product: ResolvedProduct) -> ResolvedPackage? {
90+
return self.productsToPackages[product]
91+
}
92+
private let productsToPackages: [ResolvedProduct: ResolvedPackage]
93+
8294
/// All root and root dependency packages provided as input to the graph.
8395
public let inputPackages: [ResolvedPackage]
8496

@@ -92,6 +104,13 @@ public struct PackageGraph {
92104
self.requiredDependencies = requiredDependencies
93105
self.inputPackages = rootPackages + rootDependencies
94106
self.packages = try topologicalSort(inputPackages, successors: { $0.dependencies })
107+
108+
// Create a mapping from targets to the packages that define them. Here
109+
// we include all targets, including tests in non-root packages, since
110+
// this is intended for lookup and not traversal.
111+
self.targetsToPackages = packages.reduce(into: [:], { partial, package in
112+
package.targets.forEach{ partial[$0] = package }
113+
})
95114

96115
allTargets = Set(packages.flatMap({ package -> [ResolvedTarget] in
97116
if rootPackages.contains(package) {
@@ -103,6 +122,13 @@ public struct PackageGraph {
103122
}
104123
}))
105124

125+
// Create a mapping from products to the packages that define them. Here
126+
// we include all products, including tests in non-root packages, since
127+
// this is intended for lookup and not traversal.
128+
self.productsToPackages = packages.reduce(into: [:], { partial, package in
129+
package.products.forEach{ partial[$0] = package }
130+
})
131+
106132
allProducts = Set(packages.flatMap({ package -> [ResolvedProduct] in
107133
if rootPackages.contains(package) {
108134
return package.products

Tests/PackageGraphTests/PackageGraphTests.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
4+
Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See http://swift.org/LICENSE.txt for license information
@@ -79,6 +79,15 @@ class PackageGraphTests: XCTestCase {
7979
result.checkTarget("Bar") { result in result.check(dependencies: "Foo") }
8080
result.checkTarget("Baz") { result in result.check(dependencies: "Bar") }
8181
}
82+
83+
let fooPackage = try XCTUnwrap(g.packages.first{ $0.name == "Foo" })
84+
let fooTarget = try XCTUnwrap(g.allTargets.first{ $0.name == "Foo" })
85+
let fooDepTarget = try XCTUnwrap(g.allTargets.first{ $0.name == "FooDep" })
86+
XCTAssert(g.package(for: fooTarget) == fooPackage)
87+
XCTAssert(g.package(for: fooDepTarget) == fooPackage)
88+
let barPackage = try XCTUnwrap(g.packages.first{ $0.name == "Bar" })
89+
let barTarget = try XCTUnwrap(g.allTargets.first{ $0.name == "Bar" })
90+
XCTAssert(g.package(for: barTarget) == barPackage)
8291
}
8392

8493
func testProductDependencies() throws {

0 commit comments

Comments
 (0)