@@ -132,33 +132,38 @@ public struct PubgrubDependencyResolver {
132
132
133
133
/// Execute the resolution algorithm to find a valid assignment of versions.
134
134
public func solve( constraints: [ Constraint ] ) -> Result < [ DependencyResolver . Binding ] , Error > {
135
- let root = DependencyResolutionNode . root ( package : . root(
136
- identity: . plain( " <synthesized-root> " ) ,
137
- path: . root
138
- ) )
135
+ // the graph resolution root
136
+ let root : DependencyResolutionNode
137
+ if constraints. count == 1 , let constraint = constraints. first, constraint. package . kind. isRoot {
138
+ // root level package, use it as our resolution root
139
+ root = . root( package : constraint. package )
140
+ } else {
141
+ // more complex setup requires a synthesized root
142
+ root = . root( package : . root(
143
+ identity: . plain( " <synthesized-root> " ) ,
144
+ path: . root
145
+ ) )
146
+ }
139
147
140
148
do {
141
149
// strips state
142
150
return . success( try self . solve ( root: root, constraints: constraints) . bindings)
143
151
} catch {
144
- var error = error
145
-
146
152
// If version solving failing, build the user-facing diagnostic.
147
153
if let pubGrubError = error as? PubgrubError , let rootCause = pubGrubError. rootCause, let incompatibilities = pubGrubError. incompatibilities {
148
- var builder = DiagnosticReportBuilder (
149
- root: root,
150
- incompatibilities: incompatibilities,
151
- provider: self . provider
152
- )
153
-
154
154
do {
155
+ var builder = DiagnosticReportBuilder (
156
+ root: root,
157
+ incompatibilities: incompatibilities,
158
+ provider: self . provider
159
+ )
155
160
let diagnostic = try builder. makeErrorReport ( for: rootCause)
156
- error = PubgrubError . unresolvable ( diagnostic)
161
+ return . failure ( PubgrubError . unresolvable ( diagnostic) )
157
162
} catch {
158
163
// failed to construct the report, will report the original error
164
+ return . failure( error)
159
165
}
160
166
}
161
-
162
167
return . failure( error)
163
168
}
164
169
}
@@ -262,13 +267,13 @@ public struct PubgrubDependencyResolver {
262
267
var overriddenPackages : [ PackageReference : ( version: BoundVersion , products: ProductFilter ) ] = [ : ]
263
268
264
269
// The list of version-based references reachable via local and branch-based references.
265
- // These are added as top-level incompatibilities since they always need to be statisfied .
270
+ // These are added as top-level incompatibilities since they always need to be satisfied .
266
271
// Some of these might be overridden as we discover local and branch-based references.
267
- var versionBasedDependencies : [ DependencyResolutionNode : [ VersionBasedConstraint ] ] = [ : ]
272
+ var versionBasedDependencies = OrderedDictionary < DependencyResolutionNode , [ VersionBasedConstraint ] > ( )
268
273
269
274
// Process unversioned constraints in first phase. We go through all of the unversioned packages
270
275
// and collect them and their dependencies. This gives us the complete list of unversioned
271
- // packages in the graph since unversioned packages can only be refered by other
276
+ // packages in the graph since unversioned packages can only be referred by other
272
277
// unversioned packages.
273
278
while let constraint = constraints. first ( where: { $0. requirement == . unversioned } ) {
274
279
constraints. remove ( constraint)
@@ -370,7 +375,7 @@ public struct PubgrubDependencyResolver {
370
375
case . versionSet( let req) :
371
376
for node in dependency. nodes ( ) {
372
377
let versionedBasedConstraint = VersionBasedConstraint ( node: node, req: req)
373
- versionBasedDependencies [ node , default: [ ] ] . append ( versionedBasedConstraint)
378
+ versionBasedDependencies [ . root ( package : constraint . package ) , default: [ ] ] . append ( versionedBasedConstraint)
374
379
}
375
380
case . revision:
376
381
constraints. append ( dependency)
@@ -386,13 +391,11 @@ public struct PubgrubDependencyResolver {
386
391
387
392
// At this point, we should be left with only version-based requirements in our constraints
388
393
// list. Add them to our version-based dependency list.
389
- for dependency in constraints {
390
- switch dependency . requirement {
394
+ for constraint in constraints {
395
+ switch constraint . requirement {
391
396
case . versionSet( let req) :
392
- for node in dependency . nodes ( ) {
397
+ for node in constraint . nodes ( ) {
393
398
let versionedBasedConstraint = VersionBasedConstraint ( node: node, req: req)
394
- // FIXME: It would be better to record where this constraint came from, instead of just
395
- // using root.
396
399
versionBasedDependencies [ root, default: [ ] ] . append ( versionedBasedConstraint)
397
400
}
398
401
case . revision, . unversioned:
@@ -401,11 +404,11 @@ public struct PubgrubDependencyResolver {
401
404
}
402
405
403
406
// Finally, compute the root incompatibilities (which will be all version-based).
407
+ // note versionBasedDependencies may point to the root package dependencies, or the dependencies of root's non-versioned dependencies
404
408
var rootIncompatibilities : [ Incompatibility ] = [ ]
405
409
for (node, constraints) in versionBasedDependencies {
406
410
for constraint in constraints {
407
411
if overriddenPackages. keys. contains ( constraint. node. package ) { continue }
408
-
409
412
let incompat = try Incompatibility (
410
413
Term ( root, . exact( " 1.0.0 " ) ) ,
411
414
Term ( not: constraint. node, constraint. requirement) ,
@@ -850,14 +853,20 @@ private struct DiagnosticReportBuilder {
850
853
851
854
private func description( for incompatibility: Incompatibility ) throws -> String {
852
855
switch incompatibility. cause {
853
- case . dependency( node : _ ) :
856
+ case . dependency( let causeNode ) :
854
857
assert ( incompatibility. terms. count == 2 )
855
858
let depender = incompatibility. terms. first!
856
859
let dependee = incompatibility. terms. last!
857
860
assert ( depender. isPositive)
858
861
assert ( !dependee. isPositive)
859
862
860
- let dependerDesc = try description ( for: depender, normalizeRange: true )
863
+ let dependerDesc : String
864
+ // when depender is the root node, the causeNode may be different as it may represent root's indirect dependencies (e.g. dependencies of root's unversioned dependencies)
865
+ if depender. node == self . rootNode, causeNode != self . rootNode {
866
+ dependerDesc = causeNode. nameForDiagnostics
867
+ } else {
868
+ dependerDesc = try description ( for: depender, normalizeRange: true )
869
+ }
861
870
let dependeeDesc = try description ( for: dependee)
862
871
return " \( dependerDesc) depends on \( dependeeDesc) "
863
872
case . noAvailableVersion:
@@ -871,6 +880,8 @@ private struct DiagnosticReportBuilder {
871
880
let term = incompatibility. terms. first!
872
881
assert ( term. isPositive)
873
882
return " \( term. node. nameForDiagnostics) is \( term. requirement) "
883
+ case . conflict where incompatibility. terms. count == 1 && incompatibility. terms. first? . node == self . rootNode:
884
+ return " dependencies could not be resolved "
874
885
case . conflict:
875
886
break
876
887
case . versionBasedDependencyContainsUnversionedDependency( let versionedDependency, let unversionedDependency) :
@@ -880,10 +891,6 @@ private struct DiagnosticReportBuilder {
880
891
return " \( try description ( for: term, normalizeRange: true ) ) contains incompatible tools version ( \( version) ) "
881
892
}
882
893
883
- if isFailure ( incompatibility) {
884
- return " dependencies could not be resolved "
885
- }
886
-
887
894
let terms = incompatibility. terms
888
895
if terms. count == 1 {
889
896
let term = terms. first!
@@ -957,11 +964,6 @@ private struct DiagnosticReportBuilder {
957
964
return !lineNumbers. keys. contains ( complex)
958
965
}
959
966
960
- // FIXME: This is duplicated and wrong.
961
- private func isFailure( _ incompatibility: Incompatibility ) -> Bool {
962
- return incompatibility. terms. count == 1 && incompatibility. terms. first? . node. package . identity == . plain( " <synthesized-root> " )
963
- }
964
-
965
967
private func description( for term: Term , normalizeRange: Bool = false ) throws -> String {
966
968
let name = term. node. nameForDiagnostics
967
969
@@ -1393,6 +1395,7 @@ private extension PackageRequirement {
1393
1395
1394
1396
private extension DependencyResolutionNode {
1395
1397
var nameForDiagnostics : String {
1396
- return " ' \( package . identity) ' "
1398
+ return " ' \( self . package . identity) ' "
1397
1399
}
1398
1400
}
1401
+
0 commit comments