From b36464f01ffadab9ca49eed1a06ab480626b28c2 Mon Sep 17 00:00:00 2001 From: Jaroslav Mracek Date: Mon, 16 Dec 2019 10:10:51 +0100 Subject: [PATCH 1/2] Add new query filter upgrades_by_priority It returns upgrades only from repository with the lowest priority. --- libdnf/hy-types.h | 3 +- libdnf/sack/query.cpp | 60 ++++++++++++++++++++++++++++++++++ python/hawkey/hawkeymodule.cpp | 1 + python/hawkey/query-py.cpp | 5 ++- 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/libdnf/hy-types.h b/libdnf/hy-types.h index b34988d89..380a0d5cc 100644 --- a/libdnf/hy-types.h +++ b/libdnf/hy-types.h @@ -97,7 +97,8 @@ enum _hy_key_name_e { * @brief Use for strings of whole NEVRA (missing epoch is handled as epoch 0) * Allowed compare types - only HY_EQ or HY_NEQ */ - HY_PKG_NEVRA_STRICT = 36 + HY_PKG_NEVRA_STRICT = 36, + HY_PKG_UPGRADES_BY_PRIORITY = 37, }; enum _hy_comparison_type_e { diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp index eea0ce1b1..ecfd3110f 100644 --- a/libdnf/sack/query.cpp +++ b/libdnf/sack/query.cpp @@ -148,6 +148,13 @@ NameArchSolvableComparator(const Solvable * first, const Solvable * second) return first->arch < second->arch; } +static bool +NamePrioritySolvableKey(const Solvable * first, const Solvable * second) +{ + if (first->name != second->name) + return first->name < second->name; + return first->repo->priority > second->repo->priority; +} static bool match_type_num(int keyname) { @@ -158,6 +165,7 @@ match_type_num(int keyname) { case HY_PKG_LATEST_PER_ARCH: case HY_PKG_UPGRADABLE: case HY_PKG_UPGRADES: + case HY_PKG_UPGRADES_BY_PRIORITY: case HY_PKG_DOWNGRADABLE: case HY_PKG_DOWNGRADES: return true; @@ -690,6 +698,7 @@ class Query::Impl { void filterAdvisory(const Filter & f, Map *m, int keyname); void filterLatest(const Filter & f, Map *m); void filterUpdown(const Filter & f, Map *m); + void filterUpdownByPriority(const Filter & f, Map *m); void filterUpdownAble(const Filter &f, Map *m); void filterDataiterator(const Filter & f, Map *m); int filterUnneededOrSafeToRemove(const Swdb &swdb, bool debug_solver, bool safeToRemove); @@ -1732,6 +1741,54 @@ Query::Impl::filterUpdown(const Filter & f, Map *m) } } +void +Query::Impl::filterUpdownByPriority(const Filter & f, Map *m) +{ + Pool *pool = dnf_sack_get_pool(sack); + auto resultPset = result.get(); + + dnf_sack_make_provides_ready(sack); + auto repoInstalled = pool->installed; + if (!repoInstalled) { + return; + } + + for (auto match_in : f.getMatches()) { + if (match_in.num == 0) + continue; + std::vector upgradeCandidates; + upgradeCandidates.reserve(resultPset->size()); + Id id = -1; + while ((id = resultPset->next(id)) != -1) { + Solvable *candidate = pool_id2solvable(pool, id); + if (candidate->repo == repoInstalled) + continue; + upgradeCandidates.push_back(candidate); + } + if (upgradeCandidates.empty()) { + continue; + } + std::sort(upgradeCandidates.begin(), upgradeCandidates.end(), NamePrioritySolvableKey); + Id name = 0; + int priority = 0; + for (auto * candidate: upgradeCandidates) { + if (name != candidate->name) { + name = candidate->name; + priority = candidate->repo->priority; + id = pool_solvable2id(pool, candidate); + if (what_upgrades(pool, id) > 0) { + MAPSET(m, id); + } + } else if (priority == candidate->repo->priority) { + id = pool_solvable2id(pool, candidate); + if (what_upgrades(pool, id) > 0) { + MAPSET(m, id); + } + } + } + } +} + void Query::Impl::filterUpdownAble(const Filter &f, Map *m) { @@ -1949,6 +2006,9 @@ Query::Impl::apply() case HY_PKG_UPGRADES: filterUpdown(f, &m); break; + case HY_PKG_UPGRADES_BY_PRIORITY: + filterUpdownByPriority(f, &m); + break; default: filterDataiterator(f, &m); } diff --git a/python/hawkey/hawkeymodule.cpp b/python/hawkey/hawkeymodule.cpp index 0f05f46c2..4351e96e1 100644 --- a/python/hawkey/hawkeymodule.cpp +++ b/python/hawkey/hawkeymodule.cpp @@ -281,6 +281,7 @@ PYCOMP_MOD_INIT(_hawkey) PyModule_AddIntConstant(m, "PKG_SUPPLEMENTS", HY_PKG_SUPPLEMENTS); PyModule_AddIntConstant(m, "PKG_UPGRADABLE", HY_PKG_UPGRADABLE); PyModule_AddIntConstant(m, "PKG_UPGRADES", HY_PKG_UPGRADES); + PyModule_AddIntConstant(m, "PKG_UPGRADES_BY_PRIORITY", HY_PKG_UPGRADES_BY_PRIORITY); PyModule_AddIntConstant(m, "PKG_URL", HY_PKG_URL); PyModule_AddIntConstant(m, "PKG_VERSION", HY_PKG_VERSION); diff --git a/python/hawkey/query-py.cpp b/python/hawkey/query-py.cpp index 116ffa1b0..286e306d3 100644 --- a/python/hawkey/query-py.cpp +++ b/python/hawkey/query-py.cpp @@ -89,6 +89,7 @@ static const int keyname_int_matches[] = { HY_PKG_SUPPLEMENTS, HY_PKG_UPGRADABLE, HY_PKG_UPGRADES, + HY_PKG_UPGRADES_BY_PRIORITY, HY_PKG_URL, HY_PKG_VERSION }; @@ -128,6 +129,7 @@ static const char * const keyname_char_matches[] = { "supplements", "upgradable", "upgrades", + "upgrades_by_priority", "url", "version", NULL @@ -273,7 +275,8 @@ filter_add(HyQuery query, key_t keyname, int cmp_type, PyObject *match) keyname == HY_PKG_LATEST_PER_ARCH || keyname == HY_PKG_LATEST || keyname == HY_PKG_UPGRADABLE || - keyname == HY_PKG_UPGRADES) { + keyname == HY_PKG_UPGRADES || + keyname == HY_PKG_UPGRADES_BY_PRIORITY) { int val; if (!PyInt_Check(match) || cmp_type != HY_EQ) { From 4b83ae692f90d0d3cbc377c7f93bdb7e99e477ef Mon Sep 17 00:00:00 2001 From: Jaroslav Mracek Date: Mon, 16 Dec 2019 18:34:37 +0100 Subject: [PATCH 2/2] Add new query filter obsoletes_by_priority --- libdnf/hy-types.h | 1 + libdnf/sack/query.cpp | 65 ++++++++++++++++++++++++++++++++++ python/hawkey/hawkeymodule.cpp | 1 + python/hawkey/query-py.cpp | 5 ++- 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/libdnf/hy-types.h b/libdnf/hy-types.h index 380a0d5cc..e96459c25 100644 --- a/libdnf/hy-types.h +++ b/libdnf/hy-types.h @@ -99,6 +99,7 @@ enum _hy_key_name_e { */ HY_PKG_NEVRA_STRICT = 36, HY_PKG_UPGRADES_BY_PRIORITY = 37, + HY_PKG_OBSOLETES_BY_PRIORITY = 38, }; enum _hy_comparison_type_e { diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp index ecfd3110f..6e9e4715f 100644 --- a/libdnf/sack/query.cpp +++ b/libdnf/sack/query.cpp @@ -179,6 +179,7 @@ match_type_pkg(int keyname) { switch (keyname) { case HY_PKG: case HY_PKG_OBSOLETES: + case HY_PKG_OBSOLETES_BY_PRIORITY: return true; default: return false; @@ -692,6 +693,7 @@ class Query::Impl { void filterArch(const Filter & f, Map *m); void filterSourcerpm(const Filter & f, Map *m); void filterObsoletes(const Filter & f, Map *m); + void filterObsoletesByPriority(const Filter & f, Map *m); void filterProvidesReldep(const Filter & f, Map *m); void filterReponame(const Filter & f, Map *m); void filterLocation(const Filter & f, Map *m); @@ -702,6 +704,7 @@ class Query::Impl { void filterUpdownAble(const Filter &f, Map *m); void filterDataiterator(const Filter & f, Map *m); int filterUnneededOrSafeToRemove(const Swdb &swdb, bool debug_solver, bool safeToRemove); + void obsoletesByPriority(Pool * pool, Solvable * candidate, Map * m, const Map * target, int obsprovides); bool isGlob(const std::vector &matches) const; }; @@ -1469,6 +1472,65 @@ Query::Impl::filterObsoletes(const Filter & f, Map *m) } } +void +Query::Impl::obsoletesByPriority(Pool * pool, Solvable * candidate, Map * m, const Map * target, int obsprovides) +{ + if (!candidate->repo) + return; + for (Id *r_id = candidate->repo->idarraydata + candidate->obsoletes; *r_id; ++r_id) { + Id r, rr; + FOR_PROVIDES(r, rr, *r_id) { + if (!MAPTST(target, r)) + continue; + assert(r != SYSTEMSOLVABLE); + Solvable *so = pool_id2solvable(pool, r); + if (!obsprovides && !pool_match_nevr(pool, so, *r_id)) + continue; /* only matching pkg names */ + MAPSET(m, pool_solvable2id(pool, candidate)); + break; + } + } +} + +void +Query::Impl::filterObsoletesByPriority(const Filter & f, Map *m) +{ + Pool *pool = dnf_sack_get_pool(sack); + int obsprovides = pool_get_flag(pool, POOL_FLAG_OBSOLETEUSESPROVIDES); + Map *target; + auto resultPset = result.get(); + + assert(f.getMatchType() == _HY_PKG); + assert(f.getMatches().size() == 1); + target = dnf_packageset_get_map(f.getMatches()[0].pset); + dnf_sack_make_provides_ready(sack); + std::vector obsoleteCandidates; + obsoleteCandidates.reserve(resultPset->size()); + Id id = -1; + while ((id = resultPset->next(id)) != -1) { + Solvable *candidate = pool_id2solvable(pool, id); + obsoleteCandidates.push_back(candidate); + } + if (obsoleteCandidates.empty()) { + return; + } + std::sort(obsoleteCandidates.begin(), obsoleteCandidates.end(), NamePrioritySolvableKey); + Id name = 0; + int priority = 0; + for (auto * candidate: obsoleteCandidates) { + if (candidate->repo == pool->installed) { + obsoletesByPriority(pool, candidate, m, target, obsprovides); + } + if (name != candidate->name) { + name = candidate->name; + priority = candidate->repo->priority; + obsoletesByPriority(pool, candidate, m, target, obsprovides); + } else if (priority == candidate->repo->priority) { + obsoletesByPriority(pool, candidate, m, target, obsprovides); + } + } +} + void Query::Impl::filterProvidesReldep(const Filter & f, Map *m) { @@ -1969,6 +2031,9 @@ Query::Impl::apply() filterObsoletes(f, &m); } break; + case HY_PKG_OBSOLETES_BY_PRIORITY: + filterObsoletesByPriority(f, &m); + break; case HY_PKG_PROVIDES: assert(f.getMatchType() == _HY_RELDEP); filterProvidesReldep(f, &m); diff --git a/python/hawkey/hawkeymodule.cpp b/python/hawkey/hawkeymodule.cpp index 4351e96e1..82d05e2cb 100644 --- a/python/hawkey/hawkeymodule.cpp +++ b/python/hawkey/hawkeymodule.cpp @@ -270,6 +270,7 @@ PYCOMP_MOD_INIT(_hawkey) PyModule_AddIntConstant(m, "PKG_NEVRA", HY_PKG_NEVRA); PyModule_AddIntConstant(m, "PKG_NEVRA_STRICT", HY_PKG_NEVRA_STRICT); PyModule_AddIntConstant(m, "PKG_OBSOLETES", HY_PKG_OBSOLETES); + PyModule_AddIntConstant(m, "PKG_OBSOLETES_BY_PRIORITY", HY_PKG_OBSOLETES_BY_PRIORITY); PyModule_AddIntConstant(m, "PKG_PROVIDES", HY_PKG_PROVIDES); PyModule_AddIntConstant(m, "PKG_RECOMMENDS", HY_PKG_RECOMMENDS); PyModule_AddIntConstant(m, "PKG_RELEASE", HY_PKG_RELEASE); diff --git a/python/hawkey/query-py.cpp b/python/hawkey/query-py.cpp index 286e306d3..9178a6d0c 100644 --- a/python/hawkey/query-py.cpp +++ b/python/hawkey/query-py.cpp @@ -78,6 +78,7 @@ static const int keyname_int_matches[] = { HY_PKG_NEVRA, HY_PKG_NEVRA_STRICT, HY_PKG_OBSOLETES, + HY_PKG_OBSOLETES_BY_PRIORITY, HY_PKG_PROVIDES, HY_PKG_RECOMMENDS, HY_PKG_RELEASE, @@ -118,6 +119,7 @@ static const char * const keyname_char_matches[] = { "nevra", "nevra_strict", "obsoletes", + "obsoletes_by_priority", "provides", "recommends", "release", @@ -342,7 +344,8 @@ filter_add(HyQuery query, key_t keyname, int cmp_type, PyObject *match) // match is a sequence now: switch (keyname) { case HY_PKG: - case HY_PKG_OBSOLETES: { + case HY_PKG_OBSOLETES: + case HY_PKG_OBSOLETES_BY_PRIORITY: { // It could be a sequence of packages or reldep/strings. Lets try packages first. auto pset = pyseq_to_packageset(match, query->getSack()); if (!pset) {