2 # Copyright 1999-2012 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
5 from __future__ import print_function
9 # This block ensures that ^C interrupts are handled quietly.
12 def exithandler(signum, frame):
13 signal.signal(signal.SIGINT, signal.SIG_IGN)
14 signal.signal(signal.SIGTERM, signal.SIG_IGN)
15 sys.exit(128 + signum)
17 signal.signal(signal.SIGINT, exithandler)
18 signal.signal(signal.SIGTERM, exithandler)
20 except KeyboardInterrupt:
21 sys.exit(128 + signal.SIGINT)
26 # Avoid sandbox violations after python upgrade.
27 pym_path = os.path.join(os.path.dirname(
28 os.path.dirname(os.path.realpath(__file__))), "pym")
29 if os.environ.get("SANDBOX_ON") == "1":
30 sandbox_write = os.environ.get("SANDBOX_WRITE", "").split(":")
31 if pym_path not in sandbox_write:
32 sandbox_write.append(pym_path)
33 os.environ["SANDBOX_WRITE"] = \
34 ":".join(filter(None, sandbox_write))
37 sys.path.insert(0, pym_path)
39 from portage import os
40 from portage.eapi import eapi_has_repo_deps
41 from portage.util import writemsg, writemsg_stdout
42 from portage.output import colormap
43 portage.proxy.lazyimport.lazyimport(globals(),
45 '_emerge.Package:Package',
46 '_emerge.RootConfig:RootConfig',
47 'portage.dbapi._expand_new_virt:expand_new_virt',
48 'portage._sets.base:InternalPackageSet',
51 def eval_atom_use(atom):
52 if 'USE' in os.environ:
53 use = frozenset(os.environ['USE'].split())
54 atom = atom.evaluate_conditionals(use)
57 #-----------------------------------------------------------------------------
59 # To add functionality to this tool, add a function below.
61 # The format for functions is:
64 # """<list of options for this function>
65 # <description of the function>
69 # "argv" is an array of the command line parameters provided after the command.
71 # Make sure you document the function in the right format. The documentation
72 # is used to display help on the function.
74 # You do not need to add the function to any lists, this tool is introspective,
75 # and will automaticly add a command by the same name as the function!
78 def has_version(argv):
79 """<eroot> <category/package>
80 Return code 0 if it's available, 1 otherwise.
83 print("ERROR: insufficient parameters!")
88 allow_repo = atom_validate_strict is False or eapi_has_repo_deps(eapi)
90 atom = portage.dep.Atom(argv[1], allow_repo=allow_repo)
91 except portage.exception.InvalidAtom:
92 if atom_validate_strict:
93 portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
99 if atom_validate_strict:
101 atom = portage.dep.Atom(argv[1], allow_repo=allow_repo, eapi=eapi)
102 except portage.exception.InvalidAtom as e:
104 portage._unicode_decode("QA Notice: %s: %s") % \
106 atom = eval_atom_use(atom)
109 elog('eqawarn', warnings)
112 mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
119 except portage.exception.InvalidAtom:
120 portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
123 has_version.uses_eroot = True
126 def best_version(argv):
127 """<eroot> <category/package>
128 Returns category/package-version (without .ebuild).
131 print("ERROR: insufficient parameters!")
136 allow_repo = atom_validate_strict is False or eapi_has_repo_deps(eapi)
138 atom = portage.dep.Atom(argv[1], allow_repo=allow_repo)
139 except portage.exception.InvalidAtom:
140 if atom_validate_strict:
141 portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
147 if atom_validate_strict:
149 atom = portage.dep.Atom(argv[1], allow_repo=allow_repo, eapi=eapi)
150 except portage.exception.InvalidAtom as e:
152 portage._unicode_decode("QA Notice: %s: %s") % \
154 atom = eval_atom_use(atom)
157 elog('eqawarn', warnings)
160 mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
161 print(portage.best(mylist))
164 best_version.uses_eroot = True
167 def mass_best_version(argv):
168 """<eroot> [<category/package>]+
169 Returns category/package-version (without .ebuild).
172 print("ERROR: insufficient parameters!")
175 for pack in argv[1:]:
176 mylist=portage.db[argv[0]]["vartree"].dbapi.match(pack)
177 print(pack+":"+portage.best(mylist))
180 mass_best_version.uses_eroot = True
184 print("ERROR: insufficient parameters!", file=sys.stderr)
187 eroot, pkgtype, pkgspec = argv[0:3]
192 "installed":"vartree"}
193 if pkgtype not in type_map:
194 print("Unrecognized package type: '%s'" % pkgtype, file=sys.stderr)
197 repo = portage.dep.dep_getrepo(pkgspec)
198 pkgspec = portage.dep.remove_slot(pkgspec)
200 values = trees[eroot][type_map[pkgtype]].dbapi.aux_get(
201 pkgspec, metakeys, myrepo=repo)
202 writemsg_stdout(''.join('%s\n' % x for x in values), noiselevel=-1)
204 print("Package not found: '%s'" % pkgspec, file=sys.stderr)
207 metadata.__doc__ = """
208 <eroot> <pkgtype> <category/package> [<key>]+
209 Returns metadata values for the specified package.
211 """ % ','.join(sorted(x for x in portage.auxdbkeys \
212 if not x.startswith('UNUSED_')))
214 metadata.uses_eroot = True
217 """<eroot> <category/package>
218 List the files that are installed for a given package, with
219 one file listed on each line. All file names will begin with
223 print("ERROR: expected 2 parameters, got %d!" % len(argv))
227 vartree = portage.db[root]["vartree"]
228 if not vartree.dbapi.cpv_exists(cpv):
229 sys.stderr.write("Package not found: '%s'\n" % cpv)
231 cat, pkg = portage.catsplit(cpv)
232 db = portage.dblink(cat, pkg, root, vartree.settings,
233 treetype="vartree", vartree=vartree)
234 writemsg_stdout(''.join('%s\n' % x for x in sorted(db.getcontents())),
236 contents.uses_eroot = True
239 """<eroot> [<filename>]+
240 Given a list of files, print the packages that own the files and which
241 files belong to each package. Files owned by a package are listed on
242 the lines below it, indented by a single tab character (\\t). All file
243 paths must either start with <eroot> or be a basename alone.
244 Returns 1 if no owners could be found, and 0 otherwise.
247 sys.stderr.write("ERROR: insufficient parameters!\n")
251 from portage import catsplit, dblink
253 vardb = portage.db[eroot]["vartree"].dbapi
254 root = portage.settings['ROOT']
263 orphan_abs_paths = set()
264 orphan_basenames = set()
266 f = portage.normalize_path(f)
267 is_basename = os.sep not in f
268 if not is_basename and f[:1] != os.sep:
270 sys.stderr.write("ERROR: cwd does not exist!\n")
273 f = os.path.join(cwd, f)
274 f = portage.normalize_path(f)
275 if not is_basename and not f.startswith(eroot):
276 sys.stderr.write("ERROR: file paths must begin with <eroot>!\n")
281 orphan_basenames.add(f)
283 files.append(f[len(root)-1:])
284 orphan_abs_paths.add(f)
286 owners = vardb._owners.get_owners(files)
289 for pkg, owned_files in owners.items():
291 msg.append("%s\n" % cpv)
292 for f in sorted(owned_files):
293 f_abs = os.path.join(root, f.lstrip(os.path.sep))
294 msg.append("\t%s\n" % (f_abs,))
295 orphan_abs_paths.discard(f_abs)
297 orphan_basenames.discard(os.path.basename(f_abs))
299 writemsg_stdout(''.join(msg), noiselevel=-1)
301 if orphan_abs_paths or orphan_basenames:
303 orphans.extend(orphan_abs_paths)
304 orphans.extend(orphan_basenames)
307 msg.append("None of the installed packages claim these files:\n")
309 msg.append("\t%s\n" % (f,))
310 sys.stderr.write("".join(msg))
317 owners.uses_eroot = True
319 def is_protected(argv):
320 """<eroot> <filename>
321 Given a single filename, return code 0 if it's protected, 1 otherwise.
322 The filename must begin with <eroot>.
325 sys.stderr.write("ERROR: expected 2 parameters, got %d!\n" % len(argv))
329 root, filename = argv
338 f = portage.normalize_path(filename)
339 if not f.startswith(os.path.sep):
341 err.write("ERROR: cwd does not exist!\n")
344 f = os.path.join(cwd, f)
345 f = portage.normalize_path(f)
347 if not f.startswith(root):
348 err.write("ERROR: file paths must begin with <eroot>!\n")
352 from portage.util import ConfigProtect
354 settings = portage.settings
355 protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", ""))
356 protect_mask = portage.util.shlex_split(
357 settings.get("CONFIG_PROTECT_MASK", ""))
358 protect_obj = ConfigProtect(root, protect, protect_mask)
360 if protect_obj.isprotected(f):
364 is_protected.uses_eroot = True
366 def filter_protected(argv):
368 Read filenames from stdin and write them to stdout if they are protected.
369 All filenames are delimited by \\n and must begin with <eroot>.
372 sys.stderr.write("ERROR: expected 1 parameter, got %d!\n" % len(argv))
385 from portage.util import ConfigProtect
387 settings = portage.settings
388 protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", ""))
389 protect_mask = portage.util.shlex_split(
390 settings.get("CONFIG_PROTECT_MASK", ""))
391 protect_obj = ConfigProtect(root, protect, protect_mask)
396 for line in sys.stdin:
397 filename = line.rstrip("\n")
398 f = portage.normalize_path(filename)
399 if not f.startswith(os.path.sep):
401 err.write("ERROR: cwd does not exist!\n")
405 f = os.path.join(cwd, f)
406 f = portage.normalize_path(f)
408 if not f.startswith(root):
409 err.write("ERROR: file paths must begin with <eroot>!\n")
414 if protect_obj.isprotected(f):
416 out.write("%s\n" % filename)
424 filter_protected.uses_eroot = True
426 def best_visible(argv):
427 """<eroot> [pkgtype] <atom>
428 Returns category/package-version (without .ebuild).
429 The pkgtype argument defaults to "ebuild" if unspecified,
430 otherwise it must be one of ebuild, binary, or installed.
433 writemsg("ERROR: insufficient parameters!\n", noiselevel=-1)
446 "installed":"vartree"}
448 if pkgtype not in type_map:
449 writemsg("Unrecognized package type: '%s'\n" % pkgtype,
454 db = portage.db[eroot][type_map[pkgtype]].dbapi
457 atom = portage.dep_expand(atom, mydb=db, settings=portage.settings)
458 except portage.exception.InvalidAtom:
459 writemsg("ERROR: Invalid atom: '%s'\n" % atom,
463 root_config = RootConfig(portage.settings,
464 portage.db[eroot], None)
466 if hasattr(db, "xmatch"):
467 cpv_list = db.xmatch("match-all-cpv-only", atom)
469 cpv_list = db.match(atom)
472 # reversed, for descending order
474 # verify match, since the atom may match the package
475 # for a given cpv from one repo but not another, and
476 # we can use match-all-cpv-only to avoid redundant
478 atom_set = InternalPackageSet(initial_atoms=(atom,))
480 if atom.repo is None and hasattr(db, "getRepositories"):
481 repo_list = db.getRepositories()
483 repo_list = [atom.repo]
486 for repo in repo_list:
488 metadata = dict(zip(Package.metadata_keys,
489 db.aux_get(cpv, Package.metadata_keys, myrepo=repo)))
492 pkg = Package(built=(pkgtype != "ebuild"), cpv=cpv,
493 installed=(pkgtype=="installed"), metadata=metadata,
494 root_config=root_config, type_name=pkgtype)
495 if not atom_set.findAtomForPackage(pkg):
499 writemsg_stdout("%s\n" % (pkg.cpv,), noiselevel=-1)
502 # No package found, write out an empty line.
503 writemsg_stdout("\n", noiselevel=-1)
506 best_visible.uses_eroot = True
509 def mass_best_visible(argv):
510 """<eroot> [<type>] [<category/package>]+
511 Returns category/package-version (without .ebuild).
512 The pkgtype argument defaults to "ebuild" if unspecified,
513 otherwise it must be one of ebuild, binary, or installed.
518 "installed":"vartree"}
521 print("ERROR: insufficient parameters!")
526 if argv[0] in type_map:
527 pkgtype = argv.pop(0)
529 writemsg_stdout("%s:" % pack, noiselevel=-1)
530 best_visible([root, pkgtype, pack])
533 mass_best_visible.uses_eroot = True
536 def all_best_visible(argv):
538 Returns all best_visible packages (without .ebuild).
541 sys.stderr.write("ERROR: insufficient parameters!\n")
545 #print portage.db[argv[0]]["porttree"].dbapi.cp_all()
546 for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all():
547 mybest=portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg))
550 all_best_visible.uses_eroot = True
555 Returns a \\n separated list of category/package-version.
556 When given an empty string, all installed packages will
560 print("ERROR: expected 2 parameters, got %d!" % len(argv))
566 vardb = portage.db[root]["vartree"].dbapi
568 atom = portage.dep.Atom(atom, allow_wildcard=True, allow_repo=True)
569 except portage.exception.InvalidAtom:
570 # maybe it's valid but missing category
571 atom = portage.dep_expand(atom, mydb=vardb, settings=vardb.settings)
573 if atom.extended_syntax:
575 results = vardb.cpv_all()
578 require_metadata = atom.slot or atom.repo
579 for cpv in vardb.cpv_all():
581 if not portage.match_from_list(atom, [cpv]):
586 cpv = vardb._pkg_str(cpv, atom.repo)
587 except (KeyError, portage.exception.InvalidData):
589 if not portage.match_from_list(atom, [cpv]):
596 results = vardb.match(atom)
599 match.uses_eroot = True
601 def expand_virtual(argv):
603 Returns a \\n separated list of atoms expanded from a
604 given virtual atom (GLEP 37 virtuals only),
605 excluding blocker atoms. Satisfied
606 virtual atoms are not included in the output, since
607 they are expanded to real atoms which are displayed.
608 Unsatisfied virtual atoms are displayed without
609 any expansion. The "match" command can be used to
610 resolve the returned atoms to specific installed
614 writemsg("ERROR: expected 2 parameters, got %d!\n" % len(argv),
621 results = list(expand_new_virt(
622 portage.db[root]["vartree"].dbapi, atom))
623 except portage.exception.InvalidAtom:
624 writemsg("ERROR: Invalid atom: '%s'\n" % atom,
631 writemsg_stdout("%s\n" % (x,))
635 expand_virtual.uses_eroot = True
639 Returns the path used for the var(installed) package database for the
640 set environment/configuration options.
643 out.write(os.path.join(portage.settings["EROOT"], portage.VDB_PATH) + "\n")
647 def gentoo_mirrors(argv):
649 Returns the mirrors set to use in the portage configuration.
651 print(portage.settings["GENTOO_MIRRORS"])
656 Returns the PORTDIR path.
658 print(portage.settings["PORTDIR"])
661 def config_protect(argv):
663 Returns the CONFIG_PROTECT paths.
665 print(portage.settings["CONFIG_PROTECT"])
668 def config_protect_mask(argv):
670 Returns the CONFIG_PROTECT_MASK paths.
672 print(portage.settings["CONFIG_PROTECT_MASK"])
675 def portdir_overlay(argv):
677 Returns the PORTDIR_OVERLAY path.
679 print(portage.settings["PORTDIR_OVERLAY"])
684 Returns the PKGDIR path.
686 print(portage.settings["PKGDIR"])
691 Returns the DISTDIR path.
693 print(portage.settings["DISTDIR"])
698 Display the color.map as environment variables.
700 print(portage.output.colormap())
705 Returns a specific environment variable as exists prior to ebuild.sh.
706 Similar to: emerge --verbose --info | egrep '^<variable>='
708 verbose = "-v" in argv
710 argv.pop(argv.index("-v"))
713 print("ERROR: insufficient parameters!")
718 print(arg +"='"+ portage.settings[arg] +"'")
720 print(portage.settings[arg])
724 Returns all repos with names (repo_name file) argv[0] = $EROOT
727 print("ERROR: insufficient parameters!")
729 print(" ".join(portage.db[argv[0]]["porttree"].dbapi.getRepositories()))
731 get_repos.uses_eroot = True
733 def get_repo_path(argv):
734 """<eroot> <repo_id>+
735 Returns the path to the repo named argv[1], argv[0] = $EROOT
738 print("ERROR: insufficient parameters!")
741 path = portage.db[argv[0]]["porttree"].dbapi.getRepositoryPath(arg)
746 get_repo_path.uses_eroot = True
748 def list_preserved_libs(argv):
750 Print a list of libraries preserved during a package update in the form
751 package: path. Returns 1 if no preserved libraries could be found,
756 print("ERROR: wrong number of arguments")
758 mylibs = portage.db[argv[0]]["vartree"].dbapi._plib_registry.getPreservedLibs()
761 for cpv in sorted(mylibs):
763 for path in mylibs[cpv]:
764 msg.append(' ' + path)
767 writemsg_stdout(''.join(msg), noiselevel=-1)
769 list_preserved_libs.uses_eroot = True
771 #-----------------------------------------------------------------------------
773 # DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED!
776 non_commands = frozenset(['elog', 'eval_atom_use', 'exithandler', 'main', 'usage'])
777 commands = sorted(k for k, v in globals().items() \
778 if k not in non_commands and isinstance(v, types.FunctionType) and v.__module__ == "__main__")
781 print(">>> Portage information query tool")
782 print(">>> %s" % portage.VERSION)
783 print(">>> Usage: portageq <command> [<option> ...]")
785 print("Available commands:")
788 # Show our commands -- we do this by scanning the functions in this
789 # file, and formatting each functions documentation.
791 help_mode = '--help' in sys.argv
792 for name in commands:
794 obj = globals()[name]
799 print(" MISSING DOCUMENTATION!")
803 lines = doc.lstrip("\n").split("\n")
804 print(" " + name + " " + lines[0].strip())
805 if (len(sys.argv) > 1):
808 for line in lines[1:]:
809 print(" " + line.strip())
810 if (len(sys.argv) == 1):
811 print("\nRun portageq with --help for info")
813 atom_validate_strict = "EBUILD_PHASE" in os.environ
815 if atom_validate_strict:
816 eapi = os.environ.get('EAPI')
818 def elog(elog_funcname, lines):
819 cmd = "source '%s/isolated-functions.sh' ; " % \
820 os.environ["PORTAGE_BIN_PATH"]
822 cmd += "%s %s ; " % (elog_funcname, portage._shell_quote(line))
823 subprocess.call([portage.const.BASH_BINARY, "-c", cmd])
826 def elog(elog_funcname, lines):
831 nocolor = os.environ.get('NOCOLOR')
832 if nocolor in ('yes', 'true'):
833 portage.output.nocolor()
835 if len(sys.argv) < 2:
837 sys.exit(os.EX_USAGE)
840 if x in ("-h", "--help"):
843 elif x == "--version":
844 print("Portage", portage.VERSION)
848 function = globals().get(cmd)
849 if function is None or cmd not in commands:
851 sys.exit(os.EX_USAGE)
852 function = globals()[cmd]
853 uses_eroot = getattr(function, "uses_eroot", False) and len(sys.argv) > 2
855 if not os.path.isdir(sys.argv[2]):
856 sys.stderr.write("Not a directory: '%s'\n" % sys.argv[2])
857 sys.stderr.write("Run portageq with --help for info\n")
859 sys.exit(os.EX_USAGE)
860 eprefix = portage.const.EPREFIX
861 eroot = portage.util.normalize_path(sys.argv[2])
864 if not eroot.endswith(eprefix):
865 sys.stderr.write("ERROR: This version of portageq"
866 " only supports <eroot>s ending in"
867 " '%s'. The provided <eroot>, '%s',"
868 " doesn't.\n" % (eprefix, eroot));
870 sys.exit(os.EX_USAGE)
871 root = eroot[:1-len(eprefix)]
875 os.environ["ROOT"] = root
878 if args and isinstance(args[0], bytes):
879 for i in range(len(args)):
880 args[i] = portage._unicode_decode(args[i])
884 args[0] = portage.settings['EROOT']
885 retval = function(args)
888 except portage.exception.PermissionDenied as e:
889 sys.stderr.write("Permission denied: '%s'\n" % str(e))
891 except portage.exception.ParseError as e:
892 sys.stderr.write("%s\n" % str(e))
894 except portage.exception.AmbiguousPackageName as e:
895 # Multiple matches thrown from cpv_expand
897 # An error has occurred so we writemsg to stderr and exit nonzero.
898 portage.writemsg("You specified an unqualified atom that matched multiple packages:\n", noiselevel=-1)
900 portage.writemsg("* %s\n" % pkg, noiselevel=-1)
901 portage.writemsg("\nPlease use a more specific atom.\n", noiselevel=-1)
906 #-----------------------------------------------------------------------------