From 93558b6bc99c00b2fd25a3f5231cb46d5d658ecf Mon Sep 17 00:00:00 2001
From: Karsten Hopp <karsten@redhat.com>
Date: May 22 2018 08:50:05 +0000
Subject: [PATCH 1/2] Build an in-memory cache for whatprovides, issue #51


---

diff --git a/src/_fedmod/_depchase.py b/src/_fedmod/_depchase.py
index dc69031..ef73b53 100644
--- a/src/_fedmod/_depchase.py
+++ b/src/_fedmod/_depchase.py
@@ -2,6 +2,7 @@
 
 import collections
 import configparser
+import functools
 import itertools
 import logging
 import os
@@ -78,26 +79,32 @@ def _iterate_all_requires(package):
     for dep in package.lookup_deparray(solv.SOLVABLE_REQUIRES, -1): # requires
         yield dep
 
+
+@functools.lru_cache(maxsize=None)
+def whatprovides(pool, dep):
+    sel = pool.matchdepid(dep, solv.Selection.SELECTION_PROVIDES, solv.SOLVABLE_PROVIDES)
+    if sel.isempty() and str(dep).startswith("/"):
+        # TODO: use Dataiterator for getting filelist
+        sel = pool.select(str(dep), solv.Selection.SELECTION_FILELIST)
+    return set(sel.solvables())
+
+
 def _get_dependency_details(pool, transaction):
     candq = transaction.newpackages()
     result = {}
     for p in candq:
         pkg_details = {}
         for dep in _iterate_all_requires(p):
-            matches = set(s for s in candq if s.matchesdep(solv.SOLVABLE_PROVIDES, dep))
-            if not matches and str(dep).startswith("/"):
-                # Append provides by files
-                # TODO: use Dataiterator for getting filelist
-                matches = set(s for s in pool.select(str(dep), solv.Selection.SELECTION_FILELIST).solvables() if s in candq)
+            matches = whatprovides(pool, dep)
             # It was possible to resolve set, so something is wrong here
             assert matches
+            matches = set(s for s in matches if s in candq)
             # While multiple packages providing the same thing is rare, it's
             # the kind of duplication we want fedmod to be able to help find.
             # So we always return a list here, even though it will normally
             # only have one entry in it
             pkg_details[str(dep)] = sorted(str(m) for m in matches)
         result[str(p)] = pkg_details
-
     return result
 
 def print_transaction(details):

From d212dd2241ed343c35cd3b908df6f49e62db0ae9 Mon Sep 17 00:00:00 2001
From: Karsten Hopp <karsten@redhat.com>
Date: May 23 2018 12:46:17 +0000
Subject: [PATCH 2/2] use local cache (otaylor)


---

diff --git a/src/_fedmod/_depchase.py b/src/_fedmod/_depchase.py
index ef73b53..420ee2d 100644
--- a/src/_fedmod/_depchase.py
+++ b/src/_fedmod/_depchase.py
@@ -2,7 +2,6 @@
 
 import collections
 import configparser
-import functools
 import itertools
 import logging
 import os
@@ -79,32 +78,31 @@ def _iterate_all_requires(package):
     for dep in package.lookup_deparray(solv.SOLVABLE_REQUIRES, -1): # requires
         yield dep
 
-
-@functools.lru_cache(maxsize=None)
-def whatprovides(pool, dep):
-    sel = pool.matchdepid(dep, solv.Selection.SELECTION_PROVIDES, solv.SOLVABLE_PROVIDES)
-    if sel.isempty() and str(dep).startswith("/"):
-        # TODO: use Dataiterator for getting filelist
-        sel = pool.select(str(dep), solv.Selection.SELECTION_FILELIST)
-    return set(sel.solvables())
-
-
 def _get_dependency_details(pool, transaction):
     candq = transaction.newpackages()
     result = {}
+    cache = {}
     for p in candq:
         pkg_details = {}
         for dep in _iterate_all_requires(p):
-            matches = whatprovides(pool, dep)
-            # It was possible to resolve set, so something is wrong here
-            assert matches
-            matches = set(s for s in matches if s in candq)
-            # While multiple packages providing the same thing is rare, it's
-            # the kind of duplication we want fedmod to be able to help find.
-            # So we always return a list here, even though it will normally
-            # only have one entry in it
-            pkg_details[str(dep)] = sorted(str(m) for m in matches)
+            if dep in cache:
+                matches = cache[dep]
+            else:
+                matches = set(s for s in candq if s.matchesdep(solv.SOLVABLE_PROVIDES, dep))
+                if not matches and str(dep).startswith("/"):
+                    # Append provides by files
+                    # TODO: use Dataiterator for getting filelist
+                    matches = set(s for s in pool.select(str(dep), solv.Selection.SELECTION_FILELIST).solvables() if s in candq)
+                # It was possible to resolve set, so something is wrong here
+                assert matches
+                cache[dep] = matches
+                # While multiple packages providing the same thing is rare, it's
+                # the kind of duplication we want fedmod to be able to help find.
+                # So we always return a list here, even though it will normally
+                # only have one entry in it
+                pkg_details[str(dep)] = sorted(str(m) for m in matches)
         result[str(p)] = pkg_details
+
     return result
 
 def print_transaction(details):

