Files
entropy/client/solo/commands/query.py
T
Fabio Erculiani 7771d641e2 [entropy.client] extend Client.calculate_updates() to return critical updates info
calculate_updates() now returns a dictionary containing the same pieces of
information available before. In addition, it now also returns if critical
updates were found and returned by the method itself.
This is particularly useful for enforcing relaxed deps calculation in case
of critical updates (which is what happens now).

This commit breaks the Entropy Client API.
2013-02-24 13:30:28 +00:00

1587 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, []
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=quiet)
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"))
)