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

Ximin Luo infinity0 at debian.org
Tue Jun 19 03:55:31 BST 2018

Package: dpkg
Severity: wishlist

Dear Maintainer,

The Rust package manager Cargo, makes it possible to declare two-sided version
constraint ranges such as X (>= 6, << 7). In dpkg, historically this has been
expressed by declaring two one-sided version constraint ranges for the same
package like X (>= 6), X (<< 7), however this is not sufficient for Cargo due
to its other feature of allowing transitive dependencies on multiple versions
of the same package.

Currently to support this we are creating packages called X-$version, and
declaring Provides: X (= $version). This breaks in the following situation:

mdbook 0.1.7 transitively depends on slab 0.1.3, 0.3.0, and 0.4.0, via mio 0.5.1,
mio 0.6.14, and ws-0.7.6. These dependencies are declared as:

mio-0.5.1/debian/control: librust-slab+default-dev (>= 0.1.0~~),
mio-0.5.1/debian/control: librust-slab+default-dev (<< 0.2~~),
ws-0.7.6/debian/control: librust-slab+default-dev (>= 0.3~~),
ws-0.7.6/debian/control: librust-slab+default-dev (<< 0.4~~),
mio-0.6.14/debian/control: librust-slab+default-dev (>= 0.4.0~~),
mio-0.6.14/debian/control: librust-slab+default-dev (<< 0.5~~),

I have:

librust-slab-0.1-dev_0.1.3-1_amd64.deb Provides: librust-slab+default-dev (= 0.1.3-1), librust-slab-0.1+default-dev (= 0.1.3-1), librust-slab-dev (= 0.1.3-1)
librust-slab-0.3-dev_0.3.0-1_amd64.deb Provides: librust-slab+default-dev (= 0.3.0-1), librust-slab-0.3+default-dev (= 0.3.0-1), librust-slab-dev (= 0.3.0-1)

Unfortunately, APT chooses to resolve the full set by only installing slab
0.1.3 and 0.4.0, because these two are enough to satisfy the full set,
including the two separate (>= 0.3~~) (<< 0.4~~) constraints. From dpkg's
viewpoint these are allowed to be satisfied by two separate packages.

RPM has resolved this by implementing "rich dependencies" which is a general
solution to express "the same package must satisfy both A and B". However, it
is apparently more difficult to do this in dpkg.

What I am suggesting is smaller: we only need to support two-sided version
ranges like (>= 0.3~~, << 0.4~~), which does not seem to be such a major
addition to the existing one-sided version range syntax.

In the Debian Rust team, we previously experimented with e.g. converting:

- Cargo dependencies X (>= 6, << 7) into dpkg dependencies X-6 | X-7
- Cargo dependencies X (>= 6)       into dpkg dependencies X-6 | X-7 | X-8 | X-9 | X-10

but this causes other problems (unwieldy dependency conversion logic) and does
not really solve the problem described within this bug report, since it is
perfectly legal for separate Cargo crates to declare (= 6.1) (= 6.2) (= 6.3)
dependencies and Cargo will require all three to be installed even though they
are (supposed to be) semantically compatible. In this case, we would have to
create new Debian packages called X-6.i (Provides: X-6 = 6.i) for i={1,2,3}
which puts us right back where we started. (Although granted it is unlikely,
assuming that everyone in the Rust ecosystem is sane and avoids this forever.)

So the cleanest solution to this problem would be to support two-sided version
ranges. This would be beneficial across the whole archive as well - I have
needed to do the Depends: X (>= 4), X (<< 5) hack before when what I really
meant was (>= 4, << 5), and I remember this in others' packages too.


-- System Information:
Debian Release: buster/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable-debug'), (500, 'testing-debug'), (500, 'buildd-unstable'), (500, 'stable'), (300, 'unstable'), (100, 'experimental'), (1, 'experimental-debug')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.16.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_GB.utf8, LC_CTYPE=en_GB.utf8 (charmap=UTF-8), LANGUAGE=en_GB:en (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages dpkg depends on:
ii  libbz2-1.0   1.0.6-8.1
ii  libc6        2.27-3
ii  liblzma5     5.2.2-1.3
ii  libselinux1  2.8-1
ii  tar          1.30+dfsg-2
ii  zlib1g       1:1.2.11.dfsg-1

dpkg recommends no packages.

Versions of packages dpkg suggests:
ii  apt            1.6.1
pn  debsig-verify  <none>

-- no debconf information

More information about the Pkg-rust-maintainers mailing list