diff options
-rw-r--r-- | bpkg/system-package-manager-debian.cxx | 75 | ||||
-rw-r--r-- | bpkg/system-package-manager.hxx | 4 |
2 files changed, 64 insertions, 15 deletions
diff --git a/bpkg/system-package-manager-debian.cxx b/bpkg/system-package-manager-debian.cxx index 1f187c8..2722552 100644 --- a/bpkg/system-package-manager-debian.cxx +++ b/bpkg/system-package-manager-debian.cxx @@ -61,7 +61,7 @@ namespace bpkg reference_wrapper<const string> name; string installed_version; // Empty if none. - string candidate_version; // Empty if none. + string candidate_version; // Empty if none and no installed_version. explicit package_policy (const string& n): name (n) {} @@ -78,6 +78,7 @@ namespace bpkg strings extras; vector<package_policy> package_policies; + size_t package_policies_main = 0; // Size of the main group. explicit system_package_status_debian (string m, string d = {}) @@ -323,6 +324,9 @@ namespace bpkg // package result in multiple corresponding blocks. It looks like // there should be not blank lines but who really knows. // + // Note also that if Installed version is not (none), then the + // Candidate version will be that version of better. + // { auto df = make_diag_frame ( [&pe, &args] (diag_record& dr) @@ -781,21 +785,29 @@ namespace bpkg // Return nullopt if there is a component without installed or candidate // version (which means the package cannot be installed). // - // @@ Maybe we shouldn't be considering extras for partially_installed - // determination? + // The main argument specified the size of the main group. Only components + // from this group are considered for partially_installed determination. // using status_type = package_status::status_type; - auto status = [] (const vector<package_policy>& pps) -> optional<status_type> + auto status = [] (const vector<package_policy>& pps, size_t main) + -> optional<status_type> { bool i (false), u (false); - for (const package_policy& pp: pps) + for (size_t j (0); j != pps.size (); ++j) { - if (pp.installed_version.empty () && pp.candidate_version.empty ()) - return nullopt; + const package_policy& pp (pps[j]); + + if (pp.installed_version.empty ()) + { + if (pp.candidate_version.empty ()) + return nullopt; - (pp.installed_version.empty () ? u : i) = true; + u = true; + } + else if (j < main) + i = true; } return (!u ? package_status::installed : @@ -816,6 +828,7 @@ namespace bpkg if (!ps->doc.empty () && need_doc) pps.emplace_back (ps->doc); if (!ps->dbg.empty () && need_dbg) pps.emplace_back (ps->dbg); if (!ps->common.empty () && false) pps.emplace_back (ps->common); + ps->package_policies_main = pps.size (); for (const string& n: ps->extras) pps.emplace_back (n); apt_cache_policy (pps); @@ -834,10 +847,11 @@ namespace bpkg guess_main (*ps, dev.installed_version); pps.emplace (pps.begin (), ps->main); + ps->package_policies_main++; apt_cache_policy (pps, 1); } - optional<status_type> s (status (pps)); + optional<status_type> s (status (pps, ps->package_policies_main)); if (!s) continue; @@ -900,13 +914,11 @@ namespace bpkg guess_main (*ps, dev.candidate_version); pps.emplace (pps.begin (), ps->main); + ps->package_policies_main++; apt_cache_policy (pps, 1); - - // @@ What if the main version doesn't match dev? Or it must? Or we - // use the candidate_version for main? Fuzzy. } - optional<status_type> s (status (pps)); + optional<status_type> s (status (pps, ps->package_policies_main)); if (!s) { @@ -918,6 +930,13 @@ namespace bpkg const package_policy& main (pps.front ()); + // Note that if we are installing something for this main package, + // then we always go for the candidate version even though it may have + // an installed version that may be good enough (especially if what we + // are installing are extras). The reason is that it may as well not + // be good enough (especially if we are installing the -dev package) + // and there is no straightforward way to change our mind. + // ps->status = *s; ps->system_name = main.name; ps->system_version = main.candidate_version; @@ -964,7 +983,35 @@ namespace bpkg if (r != nullptr) { - // @@ TODO: map system version to bpkg version. + // Map the system version to bpkg version. + // + optional<version> v ( + downstream_package_version (r->system_version, + *aps, + os_release_.name_id, + os_release_.version_id, + os_release_.like_ids)); + + if (!v) + { + // Fallback to using system version as downstream version. + // + try + { + v = version (r->system_version); + } + catch (const invalid_argument& e) + { + fail << "unable to map Debian package " << r->system_name + << " version " << r->system_version << " to bpkg package " + << pn << " version" << + info << "Debian version is not a valid bpkg version: " << e.what () << + info << "consider specifying explicit mapping in " << pn + << " package manifest"; + } + } + + r->version = move (*v); } // Cache. diff --git a/bpkg/system-package-manager.hxx b/bpkg/system-package-manager.hxx index f4ce37e..ad3be36 100644 --- a/bpkg/system-package-manager.hxx +++ b/bpkg/system-package-manager.hxx @@ -209,7 +209,9 @@ namespace bpkg // <distribution>-to-downstream-version values corresponding to // name_id. If none match, then repeat the above process for every // like_ids entry with version_id equal 0. If still no match, then return - // nullopt. + // nullopt (in which case the caller may choose to fallback to the system + // package version or do something more elaborate, like translate + // version_id to the like_id's version and try that). // static optional<version> downstream_package_version (const string& system_version, |