Use EROOT instead of ROOT for keys everywhere.
[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         '_emerge.Package:Package',
49         '_emerge.RootConfig:RootConfig',
50         'portage.dbapi._expand_new_virt:expand_new_virt',
51         'portage._sets.base:InternalPackageSet',
52 )
53
54 def eval_atom_use(atom):
55         if 'USE' in os.environ:
56                 use = frozenset(os.environ['USE'].split())
57                 atom = atom.evaluate_conditionals(use)
58         return atom
59
60 #-----------------------------------------------------------------------------
61 #
62 # To add functionality to this tool, add a function below.
63 #
64 # The format for functions is:
65 #
66 #   def function(argv):
67 #       """<list of options for this function>
68 #       <description of the function>
69 #       """
70 #       <code>
71 #
72 # "argv" is an array of the command line parameters provided after the command.
73 #
74 # Make sure you document the function in the right format.  The documentation
75 # is used to display help on the function.
76 #
77 # You do not need to add the function to any lists, this tool is introspective,
78 # and will automaticly add a command by the same name as the function!
79 #
80
81 def has_version(argv):
82         """<root> <category/package>
83         Return code 0 if it's available, 1 otherwise.
84         """
85         if (len(argv) < 2):
86                 print("ERROR: insufficient parameters!")
87                 sys.exit(2)
88
89         warnings = []
90
91         try:
92                 atom = portage.dep.Atom(argv[1])
93         except portage.exception.InvalidAtom:
94                 if atom_validate_strict:
95                         portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
96                                 noiselevel=-1)
97                         return 2
98                 else:
99                         atom = argv[1]
100         else:
101                 if atom_validate_strict:
102                         try:
103                                 atom = portage.dep.Atom(argv[1], eapi=eapi)
104                         except portage.exception.InvalidAtom as e:
105                                 warnings.append(
106                                         portage._unicode_decode("QA Notice: %s: %s") % \
107                                         ('has_version', e))
108                 atom = eval_atom_use(atom)
109
110         if warnings:
111                 elog('eqawarn', warnings)
112
113         try:
114                 mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
115                 if mylist:
116                         sys.exit(0)
117                 else:
118                         sys.exit(1)
119         except KeyError:
120                 sys.exit(1)
121         except portage.exception.InvalidAtom:
122                 portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
123                         noiselevel=-1)
124                 return 2
125 has_version.uses_root = True
126
127
128 def best_version(argv):
129         """<root> <category/package>
130         Returns category/package-version (without .ebuild).
131         """
132         if (len(argv) < 2):
133                 print("ERROR: insufficient parameters!")
134                 sys.exit(2)
135
136         warnings = []
137
138         try:
139                 atom = portage.dep.Atom(argv[1])
140         except portage.exception.InvalidAtom:
141                 if atom_validate_strict:
142                         portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
143                                 noiselevel=-1)
144                         return 2
145                 else:
146                         atom = argv[1]
147         else:
148                 if atom_validate_strict:
149                         try:
150                                 atom = portage.dep.Atom(argv[1], eapi=eapi)
151                         except portage.exception.InvalidAtom as e:
152                                 warnings.append(
153                                         portage._unicode_decode("QA Notice: %s: %s") % \
154                                         ('best_version', e))
155                 atom = eval_atom_use(atom)
156
157         if warnings:
158                 elog('eqawarn', warnings)
159
160         try:
161                 mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
162                 print(portage.best(mylist))
163         except KeyError:
164                 sys.exit(1)
165 best_version.uses_root = True
166
167
168 def mass_best_version(argv):
169         """<root> [<category/package>]+
170         Returns category/package-version (without .ebuild).
171         """
172         if (len(argv) < 2):
173                 print("ERROR: insufficient parameters!")
174                 sys.exit(2)
175         try:
176                 for pack in argv[1:]:
177                         mylist=portage.db[argv[0]]["vartree"].dbapi.match(pack)
178                         print(pack+":"+portage.best(mylist))
179         except KeyError:
180                 sys.exit(1)
181 mass_best_version.uses_root = True
182
183 def metadata(argv):
184         if (len(argv) < 4):
185                 print("ERROR: insufficient parameters!", file=sys.stderr)
186                 sys.exit(2)
187
188         eroot, pkgtype, pkgspec = argv[0:3]
189         metakeys = argv[3:]
190         type_map = {
191                 "ebuild":"porttree",
192                 "binary":"bintree",
193                 "installed":"vartree"}
194         if pkgtype not in type_map:
195                 print("Unrecognized package type: '%s'" % pkgtype, file=sys.stderr)
196                 sys.exit(1)
197         trees = portage.db
198         try:
199                         values = trees[eroot][type_map[pkgtype]].dbapi.aux_get(
200                                 pkgspec, metakeys)
201                         writemsg_stdout(''.join('%s\n' % x for x in values), noiselevel=-1)
202         except KeyError:
203                 print("Package not found: '%s'" % pkgspec, file=sys.stderr)
204                 sys.exit(1)
205
206 metadata.__doc__ = """
207 <root> <pkgtype> <category/package> [<key>]+
208 Returns metadata values for the specified package.
209 Available keys: %s
210 """  % ','.join(sorted(x for x in portage.auxdbkeys \
211 if not x.startswith('UNUSED_')))
212
213 metadata.uses_root = True
214
215 def contents(argv):
216         """<root> <category/package>
217         List the files that are installed for a given package, with
218         one file listed on each line. All file names will begin with
219         <root>.
220         """
221         if len(argv) != 2:
222                 print("ERROR: expected 2 parameters, got %d!" % len(argv))
223                 return 2
224
225         root, cpv = argv
226         vartree = portage.db[root]["vartree"]
227         if not vartree.dbapi.cpv_exists(cpv):
228                 sys.stderr.write("Package not found: '%s'\n" % cpv)
229                 return 1
230         cat, pkg = portage.catsplit(cpv)
231         db = portage.dblink(cat, pkg, root, vartree.settings,
232                 treetype="vartree", vartree=vartree)
233         writemsg_stdout(''.join('%s\n' % x for x in sorted(db.getcontents())),
234                 noiselevel=-1)
235 contents.uses_root = True
236
237 def owners(argv):
238         """<root> [<filename>]+
239         Given a list of files, print the packages that own the files and which
240         files belong to each package. Files owned by a package are listed on
241         the lines below it, indented by a single tab character (\\t). All file
242         paths must either start with <root> or be a basename alone.
243         Returns 1 if no owners could be found, and 0 otherwise.
244         """
245         if len(argv) < 2:
246                 sys.stderr.write("ERROR: insufficient parameters!\n")
247                 sys.stderr.flush()
248                 return 2
249
250         from portage import catsplit, dblink
251         eroot = argv[0]
252         vardb = portage.db[eroot]["vartree"].dbapi
253         root = portage.settings['ROOT']
254
255         cwd = None
256         try:
257                 cwd = os.getcwd()
258         except OSError:
259                 pass
260
261         files = []
262         orphan_abs_paths = set()
263         orphan_basenames = set()
264         for f in argv[1:]:
265                 f = portage.normalize_path(f)
266                 is_basename = os.sep not in f
267                 if not is_basename and f[:1] != os.sep:
268                         if cwd is None:
269                                 sys.stderr.write("ERROR: cwd does not exist!\n")
270                                 sys.stderr.flush()
271                                 return 2
272                         f = os.path.join(cwd, f)
273                         f = portage.normalize_path(f)
274                 if not is_basename and not f.startswith(root):
275                         sys.stderr.write("ERROR: file paths must begin with <root>!\n")
276                         sys.stderr.flush()
277                         return 2
278                 if is_basename:
279                         files.append(f)
280                         orphan_basenames.add(f)
281                 else:
282                         files.append(f[len(root)-1:])
283                         orphan_abs_paths.add(f)
284
285         owners = vardb._owners.get_owners(files)
286
287         msg = []
288         for pkg, owned_files in owners.items():
289                 cpv = pkg.mycpv
290                 msg.append("%s\n" % cpv)
291                 for f in sorted(owned_files):
292                         f_abs = os.path.join(root, f.lstrip(os.path.sep))
293                         msg.append("\t%s\n" % (f_abs,))
294                         orphan_abs_paths.discard(f_abs)
295                         if orphan_basenames:
296                                 orphan_basenames.discard(os.path.basename(f_abs))
297
298         writemsg_stdout(''.join(msg), noiselevel=-1)
299
300         if orphan_abs_paths or orphan_basenames:
301                 orphans = []
302                 orphans.extend(orphan_abs_paths)
303                 orphans.extend(orphan_basenames)
304                 orphans.sort()
305                 msg = []
306                 msg.append("None of the installed packages claim these files:\n")
307                 for f in orphans:
308                         msg.append("\t%s\n" % (f,))
309                 sys.stderr.write("".join(msg))
310                 sys.stderr.flush()
311
312         if owners:
313                 return 0
314         return 1
315
316 owners.uses_root = True
317
318 def is_protected(argv):
319         """<root> <filename>
320         Given a single filename, return code 0 if it's protected, 1 otherwise.
321         The filename must begin with <root>.
322         """
323         if len(argv) != 2:
324                 sys.stderr.write("ERROR: expected 2 parameters, got %d!\n" % len(argv))
325                 sys.stderr.flush()
326                 return 2
327
328         root, filename = argv
329
330         err = sys.stderr
331         cwd = None
332         try:
333                 cwd = os.getcwd()
334         except OSError:
335                 pass
336
337         f = portage.normalize_path(filename)
338         if not f.startswith(os.path.sep):
339                 if cwd is None:
340                         err.write("ERROR: cwd does not exist!\n")
341                         err.flush()
342                         return 2
343                 f = os.path.join(cwd, f)
344                 f = portage.normalize_path(f)
345
346         if not f.startswith(root):
347                 err.write("ERROR: file paths must begin with <root>!\n")
348                 err.flush()
349                 return 2
350
351         from portage.util import ConfigProtect
352
353         settings = portage.settings
354         protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", ""))
355         protect_mask = portage.util.shlex_split(
356                 settings.get("CONFIG_PROTECT_MASK", ""))
357         protect_obj = ConfigProtect(root, protect, protect_mask)
358
359         if protect_obj.isprotected(f):
360                 return 0
361         return 1
362
363 is_protected.uses_root = True
364
365 def filter_protected(argv):
366         """<root>
367         Read filenames from stdin and write them to stdout if they are protected.
368         All filenames are delimited by \\n and must begin with <root>.
369         """
370         if len(argv) != 1:
371                 sys.stderr.write("ERROR: expected 1 parameter, got %d!\n" % len(argv))
372                 sys.stderr.flush()
373                 return 2
374
375         root, = argv
376         out = sys.stdout
377         err = sys.stderr
378         cwd = None
379         try:
380                 cwd = os.getcwd()
381         except OSError:
382                 pass
383
384         from portage.util import ConfigProtect
385
386         settings = portage.settings
387         protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", ""))
388         protect_mask = portage.util.shlex_split(
389                 settings.get("CONFIG_PROTECT_MASK", ""))
390         protect_obj = ConfigProtect(root, protect, protect_mask)
391
392         protected = 0
393         errors = 0
394
395         for line in sys.stdin:
396                 filename = line.rstrip("\n")
397                 f = portage.normalize_path(filename)
398                 if not f.startswith(os.path.sep):
399                         if cwd is None:
400                                 err.write("ERROR: cwd does not exist!\n")
401                                 err.flush()
402                                 errors += 1
403                                 continue
404                         f = os.path.join(cwd, f)
405                         f = portage.normalize_path(f)
406
407                 if not f.startswith(root):
408                         err.write("ERROR: file paths must begin with <root>!\n")
409                         err.flush()
410                         errors += 1
411                         continue
412
413                 if protect_obj.isprotected(f):
414                         protected += 1
415                         out.write("%s\n" % filename)
416         out.flush()
417
418         if errors:
419                 return 2
420
421         return 0
422
423 filter_protected.uses_root = True
424
425 def best_visible(argv):
426         """<root> [pkgtype] <atom>
427         Returns category/package-version (without .ebuild).
428         The pkgtype argument defaults to "ebuild" if unspecified,
429         otherwise it must be one of ebuild, binary, or installed.
430         """
431         if (len(argv) < 2):
432                 writemsg("ERROR: insufficient parameters!\n", noiselevel=-1)
433                 return 2
434
435         pkgtype = "ebuild"
436         if len(argv) > 2:
437                 pkgtype = argv[1]
438                 atom = argv[2]
439         else:
440                 atom = argv[1]
441
442         type_map = {
443                 "ebuild":"porttree",
444                 "binary":"bintree",
445                 "installed":"vartree"}
446
447         if pkgtype not in type_map:
448                 writemsg("Unrecognized package type: '%s'\n" % pkgtype,
449                         noiselevel=-1)
450                 return 2
451
452         eroot = argv[0]
453         db = portage.db[eroot][type_map[pkgtype]].dbapi
454
455         try:
456                 atom = portage.dep_expand(atom, mydb=db, settings=portage.settings)
457         except portage.exception.InvalidAtom:
458                 writemsg("ERROR: Invalid atom: '%s'\n" % atom,
459                         noiselevel=-1)
460                 return 2
461
462         root_config = RootConfig(portage.settings,
463                 portage.db[eroot], None)
464
465         if hasattr(db, "xmatch"):
466                 cpv_list = db.xmatch("match-all-cpv-only", atom)
467         else:
468                 cpv_list = db.match(atom)
469
470         if cpv_list:
471                 # reversed, for descending order
472                 cpv_list.reverse()
473                 # verify match, since the atom may match the package
474                 # for a given cpv from one repo but not another, and
475                 # we can use match-all-cpv-only to avoid redundant
476                 # metadata access.
477                 atom_set = InternalPackageSet(initial_atoms=(atom,))
478
479                 if atom.repo is None and hasattr(db, "getRepositories"):
480                         repo_list = db.getRepositories()
481                 else:
482                         repo_list = [atom.repo]
483
484                 for cpv in cpv_list:
485                         for repo in repo_list:
486                                 try:
487                                         metadata = dict(zip(Package.metadata_keys,
488                                                 db.aux_get(cpv, Package.metadata_keys, myrepo=repo)))
489                                 except KeyError:
490                                         continue
491                                 pkg = Package(built=(pkgtype != "ebuild"), cpv=cpv,
492                                         installed=(pkgtype=="installed"), metadata=metadata,
493                                         root_config=root_config, type_name=pkgtype)
494                                 if not atom_set.findAtomForPackage(pkg):
495                                         continue
496
497                                 if pkg.visible:
498                                         writemsg_stdout("%s\n" % (pkg.cpv,), noiselevel=-1)
499                                         return os.EX_OK
500
501         return 1
502 best_visible.uses_root = True
503
504
505 def mass_best_visible(argv):
506         """<root> [<category/package>]+
507         Returns category/package-version (without .ebuild).
508         """
509         if (len(argv) < 2):
510                 print("ERROR: insufficient parameters!")
511                 sys.exit(2)
512         try:
513                 for pack in argv[1:]:
514                         mylist=portage.db[argv[0]]["porttree"].dbapi.match(pack)
515                         print(pack+":"+portage.best(mylist))
516         except KeyError:
517                 sys.exit(1)
518 mass_best_visible.uses_root = True
519
520
521 def all_best_visible(argv):
522         """<root>
523         Returns all best_visible packages (without .ebuild).
524         """
525         if len(argv) < 1:
526                 sys.stderr.write("ERROR: insufficient parameters!\n")
527                 sys.stderr.flush()
528                 return 2
529
530         #print portage.db[argv[0]]["porttree"].dbapi.cp_all()
531         for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all():
532                 mybest=portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg))
533                 if mybest:
534                         print(mybest)
535 all_best_visible.uses_root = True
536
537
538 def match(argv):
539         """<root> <atom>
540         Returns a \\n separated list of category/package-version.
541         When given an empty string, all installed packages will
542         be listed.
543         """
544         if len(argv) != 2:
545                 print("ERROR: expected 2 parameters, got %d!" % len(argv))
546                 sys.exit(2)
547         root, atom = argv
548         if not atom:
549                 atom = "*/*"
550
551         vardb = portage.db[root]["vartree"].dbapi
552         try:
553                 atom = portage.dep.Atom(atom, allow_wildcard=True, allow_repo=True)
554         except portage.exception.InvalidAtom:
555                 # maybe it's valid but missing category
556                 atom = portage.dep_expand(atom, mydb=vardb, settings=vardb.settings)
557
558         if atom.extended_syntax:
559                 if atom == "*/*":
560                         results = vardb.cpv_all()
561                 else:
562                         results = []
563                         require_metadata = atom.slot or atom.repo
564                         for cpv in vardb.cpv_all():
565
566                                 if not portage.dep.extended_cp_match(
567                                         atom.cp, portage.cpv_getkey(cpv)):
568                                         continue
569
570                                 if require_metadata:
571                                         slot, repo = vardb.aux_get(cpv, ["SLOT", "repository"])
572
573                                         if atom.slot is not None and atom.slot != slot:
574                                                 continue
575
576                                         if atom.repo is not None and atom.repo != repo:
577                                                 continue
578
579                                 results.append(cpv)
580
581                 results.sort()
582         else:
583                 results = vardb.match(atom)
584         for cpv in results:
585                 print(cpv)
586 match.uses_root = True
587
588 def expand_virtual(argv):
589         """<root> <atom>
590         Returns a \\n separated list of atoms expanded from a
591         given virtual atom (GLEP 37 virtuals only),
592         excluding blocker atoms. Satisfied
593         virtual atoms are not included in the output, since
594         they are expanded to real atoms which are displayed.
595         Unsatisfied virtual atoms are displayed without
596         any expansion. The "match" command can be used to
597         resolve the returned atoms to specific installed
598         packages.
599         """
600         if len(argv) != 2:
601                 writemsg("ERROR: expected 2 parameters, got %d!\n" % len(argv),
602                         noiselevel=-1)
603                 return 2
604
605         root, atom = argv
606
607         try:
608                 results = list(expand_new_virt(
609                         portage.db[root]["vartree"].dbapi, atom))
610         except portage.exception.InvalidAtom:
611                 writemsg("ERROR: Invalid atom: '%s'\n" % atom,
612                         noiselevel=-1)
613                 return 2
614
615         results.sort()
616         for x in results:
617                 if not x.blocker:
618                         writemsg_stdout("%s\n" % (x,))
619
620         return os.EX_OK
621
622 expand_virtual.uses_root = True
623
624 def vdb_path(argv):
625         """
626         Returns the path used for the var(installed) package database for the
627         set environment/configuration options.
628         """
629         out = sys.stdout
630         out.write(os.path.join(portage.settings["EROOT"], portage.VDB_PATH) + "\n")
631         out.flush()
632         return os.EX_OK
633
634 def gentoo_mirrors(argv):
635         """
636         Returns the mirrors set to use in the portage configuration.
637         """
638         print(portage.settings["GENTOO_MIRRORS"])
639
640
641 def portdir(argv):
642         """
643         Returns the PORTDIR path.
644         """
645         print(portage.settings["PORTDIR"])
646
647
648 def config_protect(argv):
649         """
650         Returns the CONFIG_PROTECT paths.
651         """
652         print(portage.settings["CONFIG_PROTECT"])
653
654
655 def config_protect_mask(argv):
656         """
657         Returns the CONFIG_PROTECT_MASK paths.
658         """
659         print(portage.settings["CONFIG_PROTECT_MASK"])
660
661
662 def portdir_overlay(argv):
663         """
664         Returns the PORTDIR_OVERLAY path.
665         """
666         print(portage.settings["PORTDIR_OVERLAY"])
667
668
669 def pkgdir(argv):
670         """
671         Returns the PKGDIR path.
672         """
673         print(portage.settings["PKGDIR"])
674
675
676 def distdir(argv):
677         """
678         Returns the DISTDIR path.
679         """
680         print(portage.settings["DISTDIR"])
681
682
683 def envvar(argv):
684         """<variable>+
685         Returns a specific environment variable as exists prior to ebuild.sh.
686         Similar to: emerge --verbose --info | egrep '^<variable>='
687         """
688         verbose = "-v" in argv
689         if verbose:
690                 argv.pop(argv.index("-v"))
691
692         if len(argv) == 0:
693                 print("ERROR: insufficient parameters!")
694                 sys.exit(2)
695
696         for arg in argv:
697                 if verbose:
698                         print(arg +"='"+ portage.settings[arg] +"'")
699                 else:
700                         print(portage.settings[arg])
701
702 def get_repos(argv):
703         """<root>
704         Returns all repos with names (repo_name file) argv[0] = $ROOT
705         """
706         if len(argv) < 1:
707                 print("ERROR: insufficient parameters!")
708                 sys.exit(2)
709         print(" ".join(portage.db[argv[0]]["porttree"].dbapi.getRepositories()))
710
711 def get_repo_path(argv):
712         """<root> <repo_id>+
713         Returns the path to the repo named argv[1], argv[0] = $ROOT
714         """
715         if len(argv) < 2:
716                 print("ERROR: insufficient parameters!")
717                 sys.exit(2)
718         for arg in argv[1:]:
719                 path = portage.db[argv[0]]["porttree"].dbapi.getRepositoryPath(arg)
720                 if path is None:
721                         path = ""
722                 print(path)
723
724 def list_preserved_libs(argv):
725         """<root>
726         Print a list of libraries preserved during a package update in the form
727         package: path. Returns 1 if no preserved libraries could be found,
728         0 otherwise.
729         """
730
731         if len(argv) != 1:
732                 print("ERROR: wrong number of arguments")
733                 sys.exit(2)
734         mylibs = portage.db[argv[0]]["vartree"].dbapi._plib_registry.getPreservedLibs()
735         rValue = 1
736         msg = []
737         for cpv in sorted(mylibs):
738                 msg.append(cpv)
739                 for path in mylibs[cpv]:
740                         msg.append(' ' + path)
741                         rValue = 0
742                 msg.append('\n')
743         writemsg_stdout(''.join(msg), noiselevel=-1)
744         return rValue
745 list_preserved_libs.uses_root = True
746
747 #-----------------------------------------------------------------------------
748 #
749 # DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED!
750 #
751
752 if not portage.const._ENABLE_PRESERVE_LIBS:
753         del list_preserved_libs
754
755 non_commands = frozenset(['elog', 'eval_atom_use',
756         'exithandler', 'expand_new_virt', 'main',
757         'usage', 'writemsg', 'writemsg_stdout'])
758 commands = sorted(k for k, v in globals().items() \
759         if k not in non_commands and isinstance(v, types.FunctionType))
760
761 def usage(argv):
762         print(">>> Portage information query tool")
763         print(">>> %s" % portage.VERSION)
764         print(">>> Usage: portageq <command> [<option> ...]")
765         print("")
766         print("Available commands:")
767
768         #
769         # Show our commands -- we do this by scanning the functions in this
770         # file, and formatting each functions documentation.
771         #
772         help_mode = '--help' in sys.argv
773         for name in commands:
774                 # Drop non-functions
775                 obj = globals()[name]
776
777                 doc = obj.__doc__
778                 if (doc == None):
779                         print("   " + name)
780                         print("      MISSING DOCUMENTATION!")
781                         print("")
782                         continue
783
784                 lines = doc.lstrip("\n").split("\n")
785                 print("   " + name + " " + lines[0].strip())
786                 if (len(sys.argv) > 1):
787                         if (not help_mode):
788                                 lines = lines[:-1]
789                         for line in lines[1:]:
790                                 print("      " + line.strip())
791         if (len(sys.argv) == 1):
792                 print("\nRun portageq with --help for info")
793
794 atom_validate_strict = "EBUILD_PHASE" in os.environ
795 eapi = None
796 if atom_validate_strict:
797         eapi = os.environ.get('EAPI')
798
799         def elog(elog_funcname, lines):
800                 cmd = "source '%s/isolated-functions.sh' ; " % \
801                         os.environ["PORTAGE_BIN_PATH"]
802                 for line in lines:
803                         cmd += "%s %s ; " % (elog_funcname, portage._shell_quote(line))
804                 subprocess.call([portage.const.BASH_BINARY, "-c", cmd])
805
806 else:
807         def elog(elog_funcname, lines):
808                 pass
809
810 def main():
811
812         nocolor = os.environ.get('NOCOLOR')
813         if nocolor in ('yes', 'true'):
814                 portage.output.nocolor()
815
816         if len(sys.argv) < 2:
817                 usage(sys.argv)
818                 sys.exit(os.EX_USAGE)
819
820         for x in sys.argv:
821                 if x in ("-h", "--help"):
822                         usage(sys.argv)
823                         sys.exit(os.EX_OK)
824                 elif x == "--version":
825                         print("Portage", portage.VERSION)
826                         sys.exit(os.EX_OK)
827
828         cmd = sys.argv[1]
829         function = globals().get(cmd)
830         if function is None or cmd not in commands:
831                 usage(sys.argv)
832                 sys.exit(os.EX_USAGE)
833         function = globals()[cmd]
834         uses_root = getattr(function, "uses_root", False) and len(sys.argv) > 2
835         if uses_root:
836                 if not os.path.isdir(sys.argv[2]):
837                         sys.stderr.write("Not a directory: '%s'\n" % sys.argv[2])
838                         sys.stderr.write("Run portageq with --help for info\n")
839                         sys.stderr.flush()
840                         sys.exit(os.EX_USAGE)
841                 eprefix = os.environ.get("__PORTAGE_TEST_EPREFIX")
842                 eroot = portage.util.normalize_path(sys.argv[2])
843                 if eprefix:
844                         root = eroot[:1-len(eprefix)]
845                 else:
846                         root = eroot
847                 os.environ["ROOT"] = root
848
849         args = sys.argv[2:]
850         if args and sys.hexversion < 0x3000000 and not isinstance(args[0], unicode):
851                 for i in range(len(args)):
852                         args[i] = portage._unicode_decode(args[i])
853
854         try:
855                 if uses_root:
856                         args[0] = portage.settings['EROOT']
857                 retval = function(args)
858                 if retval:
859                         sys.exit(retval)
860         except portage.exception.PermissionDenied as e:
861                 sys.stderr.write("Permission denied: '%s'\n" % str(e))
862                 sys.exit(e.errno)
863         except portage.exception.ParseError as e:
864                 sys.stderr.write("%s\n" % str(e))
865                 sys.exit(1)
866         except portage.exception.AmbiguousPackageName as e:
867                 # Multiple matches thrown from cpv_expand
868                 pkgs = e.args[0]
869                 # An error has occurred so we writemsg to stderr and exit nonzero.
870                 portage.writemsg("You specified an unqualified atom that matched multiple packages:\n", noiselevel=-1)
871                 for pkg in pkgs:
872                         portage.writemsg("* %s\n" % pkg, noiselevel=-1)
873                 portage.writemsg("\nPlease use a more specific atom.\n", noiselevel=-1)
874                 sys.exit(1)
875
876 main()
877
878 #-----------------------------------------------------------------------------