emerge: portage.util._argparse
[portage.git] / pym / _emerge / main.py
1 # Copyright 1999-2013 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 from __future__ import print_function
5
6 import platform
7 import sys
8
9 import portage
10 portage.proxy.lazyimport.lazyimport(globals(),
11         'logging',
12         'portage.dep:Atom',
13         'portage.util:writemsg_level',
14         'textwrap',
15         '_emerge.actions:load_emerge_config,run_action,' + \
16                 'validate_ebuild_environment',
17         '_emerge.help:help@emerge_help',
18         '_emerge.is_valid_package_atom:insert_category_into_atom'
19 )
20 from portage import os
21 from portage.util._argparse import ArgumentParser
22
23 if sys.hexversion >= 0x3000000:
24         long = int
25
26 options=[
27 "--alphabetical",
28 "--ask-enter-invalid",
29 "--buildpkgonly",
30 "--changed-use",
31 "--changelog",    "--columns",
32 "--debug",
33 "--digest",
34 "--emptytree",
35 "--fetchonly",    "--fetch-all-uri",
36 "--ignore-default-opts",
37 "--noconfmem",
38 "--newuse",
39 "--nodeps",       "--noreplace",
40 "--nospinner",    "--oneshot",
41 "--onlydeps",     "--pretend",
42 "--quiet-repo-display",
43 "--quiet-unmerge-warn",
44 "--resume",
45 "--searchdesc",
46 "--skipfirst",
47 "--tree",
48 "--unordered-display",
49 "--update",
50 "--verbose-main-repo-display",
51 ]
52
53 shortmapping={
54 "1":"--oneshot",
55 "B":"--buildpkgonly",
56 "c":"--depclean",
57 "C":"--unmerge",
58 "d":"--debug",
59 "e":"--emptytree",
60 "f":"--fetchonly", "F":"--fetch-all-uri",
61 "h":"--help",
62 "l":"--changelog",
63 "n":"--noreplace", "N":"--newuse",
64 "o":"--onlydeps",  "O":"--nodeps",
65 "p":"--pretend",   "P":"--prune",
66 "r":"--resume",
67 "s":"--search",    "S":"--searchdesc",
68 "t":"--tree",
69 "u":"--update",
70 "V":"--version"
71 }
72
73 COWSAY_MOO = """
74
75   Larry loves Gentoo (%s)
76
77  _______________________
78 < Have you mooed today? >
79  -----------------------
80         \   ^__^
81          \  (oo)\_______
82             (__)\       )\/\ 
83                 ||----w |
84                 ||     ||
85
86 """
87
88 def multiple_actions(action1, action2):
89         sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
90         sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
91         sys.exit(1)
92
93 def insert_optional_args(args):
94         """
95         Parse optional arguments and insert a value if one has
96         not been provided. This is done before feeding the args
97         to the optparse parser since that parser does not support
98         this feature natively.
99         """
100
101         class valid_integers(object):
102                 def __contains__(self, s):
103                         try:
104                                 return int(s) >= 0
105                         except (ValueError, OverflowError):
106                                 return False
107
108         valid_integers = valid_integers()
109
110         class valid_floats(object):
111                 def __contains__(self, s):
112                         try:
113                                 return float(s) >= 0
114                         except (ValueError, OverflowError):
115                                 return False
116
117         valid_floats = valid_floats()
118
119         y_or_n = ('y', 'n',)
120
121         new_args = []
122
123         default_arg_opts = {
124                 '--ask'                  : y_or_n,
125                 '--autounmask'           : y_or_n,
126                 '--autounmask-keep-masks': y_or_n,
127                 '--autounmask-unrestricted-atoms' : y_or_n,
128                 '--autounmask-write'     : y_or_n,
129                 '--buildpkg'             : y_or_n,
130                 '--complete-graph'       : y_or_n,
131                 '--deep'       : valid_integers,
132                 '--depclean-lib-check'   : y_or_n,
133                 '--deselect'             : y_or_n,
134                 '--binpkg-respect-use'   : y_or_n,
135                 '--fail-clean'           : y_or_n,
136                 '--getbinpkg'            : y_or_n,
137                 '--getbinpkgonly'        : y_or_n,
138                 '--jobs'       : valid_integers,
139                 '--keep-going'           : y_or_n,
140                 '--load-average'         : valid_floats,
141                 '--package-moves'        : y_or_n,
142                 '--quiet'                : y_or_n,
143                 '--quiet-build'          : y_or_n,
144                 '--quiet-fail'           : y_or_n,
145                 '--rebuild-if-new-slot': y_or_n,
146                 '--rebuild-if-new-rev'   : y_or_n,
147                 '--rebuild-if-new-ver'   : y_or_n,
148                 '--rebuild-if-unbuilt'   : y_or_n,
149                 '--rebuilt-binaries'     : y_or_n,
150                 '--root-deps'  : ('rdeps',),
151                 '--select'               : y_or_n,
152                 '--selective'            : y_or_n,
153                 "--use-ebuild-visibility": y_or_n,
154                 '--usepkg'               : y_or_n,
155                 '--usepkgonly'           : y_or_n,
156                 '--verbose'              : y_or_n,
157         }
158
159         short_arg_opts = {
160                 'D' : valid_integers,
161                 'j' : valid_integers,
162         }
163
164         # Don't make things like "-kn" expand to "-k n"
165         # since existence of -n makes it too ambiguous.
166         short_arg_opts_n = {
167                 'a' : y_or_n,
168                 'b' : y_or_n,
169                 'g' : y_or_n,
170                 'G' : y_or_n,
171                 'k' : y_or_n,
172                 'K' : y_or_n,
173                 'q' : y_or_n,
174                 'v' : y_or_n,
175                 'w' : y_or_n,
176         }
177
178         arg_stack = args[:]
179         arg_stack.reverse()
180         while arg_stack:
181                 arg = arg_stack.pop()
182
183                 default_arg_choices = default_arg_opts.get(arg)
184                 if default_arg_choices is not None:
185                         new_args.append(arg)
186                         if arg_stack and arg_stack[-1] in default_arg_choices:
187                                 new_args.append(arg_stack.pop())
188                         else:
189                                 # insert default argument
190                                 new_args.append('True')
191                         continue
192
193                 if arg[:1] != "-" or arg[:2] == "--":
194                         new_args.append(arg)
195                         continue
196
197                 match = None
198                 for k, arg_choices in short_arg_opts.items():
199                         if k in arg:
200                                 match = k
201                                 break
202
203                 if match is None:
204                         for k, arg_choices in short_arg_opts_n.items():
205                                 if k in arg:
206                                         match = k
207                                         break
208
209                 if match is None:
210                         new_args.append(arg)
211                         continue
212
213                 if len(arg) == 2:
214                         new_args.append(arg)
215                         if arg_stack and arg_stack[-1] in arg_choices:
216                                 new_args.append(arg_stack.pop())
217                         else:
218                                 # insert default argument
219                                 new_args.append('True')
220                         continue
221
222                 # Insert an empty placeholder in order to
223                 # satisfy the requirements of optparse.
224
225                 new_args.append("-" + match)
226                 opt_arg = None
227                 saved_opts = None
228
229                 if arg[1:2] == match:
230                         if match not in short_arg_opts_n and arg[2:] in arg_choices:
231                                 opt_arg = arg[2:]
232                         else:
233                                 saved_opts = arg[2:]
234                                 opt_arg = "True"
235                 else:
236                         saved_opts = arg[1:].replace(match, "")
237                         opt_arg = "True"
238
239                 if opt_arg is None and arg_stack and \
240                         arg_stack[-1] in arg_choices:
241                         opt_arg = arg_stack.pop()
242
243                 if opt_arg is None:
244                         new_args.append("True")
245                 else:
246                         new_args.append(opt_arg)
247
248                 if saved_opts is not None:
249                         # Recycle these on arg_stack since they
250                         # might contain another match.
251                         arg_stack.append("-" + saved_opts)
252
253         return new_args
254
255 def _find_bad_atoms(atoms, less_strict=False):
256         """
257         Declares all atoms as invalid that have an operator,
258         a use dependency, a blocker or a repo spec.
259         It accepts atoms with wildcards.
260         In less_strict mode it accepts operators and repo specs.
261         """
262         bad_atoms = []
263         for x in ' '.join(atoms).split():
264                 atom = x
265                 if "/" not in x.split(":")[0]:
266                         x_cat = insert_category_into_atom(x, 'dummy-category')
267                         if x_cat is not None:
268                                 atom = x_cat
269
270                 bad_atom = False
271                 try:
272                         atom = Atom(atom, allow_wildcard=True, allow_repo=less_strict)
273                 except portage.exception.InvalidAtom:
274                         bad_atom = True
275
276                 if bad_atom or (atom.operator and not less_strict) or atom.blocker or atom.use:
277                         bad_atoms.append(x)
278         return bad_atoms
279
280
281 def parse_opts(tmpcmdline, silent=False):
282         myaction=None
283         myopts = {}
284         myfiles=[]
285
286         actions = frozenset([
287                 "clean", "check-news", "config", "depclean", "help",
288                 "info", "list-sets", "metadata", "moo",
289                 "prune", "regen",  "search",
290                 "sync",  "unmerge", "version",
291         ])
292
293         longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
294         y_or_n = ("y", "n")
295         true_y_or_n = ("True", "y", "n")
296         true_y = ("True", "y")
297         argument_options = {
298
299                 "--ask": {
300                         "shortopt" : "-a",
301                         "help"    : "prompt before performing any actions",
302                         "choices" : true_y_or_n
303                 },
304
305                 "--autounmask": {
306                         "help"    : "automatically unmask packages",
307                         "choices" : true_y_or_n
308                 },
309
310                 "--autounmask-unrestricted-atoms": {
311                         "help"    : "write autounmask changes with >= atoms if possible",
312                         "choices" : true_y_or_n
313                 },
314
315                 "--autounmask-keep-masks": {
316                         "help"    : "don't add package.unmask entries",
317                         "choices" : true_y_or_n
318                 },
319
320                 "--autounmask-write": {
321                         "help"    : "write changes made by --autounmask to disk",
322                         "choices" : true_y_or_n
323                 },
324
325                 "--accept-properties": {
326                         "help":"temporarily override ACCEPT_PROPERTIES",
327                         "action":"store"
328                 },
329
330                 "--accept-restrict": {
331                         "help":"temporarily override ACCEPT_RESTRICT",
332                         "action":"store"
333                 },
334
335                 "--backtrack": {
336
337                         "help"   : "Specifies how many times to backtrack if dependency " + \
338                                 "calculation fails ",
339
340                         "action" : "store"
341                 },
342
343                 "--buildpkg": {
344                         "shortopt" : "-b",
345                         "help"     : "build binary packages",
346                         "choices"  : true_y_or_n
347                 },
348
349                 "--buildpkg-exclude": {
350                         "help"   :"A space separated list of package atoms for which " + \
351                                 "no binary packages should be built. This option overrides all " + \
352                                 "possible ways to enable building of binary packages.",
353
354                         "action" : "append"
355                 },
356
357                 "--config-root": {
358                         "help":"specify the location for portage configuration files",
359                         "action":"store"
360                 },
361                 "--color": {
362                         "help":"enable or disable color output",
363                         "choices":("y", "n")
364                 },
365
366                 "--complete-graph": {
367                         "help"    : "completely account for all known dependencies",
368                         "choices" : true_y_or_n
369                 },
370
371                 "--complete-graph-if-new-use": {
372                         "help"    : "trigger --complete-graph behavior if USE or IUSE will change for an installed package",
373                         "choices" : y_or_n
374                 },
375
376                 "--complete-graph-if-new-ver": {
377                         "help"    : "trigger --complete-graph behavior if an installed package version will change (upgrade or downgrade)",
378                         "choices" : y_or_n
379                 },
380
381                 "--deep": {
382
383                         "shortopt" : "-D",
384
385                         "help"   : "Specifies how deep to recurse into dependencies " + \
386                                 "of packages given as arguments. If no argument is given, " + \
387                                 "depth is unlimited. Default behavior is to skip " + \
388                                 "dependencies of installed packages.",
389
390                         "action" : "store"
391                 },
392
393                 "--depclean-lib-check": {
394                         "help"    : "check for consumers of libraries before removing them",
395                         "choices" : true_y_or_n
396                 },
397
398                 "--deselect": {
399                         "help"    : "remove atoms/sets from the world file",
400                         "choices" : true_y_or_n
401                 },
402
403                 "--dynamic-deps": {
404                         "help": "substitute the dependencies of installed packages with the dependencies of unbuilt ebuilds",
405                         "choices": y_or_n
406                 },
407
408                 "--exclude": {
409                         "help"   :"A space separated list of package names or slot atoms. " + \
410                                 "Emerge won't  install any ebuild or binary package that " + \
411                                 "matches any of the given package atoms.",
412
413                         "action" : "append"
414                 },
415
416                 "--fail-clean": {
417                         "help"    : "clean temp files after build failure",
418                         "choices" : true_y_or_n
419                 },
420
421                 "--ignore-built-slot-operator-deps": {
422                         "help": "Ignore the slot/sub-slot := operator parts of dependencies that have "
423                                 "been recorded when packages where built. This option is intended "
424                                 "only for debugging purposes, and it only affects built packages "
425                                 "that specify slot/sub-slot := operator dependencies using the "
426                                 "experimental \"4-slot-abi\" EAPI.",
427                         "choices": y_or_n
428                 },
429
430                 "--jobs": {
431
432                         "shortopt" : "-j",
433
434                         "help"   : "Specifies the number of packages to build " + \
435                                 "simultaneously.",
436
437                         "action" : "store"
438                 },
439
440                 "--keep-going": {
441                         "help"    : "continue as much as possible after an error",
442                         "choices" : true_y_or_n
443                 },
444
445                 "--load-average": {
446
447                         "help"   :"Specifies that no new builds should be started " + \
448                                 "if there are other builds running and the load average " + \
449                                 "is at least LOAD (a floating-point number).",
450
451                         "action" : "store"
452                 },
453
454                 "--misspell-suggestions": {
455                         "help"    : "enable package name misspell suggestions",
456                         "choices" : ("y", "n")
457                 },
458
459                 "--with-bdeps": {
460                         "help":"include unnecessary build time dependencies",
461                         "choices":("y", "n")
462                 },
463                 "--reinstall": {
464                         "help":"specify conditions to trigger package reinstallation",
465                         "choices":["changed-use"]
466                 },
467
468                 "--reinstall-atoms": {
469                         "help"   :"A space separated list of package names or slot atoms. " + \
470                                 "Emerge will treat matching packages as if they are not " + \
471                                 "installed, and reinstall them if necessary. Implies --deep.",
472
473                         "action" : "append",
474                 },
475
476                 "--binpkg-respect-use": {
477                         "help"    : "discard binary packages if their use flags \
478                                 don't match the current configuration",
479                         "choices" : true_y_or_n
480                 },
481
482                 "--getbinpkg": {
483                         "shortopt" : "-g",
484                         "help"     : "fetch binary packages",
485                         "choices"  : true_y_or_n
486                 },
487
488                 "--getbinpkgonly": {
489                         "shortopt" : "-G",
490                         "help"     : "fetch binary packages only",
491                         "choices"  : true_y_or_n
492                 },
493
494                 "--usepkg-exclude": {
495                         "help"   :"A space separated list of package names or slot atoms. " + \
496                                 "Emerge will ignore matching binary packages. ",
497
498                         "action" : "append",
499                 },
500
501                 "--rebuild-exclude": {
502                         "help"   :"A space separated list of package names or slot atoms. " + \
503                                 "Emerge will not rebuild these packages due to the " + \
504                                 "--rebuild flag. ",
505
506                         "action" : "append",
507                 },
508
509                 "--rebuild-ignore": {
510                         "help"   :"A space separated list of package names or slot atoms. " + \
511                                 "Emerge will not rebuild packages that depend on matching " + \
512                                 "packages due to the --rebuild flag. ",
513
514                         "action" : "append",
515                 },
516
517                 "--package-moves": {
518                         "help"     : "perform package moves when necessary",
519                         "choices"  : true_y_or_n
520                 },
521
522                 "--prefix": {
523                         "help"     : "specify the installation prefix",
524                         "action"   : "store"
525                 },
526
527                 "--pkg-format": {
528                         "help"     : "format of result binary package",
529                         "action"   : "store",
530                 },
531
532                 "--quiet": {
533                         "shortopt" : "-q",
534                         "help"     : "reduced or condensed output",
535                         "choices"  : true_y_or_n
536                 },
537
538                 "--quiet-build": {
539                         "help"     : "redirect build output to logs",
540                         "choices"  : true_y_or_n,
541                 },
542
543                 "--quiet-fail": {
544                         "help"     : "suppresses display of the build log on stdout",
545                         "choices"  : true_y_or_n,
546                 },
547
548                 "--rebuild-if-new-slot": {
549                         "help"     : ("Automatically rebuild or reinstall packages when slot/sub-slot := "
550                                 "operator dependencies can be satisfied by a newer slot, so that "
551                                 "older packages slots will become eligible for removal by the "
552                                 "--depclean action as soon as possible."),
553                         "choices"  : true_y_or_n
554                 },
555
556                 "--rebuild-if-new-rev": {
557                         "help"     : "Rebuild packages when dependencies that are " + \
558                                 "used at both build-time and run-time are built, " + \
559                                 "if the dependency is not already installed with the " + \
560                                 "same version and revision.",
561                         "choices"  : true_y_or_n
562                 },
563
564                 "--rebuild-if-new-ver": {
565                         "help"     : "Rebuild packages when dependencies that are " + \
566                                 "used at both build-time and run-time are built, " + \
567                                 "if the dependency is not already installed with the " + \
568                                 "same version. Revision numbers are ignored.",
569                         "choices"  : true_y_or_n
570                 },
571
572                 "--rebuild-if-unbuilt": {
573                         "help"     : "Rebuild packages when dependencies that are " + \
574                                 "used at both build-time and run-time are built.",
575                         "choices"  : true_y_or_n
576                 },
577
578                 "--rebuilt-binaries": {
579                         "help"     : "replace installed packages with binary " + \
580                                      "packages that have been rebuilt",
581                         "choices"  : true_y_or_n
582                 },
583                 
584                 "--rebuilt-binaries-timestamp": {
585                         "help"   : "use only binaries that are newer than this " + \
586                                    "timestamp for --rebuilt-binaries",
587                         "action" : "store"
588                 },
589
590                 "--root": {
591                  "help"   : "specify the target root filesystem for merging packages",
592                  "action" : "store"
593                 },
594
595                 "--root-deps": {
596                         "help"    : "modify interpretation of depedencies",
597                         "choices" :("True", "rdeps")
598                 },
599
600                 "--select": {
601                         "shortopt" : "-w",
602                         "help"    : "add specified packages to the world set " + \
603                                     "(inverse of --oneshot)",
604                         "choices" : true_y_or_n
605                 },
606
607                 "--selective": {
608                         "help"    : "identical to --noreplace",
609                         "choices" : true_y_or_n
610                 },
611
612                 "--use-ebuild-visibility": {
613                         "help"     : "use unbuilt ebuild metadata for visibility checks on built packages",
614                         "choices"  : true_y_or_n
615                 },
616
617                 "--useoldpkg-atoms": {
618                         "help"   :"A space separated list of package names or slot atoms. " + \
619                                 "Emerge will prefer matching binary packages over newer unbuilt packages. ",
620
621                         "action" : "append",
622                 },
623
624                 "--usepkg": {
625                         "shortopt" : "-k",
626                         "help"     : "use binary packages",
627                         "choices"  : true_y_or_n
628                 },
629
630                 "--usepkgonly": {
631                         "shortopt" : "-K",
632                         "help"     : "use only binary packages",
633                         "choices"  : true_y_or_n
634                 },
635
636                 "--verbose": {
637                         "shortopt" : "-v",
638                         "help"     : "verbose output",
639                         "choices"  : true_y_or_n
640                 },
641         }
642
643         parser = ArgumentParser(add_help=False)
644
645         for action_opt in actions:
646                 parser.add_argument("--" + action_opt, action="store_true",
647                         dest=action_opt.replace("-", "_"), default=False)
648         for myopt in options:
649                 parser.add_argument(myopt, action="store_true",
650                         dest=myopt.lstrip("--").replace("-", "_"), default=False)
651         for shortopt, longopt in shortmapping.items():
652                 parser.add_argument("-" + shortopt, action="store_true",
653                         dest=longopt.lstrip("--").replace("-", "_"), default=False)
654         for myalias, myopt in longopt_aliases.items():
655                 parser.add_argument(myalias, action="store_true",
656                         dest=myopt.lstrip("--").replace("-", "_"), default=False)
657
658         for myopt, kwargs in argument_options.items():
659                 shortopt = kwargs.pop("shortopt", None)
660                 args = [myopt]
661                 if shortopt is not None:
662                         args.append(shortopt)
663                 parser.add_argument(dest=myopt.lstrip("--").replace("-", "_"),
664                         *args, **kwargs)
665
666         tmpcmdline = insert_optional_args(tmpcmdline)
667
668         myoptions, myargs = parser.parse_known_args(args=tmpcmdline)
669
670         if myoptions.ask in true_y:
671                 myoptions.ask = True
672         else:
673                 myoptions.ask = None
674
675         if myoptions.autounmask in true_y:
676                 myoptions.autounmask = True
677
678         if myoptions.autounmask_unrestricted_atoms in true_y:
679                 myoptions.autounmask_unrestricted_atoms = True
680
681         if myoptions.autounmask_keep_masks in true_y:
682                 myoptions.autounmask_keep_masks = True
683
684         if myoptions.autounmask_write in true_y:
685                 myoptions.autounmask_write = True
686
687         if myoptions.buildpkg in true_y:
688                 myoptions.buildpkg = True
689
690         if myoptions.buildpkg_exclude:
691                 bad_atoms = _find_bad_atoms(myoptions.buildpkg_exclude, less_strict=True)
692                 if bad_atoms and not silent:
693                         parser.error("Invalid Atom(s) in --buildpkg-exclude parameter: '%s'\n" % \
694                                 (",".join(bad_atoms),))
695
696         if myoptions.changed_use is not False:
697                 myoptions.reinstall = "changed-use"
698                 myoptions.changed_use = False
699
700         if myoptions.deselect in true_y:
701                 myoptions.deselect = True
702
703         if myoptions.binpkg_respect_use is not None:
704                 if myoptions.binpkg_respect_use in true_y:
705                         myoptions.binpkg_respect_use = 'y'
706                 else:
707                         myoptions.binpkg_respect_use = 'n'
708
709         if myoptions.complete_graph in true_y:
710                 myoptions.complete_graph = True
711         else:
712                 myoptions.complete_graph = None
713
714         if myoptions.depclean_lib_check in true_y:
715                 myoptions.depclean_lib_check = True
716
717         if myoptions.exclude:
718                 bad_atoms = _find_bad_atoms(myoptions.exclude)
719                 if bad_atoms and not silent:
720                         parser.error("Invalid Atom(s) in --exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
721                                 (",".join(bad_atoms),))
722
723         if myoptions.reinstall_atoms:
724                 bad_atoms = _find_bad_atoms(myoptions.reinstall_atoms)
725                 if bad_atoms and not silent:
726                         parser.error("Invalid Atom(s) in --reinstall-atoms parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
727                                 (",".join(bad_atoms),))
728
729         if myoptions.rebuild_exclude:
730                 bad_atoms = _find_bad_atoms(myoptions.rebuild_exclude)
731                 if bad_atoms and not silent:
732                         parser.error("Invalid Atom(s) in --rebuild-exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
733                                 (",".join(bad_atoms),))
734
735         if myoptions.rebuild_ignore:
736                 bad_atoms = _find_bad_atoms(myoptions.rebuild_ignore)
737                 if bad_atoms and not silent:
738                         parser.error("Invalid Atom(s) in --rebuild-ignore parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
739                                 (",".join(bad_atoms),))
740
741         if myoptions.usepkg_exclude:
742                 bad_atoms = _find_bad_atoms(myoptions.usepkg_exclude)
743                 if bad_atoms and not silent:
744                         parser.error("Invalid Atom(s) in --usepkg-exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
745                                 (",".join(bad_atoms),))
746
747         if myoptions.useoldpkg_atoms:
748                 bad_atoms = _find_bad_atoms(myoptions.useoldpkg_atoms)
749                 if bad_atoms and not silent:
750                         parser.error("Invalid Atom(s) in --useoldpkg-atoms parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
751                                 (",".join(bad_atoms),))
752
753         if myoptions.fail_clean in true_y:
754                 myoptions.fail_clean = True
755
756         if myoptions.getbinpkg in true_y:
757                 myoptions.getbinpkg = True
758         else:
759                 myoptions.getbinpkg = None
760
761         if myoptions.getbinpkgonly in true_y:
762                 myoptions.getbinpkgonly = True
763         else:
764                 myoptions.getbinpkgonly = None
765
766         if myoptions.keep_going in true_y:
767                 myoptions.keep_going = True
768         else:
769                 myoptions.keep_going = None
770
771         if myoptions.package_moves in true_y:
772                 myoptions.package_moves = True
773
774         if myoptions.quiet in true_y:
775                 myoptions.quiet = True
776         else:
777                 myoptions.quiet = None
778
779         if myoptions.quiet_build in true_y:
780                 myoptions.quiet_build = 'y'
781
782         if myoptions.quiet_fail in true_y:
783                 myoptions.quiet_fail = 'y'
784
785         if myoptions.rebuild_if_new_slot in true_y:
786                 myoptions.rebuild_if_new_slot = 'y'
787
788         if myoptions.rebuild_if_new_ver in true_y:
789                 myoptions.rebuild_if_new_ver = True
790         else:
791                 myoptions.rebuild_if_new_ver = None
792
793         if myoptions.rebuild_if_new_rev in true_y:
794                 myoptions.rebuild_if_new_rev = True
795                 myoptions.rebuild_if_new_ver = None
796         else:
797                 myoptions.rebuild_if_new_rev = None
798
799         if myoptions.rebuild_if_unbuilt in true_y:
800                 myoptions.rebuild_if_unbuilt = True
801                 myoptions.rebuild_if_new_rev = None
802                 myoptions.rebuild_if_new_ver = None
803         else:
804                 myoptions.rebuild_if_unbuilt = None
805
806         if myoptions.rebuilt_binaries in true_y:
807                 myoptions.rebuilt_binaries = True
808
809         if myoptions.root_deps in true_y:
810                 myoptions.root_deps = True
811
812         if myoptions.select in true_y:
813                 myoptions.select = True
814                 myoptions.oneshot = False
815         elif myoptions.select == "n":
816                 myoptions.oneshot = True
817
818         if myoptions.selective in true_y:
819                 myoptions.selective = True
820
821         if myoptions.backtrack is not None:
822
823                 try:
824                         backtrack = int(myoptions.backtrack)
825                 except (OverflowError, ValueError):
826                         backtrack = -1
827
828                 if backtrack < 0:
829                         backtrack = None
830                         if not silent:
831                                 parser.error("Invalid --backtrack parameter: '%s'\n" % \
832                                         (myoptions.backtrack,))
833
834                 myoptions.backtrack = backtrack
835
836         if myoptions.deep is not None:
837                 deep = None
838                 if myoptions.deep == "True":
839                         deep = True
840                 else:
841                         try:
842                                 deep = int(myoptions.deep)
843                         except (OverflowError, ValueError):
844                                 deep = -1
845
846                 if deep is not True and deep < 0:
847                         deep = None
848                         if not silent:
849                                 parser.error("Invalid --deep parameter: '%s'\n" % \
850                                         (myoptions.deep,))
851
852                 myoptions.deep = deep
853
854         if myoptions.jobs:
855                 jobs = None
856                 if myoptions.jobs == "True":
857                         jobs = True
858                 else:
859                         try:
860                                 jobs = int(myoptions.jobs)
861                         except ValueError:
862                                 jobs = -1
863
864                 if jobs is not True and \
865                         jobs < 1:
866                         jobs = None
867                         if not silent:
868                                 parser.error("Invalid --jobs parameter: '%s'\n" % \
869                                         (myoptions.jobs,))
870
871                 myoptions.jobs = jobs
872
873         if myoptions.load_average == "True":
874                 myoptions.load_average = None
875
876         if myoptions.load_average:
877                 try:
878                         load_average = float(myoptions.load_average)
879                 except ValueError:
880                         load_average = 0.0
881
882                 if load_average <= 0.0:
883                         load_average = None
884                         if not silent:
885                                 parser.error("Invalid --load-average parameter: '%s'\n" % \
886                                         (myoptions.load_average,))
887
888                 myoptions.load_average = load_average
889         
890         if myoptions.rebuilt_binaries_timestamp:
891                 try:
892                         rebuilt_binaries_timestamp = int(myoptions.rebuilt_binaries_timestamp)
893                 except ValueError:
894                         rebuilt_binaries_timestamp = -1
895
896                 if rebuilt_binaries_timestamp < 0:
897                         rebuilt_binaries_timestamp = 0
898                         if not silent:
899                                 parser.error("Invalid --rebuilt-binaries-timestamp parameter: '%s'\n" % \
900                                         (myoptions.rebuilt_binaries_timestamp,))
901
902                 myoptions.rebuilt_binaries_timestamp = rebuilt_binaries_timestamp
903
904         if myoptions.use_ebuild_visibility in true_y:
905                 myoptions.use_ebuild_visibility = True
906         else:
907                 # None or "n"
908                 pass
909
910         if myoptions.usepkg in true_y:
911                 myoptions.usepkg = True
912         else:
913                 myoptions.usepkg = None
914
915         if myoptions.usepkgonly in true_y:
916                 myoptions.usepkgonly = True
917         else:
918                 myoptions.usepkgonly = None
919
920         if myoptions.verbose in true_y:
921                 myoptions.verbose = True
922         else:
923                 myoptions.verbose = None
924
925         for myopt in options:
926                 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
927                 if v:
928                         myopts[myopt] = True
929
930         for myopt in argument_options:
931                 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
932                 if v is not None:
933                         myopts[myopt] = v
934
935         if myoptions.searchdesc:
936                 myoptions.search = True
937
938         for action_opt in actions:
939                 v = getattr(myoptions, action_opt.replace("-", "_"))
940                 if v:
941                         if myaction:
942                                 multiple_actions(myaction, action_opt)
943                                 sys.exit(1)
944                         myaction = action_opt
945
946         if myaction is None and myoptions.deselect is True:
947                 myaction = 'deselect'
948
949         myfiles += myargs
950
951         return myaction, myopts, myfiles
952
953 def profile_check(trees, myaction):
954         if myaction in ("help", "info", "search", "sync", "version"):
955                 return os.EX_OK
956         for root_trees in trees.values():
957                 if root_trees["root_config"].settings.profiles:
958                         continue
959                 # generate some profile related warning messages
960                 validate_ebuild_environment(trees)
961                 msg = ("Your current profile is invalid. If you have just changed "
962                         "your profile configuration, you should revert back to the "
963                         "previous configuration. Allowed actions are limited to "
964                         "--help, --info, --search, --sync, and --version.")
965                 writemsg_level("".join("!!! %s\n" % l for l in textwrap.wrap(msg, 70)),
966                         level=logging.ERROR, noiselevel=-1)
967                 return 1
968         return os.EX_OK
969
970 def emerge_main(args=None):
971         """
972         @param args: command arguments (default: sys.argv[1:])
973         @type args: list
974         """
975         if args is None:
976                 args = sys.argv[1:]
977
978         args = portage._decode_argv(args)
979
980         # Disable color until we're sure that it should be enabled (after
981         # EMERGE_DEFAULT_OPTS has been parsed).
982         portage.output.havecolor = 0
983
984         # This first pass is just for options that need to be known as early as
985         # possible, such as --config-root.  They will be parsed again later,
986         # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
987         # the value of --config-root).
988         myaction, myopts, myfiles = parse_opts(args, silent=True)
989         if "--debug" in myopts:
990                 os.environ["PORTAGE_DEBUG"] = "1"
991         if "--config-root" in myopts:
992                 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
993         if "--root" in myopts:
994                 os.environ["ROOT"] = myopts["--root"]
995         if "--prefix" in myopts:
996                 os.environ["EPREFIX"] = myopts["--prefix"]
997         if "--accept-properties" in myopts:
998                 os.environ["ACCEPT_PROPERTIES"] = myopts["--accept-properties"]
999         if "--accept-restrict" in myopts:
1000                 os.environ["ACCEPT_RESTRICT"] = myopts["--accept-restrict"]
1001
1002         # optimize --help (no need to load config / EMERGE_DEFAULT_OPTS)
1003         if myaction == "help":
1004                 emerge_help()
1005                 return os.EX_OK
1006         elif myaction == "moo":
1007                 print(COWSAY_MOO % platform.system())
1008                 return os.EX_OK
1009
1010         # Portage needs to ensure a sane umask for the files it creates.
1011         os.umask(0o22)
1012         if myaction == "sync":
1013                 portage._sync_disabled_warnings = True
1014         emerge_config = load_emerge_config(
1015                 action=myaction, args=myfiles, opts=myopts)
1016         rval = profile_check(emerge_config.trees, emerge_config.action)
1017         if rval != os.EX_OK:
1018                 return rval
1019
1020         tmpcmdline = []
1021         if "--ignore-default-opts" not in myopts:
1022                 tmpcmdline.extend(portage.util.shlex_split(
1023                         emerge_config.target_config.settings.get(
1024                         "EMERGE_DEFAULT_OPTS", "")))
1025         tmpcmdline.extend(args)
1026         emerge_config.action, emerge_config.opts, emerge_config.args = \
1027                 parse_opts(tmpcmdline)
1028
1029         try:
1030                 return run_action(emerge_config)
1031         finally:
1032                 # Call destructors for our portdbapi instances.
1033                 for x in emerge_config.trees.values():
1034                         if "porttree" in x.lazy_items:
1035                                 continue
1036                         x["porttree"].dbapi.close_caches()