From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) by finch.gentoo.org (Postfix) with ESMTP id AAB101389E2 for ; Sun, 7 Dec 2014 23:14:08 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 928B8E0C4D; Sun, 7 Dec 2014 23:14:05 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id DA7AAE0C4A for ; Sun, 7 Dec 2014 23:14:04 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id BFA04340504 for ; Sun, 7 Dec 2014 23:14:03 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 4140BBCFB for ; Sun, 7 Dec 2014 23:14:02 +0000 (UTC) From: "Zac Medico" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Zac Medico" Message-ID: <1417993847.4938b8a8a72e719b394a5c5b0c5030c160091d57.zmedico@gentoo> Subject: [gentoo-commits] proj/portage:master commit in: pym/_emerge/ X-VCS-Repository: proj/portage X-VCS-Files: pym/_emerge/search.py X-VCS-Directories: pym/_emerge/ X-VCS-Committer: zmedico X-VCS-Committer-Name: Zac Medico X-VCS-Revision: 4938b8a8a72e719b394a5c5b0c5030c160091d57 X-VCS-Branch: master Date: Sun, 7 Dec 2014 23:14:02 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 2263e0ba-3232-476e-9943-43b1872a6fde X-Archives-Hash: c6fb1a5254158f523e3f9bd2e31db26d commit: 4938b8a8a72e719b394a5c5b0c5030c160091d57 Author: Zac Medico gentoo org> AuthorDate: Sat Nov 1 15:06:16 2014 +0000 Commit: Zac Medico gentoo 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: