2 # Copyright 1999-2011 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))
40 sys.path.insert(0, pym_path)
44 from portage import os
45 from portage.util import writemsg, writemsg_stdout
46 portage.proxy.lazyimport.lazyimport(globals(),
48 'portage.dbapi._expand_new_virt:expand_new_virt',
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 """<root> <category/package>
80 Return code 0 if it's available, 1 otherwise.
83 print("ERROR: insufficient parameters!")
89 atom = portage.dep.Atom(argv[1])
90 except portage.exception.InvalidAtom:
91 if atom_validate_strict:
92 portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
98 if atom_validate_strict:
100 atom = portage.dep.Atom(argv[1], eapi=eapi)
101 except portage.exception.InvalidAtom as e:
103 portage._unicode_decode("QA Notice: %s: %s") % \
105 atom = eval_atom_use(atom)
108 elog('eqawarn', warnings)
111 mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
118 except portage.exception.InvalidAtom:
119 portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
122 has_version.uses_root = True
125 def best_version(argv):
126 """<root> <category/package>
127 Returns category/package-version (without .ebuild).
130 print("ERROR: insufficient parameters!")
136 atom = portage.dep.Atom(argv[1])
137 except portage.exception.InvalidAtom:
138 if atom_validate_strict:
139 portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
145 if atom_validate_strict:
147 atom = portage.dep.Atom(argv[1], eapi=eapi)
148 except portage.exception.InvalidAtom as e:
150 portage._unicode_decode("QA Notice: %s: %s") % \
152 atom = eval_atom_use(atom)
155 elog('eqawarn', warnings)
158 mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
159 print(portage.best(mylist))
162 best_version.uses_root = True
165 def mass_best_version(argv):
166 """<root> [<category/package>]+
167 Returns category/package-version (without .ebuild).
170 print("ERROR: insufficient parameters!")
173 for pack in argv[1:]:
174 mylist=portage.db[argv[0]]["vartree"].dbapi.match(pack)
175 print(pack+":"+portage.best(mylist))
178 mass_best_version.uses_root = True
182 print("ERROR: insufficient parameters!", file=sys.stderr)
185 root, pkgtype, pkgspec = argv[0:3]
190 "installed":"vartree"}
191 if pkgtype not in type_map:
192 print("Unrecognized package type: '%s'" % pkgtype, file=sys.stderr)
195 if os.path.realpath(root) == os.path.realpath(portage.settings["ROOT"]):
196 root = portage.settings["ROOT"] # contains the normalized $ROOT
198 values = trees[root][type_map[pkgtype]].dbapi.aux_get(
200 writemsg_stdout(''.join('%s\n' % x for x in values), noiselevel=-1)
202 print("Package not found: '%s'" % pkgspec, file=sys.stderr)
205 metadata.__doc__ = """
206 <root> <pkgtype> <category/package> [<key>]+
207 Returns metadata values for the specified package.
209 """ % ','.join(sorted(x for x in portage.auxdbkeys \
210 if not x.startswith('UNUSED_')))
212 metadata.uses_root = True
215 """<root> <category/package>
216 List the files that are installed for a given package, with
217 one file listed on each line. All file names will begin with
221 print("ERROR: expected 2 parameters, got %d!" % len(argv))
225 vartree = portage.db[root]["vartree"]
226 if not vartree.dbapi.cpv_exists(cpv):
227 sys.stderr.write("Package not found: '%s'\n" % cpv)
229 cat, pkg = portage.catsplit(cpv)
230 db = portage.dblink(cat, pkg, root, vartree.settings,
231 treetype="vartree", vartree=vartree)
232 writemsg_stdout(''.join('%s\n' % x for x in sorted(db.getcontents())),
234 contents.uses_root = True
237 """<root> [<filename>]+
238 Given a list of files, print the packages that own the files and which
239 files belong to each package. Files owned by a package are listed on
240 the lines below it, indented by a single tab character (\\t). All file
241 paths must either start with <root> or be a basename alone.
242 Returns 1 if no owners could be found, and 0 otherwise.
245 sys.stderr.write("ERROR: insufficient parameters!\n")
249 from portage import catsplit, dblink
250 settings = portage.settings
251 root = settings["ROOT"]
252 vardb = portage.db[root]["vartree"].dbapi
261 orphan_abs_paths = set()
262 orphan_basenames = set()
264 f = portage.normalize_path(f)
265 is_basename = os.sep not in f
266 if not is_basename and f[:1] != os.sep:
268 sys.stderr.write("ERROR: cwd does not exist!\n")
271 f = os.path.join(cwd, f)
272 f = portage.normalize_path(f)
273 if not is_basename and not f.startswith(root):
274 sys.stderr.write("ERROR: file paths must begin with <root>!\n")
279 orphan_basenames.add(f)
281 files.append(f[len(root)-1:])
282 orphan_abs_paths.add(f)
284 owners = vardb._owners.get_owners(files)
287 for pkg, owned_files in owners.items():
289 msg.append("%s\n" % cpv)
290 for f in sorted(owned_files):
291 f_abs = os.path.join(root, f.lstrip(os.path.sep))
292 msg.append("\t%s\n" % (f_abs,))
293 orphan_abs_paths.discard(f_abs)
295 orphan_basenames.discard(os.path.basename(f_abs))
297 writemsg_stdout(''.join(msg), noiselevel=-1)
299 if orphan_abs_paths or orphan_basenames:
301 orphans.extend(orphan_abs_paths)
302 orphans.extend(orphan_basenames)
305 msg.append("None of the installed packages claim these files:\n")
307 msg.append("\t%s\n" % (f,))
308 sys.stderr.write("".join(msg))
315 owners.uses_root = True
317 def is_protected(argv):
319 Given a single filename, return code 0 if it's protected, 1 otherwise.
320 The filename must begin with <root>.
323 sys.stderr.write("ERROR: expected 2 parameters, got %d!\n" % len(argv))
327 root, filename = argv
336 f = portage.normalize_path(filename)
337 if not f.startswith(os.path.sep):
339 err.write("ERROR: cwd does not exist!\n")
342 f = os.path.join(cwd, f)
343 f = portage.normalize_path(f)
345 if not f.startswith(root):
346 err.write("ERROR: file paths must begin with <root>!\n")
350 from portage.util import ConfigProtect
352 settings = portage.settings
353 protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", ""))
354 protect_mask = portage.util.shlex_split(
355 settings.get("CONFIG_PROTECT_MASK", ""))
356 protect_obj = ConfigProtect(root, protect, protect_mask)
358 if protect_obj.isprotected(f):
362 is_protected.uses_root = True
364 def filter_protected(argv):
366 Read filenames from stdin and write them to stdout if they are protected.
367 All filenames are delimited by \\n and must begin with <root>.
370 sys.stderr.write("ERROR: expected 1 parameter, got %d!\n" % len(argv))
383 from portage.util import ConfigProtect
385 settings = portage.settings
386 protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", ""))
387 protect_mask = portage.util.shlex_split(
388 settings.get("CONFIG_PROTECT_MASK", ""))
389 protect_obj = ConfigProtect(root, protect, protect_mask)
394 for line in sys.stdin:
395 filename = line.rstrip("\n")
396 f = portage.normalize_path(filename)
397 if not f.startswith(os.path.sep):
399 err.write("ERROR: cwd does not exist!\n")
403 f = os.path.join(cwd, f)
404 f = portage.normalize_path(f)
406 if not f.startswith(root):
407 err.write("ERROR: file paths must begin with <root>!\n")
412 if protect_obj.isprotected(f):
414 out.write("%s\n" % filename)
422 filter_protected.uses_root = True
424 def best_visible(argv):
425 """<root> [<category/package>]+
426 Returns category/package-version (without .ebuild).
429 print("ERROR: insufficient parameters!")
432 mylist=portage.db[argv[0]]["porttree"].dbapi.match(argv[1])
433 visible=portage.best(mylist)
441 best_visible.uses_root = True
444 def mass_best_visible(argv):
445 """<root> [<category/package>]+
446 Returns category/package-version (without .ebuild).
449 print("ERROR: insufficient parameters!")
452 for pack in argv[1:]:
453 mylist=portage.db[argv[0]]["porttree"].dbapi.match(pack)
454 print(pack+":"+portage.best(mylist))
457 mass_best_visible.uses_root = True
460 def all_best_visible(argv):
462 Returns all best_visible packages (without .ebuild).
465 print("ERROR: insufficient parameters!")
467 #print portage.db[argv[0]]["porttree"].dbapi.cp_all()
468 for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all():
469 mybest=portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg))
472 all_best_visible.uses_root = True
477 Returns a \\n separated list of category/package-version.
478 When given an empty string, all installed packages will
482 print("ERROR: expected 2 parameters, got %d!" % len(argv))
486 if atom_validate_strict and not portage.isvalidatom(atom):
487 portage.writemsg("ERROR: Invalid atom: '%s'\n" % atom,
490 results = portage.db[root]["vartree"].dbapi.match(atom)
492 results = portage.db[root]["vartree"].dbapi.cpv_all()
496 match.uses_root = True
498 def expand_virtual(argv):
500 Returns a \\n separated list of atoms expanded from a
501 given virtual atom, excluding blocker atoms. Satisfied
502 virtual atoms are not included in the output, since
503 they are expanded to real atoms which are displayed.
504 Unsatisfied virtual atoms are displayed without
505 any expansion. The "match" command can be used to
506 resolve the returned atoms to specific installed
510 writemsg("ERROR: expected 2 parameters, got %d!\n" % len(argv),
517 results = list(expand_new_virt(
518 portage.db[root]["vartree"].dbapi, atom))
519 except portage.exception.InvalidAtom:
520 writemsg("ERROR: Invalid atom: '%s'\n" % atom,
527 writemsg_stdout("%s\n" % (x,))
531 expand_virtual.uses_root = True
535 Returns the path used for the var(installed) package database for the
536 set environment/configuration options.
539 out.write(os.path.join(portage.settings["EROOT"], portage.VDB_PATH) + "\n")
543 def gentoo_mirrors(argv):
545 Returns the mirrors set to use in the portage configuration.
547 print(portage.settings["GENTOO_MIRRORS"])
552 Returns the PORTDIR path.
554 print(portage.settings["PORTDIR"])
557 def config_protect(argv):
559 Returns the CONFIG_PROTECT paths.
561 print(portage.settings["CONFIG_PROTECT"])
564 def config_protect_mask(argv):
566 Returns the CONFIG_PROTECT_MASK paths.
568 print(portage.settings["CONFIG_PROTECT_MASK"])
571 def portdir_overlay(argv):
573 Returns the PORTDIR_OVERLAY path.
575 print(portage.settings["PORTDIR_OVERLAY"])
580 Returns the PKGDIR path.
582 print(portage.settings["PKGDIR"])
587 Returns the DISTDIR path.
589 print(portage.settings["DISTDIR"])
594 Returns a specific environment variable as exists prior to ebuild.sh.
595 Similar to: emerge --verbose --info | egrep '^<variable>='
597 verbose = "-v" in argv
599 argv.pop(argv.index("-v"))
602 print("ERROR: insufficient parameters!")
607 print(arg +"='"+ portage.settings[arg] +"'")
609 print(portage.settings[arg])
613 Returns all repos with names (repo_name file) argv[0] = $ROOT
616 print("ERROR: insufficient parameters!")
618 print(" ".join(portage.db[argv[0]]["porttree"].dbapi.getRepositories()))
620 def get_repo_path(argv):
622 Returns the path to the repo named argv[1], argv[0] = $ROOT
625 print("ERROR: insufficient parameters!")
628 print(portage.db[argv[0]]["porttree"].dbapi.getRepositoryPath(arg))
630 def list_preserved_libs(argv):
632 Print a list of libraries preserved during a package update in the form
633 package: path. Returns 1 if no preserved libraries could be found,
638 print("ERROR: wrong number of arguments")
640 mylibs = portage.db[argv[0]]["vartree"].dbapi._plib_registry.getPreservedLibs()
643 for cpv in sorted(mylibs):
645 for path in mylibs[cpv]:
646 msg.append(' ' + path)
649 writemsg_stdout(''.join(msg), noiselevel=-1)
651 list_preserved_libs.uses_root = True
653 #-----------------------------------------------------------------------------
655 # DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED!
658 if not portage.const._ENABLE_PRESERVE_LIBS:
659 del list_preserved_libs
661 non_commands = frozenset(['elog', 'eval_atom_use',
662 'exithandler', 'expand_new_virt', 'main',
663 'usage', 'writemsg', 'writemsg_stdout'])
664 commands = sorted(k for k, v in globals().items() \
665 if k not in non_commands and isinstance(v, types.FunctionType))
668 print(">>> Portage information query tool")
669 print(">>> %s" % portage.VERSION)
670 print(">>> Usage: portageq <command> [<option> ...]")
672 print("Available commands:")
675 # Show our commands -- we do this by scanning the functions in this
676 # file, and formatting each functions documentation.
678 help_mode = '--help' in sys.argv
679 for name in commands:
681 obj = globals()[name]
686 print(" MISSING DOCUMENTATION!")
690 lines = doc.split("\n")
691 print(" " + name + " " + lines[0].strip())
692 if (len(sys.argv) > 1):
695 for line in lines[1:]:
696 print(" " + line.strip())
697 if (len(sys.argv) == 1):
698 print("\nRun portageq with --help for info")
700 atom_validate_strict = "EBUILD_PHASE" in os.environ
702 if atom_validate_strict:
703 eapi = os.environ.get('EAPI')
705 def elog(elog_funcname, lines):
706 cmd = "source '%s/isolated-functions.sh' ; " % \
707 os.environ["PORTAGE_BIN_PATH"]
709 cmd += "%s %s ; " % (elog_funcname, portage._shell_quote(line))
710 subprocess.call([portage.const.BASH_BINARY, "-c", cmd])
713 def elog(elog_funcname, lines):
718 nocolor = os.environ.get('NOCOLOR')
719 if nocolor in ('yes', 'true'):
720 portage.output.nocolor()
722 if "-h" in sys.argv or "--help" in sys.argv:
725 elif len(sys.argv) < 2:
727 sys.exit(os.EX_USAGE)
730 function = globals().get(cmd)
731 if function is None or cmd not in commands:
733 sys.exit(os.EX_USAGE)
734 function = globals()[cmd]
735 uses_root = getattr(function, "uses_root", False) and len(sys.argv) > 2
737 if not os.path.isdir(sys.argv[2]):
738 sys.stderr.write("Not a directory: '%s'\n" % sys.argv[2])
739 sys.stderr.write("Run portageq with --help for info\n")
741 sys.exit(os.EX_USAGE)
742 os.environ["ROOT"] = sys.argv[2]
745 if args and sys.hexversion < 0x3000000 and not isinstance(args[0], unicode):
746 for i in range(len(args)):
747 args[i] = portage._unicode_decode(args[i])
751 args[0] = portage.settings["ROOT"]
752 retval = function(args)
755 except portage.exception.PermissionDenied as e:
756 sys.stderr.write("Permission denied: '%s'\n" % str(e))
758 except portage.exception.ParseError as e:
759 sys.stderr.write("%s\n" % str(e))
761 except portage.exception.AmbiguousPackageName as e:
762 # Multiple matches thrown from cpv_expand
764 # An error has occurred so we writemsg to stderr and exit nonzero.
765 portage.writemsg("You specified an unqualified atom that matched multiple packages:\n", noiselevel=-1)
767 portage.writemsg("* %s\n" % pkg, noiselevel=-1)
768 portage.writemsg("\nPlease use a more specific atom.\n", noiselevel=-1)
773 #-----------------------------------------------------------------------------