Skip to content

Commit 8235de2

Browse files
Fix edge-cases of virtual packages (#203)
This fixes some edge-cases with virtual packages resolution introduced in #146 - Sometimes multiple versions of the same package are available, just pick the most recent one - Fix comparison in version_constraint - Sometimes virtual packages are not in the arch folder One way to reproduce this is to use the following manifest slightly adapted from the examples folder to: - add the curl package that will have several of the issues solved by this patch - bump the snapshot time <details><summary>Example manifest</summary> ``` version: 1 sources: - channel: noble main url: https://snapshot.ubuntu.com/ubuntu/20250930T150000Z - channel: noble-security main url: https://snapshot.ubuntu.com/ubuntu/20250930T150000Z - channel: noble-updates main url: https://snapshot.ubuntu.com/ubuntu/20250930T150000Z archs: - "amd64" - "arm64" packages: - "ncurses-base" - "libncurses6" - "tzdata" - "bash" - "coreutils" # for commands like `ls` - "grep" # for apt list --installed - "dpkg" - "apt" - "perl" - "curl" ``` </details> This will build but you should see the following warning messages with the current main version: ``` DEBUG: [cache]/external/rules_distroless+/apt/private/apt_dep_resolver.bzl:40:14: Multiple candidates for virtual package 'libnettle8': ["libnettle8t64", "libnettle8t64"] DEBUG: [cache]/external/rules_distroless+/apt/private/apt_dep_resolver.bzl:40:14: Multiple candidates for virtual package 'libhogweed6': ["libhogweed6t64", "libhogweed6t64"] WARNING: Following dependencies could not be resolved for curl: libnettle8,libhogweed6,libgnutls30 DEBUG: [cache]/external/rules_distroless+/apt/extensions.bzl:27:26: ``` The first two are solved by picking whichever of the package has the most recent version. For the `libgnutls30` issue reported here, I had to add some extra ouptut to figure things out. In this version of the snapshot, the package is required with a constraint `>= 3.8.1` and the packages available in the snapshot have versions `3.8.3-1.1ubuntu3` and `3.8.3-1.1ubuntu4`. They should both satisfy the constraint but because the operands are inverted they are rejected. The last point is more peculiar. We saw this happen with the OpenVINO apt distribution (see [here](https://docs.openvino.ai/2025/get-started/install-openvino/install-openvino-apt.html)) but I think it's fairly reasonable to fallback to the all architecture just in case 🤔
1 parent 8fe8488 commit 8235de2

2 files changed

Lines changed: 11 additions & 1 deletion

File tree

apt/private/apt_dep_resolver.bzl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ load(":version_constraint.bzl", "version_constraint")
66
def _resolve_package(state, name, version, arch):
77
# First check if the constraint is satisfied by a virtual package
88
virtual_packages = state.repository.virtual_packages(name = name, arch = arch)
9+
virtual_packages.extend(state.repository.virtual_packages(name = name, arch = "all"))
910

1011
candidates = [
1112
package
@@ -34,6 +35,15 @@ def _resolve_package(state, name, version, arch):
3435
if "Priority" in package and package["Priority"] == "required":
3536
return package
3637

38+
# Sometimes they are provided by multiple versions of the same library
39+
if len({c["Package"]: None for c in candidates}.keys()) == 1:
40+
versions = [c["Version"] for c in candidates]
41+
selected_version = 0
42+
for i in range(1, len(versions)):
43+
if version_constraint.relop(versions[i], versions[selected_version], ">>"):
44+
selected_version = i
45+
return candidates[selected_version]
46+
3747
# Otherwise, we can't disambiguate the virtual package providers so
3848
# choose none and warn.
3949
# buildifier: disable=print

apt/private/version_constraint.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def _is_satisfied_by(va, vb):
7474
if vb[0] != "=":
7575
fail("Per https://www.debian.org/doc/debian-policy/ch-relationships.html only = is allowed for Provides field.")
7676

77-
return _version_relop(va[1], vb[1], va[0])
77+
return _version_relop(vb[1], va[1], va[0])
7878

7979
version_constraint = struct(
8080
relop = _version_relop,

0 commit comments

Comments
 (0)