commit:     4938b8a8a72e719b394a5c5b0c5030c160091d57
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Sat Nov  1 15:06:16 2014 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Sun Dec  7 23:10:47 2014 +0000
URL:        
http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=4938b8a8

Display emerge search results incrementally (412471)

This makes emerge --search / --searchdesc display individual search
results as soon as they become available. A search._iter_search method
is split out from the search.execute method, and the search.output
method operates on that. The spinner is now disabled, but the spinner
code remains, in case we later decide to enable it optionally.

X-Gentoo-Bug: 412471
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=412471

---
 pym/_emerge/search.py | 120 +++++++++++++++++++++++++++++---------------------
 1 file changed, 71 insertions(+), 49 deletions(-)

diff --git a/pym/_emerge/search.py b/pym/_emerge/search.py
index 4b0fd9f..e51d206 100644
--- a/pym/_emerge/search.py
+++ b/pym/_emerge/search.py
@@ -1,8 +1,6 @@
 # Copyright 1999-2014 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
-from __future__ import print_function
-
 import re
 import portage
 from portage import os
@@ -30,10 +28,12 @@ class search(object):
                The list of available and installed packages is created at 
object instantiation.
                This makes successive searches faster."""
                self.settings = root_config.settings
-               self.vartree = root_config.trees["vartree"]
-               self.spinner = spinner
                self.verbose = verbose
                self.searchdesc = searchdesc
+               self.searchkey = None
+               # Disable the spinner since search results are displayed
+               # incrementally.
+               self.spinner = None
                self.root_config = root_config
                self.setconfig = root_config.setconfig
                self.matches = {"pkg" : []}
@@ -53,6 +53,7 @@ class search(object):
 
                self._dbs.append(vardb)
                self._portdb = portdb
+               self._vardb = vardb
 
        def _spinner_update(self):
                if self.spinner:
@@ -97,7 +98,7 @@ class search(object):
                return {}
 
        def _visible(self, db, cpv, metadata):
-               installed = db is self.vartree.dbapi
+               installed = db is self._vardb
                built = installed or db is not self._portdb
                pkg_type = "ebuild"
                if installed:
@@ -171,8 +172,11 @@ class search(object):
 
        def execute(self,searchkey):
                """Performs the search for the supplied search key"""
+               self.searchkey = searchkey
+
+       def _iter_search(self):
+
                match_category = 0
-               self.searchkey=searchkey
                self.packagematches = []
                if self.searchdesc:
                        self.searchdesc=1
@@ -180,7 +184,7 @@ class search(object):
                else:
                        self.searchdesc=0
                        self.matches = {"pkg":[], "set":[]}
-               print("Searching...   ", end=' ')
+               writemsg_stdout("Searching...\n\n", noiselevel=-1)
 
                regexsearch = False
                if self.searchkey.startswith('%'):
@@ -202,29 +206,28 @@ class search(object):
                        else:
                                match_string  = package.split("/")[-1]
 
-                       masked=0
                        if self.searchre.search(match_string):
-                               if not self._xmatch("match-visible", package):
-                                       masked=1
-                               self.matches["pkg"].append([package,masked])
+                               yield ("pkg", package)
                        elif self.searchdesc: # DESCRIPTION searching
-                               full_package = 
self._xmatch("bestmatch-visible", package)
+                               # Use match-all to avoid an expensive 
visibility check,
+                               # since the visibility check can be avoided 
entirely
+                               # when the DESCRIPTION does not match.
+                               full_package = self._xmatch("match-all", 
package)
                                if not full_package:
-                                       #no match found; we don't want to query 
description
-                                       full_package = portage.best(
-                                               self._xmatch("match-all", 
package))
-                                       if not full_package:
-                                               continue
-                                       else:
-                                               masked=1
+                                       continue
+                               full_package = full_package[-1]
                                try:
                                        full_desc = self._aux_get(
                                                full_package, 
["DESCRIPTION"])[0]
                                except KeyError:
-                                       print("emerge: search: aux_get() 
failed, skipping")
+                                       portage.writemsg(
+                                               "emerge: search: aux_get() 
failed, skipping\n",
+                                               noiselevel=-1)
                                        continue
-                               if self.searchre.search(full_desc):
-                                       
self.matches["desc"].append([full_package,masked])
+                               if not self.searchre.search(full_desc):
+                                       continue
+
+                               yield ("desc", package)
 
                self.sdict = self.setconfig.getSets()
                for setname in self.sdict:
@@ -235,51 +238,56 @@ class search(object):
                                match_string = setname.split("/")[-1]
                        
                        if self.searchre.search(match_string):
-                               self.matches["set"].append([setname, False])
+                               yield ("set", setname)
                        elif self.searchdesc:
                                if self.searchre.search(
                                        
self.sdict[setname].getMetadata("DESCRIPTION")):
-                                       self.matches["set"].append([setname, 
False])
-                       
-               self.mlen=0
-               for mtype in self.matches:
-                       self.matches[mtype].sort()
-                       self.mlen += len(self.matches[mtype])
+                                       yield ("set", setname)
 
        def addCP(self, cp):
                if not self._xmatch("match-all", cp):
                        return
-               masked = 0
-               if not self._xmatch("bestmatch-visible", cp):
-                       masked = 1
-               self.matches["pkg"].append([cp, masked])
+               self.matches["pkg"].append(cp)
                self.mlen += 1
 
        def output(self):
                """Outputs the results of the search."""
-               msg = []
+
+               class msg(object):
+                       @staticmethod
+                       def append(msg):
+                               writemsg_stdout(msg, noiselevel=-1)
+
                msg.append("\b\b  \n[ Results for search key : " + \
                        bold(self.searchkey) + " ]\n")
-               msg.append("[ Applications found : " + \
-                       bold(str(self.mlen)) + " ]\n\n")
-               vardb = self.vartree.dbapi
+               vardb = self._vardb
                metadata_keys = set(Package.metadata_keys)
                metadata_keys.update(["DESCRIPTION", "HOMEPAGE", "LICENSE", 
"SRC_URI"])
                metadata_keys = tuple(metadata_keys)
-               for mtype in self.matches:
-                       for match,masked in self.matches[mtype]:
+
+               if self.searchkey is None:
+                       # Handle results added via addCP
+                       addCP_matches = []
+                       for mytype, match in self.matches.items():
+                               addCP_matches.append(mytype, match)
+                       iterator = iter(addCP_matches)
+
+               else:
+                       # Do a normal search
+                       iterator = self._iter_search()
+
+               for mtype, match in iterator:
+                               self.mlen += 1
+                               masked = False
                                full_package = None
-                               if mtype == "pkg":
+                               if mtype in ("pkg", "desc"):
                                        full_package = self._xmatch(
                                                "bestmatch-visible", match)
                                        if not full_package:
-                                               #no match found; we don't want 
to query description
-                                               masked=1
-                                               full_package = portage.best(
-                                                       
self._xmatch("match-all",match))
-                               elif mtype == "desc":
-                                       full_package = match
-                                       match        = portage.cpv_getkey(match)
+                                               masked = True
+                                               full_package = 
self._xmatch("match-all", match)
+                                               if full_package:
+                                                       full_package = 
full_package[-1]
                                elif mtype == "set":
                                        msg.append(green("*") + "  " + 
bold(match) + "\n")
                                        if self.verbose:
@@ -367,12 +375,26 @@ class search(object):
                                                        + "   " + desc + "\n")
                                                msg.append("      " + 
darkgreen("License:") + \
                                                        "       " + license + 
"\n\n")
-               writemsg_stdout(''.join(msg), noiselevel=-1)
+
+               msg.append("[ Applications found : " + \
+                       bold(str(self.mlen)) + " ]\n\n")
+
+               # This method can be called multiple times, so
+               # reset the match count for the next call. Don't
+               # reset it at the beginning of this method, since
+               # that would lose modfications from the addCP
+               # method.
+               self.mlen = 0
+
        #
        # private interface
        #
        def getInstallationStatus(self,package):
-               installed_package = self.vartree.dep_bestmatch(package)
+               installed_package = self._vardb.match(package)
+               if installed_package:
+                       installed_package = installed_package[-1]
+               else:
+                       installed_package = ""
                result = ""
                version = 
self.getVersion(installed_package,search.VERSION_RELEASE)
                if len(version) > 0:

Reply via email to