2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4 # $Id: emerge 5976 2007-02-17 09:14:53Z genone $
7 # This block ensures that ^C interrupts are handled quietly.
11 def exithandler(signum,frame):
12 signal.signal(signal.SIGINT, signal.SIG_IGN)
13 signal.signal(signal.SIGTERM, signal.SIG_IGN)
16 signal.signal(signal.SIGINT, exithandler)
17 signal.signal(signal.SIGTERM, exithandler)
18 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
20 except KeyboardInterrupt:
25 os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
29 from os import path as osp
30 sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
32 del os.environ["PORTAGE_LEGACY_GLOBALS"]
33 from portage import digraph, portdbapi
34 from portage.const import NEWS_LIB_PATH
37 import portage.xpak, commands, errno, re, socket, time, types
38 from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
39 havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
40 xtermTitleReset, yellow
41 from portage.output import create_color_func
42 good = create_color_func("GOOD")
43 bad = create_color_func("BAD")
46 portage.dep._dep_check_strict = True
49 import portage.exception
50 from portage.data import secpass
51 from portage.util import normalize_path as normpath
53 if not hasattr(__builtins__, "set"):
54 from sets import Set as set
55 from itertools import chain, izip
56 from UserDict import DictMixin
61 import pickle as cPickle
63 class stdout_spinner(object):
65 "Gentoo Rocks ("+os.uname()[0]+")",
66 "Thank you for using Gentoo. :)",
67 "Are you actually trying to read this?",
68 "How many times have you stared at this?",
69 "We are generating the cache right now",
70 "You are paying too much attention.",
71 "A theory is better than its explanation.",
72 "Phasers locked on target, Captain.",
73 "Thrashing is just virtual crashing.",
74 "To be is to program.",
75 "Real Users hate Real Programmers.",
76 "When all else fails, read the instructions.",
77 "Functionality breeds Contempt.",
78 "The future lies ahead.",
79 "3.1415926535897932384626433832795028841971694",
80 "Sometimes insanity is the only alternative.",
81 "Inaccuracy saves a world of explanation.",
84 twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
88 self.update = self.update_twirl
89 self.scroll_sequence = self.scroll_msgs[
90 int(time.time() * 100) % len(self.scroll_msgs)]
92 def update_basic(self):
93 self.spinpos = (self.spinpos + 1) % 500
94 if (self.spinpos % 100) == 0:
96 sys.stdout.write(". ")
101 def update_scroll(self):
102 if(self.spinpos >= len(self.scroll_sequence)):
103 sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
104 len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
106 sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
108 self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
110 def update_twirl(self):
111 self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
112 sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
115 def update_quiet(self):
118 def userquery(prompt, responses=None, colours=None):
119 """Displays a prompt and a set of responses, then waits for a response
120 which is checked against the responses and the first to match is
121 returned. An empty response will match the first value in responses. The
122 input buffer is *not* cleared prior to the prompt!
125 responses: a List of Strings.
126 colours: a List of Functions taking and returning a String, used to
127 process the responses for display. Typically these will be functions
128 like red() but could be e.g. lambda x: "DisplayString".
129 If responses is omitted, defaults to ["Yes", "No"], [green, red].
130 If only colours is omitted, defaults to [bold, ...].
132 Returns a member of the List responses. (If called without optional
133 arguments, returns "Yes" or "No".)
134 KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
136 if responses is None:
137 responses, colours = ["Yes", "No"], [green, red]
138 elif colours is None:
140 colours=(colours*len(responses))[:len(responses)]
144 response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
145 for key in responses:
146 # An empty response will match the first value in responses.
147 if response.upper()==key[:len(response)].upper():
149 print "Sorry, response '%s' not understood." % response,
150 except (EOFError, KeyboardInterrupt):
155 "clean", "config", "depclean",
157 "prune", "regen", "search",
158 "sync", "system", "unmerge", "world",
161 "--ask", "--alphabetical",
162 "--buildpkg", "--buildpkgonly",
163 "--changelog", "--columns",
167 "--fetchonly", "--fetch-all-uri",
168 "--getbinpkg", "--getbinpkgonly",
169 "--help", "--ignore-default-opts",
171 "--newuse", "--nocolor",
172 "--nodeps", "--noreplace",
173 "--nospinner", "--oneshot",
174 "--onlydeps", "--pretend",
175 "--quiet", "--resume",
176 "--searchdesc", "--selective",
180 "--usepkg", "--usepkgonly",
181 "--verbose", "--version"
187 "b":"--buildpkg", "B":"--buildpkgonly",
188 "c":"--clean", "C":"--unmerge",
189 "d":"--debug", "D":"--deep",
191 "f":"--fetchonly", "F":"--fetch-all-uri",
192 "g":"--getbinpkg", "G":"--getbinpkgonly",
194 "k":"--usepkg", "K":"--usepkgonly",
196 "n":"--noreplace", "N":"--newuse",
197 "o":"--onlydeps", "O":"--nodeps",
198 "p":"--pretend", "P":"--prune",
200 "s":"--search", "S":"--searchdesc",
203 "v":"--verbose", "V":"--version"
206 def emergelog(xterm_titles, mystr, short_msg=None):
208 if short_msg == None:
210 if "HOSTNAME" in os.environ.keys():
211 short_msg = os.environ["HOSTNAME"]+": "+short_msg
212 xtermTitle(short_msg)
214 file_path = "/var/log/emerge.log"
215 mylogfile = open(file_path, "a")
216 portage.util.apply_secpass_permissions(file_path,
217 uid=portage.portage_uid, gid=portage.portage_gid,
221 mylock = portage.locks.lockfile(mylogfile)
222 # seek because we may have gotten held up by the lock.
223 # if so, we may not be positioned at the end of the file.
225 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
229 portage.locks.unlockfile(mylock)
231 except (IOError,OSError,portage.exception.PortageException), e:
233 print >> sys.stderr, "emergelog():",e
235 def countdown(secs=5, doing="Starting"):
237 print ">>> Waiting",secs,"seconds before starting..."
238 print ">>> (Control-C to abort)...\n"+doing+" in: ",
242 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
247 # formats a size given in bytes nicely
248 def format_size(mysize):
249 if type(mysize) not in [types.IntType,types.LongType]:
251 if 0 != mysize % 1024:
252 # Always round up to the next kB so that it doesn't show 0 kB when
253 # some small file still needs to be fetched.
254 mysize += 1024 - mysize % 1024
255 mystr=str(mysize/1024)
259 mystr=mystr[:mycount]+","+mystr[mycount:]
263 def getgccversion(chost):
266 return: the current in-use gcc version
269 gcc_ver_command = 'gcc -dumpversion'
270 gcc_ver_prefix = 'gcc-'
272 gcc_not_found_error = red(
273 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
274 "!!! to update the environment of this terminal and possibly\n" +
275 "!!! other terminals also.\n"
278 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
279 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
280 part1, part2 = myoutput.split("/")
281 if part1.startswith(chost + "-"):
282 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
284 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
285 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
286 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
288 mystatus, myoutput = commands.getstatusoutput(
289 chost + "-" + gcc_ver_command)
290 if mystatus == os.EX_OK:
291 return gcc_ver_prefix + myoutput
293 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
294 if mystatus == os.EX_OK:
295 return gcc_ver_prefix + myoutput
297 portage.writemsg(gcc_not_found_error, noiselevel=-1)
298 return "[unavailable]"
300 def getportageversion(portdir, target_root, profile, chost, vardb):
301 profilever = "unavailable"
303 realpath = os.path.realpath(profile)
304 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
305 if realpath.startswith(basepath):
306 profilever = realpath[1 + len(basepath):]
309 profilever = "!" + os.readlink(profile)
312 del realpath, basepath
315 libclist = vardb.match("virtual/libc")
316 libclist += vardb.match("virtual/glibc")
317 libclist = portage.util.unique_array(libclist)
319 xs=portage.catpkgsplit(x)
321 libcver+=","+"-".join(xs[1:])
323 libcver="-".join(xs[1:])
325 libcver="unavailable"
327 gccver = getgccversion(chost)
328 unameout=os.uname()[2]+" "+os.uname()[4]
330 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
332 def create_depgraph_params(myopts, myaction):
333 #configure emerge engine parameters
335 # self: include _this_ package regardless of if it is merged.
336 # selective: exclude the package if it is merged
337 # recurse: go into the dependencies
338 # deep: go into the dependencies of already merged packages
339 # empty: pretend nothing is merged
340 myparams = ["recurse"]
343 if "--update" in myopts or \
344 "--newuse" in myopts or \
345 "--noreplace" in myopts or \
346 myaction in ("system", "world"):
347 add.extend(["selective"])
348 if "--emptytree" in myopts:
349 add.extend(["empty"])
350 sub.extend(["selective"])
351 if "--nodeps" in myopts:
352 sub.extend(["recurse"])
353 if "--deep" in myopts:
356 if (x not in myparams) and (x not in sub):
363 # search functionality
375 def __init__(self, settings, portdb, vartree, spinner, searchdesc,
377 """Searches the available and installed packages for the supplied search key.
378 The list of available and installed packages is created at object instantiation.
379 This makes successive searches faster."""
380 self.settings = settings
382 self.vartree = vartree
383 self.spinner = spinner
384 self.verbose = verbose
385 self.searchdesc = searchdesc
387 def execute(self,searchkey):
388 """Performs the search for the supplied search key"""
390 self.searchkey=searchkey
391 self.packagematches = []
394 self.matches = {"pkg":[], "desc":[]}
397 self.matches = {"pkg":[]}
398 print "Searching... ",
401 if self.searchkey[0] == '%':
403 self.searchkey = self.searchkey[1:]
404 if self.searchkey[0] == '@':
406 self.searchkey = self.searchkey[1:]
408 self.searchre=re.compile(self.searchkey,re.I)
410 self.searchre=re.compile(re.escape(self.searchkey), re.I)
411 for package in self.portdb.cp_all():
412 self.spinner.update()
415 match_string = package[:]
417 match_string = package.split("/")[-1]
420 if self.searchre.search(match_string):
421 if not self.portdb.xmatch("match-visible", package):
423 self.matches["pkg"].append([package,masked])
424 elif self.searchdesc: # DESCRIPTION searching
425 full_package = self.portdb.xmatch("bestmatch-visible", package)
427 #no match found; we don't want to query description
428 full_package = portage.best(
429 self.portdb.xmatch("match-all", package))
435 full_desc = self.portdb.aux_get(
436 full_package, ["DESCRIPTION"])[0]
438 print "emerge: search: aux_get() failed, skipping"
440 if self.searchre.search(full_desc):
441 self.matches["desc"].append([full_package,masked])
443 for mtype in self.matches.keys():
444 self.matches[mtype].sort()
445 self.mlen += len(self.matches[mtype])
448 """Outputs the results of the search."""
449 print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
450 print "[ Applications found : "+white(str(self.mlen))+" ]"
452 for mtype in self.matches.keys():
453 for match,masked in self.matches[mtype]:
456 full_package = self.portdb.xmatch(
457 "bestmatch-visible", match)
459 #no match found; we don't want to query description
461 full_package = portage.best(
462 self.portdb.xmatch("match-all",match))
465 match = portage.pkgsplit(match)[0]
469 desc, homepage, license = self.portdb.aux_get(
470 full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
472 print "emerge: search: aux_get() failed, skipping"
475 print green("*")+" "+white(match)+" "+red("[ Masked ]")
477 print green("*")+" "+white(match)
478 myversion = self.getVersion(full_package, search.VERSION_RELEASE)
481 mycat = match.split("/")[0]
482 mypkg = match.split("/")[1]
483 mycpv = match + "-" + myversion
484 myebuild = self.portdb.findname(mycpv)
485 pkgdir = os.path.dirname(myebuild)
486 from portage import manifest
487 mf = manifest.Manifest(
488 pkgdir, self.settings["DISTDIR"])
489 fetchlist = self.portdb.getfetchlist(mycpv,
490 mysettings=self.settings, all=True)[1]
492 mysum[0] = mf.getDistfilesSize(fetchlist)
493 mystr = str(mysum[0]/1024)
497 mystr=mystr[:mycount]+","+mystr[mycount:]
500 mysum[0] = "Unknown (missing digest for %s)" % str(e)
503 print " ", darkgreen("Latest version available:"),myversion
504 print " ", self.getInstallationStatus(mycat+'/'+mypkg)
505 print " ", darkgreen("Size of files:"),mysum[0]
506 print " ", darkgreen("Homepage:")+" ",homepage
507 print " ", darkgreen("Description:")+" ",desc
508 print " ", darkgreen("License:")+" ",license
514 def getInstallationStatus(self,package):
515 installed_package = self.vartree.dep_bestmatch(package)
517 version = self.getVersion(installed_package,search.VERSION_RELEASE)
519 result = darkgreen("Latest version installed:")+" "+version
521 result = darkgreen("Latest version installed:")+" [ Not Installed ]"
524 def getVersion(self,full_package,detail):
525 if len(full_package) > 1:
526 package_parts = portage.catpkgsplit(full_package)
527 if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
528 result = package_parts[2]+ "-" + package_parts[3]
530 result = package_parts[2]
536 #build our package digraph
537 def getlist(settings, mode):
539 mylines = settings.packages
542 file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
543 myfile = open(file_path, "r")
544 mylines = myfile.readlines()
546 except (OSError, IOError), e:
547 if e.errno == errno.ENOENT:
548 portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
554 myline=" ".join(x.split())
563 mynewlines.append(myline.strip())
567 def clean_world(vardb, cpv):
568 """Remove a package from the world file when unmerged."""
569 world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
570 worldlist = portage.util.grabfile(world_filename)
571 mykey = portage.cpv_getkey(cpv)
574 if portage.dep_getkey(x) == mykey:
575 matches = vardb.match(x, use_cache=0)
579 elif len(matches) == 1 and matches[0] == cpv:
583 #others are around; keep it.
584 newworldlist.append(x)
586 #this doesn't match the package we're unmerging; keep it.
587 newworldlist.append(x)
589 portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
590 gid=portage.portage_gid, mode=02770)
591 portage.util.write_atomic(world_filename, "\n".join(newworldlist))
593 def genericdict(mylist):
596 mynewdict[portage.dep_getkey(x)]=x
599 def filter_iuse_defaults(iuse):
601 if flag.startswith("+"):
606 class DepPriority(object):
608 This class generates an integer priority level based of various
609 attributes of the dependency relationship. Attributes can be assigned
610 at any time and the new integer value will be generated on calls to the
611 __int__() method. Rich comparison operators are supported.
613 The boolean attributes that affect the integer value are "satisfied",
614 "buildtime", "runtime", and "system". Various combinations of
615 attributes lead to the following priority levels:
617 Combination of properties Priority level
619 not satisfied and buildtime 0
620 not satisfied and runtime -1
621 satisfied and buildtime -2
622 satisfied and runtime -3
623 (none of the above) -4
625 Several integer constants are defined for categorization of priority
628 MEDIUM The upper boundary for medium dependencies.
629 SOFT The upper boundary for soft dependencies.
630 MIN The lower boundary for soft dependencies.
632 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
636 def __init__(self, **kwargs):
637 for myattr in self.__slots__:
638 if myattr == "__weakref__":
640 myvalue = kwargs.get(myattr, False)
641 setattr(self, myattr, myvalue)
643 if not self.satisfied:
653 def __lt__(self, other):
654 return self.__int__() < other
655 def __le__(self, other):
656 return self.__int__() <= other
657 def __eq__(self, other):
658 return self.__int__() == other
659 def __ne__(self, other):
660 return self.__int__() != other
661 def __gt__(self, other):
662 return self.__int__() > other
663 def __ge__(self, other):
664 return self.__int__() >= other
667 return copy.copy(self)
669 myvalue = self.__int__()
670 if myvalue > self.MEDIUM:
672 if myvalue > self.SOFT:
676 class FakeVartree(portage.vartree):
677 """This is implements an in-memory copy of a vartree instance that provides
678 all the interfaces required for use by the depgraph. The vardb is locked
679 during the constructor call just long enough to read a copy of the
680 installed package information. This allows the depgraph to do it's
681 dependency calculations without holding a lock on the vardb. It also
682 allows things like vardb global updates to be done in memory so that the
683 user doesn't necessarily need write access to the vardb in cases where
684 global updates are necessary (updates are performed when necessary if there
685 is not a matching ebuild in the tree)."""
686 def __init__(self, real_vartree, portdb):
687 self.root = real_vartree.root
688 self.settings = real_vartree.settings
689 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
690 vdb_path = os.path.join(self.root, portage.VDB_PATH)
692 # At least the parent needs to exist for the lock file.
693 portage.util.ensure_dirs(vdb_path)
694 except portage.exception.PortageException:
698 if os.access(vdb_path, os.W_OK):
699 vdb_lock = portage.locks.lockdir(vdb_path)
700 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
701 "DEPEND", "RDEPEND", "PDEPEND"]
702 real_dbapi = real_vartree.dbapi
704 for cpv in real_dbapi.cpv_all():
705 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
706 myslot = metadata["SLOT"]
707 mycp = portage.dep_getkey(cpv)
708 myslot_atom = "%s:%s" % (mycp, myslot)
710 mycounter = long(metadata["COUNTER"])
713 metadata["COUNTER"] = str(mycounter)
714 other_counter = slot_counters.get(myslot_atom, None)
715 if other_counter is not None:
716 if other_counter > mycounter:
718 slot_counters[myslot_atom] = mycounter
719 self.dbapi.cpv_inject(cpv, metadata=metadata)
720 real_dbapi.flush_cache()
723 portage.locks.unlockdir(vdb_lock)
724 # Populate the old-style virtuals using the cached values.
725 if not self.settings.treeVirtuals:
726 self.settings.treeVirtuals = portage.util.map_dictlist_vals(
727 portage.getCPFromCPV, self.get_all_provides())
729 # Intialize variables needed for lazy cache pulls of the live ebuild
730 # metadata. This ensures that the vardb lock is released ASAP, without
731 # being delayed in case cache generation is triggered.
732 self._aux_get = self.dbapi.aux_get
733 self.dbapi.aux_get = self._aux_get_wrapper
734 self._aux_get_history = set()
735 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
736 self._portdb = portdb
737 self._global_updates = None
739 def _aux_get_wrapper(self, pkg, wants):
740 if pkg in self._aux_get_history:
741 return self._aux_get(pkg, wants)
742 self._aux_get_history.add(pkg)
744 # Use the live ebuild metadata if possible.
745 live_metadata = dict(izip(self._portdb_keys,
746 self._portdb.aux_get(pkg, self._portdb_keys)))
747 self.dbapi.aux_update(pkg, live_metadata)
748 except (KeyError, portage.exception.PortageException):
749 if self._global_updates is None:
750 self._global_updates = \
751 grab_global_updates(self._portdb.porttree_root)
752 perform_global_updates(
753 pkg, self.dbapi, self._global_updates)
754 return self._aux_get(pkg, wants)
756 def grab_global_updates(portdir):
757 from portage.update import grab_updates, parse_updates
758 updpath = os.path.join(portdir, "profiles", "updates")
760 rawupdates = grab_updates(updpath)
761 except portage.exception.DirectoryNotFound:
764 for mykey, mystat, mycontent in rawupdates:
765 commands, errors = parse_updates(mycontent)
766 upd_commands.extend(commands)
769 def perform_global_updates(mycpv, mydb, mycommands):
770 from portage.update import update_dbentries
771 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
772 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
773 updates = update_dbentries(mycommands, aux_dict)
775 mydb.aux_update(mycpv, updates)
777 class BlockerCache(DictMixin):
778 """This caches blockers of installed packages so that dep_check does not
779 have to be done for every single installed package on every invocation of
780 emerge. The cache is invalidated whenever it is detected that something
781 has changed that might alter the results of dep_check() calls:
782 1) the set of installed packages (including COUNTER) has changed
783 2) the old-style virtuals have changed
785 class BlockerData(object):
786 def __init__(self, counter, atoms):
787 self.counter = counter
790 def __init__(self, myroot, vardb):
792 self._installed_pkgs = set(vardb.cpv_all())
793 self._virtuals = vardb.settings.getvirtuals()
794 self._cache_filename = os.path.join(myroot,
795 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
796 self._cache_version = "1"
797 self._cache_data = None
798 self._modified = False
803 f = open(self._cache_filename)
804 mypickle = cPickle.Unpickler(f)
805 mypickle.find_global = None
806 self._cache_data = mypickle.load()
809 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
811 cache_valid = self._cache_data and \
812 isinstance(self._cache_data, dict) and \
813 self._cache_data.get("version") == self._cache_version and \
814 self._cache_data.get("virtuals") == self._virtuals and \
815 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
817 for pkg in self._installed_pkgs:
818 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
823 self._cache_data = {"version":self._cache_version}
824 self._cache_data["blockers"] = {}
825 self._cache_data["virtuals"] = self._virtuals
826 self._modified = False
829 """If the current user has permission and the internal blocker cache
830 been updated, save it to disk and mark it unmodified. This is called
831 by emerge after it has proccessed blockers for all installed packages.
832 Currently, the cache is only written if the user has superuser
833 privileges (since that's required to obtain a lock), but all users
834 have read access and benefit from faster blocker lookups (as long as
835 the entire cache is still valid). The cache is stored as a pickled
836 dict object with the following format:
840 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
841 "virtuals" : vardb.settings.getvirtuals()
844 if self._modified and \
847 f = portage.util.atomic_ofstream(self._cache_filename)
848 cPickle.dump(self._cache_data, f, -1)
850 portage.util.apply_secpass_permissions(
851 self._cache_filename, gid=portage.portage_gid, mode=0644)
852 except (IOError, OSError), e:
854 self._modified = False
856 def __setitem__(self, cpv, blocker_data):
858 Update the cache and mark it as modified for a future call to
861 @param cpv: Package for which to cache blockers.
863 @param blocker_data: An object with counter and atoms attributes.
864 @type blocker_data: BlockerData
866 self._cache_data["blockers"][cpv] = \
867 (blocker_data.counter, blocker_data.atoms)
868 self._modified = True
870 def __getitem__(self, cpv):
873 @returns: An object with counter and atoms attributes.
875 return self.BlockerData(*self._cache_data["blockers"][cpv])
877 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
879 from formatter import AbstractFormatter, DumbWriter
880 f = AbstractFormatter(DumbWriter(maxcol=72))
882 print "\n\n!!! Invalid or corrupt dependency specification: "
890 p_type, p_root, p_key, p_status = parent_node
892 if p_status == "nomerge":
893 category, pf = portage.catsplit(p_key)
894 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
895 msg.append("Portage is unable to process the dependencies of the ")
896 msg.append("'%s' package. " % p_key)
897 msg.append("In order to correct this problem, the package ")
898 msg.append("should be uninstalled, reinstalled, or upgraded. ")
899 msg.append("As a temporary workaround, the --nodeps option can ")
900 msg.append("be used to ignore all dependencies. For reference, ")
901 msg.append("the problematic dependencies can be found in the ")
902 msg.append("*DEPEND files located in '%s/'." % pkg_location)
904 msg.append("This package can not be installed. ")
905 msg.append("Please notify the '%s' package maintainer " % p_key)
906 msg.append("about this problem.")
909 f.add_flowing_data(x)
917 "installed":"vartree"}
919 def __init__(self, settings, trees, myopts, myparams, spinner):
920 self.settings = settings
921 self.target_root = settings["ROOT"]
923 self.myparams = myparams
925 if settings.get("PORTAGE_DEBUG", "") == "1":
927 self.spinner = spinner
928 self.pkgsettings = {}
929 # Maps cpv to digraph node for all nodes added to the graph.
930 self.pkg_node_map = {}
931 # Maps slot atom to digraph node for all nodes added to the graph.
932 self._slot_node_map = {}
934 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
938 self.trees[myroot] = {}
939 for tree in ("porttree", "bintree"):
940 self.trees[myroot][tree] = trees[myroot][tree]
941 self.trees[myroot]["vartree"] = \
942 FakeVartree(trees[myroot]["vartree"],
943 trees[myroot]["porttree"].dbapi)
944 self.pkgsettings[myroot] = portage.config(
945 clone=self.trees[myroot]["vartree"].settings)
946 self.pkg_node_map[myroot] = {}
947 self._slot_node_map[myroot] = {}
948 vardb = self.trees[myroot]["vartree"].dbapi
949 # This fakedbapi instance will model the state that the vdb will
950 # have after new packages have been installed.
951 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
952 self.mydbapi[myroot] = fakedb
953 if "--nodeps" not in self.myopts and \
954 "--buildpkgonly" not in self.myopts:
955 # --nodeps bypasses this, since it isn't needed in this case
956 # and the cache pulls might trigger (slow) cache generation.
957 for pkg in vardb.cpv_all():
958 self.spinner.update()
959 fakedb.cpv_inject(pkg,
960 metadata=dict(izip(self._mydbapi_keys,
961 vardb.aux_get(pkg, self._mydbapi_keys))))
963 self.useFlags[myroot] = {}
964 if "--usepkg" in self.myopts:
965 self.trees[myroot]["bintree"].populate(
966 "--getbinpkg" in self.myopts,
967 "--getbinpkgonly" in self.myopts)
971 self.digraph=portage.digraph()
972 # Tracks simple parent/child relationships (PDEPEND relationships are
974 self._parent_child_digraph = digraph()
976 self.outdatedpackages=[]
978 self.blocker_digraph = digraph()
979 self.blocker_parents = {}
980 self._slot_collision_info = []
981 # Slot collision nodes are not allowed to block other packages since
982 # blocker validation is only able to account for one package per slot.
983 self._slot_collision_nodes = set()
984 self._altlist_cache = {}
985 self._pprovided_args = []
987 def _show_slot_collision_notice(self, packages):
988 """Show an informational message advising the user to mask one of the
989 the packages. In some cases it may be possible to resolve this
990 automatically, but support for backtracking (removal nodes that have
991 already been selected) will be required in order to handle all possible
995 msg.append("\n!!! Multiple versions within a single " + \
996 "package slot have been \n")
997 msg.append("!!! pulled into the dependency graph:\n\n")
998 for node, parents in packages:
999 msg.append(str(node))
1001 msg.append(" pulled in by\n")
1002 for parent in parents:
1004 msg.append(str(parent))
1007 msg.append(" (no parents)\n")
1009 sys.stderr.write("".join(msg))
1012 if "--quiet" in self.myopts:
1016 msg.append("It may be possible to solve this problem ")
1017 msg.append("by using package.mask to prevent one of ")
1018 msg.append("those packages from being selected. ")
1019 msg.append("However, it is also possible that conflicting ")
1020 msg.append("dependencies exist such that they are impossible to ")
1021 msg.append("satisfy simultaneously. If such a conflict exists in ")
1022 msg.append("the dependencies of two different packages, then those ")
1023 msg.append("packages can not be installed simultaneously.")
1025 from formatter import AbstractFormatter, DumbWriter
1026 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1028 f.add_flowing_data(x)
1032 msg.append("For more information, see MASKED PACKAGES ")
1033 msg.append("section in the emerge man page or refer ")
1034 msg.append("to the Gentoo Handbook.")
1036 f.add_flowing_data(x)
1040 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1041 priority=DepPriority(), rev_dep=False, arg=None):
1043 Fills the digraph with nodes comprised of packages to merge.
1044 mybigkey is the package spec of the package to merge.
1045 myparent is the package depending on mybigkey ( or None )
1046 addme = Should we add this package to the digraph or are we just looking at it's deps?
1047 Think --onlydeps, we need to ignore packages in that case.
1050 #IUSE-aware emerge -> USE DEP aware depgraph
1051 #"no downgrade" emerge
1053 mytype, myroot, mykey = mybigkey
1054 existing_node = None
1056 existing_node = self.pkg_node_map[myroot].get(mykey)
1058 self._parent_child_digraph.add(existing_node, myparent)
1059 if existing_node != myparent:
1060 # Refuse to make a node depend on itself so that the we don't
1061 # don't create a bogus circular dependency in self.altlist().
1062 if rev_dep and myparent:
1063 self.digraph.addnode(myparent, existing_node,
1066 self.digraph.addnode(existing_node, myparent,
1070 if "--nodeps" not in self.myopts:
1071 self.spinner.update()
1072 if mytype == "blocks":
1074 "--buildpkgonly" not in self.myopts and \
1075 "--nodeps" not in self.myopts and \
1076 myparent not in self._slot_collision_nodes:
1077 mybigkey[1] = myparent[1]
1078 self.blocker_parents.setdefault(
1079 tuple(mybigkey), set()).add(myparent)
1081 if not arg and myroot == self.target_root:
1082 arg = portage.best_match_to_list(mykey, self.args_keys)
1083 # select the correct /var database that we'll be checking against
1084 vardbapi = self.trees[myroot]["vartree"].dbapi
1085 portdb = self.trees[myroot]["porttree"].dbapi
1086 bindb = self.trees[myroot]["bintree"].dbapi
1087 pkgsettings = self.pkgsettings[myroot]
1089 # if the package is already on the system, we add a "nomerge"
1090 # directive, otherwise we add a "merge" directive.
1092 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1095 self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
1096 myuse = self.pkgsettings[myroot]["USE"].split()
1099 if mytype == "installed":
1101 if addme and mytype != "installed":
1102 # this is where we add the node to the list of packages to merge
1103 if "selective" in self.myparams or not arg:
1104 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1107 """ If we aren't merging, perform the --newuse check.
1108 If the package has new iuse flags or different use flags then if
1109 --newuse is specified, we need to merge the package. """
1110 if merging==0 and "--newuse" in self.myopts and \
1111 vardbapi.cpv_exists(mykey):
1112 pkgsettings.setcpv(mykey, mydb=mydbapi)
1113 forced_flags = set()
1114 forced_flags.update(pkgsettings.useforce)
1115 forced_flags.update(pkgsettings.usemask)
1116 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1117 iuses = set(filter_iuse_defaults(
1118 mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
1119 old_iuse = set(filter_iuse_defaults(
1120 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1121 if iuses.symmetric_difference(
1122 old_iuse).difference(forced_flags):
1124 elif old_iuse.intersection(old_use) != \
1125 iuses.intersection(myuse):
1128 if addme and merging == 1:
1129 mybigkey.append("merge")
1131 mybigkey.append("nomerge")
1132 jbigkey = tuple(mybigkey)
1135 metadata = dict(izip(self._mydbapi_keys,
1136 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1137 if merging == 0 and vardbapi.cpv_exists(mykey) and \
1138 mytype != "installed":
1139 mybigkey[0] = "installed"
1141 jbigkey = tuple(mybigkey)
1142 metadata = dict(izip(self._mydbapi_keys,
1143 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1144 myuse = mydbapi.aux_get(mykey, ["USE"])[0].split()
1145 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1146 existing_node = self._slot_node_map[myroot].get(
1148 slot_collision = False
1150 e_type, myroot, e_cpv, e_status = existing_node
1152 # The existing node can be reused.
1153 self._parent_child_digraph.add(existing_node, myparent)
1154 if rev_dep and myparent:
1155 ptype, proot, pkey, pstatus = myparent
1156 self.digraph.addnode(myparent, existing_node,
1159 self.digraph.addnode(existing_node, myparent,
1163 # A slot collision has occurred. Sometimes this coincides
1164 # with unresolvable blockers, so the slot collision will be
1165 # shown later if there are no unresolvable blockers.
1166 e_parents = self._parent_child_digraph.parent_nodes(
1170 myparents.append(myparent)
1171 self._slot_collision_info.append(
1172 ((jbigkey, myparents), (existing_node, e_parents)))
1173 self._slot_collision_nodes.add(jbigkey)
1174 slot_collision = True
1177 # Now add this node to the graph so that self.display()
1178 # can show use flags and --tree portage.output. This node is
1179 # only being partially added to the graph. It must not be
1180 # allowed to interfere with the other nodes that have been
1181 # added. Do not overwrite data for existing nodes in
1182 # self.pkg_node_map and self.mydbapi since that data will
1183 # be used for blocker validation.
1184 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1185 self.useFlags[myroot].setdefault(mykey, myuse)
1186 # Even though the graph is now invalid, continue to process
1187 # dependencies so that things like --fetchonly can still
1188 # function despite collisions.
1190 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1191 self._slot_node_map[myroot][slot_atom] = jbigkey
1192 self.pkg_node_map[myroot][mykey] = jbigkey
1193 self.useFlags[myroot][mykey] = myuse
1195 if rev_dep and myparent:
1196 self.digraph.addnode(myparent, jbigkey,
1199 self.digraph.addnode(jbigkey, myparent,
1202 # Do this even when addme is False (--onlydeps) so that the
1203 # parent/child relationship is always known in case
1204 # self._show_slot_collision_notice() needs to be called later.
1205 self._parent_child_digraph.add(jbigkey, myparent)
1207 """ This section determines whether we go deeper into dependencies or not.
1208 We want to go deeper on a few occasions:
1209 Installing package A, we need to make sure package A's deps are met.
1210 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1211 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1213 if "deep" not in self.myparams and not merging and \
1214 not ("--update" in self.myopts and arg and merging):
1216 elif "recurse" not in self.myparams:
1219 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1220 Pull from bintree if it's binary package, porttree if it's ebuild.
1221 Binpkg's can be either remote or local. """
1224 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1225 depvalues = mydbapi.aux_get(mykey, depkeys)
1226 for i in xrange(len(depkeys)):
1227 edepend[depkeys[i]] = depvalues[i]
1229 if mytype == "ebuild":
1230 if "--buildpkgonly" in self.myopts:
1231 edepend["RDEPEND"] = ""
1232 edepend["PDEPEND"] = ""
1233 if not (arg and "--onlydeps" in self.myopts and \
1234 mytype == "ebuild") and \
1235 self.myopts.get("--with-bdeps", "n") == "n" and \
1236 (mytype == "binary" or mybigkey[3] == "nomerge"):
1237 edepend["DEPEND"] = ""
1239 """ We have retrieve the dependency information, now we need to recursively
1240 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1242 mp = tuple(mybigkey)
1245 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1246 myuse=myuse, priority=DepPriority(buildtime=True),
1249 """RDEPEND is soft by definition. However, in order to ensure
1250 correct merge order, we make it a hard dependency. Otherwise, a
1251 build time dependency might not be usable due to it's run time
1252 dependencies not being installed yet.
1254 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1255 myuse=myuse, priority=DepPriority(runtime=True),
1258 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1259 # Post Depend -- Add to the list without a parent, as it depends
1260 # on a package being present AND must be built after that package.
1261 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1262 myuse=myuse, priority=DepPriority(), rev_deps=True,
1265 except ValueError, e:
1267 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1268 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1270 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1271 portage.writemsg("\n", noiselevel=-1)
1272 if mytype == "binary":
1274 "!!! This binary package cannot be installed: '%s'\n" % \
1275 mykey, noiselevel=-1)
1276 elif mytype == "ebuild":
1277 myebuild, mylocation = portdb.findname2(mykey)
1278 portage.writemsg("!!! This ebuild cannot be installed: " + \
1279 "'%s'\n" % myebuild, noiselevel=-1)
1280 portage.writemsg("!!! Please notify the package maintainer " + \
1281 "that atoms must be fully-qualified.\n", noiselevel=-1)
1285 def select_files(self,myfiles):
1286 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1288 myroot = self.target_root
1289 portdb = self.trees[myroot]["porttree"].dbapi
1290 bindb = self.trees[myroot]["bintree"].dbapi
1291 pkgsettings = self.pkgsettings[myroot]
1293 def visible(mylist):
1294 matches = portdb.gvisible(portdb.visible(mylist))
1295 return [x for x in mylist \
1296 if x in matches or not portdb.cpv_exists(x)]
1298 ext = os.path.splitext(x)[1]
1300 if not os.path.exists(x):
1302 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1303 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1304 elif os.path.exists(
1305 os.path.join(pkgsettings["PKGDIR"], x)):
1306 x = os.path.join(pkgsettings["PKGDIR"], x)
1308 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1309 print "!!! Please ensure the tbz2 exists as specified.\n"
1311 mytbz2=portage.xpak.tbz2(x)
1312 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1313 if os.path.realpath(x) != \
1314 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1315 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1317 if not self.create(["binary", myroot, mykey],
1318 None, "--onlydeps" not in self.myopts):
1319 return (0,myfavorites)
1320 elif not "--oneshot" in self.myopts:
1321 myfavorites.append(mykey)
1322 elif ext==".ebuild":
1323 x = os.path.realpath(x)
1324 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1325 ebuild_path = portdb.findname(mykey)
1327 if os.path.realpath(ebuild_path) != x:
1328 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1330 if mykey not in portdb.xmatch(
1331 "match-visible", portage.dep_getkey(mykey)):
1332 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1333 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1334 print colorize("BAD", "*** page for details.")
1335 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1338 raise portage.exception.PackageNotFound(
1339 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1340 if not self.create(["ebuild", myroot, mykey],
1341 None, "--onlydeps" not in self.myopts):
1342 return (0,myfavorites)
1343 elif not "--oneshot" in self.myopts:
1344 myfavorites.append(mykey)
1346 if not is_valid_package_atom(x):
1347 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1349 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1350 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1354 if "--usepkg" in self.myopts:
1355 mykey = portage.dep_expand(x, mydb=bindb,
1356 settings=pkgsettings)
1357 if (mykey and not mykey.startswith("null/")) or \
1358 "--usepkgonly" in self.myopts:
1359 arg_atoms.append((x, mykey))
1362 mykey = portage.dep_expand(x,
1363 mydb=portdb, settings=pkgsettings)
1364 arg_atoms.append((x, mykey))
1365 except ValueError, errpkgs:
1366 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1367 print "!!! one of the following fully-qualified ebuild names instead:\n"
1368 for i in errpkgs[0]:
1369 print " " + green(i)
1373 if "--update" in self.myopts:
1374 """Make sure all installed slots are updated when possible. Do this
1375 with --emptytree also, to ensure that all slots are remerged."""
1376 vardb = self.trees[self.target_root]["vartree"].dbapi
1378 for myarg, myatom in arg_atoms:
1379 greedy_atoms.append((myarg, myatom))
1381 for cpv in vardb.match(myatom):
1382 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1385 if "--usepkg" in self.myopts:
1386 mymatches = bindb.match(myatom)
1387 if "--usepkgonly" not in self.myopts:
1388 mymatches = visible(mymatches)
1389 best_pkg = portage.best(mymatches)
1391 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1392 best_pkgs.append(("binary", best_pkg, best_slot))
1393 if "--usepkgonly" not in self.myopts:
1394 best_pkg = portage.best(portdb.match(myatom))
1396 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1397 best_pkgs.append(("ebuild", best_pkg, best_slot))
1399 best_pkg = portage.best([x[1] for x in best_pkgs])
1400 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1401 best_slot = best_pkgs[0][2]
1402 myslots.add(best_slot)
1403 if len(myslots) > 1:
1404 for myslot in myslots:
1405 myslot_atom = "%s:%s" % \
1406 (portage.dep_getkey(myatom), myslot)
1408 if "--usepkgonly" not in self.myopts and \
1409 self.trees[self.target_root][
1410 "porttree"].dbapi.match(myslot_atom):
1412 elif "--usepkg" in self.myopts:
1413 mymatches = bindb.match(myslot_atom)
1414 if "--usepkgonly" not in self.myopts:
1415 mymatches = visible(mymatches)
1419 greedy_atoms.append((myarg, myslot_atom))
1420 arg_atoms = greedy_atoms
1422 """ These are used inside self.create() in order to ensure packages
1423 that happen to match arguments are not incorrectly marked as nomerge."""
1424 self.args_keys = [x[1] for x in arg_atoms]
1425 for myarg, myatom in arg_atoms:
1427 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1428 except portage.exception.MissingSignature, e:
1429 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1430 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1431 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1432 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1433 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1435 except portage.exception.InvalidSignature, e:
1436 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1437 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1438 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1439 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1440 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1442 except SystemExit, e:
1443 raise # Needed else can't exit
1444 except Exception, e:
1445 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1446 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1450 return (0,myfavorites)
1451 elif not "--oneshot" in self.myopts:
1452 mykey = portage.dep_getkey(myatom)
1453 if mykey not in myfavorites:
1454 myfavorites.append(mykey)
1457 if "--usepkgonly" in self.myopts:
1458 for xs in self.digraph.all_nodes():
1459 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1463 print "Missing binary for:",xs[2]
1465 if not self.validate_blockers():
1466 return False, myfavorites
1468 # We're true here unless we are missing binaries.
1469 return (not missing,myfavorites)
1471 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1472 myuse=None, raise_on_missing=False, priority=DepPriority(),
1473 rev_deps=False, parent_arg=None):
1474 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1475 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1476 myparent = the node whose depstring is being passed in
1477 arg = package was specified on the command line, merge even if it's already installed
1478 myuse = USE flags at present
1479 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1480 else continue trying.
1481 return 1 on success, 0 for failure
1484 portdb = self.trees[myroot]["porttree"].dbapi
1485 bindb = self.trees[myroot]["bintree"].dbapi
1486 vardb = self.trees[myroot]["vartree"].dbapi
1487 pkgsettings = self.pkgsettings[myroot]
1489 p_type, p_root, p_key, p_status = myparent
1491 if "--debug" in self.myopts:
1493 print "Parent: ",myparent
1494 print "Depstring:",depstring
1496 print "Reverse:", rev_deps
1497 print "Priority:", priority
1499 #processing dependencies
1500 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1501 dependencies are satisfiable. """
1503 mymerge = [depstring]
1504 pprovided = pkgsettings.pprovideddict.get(
1505 portage.dep_getkey(depstring))
1506 if pprovided and portage.match_from_list(depstring, pprovided):
1510 if myparent and p_status == "nomerge":
1511 portage.dep._dep_check_strict = False
1512 mycheck = portage.dep_check(depstring, None,
1513 pkgsettings, myuse=myuse,
1514 use_binaries=("--usepkgonly" in self.myopts),
1515 myroot=myroot, trees=self.trees)
1517 portage.dep._dep_check_strict = True
1521 show_invalid_depstring_notice(
1522 myparent, depstring, mycheck[1])
1524 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1526 mymerge = mycheck[1]
1528 if not mymerge and arg and \
1529 portage.best_match_to_list(depstring, self.args_keys):
1530 # A provided package has been specified on the command line. The
1531 # package will not be merged and a warning will be displayed.
1532 self._pprovided_args.append(arg)
1535 # The parent is added after it's own dep_check call so that it
1536 # isn't allowed to satisfy a direct bootstrap dependency on itself
1537 # via an old-style virtual. This isn't a problem with new-style
1538 # virtuals, which are preferenced in dep_zapdeps by looking only at
1539 # the depstring, vdb, and available packages.
1541 p_type, p_root, p_key, p_status = myparent
1542 if p_status == "merge":
1543 # Update old-style virtuals if this package provides any.
1544 # These are needed for dep_virtual calls inside dep_check.
1545 self.pkgsettings[p_root].setinst(p_key,
1546 self.trees[p_root][self.pkg_tree_map[p_type]].dbapi)
1548 if "--debug" in self.myopts:
1549 print "Candidates:",mymerge
1553 selected_pkg = ["blocks", myroot, x[1:], None]
1555 #We are not processing a blocker but a normal dependency
1557 """In some cases, dep_check will return deps that shouldn't
1558 be proccessed any further, so they are identified and
1560 if "empty" not in self.myparams and \
1561 "deep" not in self.myparams and \
1562 not ("--update" in self.myopts and parent_arg) and \
1566 # List of acceptable packages, ordered by type preference.
1567 matched_packages = []
1568 myeb_matches = portdb.xmatch("match-visible", x)
1570 if "--usepkgonly" not in self.myopts:
1571 myeb = portage.best(myeb_matches)
1574 if "--usepkg" in self.myopts:
1575 # The next line assumes the binarytree has been populated.
1576 # XXX: Need to work out how we use the binary tree with roots.
1577 myeb_pkg_matches = bindb.match(x)
1578 if "--usepkgonly" not in self.myopts:
1579 # Remove any binary package entries that are masked in the portage tree (#55871)
1580 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1581 if pkg in myeb_matches or \
1582 not portdb.cpv_exists(pkg)]
1583 if myeb_pkg_matches:
1584 myeb_pkg = portage.best(myeb_pkg_matches)
1586 if myeb_pkg and "--newuse" in self.myopts:
1587 iuses = set(filter_iuse_defaults(
1588 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1589 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1591 if "--usepkgonly" not in self.myopts and myeb:
1594 pkgsettings.setcpv(myeb, mydb=mydb)
1596 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1597 now_use = pkgsettings["USE"].split()
1598 forced_flags = set()
1599 forced_flags.update(pkgsettings.useforce)
1600 forced_flags.update(pkgsettings.usemask)
1602 if "--usepkgonly" not in self.myopts and myeb:
1603 cur_iuse = set(filter_iuse_defaults(
1604 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1605 if iuses.symmetric_difference(
1606 cur_iuse).difference(forced_flags):
1608 elif iuses.intersection(old_use) != \
1609 cur_iuse.intersection(now_use):
1613 self.trees[myroot]["bintree"].dbapi.aux_get(
1614 myeb_pkg, ["USE"])[0].split()
1615 matched_packages.append(
1616 ["binary", myroot, myeb_pkg, binpkguseflags])
1618 if "--usepkgonly" not in self.myopts and myeb_matches:
1619 matched_packages.append(
1620 ["ebuild", myroot, myeb, None])
1622 if not matched_packages and \
1623 not (arg and "selective" not in self.myparams):
1624 """Fall back to the installed package database. This is a
1625 last resort because the metadata tends to diverge from that
1626 of the ebuild in the tree."""
1627 myeb_inst_matches = vardb.match(x)
1628 if "--usepkgonly" not in self.myopts:
1629 """ TODO: Improve masking check for installed and
1630 binary packages. bug #149816"""
1631 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1632 if not portdb.cpv_exists(pkg)]
1634 if myeb_inst_matches:
1635 myeb_inst = portage.best(myeb_inst_matches)
1637 binpkguseflags = vardb.aux_get(
1638 myeb_inst, ["USE"])[0].split()
1639 matched_packages.append(
1640 ["installed", myroot, myeb_inst, binpkguseflags])
1642 if not matched_packages:
1643 if raise_on_missing:
1650 xfrom = '(dependency required by '+ \
1651 green('"%s"' % myparent[2]) + \
1652 red(' [%s]' % myparent[0]) + ')'
1653 alleb = portdb.xmatch("match-all", x)
1655 if "--usepkgonly" not in self.myopts:
1656 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1657 print "!!! One of the following masked packages is required to complete your request:"
1661 mreasons = portage.getmaskingstatus(p,
1662 settings=pkgsettings, portdb=portdb)
1663 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1664 if "package.mask" in mreasons:
1665 comment, filename = \
1666 portage.getmaskingreason(p,
1667 settings=pkgsettings, portdb=portdb,
1668 return_location=True)
1669 if comment and comment != oldcomment:
1672 oldcomment = comment
1673 licenses = portdb.aux_get(p, ["LICENSE"])[0]
1676 pkgsettings.setcpv(p, mydb=portdb)
1677 uselist = pkgsettings.get("USE", "").split()
1678 missing_licenses = []
1680 missing_licenses = \
1681 pkgsettings.getMissingLicenses(
1682 licenses, p, uselist)
1683 except portage.exception.InvalidDependString:
1684 # This will have already been reported
1685 # above via mreasons.
1687 for l in missing_licenses:
1688 l_path = portdb.findLicensePath(l)
1689 if l in shown_licenses:
1691 msg = ("A copy of the '%s' license" + \
1692 " is located at '%s'.") % (l, l_path)
1695 shown_licenses.append(l)
1697 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1698 print "refer to the Gentoo Handbook."
1700 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1701 print "!!! Either add a suitable binary package or compile from an ebuild."
1703 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1709 if "--debug" in self.myopts:
1710 for pkg in matched_packages:
1711 print (pkg[0] + ":").rjust(10), pkg[2]
1713 if len(matched_packages) > 1:
1714 bestmatch = portage.best(
1715 [pkg[2] for pkg in matched_packages])
1716 matched_packages = [pkg for pkg in matched_packages \
1717 if pkg[2] == bestmatch]
1719 # ordered by type preference ("ebuild" type is the last resort)
1720 selected_pkg = matched_packages[0]
1721 pkgtype, myroot, mycpv, myuse = selected_pkg
1722 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1723 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1724 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1725 existing_node = self._slot_node_map[myroot].get(
1728 e_type, myroot, e_cpv, e_status = existing_node
1729 if portage.match_from_list(x, [e_cpv]):
1730 # The existing node can be reused.
1731 selected_pkg = [e_type, myroot, e_cpv,
1732 self.useFlags[myroot][e_cpv]]
1735 #we are a dependency, so we want to be unconditionally added
1736 mypriority = priority.copy()
1738 mypriority.satisfied = True
1739 if not self.create(selected_pkg[0:3], myparent,
1740 myuse=selected_pkg[-1], priority=mypriority,
1741 rev_dep=rev_deps, arg=arg):
1744 #if mysource is not set, then we are a command-line dependency and should not be added
1745 #if --onlydeps is specified.
1746 if not self.create(selected_pkg[0:3], myparent,
1747 addme=("--onlydeps" not in self.myopts),
1748 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1751 if "--debug" in self.myopts:
1752 print "Exiting...",myparent
1755 def validate_blockers(self):
1756 """Remove any blockers from the digraph that do not match any of the
1757 packages within the graph. If necessary, create hard deps to ensure
1758 correct merge order such that mutually blocking packages are never
1759 installed simultaneously."""
1761 if "--buildpkgonly" in self.myopts or \
1762 "--nodeps" in self.myopts:
1766 for myroot in self.trees:
1768 modified_slots[myroot] = myslots
1769 final_db = self.mydbapi[myroot]
1770 slot_node_map = self._slot_node_map[myroot]
1771 for slot_atom, mynode in slot_node_map.iteritems():
1772 mytype, myroot, mycpv, mystatus = mynode
1773 if mystatus == "merge":
1774 myslots[slot_atom] = mycpv
1776 #if "deep" in self.myparams:
1778 # Pull in blockers from all installed packages that haven't already
1779 # been pulled into the depgraph. This is not enabled by default
1780 # due to the performance penalty that is incurred by all the
1781 # additional dep_check calls that are required.
1783 # Optimization hack for dep_check calls that minimizes the
1784 # available matches by replacing the portdb with a fakedbapi
1786 class FakePortageTree(object):
1787 def __init__(self, mydb):
1789 dep_check_trees = {}
1790 for myroot in self.trees:
1791 dep_check_trees[myroot] = self.trees[myroot].copy()
1792 dep_check_trees[myroot]["porttree"] = \
1793 FakePortageTree(self.mydbapi[myroot])
1795 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1796 for myroot in self.trees:
1797 pkg_node_map = self.pkg_node_map[myroot]
1798 vardb = self.trees[myroot]["vartree"].dbapi
1799 portdb = self.trees[myroot]["porttree"].dbapi
1800 pkgsettings = self.pkgsettings[myroot]
1801 final_db = self.mydbapi[myroot]
1802 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
1803 blocker_cache = BlockerCache(myroot, vardb)
1804 for pkg in cpv_all_installed:
1805 blocker_atoms = None
1806 matching_node = pkg_node_map.get(pkg, None)
1807 if matching_node and \
1808 matching_node[3] == "nomerge":
1810 # If this node has any blockers, create a "nomerge"
1811 # node for it so that they can be enforced.
1812 self.spinner.update()
1813 blocker_data = blocker_cache.get(pkg)
1815 blocker_atoms = blocker_data.atoms
1817 dep_vals = vardb.aux_get(pkg, dep_keys)
1818 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
1819 depstr = " ".join(dep_vals)
1820 # It is crucial to pass in final_db here in order to
1821 # optimize dep_check calls by eliminating atoms via
1822 # dep_wordreduce and dep_eval calls.
1824 portage.dep._dep_check_strict = False
1826 success, atoms = portage.dep_check(depstr,
1827 final_db, pkgsettings, myuse=myuse,
1828 trees=dep_check_trees, myroot=myroot)
1829 except Exception, e:
1830 if isinstance(e, SystemExit):
1832 # This is helpful, for example, if a ValueError
1833 # is thrown from cpv_expand due to multiple
1834 # matches (this can happen if an atom lacks a
1836 show_invalid_depstring_notice(
1837 ("installed", myroot, pkg, "nomerge"),
1842 portage.dep._dep_check_strict = True
1844 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
1845 vardb.aux_get(pkg, ["SLOT"])[0])
1846 if slot_atom in modified_slots[myroot]:
1847 # This package is being replaced anyway, so
1848 # ignore invalid dependencies so as not to
1849 # annoy the user too much (otherwise they'd be
1850 # forced to manually unmerge it first).
1852 show_invalid_depstring_notice(
1853 ("installed", myroot, pkg, "nomerge"),
1856 blocker_atoms = [myatom for myatom in atoms \
1857 if myatom.startswith("!")]
1858 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
1859 blocker_cache[pkg] = \
1860 blocker_cache.BlockerData(counter, blocker_atoms)
1862 # Don't store this parent in pkg_node_map, because it's
1863 # not needed there and it might overwrite a "merge"
1864 # node with the same cpv.
1865 myparent = ("installed", myroot, pkg, "nomerge")
1866 for myatom in blocker_atoms:
1867 blocker = ("blocks", myroot, myatom[1:])
1869 self.blocker_parents.get(blocker, None)
1872 self.blocker_parents[blocker] = myparents
1873 myparents.add(myparent)
1874 blocker_cache.flush()
1877 for blocker in self.blocker_parents.keys():
1878 mytype, myroot, mydep = blocker
1879 initial_db = self.trees[myroot]["vartree"].dbapi
1880 final_db = self.mydbapi[myroot]
1881 blocked_initial = initial_db.match(mydep)
1882 blocked_final = final_db.match(mydep)
1883 if not blocked_initial and not blocked_final:
1884 del self.blocker_parents[blocker]
1886 blocked_slots_initial = {}
1887 blocked_slots_final = {}
1888 for cpv in blocked_initial:
1889 blocked_slots_initial[cpv] = \
1890 "%s:%s" % (portage.dep_getkey(cpv),
1891 initial_db.aux_get(cpv, ["SLOT"])[0])
1892 for cpv in blocked_final:
1893 blocked_slots_final[cpv] = \
1894 "%s:%s" % (portage.dep_getkey(cpv),
1895 final_db.aux_get(cpv, ["SLOT"])[0])
1896 blocked_slots_final_values = set(blocked_slots_final.itervalues())
1897 for parent in list(self.blocker_parents[blocker]):
1898 ptype, proot, pcpv, pstatus = parent
1899 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1900 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1901 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1902 parent_static = pslot_atom not in modified_slots[proot]
1903 unresolved_blocks = False
1904 depends_on_order = set()
1905 for cpv in blocked_initial:
1906 slot_atom = blocked_slots_initial[cpv]
1907 if slot_atom == pslot_atom:
1908 # The parent blocks an initial package in the same
1909 # slot as itself. The merge/nomerge status of neither
1910 # node matters. In any case, this particular block is
1911 # automatically resolved.
1913 if parent_static and \
1914 slot_atom not in modified_slots[myroot]:
1915 # This blocker will be handled the next time that a
1916 # merge of either package is triggered.
1918 if pstatus == "merge" and \
1919 slot_atom not in blocked_slots_final_values:
1920 upgrade_matches = final_db.match(slot_atom)
1922 # Apparently an upgrade may be able to invalidate
1925 self.pkg_node_map[proot][upgrade_matches[0]]
1926 depends_on_order.add(upgrade_node)
1928 # None of the above blocker resolutions techniques apply,
1929 # so apparently this one is unresolvable.
1930 unresolved_blocks = True
1931 for cpv in blocked_final:
1932 slot_atom = blocked_slots_final[cpv]
1933 if slot_atom == pslot_atom:
1934 # The parent blocks itself, so the merge order does not
1935 # need to be enforced.
1937 if parent_static and \
1938 slot_atom not in modified_slots[myroot]:
1939 # This blocker will be handled the next time that a
1940 # merge of either package is triggered.
1942 # None of the above blocker resolutions techniques apply,
1943 # so apparently this one is unresolvable.
1944 unresolved_blocks = True
1945 if not unresolved_blocks and depends_on_order:
1946 for node in depends_on_order:
1947 # Enforce correct merge order with a hard dep.
1948 self.digraph.addnode(node, parent,
1949 priority=DepPriority(buildtime=True))
1950 # Count references to this blocker so that it can be
1951 # invalidated after nodes referencing it have been
1953 self.blocker_digraph.addnode(node, blocker)
1954 if not unresolved_blocks and not depends_on_order:
1955 self.blocker_parents[blocker].remove(parent)
1956 if not self.blocker_parents[blocker]:
1957 del self.blocker_parents[blocker]
1958 # Validate blockers that depend on merge order.
1959 if not self.blocker_digraph.empty():
1961 if self._slot_collision_info:
1962 # The user is only notified of a slot collision if there are no
1963 # unresolvable blocks.
1964 for x in self.altlist():
1965 if x[0] == "blocks":
1967 self._show_slot_collision_notice(self._slot_collision_info[0])
1968 if not self._accept_collisions():
1972 def _accept_collisions(self):
1974 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
1975 if x in self.myopts:
1980 def _merge_order_bias(self, mygraph):
1981 """Order nodes from highest to lowest overall reference count for
1982 optimal leaf node selection."""
1984 for node in mygraph.order:
1985 node_info[node] = len(mygraph.parent_nodes(node))
1986 def cmp_merge_preference(node1, node2):
1987 return node_info[node2] - node_info[node1]
1988 mygraph.order.sort(cmp_merge_preference)
1990 def altlist(self, reversed=False):
1991 if reversed in self._altlist_cache:
1992 return self._altlist_cache[reversed][:]
1994 retlist = self.altlist()
1996 self._altlist_cache[reversed] = retlist[:]
1998 mygraph=self.digraph.copy()
1999 self._merge_order_bias(mygraph)
2000 myblockers = self.blocker_digraph.copy()
2002 circular_blocks = False
2006 get_nodes = mygraph.root_nodes
2008 get_nodes = mygraph.leaf_nodes
2009 for cpv, node in self.pkg_node_map["/"].iteritems():
2010 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
2011 asap_nodes.append(node)
2013 ignore_priority_range = [None]
2014 ignore_priority_range.extend(
2015 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2016 tree_mode = "--tree" in self.myopts
2017 while not mygraph.empty():
2018 ignore_priority = None
2021 """ASAP nodes are merged before their soft deps."""
2022 for node in asap_nodes:
2023 if not mygraph.contains(node):
2024 asap_nodes.remove(node)
2026 if not mygraph.child_nodes(node,
2027 ignore_priority=DepPriority.SOFT):
2029 asap_nodes.remove(node)
2032 for ignore_priority in ignore_priority_range:
2033 nodes = get_nodes(ignore_priority=ignore_priority)
2036 selected_nodes = None
2038 if ignore_priority <= DepPriority.SOFT:
2039 if ignore_priority is None and not tree_mode:
2040 # Greedily pop all of these nodes since no relationship
2041 # has been ignored. This optimization destroys --tree
2042 # output, so it's disabled in reversed mode.
2043 selected_nodes = nodes
2045 # For optimal merge order:
2046 # * Only pop one node.
2047 # * Removing a root node (node without a parent)
2048 # will not produce a leaf node, so avoid it.
2050 if mygraph.parent_nodes(node):
2051 # found a non-root node
2052 selected_nodes = [node]
2054 if not selected_nodes:
2055 # settle for a root node
2056 selected_nodes = [nodes[0]]
2058 """Recursively gather a group of nodes that RDEPEND on
2059 eachother. This ensures that they are merged as a group
2060 and get their RDEPENDs satisfied as soon as possible."""
2061 def gather_deps(mergeable_nodes, selected_nodes, node):
2062 if node in selected_nodes:
2064 if node not in mergeable_nodes:
2066 selected_nodes.add(node)
2067 for child in mygraph.child_nodes(node,
2068 ignore_priority=DepPriority.SOFT):
2070 mergeable_nodes, selected_nodes, child):
2073 mergeable_nodes = set(nodes)
2075 selected_nodes = set()
2077 mergeable_nodes, selected_nodes, node):
2080 selected_nodes = None
2082 if not selected_nodes:
2083 if not myblockers.is_empty():
2084 """A blocker couldn't be circumnavigated while keeping all
2085 dependencies satisfied. The user will have to resolve this
2086 manually. This is a panic condition and thus the order
2087 doesn't really matter, so just pop a random node in order
2088 to avoid a circular dependency panic if possible."""
2089 if not circular_blocks:
2090 circular_blocks = True
2091 blocker_deps = myblockers.leaf_nodes()
2093 selected_nodes = [blocker_deps.pop()]
2095 if not selected_nodes:
2096 # No leaf nodes are available, so we have a circular
2097 # dependency panic situation. Reduce the noise level to a
2098 # minimum via repeated elimination of root nodes since they
2099 # have no parents and thus can not be part of a cycle.
2101 root_nodes = mygraph.root_nodes(
2102 ignore_priority=DepPriority.SOFT)
2105 for node in root_nodes:
2106 mygraph.remove(node)
2107 # Display the USE flags that are enabled on nodes that are part
2108 # of dependency cycles in case that helps the user decide to
2109 # disable some of them.
2111 tempgraph = mygraph.copy()
2112 while not tempgraph.empty():
2113 nodes = tempgraph.leaf_nodes()
2115 node = tempgraph.order[0]
2118 display_order.append(list(node))
2119 tempgraph.remove(node)
2120 display_order.reverse()
2121 self.myopts.pop("--quiet", None)
2122 self.myopts.pop("--verbose", None)
2123 self.myopts["--tree"] = True
2124 self.display(display_order)
2125 print "!!! Error: circular dependencies:"
2127 mygraph.debug_print()
2129 print "!!! Note that circular dependencies can often be avoided by temporarily"
2130 print "!!! disabling USE flags that trigger optional dependencies."
2133 for node in selected_nodes:
2134 retlist.append(list(node))
2135 mygraph.remove(node)
2136 if not reversed and not circular_blocks and myblockers.contains(node):
2137 """This node may have invalidated one or more blockers."""
2138 myblockers.remove(node)
2139 for blocker in myblockers.root_nodes():
2140 if not myblockers.child_nodes(blocker):
2141 myblockers.remove(blocker)
2142 del self.blocker_parents[blocker]
2145 """Blocker validation does not work with reverse mode,
2146 so self.altlist() should first be called with reverse disabled
2147 so that blockers are properly validated."""
2148 self.blocker_digraph = myblockers
2150 """ Add any unresolved blocks so that they can be displayed."""
2151 for blocker in self.blocker_parents:
2152 retlist.append(list(blocker))
2153 self._altlist_cache[reversed] = retlist[:]
2156 def xcreate(self,mode="system"):
2157 vardb = self.trees[self.target_root]["vartree"].dbapi
2158 portdb = self.trees[self.target_root]["porttree"].dbapi
2159 bindb = self.trees[self.target_root]["bintree"].dbapi
2160 def visible(mylist):
2161 matches = portdb.gvisible(portdb.visible(mylist))
2162 return [x for x in mylist \
2163 if x in matches or not portdb.cpv_exists(x)]
2164 world_problems = False
2166 mylist = getlist(self.settings, "system")
2169 worldlist = getlist(self.settings, "world")
2170 mylist = getlist(self.settings, "system")
2171 worlddict=genericdict(worldlist)
2173 for x in worlddict.keys():
2174 if not portage.isvalidatom(x):
2175 world_problems = True
2176 elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
2177 world_problems = True
2183 mykey = portage.dep_getkey(atom)
2185 newlist.append(atom)
2186 """Make sure all installed slots are updated when possible.
2187 Do this with --emptytree also, to ensure that all slots are
2190 for cpv in vardb.match(mykey):
2191 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2194 if "--usepkg" in self.myopts:
2195 mymatches = bindb.match(atom)
2196 if "--usepkgonly" not in self.myopts:
2197 mymatches = visible(mymatches)
2198 best_pkg = portage.best(mymatches)
2200 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2201 best_pkgs.append(("binary", best_pkg, best_slot))
2202 if "--usepkgonly" not in self.myopts:
2203 best_pkg = portage.best(portdb.match(atom))
2205 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2206 best_pkgs.append(("ebuild", best_pkg, best_slot))
2208 best_pkg = portage.best([x[1] for x in best_pkgs])
2209 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2210 best_slot = best_pkgs[0][2]
2211 myslots.add(best_slot)
2212 if len(myslots) > 1:
2213 for myslot in myslots:
2214 myslot_atom = "%s:%s" % (mykey, myslot)
2216 if "--usepkgonly" not in self.myopts and \
2217 self.trees[self.target_root][
2218 "porttree"].dbapi.match(myslot_atom):
2220 elif "--usepkg" in self.myopts:
2221 mymatches = bindb.match(myslot_atom)
2222 if "--usepkgonly" not in self.myopts:
2223 mymatches = visible(mymatches)
2227 newlist.append(myslot_atom)
2231 for mydep in mylist:
2233 if not self.select_dep(
2234 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2235 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2238 missing_atoms.append(mydep)
2240 if not self.validate_blockers():
2244 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2245 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2248 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2249 " Ebuilds for the following packages are either all"
2250 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2251 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2255 def display(self,mylist,verbosity=None):
2256 if verbosity is None:
2257 verbosity = ("--quiet" in self.myopts and 1 or \
2258 "--verbose" in self.myopts and 3 or 2)
2263 counters = PackageCounters()
2265 if verbosity == 1 and "--verbose" not in self.myopts:
2266 def create_use_string(*args):
2269 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2271 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2272 alphabetical=("--alphabetical" in self.myopts)):
2280 cur_iuse = set(cur_iuse)
2281 enabled_flags = cur_iuse.intersection(cur_use)
2282 removed_iuse = set(old_iuse).difference(cur_iuse)
2283 any_iuse = cur_iuse.union(old_iuse)
2284 any_iuse = list(any_iuse)
2286 for flag in any_iuse:
2289 if flag in enabled_flags:
2291 if is_new or flag in old_use and all_flags:
2292 flag_str = red(flag)
2293 elif flag not in old_iuse:
2294 flag_str = yellow(flag) + "%*"
2295 elif flag not in old_use:
2296 flag_str = green(flag) + "*"
2297 elif flag in removed_iuse:
2299 flag_str = yellow("-" + flag) + "%"
2302 flag_str = "(" + flag_str + ")"
2303 removed.append(flag_str)
2306 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2307 flag_str = blue("-" + flag)
2308 elif flag not in old_iuse:
2309 flag_str = yellow("-" + flag)
2310 if flag not in iuse_forced:
2312 elif flag in old_use:
2313 flag_str = green("-" + flag) + "*"
2315 if flag in iuse_forced:
2316 flag_str = "(" + flag_str + ")"
2318 enabled.append(flag_str)
2320 disabled.append(flag_str)
2323 ret = " ".join(enabled)
2325 ret = " ".join(enabled + disabled + removed)
2327 ret = '%s="%s" ' % (name, ret)
2331 # FIXME: account for the possibility of different overlays in
2332 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2333 overlays = self.settings["PORTDIR_OVERLAY"].split()
2334 overlays_real = [os.path.realpath(t) \
2335 for t in self.settings["PORTDIR_OVERLAY"].split()]
2339 mygraph = self._parent_child_digraph
2343 if "blocks" == x[0]:
2344 display_list.append((x, 0, True))
2346 graph_key = tuple(x)
2347 if "--tree" in self.myopts:
2348 depth = len(tree_nodes)
2349 while depth and graph_key not in \
2350 mygraph.child_nodes(tree_nodes[depth-1]):
2353 tree_nodes = tree_nodes[:depth]
2354 tree_nodes.append(graph_key)
2355 display_list.append((x, depth, True))
2357 traversed_nodes = set() # prevent endless circles
2358 traversed_nodes.add(graph_key)
2359 def add_parents(current_node, ordered):
2360 parent_nodes = mygraph.parent_nodes(current_node)
2362 child_nodes = set(mygraph.child_nodes(current_node))
2363 selected_parent = None
2364 # First, try to avoid a direct cycle.
2365 for node in parent_nodes:
2366 if node not in traversed_nodes and \
2367 node not in child_nodes:
2368 selected_parent = node
2370 if not selected_parent:
2371 # A direct cycle is unavoidable.
2372 for node in parent_nodes:
2373 if node not in traversed_nodes:
2374 selected_parent = node
2377 traversed_nodes.add(selected_parent)
2378 add_parents(selected_parent, False)
2379 display_list.append((list(current_node),
2380 len(tree_nodes), ordered))
2381 tree_nodes.append(current_node)
2383 add_parents(graph_key, True)
2385 display_list.append((x, depth, True))
2386 mylist = display_list
2388 last_merge_depth = 0
2389 for i in xrange(len(mylist)-1,-1,-1):
2390 graph_key, depth, ordered = mylist[i]
2391 if not ordered and depth == 0 and i > 0 \
2392 and graph_key == mylist[i-1][0] and \
2393 mylist[i-1][1] == 0:
2394 # An ordered node got a consecutive duplicate when the tree was
2398 if "blocks" == graph_key[0]:
2400 if ordered and graph_key[-1] != "nomerge":
2401 last_merge_depth = depth
2403 if depth >= last_merge_depth or \
2404 i < len(mylist) - 1 and \
2405 depth >= mylist[i+1][1]:
2408 display_overlays=False
2409 # files to fetch list - avoids counting a same file twice
2410 # in size display (verbose mode)
2412 for mylist_index in xrange(len(mylist)):
2413 x, depth, ordered = mylist[mylist_index]
2417 portdb = self.trees[myroot]["porttree"].dbapi
2418 bindb = self.trees[myroot]["bintree"].dbapi
2419 vardb = self.trees[myroot]["vartree"].dbapi
2420 vartree = self.trees[myroot]["vartree"]
2421 pkgsettings = self.pkgsettings[myroot]
2426 addl=""+red("B")+" "+fetch+" "
2428 counters.blocks += 1
2429 resolved = portage.key_expand(
2430 pkg_key, mydb=vardb, settings=pkgsettings)
2431 if "--columns" in self.myopts and "--quiet" in self.myopts:
2432 addl = addl + " " + red(resolved)
2434 addl = "[blocks " + addl + "] " + red(resolved)
2435 block_parents = self.blocker_parents[tuple(x)]
2436 block_parents = set([pnode[2] for pnode in block_parents])
2437 block_parents = ", ".join(block_parents)
2439 addl += bad(" (\"%s\" is blocking %s)") % \
2440 (pkg_key, block_parents)
2442 addl += bad(" (is blocking %s)") % block_parents
2443 blockers.append(addl)
2445 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2446 binary_package = True
2447 if "ebuild" == pkg_type:
2448 if "merge" == x[3] or \
2449 not vartree.dbapi.cpv_exists(pkg_key):
2450 """An ebuild "merge" node or a --onlydeps "nomerge"
2452 binary_package = False
2453 pkgsettings.setcpv(pkg_key, mydb=portdb)
2454 if pkg_key not in self.useFlags[myroot]:
2455 self.useFlags[myroot][pkg_key] = \
2456 pkgsettings["USE"].split()
2458 # An ebuild "nomerge" node, so USE come from the vardb.
2459 mydbapi = vartree.dbapi
2460 if pkg_key not in self.useFlags[myroot]:
2461 """If this is a --resume then the USE flags need to be
2462 fetched from the appropriate locations here."""
2463 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2464 pkg_key, ["USE"])[0].split()
2466 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2467 "fetch" in portdb.aux_get(
2468 x[2], ["RESTRICT"])[0].split():
2471 counters.restrict_fetch += 1
2472 if portdb.fetch_check(
2473 pkg_key, self.useFlags[myroot][pkg_key]):
2476 counters.restrict_fetch_satisfied += 1
2478 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2479 #param is used for -u, where you still *do* want to see when something is being upgraded.
2481 if vardb.cpv_exists(pkg_key):
2482 addl=" "+yellow("R")+fetch+" "
2483 if x[3] != "nomerge":
2485 counters.reinst += 1
2486 elif vardb.match(portage.dep_getkey(pkg_key)):
2487 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2488 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2489 portage.pkgsplit(x[2])[0])
2490 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2491 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2493 myoldbest=portage.best(myinslotlist)
2495 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2497 addl+=turquoise("U")+blue("D")
2499 counters.downgrades += 1
2502 addl+=turquoise("U")+" "
2504 counters.upgrades += 1
2506 # New slot, mark it new.
2507 addl=" "+green("NS")+fetch+" "
2509 counters.newslot += 1
2511 if "--changelog" in self.myopts:
2512 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2513 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2514 inst_matches = vardb.match(slot_atom)
2516 changelogs.extend(self.calc_changelog(
2517 portdb.findname(pkg_key),
2518 inst_matches[0], pkg_key))
2520 addl=" "+green("N")+" "+fetch+" "
2526 if pkg_key in self.useFlags[myroot]:
2528 cur_iuse = list(filter_iuse_defaults(
2529 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2531 forced_flags = set()
2532 if not binary_package:
2533 forced_flags.update(pkgsettings.useforce)
2534 forced_flags.update(pkgsettings.usemask)
2536 cur_iuse = portage.unique_array(cur_iuse)
2538 cur_use = self.useFlags[myroot][pkg_key]
2539 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2545 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2546 old_iuse, old_use = \
2547 self.trees[x[1]]["vartree"].dbapi.aux_get(
2548 pkg, ["IUSE", "USE"])
2549 old_iuse = list(set(
2550 filter_iuse_defaults(old_iuse.split())))
2552 old_use = old_use.split()
2559 old_use = [flag for flag in old_use if flag in old_iuse]
2561 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2563 use_expand.reverse()
2564 use_expand_hidden = \
2565 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2567 def map_to_use_expand(myvals, forcedFlags=False):
2570 for exp in use_expand:
2573 for val in myvals[:]:
2574 if val.startswith(exp.lower()+"_"):
2575 if val in forced_flags:
2576 forced[exp].add(val[len(exp)+1:])
2577 ret[exp].append(val[len(exp)+1:])
2580 forced["USE"] = [val for val in myvals \
2581 if val in forced_flags]
2582 for exp in use_expand_hidden:
2589 cur_iuse_map, iuse_forced = \
2590 map_to_use_expand(cur_iuse, forcedFlags=True)
2591 cur_use_map = map_to_use_expand(cur_use)
2592 old_iuse_map = map_to_use_expand(old_iuse)
2593 old_use_map = map_to_use_expand(old_use)
2596 use_expand.insert(0, "USE")
2598 for key in use_expand:
2599 if key in use_expand_hidden:
2601 verboseadd += create_use_string(key.upper(),
2602 cur_iuse_map[key], iuse_forced[key],
2603 cur_use_map[key], old_iuse_map[key],
2604 old_use_map[key], is_new)
2609 if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
2611 myfilesdict = portdb.getfetchsizes(pkg_key,
2612 useflags=self.useFlags[myroot][pkg_key],
2614 except portage.exception.InvalidDependString, e:
2615 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2616 show_invalid_depstring_notice(x, src_uri, str(e))
2619 if myfilesdict is None:
2620 myfilesdict="[empty/missing/bad digest]"
2622 for myfetchfile in myfilesdict.keys():
2623 if myfetchfile not in myfetchlist:
2624 mysize+=myfilesdict[myfetchfile]
2625 myfetchlist.append(myfetchfile)
2626 counters.totalsize += mysize
2627 verboseadd+=format_size(mysize)+" "
2630 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2631 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2632 file_name = portdb.findname(pkg_key)
2633 if file_name: # It might not exist in the tree
2634 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2635 if (overlays_real.count(dir_name)>0):
2636 verboseadd+=teal("["+str(overlays_real.index(
2637 os.path.normpath(dir_name))+1)+"]")+" "
2638 display_overlays=True
2640 verboseadd += "[No ebuild?]"
2642 xs=portage.pkgsplit(x[2])
2649 if "COLUMNWIDTH" in self.settings:
2651 mywidth = int(self.settings["COLUMNWIDTH"])
2652 except ValueError, e:
2653 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2655 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2656 self.settings["COLUMNWIDTH"], noiselevel=-1)
2661 indent = " " * depth
2664 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2665 if myoldbest[-3:]=="-r0":
2666 myoldbest=myoldbest[:-3]
2667 myoldbest=blue("["+myoldbest+"]")
2672 if "--columns" in self.myopts:
2673 if "--quiet" in self.myopts:
2674 myprint=addl+" "+indent+darkgreen(xs[0])
2675 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2676 myprint=myprint+myoldbest
2677 myprint=myprint+darkgreen("to "+x[1])
2679 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2680 if (newlp-nc_len(myprint)) > 0:
2681 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2682 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2683 if (oldlp-nc_len(myprint)) > 0:
2684 myprint=myprint+" "*(oldlp-nc_len(myprint))
2685 myprint=myprint+myoldbest
2686 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2688 if x[-1] == "nomerge" or not ordered:
2689 myprint = darkblue("[nomerge ] ")
2691 myprint = "[" + pkg_type + " " + addl + "] "
2692 myprint += indent + darkgreen(pkg_key) + " " + \
2693 myoldbest + darkgreen("to " + myroot) + " " + \
2696 if "--columns" in self.myopts:
2697 if "--quiet" in self.myopts:
2698 myprint=addl+" "+indent+darkgreen(xs[0])
2699 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2700 myprint=myprint+myoldbest
2702 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2703 if (newlp-nc_len(myprint)) > 0:
2704 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2705 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2706 if (oldlp-nc_len(myprint)) > 0:
2707 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2708 myprint=myprint+myoldbest+" "+verboseadd
2710 if x[-1] == "nomerge" or not ordered:
2711 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2713 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2716 mysplit = portage.pkgsplit(x[2])
2717 if "--tree" not in self.myopts and mysplit and \
2718 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2721 if mysplit[2] == "r0":
2722 myversion = mysplit[1]
2724 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2726 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2727 if mylist_index < len(mylist) - 1 and \
2728 "livecvsportage" not in self.settings.features:
2729 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2730 p.append(colorize("WARN", " then resume the merge."))
2742 if overlays and display_overlays:
2743 print "Portage overlays:"
2747 print " "+teal("["+str(y)+"]"),x
2749 if "--changelog" in self.myopts:
2751 for revision,text in changelogs:
2752 print bold('*'+revision)
2753 sys.stdout.write(text)
2755 if self._pprovided_args:
2757 msg.append(bad("\nWARNING: "))
2758 if len(self._pprovided_args) > 1:
2759 msg.append("Requested packages will not be " + \
2760 "merged because they are listed in\n")
2762 msg.append("A requested package will not be " + \
2763 "merged because it is listed in\n")
2764 msg.append(" package.provided:\n\n")
2765 for arg in self._pprovided_args:
2766 msg.append(" " + arg + "\n")
2768 sys.stderr.write("".join(msg))
2770 def calc_changelog(self,ebuildpath,current,next):
2771 current = '-'.join(portage.catpkgsplit(current)[1:])
2772 if current.endswith('-r0'): current = current[:-3]
2773 next = '-'.join(portage.catpkgsplit(next)[1:])
2774 if next.endswith('-r0'): next = next[:-3]
2775 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2777 changelog = open(changelogpath).read()
2778 except SystemExit, e:
2779 raise # Needed else can't exit
2782 divisions = self.find_changelog_tags(changelog)
2783 #print 'XX from',current,'to',next
2784 #for div,text in divisions: print 'XX',div
2785 # skip entries for all revisions above the one we are about to emerge
2786 for i in range(len(divisions)):
2787 if divisions[i][0]==next:
2788 divisions = divisions[i:]
2790 # find out how many entries we are going to display
2791 for i in range(len(divisions)):
2792 if divisions[i][0]==current:
2793 divisions = divisions[:i]
2796 # couldnt find the current revision in the list. display nothing
2800 def find_changelog_tags(self,changelog):
2804 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2806 if release is not None:
2807 divs.append((release,changelog))
2809 if release is not None:
2810 divs.append((release,changelog[:match.start()]))
2811 changelog = changelog[match.end():]
2812 release = match.group(1)
2813 if release.endswith('.ebuild'):
2814 release = release[:-7]
2815 if release.endswith('-r0'):
2816 release = release[:-3]
2819 return self.outdatedpackages
2821 class PackageCounters(object):
2831 self.restrict_fetch = 0
2832 self.restrict_fetch_satisfied = 0
2835 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2838 myoutput.append("Total: %s package" % total_installs)
2839 if total_installs != 1:
2840 myoutput.append("s")
2841 if total_installs != 0:
2842 myoutput.append(" (")
2843 if self.upgrades > 0:
2844 details.append("%s upgrade" % self.upgrades)
2845 if self.upgrades > 1:
2847 if self.downgrades > 0:
2848 details.append("%s downgrade" % self.downgrades)
2849 if self.downgrades > 1:
2852 details.append("%s new" % self.new)
2853 if self.newslot > 0:
2854 details.append("%s in new slot" % self.newslot)
2855 if self.newslot > 1:
2858 details.append("%s reinstall" % self.reinst)
2862 details.append("%s block" % self.blocks)
2865 myoutput.append(", ".join(details))
2866 if total_installs != 0:
2867 myoutput.append(")")
2868 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2869 if self.restrict_fetch:
2870 myoutput.append("\nFetch Restriction: %s package" % \
2871 self.restrict_fetch)
2872 if self.restrict_fetch > 1:
2873 myoutput.append("s")
2874 if self.restrict_fetch_satisfied < self.restrict_fetch:
2875 myoutput.append(bad(" (%s unsatisfied)") % \
2876 (self.restrict_fetch - self.restrict_fetch_satisfied))
2877 return "".join(myoutput)
2879 class MergeTask(object):
2881 def __init__(self, settings, trees, myopts):
2882 self.settings = settings
2883 self.target_root = settings["ROOT"]
2885 self.myopts = myopts
2887 if settings.get("PORTAGE_DEBUG", "") == "1":
2889 self.pkgsettings = {}
2890 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2891 if self.target_root != "/":
2892 self.pkgsettings["/"] = \
2893 portage.config(clone=trees["/"]["vartree"].settings)
2895 def merge(self, mylist, favorites, mtimedb):
2898 ldpath_mtimes = mtimedb["ldpath"]
2899 xterm_titles = "notitles" not in self.settings.features
2901 #check for blocking dependencies
2902 if "--fetchonly" not in self.myopts and \
2903 "--fetch-all-uri" not in self.myopts and \
2904 "--buildpkgonly" not in self.myopts:
2907 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2908 print "!!! the two packages cannot be installed on the same system together."
2909 print "!!! Please use 'emerge --pretend' to determine blockers."
2910 if "--quiet" not in self.myopts:
2911 show_blocker_docs_link()
2914 # Verify all the manifests now so that the user is notified of failure
2915 # as soon as possible.
2916 if "--fetchonly" not in self.myopts and \
2917 "--fetch-all-uri" not in self.myopts and \
2918 "strict" in self.settings.features:
2919 shown_verifying_msg = False
2921 for myroot, pkgsettings in self.pkgsettings.iteritems():
2922 quiet_config = portage.config(clone=pkgsettings)
2923 quiet_config["PORTAGE_QUIET"] = "1"
2924 quiet_config.backup_changes("PORTAGE_QUIET")
2925 quiet_settings[myroot] = quiet_config
2928 if x[0] != "ebuild" or x[-1] == "nomerge":
2930 if not shown_verifying_msg:
2931 shown_verifying_msg = True
2932 print ">>> Verifying ebuild Manifests..."
2933 mytype, myroot, mycpv, mystatus = x
2934 portdb = self.trees[myroot]["porttree"].dbapi
2935 quiet_config = quiet_settings[myroot]
2936 quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
2937 if not portage.digestcheck([], quiet_config, strict=True):
2939 del x, mytype, myroot, mycpv, mystatus, quiet_config
2940 del shown_verifying_msg, quiet_settings
2942 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
2943 mysysdict = genericdict(getlist(self.settings, "system"))
2944 if "--resume" in self.myopts:
2946 print colorize("GOOD", "*** Resuming merge...")
2947 emergelog(xterm_titles, " *** Resuming merge...")
2948 mymergelist=mtimedb["resume"]["mergelist"][:]
2949 if "--skipfirst" in self.myopts and mymergelist:
2950 del mtimedb["resume"]["mergelist"][0]
2953 validate_merge_list(self.trees, mymergelist)
2955 myfavs = portage.grabfile(
2956 os.path.join(self.target_root, portage.WORLD_FILE))
2957 myfavdict=genericdict(myfavs)
2958 for x in range(len(mylist)):
2959 if mylist[x][3]!="nomerge":
2960 # Add to the mergelist
2961 mymergelist.append(mylist[x])
2963 myfavkey=portage.cpv_getkey(mylist[x][2])
2964 if "--onlydeps" in self.myopts:
2966 # Add to the world file. Since we won't be able to later.
2967 if "--fetchonly" not in self.myopts and \
2968 myfavkey in favorites:
2969 #don't record if already in system profile or already recorded
2970 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
2971 #we don't have a favorites entry for this package yet; add one
2972 myfavdict[myfavkey]=myfavkey
2973 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
2974 if not ("--fetchonly" in self.myopts or \
2975 "--fetch-all-uri" in self.myopts or \
2976 "--pretend" in self.myopts):
2977 portage.write_atomic(
2978 os.path.join(self.target_root, portage.WORLD_FILE),
2979 "\n".join(myfavdict.values()))
2981 mtimedb["resume"]["mergelist"]=mymergelist[:]
2984 myfeat = self.settings.features[:]
2985 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
2987 if "parallel-fetch" in myfeat and \
2988 not ("--pretend" in self.myopts or \
2989 "--fetch-all-uri" in self.myopts or \
2990 "--fetchonly" in self.myopts):
2991 if "distlocks" not in myfeat:
2993 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
2994 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
2996 elif len(mymergelist) > 1:
2997 print ">>> starting parallel fetching"
2998 fetch_log = "/var/log/emerge-fetch.log"
2999 logfile = open(fetch_log, "w")
3000 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3001 portage.util.apply_secpass_permissions(fetch_log,
3002 uid=portage.portage_uid, gid=portage.portage_gid,
3004 fetch_env = os.environ.copy()
3005 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3006 fetch_env["PORTAGE_NICENESS"] = "0"
3007 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3008 resume_opts = self.myopts.copy()
3009 # For automatic resume, we need to prevent
3010 # any of bad_resume_opts from leaking in
3011 # via EMERGE_DEFAULT_OPTS.
3012 resume_opts["--ignore-default-opts"] = True
3013 for myopt, myarg in resume_opts.iteritems():
3014 if myopt not in bad_resume_opts:
3016 fetch_args.append(myopt)
3018 fetch_args.append(myopt +"="+ myarg)
3019 portage.process.spawn(fetch_args, env=fetch_env,
3020 fd_pipes=fd_pipes, returnpid=True)
3021 logfile.close() # belongs to the spawned process
3022 del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3026 for x in mymergelist:
3031 portdb = self.trees[myroot]["porttree"].dbapi
3032 bindb = self.trees[myroot]["bintree"].dbapi
3033 vartree = self.trees[myroot]["vartree"]
3034 pkgsettings = self.pkgsettings[myroot]
3037 y = portdb.findname(pkg_key)
3038 if "--pretend" not in self.myopts:
3039 print "\n>>> Emerging (" + \
3040 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3041 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3042 colorize("GOOD", x[pkgindex]) + " to " + x[1]
3043 emergelog(xterm_titles, " >>> emerge ("+\
3044 str(mergecount)+" of "+str(len(mymergelist))+\
3045 ") "+x[pkgindex]+" to "+x[1])
3047 pkgsettings["EMERGE_FROM"] = x[0]
3048 pkgsettings.backup_changes("EMERGE_FROM")
3051 #buildsyspkg: Check if we need to _force_ binary package creation
3052 issyspkg = ("buildsyspkg" in myfeat) \
3053 and x[0] != "blocks" \
3054 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3055 and "--buildpkg" not in self.myopts
3056 if x[0] in ["ebuild","blocks"]:
3057 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3058 raise Exception, "Merging a blocker"
3059 elif "--fetchonly" in self.myopts or \
3060 "--fetch-all-uri" in self.myopts:
3061 if "--fetch-all-uri" in self.myopts:
3062 retval = portage.doebuild(y, "fetch", myroot,
3063 pkgsettings, self.edebug,
3064 "--pretend" in self.myopts, fetchonly=1,
3065 fetchall=1, mydbapi=portdb, tree="porttree")
3067 retval = portage.doebuild(y, "fetch", myroot,
3068 pkgsettings, self.edebug,
3069 "--pretend" in self.myopts, fetchonly=1,
3070 mydbapi=portdb, tree="porttree")
3071 if (retval is None) or retval:
3073 print "!!! Fetch for",y,"failed, continuing..."
3075 failed_fetches.append(pkg_key)
3078 portage.doebuild_environment(y, "setup", myroot,
3079 pkgsettings, self.edebug, 1, portdb)
3080 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3081 portage.util.ensure_dirs(os.path.dirname(catdir),
3082 uid=portage.portage_uid, gid=portage.portage_gid,
3084 builddir_lock = None
3087 catdir_lock = portage.locks.lockdir(catdir)
3088 portage.util.ensure_dirs(catdir,
3089 uid=portage.portage_uid, gid=portage.portage_gid,
3091 builddir_lock = portage.locks.lockdir(
3092 pkgsettings["PORTAGE_BUILDDIR"])
3094 portage.locks.unlockdir(catdir_lock)
3097 msg = " === (%s of %s) Cleaning (%s::%s)" % \
3098 (mergecount, len(mymergelist), pkg_key, y)
3099 short_msg = "emerge: (%s of %s) %s Clean" % \
3100 (mergecount, len(mymergelist), pkg_key)
3101 emergelog(xterm_titles, msg, short_msg=short_msg)
3102 retval = portage.doebuild(y, "clean", myroot,
3103 pkgsettings, self.edebug, cleanup=1,
3104 mydbapi=portdb, tree="porttree")
3105 if retval != os.EX_OK:
3107 if "--buildpkg" in self.myopts or issyspkg:
3109 print ">>> This is a system package, " + \
3110 "let's pack a rescue tarball."
3111 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3112 (mergecount, len(mymergelist), pkg_key, y)
3113 short_msg = "emerge: (%s of %s) %s Compile" % \
3114 (mergecount, len(mymergelist), pkg_key)
3115 emergelog(xterm_titles, msg, short_msg=short_msg)
3116 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3117 retval = portage.doebuild(y, "package", myroot,
3118 pkgsettings, self.edebug, mydbapi=portdb,
3120 if retval != os.EX_OK:
3122 bintree = self.trees[myroot]["bintree"]
3123 if bintree.populated:
3124 bintree.inject(pkg_key)
3125 if "--buildpkgonly" not in self.myopts:
3126 msg = " === (%s of %s) Merging (%s::%s)" % \
3127 (mergecount, len(mymergelist), pkg_key, y)
3128 short_msg = "emerge: (%s of %s) %s Merge" % \
3129 (mergecount, len(mymergelist), pkg_key)
3130 emergelog(xterm_titles, msg, short_msg=short_msg)
3131 retval = portage.merge(pkgsettings["CATEGORY"],
3132 pkgsettings["PF"], pkgsettings["D"],
3133 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3134 "build-info"), myroot, pkgsettings,
3135 myebuild=pkgsettings["EBUILD"],
3136 mytree="porttree", mydbapi=portdb,
3137 vartree=vartree, prev_mtimes=ldpath_mtimes)
3138 if retval != os.EX_OK:
3140 elif "noclean" not in pkgsettings.features:
3141 portage.doebuild(y, "clean", myroot,
3142 pkgsettings, self.edebug, mydbapi=portdb,
3145 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3146 (mergecount, len(mymergelist), pkg_key, y)
3147 short_msg = "emerge: (%s of %s) %s Compile" % \
3148 (mergecount, len(mymergelist), pkg_key)
3149 emergelog(xterm_titles, msg, short_msg=short_msg)
3150 retval = portage.doebuild(y, "merge", myroot,
3151 pkgsettings, self.edebug, vartree=vartree,
3152 mydbapi=portdb, tree="porttree",
3153 prev_mtimes=ldpath_mtimes)
3154 if retval != os.EX_OK:
3158 portage.locks.unlockdir(builddir_lock)
3161 # Lock catdir for removal if empty.
3162 catdir_lock = portage.locks.lockdir(catdir)
3168 if e.errno not in (errno.ENOENT,
3169 errno.ENOTEMPTY, errno.EEXIST):
3172 portage.locks.unlockdir(catdir_lock)
3174 elif x[0]=="binary":
3176 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3177 if "--getbinpkg" in self.myopts:
3180 if "distlocks" in pkgsettings.features and \
3181 os.access(pkgsettings["PKGDIR"], os.W_OK):
3182 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3183 tbz2_lock = portage.locks.lockfile(mytbz2,
3185 if self.trees[myroot]["bintree"].isremote(pkg_key):
3186 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3187 (mergecount, len(mymergelist), pkg_key, mytbz2)
3188 short_msg = "emerge: (%s of %s) %s Fetch" % \
3189 (mergecount, len(mymergelist), pkg_key)
3190 emergelog(xterm_titles, msg, short_msg=short_msg)
3191 if not self.trees[myroot]["bintree"].gettbz2(
3196 portage.locks.unlockfile(tbz2_lock)
3198 if "--fetchonly" in self.myopts or \
3199 "--fetch-all-uri" in self.myopts:
3202 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3203 emergelog(xterm_titles, " === ("+str(mergecount)+\
3204 " of "+str(len(mymergelist))+") Merging Binary ("+\
3205 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3206 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3208 vartree=self.trees[myroot]["vartree"],
3209 prev_mtimes=ldpath_mtimes)
3210 if retval != os.EX_OK:
3212 #need to check for errors
3213 if "--buildpkgonly" not in self.myopts:
3214 self.trees[x[1]]["vartree"].inject(x[2])
3215 myfavkey=portage.cpv_getkey(x[2])
3216 if "--fetchonly" not in self.myopts and \
3217 "--fetch-all-uri" not in self.myopts and \
3218 myfavkey in favorites:
3219 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3220 myfavdict=genericdict(myfavs)
3221 #don't record if already in system profile or already recorded
3222 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3223 #we don't have a favorites entry for this package yet; add one
3224 myfavdict[myfavkey]=myfavkey
3225 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3226 emergelog(xterm_titles, " === ("+\
3227 str(mergecount)+" of "+\
3228 str(len(mymergelist))+\
3229 ") Updating world file ("+x[pkgindex]+")")
3230 portage.write_atomic(
3231 os.path.join(myroot, portage.WORLD_FILE),
3232 "\n".join(myfavdict.values()))
3234 if "--pretend" not in self.myopts and \
3235 "--fetchonly" not in self.myopts and \
3236 "--fetch-all-uri" not in self.myopts:
3237 # Clean the old package that we have merged over top of it.
3238 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3239 xsplit=portage.pkgsplit(x[2])
3240 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3241 retval = unmerge(pkgsettings, self.myopts, vartree,
3242 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3244 emergelog(xterm_titles,
3245 " --- AUTOCLEAN: Nothing unmerged.")
3247 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3248 + " AUTOCLEAN is disabled. This can cause serious"
3249 + " problems due to overlapping packages.\n")
3251 # Figure out if we need a restart.
3252 mysplit=portage.pkgsplit(x[2])
3253 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3254 myver=mysplit[1]+"-"+mysplit[2]
3255 if myver[-3:]=='-r0':
3257 if (myver != portage.VERSION) and \
3258 "livecvsportage" not in self.settings.features:
3259 if len(mymergelist) > mergecount:
3260 emergelog(xterm_titles,
3261 " ::: completed emerge ("+ \
3262 str(mergecount)+" of "+ \
3263 str(len(mymergelist))+") "+ \
3265 emergelog(xterm_titles, " *** RESTARTING " + \
3266 "emerge via exec() after change of " + \
3268 del mtimedb["resume"]["mergelist"][0]
3270 portage.run_exitfuncs()
3271 mynewargv=[sys.argv[0],"--resume"]
3272 resume_opts = self.myopts.copy()
3273 # For automatic resume, we need to prevent
3274 # any of bad_resume_opts from leaking in
3275 # via EMERGE_DEFAULT_OPTS.
3276 resume_opts["--ignore-default-opts"] = True
3277 for myopt, myarg in resume_opts.iteritems():
3278 if myopt not in bad_resume_opts:
3280 mynewargv.append(myopt)
3282 mynewargv.append(myopt +"="+ myarg)
3283 # priority only needs to be adjusted on the first run
3284 os.environ["PORTAGE_NICENESS"] = "0"
3285 os.execv(mynewargv[0], mynewargv)
3287 if "--pretend" not in self.myopts and \
3288 "--fetchonly" not in self.myopts and \
3289 "--fetch-all-uri" not in self.myopts:
3290 if "noclean" not in self.settings.features:
3291 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3292 (mergecount, len(mymergelist), x[pkgindex])
3293 emergelog(xterm_titles, (" === (%s of %s) " + \
3294 "Post-Build Cleaning (%s::%s)") % \
3295 (mergecount, len(mymergelist), x[pkgindex], y),
3296 short_msg=short_msg)
3297 emergelog(xterm_titles, " ::: completed emerge ("+\
3298 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3301 # Unsafe for parallel merges
3302 del mtimedb["resume"]["mergelist"][0]
3303 # Commit after each merge so that --resume may still work in
3304 # in the event that portage is not allowed to exit normally
3305 # due to power failure, SIGKILL, etc...
3308 if "--pretend" not in self.myopts:
3309 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3311 # We're out of the loop... We're done. Delete the resume data.
3312 if mtimedb.has_key("resume"):
3313 del mtimedb["resume"]
3316 #by doing an exit this way, --fetchonly can continue to try to
3317 #fetch everything even if a particular download fails.
3318 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3320 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3321 "encountered. Please see above for details.\n\n")
3322 for cpv in failed_fetches:
3323 sys.stderr.write(" ")
3324 sys.stderr.write(cpv)
3325 sys.stderr.write("\n")
3326 sys.stderr.write("\n")
3332 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3333 ldpath_mtimes, autoclean=0):
3334 candidate_catpkgs=[]
3336 xterm_titles = "notitles" not in settings.features
3338 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3340 # At least the parent needs to exist for the lock file.
3341 portage.util.ensure_dirs(vdb_path)
3342 except portage.exception.PortageException:
3346 if os.access(vdb_path, os.W_OK):
3347 vdb_lock = portage.locks.lockdir(vdb_path)
3348 realsyslist = getlist(settings, "system")
3350 for x in realsyslist:
3351 mycp = portage.dep_getkey(x)
3352 if mycp in settings.getvirtuals():
3354 for provider in settings.getvirtuals()[mycp]:
3355 if vartree.dbapi.match(provider):
3356 providers.append(provider)
3357 if len(providers) == 1:
3358 syslist.extend(providers)
3360 syslist.append(mycp)
3362 mysettings = portage.config(clone=settings)
3364 if not unmerge_files or "world" in unmerge_files or \
3365 "system" in unmerge_files:
3366 if "unmerge"==unmerge_action:
3368 print bold("emerge unmerge") + " can only be used with " + \
3369 "specific package names, not with "+bold("world")+" or"
3370 print bold("system")+" targets."
3377 # process all arguments and add all
3378 # valid db entries to candidate_catpkgs
3380 if not unmerge_files or "world" in unmerge_files:
3381 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3382 elif "system" in unmerge_files:
3383 candidate_catpkgs.extend(getlist(settings, "system"))
3385 #we've got command-line arguments
3386 if not unmerge_files:
3387 print "\nNo packages to unmerge have been provided.\n"
3389 for x in unmerge_files:
3390 arg_parts = x.split('/')
3391 if x[0] not in [".","/"] and \
3392 arg_parts[-1][-7:] != ".ebuild":
3393 #possible cat/pkg or dep; treat as such
3394 candidate_catpkgs.append(x)
3395 elif unmerge_action in ["prune","clean"]:
3396 print "\n!!! Prune and clean do not accept individual" + \
3397 " ebuilds as arguments;\n skipping.\n"
3400 # it appears that the user is specifying an installed
3401 # ebuild and we're in "unmerge" mode, so it's ok.
3402 if not os.path.exists(x):
3403 print "\n!!! The path '"+x+"' doesn't exist.\n"
3406 absx = os.path.abspath(x)
3407 sp_absx = absx.split("/")
3408 if sp_absx[-1][-7:] == ".ebuild":
3410 absx = "/".join(sp_absx)
3412 sp_absx_len = len(sp_absx)
3414 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3415 vdb_len = len(vdb_path)
3417 sp_vdb = vdb_path.split("/")
3418 sp_vdb_len = len(sp_vdb)
3420 if not os.path.exists(absx+"/CONTENTS"):
3421 print "!!! Not a valid db dir: "+str(absx)
3424 if sp_absx_len <= sp_vdb_len:
3425 # The Path is shorter... so it can't be inside the vdb.
3428 print "\n!!!",x,"cannot be inside "+ \
3429 vdb_path+"; aborting.\n"
3432 for idx in range(0,sp_vdb_len):
3433 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3436 print "\n!!!", x, "is not inside "+\
3437 vdb_path+"; aborting.\n"
3440 print "="+"/".join(sp_absx[sp_vdb_len:])
3441 candidate_catpkgs.append(
3442 "="+"/".join(sp_absx[sp_vdb_len:]))
3445 if (not "--quiet" in myopts):
3447 if settings["ROOT"] != "/":
3448 print darkgreen(newline+ \
3449 ">>> Using system located in ROOT tree "+settings["ROOT"])
3450 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3451 not ("--quiet" in myopts):
3452 print darkgreen(newline+\
3453 ">>> These are the packages that would be unmerged:")
3457 for x in candidate_catpkgs:
3458 # cycle through all our candidate deps and determine
3459 # what will and will not get unmerged
3461 mymatch=localtree.dep_match(x)
3464 except ValueError, errpkgs:
3465 print "\n\n!!! The short ebuild name \"" + \
3466 x + "\" is ambiguous. Please specify"
3467 print "!!! one of the following fully-qualified " + \
3468 "ebuild names instead:\n"
3469 for i in errpkgs[0]:
3470 print " " + green(i)
3474 if not mymatch and x[0] not in "<>=~":
3475 #add a "=" if missing
3476 mymatch=localtree.dep_match("="+x)
3478 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3479 (x, unmerge_action), noiselevel=-1)
3481 mykey = portage.key_expand(
3483 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3484 if not pkgmap.has_key(mykey):
3485 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3486 if unmerge_action=="unmerge":
3488 if y not in pkgmap[mykey]["selected"]:
3489 pkgmap[mykey]["selected"].append(y)
3490 numselected=numselected+len(mymatch)
3493 #unmerge_action in ["prune", clean"]
3495 for mypkg in mymatch:
3496 if unmerge_action=="clean":
3497 myslot=localtree.getslot(mypkg)
3499 # since we're pruning, we don't care about slots
3500 # and put all the pkgs in together
3502 if not slotmap.has_key(myslot):
3504 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3505 for myslot in slotmap.keys():
3506 counterkeys=slotmap[myslot].keys()
3511 pkgmap[mykey]["protected"].append(
3512 slotmap[myslot][counterkeys[-1]])
3514 #be pretty and get them in order of merge:
3515 for ckey in counterkeys:
3516 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
3517 numselected=numselected+1
3518 # ok, now the last-merged package
3519 # is protected, and the rest are selected
3520 if global_unmerge and not numselected:
3521 portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
3525 portage.writemsg_stdout(
3526 "\n>>> No packages selected for removal by " + \
3527 unmerge_action + "\n")
3531 portage.locks.unlockdir(vdb_lock)
3532 for x in pkgmap.keys():
3533 for y in localtree.dep_match(x):
3534 if y not in pkgmap[x]["omitted"] and \
3535 y not in pkgmap[x]["selected"] and \
3536 y not in pkgmap[x]["protected"]:
3537 pkgmap[x]["omitted"].append(y)
3538 if global_unmerge and not pkgmap[x]["selected"]:
3539 #avoid cluttering the preview printout with stuff that isn't getting unmerged
3541 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
3542 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
3543 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
3544 if "--pretend" not in myopts and "--ask" not in myopts:
3545 countdown(int(settings["EMERGE_WARNING_DELAY"]),
3546 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3547 print "\n "+white(x)
3548 for mytype in ["selected","protected","omitted"]:
3549 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
3550 if pkgmap[x][mytype]:
3551 for mypkg in pkgmap[x][mytype]:
3552 mysplit=portage.catpkgsplit(mypkg)
3553 if mysplit[3]=="r0":
3554 myversion=mysplit[2]
3556 myversion=mysplit[2]+"-"+mysplit[3]
3557 if mytype=="selected":
3558 portage.writemsg_stdout(
3559 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
3561 portage.writemsg_stdout(
3562 colorize("GOOD", myversion + " "), noiselevel=-1)
3564 portage.writemsg_stdout("none", noiselevel=-1)
3565 portage.writemsg_stdout("\n", noiselevel=-1)
3567 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3568 " packages are slated for removal.\n")
3569 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
3570 " and " + colorize("GOOD", "'omitted'") + \
3571 " packages will not be removed.\n\n")
3573 if "--pretend" in myopts:
3574 #we're done... return
3576 if "--ask" in myopts:
3577 if userquery("Would you like to unmerge these packages?")=="No":
3578 # enter pretend mode for correct formatting of results
3579 myopts["--pretend"] = True
3584 #the real unmerging begins, after a short delay....
3586 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3588 for x in pkgmap.keys():
3589 for y in pkgmap[x]["selected"]:
3590 print ">>> Unmerging "+y+"..."
3591 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3592 mysplit=y.split("/")
3594 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3595 mysettings, unmerge_action not in ["clean","prune"],
3596 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3597 if retval != os.EX_OK:
3598 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3599 ebuild = vartree.dbapi.findname(y)
3600 show_unmerge_failure_message(y, ebuild, retval)
3603 clean_world(vartree.dbapi, y)
3604 emergelog(xterm_titles, " >>> unmerge success: "+y)
3607 def show_unmerge_failure_message(pkg, ebuild, retval):
3609 from formatter import AbstractFormatter, DumbWriter
3610 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3613 msg.append("A removal phase of the '%s' package " % pkg)
3614 msg.append("has failed with exit value %s. " % retval)
3615 msg.append("The problem occurred while executing ")
3616 msg.append("the ebuild located at '%s'. " % ebuild)
3617 msg.append("If necessary, manually remove the ebuild " )
3618 msg.append("in order to skip the execution of removal phases.")
3622 f.add_flowing_data(x)
3626 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3628 if os.path.exists("/usr/bin/install-info"):
3633 inforoot=normpath(root+z)
3634 if os.path.isdir(inforoot):
3635 infomtime = long(os.stat(inforoot).st_mtime)
3636 if inforoot not in prev_mtimes or \
3637 prev_mtimes[inforoot] != infomtime:
3638 regen_infodirs.append(inforoot)
3640 if not regen_infodirs:
3641 portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
3643 portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
3647 for inforoot in regen_infodirs:
3650 for filename in ("dir", "dir.gz", "dir.bz2"):
3651 file_path = os.path.join(inforoot, filename)
3653 os.rename(file_path, file_path + ".old")
3655 if e.errno != errno.ENOENT:
3659 if not os.path.isdir(inforoot):
3662 file_list = os.listdir(inforoot)
3665 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3667 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3668 existsstr="already exists, for file `"
3670 if re.search(existsstr,myso):
3671 # Already exists... Don't increment the count for this.
3673 elif myso[:44]=="install-info: warning: no info dir entry in ":
3674 # This info file doesn't contain a DIR-header: install-info produces this
3675 # (harmless) warning (the --quiet switch doesn't seem to work).
3676 # Don't increment the count for this.
3680 errmsg += myso + "\n"
3683 #update mtime so we can potentially avoid regenerating.
3684 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3687 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3690 print " "+green("*")+" Processed",icount,"info files."
3693 def post_emerge(settings, mtimedb, retval):
3695 Misc. things to run at the end of a merge session.
3703 @param settings: Configuration settings (typically portage.settings)
3704 @type settings: portage.config()
3705 @param mtimedb: The mtimeDB to store data needed across merge invocations
3706 @type mtimedb: MtimeDB class instance
3707 @param retval: Emerge's return value
3711 1. Calls sys.exit(retval)
3713 target_root = settings["ROOT"]
3714 info_mtimes = mtimedb["info"]
3716 # Load the most current variables from ${ROOT}/etc/profile.env
3718 settings.regenerate()
3721 config_protect = settings.get("CONFIG_PROTECT","").split()
3722 infodirs = settings.get("INFOPATH","").split(":") + \
3723 settings.get("INFODIR","").split(":")
3727 emergelog("notitles" not in settings.features,
3728 " *** exiting successfully.")
3730 if "noinfo" not in settings.features:
3731 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3733 chk_updated_cfg_files(target_root, config_protect)
3735 NEWS_PATH = os.path.join( "metadata", "news" )
3736 UNREAD_PATH = os.path.join( target_root, NEWS_LIB_PATH, 'news')
3737 porttree = portdbapi( porttree_root = settings["PORTDIR"], mysettings = settings )
3738 newsReaderDisplay = False
3740 for repo in porttree.getRepositories():
3741 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3743 print colorize("WARN", " * IMPORTANT:"),
3744 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3745 newsReaderDisplay = True
3747 if newsReaderDisplay:
3748 print colorize("WARN", " *"),
3749 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3755 def chk_updated_cfg_files(target_root, config_protect):
3757 #number of directories with some protect files in them
3759 for x in config_protect:
3760 x = os.path.join(target_root, x.lstrip(os.path.sep))
3762 mymode = os.lstat(x).st_mode
3765 if stat.S_ISDIR(mymode):
3766 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3768 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3769 os.path.split(x.rstrip(os.path.sep))
3770 a = commands.getstatusoutput(mycommand + \
3771 " ! -iname '.*~' ! -iname '.*.bak'")
3773 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3775 files = a[1].split()
3778 print colorize("WARN", " * IMPORTANT:"),
3779 if stat.S_ISDIR(mymode):
3780 print "%d config files in '%s' need updating." % \
3783 print "config file '%s' needs updating." % x
3786 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3787 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3789 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3791 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3792 Returns the number of unread (yet relevent) items.
3804 1. The number of unread but relevant news items.
3807 from portage.news import NewsManager
3808 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3809 return manager.getUnreadItems( repo_id, update=True )
3811 def is_valid_package_atom(x):
3813 testkey = portage.dep_getkey(x)
3814 except portage.exception.InvalidData:
3816 if testkey.startswith("null/"):
3817 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3822 return portage.isvalidatom(testatom)
3824 def validate_merge_list(trees, mergelist):
3825 """Validate the list to make sure all the packages are still available.
3826 This is needed for --resume."""
3827 for (pkg_type, myroot, pkg_key, action) in mergelist:
3828 if pkg_type == "binary" and \
3829 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3830 pkg_type == "ebuild" and \
3831 not trees[myroot]["porttree"].dbapi.xmatch(
3832 "match-all", "="+pkg_key):
3833 print red("!!! Error: The resume list contains packages that are no longer")
3834 print red("!!! available to be emerged. Please restart/continue")
3835 print red("!!! the merge operation manually.")
3838 def show_blocker_docs_link():
3840 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3841 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3843 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3846 def action_sync(settings, trees, mtimedb, myopts, myaction):
3847 xterm_titles = "notitles" not in settings.features
3848 emergelog(xterm_titles, " === sync")
3849 myportdir = settings.get("PORTDIR", None)
3851 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3853 if myportdir[-1]=="/":
3854 myportdir=myportdir[:-1]
3855 if not os.path.exists(myportdir):
3856 print ">>>",myportdir,"not found, creating it."
3857 os.makedirs(myportdir,0755)
3858 syncuri=settings["SYNC"].rstrip()
3860 updatecache_flg = False
3861 if myaction == "metadata":
3862 print "skipping sync"
3863 updatecache_flg = True
3864 tmpservertimestampfile = None
3865 elif syncuri[:8]=="rsync://":
3866 if not os.path.exists("/usr/bin/rsync"):
3867 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3868 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3874 if settings["PORTAGE_RSYNC_OPTS"] == "":
3875 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3877 "--recursive", # Recurse directories
3878 "--links", # Consider symlinks
3879 "--safe-links", # Ignore links outside of tree
3880 "--perms", # Preserve permissions
3881 "--times", # Preserive mod times
3882 "--compress", # Compress the data transmitted
3883 "--force", # Force deletion on non-empty dirs
3884 "--whole-file", # Don't do block transfers, only entire files
3885 "--delete", # Delete files that aren't in the master tree
3886 "--delete-after", # Delete only after everything else is done
3887 "--stats", # Show final statistics about what was transfered
3888 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3889 "--exclude=/distfiles", # Exclude distfiles from consideration
3890 "--exclude=/local", # Exclude local from consideration
3891 "--exclude=/packages", # Exclude packages from consideration
3892 "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
3896 # The below validation is not needed when using the above hardcoded
3899 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3900 rsync_opts.extend(settings["PORTAGE_RSYNC_OPTS"].split())
3902 for opt in ("--recursive", "--times"):
3903 if opt not in rsync_opts:
3904 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3905 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3906 rsync_opts.append(opt)
3908 for exclude in ("distfiles", "local", "packages"):
3909 opt = "--exclude=/%s" % exclude
3910 if opt not in rsync_opts:
3911 portage.writemsg(yellow("WARNING:") + \
3912 " adding required option %s not included in " % opt + \
3913 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3914 rsync_opts.append(opt)
3916 if settings["RSYNC_TIMEOUT"] != "":
3917 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3918 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3920 mytimeout = int(settings["RSYNC_TIMEOUT"])
3921 rsync_opts.append("--timeout=%d" % mytimeout)
3922 except ValueError, e:
3923 portage.writemsg("!!! %s\n" % str(e))
3925 # TODO: determine options required for official servers
3926 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
3928 def rsync_opt_startswith(opt_prefix):
3929 for x in rsync_opts:
3930 if x.startswith(opt_prefix):
3934 if not rsync_opt_startswith("--timeout="):
3935 rsync_opts.append("--timeout=%d" % mytimeout)
3937 for opt in ("--compress", "--whole-file"):
3938 if opt not in rsync_opts:
3939 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3940 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3941 rsync_opts.append(opt)
3943 if "--quiet" in myopts:
3944 rsync_opts.append("--quiet") # Shut up a lot
3946 rsync_opts.append("--verbose") # Print filelist
3948 if "--verbose" in myopts:
3949 rsync_opts.append("--progress") # Progress meter for each file
3951 if "--debug" in myopts:
3952 rsync_opts.append("--checksum") # Force checksum on all files
3954 if settings["RSYNC_EXCLUDEFROM"] != "":
3955 portage.writemsg(yellow("WARNING:") + \
3956 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
3957 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3958 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
3959 rsync_opts.append("--exclude-from=%s" % \
3960 settings["RSYNC_EXCLUDEFROM"])
3962 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
3963 " but file does not exist.\n")
3965 if settings["RSYNC_RATELIMIT"] != "":
3966 portage.writemsg(yellow("WARNING:") + \
3967 " usage of RSYNC_RATELIMIT is deprecated, use " + \
3968 "PORTAGE_RSYNC_EXTRA_OPTS instead")
3969 rsync_opts.append("--bwlimit=%s" % \
3970 settings["RSYNC_RATELIMIT"])
3972 # Real local timestamp file.
3973 servertimestampfile = os.path.join(
3974 myportdir, "metadata", "timestamp.chk")
3975 # Temporary file for remote server timestamp comparison.
3976 tmpservertimestampfile = os.path.join(
3977 settings["PORTAGE_TMPDIR"], "timestamp.chk")
3979 content = portage.util.grabfile(servertimestampfile)
3983 mytimestamp = time.mktime(time.strptime(content[0],
3984 "%a, %d %b %Y %H:%M:%S +0000"))
3985 except (OverflowError, ValueError):
3990 if settings.has_key("RSYNC_RETRIES"):
3991 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
3992 maxretries=int(settings["RSYNC_RETRIES"])
3994 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
3995 except SystemExit, e:
3996 raise # Needed else can't exit
3998 maxretries=3 #default number of retries
4001 user_name, hostname, port = re.split(
4002 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
4005 if user_name is None:
4007 updatecache_flg=True
4008 all_rsync_opts = set(rsync_opts)
4009 all_rsync_opts.update(
4010 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
4011 family = socket.AF_INET
4012 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
4013 family = socket.AF_INET
4014 elif socket.has_ipv6 and \
4015 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
4016 family = socket.AF_INET6
4023 for addrinfo in socket.getaddrinfo(
4024 hostname, None, family, socket.SOCK_STREAM):
4025 if addrinfo[0] == socket.AF_INET6:
4026 # IPv6 addresses need to be enclosed in square brackets
4027 ips.append("[%s]" % addrinfo[4][0])
4029 ips.append(addrinfo[4][0])
4030 from random import shuffle
4032 except SystemExit, e:
4033 raise # Needed else can't exit
4034 except Exception, e:
4035 print "Notice:",str(e)
4040 dosyncuri = syncuri.replace(
4041 "//" + user_name + hostname + port + "/",
4042 "//" + user_name + ips[0] + port + "/", 1)
4043 except SystemExit, e:
4044 raise # Needed else can't exit
4045 except Exception, e:
4046 print "Notice:",str(e)
4050 if "--ask" in myopts:
4051 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
4056 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
4057 if "--quiet" not in myopts:
4058 print ">>> Starting rsync with "+dosyncuri+"..."
4060 emergelog(xterm_titles,
4061 ">>> Starting retry %d of %d with %s" % \
4062 (retries,maxretries,dosyncuri))
4063 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
4065 if mytimestamp != 0 and "--quiet" not in myopts:
4066 print ">>> Checking server timestamp ..."
4068 rsynccommand = " ".join(["/usr/bin/rsync", " ".join(rsync_opts),
4069 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
4071 if "--debug" in myopts:
4076 # Even if there's no timestamp available locally, fetch the
4077 # timestamp anyway as an initial probe to verify that the server is
4078 # responsive. This protects us from hanging indefinitely on a
4079 # connection attempt to an unresponsive server which rsync's
4080 # --timeout option does not prevent.
4082 mycommand = rsynccommand.split()
4083 mycommand.append(dosyncuri.rstrip("/") + \
4084 "/metadata/timestamp.chk")
4085 mycommand.append(tmpservertimestampfile)
4089 def timeout_handler(signum, frame):
4090 raise portage.exception.PortageException("timed out")
4091 signal.signal(signal.SIGALRM, timeout_handler)
4092 # Timeout here in case the server is unresponsive. The
4093 # --timeout rsync option doesn't apply to the initial
4094 # connection attempt.
4097 mypids.extend(portage.process.spawn(
4098 mycommand, env=settings.environ(), returnpid=True))
4099 exitcode = os.waitpid(mypids[0], 0)[1]
4100 content = portage.grabfile(tmpservertimestampfile)
4104 os.unlink(tmpservertimestampfile)
4107 except portage.exception.PortageException, e:
4111 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
4112 os.kill(mypids[0], signal.SIGTERM)
4113 os.waitpid(mypids[0], 0)
4114 # This is the same code rsync uses for timeout.
4117 if exitcode != os.EX_OK:
4119 exitcode = (exitcode & 0xff) << 8
4121 exitcode = exitcode >> 8
4123 portage.process.spawned_pids.remove(mypids[0])
4126 servertimestamp = time.mktime(time.strptime(
4127 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
4128 except (OverflowError, ValueError):
4130 del mycommand, mypids, content
4131 if exitcode == os.EX_OK:
4132 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4133 emergelog(xterm_titles,
4134 ">>> Cancelling sync -- Already current.")
4137 print ">>> Timestamps on the server and in the local repository are the same."
4138 print ">>> Cancelling all further sync action. You are already up to date."
4140 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4144 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4145 emergelog(xterm_titles,
4146 ">>> Server out of date: %s" % dosyncuri)
4149 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4151 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4154 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4156 mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
4157 mycommand = mycommand.split()
4158 exitcode = portage.process.spawn(mycommand,
4159 env=settings.environ())
4160 if exitcode in [0,1,3,4,11,14,20,21]:
4162 elif exitcode in [1,3,4,11,14,20,21]:
4165 # Code 2 indicates protocol incompatibility, which is expected
4166 # for servers with protocol < 29 that don't support
4167 # --prune-empty-directories. Retry for a server that supports
4168 # at least rsync protocol version 29 (>=rsync-2.6.4).
4173 if retries<=maxretries:
4174 print ">>> Retrying..."
4179 updatecache_flg=False
4183 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4187 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4188 print darkred("!!!")+green(" that your SYNC statement is proper.")
4189 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4191 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4192 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4193 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4194 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4195 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4197 print darkred("!!!")+green(" Rsync was killed before it finished.")
4199 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4200 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4201 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4202 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4203 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4206 elif syncuri[:6]=="cvs://":
4207 if not os.path.exists("/usr/bin/cvs"):
4208 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4209 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4212 cvsdir=os.path.dirname(myportdir)
4213 if not os.path.exists(myportdir+"/CVS"):
4215 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4216 if os.path.exists(cvsdir+"/gentoo-x86"):
4217 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4222 if e.errno != errno.ENOENT:
4224 "!!! existing '%s' directory; exiting.\n" % myportdir)
4227 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4228 print "!!! cvs checkout error; exiting."
4230 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4233 print ">>> Starting cvs update with "+syncuri+"..."
4234 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4235 myportdir, settings, free=1)
4236 if retval != os.EX_OK:
4240 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4243 if updatecache_flg and \
4244 myaction != "metadata" and \
4245 "metadata-transfer" not in settings.features:
4246 updatecache_flg = False
4248 # Reload the whole config from scratch.
4249 settings, trees, mtimedb = load_emerge_config(trees=trees)
4250 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4252 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4253 action_metadata(settings, portdb, myopts)
4255 if portage.global_updates(settings, trees, mtimedb["updates"]):
4257 # Reload the whole config from scratch.
4258 settings, trees, mtimedb = load_emerge_config(trees=trees)
4259 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4261 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4262 mypvs = portage.best(
4263 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4265 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4267 if myaction != "metadata":
4268 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4269 retval = portage.process.spawn(
4270 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4271 dosyncuri], env=settings.environ())
4272 if retval != os.EX_OK:
4273 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4275 if(mybestpv != mypvs) and not "--quiet" in myopts:
4277 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4278 print red(" * ")+"that you update portage now, before any other packages are updated."
4279 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4280 print red(" * ")+"configuration files."
4281 print red(" * ")+"To update portage, run 'emerge portage'."
4284 def action_metadata(settings, portdb, myopts):
4285 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4286 old_umask = os.umask(0002)
4287 cachedir = os.path.normpath(settings.depcachedir)
4288 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4289 "/lib", "/opt", "/proc", "/root", "/sbin",
4290 "/sys", "/tmp", "/usr", "/var"]:
4291 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4292 "ROOT DIRECTORY ON YOUR SYSTEM."
4293 print >> sys.stderr, \
4294 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4296 if not os.path.exists(cachedir):
4299 ec = portage.eclass_cache.cache(portdb.porttree_root)
4300 myportdir = os.path.realpath(settings["PORTDIR"])
4301 cm = settings.load_best_module("portdbapi.metadbmodule")(
4302 myportdir, "metadata/cache", portage.auxdbkeys[:])
4304 from portage.cache import util
4306 class percentage_noise_maker(util.quiet_mirroring):
4307 def __init__(self, dbapi):
4309 self.cp_all = dbapi.cp_all()
4310 l = len(self.cp_all)
4311 self.call_update_min = 100000000
4312 self.min_cp_all = l/100.0
4317 for x in self.cp_all:
4319 if self.count > self.min_cp_all:
4320 self.call_update_min = 0
4322 for y in self.dbapi.cp_list(x):
4324 self.call_update_mine = 0
4326 def update(self, *arg):
4327 try: self.pstr = int(self.pstr) + 1
4328 except ValueError: self.pstr = 1
4329 sys.stdout.write("%s%i%%" % \
4330 ("\b" * (len(str(self.pstr))+1), self.pstr))
4332 self.call_update_min = 10000000
4334 def finish(self, *arg):
4335 sys.stdout.write("\b\b\b\b100%\n")
4338 if "--quiet" in myopts:
4339 def quicky_cpv_generator(cp_all_list):
4340 for x in cp_all_list:
4341 for y in portdb.cp_list(x):
4343 source = quicky_cpv_generator(portdb.cp_all())
4344 noise_maker = portage.cache.util.quiet_mirroring()
4346 noise_maker = source = percentage_noise_maker(portdb)
4347 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4348 eclass_cache=ec, verbose_instance=noise_maker)
4353 def action_regen(settings, portdb):
4354 xterm_titles = "notitles" not in settings.features
4355 emergelog(xterm_titles, " === regen")
4356 #regenerate cache entries
4357 print "Regenerating cache entries... "
4359 os.close(sys.stdin.fileno())
4360 except SystemExit, e:
4361 raise # Needed else can't exit
4365 mynodes = portdb.cp_all()
4366 from portage.cache.cache_errors import CacheError
4368 for mytree in portdb.porttrees:
4370 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4371 except CacheError, e:
4372 print "\n error listing cache entries for " + \
4373 "'%s': %s, continuing..." % (mytree, e)
4378 mymatches = portdb.cp_list(x)
4379 portage.writemsg_stdout("processing %s\n" % x)
4382 foo = portdb.aux_get(y,["DEPEND"])
4383 except SystemExit, e:
4384 # sys.exit is an exception... And consequently, we can't catch it.
4386 except Exception, e:
4387 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4389 for mytree in portdb.porttrees:
4390 if portdb.findname2(y, mytree=mytree)[0]:
4391 dead_nodes[mytree].discard(y)
4393 for mytree, nodes in dead_nodes.iteritems():
4394 auxdb = portdb.auxdb[mytree]
4398 except (KeyError, CacheError):
4402 def action_config(settings, trees, myopts, myfiles):
4403 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4404 print red("!!! config can only take a single package atom at this time\n")
4406 if not is_valid_package_atom(myfiles[0]):
4407 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4409 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4410 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4414 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4415 except ValueError, e:
4416 # Multiple matches thrown from cpv_expand
4419 print "No packages found.\n"
4422 if "--ask" in myopts:
4424 print "Please select a package to configure:"
4428 options.append(str(idx))
4429 print options[-1]+") "+pkg
4432 idx = userquery("Selection?", options)
4435 pkg = pkgs[int(idx)-1]
4437 print "The following packages available:"
4440 print "\nPlease use a specific atom or the --ask option."
4446 if "--ask" in myopts:
4447 if userquery("Ready to configure "+pkg+"?") == "No":
4450 print "Configuring pkg..."
4452 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4453 mysettings = portage.config(clone=settings)
4454 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4455 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4456 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4459 def action_info(settings, trees, myopts, myfiles):
4460 unameout=commands.getstatusoutput("uname -mrp")[1]
4461 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4462 settings.profile_path, settings["CHOST"],
4463 trees[settings["ROOT"]]["vartree"].dbapi)
4465 header_title = "System Settings"
4467 print header_width * "="
4468 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4469 print header_width * "="
4470 print "System uname: "+unameout
4471 gentoo_release = portage.grabfile(os.path.join(
4472 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4474 print gentoo_release[0]
4476 print "Unknown Host Operating System"
4477 lastSync = portage.grabfile(os.path.join(
4478 settings["PORTDIR"], "metadata", "timestamp.chk"))
4479 print "Timestamp of tree:",
4485 output=commands.getstatusoutput("distcc --version")
4487 print str(output[1].split("\n",1)[0]),
4488 if "distcc" in settings.features:
4493 output=commands.getstatusoutput("ccache -V")
4495 print str(output[1].split("\n",1)[0]),
4496 if "ccache" in settings.features:
4501 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4502 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4503 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4504 myvars = portage.util.unique_array(myvars)
4508 if portage.isvalidatom(x):
4509 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4510 pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
4511 pkg_matches.sort(portage.pkgcmp)
4513 for pn, ver, rev in pkg_matches:
4515 pkgs.append(ver + "-" + rev)
4519 pkgs = ", ".join(pkgs)
4520 print "%-20s %s" % (x+":", pkgs)
4522 print "%-20s %s" % (x+":", "[NOT VALID]")
4524 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4526 if "--verbose" in myopts:
4527 myvars=settings.keys()
4529 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4530 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4531 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4532 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4534 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4536 myvars = portage.util.unique_array(myvars)
4542 print '%s="%s"' % (x, settings[x])
4544 use = set(settings["USE"].split())
4545 use_expand = settings["USE_EXPAND"].split()
4547 for varname in use_expand:
4548 flag_prefix = varname.lower() + "_"
4550 if f.startswith(flag_prefix):
4554 print 'USE="%s"' % " ".join(use),
4555 for varname in use_expand:
4556 myval = settings.get(varname)
4558 print '%s="%s"' % (varname, myval),
4561 unset_vars.append(x)
4563 print "Unset: "+", ".join(unset_vars)
4566 if "--debug" in myopts:
4567 for x in dir(portage):
4568 module = getattr(portage, x)
4569 if "cvs_id_string" in dir(module):
4570 print "%s: %s" % (str(x), str(module.cvs_id_string))
4572 # See if we can find any packages installed matching the strings
4573 # passed on the command line
4575 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4576 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4578 mypkgs.extend(vardb.match(x))
4580 # If some packages were found...
4582 # Get our global settings (we only print stuff if it varies from
4583 # the current config)
4584 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4585 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4587 pkgsettings = portage.config(clone=settings)
4589 for myvar in mydesiredvars:
4590 global_vals[myvar] = set(settings.get(myvar, "").split())
4592 # Loop through each package
4593 # Only print settings if they differ from global settings
4594 header_printed = False
4596 # Get all package specific variables
4597 auxvalues = vardb.aux_get(pkg, auxkeys)
4599 for i in xrange(len(auxkeys)):
4600 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4602 for myvar in mydesiredvars:
4603 # If the package variable doesn't match the
4604 # current global variable, something has changed
4605 # so set diff_found so we know to print
4606 if valuesmap[myvar] != global_vals[myvar]:
4607 diff_values[myvar] = valuesmap[myvar]
4608 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4609 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4611 # If a matching ebuild is no longer available in the tree, maybe it
4612 # would make sense to compare against the flags for the best
4613 # available version with the same slot?
4615 if portdb.cpv_exists(pkg):
4617 pkgsettings.setcpv(pkg, mydb=mydb)
4618 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4620 diff_values["USE"] = valuesmap["USE"]
4621 # If a difference was found, print the info for
4625 # If we have not yet printed the header,
4627 if not header_printed:
4628 header_title = "Package Settings"
4629 print header_width * "="
4630 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4631 print header_width * "="
4632 header_printed = True
4634 # Print package info
4635 print "%s was built with the following:" % pkg
4636 for myvar in mydesiredvars + ["USE"]:
4637 if myvar in diff_values:
4638 mylist = list(diff_values[myvar])
4640 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4643 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4645 print "emerge: no search terms provided."
4647 searchinstance = search(settings, portdb,
4648 vartree, spinner, "--searchdesc" in myopts,
4649 "--quiet" not in myopts)
4650 for mysearch in myfiles:
4652 searchinstance.execute(mysearch)
4653 except re.error, comment:
4654 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4656 searchinstance.output()
4658 def action_depclean(settings, trees, ldpath_mtimes,
4660 # Kill packages that aren't explicitly merged or are required as a
4661 # dependency of another package. World file is explicit.
4663 warn_prefix = colorize("BAD", "*** WARNING *** ")
4665 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4666 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4667 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4669 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4670 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4671 print warn_prefix + "be kept. They can be manually added to this set with"
4672 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4673 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4674 print warn_prefix + "depclean, even if they are part of the world set."
4676 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4677 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4678 print warn_prefix + "consequence, it is often necessary to run "
4679 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4681 xterm_titles = "notitles" not in settings.features
4682 myroot = settings["ROOT"]
4683 dep_check_trees = {}
4684 dep_check_trees[myroot] = {}
4685 dep_check_trees[myroot]["vartree"] = \
4686 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4687 vardb = dep_check_trees[myroot]["vartree"].dbapi
4688 # Constrain dependency selection to the installed packages.
4689 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4690 syslist = getlist(settings, "system")
4691 worldlist = getlist(settings, "world")
4692 system_world_dict = genericdict(worldlist)
4693 system_world_dict.update(genericdict(syslist))
4694 fakedb = portage.fakedbapi(settings=settings)
4695 myvarlist = vardb.cpv_all()
4698 print "\n!!! You have no system list.",
4700 print "\n!!! You have no world file.",
4702 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4704 if not (syslist and worldlist and myvarlist):
4705 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4706 print " break your installation.\n"
4707 if "--pretend" not in myopts:
4708 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4710 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4711 emergelog(xterm_titles, " >>> depclean")
4713 if "--quiet" not in myopts:
4714 print "\nCalculating dependencies ",
4718 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4719 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4721 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4723 while remaining_atoms:
4724 atom, parent, priority = remaining_atoms.pop()
4725 pkgs = vardb.match(atom)
4727 if not atom.startswith("!") and priority == hard:
4728 unresolveable.setdefault(atom, []).append(parent)
4730 if portage.dep_getkey(atom) not in system_world_dict:
4731 # Prune all but the best matching slot, since that's all that a
4732 # deep world update would pull in. Don't prune if the cpv is in
4733 # system or world though, since those sets trigger greedy update
4735 pkgs = [portage.best(pkgs)]
4737 if fakedb.cpv_exists(pkg):
4740 fakedb.cpv_inject(pkg)
4741 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4743 if myopts.get("--with-bdeps", "y") == "y":
4744 mydeps.append((myaux["DEPEND"], soft))
4746 mydeps.append((" ".join(myaux.values()), hard))
4747 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4748 for depstr, priority in mydeps:
4753 if "--debug" in myopts:
4755 print "Parent: ", pkg
4756 print "Depstring:", depstr
4758 if priority == soft:
4764 portage.dep._dep_check_strict = False
4765 success, atoms = portage.dep_check(depstr, None, settings,
4766 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4768 portage.dep._dep_check_strict = True
4770 show_invalid_depstring_notice(
4771 ("installed", myroot, pkg, "nomerge"),
4775 if "--debug" in myopts:
4776 print "Candidates:", atoms
4779 remaining_atoms.append((atom, pkg, priority))
4781 if "--quiet" not in myopts:
4782 print "\b\b... done!\n"
4785 print "Dependencies could not be completely resolved due to"
4786 print "the following required packages not being installed:"
4788 for atom in unresolveable:
4789 print atom, "required by", " ".join(unresolveable[atom])
4791 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4792 print "depclean? It may be necessary to manually uninstall packages that no longer"
4793 print "exist in the portage tree since it may not be possible to satisfy their"
4794 print "dependencies. Also, be aware of the --with-bdeps option that is documented"
4795 print "in " + good("`man emerge`") + "."
4799 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4802 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4803 "unmerge", cleanlist, ldpath_mtimes)
4805 print "Packages installed: "+str(len(myvarlist))
4806 print "Packages in world: "+str(len(worldlist))
4807 print "Packages in system: "+str(len(syslist))
4808 print "Unique package names: "+str(len(myvarlist))
4809 print "Required packages: "+str(len(fakedb.cpv_all()))
4810 if "--pretend" in myopts:
4811 print "Number to remove: "+str(len(cleanlist))
4813 print "Number removed: "+str(len(cleanlist))
4815 def action_build(settings, trees, mtimedb,
4816 myopts, myaction, myfiles, spinner):
4817 ldpath_mtimes = mtimedb["ldpath"]
4819 if "--quiet" not in myopts and \
4820 ("--pretend" in myopts or "--ask" in myopts or \
4821 "--tree" in myopts or "--verbose" in myopts):
4823 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4827 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4829 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4833 print darkgreen("These are the packages that would be %s, in order:") % action
4836 # validate the state of the resume data
4837 # so that we can make assumptions later.
4838 for k in ("resume", "resume_backup"):
4840 if "mergelist" in mtimedb[k]:
4841 if not mtimedb[k]["mergelist"]:
4846 if "--resume" in myopts and \
4847 ("resume" in mtimedb or
4848 "resume_backup" in mtimedb):
4849 if "resume" not in mtimedb:
4850 mtimedb["resume"] = mtimedb["resume_backup"]
4851 del mtimedb["resume_backup"]
4853 # XXX: "myopts" is a list for backward compatibility.
4854 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4856 for opt in ("--skipfirst", "--ask", "--tree"):
4857 myresumeopts.pop(opt, None)
4859 for myopt, myarg in myopts.iteritems():
4860 if myopt not in myresumeopts:
4861 myresumeopts[myopt] = myarg
4863 myparams = create_depgraph_params(myopts, myaction)
4864 if "--quiet" not in myopts and "--nodeps" not in myopts:
4865 print "Calculating dependencies ",
4866 mydepgraph = depgraph(settings, trees,
4867 myopts, myparams, spinner)
4868 if "--quiet" not in myopts and "--nodeps" not in myopts:
4869 print "\b\b... done!"
4871 if ("--resume" in myopts):
4872 print darkgreen("emerge: It seems we have nothing to resume...")
4875 myparams = create_depgraph_params(myopts, myaction)
4876 if myaction in ["system","world"]:
4877 if "--quiet" not in myopts and "--nodeps" not in myopts:
4878 print "Calculating",myaction,"dependencies ",
4880 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4881 if not mydepgraph.xcreate(myaction):
4882 print "!!! Depgraph creation failed."
4884 if "--quiet" not in myopts and "--nodeps" not in myopts:
4885 print "\b\b... done!"
4887 if "--quiet" not in myopts and "--nodeps" not in myopts:
4888 print "Calculating dependencies ",
4890 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4892 retval, favorites = mydepgraph.select_files(myfiles)
4893 except portage.exception.PackageNotFound, e:
4894 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4898 if "--quiet" not in myopts and "--nodeps" not in myopts:
4899 print "\b\b... done!"
4901 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4902 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4904 if mydepgraph.missingbins:
4905 for x in mydepgraph.missingbins:
4906 sys.stderr.write(" "+str(x)+"\n")
4907 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4910 if "--pretend" not in myopts and \
4911 ("--ask" in myopts or "--tree" in myopts or \
4912 "--verbose" in myopts) and \
4913 not ("--quiet" in myopts and "--ask" not in myopts):
4914 if "--resume" in myopts:
4915 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4916 mymergelist = mtimedb["resume"]["mergelist"]
4917 if "--skipfirst" in myopts:
4918 mymergelist = mymergelist[1:]
4919 if len(mymergelist) == 0:
4920 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4922 mydepgraph.display(mymergelist)
4923 prompt="Would you like to resume merging these packages?"
4926 mydepgraph.altlist(reversed=("--tree" in myopts)))
4928 for x in mydepgraph.altlist():
4929 if x[0] != "blocks" and x[3] != "nomerge":
4931 #check for blocking dependencies
4932 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
4933 print "\n!!! Error: The above package list contains packages which cannot be installed"
4934 print "!!! at the same time on the same system."
4935 if "--quiet" not in myopts:
4936 show_blocker_docs_link()
4939 if "--noreplace" in myopts and favorites:
4942 print " %s %s" % (good("*"), x)
4943 prompt="Would you like to add these packages to your world favorites?"
4944 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4945 prompt="Nothing to merge; would you like to auto-clean packages?"
4948 print "Nothing to merge; quitting."
4951 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4952 prompt="Would you like to fetch the source files for these packages?"
4954 prompt="Would you like to merge these packages?"
4956 if "--ask" in myopts and userquery(prompt) == "No":
4961 # Don't ask again (e.g. when auto-cleaning packages after merge)
4962 myopts.pop("--ask", None)
4964 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4965 if ("--resume" in myopts):
4966 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4967 mymergelist = mtimedb["resume"]["mergelist"]
4968 if "--skipfirst" in myopts:
4969 mymergelist = mymergelist[1:]
4970 if len(mymergelist) == 0:
4971 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4973 mydepgraph.display(mymergelist)
4976 mydepgraph.altlist(reversed=("--tree" in myopts)))
4977 if ("--buildpkgonly" in myopts):
4978 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
4979 print "\n!!! --buildpkgonly requires all dependencies to be merged."
4980 print "!!! You have to merge the dependencies before you can build this package.\n"
4983 if ("--buildpkgonly" in myopts):
4984 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
4985 print "\n!!! --buildpkgonly requires all dependencies to be merged."
4986 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
4989 if ("--resume" in myopts):
4990 favorites=mtimedb["resume"]["favorites"]
4991 mergetask = MergeTask(settings, trees, myopts)
4992 if "--fetchonly" in myopts:
4993 """ parallel-fetch uses --resume --fetchonly and we don't want
4994 it to write the mtimedb"""
4995 mtimedb.filename = None
4996 time.sleep(3) # allow the parent to have first fetch
4998 retval = mergetask.merge(
4999 mtimedb["resume"]["mergelist"], favorites, mtimedb)
5000 if retval != os.EX_OK:
5003 if "resume" in mtimedb and \
5004 "mergelist" in mtimedb["resume"] and \
5005 len(mtimedb["resume"]["mergelist"]) > 1:
5006 mtimedb["resume_backup"] = mtimedb["resume"]
5007 del mtimedb["resume"]
5009 mtimedb["resume"]={}
5010 # XXX: Stored as a list for backward compatibility.
5011 mtimedb["resume"]["myopts"] = \
5012 [k for k in myopts if myopts[k] is True]
5013 mtimedb["resume"]["favorites"]=favorites
5014 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5015 for pkgline in mydepgraph.altlist():
5016 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5017 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
5018 tmpsettings = portage.config(clone=settings)
5020 if settings.get("PORTAGE_DEBUG", "") == "1":
5022 retval = portage.doebuild(
5023 y, "digest", settings["ROOT"], tmpsettings, edebug,
5024 ("--pretend" in myopts),
5025 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
5027 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5029 for pkg in mydepgraph.altlist():
5030 if pkg[0] != "blocks":
5033 pkglist = mydepgraph.altlist()
5035 mergetask = MergeTask(settings, trees, myopts)
5036 retval = mergetask.merge(pkglist, favorites, mtimedb)
5037 if retval != os.EX_OK:
5040 if mtimedb.has_key("resume"):
5041 del mtimedb["resume"]
5042 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5043 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5044 vartree = trees[settings["ROOT"]]["vartree"]
5045 unmerge(settings, myopts, vartree, "clean", ["world"],
5046 ldpath_mtimes, autoclean=1)
5048 portage.writemsg_stdout(colorize("WARN", "WARNING:")
5049 + " AUTOCLEAN is disabled. This can cause serious"
5050 + " problems due to overlapping packages.\n")
5052 def multiple_actions(action1, action2):
5053 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
5054 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
5057 def parse_opts(tmpcmdline, silent=False):
5062 global actions, options, shortmapping
5064 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
5065 argument_options = {
5067 "help":"specify the location for portage configuration files",
5071 "help":"enable or disable color output",
5073 "choices":("y", "n")
5076 "help":"include unnecessary build time dependencies",
5078 "choices":("y", "n")
5082 from optparse import OptionParser
5083 parser = OptionParser()
5084 if parser.has_option("--help"):
5085 parser.remove_option("--help")
5087 for action_opt in actions:
5088 parser.add_option("--" + action_opt, action="store_true",
5089 dest=action_opt.replace("-", "_"), default=False)
5090 for myopt in options:
5091 parser.add_option(myopt, action="store_true",
5092 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5093 for shortopt, longopt in shortmapping.iteritems():
5094 parser.add_option("-" + shortopt, action="store_true",
5095 dest=longopt.lstrip("--").replace("-", "_"), default=False)
5096 for myalias, myopt in longopt_aliases.iteritems():
5097 parser.add_option(myalias, action="store_true",
5098 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5100 for myopt, kwargs in argument_options.iteritems():
5101 parser.add_option(myopt,
5102 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
5104 myoptions, myargs = parser.parse_args(args=tmpcmdline)
5106 for myopt in options:
5107 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
5109 myopts[myopt] = True
5111 for myopt in argument_options:
5112 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
5116 for action_opt in actions:
5117 v = getattr(myoptions, action_opt.replace("-", "_"))
5120 multiple_actions(myaction, action_opt)
5122 myaction = action_opt
5125 if x in actions and myaction != "search":
5126 if not silent and x not in ["system", "world"]:
5127 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
5128 # special case "search" so people can search for action terms, e.g. emerge -s sync
5130 multiple_actions(myaction, x)
5136 if "--nocolor" in myopts:
5138 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
5139 "use '--color=n' instead.\n")
5140 del myopts["--nocolor"]
5141 myopts["--color"] = "n"
5143 return myaction, myopts, myfiles
5145 def validate_ebuild_environment(trees):
5146 for myroot in trees:
5147 mysettings = trees[myroot]["vartree"].settings
5148 for var in "ARCH", "USERLAND":
5149 if mysettings.get(var):
5151 print >> sys.stderr, bad(("\a!!! %s is not set... " % var) + \
5152 "Are you missing the '%setc/make.profile' symlink?" % \
5153 mysettings["PORTAGE_CONFIGROOT"])
5154 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5155 "Is your portage tree complete?\n")
5157 del myroot, mysettings
5159 def load_emerge_config(trees=None):
5161 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5162 kwargs[k] = os.environ.get(envvar, None)
5163 trees = portage.create_trees(trees=trees, **kwargs)
5165 settings = trees["/"]["vartree"].settings
5167 for myroot in trees:
5169 settings = trees[myroot]["vartree"].settings
5172 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5173 mtimedb = portage.MtimeDB(mtimedbfile)
5174 return settings, trees, mtimedb
5176 def adjust_config(myopts, settings):
5177 """Make emerge specific adjustments to the config."""
5179 # To enhance usability, make some vars case insensitive by forcing them to
5181 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5182 if myvar in settings:
5183 settings[myvar] = settings[myvar].lower()
5184 settings.backup_changes(myvar)
5187 # Kill noauto as it will break merges otherwise.
5188 if "noauto" in settings.features:
5189 while "noauto" in settings.features:
5190 settings.features.remove("noauto")
5191 settings["FEATURES"] = " ".join(settings.features)
5192 settings.backup_changes("FEATURES")
5196 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5197 except ValueError, e:
5198 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5199 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5200 settings["CLEAN_DELAY"], noiselevel=-1)
5201 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5202 settings.backup_changes("CLEAN_DELAY")
5204 EMERGE_WARNING_DELAY = 10
5206 EMERGE_WARNING_DELAY = int(settings.get(
5207 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5208 except ValueError, e:
5209 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5210 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5211 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5212 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5213 settings.backup_changes("EMERGE_WARNING_DELAY")
5215 if "--quiet" in myopts:
5216 settings["PORTAGE_QUIET"]="1"
5217 settings.backup_changes("PORTAGE_QUIET")
5219 # Set so that configs will be merged regardless of remembered status
5220 if ("--noconfmem" in myopts):
5221 settings["NOCONFMEM"]="1"
5222 settings.backup_changes("NOCONFMEM")
5224 # Set various debug markers... They should be merged somehow.
5227 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5228 if PORTAGE_DEBUG not in (0, 1):
5229 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5230 PORTAGE_DEBUG, noiselevel=-1)
5231 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5234 except ValueError, e:
5235 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5236 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5237 settings["PORTAGE_DEBUG"], noiselevel=-1)
5239 if "--debug" in myopts:
5241 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5242 settings.backup_changes("PORTAGE_DEBUG")
5244 if settings.get("NOCOLOR") not in ("yes","true"):
5245 portage.output.havecolor = 1
5247 """The explicit --color < y | n > option overrides the NOCOLOR environment
5248 variable and stdout auto-detection."""
5249 if "--color" in myopts:
5250 if "y" == myopts["--color"]:
5251 portage.output.havecolor = 1
5252 settings["NOCOLOR"] = "false"
5254 portage.output.havecolor = 0
5255 settings["NOCOLOR"] = "true"
5256 settings.backup_changes("NOCOLOR")
5257 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5258 portage.output.havecolor = 0
5259 settings["NOCOLOR"] = "true"
5260 settings.backup_changes("NOCOLOR")
5263 global portage # NFC why this is necessary now - genone
5264 # Disable color until we're sure that it should be enabled (after
5265 # EMERGE_DEFAULT_OPTS has been parsed).
5266 portage.output.havecolor = 0
5267 # This first pass is just for options that need to be known as early as
5268 # possible, such as --config-root. They will be parsed again later,
5269 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5270 # the value of --config-root).
5271 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5272 if "--debug" in myopts:
5273 os.environ["PORTAGE_DEBUG"] = "1"
5274 if "--config-root" in myopts:
5275 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5277 # Portage needs to ensure a sane umask for the files it creates.
5279 settings, trees, mtimedb = load_emerge_config()
5280 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5283 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5284 except (OSError, ValueError), e:
5285 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5286 settings["PORTAGE_NICENESS"])
5287 portage.writemsg("!!! %s\n" % str(e))
5290 if portage.global_updates(settings, trees, mtimedb["updates"]):
5292 # Reload the whole config from scratch.
5293 settings, trees, mtimedb = load_emerge_config(trees=trees)
5294 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5296 xterm_titles = "notitles" not in settings.features
5299 if "--ignore-default-opts" not in sys.argv:
5300 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5301 tmpcmdline.extend(sys.argv[1:])
5302 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5304 if "--digest" in myopts:
5305 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5306 # Reload the whole config from scratch so that the portdbapi internal
5307 # config is updated with new FEATURES.
5308 settings, trees, mtimedb = load_emerge_config(trees=trees)
5309 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5311 for myroot in trees:
5312 mysettings = trees[myroot]["vartree"].settings
5314 adjust_config(myopts, mysettings)
5316 del myroot, mysettings
5318 spinner = stdout_spinner()
5319 if "candy" in settings.features:
5320 spinner.update = spinner.update_scroll
5322 portage.deprecated_profile_check()
5324 #Freeze the portdbapi for enhanced performance:
5325 for myroot in trees:
5326 trees[myroot]["porttree"].dbapi.freeze()
5329 if "moo" in myfiles:
5332 Larry loves Gentoo (""" + os.uname()[0] + """)
5334 _______________________
5335 < Have you mooed today? >
5336 -----------------------
5345 if (myaction in ["world", "system"]) and myfiles:
5346 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5350 ext = os.path.splitext(x)[1]
5351 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5352 print "emerging by path implies --oneshot... adding --oneshot to options."
5353 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5356 if ("--tree" in myopts) and ("--columns" in myopts):
5357 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5360 if ("--quiet" in myopts):
5361 spinner.update = spinner.update_quiet
5362 portage.util.noiselimit = -1
5364 # Always create packages if FEATURES=buildpkg
5365 # Imply --buildpkg if --buildpkgonly
5366 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5367 if "--buildpkg" not in myopts:
5368 myopts["--buildpkg"] = True
5370 # Also allow -S to invoke search action (-sS)
5371 if ("--searchdesc" in myopts):
5372 if myaction and myaction != "search":
5373 myfiles.append(myaction)
5374 if "--search" not in myopts:
5375 myopts["--search"] = True
5378 # Always try and fetch binary packages if FEATURES=getbinpkg
5379 if ("getbinpkg" in settings.features):
5380 myopts["--getbinpkg"] = True
5382 if "--skipfirst" in myopts and "--resume" not in myopts:
5383 myopts["--resume"] = True
5385 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5386 myopts["--usepkgonly"] = True
5388 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5389 myopts["--getbinpkg"] = True
5391 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5392 myopts["--usepkg"] = True
5394 # Also allow -K to apply --usepkg/-k
5395 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5396 myopts["--usepkg"] = True
5398 # Allow -p to remove --ask
5399 if ("--pretend" in myopts) and ("--ask" in myopts):
5400 print ">>> --pretend disables --ask... removing --ask from options."
5403 # forbid --ask when not in a terminal
5404 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5405 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5406 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5410 if settings.get("PORTAGE_DEBUG", "") == "1":
5411 spinner.update = spinner.update_quiet
5413 if "python-trace" in settings.features:
5414 import portage.debug
5415 portage.debug.set_trace(True)
5417 if ("--resume" in myopts):
5418 if "--tree" in myopts:
5419 print "* --tree is currently broken with --resume. Disabling..."
5420 del myopts["--tree"]
5422 if not ("--quiet" in myopts):
5423 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5424 spinner.update = spinner.update_basic
5426 if "--version" in myopts:
5427 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5428 settings.profile_path, settings["CHOST"],
5429 trees[settings["ROOT"]]["vartree"].dbapi)
5431 elif "--help" in myopts:
5432 emerge.help.help(myaction, myopts, portage.output.havecolor)
5435 if portage.wheelgid == portage.portage_gid:
5436 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5437 print " include the portage user as noted above, and then use group portage."
5439 if "--debug" in myopts:
5440 print "myaction", myaction
5441 print "myopts", myopts
5443 if not myaction and not myfiles and "--resume" not in myopts:
5444 emerge.help.help(myaction, myopts, portage.output.havecolor)
5447 # check if root user is the current user for the actions where emerge needs this
5448 if portage.secpass < 2:
5449 # We've already allowed "--version" and "--help" above.
5450 if "--pretend" not in myopts and \
5451 myaction not in ("search","info"):
5452 need_superuser = not \
5453 ("--fetchonly" in myopts or \
5454 "--fetch-all-uri" in myopts or \
5455 myaction in ("metadata", "regen"))
5456 if portage.secpass < 1 or \
5459 access_desc = "superuser"
5461 access_desc = "portage group"
5462 # Always show portage_group_warning() when only portage group
5463 # access is required but the user is not in the portage group.
5464 from portage.data import portage_group_warning
5465 if "--ask" in myopts:
5466 myopts["--pretend"] = True
5468 print ("%s access would be required... " + \
5469 "adding --pretend to options.\n") % access_desc
5470 if portage.secpass < 1 and not need_superuser:
5471 portage_group_warning()
5473 sys.stderr.write(("emerge: %s access would be " + \
5474 "required.\n\n") % access_desc)
5475 if portage.secpass < 1 and not need_superuser:
5476 portage_group_warning()
5479 disable_emergelog = False
5480 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5482 disable_emergelog = True
5484 if myaction in ("search", "info"):
5485 disable_emergelog = True
5486 if disable_emergelog:
5487 """ Disable emergelog for everything except build or unmerge
5488 operations. This helps minimize parallel emerge.log entries that can
5489 confuse log parsers. We especially want it disabled during
5490 parallel-fetch, which uses --resume --fetchonly."""
5492 def emergelog(*pargs, **kargs):
5495 if not "--pretend" in myopts:
5496 emergelog(xterm_titles, "Started emerge on: "+\
5497 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5500 myelogstr=" ".join(myopts)
5502 myelogstr+=" "+myaction
5504 myelogstr+=" "+" ".join(myfiles)
5505 emergelog(xterm_titles, " *** emerge " + myelogstr)
5507 def emergeexitsig(signum, frame):
5508 signal.signal(signal.SIGINT, signal.SIG_IGN)
5509 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5510 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5511 sys.exit(100+signum)
5512 signal.signal(signal.SIGINT, emergeexitsig)
5513 signal.signal(signal.SIGTERM, emergeexitsig)
5516 """This gets out final log message in before we quit."""
5517 if "--pretend" not in myopts:
5518 emergelog(xterm_titles, " *** terminating.")
5519 if "notitles" not in settings.features:
5521 portage.atexit_register(emergeexit)
5523 if myaction in ("config", "metadata", "regen", "sync"):
5524 if "--pretend" in myopts:
5525 sys.stderr.write(("emerge: The '%s' action does " + \
5526 "not support '--pretend'.\n") % myaction)
5528 if "sync" == myaction:
5529 action_sync(settings, trees, mtimedb, myopts, myaction)
5530 elif "metadata" == myaction:
5531 action_metadata(settings, portdb, myopts)
5532 elif myaction=="regen":
5533 validate_ebuild_environment(trees)
5534 action_regen(settings, portdb)
5536 elif "config"==myaction:
5537 validate_ebuild_environment(trees)
5538 action_config(settings, trees, myopts, myfiles)
5541 elif "info"==myaction:
5542 action_info(settings, trees, myopts, myfiles)
5545 elif "search"==myaction:
5546 validate_ebuild_environment(trees)
5547 action_search(settings, portdb, trees["/"]["vartree"],
5548 myopts, myfiles, spinner)
5549 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5550 validate_ebuild_environment(trees)
5551 vartree = trees[settings["ROOT"]]["vartree"]
5552 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5554 if "--pretend" not in myopts:
5555 post_emerge(settings, mtimedb, 0)
5557 elif "depclean"==myaction:
5558 validate_ebuild_environment(trees)
5559 action_depclean(settings, trees, mtimedb["ldpath"],
5561 if "--pretend" not in myopts:
5562 post_emerge(settings, mtimedb, 0)
5563 # "update", "system", or just process files:
5565 validate_ebuild_environment(trees)
5566 action_build(settings, trees, mtimedb,
5567 myopts, myaction, myfiles, spinner)
5568 if "--pretend" not in myopts:
5569 post_emerge(settings, mtimedb, 0)
5571 if __name__ == "__main__":
5572 retval = emerge_main()