|
Packit |
6f3914 |
# search.py
|
|
Packit |
6f3914 |
# Search CLI command.
|
|
Packit |
6f3914 |
#
|
|
Packit |
6f3914 |
# Copyright (C) 2012-2016 Red Hat, Inc.
|
|
Packit |
6f3914 |
#
|
|
Packit |
6f3914 |
# This copyrighted material is made available to anyone wishing to use,
|
|
Packit |
6f3914 |
# modify, copy, or redistribute it subject to the terms and conditions of
|
|
Packit |
6f3914 |
# the GNU General Public License v.2, or (at your option) any later version.
|
|
Packit |
6f3914 |
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
Packit |
6f3914 |
# ANY WARRANTY expressed or implied, including the implied warranties of
|
|
Packit |
6f3914 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
Packit |
6f3914 |
# Public License for more details. You should have received a copy of the
|
|
Packit |
6f3914 |
# GNU General Public License along with this program; if not, write to the
|
|
Packit |
6f3914 |
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit |
6f3914 |
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
|
|
Packit |
6f3914 |
# source code or documentation are not subject to the GNU General Public
|
|
Packit |
6f3914 |
# License and may only be used or replicated with the express permission of
|
|
Packit |
6f3914 |
# Red Hat, Inc.
|
|
Packit |
6f3914 |
#
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
from __future__ import absolute_import
|
|
Packit |
6f3914 |
from __future__ import print_function
|
|
Packit |
6f3914 |
from __future__ import unicode_literals
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
import collections
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
from dnf.cli import commands
|
|
Packit |
6f3914 |
from dnf.cli.option_parser import OptionParser
|
|
Packit |
6f3914 |
from dnf.i18n import ucd, _, C_
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
import dnf.i18n
|
|
Packit |
6f3914 |
import dnf.match_counter
|
|
Packit |
6f3914 |
import dnf.util
|
|
Packit |
6f3914 |
import hawkey
|
|
Packit |
6f3914 |
import logging
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
logger = logging.getLogger('dnf')
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
class SearchCommand(commands.Command):
|
|
Packit |
6f3914 |
"""A class containing methods needed by the cli to execute the
|
|
Packit |
6f3914 |
search command.
|
|
Packit |
6f3914 |
"""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
aliases = ('search', 'se')
|
|
Packit |
6f3914 |
summary = _('search package details for the given string')
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
@staticmethod
|
|
Packit |
6f3914 |
def set_argparser(parser):
|
|
Packit |
6f3914 |
parser.add_argument('--all', action='store_true',
|
|
Packit |
6f3914 |
help=_("search also package description and URL"))
|
|
Packit |
6f3914 |
parser.add_argument('query_string', nargs='+', metavar=_('KEYWORD'),
|
|
Packit |
6f3914 |
choices=['all'], default=None,
|
|
Packit |
6f3914 |
action=OptionParser.PkgNarrowCallback,
|
|
Packit |
6f3914 |
help=_("Keyword to search for"))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _search(self, args):
|
|
Packit |
6f3914 |
"""Search for simple text tags in a package object."""
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
TRANS_TBL = collections.OrderedDict((
|
|
Packit |
6f3914 |
('name', C_('long', 'Name')),
|
|
Packit |
6f3914 |
('summary', C_('long', 'Summary')),
|
|
Packit |
6f3914 |
('description', C_('long', 'Description')),
|
|
Packit |
6f3914 |
('url', _('URL')),
|
|
Packit |
6f3914 |
))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _translate_attr(attr):
|
|
Packit |
6f3914 |
try:
|
|
Packit |
6f3914 |
return TRANS_TBL[attr]
|
|
Packit |
6f3914 |
except:
|
|
Packit |
6f3914 |
return attr
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _print_section_header(exact_match, attrs, keys):
|
|
Packit |
6f3914 |
trans_attrs = map(_translate_attr, attrs)
|
|
Packit |
6f3914 |
# TRANSLATORS: separator used between package attributes (eg. Name & Summary & URL)
|
|
Packit |
6f3914 |
trans_attrs_str = _(' & ').join(trans_attrs)
|
|
Packit |
6f3914 |
if exact_match:
|
|
Packit |
6f3914 |
# TRANSLATORS: %s - translated package attributes,
|
|
Packit |
6f3914 |
# %%s - found keys (in listed attributes)
|
|
Packit |
6f3914 |
section_text = _('%s Exactly Matched: %%s') % trans_attrs_str
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
# TRANSLATORS: %s - translated package attributes,
|
|
Packit |
6f3914 |
# %%s - found keys (in listed attributes)
|
|
Packit |
6f3914 |
section_text = _('%s Matched: %%s') % trans_attrs_str
|
|
Packit |
6f3914 |
formatted = self.base.output.fmtSection(section_text % ", ".join(keys))
|
|
Packit |
6f3914 |
print(ucd(formatted))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
counter = dnf.match_counter.MatchCounter()
|
|
Packit |
6f3914 |
for arg in args:
|
|
Packit |
6f3914 |
self._search_counted(counter, 'name', arg)
|
|
Packit |
6f3914 |
self._search_counted(counter, 'summary', arg)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if self.opts.all:
|
|
Packit |
6f3914 |
for arg in args:
|
|
Packit |
6f3914 |
self._search_counted(counter, 'description', arg)
|
|
Packit |
6f3914 |
self._search_counted(counter, 'url', arg)
|
|
Packit |
6f3914 |
else:
|
|
Packit |
6f3914 |
needles = len(args)
|
|
Packit |
6f3914 |
pkgs = list(counter.keys())
|
|
Packit |
6f3914 |
for pkg in pkgs:
|
|
Packit |
6f3914 |
if len(counter.matched_needles(pkg)) != needles:
|
|
Packit |
6f3914 |
del counter[pkg]
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
used_attrs = None
|
|
Packit |
6f3914 |
matched_needles = None
|
|
Packit |
6f3914 |
exact_match = False
|
|
Packit |
6f3914 |
print_section_header = False
|
|
Packit |
6f3914 |
limit = None
|
|
Packit |
6f3914 |
if not self.base.conf.showdupesfromrepos:
|
|
Packit |
6f3914 |
limit = self.base.sack.query().filterm(pkg=counter.keys()).latest()
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
seen = set()
|
|
Packit |
6f3914 |
for pkg in counter.sorted(reverse=True, limit_to=limit):
|
|
Packit |
6f3914 |
if not self.base.conf.showdupesfromrepos:
|
|
Packit |
6f3914 |
if pkg.name + pkg.arch in seen:
|
|
Packit |
6f3914 |
continue
|
|
Packit |
6f3914 |
seen.add(pkg.name + pkg.arch)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if used_attrs != counter.matched_keys(pkg):
|
|
Packit |
6f3914 |
used_attrs = counter.matched_keys(pkg)
|
|
Packit |
6f3914 |
print_section_header = True
|
|
Packit |
6f3914 |
if matched_needles != counter.matched_needles(pkg):
|
|
Packit |
6f3914 |
matched_needles = counter.matched_needles(pkg)
|
|
Packit |
6f3914 |
print_section_header = True
|
|
Packit |
6f3914 |
if exact_match != (counter.matched_haystacks(pkg) == matched_needles):
|
|
Packit |
6f3914 |
exact_match = counter.matched_haystacks(pkg) == matched_needles
|
|
Packit |
6f3914 |
print_section_header = True
|
|
Packit |
6f3914 |
if print_section_header:
|
|
Packit |
6f3914 |
_print_section_header(exact_match, used_attrs, matched_needles)
|
|
Packit |
6f3914 |
print_section_header = False
|
|
Packit |
6f3914 |
self.base.output.matchcallback(pkg, counter.matched_haystacks(pkg), args)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
if len(counter) == 0:
|
|
Packit |
6f3914 |
logger.info(_('No matches found.'))
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def _search_counted(self, counter, attr, needle):
|
|
Packit |
6f3914 |
fdict = {'%s__substr' % attr : needle}
|
|
Packit |
6f3914 |
if dnf.util.is_glob_pattern(needle):
|
|
Packit |
6f3914 |
fdict = {'%s__glob' % attr : needle}
|
|
Packit |
6f3914 |
q = self.base.sack.query().filterm(hawkey.ICASE, **fdict)
|
|
Packit |
6f3914 |
for pkg in q.run():
|
|
Packit |
6f3914 |
counter.add(pkg, attr, needle)
|
|
Packit |
6f3914 |
return counter
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def pre_configure(self):
|
|
Packit Service |
8b25b4 |
if not self.opts.quiet:
|
|
Packit |
6f3914 |
self.cli.redirect_logger(stdout=logging.WARNING, stderr=logging.INFO)
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def configure(self):
|
|
Packit Service |
8b25b4 |
if not self.opts.quiet:
|
|
Packit |
6f3914 |
self.cli.redirect_repo_progress()
|
|
Packit |
6f3914 |
demands = self.cli.demands
|
|
Packit |
6f3914 |
demands.available_repos = True
|
|
Packit |
6f3914 |
demands.fresh_metadata = False
|
|
Packit |
6f3914 |
demands.sack_activation = True
|
|
Packit |
6f3914 |
self.opts.all = self.opts.all or self.opts.query_string_action
|
|
Packit |
6f3914 |
|
|
Packit |
6f3914 |
def run(self):
|
|
Packit |
6f3914 |
logger.debug(_('Searching Packages: '))
|
|
Packit |
6f3914 |
return self._search(self.opts.query_string)
|