1591 lines
55 KiB
Python
1591 lines
55 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
|
|
@author: Fabio Erculiani <lxnay@sabayon.org>
|
|
@contact: lxnay@sabayon.org
|
|
@copyright: Fabio Erculiani
|
|
@license: GPL-2
|
|
|
|
B{Entropy Command Line Client}.
|
|
|
|
"""
|
|
import os
|
|
import sys
|
|
import re
|
|
import argparse
|
|
|
|
from entropy.const import etpConst, const_convert_to_unicode, \
|
|
const_convert_to_rawstring
|
|
from entropy.i18n import _, ngettext
|
|
from entropy.output import darkgreen, darkred, blue, teal, purple, brown, \
|
|
bold
|
|
|
|
import entropy.tools
|
|
|
|
from solo.commands.descriptor import SoloCommandDescriptor
|
|
from solo.commands.command import SoloCommand
|
|
from solo.utils import print_package_info, print_table, get_file_mime, \
|
|
graph_packages, revgraph_packages
|
|
|
|
|
|
class SoloQuery(SoloCommand):
|
|
"""
|
|
Main Solo Query command.
|
|
"""
|
|
|
|
NAME = "query"
|
|
ALIASES = ["q"]
|
|
ALLOW_UNPRIVILEGED = True
|
|
|
|
INTRODUCTION = """\
|
|
Repository query tools.
|
|
"""
|
|
SEE_ALSO = ""
|
|
|
|
def __init__(self, args):
|
|
SoloCommand.__init__(self, args)
|
|
self._nsargs = None
|
|
self._commands = {}
|
|
|
|
def man(self):
|
|
"""
|
|
Overridden from SoloCommand.
|
|
"""
|
|
return self._man()
|
|
|
|
def _get_parser(self):
|
|
"""
|
|
Overridden from SoloCommand.
|
|
"""
|
|
_commands = {}
|
|
|
|
descriptor = SoloCommandDescriptor.obtain_descriptor(
|
|
SoloQuery.NAME)
|
|
parser = argparse.ArgumentParser(
|
|
description=descriptor.get_description(),
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
prog="%s %s" % (sys.argv[0], SoloQuery.NAME))
|
|
|
|
self._setup_verbose_quiet_parser(parser)
|
|
|
|
subparsers = parser.add_subparsers(
|
|
title="action", description=_("repository query tools"),
|
|
help=_("available commands"))
|
|
|
|
belongs_parser = subparsers.add_parser(
|
|
"belongs",
|
|
help=_("resolve what package a file belongs to"))
|
|
belongs_parser.add_argument(
|
|
"files", nargs='+', metavar="<file>",
|
|
help=_("file path"))
|
|
self._setup_verbose_quiet_parser(belongs_parser)
|
|
belongs_parser.set_defaults(func=self._belongs)
|
|
_commands["belongs"] = {}
|
|
|
|
changelog_parser = subparsers.add_parser(
|
|
"changelog",
|
|
help=_("show package changelog"))
|
|
changelog_parser.add_argument(
|
|
"packages", nargs='+', metavar="<package>",
|
|
help=_("package name"))
|
|
self._setup_verbose_quiet_parser(changelog_parser)
|
|
changelog_parser.set_defaults(func=self._changelog)
|
|
_commands["changelog"] = {}
|
|
|
|
revdeps_parser = subparsers.add_parser(
|
|
"revdeps",
|
|
help=_("show reverse dependencies of package"))
|
|
revdeps_parser.add_argument(
|
|
"packages", nargs='+', metavar="<package>",
|
|
help=_("package name"))
|
|
self._setup_verbose_quiet_parser(revdeps_parser)
|
|
revdeps_parser.set_defaults(func=self._revdeps)
|
|
_commands["revdeps"] = {}
|
|
|
|
desc_parser = subparsers.add_parser(
|
|
"description",
|
|
help=_("search package by description"))
|
|
desc_parser.add_argument(
|
|
"descriptions", nargs='+', metavar="<description>",
|
|
help=_("description keyword"))
|
|
desc_parser.set_defaults(func=self._description)
|
|
self._setup_verbose_quiet_parser(desc_parser)
|
|
_commands["description"] = {}
|
|
|
|
files_parser = subparsers.add_parser(
|
|
"files",
|
|
help=_("show files owned by package"))
|
|
files_parser.add_argument(
|
|
"packages", nargs='+', metavar="<package>",
|
|
help=_("package name"))
|
|
files_parser.set_defaults(func=self._files)
|
|
self._setup_verbose_quiet_parser(files_parser)
|
|
_commands["files"] = {}
|
|
|
|
installed_parser = subparsers.add_parser(
|
|
"installed",
|
|
help=_("search installed packages"))
|
|
installed_parser.add_argument(
|
|
"packages", nargs='+', metavar="<package>",
|
|
help=_("package name"))
|
|
installed_parser.set_defaults(func=self._installed)
|
|
self._setup_verbose_quiet_parser(installed_parser)
|
|
_commands["installed"] = {}
|
|
|
|
lic_parser = subparsers.add_parser(
|
|
"license",
|
|
help=_("show packages using the given license"))
|
|
lic_parser.add_argument(
|
|
"licenses", nargs='+', metavar="<license>",
|
|
help=_("license name"))
|
|
lic_parser.set_defaults(func=self._license)
|
|
self._setup_verbose_quiet_parser(lic_parser)
|
|
_commands["license"] = {}
|
|
|
|
list_parser = subparsers.add_parser(
|
|
"list", help=_("list packages"))
|
|
self._setup_verbose_quiet_parser(list_parser)
|
|
list_d = {}
|
|
_commands["list"] = list_d
|
|
|
|
|
|
list_subparsers = list_parser.add_subparsers(
|
|
title="action", description=_("list packages"),
|
|
help=_("available commands"))
|
|
|
|
installed_parser = list_subparsers.add_parser(
|
|
"installed", help=_("list installed packages"))
|
|
installed_parser.add_argument(
|
|
"--by-user", action="store_true", default=False,
|
|
help=_("only list packages installed by user"))
|
|
installed_parser.add_argument(
|
|
"repos", metavar="<repo>", nargs="*",
|
|
help=_("only list packages installed from given repositories"))
|
|
self._setup_verbose_quiet_parser(installed_parser)
|
|
installed_parser.set_defaults(func=self._list_installed)
|
|
list_d["installed"] = {
|
|
"--by-user": {},
|
|
}
|
|
|
|
available_parser = list_subparsers.add_parser(
|
|
"available", help=_("list available packages"))
|
|
available_parser.add_argument(
|
|
"repos", metavar="<repo>", nargs="+",
|
|
help=_("only list packages from given repositories"))
|
|
self._setup_verbose_quiet_parser(available_parser)
|
|
available_parser.set_defaults(func=self._list_available)
|
|
list_d["available"] = {}
|
|
|
|
|
|
mime_parser = subparsers.add_parser(
|
|
"mimetype",
|
|
help=_("show packages able to handle the given mimetype"))
|
|
mime_parser.add_argument(
|
|
"mimes", nargs='+', metavar="<mime>",
|
|
help=_("mimetype"))
|
|
mime_parser.add_argument(
|
|
"--installed", action="store_true", default=False,
|
|
help=_("only show installed packages"))
|
|
self._setup_verbose_quiet_parser(mime_parser)
|
|
mime_parser.set_defaults(func=self._mimetype)
|
|
_commands["mimetype"] = {
|
|
"--installed": {},
|
|
}
|
|
|
|
associate_parser = subparsers.add_parser(
|
|
"associate",
|
|
help=_("associate file to packages able to handle it"))
|
|
associate_parser.add_argument(
|
|
"files", nargs='+', metavar="<file>",
|
|
help=_("file path"))
|
|
associate_parser.add_argument(
|
|
"--installed", action="store_true", default=False,
|
|
help=_("only show installed packages"))
|
|
self._setup_verbose_quiet_parser(associate_parser)
|
|
associate_parser.set_defaults(func=self._associate)
|
|
_commands["associate"] = {
|
|
"--installed": {},
|
|
}
|
|
|
|
needed_parser = subparsers.add_parser(
|
|
"needed",
|
|
help=_("show runtime libraries needed by the given package"))
|
|
needed_parser.add_argument(
|
|
"packages", nargs='+', metavar="<package>",
|
|
help=_("package name"))
|
|
self._setup_verbose_quiet_parser(needed_parser)
|
|
needed_parser.set_defaults(func=self._needed)
|
|
_commands["needed"] = {}
|
|
|
|
orphans_parser = subparsers.add_parser(
|
|
"orphans",
|
|
help=_("search files not belonging to any packages"))
|
|
orphans_parser.set_defaults(func=self._orphans)
|
|
_commands["orphans"] = {}
|
|
|
|
required_parser = subparsers.add_parser(
|
|
"required",
|
|
help=_("show packages requiring the given library name"))
|
|
required_parser.add_argument(
|
|
"libraries", nargs='+', metavar="<library>",
|
|
help=_("library name (example: libdl.so.2)"))
|
|
self._setup_verbose_quiet_parser(required_parser)
|
|
required_parser.set_defaults(func=self._required)
|
|
_commands["required"] = {}
|
|
|
|
sets_parser = subparsers.add_parser(
|
|
"sets",
|
|
help=_("search package sets"))
|
|
sets_parser.add_argument(
|
|
"sets", nargs='*', metavar="<set>",
|
|
help=_("set name"))
|
|
self._setup_verbose_quiet_parser(sets_parser)
|
|
sets_parser.set_defaults(func=self._sets)
|
|
_commands["sets"] = {}
|
|
|
|
slot_parser = subparsers.add_parser(
|
|
"slot",
|
|
help=_("show packages owning the given slot"))
|
|
slot_parser.add_argument(
|
|
"slots", nargs='+', metavar="<slot>",
|
|
help=_("slot name"))
|
|
self._setup_verbose_quiet_parser(slot_parser)
|
|
slot_parser.set_defaults(func=self._slot)
|
|
_commands["slot"] = {}
|
|
|
|
tags_parser = subparsers.add_parser(
|
|
"tags",
|
|
help=_("show packages owning the given tag"))
|
|
tags_parser.add_argument(
|
|
"tags", nargs='+', metavar="<tag>",
|
|
help=_("tag name"))
|
|
self._setup_verbose_quiet_parser(tags_parser)
|
|
tags_parser.set_defaults(func=self._tags)
|
|
_commands["tags"] = {}
|
|
|
|
revs_parser = subparsers.add_parser(
|
|
"revisions",
|
|
help=_("show packages at the given revision"))
|
|
revs_parser.add_argument(
|
|
"revisions", nargs='+', metavar="<revision>",
|
|
help=_("revision name"))
|
|
self._setup_verbose_quiet_parser(revs_parser)
|
|
revs_parser.set_defaults(func=self._revisions)
|
|
_commands["revisions"] = {}
|
|
|
|
graph_parser = subparsers.add_parser(
|
|
"graph",
|
|
help=_("show the direct dependencies graph "
|
|
"for the given package"))
|
|
graph_parser.add_argument(
|
|
"packages", nargs='+', metavar="<package>",
|
|
help=_("package name"))
|
|
graph_parser.add_argument(
|
|
"--complete", action="store_true", default=False,
|
|
help=_("include system packages, build-time dependencies "
|
|
"and circular dependencies information"))
|
|
self._setup_verbose_quiet_parser(graph_parser)
|
|
graph_parser.set_defaults(func=self._graph)
|
|
_commands["graph"] = {
|
|
"--complete": {},
|
|
}
|
|
|
|
revgraph_parser = subparsers.add_parser(
|
|
"revgraph",
|
|
help=_("show the inverse dependencies graph "
|
|
"for the given package"))
|
|
revgraph_parser.add_argument(
|
|
"packages", nargs='+', metavar="<package>",
|
|
help=_("package name"))
|
|
revgraph_parser.add_argument(
|
|
"--complete", action="store_true", default=False,
|
|
help=_("include system packages, build-time dependencies "
|
|
"and circular dependencies information"))
|
|
self._setup_verbose_quiet_parser(revgraph_parser)
|
|
revgraph_parser.set_defaults(func=self._revgraph)
|
|
_commands["revgraph"] = {
|
|
"--complete": {},
|
|
}
|
|
|
|
updates_parser = subparsers.add_parser(
|
|
"updates",
|
|
help=_("show the number of updates available"))
|
|
self._setup_verbose_quiet_parser(updates_parser)
|
|
updates_parser.set_defaults(func=self._updates)
|
|
_commands["updates"] = {}
|
|
|
|
|
|
self._commands = _commands
|
|
return parser
|
|
|
|
def parse(self):
|
|
"""
|
|
Parse command
|
|
"""
|
|
parser = self._get_parser()
|
|
try:
|
|
nsargs = parser.parse_args(self._args)
|
|
except IOError as err:
|
|
sys.stderr.write("%s\n" % (err,))
|
|
return parser.print_help, []
|
|
|
|
# Python 3.3 bug #16308
|
|
if not hasattr(nsargs, "func"):
|
|
return parser.print_help, []
|
|
|
|
self._nsargs = nsargs
|
|
return self._call_locked, [nsargs.func]
|
|
|
|
def bashcomp(self, last_arg):
|
|
"""
|
|
Overridden from SoloCommand.
|
|
"""
|
|
self._get_parser() # this will generate self._commands
|
|
outcome = ["--quiet", "-q", "--verbose", "-v"]
|
|
return self._hierarchical_bashcomp(
|
|
last_arg, outcome, self._commands)
|
|
|
|
def _belongs(self, entropy_client):
|
|
"""
|
|
Solo Query Belongs command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
files = self._nsargs.files
|
|
entropy_repository = entropy_client.installed_repository()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Belong Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
results = {}
|
|
flatresults = {}
|
|
reverse_symlink_map = entropy_client.Settings(
|
|
)['system_rev_symlinks']
|
|
|
|
for xfile in files:
|
|
results[xfile] = set()
|
|
pkg_ids = entropy_repository.searchBelongs(xfile)
|
|
if not pkg_ids:
|
|
# try real path if possible
|
|
pkg_ids = entropy_repository.searchBelongs(
|
|
os.path.realpath(xfile))
|
|
|
|
if not pkg_ids:
|
|
# try using reverse symlink mapping
|
|
for sym_dir in reverse_symlink_map:
|
|
if xfile.startswith(sym_dir):
|
|
for sym_child in reverse_symlink_map[sym_dir]:
|
|
my_file = sym_child+xfile[len(sym_dir):]
|
|
pkg_ids = entropy_repository.searchBelongs(
|
|
my_file)
|
|
if pkg_ids:
|
|
break
|
|
|
|
for pkg_id in pkg_ids:
|
|
if not flatresults.get(pkg_id):
|
|
results[xfile].add(pkg_id)
|
|
flatresults[pkg_id] = True
|
|
|
|
if results:
|
|
key_sorter = lambda x: entropy_repository.retrieveAtom(x)
|
|
for result in results:
|
|
|
|
# print info
|
|
xfile = result
|
|
result = results[result]
|
|
|
|
for pkg_id in sorted(result, key = key_sorter):
|
|
if quiet:
|
|
entropy_client.output(
|
|
entropy_repository.retrieveAtom(pkg_id),
|
|
level="generic")
|
|
else:
|
|
print_package_info(pkg_id, entropy_client,
|
|
entropy_repository, installed_search = True,
|
|
extended = verbose, quiet = quiet)
|
|
if not quiet:
|
|
toc = []
|
|
toc.append(("%s:" % (
|
|
blue(_("Keyword")),), purple(xfile)))
|
|
toc.append((
|
|
"%s:" % (
|
|
blue(_("Found")),), "%s %s" % (
|
|
len(result),
|
|
brown(ngettext("entry", "entries",
|
|
len(result))),)))
|
|
print_table(entropy_client, toc)
|
|
|
|
return 0
|
|
|
|
def _changelog(self, entropy_client):
|
|
"""
|
|
Solo Query Changelog command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
packages = self._nsargs.packages
|
|
entropy_repository = entropy_client.installed_repository()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("ChangeLog Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
for package in packages:
|
|
repo = entropy_repository
|
|
if entropy_repository is not None:
|
|
pkg_id, rc = entropy_repository.atomMatch(package)
|
|
if rc != 0:
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
darkred(_("No match for")),
|
|
bold(package),))
|
|
continue
|
|
else:
|
|
pkg_id, r_id = entropy_client.atom_match(package)
|
|
if pkg_id == -1:
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
darkred(_("No match for")),
|
|
bold(package),))
|
|
continue
|
|
repo = entropy_client.open_repository(r_id)
|
|
|
|
repo_atom = repo.retrieveAtom(pkg_id)
|
|
if quiet:
|
|
entropy_client.output(
|
|
"%s :" % (repo_atom,),
|
|
level="generic")
|
|
else:
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Package")),
|
|
bold(repo_atom),
|
|
),
|
|
header=" "
|
|
)
|
|
|
|
changelog = repo.retrieveChangelog(pkg_id)
|
|
if not changelog or (changelog == "None"):
|
|
# == "None" is a bug, see:
|
|
# 685b865453d552d37ce3a9559f4cefb9a88f8beb
|
|
entropy_client.output(
|
|
_("No ChangeLog available"),
|
|
level="generic")
|
|
else:
|
|
entropy_client.output(changelog, level="generic")
|
|
entropy_client.output("=" * 80)
|
|
|
|
if not quiet:
|
|
# check developer repo mode
|
|
repo_conf = entropy_client.Settings().get_setting_files_data(
|
|
)['repositories']
|
|
dev_repo = entropy_client.Settings(
|
|
)['repositories']['developer_repo']
|
|
if not dev_repo:
|
|
entropy_client.output(
|
|
"%s ! [%s]" % (
|
|
brown(_("Attention: developer-repo "
|
|
"option not enabled")),
|
|
blue(repo_conf),
|
|
),
|
|
level=bold(" !!! "))
|
|
|
|
return 0
|
|
|
|
def _revdeps(self, entropy_client):
|
|
"""
|
|
Solo Query Revdeps command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
packages = self._nsargs.packages
|
|
entropy_repository = entropy_client.installed_repository()
|
|
settings = entropy_client.Settings()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Reverse Dependencies Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
include_build_deps = False
|
|
excluded_dep_types = None
|
|
if include_build_deps:
|
|
excluded_dep_types.append(
|
|
etpConst['dependency_type_ids']['bdepend_id'])
|
|
|
|
for package in packages:
|
|
|
|
result = entropy_repository.atomMatch(package)
|
|
match_in_repo = False
|
|
repo_masked = False
|
|
|
|
if result[0] == -1:
|
|
match_in_repo = True
|
|
result = entropy_client.atom_match(package)
|
|
|
|
if result[0] == -1:
|
|
result = entropy_client.atom_match(
|
|
package, mask_filter = False)
|
|
if result[0] != -1:
|
|
repo_masked = True
|
|
|
|
if result[0] != -1:
|
|
|
|
repo = entropy_repository
|
|
if match_in_repo:
|
|
repo = entropy_client.open_repository(result[1])
|
|
key_sorter = lambda x: repo.retrieveAtom(x)
|
|
|
|
found_atom = repo.retrieveAtom(result[0])
|
|
if repo_masked:
|
|
package_id_masked, idmasking_reason = repo.maskFilter(
|
|
result[0])
|
|
|
|
search_results = repo.retrieveReverseDependencies(
|
|
result[0], exclude_deptypes = excluded_dep_types)
|
|
for pkg_id in sorted(search_results, key = key_sorter):
|
|
print_package_info(pkg_id, entropy_client, repo,
|
|
installed_search = True, strict_output = quiet,
|
|
extended = verbose, quiet = quiet)
|
|
|
|
if not quiet:
|
|
|
|
masking_reason = ''
|
|
if repo_masked:
|
|
masking_reason = ", %s" % (
|
|
settings['pkg_masking_reasons'].get(
|
|
idmasking_reason),
|
|
)
|
|
repo_masked_str = const_convert_to_unicode(
|
|
repo_masked)
|
|
mask_str = bold(repo_masked_str) + masking_reason
|
|
|
|
toc = []
|
|
toc.append(("%s:" % (
|
|
blue(_("Keyword")),), purple(package)))
|
|
toc.append(("%s:" % (
|
|
blue(_("Matched")),), teal(found_atom)))
|
|
toc.append(("%s:" % (
|
|
blue(_("Masked")),), mask_str))
|
|
|
|
if match_in_repo:
|
|
where = "%s %s" % (
|
|
_("from repository"), result[1])
|
|
else:
|
|
where = _("from the installed packages repository")
|
|
|
|
entry_str = ngettext(
|
|
"entry", "entries", len(search_results))
|
|
toc.append(
|
|
("%s:" % (blue(_("Found")),),
|
|
"%s %s %s" % (
|
|
len(search_results),
|
|
brown(entry_str),
|
|
where,)
|
|
))
|
|
print_table(entropy_client, toc)
|
|
|
|
return 0
|
|
|
|
def _description(self, entropy_client):
|
|
"""
|
|
Solo Query Description command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
descriptions = self._nsargs.descriptions
|
|
entropy_repository = entropy_client.installed_repository()
|
|
settings = entropy_client.Settings()
|
|
|
|
found = False
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Description Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
repo_number = 0
|
|
for repo_id in entropy_client.repositories():
|
|
repo_number += 1
|
|
repo_data = settings['repositories']['available'][repo_id]
|
|
|
|
if not quiet:
|
|
header = const_convert_to_unicode(" #") + \
|
|
const_convert_to_unicode(repo_number) + \
|
|
const_convert_to_unicode(" ")
|
|
entropy_client.output(
|
|
"%s" % (
|
|
bold(repo_data['description']),
|
|
),
|
|
header=blue(header))
|
|
|
|
repo = entropy_client.open_repository(repo_id)
|
|
found = self._search_descriptions(
|
|
descriptions, entropy_client, repo, quiet, verbose)
|
|
|
|
if not quiet and not found:
|
|
entropy_client.output(
|
|
darkgreen("%s." % (_("No matches"),)),
|
|
header=darkred(" @@ "))
|
|
|
|
return 0
|
|
|
|
def _search_descriptions(self, descriptions,
|
|
entropy_client, entropy_repository,
|
|
quiet, verbose):
|
|
|
|
key_sorter = lambda x: entropy_repository.retrieveAtom(x)
|
|
found = 0
|
|
for desc in descriptions:
|
|
|
|
pkg_ids = entropy_repository.searchDescription(
|
|
desc, just_id = True)
|
|
if not pkg_ids:
|
|
continue
|
|
|
|
found += len(pkg_ids)
|
|
for pkg_id in sorted(pkg_ids, key = key_sorter):
|
|
if quiet:
|
|
entropy_client.output(
|
|
entropy_repository.retrieveAtom(pkg_id))
|
|
else:
|
|
print_package_info(
|
|
pkg_id, entropy_client,
|
|
entropy_repository,
|
|
extended = verbose, strict_output = False,
|
|
quiet = False)
|
|
|
|
if not quiet:
|
|
toc = []
|
|
toc.append(("%s:" % (blue(_("Keyword")),), purple(desc)))
|
|
toc.append(("%s:" % (blue(_("Found")),), "%s %s" % (
|
|
len(pkg_ids),
|
|
brown(ngettext("entry", "entries", len(pkg_ids))),)))
|
|
print_table(entropy_client, toc)
|
|
|
|
return found
|
|
|
|
def _files(self, entropy_client):
|
|
"""
|
|
Solo Query Files command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
packages = self._nsargs.packages
|
|
entropy_repository = entropy_client.installed_repository()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Files Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
for package in packages:
|
|
|
|
pkg_id, pkg_rc = entropy_repository.atomMatch(package)
|
|
if pkg_id == -1:
|
|
continue
|
|
|
|
atom = entropy_repository.retrieveAtom(pkg_id)
|
|
files = entropy_repository.retrieveContentIter(
|
|
pkg_id, order_by="file")
|
|
files_len = 0
|
|
if quiet:
|
|
for xfile, ftype in files:
|
|
files_len += 1
|
|
entropy_client.output(xfile, level="generic")
|
|
else:
|
|
for xfile, ftype in files:
|
|
files_len += 1
|
|
entropy_client.output(
|
|
brown(xfile),
|
|
header=blue(" ### "))
|
|
|
|
if not quiet:
|
|
toc = []
|
|
toc.append(("%s:" % (blue(_("Package")),), purple(atom)))
|
|
toc.append(("%s:" % (blue(_("Found")),), "%s %s" % (
|
|
files_len, brown(_("files")),)))
|
|
print_table(entropy_client, toc)
|
|
|
|
return 0
|
|
|
|
def _installed(self, entropy_client):
|
|
"""
|
|
Solo Query Installed command.
|
|
Alias of "solo search --installed".
|
|
"""
|
|
from solo.commands.search import SoloSearch
|
|
search = SoloSearch(
|
|
self._nsargs, quiet=self._nsargs.quiet,
|
|
verbose=self._nsargs.verbose,
|
|
installed=True, packages=self._nsargs.packages)
|
|
return search.search(entropy_client)
|
|
|
|
def _license(self, entropy_client):
|
|
"""
|
|
Solo Query License command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
licenses = self._nsargs.licenses
|
|
settings = entropy_client.Settings()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("License Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
found = False
|
|
repo_number = 0
|
|
for repo_id in entropy_client.repositories():
|
|
repo_number += 1
|
|
repo_data = settings['repositories']['available'][repo_id]
|
|
|
|
if not quiet:
|
|
header = const_convert_to_unicode(" #") + \
|
|
const_convert_to_unicode(repo_number) + \
|
|
const_convert_to_unicode(" ")
|
|
entropy_client.output(
|
|
"%s" % (
|
|
bold(repo_data['description']),
|
|
),
|
|
header=blue(header))
|
|
|
|
repo = entropy_client.open_repository(repo_id)
|
|
key_sorter = lambda x: repo.retrieveAtom(x)
|
|
for mylicense in licenses:
|
|
|
|
results = repo.searchLicense(mylicense, just_id = True)
|
|
if not results:
|
|
continue
|
|
|
|
found = True
|
|
for pkg_id in sorted(results, key = key_sorter):
|
|
print_package_info(
|
|
pkg_id, entropy_client, repo,
|
|
extended = verbose,
|
|
strict_output = quiet,
|
|
quiet = quiet)
|
|
|
|
if not quiet:
|
|
res_txt = ngettext("entry", "entries", len(results))
|
|
toc = []
|
|
toc.append(
|
|
("%s:" % (blue(_("Keyword")),),
|
|
purple(mylicense)))
|
|
toc.append(
|
|
("%s:" % (blue(_("Found")),),
|
|
"%s %s" % (len(results), brown(res_txt),)))
|
|
|
|
print_table(entropy_client, toc)
|
|
|
|
if not quiet and not found:
|
|
entropy_client.output(
|
|
darkgreen("%s." % (_("No matches"),)),
|
|
header=darkred(" @@ "))
|
|
|
|
return 0
|
|
|
|
def _list_packages(self, entropy_client, entropy_repository,
|
|
filter_funcs):
|
|
"""
|
|
List packages in repository. The filter functions determine
|
|
what packages shall be listed.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
settings = entropy_client.Settings()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Listing Packages")),
|
|
header=darkred(" @@ "))
|
|
|
|
repository_id = entropy_repository.repository_id()
|
|
pkg_ids = entropy_repository.listAllPackageIds(
|
|
order_by = "atom")
|
|
for filter_func in filter_funcs:
|
|
pkg_mtc = filter(
|
|
filter_func,
|
|
[(x, repository_id) for x in pkg_ids])
|
|
pkg_ids = [x[0] for x in pkg_mtc]
|
|
|
|
for pkg_id in pkg_ids:
|
|
atom = entropy_repository.retrieveAtom(pkg_id)
|
|
if atom is None:
|
|
continue
|
|
if not verbose:
|
|
atom = entropy.dep.dep_getkey(atom)
|
|
|
|
branchinfo = ""
|
|
sizeinfo = ""
|
|
if verbose:
|
|
branch = entropy_repository.retrieveBranch(pkg_id)
|
|
branchinfo = darkgreen(" [") + darkred(branch) + \
|
|
darkgreen("] ")
|
|
mysize = entropy_repository.retrieveOnDiskSize(pkg_id)
|
|
mysize = entropy.tools.bytes_into_human(mysize)
|
|
sizeinfo = brown(" [") + purple(mysize) + brown("]")
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
"%s%s%s %s" % (
|
|
blue(const_convert_to_unicode(pkg_id)),
|
|
sizeinfo,
|
|
branchinfo,
|
|
atom),
|
|
header=darkred("# "))
|
|
else:
|
|
entropy_client.output(atom, level="generic")
|
|
|
|
if not pkg_ids and not quiet:
|
|
entropy_client.output(
|
|
darkgreen("%s." % (_("No matches"),)),
|
|
header=darkred(" @@ "))
|
|
|
|
return 0
|
|
|
|
def _list_installed(self, entropy_client):
|
|
"""
|
|
Solo Query List Installed command.
|
|
"""
|
|
repositories = self._nsargs.repos
|
|
by_user = self._nsargs.by_user
|
|
|
|
def by_user_filter(pkg_match):
|
|
pkg_id, pkg_repo = pkg_match
|
|
repo_db = entropy_client.open_repository(pkg_repo)
|
|
source_id = repo_db.getInstalledPackageSource(
|
|
pkg_id)
|
|
return source_id == etpConst['install_sources']['user']
|
|
|
|
def by_repoid_filter(pkg_match):
|
|
pkg_id, pkg_repo = pkg_match
|
|
repo_db = entropy_client.open_repository(pkg_repo)
|
|
inst_pkg_repo = repo_db.getInstalledPackageRepository(
|
|
pkg_id)
|
|
return inst_pkg_repo in repositories
|
|
|
|
filter_funcs = []
|
|
if by_user:
|
|
filter_funcs.append(by_user_filter)
|
|
if repositories:
|
|
filter_funcs.append(by_repoid_filter)
|
|
|
|
return self._list_packages(entropy_client,
|
|
entropy_client.installed_repository(),
|
|
filter_funcs)
|
|
|
|
def _list_available(self, entropy_client):
|
|
"""
|
|
Solo Query List Available command.
|
|
"""
|
|
repositories = self._nsargs.repos
|
|
quiet = self._nsargs.quiet
|
|
entropy_repositories = entropy_client.repositories()
|
|
exit_st = 1
|
|
|
|
for repository_id in repositories:
|
|
|
|
if repository_id not in entropy_repositories:
|
|
if not quiet:
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
teal(_("Repository is not available")),
|
|
repository_id,),
|
|
header=purple(" !!! "),
|
|
level="warning", importance=1)
|
|
exit_st = 1
|
|
break
|
|
|
|
repo = entropy_client.open_repository(repository_id)
|
|
exit_st = self._list_packages(entropy_client, repo, [])
|
|
if exit_st != 0:
|
|
break
|
|
|
|
return exit_st
|
|
|
|
def _search_mimetype(self, entropy_client, associate=False):
|
|
"""
|
|
Solo Query Mimetype command.
|
|
"""
|
|
installed = self._nsargs.installed
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
settings = entropy_client.Settings()
|
|
inst_repo = entropy_client.installed_repository()
|
|
inst_repo_id = inst_repo.repository_id()
|
|
if associate:
|
|
mimetypes = self._nsargs.files
|
|
else:
|
|
mimetypes = self._nsargs.mimes
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Searching Mimetype")),
|
|
header=darkred(" @@ "))
|
|
|
|
found = False
|
|
for mimetype in mimetypes:
|
|
|
|
if associate:
|
|
# consider mimetype a file path
|
|
mimetype = get_file_mime(mimetype)
|
|
if mimetype is None:
|
|
continue
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
bold(mimetype),
|
|
header=blue(" # "))
|
|
|
|
if installed:
|
|
|
|
matches = [(x, inst_repo_id) for x in \
|
|
entropy_client.search_installed_mimetype(mimetype)]
|
|
else:
|
|
matches = entropy_client.search_available_mimetype(
|
|
mimetype)
|
|
|
|
if matches:
|
|
found = True
|
|
|
|
key_sorter = lambda x: \
|
|
entropy_client.open_repository(x[1]).retrieveAtom(x[0])
|
|
for pkg_id, pkg_repo in sorted(matches, key = key_sorter):
|
|
repo = entropy_client.open_repository(pkg_repo)
|
|
print_package_info(pkg_id, entropy_client, repo,
|
|
extended = verbose, quiet = quiet)
|
|
|
|
if not quiet:
|
|
entry_str = ngettext("entry", "entries", len(matches))
|
|
toc = []
|
|
toc.append(("%s:" % (
|
|
blue(_("Keyword")),), purple(mimetype)))
|
|
toc.append((
|
|
"%s:" % (blue(_("Found")),),
|
|
"%s %s" % (
|
|
len(matches),
|
|
brown(entry_str))
|
|
))
|
|
print_table(entropy_client, toc)
|
|
|
|
if not quiet and not found:
|
|
entropy_client.output(
|
|
darkgreen("%s." % (_("No matches"),)),
|
|
header=darkred(" @@ "))
|
|
|
|
return 0
|
|
|
|
def _mimetype(self, entropy_client):
|
|
"""
|
|
Solo Query Mimetype command.
|
|
"""
|
|
return self._search_mimetype(
|
|
entropy_client,
|
|
associate=False)
|
|
|
|
def _associate(self, entropy_client):
|
|
"""
|
|
Solo Query Associate command.
|
|
"""
|
|
return self._search_mimetype(
|
|
entropy_client,
|
|
associate=True)
|
|
|
|
def _needed(self, entropy_client):
|
|
"""
|
|
Solo Query Needed command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
packages = self._nsargs.packages
|
|
entropy_repository = entropy_client.installed_repository()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Needed Libraries Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
for package in packages:
|
|
pkg_id, pkg_rc = entropy_repository.atomMatch(package)
|
|
if pkg_id == -1:
|
|
continue
|
|
|
|
atom = entropy_repository.retrieveAtom(pkg_id)
|
|
neededs = entropy_repository.retrieveNeeded(
|
|
pkg_id, extended=True)
|
|
for needed, elfclass in neededs:
|
|
if verbose:
|
|
needed = "%s %s" % (needed, elfclass)
|
|
if quiet:
|
|
entropy_client.output(
|
|
needed, level="generic")
|
|
else:
|
|
entropy_client.output(
|
|
darkred(const_convert_to_unicode(needed)),
|
|
header=blue(" # "))
|
|
if not quiet:
|
|
toc = []
|
|
toc.append(("%s:" % (blue(_("Package")),), purple(atom)))
|
|
toc.append(("%s:" % (blue(_("Found")),), "%s %s" % (
|
|
len(neededs), brown(_("libraries")),)))
|
|
print_table(entropy_client, toc)
|
|
|
|
return 0
|
|
|
|
def _orphans(self, entropy_client):
|
|
"""
|
|
Solo Query Orphans command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
settings = entropy_client.Settings()
|
|
entropy_repository = entropy_client.installed_repository()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Orphans Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
reverse_symlink_map = settings['system_rev_symlinks']
|
|
system_dirs_mask = [x for x in settings['system_dirs_mask'] \
|
|
if entropy.tools.is_valid_path(x)]
|
|
# make sure we're all rawstring.
|
|
system_dirs_mask = [const_convert_to_rawstring(x) for x in \
|
|
system_dirs_mask]
|
|
|
|
system_dirs_mask_regexp = []
|
|
for mask in settings['system_dirs_mask']:
|
|
reg_mask = re.compile(mask)
|
|
system_dirs_mask_regexp.append(reg_mask)
|
|
|
|
file_data = set()
|
|
dirs = settings['system_dirs']
|
|
count = 0
|
|
for xdir in dirs:
|
|
# make sure it's bytes (raw encoding
|
|
# as per EntropyRepository.retrieveContent())
|
|
xdir = const_convert_to_rawstring(
|
|
xdir,
|
|
from_enctype=etpConst['conf_raw_encoding'])
|
|
try:
|
|
wd = os.walk(xdir)
|
|
except RuntimeError: # maximum recursion?
|
|
continue
|
|
|
|
for currentdir, subdirs, files in wd:
|
|
found_files = set()
|
|
|
|
for filename in files:
|
|
filename = os.path.join(currentdir, filename)
|
|
|
|
# filter symlinks, broken ones will be reported
|
|
if os.path.islink(filename) and \
|
|
os.path.lexists(filename):
|
|
continue
|
|
|
|
do_cont = False
|
|
for mask in system_dirs_mask:
|
|
if filename.startswith(mask):
|
|
do_cont = True
|
|
break
|
|
if do_cont:
|
|
continue
|
|
|
|
for mask in system_dirs_mask_regexp:
|
|
if mask.match(filename):
|
|
do_cont = True
|
|
break
|
|
|
|
if do_cont:
|
|
continue
|
|
|
|
count += 1
|
|
filename_utf = const_convert_to_unicode(filename)
|
|
if not quiet and ((count == 0) or (count % 500 == 0)):
|
|
count = 0
|
|
if len(filename_utf) > 50:
|
|
fname = filename_utf[:40] + \
|
|
const_convert_to_unicode("...") + \
|
|
filename_utf[-10:]
|
|
else:
|
|
fname = filename_utf
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Analyzing")),
|
|
fname),
|
|
header=darkred(" @@ "),
|
|
back=True)
|
|
found_files.add(filename_utf)
|
|
|
|
if found_files:
|
|
file_data |= found_files
|
|
|
|
totalfiles = len(file_data)
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Analyzed directories")),
|
|
" ".join(settings['system_dirs']),),
|
|
header=darkred(" @@ "))
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Masked directories")),
|
|
" ".join(settings['system_dirs_mask']),),
|
|
header=darkred(" @@ "))
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Number of files collected on the filesystem")),
|
|
bold(const_convert_to_unicode(totalfiles)),),
|
|
header=darkred(" @@ "))
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Now searching among installed packages")),
|
|
bold(const_convert_to_unicode(totalfiles)),),
|
|
header=darkred(" @@ "))
|
|
|
|
|
|
pkg_ids = entropy_repository.listAllPackageIds()
|
|
length = str(len(pkg_ids))
|
|
count = 0
|
|
|
|
def gen_cont(pkg_id):
|
|
for path, ftype in entropy_repository.retrieveContentIter(
|
|
pkg_id):
|
|
# reverse sym
|
|
for sym_dir in reverse_symlink_map:
|
|
if path.startswith(sym_dir):
|
|
for sym_child in reverse_symlink_map[sym_dir]:
|
|
yield sym_child+path[len(sym_dir):]
|
|
# real path also
|
|
dirname_real = os.path.realpath(os.path.dirname(path))
|
|
yield os.path.join(dirname_real, os.path.basename(path))
|
|
yield path
|
|
|
|
for pkg_id in pkg_ids:
|
|
|
|
if not quiet:
|
|
count += 1
|
|
atom = entropy_repository.retrieveAtom(pkg_id)
|
|
if atom is None:
|
|
continue
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Checking")),
|
|
bold(atom),),
|
|
header=darkred(" @@ "),
|
|
count=(count, length),
|
|
back=True)
|
|
|
|
# remove from file_data
|
|
file_data -= set(gen_cont(pkg_id))
|
|
|
|
orphanedfiles = len(file_data)
|
|
fname = "/tmp/entropy-orphans.txt"
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Number of total files")),
|
|
bold(const_convert_to_unicode(totalfiles))
|
|
),
|
|
header=darkred(" @@ "))
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Number of matching files")),
|
|
bold(const_convert_to_unicode(
|
|
totalfiles - orphanedfiles))
|
|
),
|
|
header=darkred(" @@ "))
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Number of orphaned files")),
|
|
bold(const_convert_to_unicode(orphanedfiles))
|
|
),
|
|
header=darkred(" @@ "))
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Writing file to disk")),
|
|
bold(const_convert_to_unicode(fname))
|
|
),
|
|
header=darkred(" @@ "))
|
|
|
|
sizecount = 0
|
|
file_data = list(file_data)
|
|
file_data.sort(reverse = True)
|
|
|
|
with open(fname, "wb") as f_out:
|
|
|
|
for myfile in file_data:
|
|
myfile = const_convert_to_rawstring(myfile)
|
|
mysize = 0
|
|
try:
|
|
mysize += os.stat(myfile).st_size
|
|
except OSError:
|
|
mysize = 0
|
|
sizecount += mysize
|
|
|
|
f_out.write(myfile + const_convert_to_rawstring("\n"))
|
|
if quiet:
|
|
entropy_client.output(myfile, level="generic")
|
|
|
|
f_out.flush()
|
|
|
|
humansize = entropy.tools.bytes_into_human(sizecount)
|
|
if not quiet:
|
|
entropy_client.output(
|
|
"%s: %s" % (
|
|
blue(_("Total space wasted")),
|
|
bold(humansize)),
|
|
header=darkred(" @@ "))
|
|
else:
|
|
entropy_client.output(humansize, level="generic")
|
|
return 0
|
|
|
|
def _required(self, entropy_client):
|
|
"""
|
|
Solo Query Required command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
libraries = self._nsargs.libraries
|
|
entropy_repository = entropy_client.installed_repository()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Required Packages Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
key_sorter = lambda x: entropy_repository.retrieveAtom(x)
|
|
for library in libraries:
|
|
results = entropy_repository.searchNeeded(
|
|
library, like = True)
|
|
|
|
for pkg_id in sorted(results, key = key_sorter):
|
|
print_package_info(
|
|
pkg_id, entropy_client, entropy_repository,
|
|
installed_search=True, strict_output=True,
|
|
extended=verbose, quiet=quiet)
|
|
|
|
if not quiet:
|
|
toc = []
|
|
entity_str = ngettext("package", "packages", len(results))
|
|
toc.append((
|
|
"%s:" % (blue(_("Library")),),
|
|
purple(library)))
|
|
toc.append((
|
|
"%s:" % (
|
|
blue(_("Found")),),
|
|
"%s %s" % (
|
|
len(results),
|
|
brown(entity_str),)))
|
|
print_table(entropy_client, toc)
|
|
|
|
return 0
|
|
|
|
def _sets(self, entropy_client):
|
|
"""
|
|
Solo Query Sets command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
items = self._nsargs.sets
|
|
if not items:
|
|
items.append("*")
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Package Set Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
sets = entropy_client.Sets()
|
|
|
|
count = 0
|
|
found = False
|
|
for item in items:
|
|
results = sets.search(item)
|
|
key_sorter = lambda x: x[1]
|
|
for repo, set_name, set_data in sorted(
|
|
results, key = key_sorter):
|
|
count += 1
|
|
found = True
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
bold(set_name),
|
|
header=blue(" #%d " % (count,)))
|
|
|
|
elements = sorted(set_data)
|
|
for element in elements:
|
|
entropy_client.output(
|
|
brown(element),
|
|
header=" ")
|
|
else:
|
|
for element in sorted(set_data):
|
|
entropy_client.output(
|
|
element, level="generic")
|
|
|
|
if not quiet:
|
|
toc = []
|
|
entity_str = ngettext("entry", "entries", count)
|
|
toc.append(("%s:" % (blue(_("Keyword")),), purple(item)))
|
|
toc.append(("%s:" % (blue(_("Found")),), "%s %s" % (
|
|
count, brown(entity_str),)))
|
|
print_table(entropy_client, toc)
|
|
|
|
if not quiet and not found:
|
|
entropy_client.output(
|
|
darkgreen("%s." % (_("No matches"),)),
|
|
header=darkred(" @@ "))
|
|
|
|
return 0
|
|
|
|
def _slot(self, entropy_client):
|
|
"""
|
|
Solo Query Slot command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
slots = self._nsargs.slots
|
|
settings = entropy_client.Settings()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Slot Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
found = False
|
|
# search inside each available database
|
|
repo_number = 0
|
|
|
|
for repo_id in entropy_client.repositories():
|
|
repo_number += 1
|
|
repo_data = settings['repositories']['available'][repo_id]
|
|
|
|
if not quiet:
|
|
header = const_convert_to_unicode(" #") + \
|
|
const_convert_to_unicode(repo_number) + \
|
|
const_convert_to_unicode(" ")
|
|
entropy_client.output(
|
|
"%s" % (
|
|
bold(repo_data['description']),
|
|
),
|
|
header=blue(header))
|
|
|
|
repo = entropy_client.open_repository(repo_id)
|
|
for slot in slots:
|
|
|
|
results = repo.searchSlotted(slot, just_id = True)
|
|
key_sorter = lambda x: repo.retrieveAtom(x)
|
|
for pkg_id in sorted(results, key = key_sorter):
|
|
found = True
|
|
print_package_info(pkg_id, entropy_client, repo,
|
|
extended=verbose, strict_output=quiet,
|
|
quiet=quiet)
|
|
|
|
if not quiet:
|
|
toc = []
|
|
entity_str = ngettext("entry", "entries", len(results))
|
|
toc.append((
|
|
"%s:" % (blue(_("Keyword")),),
|
|
purple(slot)))
|
|
toc.append((
|
|
"%s:" % (blue(_("Found")),),
|
|
"%s %s" % (
|
|
len(results),
|
|
brown(entity_str),)))
|
|
print_table(entropy_client, toc)
|
|
|
|
if not quiet and not found:
|
|
entropy_client.output(
|
|
darkgreen("%s." % (_("No matches"),)),
|
|
header=darkred(" @@ "))
|
|
|
|
return 0
|
|
|
|
def _tags(self, entropy_client):
|
|
"""
|
|
Solo Query Tags command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
tags = self._nsargs.tags
|
|
settings = entropy_client.Settings()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Tag Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
found = False
|
|
# search inside each available database
|
|
repo_number = 0
|
|
|
|
for repo_id in entropy_client.repositories():
|
|
repo_number += 1
|
|
repo_data = settings['repositories']['available'][repo_id]
|
|
|
|
if not quiet:
|
|
header = const_convert_to_unicode(" #") + \
|
|
const_convert_to_unicode(repo_number) + \
|
|
const_convert_to_unicode(" ")
|
|
entropy_client.output(
|
|
"%s" % (
|
|
bold(repo_data['description']),
|
|
),
|
|
header=blue(header))
|
|
|
|
repo = entropy_client.open_repository(repo_id)
|
|
for tag in tags:
|
|
|
|
results = repo.searchTaggedPackages(tag)
|
|
key_sorter = lambda x: repo.retrieveAtom(x)
|
|
for pkg_id in sorted(results, key = key_sorter):
|
|
found = True
|
|
print_package_info(pkg_id, entropy_client, repo,
|
|
extended=verbose, strict_output=quiet,
|
|
quiet=quiet)
|
|
|
|
if not quiet:
|
|
toc = []
|
|
entity_str = ngettext("entry", "entries", len(results))
|
|
toc.append((
|
|
"%s:" % (blue(_("Keyword")),),
|
|
purple(tag)))
|
|
toc.append((
|
|
"%s:" % (blue(_("Found")),),
|
|
"%s %s" % (
|
|
len(results),
|
|
brown(entity_str),)))
|
|
print_table(entropy_client, toc)
|
|
|
|
if not quiet and not found:
|
|
entropy_client.output(
|
|
darkgreen("%s." % (_("No matches"),)),
|
|
header=darkred(" @@ "))
|
|
return 0
|
|
|
|
def _revisions(self, entropy_client):
|
|
"""
|
|
Solo Query Revisions command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
revisions = self._nsargs.revisions
|
|
settings = entropy_client.Settings()
|
|
entropy_repository = entropy_client.installed_repository()
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
darkgreen(_("Revision Search")),
|
|
header=darkred(" @@ "))
|
|
|
|
found = False
|
|
key_sorter = lambda x: entropy_repository.retrieveAtom(x)
|
|
|
|
for revision in revisions:
|
|
results = entropy_repository.searchRevisionedPackages(
|
|
revision)
|
|
|
|
found = True
|
|
for pkg_id in sorted(results, key = key_sorter):
|
|
print_package_info(
|
|
pkg_id, entropy_client, entropy_repository,
|
|
extended=verbose, strict_output=quiet,
|
|
installed_search=True, quiet=quiet)
|
|
|
|
if not quiet:
|
|
toc = []
|
|
entity_str = ngettext("entry", "entries", len(results))
|
|
toc.append((
|
|
"%s:" % (blue(_("Keyword")),),
|
|
purple(revision)))
|
|
toc.append((
|
|
"%s:" % (blue(_("Found")),),
|
|
"%s %s" % (
|
|
len(results),
|
|
brown(entity_str),)))
|
|
print_table(entropy_client, toc)
|
|
|
|
if not quiet and not found:
|
|
entropy_client.output(
|
|
darkgreen("%s." % (_("No matches"),)),
|
|
header=darkred(" @@ "))
|
|
return 0
|
|
|
|
def _graph(self, entropy_client):
|
|
"""
|
|
Solo Query Graph command.
|
|
"""
|
|
packages = self._nsargs.packages
|
|
quiet = self._nsargs.quiet
|
|
complete = self._nsargs.complete
|
|
|
|
return graph_packages(
|
|
packages, entropy_client,
|
|
complete=complete, quiet=quiet)
|
|
|
|
def _revgraph(self, entropy_client):
|
|
"""
|
|
Solo Query Revgraph command.
|
|
"""
|
|
packages = self._nsargs.packages
|
|
quiet = self._nsargs.quiet
|
|
complete = self._nsargs.complete
|
|
|
|
return revgraph_packages(
|
|
packages, entropy_client,
|
|
complete=complete, quiet=quiet)
|
|
|
|
def _updates(self, entropy_client):
|
|
"""
|
|
Solo Query Updates command.
|
|
"""
|
|
quiet = self._nsargs.quiet
|
|
verbose = self._nsargs.verbose
|
|
|
|
if not quiet:
|
|
entropy_client.output(
|
|
brown(_("Available Updates")),
|
|
header=darkred(" @@ "))
|
|
|
|
outcome = entropy_client.calculate_updates(quiet=True)
|
|
update, remove = outcome['update'], outcome['remove']
|
|
fine, critical_f = outcome['fine'], outcome['critical_found']
|
|
|
|
if quiet:
|
|
entropy_client.output(
|
|
"%d" % (len(update),),
|
|
level="generic")
|
|
return 0
|
|
|
|
toc = []
|
|
toc.append((
|
|
darkgreen(_("Packages to update:")),
|
|
bold(const_convert_to_unicode(len(update)))))
|
|
toc.append((
|
|
darkred(_("Packages to remove:")),
|
|
bold(const_convert_to_unicode(len(remove)))))
|
|
if verbose:
|
|
toc.append((
|
|
blue(_("Packages already up-to-date:")),
|
|
bold(const_convert_to_unicode(len(fine)))))
|
|
toc.append((
|
|
purple(_("Critical updates found:")),
|
|
teal(const_convert_to_unicode(str(critical_f)))))
|
|
print_table(entropy_client, toc)
|
|
|
|
return 0
|
|
|
|
|
|
SoloCommandDescriptor.register(
|
|
SoloCommandDescriptor(
|
|
SoloQuery,
|
|
SoloQuery.NAME,
|
|
_("repository query tools"))
|
|
)
|