@@ -150,6 +150,43 @@ 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
+ /// Find a manifest given its name.
180
+ func lookup( _ name: String ) -> Manifest ? {
181
+ return dependencies. first ( where: { $0. name == name } )
182
+ }
183
+
184
+ init ( root: Manifest , dependencies: [ Manifest ] ) {
185
+ self . root = root
186
+ self . dependencies = dependencies
187
+ }
188
+ }
189
+
153
190
/// The delegate interface.
154
191
public let delegate : WorkspaceDelegate
155
192
@@ -430,7 +467,7 @@ public class Workspace {
430
467
/// current dependencies from the working checkouts.
431
468
///
432
469
/// Throws: If the root manifest could not be loaded.
433
- func loadDependencyManifests( ) throws -> ( root : Manifest , dependencies : [ Manifest ] ) {
470
+ func loadDependencyManifests( ) throws -> DependencyManifests {
434
471
// Load the root manifest.
435
472
let rootManifest = try loadRootManifest ( )
436
473
@@ -456,7 +493,7 @@ public class Workspace {
456
493
}
457
494
}
458
495
459
- return ( root: rootManifest, dependencies: dependencies. map { $0. item } )
496
+ return DependencyManifests ( root: rootManifest, dependencies: dependencies. map { $0. item } )
460
497
}
461
498
462
499
/// Fetch and load the complete package at the given path.
@@ -474,42 +511,29 @@ public class Workspace {
474
511
/// - Throws: Rethrows errors from dependency resolution (if required) and package graph loading.
475
512
public func loadPackageGraph( ) throws -> PackageGraph {
476
513
// 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) )
514
+ let currentManifests = try loadDependencyManifests ( )
491
515
492
- // Check if there are any missing URLs.
493
- let missingURLs = requiredURLs . subtracting ( availableURLs )
516
+ // Look for any missing URLs.
517
+ let missingURLs = currentManifests . missingURLs ( )
494
518
if missingURLs. isEmpty {
495
519
// If not, we are done.
496
- return try PackageGraphLoader ( ) . load ( rootManifest: rootManifest , externalManifests: currentExternalManifests )
520
+ return try PackageGraphLoader ( ) . load ( rootManifest: currentManifests . root , externalManifests: currentManifests . dependencies )
497
521
}
498
522
499
523
// If so, we need to resolve and fetch them. Start by informing the
500
524
// delegate of what is happening.
501
525
delegate. fetchingMissingRepositories ( missingURLs)
502
526
503
527
// First, add the root package constraints.
504
- var constraints = computeRootPackageConstraints ( rootManifest )
528
+ var constraints = computeRootPackageConstraints ( currentManifests . root )
505
529
506
530
// Add constraints to pin to *exactly* all the checkouts we have.
507
531
//
508
532
// FIXME: We may need a better way to tell the resolution algorithm that
509
533
// certain repositories are pinned to the current checkout. We might be
510
534
// able to do that simply by overriding the view presented by the
511
535
// repository container provider.
512
- for externalManifest in currentExternalManifests {
536
+ for externalManifest in currentManifests . dependencies {
513
537
let specifier = RepositorySpecifier ( url: externalManifest. url)
514
538
let managedDependency = dependencyMap [ specifier] !
515
539
@@ -534,7 +558,7 @@ public class Workspace {
534
558
// currently provide constraints, but if we provided only the root and
535
559
// then the restrictions (to the current assignment) it would be
536
560
// possible.
537
- var externalManifests = currentExternalManifests
561
+ var externalManifests = currentManifests . dependencies
538
562
for (specifier, state) in packageStateChanges {
539
563
switch state {
540
564
case . added( let version) :
@@ -551,7 +575,7 @@ public class Workspace {
551
575
}
552
576
553
577
// We've loaded the complete set of manifests, load the graph.
554
- return try PackageGraphLoader ( ) . load ( rootManifest: rootManifest , externalManifests: externalManifests)
578
+ return try PackageGraphLoader ( ) . load ( rootManifest: currentManifests . root , externalManifests: externalManifests)
555
579
}
556
580
557
581
/// Removes the clone and checkout of the provided specifier.
0 commit comments