| #!/usr/bin/python -bO |
| # Copyright 1999-2014 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| from __future__ import print_function, unicode_literals |
| |
| import signal |
| import sys |
| # This block ensures that ^C interrupts are handled quietly. |
| try: |
| |
| def exithandler(signum, _frame): |
| signal.signal(signal.SIGINT, signal.SIG_IGN) |
| signal.signal(signal.SIGTERM, signal.SIG_IGN) |
| sys.exit(128 + signum) |
| |
| signal.signal(signal.SIGINT, exithandler) |
| signal.signal(signal.SIGTERM, exithandler) |
| |
| except KeyboardInterrupt: |
| sys.exit(128 + signal.SIGINT) |
| |
| import os |
| import types |
| |
| # Avoid sandbox violations after python upgrade. |
| pym_path = os.path.join(os.path.dirname( |
| os.path.dirname(os.path.realpath(__file__))), "pym") |
| if os.environ.get("SANDBOX_ON") == "1": |
| sandbox_write = os.environ.get("SANDBOX_WRITE", "").split(":") |
| if pym_path not in sandbox_write: |
| sandbox_write.append(pym_path) |
| os.environ["SANDBOX_WRITE"] = \ |
| ":".join(filter(None, sandbox_write)) |
| del sandbox_write |
| |
| sys.path.insert(0, pym_path) |
| import portage |
| portage._internal_caller = True |
| from portage import os |
| from portage.eapi import eapi_has_repo_deps |
| from portage.util import writemsg, writemsg_stdout |
| from portage.util._argparse import ArgumentParser |
| portage.proxy.lazyimport.lazyimport(globals(), |
| 're', |
| 'subprocess', |
| '_emerge.Package:Package', |
| '_emerge.RootConfig:RootConfig', |
| '_emerge.is_valid_package_atom:insert_category_into_atom', |
| 'portage.dbapi._expand_new_virt:expand_new_virt', |
| 'portage._sets.base:InternalPackageSet', |
| 'portage.xml.metadata:MetaDataXML' |
| ) |
| |
| def eval_atom_use(atom): |
| if 'USE' in os.environ: |
| use = frozenset(os.environ['USE'].split()) |
| atom = atom.evaluate_conditionals(use) |
| return atom |
| |
| def uses_eroot(function): |
| function.uses_eroot = True |
| return function |
| |
| #----------------------------------------------------------------------------- |
| # |
| # To add functionality to this tool, add a function below. |
| # |
| # The format for functions is: |
| # |
| # def function(argv): |
| # """<list of options for this function> |
| # <description of the function> |
| # """ |
| # <code> |
| # |
| # "argv" is an array of the command line parameters provided after the command. |
| # |
| # Make sure you document the function in the right format. The documentation |
| # is used to display help on the function. |
| # |
| # You do not need to add the function to any lists, this tool is introspective, |
| # and will automaticly add a command by the same name as the function! |
| # |
| |
| @uses_eroot |
| def has_version(argv): |
| """<eroot> <category/package> |
| Return code 0 if it's available, 1 otherwise. |
| """ |
| if (len(argv) < 2): |
| print("ERROR: insufficient parameters!") |
| return 3 |
| |
| warnings = [] |
| |
| allow_repo = atom_validate_strict is False or eapi_has_repo_deps(eapi) |
| try: |
| atom = portage.dep.Atom(argv[1], allow_repo=allow_repo) |
| except portage.exception.InvalidAtom: |
| if atom_validate_strict: |
| portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1], |
| noiselevel=-1) |
| return 2 |
| else: |
| atom = argv[1] |
| else: |
| if atom_validate_strict: |
| try: |
| atom = portage.dep.Atom(argv[1], allow_repo=allow_repo, eapi=eapi) |
| except portage.exception.InvalidAtom as e: |
| warnings.append("QA Notice: %s: %s" % ('has_version', e)) |
| atom = eval_atom_use(atom) |
| |
| if warnings: |
| elog('eqawarn', warnings) |
| |
| try: |
| mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom) |
| if mylist: |
| return 0 |
| else: |
| return 1 |
| except KeyError: |
| return 1 |
| except portage.exception.InvalidAtom: |
| portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1], |
| noiselevel=-1) |
| return 2 |
| |
| |
| @uses_eroot |
| def best_version(argv): |
| """<eroot> <category/package> |
| Returns category/package-version (without .ebuild). |
| """ |
| if (len(argv) < 2): |
| print("ERROR: insufficient parameters!") |
| return 3 |
| |
| warnings = [] |
| |
| allow_repo = atom_validate_strict is False or eapi_has_repo_deps(eapi) |
| try: |
| atom = portage.dep.Atom(argv[1], allow_repo=allow_repo) |
| except portage.exception.InvalidAtom: |
| if atom_validate_strict: |
| portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1], |
| noiselevel=-1) |
| return 2 |
| else: |
| atom = argv[1] |
| else: |
| if atom_validate_strict: |
| try: |
| atom = portage.dep.Atom(argv[1], allow_repo=allow_repo, eapi=eapi) |
| except portage.exception.InvalidAtom as e: |
| warnings.append("QA Notice: %s: %s" % ('best_version', e)) |
| atom = eval_atom_use(atom) |
| |
| if warnings: |
| elog('eqawarn', warnings) |
| |
| try: |
| mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom) |
| print(portage.best(mylist)) |
| except KeyError: |
| return 1 |
| |
| |
| @uses_eroot |
| def mass_best_version(argv): |
| """<eroot> [<category/package>]+ |
| Returns category/package-version (without .ebuild). |
| """ |
| if (len(argv) < 2): |
| print("ERROR: insufficient parameters!") |
| return 2 |
| try: |
| for pack in argv[1:]: |
| mylist = portage.db[argv[0]]['vartree'].dbapi.match(pack) |
| print('%s:%s' % (pack, portage.best(mylist))) |
| except KeyError: |
| return 1 |
| |
| |
| @uses_eroot |
| def metadata(argv): |
| if (len(argv) < 4): |
| print('ERROR: insufficient parameters!', file=sys.stderr) |
| return 2 |
| |
| eroot, pkgtype, pkgspec = argv[0:3] |
| metakeys = argv[3:] |
| type_map = { |
| 'ebuild': 'porttree', |
| 'binary': 'bintree', |
| 'installed': 'vartree' |
| } |
| if pkgtype not in type_map: |
| print("Unrecognized package type: '%s'" % pkgtype, file=sys.stderr) |
| return 1 |
| trees = portage.db |
| repo = portage.dep.dep_getrepo(pkgspec) |
| pkgspec = portage.dep.remove_slot(pkgspec) |
| try: |
| values = trees[eroot][type_map[pkgtype]].dbapi.aux_get( |
| pkgspec, metakeys, myrepo=repo) |
| writemsg_stdout(''.join('%s\n' % x for x in values), noiselevel=-1) |
| except KeyError: |
| print("Package not found: '%s'" % pkgspec, file=sys.stderr) |
| return 1 |
| |
| metadata.__doc__ = """ |
| <eroot> <pkgtype> <category/package> [<key>]+ |
| Returns metadata values for the specified package. |
| Available keys: %s |
| """ % ','.join(sorted(x for x in portage.auxdbkeys \ |
| if not x.startswith('UNUSED_'))) |
| |
| |
| @uses_eroot |
| def contents(argv): |
| """<eroot> <category/package> |
| List the files that are installed for a given package, with |
| one file listed on each line. All file names will begin with |
| <eroot>. |
| """ |
| if len(argv) != 2: |
| print("ERROR: expected 2 parameters, got %d!" % len(argv)) |
| return 2 |
| |
| root, cpv = argv |
| vartree = portage.db[root]["vartree"] |
| if not vartree.dbapi.cpv_exists(cpv): |
| sys.stderr.write("Package not found: '%s'\n" % cpv) |
| return 1 |
| cat, pkg = portage.catsplit(cpv) |
| db = portage.dblink(cat, pkg, root, vartree.settings, |
| treetype="vartree", vartree=vartree) |
| writemsg_stdout(''.join('%s\n' % x for x in sorted(db.getcontents())), |
| noiselevel=-1) |
| |
| |
| @uses_eroot |
| def owners(argv): |
| """<eroot> [<filename>]+ |
| Given a list of files, print the packages that own the files and which |
| files belong to each package. Files owned by a package are listed on |
| the lines below it, indented by a single tab character (\\t). All file |
| paths must either start with <eroot> or be a basename alone. |
| Returns 1 if no owners could be found, and 0 otherwise. |
| """ |
| if len(argv) < 2: |
| sys.stderr.write("ERROR: insufficient parameters!\n") |
| sys.stderr.flush() |
| return 2 |
| |
| eroot = argv[0] |
| vardb = portage.db[eroot]["vartree"].dbapi |
| root = portage.settings['ROOT'] |
| |
| cwd = None |
| try: |
| cwd = os.getcwd() |
| except OSError: |
| pass |
| |
| files = [] |
| orphan_abs_paths = set() |
| orphan_basenames = set() |
| for f in argv[1:]: |
| f = portage.normalize_path(f) |
| is_basename = os.sep not in f |
| if not is_basename and f[:1] != os.sep: |
| if cwd is None: |
| sys.stderr.write("ERROR: cwd does not exist!\n") |
| sys.stderr.flush() |
| return 2 |
| f = os.path.join(cwd, f) |
| f = portage.normalize_path(f) |
| if not is_basename and not f.startswith(eroot): |
| sys.stderr.write("ERROR: file paths must begin with <eroot>!\n") |
| sys.stderr.flush() |
| return 2 |
| if is_basename: |
| files.append(f) |
| orphan_basenames.add(f) |
| else: |
| files.append(f[len(root)-1:]) |
| orphan_abs_paths.add(f) |
| |
| owners = vardb._owners.get_owners(files) |
| |
| msg = [] |
| for pkg, owned_files in owners.items(): |
| cpv = pkg.mycpv |
| msg.append("%s\n" % cpv) |
| for f in sorted(owned_files): |
| f_abs = os.path.join(root, f.lstrip(os.path.sep)) |
| msg.append("\t%s\n" % (f_abs,)) |
| orphan_abs_paths.discard(f_abs) |
| if orphan_basenames: |
| orphan_basenames.discard(os.path.basename(f_abs)) |
| |
| writemsg_stdout(''.join(msg), noiselevel=-1) |
| |
| if orphan_abs_paths or orphan_basenames: |
| orphans = [] |
| orphans.extend(orphan_abs_paths) |
| orphans.extend(orphan_basenames) |
| orphans.sort() |
| msg = [] |
| msg.append("None of the installed packages claim these files:\n") |
| for f in orphans: |
| msg.append("\t%s\n" % (f,)) |
| sys.stderr.write("".join(msg)) |
| sys.stderr.flush() |
| |
| if owners: |
| return 0 |
| return 1 |
| |
| |
| @uses_eroot |
| def is_protected(argv): |
| """<eroot> <filename> |
| Given a single filename, return code 0 if it's protected, 1 otherwise. |
| The filename must begin with <eroot>. |
| """ |
| if len(argv) != 2: |
| sys.stderr.write("ERROR: expected 2 parameters, got %d!\n" % len(argv)) |
| sys.stderr.flush() |
| return 2 |
| |
| root, filename = argv |
| |
| err = sys.stderr |
| cwd = None |
| try: |
| cwd = os.getcwd() |
| except OSError: |
| pass |
| |
| f = portage.normalize_path(filename) |
| if not f.startswith(os.path.sep): |
| if cwd is None: |
| err.write("ERROR: cwd does not exist!\n") |
| err.flush() |
| return 2 |
| f = os.path.join(cwd, f) |
| f = portage.normalize_path(f) |
| |
| if not f.startswith(root): |
| err.write("ERROR: file paths must begin with <eroot>!\n") |
| err.flush() |
| return 2 |
| |
| from portage.util import ConfigProtect |
| |
| settings = portage.settings |
| protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", "")) |
| protect_mask = portage.util.shlex_split( |
| settings.get("CONFIG_PROTECT_MASK", "")) |
| protect_obj = ConfigProtect(root, protect, protect_mask) |
| |
| if protect_obj.isprotected(f): |
| return 0 |
| return 1 |
| |
| |
| @uses_eroot |
| def filter_protected(argv): |
| """<eroot> |
| Read filenames from stdin and write them to stdout if they are protected. |
| All filenames are delimited by \\n and must begin with <eroot>. |
| """ |
| if len(argv) != 1: |
| sys.stderr.write("ERROR: expected 1 parameter, got %d!\n" % len(argv)) |
| sys.stderr.flush() |
| return 2 |
| |
| root, = argv |
| out = sys.stdout |
| err = sys.stderr |
| cwd = None |
| try: |
| cwd = os.getcwd() |
| except OSError: |
| pass |
| |
| from portage.util import ConfigProtect |
| |
| settings = portage.settings |
| protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", "")) |
| protect_mask = portage.util.shlex_split( |
| settings.get("CONFIG_PROTECT_MASK", "")) |
| protect_obj = ConfigProtect(root, protect, protect_mask) |
| |
| errors = 0 |
| |
| for line in sys.stdin: |
| filename = line.rstrip("\n") |
| f = portage.normalize_path(filename) |
| if not f.startswith(os.path.sep): |
| if cwd is None: |
| err.write("ERROR: cwd does not exist!\n") |
| err.flush() |
| errors += 1 |
| continue |
| f = os.path.join(cwd, f) |
| f = portage.normalize_path(f) |
| |
| if not f.startswith(root): |
| err.write("ERROR: file paths must begin with <eroot>!\n") |
| err.flush() |
| errors += 1 |
| continue |
| |
| if protect_obj.isprotected(f): |
| out.write("%s\n" % filename) |
| out.flush() |
| |
| if errors: |
| return 2 |
| |
| return 0 |
| |
| |
| @uses_eroot |
| def best_visible(argv): |
| """<eroot> [pkgtype] <atom> |
| Returns category/package-version (without .ebuild). |
| The pkgtype argument defaults to "ebuild" if unspecified, |
| otherwise it must be one of ebuild, binary, or installed. |
| """ |
| if (len(argv) < 2): |
| writemsg("ERROR: insufficient parameters!\n", noiselevel=-1) |
| return 2 |
| |
| pkgtype = "ebuild" |
| if len(argv) > 2: |
| pkgtype = argv[1] |
| atom = argv[2] |
| else: |
| atom = argv[1] |
| |
| type_map = { |
| "ebuild":"porttree", |
| "binary":"bintree", |
| "installed":"vartree"} |
| |
| if pkgtype not in type_map: |
| writemsg("Unrecognized package type: '%s'\n" % pkgtype, |
| noiselevel=-1) |
| return 2 |
| |
| eroot = argv[0] |
| db = portage.db[eroot][type_map[pkgtype]].dbapi |
| |
| try: |
| atom = portage.dep_expand(atom, mydb=db, settings=portage.settings) |
| except portage.exception.InvalidAtom: |
| writemsg("ERROR: Invalid atom: '%s'\n" % atom, |
| noiselevel=-1) |
| return 2 |
| |
| root_config = RootConfig(portage.settings, portage.db[eroot], None) |
| |
| if hasattr(db, "xmatch"): |
| cpv_list = db.xmatch("match-all-cpv-only", atom) |
| else: |
| cpv_list = db.match(atom) |
| |
| if cpv_list: |
| # reversed, for descending order |
| cpv_list.reverse() |
| # verify match, since the atom may match the package |
| # for a given cpv from one repo but not another, and |
| # we can use match-all-cpv-only to avoid redundant |
| # metadata access. |
| atom_set = InternalPackageSet(initial_atoms=(atom,)) |
| |
| if atom.repo is None and hasattr(db, "getRepositories"): |
| repo_list = db.getRepositories() |
| else: |
| repo_list = [atom.repo] |
| |
| for cpv in cpv_list: |
| for repo in repo_list: |
| try: |
| metadata = dict(zip(Package.metadata_keys, |
| db.aux_get(cpv, Package.metadata_keys, myrepo=repo))) |
| except KeyError: |
| continue |
| pkg = Package(built=(pkgtype != "ebuild"), cpv=cpv, |
| installed=(pkgtype=="installed"), metadata=metadata, |
| root_config=root_config, type_name=pkgtype) |
| if not atom_set.findAtomForPackage(pkg): |
| continue |
| |
| if pkg.visible: |
| writemsg_stdout("%s\n" % (pkg.cpv,), noiselevel=-1) |
| return os.EX_OK |
| |
| # No package found, write out an empty line. |
| writemsg_stdout("\n", noiselevel=-1) |
| |
| return 1 |
| |
| |
| @uses_eroot |
| def mass_best_visible(argv): |
| """<eroot> [<type>] [<category/package>]+ |
| Returns category/package-version (without .ebuild). |
| The pkgtype argument defaults to "ebuild" if unspecified, |
| otherwise it must be one of ebuild, binary, or installed. |
| """ |
| type_map = { |
| "ebuild":"porttree", |
| "binary":"bintree", |
| "installed":"vartree"} |
| |
| if (len(argv) < 2): |
| print("ERROR: insufficient parameters!") |
| return 2 |
| try: |
| root = argv.pop(0) |
| pkgtype = "ebuild" |
| if argv[0] in type_map: |
| pkgtype = argv.pop(0) |
| for pack in argv: |
| writemsg_stdout("%s:" % pack, noiselevel=-1) |
| best_visible([root, pkgtype, pack]) |
| except KeyError: |
| return 1 |
| |
| |
| @uses_eroot |
| def all_best_visible(argv): |
| """<eroot> |
| Returns all best_visible packages (without .ebuild). |
| """ |
| if len(argv) < 1: |
| sys.stderr.write("ERROR: insufficient parameters!\n") |
| sys.stderr.flush() |
| return 2 |
| |
| #print portage.db[argv[0]]["porttree"].dbapi.cp_all() |
| for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all(): |
| mybest=portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg)) |
| if mybest: |
| print(mybest) |
| |
| |
| @uses_eroot |
| def match(argv): |
| """<eroot> <atom> |
| Returns a \\n separated list of category/package-version. |
| When given an empty string, all installed packages will |
| be listed. |
| """ |
| if len(argv) != 2: |
| print("ERROR: expected 2 parameters, got %d!" % len(argv)) |
| return 2 |
| root, atom = argv |
| if not atom: |
| atom = "*/*" |
| |
| vardb = portage.db[root]["vartree"].dbapi |
| try: |
| atom = portage.dep.Atom(atom, allow_wildcard=True, allow_repo=True) |
| except portage.exception.InvalidAtom: |
| # maybe it's valid but missing category |
| atom = portage.dep_expand(atom, mydb=vardb, settings=vardb.settings) |
| |
| if atom.extended_syntax: |
| if atom == "*/*": |
| results = vardb.cpv_all() |
| else: |
| results = [] |
| require_metadata = atom.slot or atom.repo |
| for cpv in vardb.cpv_all(): |
| |
| if not portage.match_from_list(atom, [cpv]): |
| continue |
| |
| if require_metadata: |
| try: |
| cpv = vardb._pkg_str(cpv, atom.repo) |
| except (KeyError, portage.exception.InvalidData): |
| continue |
| if not portage.match_from_list(atom, [cpv]): |
| continue |
| |
| results.append(cpv) |
| |
| results.sort() |
| else: |
| results = vardb.match(atom) |
| for cpv in results: |
| print(cpv) |
| |
| |
| @uses_eroot |
| def expand_virtual(argv): |
| """<eroot> <atom> |
| Returns a \\n separated list of atoms expanded from a |
| given virtual atom (GLEP 37 virtuals only), |
| excluding blocker atoms. Satisfied |
| virtual atoms are not included in the output, since |
| they are expanded to real atoms which are displayed. |
| Unsatisfied virtual atoms are displayed without |
| any expansion. The "match" command can be used to |
| resolve the returned atoms to specific installed |
| packages. |
| """ |
| if len(argv) != 2: |
| writemsg("ERROR: expected 2 parameters, got %d!\n" % len(argv), |
| noiselevel=-1) |
| return 2 |
| |
| root, atom = argv |
| |
| try: |
| results = list(expand_new_virt( |
| portage.db[root]["vartree"].dbapi, atom)) |
| except portage.exception.InvalidAtom: |
| writemsg("ERROR: Invalid atom: '%s'\n" % atom, |
| noiselevel=-1) |
| return 2 |
| |
| results.sort() |
| for x in results: |
| if not x.blocker: |
| writemsg_stdout("%s\n" % (x,)) |
| |
| return os.EX_OK |
| |
| |
| def vdb_path(_argv): |
| """ |
| Returns the path used for the var(installed) package database for the |
| set environment/configuration options. |
| """ |
| out = sys.stdout |
| out.write(os.path.join(portage.settings["EROOT"], portage.VDB_PATH) + "\n") |
| out.flush() |
| return os.EX_OK |
| |
| def gentoo_mirrors(_argv): |
| """ |
| Returns the mirrors set to use in the portage configuration. |
| """ |
| print(portage.settings["GENTOO_MIRRORS"]) |
| |
| |
| @uses_eroot |
| def repositories_configuration(argv): |
| """<eroot> |
| Returns the configuration of repositories. |
| """ |
| if len(argv) < 1: |
| print("ERROR: insufficient parameters!", file=sys.stderr) |
| return 3 |
| sys.stdout.write(portage.db[argv[0]]["vartree"].settings.repositories.config_string()) |
| sys.stdout.flush() |
| |
| @uses_eroot |
| def repos_config(argv): |
| """ |
| <eroot> |
| This is an alias for the repositories_configuration command. |
| """ |
| return repositories_configuration(argv) |
| |
| def portdir(_argv): |
| """ |
| Returns the PORTDIR path. |
| Deprecated in favor of repositories_configuration command. |
| """ |
| print("WARNING: 'portageq portdir' is deprecated. Use 'portageq repositories_configuration' instead.", file=sys.stderr) |
| print(portage.settings["PORTDIR"]) |
| |
| |
| def config_protect(_argv): |
| """ |
| Returns the CONFIG_PROTECT paths. |
| """ |
| print(portage.settings["CONFIG_PROTECT"]) |
| |
| |
| def config_protect_mask(_argv): |
| """ |
| Returns the CONFIG_PROTECT_MASK paths. |
| """ |
| print(portage.settings["CONFIG_PROTECT_MASK"]) |
| |
| |
| def portdir_overlay(_argv): |
| """ |
| Returns the PORTDIR_OVERLAY path. |
| Deprecated in favor of repositories_configuration command. |
| """ |
| print("WARNING: 'portageq portdir_overlay' is deprecated. Use 'portageq repositories_configuration' instead.", file=sys.stderr) |
| print(portage.settings["PORTDIR_OVERLAY"]) |
| |
| |
| def pkgdir(_argv): |
| """ |
| Returns the PKGDIR path. |
| """ |
| print(portage.settings["PKGDIR"]) |
| |
| |
| def distdir(_argv): |
| """ |
| Returns the DISTDIR path. |
| """ |
| print(portage.settings["DISTDIR"]) |
| |
| |
| def colormap(_argv): |
| """ |
| Display the color.map as environment variables. |
| """ |
| print(portage.output.colormap()) |
| |
| |
| def envvar(argv): |
| """<variable>+ |
| Returns a specific environment variable as exists prior to ebuild.sh. |
| Similar to: emerge --verbose --info | egrep '^<variable>=' |
| """ |
| verbose = "-v" in argv |
| if verbose: |
| argv.pop(argv.index("-v")) |
| |
| if len(argv) == 0: |
| print("ERROR: insufficient parameters!") |
| return 2 |
| |
| for arg in argv: |
| if arg in ("PORTDIR", "PORTDIR_OVERLAY", "SYNC"): |
| print("WARNING: 'portageq envvar %s' is deprecated. Use 'portageq repositories_configuration' instead." % arg, file=sys.stderr) |
| if verbose: |
| print(arg + "=" + portage._shell_quote(portage.settings[arg])) |
| else: |
| print(portage.settings[arg]) |
| |
| |
| @uses_eroot |
| def get_repos(argv): |
| """<eroot> |
| Returns all repos with names (repo_name file) argv[0] = $EROOT |
| """ |
| if len(argv) < 1: |
| print("ERROR: insufficient parameters!") |
| return 2 |
| print(" ".join(reversed(portage.db[argv[0]]["vartree"].settings.repositories.prepos_order))) |
| |
| |
| @uses_eroot |
| def master_repositories(argv): |
| """<eroot> <repo_id>+ |
| Returns space-separated list of master repositories for specified repository. |
| """ |
| if len(argv) < 2: |
| print("ERROR: insufficient parameters!", file=sys.stderr) |
| return 3 |
| for arg in argv[1:]: |
| if portage.dep._repo_name_re.match(arg) is None: |
| print("ERROR: invalid repository: %s" % arg, file=sys.stderr) |
| return 2 |
| try: |
| repo = portage.db[argv[0]]["vartree"].settings.repositories[arg] |
| except KeyError: |
| print("") |
| return 1 |
| else: |
| print(" ".join(x.name for x in repo.masters)) |
| |
| @uses_eroot |
| def master_repos(argv): |
| """<eroot> <repo_id>+ |
| This is an alias for the master_repositories command. |
| """ |
| return master_repositories(argv) |
| |
| @uses_eroot |
| def get_repo_path(argv): |
| """<eroot> <repo_id>+ |
| Returns the path to the repo named argv[1], argv[0] = $EROOT |
| """ |
| if len(argv) < 2: |
| print("ERROR: insufficient parameters!", file=sys.stderr) |
| return 3 |
| for arg in argv[1:]: |
| if portage.dep._repo_name_re.match(arg) is None: |
| print("ERROR: invalid repository: %s" % arg, file=sys.stderr) |
| return 2 |
| path = portage.db[argv[0]]["vartree"].settings.repositories.treemap.get(arg) |
| if path is None: |
| print("") |
| return 1 |
| print(path) |
| |
| |
| @uses_eroot |
| def available_eclasses(argv): |
| """<eroot> <repo_id>+ |
| Returns space-separated list of available eclasses for specified repository. |
| """ |
| if len(argv) < 2: |
| print("ERROR: insufficient parameters!", file=sys.stderr) |
| return 3 |
| for arg in argv[1:]: |
| if portage.dep._repo_name_re.match(arg) is None: |
| print("ERROR: invalid repository: %s" % arg, file=sys.stderr) |
| return 2 |
| try: |
| repo = portage.db[argv[0]]["vartree"].settings.repositories[arg] |
| except KeyError: |
| print("") |
| return 1 |
| else: |
| print(" ".join(sorted(repo.eclass_db.eclasses))) |
| |
| |
| @uses_eroot |
| def eclass_path(argv): |
| """<eroot> <repo_id> <eclass>+ |
| Returns the path to specified eclass for specified repository. |
| """ |
| if len(argv) < 3: |
| print("ERROR: insufficient parameters!", file=sys.stderr) |
| return 3 |
| if portage.dep._repo_name_re.match(argv[1]) is None: |
| print("ERROR: invalid repository: %s" % argv[1], file=sys.stderr) |
| return 2 |
| try: |
| repo = portage.db[argv[0]]["vartree"].settings.repositories[argv[1]] |
| except KeyError: |
| print("") |
| return 1 |
| else: |
| retval = 0 |
| for arg in argv[2:]: |
| try: |
| eclass = repo.eclass_db.eclasses[arg] |
| except KeyError: |
| print("") |
| retval = 1 |
| else: |
| print(eclass.location) |
| return retval |
| |
| |
| @uses_eroot |
| def license_path(argv): |
| """<eroot> <repo_id> <license>+ |
| Returns the path to specified license for specified repository. |
| """ |
| if len(argv) < 3: |
| print("ERROR: insufficient parameters!", file=sys.stderr) |
| return 3 |
| if portage.dep._repo_name_re.match(argv[1]) is None: |
| print("ERROR: invalid repository: %s" % argv[1], file=sys.stderr) |
| return 2 |
| try: |
| repo = portage.db[argv[0]]["vartree"].settings.repositories[argv[1]] |
| except KeyError: |
| print("") |
| return 1 |
| else: |
| retval = 0 |
| for arg in argv[2:]: |
| eclass_path = "" |
| paths = reversed([os.path.join(x.location, 'licenses', arg) for x in list(repo.masters) + [repo]]) |
| for path in paths: |
| if os.path.exists(path): |
| eclass_path = path |
| break |
| if eclass_path == "": |
| retval = 1 |
| print(eclass_path) |
| return retval |
| |
| |
| @uses_eroot |
| def list_preserved_libs(argv): |
| """<eroot> |
| Print a list of libraries preserved during a package update in the form |
| package: path. Returns 1 if no preserved libraries could be found, |
| 0 otherwise. |
| """ |
| |
| if len(argv) != 1: |
| print("ERROR: wrong number of arguments") |
| return 2 |
| mylibs = portage.db[argv[0]]["vartree"].dbapi._plib_registry.getPreservedLibs() |
| rValue = 1 |
| msg = [] |
| for cpv in sorted(mylibs): |
| msg.append(cpv) |
| for path in mylibs[cpv]: |
| msg.append(' ' + path) |
| rValue = 0 |
| msg.append('\n') |
| writemsg_stdout(''.join(msg), noiselevel=-1) |
| return rValue |
| |
| |
| class MaintainerEmailMatcher(object): |
| def __init__(self, maintainer_emails): |
| self._re = re.compile("^(%s)$" % "|".join(maintainer_emails)) |
| |
| def __call__(self, metadata_xml): |
| match = False |
| matcher = self._re.match |
| for x in metadata_xml.maintainers(): |
| if x.email is not None and matcher(x.email) is not None: |
| match = True |
| break |
| return match |
| |
| class HerdMatcher(object): |
| def __init__(self, herds): |
| self._herds = frozenset(herds) |
| |
| def __call__(self, metadata_xml): |
| herds = self._herds |
| return any(x in herds for x in metadata_xml.herds()) |
| |
| |
| def pquery(parser, opts, args): |
| """[options] [atom]+ |
| Emulates a subset of Pkgcore's pquery tool. |
| """ |
| |
| portdb = portage.db[portage.root]['porttree'].dbapi |
| root_config = RootConfig(portdb.settings, |
| portage.db[portage.root], None) |
| |
| def _pkg(cpv, repo_name): |
| try: |
| metadata = dict(zip( |
| Package.metadata_keys, |
| portdb.aux_get(cpv, |
| Package.metadata_keys, |
| myrepo=repo_name))) |
| except KeyError: |
| raise portage.exception.PackageNotFound(cpv) |
| return Package(built=False, cpv=cpv, |
| installed=False, metadata=metadata, |
| root_config=root_config, |
| type_name="ebuild") |
| |
| need_metadata = False |
| atoms = [] |
| for arg in args: |
| if "/" not in arg.split(":")[0]: |
| atom = insert_category_into_atom(arg, '*') |
| if atom is None: |
| writemsg("ERROR: Invalid atom: '%s'\n" % arg, |
| noiselevel=-1) |
| return 2 |
| else: |
| atom = arg |
| |
| try: |
| atom = portage.dep.Atom(atom, allow_wildcard=True, allow_repo=True) |
| except portage.exception.InvalidAtom: |
| writemsg("ERROR: Invalid atom: '%s'\n" % arg, |
| noiselevel=-1) |
| return 2 |
| |
| if atom.slot is not None: |
| need_metadata = True |
| |
| atoms.append(atom) |
| |
| if "*/*" in atoms: |
| del atoms[:] |
| need_metadata = False |
| |
| if not opts.no_filters: |
| need_metadata = True |
| |
| xml_matchers = [] |
| if opts.maintainer_email: |
| maintainer_emails = [] |
| for x in opts.maintainer_email: |
| maintainer_emails.extend(x.split(",")) |
| xml_matchers.append(MaintainerEmailMatcher(maintainer_emails)) |
| if opts.herd is not None: |
| herds = [] |
| for x in opts.herd: |
| herds.extend(x.split(",")) |
| xml_matchers.append(HerdMatcher(herds)) |
| |
| repos = [] |
| if opts.all_repos: |
| repos.extend(portdb.repositories.get_repo_for_location(location) |
| for location in portdb.porttrees) |
| elif opts.repo is not None: |
| repos.append(portdb.repositories[opts.repo]) |
| else: |
| repos.append(portdb.repositories.mainRepo()) |
| |
| if not atoms: |
| names = None |
| categories = list(portdb.categories) |
| else: |
| category_wildcard = False |
| name_wildcard = False |
| categories = [] |
| names = [] |
| for atom in atoms: |
| category, name = portage.catsplit(atom.cp) |
| categories.append(category) |
| names.append(name) |
| if "*" in category: |
| category_wildcard = True |
| if "*" in name: |
| name_wildcard = True |
| |
| if category_wildcard: |
| categories = list(portdb.categories) |
| else: |
| categories = list(set(categories)) |
| |
| if name_wildcard: |
| names = None |
| else: |
| names = sorted(set(names)) |
| |
| no_version = opts.no_version |
| categories.sort() |
| |
| for category in categories: |
| if names is None: |
| cp_list = portdb.cp_all(categories=(category,)) |
| else: |
| cp_list = [category + "/" + name for name in names] |
| for cp in cp_list: |
| matches = [] |
| for repo in repos: |
| match = True |
| if xml_matchers: |
| metadata_xml_path = os.path.join( |
| repo.location, cp, 'metadata.xml') |
| try: |
| metadata_xml = MetaDataXML(metadata_xml_path, None) |
| except (EnvironmentError, SyntaxError): |
| match = False |
| else: |
| for matcher in xml_matchers: |
| if not matcher(metadata_xml): |
| match = False |
| break |
| if not match: |
| continue |
| cpv_list = portdb.cp_list(cp, mytree=[repo.location]) |
| if atoms: |
| for cpv in cpv_list: |
| pkg = None |
| for atom in atoms: |
| if atom.repo is not None and \ |
| atom.repo != repo.name: |
| continue |
| if not portage.match_from_list(atom, [cpv]): |
| continue |
| if need_metadata: |
| if pkg is None: |
| try: |
| pkg = _pkg(cpv, repo.name) |
| except portage.exception.PackageNotFound: |
| continue |
| |
| if not (opts.no_filters or pkg.visible): |
| continue |
| if not portage.match_from_list(atom, [pkg]): |
| continue |
| matches.append(cpv) |
| break |
| if no_version and matches: |
| break |
| elif opts.no_filters: |
| matches.extend(cpv_list) |
| else: |
| for cpv in cpv_list: |
| try: |
| pkg = _pkg(cpv, repo.name) |
| except portage.exception.PackageNotFound: |
| continue |
| else: |
| if pkg.visible: |
| matches.append(cpv) |
| if no_version: |
| break |
| |
| if no_version and matches: |
| break |
| |
| if not matches: |
| continue |
| |
| if no_version: |
| writemsg_stdout("%s\n" % (cp,), noiselevel=-1) |
| else: |
| matches = list(set(matches)) |
| portdb._cpv_sort_ascending(matches) |
| for cpv in matches: |
| writemsg_stdout("%s\n" % (cpv,), noiselevel=-1) |
| |
| return os.EX_OK |
| |
| |
| def use_reduce(argv): |
| """<depend_string> |
| Reduce a dependency string possibly containing use conditionals. |
| """ |
| |
| if len(argv) != 1: |
| print("ERROR: wrong number of arguments") |
| return 2 |
| from portage.dep import use_reduce as use_internal |
| print(' '.join(use_internal(argv[0], uselist=os.environ['USE'].split(' ')))) |
| |
| #----------------------------------------------------------------------------- |
| # |
| # DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED! |
| # |
| |
| non_commands = frozenset(['elog', 'eval_atom_use', 'exithandler', 'main', 'usage', 'uses_eroot']) |
| commands = sorted(k for k, v in globals().items() \ |
| if k not in non_commands and isinstance(v, types.FunctionType) and v.__module__ == "__main__") |
| |
| |
| def add_pquery_arguments(parser): |
| pquery_option_groups = ( |
| ( |
| 'Repository matching options', |
| ( |
| { |
| "longopt": "--no-filters", |
| "action": "store_true", |
| "help": "no visibility filters (ACCEPT_KEYWORDS, package masking, etc)" |
| }, |
| { |
| "longopt": "--repo", |
| "help": "repo to use (default is PORTDIR if omitted)" |
| }, |
| { |
| "longopt": "--all-repos", |
| "help": "search all repos" |
| } |
| ) |
| ), |
| ( |
| 'Package matching options', |
| ( |
| { |
| "longopt": "--herd", |
| "action": "append", |
| "help": "exact match on a herd" |
| }, |
| { |
| "longopt": "--maintainer-email", |
| "action": "append", |
| "help": "comma-separated list of maintainer email regexes to search for" |
| } |
| ) |
| ), |
| ( |
| 'Output formatting', |
| ( |
| { |
| "shortopt": "-n", |
| "longopt": "--no-version", |
| "action": "store_true", |
| "help": "collapse multiple matching versions together" |
| }, |
| ) |
| ), |
| ) |
| |
| for group_title, opt_data in pquery_option_groups: |
| arg_group = parser.add_argument_group(group_title) |
| for opt_info in opt_data: |
| pargs = [] |
| try: |
| pargs.append(opt_info["shortopt"]) |
| except KeyError: |
| pass |
| try: |
| pargs.append(opt_info["longopt"]) |
| except KeyError: |
| pass |
| |
| kwargs = {} |
| try: |
| kwargs["action"] = opt_info["action"] |
| except KeyError: |
| pass |
| try: |
| kwargs["help"] = opt_info["help"] |
| except KeyError: |
| pass |
| arg_group.add_argument(*pargs, **portage._native_kwargs(kwargs)) |
| |
| |
| def usage(argv): |
| print(">>> Portage information query tool") |
| print(">>> %s" % portage.VERSION) |
| print(">>> Usage: portageq <command> [<option> ...]") |
| print("") |
| print("Available commands:") |
| |
| # |
| # Show our commands -- we do this by scanning the functions in this |
| # file, and formatting each functions documentation. |
| # |
| help_mode = '--help' in argv |
| for name in commands: |
| # Drop non-functions |
| obj = globals()[name] |
| |
| doc = obj.__doc__ |
| if (doc == None): |
| print(" " + name) |
| print(" MISSING DOCUMENTATION!") |
| print("") |
| continue |
| |
| lines = doc.lstrip("\n").split("\n") |
| print(" " + name + " " + lines[0].strip()) |
| if len(argv) > 1: |
| if (not help_mode): |
| lines = lines[:-1] |
| for line in lines[1:]: |
| print(" " + line.strip()) |
| |
| print() |
| print('Pkgcore pquery compatible options:') |
| print() |
| parser = ArgumentParser(add_help=False, |
| usage='portageq pquery [options] [atom ...]') |
| add_pquery_arguments(parser) |
| parser.print_help() |
| |
| if len(argv) == 1: |
| print("\nRun portageq with --help for info") |
| |
| atom_validate_strict = "EBUILD_PHASE" in os.environ |
| eapi = None |
| if atom_validate_strict: |
| eapi = os.environ.get('EAPI') |
| |
| def elog(elog_funcname, lines): |
| cmd = "source '%s/isolated-functions.sh' ; " % \ |
| os.environ["PORTAGE_BIN_PATH"] |
| for line in lines: |
| cmd += "%s %s ; " % (elog_funcname, portage._shell_quote(line)) |
| subprocess.call([portage.const.BASH_BINARY, "-c", cmd]) |
| |
| else: |
| def elog(elog_funcname, lines): |
| pass |
| |
| def main(argv): |
| |
| argv = portage._decode_argv(argv) |
| |
| nocolor = os.environ.get('NOCOLOR') |
| if nocolor in ('yes', 'true'): |
| portage.output.nocolor() |
| |
| parser = ArgumentParser(add_help=False) |
| |
| # used by envvar |
| parser.add_argument("-v", dest="verbose", action="store_true") |
| |
| actions = parser.add_argument_group('Actions') |
| actions.add_argument("-h", "--help", action="store_true") |
| actions.add_argument("--version", action="store_true") |
| |
| add_pquery_arguments(parser) |
| |
| opts, args = parser.parse_known_args(argv[1:]) |
| |
| if opts.help: |
| usage(argv) |
| return os.EX_OK |
| elif opts.version: |
| print("Portage", portage.VERSION) |
| return os.EX_OK |
| |
| cmd = None |
| if args and args[0] in commands: |
| cmd = args[0] |
| |
| if cmd == 'pquery': |
| cmd = None |
| args = args[1:] |
| |
| if cmd is None: |
| return pquery(parser, opts, args) |
| |
| if opts.verbose: |
| # used by envvar |
| args.append("-v") |
| |
| argv = argv[:1] + args |
| |
| if len(argv) < 2: |
| usage(argv) |
| sys.exit(os.EX_USAGE) |
| |
| function = globals()[cmd] |
| uses_eroot = getattr(function, "uses_eroot", False) and len(argv) > 2 |
| if uses_eroot: |
| if not os.path.isdir(argv[2]): |
| sys.stderr.write("Not a directory: '%s'\n" % argv[2]) |
| sys.stderr.write("Run portageq with --help for info\n") |
| sys.stderr.flush() |
| sys.exit(os.EX_USAGE) |
| eprefix = portage.settings["EPREFIX"] |
| eroot = portage.util.normalize_path(argv[2]) |
| |
| if eprefix: |
| if not eroot.endswith(eprefix): |
| sys.stderr.write("ERROR: This version of portageq" |
| " only supports <eroot>s ending in" |
| " '%s'. The provided <eroot>, '%s'," |
| " doesn't.\n" % (eprefix, eroot)) |
| sys.stderr.flush() |
| sys.exit(os.EX_USAGE) |
| root = eroot[:1 - len(eprefix)] |
| else: |
| root = eroot |
| |
| os.environ["ROOT"] = root |
| |
| args = argv[2:] |
| |
| try: |
| if uses_eroot: |
| args[0] = portage.settings['EROOT'] |
| retval = function(args) |
| if retval: |
| sys.exit(retval) |
| except portage.exception.PermissionDenied as e: |
| sys.stderr.write("Permission denied: '%s'\n" % str(e)) |
| sys.exit(e.errno) |
| except portage.exception.ParseError as e: |
| sys.stderr.write("%s\n" % str(e)) |
| sys.exit(1) |
| except portage.exception.AmbiguousPackageName as e: |
| # Multiple matches thrown from cpv_expand |
| pkgs = e.args[0] |
| # An error has occurred so we writemsg to stderr and exit nonzero. |
| portage.writemsg("You specified an unqualified atom that matched multiple packages:\n", noiselevel=-1) |
| for pkg in pkgs: |
| portage.writemsg("* %s\n" % pkg, noiselevel=-1) |
| portage.writemsg("\nPlease use a more specific atom.\n", noiselevel=-1) |
| sys.exit(1) |
| |
| if __name__ == '__main__': |
| sys.exit(main(sys.argv)) |
| |
| #----------------------------------------------------------------------------- |