Skip to content

Commit b11aded

Browse files
committed
[Workspace] Refactor dependencyManifests into its own struct
1 parent 0f1ff16 commit b11aded

File tree

2 files changed

+44
-23
lines changed

2 files changed

+44
-23
lines changed

Sources/Commands/Workspace.swift

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,38 @@ public class Workspace {
150150
}
151151
}
152152

153+
/// A struct representing all the current manifests (root + external) in a package graph.
154+
struct DependencyManifests {
155+
/// The root manifest.
156+
let root: Manifest
157+
158+
/// The dependency manifests in the transitive closure of root manifest.
159+
let dependencies: [Manifest]
160+
161+
/// Computes the URLs which are declared in the manifests but aren't present in dependencies.
162+
func missingURLs() -> Set<String> {
163+
let manifestsMap = Dictionary<String, Manifest>(
164+
items: [(root.url, root)] + dependencies.map{ ($0.url, $0) })
165+
166+
var requiredURLs = transitiveClosure([root.url]) { url in
167+
guard let manifest = manifestsMap[url] else { return [] }
168+
return manifest.package.dependencies.map{ $0.url }
169+
}
170+
requiredURLs.insert(root.url)
171+
172+
let availableURLs = Set<String>(manifestsMap.keys)
173+
// We should never have loaded a manifest we don't need.
174+
assert(availableURLs.isSubset(of: requiredURLs))
175+
// These are the missing URLs.
176+
return requiredURLs.subtracting(availableURLs)
177+
}
178+
179+
init(root: Manifest, dependencies: [Manifest]) {
180+
self.root = root
181+
self.dependencies = dependencies
182+
}
183+
}
184+
153185
/// The delegate interface.
154186
public let delegate: WorkspaceDelegate
155187

@@ -430,7 +462,7 @@ public class Workspace {
430462
/// current dependencies from the working checkouts.
431463
///
432464
/// Throws: If the root manifest could not be loaded.
433-
func loadDependencyManifests() throws -> (root: Manifest, dependencies: [Manifest]) {
465+
func loadDependencyManifests() throws -> DependencyManifests {
434466
// Load the root manifest.
435467
let rootManifest = try loadRootManifest()
436468

@@ -456,7 +488,7 @@ public class Workspace {
456488
}
457489
}
458490

459-
return (root: rootManifest, dependencies: dependencies.map{ $0.item })
491+
return DependencyManifests(root: rootManifest, dependencies: dependencies.map{ $0.item })
460492
}
461493

462494
/// Fetch and load the complete package at the given path.
@@ -474,42 +506,29 @@ public class Workspace {
474506
/// - Throws: Rethrows errors from dependency resolution (if required) and package graph loading.
475507
public func loadPackageGraph() throws -> PackageGraph {
476508
// First, load the active manifest sets.
477-
let (rootManifest, currentExternalManifests) = try loadDependencyManifests()
478-
479-
// Check for missing checkouts.
480-
let manifestsMap = Dictionary<String, Manifest>(
481-
items: [(rootManifest.url, rootManifest)] + currentExternalManifests.map{ ($0.url, $0) })
482-
let availableURLs = Set<String>(manifestsMap.keys)
483-
var requiredURLs = transitiveClosure([rootManifest.url]) { url in
484-
guard let manifest = manifestsMap[url] else { return [] }
485-
return manifest.package.dependencies.map{ $0.url }
486-
}
487-
requiredURLs.insert(rootManifest.url)
488-
489-
// We should never have loaded a manifest we don't need.
490-
assert(availableURLs.isSubset(of: requiredURLs))
509+
let currentManifests = try loadDependencyManifests()
491510

492-
// Check if there are any missing URLs.
493-
let missingURLs = requiredURLs.subtracting(availableURLs)
511+
// Look for any missing URLs.
512+
let missingURLs = currentManifests.missingURLs()
494513
if missingURLs.isEmpty {
495514
// If not, we are done.
496-
return try PackageGraphLoader().load(rootManifest: rootManifest, externalManifests: currentExternalManifests)
515+
return try PackageGraphLoader().load(rootManifest: currentManifests.root, externalManifests: currentManifests.dependencies)
497516
}
498517

499518
// If so, we need to resolve and fetch them. Start by informing the
500519
// delegate of what is happening.
501520
delegate.fetchingMissingRepositories(missingURLs)
502521

503522
// First, add the root package constraints.
504-
var constraints = computeRootPackageConstraints(rootManifest)
523+
var constraints = computeRootPackageConstraints(currentManifests.root)
505524

506525
// Add constraints to pin to *exactly* all the checkouts we have.
507526
//
508527
// FIXME: We may need a better way to tell the resolution algorithm that
509528
// certain repositories are pinned to the current checkout. We might be
510529
// able to do that simply by overriding the view presented by the
511530
// repository container provider.
512-
for externalManifest in currentExternalManifests {
531+
for externalManifest in currentManifests.dependencies {
513532
let specifier = RepositorySpecifier(url: externalManifest.url)
514533
let managedDependency = dependencyMap[specifier]!
515534

@@ -534,7 +553,7 @@ public class Workspace {
534553
// currently provide constraints, but if we provided only the root and
535554
// then the restrictions (to the current assignment) it would be
536555
// possible.
537-
var externalManifests = currentExternalManifests
556+
var externalManifests = currentManifests.dependencies
538557
for (specifier, state) in packageStateChanges {
539558
switch state {
540559
case .added(let version):
@@ -551,7 +570,7 @@ public class Workspace {
551570
}
552571

553572
// We've loaded the complete set of manifests, load the graph.
554-
return try PackageGraphLoader().load(rootManifest: rootManifest, externalManifests: externalManifests)
573+
return try PackageGraphLoader().load(rootManifest: currentManifests.root, externalManifests: externalManifests)
555574
}
556575

557576
/// Removes the clone and checkout of the provided specifier.

Tests/CommandsTests/WorkspaceTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ final class WorkspaceTests: XCTestCase {
157157
// Load the "current" manifests.
158158
let manifests = try workspace.loadDependencyManifests()
159159
XCTAssertEqual(manifests.root.package, graph.rootManifest.package)
160+
// B should be missing.
161+
XCTAssertEqual(manifests.missingURLs(), ["//B"])
160162
var dependencyManifests: [String: Manifest] = [:]
161163
for manifest in manifests.dependencies {
162164
dependencyManifests[manifest.package.name] = manifest

0 commit comments

Comments
 (0)