|
|
@@ -0,0 +1,116 @@ |
|
|
|
Error: Dependency Resolution Failure |
|
|
|
#################################### |
|
|
|
|
|
|
|
.. note:: |
|
|
|
``dds`` implements the `Pubgrub`_ dependency resolution algorithm. |
|
|
|
|
|
|
|
.. _Pubgrub: https://github.com/dart-lang/pub/blob/master/doc/solver.md |
|
|
|
|
|
|
|
If you receive this error, it indicates that the requested dependencies create |
|
|
|
one or more conflicts. ``dds`` will do its best to emit a useful explanation of |
|
|
|
how this conflict was formed that can hopefully be used to find the original |
|
|
|
basis for the conflict. |
|
|
|
|
|
|
|
Every package can have some number of dependencies, which are other packages |
|
|
|
that are required for the dependent package to be used. Beyond just a package |
|
|
|
name, a dependency will also have a *compatible version range*. |
|
|
|
|
|
|
|
|
|
|
|
Resolution Example |
|
|
|
****************** |
|
|
|
|
|
|
|
For example, let us suppose a package ``Widgets@4.2.8`` may have a *dependency* |
|
|
|
on ``Gadgets^2.4.4`` and ``Gizmos^3.2.0``. |
|
|
|
|
|
|
|
.. note:: |
|
|
|
The ``@4.2.8`` suffix on ``Widgets`` means that ``4.2.8`` is the *exact* |
|
|
|
version of ``Widgets``, while the ``^2.4.4`` is a *version range* on |
|
|
|
``Gadgets`` which starts at ``2.4.4`` and includes every version until (but |
|
|
|
not including) ``3.0.0``. ``^3.2.0`` is a version range on ``Gizmos`` that |
|
|
|
starts at ``3.2.0`` and includes every version until (but not including) |
|
|
|
``4.0.0``. |
|
|
|
|
|
|
|
Now let us suppose the following versions of ``Gadgets`` and ``Gizmos`` are |
|
|
|
available: |
|
|
|
|
|
|
|
``Gadgets``: |
|
|
|
- ``2.4.0`` |
|
|
|
- ``2.4.3`` |
|
|
|
- ``2.4.4`` |
|
|
|
- ``2.5.0`` |
|
|
|
- ``2.6.0`` |
|
|
|
- ``3.1.0`` |
|
|
|
|
|
|
|
``Gizmos``: |
|
|
|
- ``2.1.0`` |
|
|
|
- ``3.2.0`` |
|
|
|
- ``3.5.6`` |
|
|
|
- ``4.5.0`` |
|
|
|
|
|
|
|
We can immediately rule out some candidates of ``Gadgets``: for the dependency |
|
|
|
``Gadgets^2.4.4``, ``2.4.0`` and ``2.4.3`` are *too old*, while ``3.1.0`` is |
|
|
|
*too new*. This leaves us with ``2.4.4``, ``2.5.0``, and ``2.6.0``. |
|
|
|
|
|
|
|
We'll first look at ``Gadgets@2.4.4``. We need to recursively solve its |
|
|
|
dependencies. Suppose that it declares a dependency of ``Gizmos^2.1.0``. We |
|
|
|
have already established that we *require* ``Gizmos^3.2.0``, and because |
|
|
|
``^2.1.0`` and ``^3.2.0`` are *disjoint* (they share no common versions) we can |
|
|
|
say that ``Gizmos^3.2.0`` is *incompatible* with our existing partial solution, |
|
|
|
and that its dependent, ``Gadgets@2.4.4`` is *transitively incompatible* with |
|
|
|
the partial solution. Thus, ``Gadgets@2.4.4`` is out of the running. |
|
|
|
|
|
|
|
This doesn't mean we're immediately broken, though. We still have two more |
|
|
|
versions of ``Gadgets`` to inspect. We'll start with the next version in line: |
|
|
|
``Gadgets@2.5.0``. Suppose that it has a dependency on ``Gizmos^3.4.0``. We |
|
|
|
have already established a requirement of ``Gizmos^3.2.0``, so we must find |
|
|
|
a candidate for ``Gizmos`` that satisfies both dependencies. Fortunately, we |
|
|
|
have exactly one: ``Gizmos@3.5.6`` satisfies *both* ``Gizmos^3.2.0`` *and* |
|
|
|
``Gizmos^3.4.0``. |
|
|
|
|
|
|
|
Suppose that ``Gizmos@3.5.6`` has no further dependencies. At this point, we |
|
|
|
have inspected all dependencies and have resolutions for every named package: |
|
|
|
Thus, we have a valid solution of ``Widgets@4.2.8``, ``Gadgets@2.5.0``, and |
|
|
|
``Gizmos@2.6.0``! We didn't even need to inspect ``Gadgets@2.6.0``. |
|
|
|
|
|
|
|
In this case, ``dds`` will not produce an error, and the given package solution |
|
|
|
will be used. |
|
|
|
|
|
|
|
|
|
|
|
Breaking the Solution |
|
|
|
===================== |
|
|
|
|
|
|
|
Now suppose the same case, except that ``Gadgets@2.5.0`` is not available. |
|
|
|
We'll instead move to check ``Gadgets@2.6.0``. |
|
|
|
|
|
|
|
Suppose that ``Gadgets@2.6.0`` has a dependency on ``Gizmos^4.0.6``. While we |
|
|
|
*do* have a candidate thereof, we've already declared a requriement on |
|
|
|
``Gizmos^3.2.0``. Because ``^4.0.6`` and ``^3.2.0`` are disjoint, then there is |
|
|
|
no possible satisfier for both ranges. This means that ``Gizmos^4.0.6`` is |
|
|
|
incompatible in the partial solution, and that ``Gadgets@2.6.0`` is |
|
|
|
transitively incompatible as well. It is no longer a candidate. |
|
|
|
|
|
|
|
We've exhausted the available candidates for ``Gadgets^2.4.4``, so we must now |
|
|
|
conclude that ``Gadgets^2.4.4`` is *also incompatible*. Transitively, this also |
|
|
|
means that ``Widgets@4.2.8`` is incompatible as well. |
|
|
|
|
|
|
|
We've reached a problem, though: ``Widgets@4.2.8`` is our original requirement! |
|
|
|
There is nothing left to invalidate in our partial solution, so we rule that |
|
|
|
our original requirements are *unsatisfiable*. |
|
|
|
|
|
|
|
At this point, ``dds`` will raise the error that *dependency resolution has |
|
|
|
failed*. It will attempt its best to reconstruct the logic that we have used |
|
|
|
above in order to explain what has gone wrong. |
|
|
|
|
|
|
|
|
|
|
|
Fixing the Problem |
|
|
|
****************** |
|
|
|
|
|
|
|
There is no strict process for fixing these conflicts. |
|
|
|
|
|
|
|
Fixing a dependency conflict is a manual process. It will require reviewing the |
|
|
|
available versions and underlying reasons that the dependency maintainers have |
|
|
|
chosen their compatibility ranges statements. |
|
|
|
|
|
|
|
Your own dependency statements will often need to be changed, and sometimes |
|
|
|
even code will have to be revised to reach compatibility with newer or older |
|
|
|
dependency versions. |