commit: d22ba91d4adc177551be8b4be95a6fc1f061fc2e Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Sat Nov 1 15:04:46 2014 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Sun Dec 7 23:10:48 2014 +0000 URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=d22ba91d
Add egencache --update-pkg-desc-index action. This adds an egencache --update-pkg-desc-index action which generates a plain-text index of package names, versions, and descriptions. The index can then be used to optimize emerge --search / --searchdesc actions. X-Gentoo-Bug: 525718 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=525718 --- bin/egencache | 38 ++++++++++++++++++-- man/egencache.1 | 4 +++ man/portage.5 | 12 +++++++ pym/portage/cache/index/__init__.py | 2 ++ pym/portage/cache/index/pkg_desc_index.py | 59 +++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 2 deletions(-) diff --git a/bin/egencache b/bin/egencache index e366058..f97432f 100755 --- a/bin/egencache +++ b/bin/egencache @@ -48,6 +48,7 @@ portage._internal_caller = True from portage import os, _encodings, _unicode_encode, _unicode_decode from _emerge.MetadataRegen import MetadataRegen from portage.cache.cache_errors import CacheError, StatCollision +from portage.cache.index.pkg_desc_index import pkg_desc_index_line_format from portage.const import TIMESTAMP_FORMAT from portage.manifest import guessManifestFileType from portage.package.ebuild._parallel_manifest.ManifestScheduler import ManifestScheduler @@ -57,7 +58,7 @@ from portage.util._async.run_main_scheduler import run_main_scheduler from portage.util._eventloop.global_event_loop import global_event_loop from portage import cpv_getkey from portage.dep import Atom, isjustname -from portage.versions import pkgsplit, vercmp +from portage.versions import pkgsplit, vercmp, _pkg_str try: from xml.etree import ElementTree @@ -91,6 +92,9 @@ def parse_args(args): actions.add_argument("--update-changelogs", action="store_true", help="update the ChangeLog files from SCM logs") + actions.add_argument("--update-pkg-desc-index", + action="store_true", + help="update package description index") actions.add_argument("--update-manifests", action="store_true", help="update manifests") @@ -451,6 +455,29 @@ class GenCache(object): if hasattr(trg_cache, '_prune_empty_dirs'): trg_cache._prune_empty_dirs() +class GenPkgDescIndex(object): + def __init__(self, portdb, output_file): + self.returncode = os.EX_OK + self._portdb = portdb + self._output_file = output_file + + def run(self): + + portage.util.ensure_dirs(os.path.dirname(self._output_file)) + f = portage.util.atomic_ofstream(self._output_file, + encoding=_encodings["repo.content"]) + + portdb = self._portdb + for cp in portdb.cp_all(): + pkgs = portdb.cp_list(cp) + if not pkgs: + continue + desc, = portdb.aux_get(pkgs[-1], ["DESCRIPTION"]) + + f.write(pkg_desc_index_line_format(cp, pkgs, desc)) + + f.close() + class GenUseLocalDesc(object): def __init__(self, portdb, output=None, preserve_comments=False): @@ -893,7 +920,8 @@ def egencache_main(args): local_config=False, env=env) if not (options.update or options.update_use_local_desc or - options.update_changelogs or options.update_manifests): + options.update_changelogs or options.update_manifests or + options.update_pkg_desc_index): parser.error('No action specified') return 1 @@ -1057,6 +1085,12 @@ def egencache_main(args): else: ret.append(scheduler.returncode) + if options.update_pkg_desc_index: + gen_index = GenPkgDescIndex(portdb, os.path.join( + repo_config.location, "metadata", "pkg_desc_index")) + gen_index.run() + ret.append(gen_index.returncode) + if options.update_use_local_desc: gen_desc = GenUseLocalDesc(portdb, output=options.uld_output, diff --git a/man/egencache.1 b/man/egencache.1 index f71feb3..3a3197f 100644 --- a/man/egencache.1 +++ b/man/egencache.1 @@ -19,6 +19,10 @@ for the details on package atom syntax. .BR "\-\-update\-changelogs" Update the ChangeLog files from SCM logs (supported only in git repos). .TP +.BR "\-\-update\-pkg\-desc\-index" +Update the package description index which is located at +\fImetadata/pkg_desc_index\fR in the repository. +.TP .BR "\-\-update\-use\-local\-desc" Update the \fIprofiles/use.local.desc\fR file from metadata.xml. .TP diff --git a/man/portage.5 b/man/portage.5 index 4a02c64..2fa699c 100644 --- a/man/portage.5 +++ b/man/portage.5 @@ -76,6 +76,7 @@ user\-defined package sets .BR /usr/portage/metadata/ .nf layout.conf +pkg_desc_index .fi .TP .BR /usr/portage/profiles/ @@ -1165,6 +1166,17 @@ cache\-formats = md5-dict pms profile\-formats = portage-2 .fi .RE +.TP +.BR pkg_desc_index +This is an index of package names, versions, and descriptions which +may be generated by \fBegencache\fR(1) in order to optimize +\fBemerge\fR(1) search actions. + +.I Example: +.nf +sys-apps/sed 4.2 4.2.1 4.2.1-r1 4.2.2: Super-useful stream editor +sys-apps/usleep 0.1: A wrapper for usleep +.fi .RE .TP .BR /usr/portage/profiles/ diff --git a/pym/portage/cache/index/__init__.py b/pym/portage/cache/index/__init__.py new file mode 100644 index 0000000..7cd880e --- /dev/null +++ b/pym/portage/cache/index/__init__.py @@ -0,0 +1,2 @@ +# Copyright 2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 diff --git a/pym/portage/cache/index/pkg_desc_index.py b/pym/portage/cache/index/pkg_desc_index.py new file mode 100644 index 0000000..a2e45da --- /dev/null +++ b/pym/portage/cache/index/pkg_desc_index.py @@ -0,0 +1,59 @@ +# Copyright 2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from __future__ import unicode_literals + +import collections +import sys + +from portage.versions import _pkg_str + +if sys.hexversion >= 0x3000000: + _unicode = str +else: + _unicode = unicode + +pkg_desc_index_node = collections.namedtuple("pkg_desc_index_node", + ["cp", "cpv_list", "desc"]) + +class pkg_node(_unicode): + """ + A minimal package node class. For performance reasons, inputs + are not validated. + """ + + def __init__(self, cp, version, repo=None): + self.__dict__['cp'] = cp + self.__dict__['repo'] = repo + self.__dict__['version'] = version + + def __new__(cls, cp, version, repo=None): + return _unicode.__new__(cls, cp + "-" + version) + + def __setattr__(self, name, value): + raise AttributeError("pkg_node instances are immutable", + self.__class__, name, value) + +def pkg_desc_index_line_format(cp, pkgs, desc): + return "%s %s: %s\n" % (cp, + " ".join(_pkg_str(cpv).version + for cpv in pkgs), desc) + +def pkg_desc_index_line_read(line, repo=None): + + try: + pkgs, desc = line.split(":", 1) + except ValueError: + return None + desc = desc.strip() + + try: + cp, pkgs = pkgs.split(" ", 1) + except ValueError: + return None + + cp_list = [] + for ver in pkgs.split(): + cp_list.append(pkg_node(cp, ver, repo)) + + return pkg_desc_index_node(cp, tuple(cp_list), desc)