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, CACHE_PATH
37 import portage.xpak, commands, errno, re, socket, time, types
38 from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
39 havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
40 xtermTitleReset, yellow
41 from portage.output import create_color_func
42 good = create_color_func("GOOD")
43 bad = create_color_func("BAD")
46 portage.dep._dep_check_strict = True
49 import portage.exception
50 from portage.data import secpass
51 from portage.util import normalize_path as normpath
53 if not hasattr(__builtins__, "set"):
54 from sets import Set as set
55 from itertools import chain, izip
56 from UserDict import DictMixin
61 import pickle as cPickle
63 class stdout_spinner(object):
65 "Gentoo Rocks ("+os.uname()[0]+")",
66 "Thank you for using Gentoo. :)",
67 "Are you actually trying to read this?",
68 "How many times have you stared at this?",
69 "We are generating the cache right now",
70 "You are paying too much attention.",
71 "A theory is better than its explanation.",
72 "Phasers locked on target, Captain.",
73 "Thrashing is just virtual crashing.",
74 "To be is to program.",
75 "Real Users hate Real Programmers.",
76 "When all else fails, read the instructions.",
77 "Functionality breeds Contempt.",
78 "The future lies ahead.",
79 "3.1415926535897932384626433832795028841971694",
80 "Sometimes insanity is the only alternative.",
81 "Inaccuracy saves a world of explanation.",
84 twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
88 self.update = self.update_twirl
89 self.scroll_sequence = self.scroll_msgs[
90 int(time.time() * 100) % len(self.scroll_msgs)]
92 def update_basic(self):
93 self.spinpos = (self.spinpos + 1) % 500
94 if (self.spinpos % 100) == 0:
96 sys.stdout.write(". ")
101 def update_scroll(self):
102 if(self.spinpos >= len(self.scroll_sequence)):
103 sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
104 len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
106 sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
108 self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
110 def update_twirl(self):
111 self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
112 sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
115 def update_quiet(self):
118 def userquery(prompt, responses=None, colours=None):
119 """Displays a prompt and a set of responses, then waits for a response
120 which is checked against the responses and the first to match is
121 returned. An empty response will match the first value in responses. The
122 input buffer is *not* cleared prior to the prompt!
125 responses: a List of Strings.
126 colours: a List of Functions taking and returning a String, used to
127 process the responses for display. Typically these will be functions
128 like red() but could be e.g. lambda x: "DisplayString".
129 If responses is omitted, defaults to ["Yes", "No"], [green, red].
130 If only colours is omitted, defaults to [bold, ...].
132 Returns a member of the List responses. (If called without optional
133 arguments, returns "Yes" or "No".)
134 KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
136 if responses is None:
137 responses, colours = ["Yes", "No"], [green, red]
138 elif colours is None:
140 colours=(colours*len(responses))[:len(responses)]
144 response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
145 for key in responses:
146 # An empty response will match the first value in responses.
147 if response.upper()==key[:len(response)].upper():
149 print "Sorry, response '%s' not understood." % response,
150 except (EOFError, KeyboardInterrupt):
155 "clean", "config", "depclean",
157 "prune", "regen", "search",
158 "sync", "system", "unmerge", "world",
161 "--ask", "--alphabetical",
162 "--buildpkg", "--buildpkgonly",
163 "--changelog", "--columns",
167 "--fetchonly", "--fetch-all-uri",
168 "--getbinpkg", "--getbinpkgonly",
169 "--help", "--ignore-default-opts",
171 "--newuse", "--nocolor",
172 "--nodeps", "--noreplace",
173 "--nospinner", "--oneshot",
174 "--onlydeps", "--pretend",
175 "--quiet", "--resume",
176 "--searchdesc", "--selective",
180 "--usepkg", "--usepkgonly",
181 "--verbose", "--version"
187 "b":"--buildpkg", "B":"--buildpkgonly",
188 "c":"--clean", "C":"--unmerge",
189 "d":"--debug", "D":"--deep",
191 "f":"--fetchonly", "F":"--fetch-all-uri",
192 "g":"--getbinpkg", "G":"--getbinpkgonly",
194 "k":"--usepkg", "K":"--usepkgonly",
196 "n":"--noreplace", "N":"--newuse",
197 "o":"--onlydeps", "O":"--nodeps",
198 "p":"--pretend", "P":"--prune",
200 "s":"--search", "S":"--searchdesc",
203 "v":"--verbose", "V":"--version"
206 def emergelog(xterm_titles, mystr, short_msg=None):
208 if short_msg == None:
210 if "HOSTNAME" in os.environ.keys():
211 short_msg = os.environ["HOSTNAME"]+": "+short_msg
212 xtermTitle(short_msg)
214 file_path = "/var/log/emerge.log"
215 mylogfile = open(file_path, "a")
216 portage.util.apply_secpass_permissions(file_path,
217 uid=portage.portage_uid, gid=portage.portage_gid,
221 mylock = portage.locks.lockfile(mylogfile)
222 # seek because we may have gotten held up by the lock.
223 # if so, we may not be positioned at the end of the file.
225 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
229 portage.locks.unlockfile(mylock)
231 except (IOError,OSError,portage.exception.PortageException), e:
233 print >> sys.stderr, "emergelog():",e
235 def countdown(secs=5, doing="Starting"):
237 print ">>> Waiting",secs,"seconds before starting..."
238 print ">>> (Control-C to abort)...\n"+doing+" in: ",
242 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
247 # formats a size given in bytes nicely
248 def format_size(mysize):
249 if type(mysize) not in [types.IntType,types.LongType]:
251 if 0 != mysize % 1024:
252 # Always round up to the next kB so that it doesn't show 0 kB when
253 # some small file still needs to be fetched.
254 mysize += 1024 - mysize % 1024
255 mystr=str(mysize/1024)
259 mystr=mystr[:mycount]+","+mystr[mycount:]
263 def getgccversion(chost):
266 return: the current in-use gcc version
269 gcc_ver_command = 'gcc -dumpversion'
270 gcc_ver_prefix = 'gcc-'
272 gcc_not_found_error = red(
273 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
274 "!!! to update the environment of this terminal and possibly\n" +
275 "!!! other terminals also.\n"
278 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
279 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
280 part1, part2 = myoutput.split("/")
281 if part1.startswith(chost + "-"):
282 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
284 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
285 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
286 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
288 mystatus, myoutput = commands.getstatusoutput(
289 chost + "-" + gcc_ver_command)
290 if mystatus == os.EX_OK:
291 return gcc_ver_prefix + myoutput
293 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
294 if mystatus == os.EX_OK:
295 return gcc_ver_prefix + myoutput
297 portage.writemsg(gcc_not_found_error, noiselevel=-1)
298 return "[unavailable]"
300 def getportageversion(portdir, target_root, profile, chost, vardb):
301 profilever = "unavailable"
303 realpath = os.path.realpath(profile)
304 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
305 if realpath.startswith(basepath):
306 profilever = realpath[1 + len(basepath):]
309 profilever = "!" + os.readlink(profile)
312 del realpath, basepath
315 libclist = vardb.match("virtual/libc")
316 libclist += vardb.match("virtual/glibc")
317 libclist = portage.util.unique_array(libclist)
319 xs=portage.catpkgsplit(x)
321 libcver+=","+"-".join(xs[1:])
323 libcver="-".join(xs[1:])
325 libcver="unavailable"
327 gccver = getgccversion(chost)
328 unameout=os.uname()[2]+" "+os.uname()[4]
330 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
332 def create_depgraph_params(myopts, myaction):
333 #configure emerge engine parameters
335 # self: include _this_ package regardless of if it is merged.
336 # selective: exclude the package if it is merged
337 # recurse: go into the dependencies
338 # deep: go into the dependencies of already merged packages
339 # empty: pretend nothing is merged
340 myparams = ["recurse"]
343 if "--update" in myopts or \
344 "--newuse" in myopts or \
345 "--noreplace" in myopts or \
346 myaction in ("system", "world"):
347 add.extend(["selective"])
348 if "--emptytree" in myopts:
349 add.extend(["empty"])
350 sub.extend(["selective"])
351 if "--nodeps" in myopts:
352 sub.extend(["recurse"])
353 if "--deep" in myopts:
356 if (x not in myparams) and (x not in sub):
363 # search functionality
375 def __init__(self, settings, portdb, vartree, spinner, searchdesc,
377 """Searches the available and installed packages for the supplied search key.
378 The list of available and installed packages is created at object instantiation.
379 This makes successive searches faster."""
380 self.settings = settings
382 self.vartree = vartree
383 self.spinner = spinner
384 self.verbose = verbose
385 self.searchdesc = searchdesc
387 def execute(self,searchkey):
388 """Performs the search for the supplied search key"""
390 self.searchkey=searchkey
391 self.packagematches = []
394 self.matches = {"pkg":[], "desc":[]}
397 self.matches = {"pkg":[]}
398 print "Searching... ",
401 if self.searchkey[0] == '%':
403 self.searchkey = self.searchkey[1:]
404 if self.searchkey[0] == '@':
406 self.searchkey = self.searchkey[1:]
408 self.searchre=re.compile(self.searchkey,re.I)
410 self.searchre=re.compile(re.escape(self.searchkey), re.I)
411 for package in self.portdb.cp_all():
412 self.spinner.update()
415 match_string = package[:]
417 match_string = package.split("/")[-1]
420 if self.searchre.search(match_string):
421 if not self.portdb.xmatch("match-visible", package):
423 self.matches["pkg"].append([package,masked])
424 elif self.searchdesc: # DESCRIPTION searching
425 full_package = self.portdb.xmatch("bestmatch-visible", package)
427 #no match found; we don't want to query description
428 full_package = portage.best(
429 self.portdb.xmatch("match-all", package))
435 full_desc = self.portdb.aux_get(
436 full_package, ["DESCRIPTION"])[0]
438 print "emerge: search: aux_get() failed, skipping"
440 if self.searchre.search(full_desc):
441 self.matches["desc"].append([full_package,masked])
443 for mtype in self.matches.keys():
444 self.matches[mtype].sort()
445 self.mlen += len(self.matches[mtype])
448 """Outputs the results of the search."""
449 print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
450 print "[ Applications found : "+white(str(self.mlen))+" ]"
452 for mtype in self.matches.keys():
453 for match,masked in self.matches[mtype]:
456 full_package = self.portdb.xmatch(
457 "bestmatch-visible", match)
459 #no match found; we don't want to query description
461 full_package = portage.best(
462 self.portdb.xmatch("match-all",match))
465 match = portage.pkgsplit(match)[0]
469 desc, homepage, license = self.portdb.aux_get(
470 full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
472 print "emerge: search: aux_get() failed, skipping"
475 print green("*")+" "+white(match)+" "+red("[ Masked ]")
477 print green("*")+" "+white(match)
478 myversion = self.getVersion(full_package, search.VERSION_RELEASE)
481 mycat = match.split("/")[0]
482 mypkg = match.split("/")[1]
483 mycpv = match + "-" + myversion
484 myebuild = self.portdb.findname(mycpv)
485 pkgdir = os.path.dirname(myebuild)
486 from portage import manifest
487 mf = manifest.Manifest(
488 pkgdir, self.settings["DISTDIR"])
489 fetchlist = self.portdb.getfetchlist(mycpv,
490 mysettings=self.settings, all=True)[1]
492 mysum[0] = mf.getDistfilesSize(fetchlist)
493 mystr = str(mysum[0]/1024)
497 mystr=mystr[:mycount]+","+mystr[mycount:]
500 mysum[0] = "Unknown (missing digest for %s)" % str(e)
503 print " ", darkgreen("Latest version available:"),myversion
504 print " ", self.getInstallationStatus(mycat+'/'+mypkg)
505 print " ", darkgreen("Size of files:"),mysum[0]
506 print " ", darkgreen("Homepage:")+" ",homepage
507 print " ", darkgreen("Description:")+" ",desc
508 print " ", darkgreen("License:")+" ",license
514 def getInstallationStatus(self,package):
515 installed_package = self.vartree.dep_bestmatch(package)
517 version = self.getVersion(installed_package,search.VERSION_RELEASE)
519 result = darkgreen("Latest version installed:")+" "+version
521 result = darkgreen("Latest version installed:")+" [ Not Installed ]"
524 def getVersion(self,full_package,detail):
525 if len(full_package) > 1:
526 package_parts = portage.catpkgsplit(full_package)
527 if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
528 result = package_parts[2]+ "-" + package_parts[3]
530 result = package_parts[2]
536 #build our package digraph
537 def getlist(settings, mode):
539 mylines = settings.packages
542 file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
543 myfile = open(file_path, "r")
544 mylines = myfile.readlines()
546 except (OSError, IOError), e:
547 if e.errno == errno.ENOENT:
548 portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
554 myline=" ".join(x.split())
563 mynewlines.append(myline.strip())
567 def clean_world(vardb, cpv):
568 """Remove a package from the world file when unmerged."""
569 world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
570 worldlist = portage.util.grabfile(world_filename)
571 mykey = portage.cpv_getkey(cpv)
574 if portage.dep_getkey(x) == mykey:
575 matches = vardb.match(x, use_cache=0)
579 elif len(matches) == 1 and matches[0] == cpv:
583 #others are around; keep it.
584 newworldlist.append(x)
586 #this doesn't match the package we're unmerging; keep it.
587 newworldlist.append(x)
589 portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
590 gid=portage.portage_gid, mode=02770)
591 portage.util.write_atomic(world_filename, "\n".join(newworldlist))
593 def genericdict(mylist):
596 mynewdict[portage.dep_getkey(x)]=x
599 def filter_iuse_defaults(iuse):
601 if flag.startswith("+"):
606 class DepPriority(object):
608 This class generates an integer priority level based of various
609 attributes of the dependency relationship. Attributes can be assigned
610 at any time and the new integer value will be generated on calls to the
611 __int__() method. Rich comparison operators are supported.
613 The boolean attributes that affect the integer value are "satisfied",
614 "buildtime", "runtime", and "system". Various combinations of
615 attributes lead to the following priority levels:
617 Combination of properties Priority level
619 not satisfied and buildtime 0
620 not satisfied and runtime -1
621 satisfied and buildtime -2
622 satisfied and runtime -3
623 (none of the above) -4
625 Several integer constants are defined for categorization of priority
628 MEDIUM The upper boundary for medium dependencies.
629 SOFT The upper boundary for soft dependencies.
630 MIN The lower boundary for soft dependencies.
632 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
636 def __init__(self, **kwargs):
637 for myattr in self.__slots__:
638 if myattr == "__weakref__":
640 myvalue = kwargs.get(myattr, False)
641 setattr(self, myattr, myvalue)
643 if not self.satisfied:
653 def __lt__(self, other):
654 return self.__int__() < other
655 def __le__(self, other):
656 return self.__int__() <= other
657 def __eq__(self, other):
658 return self.__int__() == other
659 def __ne__(self, other):
660 return self.__int__() != other
661 def __gt__(self, other):
662 return self.__int__() > other
663 def __ge__(self, other):
664 return self.__int__() >= other
667 return copy.copy(self)
669 myvalue = self.__int__()
670 if myvalue > self.MEDIUM:
672 if myvalue > self.SOFT:
676 class FakeVartree(portage.vartree):
677 """This is implements an in-memory copy of a vartree instance that provides
678 all the interfaces required for use by the depgraph. The vardb is locked
679 during the constructor call just long enough to read a copy of the
680 installed package information. This allows the depgraph to do it's
681 dependency calculations without holding a lock on the vardb. It also
682 allows things like vardb global updates to be done in memory so that the
683 user doesn't necessarily need write access to the vardb in cases where
684 global updates are necessary (updates are performed when necessary if there
685 is not a matching ebuild in the tree)."""
686 def __init__(self, real_vartree, portdb):
687 self.root = real_vartree.root
688 self.settings = real_vartree.settings
689 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
690 vdb_path = os.path.join(self.root, portage.VDB_PATH)
692 # At least the parent needs to exist for the lock file.
693 portage.util.ensure_dirs(vdb_path)
694 except portage.exception.PortageException:
698 if os.access(vdb_path, os.W_OK):
699 vdb_lock = portage.locks.lockdir(vdb_path)
700 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
701 "DEPEND", "RDEPEND", "PDEPEND"]
702 real_dbapi = real_vartree.dbapi
704 for cpv in real_dbapi.cpv_all():
705 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
706 myslot = metadata["SLOT"]
707 mycp = portage.dep_getkey(cpv)
708 myslot_atom = "%s:%s" % (mycp, myslot)
710 mycounter = long(metadata["COUNTER"])
713 metadata["COUNTER"] = str(mycounter)
714 other_counter = slot_counters.get(myslot_atom, None)
715 if other_counter is not None:
716 if other_counter > mycounter:
718 slot_counters[myslot_atom] = mycounter
719 self.dbapi.cpv_inject(cpv, metadata=metadata)
720 real_dbapi.flush_cache()
723 portage.locks.unlockdir(vdb_lock)
724 # Populate the old-style virtuals using the cached values.
725 if not self.settings.treeVirtuals:
726 self.settings.treeVirtuals = portage.util.map_dictlist_vals(
727 portage.getCPFromCPV, self.get_all_provides())
729 # Intialize variables needed for lazy cache pulls of the live ebuild
730 # metadata. This ensures that the vardb lock is released ASAP, without
731 # being delayed in case cache generation is triggered.
732 self._aux_get = self.dbapi.aux_get
733 self.dbapi.aux_get = self._aux_get_wrapper
734 self._aux_get_history = set()
735 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
736 self._portdb = portdb
737 self._global_updates = None
739 def _aux_get_wrapper(self, pkg, wants):
740 if pkg in self._aux_get_history:
741 return self._aux_get(pkg, wants)
742 self._aux_get_history.add(pkg)
744 # Use the live ebuild metadata if possible.
745 live_metadata = dict(izip(self._portdb_keys,
746 self._portdb.aux_get(pkg, self._portdb_keys)))
747 self.dbapi.aux_update(pkg, live_metadata)
748 except (KeyError, portage.exception.PortageException):
749 if self._global_updates is None:
750 self._global_updates = \
751 grab_global_updates(self._portdb.porttree_root)
752 perform_global_updates(
753 pkg, self.dbapi, self._global_updates)
754 return self._aux_get(pkg, wants)
756 def grab_global_updates(portdir):
757 from portage.update import grab_updates, parse_updates
758 updpath = os.path.join(portdir, "profiles", "updates")
760 rawupdates = grab_updates(updpath)
761 except portage.exception.DirectoryNotFound:
764 for mykey, mystat, mycontent in rawupdates:
765 commands, errors = parse_updates(mycontent)
766 upd_commands.extend(commands)
769 def perform_global_updates(mycpv, mydb, mycommands):
770 from portage.update import update_dbentries
771 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
772 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
773 updates = update_dbentries(mycommands, aux_dict)
775 mydb.aux_update(mycpv, updates)
777 class BlockerCache(DictMixin):
778 """This caches blockers of installed packages so that dep_check does not
779 have to be done for every single installed package on every invocation of
780 emerge. The cache is invalidated whenever it is detected that something
781 has changed that might alter the results of dep_check() calls:
782 1) the set of installed packages (including COUNTER) has changed
783 2) the old-style virtuals have changed
785 class BlockerData(object):
786 def __init__(self, counter, atoms):
787 self.counter = counter
790 def __init__(self, myroot, vardb):
792 self._installed_pkgs = set(vardb.cpv_all())
793 self._virtuals = vardb.settings.getvirtuals()
794 self._cache_filename = os.path.join(myroot,
795 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
796 self._cache_version = "1"
797 self._cache_data = None
798 self._modified = False
803 f = open(self._cache_filename)
804 mypickle = cPickle.Unpickler(f)
805 mypickle.find_global = None
806 self._cache_data = mypickle.load()
809 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
811 cache_valid = self._cache_data and \
812 isinstance(self._cache_data, dict) and \
813 self._cache_data.get("version") == self._cache_version and \
814 self._cache_data.get("virtuals") == self._virtuals and \
815 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
817 for pkg in self._installed_pkgs:
818 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
823 self._cache_data = {"version":self._cache_version}
824 self._cache_data["blockers"] = {}
825 self._cache_data["virtuals"] = self._virtuals
826 self._modified = False
829 """If the current user has permission and the internal blocker cache
830 been updated, save it to disk and mark it unmodified. This is called
831 by emerge after it has proccessed blockers for all installed packages.
832 Currently, the cache is only written if the user has superuser
833 privileges (since that's required to obtain a lock), but all users
834 have read access and benefit from faster blocker lookups (as long as
835 the entire cache is still valid). The cache is stored as a pickled
836 dict object with the following format:
840 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
841 "virtuals" : vardb.settings.getvirtuals()
844 if self._modified and \
847 f = portage.util.atomic_ofstream(self._cache_filename)
848 cPickle.dump(self._cache_data, f, -1)
850 portage.util.apply_secpass_permissions(
851 self._cache_filename, gid=portage.portage_gid, mode=0644)
852 except (IOError, OSError), e:
854 self._modified = False
856 def __setitem__(self, cpv, blocker_data):
858 Update the cache and mark it as modified for a future call to
861 @param cpv: Package for which to cache blockers.
863 @param blocker_data: An object with counter and atoms attributes.
864 @type blocker_data: BlockerData
866 self._cache_data["blockers"][cpv] = \
867 (blocker_data.counter, blocker_data.atoms)
868 self._modified = True
870 def __getitem__(self, cpv):
873 @returns: An object with counter and atoms attributes.
875 return self.BlockerData(*self._cache_data["blockers"][cpv])
877 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
879 from formatter import AbstractFormatter, DumbWriter
880 f = AbstractFormatter(DumbWriter(maxcol=72))
882 print "\n\n!!! Invalid or corrupt dependency specification: "
890 p_type, p_root, p_key, p_status = parent_node
892 if p_status == "nomerge":
893 category, pf = portage.catsplit(p_key)
894 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
895 msg.append("Portage is unable to process the dependencies of the ")
896 msg.append("'%s' package. " % p_key)
897 msg.append("In order to correct this problem, the package ")
898 msg.append("should be uninstalled, reinstalled, or upgraded. ")
899 msg.append("As a temporary workaround, the --nodeps option can ")
900 msg.append("be used to ignore all dependencies. For reference, ")
901 msg.append("the problematic dependencies can be found in the ")
902 msg.append("*DEPEND files located in '%s/'." % pkg_location)
904 msg.append("This package can not be installed. ")
905 msg.append("Please notify the '%s' package maintainer " % p_key)
906 msg.append("about this problem.")
909 f.add_flowing_data(x)
917 "installed":"vartree"}
919 def __init__(self, settings, trees, myopts, myparams, spinner):
920 self.settings = settings
921 self.target_root = settings["ROOT"]
923 self.myparams = myparams
925 if settings.get("PORTAGE_DEBUG", "") == "1":
927 self.spinner = spinner
928 self.pkgsettings = {}
929 # Maps cpv to digraph node for all nodes added to the graph.
930 self.pkg_node_map = {}
931 # Maps slot atom to digraph node for all nodes added to the graph.
932 self._slot_node_map = {}
934 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
938 self.trees[myroot] = {}
939 for tree in ("porttree", "bintree"):
940 self.trees[myroot][tree] = trees[myroot][tree]
941 self.trees[myroot]["vartree"] = \
942 FakeVartree(trees[myroot]["vartree"],
943 trees[myroot]["porttree"].dbapi)
944 self.pkgsettings[myroot] = portage.config(
945 clone=self.trees[myroot]["vartree"].settings)
946 self.pkg_node_map[myroot] = {}
947 self._slot_node_map[myroot] = {}
948 vardb = self.trees[myroot]["vartree"].dbapi
949 # This fakedbapi instance will model the state that the vdb will
950 # have after new packages have been installed.
951 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
952 self.mydbapi[myroot] = fakedb
953 if "--nodeps" not in self.myopts and \
954 "--buildpkgonly" not in self.myopts:
955 # --nodeps bypasses this, since it isn't needed in this case
956 # and the cache pulls might trigger (slow) cache generation.
957 for pkg in vardb.cpv_all():
958 self.spinner.update()
959 fakedb.cpv_inject(pkg,
960 metadata=dict(izip(self._mydbapi_keys,
961 vardb.aux_get(pkg, self._mydbapi_keys))))
963 self.useFlags[myroot] = {}
964 if "--usepkg" in self.myopts:
965 self.trees[myroot]["bintree"].populate(
966 "--getbinpkg" in self.myopts,
967 "--getbinpkgonly" in self.myopts)
971 self.digraph=portage.digraph()
972 # Tracks simple parent/child relationships (PDEPEND relationships are
974 self._parent_child_digraph = digraph()
976 self.outdatedpackages=[]
978 self.blocker_digraph = digraph()
979 self.blocker_parents = {}
980 self._unresolved_blocker_parents = {}
981 self._slot_collision_info = []
982 # Slot collision nodes are not allowed to block other packages since
983 # blocker validation is only able to account for one package per slot.
984 self._slot_collision_nodes = set()
985 self._altlist_cache = {}
986 self._pprovided_args = []
988 def _show_slot_collision_notice(self, packages):
989 """Show an informational message advising the user to mask one of the
990 the packages. In some cases it may be possible to resolve this
991 automatically, but support for backtracking (removal nodes that have
992 already been selected) will be required in order to handle all possible
996 msg.append("\n!!! Multiple versions within a single " + \
997 "package slot have been \n")
998 msg.append("!!! pulled into the dependency graph:\n\n")
999 for node, parents in packages:
1000 msg.append(str(node))
1002 msg.append(" pulled in by\n")
1003 for parent in parents:
1005 msg.append(str(parent))
1008 msg.append(" (no parents)\n")
1010 sys.stderr.write("".join(msg))
1013 if "--quiet" in self.myopts:
1017 msg.append("It may be possible to solve this problem ")
1018 msg.append("by using package.mask to prevent one of ")
1019 msg.append("those packages from being selected. ")
1020 msg.append("However, it is also possible that conflicting ")
1021 msg.append("dependencies exist such that they are impossible to ")
1022 msg.append("satisfy simultaneously. If such a conflict exists in ")
1023 msg.append("the dependencies of two different packages, then those ")
1024 msg.append("packages can not be installed simultaneously.")
1026 from formatter import AbstractFormatter, DumbWriter
1027 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1029 f.add_flowing_data(x)
1033 msg.append("For more information, see MASKED PACKAGES ")
1034 msg.append("section in the emerge man page or refer ")
1035 msg.append("to the Gentoo Handbook.")
1037 f.add_flowing_data(x)
1041 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1042 priority=DepPriority(), rev_dep=False, arg=None):
1044 Fills the digraph with nodes comprised of packages to merge.
1045 mybigkey is the package spec of the package to merge.
1046 myparent is the package depending on mybigkey ( or None )
1047 addme = Should we add this package to the digraph or are we just looking at it's deps?
1048 Think --onlydeps, we need to ignore packages in that case.
1051 #IUSE-aware emerge -> USE DEP aware depgraph
1052 #"no downgrade" emerge
1054 mytype, myroot, mykey = mybigkey
1055 existing_node = None
1057 existing_node = self.pkg_node_map[myroot].get(mykey)
1059 self._parent_child_digraph.add(existing_node, myparent)
1060 if existing_node != myparent:
1061 # Refuse to make a node depend on itself so that the we don't
1062 # don't create a bogus circular dependency in self.altlist().
1063 if rev_dep and myparent:
1064 self.digraph.addnode(myparent, existing_node,
1067 self.digraph.addnode(existing_node, myparent,
1071 if "--nodeps" not in self.myopts:
1072 self.spinner.update()
1073 if mytype == "blocks":
1075 "--buildpkgonly" not in self.myopts and \
1076 "--nodeps" not in self.myopts and \
1077 myparent not in self._slot_collision_nodes:
1078 mybigkey[1] = myparent[1]
1079 self.blocker_parents.setdefault(
1080 tuple(mybigkey), set()).add(myparent)
1082 if not arg and myroot == self.target_root:
1083 arg = portage.best_match_to_list(mykey, self.args_keys)
1084 # select the correct /var database that we'll be checking against
1085 vardbapi = self.trees[myroot]["vartree"].dbapi
1086 portdb = self.trees[myroot]["porttree"].dbapi
1087 bindb = self.trees[myroot]["bintree"].dbapi
1088 pkgsettings = self.pkgsettings[myroot]
1090 # if the package is already on the system, we add a "nomerge"
1091 # directive, otherwise we add a "merge" directive.
1093 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1096 self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
1097 myuse = self.pkgsettings[myroot]["USE"].split()
1100 if mytype == "installed":
1102 if addme and mytype != "installed":
1103 # this is where we add the node to the list of packages to merge
1104 if "selective" in self.myparams or not arg:
1105 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1108 """ If we aren't merging, perform the --newuse check.
1109 If the package has new iuse flags or different use flags then if
1110 --newuse is specified, we need to merge the package. """
1111 if merging==0 and "--newuse" in self.myopts and \
1112 vardbapi.cpv_exists(mykey):
1113 pkgsettings.setcpv(mykey, mydb=mydbapi)
1114 forced_flags = set()
1115 forced_flags.update(pkgsettings.useforce)
1116 forced_flags.update(pkgsettings.usemask)
1117 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1118 iuses = set(filter_iuse_defaults(
1119 mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
1120 old_iuse = set(filter_iuse_defaults(
1121 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1122 if iuses.symmetric_difference(
1123 old_iuse).difference(forced_flags):
1125 elif old_iuse.intersection(old_use) != \
1126 iuses.intersection(myuse):
1129 if addme and merging == 1:
1130 mybigkey.append("merge")
1132 mybigkey.append("nomerge")
1133 jbigkey = tuple(mybigkey)
1136 metadata = dict(izip(self._mydbapi_keys,
1137 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1138 if merging == 0 and vardbapi.cpv_exists(mykey) and \
1139 mytype != "installed":
1140 mybigkey[0] = "installed"
1142 jbigkey = tuple(mybigkey)
1143 metadata = dict(izip(self._mydbapi_keys,
1144 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1145 myuse = mydbapi.aux_get(mykey, ["USE"])[0].split()
1146 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1147 existing_node = self._slot_node_map[myroot].get(
1149 slot_collision = False
1151 e_type, myroot, e_cpv, e_status = existing_node
1153 # The existing node can be reused.
1154 self._parent_child_digraph.add(existing_node, myparent)
1155 if rev_dep and myparent:
1156 ptype, proot, pkey, pstatus = myparent
1157 self.digraph.addnode(myparent, existing_node,
1160 self.digraph.addnode(existing_node, myparent,
1164 # A slot collision has occurred. Sometimes this coincides
1165 # with unresolvable blockers, so the slot collision will be
1166 # shown later if there are no unresolvable blockers.
1167 e_parents = self._parent_child_digraph.parent_nodes(
1171 myparents.append(myparent)
1172 self._slot_collision_info.append(
1173 ((jbigkey, myparents), (existing_node, e_parents)))
1174 self._slot_collision_nodes.add(jbigkey)
1175 slot_collision = True
1178 # Now add this node to the graph so that self.display()
1179 # can show use flags and --tree portage.output. This node is
1180 # only being partially added to the graph. It must not be
1181 # allowed to interfere with the other nodes that have been
1182 # added. Do not overwrite data for existing nodes in
1183 # self.pkg_node_map and self.mydbapi since that data will
1184 # be used for blocker validation.
1185 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1186 self.useFlags[myroot].setdefault(mykey, myuse)
1187 # Even though the graph is now invalid, continue to process
1188 # dependencies so that things like --fetchonly can still
1189 # function despite collisions.
1191 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1192 self._slot_node_map[myroot][slot_atom] = jbigkey
1193 self.pkg_node_map[myroot][mykey] = jbigkey
1194 self.useFlags[myroot][mykey] = myuse
1196 if rev_dep and myparent:
1197 self.digraph.addnode(myparent, jbigkey,
1200 self.digraph.addnode(jbigkey, myparent,
1203 # Do this even when addme is False (--onlydeps) so that the
1204 # parent/child relationship is always known in case
1205 # self._show_slot_collision_notice() needs to be called later.
1206 self._parent_child_digraph.add(jbigkey, myparent)
1208 """ This section determines whether we go deeper into dependencies or not.
1209 We want to go deeper on a few occasions:
1210 Installing package A, we need to make sure package A's deps are met.
1211 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1212 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1214 if "deep" not in self.myparams and not merging and \
1215 not ("--update" in self.myopts and arg and merging):
1217 elif "recurse" not in self.myparams:
1220 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1221 Pull from bintree if it's binary package, porttree if it's ebuild.
1222 Binpkg's can be either remote or local. """
1225 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1226 depvalues = mydbapi.aux_get(mykey, depkeys)
1227 for i in xrange(len(depkeys)):
1228 edepend[depkeys[i]] = depvalues[i]
1230 if mytype == "ebuild":
1231 if "--buildpkgonly" in self.myopts:
1232 edepend["RDEPEND"] = ""
1233 edepend["PDEPEND"] = ""
1234 if not (arg and "--onlydeps" in self.myopts and \
1235 mytype == "ebuild") and \
1236 self.myopts.get("--with-bdeps", "n") == "n" and \
1237 (mytype == "binary" or mybigkey[3] == "nomerge"):
1238 edepend["DEPEND"] = ""
1240 """ We have retrieve the dependency information, now we need to recursively
1241 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1243 mp = tuple(mybigkey)
1246 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1247 myuse=myuse, priority=DepPriority(buildtime=True),
1250 """RDEPEND is soft by definition. However, in order to ensure
1251 correct merge order, we make it a hard dependency. Otherwise, a
1252 build time dependency might not be usable due to it's run time
1253 dependencies not being installed yet.
1255 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1256 myuse=myuse, priority=DepPriority(runtime=True),
1259 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1260 # Post Depend -- Add to the list without a parent, as it depends
1261 # on a package being present AND must be built after that package.
1262 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1263 myuse=myuse, priority=DepPriority(), rev_deps=True,
1266 except ValueError, e:
1268 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1269 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1271 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1272 portage.writemsg("\n", noiselevel=-1)
1273 if mytype == "binary":
1275 "!!! This binary package cannot be installed: '%s'\n" % \
1276 mykey, noiselevel=-1)
1277 elif mytype == "ebuild":
1278 myebuild, mylocation = portdb.findname2(mykey)
1279 portage.writemsg("!!! This ebuild cannot be installed: " + \
1280 "'%s'\n" % myebuild, noiselevel=-1)
1281 portage.writemsg("!!! Please notify the package maintainer " + \
1282 "that atoms must be fully-qualified.\n", noiselevel=-1)
1286 def select_files(self,myfiles):
1287 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1289 myroot = self.target_root
1290 portdb = self.trees[myroot]["porttree"].dbapi
1291 bindb = self.trees[myroot]["bintree"].dbapi
1292 pkgsettings = self.pkgsettings[myroot]
1294 def visible(mylist):
1295 matches = portdb.gvisible(portdb.visible(mylist))
1296 return [x for x in mylist \
1297 if x in matches or not portdb.cpv_exists(x)]
1299 ext = os.path.splitext(x)[1]
1301 if not os.path.exists(x):
1303 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1304 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1305 elif os.path.exists(
1306 os.path.join(pkgsettings["PKGDIR"], x)):
1307 x = os.path.join(pkgsettings["PKGDIR"], x)
1309 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1310 print "!!! Please ensure the tbz2 exists as specified.\n"
1312 mytbz2=portage.xpak.tbz2(x)
1313 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1314 if os.path.realpath(x) != \
1315 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1316 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1318 if not self.create(["binary", myroot, mykey],
1319 None, "--onlydeps" not in self.myopts):
1320 return (0,myfavorites)
1321 elif not "--oneshot" in self.myopts:
1322 myfavorites.append(mykey)
1323 elif ext==".ebuild":
1324 x = os.path.realpath(x)
1325 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1326 ebuild_path = portdb.findname(mykey)
1328 if os.path.realpath(ebuild_path) != x:
1329 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1331 if mykey not in portdb.xmatch(
1332 "match-visible", portage.dep_getkey(mykey)):
1333 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1334 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1335 print colorize("BAD", "*** page for details.")
1336 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1339 raise portage.exception.PackageNotFound(
1340 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1341 if not self.create(["ebuild", myroot, mykey],
1342 None, "--onlydeps" not in self.myopts):
1343 return (0,myfavorites)
1344 elif not "--oneshot" in self.myopts:
1345 myfavorites.append(mykey)
1347 if not is_valid_package_atom(x):
1348 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1350 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1351 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1355 if "--usepkg" in self.myopts:
1356 mykey = portage.dep_expand(x, mydb=bindb,
1357 settings=pkgsettings)
1358 if (mykey and not mykey.startswith("null/")) or \
1359 "--usepkgonly" in self.myopts:
1360 arg_atoms.append((x, mykey))
1363 mykey = portage.dep_expand(x,
1364 mydb=portdb, settings=pkgsettings)
1365 arg_atoms.append((x, mykey))
1366 except ValueError, errpkgs:
1367 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1368 print "!!! one of the following fully-qualified ebuild names instead:\n"
1369 for i in errpkgs[0]:
1370 print " " + green(i)
1374 if "--update" in self.myopts:
1375 """Make sure all installed slots are updated when possible. Do this
1376 with --emptytree also, to ensure that all slots are remerged."""
1377 vardb = self.trees[self.target_root]["vartree"].dbapi
1379 for myarg, myatom in arg_atoms:
1380 greedy_atoms.append((myarg, myatom))
1382 for cpv in vardb.match(myatom):
1383 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1386 if "--usepkg" in self.myopts:
1387 mymatches = bindb.match(myatom)
1388 if "--usepkgonly" not in self.myopts:
1389 mymatches = visible(mymatches)
1390 best_pkg = portage.best(mymatches)
1392 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1393 best_pkgs.append(("binary", best_pkg, best_slot))
1394 if "--usepkgonly" not in self.myopts:
1395 best_pkg = portage.best(portdb.match(myatom))
1397 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1398 best_pkgs.append(("ebuild", best_pkg, best_slot))
1400 best_pkg = portage.best([x[1] for x in best_pkgs])
1401 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1402 best_slot = best_pkgs[0][2]
1403 myslots.add(best_slot)
1404 if len(myslots) > 1:
1405 for myslot in myslots:
1406 myslot_atom = "%s:%s" % \
1407 (portage.dep_getkey(myatom), myslot)
1409 if "--usepkgonly" not in self.myopts and \
1410 self.trees[self.target_root][
1411 "porttree"].dbapi.match(myslot_atom):
1413 elif "--usepkg" in self.myopts:
1414 mymatches = bindb.match(myslot_atom)
1415 if "--usepkgonly" not in self.myopts:
1416 mymatches = visible(mymatches)
1420 greedy_atoms.append((myarg, myslot_atom))
1421 arg_atoms = greedy_atoms
1423 """ These are used inside self.create() in order to ensure packages
1424 that happen to match arguments are not incorrectly marked as nomerge."""
1425 self.args_keys = [x[1] for x in arg_atoms]
1426 for myarg, myatom in arg_atoms:
1428 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1429 except portage.exception.MissingSignature, e:
1430 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1431 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1432 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1433 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1434 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1436 except portage.exception.InvalidSignature, e:
1437 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1438 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1439 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1440 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1441 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1443 except SystemExit, e:
1444 raise # Needed else can't exit
1445 except Exception, e:
1446 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1447 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1451 return (0,myfavorites)
1452 elif not "--oneshot" in self.myopts:
1453 mykey = portage.dep_getkey(myatom)
1454 if mykey not in myfavorites:
1455 myfavorites.append(mykey)
1458 if "--usepkgonly" in self.myopts:
1459 for xs in self.digraph.all_nodes():
1460 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1464 print "Missing binary for:",xs[2]
1466 if not self.validate_blockers():
1467 return False, myfavorites
1469 # We're true here unless we are missing binaries.
1470 return (not missing,myfavorites)
1472 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1473 myuse=None, raise_on_missing=False, priority=DepPriority(),
1474 rev_deps=False, parent_arg=None):
1475 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1476 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1477 myparent = the node whose depstring is being passed in
1478 arg = package was specified on the command line, merge even if it's already installed
1479 myuse = USE flags at present
1480 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1481 else continue trying.
1482 return 1 on success, 0 for failure
1485 portdb = self.trees[myroot]["porttree"].dbapi
1486 bindb = self.trees[myroot]["bintree"].dbapi
1487 vardb = self.trees[myroot]["vartree"].dbapi
1488 pkgsettings = self.pkgsettings[myroot]
1490 p_type, p_root, p_key, p_status = myparent
1492 if "--debug" in self.myopts:
1494 print "Parent: ",myparent
1495 print "Depstring:",depstring
1497 print "Reverse:", rev_deps
1498 print "Priority:", priority
1500 #processing dependencies
1501 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1502 dependencies are satisfiable. """
1504 mymerge = [depstring]
1505 pprovided = pkgsettings.pprovideddict.get(
1506 portage.dep_getkey(depstring))
1507 if pprovided and portage.match_from_list(depstring, pprovided):
1511 if myparent and p_status == "nomerge":
1512 portage.dep._dep_check_strict = False
1513 mycheck = portage.dep_check(depstring, None,
1514 pkgsettings, myuse=myuse,
1515 use_binaries=("--usepkgonly" in self.myopts),
1516 myroot=myroot, trees=self.trees)
1518 portage.dep._dep_check_strict = True
1522 show_invalid_depstring_notice(
1523 myparent, depstring, mycheck[1])
1525 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1527 mymerge = mycheck[1]
1529 if not mymerge and arg and \
1530 portage.best_match_to_list(depstring, self.args_keys):
1531 # A provided package has been specified on the command line. The
1532 # package will not be merged and a warning will be displayed.
1533 self._pprovided_args.append(arg)
1536 # The parent is added after it's own dep_check call so that it
1537 # isn't allowed to satisfy a direct bootstrap dependency on itself
1538 # via an old-style virtual. This isn't a problem with new-style
1539 # virtuals, which are preferenced in dep_zapdeps by looking only at
1540 # the depstring, vdb, and available packages.
1542 p_type, p_root, p_key, p_status = myparent
1543 if p_status == "merge":
1544 # Update old-style virtuals if this package provides any.
1545 # These are needed for dep_virtual calls inside dep_check.
1546 p_db = self.trees[p_root][self.pkg_tree_map[p_type]].dbapi
1548 self.pkgsettings[p_root].setinst(p_key, p_db)
1549 except portage.exception.InvalidDependString, e:
1550 provide = p_db.aux_get(p_key, ["PROVIDE"])[0]
1551 show_invalid_depstring_notice(myparent, provide, str(e))
1555 if "--debug" in self.myopts:
1556 print "Candidates:",mymerge
1560 selected_pkg = ["blocks", myroot, x[1:], None]
1562 #We are not processing a blocker but a normal dependency
1564 """In some cases, dep_check will return deps that shouldn't
1565 be proccessed any further, so they are identified and
1567 if "empty" not in self.myparams and \
1568 "deep" not in self.myparams and \
1569 not ("--update" in self.myopts and parent_arg) and \
1573 # List of acceptable packages, ordered by type preference.
1574 matched_packages = []
1575 myeb_matches = portdb.xmatch("match-visible", x)
1577 if "--usepkgonly" not in self.myopts:
1578 myeb = portage.best(myeb_matches)
1581 if "--usepkg" in self.myopts:
1582 # The next line assumes the binarytree has been populated.
1583 # XXX: Need to work out how we use the binary tree with roots.
1584 myeb_pkg_matches = bindb.match(x)
1585 if "--usepkgonly" not in self.myopts:
1586 # Remove any binary package entries that are masked in the portage tree (#55871)
1587 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1588 if pkg in myeb_matches or \
1589 not portdb.cpv_exists(pkg)]
1590 if myeb_pkg_matches:
1591 myeb_pkg = portage.best(myeb_pkg_matches)
1593 if myeb_pkg and "--newuse" in self.myopts:
1594 iuses = set(filter_iuse_defaults(
1595 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1596 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1598 if "--usepkgonly" not in self.myopts and myeb:
1601 pkgsettings.setcpv(myeb, mydb=mydb)
1603 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1604 now_use = pkgsettings["USE"].split()
1605 forced_flags = set()
1606 forced_flags.update(pkgsettings.useforce)
1607 forced_flags.update(pkgsettings.usemask)
1609 if "--usepkgonly" not in self.myopts and myeb:
1610 cur_iuse = set(filter_iuse_defaults(
1611 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1612 if iuses.symmetric_difference(
1613 cur_iuse).difference(forced_flags):
1615 elif iuses.intersection(old_use) != \
1616 cur_iuse.intersection(now_use):
1620 self.trees[myroot]["bintree"].dbapi.aux_get(
1621 myeb_pkg, ["USE"])[0].split()
1622 matched_packages.append(
1623 ["binary", myroot, myeb_pkg, binpkguseflags])
1625 if "--usepkgonly" not in self.myopts and myeb_matches:
1626 matched_packages.append(
1627 ["ebuild", myroot, myeb, None])
1629 if not matched_packages and \
1630 not (arg and "selective" not in self.myparams):
1631 """Fall back to the installed package database. This is a
1632 last resort because the metadata tends to diverge from that
1633 of the ebuild in the tree."""
1634 myeb_inst_matches = vardb.match(x)
1635 if "--usepkgonly" not in self.myopts:
1636 """ TODO: Improve masking check for installed and
1637 binary packages. bug #149816"""
1638 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1639 if not portdb.cpv_exists(pkg)]
1641 if myeb_inst_matches:
1642 myeb_inst = portage.best(myeb_inst_matches)
1644 binpkguseflags = vardb.aux_get(
1645 myeb_inst, ["USE"])[0].split()
1646 matched_packages.append(
1647 ["installed", myroot, myeb_inst, binpkguseflags])
1649 if not matched_packages:
1650 if raise_on_missing:
1657 xfrom = '(dependency required by '+ \
1658 green('"%s"' % myparent[2]) + \
1659 red(' [%s]' % myparent[0]) + ')'
1660 alleb = portdb.xmatch("match-all", x)
1662 if "--usepkgonly" not in self.myopts:
1663 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1664 print "!!! One of the following masked packages is required to complete your request:"
1668 mreasons = portage.getmaskingstatus(p,
1669 settings=pkgsettings, portdb=portdb)
1670 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1671 if "package.mask" in mreasons:
1672 comment, filename = \
1673 portage.getmaskingreason(p,
1674 settings=pkgsettings, portdb=portdb,
1675 return_location=True)
1676 if comment and comment != oldcomment:
1679 oldcomment = comment
1681 licenses = portdb.aux_get(p, ["LICENSE"])[0]
1683 # Corruption will have been reported above.
1687 pkgsettings.setcpv(p, mydb=portdb)
1688 uselist = pkgsettings.get("USE", "").split()
1689 missing_licenses = []
1691 missing_licenses = \
1692 pkgsettings.getMissingLicenses(
1693 licenses, p, uselist)
1694 except portage.exception.InvalidDependString:
1695 # This will have already been reported
1696 # above via mreasons.
1698 for l in missing_licenses:
1699 l_path = portdb.findLicensePath(l)
1700 if l in shown_licenses:
1702 msg = ("A copy of the '%s' license" + \
1703 " is located at '%s'.") % (l, l_path)
1706 shown_licenses.append(l)
1708 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1709 print "refer to the Gentoo Handbook."
1711 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1712 print "!!! Either add a suitable binary package or compile from an ebuild."
1714 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1720 if "--debug" in self.myopts:
1721 for pkg in matched_packages:
1722 print (pkg[0] + ":").rjust(10), pkg[2]
1724 if len(matched_packages) > 1:
1725 bestmatch = portage.best(
1726 [pkg[2] for pkg in matched_packages])
1727 matched_packages = [pkg for pkg in matched_packages \
1728 if pkg[2] == bestmatch]
1730 # ordered by type preference ("ebuild" type is the last resort)
1731 selected_pkg = matched_packages[0]
1732 pkgtype, myroot, mycpv, myuse = selected_pkg
1733 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1734 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1735 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1736 existing_node = self._slot_node_map[myroot].get(
1739 e_type, myroot, e_cpv, e_status = existing_node
1740 if portage.match_from_list(x, [e_cpv]):
1741 # The existing node can be reused.
1742 selected_pkg = [e_type, myroot, e_cpv,
1743 self.useFlags[myroot][e_cpv]]
1746 #we are a dependency, so we want to be unconditionally added
1747 mypriority = priority.copy()
1749 mypriority.satisfied = True
1750 if not self.create(selected_pkg[0:3], myparent,
1751 myuse=selected_pkg[-1], priority=mypriority,
1752 rev_dep=rev_deps, arg=arg):
1755 #if mysource is not set, then we are a command-line dependency and should not be added
1756 #if --onlydeps is specified.
1757 if not self.create(selected_pkg[0:3], myparent,
1758 addme=("--onlydeps" not in self.myopts),
1759 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1762 if "--debug" in self.myopts:
1763 print "Exiting...",myparent
1766 def validate_blockers(self):
1767 """Remove any blockers from the digraph that do not match any of the
1768 packages within the graph. If necessary, create hard deps to ensure
1769 correct merge order such that mutually blocking packages are never
1770 installed simultaneously."""
1772 if "--buildpkgonly" in self.myopts or \
1773 "--nodeps" in self.myopts:
1777 for myroot in self.trees:
1779 modified_slots[myroot] = myslots
1780 final_db = self.mydbapi[myroot]
1781 slot_node_map = self._slot_node_map[myroot]
1782 for slot_atom, mynode in slot_node_map.iteritems():
1783 mytype, myroot, mycpv, mystatus = mynode
1784 if mystatus == "merge":
1785 myslots[slot_atom] = mycpv
1787 #if "deep" in self.myparams:
1789 # Pull in blockers from all installed packages that haven't already
1790 # been pulled into the depgraph. This is not enabled by default
1791 # due to the performance penalty that is incurred by all the
1792 # additional dep_check calls that are required.
1794 # Optimization hack for dep_check calls that minimizes the
1795 # available matches by replacing the portdb with a fakedbapi
1797 class FakePortageTree(object):
1798 def __init__(self, mydb):
1800 dep_check_trees = {}
1801 for myroot in self.trees:
1802 dep_check_trees[myroot] = self.trees[myroot].copy()
1803 dep_check_trees[myroot]["porttree"] = \
1804 FakePortageTree(self.mydbapi[myroot])
1806 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1807 for myroot in self.trees:
1808 pkg_node_map = self.pkg_node_map[myroot]
1809 vardb = self.trees[myroot]["vartree"].dbapi
1810 portdb = self.trees[myroot]["porttree"].dbapi
1811 pkgsettings = self.pkgsettings[myroot]
1812 final_db = self.mydbapi[myroot]
1813 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
1814 blocker_cache = BlockerCache(myroot, vardb)
1815 for pkg in cpv_all_installed:
1816 blocker_atoms = None
1817 matching_node = pkg_node_map.get(pkg, None)
1818 if matching_node and \
1819 matching_node[3] == "nomerge":
1821 # If this node has any blockers, create a "nomerge"
1822 # node for it so that they can be enforced.
1823 self.spinner.update()
1824 blocker_data = blocker_cache.get(pkg)
1826 blocker_atoms = blocker_data.atoms
1828 dep_vals = vardb.aux_get(pkg, dep_keys)
1829 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
1830 depstr = " ".join(dep_vals)
1831 # It is crucial to pass in final_db here in order to
1832 # optimize dep_check calls by eliminating atoms via
1833 # dep_wordreduce and dep_eval calls.
1835 portage.dep._dep_check_strict = False
1837 success, atoms = portage.dep_check(depstr,
1838 final_db, pkgsettings, myuse=myuse,
1839 trees=dep_check_trees, myroot=myroot)
1840 except Exception, e:
1841 if isinstance(e, SystemExit):
1843 # This is helpful, for example, if a ValueError
1844 # is thrown from cpv_expand due to multiple
1845 # matches (this can happen if an atom lacks a
1847 show_invalid_depstring_notice(
1848 ("installed", myroot, pkg, "nomerge"),
1853 portage.dep._dep_check_strict = True
1855 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
1856 vardb.aux_get(pkg, ["SLOT"])[0])
1857 if slot_atom in modified_slots[myroot]:
1858 # This package is being replaced anyway, so
1859 # ignore invalid dependencies so as not to
1860 # annoy the user too much (otherwise they'd be
1861 # forced to manually unmerge it first).
1863 show_invalid_depstring_notice(
1864 ("installed", myroot, pkg, "nomerge"),
1867 blocker_atoms = [myatom for myatom in atoms \
1868 if myatom.startswith("!")]
1869 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
1870 blocker_cache[pkg] = \
1871 blocker_cache.BlockerData(counter, blocker_atoms)
1873 # Don't store this parent in pkg_node_map, because it's
1874 # not needed there and it might overwrite a "merge"
1875 # node with the same cpv.
1876 myparent = ("installed", myroot, pkg, "nomerge")
1877 for myatom in blocker_atoms:
1878 blocker = ("blocks", myroot, myatom[1:])
1880 self.blocker_parents.get(blocker, None)
1883 self.blocker_parents[blocker] = myparents
1884 myparents.add(myparent)
1885 blocker_cache.flush()
1888 for blocker in self.blocker_parents.keys():
1889 mytype, myroot, mydep = blocker
1890 initial_db = self.trees[myroot]["vartree"].dbapi
1891 final_db = self.mydbapi[myroot]
1892 blocked_initial = initial_db.match(mydep)
1893 blocked_final = final_db.match(mydep)
1894 if not blocked_initial and not blocked_final:
1895 del self.blocker_parents[blocker]
1897 blocked_slots_initial = {}
1898 blocked_slots_final = {}
1899 for cpv in blocked_initial:
1900 blocked_slots_initial[cpv] = \
1901 "%s:%s" % (portage.dep_getkey(cpv),
1902 initial_db.aux_get(cpv, ["SLOT"])[0])
1903 for cpv in blocked_final:
1904 blocked_slots_final[cpv] = \
1905 "%s:%s" % (portage.dep_getkey(cpv),
1906 final_db.aux_get(cpv, ["SLOT"])[0])
1907 for parent in list(self.blocker_parents[blocker]):
1908 ptype, proot, pcpv, pstatus = parent
1909 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1910 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1911 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1912 parent_static = pslot_atom not in modified_slots[proot]
1913 unresolved_blocks = False
1914 depends_on_order = set()
1915 for cpv in blocked_initial:
1916 slot_atom = blocked_slots_initial[cpv]
1917 if slot_atom == pslot_atom:
1918 # TODO: Support blocks within slots in cases where it
1919 # might make sense. For example, a new version might
1920 # require that the old version be uninstalled at build
1923 if parent_static and \
1924 slot_atom not in modified_slots[myroot]:
1925 # This blocker will be handled the next time that a
1926 # merge of either package is triggered.
1928 if pstatus == "merge" and \
1929 slot_atom in modified_slots[myroot]:
1930 replacement = final_db.match(slot_atom)
1932 if not portage.match_from_list(mydep, replacement):
1933 # Apparently a replacement may be able to
1934 # invalidate this block.
1935 replacement_node = \
1936 self.pkg_node_map[proot][replacement[0]]
1937 depends_on_order.add((replacement_node, parent))
1939 # None of the above blocker resolutions techniques apply,
1940 # so apparently this one is unresolvable.
1941 unresolved_blocks = True
1942 for cpv in blocked_final:
1943 slot_atom = blocked_slots_final[cpv]
1944 if slot_atom == pslot_atom:
1945 # TODO: Support blocks within slots.
1947 if parent_static and \
1948 slot_atom not in modified_slots[myroot]:
1949 # This blocker will be handled the next time that a
1950 # merge of either package is triggered.
1952 if not parent_static and pstatus == "nomerge" and \
1953 slot_atom in modified_slots[myroot]:
1954 replacement = final_db.match(pslot_atom)
1956 replacement_node = \
1957 self.pkg_node_map[proot][replacement[0]]
1958 if replacement_node not in \
1959 self.blocker_parents[blocker]:
1960 # Apparently a replacement may be able to
1961 # invalidate this block.
1962 blocked_node = self.pkg_node_map[proot][cpv]
1963 depends_on_order.add(
1964 (replacement_node, blocked_node))
1966 # None of the above blocker resolutions techniques apply,
1967 # so apparently this one is unresolvable.
1968 unresolved_blocks = True
1969 if not unresolved_blocks and depends_on_order:
1970 for node, pnode in depends_on_order:
1971 # Enforce correct merge order with a hard dep.
1972 self.digraph.addnode(node, pnode,
1973 priority=DepPriority(buildtime=True))
1974 # Count references to this blocker so that it can be
1975 # invalidated after nodes referencing it have been
1977 self.blocker_digraph.addnode(node, blocker)
1978 if not unresolved_blocks and not depends_on_order:
1979 self.blocker_parents[blocker].remove(parent)
1980 if unresolved_blocks:
1981 self._unresolved_blocker_parents.setdefault(
1982 blocker, set()).add(parent)
1983 if not self.blocker_parents[blocker]:
1984 del self.blocker_parents[blocker]
1985 # Validate blockers that depend on merge order.
1986 if not self.blocker_digraph.empty():
1988 if self._slot_collision_info:
1989 # The user is only notified of a slot collision if there are no
1990 # unresolvable blocks.
1991 for x in self.altlist():
1992 if x[0] == "blocks":
1994 self._show_slot_collision_notice(self._slot_collision_info[0])
1995 if not self._accept_collisions():
1999 def _accept_collisions(self):
2001 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
2002 if x in self.myopts:
2007 def _merge_order_bias(self, mygraph):
2008 """Order nodes from highest to lowest overall reference count for
2009 optimal leaf node selection."""
2011 for node in mygraph.order:
2012 node_info[node] = len(mygraph.parent_nodes(node))
2013 def cmp_merge_preference(node1, node2):
2014 return node_info[node2] - node_info[node1]
2015 mygraph.order.sort(cmp_merge_preference)
2017 def altlist(self, reversed=False):
2018 if reversed in self._altlist_cache:
2019 return self._altlist_cache[reversed][:]
2021 retlist = self.altlist()
2023 self._altlist_cache[reversed] = retlist[:]
2025 mygraph=self.digraph.copy()
2026 self._merge_order_bias(mygraph)
2027 myblockers = self.blocker_digraph.copy()
2029 circular_blocks = False
2033 get_nodes = mygraph.root_nodes
2035 get_nodes = mygraph.leaf_nodes
2036 for cpv, node in self.pkg_node_map["/"].iteritems():
2037 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
2038 asap_nodes.append(node)
2040 ignore_priority_range = [None]
2041 ignore_priority_range.extend(
2042 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2043 tree_mode = "--tree" in self.myopts
2044 while not mygraph.empty():
2045 ignore_priority = None
2048 """ASAP nodes are merged before their soft deps."""
2049 for node in asap_nodes:
2050 if not mygraph.contains(node):
2051 asap_nodes.remove(node)
2053 if not mygraph.child_nodes(node,
2054 ignore_priority=DepPriority.SOFT):
2056 asap_nodes.remove(node)
2059 for ignore_priority in ignore_priority_range:
2060 nodes = get_nodes(ignore_priority=ignore_priority)
2063 selected_nodes = None
2065 if ignore_priority <= DepPriority.SOFT:
2066 if ignore_priority is None and not tree_mode:
2067 # Greedily pop all of these nodes since no relationship
2068 # has been ignored. This optimization destroys --tree
2069 # output, so it's disabled in reversed mode.
2070 selected_nodes = nodes
2072 # For optimal merge order:
2073 # * Only pop one node.
2074 # * Removing a root node (node without a parent)
2075 # will not produce a leaf node, so avoid it.
2077 if mygraph.parent_nodes(node):
2078 # found a non-root node
2079 selected_nodes = [node]
2081 if not selected_nodes:
2082 # settle for a root node
2083 selected_nodes = [nodes[0]]
2085 """Recursively gather a group of nodes that RDEPEND on
2086 eachother. This ensures that they are merged as a group
2087 and get their RDEPENDs satisfied as soon as possible."""
2088 def gather_deps(mergeable_nodes, selected_nodes, node):
2089 if node in selected_nodes:
2091 if node not in mergeable_nodes:
2093 selected_nodes.add(node)
2094 for child in mygraph.child_nodes(node,
2095 ignore_priority=DepPriority.SOFT):
2097 mergeable_nodes, selected_nodes, child):
2100 mergeable_nodes = set(nodes)
2102 selected_nodes = set()
2104 mergeable_nodes, selected_nodes, node):
2107 selected_nodes = None
2109 if not selected_nodes:
2110 if not myblockers.is_empty():
2111 """A blocker couldn't be circumnavigated while keeping all
2112 dependencies satisfied. The user will have to resolve this
2113 manually. This is a panic condition and thus the order
2114 doesn't really matter, so just pop a random node in order
2115 to avoid a circular dependency panic if possible."""
2116 if not circular_blocks:
2117 circular_blocks = True
2118 blocker_deps = myblockers.leaf_nodes()
2120 selected_nodes = [blocker_deps.pop()]
2122 if not selected_nodes:
2123 # No leaf nodes are available, so we have a circular
2124 # dependency panic situation. Reduce the noise level to a
2125 # minimum via repeated elimination of root nodes since they
2126 # have no parents and thus can not be part of a cycle.
2128 root_nodes = mygraph.root_nodes(
2129 ignore_priority=DepPriority.SOFT)
2132 for node in root_nodes:
2133 mygraph.remove(node)
2134 # Display the USE flags that are enabled on nodes that are part
2135 # of dependency cycles in case that helps the user decide to
2136 # disable some of them.
2138 tempgraph = mygraph.copy()
2139 while not tempgraph.empty():
2140 nodes = tempgraph.leaf_nodes()
2142 node = tempgraph.order[0]
2145 display_order.append(list(node))
2146 tempgraph.remove(node)
2147 display_order.reverse()
2148 self.myopts.pop("--quiet", None)
2149 self.myopts.pop("--verbose", None)
2150 self.myopts["--tree"] = True
2151 self.display(display_order)
2152 print "!!! Error: circular dependencies:"
2154 mygraph.debug_print()
2156 print "!!! Note that circular dependencies can often be avoided by temporarily"
2157 print "!!! disabling USE flags that trigger optional dependencies."
2160 for node in selected_nodes:
2161 retlist.append(list(node))
2162 mygraph.remove(node)
2163 if not reversed and not circular_blocks and myblockers.contains(node):
2164 """This node may have invalidated one or more blockers."""
2165 myblockers.remove(node)
2166 for blocker in myblockers.root_nodes():
2167 if not myblockers.child_nodes(blocker):
2168 myblockers.remove(blocker)
2170 self._unresolved_blocker_parents.get(blocker)
2172 self.blocker_parents[blocker] = unresolved
2174 del self.blocker_parents[blocker]
2177 """Blocker validation does not work with reverse mode,
2178 so self.altlist() should first be called with reverse disabled
2179 so that blockers are properly validated."""
2180 self.blocker_digraph = myblockers
2182 """ Add any unresolved blocks so that they can be displayed."""
2183 for blocker in self.blocker_parents:
2184 retlist.append(list(blocker))
2185 self._altlist_cache[reversed] = retlist[:]
2188 def xcreate(self,mode="system"):
2189 vardb = self.trees[self.target_root]["vartree"].dbapi
2190 portdb = self.trees[self.target_root]["porttree"].dbapi
2191 bindb = self.trees[self.target_root]["bintree"].dbapi
2192 def visible(mylist):
2193 matches = portdb.gvisible(portdb.visible(mylist))
2194 return [x for x in mylist \
2195 if x in matches or not portdb.cpv_exists(x)]
2196 world_problems = False
2198 mylist = getlist(self.settings, "system")
2201 worldlist = getlist(self.settings, "world")
2202 mylist = getlist(self.settings, "system")
2203 worlddict=genericdict(worldlist)
2205 for x in worlddict.keys():
2206 if not portage.isvalidatom(x):
2207 world_problems = True
2208 elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
2209 world_problems = True
2215 mykey = portage.dep_getkey(atom)
2217 newlist.append(atom)
2218 """Make sure all installed slots are updated when possible.
2219 Do this with --emptytree also, to ensure that all slots are
2222 for cpv in vardb.match(mykey):
2223 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2226 if "--usepkg" in self.myopts:
2227 mymatches = bindb.match(atom)
2228 if "--usepkgonly" not in self.myopts:
2229 mymatches = visible(mymatches)
2230 best_pkg = portage.best(mymatches)
2232 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2233 best_pkgs.append(("binary", best_pkg, best_slot))
2234 if "--usepkgonly" not in self.myopts:
2235 best_pkg = portage.best(portdb.match(atom))
2237 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2238 best_pkgs.append(("ebuild", best_pkg, best_slot))
2240 best_pkg = portage.best([x[1] for x in best_pkgs])
2241 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2242 best_slot = best_pkgs[0][2]
2243 myslots.add(best_slot)
2244 if len(myslots) > 1:
2245 for myslot in myslots:
2246 myslot_atom = "%s:%s" % (mykey, myslot)
2248 if "--usepkgonly" not in self.myopts and \
2249 self.trees[self.target_root][
2250 "porttree"].dbapi.match(myslot_atom):
2252 elif "--usepkg" in self.myopts:
2253 mymatches = bindb.match(myslot_atom)
2254 if "--usepkgonly" not in self.myopts:
2255 mymatches = visible(mymatches)
2259 newlist.append(myslot_atom)
2263 for mydep in mylist:
2265 if not self.select_dep(
2266 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2267 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2270 missing_atoms.append(mydep)
2272 if not self.validate_blockers():
2276 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2277 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2280 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2281 " Ebuilds for the following packages are either all"
2282 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2283 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2287 def display(self,mylist,verbosity=None):
2288 if verbosity is None:
2289 verbosity = ("--quiet" in self.myopts and 1 or \
2290 "--verbose" in self.myopts and 3 or 2)
2295 counters = PackageCounters()
2297 if verbosity == 1 and "--verbose" not in self.myopts:
2298 def create_use_string(*args):
2301 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2303 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2304 alphabetical=("--alphabetical" in self.myopts)):
2312 cur_iuse = set(cur_iuse)
2313 enabled_flags = cur_iuse.intersection(cur_use)
2314 removed_iuse = set(old_iuse).difference(cur_iuse)
2315 any_iuse = cur_iuse.union(old_iuse)
2316 any_iuse = list(any_iuse)
2318 for flag in any_iuse:
2321 if flag in enabled_flags:
2323 if is_new or flag in old_use and all_flags:
2324 flag_str = red(flag)
2325 elif flag not in old_iuse:
2326 flag_str = yellow(flag) + "%*"
2327 elif flag not in old_use:
2328 flag_str = green(flag) + "*"
2329 elif flag in removed_iuse:
2331 flag_str = yellow("-" + flag) + "%"
2334 flag_str = "(" + flag_str + ")"
2335 removed.append(flag_str)
2338 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2339 flag_str = blue("-" + flag)
2340 elif flag not in old_iuse:
2341 flag_str = yellow("-" + flag)
2342 if flag not in iuse_forced:
2344 elif flag in old_use:
2345 flag_str = green("-" + flag) + "*"
2347 if flag in iuse_forced:
2348 flag_str = "(" + flag_str + ")"
2350 enabled.append(flag_str)
2352 disabled.append(flag_str)
2355 ret = " ".join(enabled)
2357 ret = " ".join(enabled + disabled + removed)
2359 ret = '%s="%s" ' % (name, ret)
2363 # FIXME: account for the possibility of different overlays in
2364 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2365 overlays = self.settings["PORTDIR_OVERLAY"].split()
2366 overlays_real = [os.path.realpath(t) \
2367 for t in self.settings["PORTDIR_OVERLAY"].split()]
2371 mygraph = self._parent_child_digraph
2375 if "blocks" == x[0]:
2376 display_list.append((x, 0, True))
2378 graph_key = tuple(x)
2379 if "--tree" in self.myopts:
2380 depth = len(tree_nodes)
2381 while depth and graph_key not in \
2382 mygraph.child_nodes(tree_nodes[depth-1]):
2385 tree_nodes = tree_nodes[:depth]
2386 tree_nodes.append(graph_key)
2387 display_list.append((x, depth, True))
2389 traversed_nodes = set() # prevent endless circles
2390 traversed_nodes.add(graph_key)
2391 def add_parents(current_node, ordered):
2392 parent_nodes = mygraph.parent_nodes(current_node)
2394 child_nodes = set(mygraph.child_nodes(current_node))
2395 selected_parent = None
2396 # First, try to avoid a direct cycle.
2397 for node in parent_nodes:
2398 if node not in traversed_nodes and \
2399 node not in child_nodes:
2400 selected_parent = node
2402 if not selected_parent:
2403 # A direct cycle is unavoidable.
2404 for node in parent_nodes:
2405 if node not in traversed_nodes:
2406 selected_parent = node
2409 traversed_nodes.add(selected_parent)
2410 add_parents(selected_parent, False)
2411 display_list.append((list(current_node),
2412 len(tree_nodes), ordered))
2413 tree_nodes.append(current_node)
2415 add_parents(graph_key, True)
2417 display_list.append((x, depth, True))
2418 mylist = display_list
2420 last_merge_depth = 0
2421 for i in xrange(len(mylist)-1,-1,-1):
2422 graph_key, depth, ordered = mylist[i]
2423 if not ordered and depth == 0 and i > 0 \
2424 and graph_key == mylist[i-1][0] and \
2425 mylist[i-1][1] == 0:
2426 # An ordered node got a consecutive duplicate when the tree was
2430 if "blocks" == graph_key[0]:
2432 if ordered and graph_key[-1] != "nomerge":
2433 last_merge_depth = depth
2435 if depth >= last_merge_depth or \
2436 i < len(mylist) - 1 and \
2437 depth >= mylist[i+1][1]:
2440 display_overlays=False
2441 # files to fetch list - avoids counting a same file twice
2442 # in size display (verbose mode)
2444 for mylist_index in xrange(len(mylist)):
2445 x, depth, ordered = mylist[mylist_index]
2449 portdb = self.trees[myroot]["porttree"].dbapi
2450 bindb = self.trees[myroot]["bintree"].dbapi
2451 vardb = self.trees[myroot]["vartree"].dbapi
2452 vartree = self.trees[myroot]["vartree"]
2453 pkgsettings = self.pkgsettings[myroot]
2458 addl=""+red("B")+" "+fetch+" "
2460 counters.blocks += 1
2461 resolved = portage.key_expand(
2462 pkg_key, mydb=vardb, settings=pkgsettings)
2463 if "--columns" in self.myopts and "--quiet" in self.myopts:
2464 addl = addl + " " + red(resolved)
2466 addl = "[blocks " + addl + "] " + red(resolved)
2467 block_parents = self.blocker_parents[tuple(x)]
2468 block_parents = set([pnode[2] for pnode in block_parents])
2469 block_parents = ", ".join(block_parents)
2471 addl += bad(" (\"%s\" is blocking %s)") % \
2472 (pkg_key, block_parents)
2474 addl += bad(" (is blocking %s)") % block_parents
2475 blockers.append(addl)
2477 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2478 binary_package = True
2479 if "ebuild" == pkg_type:
2480 if "merge" == x[3] or \
2481 not vartree.dbapi.cpv_exists(pkg_key):
2482 """An ebuild "merge" node or a --onlydeps "nomerge"
2484 binary_package = False
2485 pkgsettings.setcpv(pkg_key, mydb=portdb)
2486 if pkg_key not in self.useFlags[myroot]:
2487 self.useFlags[myroot][pkg_key] = \
2488 pkgsettings["USE"].split()
2490 # An ebuild "nomerge" node, so USE come from the vardb.
2491 mydbapi = vartree.dbapi
2492 if pkg_key not in self.useFlags[myroot]:
2493 """If this is a --resume then the USE flags need to be
2494 fetched from the appropriate locations here."""
2495 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2496 pkg_key, ["USE"])[0].split()
2498 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2499 "fetch" in portdb.aux_get(
2500 x[2], ["RESTRICT"])[0].split():
2503 counters.restrict_fetch += 1
2504 if portdb.fetch_check(
2505 pkg_key, self.useFlags[myroot][pkg_key]):
2508 counters.restrict_fetch_satisfied += 1
2510 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2511 #param is used for -u, where you still *do* want to see when something is being upgraded.
2513 if vardb.cpv_exists(pkg_key):
2514 addl=" "+yellow("R")+fetch+" "
2515 if x[3] != "nomerge":
2517 counters.reinst += 1
2518 elif vardb.match(portage.dep_getkey(pkg_key)):
2519 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2520 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2521 portage.pkgsplit(x[2])[0])
2522 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2523 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2525 myoldbest=portage.best(myinslotlist)
2527 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2529 addl+=turquoise("U")+blue("D")
2531 counters.downgrades += 1
2534 addl+=turquoise("U")+" "
2536 counters.upgrades += 1
2538 # New slot, mark it new.
2539 addl=" "+green("NS")+fetch+" "
2541 counters.newslot += 1
2543 if "--changelog" in self.myopts:
2544 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2545 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2546 inst_matches = vardb.match(slot_atom)
2548 changelogs.extend(self.calc_changelog(
2549 portdb.findname(pkg_key),
2550 inst_matches[0], pkg_key))
2552 addl=" "+green("N")+" "+fetch+" "
2558 if pkg_key in self.useFlags[myroot]:
2560 cur_iuse = list(filter_iuse_defaults(
2561 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2563 forced_flags = set()
2564 if not binary_package:
2565 forced_flags.update(pkgsettings.useforce)
2566 forced_flags.update(pkgsettings.usemask)
2568 cur_iuse = portage.unique_array(cur_iuse)
2570 cur_use = self.useFlags[myroot][pkg_key]
2571 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2577 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2578 old_iuse, old_use = \
2579 self.trees[x[1]]["vartree"].dbapi.aux_get(
2580 pkg, ["IUSE", "USE"])
2581 old_iuse = list(set(
2582 filter_iuse_defaults(old_iuse.split())))
2584 old_use = old_use.split()
2591 old_use = [flag for flag in old_use if flag in old_iuse]
2593 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2595 use_expand.reverse()
2596 use_expand_hidden = \
2597 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2599 def map_to_use_expand(myvals, forcedFlags=False):
2602 for exp in use_expand:
2605 for val in myvals[:]:
2606 if val.startswith(exp.lower()+"_"):
2607 if val in forced_flags:
2608 forced[exp].add(val[len(exp)+1:])
2609 ret[exp].append(val[len(exp)+1:])
2612 forced["USE"] = [val for val in myvals \
2613 if val in forced_flags]
2614 for exp in use_expand_hidden:
2621 cur_iuse_map, iuse_forced = \
2622 map_to_use_expand(cur_iuse, forcedFlags=True)
2623 cur_use_map = map_to_use_expand(cur_use)
2624 old_iuse_map = map_to_use_expand(old_iuse)
2625 old_use_map = map_to_use_expand(old_use)
2628 use_expand.insert(0, "USE")
2630 for key in use_expand:
2631 if key in use_expand_hidden:
2633 verboseadd += create_use_string(key.upper(),
2634 cur_iuse_map[key], iuse_forced[key],
2635 cur_use_map[key], old_iuse_map[key],
2636 old_use_map[key], is_new)
2641 if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
2643 myfilesdict = portdb.getfetchsizes(pkg_key,
2644 useflags=self.useFlags[myroot][pkg_key],
2646 except portage.exception.InvalidDependString, e:
2647 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2648 show_invalid_depstring_notice(x, src_uri, str(e))
2651 if myfilesdict is None:
2652 myfilesdict="[empty/missing/bad digest]"
2654 for myfetchfile in myfilesdict.keys():
2655 if myfetchfile not in myfetchlist:
2656 mysize+=myfilesdict[myfetchfile]
2657 myfetchlist.append(myfetchfile)
2658 counters.totalsize += mysize
2659 verboseadd+=format_size(mysize)+" "
2662 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2663 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2664 file_name = portdb.findname(pkg_key)
2665 if file_name: # It might not exist in the tree
2666 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2667 if (overlays_real.count(dir_name)>0):
2668 verboseadd+=teal("["+str(overlays_real.index(
2669 os.path.normpath(dir_name))+1)+"]")+" "
2670 display_overlays=True
2672 verboseadd += "[No ebuild?]"
2674 xs=portage.pkgsplit(x[2])
2681 if "COLUMNWIDTH" in self.settings:
2683 mywidth = int(self.settings["COLUMNWIDTH"])
2684 except ValueError, e:
2685 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2687 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2688 self.settings["COLUMNWIDTH"], noiselevel=-1)
2693 indent = " " * depth
2696 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2697 if myoldbest[-3:]=="-r0":
2698 myoldbest=myoldbest[:-3]
2699 myoldbest=blue("["+myoldbest+"]")
2704 if "--columns" in self.myopts:
2705 if "--quiet" in self.myopts:
2706 myprint=addl+" "+indent+darkgreen(xs[0])
2707 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2708 myprint=myprint+myoldbest
2709 myprint=myprint+darkgreen("to "+x[1])
2711 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2712 if (newlp-nc_len(myprint)) > 0:
2713 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2714 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2715 if (oldlp-nc_len(myprint)) > 0:
2716 myprint=myprint+" "*(oldlp-nc_len(myprint))
2717 myprint=myprint+myoldbest
2718 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2720 if x[-1] == "nomerge" or not ordered:
2721 myprint = darkblue("[nomerge ] ")
2723 myprint = "[" + pkg_type + " " + addl + "] "
2724 myprint += indent + darkgreen(pkg_key) + " " + \
2725 myoldbest + darkgreen("to " + myroot) + " " + \
2728 if "--columns" in self.myopts:
2729 if "--quiet" in self.myopts:
2730 myprint=addl+" "+indent+darkgreen(xs[0])
2731 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2732 myprint=myprint+myoldbest
2734 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2735 if (newlp-nc_len(myprint)) > 0:
2736 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2737 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2738 if (oldlp-nc_len(myprint)) > 0:
2739 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2740 myprint=myprint+myoldbest+" "+verboseadd
2742 if x[-1] == "nomerge" or not ordered:
2743 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2745 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2748 mysplit = portage.pkgsplit(x[2])
2749 if "--tree" not in self.myopts and mysplit and \
2750 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2753 if mysplit[2] == "r0":
2754 myversion = mysplit[1]
2756 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2758 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2759 if mylist_index < len(mylist) - 1 and \
2760 "livecvsportage" not in self.settings.features:
2761 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2762 p.append(colorize("WARN", " then resume the merge."))
2774 if overlays and display_overlays:
2775 print "Portage overlays:"
2779 print " "+teal("["+str(y)+"]"),x
2781 if "--changelog" in self.myopts:
2783 for revision,text in changelogs:
2784 print bold('*'+revision)
2785 sys.stdout.write(text)
2787 if self._pprovided_args:
2789 msg.append(bad("\nWARNING: "))
2790 if len(self._pprovided_args) > 1:
2791 msg.append("Requested packages will not be " + \
2792 "merged because they are listed in\n")
2794 msg.append("A requested package will not be " + \
2795 "merged because it is listed in\n")
2796 msg.append(" package.provided:\n\n")
2797 for arg in self._pprovided_args:
2798 msg.append(" " + arg + "\n")
2800 sys.stderr.write("".join(msg))
2802 def calc_changelog(self,ebuildpath,current,next):
2803 current = '-'.join(portage.catpkgsplit(current)[1:])
2804 if current.endswith('-r0'): current = current[:-3]
2805 next = '-'.join(portage.catpkgsplit(next)[1:])
2806 if next.endswith('-r0'): next = next[:-3]
2807 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2809 changelog = open(changelogpath).read()
2810 except SystemExit, e:
2811 raise # Needed else can't exit
2814 divisions = self.find_changelog_tags(changelog)
2815 #print 'XX from',current,'to',next
2816 #for div,text in divisions: print 'XX',div
2817 # skip entries for all revisions above the one we are about to emerge
2818 for i in range(len(divisions)):
2819 if divisions[i][0]==next:
2820 divisions = divisions[i:]
2822 # find out how many entries we are going to display
2823 for i in range(len(divisions)):
2824 if divisions[i][0]==current:
2825 divisions = divisions[:i]
2828 # couldnt find the current revision in the list. display nothing
2832 def find_changelog_tags(self,changelog):
2836 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2838 if release is not None:
2839 divs.append((release,changelog))
2841 if release is not None:
2842 divs.append((release,changelog[:match.start()]))
2843 changelog = changelog[match.end():]
2844 release = match.group(1)
2845 if release.endswith('.ebuild'):
2846 release = release[:-7]
2847 if release.endswith('-r0'):
2848 release = release[:-3]
2851 return self.outdatedpackages
2853 class PackageCounters(object):
2863 self.restrict_fetch = 0
2864 self.restrict_fetch_satisfied = 0
2867 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2870 myoutput.append("Total: %s package" % total_installs)
2871 if total_installs != 1:
2872 myoutput.append("s")
2873 if total_installs != 0:
2874 myoutput.append(" (")
2875 if self.upgrades > 0:
2876 details.append("%s upgrade" % self.upgrades)
2877 if self.upgrades > 1:
2879 if self.downgrades > 0:
2880 details.append("%s downgrade" % self.downgrades)
2881 if self.downgrades > 1:
2884 details.append("%s new" % self.new)
2885 if self.newslot > 0:
2886 details.append("%s in new slot" % self.newslot)
2887 if self.newslot > 1:
2890 details.append("%s reinstall" % self.reinst)
2894 details.append("%s block" % self.blocks)
2897 myoutput.append(", ".join(details))
2898 if total_installs != 0:
2899 myoutput.append(")")
2900 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2901 if self.restrict_fetch:
2902 myoutput.append("\nFetch Restriction: %s package" % \
2903 self.restrict_fetch)
2904 if self.restrict_fetch > 1:
2905 myoutput.append("s")
2906 if self.restrict_fetch_satisfied < self.restrict_fetch:
2907 myoutput.append(bad(" (%s unsatisfied)") % \
2908 (self.restrict_fetch - self.restrict_fetch_satisfied))
2909 return "".join(myoutput)
2911 class MergeTask(object):
2913 def __init__(self, settings, trees, myopts):
2914 self.settings = settings
2915 self.target_root = settings["ROOT"]
2917 self.myopts = myopts
2919 if settings.get("PORTAGE_DEBUG", "") == "1":
2921 self.pkgsettings = {}
2922 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2923 if self.target_root != "/":
2924 self.pkgsettings["/"] = \
2925 portage.config(clone=trees["/"]["vartree"].settings)
2927 def merge(self, mylist, favorites, mtimedb):
2930 ldpath_mtimes = mtimedb["ldpath"]
2931 xterm_titles = "notitles" not in self.settings.features
2933 #check for blocking dependencies
2934 if "--fetchonly" not in self.myopts and \
2935 "--fetch-all-uri" not in self.myopts and \
2936 "--buildpkgonly" not in self.myopts:
2939 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2940 print "!!! the two packages cannot be installed on the same system together."
2941 print "!!! Please use 'emerge --pretend' to determine blockers."
2942 if "--quiet" not in self.myopts:
2943 show_blocker_docs_link()
2946 if "--resume" in self.myopts:
2948 print colorize("GOOD", "*** Resuming merge...")
2949 emergelog(xterm_titles, " *** Resuming merge...")
2950 mylist = mtimedb["resume"]["mergelist"][:]
2951 if "--skipfirst" in self.myopts and mylist:
2952 del mtimedb["resume"]["mergelist"][0]
2955 validate_merge_list(self.trees, mylist)
2956 mymergelist = mylist
2958 # Verify all the manifests now so that the user is notified of failure
2959 # as soon as possible.
2960 if "--fetchonly" not in self.myopts and \
2961 "--fetch-all-uri" not in self.myopts and \
2962 "strict" in self.settings.features:
2963 shown_verifying_msg = False
2965 for myroot, pkgsettings in self.pkgsettings.iteritems():
2966 quiet_config = portage.config(clone=pkgsettings)
2967 quiet_config["PORTAGE_QUIET"] = "1"
2968 quiet_config.backup_changes("PORTAGE_QUIET")
2969 quiet_settings[myroot] = quiet_config
2972 if x[0] != "ebuild" or x[-1] == "nomerge":
2974 if not shown_verifying_msg:
2975 shown_verifying_msg = True
2976 print ">>> Verifying ebuild Manifests..."
2977 mytype, myroot, mycpv, mystatus = x
2978 portdb = self.trees[myroot]["porttree"].dbapi
2979 quiet_config = quiet_settings[myroot]
2980 quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
2981 if not portage.digestcheck([], quiet_config, strict=True):
2983 del x, mytype, myroot, mycpv, mystatus, quiet_config
2984 del shown_verifying_msg, quiet_settings
2986 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
2987 mysysdict = genericdict(getlist(self.settings, "system"))
2988 if "--resume" not in self.myopts:
2989 myfavs = portage.grabfile(
2990 os.path.join(self.target_root, portage.WORLD_FILE))
2991 myfavdict=genericdict(myfavs)
2992 for x in range(len(mylist)):
2993 if mylist[x][3]!="nomerge":
2994 # Add to the mergelist
2995 mymergelist.append(mylist[x])
2997 myfavkey=portage.cpv_getkey(mylist[x][2])
2998 if "--onlydeps" in self.myopts:
3000 # Add to the world file. Since we won't be able to later.
3001 if "--fetchonly" not in self.myopts and \
3002 myfavkey in favorites:
3003 #don't record if already in system profile or already recorded
3004 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3005 #we don't have a favorites entry for this package yet; add one
3006 myfavdict[myfavkey]=myfavkey
3007 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3008 if not ("--fetchonly" in self.myopts or \
3009 "--fetch-all-uri" in self.myopts or \
3010 "--pretend" in self.myopts):
3011 portage.write_atomic(
3012 os.path.join(self.target_root, portage.WORLD_FILE),
3013 "\n".join(myfavdict.values()))
3015 mtimedb["resume"]["mergelist"]=mymergelist[:]
3018 myfeat = self.settings.features[:]
3019 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3021 if "parallel-fetch" in myfeat and \
3022 not ("--pretend" in self.myopts or \
3023 "--fetch-all-uri" in self.myopts or \
3024 "--fetchonly" in self.myopts):
3025 if "distlocks" not in myfeat:
3027 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
3028 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
3030 elif len(mymergelist) > 1:
3031 print ">>> starting parallel fetching"
3032 fetch_log = "/var/log/emerge-fetch.log"
3033 logfile = open(fetch_log, "w")
3034 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3035 portage.util.apply_secpass_permissions(fetch_log,
3036 uid=portage.portage_uid, gid=portage.portage_gid,
3038 fetch_env = os.environ.copy()
3039 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3040 fetch_env["PORTAGE_NICENESS"] = "0"
3041 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3042 resume_opts = self.myopts.copy()
3043 # For automatic resume, we need to prevent
3044 # any of bad_resume_opts from leaking in
3045 # via EMERGE_DEFAULT_OPTS.
3046 resume_opts["--ignore-default-opts"] = True
3047 for myopt, myarg in resume_opts.iteritems():
3048 if myopt not in bad_resume_opts:
3050 fetch_args.append(myopt)
3052 fetch_args.append(myopt +"="+ myarg)
3053 portage.process.spawn(fetch_args, env=fetch_env,
3054 fd_pipes=fd_pipes, returnpid=True)
3055 logfile.close() # belongs to the spawned process
3056 del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3060 for x in mymergelist:
3065 portdb = self.trees[myroot]["porttree"].dbapi
3066 bindb = self.trees[myroot]["bintree"].dbapi
3067 vartree = self.trees[myroot]["vartree"]
3068 pkgsettings = self.pkgsettings[myroot]
3071 y = portdb.findname(pkg_key)
3072 if "--pretend" not in self.myopts:
3073 print "\n>>> Emerging (" + \
3074 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3075 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3076 colorize("GOOD", x[pkgindex]) + " to " + x[1]
3077 emergelog(xterm_titles, " >>> emerge ("+\
3078 str(mergecount)+" of "+str(len(mymergelist))+\
3079 ") "+x[pkgindex]+" to "+x[1])
3081 pkgsettings["EMERGE_FROM"] = x[0]
3082 pkgsettings.backup_changes("EMERGE_FROM")
3085 #buildsyspkg: Check if we need to _force_ binary package creation
3086 issyspkg = ("buildsyspkg" in myfeat) \
3087 and x[0] != "blocks" \
3088 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3089 and "--buildpkg" not in self.myopts
3090 if x[0] in ["ebuild","blocks"]:
3091 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3092 raise Exception, "Merging a blocker"
3093 elif "--fetchonly" in self.myopts or \
3094 "--fetch-all-uri" in self.myopts:
3095 if "--fetch-all-uri" in self.myopts:
3096 retval = portage.doebuild(y, "fetch", myroot,
3097 pkgsettings, self.edebug,
3098 "--pretend" in self.myopts, fetchonly=1,
3099 fetchall=1, mydbapi=portdb, tree="porttree")
3101 retval = portage.doebuild(y, "fetch", myroot,
3102 pkgsettings, self.edebug,
3103 "--pretend" in self.myopts, fetchonly=1,
3104 mydbapi=portdb, tree="porttree")
3105 if (retval is None) or retval:
3107 print "!!! Fetch for",y,"failed, continuing..."
3109 failed_fetches.append(pkg_key)
3112 portage.doebuild_environment(y, "setup", myroot,
3113 pkgsettings, self.edebug, 1, portdb)
3114 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3115 portage.util.ensure_dirs(os.path.dirname(catdir),
3116 uid=portage.portage_uid, gid=portage.portage_gid,
3118 builddir_lock = None
3121 catdir_lock = portage.locks.lockdir(catdir)
3122 portage.util.ensure_dirs(catdir,
3123 uid=portage.portage_uid, gid=portage.portage_gid,
3125 builddir_lock = portage.locks.lockdir(
3126 pkgsettings["PORTAGE_BUILDDIR"])
3128 portage.locks.unlockdir(catdir_lock)
3131 msg = " === (%s of %s) Cleaning (%s::%s)" % \
3132 (mergecount, len(mymergelist), pkg_key, y)
3133 short_msg = "emerge: (%s of %s) %s Clean" % \
3134 (mergecount, len(mymergelist), pkg_key)
3135 emergelog(xterm_titles, msg, short_msg=short_msg)
3136 retval = portage.doebuild(y, "clean", myroot,
3137 pkgsettings, self.edebug, cleanup=1,
3138 mydbapi=portdb, tree="porttree")
3139 if retval != os.EX_OK:
3141 if "--buildpkg" in self.myopts or issyspkg:
3143 print ">>> This is a system package, " + \
3144 "let's pack a rescue tarball."
3145 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3146 (mergecount, len(mymergelist), pkg_key, y)
3147 short_msg = "emerge: (%s of %s) %s Compile" % \
3148 (mergecount, len(mymergelist), pkg_key)
3149 emergelog(xterm_titles, msg, short_msg=short_msg)
3150 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3151 retval = portage.doebuild(y, "package", myroot,
3152 pkgsettings, self.edebug, mydbapi=portdb,
3154 if retval != os.EX_OK:
3156 bintree = self.trees[myroot]["bintree"]
3157 if bintree.populated:
3158 bintree.inject(pkg_key)
3159 if "--buildpkgonly" not in self.myopts:
3160 msg = " === (%s of %s) Merging (%s::%s)" % \
3161 (mergecount, len(mymergelist), pkg_key, y)
3162 short_msg = "emerge: (%s of %s) %s Merge" % \
3163 (mergecount, len(mymergelist), pkg_key)
3164 emergelog(xterm_titles, msg, short_msg=short_msg)
3165 retval = portage.merge(pkgsettings["CATEGORY"],
3166 pkgsettings["PF"], pkgsettings["D"],
3167 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3168 "build-info"), myroot, pkgsettings,
3169 myebuild=pkgsettings["EBUILD"],
3170 mytree="porttree", mydbapi=portdb,
3171 vartree=vartree, prev_mtimes=ldpath_mtimes)
3172 if retval != os.EX_OK:
3174 elif "noclean" not in pkgsettings.features:
3175 portage.doebuild(y, "clean", myroot,
3176 pkgsettings, self.edebug, mydbapi=portdb,
3179 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3180 (mergecount, len(mymergelist), pkg_key, y)
3181 short_msg = "emerge: (%s of %s) %s Compile" % \
3182 (mergecount, len(mymergelist), pkg_key)
3183 emergelog(xterm_titles, msg, short_msg=short_msg)
3184 retval = portage.doebuild(y, "merge", myroot,
3185 pkgsettings, self.edebug, vartree=vartree,
3186 mydbapi=portdb, tree="porttree",
3187 prev_mtimes=ldpath_mtimes)
3188 if retval != os.EX_OK:
3192 portage.locks.unlockdir(builddir_lock)
3195 # Lock catdir for removal if empty.
3196 catdir_lock = portage.locks.lockdir(catdir)
3202 if e.errno not in (errno.ENOENT,
3203 errno.ENOTEMPTY, errno.EEXIST):
3206 portage.locks.unlockdir(catdir_lock)
3208 elif x[0]=="binary":
3210 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3211 if "--getbinpkg" in self.myopts:
3214 if "distlocks" in pkgsettings.features and \
3215 os.access(pkgsettings["PKGDIR"], os.W_OK):
3216 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3217 tbz2_lock = portage.locks.lockfile(mytbz2,
3219 if self.trees[myroot]["bintree"].isremote(pkg_key):
3220 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3221 (mergecount, len(mymergelist), pkg_key, mytbz2)
3222 short_msg = "emerge: (%s of %s) %s Fetch" % \
3223 (mergecount, len(mymergelist), pkg_key)
3224 emergelog(xterm_titles, msg, short_msg=short_msg)
3225 if not self.trees[myroot]["bintree"].gettbz2(
3230 portage.locks.unlockfile(tbz2_lock)
3232 if "--fetchonly" in self.myopts or \
3233 "--fetch-all-uri" in self.myopts:
3236 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3237 emergelog(xterm_titles, " === ("+str(mergecount)+\
3238 " of "+str(len(mymergelist))+") Merging Binary ("+\
3239 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3240 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3242 vartree=self.trees[myroot]["vartree"],
3243 prev_mtimes=ldpath_mtimes)
3244 if retval != os.EX_OK:
3246 #need to check for errors
3247 if "--buildpkgonly" not in self.myopts:
3248 self.trees[x[1]]["vartree"].inject(x[2])
3249 myfavkey=portage.cpv_getkey(x[2])
3250 if "--fetchonly" not in self.myopts and \
3251 "--fetch-all-uri" not in self.myopts and \
3252 myfavkey in favorites:
3253 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3254 myfavdict=genericdict(myfavs)
3255 #don't record if already in system profile or already recorded
3256 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3257 #we don't have a favorites entry for this package yet; add one
3258 myfavdict[myfavkey]=myfavkey
3259 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3260 emergelog(xterm_titles, " === ("+\
3261 str(mergecount)+" of "+\
3262 str(len(mymergelist))+\
3263 ") Updating world file ("+x[pkgindex]+")")
3264 portage.write_atomic(
3265 os.path.join(myroot, portage.WORLD_FILE),
3266 "\n".join(myfavdict.values()))
3268 if "--pretend" not in self.myopts and \
3269 "--fetchonly" not in self.myopts and \
3270 "--fetch-all-uri" not in self.myopts:
3271 # Clean the old package that we have merged over top of it.
3272 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3273 xsplit=portage.pkgsplit(x[2])
3274 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3275 retval = unmerge(pkgsettings, self.myopts, vartree,
3276 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3278 emergelog(xterm_titles,
3279 " --- AUTOCLEAN: Nothing unmerged.")
3281 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3282 + " AUTOCLEAN is disabled. This can cause serious"
3283 + " problems due to overlapping packages.\n")
3285 # Figure out if we need a restart.
3286 mysplit=portage.pkgsplit(x[2])
3287 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3288 myver=mysplit[1]+"-"+mysplit[2]
3289 if myver[-3:]=='-r0':
3291 if (myver != portage.VERSION) and \
3292 "livecvsportage" not in self.settings.features:
3293 if len(mymergelist) > mergecount:
3294 emergelog(xterm_titles,
3295 " ::: completed emerge ("+ \
3296 str(mergecount)+" of "+ \
3297 str(len(mymergelist))+") "+ \
3299 emergelog(xterm_titles, " *** RESTARTING " + \
3300 "emerge via exec() after change of " + \
3302 del mtimedb["resume"]["mergelist"][0]
3304 portage.run_exitfuncs()
3305 mynewargv=[sys.argv[0],"--resume"]
3306 resume_opts = self.myopts.copy()
3307 # For automatic resume, we need to prevent
3308 # any of bad_resume_opts from leaking in
3309 # via EMERGE_DEFAULT_OPTS.
3310 resume_opts["--ignore-default-opts"] = True
3311 for myopt, myarg in resume_opts.iteritems():
3312 if myopt not in bad_resume_opts:
3314 mynewargv.append(myopt)
3316 mynewargv.append(myopt +"="+ myarg)
3317 # priority only needs to be adjusted on the first run
3318 os.environ["PORTAGE_NICENESS"] = "0"
3319 os.execv(mynewargv[0], mynewargv)
3321 if "--pretend" not in self.myopts and \
3322 "--fetchonly" not in self.myopts and \
3323 "--fetch-all-uri" not in self.myopts:
3324 if "noclean" not in self.settings.features:
3325 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3326 (mergecount, len(mymergelist), x[pkgindex])
3327 emergelog(xterm_titles, (" === (%s of %s) " + \
3328 "Post-Build Cleaning (%s::%s)") % \
3329 (mergecount, len(mymergelist), x[pkgindex], y),
3330 short_msg=short_msg)
3331 emergelog(xterm_titles, " ::: completed emerge ("+\
3332 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3335 # Unsafe for parallel merges
3336 del mtimedb["resume"]["mergelist"][0]
3337 # Commit after each merge so that --resume may still work in
3338 # in the event that portage is not allowed to exit normally
3339 # due to power failure, SIGKILL, etc...
3342 if "--pretend" not in self.myopts:
3343 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3345 # We're out of the loop... We're done. Delete the resume data.
3346 if mtimedb.has_key("resume"):
3347 del mtimedb["resume"]
3350 #by doing an exit this way, --fetchonly can continue to try to
3351 #fetch everything even if a particular download fails.
3352 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3354 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3355 "encountered. Please see above for details.\n\n")
3356 for cpv in failed_fetches:
3357 sys.stderr.write(" ")
3358 sys.stderr.write(cpv)
3359 sys.stderr.write("\n")
3360 sys.stderr.write("\n")
3366 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3367 ldpath_mtimes, autoclean=0):
3368 candidate_catpkgs=[]
3370 xterm_titles = "notitles" not in settings.features
3372 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3374 # At least the parent needs to exist for the lock file.
3375 portage.util.ensure_dirs(vdb_path)
3376 except portage.exception.PortageException:
3380 if os.access(vdb_path, os.W_OK):
3381 vdb_lock = portage.locks.lockdir(vdb_path)
3382 realsyslist = getlist(settings, "system")
3384 for x in realsyslist:
3385 mycp = portage.dep_getkey(x)
3386 if mycp in settings.getvirtuals():
3388 for provider in settings.getvirtuals()[mycp]:
3389 if vartree.dbapi.match(provider):
3390 providers.append(provider)
3391 if len(providers) == 1:
3392 syslist.extend(providers)
3394 syslist.append(mycp)
3396 mysettings = portage.config(clone=settings)
3398 if not unmerge_files or "world" in unmerge_files or \
3399 "system" in unmerge_files:
3400 if "unmerge"==unmerge_action:
3402 print bold("emerge unmerge") + " can only be used with " + \
3403 "specific package names, not with "+bold("world")+" or"
3404 print bold("system")+" targets."
3411 # process all arguments and add all
3412 # valid db entries to candidate_catpkgs
3414 if not unmerge_files or "world" in unmerge_files:
3415 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3416 elif "system" in unmerge_files:
3417 candidate_catpkgs.extend(getlist(settings, "system"))
3419 #we've got command-line arguments
3420 if not unmerge_files:
3421 print "\nNo packages to unmerge have been provided.\n"
3423 for x in unmerge_files:
3424 arg_parts = x.split('/')
3425 if x[0] not in [".","/"] and \
3426 arg_parts[-1][-7:] != ".ebuild":
3427 #possible cat/pkg or dep; treat as such
3428 candidate_catpkgs.append(x)
3429 elif unmerge_action in ["prune","clean"]:
3430 print "\n!!! Prune and clean do not accept individual" + \
3431 " ebuilds as arguments;\n skipping.\n"
3434 # it appears that the user is specifying an installed
3435 # ebuild and we're in "unmerge" mode, so it's ok.
3436 if not os.path.exists(x):
3437 print "\n!!! The path '"+x+"' doesn't exist.\n"
3440 absx = os.path.abspath(x)
3441 sp_absx = absx.split("/")
3442 if sp_absx[-1][-7:] == ".ebuild":
3444 absx = "/".join(sp_absx)
3446 sp_absx_len = len(sp_absx)
3448 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3449 vdb_len = len(vdb_path)
3451 sp_vdb = vdb_path.split("/")
3452 sp_vdb_len = len(sp_vdb)
3454 if not os.path.exists(absx+"/CONTENTS"):
3455 print "!!! Not a valid db dir: "+str(absx)
3458 if sp_absx_len <= sp_vdb_len:
3459 # The Path is shorter... so it can't be inside the vdb.
3462 print "\n!!!",x,"cannot be inside "+ \
3463 vdb_path+"; aborting.\n"
3466 for idx in range(0,sp_vdb_len):
3467 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3470 print "\n!!!", x, "is not inside "+\
3471 vdb_path+"; aborting.\n"
3474 print "="+"/".join(sp_absx[sp_vdb_len:])
3475 candidate_catpkgs.append(
3476 "="+"/".join(sp_absx[sp_vdb_len:]))
3479 if (not "--quiet" in myopts):
3481 if settings["ROOT"] != "/":
3482 print darkgreen(newline+ \
3483 ">>> Using system located in ROOT tree "+settings["ROOT"])
3484 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3485 not ("--quiet" in myopts):
3486 print darkgreen(newline+\
3487 ">>> These are the packages that would be unmerged:")
3491 for x in candidate_catpkgs:
3492 # cycle through all our candidate deps and determine
3493 # what will and will not get unmerged
3495 mymatch=localtree.dep_match(x)
3498 except ValueError, errpkgs:
3499 print "\n\n!!! The short ebuild name \"" + \
3500 x + "\" is ambiguous. Please specify"
3501 print "!!! one of the following fully-qualified " + \
3502 "ebuild names instead:\n"
3503 for i in errpkgs[0]:
3504 print " " + green(i)
3508 if not mymatch and x[0] not in "<>=~":
3509 #add a "=" if missing
3510 mymatch=localtree.dep_match("="+x)
3512 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3513 (x, unmerge_action), noiselevel=-1)
3515 mykey = portage.key_expand(
3517 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3518 if not pkgmap.has_key(mykey):
3519 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3520 if unmerge_action=="unmerge":
3522 if y not in pkgmap[mykey]["selected"]:
3523 pkgmap[mykey]["selected"].append(y)
3524 numselected=numselected+len(mymatch)
3527 #unmerge_action in ["prune", clean"]
3529 for mypkg in mymatch:
3530 if unmerge_action=="clean":
3531 myslot=localtree.getslot(mypkg)
3533 # since we're pruning, we don't care about slots
3534 # and put all the pkgs in together
3536 if not slotmap.has_key(myslot):
3538 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3539 for myslot in slotmap.keys():
3540 counterkeys=slotmap[myslot].keys()
3545 pkgmap[mykey]["protected"].append(
3546 slotmap[myslot][counterkeys[-1]])
3548 #be pretty and get them in order of merge:
3549 for ckey in counterkeys:
3550 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
3551 numselected=numselected+1
3552 # ok, now the last-merged package
3553 # is protected, and the rest are selected
3554 if global_unmerge and not numselected:
3555 portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
3559 portage.writemsg_stdout(
3560 "\n>>> No packages selected for removal by " + \
3561 unmerge_action + "\n")
3565 portage.locks.unlockdir(vdb_lock)
3566 for x in pkgmap.keys():
3567 for y in localtree.dep_match(x):
3568 if y not in pkgmap[x]["omitted"] and \
3569 y not in pkgmap[x]["selected"] and \
3570 y not in pkgmap[x]["protected"]:
3571 pkgmap[x]["omitted"].append(y)
3572 if global_unmerge and not pkgmap[x]["selected"]:
3573 #avoid cluttering the preview printout with stuff that isn't getting unmerged
3575 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
3576 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
3577 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
3578 if "--pretend" not in myopts and "--ask" not in myopts:
3579 countdown(int(settings["EMERGE_WARNING_DELAY"]),
3580 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3581 print "\n "+white(x)
3582 for mytype in ["selected","protected","omitted"]:
3583 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
3584 if pkgmap[x][mytype]:
3585 for mypkg in pkgmap[x][mytype]:
3586 mysplit=portage.catpkgsplit(mypkg)
3587 if mysplit[3]=="r0":
3588 myversion=mysplit[2]
3590 myversion=mysplit[2]+"-"+mysplit[3]
3591 if mytype=="selected":
3592 portage.writemsg_stdout(
3593 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
3595 portage.writemsg_stdout(
3596 colorize("GOOD", myversion + " "), noiselevel=-1)
3598 portage.writemsg_stdout("none", noiselevel=-1)
3599 portage.writemsg_stdout("\n", noiselevel=-1)
3601 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3602 " packages are slated for removal.\n")
3603 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
3604 " and " + colorize("GOOD", "'omitted'") + \
3605 " packages will not be removed.\n\n")
3607 if "--pretend" in myopts:
3608 #we're done... return
3610 if "--ask" in myopts:
3611 if userquery("Would you like to unmerge these packages?")=="No":
3612 # enter pretend mode for correct formatting of results
3613 myopts["--pretend"] = True
3618 #the real unmerging begins, after a short delay....
3620 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3622 for x in pkgmap.keys():
3623 for y in pkgmap[x]["selected"]:
3624 print ">>> Unmerging "+y+"..."
3625 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3626 mysplit=y.split("/")
3628 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3629 mysettings, unmerge_action not in ["clean","prune"],
3630 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3631 if retval != os.EX_OK:
3632 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3633 ebuild = vartree.dbapi.findname(y)
3634 show_unmerge_failure_message(y, ebuild, retval)
3637 clean_world(vartree.dbapi, y)
3638 emergelog(xterm_titles, " >>> unmerge success: "+y)
3641 def show_unmerge_failure_message(pkg, ebuild, retval):
3643 from formatter import AbstractFormatter, DumbWriter
3644 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3647 msg.append("A removal phase of the '%s' package " % pkg)
3648 msg.append("has failed with exit value %s. " % retval)
3649 msg.append("The problem occurred while executing ")
3650 msg.append("the ebuild located at '%s'. " % ebuild)
3651 msg.append("If necessary, manually remove the ebuild " )
3652 msg.append("in order to skip the execution of removal phases.")
3656 f.add_flowing_data(x)
3660 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3662 if os.path.exists("/usr/bin/install-info"):
3667 inforoot=normpath(root+z)
3668 if os.path.isdir(inforoot):
3669 infomtime = long(os.stat(inforoot).st_mtime)
3670 if inforoot not in prev_mtimes or \
3671 prev_mtimes[inforoot] != infomtime:
3672 regen_infodirs.append(inforoot)
3674 if not regen_infodirs:
3675 portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
3677 portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
3681 for inforoot in regen_infodirs:
3684 for filename in ("dir", "dir.gz", "dir.bz2"):
3685 file_path = os.path.join(inforoot, filename)
3687 os.rename(file_path, file_path + ".old")
3689 if e.errno != errno.ENOENT:
3693 if not os.path.isdir(inforoot):
3696 file_list = os.listdir(inforoot)
3699 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3701 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3702 existsstr="already exists, for file `"
3704 if re.search(existsstr,myso):
3705 # Already exists... Don't increment the count for this.
3707 elif myso[:44]=="install-info: warning: no info dir entry in ":
3708 # This info file doesn't contain a DIR-header: install-info produces this
3709 # (harmless) warning (the --quiet switch doesn't seem to work).
3710 # Don't increment the count for this.
3714 errmsg += myso + "\n"
3717 #update mtime so we can potentially avoid regenerating.
3718 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3721 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3724 print " "+green("*")+" Processed",icount,"info files."
3727 def display_news_notification(settings):
3728 target_root = settings["ROOT"]
3729 NEWS_PATH = os.path.join("metadata", "news")
3730 UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
3731 porttree = portdbapi(porttree_root=settings["PORTDIR"], mysettings=settings)
3732 newsReaderDisplay = False
3735 for repo in porttree.getRepositories():
3736 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3738 print colorize("WARN", " * IMPORTANT:"),
3739 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3740 newsReaderDisplay = True
3742 if newsReaderDisplay:
3743 print colorize("WARN", " *"),
3744 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3747 def post_emerge(settings, mtimedb, retval):
3749 Misc. things to run at the end of a merge session.
3755 Display preserved libs warnings
3758 @param settings: Configuration settings (typically portage.settings)
3759 @type settings: portage.config()
3760 @param mtimedb: The mtimeDB to store data needed across merge invocations
3761 @type mtimedb: MtimeDB class instance
3762 @param retval: Emerge's return value
3766 1. Calls sys.exit(retval)
3768 target_root = settings["ROOT"]
3769 info_mtimes = mtimedb["info"]
3771 # Load the most current variables from ${ROOT}/etc/profile.env
3773 settings.regenerate()
3776 config_protect = settings.get("CONFIG_PROTECT","").split()
3777 infodirs = settings.get("INFOPATH","").split(":") + \
3778 settings.get("INFODIR","").split(":")
3782 emergelog("notitles" not in settings.features,
3783 " *** exiting successfully.")
3785 if "noinfo" not in settings.features:
3786 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3788 chk_updated_cfg_files(target_root, config_protect)
3790 display_news_notification(settings)
3792 from portage.dbapi.vartree import PreservedLibsRegistry
3793 plib_registry = PreservedLibsRegistry(os.path.join(target_root, CACHE_PATH, "preserved_libs_registry"))
3794 if plib_registry.hasEntries():
3795 print colorize("WARN", "!!!") + " existing preserved libs:"
3796 plibdata = plib_registry.getPreservedLibs()
3797 for cpv in plibdata.keys():
3798 print colorize("WARN", ">>>") + " package: %s" % cpv
3799 for f in plibdata[cpv]:
3800 print colorize("WARN", " * ") + " - %s" % f
3801 print "Use " + colorize("GOOD", "revdep-rebuild") + " to rebuild packages using these libraries"
3802 print "and then remerge the packages listed above."
3808 def chk_updated_cfg_files(target_root, config_protect):
3810 #number of directories with some protect files in them
3812 for x in config_protect:
3813 x = os.path.join(target_root, x.lstrip(os.path.sep))
3815 mymode = os.lstat(x).st_mode
3818 if stat.S_ISDIR(mymode):
3819 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3821 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3822 os.path.split(x.rstrip(os.path.sep))
3823 a = commands.getstatusoutput(mycommand + \
3824 " ! -iname '.*~' ! -iname '.*.bak'")
3826 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3828 files = a[1].split()
3831 print colorize("WARN", " * IMPORTANT:"),
3832 if stat.S_ISDIR(mymode):
3833 print "%d config files in '%s' need updating." % \
3836 print "config file '%s' needs updating." % x
3839 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3840 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3842 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3844 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3845 Returns the number of unread (yet relevent) items.
3857 1. The number of unread but relevant news items.
3860 from portage.news import NewsManager
3861 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3862 return manager.getUnreadItems( repo_id, update=True )
3864 def is_valid_package_atom(x):
3866 testkey = portage.dep_getkey(x)
3867 except portage.exception.InvalidData:
3869 if testkey.startswith("null/"):
3870 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3875 return portage.isvalidatom(testatom)
3877 def validate_merge_list(trees, mergelist):
3878 """Validate the list to make sure all the packages are still available.
3879 This is needed for --resume."""
3880 for (pkg_type, myroot, pkg_key, action) in mergelist:
3881 if pkg_type == "binary" and \
3882 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3883 pkg_type == "ebuild" and \
3884 not trees[myroot]["porttree"].dbapi.xmatch(
3885 "match-all", "="+pkg_key):
3886 print red("!!! Error: The resume list contains packages that are no longer")
3887 print red("!!! available to be emerged. Please restart/continue")
3888 print red("!!! the merge operation manually.")
3891 def show_blocker_docs_link():
3893 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3894 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3896 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3899 def action_sync(settings, trees, mtimedb, myopts, myaction):
3900 xterm_titles = "notitles" not in settings.features
3901 emergelog(xterm_titles, " === sync")
3902 myportdir = settings.get("PORTDIR", None)
3904 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3906 if myportdir[-1]=="/":
3907 myportdir=myportdir[:-1]
3908 if not os.path.exists(myportdir):
3909 print ">>>",myportdir,"not found, creating it."
3910 os.makedirs(myportdir,0755)
3911 syncuri=settings["SYNC"].rstrip()
3913 updatecache_flg = False
3914 if myaction == "metadata":
3915 print "skipping sync"
3916 updatecache_flg = True
3917 tmpservertimestampfile = None
3918 elif syncuri[:8]=="rsync://":
3919 if not os.path.exists("/usr/bin/rsync"):
3920 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3921 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3926 import shlex, StringIO
3927 if settings["PORTAGE_RSYNC_OPTS"] == "":
3928 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3930 "--recursive", # Recurse directories
3931 "--links", # Consider symlinks
3932 "--safe-links", # Ignore links outside of tree
3933 "--perms", # Preserve permissions
3934 "--times", # Preserive mod times
3935 "--compress", # Compress the data transmitted
3936 "--force", # Force deletion on non-empty dirs
3937 "--whole-file", # Don't do block transfers, only entire files
3938 "--delete", # Delete files that aren't in the master tree
3939 "--delete-after", # Delete only after everything else is done
3940 "--stats", # Show final statistics about what was transfered
3941 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3942 "--exclude=/distfiles", # Exclude distfiles from consideration
3943 "--exclude=/local", # Exclude local from consideration
3944 "--exclude=/packages", # Exclude packages from consideration
3945 "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
3949 # The below validation is not needed when using the above hardcoded
3952 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3953 lexer = shlex.shlex(StringIO.StringIO(
3954 settings.get("PORTAGE_RSYNC_OPTS","")), posix=True)
3955 lexer.whitespace_split = True
3956 rsync_opts.extend(lexer)
3959 for opt in ("--recursive", "--times"):
3960 if opt not in rsync_opts:
3961 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3962 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3963 rsync_opts.append(opt)
3965 for exclude in ("distfiles", "local", "packages"):
3966 opt = "--exclude=/%s" % exclude
3967 if opt not in rsync_opts:
3968 portage.writemsg(yellow("WARNING:") + \
3969 " adding required option %s not included in " % opt + \
3970 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3971 rsync_opts.append(opt)
3973 if settings["RSYNC_TIMEOUT"] != "":
3974 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3975 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3977 mytimeout = int(settings["RSYNC_TIMEOUT"])
3978 rsync_opts.append("--timeout=%d" % mytimeout)
3979 except ValueError, e:
3980 portage.writemsg("!!! %s\n" % str(e))
3982 # TODO: determine options required for official servers
3983 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
3985 def rsync_opt_startswith(opt_prefix):
3986 for x in rsync_opts:
3987 if x.startswith(opt_prefix):
3991 if not rsync_opt_startswith("--timeout="):
3992 rsync_opts.append("--timeout=%d" % mytimeout)
3994 for opt in ("--compress", "--whole-file"):
3995 if opt not in rsync_opts:
3996 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3997 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3998 rsync_opts.append(opt)
4000 if "--quiet" in myopts:
4001 rsync_opts.append("--quiet") # Shut up a lot
4003 rsync_opts.append("--verbose") # Print filelist
4005 if "--verbose" in myopts:
4006 rsync_opts.append("--progress") # Progress meter for each file
4008 if "--debug" in myopts:
4009 rsync_opts.append("--checksum") # Force checksum on all files
4011 if settings["RSYNC_EXCLUDEFROM"] != "":
4012 portage.writemsg(yellow("WARNING:") + \
4013 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
4014 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4015 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
4016 rsync_opts.append("--exclude-from=%s" % \
4017 settings["RSYNC_EXCLUDEFROM"])
4019 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
4020 " but file does not exist.\n")
4022 if settings["RSYNC_RATELIMIT"] != "":
4023 portage.writemsg(yellow("WARNING:") + \
4024 " usage of RSYNC_RATELIMIT is deprecated, use " + \
4025 "PORTAGE_RSYNC_EXTRA_OPTS instead")
4026 rsync_opts.append("--bwlimit=%s" % \
4027 settings["RSYNC_RATELIMIT"])
4029 # Real local timestamp file.
4030 servertimestampfile = os.path.join(
4031 myportdir, "metadata", "timestamp.chk")
4032 # Temporary file for remote server timestamp comparison.
4033 tmpservertimestampfile = os.path.join(
4034 settings["PORTAGE_TMPDIR"], "timestamp.chk")
4036 content = portage.util.grabfile(servertimestampfile)
4040 mytimestamp = time.mktime(time.strptime(content[0],
4041 "%a, %d %b %Y %H:%M:%S +0000"))
4042 except (OverflowError, ValueError):
4047 if settings.has_key("RSYNC_RETRIES"):
4048 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
4049 maxretries=int(settings["RSYNC_RETRIES"])
4051 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
4052 except SystemExit, e:
4053 raise # Needed else can't exit
4055 maxretries=3 #default number of retries
4058 user_name, hostname, port = re.split(
4059 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
4062 if user_name is None:
4064 updatecache_flg=True
4065 all_rsync_opts = set(rsync_opts)
4066 lexer = shlex.shlex(StringIO.StringIO(
4067 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")), posix=True)
4068 lexer.whitespace_split = True
4069 extra_rsync_opts = list(lexer)
4071 all_rsync_opts.update(extra_rsync_opts)
4072 family = socket.AF_INET
4073 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
4074 family = socket.AF_INET
4075 elif socket.has_ipv6 and \
4076 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
4077 family = socket.AF_INET6
4084 for addrinfo in socket.getaddrinfo(
4085 hostname, None, family, socket.SOCK_STREAM):
4086 if addrinfo[0] == socket.AF_INET6:
4087 # IPv6 addresses need to be enclosed in square brackets
4088 ips.append("[%s]" % addrinfo[4][0])
4090 ips.append(addrinfo[4][0])
4091 from random import shuffle
4093 except SystemExit, e:
4094 raise # Needed else can't exit
4095 except Exception, e:
4096 print "Notice:",str(e)
4101 dosyncuri = syncuri.replace(
4102 "//" + user_name + hostname + port + "/",
4103 "//" + user_name + ips[0] + port + "/", 1)
4104 except SystemExit, e:
4105 raise # Needed else can't exit
4106 except Exception, e:
4107 print "Notice:",str(e)
4111 if "--ask" in myopts:
4112 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
4117 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
4118 if "--quiet" not in myopts:
4119 print ">>> Starting rsync with "+dosyncuri+"..."
4121 emergelog(xterm_titles,
4122 ">>> Starting retry %d of %d with %s" % \
4123 (retries,maxretries,dosyncuri))
4124 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
4126 if mytimestamp != 0 and "--quiet" not in myopts:
4127 print ">>> Checking server timestamp ..."
4129 rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
4131 if "--debug" in myopts:
4136 # Even if there's no timestamp available locally, fetch the
4137 # timestamp anyway as an initial probe to verify that the server is
4138 # responsive. This protects us from hanging indefinitely on a
4139 # connection attempt to an unresponsive server which rsync's
4140 # --timeout option does not prevent.
4142 mycommand = rsynccommand[:]
4143 mycommand.append(dosyncuri.rstrip("/") + \
4144 "/metadata/timestamp.chk")
4145 mycommand.append(tmpservertimestampfile)
4149 def timeout_handler(signum, frame):
4150 raise portage.exception.PortageException("timed out")
4151 signal.signal(signal.SIGALRM, timeout_handler)
4152 # Timeout here in case the server is unresponsive. The
4153 # --timeout rsync option doesn't apply to the initial
4154 # connection attempt.
4157 mypids.extend(portage.process.spawn(
4158 mycommand, env=settings.environ(), returnpid=True))
4159 exitcode = os.waitpid(mypids[0], 0)[1]
4160 content = portage.grabfile(tmpservertimestampfile)
4164 os.unlink(tmpservertimestampfile)
4167 except portage.exception.PortageException, e:
4171 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
4172 os.kill(mypids[0], signal.SIGTERM)
4173 os.waitpid(mypids[0], 0)
4174 # This is the same code rsync uses for timeout.
4177 if exitcode != os.EX_OK:
4179 exitcode = (exitcode & 0xff) << 8
4181 exitcode = exitcode >> 8
4183 portage.process.spawned_pids.remove(mypids[0])
4186 servertimestamp = time.mktime(time.strptime(
4187 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
4188 except (OverflowError, ValueError):
4190 del mycommand, mypids, content
4191 if exitcode == os.EX_OK:
4192 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4193 emergelog(xterm_titles,
4194 ">>> Cancelling sync -- Already current.")
4197 print ">>> Timestamps on the server and in the local repository are the same."
4198 print ">>> Cancelling all further sync action. You are already up to date."
4200 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4204 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4205 emergelog(xterm_titles,
4206 ">>> Server out of date: %s" % dosyncuri)
4209 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4211 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4214 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4216 mycommand = rsynccommand + [dosyncuri+"/", myportdir]
4217 exitcode = portage.process.spawn(mycommand,
4218 env=settings.environ())
4219 if exitcode in [0,1,3,4,11,14,20,21]:
4221 elif exitcode in [1,3,4,11,14,20,21]:
4224 # Code 2 indicates protocol incompatibility, which is expected
4225 # for servers with protocol < 29 that don't support
4226 # --prune-empty-directories. Retry for a server that supports
4227 # at least rsync protocol version 29 (>=rsync-2.6.4).
4232 if retries<=maxretries:
4233 print ">>> Retrying..."
4238 updatecache_flg=False
4242 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4246 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4247 print darkred("!!!")+green(" that your SYNC statement is proper.")
4248 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4250 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4251 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4252 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4253 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4254 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4256 print darkred("!!!")+green(" Rsync was killed before it finished.")
4258 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4259 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4260 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4261 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4262 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4265 elif syncuri[:6]=="cvs://":
4266 if not os.path.exists("/usr/bin/cvs"):
4267 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4268 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4271 cvsdir=os.path.dirname(myportdir)
4272 if not os.path.exists(myportdir+"/CVS"):
4274 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4275 if os.path.exists(cvsdir+"/gentoo-x86"):
4276 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4281 if e.errno != errno.ENOENT:
4283 "!!! existing '%s' directory; exiting.\n" % myportdir)
4286 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4287 print "!!! cvs checkout error; exiting."
4289 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4292 print ">>> Starting cvs update with "+syncuri+"..."
4293 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4294 myportdir, settings, free=1)
4295 if retval != os.EX_OK:
4299 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4302 if updatecache_flg and \
4303 myaction != "metadata" and \
4304 "metadata-transfer" not in settings.features:
4305 updatecache_flg = False
4307 # Reload the whole config from scratch.
4308 settings, trees, mtimedb = load_emerge_config(trees=trees)
4309 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4311 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4312 action_metadata(settings, portdb, myopts)
4314 if portage.global_updates(settings, trees, mtimedb["updates"]):
4316 # Reload the whole config from scratch.
4317 settings, trees, mtimedb = load_emerge_config(trees=trees)
4318 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4320 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4321 mypvs = portage.best(
4322 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4324 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4326 if myaction != "metadata":
4327 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4328 retval = portage.process.spawn(
4329 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4330 dosyncuri], env=settings.environ())
4331 if retval != os.EX_OK:
4332 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4334 if(mybestpv != mypvs) and not "--quiet" in myopts:
4336 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4337 print red(" * ")+"that you update portage now, before any other packages are updated."
4338 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4339 print red(" * ")+"configuration files."
4340 print red(" * ")+"To update portage, run 'emerge portage'."
4343 display_news_notification(settings)
4345 def action_metadata(settings, portdb, myopts):
4346 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4347 old_umask = os.umask(0002)
4348 cachedir = os.path.normpath(settings.depcachedir)
4349 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4350 "/lib", "/opt", "/proc", "/root", "/sbin",
4351 "/sys", "/tmp", "/usr", "/var"]:
4352 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4353 "ROOT DIRECTORY ON YOUR SYSTEM."
4354 print >> sys.stderr, \
4355 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4357 if not os.path.exists(cachedir):
4360 ec = portage.eclass_cache.cache(portdb.porttree_root)
4361 myportdir = os.path.realpath(settings["PORTDIR"])
4362 cm = settings.load_best_module("portdbapi.metadbmodule")(
4363 myportdir, "metadata/cache", portage.auxdbkeys[:])
4365 from portage.cache import util
4367 class percentage_noise_maker(util.quiet_mirroring):
4368 def __init__(self, dbapi):
4370 self.cp_all = dbapi.cp_all()
4371 l = len(self.cp_all)
4372 self.call_update_min = 100000000
4373 self.min_cp_all = l/100.0
4378 for x in self.cp_all:
4380 if self.count > self.min_cp_all:
4381 self.call_update_min = 0
4383 for y in self.dbapi.cp_list(x):
4385 self.call_update_mine = 0
4387 def update(self, *arg):
4388 try: self.pstr = int(self.pstr) + 1
4389 except ValueError: self.pstr = 1
4390 sys.stdout.write("%s%i%%" % \
4391 ("\b" * (len(str(self.pstr))+1), self.pstr))
4393 self.call_update_min = 10000000
4395 def finish(self, *arg):
4396 sys.stdout.write("\b\b\b\b100%\n")
4399 if "--quiet" in myopts:
4400 def quicky_cpv_generator(cp_all_list):
4401 for x in cp_all_list:
4402 for y in portdb.cp_list(x):
4404 source = quicky_cpv_generator(portdb.cp_all())
4405 noise_maker = portage.cache.util.quiet_mirroring()
4407 noise_maker = source = percentage_noise_maker(portdb)
4408 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4409 eclass_cache=ec, verbose_instance=noise_maker)
4414 def action_regen(settings, portdb):
4415 xterm_titles = "notitles" not in settings.features
4416 emergelog(xterm_titles, " === regen")
4417 #regenerate cache entries
4418 print "Regenerating cache entries... "
4420 os.close(sys.stdin.fileno())
4421 except SystemExit, e:
4422 raise # Needed else can't exit
4426 mynodes = portdb.cp_all()
4427 from portage.cache.cache_errors import CacheError
4429 for mytree in portdb.porttrees:
4431 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4432 except CacheError, e:
4433 print "\n error listing cache entries for " + \
4434 "'%s': %s, continuing..." % (mytree, e)
4439 mymatches = portdb.cp_list(x)
4440 portage.writemsg_stdout("processing %s\n" % x)
4443 foo = portdb.aux_get(y,["DEPEND"])
4444 except SystemExit, e:
4445 # sys.exit is an exception... And consequently, we can't catch it.
4447 except Exception, e:
4448 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4450 for mytree in portdb.porttrees:
4451 if portdb.findname2(y, mytree=mytree)[0]:
4452 dead_nodes[mytree].discard(y)
4454 for mytree, nodes in dead_nodes.iteritems():
4455 auxdb = portdb.auxdb[mytree]
4459 except (KeyError, CacheError):
4463 def action_config(settings, trees, myopts, myfiles):
4464 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4465 print red("!!! config can only take a single package atom at this time\n")
4467 if not is_valid_package_atom(myfiles[0]):
4468 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4470 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4471 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4475 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4476 except ValueError, e:
4477 # Multiple matches thrown from cpv_expand
4480 print "No packages found.\n"
4483 if "--ask" in myopts:
4485 print "Please select a package to configure:"
4489 options.append(str(idx))
4490 print options[-1]+") "+pkg
4493 idx = userquery("Selection?", options)
4496 pkg = pkgs[int(idx)-1]
4498 print "The following packages available:"
4501 print "\nPlease use a specific atom or the --ask option."
4507 if "--ask" in myopts:
4508 if userquery("Ready to configure "+pkg+"?") == "No":
4511 print "Configuring pkg..."
4513 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4514 mysettings = portage.config(clone=settings)
4515 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4516 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4517 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4520 def action_info(settings, trees, myopts, myfiles):
4521 unameout=commands.getstatusoutput("uname -mrp")[1]
4522 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4523 settings.profile_path, settings["CHOST"],
4524 trees[settings["ROOT"]]["vartree"].dbapi)
4526 header_title = "System Settings"
4528 print header_width * "="
4529 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4530 print header_width * "="
4531 print "System uname: "+unameout
4532 gentoo_release = portage.grabfile(os.path.join(
4533 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4535 print gentoo_release[0]
4537 print "Unknown Host Operating System"
4538 lastSync = portage.grabfile(os.path.join(
4539 settings["PORTDIR"], "metadata", "timestamp.chk"))
4540 print "Timestamp of tree:",
4546 output=commands.getstatusoutput("distcc --version")
4548 print str(output[1].split("\n",1)[0]),
4549 if "distcc" in settings.features:
4554 output=commands.getstatusoutput("ccache -V")
4556 print str(output[1].split("\n",1)[0]),
4557 if "ccache" in settings.features:
4562 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4563 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4564 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4565 myvars = portage.util.unique_array(myvars)
4569 if portage.isvalidatom(x):
4570 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4571 pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
4572 pkg_matches.sort(portage.pkgcmp)
4574 for pn, ver, rev in pkg_matches:
4576 pkgs.append(ver + "-" + rev)
4580 pkgs = ", ".join(pkgs)
4581 print "%-20s %s" % (x+":", pkgs)
4583 print "%-20s %s" % (x+":", "[NOT VALID]")
4585 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4587 if "--verbose" in myopts:
4588 myvars=settings.keys()
4590 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4591 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4592 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4593 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4595 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4597 myvars = portage.util.unique_array(myvars)
4603 print '%s="%s"' % (x, settings[x])
4605 use = set(settings["USE"].split())
4606 use_expand = settings["USE_EXPAND"].split()
4608 for varname in use_expand:
4609 flag_prefix = varname.lower() + "_"
4611 if f.startswith(flag_prefix):
4615 print 'USE="%s"' % " ".join(use),
4616 for varname in use_expand:
4617 myval = settings.get(varname)
4619 print '%s="%s"' % (varname, myval),
4622 unset_vars.append(x)
4624 print "Unset: "+", ".join(unset_vars)
4627 if "--debug" in myopts:
4628 for x in dir(portage):
4629 module = getattr(portage, x)
4630 if "cvs_id_string" in dir(module):
4631 print "%s: %s" % (str(x), str(module.cvs_id_string))
4633 # See if we can find any packages installed matching the strings
4634 # passed on the command line
4636 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4637 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4639 mypkgs.extend(vardb.match(x))
4641 # If some packages were found...
4643 # Get our global settings (we only print stuff if it varies from
4644 # the current config)
4645 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4646 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4648 pkgsettings = portage.config(clone=settings)
4650 for myvar in mydesiredvars:
4651 global_vals[myvar] = set(settings.get(myvar, "").split())
4653 # Loop through each package
4654 # Only print settings if they differ from global settings
4655 header_printed = False
4657 # Get all package specific variables
4658 auxvalues = vardb.aux_get(pkg, auxkeys)
4660 for i in xrange(len(auxkeys)):
4661 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4663 for myvar in mydesiredvars:
4664 # If the package variable doesn't match the
4665 # current global variable, something has changed
4666 # so set diff_found so we know to print
4667 if valuesmap[myvar] != global_vals[myvar]:
4668 diff_values[myvar] = valuesmap[myvar]
4669 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4670 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4672 # If a matching ebuild is no longer available in the tree, maybe it
4673 # would make sense to compare against the flags for the best
4674 # available version with the same slot?
4676 if portdb.cpv_exists(pkg):
4678 pkgsettings.setcpv(pkg, mydb=mydb)
4679 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4681 diff_values["USE"] = valuesmap["USE"]
4682 # If a difference was found, print the info for
4686 # If we have not yet printed the header,
4688 if not header_printed:
4689 header_title = "Package Settings"
4690 print header_width * "="
4691 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4692 print header_width * "="
4693 header_printed = True
4695 # Print package info
4696 print "%s was built with the following:" % pkg
4697 for myvar in mydesiredvars + ["USE"]:
4698 if myvar in diff_values:
4699 mylist = list(diff_values[myvar])
4701 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4704 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4706 print "emerge: no search terms provided."
4708 searchinstance = search(settings, portdb,
4709 vartree, spinner, "--searchdesc" in myopts,
4710 "--quiet" not in myopts)
4711 for mysearch in myfiles:
4713 searchinstance.execute(mysearch)
4714 except re.error, comment:
4715 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4717 searchinstance.output()
4719 def action_depclean(settings, trees, ldpath_mtimes,
4721 # Kill packages that aren't explicitly merged or are required as a
4722 # dependency of another package. World file is explicit.
4724 warn_prefix = colorize("BAD", "*** WARNING *** ")
4726 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4727 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4728 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4730 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4731 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4732 print warn_prefix + "be kept. They can be manually added to this set with"
4733 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4734 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4735 print warn_prefix + "depclean, even if they are part of the world set."
4737 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4738 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4739 print warn_prefix + "consequence, it is often necessary to run "
4740 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4742 xterm_titles = "notitles" not in settings.features
4743 myroot = settings["ROOT"]
4744 dep_check_trees = {}
4745 dep_check_trees[myroot] = {}
4746 dep_check_trees[myroot]["vartree"] = \
4747 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4748 vardb = dep_check_trees[myroot]["vartree"].dbapi
4749 # Constrain dependency selection to the installed packages.
4750 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4751 syslist = getlist(settings, "system")
4752 worldlist = getlist(settings, "world")
4753 system_world_dict = genericdict(worldlist)
4754 system_world_dict.update(genericdict(syslist))
4755 fakedb = portage.fakedbapi(settings=settings)
4756 myvarlist = vardb.cpv_all()
4759 print "\n!!! You have no system list.",
4761 print "\n!!! You have no world file.",
4763 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4765 if not (syslist and worldlist and myvarlist):
4766 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4767 print " break your installation.\n"
4768 if "--pretend" not in myopts:
4769 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4771 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4772 emergelog(xterm_titles, " >>> depclean")
4774 if "--quiet" not in myopts:
4775 print "\nCalculating dependencies ",
4779 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4780 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4782 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4784 while remaining_atoms:
4785 atom, parent, priority = remaining_atoms.pop()
4786 pkgs = vardb.match(atom)
4788 if not atom.startswith("!") and priority == hard:
4789 unresolveable.setdefault(atom, []).append(parent)
4791 if portage.dep_getkey(atom) not in system_world_dict:
4792 # Prune all but the best matching slot, since that's all that a
4793 # deep world update would pull in. Don't prune if the cpv is in
4794 # system or world though, since those sets trigger greedy update
4796 pkgs = [portage.best(pkgs)]
4798 if fakedb.cpv_exists(pkg):
4801 fakedb.cpv_inject(pkg)
4802 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4804 if myopts.get("--with-bdeps", "y") == "y":
4805 mydeps.append((myaux["DEPEND"], soft))
4807 mydeps.append((" ".join(myaux.values()), hard))
4808 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4809 for depstr, priority in mydeps:
4814 if "--debug" in myopts:
4816 print "Parent: ", pkg
4817 print "Depstring:", depstr
4819 if priority == soft:
4825 portage.dep._dep_check_strict = False
4826 success, atoms = portage.dep_check(depstr, None, settings,
4827 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4829 portage.dep._dep_check_strict = True
4831 show_invalid_depstring_notice(
4832 ("installed", myroot, pkg, "nomerge"),
4836 if "--debug" in myopts:
4837 print "Candidates:", atoms
4840 remaining_atoms.append((atom, pkg, priority))
4842 if "--quiet" not in myopts:
4843 print "\b\b... done!\n"
4846 print "Dependencies could not be completely resolved due to"
4847 print "the following required packages not being installed:"
4849 for atom in unresolveable:
4850 print atom, "required by", " ".join(unresolveable[atom])
4852 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4853 print "depclean? It may be necessary to manually uninstall packages that no longer"
4854 print "exist in the portage tree since it may not be possible to satisfy their"
4855 print "dependencies. Also, be aware of the --with-bdeps option that is documented"
4856 print "in " + good("`man emerge`") + "."
4860 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4863 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4864 "unmerge", cleanlist, ldpath_mtimes)
4866 print "Packages installed: "+str(len(myvarlist))
4867 print "Packages in world: "+str(len(worldlist))
4868 print "Packages in system: "+str(len(syslist))
4869 print "Unique package names: "+str(len(myvarlist))
4870 print "Required packages: "+str(len(fakedb.cpv_all()))
4871 if "--pretend" in myopts:
4872 print "Number to remove: "+str(len(cleanlist))
4874 print "Number removed: "+str(len(cleanlist))
4876 def action_build(settings, trees, mtimedb,
4877 myopts, myaction, myfiles, spinner):
4878 ldpath_mtimes = mtimedb["ldpath"]
4880 if "--quiet" not in myopts and \
4881 ("--pretend" in myopts or "--ask" in myopts or \
4882 "--tree" in myopts or "--verbose" in myopts):
4884 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4888 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4890 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4894 print darkgreen("These are the packages that would be %s, in order:") % action
4897 # validate the state of the resume data
4898 # so that we can make assumptions later.
4899 for k in ("resume", "resume_backup"):
4901 if "mergelist" in mtimedb[k]:
4902 if not mtimedb[k]["mergelist"]:
4907 if "--resume" in myopts and \
4908 ("resume" in mtimedb or
4909 "resume_backup" in mtimedb):
4910 if "resume" not in mtimedb:
4911 mtimedb["resume"] = mtimedb["resume_backup"]
4912 del mtimedb["resume_backup"]
4914 # XXX: "myopts" is a list for backward compatibility.
4915 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4917 for opt in ("--skipfirst", "--ask", "--tree"):
4918 myresumeopts.pop(opt, None)
4920 for myopt, myarg in myopts.iteritems():
4921 if myopt not in myresumeopts:
4922 myresumeopts[myopt] = myarg
4925 # Adjust config according to options of the command being resumed.
4926 for myroot in trees:
4927 mysettings = trees[myroot]["vartree"].settings
4929 adjust_config(myopts, mysettings)
4931 del myroot, mysettings
4933 myparams = create_depgraph_params(myopts, myaction)
4934 if "--quiet" not in myopts and "--nodeps" not in myopts:
4935 print "Calculating dependencies ",
4936 mydepgraph = depgraph(settings, trees,
4937 myopts, myparams, spinner)
4938 if "--quiet" not in myopts and "--nodeps" not in myopts:
4939 print "\b\b... done!"
4941 if ("--resume" in myopts):
4942 print darkgreen("emerge: It seems we have nothing to resume...")
4945 myparams = create_depgraph_params(myopts, myaction)
4946 if myaction in ["system","world"]:
4947 if "--quiet" not in myopts and "--nodeps" not in myopts:
4948 print "Calculating",myaction,"dependencies ",
4950 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4951 if not mydepgraph.xcreate(myaction):
4952 print "!!! Depgraph creation failed."
4954 if "--quiet" not in myopts and "--nodeps" not in myopts:
4955 print "\b\b... done!"
4957 if "--quiet" not in myopts and "--nodeps" not in myopts:
4958 print "Calculating dependencies ",
4960 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4962 retval, favorites = mydepgraph.select_files(myfiles)
4963 except portage.exception.PackageNotFound, e:
4964 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4968 if "--quiet" not in myopts and "--nodeps" not in myopts:
4969 print "\b\b... done!"
4971 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4972 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4974 if mydepgraph.missingbins:
4975 for x in mydepgraph.missingbins:
4976 sys.stderr.write(" "+str(x)+"\n")
4977 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4980 if "--pretend" not in myopts and \
4981 ("--ask" in myopts or "--tree" in myopts or \
4982 "--verbose" in myopts) and \
4983 not ("--quiet" in myopts and "--ask" not in myopts):
4984 if "--resume" in myopts:
4985 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4986 mymergelist = mtimedb["resume"]["mergelist"]
4987 if "--skipfirst" in myopts:
4988 mymergelist = mymergelist[1:]
4989 if len(mymergelist) == 0:
4990 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4992 mydepgraph.display(mymergelist)
4993 prompt="Would you like to resume merging these packages?"
4996 mydepgraph.altlist(reversed=("--tree" in myopts)))
4998 for x in mydepgraph.altlist():
4999 if x[0] != "blocks" and x[3] != "nomerge":
5001 #check for blocking dependencies
5002 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
5003 print "\n!!! Error: The above package list contains packages which cannot be installed"
5004 print "!!! at the same time on the same system."
5005 if "--quiet" not in myopts:
5006 show_blocker_docs_link()
5009 if "--noreplace" in myopts and favorites:
5012 print " %s %s" % (good("*"), x)
5013 prompt="Would you like to add these packages to your world favorites?"
5014 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5015 prompt="Nothing to merge; would you like to auto-clean packages?"
5018 print "Nothing to merge; quitting."
5021 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5022 prompt="Would you like to fetch the source files for these packages?"
5024 prompt="Would you like to merge these packages?"
5026 if "--ask" in myopts and userquery(prompt) == "No":
5031 # Don't ask again (e.g. when auto-cleaning packages after merge)
5032 myopts.pop("--ask", None)
5034 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5035 if ("--resume" in myopts):
5036 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5037 mymergelist = mtimedb["resume"]["mergelist"]
5038 if "--skipfirst" in myopts:
5039 mymergelist = mymergelist[1:]
5040 if len(mymergelist) == 0:
5041 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5043 mydepgraph.display(mymergelist)
5046 mydepgraph.altlist(reversed=("--tree" in myopts)))
5047 if ("--buildpkgonly" in myopts):
5048 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5049 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5050 print "!!! You have to merge the dependencies before you can build this package.\n"
5053 if ("--buildpkgonly" in myopts):
5054 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5055 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5056 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
5059 if ("--resume" in myopts):
5060 favorites=mtimedb["resume"]["favorites"]
5061 mergetask = MergeTask(settings, trees, myopts)
5062 if "--fetchonly" in myopts:
5063 """ parallel-fetch uses --resume --fetchonly and we don't want
5064 it to write the mtimedb"""
5065 mtimedb.filename = None
5066 time.sleep(3) # allow the parent to have first fetch
5068 retval = mergetask.merge(
5069 mtimedb["resume"]["mergelist"], favorites, mtimedb)
5070 if retval != os.EX_OK:
5073 if "resume" in mtimedb and \
5074 "mergelist" in mtimedb["resume"] and \
5075 len(mtimedb["resume"]["mergelist"]) > 1:
5076 mtimedb["resume_backup"] = mtimedb["resume"]
5077 del mtimedb["resume"]
5079 mtimedb["resume"]={}
5080 # XXX: Stored as a list for backward compatibility.
5081 mtimedb["resume"]["myopts"] = \
5082 [k for k in myopts if myopts[k] is True]
5083 mtimedb["resume"]["favorites"]=favorites
5084 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5085 for pkgline in mydepgraph.altlist():
5086 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5087 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
5088 tmpsettings = portage.config(clone=settings)
5090 if settings.get("PORTAGE_DEBUG", "") == "1":
5092 retval = portage.doebuild(
5093 y, "digest", settings["ROOT"], tmpsettings, edebug,
5094 ("--pretend" in myopts),
5095 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
5097 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5099 for pkg in mydepgraph.altlist():
5100 if pkg[0] != "blocks":
5103 pkglist = mydepgraph.altlist()
5105 mergetask = MergeTask(settings, trees, myopts)
5106 retval = mergetask.merge(pkglist, favorites, mtimedb)
5107 if retval != os.EX_OK:
5110 if mtimedb.has_key("resume"):
5111 del mtimedb["resume"]
5112 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5113 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5114 vartree = trees[settings["ROOT"]]["vartree"]
5115 unmerge(settings, myopts, vartree, "clean", ["world"],
5116 ldpath_mtimes, autoclean=1)
5118 portage.writemsg_stdout(colorize("WARN", "WARNING:")
5119 + " AUTOCLEAN is disabled. This can cause serious"
5120 + " problems due to overlapping packages.\n")
5122 def multiple_actions(action1, action2):
5123 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
5124 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
5127 def parse_opts(tmpcmdline, silent=False):
5132 global actions, options, shortmapping
5134 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
5135 argument_options = {
5137 "help":"specify the location for portage configuration files",
5141 "help":"enable or disable color output",
5143 "choices":("y", "n")
5146 "help":"include unnecessary build time dependencies",
5148 "choices":("y", "n")
5152 from optparse import OptionParser
5153 parser = OptionParser()
5154 if parser.has_option("--help"):
5155 parser.remove_option("--help")
5157 for action_opt in actions:
5158 parser.add_option("--" + action_opt, action="store_true",
5159 dest=action_opt.replace("-", "_"), default=False)
5160 for myopt in options:
5161 parser.add_option(myopt, action="store_true",
5162 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5163 for shortopt, longopt in shortmapping.iteritems():
5164 parser.add_option("-" + shortopt, action="store_true",
5165 dest=longopt.lstrip("--").replace("-", "_"), default=False)
5166 for myalias, myopt in longopt_aliases.iteritems():
5167 parser.add_option(myalias, action="store_true",
5168 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5170 for myopt, kwargs in argument_options.iteritems():
5171 parser.add_option(myopt,
5172 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
5174 myoptions, myargs = parser.parse_args(args=tmpcmdline)
5176 for myopt in options:
5177 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
5179 myopts[myopt] = True
5181 for myopt in argument_options:
5182 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
5186 for action_opt in actions:
5187 v = getattr(myoptions, action_opt.replace("-", "_"))
5190 multiple_actions(myaction, action_opt)
5192 myaction = action_opt
5195 if x in actions and myaction != "search":
5196 if not silent and x not in ["system", "world"]:
5197 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
5198 # special case "search" so people can search for action terms, e.g. emerge -s sync
5200 multiple_actions(myaction, x)
5206 if "--nocolor" in myopts:
5208 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
5209 "use '--color=n' instead.\n")
5210 del myopts["--nocolor"]
5211 myopts["--color"] = "n"
5213 return myaction, myopts, myfiles
5215 def validate_ebuild_environment(trees):
5216 for myroot in trees:
5217 mysettings = trees[myroot]["vartree"].settings
5218 for var in "ARCH", "USERLAND":
5219 if mysettings.get(var):
5221 print >> sys.stderr, bad(("\a!!! %s is not set... " % var) + \
5222 "Are you missing the '%setc/make.profile' symlink?" % \
5223 mysettings["PORTAGE_CONFIGROOT"])
5224 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5225 "Is your portage tree complete?\n")
5227 del myroot, mysettings
5229 def load_emerge_config(trees=None):
5231 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5232 kwargs[k] = os.environ.get(envvar, None)
5233 trees = portage.create_trees(trees=trees, **kwargs)
5235 settings = trees["/"]["vartree"].settings
5237 for myroot in trees:
5239 settings = trees[myroot]["vartree"].settings
5242 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5243 mtimedb = portage.MtimeDB(mtimedbfile)
5244 return settings, trees, mtimedb
5246 def adjust_config(myopts, settings):
5247 """Make emerge specific adjustments to the config."""
5249 # To enhance usability, make some vars case insensitive by forcing them to
5251 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5252 if myvar in settings:
5253 settings[myvar] = settings[myvar].lower()
5254 settings.backup_changes(myvar)
5257 # Kill noauto as it will break merges otherwise.
5258 if "noauto" in settings.features:
5259 while "noauto" in settings.features:
5260 settings.features.remove("noauto")
5261 settings["FEATURES"] = " ".join(settings.features)
5262 settings.backup_changes("FEATURES")
5266 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5267 except ValueError, e:
5268 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5269 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5270 settings["CLEAN_DELAY"], noiselevel=-1)
5271 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5272 settings.backup_changes("CLEAN_DELAY")
5274 EMERGE_WARNING_DELAY = 10
5276 EMERGE_WARNING_DELAY = int(settings.get(
5277 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5278 except ValueError, e:
5279 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5280 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5281 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5282 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5283 settings.backup_changes("EMERGE_WARNING_DELAY")
5285 if "--quiet" in myopts:
5286 settings["PORTAGE_QUIET"]="1"
5287 settings.backup_changes("PORTAGE_QUIET")
5289 # Set so that configs will be merged regardless of remembered status
5290 if ("--noconfmem" in myopts):
5291 settings["NOCONFMEM"]="1"
5292 settings.backup_changes("NOCONFMEM")
5294 # Set various debug markers... They should be merged somehow.
5297 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5298 if PORTAGE_DEBUG not in (0, 1):
5299 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5300 PORTAGE_DEBUG, noiselevel=-1)
5301 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5304 except ValueError, e:
5305 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5306 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5307 settings["PORTAGE_DEBUG"], noiselevel=-1)
5309 if "--debug" in myopts:
5311 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5312 settings.backup_changes("PORTAGE_DEBUG")
5314 if settings.get("NOCOLOR") not in ("yes","true"):
5315 portage.output.havecolor = 1
5317 """The explicit --color < y | n > option overrides the NOCOLOR environment
5318 variable and stdout auto-detection."""
5319 if "--color" in myopts:
5320 if "y" == myopts["--color"]:
5321 portage.output.havecolor = 1
5322 settings["NOCOLOR"] = "false"
5324 portage.output.havecolor = 0
5325 settings["NOCOLOR"] = "true"
5326 settings.backup_changes("NOCOLOR")
5327 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5328 portage.output.havecolor = 0
5329 settings["NOCOLOR"] = "true"
5330 settings.backup_changes("NOCOLOR")
5333 global portage # NFC why this is necessary now - genone
5334 # Disable color until we're sure that it should be enabled (after
5335 # EMERGE_DEFAULT_OPTS has been parsed).
5336 portage.output.havecolor = 0
5337 # This first pass is just for options that need to be known as early as
5338 # possible, such as --config-root. They will be parsed again later,
5339 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5340 # the value of --config-root).
5341 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5342 if "--debug" in myopts:
5343 os.environ["PORTAGE_DEBUG"] = "1"
5344 if "--config-root" in myopts:
5345 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5347 # Portage needs to ensure a sane umask for the files it creates.
5349 settings, trees, mtimedb = load_emerge_config()
5350 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5353 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5354 except (OSError, ValueError), e:
5355 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5356 settings["PORTAGE_NICENESS"])
5357 portage.writemsg("!!! %s\n" % str(e))
5360 if portage.global_updates(settings, trees, mtimedb["updates"]):
5362 # Reload the whole config from scratch.
5363 settings, trees, mtimedb = load_emerge_config(trees=trees)
5364 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5366 xterm_titles = "notitles" not in settings.features
5369 if "--ignore-default-opts" not in sys.argv:
5370 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5371 tmpcmdline.extend(sys.argv[1:])
5372 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5374 if "--digest" in myopts:
5375 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5376 # Reload the whole config from scratch so that the portdbapi internal
5377 # config is updated with new FEATURES.
5378 settings, trees, mtimedb = load_emerge_config(trees=trees)
5379 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5381 for myroot in trees:
5382 mysettings = trees[myroot]["vartree"].settings
5384 adjust_config(myopts, mysettings)
5386 del myroot, mysettings
5388 spinner = stdout_spinner()
5389 if "candy" in settings.features:
5390 spinner.update = spinner.update_scroll
5392 if "--quiet" not in myopts:
5393 portage.deprecated_profile_check()
5395 #Freeze the portdbapi for enhanced performance:
5396 for myroot in trees:
5397 trees[myroot]["porttree"].dbapi.freeze()
5400 if "moo" in myfiles:
5403 Larry loves Gentoo (""" + os.uname()[0] + """)
5405 _______________________
5406 < Have you mooed today? >
5407 -----------------------
5416 if (myaction in ["world", "system"]) and myfiles:
5417 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5421 ext = os.path.splitext(x)[1]
5422 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5423 print "emerging by path implies --oneshot... adding --oneshot to options."
5424 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5427 if ("--tree" in myopts) and ("--columns" in myopts):
5428 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5431 if ("--quiet" in myopts):
5432 spinner.update = spinner.update_quiet
5433 portage.util.noiselimit = -1
5435 # Always create packages if FEATURES=buildpkg
5436 # Imply --buildpkg if --buildpkgonly
5437 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5438 if "--buildpkg" not in myopts:
5439 myopts["--buildpkg"] = True
5441 # Also allow -S to invoke search action (-sS)
5442 if ("--searchdesc" in myopts):
5443 if myaction and myaction != "search":
5444 myfiles.append(myaction)
5445 if "--search" not in myopts:
5446 myopts["--search"] = True
5449 # Always try and fetch binary packages if FEATURES=getbinpkg
5450 if ("getbinpkg" in settings.features):
5451 myopts["--getbinpkg"] = True
5453 if "--skipfirst" in myopts and "--resume" not in myopts:
5454 myopts["--resume"] = True
5456 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5457 myopts["--usepkgonly"] = True
5459 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5460 myopts["--getbinpkg"] = True
5462 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5463 myopts["--usepkg"] = True
5465 # Also allow -K to apply --usepkg/-k
5466 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5467 myopts["--usepkg"] = True
5469 # Allow -p to remove --ask
5470 if ("--pretend" in myopts) and ("--ask" in myopts):
5471 print ">>> --pretend disables --ask... removing --ask from options."
5474 # forbid --ask when not in a terminal
5475 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5476 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5477 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5481 if settings.get("PORTAGE_DEBUG", "") == "1":
5482 spinner.update = spinner.update_quiet
5484 if "python-trace" in settings.features:
5485 import portage.debug
5486 portage.debug.set_trace(True)
5488 if ("--resume" in myopts):
5489 if "--tree" in myopts:
5490 print "* --tree is currently broken with --resume. Disabling..."
5491 del myopts["--tree"]
5493 if not ("--quiet" in myopts):
5494 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5495 spinner.update = spinner.update_basic
5497 if "--version" in myopts:
5498 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5499 settings.profile_path, settings["CHOST"],
5500 trees[settings["ROOT"]]["vartree"].dbapi)
5502 elif "--help" in myopts:
5503 emerge.help.help(myaction, myopts, portage.output.havecolor)
5506 if portage.wheelgid == portage.portage_gid:
5507 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5508 print " include the portage user as noted above, and then use group portage."
5510 if "--debug" in myopts:
5511 print "myaction", myaction
5512 print "myopts", myopts
5514 if not myaction and not myfiles and "--resume" not in myopts:
5515 emerge.help.help(myaction, myopts, portage.output.havecolor)
5518 # check if root user is the current user for the actions where emerge needs this
5519 if portage.secpass < 2:
5520 # We've already allowed "--version" and "--help" above.
5521 if "--pretend" not in myopts and \
5522 myaction not in ("search","info"):
5523 need_superuser = not \
5524 ("--fetchonly" in myopts or \
5525 "--fetch-all-uri" in myopts or \
5526 myaction in ("metadata", "regen"))
5527 if portage.secpass < 1 or \
5530 access_desc = "superuser"
5532 access_desc = "portage group"
5533 # Always show portage_group_warning() when only portage group
5534 # access is required but the user is not in the portage group.
5535 from portage.data import portage_group_warning
5536 if "--ask" in myopts:
5537 myopts["--pretend"] = True
5539 print ("%s access would be required... " + \
5540 "adding --pretend to options.\n") % access_desc
5541 if portage.secpass < 1 and not need_superuser:
5542 portage_group_warning()
5544 sys.stderr.write(("emerge: %s access would be " + \
5545 "required.\n\n") % access_desc)
5546 if portage.secpass < 1 and not need_superuser:
5547 portage_group_warning()
5550 disable_emergelog = False
5551 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5553 disable_emergelog = True
5555 if myaction in ("search", "info"):
5556 disable_emergelog = True
5557 if disable_emergelog:
5558 """ Disable emergelog for everything except build or unmerge
5559 operations. This helps minimize parallel emerge.log entries that can
5560 confuse log parsers. We especially want it disabled during
5561 parallel-fetch, which uses --resume --fetchonly."""
5563 def emergelog(*pargs, **kargs):
5566 if not "--pretend" in myopts:
5567 emergelog(xterm_titles, "Started emerge on: "+\
5568 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5571 myelogstr=" ".join(myopts)
5573 myelogstr+=" "+myaction
5575 myelogstr+=" "+" ".join(myfiles)
5576 emergelog(xterm_titles, " *** emerge " + myelogstr)
5578 def emergeexitsig(signum, frame):
5579 signal.signal(signal.SIGINT, signal.SIG_IGN)
5580 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5581 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5582 sys.exit(100+signum)
5583 signal.signal(signal.SIGINT, emergeexitsig)
5584 signal.signal(signal.SIGTERM, emergeexitsig)
5587 """This gets out final log message in before we quit."""
5588 if "--pretend" not in myopts:
5589 emergelog(xterm_titles, " *** terminating.")
5590 if "notitles" not in settings.features:
5592 portage.atexit_register(emergeexit)
5594 if myaction in ("config", "metadata", "regen", "sync"):
5595 if "--pretend" in myopts:
5596 sys.stderr.write(("emerge: The '%s' action does " + \
5597 "not support '--pretend'.\n") % myaction)
5599 if "sync" == myaction:
5600 action_sync(settings, trees, mtimedb, myopts, myaction)
5601 elif "metadata" == myaction:
5602 action_metadata(settings, portdb, myopts)
5603 elif myaction=="regen":
5604 validate_ebuild_environment(trees)
5605 action_regen(settings, portdb)
5607 elif "config"==myaction:
5608 validate_ebuild_environment(trees)
5609 action_config(settings, trees, myopts, myfiles)
5612 elif "info"==myaction:
5613 action_info(settings, trees, myopts, myfiles)
5616 elif "search"==myaction:
5617 validate_ebuild_environment(trees)
5618 action_search(settings, portdb, trees["/"]["vartree"],
5619 myopts, myfiles, spinner)
5620 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5621 validate_ebuild_environment(trees)
5622 vartree = trees[settings["ROOT"]]["vartree"]
5623 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5625 if "--pretend" not in myopts:
5626 post_emerge(settings, mtimedb, 0)
5628 elif "depclean"==myaction:
5629 validate_ebuild_environment(trees)
5630 action_depclean(settings, trees, mtimedb["ldpath"],
5632 if "--pretend" not in myopts:
5633 post_emerge(settings, mtimedb, 0)
5634 # "update", "system", or just process files:
5636 validate_ebuild_environment(trees)
5637 if "--pretend" not in myopts:
5638 display_news_notification(settings)
5639 action_build(settings, trees, mtimedb,
5640 myopts, myaction, myfiles, spinner)
5641 if "--pretend" not in myopts:
5642 post_emerge(settings, mtimedb, 0)
5644 display_news_notification(settings)
5646 if __name__ == "__main__":
5647 retval = emerge_main()