Repository navigation
Conversation
Solve for the requested architecture instead of the host one and feed it to $basearch in repo URLs. Adds the shared rpm_lock solver-args plumbing, the synthetic features repository and the sharded e2e test skeleton. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- --excludepkgs and rpm_lock(excludepkgs=): hide packages matching NEVRA globs from the solver, like dnf excludepkgs. Any other --setopt key goes to libdnf. - --module-enable and rpm_lock(module_enable=, module_platform_id=): enable module streams before resolving and recompute modular filtering. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Best stays the default; --nobest lets the solver fall back to older candidates while keeping pinned versions as constraints, and solver problems are reported in the error. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- The same NEVRA in two enabled repositories no longer breaks best mode: pick_one_pkg_per_name_arch keeps a single candidate. - Weak dependencies (Recommends, Supplements) are no longer trimmed from the solution: install_weak_deps is honoured, so they are resolved and locked. - A lower-layer entry with a NULL or empty integrity means the same build, not a change. - A lower-layer package with no candidate in the repositories became a synthetic solvable providing only its own name, so packages relying on its sonames looked broken and libsolv bent its provider choice (openssh 9.9p1 + openssh-clients instead of the 10.5p1 real dnf installs). It now inherits the provides of the newest build of that name in the repositories, minus that build's self-provides. Verified against real dnf on a perl-ci repro: the 83-package transaction is identical. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…grades - A requested package the layer below holds at the repositories' version or newer no longer gets an install job: libsolv counted it as a fresh install and pulled in its weak dependencies (glibc-gconv-extra, the systemd chain, ...). On the cs9-slim and ol9-upgrades repros the result now matches dnf. - The goal runs through dnf_goal_depsolve, which adds exclude_from_weak_autodetect: providers of Recommends an installed package left unmet stay out of weak installation, so an upgrade adds only the new weak dependencies, as `dnf update` and `microdnf update` do (verified on a two-version fixture). An empty transaction is not an error. - The lockfile records "recommends" and "supplements" (dependency strings, rich ones included) per package and reads them back onto the synthetic installed solvable, so this also holds when the repositories lack the layer's build. Entries without the fields behave as before; tools that rewrite lockfile entries must pass them through. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
On an arm64 host libsolv rejected the x86_64 packages of an `--archlist x86_64` mark, so their dependencies went unmarked (oracle_linux_curl_mark_test failed on macOS arm64). dnf_lock already set the solve architecture; its helpers move to dnf/solve-arch.h and mark uses them too. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Run pull requests on `pull_request` instead of `pull_request_target`, which GitHub restricts on public repositories by default from 2026-12-02. Fork PRs get no secrets and fall back to the Docker sandbox (setup_buildbuddy.sh). - actions/checkout v7.0.1, softprops/action-gh-release v3.0.3; setup_buildbuddy.sh: results URL on app.buildbuddy.io, 100 remote jobs. - Per-platform transition binaries and their filegroups are `manual`, so `bazel test //...` builds only the host tools; an empty stand-in for rules_swift's local toolchain config saves its 25-80 s Swift probe. - `--config=asan` builds dnf_lock and every C dependency with ASan + LSan + UBSan (hermetic LLVM); suppressions for proven third-party noise ship to the tests only under this config. The Sanitizers workflow runs the lock, mark and tools e2e tests with it on every pull request and push to main. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
dnf5 5.4.6.0 needs libsolv >= 0.7.36 (libdnf5/CMakeLists.txt:93); take the latest 0.7.41. Upstream split pool.c into pooldep.c, poollang.c and poolwhatprovides.c and moved the built-in hashes behind chksum_impl.c (the WITH_OPENSSL=OFF path, as before). libdnf keeps building against it; single_version_override replaces its 0.7.32 request. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
dnf5 5.4.6.0 needs librepo >= 1.20.0 (libdnf5/CMakeLists.txt:122); on 1.19.0 every dnf5 repo load crashes in lr_metadata_downloader. Take the latest 1.21.2. The configured header templates are unchanged upstream, so only version.h moves; the source list and the gpgme backend (-DUSE_GPGME=1) stay. libdnf keeps building against it; single_version_override replaces its 1.19.0 request. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…ame) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…ty module Needed by rpm 4.20 (WITH_SEQUOIA=OFF, WITH_LEGACY_OPENPGP=ON). Exported as a filegroup of sources: upstream cannot build standalone, it needs rpm's system.h/rpmpgpval.h/config.h, so @rpm//:rpmio compiles it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
rpm 4.20 switched to CMake and moved system.h/debug.h/rpmhash.[CH] into misc/. Overlay changes: OpenPGP comes from @rpmpgp_legacy (WITH_SEQUOIA=OFF, WITH_LEGACY_OPENPGP=ON) instead of rpmio/rpmpgp_internal.c; tagtbl.inc, which upstream generates with lib/gentagtbl.sh at build time, is checked in to avoid a genrule; rpm_config.h gains RPM_VENDOR/RPM_CONFIGDIR/C_LOCALE and renames WITH_SQLITE/WITH_BDB_RO to ENABLE_*. Targets and labels are unchanged; libdnf and microdnf need no source changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bookingcom#55) into the fork 🤖 Generated with [Claude Code](https://claude.com/claude-code)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
rpm 4.20 reports the x86_64 microarchitecture level as the arch on Linux (x86_64_v3 on current CI runners). libdnf 0.74 has no base arch for it, so dnf_context_get_base_arch() returns NULL and every repo fails with "basearch not set". dnf5 maps these levels to x86_64; do the same. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add dnf5 5.4.6.0 and toml11 4.4.0 to the local registry. The dnf5 module builds the upstream sources from the release tarball with an overlay (BUILD, module file, generated config.h, a force-included compat header for macOS) and patches for what a Bazel build cannot express (fs/utils.hpp, nsvcap regexes under libc++). This change builds libdnf5 only; the plugins, the hermetic rpm configuration, the CLI and the wiring follow. The root module depends on dnf5 as a dev dependency so //... resolves it. Based on the dnf5 work by Manuel Naranjo. Co-authored-by: Manuel Naranjo <naranjo.manuel@gmail.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Upstream builds libdnf5 plugins as shared objects and dlopen()s them from the host. Link actions, expired-pgp-keys and local into libdnf5 instead: defs.bzl renames each plugin's extern "C" entry points, and plugins.cpp finds them in a static table. A plugin configuration naming a plugin that is not built in (rhsm, snapper, ...) is skipped with a warning, not fatal. The plugin configuration directories are resolved below the installroot. libdnf5 and its plugins call each other, so the plugins are alwayslink and depend on libdnf5_core, and :libdnf5 ties the three together. init_lib_rpm no longer reads the host's rpmrc, macros or init.lua: it points RPM_CONFIGDIR at /dev/null, supplies the architecture compat table, targets <arch>-linux whatever the host is, and defines the few macros the rpmdb and transactions need (dbpath, sqlite backend, colors, verify level, ...). Based on the dnf5 work by Manuel Naranjo. Co-authored-by: Manuel Naranjo <naranjo.manuel@gmail.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add libdnf5-cli and the dnf5 binary. The command plugins (changelog, config-manager, copr, repoclosure, repomanage, reposync) are linked into the binary with renamed entry points and registered from a static table in main.cpp. Nothing is loaded from the host: command aliases (aliases.d) and external plugins (DNF5_PLUGINS_DIR) are disabled on purpose. Two patches for libc++: the progress bar takes its time from system_clock (high_resolution_clock is not the type of its stored time points), and --changelogs-since is parsed with std::get_time, which libc++ has where it lacks std::chrono::parse; impossible dates such as 2024-02-31 are still rejected. Based on the dnf5 work by Manuel Naranjo. Co-authored-by: Manuel Naranjo <naranjo.manuel@gmail.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Wire dnf5 into the repository like the other tools: //dnf:dnf5 and the per-platform dnf5_<platform> binaries, the @dnf5 host alias, the root aliases, release packaging (5 tools on 4 platforms, 20 binaries), the CI and release workflows, README and AGENTS.md. The dnf5_* prebuilt repositories exist only once a release has generated integrities, so the root module has no use_repo for them. e2e:dnf5_smoke_test runs the built binary against the ol9 test repository inside a temporary installroot and checks exit codes: repoquery, the solver reporting missing dependencies, a plugin configuration for a plugin that is not built in being skipped, the host's rpm Lua not running (RPM_CONFIGDIR pointing at an init.lua that writes a marker), a noarch package passing rpm's arch, os and digest checks, and the rpmdb being created inside the installroot. Based on the dnf5 work by Manuel Naranjo. Co-authored-by: Manuel Naranjo <naranjo.manuel@gmail.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…e test dnf_config renders dnf.conf (best, install_weak_deps, excludepkgs, module_platform_id) and one .repo per repository with ctx.actions.write and expand_template, and returns DnfConfigInfo with the files and the preamble. DNF5_PREAMBLE is the one list of flags that pins every host input dnf5 reads. The smoke test runs repoquery and install --assumeno through the rule. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…eamble Dumps the main and repository configuration through DNF5_PREAMBLE, replaces the execroot and the scratch directory by placeholders, fails on any value that is a host path or contains $HOME, and compares the rest with a checked-in golden file. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
A googletest cc_test linked against libdnf5_core covers the 18 forms with upstream's own cases, globs, dashes and dots, the 2 KB limit, invalid specs and the default-forms parse. It guards the patch that moved the NSVCAP regexes from POSIX extended to ECMAScript. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…nstalled set without an rpmdb libdnf5 gets RepoSack::create_system_repo_from_libsolv_testcase, which fills the system repository from a libsolv testcase (Repo::add_libsolv_testcase is private, RepoSack is its friend). The lock command will write the packages of the lower layers as such a testcase. The command itself lives in dnf/dnf5 and is linked into the binary like the upstream command plugins. The binary is therefore now built in //dnf (dnf5_binary) from the module's new dnf5_main library. This commit only parses the command line. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The lock command now picks one candidate per name.arch, resolves them with the libdnf5 goal (best or, with best=False, any version of a request), and writes the lockfile in dnf_lock's format: field order, integrity, URL, dependency edges and the weak dependency strings. Packages are emitted in the iteration order of a GLib hash table keyed by NEVRA, as dnf_lock does. Layers and --prune come in the next commits. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…ock command --prune trims the named packages and what only they pulled in, like dnf_lock --exclude. --module-enable goes through the libdnf5 module API; a small patch exposes RepoSack::reapply_module_filtering so queries made after the enable see the new module state. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
--lockfile loads the packages of the layers below and hands them to libdnf5 as a libsolv testcase through RepoSack::create_system_repo_from_libsolv_testcase: a package the repositories hold takes their metadata, one they lack becomes a synthetic package, and one whose integrity differs is left out. The archlist is inherited from the first lockfile that names one. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Install jobs are skipped for a package a layer already holds, a synthetic layer package gets the provides of the newest build of its name, and a solve that obsoletes a package of a layer below warns and records it under "obsoleted". test_lock_layers.py can drive dnf5 lock with the preamble of a dnf_config. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
rpm_lock gets backend = "libdnf" | "dnf5" (default libdnf) and dnf5_tool. The dnf5 backend renders a dnf_config (now also reachable as render_dnf_config) and runs `dnf5 lock` under its preamble. //microdnf:dnf5 pointed at a target that does not exist; it now aliases //:dnf5. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Every rpm_lock e2e case gets a backend = "dnf5" twin and a diff_test between the two lockfiles; test_lock_layers.py also runs against dnf5. The only normalization is the sandbox directory number in repo-local urls, which differs per action. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dnf5 rpmdb-mark records packages, and their required dependencies unless --nodeps, in <rpmdb-root>/var/lib/rpm/rpmdb.sqlite as dnf/mark.c does: the headers are imported without files, a root or a chroot. Specs are NAME, NAME=VERSION[-RELEASE] or anything dnf resolves, limited to --archlist, whatever the host arch. It is registered in DNF5_BUILTIN_PLUGINS next to lock. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
backend = "dnf5" runs `dnf5 rpmdb-mark` under the dnf_config preamble instead of the mark tool; the default stays libdnf. The script that runs dnf5 under the preamble moves from lock.bzl to config.bzl, taking the command, so both rules share it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Contributor
Author
|
Superseded by #76–#94: the dnf5 series regrouped into 19 focused commits (same final tree), without the transitional libdnf backend. 🤖 Generated with Claude Code |
This branch is waiting to be deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the dnf5 migration, step 4:
dnf5 rpmdb-mark, a statically linked dnf5 command plugin that records packages and their dependency closure in an rpmdb without installing them, without root or chroot, for the--archlistarch — the dnf5 counterpart of themarktool. Stacked on #56–#70, #71. Review only the last commit; merge the earlier PRs first.Size: 3 files, +74/-26.
backend = "dnf5" runs
dnf5 rpmdb-markunder the dnf_config preamble instead of the mark tool; the default stays libdnf. The script that runs dnf5 under the preamble moves from lock.bzl to config.bzl, taking the command, so both rules share it.Step 4 as a whole is tested on macOS arm64 (
bazel test //...31/31) and Linux x86_64 (x86_64_v3):bazel test //...30/31 and--config=asan(ASan + UBSan; LSan off) 13/14 on the mark, dnf5 smoke and lock parity tests. The only failure on Linux is the libdnforacle_linux_curl_mark_test, fixed by #63; its dnf5 counterpart already usesfile -Land passes. On macOS a directly executed sanitized binary cannot find the ASan runtime (pre-existing for every such test), so ASan there covers only the rule actions.🤖 Generated with Claude Code