@@ -150,6 +150,38 @@ public class Workspace {
150
150
}
151
151
}
152
152
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
+
153
185
/// The delegate interface.
154
186
public let delegate : WorkspaceDelegate
155
187
@@ -430,7 +462,7 @@ public class Workspace {
430
462
/// current dependencies from the working checkouts.
431
463
///
432
464
/// Throws: If the root manifest could not be loaded.
433
- func loadDependencyManifests( ) throws -> ( root : Manifest , dependencies : [ Manifest ] ) {
465
+ func loadDependencyManifests( ) throws -> DependencyManifests {
434
466
// Load the root manifest.
435
467
let rootManifest = try loadRootManifest ( )
436
468
@@ -456,7 +488,7 @@ public class Workspace {
456
488
}
457
489
}
458
490
459
- return ( root: rootManifest, dependencies: dependencies. map { $0. item } )
491
+ return DependencyManifests ( root: rootManifest, dependencies: dependencies. map { $0. item } )
460
492
}
461
493
462
494
/// Fetch and load the complete package at the given path.
@@ -474,42 +506,29 @@ public class Workspace {
474
506
/// - Throws: Rethrows errors from dependency resolution (if required) and package graph loading.
475
507
public func loadPackageGraph( ) throws -> PackageGraph {
476
508
// 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 ( )
491
510
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 ( )
494
513
if missingURLs. isEmpty {
495
514
// 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 )
497
516
}
498
517
499
518
// If so, we need to resolve and fetch them. Start by informing the
500
519
// delegate of what is happening.
501
520
delegate. fetchingMissingRepositories ( missingURLs)
502
521
503
522
// First, add the root package constraints.
504
- var constraints = computeRootPackageConstraints ( rootManifest )
523
+ var constraints = computeRootPackageConstraints ( currentManifests . root )
505
524
506
525
// Add constraints to pin to *exactly* all the checkouts we have.
507
526
//
508
527
// FIXME: We may need a better way to tell the resolution algorithm that
509
528
// certain repositories are pinned to the current checkout. We might be
510
529
// able to do that simply by overriding the view presented by the
511
530
// repository container provider.
512
- for externalManifest in currentExternalManifests {
531
+ for externalManifest in currentManifests . dependencies {
513
532
let specifier = RepositorySpecifier ( url: externalManifest. url)
514
533
let managedDependency = dependencyMap [ specifier] !
515
534
@@ -534,7 +553,7 @@ public class Workspace {
534
553
// currently provide constraints, but if we provided only the root and
535
554
// then the restrictions (to the current assignment) it would be
536
555
// possible.
537
- var externalManifests = currentExternalManifests
556
+ var externalManifests = currentManifests . dependencies
538
557
for (specifier, state) in packageStateChanges {
539
558
switch state {
540
559
case . added( let version) :
@@ -551,7 +570,7 @@ public class Workspace {
551
570
}
552
571
553
572
// 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)
555
574
}
556
575
557
576
/// Removes the clone and checkout of the provided specifier.
0 commit comments