# -*- coding: utf-8 -*- """ @author: Fabio Erculiani @contact: lxnay@sabayon.org @copyright: Fabio Erculiani @license: GPL-2 B{Entropy Infrastructure Toolkit}. """ import sys import os import argparse from entropy.i18n import _ from entropy.output import purple, darkgreen, teal, bold from entropy.cli import print_package_info from eit.commands.descriptor import EitCommandDescriptor from eit.commands.command import EitCommand class EitOwn(EitCommand): """ Main Eit own command. """ NAME = "own" ALIASES = [] ALLOW_UNPRIVILEGED = True def __init__(self, args): EitCommand.__init__(self, args) self._paths = [] self._quiet = False self._verbose = False self._repository_id = None def _get_parser(self): descriptor = EitCommandDescriptor.obtain_descriptor( EitOwn.NAME) parser = argparse.ArgumentParser( description=descriptor.get_description(), formatter_class=argparse.RawDescriptionHelpFormatter, prog="%s %s" % (sys.argv[0], EitOwn.NAME)) parser.add_argument("paths", nargs='+', metavar="", help=_("path")) parser.add_argument("--quiet", "-q", action="store_true", default=self._quiet, help=_('quiet output, for scripting purposes')) parser.add_argument("--verbose", "-v", action="store_true", default=self._verbose, help=_('output more package info')) parser.add_argument("--in", metavar="", help=_("search packages in given repository"), dest="inrepo", default=None) return parser INTRODUCTION = """\ List packages owning given file paths. Paths are searched through all the currently available repositories, even though you can restrict the search to a certain repository by using the *--in* argument. If you want to do the inverse operation (listing files owned by packages), please use *eit files*. """ SEE_ALSO = "eit-files(1)" def man(self): """ Overridden from EitCommand. """ return self._man() def parse(self): parser = self._get_parser() try: nsargs = parser.parse_args(self._args) except IOError: return parser.print_help, [] self._quiet = nsargs.quiet self._quiet = nsargs.quiet self._paths += nsargs.paths self._repository_id = nsargs.inrepo return self._call_unlocked, [self._own, self._repository_id] def _own(self, entropy_server): """ Actual Eit own code. """ if self._repository_id is None: repository_ids = entropy_server.repositories() else: repository_ids = [self._repository_id] exit_st = 1 for repository_id in repository_ids: repo = entropy_server.open_repository(repository_id) sts = self._search(entropy_server, repository_id, repo) if sts != 0: exit_st = 1 return exit_st def _search(self, entropy_server, repository_id, repo): results = {} flatresults = {} reverse_symlink_map = self._settings()['system_rev_symlinks'] for xfile in self._paths: results[xfile] = set() pkg_ids = repo.searchBelongs(xfile) if not pkg_ids: # try real path if possible pkg_ids = repo.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 = repo.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: repo.retrieveAtom(x) for result in results: # print info xfile = result result = results[result] for pkg_id in sorted(result, key = key_sorter): if self._quiet: entropy_server.output( repo.retrieveAtom(pkg_id), level="generic") else: print_package_info(pkg_id, entropy_server, repo, installed_search = True, extended = self._verbose, quiet = self._quiet) if not self._quiet: entropy_server.output( "[%s] %s: %s %s" % ( purple(repository_id), darkgreen(xfile), bold(str(len(result))), teal(_("packages found")))) return 0 EitCommandDescriptor.register( EitCommandDescriptor( EitOwn, EitOwn.NAME, _('search packages owning paths')) )