Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

opamCudf: provide machine-readable information on conflicts caused by cycles #4039

Merged

Conversation

gasche
Copy link
Member

@gasche gasche commented Dec 9, 2019

For conflicts caused by cyclic actions, the opamCudf API would
previously only allow to observe the cycle with actions described as
strings for human pretty-printing.

We would like to write a script, using the opam API, that can react to
solution errors caused by cycles by patching the query and calling the
solver again. For this we need a machine-readable representation of
conflict cycles. ("We" here is myself and @Armael.)

The present commit makes the minimal change to the opamCudf API to
make this possible:

  • The internal representation of cycles is changed to take CUDF
    packages (the most general information) instead of strings.
  • The OpamCudf.cycle_conflicts function has its type changed accordingly
    (this changes the module interface and may break library consumers).
  • A new function OpamCudf.conflict_cycles is exposed to recover
    a cycle representation carrying "opam package" actions.

Remark: conflict_cycles is in the style of the current API on the
abstract conflict type, which is not very good: a conflict is
a variant/sum type in hiding (either an incompatibility in the query
or a cycle in the solution), and functions do something in one case
and silently return nothing in the other.

It would be nicer to expose a variant-sum type view of the conflict
type to users, but this should be discussed with OPAM maintainers, and
is not a requirement for our work.

@rjbou
Copy link
Collaborator

rjbou commented Dec 9, 2019

cc @AltGr

@rjbou rjbou requested a review from AltGr December 9, 2019 18:02
Copy link
Member

@AltGr AltGr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok for me !
Now I am curious what exactly your are doing here... how about a chat some day?
Loosely related, and you probably know about it, but from the command-line there is a generic command (as in, not related to a specific query) to check for all possible dependency cycles:

% opam admin check --ignore-test-doc  --cycles  
[ERROR] Dependency cycles detected:
  * fileutils = 0.6.0 → oasis = 0.2.0
  * oasis (>= 0.3.0 & < 0.4.2) → ocamlmod < 0.0.7 → fileutils = 0.6.0
  * fileutils = 0.6.0 → oasis (>= 0.4.5 & < 0.4.7) → gettext
  * ocamlmod < 0.0.7 → fileutils = 0.6.0 → oasis (>= 0.4.5 & < 0.4.7)
  * fileutils = 0.6.0 → oasis = 0.4.7
  * ocamlmod < 0.0.7 → fileutils = 0.6.0 → oasis = 0.4.7
  * ocamlmod < 0.0.7 → fileutils = 0.6.0 → oasis (>= 0.4.2 & < 0.4.5 | >= 0.4.8)
  * ocamlfind-secondary = 1.8.1 → ocamlfind = 1.8.1 → graphics = 5.0.0 → dune = 2.0.0
  * ocamlfind-secondary = 1.8.1 → ocamlfind = 1.8.1 → graphics = 5.1.0 → dune = 2.0.0
  * ocamlfind-secondary = 1.8.1 → ocamlfind = 1.8.1 → graphics = 5.1.0 → dune-configurator = 1.11.4 → dune = 2.0.0
  * ocamlfind-secondary = 1.8.1 → ocamlfind = 1.8.1 → graphics = 5.1.0 → dune-configurator = 2.0.0 → dune = 2.0.0
  * ocamlfind-secondary = 1.8.1 → ocamlfind = 1.8.1 → graphics = 5.1.0 → dune-configurator = 2.0.0 → dune-private-libs = 2.0.0 → dune = 2.0.0
Summary: out of 12977 packages (2542 distinct names)
- 29 packages part of dependency cycles

src/solver/opamActionGraph.mli Outdated Show resolved Hide resolved
@gasche
Copy link
Member Author

gasche commented Dec 11, 2019

Now I am curious what exactly your are doing here... how about a chat some day?

(I've been trying to have a physical meeting with you for unrelated matter, but scheduling appears to be tricky due to everyone's constraints.)

This is part of the Marracheck project that we already discussed. We are calling a solver to create "large sets of co-installable packages", but the solver sometimes returns solutions that contain a cycle (the example found by Armaël is that OASIS has a dependency for which some earlier versions depended on OASIS themselves). When OPAM (invoked programmatically through its API) complains about the cycle, we feed a fixed query to the solver that forbid the particular choice of packages involved in the cycle, to get a new solution that avoids it.

@Armael
Copy link
Member

Armael commented Dec 11, 2019

@AltGr I was not aware that there was a way to precompute all possible cycles, thank you for that.
Given this, we could simplify our strategy a bit.

As @gasche said, currently we detect cycles "dynamically": whenever the solver returns a solution that contains a cycle, we add this cycle as a conflict and re-run the query. Instead, we could pre-compute all cycles in the universe of packages and add them as conflicts beforehand.

If we do that (which seems a bit cleaner and possibly more efficient than patching and re-running queries), then we don't strictly need the present PR. Indeed, it seems we can then use OpamAdminCheck.cycle_check : universe -> package_set * formula list list to get the cycles.

I still think this PR is a nice cleanup, though :-).

@Armael
Copy link
Member

Armael commented Dec 11, 2019

In fact, I am now wondering: why isn't opam already doing this before calling to a solver (that is, pre-computing the cycles and adding them as conflicts)?

As far as I understand, the fact that the solver can return a solution that can contain cycles is because the encoding of the installability problem typically does not require a solution to be acyclic. And if I'm reading the code correctly, when a cyclic solution is returned by the solver, opam simply fails and prints the cycle back to the user. However, it's not really the user's fault, is it?

So it seems to me that the correct thing to do would be to pre-compute the cycles and exclude them from the universe before calling to the solver. Is the reason why that's not done currently simply that solution containing cycles happen rarely enough in practice? And maybe that pre-computing cycles would reliably slow down "opam install" queries?

Or am I missing something?

@rjbou rjbou added the PR: WIP Not for merge at this stage label Jan 27, 2020
@AltGr
Copy link
Member

AltGr commented Mar 4, 2020

So it seems to me that the correct thing to do would be to pre-compute the cycles and exclude them from the universe before calling to the solver.

This is correct. There are two reasons why it is was not done:

  • it would be costly
  • we have been considering this an error in the repository, that we can actually fix upstream. There is a corresponding verification in opam admin check, but it's not sufficiently enforced at the moment.

Granted, you could technically have two independent cycle-free repositories and end up with a cycle when you use both together, but I guess we can keep looking over this for the moment.

@AltGr AltGr added this to the Next milestone Mar 9, 2020
@rjbou rjbou removed this from the Next milestone May 20, 2020
@rjbou rjbou removed the PR: WIP Not for merge at this stage label Mar 19, 2021
@dra27 dra27 added this to the 2.2.0~alpha milestone Mar 26, 2021
@dra27
Copy link
Member

dra27 commented Jun 25, 2021

This is a nice change, and apologies for it's having been dropped for so long. Would you be to happy to rebase it so that it can reviewed with rather less lag for opam 2.2? If you don't have time at the moment, we'd be happy to take this on.

@rjbou rjbou added this to PR in progress in Opam 2.2.0 via automation Sep 3, 2021
@rjbou rjbou self-assigned this Sep 3, 2021
@rjbou rjbou assigned AltGr and unassigned rjbou Sep 14, 2021
… cycles

For conflicts caused by cyclic actions, the opamCudf API would
previously only allow to observe the cycle with actions described as
strings for human pretty-printing.

We would like to write a script, using the opam API, that can react to
solution errors caused by cycles by patching the query and calling the
solver again. For this we need a machine-readable representation of
conflict cycles.

The present commit makes the minimal change to the opamCudf API to
make this possible:

- The internal representation of cycles is changed to take CUDF
  packages (the most general information) instead of strings.
- The `OpamCudf.cycle_conflicts` function has its type accordingly
  (this changes the module interface and may break library consumers).
- A new function `OpamCudf.conflict_cycles` is exposed to recover
  a cycle representation carrying "opam package" actions.

Remark: `conflict_cycles` is in the style of the current API on the
abstract `conflict` type, which is not very good: a conflict is
a variant/sum type in hiding (either an incompatibility in the query
or a cycle in the solution), and functions do something in one case
and silently return nothing in the other.

It would be nicer to expose a variant-sum type view of the conflict
type to users, but this should be discussed with OPAM maintainers, and
is not a requirement for our work.
@kit-ty-kate kit-ty-kate force-pushed the better_cycle_conflicts_representation branch from 5e9e429 to 924f0e2 Compare January 18, 2022 12:33
@kit-ty-kate kit-ty-kate moved this from PR in progress to PR to review in Opam 2.2.0 Jan 18, 2022
Copy link
Member

@kit-ty-kate kit-ty-kate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Good to merge once CI is green

Opam 2.2.0 automation moved this from PR to review to PR finalised Jan 18, 2022
@Armael
Copy link
Member

Armael commented Jan 18, 2022

Thanks for the rebase. I think this is still relevant and a useful improvement of the API, so I'm happy to see it merged.
(Looking at the current code of marracheck we've been using the "other" approach of precomputing the cycles and excluding them from the solution, but it seems that there might be some remaining issues related to cycles so this PR should be useful to have in any case.)

@rjbou rjbou force-pushed the better_cycle_conflicts_representation branch from fce5e9b to 25fbab0 Compare January 18, 2022 16:13
@kit-ty-kate
Copy link
Member

Thanks!

@kit-ty-kate kit-ty-kate merged commit 8349d43 into ocaml:master Jan 19, 2022
Opam 2.2.0 automation moved this from PR finalised to Done Jan 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Opam 2.2.0
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

6 participants