From 63ef45cd77b9db7ab0b08a2c4eab8a831aafdb73 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 8 Feb 2023 20:48:01 +0300 Subject: Fix Fedora's main/devel package name resolution based on the project name --- bpkg/system-package-manager-fedora.cxx | 175 ++++++++++++--------- bpkg/system-package-manager-fedora.hxx | 9 -- bpkg/system-package-manager-fedora.test.testscript | 103 +++++------- 3 files changed, 136 insertions(+), 151 deletions(-) diff --git a/bpkg/system-package-manager-fedora.cxx b/bpkg/system-package-manager-fedora.cxx index b117eab..ab4b33c 100644 --- a/bpkg/system-package-manager-fedora.cxx +++ b/bpkg/system-package-manager-fedora.cxx @@ -1204,95 +1204,78 @@ namespace bpkg package_status::partially_installed); }; - // First, choose between the package name-based and project-based system - // package names. + // First look for an already fully installed package. // - for (package_status& ps: candidates) + optional r; + { - vector& pis (ps.package_infos); + diag_record dr; // Ambiguity diagnostics. - // Query both main and fallback packages with a single dns_list() - // invocation. - // - if (!ps.main.empty ()) pis.emplace_back (ps.main); - if (!ps.devel.empty ()) pis.emplace_back (ps.devel); - if (!ps.fallback.empty ()) pis.emplace_back (ps.fallback); - if (!ps.static_.empty ()) pis.emplace_back (ps.static_); - if (!ps.doc.empty () && need_doc) pis.emplace_back (ps.doc); + for (package_status& ps: candidates) + { + vector& pis (ps.package_infos); - if (!ps.debuginfo.empty () && need_debuginfo) - pis.emplace_back (ps.debuginfo); + // Query both main and fallback packages with a single dns_list() + // invocation. + // + if (!ps.main.empty ()) pis.emplace_back (ps.main); + if (!ps.devel.empty ()) pis.emplace_back (ps.devel); + if (!ps.fallback.empty ()) pis.emplace_back (ps.fallback); + if (!ps.static_.empty ()) pis.emplace_back (ps.static_); + if (!ps.doc.empty () && need_doc) pis.emplace_back (ps.doc); - if (!ps.debugsource.empty () && need_debugsource) - pis.emplace_back (ps.debugsource); + if (!ps.debuginfo.empty () && need_debuginfo) + pis.emplace_back (ps.debuginfo); - if (!ps.common.empty () && false) pis.emplace_back (ps.common); - ps.package_infos_main = pis.size (); - for (const string& n: ps.extras) pis.emplace_back (n); + if (!ps.debugsource.empty () && need_debugsource) + pis.emplace_back (ps.debugsource); - dnf_list (pis); + if (!ps.common.empty () && false) pis.emplace_back (ps.common); + ps.package_infos_main = pis.size (); + for (const string& n: ps.extras) pis.emplace_back (n); - // If the project-based (fallback) system package name is specified, - // then choose between the main/devel and fallback names depending on - // which of them is known to the system package manager. - // - // Specifically, if the main/devel system package exists we use that. - // Otherwise, if the fallback system package exists we use that and fail - // otherwise. - // - if (!ps.fallback.empty ()) - { - assert (pis.size () > 1); // devel, fallback,... or main, fallback,... + dnf_list (pis); - // Either devel or main is specified. + // Handle the fallback package name, if specified. // - bool devel (!ps.devel.empty ()); - assert (devel == ps.main.empty ()); - - string& name (devel ? ps.devel : ps.main); + // Specifically, if the main/devel package is known to the system + // package manager we use that. Otherwise, if the fallback package is + // known we use that. And if neither is known, then we skip this + // candidate (ps). + // + if (!ps.fallback.empty ()) + { + assert (pis.size () > 1); // devel+fallback or main+fallback - package_info& mi (pis[0]); // Main/devel package info. - package_info& fi (pis[1]); // Fallback package info. + package_info& mp (pis[0]); // Main/devel package info. + package_info& fp (pis[1]); // Fallback package info. - if (mi.unknown ()) - { - if (fi.known ()) - { - name = move (ps.fallback); - mi = move (fi); - } - else + // Note that at this stage we can only use the installed main/devel + // and fallback packages (since the candidate versions may change + // after fetch). + // + // Also note that this logic prefers installed fallback package to + // potentially available non-fallback package. + // + if (mp.installed_version.empty ()) { - // @@ This feels incorrect: there can be another candidate that is - // found. Double-check Debian semantics. - // - fail << "unable to guess " << (devel ? "devel" : "main") - << ' ' << os_release.name_id << " package for " << pn << - info << "neither " << name << " nor " << ps.fallback - << ' ' << os_release.name_id << " package exists" << - info << "consider specifying explicit mapping in " << pn - << " package manifest"; + if (!fp.installed_version.empty ()) + { + // Use the fallback. + // + (ps.main.empty () ? ps.devel : ps.main) = move (ps.fallback); + mp = move (fp); + } + else + continue; // Skip the candidate at this stage. } - } - // Whether it was used or not, cleanup the fallback information. - // - ps.fallback.clear (); - pis.erase (pis.begin () + 1); - --ps.package_infos_main; - } - } - - // Next look for an already fully installed package. - // - optional r; - - { - diag_record dr; // Ambiguity diagnostics. - - for (package_status& ps: candidates) - { - vector& pis (ps.package_infos); + // Whether it was used or not, cleanup the fallback information. + // + ps.fallback.clear (); + pis.erase (pis.begin () + 1); + --ps.package_infos_main; + } // Handle the unknown main package. // @@ -1343,7 +1326,7 @@ namespace bpkg dr << info << "consider specifying the desired version manually"; } - // Finally look for available versions if we are allowed to install. + // Next look for available versions if we are allowed to install. // if (!r && install_) { @@ -1367,6 +1350,48 @@ namespace bpkg if (requery) dnf_list (pis); + // Handle the fallback package name, if specified. + // + if (!ps.fallback.empty ()) + { + assert (pis.size () > 1); // devel+fallback or main+fallback + + package_info& mp (pis[0]); // Main/devel package info. + package_info& fp (pis[1]); // Fallback package info. + + // Note that this time we use the candidate versions. + // + if (mp.candidate_version.empty ()) + { + if (!fp.candidate_version.empty ()) + { + // Use the fallback. + // + (ps.main.empty () ? ps.devel : ps.main) = move (ps.fallback); + mp = move (fp); + } + else + { + // Otherwise, we would have resolved the name on the previous + // stage. + // + assert (mp.installed_version.empty () && + fp.installed_version.empty ()); + + // Main/devel package is not installable. + // + ps.main.clear (); + continue; + } + } + + // Whether it was used or not, cleanup the fallback information. + // + ps.fallback.clear (); + pis.erase (pis.begin () + 1); + --ps.package_infos_main; + } + // Handle the unknown main package. // if (ps.main.empty ()) diff --git a/bpkg/system-package-manager-fedora.hxx b/bpkg/system-package-manager-fedora.hxx index 52d2a3f..a1f7baf 100644 --- a/bpkg/system-package-manager-fedora.hxx +++ b/bpkg/system-package-manager-fedora.hxx @@ -172,15 +172,6 @@ namespace bpkg explicit package_info (string n): name (move (n)) {} - - bool - unknown () const - { - return installed_version.empty () && candidate_version.empty (); - } - - bool - known () const {return !unknown ();} }; vector package_infos; diff --git a/bpkg/system-package-manager-fedora.test.testscript b/bpkg/system-package-manager-fedora.test.testscript index f37b531..b023673 100644 --- a/bpkg/system-package-manager-fedora.test.testscript +++ b/bpkg/system-package-manager-fedora.test.testscript @@ -267,10 +267,6 @@ : libpq : - : Note that here we will test without package manifest, auto-creating a stub, - : and thus the -devel package name needs to be deducible from the package - : name (no project name fallback is available). - : { : installed : @@ -323,14 +319,6 @@ libpq-devel.i686 13.4-1.fc35 fedora libpq-devel.x86_64 13.4-1.fc35 fedora EOI - cat <=libpq-devel.info; - Installed Packages - rpm.x86_64 4.17.1-2.fc35 @updates - Available Packages - rpm.x86_64 4.17.1-3.fc35 updates - libpq-devel.i686 13.4-1.fc35 fedora - libpq-devel.x86_64 13.4-1.fc35 fedora - EOI cat <=libpq-devel.requires; glibc i686 0:2.34-49.fc35 glibc x86_64 0:2.34-49.fc35 @@ -348,13 +336,12 @@ EOI $* libpq --install libpq <>EOE >>EOO dnf-list: libpq-devel pq-devel libpq-devel+pq-devel.info - dnf-list: libpq-devel libpq-devel.info dnf-repoquery-requires: libpq-devel 13.4-1.fc35 x86_64 libpq-devel.requires dnf-list: libpq libpq.info EOI LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm =libpq-devel.info-fetched; + cat <=libpq-devel+pq-devel.info-fetched; Installed Packages rpm.x86_64 4.17.1-2.fc35 @updates Available Packages @@ -409,14 +396,14 @@ EOI $* libpq --install libpq <>EOE >>EOO dnf-list: libpq-devel pq-devel libpq-devel+pq-devel.info - dnf-list-fetched: libpq-devel libpq-devel.info-fetched + dnf-list-fetched: libpq-devel pq-devel libpq-devel+pq-devel.info-fetched dnf-repoquery-requires: libpq-devel 13.4-1.fc35 x86_64 libpq-devel.requires-fetched dnf-list-fetched: libpq libpq.info-fetched dnf-list-installed: libpq libpq.info-installed EOI LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm =libpq-devel.info; - Installed Packages - rpm.x86_64 4.17.1-2.fc35 @updates - Available Packages - rpm.x86_64 4.17.1-3.fc35 updates - libpq-devel.i686 13.4-1.fc35 fedora - libpq-devel.x86_64 13.4-1.fc35 @fedora - EOI cat <=libpq-devel.requires; glibc i686 0:2.34-49.fc35 glibc x86_64 0:2.34-49.fc35 @@ -528,14 +507,13 @@ EOI $* libpq --install libpq <>EOE >>EOO dnf-list: libpq-devel pq-devel libpq-devel+pq-devel.info - dnf-list: libpq-devel libpq-devel.info dnf-repoquery-requires: libpq-devel 13.4-1.fc35 x86_64 libpq-devel.requires dnf-list: libpq libpq.info dnf-list-installed: libpq libpq.info-installed EOI LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm =libsqlite3-devel+sqlite3-devel.info; Installed Packages @@ -625,15 +601,15 @@ dnf-list: libsqlite3-devel sqlite3-devel libsqlite3-devel+sqlite3-devel.info EOI LC_ALL=C dnf list --all --cacheonly --quiet libsqlite3-devel sqlite3-devel rpm =libsqlite3-devel+sqlite-devel.info; Installed Packages rpm.x86_64 4.17.1-2.fc35 @updates Available Packages rpm.x86_64 4.17.1-3.fc35 updates - sqlite-devel.i686 3.36.0-3.fc35 fedora - sqlite-devel.x86_64 3.36.0-3.fc35 @fedora EOI - cat <=sqlite-devel.requires; + cat <=sqlite-devel.requires-fetched; pkgconf-pkg-config i686 0:1.8.0-1.fc35 pkgconf-pkg-config x86_64 0:1.8.0-1.fc35 sqlite x86_64 0:3.36.0-3.fc35 sqlite-libs x86_64 0:3.36.0-3.fc35 EOI - cat <=sqlite-devel.info-fetched; + cat <=libsqlite3-devel+sqlite-devel.info-fetched; Installed Packages rpm.x86_64 4.17.1-2.fc35 @updates Available Packages @@ -721,16 +699,16 @@ $* libsqlite3 --install libsqlite3 <>EOE >>EOO manifest: libsqlite3 libsqlite3.manifest - dnf-list: libsqlite3-devel sqlite-devel libsqlite3-devel+sqlite-devel.info - dnf-repoquery-requires: sqlite-devel 3.36.0-3.fc35 x86_64 sqlite-devel.requires - dnf-list: sqlite-devel sqlite-devel.info-fetched - dnf-list-fetched: sqlite-libs sqlite-libs.info-fetched - dnf-list-installed: sqlite-libs sqlite-libs.info-installed + dnf-list: libsqlite3-devel sqlite-devel libsqlite3-devel+sqlite-devel.info + dnf-repoquery-requires-fetched: sqlite-devel 3.36.0-3.fc35 x86_64 sqlite-devel.requires-fetched + dnf-list-fetched: libsqlite3-devel sqlite-devel libsqlite3-devel+sqlite-devel.info-fetched + dnf-list-fetched: sqlite-libs sqlite-libs.info-fetched + dnf-list-installed: sqlite-libs sqlite-libs.info-installed EOI LC_ALL=C dnf list --all --cacheonly --quiet libsqlite3-devel sqlite-devel rpm =sqlite3.info; Installed Packages @@ -773,7 +751,7 @@ : installed : - : In particular test the project name-based deduction of the main + : In particular test the project name-based resolution of the main : package. : ln -s ../sqlite3.manifest ./; @@ -812,7 +790,7 @@ sqlite.i686 3.35.0-1.fc35 fedora sqlite.x86_64 3.35.0-1.fc35 @fedora EOI - cat <=sqlite.info-fetched; + cat <=sqlite3+sqlite.info-fetched; Installed Packages rpm.x86_64 4.17.1-2.fc35 @updates Available Packages @@ -832,12 +810,12 @@ manifest: sqlite3 sqlite3.manifest dnf-list: sqlite3 sqlite sqlite3+sqlite.info - dnf-list-fetched: sqlite sqlite.info-fetched + dnf-list-fetched: sqlite3 sqlite sqlite3+sqlite.info-fetched dnf-list-installed: sqlite sqlite.info-installed EOI LC_ALL=C dnf list --all --cacheonly --quiet sqlite3 sqlite rpm =ncurses-devel.info-fetched; - Installed Packages - rpm.x86_64 4.17.1-2.fc35 @updates - Available Packages - rpm.x86_64 4.17.1-3.fc35 updates - ncurses-devel.i686 6.2-8.20210508.fc35 fedora - ncurses-devel.x86_64 6.2-8.20210508.fc35 fedora - EOI cat <=ncurses-devel.requires-fetched; bash i686 0:5.1.8-3.fc35 bash x86_64 0:5.1.8-3.fc35 @@ -1008,7 +978,6 @@ manifest: libncurses-c++ libncurses-c++.manifest dnf-list: libncurses-devel ncurses-devel libncurses-devel+ncurses-devel.info - dnf-list-fetched: ncurses-devel ncurses-devel.info-fetched dnf-repoquery-requires-fetched: ncurses-devel 6.2-8.20210508.fc35 x86_64 ncurses-devel.requires-fetched dnf-list-fetched: ncurses-libs ncurses-libs.info-fetched dnf-list-fetched: ncurses-c++-libs ncurses-devel ncurses-c++-libs+ncurses-devel.info-fetched @@ -1016,7 +985,7 @@ EOI LC_ALL=C dnf list --all --cacheonly --quiet libncurses-devel ncurses-devel rpm =ncurses-devel.info-fetched; + cat <=libncurses-devel+ncurses-devel.info-fetched; Installed Packages rpm.x86_64 4.17.1-2.fc35 @updates Available Packages @@ -1092,7 +1061,7 @@ manifest: libncurses-c++ libncurses-c++.manifest dnf-list: libncurses-devel ncurses-devel libncurses-devel+ncurses-devel.info - dnf-list-fetched: ncurses-devel ncurses-devel.info-fetched + dnf-list-fetched: libncurses-devel ncurses-devel libncurses-devel+ncurses-devel.info-fetched dnf-repoquery-requires-fetched: ncurses-devel 6.2-8.20210508.fc35 x86_64 ncurses-devel.requires-fetched dnf-list-fetched: ncurses-libs ncurses-libs.info-fetched dnf-list-fetched: ncurses-c++-libs ncurses-devel ncurses-c++-libs+ncurses-devel.info-fetched @@ -1100,7 +1069,7 @@ EOI LC_ALL=C dnf list --all --cacheonly --quiet libncurses-devel ncurses-devel rpm