Blame SOURCES/0003-Add-2-query-filters.patch

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