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

Completely refactor the way orphan packages are handled (and add tests) #4969

Merged
merged 12 commits into from
Jan 5, 2022

Conversation

AltGr
Copy link
Member

@AltGr AltGr commented Dec 16, 2021

Orphan packages are packages which are installed within a switch, but no longer available. Without special handling, they become invisible to the solver, which has quite a few drawbacks:

  • bad error messages
  • forced removals upon unrelated actions
  • removal instead of up/downgrade if another version is still available
  • etc.

For these reasons, they need special care. The current approach is complex code in OpamClient that analyses them, their relationships with the user request, and lies about the universe so they can be kept when unrelated, or if they don't matter.

That code was tricky, complex, computing (reverse) dependency cones, intersections thereof and whatnot, costly — requiring a few preliminary conversions of the opam state to a solver universe, and, I found out, still incomplete and incorrect around the edges.

This PR implements a much simpler solution, that supplies the whole universe to the solver with a minimum of lies (orphans are included, but with their unavailability encoded as a fake dependency). Then, there is post-processing on the action graph after the solution is computed for removing sub-graphs that are disjoint from the requested actions, to avoid unrelated actions from being triggered.

The additional tests show a good behaviour in the considered cases (including some where the old system was incorrect).

IMPORTANT: major change compared to the previous behaviour

  • you are no longer allowed to perform actions on dependents of orphan packages; this is more consistent and in accordance with the similar policy on reinstalls that was adopted some time ago.

RELATED THINGS TO CONSIDER:

  • to ease the case above, consider adding an opam pin --current <pkg> that pins the package to its current state. Allows manual bypassing of an upstream removed packages, and would also offer a more consistent workaround for skipping pending reinstalls
  • opam upgrade --fixup has been simplified because it used to consider the specific status of orphan packages. Maybe consider re-implementing it with something like opam upgrade --criteria=fixup --best-effort --update-invariant ?

@rjbou rjbou added this to the 2.2.0~alpha milestone Dec 16, 2021
@rjbou rjbou added the PR: QUEUED Pending pull request, waiting for other work to be merged or closed label Dec 16, 2021
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.

The code looks fine, the tests are clear and show that it works. LGTM

@rjbou rjbou mentioned this pull request Dec 16, 2021
@AltGr AltGr changed the title Completely refactor the way orphan packages are handled (and add/port tests) Completely refactor the way orphan packages are handled (and add tests) Dec 21, 2021
@AltGr
Copy link
Member Author

AltGr commented Dec 21, 2021

Note: this is now based on top of #4973, which includes most of the tests, and should be rebased once that is merged.

@AltGr
Copy link
Member Author

AltGr commented Dec 21, 2021

2 opam-rt tests are failing:

  • reinstall test has been ported to reftests and can be discarded (there are some adjustments because of the no longer allowed reinstalls)
  • I am still working on the pin-advanced test, and should have a fix shortly (on either side!)

@AltGr
Copy link
Member Author

AltGr commented Dec 21, 2021

Ok, now all should be ok:

@AltGr
Copy link
Member Author

AltGr commented Dec 22, 2021

Ok, only remaining failures should be fixed by the PR on opam-rt; apparently the trick that used the same-named branch of opam-rt for tests is no longer here, so we should probably merge #4973, then ocaml-opam/opam-rt#76, then re-run CI for this PR.

The plan is to remove the pre-processing as much as possible and let the solver
handle them as much as possible. Then some post-processing could be done to
remove the irrelevant parts of the solution.
Accounting for the more restrictive handling of orphans, and working around it
with `pin --current`.
- fixed removal of orphan packages (the sanitization of the request was too
  strict)
- pass the list of relevant packages explicitely in the request. Previously this
  was inferred from the wish_install/upgrade/remove fields, assuming no
  filtering if that was empty, but:
  * `opam upgrade -a foo` would wrongly restrict to `foo`
  * the post-action on unpinning had to explicitely be an upgrade or remove,
    while now we can just let the solver choose and still properly trim the
    solution.
Can happen when changing the pinned-to version or unpinning.
Also includes a small rewrite of avoid-version handling in the package universe.

Now 'upgrade' requests are split for the solver: for pinned packages, it's
sufficient to file an 'install' request since only one version is expected to be
available.
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 aside from a small request

(** Returns [true] when the package has the [avoid-version] flag and there isn't
already a version with that flag installed (which disables the
constraint) *)
val avoid_version : 'a switch_state -> package -> bool
Copy link
Member

Choose a reason for hiding this comment

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

Since this PR also changes the code for the handling of the avoid-version flag, i just noticed there wasn’t any tests for this flag. Could you add some if you have some time?

Copy link
Member Author

Choose a reason for hiding this comment

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

I moved some code around and replaced a Set.fold+exists by a filter for efficiency, but that should be functionnally equivalent; indeed there is no fundamental reason for this to be in this PR, I just stumbled upon it while I was writing the PR.

You're right about tests — though I'd prefer not to stall this and add them in another PR.

@AltGr AltGr merged commit 214c254 into ocaml:master Jan 5, 2022
AltGr added a commit to AltGr/opam that referenced this pull request Jan 14, 2022
AltGr added a commit to AltGr/opam that referenced this pull request Jan 17, 2022
AltGr added a commit to AltGr/opam that referenced this pull request Jan 17, 2022
kit-ty-kate pushed a commit to AltGr/opam that referenced this pull request Jan 21, 2022
rjbou pushed a commit to AltGr/opam that referenced this pull request Jan 21, 2022
@rjbou rjbou removed the PR: QUEUED Pending pull request, waiting for other work to be merged or closed label May 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants