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

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