From 80bbbcd5307d7ae8abacbaa99a2b577f5571f00b Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 17 Jan 2023 11:25:57 +0300 Subject: Implement system_package_names() --- bpkg/package-query.cxx | 22 ++----- bpkg/package-query.hxx | 12 ++-- bpkg/package.hxx | 9 +++ bpkg/pkg-build.cxx | 4 +- bpkg/system-package-manager.cxx | 142 ++++++++++++++++++++++++++++++++++++++++ bpkg/system-package-manager.hxx | 5 +- 6 files changed, 166 insertions(+), 28 deletions(-) diff --git a/bpkg/package-query.cxx b/bpkg/package-query.cxx index 66cb7f0..ea64e71 100644 --- a/bpkg/package-query.cxx +++ b/bpkg/package-query.cxx @@ -315,9 +315,7 @@ namespace bpkg // revisions. // static void - sort_dedup (vector, - lazy_shared_ptr>>& pfs, - bool suppress_older_revisions = false) + sort_dedup (available_packages& pfs, bool suppress_older_revisions = false) { sort (pfs.begin (), pfs.end (), [] (const auto& x, const auto& y) @@ -335,14 +333,12 @@ namespace bpkg pfs.end ()); } - vector, - lazy_shared_ptr>> + available_packages find_available (const linked_databases& dbs, const package_name& name, const optional& c) { - vector, - lazy_shared_ptr>> r; + available_packages r; for (database& db: dbs) { @@ -380,15 +376,13 @@ namespace bpkg return r; } - vector, - lazy_shared_ptr>> + available_packages find_available (const package_name& name, const optional& c, const config_repo_fragments& rfs, bool prereq) { - vector, - lazy_shared_ptr>> r; + available_packages r; for (const auto& dfs: rfs) { @@ -550,8 +544,7 @@ namespace bpkg return make_pair (find_available (options, db, sp), nullptr); } - vector, - lazy_shared_ptr>> + available_packages find_available_all (const linked_databases& dbs, const package_name& name, bool suppress_older_revisions) @@ -591,8 +584,7 @@ namespace bpkg // Collect all the available packages from all the collected databases. // - vector, - lazy_shared_ptr>> r; + available_packages r; for (database& db: all_dbs) { diff --git a/bpkg/package-query.hxx b/bpkg/package-query.hxx index 1fbedd7..ee9b595 100644 --- a/bpkg/package-query.hxx +++ b/bpkg/package-query.hxx @@ -81,8 +81,7 @@ namespace bpkg // Note that we return (loaded) lazy_shared_ptr in order to also convey // the database to which it belongs. // - vector, - lazy_shared_ptr>> + available_packages find_available (const linked_databases&, const package_name&, const optional&); @@ -94,8 +93,8 @@ namespace bpkg using config_repo_fragments = database_map>>; - vector, - lazy_shared_ptr>> + + available_packages find_available (const package_name&, const optional&, const config_repo_fragments&, @@ -182,10 +181,7 @@ namespace bpkg // Note that we return (loaded) lazy_shared_ptr in order to also convey // the database to which it belongs. // - // @@ Add available_packages typedef and use everywhere. - // - vector, - lazy_shared_ptr>> + available_packages find_available_all (const linked_databases&, const package_name&, bool suppress_older_revisions = true); diff --git a/bpkg/package.hxx b/bpkg/package.hxx index 14cd296..6afc624 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -882,6 +882,15 @@ namespace bpkg available_package () = default; }; + // The available packages together with the repository fragments they belong + // to. + // + // Note that lazy_shared_ptr is used to also convey the databases the + // objects belong to. + // + using available_packages = vector, + lazy_shared_ptr>>; + #pragma db view object(available_package) struct available_package_count { diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index 14b0852..61bd1da 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -538,9 +538,7 @@ namespace bpkg else if (!dsys || !wildcard (*dvc)) c = dvc; - vector, - lazy_shared_ptr>> afs ( - find_available (nm, c, rfs)); + available_packages afs (find_available (nm, c, rfs)); if (afs.empty () && dsys && c) afs = find_available (nm, nullopt, rfs); diff --git a/bpkg/system-package-manager.cxx b/bpkg/system-package-manager.cxx index aa9bed8..c170041 100644 --- a/bpkg/system-package-manager.cxx +++ b/bpkg/system-package-manager.cxx @@ -3,8 +3,18 @@ #include +#include // back_inserter + +#include + +#include +#include +#include #include +using namespace std; +using namespace butl; + namespace bpkg { system_package_manager:: @@ -47,4 +57,136 @@ namespace bpkg return r; } + + strings system_package_manager:: + system_package_names (const available_packages& aps, + const string& name_id, + const string& version_id, + const string& like_id) + { + assert (!aps.empty ()); + + // Parse the version id if it is not empty and leave it "0" otherwise. + // + semantic_version vid; + + if (!version_id.empty ()) + try + { + vid = semantic_version (version_id, semantic_version::allow_omit_minor); + } + catch (const invalid_argument& e) + { + fail << "invalid VERSION_ID '" << version_id << "' for " << name_id + << " operating system identification data: " << e; + } + + // Return those [_]-name distribution values of the + // specified available packages, whose component matches the + // specified distribution name and the component (assumed as "0" + // if not present) is less or equal the specified distribution version. + // Suppress the duplicate entries with the same name (so that distribution + // values of the later available package versions are preferred) or value. + // + using values = vector>; + + auto name_vals = [&aps] (const string& n, const semantic_version& v) + { + values r; + for (const auto& a: aps) + { + const shared_ptr& ap (a.first); + + for (const distribution_name_value& nv: ap->distribution_values) + { + const string& nm (nv.name); + + if (nm.size () > 5 && nm.compare (nm.size () - 5, 5, "-name") == 0) + { + string dn (nm, 0, nm.size () - 5); // [_] + size_t p (dn.rfind ('_')); // Version-separating underscore. + + // If '_' separator is present, then make sure that the right-hand + // part looks like a version (not empty and only contains digits + // and dots). + // + if (p != string::npos) + { + if (p != dn.size () - 1) + { + for (size_t i (p); i != dn.size (); ++i) + { + if (!digit (dn[i]) && dn[i] != '.') + { + p = string::npos; + break; + } + } + } + else + p = string::npos; + } + + // Parse the distribution version if present and leave it "0" + // otherwise. + // + semantic_version dv; + if (p != string::npos) + try + { + dv = semantic_version (dn, + p + 1, + semantic_version::allow_omit_minor); + } + catch (const invalid_argument& e) + { + const std::string& s (a.second.database ().string); + + fail << "invalid distribution value " << nm << " for package " + << ap->id.name << ' ' << ap->version + << (!s.empty () ? ' ' + s : empty_string) + << " in repository " << a.second.load ()->location << ": " + << e; + } + + dn.resize (p); + + if (dn == n && + dv <= v && + find_if (r.begin (), r.end (), + [&nm, &nv] (const distribution_name_value& v) + {return v.name == nm || v.value == nv.value;}) == + r.end ()) + { + r.push_back (nv); + } + } + } + } + + return r; + }; + + // Collect the -name values that match the name id and refer + // to the version which is less or equal than the version id. + // + values vs (name_vals (name_id, vid)); + + // If the resulting list is empty and the like id is specified, then + // re-collect but now using the like id and "0" version id instead. + // + if (vs.empty () && !like_id.empty ()) + vs = name_vals (like_id, semantic_version (0, 0, 0)); + + // Return the values of the collected name/values list. + // + strings r; + r.reserve (vs.size ()); + + transform (vs.begin (), vs.end (), + back_inserter (r), + [] (const distribution_name_value& v) {return v.value;}); + + return r; + } } diff --git a/bpkg/system-package-manager.hxx b/bpkg/system-package-manager.hxx index 4f01d1d..131c670 100644 --- a/bpkg/system-package-manager.hxx +++ b/bpkg/system-package-manager.hxx @@ -10,6 +10,7 @@ #include #include +#include #include namespace bpkg @@ -71,8 +72,8 @@ namespace bpkg // something more elaborate, like translate version_id to the like_id's // version and try that). // - static vector - system_package_names (/*const available_packages&,*/ + static strings + system_package_names (const available_packages&, const string& name_id, const string& version_id, const string& like_id); -- cgit v1.1