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
3734 for repo in porttree.getRepositories():
3735 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3737 if not newsReaderDisplay:
3738 newsReaderDisplay = True
3740 print colorize("WARN", " * IMPORTANT:"),
3741 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3744 if newsReaderDisplay:
3745 print colorize("WARN", " *"),
3746 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3749 def post_emerge(settings, mtimedb, retval):
3751 Misc. things to run at the end of a merge session.
3757 Display preserved libs warnings
3760 @param settings: Configuration settings (typically portage.settings)
3761 @type settings: portage.config()
3762 @param mtimedb: The mtimeDB to store data needed across merge invocations
3763 @type mtimedb: MtimeDB class instance
3764 @param retval: Emerge's return value
3768 1. Calls sys.exit(retval)
3770 target_root = settings["ROOT"]
3771 info_mtimes = mtimedb["info"]
3773 # Load the most current variables from ${ROOT}/etc/profile.env
3775 settings.regenerate()
3778 config_protect = settings.get("CONFIG_PROTECT","").split()
3779 infodirs = settings.get("INFOPATH","").split(":") + \
3780 settings.get("INFODIR","").split(":")
3784 emergelog("notitles" not in settings.features,
3785 " *** exiting successfully.")
3787 if "noinfo" not in settings.features:
3788 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3790 chk_updated_cfg_files(target_root, config_protect)
3792 display_news_notification(settings)
3794 from portage.dbapi.vartree import PreservedLibsRegistry
3795 plib_registry = PreservedLibsRegistry(os.path.join(target_root, CACHE_PATH, "preserved_libs_registry"))
3796 if plib_registry.hasEntries():
3797 print colorize("WARN", "!!!") + " existing preserved libs:"
3798 plibdata = plib_registry.getPreservedLibs()
3799 for cpv in plibdata.keys():
3800 print colorize("WARN", ">>>") + " package: %s" % cpv
3801 for f in plibdata[cpv]:
3802 print colorize("WARN", " * ") + " - %s" % f
3803 print "Use " + colorize("GOOD", "revdep-rebuild") + " to rebuild packages using these libraries"
3804 print "and then remerge the packages listed above."
3810 def chk_updated_cfg_files(target_root, config_protect):
3812 #number of directories with some protect files in them
3814 for x in config_protect:
3815 x = os.path.join(target_root, x.lstrip(os.path.sep))
3817 mymode = os.lstat(x).st_mode
3820 if stat.S_ISDIR(mymode):
3821 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3823 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3824 os.path.split(x.rstrip(os.path.sep))
3825 a = commands.getstatusoutput(mycommand + \
3826 " ! -iname '.*~' ! -iname '.*.bak'")
3828 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3830 files = a[1].split()
3833 print colorize("WARN", " * IMPORTANT:"),
3834 if stat.S_ISDIR(mymode):
3835 print "%d config files in '%s' need updating." % \
3838 print "config file '%s' needs updating." % x
3841 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3842 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3844 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3846 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3847 Returns the number of unread (yet relevent) items.
3859 1. The number of unread but relevant news items.
3862 from portage.news import NewsManager
3863 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3864 return manager.getUnreadItems( repo_id, update=True )
3866 def is_valid_package_atom(x):
3868 testkey = portage.dep_getkey(x)
3869 except portage.exception.InvalidData:
3871 if testkey.startswith("null/"):
3872 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3877 return portage.isvalidatom(testatom)
3879 def validate_merge_list(trees, mergelist):
3880 """Validate the list to make sure all the packages are still available.
3881 This is needed for --resume."""
3882 for (pkg_type, myroot, pkg_key, action) in mergelist:
3883 if pkg_type == "binary" and \
3884 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3885 pkg_type == "ebuild" and \
3886 not trees[myroot]["porttree"].dbapi.xmatch(
3887 "match-all", "="+pkg_key):
3888 print red("!!! Error: The resume list contains packages that are no longer")
3889 print red("!!! available to be emerged. Please restart/continue")
3890 print red("!!! the merge operation manually.")
3893 def show_blocker_docs_link():
3895 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3896 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3898 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3901 def action_sync(settings, trees, mtimedb, myopts, myaction):
3902 xterm_titles = "notitles" not in settings.features
3903 emergelog(xterm_titles, " === sync")
3904 myportdir = settings.get("PORTDIR", None)
3906 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3908 if myportdir[-1]=="/":
3909 myportdir=myportdir[:-1]
3910 if not os.path.exists(myportdir):
3911 print ">>>",myportdir,"not found, creating it."
3912 os.makedirs(myportdir,0755)
3913 syncuri=settings["SYNC"].rstrip()
3915 updatecache_flg = False
3916 if myaction == "metadata":
3917 print "skipping sync"
3918 updatecache_flg = True
3919 tmpservertimestampfile = None
3920 elif syncuri[:8]=="rsync://":
3921 if not os.path.exists("/usr/bin/rsync"):
3922 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3923 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3928 import shlex, StringIO
3929 if settings["PORTAGE_RSYNC_OPTS"] == "":
3930 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3932 "--recursive", # Recurse directories
3933 "--links", # Consider symlinks
3934 "--safe-links", # Ignore links outside of tree
3935 "--perms", # Preserve permissions
3936 "--times", # Preserive mod times
3937 "--compress", # Compress the data transmitted
3938 "--force", # Force deletion on non-empty dirs
3939 "--whole-file", # Don't do block transfers, only entire files
3940 "--delete", # Delete files that aren't in the master tree
3941 "--delete-after", # Delete only after everything else is done
3942 "--stats", # Show final statistics about what was transfered
3943 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3944 "--exclude=/distfiles", # Exclude distfiles from consideration
3945 "--exclude=/local", # Exclude local from consideration
3946 "--exclude=/packages", # Exclude packages from consideration
3947 "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
3951 # The below validation is not needed when using the above hardcoded
3954 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3955 lexer = shlex.shlex(StringIO.StringIO(
3956 settings.get("PORTAGE_RSYNC_OPTS","")), posix=True)
3957 lexer.whitespace_split = True
3958 rsync_opts.extend(lexer)
3961 for opt in ("--recursive", "--times"):
3962 if opt not in rsync_opts:
3963 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3964 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3965 rsync_opts.append(opt)
3967 for exclude in ("distfiles", "local", "packages"):
3968 opt = "--exclude=/%s" % exclude
3969 if opt not in rsync_opts:
3970 portage.writemsg(yellow("WARNING:") + \
3971 " adding required option %s not included in " % opt + \
3972 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3973 rsync_opts.append(opt)
3975 if settings["RSYNC_TIMEOUT"] != "":
3976 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3977 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3979 mytimeout = int(settings["RSYNC_TIMEOUT"])
3980 rsync_opts.append("--timeout=%d" % mytimeout)
3981 except ValueError, e:
3982 portage.writemsg("!!! %s\n" % str(e))
3984 # TODO: determine options required for official servers
3985 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
3987 def rsync_opt_startswith(opt_prefix):
3988 for x in rsync_opts:
3989 if x.startswith(opt_prefix):
3993 if not rsync_opt_startswith("--timeout="):
3994 rsync_opts.append("--timeout=%d" % mytimeout)
3996 for opt in ("--compress", "--whole-file"):
3997 if opt not in rsync_opts:
3998 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3999 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4000 rsync_opts.append(opt)
4002 if "--quiet" in myopts:
4003 rsync_opts.append("--quiet") # Shut up a lot
4005 rsync_opts.append("--verbose") # Print filelist
4007 if "--verbose" in myopts:
4008 rsync_opts.append("--progress") # Progress meter for each file
4010 if "--debug" in myopts:
4011 rsync_opts.append("--checksum") # Force checksum on all files
4013 if settings["RSYNC_EXCLUDEFROM"] != "":
4014 portage.writemsg(yellow("WARNING:") + \
4015 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
4016 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4017 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
4018 rsync_opts.append("--exclude-from=%s" % \
4019 settings["RSYNC_EXCLUDEFROM"])
4021 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
4022 " but file does not exist.\n")
4024 if settings["RSYNC_RATELIMIT"] != "":
4025 portage.writemsg(yellow("WARNING:") + \
4026 " usage of RSYNC_RATELIMIT is deprecated, use " + \
4027 "PORTAGE_RSYNC_EXTRA_OPTS instead")
4028 rsync_opts.append("--bwlimit=%s" % \
4029 settings["RSYNC_RATELIMIT"])
4031 # Real local timestamp file.
4032 servertimestampfile = os.path.join(
4033 myportdir, "metadata", "timestamp.chk")
4034 # Temporary file for remote server timestamp comparison.
4035 tmpservertimestampfile = os.path.join(
4036 settings["PORTAGE_TMPDIR"], "timestamp.chk")
4038 content = portage.util.grabfile(servertimestampfile)
4042 mytimestamp = time.mktime(time.strptime(content[0],
4043 "%a, %d %b %Y %H:%M:%S +0000"))
4044 except (OverflowError, ValueError):
4049 if settings.has_key("RSYNC_RETRIES"):
4050 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
4051 maxretries=int(settings["RSYNC_RETRIES"])
4053 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
4054 except SystemExit, e:
4055 raise # Needed else can't exit
4057 maxretries=3 #default number of retries
4060 user_name, hostname, port = re.split(
4061 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
4064 if user_name is None:
4066 updatecache_flg=True
4067 all_rsync_opts = set(rsync_opts)
4068 lexer = shlex.shlex(StringIO.StringIO(
4069 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")), posix=True)
4070 lexer.whitespace_split = True
4071 extra_rsync_opts = list(lexer)
4073 all_rsync_opts.update(extra_rsync_opts)
4074 family = socket.AF_INET
4075 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
4076 family = socket.AF_INET
4077 elif socket.has_ipv6 and \
4078 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
4079 family = socket.AF_INET6
4086 for addrinfo in socket.getaddrinfo(
4087 hostname, None, family, socket.SOCK_STREAM):
4088 if addrinfo[0] == socket.AF_INET6:
4089 # IPv6 addresses need to be enclosed in square brackets
4090 ips.append("[%s]" % addrinfo[4][0])
4092 ips.append(addrinfo[4][0])
4093 from random import shuffle
4095 except SystemExit, e:
4096 raise # Needed else can't exit
4097 except Exception, e:
4098 print "Notice:",str(e)
4103 dosyncuri = syncuri.replace(
4104 "//" + user_name + hostname + port + "/",
4105 "//" + user_name + ips[0] + port + "/", 1)
4106 except SystemExit, e:
4107 raise # Needed else can't exit
4108 except Exception, e:
4109 print "Notice:",str(e)
4113 if "--ask" in myopts:
4114 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
4119 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
4120 if "--quiet" not in myopts:
4121 print ">>> Starting rsync with "+dosyncuri+"..."
4123 emergelog(xterm_titles,
4124 ">>> Starting retry %d of %d with %s" % \
4125 (retries,maxretries,dosyncuri))
4126 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
4128 if mytimestamp != 0 and "--quiet" not in myopts:
4129 print ">>> Checking server timestamp ..."
4131 rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
4133 if "--debug" in myopts:
4138 # Even if there's no timestamp available locally, fetch the
4139 # timestamp anyway as an initial probe to verify that the server is
4140 # responsive. This protects us from hanging indefinitely on a
4141 # connection attempt to an unresponsive server which rsync's
4142 # --timeout option does not prevent.
4144 mycommand = rsynccommand[:]
4145 mycommand.append(dosyncuri.rstrip("/") + \
4146 "/metadata/timestamp.chk")
4147 mycommand.append(tmpservertimestampfile)
4151 def timeout_handler(signum, frame):
4152 raise portage.exception.PortageException("timed out")
4153 signal.signal(signal.SIGALRM, timeout_handler)
4154 # Timeout here in case the server is unresponsive. The
4155 # --timeout rsync option doesn't apply to the initial
4156 # connection attempt.
4159 mypids.extend(portage.process.spawn(
4160 mycommand, env=settings.environ(), returnpid=True))
4161 exitcode = os.waitpid(mypids[0], 0)[1]
4162 content = portage.grabfile(tmpservertimestampfile)
4166 os.unlink(tmpservertimestampfile)
4169 except portage.exception.PortageException, e:
4173 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
4174 os.kill(mypids[0], signal.SIGTERM)
4175 os.waitpid(mypids[0], 0)
4176 # This is the same code rsync uses for timeout.
4179 if exitcode != os.EX_OK:
4181 exitcode = (exitcode & 0xff) << 8
4183 exitcode = exitcode >> 8
4185 portage.process.spawned_pids.remove(mypids[0])
4188 servertimestamp = time.mktime(time.strptime(
4189 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
4190 except (OverflowError, ValueError):
4192 del mycommand, mypids, content
4193 if exitcode == os.EX_OK:
4194 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4195 emergelog(xterm_titles,
4196 ">>> Cancelling sync -- Already current.")
4199 print ">>> Timestamps on the server and in the local repository are the same."
4200 print ">>> Cancelling all further sync action. You are already up to date."
4202 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4206 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4207 emergelog(xterm_titles,
4208 ">>> Server out of date: %s" % dosyncuri)
4211 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4213 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4216 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4218 mycommand = rsynccommand + [dosyncuri+"/", myportdir]
4219 exitcode = portage.process.spawn(mycommand,
4220 env=settings.environ())
4221 if exitcode in [0,1,3,4,11,14,20,21]:
4223 elif exitcode in [1,3,4,11,14,20,21]:
4226 # Code 2 indicates protocol incompatibility, which is expected
4227 # for servers with protocol < 29 that don't support
4228 # --prune-empty-directories. Retry for a server that supports
4229 # at least rsync protocol version 29 (>=rsync-2.6.4).
4234 if retries<=maxretries:
4235 print ">>> Retrying..."
4240 updatecache_flg=False
4244 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4248 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4249 print darkred("!!!")+green(" that your SYNC statement is proper.")
4250 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4252 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4253 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4254 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4255 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4256 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4258 print darkred("!!!")+green(" Rsync was killed before it finished.")
4260 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4261 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4262 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4263 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4264 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4267 elif syncuri[:6]=="cvs://":
4268 if not os.path.exists("/usr/bin/cvs"):
4269 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4270 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4273 cvsdir=os.path.dirname(myportdir)
4274 if not os.path.exists(myportdir+"/CVS"):
4276 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4277 if os.path.exists(cvsdir+"/gentoo-x86"):
4278 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4283 if e.errno != errno.ENOENT:
4285 "!!! existing '%s' directory; exiting.\n" % myportdir)
4288 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4289 print "!!! cvs checkout error; exiting."
4291 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4294 print ">>> Starting cvs update with "+syncuri+"..."
4295 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4296 myportdir, settings, free=1)
4297 if retval != os.EX_OK:
4301 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4304 if updatecache_flg and \
4305 myaction != "metadata" and \
4306 "metadata-transfer" not in settings.features:
4307 updatecache_flg = False
4309 # Reload the whole config from scratch.
4310 settings, trees, mtimedb = load_emerge_config(trees=trees)
4311 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4313 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4314 action_metadata(settings, portdb, myopts)
4316 if portage.global_updates(settings, trees, mtimedb["updates"]):
4318 # Reload the whole config from scratch.
4319 settings, trees, mtimedb = load_emerge_config(trees=trees)
4320 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4322 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4323 mypvs = portage.best(
4324 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4326 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4328 if myaction != "metadata":
4329 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4330 retval = portage.process.spawn(
4331 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4332 dosyncuri], env=settings.environ())
4333 if retval != os.EX_OK:
4334 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4336 if(mybestpv != mypvs) and not "--quiet" in myopts:
4338 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4339 print red(" * ")+"that you update portage now, before any other packages are updated."
4340 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4341 print red(" * ")+"configuration files."
4342 print red(" * ")+"To update portage, run 'emerge portage'."
4345 display_news_notification(settings)
4347 def action_metadata(settings, portdb, myopts):
4348 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4349 old_umask = os.umask(0002)
4350 cachedir = os.path.normpath(settings.depcachedir)
4351 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4352 "/lib", "/opt", "/proc", "/root", "/sbin",
4353 "/sys", "/tmp", "/usr", "/var"]:
4354 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4355 "ROOT DIRECTORY ON YOUR SYSTEM."
4356 print >> sys.stderr, \
4357 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4359 if not os.path.exists(cachedir):
4362 ec = portage.eclass_cache.cache(portdb.porttree_root)
4363 myportdir = os.path.realpath(settings["PORTDIR"])
4364 cm = settings.load_best_module("portdbapi.metadbmodule")(
4365 myportdir, "metadata/cache", portage.auxdbkeys[:])
4367 from portage.cache import util
4369 class percentage_noise_maker(util.quiet_mirroring):
4370 def __init__(self, dbapi):
4372 self.cp_all = dbapi.cp_all()
4373 l = len(self.cp_all)
4374 self.call_update_min = 100000000
4375 self.min_cp_all = l/100.0
4380 for x in self.cp_all:
4382 if self.count > self.min_cp_all:
4383 self.call_update_min = 0
4385 for y in self.dbapi.cp_list(x):
4387 self.call_update_mine = 0
4389 def update(self, *arg):
4390 try: self.pstr = int(self.pstr) + 1
4391 except ValueError: self.pstr = 1
4392 sys.stdout.write("%s%i%%" % \
4393 ("\b" * (len(str(self.pstr))+1), self.pstr))
4395 self.call_update_min = 10000000
4397 def finish(self, *arg):
4398 sys.stdout.write("\b\b\b\b100%\n")
4401 if "--quiet" in myopts:
4402 def quicky_cpv_generator(cp_all_list):
4403 for x in cp_all_list:
4404 for y in portdb.cp_list(x):
4406 source = quicky_cpv_generator(portdb.cp_all())
4407 noise_maker = portage.cache.util.quiet_mirroring()
4409 noise_maker = source = percentage_noise_maker(portdb)
4410 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4411 eclass_cache=ec, verbose_instance=noise_maker)
4416 def action_regen(settings, portdb):
4417 xterm_titles = "notitles" not in settings.features
4418 emergelog(xterm_titles, " === regen")
4419 #regenerate cache entries
4420 print "Regenerating cache entries... "
4422 os.close(sys.stdin.fileno())
4423 except SystemExit, e:
4424 raise # Needed else can't exit
4428 mynodes = portdb.cp_all()
4429 from portage.cache.cache_errors import CacheError
4431 for mytree in portdb.porttrees:
4433 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4434 except CacheError, e:
4435 print "\n error listing cache entries for " + \
4436 "'%s': %s, continuing..." % (mytree, e)
4441 mymatches = portdb.cp_list(x)
4442 portage.writemsg_stdout("processing %s\n" % x)
4445 foo = portdb.aux_get(y,["DEPEND"])
4446 except SystemExit, e:
4447 # sys.exit is an exception... And consequently, we can't catch it.
4449 except Exception, e:
4450 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4452 for mytree in portdb.porttrees:
4453 if portdb.findname2(y, mytree=mytree)[0]:
4454 dead_nodes[mytree].discard(y)
4456 for mytree, nodes in dead_nodes.iteritems():
4457 auxdb = portdb.auxdb[mytree]
4461 except (KeyError, CacheError):
4465 def action_config(settings, trees, myopts, myfiles):
4466 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4467 print red("!!! config can only take a single package atom at this time\n")
4469 if not is_valid_package_atom(myfiles[0]):
4470 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4472 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4473 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4477 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4478 except ValueError, e:
4479 # Multiple matches thrown from cpv_expand
4482 print "No packages found.\n"
4485 if "--ask" in myopts:
4487 print "Please select a package to configure:"
4491 options.append(str(idx))
4492 print options[-1]+") "+pkg
4495 idx = userquery("Selection?", options)
4498 pkg = pkgs[int(idx)-1]
4500 print "The following packages available:"
4503 print "\nPlease use a specific atom or the --ask option."
4509 if "--ask" in myopts:
4510 if userquery("Ready to configure "+pkg+"?") == "No":
4513 print "Configuring pkg..."
4515 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4516 mysettings = portage.config(clone=settings)
4517 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4518 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4519 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4522 def action_info(settings, trees, myopts, myfiles):
4523 unameout=commands.getstatusoutput("uname -mrp")[1]
4524 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4525 settings.profile_path, settings["CHOST"],
4526 trees[settings["ROOT"]]["vartree"].dbapi)
4528 header_title = "System Settings"
4530 print header_width * "="
4531 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4532 print header_width * "="
4533 print "System uname: "+unameout
4534 gentoo_release = portage.grabfile(os.path.join(
4535 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4537 print gentoo_release[0]
4539 print "Unknown Host Operating System"
4540 lastSync = portage.grabfile(os.path.join(
4541 settings["PORTDIR"], "metadata", "timestamp.chk"))
4542 print "Timestamp of tree:",
4548 output=commands.getstatusoutput("distcc --version")
4550 print str(output[1].split("\n",1)[0]),
4551 if "distcc" in settings.features:
4556 output=commands.getstatusoutput("ccache -V")
4558 print str(output[1].split("\n",1)[0]),
4559 if "ccache" in settings.features:
4564 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4565 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4566 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4567 myvars = portage.util.unique_array(myvars)
4571 if portage.isvalidatom(x):
4572 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4573 pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
4574 pkg_matches.sort(portage.pkgcmp)
4576 for pn, ver, rev in pkg_matches:
4578 pkgs.append(ver + "-" + rev)
4582 pkgs = ", ".join(pkgs)
4583 print "%-20s %s" % (x+":", pkgs)
4585 print "%-20s %s" % (x+":", "[NOT VALID]")
4587 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4589 if "--verbose" in myopts:
4590 myvars=settings.keys()
4592 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4593 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4594 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4595 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4597 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4599 myvars = portage.util.unique_array(myvars)
4605 print '%s="%s"' % (x, settings[x])
4607 use = set(settings["USE"].split())
4608 use_expand = settings["USE_EXPAND"].split()
4610 for varname in use_expand:
4611 flag_prefix = varname.lower() + "_"
4613 if f.startswith(flag_prefix):
4617 print 'USE="%s"' % " ".join(use),
4618 for varname in use_expand:
4619 myval = settings.get(varname)
4621 print '%s="%s"' % (varname, myval),
4624 unset_vars.append(x)
4626 print "Unset: "+", ".join(unset_vars)
4629 if "--debug" in myopts:
4630 for x in dir(portage):
4631 module = getattr(portage, x)
4632 if "cvs_id_string" in dir(module):
4633 print "%s: %s" % (str(x), str(module.cvs_id_string))
4635 # See if we can find any packages installed matching the strings
4636 # passed on the command line
4638 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4639 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4641 mypkgs.extend(vardb.match(x))
4643 # If some packages were found...
4645 # Get our global settings (we only print stuff if it varies from
4646 # the current config)
4647 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4648 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4650 pkgsettings = portage.config(clone=settings)
4652 for myvar in mydesiredvars:
4653 global_vals[myvar] = set(settings.get(myvar, "").split())
4655 # Loop through each package
4656 # Only print settings if they differ from global settings
4657 header_printed = False
4659 # Get all package specific variables
4660 auxvalues = vardb.aux_get(pkg, auxkeys)
4662 for i in xrange(len(auxkeys)):
4663 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4665 for myvar in mydesiredvars:
4666 # If the package variable doesn't match the
4667 # current global variable, something has changed
4668 # so set diff_found so we know to print
4669 if valuesmap[myvar] != global_vals[myvar]:
4670 diff_values[myvar] = valuesmap[myvar]
4671 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4672 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4674 # If a matching ebuild is no longer available in the tree, maybe it
4675 # would make sense to compare against the flags for the best
4676 # available version with the same slot?
4678 if portdb.cpv_exists(pkg):
4680 pkgsettings.setcpv(pkg, mydb=mydb)
4681 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4683 diff_values["USE"] = valuesmap["USE"]
4684 # If a difference was found, print the info for
4688 # If we have not yet printed the header,
4690 if not header_printed:
4691 header_title = "Package Settings"
4692 print header_width * "="
4693 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4694 print header_width * "="
4695 header_printed = True
4697 # Print package info
4698 print "%s was built with the following:" % pkg
4699 for myvar in mydesiredvars + ["USE"]:
4700 if myvar in diff_values:
4701 mylist = list(diff_values[myvar])
4703 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4706 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4708 print "emerge: no search terms provided."
4710 searchinstance = search(settings, portdb,
4711 vartree, spinner, "--searchdesc" in myopts,
4712 "--quiet" not in myopts)
4713 for mysearch in myfiles:
4715 searchinstance.execute(mysearch)
4716 except re.error, comment:
4717 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4719 searchinstance.output()
4721 def action_depclean(settings, trees, ldpath_mtimes,
4723 # Kill packages that aren't explicitly merged or are required as a
4724 # dependency of another package. World file is explicit.
4726 warn_prefix = colorize("BAD", "*** WARNING *** ")
4728 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4729 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4730 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4732 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4733 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4734 print warn_prefix + "be kept. They can be manually added to this set with"
4735 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4736 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4737 print warn_prefix + "depclean, even if they are part of the world set."
4739 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4740 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4741 print warn_prefix + "consequence, it is often necessary to run "
4742 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4744 xterm_titles = "notitles" not in settings.features
4745 myroot = settings["ROOT"]
4746 dep_check_trees = {}
4747 dep_check_trees[myroot] = {}
4748 dep_check_trees[myroot]["vartree"] = \
4749 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4750 vardb = dep_check_trees[myroot]["vartree"].dbapi
4751 # Constrain dependency selection to the installed packages.
4752 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4753 syslist = getlist(settings, "system")
4754 worldlist = getlist(settings, "world")
4755 system_world_dict = genericdict(worldlist)
4756 system_world_dict.update(genericdict(syslist))
4757 fakedb = portage.fakedbapi(settings=settings)
4758 myvarlist = vardb.cpv_all()
4761 print "\n!!! You have no system list.",
4763 print "\n!!! You have no world file.",
4765 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4767 if not (syslist and worldlist and myvarlist):
4768 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4769 print " break your installation.\n"
4770 if "--pretend" not in myopts:
4771 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4773 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4774 emergelog(xterm_titles, " >>> depclean")
4776 if "--quiet" not in myopts:
4777 print "\nCalculating dependencies ",
4781 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4782 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4784 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4786 while remaining_atoms:
4787 atom, parent, priority = remaining_atoms.pop()
4788 pkgs = vardb.match(atom)
4790 if not atom.startswith("!") and priority == hard:
4791 unresolveable.setdefault(atom, []).append(parent)
4793 if portage.dep_getkey(atom) not in system_world_dict:
4794 # Prune all but the best matching slot, since that's all that a
4795 # deep world update would pull in. Don't prune if the cpv is in
4796 # system or world though, since those sets trigger greedy update
4798 pkgs = [portage.best(pkgs)]
4800 if fakedb.cpv_exists(pkg):
4803 fakedb.cpv_inject(pkg)
4804 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4806 if myopts.get("--with-bdeps", "y") == "y":
4807 mydeps.append((myaux["DEPEND"], soft))
4809 mydeps.append((" ".join(myaux.values()), hard))
4810 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4811 for depstr, priority in mydeps:
4816 if "--debug" in myopts:
4818 print "Parent: ", pkg
4819 print "Depstring:", depstr
4821 if priority == soft:
4827 portage.dep._dep_check_strict = False
4828 success, atoms = portage.dep_check(depstr, None, settings,
4829 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4831 portage.dep._dep_check_strict = True
4833 show_invalid_depstring_notice(
4834 ("installed", myroot, pkg, "nomerge"),
4838 if "--debug" in myopts:
4839 print "Candidates:", atoms
4842 remaining_atoms.append((atom, pkg, priority))
4844 if "--quiet" not in myopts:
4845 print "\b\b... done!\n"
4848 print "Dependencies could not be completely resolved due to"
4849 print "the following required packages not being installed:"
4851 for atom in unresolveable:
4852 print atom, "required by", " ".join(unresolveable[atom])
4854 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4855 print "depclean? It may be necessary to manually uninstall packages that no longer"
4856 print "exist in the portage tree since it may not be possible to satisfy their"
4857 print "dependencies. Also, be aware of the --with-bdeps option that is documented"
4858 print "in " + good("`man emerge`") + "."
4862 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4865 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4866 "unmerge", cleanlist, ldpath_mtimes)
4868 print "Packages installed: "+str(len(myvarlist))
4869 print "Packages in world: "+str(len(worldlist))
4870 print "Packages in system: "+str(len(syslist))
4871 print "Unique package names: "+str(len(myvarlist))
4872 print "Required packages: "+str(len(fakedb.cpv_all()))
4873 if "--pretend" in myopts:
4874 print "Number to remove: "+str(len(cleanlist))
4876 print "Number removed: "+str(len(cleanlist))
4878 def action_build(settings, trees, mtimedb,
4879 myopts, myaction, myfiles, spinner):
4880 ldpath_mtimes = mtimedb["ldpath"]
4882 if "--quiet" not in myopts and \
4883 ("--pretend" in myopts or "--ask" in myopts or \
4884 "--tree" in myopts or "--verbose" in myopts):
4886 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4890 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4892 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4896 print darkgreen("These are the packages that would be %s, in order:") % action
4899 # validate the state of the resume data
4900 # so that we can make assumptions later.
4901 for k in ("resume", "resume_backup"):
4903 if "mergelist" in mtimedb[k]:
4904 if not mtimedb[k]["mergelist"]:
4909 if "--resume" in myopts and \
4910 ("resume" in mtimedb or
4911 "resume_backup" in mtimedb):
4912 if "resume" not in mtimedb:
4913 mtimedb["resume"] = mtimedb["resume_backup"]
4914 del mtimedb["resume_backup"]
4916 # XXX: "myopts" is a list for backward compatibility.
4917 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4919 for opt in ("--skipfirst", "--ask", "--tree"):
4920 myresumeopts.pop(opt, None)
4922 for myopt, myarg in myopts.iteritems():
4923 if myopt not in myresumeopts:
4924 myresumeopts[myopt] = myarg
4927 # Adjust config according to options of the command being resumed.
4928 for myroot in trees:
4929 mysettings = trees[myroot]["vartree"].settings
4931 adjust_config(myopts, mysettings)
4933 del myroot, mysettings
4935 myparams = create_depgraph_params(myopts, myaction)
4936 if "--quiet" not in myopts and "--nodeps" not in myopts:
4937 print "Calculating dependencies ",
4938 mydepgraph = depgraph(settings, trees,
4939 myopts, myparams, spinner)
4940 if "--quiet" not in myopts and "--nodeps" not in myopts:
4941 print "\b\b... done!"
4943 if ("--resume" in myopts):
4944 print darkgreen("emerge: It seems we have nothing to resume...")
4947 myparams = create_depgraph_params(myopts, myaction)
4948 if myaction in ["system","world"]:
4949 if "--quiet" not in myopts and "--nodeps" not in myopts:
4950 print "Calculating",myaction,"dependencies ",
4952 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4953 if not mydepgraph.xcreate(myaction):
4954 print "!!! Depgraph creation failed."
4956 if "--quiet" not in myopts and "--nodeps" not in myopts:
4957 print "\b\b... done!"
4959 if "--quiet" not in myopts and "--nodeps" not in myopts:
4960 print "Calculating dependencies ",
4962 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4964 retval, favorites = mydepgraph.select_files(myfiles)
4965 except portage.exception.PackageNotFound, e:
4966 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4970 if "--quiet" not in myopts and "--nodeps" not in myopts:
4971 print "\b\b... done!"
4973 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4974 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4976 if mydepgraph.missingbins:
4977 for x in mydepgraph.missingbins:
4978 sys.stderr.write(" "+str(x)+"\n")
4979 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4982 if "--pretend" not in myopts and \
4983 ("--ask" in myopts or "--tree" in myopts or \
4984 "--verbose" in myopts) and \
4985 not ("--quiet" in myopts and "--ask" not in myopts):
4986 if "--resume" in myopts:
4987 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4988 mymergelist = mtimedb["resume"]["mergelist"]
4989 if "--skipfirst" in myopts:
4990 mymergelist = mymergelist[1:]
4991 if len(mymergelist) == 0:
4992 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4994 mydepgraph.display(mymergelist)
4995 prompt="Would you like to resume merging these packages?"
4998 mydepgraph.altlist(reversed=("--tree" in myopts)))
5000 for x in mydepgraph.altlist():
5001 if x[0] != "blocks" and x[3] != "nomerge":
5003 #check for blocking dependencies
5004 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
5005 print "\n!!! Error: The above package list contains packages which cannot be installed"
5006 print "!!! at the same time on the same system."
5007 if "--quiet" not in myopts:
5008 show_blocker_docs_link()
5011 if "--noreplace" in myopts and favorites:
5014 print " %s %s" % (good("*"), x)
5015 prompt="Would you like to add these packages to your world favorites?"
5016 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5017 prompt="Nothing to merge; would you like to auto-clean packages?"
5020 print "Nothing to merge; quitting."
5023 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5024 prompt="Would you like to fetch the source files for these packages?"
5026 prompt="Would you like to merge these packages?"
5028 if "--ask" in myopts and userquery(prompt) == "No":
5033 # Don't ask again (e.g. when auto-cleaning packages after merge)
5034 myopts.pop("--ask", None)
5036 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5037 if ("--resume" in myopts):
5038 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5039 mymergelist = mtimedb["resume"]["mergelist"]
5040 if "--skipfirst" in myopts:
5041 mymergelist = mymergelist[1:]
5042 if len(mymergelist) == 0:
5043 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5045 mydepgraph.display(mymergelist)
5048 mydepgraph.altlist(reversed=("--tree" in myopts)))
5049 if ("--buildpkgonly" in myopts):
5050 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5051 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5052 print "!!! You have to merge the dependencies before you can build this package.\n"
5055 if ("--buildpkgonly" in myopts):
5056 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5057 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5058 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
5061 if ("--resume" in myopts):
5062 favorites=mtimedb["resume"]["favorites"]
5063 mergetask = MergeTask(settings, trees, myopts)
5064 if "--fetchonly" in myopts:
5065 """ parallel-fetch uses --resume --fetchonly and we don't want
5066 it to write the mtimedb"""
5067 mtimedb.filename = None
5068 time.sleep(3) # allow the parent to have first fetch
5070 retval = mergetask.merge(
5071 mtimedb["resume"]["mergelist"], favorites, mtimedb)
5072 if retval != os.EX_OK:
5075 if "resume" in mtimedb and \
5076 "mergelist" in mtimedb["resume"] and \
5077 len(mtimedb["resume"]["mergelist"]) > 1:
5078 mtimedb["resume_backup"] = mtimedb["resume"]
5079 del mtimedb["resume"]
5081 mtimedb["resume"]={}
5082 # XXX: Stored as a list for backward compatibility.
5083 mtimedb["resume"]["myopts"] = \
5084 [k for k in myopts if myopts[k] is True]
5085 mtimedb["resume"]["favorites"]=favorites
5086 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5087 for pkgline in mydepgraph.altlist():
5088 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5089 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
5090 tmpsettings = portage.config(clone=settings)
5092 if settings.get("PORTAGE_DEBUG", "") == "1":
5094 retval = portage.doebuild(
5095 y, "digest", settings["ROOT"], tmpsettings, edebug,
5096 ("--pretend" in myopts),
5097 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
5099 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5101 for pkg in mydepgraph.altlist():
5102 if pkg[0] != "blocks":
5105 pkglist = mydepgraph.altlist()
5107 mergetask = MergeTask(settings, trees, myopts)
5108 retval = mergetask.merge(pkglist, favorites, mtimedb)
5109 if retval != os.EX_OK:
5112 if mtimedb.has_key("resume"):
5113 del mtimedb["resume"]
5114 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5115 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5116 vartree = trees[settings["ROOT"]]["vartree"]
5117 unmerge(settings, myopts, vartree, "clean", ["world"],
5118 ldpath_mtimes, autoclean=1)
5120 portage.writemsg_stdout(colorize("WARN", "WARNING:")
5121 + " AUTOCLEAN is disabled. This can cause serious"
5122 + " problems due to overlapping packages.\n")
5124 def multiple_actions(action1, action2):
5125 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
5126 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
5129 def parse_opts(tmpcmdline, silent=False):
5134 global actions, options, shortmapping
5136 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
5137 argument_options = {
5139 "help":"specify the location for portage configuration files",
5143 "help":"enable or disable color output",
5145 "choices":("y", "n")
5148 "help":"include unnecessary build time dependencies",
5150 "choices":("y", "n")
5154 from optparse import OptionParser
5155 parser = OptionParser()
5156 if parser.has_option("--help"):
5157 parser.remove_option("--help")
5159 for action_opt in actions:
5160 parser.add_option("--" + action_opt, action="store_true",
5161 dest=action_opt.replace("-", "_"), default=False)
5162 for myopt in options:
5163 parser.add_option(myopt, action="store_true",
5164 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5165 for shortopt, longopt in shortmapping.iteritems():
5166 parser.add_option("-" + shortopt, action="store_true",
5167 dest=longopt.lstrip("--").replace("-", "_"), default=False)
5168 for myalias, myopt in longopt_aliases.iteritems():
5169 parser.add_option(myalias, action="store_true",
5170 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5172 for myopt, kwargs in argument_options.iteritems():
5173 parser.add_option(myopt,
5174 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
5176 myoptions, myargs = parser.parse_args(args=tmpcmdline)
5178 for myopt in options:
5179 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
5181 myopts[myopt] = True
5183 for myopt in argument_options:
5184 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
5188 for action_opt in actions:
5189 v = getattr(myoptions, action_opt.replace("-", "_"))
5192 multiple_actions(myaction, action_opt)
5194 myaction = action_opt
5197 if x in actions and myaction != "search":
5198 if not silent and x not in ["system", "world"]:
5199 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
5200 # special case "search" so people can search for action terms, e.g. emerge -s sync
5202 multiple_actions(myaction, x)
5208 if "--nocolor" in myopts:
5210 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
5211 "use '--color=n' instead.\n")
5212 del myopts["--nocolor"]
5213 myopts["--color"] = "n"
5215 return myaction, myopts, myfiles
5217 def validate_ebuild_environment(trees):
5218 for myroot in trees:
5219 mysettings = trees[myroot]["vartree"].settings
5220 for var in "ARCH", "USERLAND":
5221 if mysettings.get(var):
5223 print >> sys.stderr, bad(("\a!!! %s is not set... " % var) + \
5224 "Are you missing the '%setc/make.profile' symlink?" % \
5225 mysettings["PORTAGE_CONFIGROOT"])
5226 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5227 "Is your portage tree complete?\n")
5229 del myroot, mysettings
5231 def load_emerge_config(trees=None):
5233 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5234 kwargs[k] = os.environ.get(envvar, None)
5235 trees = portage.create_trees(trees=trees, **kwargs)
5237 settings = trees["/"]["vartree"].settings
5239 for myroot in trees:
5241 settings = trees[myroot]["vartree"].settings
5244 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5245 mtimedb = portage.MtimeDB(mtimedbfile)
5246 return settings, trees, mtimedb
5248 def adjust_config(myopts, settings):
5249 """Make emerge specific adjustments to the config."""
5251 # To enhance usability, make some vars case insensitive by forcing them to
5253 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5254 if myvar in settings:
5255 settings[myvar] = settings[myvar].lower()
5256 settings.backup_changes(myvar)
5259 # Kill noauto as it will break merges otherwise.
5260 if "noauto" in settings.features:
5261 while "noauto" in settings.features:
5262 settings.features.remove("noauto")
5263 settings["FEATURES"] = " ".join(settings.features)
5264 settings.backup_changes("FEATURES")
5268 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5269 except ValueError, e:
5270 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5271 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5272 settings["CLEAN_DELAY"], noiselevel=-1)
5273 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5274 settings.backup_changes("CLEAN_DELAY")
5276 EMERGE_WARNING_DELAY = 10
5278 EMERGE_WARNING_DELAY = int(settings.get(
5279 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5280 except ValueError, e:
5281 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5282 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5283 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5284 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5285 settings.backup_changes("EMERGE_WARNING_DELAY")
5287 if "--quiet" in myopts:
5288 settings["PORTAGE_QUIET"]="1"
5289 settings.backup_changes("PORTAGE_QUIET")
5291 # Set so that configs will be merged regardless of remembered status
5292 if ("--noconfmem" in myopts):
5293 settings["NOCONFMEM"]="1"
5294 settings.backup_changes("NOCONFMEM")
5296 # Set various debug markers... They should be merged somehow.
5299 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5300 if PORTAGE_DEBUG not in (0, 1):
5301 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5302 PORTAGE_DEBUG, noiselevel=-1)
5303 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5306 except ValueError, e:
5307 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5308 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5309 settings["PORTAGE_DEBUG"], noiselevel=-1)
5311 if "--debug" in myopts:
5313 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5314 settings.backup_changes("PORTAGE_DEBUG")
5316 if settings.get("NOCOLOR") not in ("yes","true"):
5317 portage.output.havecolor = 1
5319 """The explicit --color < y | n > option overrides the NOCOLOR environment
5320 variable and stdout auto-detection."""
5321 if "--color" in myopts:
5322 if "y" == myopts["--color"]:
5323 portage.output.havecolor = 1
5324 settings["NOCOLOR"] = "false"
5326 portage.output.havecolor = 0
5327 settings["NOCOLOR"] = "true"
5328 settings.backup_changes("NOCOLOR")
5329 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5330 portage.output.havecolor = 0
5331 settings["NOCOLOR"] = "true"
5332 settings.backup_changes("NOCOLOR")
5335 global portage # NFC why this is necessary now - genone
5336 # Disable color until we're sure that it should be enabled (after
5337 # EMERGE_DEFAULT_OPTS has been parsed).
5338 portage.output.havecolor = 0
5339 # This first pass is just for options that need to be known as early as
5340 # possible, such as --config-root. They will be parsed again later,
5341 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5342 # the value of --config-root).
5343 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5344 if "--debug" in myopts:
5345 os.environ["PORTAGE_DEBUG"] = "1"
5346 if "--config-root" in myopts:
5347 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5349 # Portage needs to ensure a sane umask for the files it creates.
5351 settings, trees, mtimedb = load_emerge_config()
5352 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5355 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5356 except (OSError, ValueError), e:
5357 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5358 settings["PORTAGE_NICENESS"])
5359 portage.writemsg("!!! %s\n" % str(e))
5362 if portage.global_updates(settings, trees, mtimedb["updates"]):
5364 # Reload the whole config from scratch.
5365 settings, trees, mtimedb = load_emerge_config(trees=trees)
5366 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5368 xterm_titles = "notitles" not in settings.features
5371 if "--ignore-default-opts" not in sys.argv:
5372 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5373 tmpcmdline.extend(sys.argv[1:])
5374 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5376 if "--digest" in myopts:
5377 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5378 # Reload the whole config from scratch so that the portdbapi internal
5379 # config is updated with new FEATURES.
5380 settings, trees, mtimedb = load_emerge_config(trees=trees)
5381 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5383 for myroot in trees:
5384 mysettings = trees[myroot]["vartree"].settings
5386 adjust_config(myopts, mysettings)
5388 del myroot, mysettings
5390 spinner = stdout_spinner()
5391 if "candy" in settings.features:
5392 spinner.update = spinner.update_scroll
5394 if "--quiet" not in myopts:
5395 portage.deprecated_profile_check()
5397 #Freeze the portdbapi for enhanced performance:
5398 for myroot in trees:
5399 trees[myroot]["porttree"].dbapi.freeze()
5402 if "moo" in myfiles:
5405 Larry loves Gentoo (""" + os.uname()[0] + """)
5407 _______________________
5408 < Have you mooed today? >
5409 -----------------------
5418 if (myaction in ["world", "system"]) and myfiles:
5419 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5423 ext = os.path.splitext(x)[1]
5424 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5425 print "emerging by path implies --oneshot... adding --oneshot to options."
5426 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5429 if ("--tree" in myopts) and ("--columns" in myopts):
5430 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5433 if ("--quiet" in myopts):
5434 spinner.update = spinner.update_quiet
5435 portage.util.noiselimit = -1
5437 # Always create packages if FEATURES=buildpkg
5438 # Imply --buildpkg if --buildpkgonly
5439 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5440 if "--buildpkg" not in myopts:
5441 myopts["--buildpkg"] = True
5443 # Also allow -S to invoke search action (-sS)
5444 if ("--searchdesc" in myopts):
5445 if myaction and myaction != "search":
5446 myfiles.append(myaction)
5447 if "--search" not in myopts:
5448 myopts["--search"] = True
5451 # Always try and fetch binary packages if FEATURES=getbinpkg
5452 if ("getbinpkg" in settings.features):
5453 myopts["--getbinpkg"] = True
5455 if "--skipfirst" in myopts and "--resume" not in myopts:
5456 myopts["--resume"] = True
5458 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5459 myopts["--usepkgonly"] = True
5461 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5462 myopts["--getbinpkg"] = True
5464 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5465 myopts["--usepkg"] = True
5467 # Also allow -K to apply --usepkg/-k
5468 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5469 myopts["--usepkg"] = True
5471 # Allow -p to remove --ask
5472 if ("--pretend" in myopts) and ("--ask" in myopts):
5473 print ">>> --pretend disables --ask... removing --ask from options."
5476 # forbid --ask when not in a terminal
5477 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5478 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5479 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5483 if settings.get("PORTAGE_DEBUG", "") == "1":
5484 spinner.update = spinner.update_quiet
5486 if "python-trace" in settings.features:
5487 import portage.debug
5488 portage.debug.set_trace(True)
5490 if ("--resume" in myopts):
5491 if "--tree" in myopts:
5492 print "* --tree is currently broken with --resume. Disabling..."
5493 del myopts["--tree"]
5495 if not ("--quiet" in myopts):
5496 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5497 spinner.update = spinner.update_basic
5499 if "--version" in myopts:
5500 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5501 settings.profile_path, settings["CHOST"],
5502 trees[settings["ROOT"]]["vartree"].dbapi)
5504 elif "--help" in myopts:
5505 emerge.help.help(myaction, myopts, portage.output.havecolor)
5508 if portage.wheelgid == portage.portage_gid:
5509 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5510 print " include the portage user as noted above, and then use group portage."
5512 if "--debug" in myopts:
5513 print "myaction", myaction
5514 print "myopts", myopts
5516 if not myaction and not myfiles and "--resume" not in myopts:
5517 emerge.help.help(myaction, myopts, portage.output.havecolor)
5520 # check if root user is the current user for the actions where emerge needs this
5521 if portage.secpass < 2:
5522 # We've already allowed "--version" and "--help" above.
5523 if "--pretend" not in myopts and \
5524 myaction not in ("search","info"):
5525 need_superuser = not \
5526 ("--fetchonly" in myopts or \
5527 "--fetch-all-uri" in myopts or \
5528 myaction in ("metadata", "regen"))
5529 if portage.secpass < 1 or \
5532 access_desc = "superuser"
5534 access_desc = "portage group"
5535 # Always show portage_group_warning() when only portage group
5536 # access is required but the user is not in the portage group.
5537 from portage.data import portage_group_warning
5538 if "--ask" in myopts:
5539 myopts["--pretend"] = True
5541 print ("%s access would be required... " + \
5542 "adding --pretend to options.\n") % access_desc
5543 if portage.secpass < 1 and not need_superuser:
5544 portage_group_warning()
5546 sys.stderr.write(("emerge: %s access would be " + \
5547 "required.\n\n") % access_desc)
5548 if portage.secpass < 1 and not need_superuser:
5549 portage_group_warning()
5552 disable_emergelog = False
5553 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5555 disable_emergelog = True
5557 if myaction in ("search", "info"):
5558 disable_emergelog = True
5559 if disable_emergelog:
5560 """ Disable emergelog for everything except build or unmerge
5561 operations. This helps minimize parallel emerge.log entries that can
5562 confuse log parsers. We especially want it disabled during
5563 parallel-fetch, which uses --resume --fetchonly."""
5565 def emergelog(*pargs, **kargs):
5568 if not "--pretend" in myopts:
5569 emergelog(xterm_titles, "Started emerge on: "+\
5570 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5573 myelogstr=" ".join(myopts)
5575 myelogstr+=" "+myaction
5577 myelogstr+=" "+" ".join(myfiles)
5578 emergelog(xterm_titles, " *** emerge " + myelogstr)
5580 def emergeexitsig(signum, frame):
5581 signal.signal(signal.SIGINT, signal.SIG_IGN)
5582 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5583 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5584 sys.exit(100+signum)
5585 signal.signal(signal.SIGINT, emergeexitsig)
5586 signal.signal(signal.SIGTERM, emergeexitsig)
5589 """This gets out final log message in before we quit."""
5590 if "--pretend" not in myopts:
5591 emergelog(xterm_titles, " *** terminating.")
5592 if "notitles" not in settings.features:
5594 portage.atexit_register(emergeexit)
5596 if myaction in ("config", "metadata", "regen", "sync"):
5597 if "--pretend" in myopts:
5598 sys.stderr.write(("emerge: The '%s' action does " + \
5599 "not support '--pretend'.\n") % myaction)
5601 if "sync" == myaction:
5602 action_sync(settings, trees, mtimedb, myopts, myaction)
5603 elif "metadata" == myaction:
5604 action_metadata(settings, portdb, myopts)
5605 elif myaction=="regen":
5606 validate_ebuild_environment(trees)
5607 action_regen(settings, portdb)
5609 elif "config"==myaction:
5610 validate_ebuild_environment(trees)
5611 action_config(settings, trees, myopts, myfiles)
5614 elif "info"==myaction:
5615 action_info(settings, trees, myopts, myfiles)
5618 elif "search"==myaction:
5619 validate_ebuild_environment(trees)
5620 action_search(settings, portdb, trees["/"]["vartree"],
5621 myopts, myfiles, spinner)
5622 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5623 validate_ebuild_environment(trees)
5624 vartree = trees[settings["ROOT"]]["vartree"]
5625 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5627 if "--pretend" not in myopts:
5628 post_emerge(settings, mtimedb, 0)
5630 elif "depclean"==myaction:
5631 validate_ebuild_environment(trees)
5632 action_depclean(settings, trees, mtimedb["ldpath"],
5634 if "--pretend" not in myopts:
5635 post_emerge(settings, mtimedb, 0)
5636 # "update", "system", or just process files:
5638 validate_ebuild_environment(trees)
5639 if "--pretend" not in myopts:
5640 display_news_notification(settings)
5641 action_build(settings, trees, mtimedb,
5642 myopts, myaction, myfiles, spinner)
5643 if "--pretend" not in myopts:
5644 post_emerge(settings, mtimedb, 0)
5646 display_news_notification(settings)
5648 if __name__ == "__main__":
5649 retval = emerge_main()