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