move-language / move

Apache License 2.0
2.25k stars 679 forks source link

[move-package] Support dependency overrides #964

Open awelc opened 1 year ago

awelc commented 1 year ago

Motivation

This PR addresses problem with package versioning introducing potential for diamond problems (two sibling dependencies with a shared dependency whose version does not match).

Have you read the Contributing Guidelines on pull requests?

Yes

Test Plan

Respective tests have been added

awelc commented 1 year ago

Overrides are specified explicitly, rather than what the previous solution assumed, that is implicitly. In other words to override some dependency C that A and B depend on (and conflict on), we specify a version of C to be used in the root package's manifest file:

[dependencies]
A = { local = "./deps_only/A" }
B = { local = "./deps_only/B" }
C = { local = "./deps_only/C", version = "1.0.0", override = true }

rather than, what was assumed before, specifying which dependency path is supposed to designate the "winning" version of the package:

[dependencies]
A = { local = "./deps_only/A", override = true }
B = { local = "./deps_only/B" }

The updated algorithm is as follows (repeated here from the doc-comment for the override_pkg function.

The algorithm relies on the fact that this check is performed when a new package is added to the graph already containing package with the same name - this allows us to resolve the conflicts pair-wise even if ultimately a package with a given name is a dependency of more than two other packages.

First we check if package already existing in the graph has been inserted there as a result of an override. If it was, then either:

Because the overridden dependencies are processed first for each package, it is guaranteed that when searching for overrides for a child (new package), a correct override will be found if it exists because by construction it must be already present in the graph.

If package already existing in the graph has not been inserted as a result of an override then either:

Correctly finding dominators only works because when trying to add a conflicting package through a new dependency edge, we add this edge early in an non-finalized state (before the package is fully processed), finalizing the edges only after package processing is done.