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