92719fb5b6931b2d8de68d46189c03385c8c0940
[portage.git] / bin / portageq
1 #!/usr/bin/python -O
2 # Copyright 1999-2011 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4
5 from __future__ import print_function
6
7 import signal
8 import sys
9 # This block ensures that ^C interrupts are handled quietly.
10 try:
11
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)
16
17         signal.signal(signal.SIGINT, exithandler)
18         signal.signal(signal.SIGTERM, exithandler)
19
20 except KeyboardInterrupt:
21         sys.exit(128 + signal.SIGINT)
22
23 import os
24 import types
25
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))
35         del sandbox_write
36
37 try:
38         import portage
39 except ImportError:
40         sys.path.insert(0, pym_path)
41         import portage
42 del pym_path
43
44 from portage import os
45 from portage.util import writemsg, writemsg_stdout
46 portage.proxy.lazyimport.lazyimport(globals(),
47         'subprocess',
48         'portage.dbapi._expand_new_virt:expand_new_virt',
49 )
50
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)
55         return atom
56
57 #-----------------------------------------------------------------------------
58 #
59 # To add functionality to this tool, add a function below.
60 #
61 # The format for functions is:
62 #
63 #   def function(argv):
64 #       """<list of options for this function>
65 #       <description of the function>
66 #       """
67 #       <code>
68 #
69 # "argv" is an array of the command line parameters provided after the command.
70 #
71 # Make sure you document the function in the right format.  The documentation
72 # is used to display help on the function.
73 #
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!
76 #
77
78 def has_version(argv):
79         """<root> <category/package>
80         Return code 0 if it's available, 1 otherwise.
81         """
82         if (len(argv) < 2):
83                 print("ERROR: insufficient parameters!")
84                 sys.exit(2)
85
86         warnings = []
87
88         try:
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],
93                                 noiselevel=-1)
94                         return 2
95                 else:
96                         atom = argv[1]
97         else:
98                 if atom_validate_strict:
99                         try:
100                                 atom = portage.dep.Atom(argv[1], eapi=eapi)
101                         except portage.exception.InvalidAtom as e:
102                                 warnings.append(
103                                         portage._unicode_decode("QA Notice: %s: %s") % \
104                                         ('has_version', e))
105                 atom = eval_atom_use(atom)
106
107         if warnings:
108                 elog('eqawarn', warnings)
109
110         try:
111                 mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
112                 if mylist:
113                         sys.exit(0)
114                 else:
115                         sys.exit(1)
116         except KeyError:
117                 sys.exit(1)
118         except portage.exception.InvalidAtom:
119                 portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
120                         noiselevel=-1)
121                 return 2
122 has_version.uses_root = True
123
124
125 def best_version(argv):
126         """<root> <category/package>
127         Returns category/package-version (without .ebuild).
128         """
129         if (len(argv) < 2):
130                 print("ERROR: insufficient parameters!")
131                 sys.exit(2)
132
133         warnings = []
134
135         try:
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],
140                                 noiselevel=-1)
141                         return 2
142                 else:
143                         atom = argv[1]
144         else:
145                 if atom_validate_strict:
146                         try:
147                                 atom = portage.dep.Atom(argv[1], eapi=eapi)
148                         except portage.exception.InvalidAtom as e:
149                                 warnings.append(
150                                         portage._unicode_decode("QA Notice: %s: %s") % \
151                                         ('best_version', e))
152                 atom = eval_atom_use(atom)
153
154         if warnings:
155                 elog('eqawarn', warnings)
156
157         try:
158                 mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
159                 print(portage.best(mylist))
160         except KeyError:
161                 sys.exit(1)
162 best_version.uses_root = True
163
164
165 def mass_best_version(argv):
166         """<root> [<category/package>]+
167         Returns category/package-version (without .ebuild).
168         """
169         if (len(argv) < 2):
170                 print("ERROR: insufficient parameters!")
171                 sys.exit(2)
172         try:
173                 for pack in argv[1:]:
174                         mylist=portage.db[argv[0]]["vartree"].dbapi.match(pack)
175                         print(pack+":"+portage.best(mylist))
176         except KeyError:
177                 sys.exit(1)
178 mass_best_version.uses_root = True
179
180 def metadata(argv):
181         if (len(argv) < 4):
182                 print("ERROR: insufficient parameters!", file=sys.stderr)
183                 sys.exit(2)
184
185         root, pkgtype, pkgspec = argv[0:3]
186         metakeys = argv[3:]
187         type_map = {
188                 "ebuild":"porttree",
189                 "binary":"bintree",
190                 "installed":"vartree"}
191         if pkgtype not in type_map:
192                 print("Unrecognized package type: '%s'" % pkgtype, file=sys.stderr)
193                 sys.exit(1)
194         trees = portage.db
195         if os.path.realpath(root) == os.path.realpath(portage.settings["ROOT"]):
196                 root = portage.settings["ROOT"] # contains the normalized $ROOT
197         try:
198                         values = trees[root][type_map[pkgtype]].dbapi.aux_get(
199                                 pkgspec, metakeys)
200                         writemsg_stdout(''.join('%s\n' % x for x in values), noiselevel=-1)
201         except KeyError:
202                 print("Package not found: '%s'" % pkgspec, file=sys.stderr)
203                 sys.exit(1)
204
205 metadata.__doc__ = """
206 <root> <pkgtype> <category/package> [<key>]+
207 Returns metadata values for the specified package.
208 Available keys: %s
209 """  % ','.join(sorted(x for x in portage.auxdbkeys \
210 if not x.startswith('UNUSED_')))
211
212 metadata.uses_root = True
213
214 def contents(argv):
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
218         <root>.
219         """
220         if len(argv) != 2:
221                 print("ERROR: expected 2 parameters, got %d!" % len(argv))
222                 return 2
223
224         root, cpv = 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)
228                 return 1
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())),
233                 noiselevel=-1)
234 contents.uses_root = True
235
236 def owners(argv):
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.
243         """
244         if len(argv) < 2:
245                 sys.stderr.write("ERROR: insufficient parameters!\n")
246                 sys.stderr.flush()
247                 return 2
248
249         from portage import catsplit, dblink
250         settings = portage.settings
251         root = settings["ROOT"]
252         vardb = portage.db[root]["vartree"].dbapi
253
254         cwd = None
255         try:
256                 cwd = os.getcwd()
257         except OSError:
258                 pass
259
260         files = []
261         orphan_abs_paths = set()
262         orphan_basenames = set()
263         for f in argv[1:]:
264                 f = portage.normalize_path(f)
265                 is_basename = os.sep not in f
266                 if not is_basename and f[:1] != os.sep:
267                         if cwd is None:
268                                 sys.stderr.write("ERROR: cwd does not exist!\n")
269                                 sys.stderr.flush()
270                                 return 2
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")
275                         sys.stderr.flush()
276                         return 2
277                 if is_basename:
278                         files.append(f)
279                         orphan_basenames.add(f)
280                 else:
281                         files.append(f[len(root)-1:])
282                         orphan_abs_paths.add(f)
283
284         owners = vardb._owners.get_owners(files)
285
286         msg = []
287         for pkg, owned_files in owners.items():
288                 cpv = pkg.mycpv
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)
294                         if orphan_basenames:
295                                 orphan_basenames.discard(os.path.basename(f_abs))
296
297         writemsg_stdout(''.join(msg), noiselevel=-1)
298
299         if orphan_abs_paths or orphan_basenames:
300                 orphans = []
301                 orphans.extend(orphan_abs_paths)
302                 orphans.extend(orphan_basenames)
303                 orphans.sort()
304                 msg = []
305                 msg.append("None of the installed packages claim these files:\n")
306                 for f in orphans:
307                         msg.append("\t%s\n" % (f,))
308                 sys.stderr.write("".join(msg))
309                 sys.stderr.flush()
310
311         if owners:
312                 return 0
313         return 1
314
315 owners.uses_root = True
316
317 def is_protected(argv):
318         """<root> <filename>
319         Given a single filename, return code 0 if it's protected, 1 otherwise.
320         The filename must begin with <root>.
321         """
322         if len(argv) != 2:
323                 sys.stderr.write("ERROR: expected 2 parameters, got %d!\n" % len(argv))
324                 sys.stderr.flush()
325                 return 2
326
327         root, filename = argv
328
329         err = sys.stderr
330         cwd = None
331         try:
332                 cwd = os.getcwd()
333         except OSError:
334                 pass
335
336         f = portage.normalize_path(filename)
337         if not f.startswith(os.path.sep):
338                 if cwd is None:
339                         err.write("ERROR: cwd does not exist!\n")
340                         err.flush()
341                         return 2
342                 f = os.path.join(cwd, f)
343                 f = portage.normalize_path(f)
344
345         if not f.startswith(root):
346                 err.write("ERROR: file paths must begin with <root>!\n")
347                 err.flush()
348                 return 2
349
350         from portage.util import ConfigProtect
351
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)
357
358         if protect_obj.isprotected(f):
359                 return 0
360         return 1
361
362 is_protected.uses_root = True
363
364 def filter_protected(argv):
365         """<root>
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>.
368         """
369         if len(argv) != 1:
370                 sys.stderr.write("ERROR: expected 1 parameter, got %d!\n" % len(argv))
371                 sys.stderr.flush()
372                 return 2
373
374         root, = argv
375         out = sys.stdout
376         err = sys.stderr
377         cwd = None
378         try:
379                 cwd = os.getcwd()
380         except OSError:
381                 pass
382
383         from portage.util import ConfigProtect
384
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)
390
391         protected = 0
392         errors = 0
393
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):
398                         if cwd is None:
399                                 err.write("ERROR: cwd does not exist!\n")
400                                 err.flush()
401                                 errors += 1
402                                 continue
403                         f = os.path.join(cwd, f)
404                         f = portage.normalize_path(f)
405
406                 if not f.startswith(root):
407                         err.write("ERROR: file paths must begin with <root>!\n")
408                         err.flush()
409                         errors += 1
410                         continue
411
412                 if protect_obj.isprotected(f):
413                         protected += 1
414                         out.write("%s\n" % filename)
415         out.flush()
416
417         if errors:
418                 return 2
419
420         return 0
421
422 filter_protected.uses_root = True
423
424 def best_visible(argv):
425         """<root> [<category/package>]+
426         Returns category/package-version (without .ebuild).
427         """
428         if (len(argv) < 2):
429                 print("ERROR: insufficient parameters!")
430                 sys.exit(2)
431         try:
432                 mylist=portage.db[argv[0]]["porttree"].dbapi.match(argv[1])
433                 visible=portage.best(mylist)
434                 if visible:
435                         print(visible)
436                         sys.exit(0)
437                 else:
438                         sys.exit(1)
439         except KeyError:
440                 sys.exit(1)
441 best_visible.uses_root = True
442
443
444 def mass_best_visible(argv):
445         """<root> [<category/package>]+
446         Returns category/package-version (without .ebuild).
447         """
448         if (len(argv) < 2):
449                 print("ERROR: insufficient parameters!")
450                 sys.exit(2)
451         try:
452                 for pack in argv[1:]:
453                         mylist=portage.db[argv[0]]["porttree"].dbapi.match(pack)
454                         print(pack+":"+portage.best(mylist))
455         except KeyError:
456                 sys.exit(1)
457 mass_best_visible.uses_root = True
458
459
460 def all_best_visible(argv):
461         """<root>
462         Returns all best_visible packages (without .ebuild).
463         """
464         if (len(argv) < 1):
465                 print("ERROR: insufficient parameters!")
466         
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))
470                 if mybest:
471                         print(mybest)
472 all_best_visible.uses_root = True
473
474
475 def match(argv):
476         """<root> <atom>
477         Returns a \\n separated list of category/package-version.
478         When given an empty string, all installed packages will
479         be listed.
480         """
481         if len(argv) != 2:
482                 print("ERROR: expected 2 parameters, got %d!" % len(argv))
483                 sys.exit(2)
484         root, atom = argv
485         if atom:
486                 if atom_validate_strict and not portage.isvalidatom(atom):
487                         portage.writemsg("ERROR: Invalid atom: '%s'\n" % atom,
488                                 noiselevel=-1)
489                         return 2
490                 results = portage.db[root]["vartree"].dbapi.match(atom)
491         else:
492                 results = portage.db[root]["vartree"].dbapi.cpv_all()
493                 results.sort()
494         for cpv in results:
495                 print(cpv)
496 match.uses_root = True
497
498 def expand_virtual(argv):
499         """<root> <atom>
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
507         packages.
508         """
509         if len(argv) != 2:
510                 writemsg("ERROR: expected 2 parameters, got %d!\n" % len(argv),
511                         noiselevel=-1)
512                 return 2
513
514         root, atom = argv
515
516         try:
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,
521                         noiselevel=-1)
522                 return 2
523
524         results.sort()
525         for x in results:
526                 if not x.blocker:
527                         writemsg_stdout("%s\n" % (x,))
528
529         return os.EX_OK
530
531 expand_virtual.uses_root = True
532
533 def vdb_path(argv):
534         """
535         Returns the path used for the var(installed) package database for the
536         set environment/configuration options.
537         """
538         out = sys.stdout
539         out.write(os.path.join(portage.settings["EROOT"], portage.VDB_PATH) + "\n")
540         out.flush()
541         return os.EX_OK
542
543 def gentoo_mirrors(argv):
544         """
545         Returns the mirrors set to use in the portage configuration.
546         """
547         print(portage.settings["GENTOO_MIRRORS"])
548
549
550 def portdir(argv):
551         """
552         Returns the PORTDIR path.
553         """
554         print(portage.settings["PORTDIR"])
555
556
557 def config_protect(argv):
558         """
559         Returns the CONFIG_PROTECT paths.
560         """
561         print(portage.settings["CONFIG_PROTECT"])
562
563
564 def config_protect_mask(argv):
565         """
566         Returns the CONFIG_PROTECT_MASK paths.
567         """
568         print(portage.settings["CONFIG_PROTECT_MASK"])
569
570
571 def portdir_overlay(argv):
572         """
573         Returns the PORTDIR_OVERLAY path.
574         """
575         print(portage.settings["PORTDIR_OVERLAY"])
576
577
578 def pkgdir(argv):
579         """
580         Returns the PKGDIR path.
581         """
582         print(portage.settings["PKGDIR"])
583
584
585 def distdir(argv):
586         """
587         Returns the DISTDIR path.
588         """
589         print(portage.settings["DISTDIR"])
590
591
592 def envvar(argv):
593         """<variable>+
594         Returns a specific environment variable as exists prior to ebuild.sh.
595         Similar to: emerge --verbose --info | egrep '^<variable>='
596         """
597         verbose = "-v" in argv
598         if verbose:
599                 argv.pop(argv.index("-v"))
600
601         if len(argv) == 0:
602                 print("ERROR: insufficient parameters!")
603                 sys.exit(2)
604
605         for arg in argv:
606                 if verbose:
607                         print(arg +"='"+ portage.settings[arg] +"'")
608                 else:
609                         print(portage.settings[arg])
610
611 def get_repos(argv):
612         """<root>
613         Returns all repos with names (repo_name file) argv[0] = $ROOT
614         """
615         if len(argv) < 1:
616                 print("ERROR: insufficient parameters!")
617                 sys.exit(2)
618         print(" ".join(portage.db[argv[0]]["porttree"].dbapi.getRepositories()))
619
620 def get_repo_path(argv):
621         """<root> <repo_id>+
622         Returns the path to the repo named argv[1], argv[0] = $ROOT
623         """
624         if len(argv) < 2:
625                 print("ERROR: insufficient parameters!")
626                 sys.exit(2)
627         for arg in argv[1:]:
628                 print(portage.db[argv[0]]["porttree"].dbapi.getRepositoryPath(arg))
629
630 def list_preserved_libs(argv):
631         """<root>
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,
634         0 otherwise.
635         """
636
637         if len(argv) != 1:
638                 print("ERROR: wrong number of arguments")
639                 sys.exit(2)
640         mylibs = portage.db[argv[0]]["vartree"].dbapi._plib_registry.getPreservedLibs()
641         rValue = 1
642         msg = []
643         for cpv in sorted(mylibs):
644                 msg.append(cpv)
645                 for path in mylibs[cpv]:
646                         msg.append(' ' + path)
647                         rValue = 0
648                 msg.append('\n')
649         writemsg_stdout(''.join(msg), noiselevel=-1)
650         return rValue
651 list_preserved_libs.uses_root = True
652
653 #-----------------------------------------------------------------------------
654 #
655 # DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED!
656 #
657
658 if not portage.const._ENABLE_PRESERVE_LIBS:
659         del list_preserved_libs
660
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))
666
667 def usage(argv):
668         print(">>> Portage information query tool")
669         print(">>> %s" % portage.VERSION)
670         print(">>> Usage: portageq <command> [<option> ...]")
671         print("")
672         print("Available commands:")
673
674         #
675         # Show our commands -- we do this by scanning the functions in this
676         # file, and formatting each functions documentation.
677         #
678         help_mode = '--help' in sys.argv
679         for name in commands:
680                 # Drop non-functions
681                 obj = globals()[name]
682
683                 doc = obj.__doc__
684                 if (doc == None):
685                         print("   " + name)
686                         print("      MISSING DOCUMENTATION!")
687                         print("")
688                         continue
689
690                 lines = doc.split("\n")
691                 print("   " + name + " " + lines[0].strip())
692                 if (len(sys.argv) > 1):
693                         if (not help_mode):
694                                 lines = lines[:-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")
699
700 atom_validate_strict = "EBUILD_PHASE" in os.environ
701 eapi = None
702 if atom_validate_strict:
703         eapi = os.environ.get('EAPI')
704
705         def elog(elog_funcname, lines):
706                 cmd = "source '%s/isolated-functions.sh' ; " % \
707                         os.environ["PORTAGE_BIN_PATH"]
708                 for line in lines:
709                         cmd += "%s %s ; " % (elog_funcname, portage._shell_quote(line))
710                 subprocess.call([portage.const.BASH_BINARY, "-c", cmd])
711
712 else:
713         def elog(elog_funcname, lines):
714                 pass
715
716 def main():
717
718         nocolor = os.environ.get('NOCOLOR')
719         if nocolor in ('yes', 'true'):
720                 portage.output.nocolor()
721
722         if "-h" in sys.argv or "--help" in sys.argv:
723                 usage(sys.argv)
724                 sys.exit(os.EX_OK)
725         elif len(sys.argv) < 2:
726                 usage(sys.argv)
727                 sys.exit(os.EX_USAGE)
728
729         cmd = sys.argv[1]
730         function = globals().get(cmd)
731         if function is None or cmd not in commands:
732                 usage(sys.argv)
733                 sys.exit(os.EX_USAGE)
734         function = globals()[cmd]
735         uses_root = getattr(function, "uses_root", False) and len(sys.argv) > 2
736         if uses_root:
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")
740                         sys.stderr.flush()
741                         sys.exit(os.EX_USAGE)
742                 os.environ["ROOT"] = sys.argv[2]
743
744         args = 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])
748
749         try:
750                 if uses_root:
751                         args[0] = portage.settings["ROOT"]
752                 retval = function(args)
753                 if retval:
754                         sys.exit(retval)
755         except portage.exception.PermissionDenied as e:
756                 sys.stderr.write("Permission denied: '%s'\n" % str(e))
757                 sys.exit(e.errno)
758         except portage.exception.ParseError as e:
759                 sys.stderr.write("%s\n" % str(e))
760                 sys.exit(1)
761         except portage.exception.AmbiguousPackageName as e:
762                 # Multiple matches thrown from cpv_expand
763                 pkgs = e.args[0]
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)
766                 for pkg in pkgs:
767                         portage.writemsg("* %s\n" % pkg, noiselevel=-1)
768                 portage.writemsg("\nPlease use a more specific atom.\n", noiselevel=-1)
769                 sys.exit(1)
770
771 main()
772
773 #-----------------------------------------------------------------------------