[Pkg-rust-maintainers] Bug#901827: dpkg: Support two-sided version constraint ranges, required to properly translate Cargo dependencies

Ximin Luo infinity0 at debian.org
Thu Jun 21 18:15:00 BST 2018

Josh Triplett:
> On Tue, Jun 19, 2018 at 08:23:00PM +0000, Ximin Luo wrote:
>> Anyway, we have a solution on the dpkg bug report that is somewhere halfway between the old and the current approach. I think it will work. It is to declare Provides: A (= X.Y.Z), A-X (= X.Y.Z), A-X.Y (= X.Y.Z) for all packages, then generate a list-of-OR-clauses for every cargo dependency that exactly matches the selected range, e.g. >= 6.1 << 9.5 gets turned into X-6 (>= 6.1) | X-7 | X-8 | X-9 (<< 9.5) and >> 9 simply gets turned into X (>> 9).
> That sounds ideal! And needing multiple branches of the OR clause should
> almost never happen, unless someone has a version constraint spanning
> major versions. The common case of a "compatible" dependency like
> X="~1.2" should just turn into "X-1 (>= 1.2)" (and X="~0.5" turns into
> just "X-0.5").

The new algorithm I did is actually quite nice, it will do two passes to do the conversion.

In Cargo, version constraints get ANDed together and treated as a single constraint for a given crate. So the first pass starts off with (>= nothing, << nothing), and goes through this list and repeatedly constrains both endpoints based on the Cargo constraints (like >>, ~, ^, etc). The second pass then converts these two endpoints into a single OR-list that is required for dpkg to process it correctly.

Then there is a couple of optimisation steps to remove redundancies like A-X (>= X) gets converted to just A-X, and A-X (<< X) gets dropped entirely. Very often this cuts down the number of items in the OR-list from 2 to 1. The remaining ones that I've seen that have >= 2 items in the OR-list are:

debcargo/tmp$ ls -1 rust-*.dsc | wc -l

debcargo/tmp$ grep " | " */debian/control
language-tags-0.2.2/debian/control: librust-heapsize-0.3+default-dev | librust-heapsize-0.2+default-dev (>= 0.2.2~~)
mime-0.2.6/debian/control: librust-heapsize-0.3+default-dev | librust-heapsize-0.2+default-dev
mime-0.2.6/debian/control: librust-serde-0.8+default-dev | librust-serde-0.7+default-dev
mime_guess-1.8.4/debian/control: librust-mime-0.2+default-dev <!nocheck> | librust-mime-0.1+default-dev <!nocheck>,
mime_guess-1.8.4/debian/control: librust-mime-0.2+default-dev | librust-mime-0.1+default-dev,
staticfile-0.5.0/debian/control: librust-iron-0.6+default-dev <!nocheck> | librust-iron-0.5+default-dev <!nocheck>,
staticfile-0.5.0/debian/control: librust-mount-0.4+default-dev <!nocheck> | librust-mount-0.3+default-dev <!nocheck>,
staticfile-0.5.0/debian/control: librust-iron-0.6+default-dev | librust-iron-0.5+default-dev,
staticfile-0.5.0/debian/control: librust-mount-0.4+default-dev | librust-mount-0.3+default-dev,
unicase-1.4.2/debian/control: librust-heapsize-0.3+default-dev | librust-heapsize-0.2+default-dev
unicode-bidi-0.3.4/debian/control: librust-serde-1+default-dev | librust-serde-0+default-dev (>= 0.8~~),
unicode-bidi-0.3.4/debian/control: librust-serde-1+derive-dev | librust-serde-0+derive-dev (>= 0.8~~)
url-1.7.0/debian/control: librust-serde-0.8+default-dev | librust-serde-0.7+default-dev | librust-serde-0.6+default-dev (>= 0.6.1~~)

out of the transitive dependencies of mdbook, exa, ripgrep, debcargo.

We are putting higher versions first because sbuild does not set "--resolve-alternatives" by default on the Debian buildds, see `man sbuild` on what that means. Hopefully this will stop it from affecting us in most cases.


GPG: ed25519/56034877E1F87C35
GPG: rsa4096/1318EFAC5FBBDBCE

More information about the Pkg-rust-maintainers mailing list