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):
154 def sorted_versions(verlist):
157 verparts = ver.split("-")
158 if len(verparts) == 2:
159 verrev = int(verparts[1][1:])
164 retparts = ret[x].split("-")
165 verdiff = portage.vercmp(retparts[0], verparts[0])
169 if len(retparts) == 2:
170 retrev = int(retparts[1][1:])
181 "clean", "config", "depclean",
183 "prune", "regen", "search",
184 "sync", "system", "unmerge", "world",
187 "--ask", "--alphabetical",
188 "--buildpkg", "--buildpkgonly",
189 "--changelog", "--columns",
193 "--fetchonly", "--fetch-all-uri",
194 "--getbinpkg", "--getbinpkgonly",
195 "--help", "--ignore-default-opts",
197 "--newuse", "--nocolor",
198 "--nodeps", "--noreplace",
199 "--nospinner", "--oneshot",
200 "--onlydeps", "--pretend",
201 "--quiet", "--resume",
202 "--searchdesc", "--selective",
206 "--usepkg", "--usepkgonly",
207 "--verbose", "--version"
213 "b":"--buildpkg", "B":"--buildpkgonly",
214 "c":"--clean", "C":"--unmerge",
215 "d":"--debug", "D":"--deep",
217 "f":"--fetchonly", "F":"--fetch-all-uri",
218 "g":"--getbinpkg", "G":"--getbinpkgonly",
220 "k":"--usepkg", "K":"--usepkgonly",
222 "n":"--noreplace", "N":"--newuse",
223 "o":"--onlydeps", "O":"--nodeps",
224 "p":"--pretend", "P":"--prune",
226 "s":"--search", "S":"--searchdesc",
229 "v":"--verbose", "V":"--version"
232 def emergelog(xterm_titles, mystr, short_msg=None):
234 if short_msg == None:
236 if "HOSTNAME" in os.environ.keys():
237 short_msg = os.environ["HOSTNAME"]+": "+short_msg
238 xtermTitle(short_msg)
240 file_path = "/var/log/emerge.log"
241 mylogfile = open(file_path, "a")
242 portage.util.apply_secpass_permissions(file_path,
243 uid=portage.portage_uid, gid=portage.portage_gid,
247 mylock = portage.locks.lockfile(mylogfile)
248 # seek because we may have gotten held up by the lock.
249 # if so, we may not be positioned at the end of the file.
251 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
255 portage.locks.unlockfile(mylock)
257 except (IOError,OSError,portage.exception.PortageException), e:
259 print >> sys.stderr, "emergelog():",e
261 def countdown(secs=5, doing="Starting"):
263 print ">>> Waiting",secs,"seconds before starting..."
264 print ">>> (Control-C to abort)...\n"+doing+" in: ",
268 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
273 # formats a size given in bytes nicely
274 def format_size(mysize):
275 if type(mysize) not in [types.IntType,types.LongType]:
277 if 0 != mysize % 1024:
278 # Always round up to the next kB so that it doesn't show 0 kB when
279 # some small file still needs to be fetched.
280 mysize += 1024 - mysize % 1024
281 mystr=str(mysize/1024)
285 mystr=mystr[:mycount]+","+mystr[mycount:]
289 def getgccversion(chost):
292 return: the current in-use gcc version
295 gcc_ver_command = 'gcc -dumpversion'
296 gcc_ver_prefix = 'gcc-'
298 gcc_not_found_error = red(
299 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
300 "!!! to update the environment of this terminal and possibly\n" +
301 "!!! other terminals also.\n"
304 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
305 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
306 part1, part2 = myoutput.split("/")
307 if part1.startswith(chost + "-"):
308 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
310 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
311 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
312 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
314 mystatus, myoutput = commands.getstatusoutput(
315 chost + "-" + gcc_ver_command)
316 if mystatus == os.EX_OK:
317 return gcc_ver_prefix + myoutput
319 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
320 if mystatus == os.EX_OK:
321 return gcc_ver_prefix + myoutput
323 portage.writemsg(gcc_not_found_error, noiselevel=-1)
324 return "[unavailable]"
326 def getportageversion(portdir, target_root, profile, chost, vardb):
327 profilever = "unavailable"
329 realpath = os.path.realpath(profile)
330 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
331 if realpath.startswith(basepath):
332 profilever = realpath[1 + len(basepath):]
335 profilever = "!" + os.readlink(profile)
338 del realpath, basepath
341 libclist = vardb.match("virtual/libc")
342 libclist += vardb.match("virtual/glibc")
343 libclist = portage.util.unique_array(libclist)
345 xs=portage.catpkgsplit(x)
347 libcver+=","+"-".join(xs[1:])
349 libcver="-".join(xs[1:])
351 libcver="unavailable"
353 gccver = getgccversion(chost)
354 unameout=os.uname()[2]+" "+os.uname()[4]
356 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
358 def create_depgraph_params(myopts, myaction):
359 #configure emerge engine parameters
361 # self: include _this_ package regardless of if it is merged.
362 # selective: exclude the package if it is merged
363 # recurse: go into the dependencies
364 # deep: go into the dependencies of already merged packages
365 # empty: pretend nothing is merged
366 myparams = ["recurse"]
369 if "--update" in myopts or \
370 "--newuse" in myopts or \
371 "--noreplace" in myopts or \
372 myaction in ("system", "world"):
373 add.extend(["selective"])
374 if "--emptytree" in myopts:
375 add.extend(["empty"])
376 sub.extend(["selective"])
377 if "--nodeps" in myopts:
378 sub.extend(["recurse"])
379 if "--deep" in myopts:
382 if (x not in myparams) and (x not in sub):
389 # search functionality
401 def __init__(self, settings, portdb, vartree, spinner, searchdesc,
403 """Searches the available and installed packages for the supplied search key.
404 The list of available and installed packages is created at object instantiation.
405 This makes successive searches faster."""
406 self.settings = settings
408 self.vartree = vartree
409 self.spinner = spinner
410 self.verbose = verbose
411 self.searchdesc = searchdesc
413 def execute(self,searchkey):
414 """Performs the search for the supplied search key"""
416 self.searchkey=searchkey
417 self.packagematches = []
420 self.matches = {"pkg":[], "desc":[]}
423 self.matches = {"pkg":[]}
424 print "Searching... ",
427 if self.searchkey[0] == '%':
429 self.searchkey = self.searchkey[1:]
430 if self.searchkey[0] == '@':
432 self.searchkey = self.searchkey[1:]
434 self.searchre=re.compile(self.searchkey,re.I)
436 self.searchre=re.compile(re.escape(self.searchkey), re.I)
437 for package in self.portdb.cp_all():
438 self.spinner.update()
441 match_string = package[:]
443 match_string = package.split("/")[-1]
446 if self.searchre.search(match_string):
447 if not self.portdb.xmatch("match-visible", package):
449 self.matches["pkg"].append([package,masked])
450 elif self.searchdesc: # DESCRIPTION searching
451 full_package = self.portdb.xmatch("bestmatch-visible", package)
453 #no match found; we don't want to query description
454 full_package = portage.best(
455 self.portdb.xmatch("match-all", package))
461 full_desc = self.portdb.aux_get(
462 full_package, ["DESCRIPTION"])[0]
464 print "emerge: search: aux_get() failed, skipping"
466 if self.searchre.search(full_desc):
467 self.matches["desc"].append([full_package,masked])
469 for mtype in self.matches.keys():
470 self.matches[mtype].sort()
471 self.mlen += len(self.matches[mtype])
474 """Outputs the results of the search."""
475 print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
476 print "[ Applications found : "+white(str(self.mlen))+" ]"
478 for mtype in self.matches.keys():
479 for match,masked in self.matches[mtype]:
482 full_package = self.portdb.xmatch(
483 "bestmatch-visible", match)
485 #no match found; we don't want to query description
487 full_package = portage.best(
488 self.portdb.xmatch("match-all",match))
491 match = portage.pkgsplit(match)[0]
495 desc, homepage, license = self.portdb.aux_get(
496 full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
498 print "emerge: search: aux_get() failed, skipping"
501 print green("*")+" "+white(match)+" "+red("[ Masked ]")
503 print green("*")+" "+white(match)
504 myversion = self.getVersion(full_package, search.VERSION_RELEASE)
507 mycat = match.split("/")[0]
508 mypkg = match.split("/")[1]
509 mycpv = match + "-" + myversion
510 myebuild = self.portdb.findname(mycpv)
511 pkgdir = os.path.dirname(myebuild)
512 from portage import manifest
513 mf = manifest.Manifest(
514 pkgdir, self.settings["DISTDIR"])
515 fetchlist = self.portdb.getfetchlist(mycpv,
516 mysettings=self.settings, all=True)[1]
518 mysum[0] = mf.getDistfilesSize(fetchlist)
519 mystr = str(mysum[0]/1024)
523 mystr=mystr[:mycount]+","+mystr[mycount:]
526 mysum[0] = "Unknown (missing digest for %s)" % str(e)
529 print " ", darkgreen("Latest version available:"),myversion
530 print " ", self.getInstallationStatus(mycat+'/'+mypkg)
531 print " ", darkgreen("Size of files:"),mysum[0]
532 print " ", darkgreen("Homepage:")+" ",homepage
533 print " ", darkgreen("Description:")+" ",desc
534 print " ", darkgreen("License:")+" ",license
540 def getInstallationStatus(self,package):
541 installed_package = self.vartree.dep_bestmatch(package)
543 version = self.getVersion(installed_package,search.VERSION_RELEASE)
545 result = darkgreen("Latest version installed:")+" "+version
547 result = darkgreen("Latest version installed:")+" [ Not Installed ]"
550 def getVersion(self,full_package,detail):
551 if len(full_package) > 1:
552 package_parts = portage.catpkgsplit(full_package)
553 if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
554 result = package_parts[2]+ "-" + package_parts[3]
556 result = package_parts[2]
562 #build our package digraph
563 def getlist(settings, mode):
565 mylines = settings.packages
568 file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
569 myfile = open(file_path, "r")
570 mylines = myfile.readlines()
572 except (OSError, IOError), e:
573 if e.errno == errno.ENOENT:
574 portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
580 myline=" ".join(x.split())
589 mynewlines.append(myline.strip())
593 def clean_world(vardb, cpv):
594 """Remove a package from the world file when unmerged."""
595 world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
596 worldlist = portage.util.grabfile(world_filename)
597 mykey = portage.cpv_getkey(cpv)
600 if portage.dep_getkey(x) == mykey:
601 matches = vardb.match(x, use_cache=0)
605 elif len(matches) == 1 and matches[0] == cpv:
609 #others are around; keep it.
610 newworldlist.append(x)
612 #this doesn't match the package we're unmerging; keep it.
613 newworldlist.append(x)
615 portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
616 gid=portage.portage_gid, mode=02770)
617 portage.util.write_atomic(world_filename, "\n".join(newworldlist))
619 def genericdict(mylist):
622 mynewdict[portage.dep_getkey(x)]=x
625 def filter_iuse_defaults(iuse):
627 if flag.startswith("+"):
632 class DepPriority(object):
634 This class generates an integer priority level based of various
635 attributes of the dependency relationship. Attributes can be assigned
636 at any time and the new integer value will be generated on calls to the
637 __int__() method. Rich comparison operators are supported.
639 The boolean attributes that affect the integer value are "satisfied",
640 "buildtime", "runtime", and "system". Various combinations of
641 attributes lead to the following priority levels:
643 Combination of properties Priority level
645 not satisfied and buildtime 0
646 not satisfied and runtime -1
647 satisfied and buildtime -2
648 satisfied and runtime -3
649 (none of the above) -4
651 Several integer constants are defined for categorization of priority
654 MEDIUM The upper boundary for medium dependencies.
655 SOFT The upper boundary for soft dependencies.
656 MIN The lower boundary for soft dependencies.
658 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
662 def __init__(self, **kwargs):
663 for myattr in self.__slots__:
664 if myattr == "__weakref__":
666 myvalue = kwargs.get(myattr, False)
667 setattr(self, myattr, myvalue)
669 if not self.satisfied:
679 def __lt__(self, other):
680 return self.__int__() < other
681 def __le__(self, other):
682 return self.__int__() <= other
683 def __eq__(self, other):
684 return self.__int__() == other
685 def __ne__(self, other):
686 return self.__int__() != other
687 def __gt__(self, other):
688 return self.__int__() > other
689 def __ge__(self, other):
690 return self.__int__() >= other
693 return copy.copy(self)
695 myvalue = self.__int__()
696 if myvalue > self.MEDIUM:
698 if myvalue > self.SOFT:
702 class FakeVartree(portage.vartree):
703 """This is implements an in-memory copy of a vartree instance that provides
704 all the interfaces required for use by the depgraph. The vardb is locked
705 during the constructor call just long enough to read a copy of the
706 installed package information. This allows the depgraph to do it's
707 dependency calculations without holding a lock on the vardb. It also
708 allows things like vardb global updates to be done in memory so that the
709 user doesn't necessarily need write access to the vardb in cases where
710 global updates are necessary (updates are performed when necessary if there
711 is not a matching ebuild in the tree)."""
712 def __init__(self, real_vartree, portdb):
713 self.root = real_vartree.root
714 self.settings = real_vartree.settings
715 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
716 vdb_path = os.path.join(self.root, portage.VDB_PATH)
718 # At least the parent needs to exist for the lock file.
719 portage.util.ensure_dirs(vdb_path)
720 except portage.exception.PortageException:
724 if os.access(vdb_path, os.W_OK):
725 vdb_lock = portage.locks.lockdir(vdb_path)
726 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
727 "DEPEND", "RDEPEND", "PDEPEND"]
728 real_dbapi = real_vartree.dbapi
730 for cpv in real_dbapi.cpv_all():
731 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
732 myslot = metadata["SLOT"]
733 mycp = portage.dep_getkey(cpv)
734 myslot_atom = "%s:%s" % (mycp, myslot)
736 mycounter = long(metadata["COUNTER"])
739 metadata["COUNTER"] = str(mycounter)
740 other_counter = slot_counters.get(myslot_atom, None)
741 if other_counter is not None:
742 if other_counter > mycounter:
744 slot_counters[myslot_atom] = mycounter
745 self.dbapi.cpv_inject(cpv, metadata=metadata)
746 real_dbapi.flush_cache()
749 portage.locks.unlockdir(vdb_lock)
750 # Populate the old-style virtuals using the cached values.
751 if not self.settings.treeVirtuals:
752 self.settings.treeVirtuals = portage.util.map_dictlist_vals(
753 portage.getCPFromCPV, self.get_all_provides())
755 # Intialize variables needed for lazy cache pulls of the live ebuild
756 # metadata. This ensures that the vardb lock is released ASAP, without
757 # being delayed in case cache generation is triggered.
758 self._aux_get = self.dbapi.aux_get
759 self.dbapi.aux_get = self._aux_get_wrapper
760 self._aux_get_history = set()
761 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
762 self._portdb = portdb
763 self._global_updates = None
765 def _aux_get_wrapper(self, pkg, wants):
766 if pkg in self._aux_get_history:
767 return self._aux_get(pkg, wants)
768 self._aux_get_history.add(pkg)
770 # Use the live ebuild metadata if possible.
771 live_metadata = dict(izip(self._portdb_keys,
772 self._portdb.aux_get(pkg, self._portdb_keys)))
773 self.dbapi.aux_update(pkg, live_metadata)
774 except (KeyError, portage.exception.PortageException):
775 if self._global_updates is None:
776 self._global_updates = \
777 grab_global_updates(self._portdb.porttree_root)
778 perform_global_updates(
779 pkg, self.dbapi, self._global_updates)
780 return self._aux_get(pkg, wants)
782 def grab_global_updates(portdir):
783 from portage.update import grab_updates, parse_updates
784 updpath = os.path.join(portdir, "profiles", "updates")
786 rawupdates = grab_updates(updpath)
787 except portage.exception.DirectoryNotFound:
790 for mykey, mystat, mycontent in rawupdates:
791 commands, errors = parse_updates(mycontent)
792 upd_commands.extend(commands)
795 def perform_global_updates(mycpv, mydb, mycommands):
796 from portage.update import update_dbentries
797 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
798 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
799 updates = update_dbentries(mycommands, aux_dict)
801 mydb.aux_update(mycpv, updates)
803 class BlockerCache(DictMixin):
804 """This caches blockers of installed packages so that dep_check does not
805 have to be done for every single installed package on every invocation of
806 emerge. The cache is invalidated whenever it is detected that something
807 has changed that might alter the results of dep_check() calls:
808 1) the set of installed packages (including COUNTER) has changed
809 2) the old-style virtuals have changed
811 class BlockerData(object):
812 def __init__(self, counter, atoms):
813 self.counter = counter
816 def __init__(self, myroot, vardb):
818 self._installed_pkgs = set(vardb.cpv_all())
819 self._virtuals = vardb.settings.getvirtuals()
820 self._cache_filename = os.path.join(myroot,
821 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
822 self._cache_version = "1"
823 self._cache_data = None
824 self._modified = False
829 f = open(self._cache_filename)
830 mypickle = cPickle.Unpickler(f)
831 mypickle.find_global = None
832 self._cache_data = mypickle.load()
835 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
837 cache_valid = self._cache_data and \
838 isinstance(self._cache_data, dict) and \
839 self._cache_data.get("version") == self._cache_version and \
840 self._cache_data.get("virtuals") == self._virtuals and \
841 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
843 for pkg in self._installed_pkgs:
844 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
849 self._cache_data = {"version":self._cache_version}
850 self._cache_data["blockers"] = {}
851 self._cache_data["virtuals"] = self._virtuals
852 self._modified = False
855 """If the current user has permission and the internal blocker cache
856 been updated, save it to disk and mark it unmodified. This is called
857 by emerge after it has proccessed blockers for all installed packages.
858 Currently, the cache is only written if the user has superuser
859 privileges (since that's required to obtain a lock), but all users
860 have read access and benefit from faster blocker lookups (as long as
861 the entire cache is still valid). The cache is stored as a pickled
862 dict object with the following format:
866 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
867 "virtuals" : vardb.settings.getvirtuals()
870 if self._modified and \
873 f = portage.util.atomic_ofstream(self._cache_filename)
874 cPickle.dump(self._cache_data, f, -1)
876 portage.util.apply_secpass_permissions(
877 self._cache_filename, gid=portage.portage_gid, mode=0644)
878 except (IOError, OSError), e:
880 self._modified = False
882 def __setitem__(self, cpv, blocker_data):
884 Update the cache and mark it as modified for a future call to
887 @param cpv: Package for which to cache blockers.
889 @param blocker_data: An object with counter and atoms attributes.
890 @type blocker_data: BlockerData
892 self._cache_data["blockers"][cpv] = \
893 (blocker_data.counter, blocker_data.atoms)
894 self._modified = True
896 def __getitem__(self, cpv):
899 @returns: An object with counter and atoms attributes.
901 return self.BlockerData(*self._cache_data["blockers"][cpv])
903 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
905 from formatter import AbstractFormatter, DumbWriter
906 f = AbstractFormatter(DumbWriter(maxcol=72))
908 print "\n\n!!! Invalid or corrupt dependency specification: "
916 p_type, p_root, p_key, p_status = parent_node
918 if p_status == "nomerge":
919 category, pf = portage.catsplit(p_key)
920 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
921 msg.append("Portage is unable to process the dependencies of the ")
922 msg.append("'%s' package. " % p_key)
923 msg.append("In order to correct this problem, the package ")
924 msg.append("should be uninstalled, reinstalled, or upgraded. ")
925 msg.append("As a temporary workaround, the --nodeps option can ")
926 msg.append("be used to ignore all dependencies. For reference, ")
927 msg.append("the problematic dependencies can be found in the ")
928 msg.append("*DEPEND files located in '%s/'." % pkg_location)
930 msg.append("This package can not be installed. ")
931 msg.append("Please notify the '%s' package maintainer " % p_key)
932 msg.append("about this problem.")
935 f.add_flowing_data(x)
943 "installed":"vartree"}
945 def __init__(self, settings, trees, myopts, myparams, spinner):
946 self.settings = settings
947 self.target_root = settings["ROOT"]
949 self.myparams = myparams
951 if settings.get("PORTAGE_DEBUG", "") == "1":
953 self.spinner = spinner
954 self.pkgsettings = {}
955 # Maps cpv to digraph node for all nodes added to the graph.
956 self.pkg_node_map = {}
957 # Maps slot atom to digraph node for all nodes added to the graph.
958 self._slot_node_map = {}
960 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
964 self.trees[myroot] = {}
965 for tree in ("porttree", "bintree"):
966 self.trees[myroot][tree] = trees[myroot][tree]
967 self.trees[myroot]["vartree"] = \
968 FakeVartree(trees[myroot]["vartree"],
969 trees[myroot]["porttree"].dbapi)
970 self.pkgsettings[myroot] = portage.config(
971 clone=self.trees[myroot]["vartree"].settings)
972 self.pkg_node_map[myroot] = {}
973 self._slot_node_map[myroot] = {}
974 vardb = self.trees[myroot]["vartree"].dbapi
975 # This fakedbapi instance will model the state that the vdb will
976 # have after new packages have been installed.
977 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
978 self.mydbapi[myroot] = fakedb
979 if "--nodeps" not in self.myopts and \
980 "--buildpkgonly" not in self.myopts:
981 # --nodeps bypasses this, since it isn't needed in this case
982 # and the cache pulls might trigger (slow) cache generation.
983 for pkg in vardb.cpv_all():
984 self.spinner.update()
985 fakedb.cpv_inject(pkg,
986 metadata=dict(izip(self._mydbapi_keys,
987 vardb.aux_get(pkg, self._mydbapi_keys))))
989 self.useFlags[myroot] = {}
990 if "--usepkg" in self.myopts:
991 self.trees[myroot]["bintree"].populate(
992 "--getbinpkg" in self.myopts,
993 "--getbinpkgonly" in self.myopts)
997 self.digraph=portage.digraph()
998 # Tracks simple parent/child relationships (PDEPEND relationships are
1000 self._parent_child_digraph = digraph()
1002 self.outdatedpackages=[]
1004 self.blocker_digraph = digraph()
1005 self.blocker_parents = {}
1006 self._slot_collision_info = []
1007 # Slot collision nodes are not allowed to block other packages since
1008 # blocker validation is only able to account for one package per slot.
1009 self._slot_collision_nodes = set()
1010 self._altlist_cache = {}
1011 self._pprovided_args = []
1013 def _show_slot_collision_notice(self, packages):
1014 """Show an informational message advising the user to mask one of the
1015 the packages. In some cases it may be possible to resolve this
1016 automatically, but support for backtracking (removal nodes that have
1017 already been selected) will be required in order to handle all possible
1021 msg.append("\n!!! Multiple versions within a single " + \
1022 "package slot have been \n")
1023 msg.append("!!! pulled into the dependency graph:\n\n")
1024 for node, parents in packages:
1025 msg.append(str(node))
1027 msg.append(" pulled in by\n")
1028 for parent in parents:
1030 msg.append(str(parent))
1033 msg.append(" (no parents)\n")
1035 sys.stderr.write("".join(msg))
1038 if "--quiet" in self.myopts:
1042 msg.append("It may be possible to solve this problem ")
1043 msg.append("by using package.mask to prevent one of ")
1044 msg.append("those packages from being selected. ")
1045 msg.append("However, it is also possible that conflicting ")
1046 msg.append("dependencies exist such that they are impossible to ")
1047 msg.append("satisfy simultaneously. If such a conflict exists in ")
1048 msg.append("the dependencies of two different packages, then those ")
1049 msg.append("packages can not be installed simultaneously.")
1051 from formatter import AbstractFormatter, DumbWriter
1052 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1054 f.add_flowing_data(x)
1058 msg.append("For more information, see MASKED PACKAGES ")
1059 msg.append("section in the emerge man page or refer ")
1060 msg.append("to the Gentoo Handbook.")
1062 f.add_flowing_data(x)
1066 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1067 priority=DepPriority(), rev_dep=False, arg=None):
1069 Fills the digraph with nodes comprised of packages to merge.
1070 mybigkey is the package spec of the package to merge.
1071 myparent is the package depending on mybigkey ( or None )
1072 addme = Should we add this package to the digraph or are we just looking at it's deps?
1073 Think --onlydeps, we need to ignore packages in that case.
1076 #IUSE-aware emerge -> USE DEP aware depgraph
1077 #"no downgrade" emerge
1079 mytype, myroot, mykey = mybigkey
1080 existing_node = None
1082 existing_node = self.pkg_node_map[myroot].get(mykey)
1084 self._parent_child_digraph.add(existing_node, myparent)
1085 if existing_node != myparent:
1086 # Refuse to make a node depend on itself so that the we don't
1087 # don't create a bogus circular dependency in self.altlist().
1088 if rev_dep and myparent:
1089 self.digraph.addnode(myparent, existing_node,
1092 self.digraph.addnode(existing_node, myparent,
1096 if "--nodeps" not in self.myopts:
1097 self.spinner.update()
1098 if mytype == "blocks":
1100 "--buildpkgonly" not in self.myopts and \
1101 "--nodeps" not in self.myopts and \
1102 myparent not in self._slot_collision_nodes:
1103 mybigkey[1] = myparent[1]
1104 self.blocker_parents.setdefault(
1105 tuple(mybigkey), set()).add(myparent)
1107 if not arg and myroot == self.target_root:
1108 arg = portage.best_match_to_list(mykey, self.args_keys)
1109 # select the correct /var database that we'll be checking against
1110 vardbapi = self.trees[myroot]["vartree"].dbapi
1111 portdb = self.trees[myroot]["porttree"].dbapi
1112 bindb = self.trees[myroot]["bintree"].dbapi
1113 pkgsettings = self.pkgsettings[myroot]
1115 # if the package is already on the system, we add a "nomerge"
1116 # directive, otherwise we add a "merge" directive.
1118 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1121 self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
1122 myuse = self.pkgsettings[myroot]["USE"].split()
1125 if mytype == "installed":
1127 if addme and mytype != "installed":
1128 # this is where we add the node to the list of packages to merge
1129 if "selective" in self.myparams or not arg:
1130 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1133 """ If we aren't merging, perform the --newuse check.
1134 If the package has new iuse flags or different use flags then if
1135 --newuse is specified, we need to merge the package. """
1136 if merging==0 and "--newuse" in self.myopts and \
1137 vardbapi.cpv_exists(mykey):
1138 pkgsettings.setcpv(mykey, mydb=mydbapi)
1139 forced_flags = set()
1140 forced_flags.update(pkgsettings.useforce)
1141 forced_flags.update(pkgsettings.usemask)
1142 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1143 iuses = set(filter_iuse_defaults(
1144 mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
1145 old_iuse = set(filter_iuse_defaults(
1146 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1147 if iuses.symmetric_difference(
1148 old_iuse).difference(forced_flags):
1150 elif old_iuse.intersection(old_use) != \
1151 iuses.intersection(myuse):
1154 if addme and merging == 1:
1155 mybigkey.append("merge")
1157 mybigkey.append("nomerge")
1158 jbigkey = tuple(mybigkey)
1161 metadata = dict(izip(self._mydbapi_keys,
1162 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1163 if merging == 0 and vardbapi.cpv_exists(mykey):
1164 metadata["USE"] = vardbapi.aux_get(mykey, ["USE"])[0]
1165 myuse = metadata["USE"].split()
1166 metadata["SLOT"] = vardbapi.aux_get(mykey, ["SLOT"])[0]
1167 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1168 existing_node = self._slot_node_map[myroot].get(
1170 slot_collision = False
1172 e_type, myroot, e_cpv, e_status = existing_node
1174 # The existing node can be reused.
1175 self._parent_child_digraph.add(existing_node, myparent)
1176 if rev_dep and myparent:
1177 ptype, proot, pkey, pstatus = myparent
1178 self.digraph.addnode(myparent, existing_node,
1181 self.digraph.addnode(existing_node, myparent,
1185 # A slot collision has occurred. Sometimes this coincides
1186 # with unresolvable blockers, so the slot collision will be
1187 # shown later if there are no unresolvable blockers.
1188 e_parents = self._parent_child_digraph.parent_nodes(
1192 myparents.append(myparent)
1193 self._slot_collision_info.append(
1194 ((jbigkey, myparents), (existing_node, e_parents)))
1195 self._slot_collision_nodes.add(jbigkey)
1196 slot_collision = True
1199 # Now add this node to the graph so that self.display()
1200 # can show use flags and --tree portage.output. This node is
1201 # only being partially added to the graph. It must not be
1202 # allowed to interfere with the other nodes that have been
1203 # added. Do not overwrite data for existing nodes in
1204 # self.pkg_node_map and self.mydbapi since that data will
1205 # be used for blocker validation.
1206 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1207 self.useFlags[myroot].setdefault(mykey, myuse)
1208 # Even though the graph is now invalid, continue to process
1209 # dependencies so that things like --fetchonly can still
1210 # function despite collisions.
1212 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1213 self._slot_node_map[myroot][slot_atom] = jbigkey
1214 self.pkg_node_map[myroot][mykey] = jbigkey
1215 self.useFlags[myroot][mykey] = myuse
1217 if rev_dep and myparent:
1218 self.digraph.addnode(myparent, jbigkey,
1221 self.digraph.addnode(jbigkey, myparent,
1224 # Do this even when addme is False (--onlydeps) so that the
1225 # parent/child relationship is always known in case
1226 # self._show_slot_collision_notice() needs to be called later.
1227 self._parent_child_digraph.add(jbigkey, myparent)
1229 """ This section determines whether we go deeper into dependencies or not.
1230 We want to go deeper on a few occasions:
1231 Installing package A, we need to make sure package A's deps are met.
1232 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1233 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1235 if "deep" not in self.myparams and not merging and \
1236 not ("--update" in self.myopts and arg and merging):
1238 elif "recurse" not in self.myparams:
1241 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1242 Pull from bintree if it's binary package, porttree if it's ebuild.
1243 Binpkg's can be either remote or local. """
1246 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1247 depvalues = mydbapi.aux_get(mykey, depkeys)
1248 for i in xrange(len(depkeys)):
1249 edepend[depkeys[i]] = depvalues[i]
1251 if mytype == "ebuild":
1252 if "--buildpkgonly" in self.myopts:
1253 edepend["RDEPEND"] = ""
1254 edepend["PDEPEND"] = ""
1255 if not (arg and "--onlydeps" in self.myopts and \
1256 mytype == "ebuild") and \
1257 self.myopts.get("--with-bdeps", "n") == "n" and \
1258 (mytype == "binary" or mybigkey[3] == "nomerge"):
1259 edepend["DEPEND"] = ""
1261 """ We have retrieve the dependency information, now we need to recursively
1262 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1264 mp = tuple(mybigkey)
1267 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1268 myuse=myuse, priority=DepPriority(buildtime=True),
1271 """RDEPEND is soft by definition. However, in order to ensure
1272 correct merge order, we make it a hard dependency. Otherwise, a
1273 build time dependency might not be usable due to it's run time
1274 dependencies not being installed yet.
1276 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1277 myuse=myuse, priority=DepPriority(runtime=True),
1280 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1281 # Post Depend -- Add to the list without a parent, as it depends
1282 # on a package being present AND must be built after that package.
1283 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1284 myuse=myuse, priority=DepPriority(), rev_deps=True,
1287 except ValueError, e:
1289 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1290 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1292 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1293 portage.writemsg("\n", noiselevel=-1)
1294 if mytype == "binary":
1296 "!!! This binary package cannot be installed: '%s'\n" % \
1297 mykey, noiselevel=-1)
1298 elif mytype == "ebuild":
1299 myebuild, mylocation = portdb.findname2(mykey)
1300 portage.writemsg("!!! This ebuild cannot be installed: " + \
1301 "'%s'\n" % myebuild, noiselevel=-1)
1302 portage.writemsg("!!! Please notify the package maintainer " + \
1303 "that atoms must be fully-qualified.\n", noiselevel=-1)
1307 def select_files(self,myfiles):
1308 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1310 myroot = self.target_root
1311 portdb = self.trees[myroot]["porttree"].dbapi
1312 bindb = self.trees[myroot]["bintree"].dbapi
1313 pkgsettings = self.pkgsettings[myroot]
1315 def visible(mylist):
1316 matches = portdb.gvisible(portdb.visible(mylist))
1317 return [x for x in mylist \
1318 if x in matches or not portdb.cpv_exists(x)]
1320 ext = os.path.splitext(x)[1]
1322 if not os.path.exists(x):
1324 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1325 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1326 elif os.path.exists(
1327 os.path.join(pkgsettings["PKGDIR"], x)):
1328 x = os.path.join(pkgsettings["PKGDIR"], x)
1330 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1331 print "!!! Please ensure the tbz2 exists as specified.\n"
1333 mytbz2=portage.xpak.tbz2(x)
1334 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1335 if os.path.realpath(x) != \
1336 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1337 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1339 if not self.create(["binary", myroot, mykey],
1340 None, "--onlydeps" not in self.myopts):
1341 return (0,myfavorites)
1342 elif not "--oneshot" in self.myopts:
1343 myfavorites.append(mykey)
1344 elif ext==".ebuild":
1345 x = os.path.realpath(x)
1346 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1347 ebuild_path = portdb.findname(mykey)
1349 if os.path.realpath(ebuild_path) != x:
1350 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1352 if mykey not in portdb.xmatch(
1353 "match-visible", portage.dep_getkey(mykey)):
1354 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1355 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1356 print colorize("BAD", "*** page for details.")
1357 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1360 raise portage.exception.PackageNotFound(
1361 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1362 if not self.create(["ebuild", myroot, mykey],
1363 None, "--onlydeps" not in self.myopts):
1364 return (0,myfavorites)
1365 elif not "--oneshot" in self.myopts:
1366 myfavorites.append(mykey)
1368 if not is_valid_package_atom(x):
1369 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1371 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1372 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1376 if "--usepkg" in self.myopts:
1377 mykey = portage.dep_expand(x, mydb=bindb,
1378 settings=pkgsettings)
1379 if (mykey and not mykey.startswith("null/")) or \
1380 "--usepkgonly" in self.myopts:
1381 arg_atoms.append((x, mykey))
1384 mykey = portage.dep_expand(x,
1385 mydb=portdb, settings=pkgsettings)
1386 arg_atoms.append((x, mykey))
1387 except ValueError, errpkgs:
1388 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1389 print "!!! one of the following fully-qualified ebuild names instead:\n"
1390 for i in errpkgs[0]:
1391 print " " + green(i)
1395 if "--update" in self.myopts:
1396 """Make sure all installed slots are updated when possible. Do this
1397 with --emptytree also, to ensure that all slots are remerged."""
1398 vardb = self.trees[self.target_root]["vartree"].dbapi
1400 for myarg, myatom in arg_atoms:
1401 greedy_atoms.append((myarg, myatom))
1403 for cpv in vardb.match(myatom):
1404 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1407 if "--usepkg" in self.myopts:
1408 mymatches = bindb.match(myatom)
1409 if "--usepkgonly" not in self.myopts:
1410 mymatches = visible(mymatches)
1411 best_pkg = portage.best(mymatches)
1413 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1414 best_pkgs.append(("binary", best_pkg, best_slot))
1415 if "--usepkgonly" not in self.myopts:
1416 best_pkg = portage.best(portdb.match(myatom))
1418 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1419 best_pkgs.append(("ebuild", best_pkg, best_slot))
1421 best_pkg = portage.best([x[1] for x in best_pkgs])
1422 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1423 best_slot = best_pkgs[0][2]
1424 myslots.add(best_slot)
1425 if len(myslots) > 1:
1426 for myslot in myslots:
1427 myslot_atom = "%s:%s" % \
1428 (portage.dep_getkey(myatom), myslot)
1430 if "--usepkgonly" not in self.myopts and \
1431 self.trees[self.target_root][
1432 "porttree"].dbapi.match(myslot_atom):
1434 elif "--usepkg" in self.myopts:
1435 mymatches = bindb.match(myslot_atom)
1436 if "--usepkgonly" not in self.myopts:
1437 mymatches = visible(mymatches)
1441 greedy_atoms.append((myarg, myslot_atom))
1442 arg_atoms = greedy_atoms
1444 """ These are used inside self.create() in order to ensure packages
1445 that happen to match arguments are not incorrectly marked as nomerge."""
1446 self.args_keys = [x[1] for x in arg_atoms]
1447 for myarg, myatom in arg_atoms:
1449 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1450 except portage.exception.MissingSignature, e:
1451 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1452 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1453 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1454 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1455 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1457 except portage.exception.InvalidSignature, e:
1458 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1459 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1460 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1461 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1462 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1464 except SystemExit, e:
1465 raise # Needed else can't exit
1466 except Exception, e:
1467 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1468 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1472 return (0,myfavorites)
1473 elif not "--oneshot" in self.myopts:
1474 mykey = portage.dep_getkey(myatom)
1475 if mykey not in myfavorites:
1476 myfavorites.append(mykey)
1479 if "--usepkgonly" in self.myopts:
1480 for xs in self.digraph.all_nodes():
1481 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1485 print "Missing binary for:",xs[2]
1487 if not self.validate_blockers():
1488 return False, myfavorites
1490 # We're true here unless we are missing binaries.
1491 return (not missing,myfavorites)
1493 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1494 myuse=None, raise_on_missing=False, priority=DepPriority(),
1495 rev_deps=False, parent_arg=None):
1496 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1497 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1498 myparent = the node whose depstring is being passed in
1499 arg = package was specified on the command line, merge even if it's already installed
1500 myuse = USE flags at present
1501 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1502 else continue trying.
1503 return 1 on success, 0 for failure
1506 portdb = self.trees[myroot]["porttree"].dbapi
1507 bindb = self.trees[myroot]["bintree"].dbapi
1508 vardb = self.trees[myroot]["vartree"].dbapi
1509 pkgsettings = self.pkgsettings[myroot]
1511 p_type, p_root, p_key, p_status = myparent
1513 if "--debug" in self.myopts:
1515 print "Parent: ",myparent
1516 print "Depstring:",depstring
1518 print "Reverse:", rev_deps
1519 print "Priority:", priority
1521 #processing dependencies
1522 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1523 dependencies are satisfiable. """
1525 mymerge = [depstring]
1526 pprovided = pkgsettings.pprovideddict.get(
1527 portage.dep_getkey(depstring))
1528 if pprovided and portage.match_from_list(depstring, pprovided):
1532 if myparent and p_status == "nomerge":
1533 portage.dep._dep_check_strict = False
1534 mycheck = portage.dep_check(depstring, None,
1535 pkgsettings, myuse=myuse,
1536 use_binaries=("--usepkgonly" in self.myopts),
1537 myroot=myroot, trees=self.trees)
1539 portage.dep._dep_check_strict = True
1543 show_invalid_depstring_notice(
1544 myparent, depstring, mycheck[1])
1546 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1548 mymerge = mycheck[1]
1550 if not mymerge and arg and \
1551 portage.best_match_to_list(depstring, self.args_keys):
1552 # A provided package has been specified on the command line. The
1553 # package will not be merged and a warning will be displayed.
1554 self._pprovided_args.append(arg)
1557 # The parent is added after it's own dep_check call so that it
1558 # isn't allowed to satisfy a direct bootstrap dependency on itself
1559 # via an old-style virtual. This isn't a problem with new-style
1560 # virtuals, which are preferenced in dep_zapdeps by looking only at
1561 # the depstring, vdb, and available packages.
1563 p_type, p_root, p_key, p_status = myparent
1564 if p_status == "merge":
1565 # Update old-style virtuals if this package provides any.
1566 # These are needed for dep_virtual calls inside dep_check.
1567 self.pkgsettings[p_root].setinst(p_key,
1568 self.trees[p_root][self.pkg_tree_map[p_type]].dbapi)
1570 if "--debug" in self.myopts:
1571 print "Candidates:",mymerge
1575 selected_pkg = ["blocks", myroot, x[1:], None]
1577 #We are not processing a blocker but a normal dependency
1579 """In some cases, dep_check will return deps that shouldn't
1580 be proccessed any further, so they are identified and
1582 if "empty" not in self.myparams and \
1583 "deep" not in self.myparams and \
1584 not ("--update" in self.myopts and parent_arg) and \
1588 # List of acceptable packages, ordered by type preference.
1589 matched_packages = []
1590 myeb_matches = portdb.xmatch("match-visible", x)
1592 if "--usepkgonly" not in self.myopts:
1593 myeb = portage.best(myeb_matches)
1596 if "--usepkg" in self.myopts:
1597 # The next line assumes the binarytree has been populated.
1598 # XXX: Need to work out how we use the binary tree with roots.
1599 myeb_pkg_matches = bindb.match(x)
1600 if "--usepkgonly" not in self.myopts:
1601 # Remove any binary package entries that are masked in the portage tree (#55871)
1602 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1603 if pkg in myeb_matches or \
1604 not portdb.cpv_exists(pkg)]
1605 if myeb_pkg_matches:
1606 myeb_pkg = portage.best(myeb_pkg_matches)
1608 if myeb_pkg and "--newuse" in self.myopts:
1609 iuses = set(filter_iuse_defaults(
1610 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1611 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1613 if "--usepkgonly" not in self.myopts and myeb:
1616 pkgsettings.setcpv(myeb, mydb=mydb)
1618 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1619 now_use = pkgsettings["USE"].split()
1620 forced_flags = set()
1621 forced_flags.update(pkgsettings.useforce)
1622 forced_flags.update(pkgsettings.usemask)
1624 if "--usepkgonly" not in self.myopts and myeb:
1625 cur_iuse = set(filter_iuse_defaults(
1626 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1627 if iuses.symmetric_difference(
1628 cur_iuse).difference(forced_flags):
1630 elif iuses.intersection(old_use) != \
1631 cur_iuse.intersection(now_use):
1635 self.trees[myroot]["bintree"].dbapi.aux_get(
1636 myeb_pkg, ["USE"])[0].split()
1637 matched_packages.append(
1638 ["binary", myroot, myeb_pkg, binpkguseflags])
1640 if "--usepkgonly" not in self.myopts and myeb_matches:
1641 matched_packages.append(
1642 ["ebuild", myroot, myeb, None])
1644 if not matched_packages and \
1645 not (arg and "selective" not in self.myparams):
1646 """Fall back to the installed package database. This is a
1647 last resort because the metadata tends to diverge from that
1648 of the ebuild in the tree."""
1649 myeb_inst_matches = vardb.match(x)
1650 if "--usepkgonly" not in self.myopts:
1651 """ TODO: Improve masking check for installed and
1652 binary packages. bug #149816"""
1653 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1654 if not portdb.cpv_exists(pkg)]
1656 if myeb_inst_matches:
1657 myeb_inst = portage.best(myeb_inst_matches)
1659 binpkguseflags = vardb.aux_get(
1660 myeb_inst, ["USE"])[0].split()
1661 matched_packages.append(
1662 ["installed", myroot, myeb_inst, binpkguseflags])
1664 if not matched_packages:
1665 if raise_on_missing:
1672 xfrom = '(dependency required by '+ \
1673 green('"%s"' % myparent[2]) + \
1674 red(' [%s]' % myparent[0]) + ')'
1675 alleb = portdb.xmatch("match-all", x)
1677 if "--usepkgonly" not in self.myopts:
1678 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1679 print "!!! One of the following masked packages is required to complete your request:"
1683 mreasons = portage.getmaskingstatus(p,
1684 settings=pkgsettings, portdb=portdb)
1685 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1686 if "package.mask" in mreasons:
1687 comment, filename = \
1688 portage.getmaskingreason(p,
1689 settings=pkgsettings, portdb=portdb,
1690 return_location=True)
1691 if comment and comment != oldcomment:
1694 oldcomment = comment
1695 licenses = portdb.aux_get(p, ["LICENSE"])[0]
1698 pkgsettings.setcpv(p, mydb=portdb)
1699 uselist = pkgsettings.get("USE", "").split()
1700 missing_licenses = []
1702 missing_licenses = \
1703 pkgsettings.getMissingLicenses(
1704 licenses, p, uselist)
1705 except portage.exception.InvalidDependString:
1706 # This will have already been reported
1707 # above via mreasons.
1709 for l in missing_licenses:
1710 l_path = portdb.findLicensePath(l)
1711 if l in shown_licenses:
1713 msg = ("A copy of the '%s' license" + \
1714 " is located at '%s'.") % (l, l_path)
1717 shown_licenses.append(l)
1719 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1720 print "refer to the Gentoo Handbook."
1722 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1723 print "!!! Either add a suitable binary package or compile from an ebuild."
1725 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1731 if "--debug" in self.myopts:
1732 for pkg in matched_packages:
1733 print (pkg[0] + ":").rjust(10), pkg[2]
1735 if len(matched_packages) > 1:
1736 bestmatch = portage.best(
1737 [pkg[2] for pkg in matched_packages])
1738 matched_packages = [pkg for pkg in matched_packages \
1739 if pkg[2] == bestmatch]
1741 # ordered by type preference ("ebuild" type is the last resort)
1742 selected_pkg = matched_packages[0]
1743 pkgtype, myroot, mycpv, myuse = selected_pkg
1744 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1745 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1746 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1747 existing_node = self._slot_node_map[myroot].get(
1750 e_type, myroot, e_cpv, e_status = existing_node
1751 if portage.match_from_list(x, [e_cpv]):
1752 # The existing node can be reused.
1753 selected_pkg = [e_type, myroot, e_cpv,
1754 self.useFlags[myroot][e_cpv]]
1757 #we are a dependency, so we want to be unconditionally added
1758 mypriority = priority.copy()
1760 mypriority.satisfied = True
1761 if not self.create(selected_pkg[0:3], myparent,
1762 myuse=selected_pkg[-1], priority=mypriority,
1763 rev_dep=rev_deps, arg=arg):
1766 #if mysource is not set, then we are a command-line dependency and should not be added
1767 #if --onlydeps is specified.
1768 if not self.create(selected_pkg[0:3], myparent,
1769 addme=("--onlydeps" not in self.myopts),
1770 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1773 if "--debug" in self.myopts:
1774 print "Exiting...",myparent
1777 def validate_blockers(self):
1778 """Remove any blockers from the digraph that do not match any of the
1779 packages within the graph. If necessary, create hard deps to ensure
1780 correct merge order such that mutually blocking packages are never
1781 installed simultaneously."""
1783 if "--buildpkgonly" in self.myopts or \
1784 "--nodeps" in self.myopts:
1788 for myroot in self.trees:
1790 modified_slots[myroot] = myslots
1791 final_db = self.mydbapi[myroot]
1792 slot_node_map = self._slot_node_map[myroot]
1793 for slot_atom, mynode in slot_node_map.iteritems():
1794 mytype, myroot, mycpv, mystatus = mynode
1795 if mystatus == "merge":
1796 myslots[slot_atom] = mycpv
1798 #if "deep" in self.myparams:
1800 # Pull in blockers from all installed packages that haven't already
1801 # been pulled into the depgraph. This is not enabled by default
1802 # due to the performance penalty that is incurred by all the
1803 # additional dep_check calls that are required.
1805 # Optimization hack for dep_check calls that minimizes the
1806 # available matches by replacing the portdb with a fakedbapi
1808 class FakePortageTree(object):
1809 def __init__(self, mydb):
1811 dep_check_trees = {}
1812 for myroot in self.trees:
1813 dep_check_trees[myroot] = self.trees[myroot].copy()
1814 dep_check_trees[myroot]["porttree"] = \
1815 FakePortageTree(self.mydbapi[myroot])
1817 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1818 for myroot in self.trees:
1819 pkg_node_map = self.pkg_node_map[myroot]
1820 vardb = self.trees[myroot]["vartree"].dbapi
1821 portdb = self.trees[myroot]["porttree"].dbapi
1822 pkgsettings = self.pkgsettings[myroot]
1823 final_db = self.mydbapi[myroot]
1824 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
1825 blocker_cache = BlockerCache(myroot, vardb)
1826 for pkg in cpv_all_installed:
1827 blocker_atoms = None
1828 matching_node = pkg_node_map.get(pkg, None)
1829 if matching_node and \
1830 matching_node[3] == "nomerge":
1832 # If this node has any blockers, create a "nomerge"
1833 # node for it so that they can be enforced.
1834 self.spinner.update()
1835 blocker_data = blocker_cache.get(pkg)
1837 blocker_atoms = blocker_data.atoms
1839 dep_vals = vardb.aux_get(pkg, dep_keys)
1840 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
1841 depstr = " ".join(dep_vals)
1842 # It is crucial to pass in final_db here in order to
1843 # optimize dep_check calls by eliminating atoms via
1844 # dep_wordreduce and dep_eval calls.
1846 portage.dep._dep_check_strict = False
1848 success, atoms = portage.dep_check(depstr,
1849 final_db, pkgsettings, myuse=myuse,
1850 trees=dep_check_trees, myroot=myroot)
1851 except Exception, e:
1852 if isinstance(e, SystemExit):
1854 # This is helpful, for example, if a ValueError
1855 # is thrown from cpv_expand due to multiple
1856 # matches (this can happen if an atom lacks a
1858 show_invalid_depstring_notice(
1859 ("installed", myroot, pkg, "nomerge"),
1864 portage.dep._dep_check_strict = True
1866 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
1867 vardb.aux_get(pkg, ["SLOT"])[0])
1868 if slot_atom in modified_slots[myroot]:
1869 # This package is being replaced anyway, so
1870 # ignore invalid dependencies so as not to
1871 # annoy the user too much (otherwise they'd be
1872 # forced to manually unmerge it first).
1874 show_invalid_depstring_notice(
1875 ("installed", myroot, pkg, "nomerge"),
1878 blocker_atoms = [myatom for myatom in atoms \
1879 if myatom.startswith("!")]
1880 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
1881 blocker_cache[pkg] = \
1882 blocker_cache.BlockerData(counter, blocker_atoms)
1884 # Don't store this parent in pkg_node_map, because it's
1885 # not needed there and it might overwrite a "merge"
1886 # node with the same cpv.
1887 myparent = ("installed", myroot, pkg, "nomerge")
1888 for myatom in blocker_atoms:
1889 blocker = ("blocks", myroot, myatom[1:])
1891 self.blocker_parents.get(blocker, None)
1894 self.blocker_parents[blocker] = myparents
1895 myparents.add(myparent)
1896 blocker_cache.flush()
1899 for blocker in self.blocker_parents.keys():
1900 mytype, myroot, mydep = blocker
1901 initial_db = self.trees[myroot]["vartree"].dbapi
1902 final_db = self.mydbapi[myroot]
1903 blocked_initial = initial_db.match(mydep)
1904 blocked_final = final_db.match(mydep)
1905 if not blocked_initial and not blocked_final:
1906 del self.blocker_parents[blocker]
1908 blocked_slots_initial = {}
1909 blocked_slots_final = {}
1910 for cpv in blocked_initial:
1911 blocked_slots_initial[cpv] = \
1912 "%s:%s" % (portage.dep_getkey(cpv),
1913 initial_db.aux_get(cpv, ["SLOT"])[0])
1914 for cpv in blocked_final:
1915 blocked_slots_final[cpv] = \
1916 "%s:%s" % (portage.dep_getkey(cpv),
1917 final_db.aux_get(cpv, ["SLOT"])[0])
1918 blocked_slots_final_values = set(blocked_slots_final.itervalues())
1919 for parent in list(self.blocker_parents[blocker]):
1920 ptype, proot, pcpv, pstatus = parent
1921 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1922 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1923 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1924 parent_static = pslot_atom not in modified_slots[proot]
1925 unresolved_blocks = False
1926 depends_on_order = set()
1927 for cpv in blocked_initial:
1928 slot_atom = blocked_slots_initial[cpv]
1929 if slot_atom == pslot_atom:
1930 # The parent blocks an initial package in the same
1931 # slot as itself. The merge/nomerge status of neither
1932 # node matters. In any case, this particular block is
1933 # automatically resolved.
1935 if parent_static and \
1936 slot_atom not in modified_slots[myroot]:
1937 # This blocker will be handled the next time that a
1938 # merge of either package is triggered.
1940 if pstatus == "merge" and \
1941 slot_atom not in blocked_slots_final_values:
1942 upgrade_matches = final_db.match(slot_atom)
1944 # Apparently an upgrade may be able to invalidate
1947 self.pkg_node_map[proot][upgrade_matches[0]]
1948 depends_on_order.add(upgrade_node)
1950 # None of the above blocker resolutions techniques apply,
1951 # so apparently this one is unresolvable.
1952 unresolved_blocks = True
1953 for cpv in blocked_final:
1954 slot_atom = blocked_slots_final[cpv]
1955 if slot_atom == pslot_atom:
1956 # The parent blocks itself, so the merge order does not
1957 # need to be enforced.
1959 if parent_static and \
1960 slot_atom not in modified_slots[myroot]:
1961 # This blocker will be handled the next time that a
1962 # merge of either package is triggered.
1964 # None of the above blocker resolutions techniques apply,
1965 # so apparently this one is unresolvable.
1966 unresolved_blocks = True
1967 if not unresolved_blocks and depends_on_order:
1968 for node in depends_on_order:
1969 # Enforce correct merge order with a hard dep.
1970 self.digraph.addnode(node, parent,
1971 priority=DepPriority(buildtime=True))
1972 # Count references to this blocker so that it can be
1973 # invalidated after nodes referencing it have been
1975 self.blocker_digraph.addnode(node, blocker)
1976 if not unresolved_blocks and not depends_on_order:
1977 self.blocker_parents[blocker].remove(parent)
1978 if not self.blocker_parents[blocker]:
1979 del self.blocker_parents[blocker]
1980 # Validate blockers that depend on merge order.
1981 if not self.blocker_digraph.empty():
1983 if self._slot_collision_info:
1984 # The user is only notified of a slot collision if there are no
1985 # unresolvable blocks.
1986 for x in self.altlist():
1987 if x[0] == "blocks":
1989 self._show_slot_collision_notice(self._slot_collision_info[0])
1990 if not self._accept_collisions():
1994 def _accept_collisions(self):
1996 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
1997 if x in self.myopts:
2002 def _merge_order_bias(self, mygraph):
2003 """Order nodes from highest to lowest overall reference count for
2004 optimal leaf node selection."""
2006 for node in mygraph.order:
2007 node_info[node] = len(mygraph.parent_nodes(node))
2008 def cmp_merge_preference(node1, node2):
2009 return node_info[node2] - node_info[node1]
2010 mygraph.order.sort(cmp_merge_preference)
2012 def altlist(self, reversed=False):
2013 if reversed in self._altlist_cache:
2014 return self._altlist_cache[reversed][:]
2016 retlist = self.altlist()
2018 self._altlist_cache[reversed] = retlist[:]
2020 mygraph=self.digraph.copy()
2021 self._merge_order_bias(mygraph)
2022 myblockers = self.blocker_digraph.copy()
2024 circular_blocks = False
2028 get_nodes = mygraph.root_nodes
2030 get_nodes = mygraph.leaf_nodes
2031 for cpv, node in self.pkg_node_map["/"].iteritems():
2032 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
2033 asap_nodes.append(node)
2035 ignore_priority_range = [None]
2036 ignore_priority_range.extend(
2037 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2038 tree_mode = "--tree" in self.myopts
2039 while not mygraph.empty():
2040 ignore_priority = None
2043 """ASAP nodes are merged before their soft deps."""
2044 for node in asap_nodes:
2045 if not mygraph.contains(node):
2046 asap_nodes.remove(node)
2048 if not mygraph.child_nodes(node,
2049 ignore_priority=DepPriority.SOFT):
2051 asap_nodes.remove(node)
2054 for ignore_priority in ignore_priority_range:
2055 nodes = get_nodes(ignore_priority=ignore_priority)
2058 selected_nodes = None
2060 if ignore_priority <= DepPriority.SOFT:
2061 if ignore_priority is None and not tree_mode:
2062 # Greedily pop all of these nodes since no relationship
2063 # has been ignored. This optimization destroys --tree
2064 # output, so it's disabled in reversed mode.
2065 selected_nodes = nodes
2067 # For optimal merge order:
2068 # * Only pop one node.
2069 # * Removing a root node (node without a parent)
2070 # will not produce a leaf node, so avoid it.
2072 if mygraph.parent_nodes(node):
2073 # found a non-root node
2074 selected_nodes = [node]
2076 if not selected_nodes:
2077 # settle for a root node
2078 selected_nodes = [nodes[0]]
2080 """Recursively gather a group of nodes that RDEPEND on
2081 eachother. This ensures that they are merged as a group
2082 and get their RDEPENDs satisfied as soon as possible."""
2083 def gather_deps(mergeable_nodes, selected_nodes, node):
2084 if node in selected_nodes:
2086 if node not in mergeable_nodes:
2088 selected_nodes.add(node)
2089 for child in mygraph.child_nodes(node,
2090 ignore_priority=DepPriority.SOFT):
2092 mergeable_nodes, selected_nodes, child):
2095 mergeable_nodes = set(nodes)
2097 selected_nodes = set()
2099 mergeable_nodes, selected_nodes, node):
2102 selected_nodes = None
2104 if not selected_nodes:
2105 if not myblockers.is_empty():
2106 """A blocker couldn't be circumnavigated while keeping all
2107 dependencies satisfied. The user will have to resolve this
2108 manually. This is a panic condition and thus the order
2109 doesn't really matter, so just pop a random node in order
2110 to avoid a circular dependency panic if possible."""
2111 if not circular_blocks:
2112 circular_blocks = True
2113 blocker_deps = myblockers.leaf_nodes()
2115 selected_nodes = [blocker_deps.pop()]
2117 if not selected_nodes:
2118 # No leaf nodes are available, so we have a circular
2119 # dependency panic situation. Reduce the noise level to a
2120 # minimum via repeated elimination of root nodes since they
2121 # have no parents and thus can not be part of a cycle.
2123 root_nodes = mygraph.root_nodes(
2124 ignore_priority=DepPriority.SOFT)
2127 for node in root_nodes:
2128 mygraph.remove(node)
2129 # Display the USE flags that are enabled on nodes that are part
2130 # of dependency cycles in case that helps the user decide to
2131 # disable some of them.
2133 tempgraph = mygraph.copy()
2134 while not tempgraph.empty():
2135 nodes = tempgraph.leaf_nodes()
2137 node = tempgraph.order[0]
2140 display_order.append(list(node))
2141 tempgraph.remove(node)
2142 display_order.reverse()
2143 self.myopts.pop("--quiet", None)
2144 self.myopts.pop("--verbose", None)
2145 self.myopts["--tree"] = True
2146 self.display(display_order)
2147 print "!!! Error: circular dependencies:"
2149 mygraph.debug_print()
2151 print "!!! Note that circular dependencies can often be avoided by temporarily"
2152 print "!!! disabling USE flags that trigger optional dependencies."
2155 for node in selected_nodes:
2156 retlist.append(list(node))
2157 mygraph.remove(node)
2158 if not reversed and not circular_blocks and myblockers.contains(node):
2159 """This node may have invalidated one or more blockers."""
2160 myblockers.remove(node)
2161 for blocker in myblockers.root_nodes():
2162 if not myblockers.child_nodes(blocker):
2163 myblockers.remove(blocker)
2164 del self.blocker_parents[blocker]
2167 """Blocker validation does not work with reverse mode,
2168 so self.altlist() should first be called with reverse disabled
2169 so that blockers are properly validated."""
2170 self.blocker_digraph = myblockers
2172 """ Add any unresolved blocks so that they can be displayed."""
2173 for blocker in self.blocker_parents:
2174 retlist.append(list(blocker))
2175 self._altlist_cache[reversed] = retlist[:]
2178 def xcreate(self,mode="system"):
2179 vardb = self.trees[self.target_root]["vartree"].dbapi
2180 portdb = self.trees[self.target_root]["porttree"].dbapi
2181 bindb = self.trees[self.target_root]["bintree"].dbapi
2182 def visible(mylist):
2183 matches = portdb.gvisible(portdb.visible(mylist))
2184 return [x for x in mylist \
2185 if x in matches or not portdb.cpv_exists(x)]
2186 world_problems = False
2188 mylist = getlist(self.settings, "system")
2191 worldlist = getlist(self.settings, "world")
2192 mylist = getlist(self.settings, "system")
2193 worlddict=genericdict(worldlist)
2195 for x in worlddict.keys():
2196 if not portage.isvalidatom(x):
2197 world_problems = True
2198 elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
2199 world_problems = True
2205 mykey = portage.dep_getkey(atom)
2207 newlist.append(atom)
2208 """Make sure all installed slots are updated when possible.
2209 Do this with --emptytree also, to ensure that all slots are
2212 for cpv in vardb.match(mykey):
2213 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2216 if "--usepkg" in self.myopts:
2217 mymatches = bindb.match(atom)
2218 if "--usepkgonly" not in self.myopts:
2219 mymatches = visible(mymatches)
2220 best_pkg = portage.best(mymatches)
2222 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2223 best_pkgs.append(("binary", best_pkg, best_slot))
2224 if "--usepkgonly" not in self.myopts:
2225 best_pkg = portage.best(portdb.match(atom))
2227 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2228 best_pkgs.append(("ebuild", best_pkg, best_slot))
2230 best_pkg = portage.best([x[1] for x in best_pkgs])
2231 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2232 best_slot = best_pkgs[0][2]
2233 myslots.add(best_slot)
2234 if len(myslots) > 1:
2235 for myslot in myslots:
2236 myslot_atom = "%s:%s" % (mykey, myslot)
2238 if "--usepkgonly" not in self.myopts and \
2239 self.trees[self.target_root][
2240 "porttree"].dbapi.match(myslot_atom):
2242 elif "--usepkg" in self.myopts:
2243 mymatches = bindb.match(myslot_atom)
2244 if "--usepkgonly" not in self.myopts:
2245 mymatches = visible(mymatches)
2249 newlist.append(myslot_atom)
2253 for mydep in mylist:
2255 if not self.select_dep(
2256 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2257 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2260 missing_atoms.append(mydep)
2262 if not self.validate_blockers():
2266 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2267 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2270 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2271 " Ebuilds for the following packages are either all"
2272 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2273 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2277 def display(self,mylist,verbosity=None):
2278 if verbosity is None:
2279 verbosity = ("--quiet" in self.myopts and 1 or \
2280 "--verbose" in self.myopts and 3 or 2)
2285 counters = PackageCounters()
2287 if verbosity == 1 and "--verbose" not in self.myopts:
2288 def create_use_string(*args):
2291 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2293 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2294 alphabetical=("--alphabetical" in self.myopts)):
2302 cur_iuse = set(cur_iuse)
2303 enabled_flags = cur_iuse.intersection(cur_use)
2304 removed_iuse = set(old_iuse).difference(cur_iuse)
2305 any_iuse = cur_iuse.union(old_iuse)
2306 any_iuse = list(any_iuse)
2308 for flag in any_iuse:
2311 if flag in enabled_flags:
2313 if is_new or flag in old_use and all_flags:
2314 flag_str = red(flag)
2315 elif flag not in old_iuse:
2316 flag_str = yellow(flag) + "%*"
2317 elif flag not in old_use:
2318 flag_str = green(flag) + "*"
2319 elif flag in removed_iuse:
2321 flag_str = yellow("-" + flag) + "%"
2324 flag_str = "(" + flag_str + ")"
2325 removed.append(flag_str)
2328 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2329 flag_str = blue("-" + flag)
2330 elif flag not in old_iuse:
2331 flag_str = yellow("-" + flag)
2332 if flag not in iuse_forced:
2334 elif flag in old_use:
2335 flag_str = green("-" + flag) + "*"
2337 if flag in iuse_forced:
2338 flag_str = "(" + flag_str + ")"
2340 enabled.append(flag_str)
2342 disabled.append(flag_str)
2345 ret = " ".join(enabled)
2347 ret = " ".join(enabled + disabled + removed)
2349 ret = '%s="%s" ' % (name, ret)
2353 # FIXME: account for the possibility of different overlays in
2354 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2355 overlays = self.settings["PORTDIR_OVERLAY"].split()
2356 overlays_real = [os.path.realpath(t) \
2357 for t in self.settings["PORTDIR_OVERLAY"].split()]
2361 mygraph = self._parent_child_digraph
2365 if "blocks" == x[0]:
2366 display_list.append((x, 0, True))
2368 graph_key = tuple(x)
2369 if "--tree" in self.myopts:
2370 depth = len(tree_nodes)
2371 while depth and graph_key not in \
2372 mygraph.child_nodes(tree_nodes[depth-1]):
2375 tree_nodes = tree_nodes[:depth]
2376 tree_nodes.append(graph_key)
2377 display_list.append((x, depth, True))
2379 traversed_nodes = set() # prevent endless circles
2380 traversed_nodes.add(graph_key)
2381 def add_parents(current_node, ordered):
2382 parent_nodes = mygraph.parent_nodes(current_node)
2384 child_nodes = set(mygraph.child_nodes(current_node))
2385 selected_parent = None
2386 # First, try to avoid a direct cycle.
2387 for node in parent_nodes:
2388 if node not in traversed_nodes and \
2389 node not in child_nodes:
2390 selected_parent = node
2392 if not selected_parent:
2393 # A direct cycle is unavoidable.
2394 for node in parent_nodes:
2395 if node not in traversed_nodes:
2396 selected_parent = node
2399 traversed_nodes.add(selected_parent)
2400 add_parents(selected_parent, False)
2401 display_list.append((list(current_node),
2402 len(tree_nodes), ordered))
2403 tree_nodes.append(current_node)
2405 add_parents(graph_key, True)
2407 display_list.append((x, depth, True))
2408 mylist = display_list
2410 last_merge_depth = 0
2411 for i in xrange(len(mylist)-1,-1,-1):
2412 graph_key, depth, ordered = mylist[i]
2413 if not ordered and depth == 0 and i > 0 \
2414 and graph_key == mylist[i-1][0] and \
2415 mylist[i-1][1] == 0:
2416 # An ordered node got a consecutive duplicate when the tree was
2420 if "blocks" == graph_key[0]:
2422 if ordered and graph_key[-1] != "nomerge":
2423 last_merge_depth = depth
2425 if depth >= last_merge_depth or \
2426 i < len(mylist) - 1 and \
2427 depth >= mylist[i+1][1]:
2430 display_overlays=False
2431 # files to fetch list - avoids counting a same file twice
2432 # in size display (verbose mode)
2434 for mylist_index in xrange(len(mylist)):
2435 x, depth, ordered = mylist[mylist_index]
2439 portdb = self.trees[myroot]["porttree"].dbapi
2440 bindb = self.trees[myroot]["bintree"].dbapi
2441 vardb = self.trees[myroot]["vartree"].dbapi
2442 vartree = self.trees[myroot]["vartree"]
2443 pkgsettings = self.pkgsettings[myroot]
2448 addl=""+red("B")+" "+fetch+" "
2450 counters.blocks += 1
2451 resolved = portage.key_expand(
2452 pkg_key, mydb=vardb, settings=pkgsettings)
2453 if "--columns" in self.myopts and "--quiet" in self.myopts:
2454 addl = addl + " " + red(resolved)
2456 addl = "[blocks " + addl + "] " + red(resolved)
2457 block_parents = self.blocker_parents[tuple(x)]
2458 block_parents = set([pnode[2] for pnode in block_parents])
2459 block_parents = ", ".join(block_parents)
2461 addl += bad(" (\"%s\" is blocking %s)") % \
2462 (pkg_key, block_parents)
2464 addl += bad(" (is blocking %s)") % block_parents
2465 blockers.append(addl)
2467 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2468 binary_package = True
2469 if "ebuild" == pkg_type:
2470 if "merge" == x[3] or \
2471 not vartree.dbapi.cpv_exists(pkg_key):
2472 """An ebuild "merge" node or a --onlydeps "nomerge"
2474 binary_package = False
2475 pkgsettings.setcpv(pkg_key, mydb=portdb)
2476 if pkg_key not in self.useFlags[myroot]:
2477 self.useFlags[myroot][pkg_key] = \
2478 pkgsettings["USE"].split()
2480 # An ebuild "nomerge" node, so USE come from the vardb.
2481 mydbapi = vartree.dbapi
2482 if pkg_key not in self.useFlags[myroot]:
2483 """If this is a --resume then the USE flags need to be
2484 fetched from the appropriate locations here."""
2485 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2486 pkg_key, ["USE"])[0].split()
2488 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2489 "fetch" in portdb.aux_get(
2490 x[2], ["RESTRICT"])[0].split():
2493 counters.restrict_fetch += 1
2494 if portdb.fetch_check(
2495 pkg_key, self.useFlags[myroot][pkg_key]):
2498 counters.restrict_fetch_satisfied += 1
2500 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2501 #param is used for -u, where you still *do* want to see when something is being upgraded.
2503 if vardb.cpv_exists(pkg_key):
2504 addl=" "+yellow("R")+fetch+" "
2505 if x[3] != "nomerge":
2507 counters.reinst += 1
2508 elif vardb.match(portage.dep_getkey(pkg_key)):
2509 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2510 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2511 portage.pkgsplit(x[2])[0])
2512 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2513 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2515 myoldbest=portage.best(myinslotlist)
2517 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2519 addl+=turquoise("U")+blue("D")
2521 counters.downgrades += 1
2524 addl+=turquoise("U")+" "
2526 counters.upgrades += 1
2528 # New slot, mark it new.
2529 addl=" "+green("NS")+fetch+" "
2531 counters.newslot += 1
2533 if "--changelog" in self.myopts:
2534 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2535 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2536 inst_matches = vardb.match(slot_atom)
2538 changelogs.extend(self.calc_changelog(
2539 portdb.findname(pkg_key),
2540 inst_matches[0], pkg_key))
2542 addl=" "+green("N")+" "+fetch+" "
2548 if pkg_key in self.useFlags[myroot]:
2550 cur_iuse = list(filter_iuse_defaults(
2551 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2553 forced_flags = set()
2554 if not binary_package:
2555 forced_flags.update(pkgsettings.useforce)
2556 forced_flags.update(pkgsettings.usemask)
2558 cur_iuse = portage.unique_array(cur_iuse)
2560 cur_use = self.useFlags[myroot][pkg_key]
2561 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2567 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2568 old_iuse, old_use = \
2569 self.trees[x[1]]["vartree"].dbapi.aux_get(
2570 pkg, ["IUSE", "USE"])
2571 old_iuse = list(set(
2572 filter_iuse_defaults(old_iuse.split())))
2574 old_use = old_use.split()
2581 old_use = [flag for flag in old_use if flag in old_iuse]
2583 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2585 use_expand.reverse()
2586 use_expand_hidden = \
2587 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2589 def map_to_use_expand(myvals, forcedFlags=False):
2592 for exp in use_expand:
2595 for val in myvals[:]:
2596 if val.startswith(exp.lower()+"_"):
2597 if val in forced_flags:
2598 forced[exp].add(val[len(exp)+1:])
2599 ret[exp].append(val[len(exp)+1:])
2602 forced["USE"] = [val for val in myvals \
2603 if val in forced_flags]
2604 for exp in use_expand_hidden:
2611 cur_iuse_map, iuse_forced = \
2612 map_to_use_expand(cur_iuse, forcedFlags=True)
2613 cur_use_map = map_to_use_expand(cur_use)
2614 old_iuse_map = map_to_use_expand(old_iuse)
2615 old_use_map = map_to_use_expand(old_use)
2618 use_expand.insert(0, "USE")
2620 for key in use_expand:
2621 if key in use_expand_hidden:
2623 verboseadd += create_use_string(key.upper(),
2624 cur_iuse_map[key], iuse_forced[key],
2625 cur_use_map[key], old_iuse_map[key],
2626 old_use_map[key], is_new)
2631 if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
2633 myfilesdict = portdb.getfetchsizes(pkg_key,
2634 useflags=self.useFlags[myroot][pkg_key],
2636 except portage.exception.InvalidDependString, e:
2637 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2638 show_invalid_depstring_notice(x, src_uri, str(e))
2641 if myfilesdict is None:
2642 myfilesdict="[empty/missing/bad digest]"
2644 for myfetchfile in myfilesdict.keys():
2645 if myfetchfile not in myfetchlist:
2646 mysize+=myfilesdict[myfetchfile]
2647 myfetchlist.append(myfetchfile)
2648 counters.totalsize += mysize
2649 verboseadd+=format_size(mysize)+" "
2652 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2653 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2654 file_name = portdb.findname(pkg_key)
2655 if file_name: # It might not exist in the tree
2656 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2657 if (overlays_real.count(dir_name)>0):
2658 verboseadd+=teal("["+str(overlays_real.index(
2659 os.path.normpath(dir_name))+1)+"]")+" "
2660 display_overlays=True
2662 verboseadd += "[No ebuild?]"
2664 xs=portage.pkgsplit(x[2])
2671 if "COLUMNWIDTH" in self.settings:
2673 mywidth = int(self.settings["COLUMNWIDTH"])
2674 except ValueError, e:
2675 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2677 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2678 self.settings["COLUMNWIDTH"], noiselevel=-1)
2683 indent = " " * depth
2686 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2687 if myoldbest[-3:]=="-r0":
2688 myoldbest=myoldbest[:-3]
2689 myoldbest=blue("["+myoldbest+"]")
2694 if "--columns" in self.myopts:
2695 if "--quiet" in self.myopts:
2696 myprint=addl+" "+indent+darkgreen(xs[0])
2697 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2698 myprint=myprint+myoldbest
2699 myprint=myprint+darkgreen("to "+x[1])
2701 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2702 if (newlp-nc_len(myprint)) > 0:
2703 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2704 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2705 if (oldlp-nc_len(myprint)) > 0:
2706 myprint=myprint+" "*(oldlp-nc_len(myprint))
2707 myprint=myprint+myoldbest
2708 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2710 if x[-1] == "nomerge" or not ordered:
2711 myprint = darkblue("[nomerge ] ")
2713 myprint = "[" + pkg_type + " " + addl + "] "
2714 myprint += indent + darkgreen(pkg_key) + " " + \
2715 myoldbest + darkgreen("to " + myroot) + " " + \
2718 if "--columns" in self.myopts:
2719 if "--quiet" in self.myopts:
2720 myprint=addl+" "+indent+darkgreen(xs[0])
2721 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2722 myprint=myprint+myoldbest
2724 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2725 if (newlp-nc_len(myprint)) > 0:
2726 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2727 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2728 if (oldlp-nc_len(myprint)) > 0:
2729 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2730 myprint=myprint+myoldbest+" "+verboseadd
2732 if x[-1] == "nomerge" or not ordered:
2733 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2735 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2738 mysplit = portage.pkgsplit(x[2])
2739 if "--tree" not in self.myopts and mysplit and \
2740 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2743 if mysplit[2] == "r0":
2744 myversion = mysplit[1]
2746 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2748 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2749 if mylist_index < len(mylist) - 1 and \
2750 "livecvsportage" not in self.settings.features:
2751 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2752 p.append(colorize("WARN", " then resume the merge."))
2764 if overlays and display_overlays:
2765 print "Portage overlays:"
2769 print " "+teal("["+str(y)+"]"),x
2771 if "--changelog" in self.myopts:
2773 for revision,text in changelogs:
2774 print bold('*'+revision)
2775 sys.stdout.write(text)
2777 if self._pprovided_args:
2779 msg.append(bad("\nWARNING: "))
2780 if len(self._pprovided_args) > 1:
2781 msg.append("Requested packages will not be " + \
2782 "merged because they are listed in\n")
2784 msg.append("A requested package will not be " + \
2785 "merged because it is listed in\n")
2786 msg.append(" package.provided:\n\n")
2787 for arg in self._pprovided_args:
2788 msg.append(" " + arg + "\n")
2790 sys.stderr.write("".join(msg))
2792 def calc_changelog(self,ebuildpath,current,next):
2793 current = '-'.join(portage.catpkgsplit(current)[1:])
2794 if current.endswith('-r0'): current = current[:-3]
2795 next = '-'.join(portage.catpkgsplit(next)[1:])
2796 if next.endswith('-r0'): next = next[:-3]
2797 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2799 changelog = open(changelogpath).read()
2800 except SystemExit, e:
2801 raise # Needed else can't exit
2804 divisions = self.find_changelog_tags(changelog)
2805 #print 'XX from',current,'to',next
2806 #for div,text in divisions: print 'XX',div
2807 # skip entries for all revisions above the one we are about to emerge
2808 for i in range(len(divisions)):
2809 if divisions[i][0]==next:
2810 divisions = divisions[i:]
2812 # find out how many entries we are going to display
2813 for i in range(len(divisions)):
2814 if divisions[i][0]==current:
2815 divisions = divisions[:i]
2818 # couldnt find the current revision in the list. display nothing
2822 def find_changelog_tags(self,changelog):
2826 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2828 if release is not None:
2829 divs.append((release,changelog))
2831 if release is not None:
2832 divs.append((release,changelog[:match.start()]))
2833 changelog = changelog[match.end():]
2834 release = match.group(1)
2835 if release.endswith('.ebuild'):
2836 release = release[:-7]
2837 if release.endswith('-r0'):
2838 release = release[:-3]
2841 return self.outdatedpackages
2843 class PackageCounters(object):
2853 self.restrict_fetch = 0
2854 self.restrict_fetch_satisfied = 0
2857 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2860 myoutput.append("Total: %s package" % total_installs)
2861 if total_installs != 1:
2862 myoutput.append("s")
2863 if total_installs != 0:
2864 myoutput.append(" (")
2865 if self.upgrades > 0:
2866 details.append("%s upgrade" % self.upgrades)
2867 if self.upgrades > 1:
2869 if self.downgrades > 0:
2870 details.append("%s downgrade" % self.downgrades)
2871 if self.downgrades > 1:
2874 details.append("%s new" % self.new)
2875 if self.newslot > 0:
2876 details.append("%s in new slot" % self.newslot)
2877 if self.newslot > 1:
2880 details.append("%s reinstall" % self.reinst)
2884 details.append("%s block" % self.blocks)
2887 myoutput.append(", ".join(details))
2888 if total_installs != 0:
2889 myoutput.append(")")
2890 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2891 if self.restrict_fetch:
2892 myoutput.append("\nFetch Restriction: %s package" % \
2893 self.restrict_fetch)
2894 if self.restrict_fetch > 1:
2895 myoutput.append("s")
2896 if self.restrict_fetch_satisfied < self.restrict_fetch:
2897 myoutput.append(bad(" (%s unsatisfied)") % \
2898 (self.restrict_fetch - self.restrict_fetch_satisfied))
2899 return "".join(myoutput)
2901 class MergeTask(object):
2903 def __init__(self, settings, trees, myopts):
2904 self.settings = settings
2905 self.target_root = settings["ROOT"]
2907 self.myopts = myopts
2909 if settings.get("PORTAGE_DEBUG", "") == "1":
2911 self.pkgsettings = {}
2912 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2913 if self.target_root != "/":
2914 self.pkgsettings["/"] = \
2915 portage.config(clone=trees["/"]["vartree"].settings)
2917 def merge(self, mylist, favorites, mtimedb):
2920 ldpath_mtimes = mtimedb["ldpath"]
2921 xterm_titles = "notitles" not in self.settings.features
2923 #check for blocking dependencies
2924 if "--fetchonly" not in self.myopts and \
2925 "--fetch-all-uri" not in self.myopts and \
2926 "--buildpkgonly" not in self.myopts:
2929 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2930 print "!!! the two packages cannot be installed on the same system together."
2931 print "!!! Please use 'emerge --pretend' to determine blockers."
2932 if "--quiet" not in self.myopts:
2933 show_blocker_docs_link()
2936 # Verify all the manifests now so that the user is notified of failure
2937 # as soon as possible.
2938 if "--fetchonly" not in self.myopts and \
2939 "--fetch-all-uri" not in self.myopts and \
2940 len(mylist) > 1 and \
2941 "strict" in self.settings.features:
2942 shown_verifying_msg = False
2944 for myroot, pkgsettings in self.pkgsettings.iteritems():
2945 quiet_config = portage.config(clone=pkgsettings)
2946 quiet_config["PORTAGE_QUIET"] = "1"
2947 quiet_config.backup_changes("PORTAGE_QUIET")
2948 quiet_settings[myroot] = quiet_config
2951 if x[0] != "ebuild" or x[-1] == "nomerge":
2953 if not shown_verifying_msg:
2954 shown_verifying_msg = True
2955 print ">>> Verifying ebuild Manifests..."
2956 mytype, myroot, mycpv, mystatus = x
2957 portdb = self.trees[myroot]["porttree"].dbapi
2958 quiet_config = quiet_settings[myroot]
2959 quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
2960 if not portage.digestcheck([], quiet_config, strict=True):
2962 del x, mytype, myroot, mycpv, mystatus, quiet_config
2963 del shown_verifying_msg, quiet_settings
2965 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
2966 mysysdict = genericdict(getlist(self.settings, "system"))
2967 if "--resume" in self.myopts:
2969 print colorize("GOOD", "*** Resuming merge...")
2970 emergelog(xterm_titles, " *** Resuming merge...")
2971 mymergelist=mtimedb["resume"]["mergelist"][:]
2972 if "--skipfirst" in self.myopts and mymergelist:
2973 del mtimedb["resume"]["mergelist"][0]
2976 validate_merge_list(self.trees, mymergelist)
2978 myfavs = portage.grabfile(
2979 os.path.join(self.target_root, portage.WORLD_FILE))
2980 myfavdict=genericdict(myfavs)
2981 for x in range(len(mylist)):
2982 if mylist[x][3]!="nomerge":
2983 # Add to the mergelist
2984 mymergelist.append(mylist[x])
2986 myfavkey=portage.cpv_getkey(mylist[x][2])
2987 if "--onlydeps" in self.myopts:
2989 # Add to the world file. Since we won't be able to later.
2990 if "--fetchonly" not in self.myopts and \
2991 myfavkey in favorites:
2992 #don't record if already in system profile or already recorded
2993 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
2994 #we don't have a favorites entry for this package yet; add one
2995 myfavdict[myfavkey]=myfavkey
2996 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
2997 if not ("--fetchonly" in self.myopts or \
2998 "--fetch-all-uri" in self.myopts or \
2999 "--pretend" in self.myopts):
3000 portage.write_atomic(
3001 os.path.join(self.target_root, portage.WORLD_FILE),
3002 "\n".join(myfavdict.values()))
3004 mtimedb["resume"]["mergelist"]=mymergelist[:]
3007 myfeat = self.settings.features[:]
3008 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3010 if "parallel-fetch" in myfeat and \
3011 not ("--pretend" in self.myopts or \
3012 "--fetch-all-uri" in self.myopts or \
3013 "--fetchonly" in self.myopts):
3014 if "distlocks" not in myfeat:
3016 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
3017 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
3019 elif len(mymergelist) > 1:
3020 print ">>> starting parallel fetching"
3021 fetch_log = "/var/log/emerge-fetch.log"
3022 logfile = open(fetch_log, "w")
3023 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3024 portage.util.apply_secpass_permissions(fetch_log,
3025 uid=portage.portage_uid, gid=portage.portage_gid,
3027 fetch_env = os.environ.copy()
3028 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3029 fetch_env["PORTAGE_NICENESS"] = "0"
3030 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3031 resume_opts = self.myopts.copy()
3032 # For automatic resume, we need to prevent
3033 # any of bad_resume_opts from leaking in
3034 # via EMERGE_DEFAULT_OPTS.
3035 resume_opts["--ignore-default-opts"] = True
3036 for myopt, myarg in resume_opts.iteritems():
3037 if myopt not in bad_resume_opts:
3039 fetch_args.append(myopt)
3041 fetch_args.append(myopt +"="+ myarg)
3042 portage.process.spawn(fetch_args, env=fetch_env,
3043 fd_pipes=fd_pipes, returnpid=True)
3044 logfile.close() # belongs to the spawned process
3045 del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3049 for x in mymergelist:
3054 portdb = self.trees[myroot]["porttree"].dbapi
3055 bindb = self.trees[myroot]["bintree"].dbapi
3056 vartree = self.trees[myroot]["vartree"]
3057 pkgsettings = self.pkgsettings[myroot]
3060 y = portdb.findname(pkg_key)
3061 if "--pretend" not in self.myopts:
3062 print "\n>>> Emerging (" + \
3063 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3064 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3065 colorize("GOOD", x[pkgindex]) + " to " + x[1]
3066 emergelog(xterm_titles, " >>> emerge ("+\
3067 str(mergecount)+" of "+str(len(mymergelist))+\
3068 ") "+x[pkgindex]+" to "+x[1])
3070 pkgsettings["EMERGE_FROM"] = x[0]
3071 pkgsettings.backup_changes("EMERGE_FROM")
3074 #buildsyspkg: Check if we need to _force_ binary package creation
3075 issyspkg = ("buildsyspkg" in myfeat) \
3076 and x[0] != "blocks" \
3077 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3078 and "--buildpkg" not in self.myopts
3079 if x[0] in ["ebuild","blocks"]:
3080 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3081 raise Exception, "Merging a blocker"
3082 elif "--fetchonly" in self.myopts or \
3083 "--fetch-all-uri" in self.myopts:
3084 if "--fetch-all-uri" in self.myopts:
3085 retval = portage.doebuild(y, "fetch", myroot,
3086 pkgsettings, self.edebug,
3087 "--pretend" in self.myopts, fetchonly=1,
3088 fetchall=1, mydbapi=portdb, tree="porttree")
3090 retval = portage.doebuild(y, "fetch", myroot,
3091 pkgsettings, self.edebug,
3092 "--pretend" in self.myopts, fetchonly=1,
3093 mydbapi=portdb, tree="porttree")
3094 if (retval is None) or retval:
3096 print "!!! Fetch for",y,"failed, continuing..."
3098 failed_fetches.append(pkg_key)
3101 portage.doebuild_environment(y, "setup", myroot,
3102 pkgsettings, self.edebug, 1, portdb)
3103 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3104 portage.util.ensure_dirs(os.path.dirname(catdir),
3105 uid=portage.portage_uid, gid=portage.portage_gid,
3107 builddir_lock = None
3110 catdir_lock = portage.locks.lockdir(catdir)
3111 portage.util.ensure_dirs(catdir,
3112 uid=portage.portage_uid, gid=portage.portage_gid,
3114 builddir_lock = portage.locks.lockdir(
3115 pkgsettings["PORTAGE_BUILDDIR"])
3117 portage.locks.unlockdir(catdir_lock)
3120 msg = " === (%s of %s) Cleaning (%s::%s)" % \
3121 (mergecount, len(mymergelist), pkg_key, y)
3122 short_msg = "emerge: (%s of %s) %s Clean" % \
3123 (mergecount, len(mymergelist), pkg_key)
3124 emergelog(xterm_titles, msg, short_msg=short_msg)
3125 retval = portage.doebuild(y, "clean", myroot,
3126 pkgsettings, self.edebug, cleanup=1,
3127 mydbapi=portdb, tree="porttree")
3128 if retval != os.EX_OK:
3130 if "--buildpkg" in self.myopts or issyspkg:
3132 print ">>> This is a system package, " + \
3133 "let's pack a rescue tarball."
3134 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3135 (mergecount, len(mymergelist), pkg_key, y)
3136 short_msg = "emerge: (%s of %s) %s Compile" % \
3137 (mergecount, len(mymergelist), pkg_key)
3138 emergelog(xterm_titles, msg, short_msg=short_msg)
3139 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3140 retval = portage.doebuild(y, "package", myroot,
3141 pkgsettings, self.edebug, mydbapi=portdb,
3143 if retval != os.EX_OK:
3145 bintree = self.trees[myroot]["bintree"]
3146 if bintree.populated:
3147 bintree.inject(pkg_key)
3148 if "--buildpkgonly" not in self.myopts:
3149 msg = " === (%s of %s) Merging (%s::%s)" % \
3150 (mergecount, len(mymergelist), pkg_key, y)
3151 short_msg = "emerge: (%s of %s) %s Merge" % \
3152 (mergecount, len(mymergelist), pkg_key)
3153 emergelog(xterm_titles, msg, short_msg=short_msg)
3154 retval = portage.merge(pkgsettings["CATEGORY"],
3155 pkgsettings["PF"], pkgsettings["D"],
3156 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3157 "build-info"), myroot, pkgsettings,
3158 myebuild=pkgsettings["EBUILD"],
3159 mytree="porttree", mydbapi=portdb,
3160 vartree=vartree, prev_mtimes=ldpath_mtimes)
3161 if retval != os.EX_OK:
3163 elif "noclean" not in pkgsettings.features:
3164 portage.doebuild(y, "clean", myroot,
3165 pkgsettings, self.edebug, mydbapi=portdb,
3168 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3169 (mergecount, len(mymergelist), pkg_key, y)
3170 short_msg = "emerge: (%s of %s) %s Compile" % \
3171 (mergecount, len(mymergelist), pkg_key)
3172 emergelog(xterm_titles, msg, short_msg=short_msg)
3173 retval = portage.doebuild(y, "merge", myroot,
3174 pkgsettings, self.edebug, vartree=vartree,
3175 mydbapi=portdb, tree="porttree",
3176 prev_mtimes=ldpath_mtimes)
3177 if retval != os.EX_OK:
3181 portage.locks.unlockdir(builddir_lock)
3184 # Lock catdir for removal if empty.
3185 catdir_lock = portage.locks.lockdir(catdir)
3191 if e.errno not in (errno.ENOENT,
3192 errno.ENOTEMPTY, errno.EEXIST):
3195 portage.locks.unlockdir(catdir_lock)
3197 elif x[0]=="binary":
3199 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3200 if "--getbinpkg" in self.myopts:
3203 if "distlocks" in pkgsettings.features and \
3204 os.access(pkgsettings["PKGDIR"], os.W_OK):
3205 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3206 tbz2_lock = portage.locks.lockfile(mytbz2,
3208 if self.trees[myroot]["bintree"].isremote(pkg_key):
3209 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3210 (mergecount, len(mymergelist), pkg_key, mytbz2)
3211 short_msg = "emerge: (%s of %s) %s Fetch" % \
3212 (mergecount, len(mymergelist), pkg_key)
3213 emergelog(xterm_titles, msg, short_msg=short_msg)
3214 if not self.trees[myroot]["bintree"].gettbz2(
3219 portage.locks.unlockfile(tbz2_lock)
3221 if "--fetchonly" in self.myopts or \
3222 "--fetch-all-uri" in self.myopts:
3225 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3226 emergelog(xterm_titles, " === ("+str(mergecount)+\
3227 " of "+str(len(mymergelist))+") Merging Binary ("+\
3228 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3229 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3231 vartree=self.trees[myroot]["vartree"],
3232 prev_mtimes=ldpath_mtimes)
3233 if retval != os.EX_OK:
3235 #need to check for errors
3236 if "--buildpkgonly" not in self.myopts:
3237 self.trees[x[1]]["vartree"].inject(x[2])
3238 myfavkey=portage.cpv_getkey(x[2])
3239 if "--fetchonly" not in self.myopts and \
3240 "--fetch-all-uri" not in self.myopts and \
3241 myfavkey in favorites:
3242 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3243 myfavdict=genericdict(myfavs)
3244 #don't record if already in system profile or already recorded
3245 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3246 #we don't have a favorites entry for this package yet; add one
3247 myfavdict[myfavkey]=myfavkey
3248 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3249 emergelog(xterm_titles, " === ("+\
3250 str(mergecount)+" of "+\
3251 str(len(mymergelist))+\
3252 ") Updating world file ("+x[pkgindex]+")")
3253 portage.write_atomic(
3254 os.path.join(myroot, portage.WORLD_FILE),
3255 "\n".join(myfavdict.values()))
3257 if "--pretend" not in self.myopts and \
3258 "--fetchonly" not in self.myopts and \
3259 "--fetch-all-uri" not in self.myopts:
3260 # Clean the old package that we have merged over top of it.
3261 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3262 xsplit=portage.pkgsplit(x[2])
3263 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3264 retval = unmerge(pkgsettings, self.myopts, vartree,
3265 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3267 emergelog(xterm_titles,
3268 " --- AUTOCLEAN: Nothing unmerged.")
3270 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3271 + " AUTOCLEAN is disabled. This can cause serious"
3272 + " problems due to overlapping packages.\n")
3274 # Figure out if we need a restart.
3275 mysplit=portage.pkgsplit(x[2])
3276 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3277 myver=mysplit[1]+"-"+mysplit[2]
3278 if myver[-3:]=='-r0':
3280 if (myver != portage.VERSION) and \
3281 "livecvsportage" not in self.settings.features:
3282 if len(mymergelist) > mergecount:
3283 emergelog(xterm_titles,
3284 " ::: completed emerge ("+ \
3285 str(mergecount)+" of "+ \
3286 str(len(mymergelist))+") "+ \
3288 emergelog(xterm_titles, " *** RESTARTING " + \
3289 "emerge via exec() after change of " + \
3291 del mtimedb["resume"]["mergelist"][0]
3293 portage.run_exitfuncs()
3294 mynewargv=[sys.argv[0],"--resume"]
3295 resume_opts = self.myopts.copy()
3296 # For automatic resume, we need to prevent
3297 # any of bad_resume_opts from leaking in
3298 # via EMERGE_DEFAULT_OPTS.
3299 resume_opts["--ignore-default-opts"] = True
3300 for myopt, myarg in resume_opts.iteritems():
3301 if myopt not in bad_resume_opts:
3303 mynewargv.append(myopt)
3305 mynewargv.append(myopt +"="+ myarg)
3306 # priority only needs to be adjusted on the first run
3307 os.environ["PORTAGE_NICENESS"] = "0"
3308 os.execv(mynewargv[0], mynewargv)
3310 if "--pretend" not in self.myopts and \
3311 "--fetchonly" not in self.myopts and \
3312 "--fetch-all-uri" not in self.myopts:
3313 if "noclean" not in self.settings.features:
3314 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3315 (mergecount, len(mymergelist), x[pkgindex])
3316 emergelog(xterm_titles, (" === (%s of %s) " + \
3317 "Post-Build Cleaning (%s::%s)") % \
3318 (mergecount, len(mymergelist), x[pkgindex], y),
3319 short_msg=short_msg)
3320 emergelog(xterm_titles, " ::: completed emerge ("+\
3321 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3324 # Unsafe for parallel merges
3325 del mtimedb["resume"]["mergelist"][0]
3326 # Commit after each merge so that --resume may still work in
3327 # in the event that portage is not allowed to exit normally
3328 # due to power failure, SIGKILL, etc...
3331 if "--pretend" not in self.myopts:
3332 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3334 # We're out of the loop... We're done. Delete the resume data.
3335 if mtimedb.has_key("resume"):
3336 del mtimedb["resume"]
3339 #by doing an exit this way, --fetchonly can continue to try to
3340 #fetch everything even if a particular download fails.
3341 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3343 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3344 "encountered. Please see above for details.\n\n")
3345 for cpv in failed_fetches:
3346 sys.stderr.write(" ")
3347 sys.stderr.write(cpv)
3348 sys.stderr.write("\n")
3349 sys.stderr.write("\n")
3355 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3356 ldpath_mtimes, autoclean=0):
3357 candidate_catpkgs=[]
3359 xterm_titles = "notitles" not in settings.features
3361 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3363 # At least the parent needs to exist for the lock file.
3364 portage.util.ensure_dirs(vdb_path)
3365 except portage.exception.PortageException:
3369 if os.access(vdb_path, os.W_OK):
3370 vdb_lock = portage.locks.lockdir(vdb_path)
3371 realsyslist = getlist(settings, "system")
3373 for x in realsyslist:
3374 mycp = portage.dep_getkey(x)
3375 if mycp in settings.getvirtuals():
3377 for provider in settings.getvirtuals()[mycp]:
3378 if vartree.dbapi.match(provider):
3379 providers.append(provider)
3380 if len(providers) == 1:
3381 syslist.extend(providers)
3383 syslist.append(mycp)
3385 mysettings = portage.config(clone=settings)
3387 if not unmerge_files or "world" in unmerge_files or \
3388 "system" in unmerge_files:
3389 if "unmerge"==unmerge_action:
3391 print bold("emerge unmerge") + " can only be used with " + \
3392 "specific package names, not with "+bold("world")+" or"
3393 print bold("system")+" targets."
3400 # process all arguments and add all
3401 # valid db entries to candidate_catpkgs
3403 if not unmerge_files or "world" in unmerge_files:
3404 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3405 elif "system" in unmerge_files:
3406 candidate_catpkgs.extend(getlist(settings, "system"))
3408 #we've got command-line arguments
3409 if not unmerge_files:
3410 print "\nNo packages to unmerge have been provided.\n"
3412 for x in unmerge_files:
3413 arg_parts = x.split('/')
3414 if x[0] not in [".","/"] and \
3415 arg_parts[-1][-7:] != ".ebuild":
3416 #possible cat/pkg or dep; treat as such
3417 candidate_catpkgs.append(x)
3418 elif unmerge_action in ["prune","clean"]:
3419 print "\n!!! Prune and clean do not accept individual" + \
3420 " ebuilds as arguments;\n skipping.\n"
3423 # it appears that the user is specifying an installed
3424 # ebuild and we're in "unmerge" mode, so it's ok.
3425 if not os.path.exists(x):
3426 print "\n!!! The path '"+x+"' doesn't exist.\n"
3429 absx = os.path.abspath(x)
3430 sp_absx = absx.split("/")
3431 if sp_absx[-1][-7:] == ".ebuild":
3433 absx = "/".join(sp_absx)
3435 sp_absx_len = len(sp_absx)
3437 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3438 vdb_len = len(vdb_path)
3440 sp_vdb = vdb_path.split("/")
3441 sp_vdb_len = len(sp_vdb)
3443 if not os.path.exists(absx+"/CONTENTS"):
3444 print "!!! Not a valid db dir: "+str(absx)
3447 if sp_absx_len <= sp_vdb_len:
3448 # The Path is shorter... so it can't be inside the vdb.
3451 print "\n!!!",x,"cannot be inside "+ \
3452 vdb_path+"; aborting.\n"
3455 for idx in range(0,sp_vdb_len):
3456 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3459 print "\n!!!", x, "is not inside "+\
3460 vdb_path+"; aborting.\n"
3463 print "="+"/".join(sp_absx[sp_vdb_len:])
3464 candidate_catpkgs.append(
3465 "="+"/".join(sp_absx[sp_vdb_len:]))
3468 if (not "--quiet" in myopts):
3470 if settings["ROOT"] != "/":
3471 print darkgreen(newline+ \
3472 ">>> Using system located in ROOT tree "+settings["ROOT"])
3473 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3474 not ("--quiet" in myopts):
3475 print darkgreen(newline+\
3476 ">>> These are the packages that would be unmerged:")
3480 for x in candidate_catpkgs:
3481 # cycle through all our candidate deps and determine
3482 # what will and will not get unmerged
3484 mymatch=localtree.dep_match(x)
3487 except ValueError, errpkgs:
3488 print "\n\n!!! The short ebuild name \"" + \
3489 x + "\" is ambiguous. Please specify"
3490 print "!!! one of the following fully-qualified " + \
3491 "ebuild names instead:\n"
3492 for i in errpkgs[0]:
3493 print " " + green(i)
3497 if not mymatch and x[0] not in "<>=~":
3498 #add a "=" if missing
3499 mymatch=localtree.dep_match("="+x)
3501 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3502 (x, unmerge_action), noiselevel=-1)
3504 mykey = portage.key_expand(
3506 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3507 if not pkgmap.has_key(mykey):
3508 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3509 if unmerge_action=="unmerge":
3511 if y not in pkgmap[mykey]["selected"]:
3512 pkgmap[mykey]["selected"].append(y)
3513 numselected=numselected+len(mymatch)
3516 #unmerge_action in ["prune", clean"]
3518 for mypkg in mymatch:
3519 if unmerge_action=="clean":
3520 myslot=localtree.getslot(mypkg)
3522 # since we're pruning, we don't care about slots
3523 # and put all the pkgs in together
3525 if not slotmap.has_key(myslot):
3527 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3528 for myslot in slotmap.keys():
3529 counterkeys=slotmap[myslot].keys()
3534 pkgmap[mykey]["protected"].append(
3535 slotmap[myslot][counterkeys[-1]])
3537 #be pretty and get them in order of merge:
3538 for ckey in counterkeys:
3539 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
3540 numselected=numselected+1
3541 # ok, now the last-merged package
3542 # is protected, and the rest are selected
3543 if global_unmerge and not numselected:
3544 portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
3548 portage.writemsg_stdout(
3549 "\n>>> No packages selected for removal by " + \
3550 unmerge_action + "\n")
3554 portage.locks.unlockdir(vdb_lock)
3555 for x in pkgmap.keys():
3556 for y in localtree.dep_match(x):
3557 if y not in pkgmap[x]["omitted"] and \
3558 y not in pkgmap[x]["selected"] and \
3559 y not in pkgmap[x]["protected"]:
3560 pkgmap[x]["omitted"].append(y)
3561 if global_unmerge and not pkgmap[x]["selected"]:
3562 #avoid cluttering the preview printout with stuff that isn't getting unmerged
3564 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
3565 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
3566 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
3567 if "--pretend" not in myopts and "--ask" not in myopts:
3568 countdown(int(settings["EMERGE_WARNING_DELAY"]),
3569 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3570 print "\n "+white(x)
3571 for mytype in ["selected","protected","omitted"]:
3572 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
3573 if pkgmap[x][mytype]:
3574 for mypkg in pkgmap[x][mytype]:
3575 mysplit=portage.catpkgsplit(mypkg)
3576 if mysplit[3]=="r0":
3577 myversion=mysplit[2]
3579 myversion=mysplit[2]+"-"+mysplit[3]
3580 if mytype=="selected":
3581 portage.writemsg_stdout(
3582 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
3584 portage.writemsg_stdout(
3585 colorize("GOOD", myversion + " "), noiselevel=-1)
3587 portage.writemsg_stdout("none", noiselevel=-1)
3588 portage.writemsg_stdout("\n", noiselevel=-1)
3590 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3591 " packages are slated for removal.\n")
3592 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
3593 " and " + colorize("GOOD", "'omitted'") + \
3594 " packages will not be removed.\n\n")
3596 if "--pretend" in myopts:
3597 #we're done... return
3599 if "--ask" in myopts:
3600 if userquery("Would you like to unmerge these packages?")=="No":
3601 # enter pretend mode for correct formatting of results
3602 myopts["--pretend"] = True
3607 #the real unmerging begins, after a short delay....
3609 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3611 for x in pkgmap.keys():
3612 for y in pkgmap[x]["selected"]:
3613 print ">>> Unmerging "+y+"..."
3614 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3615 mysplit=y.split("/")
3617 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3618 mysettings, unmerge_action not in ["clean","prune"],
3619 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3620 if retval != os.EX_OK:
3621 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3622 ebuild = vartree.dbapi.findname(y)
3623 show_unmerge_failure_message(y, ebuild, retval)
3626 clean_world(vartree.dbapi, y)
3627 emergelog(xterm_titles, " >>> unmerge success: "+y)
3630 def show_unmerge_failure_message(pkg, ebuild, retval):
3632 from formatter import AbstractFormatter, DumbWriter
3633 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3636 msg.append("A removal phase of the '%s' package " % pkg)
3637 msg.append("has failed with exit value %s. " % retval)
3638 msg.append("The problem occurred while executing ")
3639 msg.append("the ebuild located at '%s'. " % ebuild)
3640 msg.append("If necessary, manually remove the ebuild " )
3641 msg.append("in order to skip the execution of removal phases.")
3645 f.add_flowing_data(x)
3649 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3651 if os.path.exists("/usr/bin/install-info"):
3656 inforoot=normpath(root+z)
3657 if os.path.isdir(inforoot):
3658 infomtime = long(os.stat(inforoot).st_mtime)
3659 if inforoot not in prev_mtimes or \
3660 prev_mtimes[inforoot] != infomtime:
3661 regen_infodirs.append(inforoot)
3663 if not regen_infodirs:
3664 portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
3666 portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
3670 for inforoot in regen_infodirs:
3673 for filename in ("dir", "dir.gz", "dir.bz2"):
3674 file_path = os.path.join(inforoot, filename)
3676 os.rename(file_path, file_path + ".old")
3678 if e.errno != errno.ENOENT:
3682 if not os.path.isdir(inforoot):
3685 file_list = os.listdir(inforoot)
3688 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3690 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3691 existsstr="already exists, for file `"
3693 if re.search(existsstr,myso):
3694 # Already exists... Don't increment the count for this.
3696 elif myso[:44]=="install-info: warning: no info dir entry in ":
3697 # This info file doesn't contain a DIR-header: install-info produces this
3698 # (harmless) warning (the --quiet switch doesn't seem to work).
3699 # Don't increment the count for this.
3703 errmsg += myso + "\n"
3706 #update mtime so we can potentially avoid regenerating.
3707 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3710 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3713 print " "+green("*")+" Processed",icount,"info files."
3716 def post_emerge(settings, mtimedb, retval):
3718 Misc. things to run at the end of a merge session.
3726 @param settings: Configuration settings (typically portage.settings)
3727 @type settings: portage.config()
3728 @param mtimedb: The mtimeDB to store data needed across merge invocations
3729 @type mtimedb: MtimeDB class instance
3730 @param retval: Emerge's return value
3734 1. Calls sys.exit(retval)
3736 target_root = settings["ROOT"]
3737 info_mtimes = mtimedb["info"]
3739 # Load the most current variables from ${ROOT}/etc/profile.env
3741 settings.regenerate()
3744 config_protect = settings.get("CONFIG_PROTECT","").split()
3745 infodirs = settings.get("INFOPATH","").split(":") + \
3746 settings.get("INFODIR","").split(":")
3750 emergelog("notitles" not in settings.features,
3751 " *** exiting successfully.")
3753 if "noinfo" not in settings.features:
3754 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3756 chk_updated_cfg_files(target_root, config_protect)
3758 NEWS_PATH = os.path.join( "metadata", "news" )
3759 UNREAD_PATH = os.path.join( target_root, NEWS_LIB_PATH, 'news')
3760 porttree = portdbapi( porttree_root = settings["PORTDIR"], mysettings = settings )
3761 newsReaderDisplay = False
3763 for repo in porttree.getRepositories():
3764 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3766 print colorize("WARN", " * IMPORTANT:"),
3767 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3768 newsReaderDisplay = True
3770 if newsReaderDisplay:
3771 print colorize("WARN", " *"),
3772 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3778 def chk_updated_cfg_files(target_root, config_protect):
3780 #number of directories with some protect files in them
3782 for x in config_protect:
3783 x = os.path.join(target_root, x.lstrip(os.path.sep))
3785 mymode = os.lstat(x).st_mode
3788 if stat.S_ISDIR(mymode):
3789 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3791 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3792 os.path.split(x.rstrip(os.path.sep))
3793 a = commands.getstatusoutput(mycommand + \
3794 " ! -iname '.*~' ! -iname '.*.bak'")
3796 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3798 files = a[1].split()
3801 print colorize("WARN", " * IMPORTANT:"),
3802 if stat.S_ISDIR(mymode):
3803 print "%d config files in '%s' need updating." % \
3806 print "config file '%s' needs updating." % x
3809 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3810 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3812 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3814 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3815 Returns the number of unread (yet relevent) items.
3827 1. The number of unread but relevant news items.
3830 from portage.news import NewsManager
3831 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3832 return manager.getUnreadItems( repo_id, update=True )
3834 def is_valid_package_atom(x):
3836 testkey = portage.dep_getkey(x)
3837 except portage.exception.InvalidData:
3839 if testkey.startswith("null/"):
3840 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3845 return portage.isvalidatom(testatom)
3847 def validate_merge_list(trees, mergelist):
3848 """Validate the list to make sure all the packages are still available.
3849 This is needed for --resume."""
3850 for (pkg_type, myroot, pkg_key, action) in mergelist:
3851 if pkg_type == "binary" and \
3852 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3853 pkg_type == "ebuild" and \
3854 not trees[myroot]["porttree"].dbapi.xmatch(
3855 "match-all", "="+pkg_key):
3856 print red("!!! Error: The resume list contains packages that are no longer")
3857 print red("!!! available to be emerged. Please restart/continue")
3858 print red("!!! the merge operation manually.")
3861 def show_blocker_docs_link():
3863 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3864 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3866 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3869 def action_sync(settings, trees, mtimedb, myopts, myaction):
3870 xterm_titles = "notitles" not in settings.features
3871 emergelog(xterm_titles, " === sync")
3872 myportdir = settings.get("PORTDIR", None)
3874 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3876 if myportdir[-1]=="/":
3877 myportdir=myportdir[:-1]
3878 if not os.path.exists(myportdir):
3879 print ">>>",myportdir,"not found, creating it."
3880 os.makedirs(myportdir,0755)
3881 syncuri=settings["SYNC"].rstrip()
3883 updatecache_flg = False
3884 if myaction == "metadata":
3885 print "skipping sync"
3886 updatecache_flg = True
3887 tmpservertimestampfile = None
3888 elif syncuri[:8]=="rsync://":
3889 if not os.path.exists("/usr/bin/rsync"):
3890 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3891 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3897 if settings["PORTAGE_RSYNC_OPTS"] == "":
3898 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3900 "--recursive", # Recurse directories
3901 "--links", # Consider symlinks
3902 "--safe-links", # Ignore links outside of tree
3903 "--perms", # Preserve permissions
3904 "--times", # Preserive mod times
3905 "--compress", # Compress the data transmitted
3906 "--force", # Force deletion on non-empty dirs
3907 "--whole-file", # Don't do block transfers, only entire files
3908 "--delete", # Delete files that aren't in the master tree
3909 "--delete-after", # Delete only after everything else is done
3910 "--stats", # Show final statistics about what was transfered
3911 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3912 "--exclude=/distfiles", # Exclude distfiles from consideration
3913 "--exclude=/local", # Exclude local from consideration
3914 "--exclude=/packages", # Exclude packages from consideration
3915 "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
3919 # The below validation is not needed when using the above hardcoded
3922 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3923 rsync_opts.extend(settings["PORTAGE_RSYNC_OPTS"].split())
3925 for opt in ("--recursive", "--times"):
3926 if opt not in rsync_opts:
3927 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3928 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3929 rsync_opts.append(opt)
3931 for exclude in ("distfiles", "local", "packages"):
3932 opt = "--exclude=/%s" % exclude
3933 if opt not in rsync_opts:
3934 portage.writemsg(yellow("WARNING:") + \
3935 " adding required option %s not included in " % opt + \
3936 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3937 rsync_opts.append(opt)
3939 if settings["RSYNC_TIMEOUT"] != "":
3940 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3941 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3943 mytimeout = int(settings["RSYNC_TIMEOUT"])
3944 rsync_opts.append("--timeout=%d" % mytimeout)
3945 except ValueError, e:
3946 portage.writemsg("!!! %s\n" % str(e))
3948 # TODO: determine options required for official servers
3949 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
3951 def rsync_opt_startswith(opt_prefix):
3952 for x in rsync_opts:
3953 if x.startswith(opt_prefix):
3957 if not rsync_opt_startswith("--timeout="):
3958 rsync_opts.append("--timeout=%d" % mytimeout)
3960 for opt in ("--compress", "--whole-file"):
3961 if opt not in rsync_opts:
3962 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3963 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3964 rsync_opts.append(opt)
3966 if "--quiet" in myopts:
3967 rsync_opts.append("--quiet") # Shut up a lot
3969 rsync_opts.append("--verbose") # Print filelist
3971 if "--verbose" in myopts:
3972 rsync_opts.append("--progress") # Progress meter for each file
3974 if "--debug" in myopts:
3975 rsync_opts.append("--checksum") # Force checksum on all files
3977 if settings["RSYNC_EXCLUDEFROM"] != "":
3978 portage.writemsg(yellow("WARNING:") + \
3979 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
3980 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3981 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
3982 rsync_opts.append("--exclude-from=%s" % \
3983 settings["RSYNC_EXCLUDEFROM"])
3985 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
3986 " but file does not exist.\n")
3988 if settings["RSYNC_RATELIMIT"] != "":
3989 portage.writemsg(yellow("WARNING:") + \
3990 " usage of RSYNC_RATELIMIT is deprecated, use " + \
3991 "PORTAGE_RSYNC_EXTRA_OPTS instead")
3992 rsync_opts.append("--bwlimit=%s" % \
3993 settings["RSYNC_RATELIMIT"])
3995 # Real local timestamp file.
3996 servertimestampfile = os.path.join(
3997 myportdir, "metadata", "timestamp.chk")
3998 # Temporary file for remote server timestamp comparison.
3999 tmpservertimestampfile = os.path.join(
4000 settings["PORTAGE_TMPDIR"], "timestamp.chk")
4002 content = portage.util.grabfile(servertimestampfile)
4006 mytimestamp = time.mktime(time.strptime(content[0],
4007 "%a, %d %b %Y %H:%M:%S +0000"))
4008 except (OverflowError, ValueError):
4013 if settings.has_key("RSYNC_RETRIES"):
4014 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
4015 maxretries=int(settings["RSYNC_RETRIES"])
4017 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
4018 except SystemExit, e:
4019 raise # Needed else can't exit
4021 maxretries=3 #default number of retries
4024 user_name, hostname, port = re.split(
4025 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
4028 if user_name is None:
4030 updatecache_flg=True
4031 all_rsync_opts = set(rsync_opts)
4032 all_rsync_opts.update(
4033 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
4034 family = socket.AF_UNSPEC
4035 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
4036 family = socket.AF_INET
4037 elif socket.has_ipv6 and \
4038 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
4039 family = socket.AF_INET6
4046 for addrinfo in socket.getaddrinfo(
4047 hostname, None, family, socket.SOCK_STREAM):
4048 if addrinfo[0] == socket.AF_INET6:
4049 # IPv6 addresses need to be enclosed in square brackets
4050 ips.append("[%s]" % addrinfo[4][0])
4052 ips.append(addrinfo[4][0])
4053 from random import shuffle
4055 except SystemExit, e:
4056 raise # Needed else can't exit
4057 except Exception, e:
4058 print "Notice:",str(e)
4063 dosyncuri = syncuri.replace(
4064 "//" + user_name + hostname + port + "/",
4065 "//" + user_name + ips[0] + port + "/", 1)
4066 except SystemExit, e:
4067 raise # Needed else can't exit
4068 except Exception, e:
4069 print "Notice:",str(e)
4073 if "--ask" in myopts:
4074 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
4079 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
4080 if "--quiet" not in myopts:
4081 print ">>> Starting rsync with "+dosyncuri+"..."
4083 emergelog(xterm_titles,
4084 ">>> Starting retry %d of %d with %s" % \
4085 (retries,maxretries,dosyncuri))
4086 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
4088 if mytimestamp != 0 and "--quiet" not in myopts:
4089 print ">>> Checking server timestamp ..."
4091 rsynccommand = " ".join(["/usr/bin/rsync", " ".join(rsync_opts),
4092 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
4094 if "--debug" in myopts:
4099 # Even if there's no timestamp available locally, fetch the
4100 # timestamp anyway as an initial probe to verify that the server is
4101 # responsive. This protects us from hanging indefinitely on a
4102 # connection attempt to an unresponsive server which rsync's
4103 # --timeout option does not prevent.
4105 mycommand = rsynccommand.split()
4106 mycommand.append(dosyncuri.rstrip("/") + \
4107 "/metadata/timestamp.chk")
4108 mycommand.append(tmpservertimestampfile)
4112 def timeout_handler(signum, frame):
4113 raise portage.exception.PortageException("timed out")
4114 signal.signal(signal.SIGALRM, timeout_handler)
4115 # Timeout here in case the server is unresponsive. The
4116 # --timeout rsync option doesn't apply to the initial
4117 # connection attempt.
4120 mypids.extend(portage.process.spawn(
4121 mycommand, env=settings.environ(), returnpid=True))
4122 exitcode = os.waitpid(mypids[0], 0)[1]
4123 content = portage.grabfile(tmpservertimestampfile)
4127 os.unlink(tmpservertimestampfile)
4130 except portage.exception.PortageException, e:
4134 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
4135 os.kill(mypids[0], signal.SIGTERM)
4136 os.waitpid(mypids[0], 0)
4137 # This is the same code rsync uses for timeout.
4140 if exitcode != os.EX_OK:
4142 exitcode = (exitcode & 0xff) << 8
4144 exitcode = exitcode >> 8
4146 portage.process.spawned_pids.remove(mypids[0])
4149 servertimestamp = time.mktime(time.strptime(
4150 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
4151 except (OverflowError, ValueError):
4153 del mycommand, mypids, content
4154 if exitcode == os.EX_OK:
4155 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4156 emergelog(xterm_titles,
4157 ">>> Cancelling sync -- Already current.")
4160 print ">>> Timestamps on the server and in the local repository are the same."
4161 print ">>> Cancelling all further sync action. You are already up to date."
4163 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4167 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4168 emergelog(xterm_titles,
4169 ">>> Server out of date: %s" % dosyncuri)
4172 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4174 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4177 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4179 mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
4180 mycommand = mycommand.split()
4181 exitcode = portage.process.spawn(mycommand,
4182 env=settings.environ())
4183 if exitcode in [0,1,3,4,11,14,20,21]:
4185 elif exitcode in [1,3,4,11,14,20,21]:
4188 # Code 2 indicates protocol incompatibility, which is expected
4189 # for servers with protocol < 29 that don't support
4190 # --prune-empty-directories. Retry for a server that supports
4191 # at least rsync protocol version 29 (>=rsync-2.6.4).
4196 if retries<=maxretries:
4197 print ">>> Retrying..."
4202 updatecache_flg=False
4206 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4210 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4211 print darkred("!!!")+green(" that your SYNC statement is proper.")
4212 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4214 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4215 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4216 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4217 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4218 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4220 print darkred("!!!")+green(" Rsync was killed before it finished.")
4222 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4223 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4224 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4225 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4226 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4229 elif syncuri[:6]=="cvs://":
4230 if not os.path.exists("/usr/bin/cvs"):
4231 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4232 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4235 cvsdir=os.path.dirname(myportdir)
4236 if not os.path.exists(myportdir+"/CVS"):
4238 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4239 if os.path.exists(cvsdir+"/gentoo-x86"):
4240 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4245 if e.errno != errno.ENOENT:
4247 "!!! existing '%s' directory; exiting.\n" % myportdir)
4250 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4251 print "!!! cvs checkout error; exiting."
4253 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4256 print ">>> Starting cvs update with "+syncuri+"..."
4257 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4258 myportdir, settings, free=1)
4259 if retval != os.EX_OK:
4263 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4266 if updatecache_flg and \
4267 myaction != "metadata" and \
4268 "metadata-transfer" not in settings.features:
4269 updatecache_flg = False
4271 # Reload the whole config from scratch.
4272 settings, trees, mtimedb = load_emerge_config(trees=trees)
4273 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4275 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4276 action_metadata(settings, portdb, myopts)
4278 if portage.global_updates(settings, trees, mtimedb["updates"]):
4280 # Reload the whole config from scratch.
4281 settings, trees, mtimedb = load_emerge_config(trees=trees)
4282 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4284 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4285 mypvs = portage.best(
4286 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4288 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4290 if myaction != "metadata":
4291 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4292 retval = portage.process.spawn(
4293 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4294 dosyncuri], env=settings.environ())
4295 if retval != os.EX_OK:
4296 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4298 if(mybestpv != mypvs) and not "--quiet" in myopts:
4300 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4301 print red(" * ")+"that you update portage now, before any other packages are updated."
4302 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4303 print red(" * ")+"configuration files."
4304 print red(" * ")+"To update portage, run 'emerge portage'."
4307 def action_metadata(settings, portdb, myopts):
4308 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4309 old_umask = os.umask(0002)
4310 cachedir = os.path.normpath(settings.depcachedir)
4311 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4312 "/lib", "/opt", "/proc", "/root", "/sbin",
4313 "/sys", "/tmp", "/usr", "/var"]:
4314 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4315 "ROOT DIRECTORY ON YOUR SYSTEM."
4316 print >> sys.stderr, \
4317 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4319 if not os.path.exists(cachedir):
4322 ec = portage.eclass_cache.cache(portdb.porttree_root)
4323 myportdir = os.path.realpath(settings["PORTDIR"])
4324 cm = settings.load_best_module("portdbapi.metadbmodule")(
4325 myportdir, "metadata/cache", portage.auxdbkeys[:])
4327 from portage.cache import util
4329 class percentage_noise_maker(util.quiet_mirroring):
4330 def __init__(self, dbapi):
4332 self.cp_all = dbapi.cp_all()
4333 l = len(self.cp_all)
4334 self.call_update_min = 100000000
4335 self.min_cp_all = l/100.0
4340 for x in self.cp_all:
4342 if self.count > self.min_cp_all:
4343 self.call_update_min = 0
4345 for y in self.dbapi.cp_list(x):
4347 self.call_update_mine = 0
4349 def update(self, *arg):
4350 try: self.pstr = int(self.pstr) + 1
4351 except ValueError: self.pstr = 1
4352 sys.stdout.write("%s%i%%" % \
4353 ("\b" * (len(str(self.pstr))+1), self.pstr))
4355 self.call_update_min = 10000000
4357 def finish(self, *arg):
4358 sys.stdout.write("\b\b\b\b100%\n")
4361 if "--quiet" in myopts:
4362 def quicky_cpv_generator(cp_all_list):
4363 for x in cp_all_list:
4364 for y in portdb.cp_list(x):
4366 source = quicky_cpv_generator(portdb.cp_all())
4367 noise_maker = portage.cache.util.quiet_mirroring()
4369 noise_maker = source = percentage_noise_maker(portdb)
4370 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4371 eclass_cache=ec, verbose_instance=noise_maker)
4376 def action_regen(settings, portdb):
4377 xterm_titles = "notitles" not in settings.features
4378 emergelog(xterm_titles, " === regen")
4379 #regenerate cache entries
4380 print "Regenerating cache entries... "
4382 os.close(sys.stdin.fileno())
4383 except SystemExit, e:
4384 raise # Needed else can't exit
4388 mynodes = portdb.cp_all()
4389 from portage.cache.cache_errors import CacheError
4391 for mytree in portdb.porttrees:
4393 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4394 except CacheError, e:
4395 print "\n error listing cache entries for " + \
4396 "'%s': %s, continuing..." % (mytree, e)
4401 mymatches = portdb.xmatch("match-all",x)
4402 portage.writemsg_stdout("processing %s\n" % x)
4405 foo = portdb.aux_get(y,["DEPEND"])
4406 except SystemExit, e:
4407 # sys.exit is an exception... And consequently, we can't catch it.
4409 except Exception, e:
4410 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4412 for mytree in portdb.porttrees:
4413 if portdb.findname2(y, mytree=mytree)[0]:
4414 dead_nodes[mytree].discard(y)
4416 for mytree, nodes in dead_nodes.iteritems():
4417 auxdb = portdb.auxdb[mytree]
4421 except (KeyError, CacheError):
4425 def action_config(settings, trees, myopts, myfiles):
4426 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4427 print red("!!! config can only take a single package atom at this time\n")
4429 if not is_valid_package_atom(myfiles[0]):
4430 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4432 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4433 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4437 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4438 except ValueError, e:
4439 # Multiple matches thrown from cpv_expand
4442 print "No packages found.\n"
4445 if "--ask" in myopts:
4447 print "Please select a package to configure:"
4451 options.append(str(idx))
4452 print options[-1]+") "+pkg
4455 idx = userquery("Selection?", options)
4458 pkg = pkgs[int(idx)-1]
4460 print "The following packages available:"
4463 print "\nPlease use a specific atom or the --ask option."
4469 if "--ask" in myopts:
4470 if userquery("Ready to configure "+pkg+"?") == "No":
4473 print "Configuring pkg..."
4475 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4476 mysettings = portage.config(clone=settings)
4477 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4478 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4479 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4482 def action_info(settings, trees, myopts, myfiles):
4483 unameout=commands.getstatusoutput("uname -mrp")[1]
4484 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4485 settings.profile_path, settings["CHOST"],
4486 trees[settings["ROOT"]]["vartree"].dbapi)
4488 header_title = "System Settings"
4490 print header_width * "="
4491 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4492 print header_width * "="
4493 print "System uname: "+unameout
4494 gentoo_release = portage.grabfile(os.path.join(
4495 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4497 print gentoo_release[0]
4499 print "Unknown Host Operating System"
4500 lastSync = portage.grabfile(os.path.join(
4501 settings["PORTDIR"], "metadata", "timestamp.chk"))
4502 print "Timestamp of tree:",
4508 output=commands.getstatusoutput("distcc --version")
4510 print str(output[1].split("\n",1)[0]),
4511 if "distcc" in settings.features:
4516 output=commands.getstatusoutput("ccache -V")
4518 print str(output[1].split("\n",1)[0]),
4519 if "ccache" in settings.features:
4524 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4525 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4526 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4527 myvars = portage.util.unique_array(myvars)
4531 if portage.isvalidatom(x):
4532 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4534 for y in pkg_matches:
4535 mycpv = portage.catpkgsplit(y)
4536 if(mycpv[3] != "r0"):
4537 pkgs += [mycpv[2] + "-" + mycpv[3]]
4541 pkgs = ", ".join(sorted_versions(pkgs))
4542 print "%-20s %s" % (x+":", pkgs)
4544 print "%-20s %s" % (x+":", "[NOT VALID]")
4546 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4548 if "--verbose" in myopts:
4549 myvars=settings.keys()
4551 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4552 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4553 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4554 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4556 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4558 myvars = portage.util.unique_array(myvars)
4564 print '%s="%s"' % (x, settings[x])
4566 use = set(settings["USE"].split())
4567 use_expand = settings["USE_EXPAND"].split()
4569 for varname in use_expand:
4570 flag_prefix = varname.lower() + "_"
4572 if f.startswith(flag_prefix):
4576 print 'USE="%s"' % " ".join(use),
4577 for varname in use_expand:
4578 myval = settings.get(varname)
4580 print '%s="%s"' % (varname, myval),
4583 unset_vars.append(x)
4585 print "Unset: "+", ".join(unset_vars)
4588 if "--debug" in myopts:
4589 for x in dir(portage):
4590 module = getattr(portage, x)
4591 if "cvs_id_string" in dir(module):
4592 print "%s: %s" % (str(x), str(module.cvs_id_string))
4594 # See if we can find any packages installed matching the strings
4595 # passed on the command line
4597 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4598 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4600 mypkgs.extend(vardb.match(x))
4602 # If some packages were found...
4604 # Get our global settings (we only print stuff if it varies from
4605 # the current config)
4606 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4607 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4609 pkgsettings = portage.config(clone=settings)
4611 for myvar in mydesiredvars:
4612 global_vals[myvar] = set(settings.get(myvar, "").split())
4614 # Loop through each package
4615 # Only print settings if they differ from global settings
4616 header_printed = False
4618 # Get all package specific variables
4619 auxvalues = vardb.aux_get(pkg, auxkeys)
4621 for i in xrange(len(auxkeys)):
4622 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4624 for myvar in mydesiredvars:
4625 # If the package variable doesn't match the
4626 # current global variable, something has changed
4627 # so set diff_found so we know to print
4628 if valuesmap[myvar] != global_vals[myvar]:
4629 diff_values[myvar] = valuesmap[myvar]
4630 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4631 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4633 # If a matching ebuild is no longer available in the tree, maybe it
4634 # would make sense to compare against the flags for the best
4635 # available version with the same slot?
4637 if portdb.cpv_exists(pkg):
4639 pkgsettings.setcpv(pkg, mydb=mydb)
4640 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4642 diff_values["USE"] = valuesmap["USE"]
4643 # If a difference was found, print the info for
4647 # If we have not yet printed the header,
4649 if not header_printed:
4650 header_title = "Package Settings"
4651 print header_width * "="
4652 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4653 print header_width * "="
4654 header_printed = True
4656 # Print package info
4657 print "%s was built with the following:" % pkg
4658 for myvar in mydesiredvars + ["USE"]:
4659 if myvar in diff_values:
4660 mylist = list(diff_values[myvar])
4662 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4665 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4667 print "emerge: no search terms provided."
4669 searchinstance = search(settings, portdb,
4670 vartree, spinner, "--searchdesc" in myopts,
4671 "--quiet" not in myopts)
4672 for mysearch in myfiles:
4674 searchinstance.execute(mysearch)
4675 except re.error, comment:
4676 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4678 searchinstance.output()
4680 def action_depclean(settings, trees, ldpath_mtimes,
4682 # Kill packages that aren't explicitly merged or are required as a
4683 # dependency of another package. World file is explicit.
4685 warn_prefix = colorize("BAD", "*** WARNING *** ")
4687 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4688 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4689 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4691 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4692 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4693 print warn_prefix + "be kept. They can be manually added to this set with"
4694 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4695 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4696 print warn_prefix + "depclean, even if they are part of the world set."
4698 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4699 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4700 print warn_prefix + "consequence, it is often necessary to run "
4701 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4703 xterm_titles = "notitles" not in settings.features
4704 myroot = settings["ROOT"]
4705 dep_check_trees = {}
4706 dep_check_trees[myroot] = {}
4707 dep_check_trees[myroot]["vartree"] = \
4708 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4709 vardb = dep_check_trees[myroot]["vartree"].dbapi
4710 # Constrain dependency selection to the installed packages.
4711 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4712 syslist = getlist(settings, "system")
4713 worldlist = getlist(settings, "world")
4714 system_world_dict = genericdict(worldlist)
4715 system_world_dict.update(genericdict(syslist))
4716 fakedb = portage.fakedbapi(settings=settings)
4717 myvarlist = vardb.cpv_all()
4720 print "\n!!! You have no system list.",
4722 print "\n!!! You have no world file.",
4724 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4726 if not (syslist and worldlist and myvarlist):
4727 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4728 print " break your installation.\n"
4729 if "--pretend" not in myopts:
4730 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4732 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4733 emergelog(xterm_titles, " >>> depclean")
4735 if "--quiet" not in myopts:
4736 print "\nCalculating dependencies ",
4740 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4741 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4743 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4745 while remaining_atoms:
4746 atom, parent, priority = remaining_atoms.pop()
4747 pkgs = vardb.match(atom)
4749 if not atom.startswith("!") and priority == hard:
4750 unresolveable.setdefault(atom, []).append(parent)
4752 if portage.dep_getkey(atom) not in system_world_dict:
4753 # Prune all but the best matching slot, since that's all that a
4754 # deep world update would pull in. Don't prune if the cpv is in
4755 # system or world though, since those sets trigger greedy update
4757 pkgs = [portage.best(pkgs)]
4759 if fakedb.cpv_exists(pkg):
4762 fakedb.cpv_inject(pkg)
4763 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4765 if myopts.get("--with-bdeps", "y") == "y":
4766 mydeps.append((myaux["DEPEND"], soft))
4768 mydeps.append((" ".join(myaux.values()), hard))
4769 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4770 for depstr, priority in mydeps:
4775 if "--debug" in myopts:
4777 print "Parent: ", pkg
4778 print "Depstring:", depstr
4780 if priority == soft:
4786 portage.dep._dep_check_strict = False
4787 success, atoms = portage.dep_check(depstr, None, settings,
4788 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4790 portage.dep._dep_check_strict = True
4792 show_invalid_depstring_notice(
4793 ("installed", myroot, pkg, "nomerge"),
4797 if "--debug" in myopts:
4798 print "Candidates:", atoms
4801 remaining_atoms.append((atom, pkg, priority))
4803 if "--quiet" not in myopts:
4804 print "\b\b... done!\n"
4807 print "Dependencies could not be completely resolved due to"
4808 print "the following required packages not being installed:"
4810 for atom in unresolveable:
4811 print atom, "required by", " ".join(unresolveable[atom])
4813 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4814 print "depclean? It may be necessary to manually uninstall packages that no longer"
4815 print "exist in the portage tree since it may not be possible to satisfy their"
4816 print "dependencies. Also, be aware of the --with-bdeps option that is documented"
4817 print "in " + good("`man emerge`") + "."
4821 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4824 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4825 "unmerge", cleanlist, ldpath_mtimes)
4827 print "Packages installed: "+str(len(myvarlist))
4828 print "Packages in world: "+str(len(worldlist))
4829 print "Packages in system: "+str(len(syslist))
4830 print "Unique package names: "+str(len(myvarlist))
4831 print "Required packages: "+str(len(fakedb.cpv_all()))
4832 if "--pretend" in myopts:
4833 print "Number to remove: "+str(len(cleanlist))
4835 print "Number removed: "+str(len(cleanlist))
4837 def action_build(settings, trees, mtimedb,
4838 myopts, myaction, myfiles, spinner):
4839 ldpath_mtimes = mtimedb["ldpath"]
4841 if "--quiet" not in myopts and \
4842 ("--pretend" in myopts or "--ask" in myopts or \
4843 "--tree" in myopts or "--verbose" in myopts):
4845 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4849 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4851 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4855 print darkgreen("These are the packages that would be %s, in order:") % action
4858 # validate the state of the resume data
4859 # so that we can make assumptions later.
4860 for k in ("resume", "resume_backup"):
4862 if "mergelist" in mtimedb[k]:
4863 if not mtimedb[k]["mergelist"]:
4868 if "--resume" in myopts and \
4869 ("resume" in mtimedb or
4870 "resume_backup" in mtimedb):
4871 if "resume" not in mtimedb:
4872 mtimedb["resume"] = mtimedb["resume_backup"]
4873 del mtimedb["resume_backup"]
4875 # XXX: "myopts" is a list for backward compatibility.
4876 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4878 for opt in ("--skipfirst", "--ask", "--tree"):
4879 myresumeopts.pop(opt, None)
4881 for myopt, myarg in myopts.iteritems():
4882 if myopt not in myresumeopts:
4883 myresumeopts[myopt] = myarg
4885 myparams = create_depgraph_params(myopts, myaction)
4886 if "--quiet" not in myopts and "--nodeps" not in myopts:
4887 print "Calculating dependencies ",
4888 mydepgraph = depgraph(settings, trees,
4889 myopts, myparams, spinner)
4890 if "--quiet" not in myopts and "--nodeps" not in myopts:
4891 print "\b\b... done!"
4893 if ("--resume" in myopts):
4894 print darkgreen("emerge: It seems we have nothing to resume...")
4897 myparams = create_depgraph_params(myopts, myaction)
4898 if myaction in ["system","world"]:
4899 if "--quiet" not in myopts and "--nodeps" not in myopts:
4900 print "Calculating",myaction,"dependencies ",
4902 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4903 if not mydepgraph.xcreate(myaction):
4904 print "!!! Depgraph creation failed."
4906 if "--quiet" not in myopts and "--nodeps" not in myopts:
4907 print "\b\b... done!"
4909 if "--quiet" not in myopts and "--nodeps" not in myopts:
4910 print "Calculating dependencies ",
4912 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4914 retval, favorites = mydepgraph.select_files(myfiles)
4915 except portage.exception.PackageNotFound, e:
4916 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4920 if "--quiet" not in myopts and "--nodeps" not in myopts:
4921 print "\b\b... done!"
4923 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4924 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4926 if mydepgraph.missingbins:
4927 for x in mydepgraph.missingbins:
4928 sys.stderr.write(" "+str(x)+"\n")
4929 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4932 if "--pretend" not in myopts and \
4933 ("--ask" in myopts or "--tree" in myopts or \
4934 "--verbose" in myopts) and \
4935 not ("--quiet" in myopts and "--ask" not in myopts):
4936 if "--resume" in myopts:
4937 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4938 mymergelist = mtimedb["resume"]["mergelist"]
4939 if "--skipfirst" in myopts:
4940 mymergelist = mymergelist[1:]
4941 if len(mymergelist) == 0:
4942 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4944 mydepgraph.display(mymergelist)
4945 prompt="Would you like to resume merging these packages?"
4948 mydepgraph.altlist(reversed=("--tree" in myopts)))
4950 for x in mydepgraph.altlist():
4951 if x[0] != "blocks" and x[3] != "nomerge":
4953 #check for blocking dependencies
4954 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
4955 print "\n!!! Error: The above package list contains packages which cannot be installed"
4956 print "!!! at the same time on the same system."
4957 if "--quiet" not in myopts:
4958 show_blocker_docs_link()
4961 if "--noreplace" in myopts and favorites:
4964 print " %s %s" % (good("*"), x)
4965 prompt="Would you like to add these packages to your world favorites?"
4966 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4967 prompt="Nothing to merge; would you like to auto-clean packages?"
4970 print "Nothing to merge; quitting."
4973 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4974 prompt="Would you like to fetch the source files for these packages?"
4976 prompt="Would you like to merge these packages?"
4978 if "--ask" in myopts and userquery(prompt) == "No":
4983 # Don't ask again (e.g. when auto-cleaning packages after merge)
4984 myopts.pop("--ask", None)
4986 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4987 if ("--resume" in myopts):
4988 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4989 mymergelist = mtimedb["resume"]["mergelist"]
4990 if "--skipfirst" in myopts:
4991 mymergelist = mymergelist[1:]
4992 if len(mymergelist) == 0:
4993 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4995 mydepgraph.display(mymergelist)
4998 mydepgraph.altlist(reversed=("--tree" in myopts)))
4999 if ("--buildpkgonly" in myopts):
5000 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5001 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5002 print "!!! You have to merge the dependencies before you can build this package.\n"
5005 if ("--buildpkgonly" in myopts):
5006 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5007 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5008 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
5011 if ("--resume" in myopts):
5012 favorites=mtimedb["resume"]["favorites"]
5013 mergetask = MergeTask(settings, trees, myopts)
5014 if "--fetchonly" in myopts:
5015 """ parallel-fetch uses --resume --fetchonly and we don't want
5016 it to write the mtimedb"""
5017 mtimedb.filename = None
5018 time.sleep(3) # allow the parent to have first fetch
5020 retval = mergetask.merge(
5021 mtimedb["resume"]["mergelist"], favorites, mtimedb)
5022 if retval != os.EX_OK:
5025 if "resume" in mtimedb and \
5026 "mergelist" in mtimedb["resume"] and \
5027 len(mtimedb["resume"]["mergelist"]) > 1:
5028 mtimedb["resume_backup"] = mtimedb["resume"]
5029 del mtimedb["resume"]
5031 mtimedb["resume"]={}
5032 # XXX: Stored as a list for backward compatibility.
5033 mtimedb["resume"]["myopts"] = \
5034 [k for k in myopts if myopts[k] is True]
5035 mtimedb["resume"]["favorites"]=favorites
5036 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5037 for pkgline in mydepgraph.altlist():
5038 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5039 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
5040 tmpsettings = portage.config(clone=settings)
5042 if settings.get("PORTAGE_DEBUG", "") == "1":
5044 retval = portage.doebuild(
5045 y, "digest", settings["ROOT"], tmpsettings, edebug,
5046 ("--pretend" in myopts),
5047 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
5049 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5051 for pkg in mydepgraph.altlist():
5052 if pkg[0] != "blocks":
5055 pkglist = mydepgraph.altlist()
5057 mergetask = MergeTask(settings, trees, myopts)
5058 retval = mergetask.merge(pkglist, favorites, mtimedb)
5059 if retval != os.EX_OK:
5062 if mtimedb.has_key("resume"):
5063 del mtimedb["resume"]
5064 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5065 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5066 vartree = trees[settings["ROOT"]]["vartree"]
5067 unmerge(settings, myopts, vartree, "clean", ["world"],
5068 ldpath_mtimes, autoclean=1)
5070 portage.writemsg_stdout(colorize("WARN", "WARNING:")
5071 + " AUTOCLEAN is disabled. This can cause serious"
5072 + " problems due to overlapping packages.\n")
5074 def multiple_actions(action1, action2):
5075 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
5076 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
5079 def parse_opts(tmpcmdline, silent=False):
5084 global actions, options, shortmapping
5086 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
5087 argument_options = {
5089 "help":"specify the location for portage configuration files",
5093 "help":"enable or disable color output",
5095 "choices":("y", "n")
5098 "help":"include unnecessary build time dependencies",
5100 "choices":("y", "n")
5104 from optparse import OptionParser
5105 parser = OptionParser()
5106 if parser.has_option("--help"):
5107 parser.remove_option("--help")
5109 for action_opt in actions:
5110 parser.add_option("--" + action_opt, action="store_true",
5111 dest=action_opt.replace("-", "_"), default=False)
5112 for myopt in options:
5113 parser.add_option(myopt, action="store_true",
5114 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5115 for shortopt, longopt in shortmapping.iteritems():
5116 parser.add_option("-" + shortopt, action="store_true",
5117 dest=longopt.lstrip("--").replace("-", "_"), default=False)
5118 for myalias, myopt in longopt_aliases.iteritems():
5119 parser.add_option(myalias, action="store_true",
5120 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5122 for myopt, kwargs in argument_options.iteritems():
5123 parser.add_option(myopt,
5124 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
5126 myoptions, myargs = parser.parse_args(args=tmpcmdline)
5128 for myopt in options:
5129 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
5131 myopts[myopt] = True
5133 for myopt in argument_options:
5134 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
5138 for action_opt in actions:
5139 v = getattr(myoptions, action_opt.replace("-", "_"))
5142 multiple_actions(myaction, action_opt)
5144 myaction = action_opt
5147 if x in actions and myaction != "search":
5148 if not silent and x not in ["system", "world"]:
5149 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
5150 # special case "search" so people can search for action terms, e.g. emerge -s sync
5152 multiple_actions(myaction, x)
5158 if "--nocolor" in myopts:
5160 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
5161 "use '--color=n' instead.\n")
5162 del myopts["--nocolor"]
5163 myopts["--color"] = "n"
5165 return myaction, myopts, myfiles
5167 def validate_ebuild_environment(trees):
5168 for myroot in trees:
5169 mysettings = trees[myroot]["vartree"].settings
5170 if not mysettings.get("ARCH", None):
5171 print >> sys.stderr, bad("\a!!! ARCH is not set... " + \
5172 "Are you missing the '%setc/make.profile' symlink?" % \
5173 mysettings["PORTAGE_CONFIGROOT"])
5174 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5175 "Is your portage tree complete?\n")
5177 del myroot, mysettings
5179 def load_emerge_config(trees=None):
5181 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5182 kwargs[k] = os.environ.get(envvar, None)
5183 trees = portage.create_trees(trees=trees, **kwargs)
5185 settings = trees["/"]["vartree"].settings
5187 for myroot in trees:
5189 settings = trees[myroot]["vartree"].settings
5192 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5193 mtimedb = portage.MtimeDB(mtimedbfile)
5194 return settings, trees, mtimedb
5196 def adjust_config(myopts, settings):
5197 """Make emerge specific adjustments to the config."""
5199 # To enhance usability, make some vars case insensitive by forcing them to
5201 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5202 if myvar in settings:
5203 settings[myvar] = settings[myvar].lower()
5204 settings.backup_changes(myvar)
5207 # Kill noauto as it will break merges otherwise.
5208 if "noauto" in settings.features:
5209 while "noauto" in settings.features:
5210 settings.features.remove("noauto")
5211 settings["FEATURES"] = " ".join(settings.features)
5212 settings.backup_changes("FEATURES")
5216 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5217 except ValueError, e:
5218 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5219 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5220 settings["CLEAN_DELAY"], noiselevel=-1)
5221 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5222 settings.backup_changes("CLEAN_DELAY")
5224 EMERGE_WARNING_DELAY = 10
5226 EMERGE_WARNING_DELAY = int(settings.get(
5227 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5228 except ValueError, e:
5229 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5230 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5231 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5232 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5233 settings.backup_changes("EMERGE_WARNING_DELAY")
5235 if "--quiet" in myopts:
5236 settings["PORTAGE_QUIET"]="1"
5237 settings.backup_changes("PORTAGE_QUIET")
5239 # Set so that configs will be merged regardless of remembered status
5240 if ("--noconfmem" in myopts):
5241 settings["NOCONFMEM"]="1"
5242 settings.backup_changes("NOCONFMEM")
5244 # Set various debug markers... They should be merged somehow.
5247 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5248 if PORTAGE_DEBUG not in (0, 1):
5249 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5250 PORTAGE_DEBUG, noiselevel=-1)
5251 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5254 except ValueError, e:
5255 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5256 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5257 settings["PORTAGE_DEBUG"], noiselevel=-1)
5259 if "--debug" in myopts:
5261 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5262 settings.backup_changes("PORTAGE_DEBUG")
5264 if settings.get("NOCOLOR") not in ("yes","true"):
5265 portage.output.havecolor = 1
5267 """The explicit --color < y | n > option overrides the NOCOLOR environment
5268 variable and stdout auto-detection."""
5269 if "--color" in myopts:
5270 if "y" == myopts["--color"]:
5271 portage.output.havecolor = 1
5272 settings["NOCOLOR"] = "false"
5274 portage.output.havecolor = 0
5275 settings["NOCOLOR"] = "true"
5276 settings.backup_changes("NOCOLOR")
5277 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5278 portage.output.havecolor = 0
5279 settings["NOCOLOR"] = "true"
5280 settings.backup_changes("NOCOLOR")
5283 global portage # NFC why this is necessary now - genone
5284 # Disable color until we're sure that it should be enabled (after
5285 # EMERGE_DEFAULT_OPTS has been parsed).
5286 portage.output.havecolor = 0
5287 # This first pass is just for options that need to be known as early as
5288 # possible, such as --config-root. They will be parsed again later,
5289 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5290 # the value of --config-root).
5291 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5292 if "--debug" in myopts:
5293 os.environ["PORTAGE_DEBUG"] = "1"
5294 if "--config-root" in myopts:
5295 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5297 # Portage needs to ensure a sane umask for the files it creates.
5299 settings, trees, mtimedb = load_emerge_config()
5300 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5303 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5304 except (OSError, ValueError), e:
5305 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5306 settings["PORTAGE_NICENESS"])
5307 portage.writemsg("!!! %s\n" % str(e))
5310 if portage.global_updates(settings, trees, mtimedb["updates"]):
5312 # Reload the whole config from scratch.
5313 settings, trees, mtimedb = load_emerge_config(trees=trees)
5314 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5316 xterm_titles = "notitles" not in settings.features
5319 if "--ignore-default-opts" not in sys.argv:
5320 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5321 tmpcmdline.extend(sys.argv[1:])
5322 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5324 if "--digest" in myopts:
5325 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5326 # Reload the whole config from scratch so that the portdbapi internal
5327 # config is updated with new FEATURES.
5328 settings, trees, mtimedb = load_emerge_config(trees=trees)
5329 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5331 for myroot in trees:
5332 mysettings = trees[myroot]["vartree"].settings
5334 adjust_config(myopts, mysettings)
5336 del myroot, mysettings
5338 spinner = stdout_spinner()
5339 if "candy" in settings.features:
5340 spinner.update = spinner.update_scroll
5342 portage.deprecated_profile_check()
5344 #Freeze the portdbapi for enhanced performance:
5345 for myroot in trees:
5346 trees[myroot]["porttree"].dbapi.freeze()
5349 if "moo" in myfiles:
5352 Larry loves Gentoo (""" + os.uname()[0] + """)
5354 _______________________
5355 < Have you mooed today? >
5356 -----------------------
5365 if (myaction in ["world", "system"]) and myfiles:
5366 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5370 ext = os.path.splitext(x)[1]
5371 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5372 print "emerging by path implies --oneshot... adding --oneshot to options."
5373 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5376 if ("--tree" in myopts) and ("--columns" in myopts):
5377 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5380 if ("--quiet" in myopts):
5381 spinner.update = spinner.update_quiet
5382 portage.util.noiselimit = -1
5384 # Always create packages if FEATURES=buildpkg
5385 # Imply --buildpkg if --buildpkgonly
5386 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5387 if "--buildpkg" not in myopts:
5388 myopts["--buildpkg"] = True
5390 # Also allow -S to invoke search action (-sS)
5391 if ("--searchdesc" in myopts):
5392 if myaction and myaction != "search":
5393 myfiles.append(myaction)
5394 if "--search" not in myopts:
5395 myopts["--search"] = True
5398 # Always try and fetch binary packages if FEATURES=getbinpkg
5399 if ("getbinpkg" in settings.features):
5400 myopts["--getbinpkg"] = True
5402 if "--skipfirst" in myopts and "--resume" not in myopts:
5403 myopts["--resume"] = True
5405 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5406 myopts["--usepkgonly"] = True
5408 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5409 myopts["--getbinpkg"] = True
5411 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5412 myopts["--usepkg"] = True
5414 # Also allow -K to apply --usepkg/-k
5415 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5416 myopts["--usepkg"] = True
5418 # Allow -p to remove --ask
5419 if ("--pretend" in myopts) and ("--ask" in myopts):
5420 print ">>> --pretend disables --ask... removing --ask from options."
5423 # forbid --ask when not in a terminal
5424 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5425 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5426 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5430 if settings.get("PORTAGE_DEBUG", "") == "1":
5431 spinner.update = spinner.update_quiet
5433 if "python-trace" in settings.features:
5434 import portage.debug
5435 portage.debug.set_trace(True)
5437 if ("--resume" in myopts):
5438 if "--tree" in myopts:
5439 print "* --tree is currently broken with --resume. Disabling..."
5440 del myopts["--tree"]
5442 if not ("--quiet" in myopts):
5443 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5444 spinner.update = spinner.update_basic
5446 if "--version" in myopts:
5447 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5448 settings.profile_path, settings["CHOST"],
5449 trees[settings["ROOT"]]["vartree"].dbapi)
5451 elif "--help" in myopts:
5452 emerge.help.help(myaction, myopts, portage.output.havecolor)
5455 if portage.wheelgid == portage.portage_gid:
5456 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5457 print " include the portage user as noted above, and then use group portage."
5459 if "--debug" in myopts:
5460 print "myaction", myaction
5461 print "myopts", myopts
5463 if not myaction and not myfiles and "--resume" not in myopts:
5464 emerge.help.help(myaction, myopts, portage.output.havecolor)
5467 # check if root user is the current user for the actions where emerge needs this
5468 if portage.secpass < 2:
5469 # We've already allowed "--version" and "--help" above.
5470 if "--pretend" not in myopts and \
5471 myaction not in ("search","info"):
5472 need_superuser = not \
5473 ("--fetchonly" in myopts or \
5474 "--fetch-all-uri" in myopts or \
5475 myaction in ("metadata", "regen"))
5476 if portage.secpass < 1 or \
5479 access_desc = "superuser"
5481 access_desc = "portage group"
5482 # Always show portage_group_warning() when only portage group
5483 # access is required but the user is not in the portage group.
5484 from portage.data import portage_group_warning
5485 if "--ask" in myopts:
5486 myopts["--pretend"] = True
5488 print ("%s access would be required... " + \
5489 "adding --pretend to options.\n") % access_desc
5490 if portage.secpass < 1 and not need_superuser:
5491 portage_group_warning()
5493 sys.stderr.write(("emerge: %s access would be " + \
5494 "required.\n\n") % access_desc)
5495 if portage.secpass < 1 and not need_superuser:
5496 portage_group_warning()
5499 disable_emergelog = False
5500 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5502 disable_emergelog = True
5504 if myaction in ("search", "info"):
5505 disable_emergelog = True
5506 if disable_emergelog:
5507 """ Disable emergelog for everything except build or unmerge
5508 operations. This helps minimize parallel emerge.log entries that can
5509 confuse log parsers. We especially want it disabled during
5510 parallel-fetch, which uses --resume --fetchonly."""
5512 def emergelog(*pargs, **kargs):
5515 if not "--pretend" in myopts:
5516 emergelog(xterm_titles, "Started emerge on: "+\
5517 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5520 myelogstr=" ".join(myopts)
5522 myelogstr+=" "+myaction
5524 myelogstr+=" "+" ".join(myfiles)
5525 emergelog(xterm_titles, " *** emerge " + myelogstr)
5527 def emergeexitsig(signum, frame):
5528 signal.signal(signal.SIGINT, signal.SIG_IGN)
5529 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5530 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5531 sys.exit(100+signum)
5532 signal.signal(signal.SIGINT, emergeexitsig)
5533 signal.signal(signal.SIGTERM, emergeexitsig)
5536 """This gets out final log message in before we quit."""
5537 if "--pretend" not in myopts:
5538 emergelog(xterm_titles, " *** terminating.")
5539 if "notitles" not in settings.features:
5541 portage.atexit_register(emergeexit)
5543 if myaction in ("config", "metadata", "regen", "sync"):
5544 if "--pretend" in myopts:
5545 sys.stderr.write(("emerge: The '%s' action does " + \
5546 "not support '--pretend'.\n") % myaction)
5548 if "sync" == myaction:
5549 action_sync(settings, trees, mtimedb, myopts, myaction)
5550 elif "metadata" == myaction:
5551 action_metadata(settings, portdb, myopts)
5552 elif myaction=="regen":
5553 validate_ebuild_environment(trees)
5554 action_regen(settings, portdb)
5556 elif "config"==myaction:
5557 validate_ebuild_environment(trees)
5558 action_config(settings, trees, myopts, myfiles)
5561 elif "info"==myaction:
5562 action_info(settings, trees, myopts, myfiles)
5565 elif "search"==myaction:
5566 validate_ebuild_environment(trees)
5567 action_search(settings, portdb, trees["/"]["vartree"],
5568 myopts, myfiles, spinner)
5569 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5570 validate_ebuild_environment(trees)
5571 vartree = trees[settings["ROOT"]]["vartree"]
5572 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5574 if "--pretend" not in myopts:
5575 post_emerge(settings, mtimedb, 0)
5577 elif "depclean"==myaction:
5578 validate_ebuild_environment(trees)
5579 action_depclean(settings, trees, mtimedb["ldpath"],
5581 if "--pretend" not in myopts:
5582 post_emerge(settings, mtimedb, 0)
5583 # "update", "system", or just process files:
5585 validate_ebuild_environment(trees)
5586 action_build(settings, trees, mtimedb,
5587 myopts, myaction, myfiles, spinner)
5588 if "--pretend" not in myopts:
5589 post_emerge(settings, mtimedb, 0)
5591 if __name__ == "__main__":
5592 retval = emerge_main()