pubgrub-rs / pubgrub

PubGrub version solving algorithm implemented in Rust
https://pubgrub-rs.github.io/pubgrub/pubgrub/
Mozilla Public License 2.0
337 stars 30 forks source link

Allow an arbitrary, custom incompatibilities #152

Closed zanieb closed 3 weeks ago

zanieb commented 7 months ago

In a concrete example, pip allows users to define dependencies on packages via URLs. When resolving a dependency tree, we will only allow a transitive dependency to require a package with a URL if that URL is included as a direct dependency (for security). In this situation, we currently must raise an error and crash the solver. However, it'd be ideal for the solver to backtrack and attempt other versions of the transitive dependency as one may not have the URL package dependency.

Perhaps this problem could be simplified by thinking of a "banned list" of packages feature. If a transitive dependency version requires a package on the banned list, it should be marked as incompatible and other versions of the dependency should be checked.

This may be solvable by adding an Invalid incompatibility type that includes a custom message that describes why the package version was not acceptable. I'm not familiar with the design of incompatibilities though.

Eh2406 commented 7 months ago

I don't quite see why the URL situation requires crashing out, but I may not understand all the architectural decisions involved here. One solution that is already available is returning Dependencies::Unknown, although that doesn't let you customize the error message.

Users can implement the "banned list" themselves by simply filtering the versions out before providing them to PubGrub. Although this doesn't provide a way to customize the error message.

Another proposal that we have had is when returning a list of dependencies you could also return some kind of week dependency "I don't need X, but if it's present it must match this version range". See prior conversation at #120 and a draft PR at #124. This is currently held up on the additional complexity would add to the API, especially how even if you don't need the functionality you have to deal with the complexity. #148 was created to see if we could come up with an API so that users only deal with the complexity they need.

Allowing power users to provide arbitrary incompatibilities is discussed in ... I can't find the link. There will definitely be lots of ways a user can shoot themselves in the foot using this API. So I only want provided, when we're sure that the common use cases have ergonomics support.

I absolutely love the idea of allowing a "tag" | "span" | "label" to each response given to PubGrub by the user. Then the obvious answer to this is Dependencies::Unknown with a tag for whites unavailable. The challenge here is similar to #120/#124/#148 how can we add this to the API in such a way that it is not added complexity for the users who do not need the functionality.

zanieb commented 7 months ago

Users can implement the "banned list" themselves by simply filtering the versions out before providing them to PubGrub. Although this doesn't provide a way to customize the error message.

This is the heart of the issue, as we cannot include information in the derivation tree and error messages as to why those versions were excluded.

One solution that is already available is returning Dependencies::Unknown, although that doesn't let you customize the error message.

Hm I'm not sure if we tried this, I'll look into that and see if it gets us further. I like the idea of attaching additional context to the response, if feasible.

zanieb commented 7 months ago

Another use-case: We're filtering out package versions that are only available for other platforms (i.e. not published for the current/target platform) but PubGrub cannot be aware of this and consequently the information is excluded from the derivation tree.

konstin commented 3 weeks ago

Solved by #208