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
2376 if "blocks" == x[0]:
2377 display_list.append((x, 0, True))
2379 graph_key = tuple(x)
2380 if "--tree" in self.myopts:
2381 depth = len(tree_nodes)
2382 while depth and graph_key not in \
2383 mygraph.child_nodes(tree_nodes[depth-1]):
2386 tree_nodes = tree_nodes[:depth]
2387 tree_nodes.append(graph_key)
2388 display_list.append((x, depth, True))
2389 shown_edges.add((graph_key, tree_nodes[depth-1]))
2391 traversed_nodes = set() # prevent endless circles
2392 traversed_nodes.add(graph_key)
2393 def add_parents(current_node, ordered):
2394 parent_nodes = mygraph.parent_nodes(current_node)
2396 child_nodes = set(mygraph.child_nodes(current_node))
2397 selected_parent = None
2398 # First, try to avoid a direct cycle.
2399 for node in parent_nodes:
2400 if node not in traversed_nodes and \
2401 node not in child_nodes:
2402 edge = (current_node, node)
2403 if edge in shown_edges:
2405 selected_parent = node
2407 if not selected_parent:
2408 # A direct cycle is unavoidable.
2409 for node in parent_nodes:
2410 if node not in traversed_nodes:
2411 edge = (current_node, node)
2412 if edge in shown_edges:
2414 selected_parent = node
2417 edge = (current_node, selected_parent)
2418 if edge not in shown_edges:
2419 traversed_nodes.add(selected_parent)
2420 add_parents(selected_parent, False)
2421 display_list.append((list(current_node),
2422 len(tree_nodes), ordered))
2424 shown_edges.add((current_node, tree_nodes[-1]))
2425 tree_nodes.append(current_node)
2427 add_parents(graph_key, True)
2429 display_list.append((x, depth, True))
2430 mylist = display_list
2432 last_merge_depth = 0
2433 for i in xrange(len(mylist)-1,-1,-1):
2434 graph_key, depth, ordered = mylist[i]
2435 if not ordered and depth == 0 and i > 0 \
2436 and graph_key == mylist[i-1][0] and \
2437 mylist[i-1][1] == 0:
2438 # An ordered node got a consecutive duplicate when the tree was
2442 if "blocks" == graph_key[0]:
2444 if ordered and graph_key[-1] != "nomerge":
2445 last_merge_depth = depth
2447 if depth >= last_merge_depth or \
2448 i < len(mylist) - 1 and \
2449 depth >= mylist[i+1][1]:
2452 display_overlays=False
2453 # files to fetch list - avoids counting a same file twice
2454 # in size display (verbose mode)
2456 for mylist_index in xrange(len(mylist)):
2457 x, depth, ordered = mylist[mylist_index]
2461 portdb = self.trees[myroot]["porttree"].dbapi
2462 bindb = self.trees[myroot]["bintree"].dbapi
2463 vardb = self.trees[myroot]["vartree"].dbapi
2464 vartree = self.trees[myroot]["vartree"]
2465 pkgsettings = self.pkgsettings[myroot]
2470 addl=""+red("B")+" "+fetch+" "
2472 counters.blocks += 1
2473 resolved = portage.key_expand(
2474 pkg_key, mydb=vardb, settings=pkgsettings)
2475 if "--columns" in self.myopts and "--quiet" in self.myopts:
2476 addl = addl + " " + red(resolved)
2478 addl = "[blocks " + addl + "] " + red(resolved)
2479 block_parents = self.blocker_parents[tuple(x)]
2480 block_parents = set([pnode[2] for pnode in block_parents])
2481 block_parents = ", ".join(block_parents)
2483 addl += bad(" (\"%s\" is blocking %s)") % \
2484 (pkg_key, block_parents)
2486 addl += bad(" (is blocking %s)") % block_parents
2487 blockers.append(addl)
2489 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2490 binary_package = True
2491 if "ebuild" == pkg_type:
2492 if "merge" == x[3] or \
2493 not vartree.dbapi.cpv_exists(pkg_key):
2494 """An ebuild "merge" node or a --onlydeps "nomerge"
2496 binary_package = False
2497 pkgsettings.setcpv(pkg_key, mydb=portdb)
2498 if pkg_key not in self.useFlags[myroot]:
2499 self.useFlags[myroot][pkg_key] = \
2500 pkgsettings["USE"].split()
2502 # An ebuild "nomerge" node, so USE come from the vardb.
2503 mydbapi = vartree.dbapi
2504 if pkg_key not in self.useFlags[myroot]:
2505 """If this is a --resume then the USE flags need to be
2506 fetched from the appropriate locations here."""
2507 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2508 pkg_key, ["USE"])[0].split()
2510 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2511 "fetch" in portdb.aux_get(
2512 x[2], ["RESTRICT"])[0].split():
2515 counters.restrict_fetch += 1
2516 if portdb.fetch_check(
2517 pkg_key, self.useFlags[myroot][pkg_key]):
2520 counters.restrict_fetch_satisfied += 1
2522 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2523 #param is used for -u, where you still *do* want to see when something is being upgraded.
2525 if vardb.cpv_exists(pkg_key):
2526 addl=" "+yellow("R")+fetch+" "
2527 if x[3] != "nomerge":
2529 counters.reinst += 1
2530 elif vardb.match(portage.dep_getkey(pkg_key)):
2531 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2532 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2533 portage.pkgsplit(x[2])[0])
2534 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2535 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2537 myoldbest=portage.best(myinslotlist)
2539 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2541 addl+=turquoise("U")+blue("D")
2543 counters.downgrades += 1
2546 addl+=turquoise("U")+" "
2548 counters.upgrades += 1
2550 # New slot, mark it new.
2551 addl=" "+green("NS")+fetch+" "
2553 counters.newslot += 1
2555 if "--changelog" in self.myopts:
2556 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2557 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2558 inst_matches = vardb.match(slot_atom)
2560 changelogs.extend(self.calc_changelog(
2561 portdb.findname(pkg_key),
2562 inst_matches[0], pkg_key))
2564 addl=" "+green("N")+" "+fetch+" "
2570 if pkg_key in self.useFlags[myroot]:
2572 cur_iuse = list(filter_iuse_defaults(
2573 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2575 forced_flags = set()
2576 if not binary_package:
2577 forced_flags.update(pkgsettings.useforce)
2578 forced_flags.update(pkgsettings.usemask)
2580 cur_iuse = portage.unique_array(cur_iuse)
2582 cur_use = self.useFlags[myroot][pkg_key]
2583 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2589 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2590 old_iuse, old_use = \
2591 self.trees[x[1]]["vartree"].dbapi.aux_get(
2592 pkg, ["IUSE", "USE"])
2593 old_iuse = list(set(
2594 filter_iuse_defaults(old_iuse.split())))
2596 old_use = old_use.split()
2603 old_use = [flag for flag in old_use if flag in old_iuse]
2605 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2607 use_expand.reverse()
2608 use_expand_hidden = \
2609 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2611 def map_to_use_expand(myvals, forcedFlags=False):
2614 for exp in use_expand:
2617 for val in myvals[:]:
2618 if val.startswith(exp.lower()+"_"):
2619 if val in forced_flags:
2620 forced[exp].add(val[len(exp)+1:])
2621 ret[exp].append(val[len(exp)+1:])
2624 forced["USE"] = [val for val in myvals \
2625 if val in forced_flags]
2626 for exp in use_expand_hidden:
2633 cur_iuse_map, iuse_forced = \
2634 map_to_use_expand(cur_iuse, forcedFlags=True)
2635 cur_use_map = map_to_use_expand(cur_use)
2636 old_iuse_map = map_to_use_expand(old_iuse)
2637 old_use_map = map_to_use_expand(old_use)
2640 use_expand.insert(0, "USE")
2642 for key in use_expand:
2643 if key in use_expand_hidden:
2645 verboseadd += create_use_string(key.upper(),
2646 cur_iuse_map[key], iuse_forced[key],
2647 cur_use_map[key], old_iuse_map[key],
2648 old_use_map[key], is_new)
2653 if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
2655 myfilesdict = portdb.getfetchsizes(pkg_key,
2656 useflags=self.useFlags[myroot][pkg_key],
2658 except portage.exception.InvalidDependString, e:
2659 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2660 show_invalid_depstring_notice(x, src_uri, str(e))
2663 if myfilesdict is None:
2664 myfilesdict="[empty/missing/bad digest]"
2666 for myfetchfile in myfilesdict.keys():
2667 if myfetchfile not in myfetchlist:
2668 mysize+=myfilesdict[myfetchfile]
2669 myfetchlist.append(myfetchfile)
2670 counters.totalsize += mysize
2671 verboseadd+=format_size(mysize)+" "
2674 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2675 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2676 file_name = portdb.findname(pkg_key)
2677 if file_name: # It might not exist in the tree
2678 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2679 if (overlays_real.count(dir_name)>0):
2680 verboseadd+=teal("["+str(overlays_real.index(
2681 os.path.normpath(dir_name))+1)+"]")+" "
2682 display_overlays=True
2684 verboseadd += "[No ebuild?]"
2686 xs=portage.pkgsplit(x[2])
2693 if "COLUMNWIDTH" in self.settings:
2695 mywidth = int(self.settings["COLUMNWIDTH"])
2696 except ValueError, e:
2697 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2699 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2700 self.settings["COLUMNWIDTH"], noiselevel=-1)
2705 indent = " " * depth
2708 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2709 if myoldbest[-3:]=="-r0":
2710 myoldbest=myoldbest[:-3]
2711 myoldbest=blue("["+myoldbest+"]")
2716 if "--columns" in self.myopts:
2717 if "--quiet" in self.myopts:
2718 myprint=addl+" "+indent+darkgreen(xs[0])
2719 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2720 myprint=myprint+myoldbest
2721 myprint=myprint+darkgreen("to "+x[1])
2723 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2724 if (newlp-nc_len(myprint)) > 0:
2725 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2726 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2727 if (oldlp-nc_len(myprint)) > 0:
2728 myprint=myprint+" "*(oldlp-nc_len(myprint))
2729 myprint=myprint+myoldbest
2730 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2732 if x[-1] == "nomerge" or not ordered:
2733 myprint = darkblue("[nomerge ] ")
2735 myprint = "[" + pkg_type + " " + addl + "] "
2736 myprint += indent + darkgreen(pkg_key) + " " + \
2737 myoldbest + darkgreen("to " + myroot) + " " + \
2740 if "--columns" in self.myopts:
2741 if "--quiet" in self.myopts:
2742 myprint=addl+" "+indent+darkgreen(xs[0])
2743 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2744 myprint=myprint+myoldbest
2746 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2747 if (newlp-nc_len(myprint)) > 0:
2748 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2749 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2750 if (oldlp-nc_len(myprint)) > 0:
2751 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2752 myprint=myprint+myoldbest+" "+verboseadd
2754 if x[-1] == "nomerge" or not ordered:
2755 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2757 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2760 mysplit = portage.pkgsplit(x[2])
2761 if "--tree" not in self.myopts and mysplit and \
2762 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2765 if mysplit[2] == "r0":
2766 myversion = mysplit[1]
2768 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2770 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2771 if mylist_index < len(mylist) - 1 and \
2772 "livecvsportage" not in self.settings.features:
2773 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2774 p.append(colorize("WARN", " then resume the merge."))
2786 if overlays and display_overlays:
2787 print "Portage overlays:"
2791 print " "+teal("["+str(y)+"]"),x
2793 if "--changelog" in self.myopts:
2795 for revision,text in changelogs:
2796 print bold('*'+revision)
2797 sys.stdout.write(text)
2799 if self._pprovided_args:
2801 msg.append(bad("\nWARNING: "))
2802 if len(self._pprovided_args) > 1:
2803 msg.append("Requested packages will not be " + \
2804 "merged because they are listed in\n")
2806 msg.append("A requested package will not be " + \
2807 "merged because it is listed in\n")
2808 msg.append(" package.provided:\n\n")
2809 for arg in self._pprovided_args:
2810 msg.append(" " + arg + "\n")
2812 sys.stderr.write("".join(msg))
2814 def calc_changelog(self,ebuildpath,current,next):
2815 current = '-'.join(portage.catpkgsplit(current)[1:])
2816 if current.endswith('-r0'): current = current[:-3]
2817 next = '-'.join(portage.catpkgsplit(next)[1:])
2818 if next.endswith('-r0'): next = next[:-3]
2819 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2821 changelog = open(changelogpath).read()
2822 except SystemExit, e:
2823 raise # Needed else can't exit
2826 divisions = self.find_changelog_tags(changelog)
2827 #print 'XX from',current,'to',next
2828 #for div,text in divisions: print 'XX',div
2829 # skip entries for all revisions above the one we are about to emerge
2830 for i in range(len(divisions)):
2831 if divisions[i][0]==next:
2832 divisions = divisions[i:]
2834 # find out how many entries we are going to display
2835 for i in range(len(divisions)):
2836 if divisions[i][0]==current:
2837 divisions = divisions[:i]
2840 # couldnt find the current revision in the list. display nothing
2844 def find_changelog_tags(self,changelog):
2848 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2850 if release is not None:
2851 divs.append((release,changelog))
2853 if release is not None:
2854 divs.append((release,changelog[:match.start()]))
2855 changelog = changelog[match.end():]
2856 release = match.group(1)
2857 if release.endswith('.ebuild'):
2858 release = release[:-7]
2859 if release.endswith('-r0'):
2860 release = release[:-3]
2863 return self.outdatedpackages
2865 class PackageCounters(object):
2875 self.restrict_fetch = 0
2876 self.restrict_fetch_satisfied = 0
2879 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2882 myoutput.append("Total: %s package" % total_installs)
2883 if total_installs != 1:
2884 myoutput.append("s")
2885 if total_installs != 0:
2886 myoutput.append(" (")
2887 if self.upgrades > 0:
2888 details.append("%s upgrade" % self.upgrades)
2889 if self.upgrades > 1:
2891 if self.downgrades > 0:
2892 details.append("%s downgrade" % self.downgrades)
2893 if self.downgrades > 1:
2896 details.append("%s new" % self.new)
2897 if self.newslot > 0:
2898 details.append("%s in new slot" % self.newslot)
2899 if self.newslot > 1:
2902 details.append("%s reinstall" % self.reinst)
2906 details.append("%s block" % self.blocks)
2909 myoutput.append(", ".join(details))
2910 if total_installs != 0:
2911 myoutput.append(")")
2912 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2913 if self.restrict_fetch:
2914 myoutput.append("\nFetch Restriction: %s package" % \
2915 self.restrict_fetch)
2916 if self.restrict_fetch > 1:
2917 myoutput.append("s")
2918 if self.restrict_fetch_satisfied < self.restrict_fetch:
2919 myoutput.append(bad(" (%s unsatisfied)") % \
2920 (self.restrict_fetch - self.restrict_fetch_satisfied))
2921 return "".join(myoutput)
2923 class MergeTask(object):
2925 def __init__(self, settings, trees, myopts):
2926 self.settings = settings
2927 self.target_root = settings["ROOT"]
2929 self.myopts = myopts
2931 if settings.get("PORTAGE_DEBUG", "") == "1":
2933 self.pkgsettings = {}
2934 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2935 if self.target_root != "/":
2936 self.pkgsettings["/"] = \
2937 portage.config(clone=trees["/"]["vartree"].settings)
2939 def merge(self, mylist, favorites, mtimedb):
2942 ldpath_mtimes = mtimedb["ldpath"]
2943 xterm_titles = "notitles" not in self.settings.features
2945 #check for blocking dependencies
2946 if "--fetchonly" not in self.myopts and \
2947 "--fetch-all-uri" not in self.myopts and \
2948 "--buildpkgonly" not in self.myopts:
2951 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2952 print "!!! the two packages cannot be installed on the same system together."
2953 print "!!! Please use 'emerge --pretend' to determine blockers."
2954 if "--quiet" not in self.myopts:
2955 show_blocker_docs_link()
2958 if "--resume" in self.myopts:
2960 print colorize("GOOD", "*** Resuming merge...")
2961 emergelog(xterm_titles, " *** Resuming merge...")
2962 mylist = mtimedb["resume"]["mergelist"][:]
2963 if "--skipfirst" in self.myopts and mylist:
2964 del mtimedb["resume"]["mergelist"][0]
2967 validate_merge_list(self.trees, mylist)
2968 mymergelist = mylist
2970 # Verify all the manifests now so that the user is notified of failure
2971 # as soon as possible.
2972 if "--fetchonly" not in self.myopts and \
2973 "--fetch-all-uri" not in self.myopts and \
2974 "strict" in self.settings.features:
2975 shown_verifying_msg = False
2977 for myroot, pkgsettings in self.pkgsettings.iteritems():
2978 quiet_config = portage.config(clone=pkgsettings)
2979 quiet_config["PORTAGE_QUIET"] = "1"
2980 quiet_config.backup_changes("PORTAGE_QUIET")
2981 quiet_settings[myroot] = quiet_config
2984 if x[0] != "ebuild" or x[-1] == "nomerge":
2986 if not shown_verifying_msg:
2987 shown_verifying_msg = True
2988 print ">>> Verifying ebuild Manifests..."
2989 mytype, myroot, mycpv, mystatus = x
2990 portdb = self.trees[myroot]["porttree"].dbapi
2991 quiet_config = quiet_settings[myroot]
2992 quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
2993 if not portage.digestcheck([], quiet_config, strict=True):
2995 del x, mytype, myroot, mycpv, mystatus, quiet_config
2996 del shown_verifying_msg, quiet_settings
2998 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
2999 mysysdict = genericdict(getlist(self.settings, "system"))
3000 if "--resume" not in self.myopts:
3001 myfavs = portage.grabfile(
3002 os.path.join(self.target_root, portage.WORLD_FILE))
3003 myfavdict=genericdict(myfavs)
3004 for x in range(len(mylist)):
3005 if mylist[x][3]!="nomerge":
3006 # Add to the mergelist
3007 mymergelist.append(mylist[x])
3009 myfavkey=portage.cpv_getkey(mylist[x][2])
3010 if "--onlydeps" in self.myopts:
3012 # Add to the world file. Since we won't be able to later.
3013 if "--fetchonly" not in self.myopts and \
3014 myfavkey in favorites:
3015 #don't record if already in system profile or already recorded
3016 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3017 #we don't have a favorites entry for this package yet; add one
3018 myfavdict[myfavkey]=myfavkey
3019 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3020 if not ("--fetchonly" in self.myopts or \
3021 "--fetch-all-uri" in self.myopts or \
3022 "--pretend" in self.myopts):
3023 portage.write_atomic(
3024 os.path.join(self.target_root, portage.WORLD_FILE),
3025 "\n".join(myfavdict.values()))
3027 mtimedb["resume"]["mergelist"]=mymergelist[:]
3030 myfeat = self.settings.features[:]
3031 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3033 if "parallel-fetch" in myfeat and \
3034 not ("--pretend" in self.myopts or \
3035 "--fetch-all-uri" in self.myopts or \
3036 "--fetchonly" in self.myopts):
3037 if "distlocks" not in myfeat:
3039 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
3040 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
3042 elif len(mymergelist) > 1:
3043 print ">>> starting parallel fetching"
3044 fetch_log = "/var/log/emerge-fetch.log"
3045 logfile = open(fetch_log, "w")
3046 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3047 portage.util.apply_secpass_permissions(fetch_log,
3048 uid=portage.portage_uid, gid=portage.portage_gid,
3050 fetch_env = os.environ.copy()
3051 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3052 fetch_env["PORTAGE_NICENESS"] = "0"
3053 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3054 resume_opts = self.myopts.copy()
3055 # For automatic resume, we need to prevent
3056 # any of bad_resume_opts from leaking in
3057 # via EMERGE_DEFAULT_OPTS.
3058 resume_opts["--ignore-default-opts"] = True
3059 for myopt, myarg in resume_opts.iteritems():
3060 if myopt not in bad_resume_opts:
3062 fetch_args.append(myopt)
3064 fetch_args.append(myopt +"="+ myarg)
3065 portage.process.spawn(fetch_args, env=fetch_env,
3066 fd_pipes=fd_pipes, returnpid=True)
3067 logfile.close() # belongs to the spawned process
3068 del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3072 for x in mymergelist:
3077 portdb = self.trees[myroot]["porttree"].dbapi
3078 bindb = self.trees[myroot]["bintree"].dbapi
3079 vartree = self.trees[myroot]["vartree"]
3080 pkgsettings = self.pkgsettings[myroot]
3083 y = portdb.findname(pkg_key)
3084 if "--pretend" not in self.myopts:
3085 print "\n>>> Emerging (" + \
3086 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3087 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3088 colorize("GOOD", x[pkgindex]) + " to " + x[1]
3089 emergelog(xterm_titles, " >>> emerge ("+\
3090 str(mergecount)+" of "+str(len(mymergelist))+\
3091 ") "+x[pkgindex]+" to "+x[1])
3093 pkgsettings["EMERGE_FROM"] = x[0]
3094 pkgsettings.backup_changes("EMERGE_FROM")
3097 #buildsyspkg: Check if we need to _force_ binary package creation
3098 issyspkg = ("buildsyspkg" in myfeat) \
3099 and x[0] != "blocks" \
3100 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3101 and "--buildpkg" not in self.myopts
3102 if x[0] in ["ebuild","blocks"]:
3103 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3104 raise Exception, "Merging a blocker"
3105 elif "--fetchonly" in self.myopts or \
3106 "--fetch-all-uri" in self.myopts:
3107 if "--fetch-all-uri" in self.myopts:
3108 retval = portage.doebuild(y, "fetch", myroot,
3109 pkgsettings, self.edebug,
3110 "--pretend" in self.myopts, fetchonly=1,
3111 fetchall=1, mydbapi=portdb, tree="porttree")
3113 retval = portage.doebuild(y, "fetch", myroot,
3114 pkgsettings, self.edebug,
3115 "--pretend" in self.myopts, fetchonly=1,
3116 mydbapi=portdb, tree="porttree")
3117 if (retval is None) or retval:
3119 print "!!! Fetch for",y,"failed, continuing..."
3121 failed_fetches.append(pkg_key)
3124 portage.doebuild_environment(y, "setup", myroot,
3125 pkgsettings, self.edebug, 1, portdb)
3126 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3127 portage.util.ensure_dirs(os.path.dirname(catdir),
3128 uid=portage.portage_uid, gid=portage.portage_gid,
3130 builddir_lock = None
3133 catdir_lock = portage.locks.lockdir(catdir)
3134 portage.util.ensure_dirs(catdir,
3135 uid=portage.portage_uid, gid=portage.portage_gid,
3137 builddir_lock = portage.locks.lockdir(
3138 pkgsettings["PORTAGE_BUILDDIR"])
3140 portage.locks.unlockdir(catdir_lock)
3143 msg = " === (%s of %s) Cleaning (%s::%s)" % \
3144 (mergecount, len(mymergelist), pkg_key, y)
3145 short_msg = "emerge: (%s of %s) %s Clean" % \
3146 (mergecount, len(mymergelist), pkg_key)
3147 emergelog(xterm_titles, msg, short_msg=short_msg)
3148 retval = portage.doebuild(y, "clean", myroot,
3149 pkgsettings, self.edebug, cleanup=1,
3150 mydbapi=portdb, tree="porttree")
3151 if retval != os.EX_OK:
3153 if "--buildpkg" in self.myopts or issyspkg:
3155 print ">>> This is a system package, " + \
3156 "let's pack a rescue tarball."
3157 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3158 (mergecount, len(mymergelist), pkg_key, y)
3159 short_msg = "emerge: (%s of %s) %s Compile" % \
3160 (mergecount, len(mymergelist), pkg_key)
3161 emergelog(xterm_titles, msg, short_msg=short_msg)
3162 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3163 retval = portage.doebuild(y, "package", myroot,
3164 pkgsettings, self.edebug, mydbapi=portdb,
3166 if retval != os.EX_OK:
3168 bintree = self.trees[myroot]["bintree"]
3169 if bintree.populated:
3170 bintree.inject(pkg_key)
3171 if "--buildpkgonly" not in self.myopts:
3172 msg = " === (%s of %s) Merging (%s::%s)" % \
3173 (mergecount, len(mymergelist), pkg_key, y)
3174 short_msg = "emerge: (%s of %s) %s Merge" % \
3175 (mergecount, len(mymergelist), pkg_key)
3176 emergelog(xterm_titles, msg, short_msg=short_msg)
3177 retval = portage.merge(pkgsettings["CATEGORY"],
3178 pkgsettings["PF"], pkgsettings["D"],
3179 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3180 "build-info"), myroot, pkgsettings,
3181 myebuild=pkgsettings["EBUILD"],
3182 mytree="porttree", mydbapi=portdb,
3183 vartree=vartree, prev_mtimes=ldpath_mtimes)
3184 if retval != os.EX_OK:
3186 elif "noclean" not in pkgsettings.features:
3187 portage.doebuild(y, "clean", myroot,
3188 pkgsettings, self.edebug, mydbapi=portdb,
3191 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3192 (mergecount, len(mymergelist), pkg_key, y)
3193 short_msg = "emerge: (%s of %s) %s Compile" % \
3194 (mergecount, len(mymergelist), pkg_key)
3195 emergelog(xterm_titles, msg, short_msg=short_msg)
3196 retval = portage.doebuild(y, "merge", myroot,
3197 pkgsettings, self.edebug, vartree=vartree,
3198 mydbapi=portdb, tree="porttree",
3199 prev_mtimes=ldpath_mtimes)
3200 if retval != os.EX_OK:
3204 portage.locks.unlockdir(builddir_lock)
3207 # Lock catdir for removal if empty.
3208 catdir_lock = portage.locks.lockdir(catdir)
3214 if e.errno not in (errno.ENOENT,
3215 errno.ENOTEMPTY, errno.EEXIST):
3218 portage.locks.unlockdir(catdir_lock)
3220 elif x[0]=="binary":
3222 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3223 if "--getbinpkg" in self.myopts:
3226 if "distlocks" in pkgsettings.features and \
3227 os.access(pkgsettings["PKGDIR"], os.W_OK):
3228 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3229 tbz2_lock = portage.locks.lockfile(mytbz2,
3231 if self.trees[myroot]["bintree"].isremote(pkg_key):
3232 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3233 (mergecount, len(mymergelist), pkg_key, mytbz2)
3234 short_msg = "emerge: (%s of %s) %s Fetch" % \
3235 (mergecount, len(mymergelist), pkg_key)
3236 emergelog(xterm_titles, msg, short_msg=short_msg)
3237 if not self.trees[myroot]["bintree"].gettbz2(
3242 portage.locks.unlockfile(tbz2_lock)
3244 if "--fetchonly" in self.myopts or \
3245 "--fetch-all-uri" in self.myopts:
3248 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3249 emergelog(xterm_titles, " === ("+str(mergecount)+\
3250 " of "+str(len(mymergelist))+") Merging Binary ("+\
3251 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3252 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3254 vartree=self.trees[myroot]["vartree"],
3255 prev_mtimes=ldpath_mtimes)
3256 if retval != os.EX_OK:
3258 #need to check for errors
3259 if "--buildpkgonly" not in self.myopts:
3260 self.trees[x[1]]["vartree"].inject(x[2])
3261 myfavkey=portage.cpv_getkey(x[2])
3262 if "--fetchonly" not in self.myopts and \
3263 "--fetch-all-uri" not in self.myopts and \
3264 myfavkey in favorites:
3265 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3266 myfavdict=genericdict(myfavs)
3267 #don't record if already in system profile or already recorded
3268 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3269 #we don't have a favorites entry for this package yet; add one
3270 myfavdict[myfavkey]=myfavkey
3271 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3272 emergelog(xterm_titles, " === ("+\
3273 str(mergecount)+" of "+\
3274 str(len(mymergelist))+\
3275 ") Updating world file ("+x[pkgindex]+")")
3276 portage.write_atomic(
3277 os.path.join(myroot, portage.WORLD_FILE),
3278 "\n".join(myfavdict.values()))
3280 if "--pretend" not in self.myopts and \
3281 "--fetchonly" not in self.myopts and \
3282 "--fetch-all-uri" not in self.myopts:
3283 # Clean the old package that we have merged over top of it.
3284 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3285 xsplit=portage.pkgsplit(x[2])
3286 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3287 retval = unmerge(pkgsettings, self.myopts, vartree,
3288 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3290 emergelog(xterm_titles,
3291 " --- AUTOCLEAN: Nothing unmerged.")
3293 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3294 + " AUTOCLEAN is disabled. This can cause serious"
3295 + " problems due to overlapping packages.\n")
3297 # Figure out if we need a restart.
3298 mysplit=portage.pkgsplit(x[2])
3299 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3300 myver=mysplit[1]+"-"+mysplit[2]
3301 if myver[-3:]=='-r0':
3303 if (myver != portage.VERSION) and \
3304 "livecvsportage" not in self.settings.features:
3305 if len(mymergelist) > mergecount:
3306 emergelog(xterm_titles,
3307 " ::: completed emerge ("+ \
3308 str(mergecount)+" of "+ \
3309 str(len(mymergelist))+") "+ \
3311 emergelog(xterm_titles, " *** RESTARTING " + \
3312 "emerge via exec() after change of " + \
3314 del mtimedb["resume"]["mergelist"][0]
3316 portage.run_exitfuncs()
3317 mynewargv=[sys.argv[0],"--resume"]
3318 resume_opts = self.myopts.copy()
3319 # For automatic resume, we need to prevent
3320 # any of bad_resume_opts from leaking in
3321 # via EMERGE_DEFAULT_OPTS.
3322 resume_opts["--ignore-default-opts"] = True
3323 for myopt, myarg in resume_opts.iteritems():
3324 if myopt not in bad_resume_opts:
3326 mynewargv.append(myopt)
3328 mynewargv.append(myopt +"="+ myarg)
3329 # priority only needs to be adjusted on the first run
3330 os.environ["PORTAGE_NICENESS"] = "0"
3331 os.execv(mynewargv[0], mynewargv)
3333 if "--pretend" not in self.myopts and \
3334 "--fetchonly" not in self.myopts and \
3335 "--fetch-all-uri" not in self.myopts:
3336 if "noclean" not in self.settings.features:
3337 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3338 (mergecount, len(mymergelist), x[pkgindex])
3339 emergelog(xterm_titles, (" === (%s of %s) " + \
3340 "Post-Build Cleaning (%s::%s)") % \
3341 (mergecount, len(mymergelist), x[pkgindex], y),
3342 short_msg=short_msg)
3343 emergelog(xterm_titles, " ::: completed emerge ("+\
3344 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3347 # Unsafe for parallel merges
3348 del mtimedb["resume"]["mergelist"][0]
3349 # Commit after each merge so that --resume may still work in
3350 # in the event that portage is not allowed to exit normally
3351 # due to power failure, SIGKILL, etc...
3354 if "--pretend" not in self.myopts:
3355 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3357 # We're out of the loop... We're done. Delete the resume data.
3358 if mtimedb.has_key("resume"):
3359 del mtimedb["resume"]
3362 #by doing an exit this way, --fetchonly can continue to try to
3363 #fetch everything even if a particular download fails.
3364 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3366 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3367 "encountered. Please see above for details.\n\n")
3368 for cpv in failed_fetches:
3369 sys.stderr.write(" ")
3370 sys.stderr.write(cpv)
3371 sys.stderr.write("\n")
3372 sys.stderr.write("\n")
3378 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3379 ldpath_mtimes, autoclean=0):
3380 candidate_catpkgs=[]
3382 xterm_titles = "notitles" not in settings.features
3384 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3386 # At least the parent needs to exist for the lock file.
3387 portage.util.ensure_dirs(vdb_path)
3388 except portage.exception.PortageException:
3392 if os.access(vdb_path, os.W_OK):
3393 vdb_lock = portage.locks.lockdir(vdb_path)
3394 realsyslist = getlist(settings, "system")
3396 for x in realsyslist:
3397 mycp = portage.dep_getkey(x)
3398 if mycp in settings.getvirtuals():
3400 for provider in settings.getvirtuals()[mycp]:
3401 if vartree.dbapi.match(provider):
3402 providers.append(provider)
3403 if len(providers) == 1:
3404 syslist.extend(providers)
3406 syslist.append(mycp)
3408 mysettings = portage.config(clone=settings)
3410 if not unmerge_files or "world" in unmerge_files or \
3411 "system" in unmerge_files:
3412 if "unmerge"==unmerge_action:
3414 print bold("emerge unmerge") + " can only be used with " + \
3415 "specific package names, not with "+bold("world")+" or"
3416 print bold("system")+" targets."
3423 # process all arguments and add all
3424 # valid db entries to candidate_catpkgs
3426 if not unmerge_files or "world" in unmerge_files:
3427 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3428 elif "system" in unmerge_files:
3429 candidate_catpkgs.extend(getlist(settings, "system"))
3431 #we've got command-line arguments
3432 if not unmerge_files:
3433 print "\nNo packages to unmerge have been provided.\n"
3435 for x in unmerge_files:
3436 arg_parts = x.split('/')
3437 if x[0] not in [".","/"] and \
3438 arg_parts[-1][-7:] != ".ebuild":
3439 #possible cat/pkg or dep; treat as such
3440 candidate_catpkgs.append(x)
3441 elif unmerge_action in ["prune","clean"]:
3442 print "\n!!! Prune and clean do not accept individual" + \
3443 " ebuilds as arguments;\n skipping.\n"
3446 # it appears that the user is specifying an installed
3447 # ebuild and we're in "unmerge" mode, so it's ok.
3448 if not os.path.exists(x):
3449 print "\n!!! The path '"+x+"' doesn't exist.\n"
3452 absx = os.path.abspath(x)
3453 sp_absx = absx.split("/")
3454 if sp_absx[-1][-7:] == ".ebuild":
3456 absx = "/".join(sp_absx)
3458 sp_absx_len = len(sp_absx)
3460 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3461 vdb_len = len(vdb_path)
3463 sp_vdb = vdb_path.split("/")
3464 sp_vdb_len = len(sp_vdb)
3466 if not os.path.exists(absx+"/CONTENTS"):
3467 print "!!! Not a valid db dir: "+str(absx)
3470 if sp_absx_len <= sp_vdb_len:
3471 # The Path is shorter... so it can't be inside the vdb.
3474 print "\n!!!",x,"cannot be inside "+ \
3475 vdb_path+"; aborting.\n"
3478 for idx in range(0,sp_vdb_len):
3479 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3482 print "\n!!!", x, "is not inside "+\
3483 vdb_path+"; aborting.\n"
3486 print "="+"/".join(sp_absx[sp_vdb_len:])
3487 candidate_catpkgs.append(
3488 "="+"/".join(sp_absx[sp_vdb_len:]))
3491 if (not "--quiet" in myopts):
3493 if settings["ROOT"] != "/":
3494 print darkgreen(newline+ \
3495 ">>> Using system located in ROOT tree "+settings["ROOT"])
3496 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3497 not ("--quiet" in myopts):
3498 print darkgreen(newline+\
3499 ">>> These are the packages that would be unmerged:")
3503 for x in candidate_catpkgs:
3504 # cycle through all our candidate deps and determine
3505 # what will and will not get unmerged
3507 mymatch=localtree.dep_match(x)
3510 except ValueError, errpkgs:
3511 print "\n\n!!! The short ebuild name \"" + \
3512 x + "\" is ambiguous. Please specify"
3513 print "!!! one of the following fully-qualified " + \
3514 "ebuild names instead:\n"
3515 for i in errpkgs[0]:
3516 print " " + green(i)
3520 if not mymatch and x[0] not in "<>=~":
3521 #add a "=" if missing
3522 mymatch=localtree.dep_match("="+x)
3524 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3525 (x, unmerge_action), noiselevel=-1)
3527 mykey = portage.key_expand(
3529 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3530 if not pkgmap.has_key(mykey):
3531 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3532 if unmerge_action=="unmerge":
3534 if y not in pkgmap[mykey]["selected"]:
3535 pkgmap[mykey]["selected"].append(y)
3536 numselected=numselected+len(mymatch)
3539 #unmerge_action in ["prune", clean"]
3541 for mypkg in mymatch:
3542 if unmerge_action=="clean":
3543 myslot=localtree.getslot(mypkg)
3545 # since we're pruning, we don't care about slots
3546 # and put all the pkgs in together
3548 if not slotmap.has_key(myslot):
3550 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3551 for myslot in slotmap.keys():
3552 counterkeys=slotmap[myslot].keys()
3557 pkgmap[mykey]["protected"].append(
3558 slotmap[myslot][counterkeys[-1]])
3560 #be pretty and get them in order of merge:
3561 for ckey in counterkeys:
3562 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
3563 numselected=numselected+1
3564 # ok, now the last-merged package
3565 # is protected, and the rest are selected
3566 if global_unmerge and not numselected:
3567 portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
3571 portage.writemsg_stdout(
3572 "\n>>> No packages selected for removal by " + \
3573 unmerge_action + "\n")
3577 portage.locks.unlockdir(vdb_lock)
3578 for x in pkgmap.keys():
3579 for y in localtree.dep_match(x):
3580 if y not in pkgmap[x]["omitted"] and \
3581 y not in pkgmap[x]["selected"] and \
3582 y not in pkgmap[x]["protected"]:
3583 pkgmap[x]["omitted"].append(y)
3584 if global_unmerge and not pkgmap[x]["selected"]:
3585 #avoid cluttering the preview printout with stuff that isn't getting unmerged
3587 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
3588 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
3589 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
3590 if "--pretend" not in myopts and "--ask" not in myopts:
3591 countdown(int(settings["EMERGE_WARNING_DELAY"]),
3592 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3593 print "\n "+white(x)
3594 for mytype in ["selected","protected","omitted"]:
3595 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
3596 if pkgmap[x][mytype]:
3597 for mypkg in pkgmap[x][mytype]:
3598 mysplit=portage.catpkgsplit(mypkg)
3599 if mysplit[3]=="r0":
3600 myversion=mysplit[2]
3602 myversion=mysplit[2]+"-"+mysplit[3]
3603 if mytype=="selected":
3604 portage.writemsg_stdout(
3605 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
3607 portage.writemsg_stdout(
3608 colorize("GOOD", myversion + " "), noiselevel=-1)
3610 portage.writemsg_stdout("none", noiselevel=-1)
3611 portage.writemsg_stdout("\n", noiselevel=-1)
3613 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3614 " packages are slated for removal.\n")
3615 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
3616 " and " + colorize("GOOD", "'omitted'") + \
3617 " packages will not be removed.\n\n")
3619 if "--pretend" in myopts:
3620 #we're done... return
3622 if "--ask" in myopts:
3623 if userquery("Would you like to unmerge these packages?")=="No":
3624 # enter pretend mode for correct formatting of results
3625 myopts["--pretend"] = True
3630 #the real unmerging begins, after a short delay....
3632 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3634 for x in pkgmap.keys():
3635 for y in pkgmap[x]["selected"]:
3636 print ">>> Unmerging "+y+"..."
3637 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3638 mysplit=y.split("/")
3640 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3641 mysettings, unmerge_action not in ["clean","prune"],
3642 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3643 if retval != os.EX_OK:
3644 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3645 ebuild = vartree.dbapi.findname(y)
3646 show_unmerge_failure_message(y, ebuild, retval)
3649 clean_world(vartree.dbapi, y)
3650 emergelog(xterm_titles, " >>> unmerge success: "+y)
3653 def show_unmerge_failure_message(pkg, ebuild, retval):
3655 from formatter import AbstractFormatter, DumbWriter
3656 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3659 msg.append("A removal phase of the '%s' package " % pkg)
3660 msg.append("has failed with exit value %s. " % retval)
3661 msg.append("The problem occurred while executing ")
3662 msg.append("the ebuild located at '%s'. " % ebuild)
3663 msg.append("If necessary, manually remove the ebuild " )
3664 msg.append("in order to skip the execution of removal phases.")
3668 f.add_flowing_data(x)
3672 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3674 if os.path.exists("/usr/bin/install-info"):
3679 inforoot=normpath(root+z)
3680 if os.path.isdir(inforoot):
3681 infomtime = long(os.stat(inforoot).st_mtime)
3682 if inforoot not in prev_mtimes or \
3683 prev_mtimes[inforoot] != infomtime:
3684 regen_infodirs.append(inforoot)
3686 if not regen_infodirs:
3687 portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
3689 portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
3693 for inforoot in regen_infodirs:
3696 for filename in ("dir", "dir.gz", "dir.bz2"):
3697 file_path = os.path.join(inforoot, filename)
3699 os.rename(file_path, file_path + ".old")
3701 if e.errno != errno.ENOENT:
3705 if not os.path.isdir(inforoot):
3708 file_list = os.listdir(inforoot)
3711 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3713 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3714 existsstr="already exists, for file `"
3716 if re.search(existsstr,myso):
3717 # Already exists... Don't increment the count for this.
3719 elif myso[:44]=="install-info: warning: no info dir entry in ":
3720 # This info file doesn't contain a DIR-header: install-info produces this
3721 # (harmless) warning (the --quiet switch doesn't seem to work).
3722 # Don't increment the count for this.
3726 errmsg += myso + "\n"
3729 #update mtime so we can potentially avoid regenerating.
3730 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3733 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3736 print " "+green("*")+" Processed",icount,"info files."
3739 def display_news_notification(settings):
3740 target_root = settings["ROOT"]
3741 NEWS_PATH = os.path.join("metadata", "news")
3742 UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
3743 porttree = portdbapi(porttree_root=settings["PORTDIR"], mysettings=settings)
3744 newsReaderDisplay = False
3746 for repo in porttree.getRepositories():
3747 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3749 if not newsReaderDisplay:
3750 newsReaderDisplay = True
3752 print colorize("WARN", " * IMPORTANT:"),
3753 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3756 if newsReaderDisplay:
3757 print colorize("WARN", " *"),
3758 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3761 def post_emerge(settings, mtimedb, retval):
3763 Misc. things to run at the end of a merge session.
3769 Display preserved libs warnings
3772 @param settings: Configuration settings (typically portage.settings)
3773 @type settings: portage.config()
3774 @param mtimedb: The mtimeDB to store data needed across merge invocations
3775 @type mtimedb: MtimeDB class instance
3776 @param retval: Emerge's return value
3780 1. Calls sys.exit(retval)
3782 target_root = settings["ROOT"]
3783 info_mtimes = mtimedb["info"]
3785 # Load the most current variables from ${ROOT}/etc/profile.env
3787 settings.regenerate()
3790 config_protect = settings.get("CONFIG_PROTECT","").split()
3791 infodirs = settings.get("INFOPATH","").split(":") + \
3792 settings.get("INFODIR","").split(":")
3796 emergelog("notitles" not in settings.features,
3797 " *** exiting successfully.")
3799 if "noinfo" not in settings.features:
3800 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3802 chk_updated_cfg_files(target_root, config_protect)
3804 display_news_notification(settings)
3806 from portage.dbapi.vartree import PreservedLibsRegistry
3807 plib_registry = PreservedLibsRegistry(os.path.join(target_root, CACHE_PATH, "preserved_libs_registry"))
3808 if plib_registry.hasEntries():
3809 print colorize("WARN", "!!!") + " existing preserved libs:"
3810 plibdata = plib_registry.getPreservedLibs()
3811 for cpv in plibdata.keys():
3812 print colorize("WARN", ">>>") + " package: %s" % cpv
3813 for f in plibdata[cpv]:
3814 print colorize("WARN", " * ") + " - %s" % f
3815 print "Use " + colorize("GOOD", "revdep-rebuild") + " to rebuild packages using these libraries"
3816 print "and then remerge the packages listed above."
3822 def chk_updated_cfg_files(target_root, config_protect):
3824 #number of directories with some protect files in them
3826 for x in config_protect:
3827 x = os.path.join(target_root, x.lstrip(os.path.sep))
3829 mymode = os.lstat(x).st_mode
3832 if stat.S_ISDIR(mymode):
3833 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3835 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3836 os.path.split(x.rstrip(os.path.sep))
3837 a = commands.getstatusoutput(mycommand + \
3838 " ! -iname '.*~' ! -iname '.*.bak'")
3840 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3842 files = a[1].split()
3845 print colorize("WARN", " * IMPORTANT:"),
3846 if stat.S_ISDIR(mymode):
3847 print "%d config files in '%s' need updating." % \
3850 print "config file '%s' needs updating." % x
3853 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3854 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3856 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3858 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3859 Returns the number of unread (yet relevent) items.
3871 1. The number of unread but relevant news items.
3874 from portage.news import NewsManager
3875 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3876 return manager.getUnreadItems( repo_id, update=True )
3878 def is_valid_package_atom(x):
3880 testkey = portage.dep_getkey(x)
3881 except portage.exception.InvalidData:
3883 if testkey.startswith("null/"):
3884 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3889 return portage.isvalidatom(testatom)
3891 def validate_merge_list(trees, mergelist):
3892 """Validate the list to make sure all the packages are still available.
3893 This is needed for --resume."""
3894 for (pkg_type, myroot, pkg_key, action) in mergelist:
3895 if pkg_type == "binary" and \
3896 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3897 pkg_type == "ebuild" and \
3898 not trees[myroot]["porttree"].dbapi.xmatch(
3899 "match-all", "="+pkg_key):
3900 print red("!!! Error: The resume list contains packages that are no longer")
3901 print red("!!! available to be emerged. Please restart/continue")
3902 print red("!!! the merge operation manually.")
3905 def show_blocker_docs_link():
3907 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3908 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3910 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3913 def action_sync(settings, trees, mtimedb, myopts, myaction):
3914 xterm_titles = "notitles" not in settings.features
3915 emergelog(xterm_titles, " === sync")
3916 myportdir = settings.get("PORTDIR", None)
3918 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3920 if myportdir[-1]=="/":
3921 myportdir=myportdir[:-1]
3922 if not os.path.exists(myportdir):
3923 print ">>>",myportdir,"not found, creating it."
3924 os.makedirs(myportdir,0755)
3925 syncuri=settings["SYNC"].rstrip()
3927 updatecache_flg = False
3928 if myaction == "metadata":
3929 print "skipping sync"
3930 updatecache_flg = True
3931 tmpservertimestampfile = None
3932 elif syncuri[:8]=="rsync://":
3933 if not os.path.exists("/usr/bin/rsync"):
3934 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3935 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3940 import shlex, StringIO
3941 if settings["PORTAGE_RSYNC_OPTS"] == "":
3942 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3944 "--recursive", # Recurse directories
3945 "--links", # Consider symlinks
3946 "--safe-links", # Ignore links outside of tree
3947 "--perms", # Preserve permissions
3948 "--times", # Preserive mod times
3949 "--compress", # Compress the data transmitted
3950 "--force", # Force deletion on non-empty dirs
3951 "--whole-file", # Don't do block transfers, only entire files
3952 "--delete", # Delete files that aren't in the master tree
3953 "--delete-after", # Delete only after everything else is done
3954 "--stats", # Show final statistics about what was transfered
3955 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3956 "--exclude=/distfiles", # Exclude distfiles from consideration
3957 "--exclude=/local", # Exclude local from consideration
3958 "--exclude=/packages", # Exclude packages from consideration
3959 "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
3963 # The below validation is not needed when using the above hardcoded
3966 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3967 lexer = shlex.shlex(StringIO.StringIO(
3968 settings.get("PORTAGE_RSYNC_OPTS","")), posix=True)
3969 lexer.whitespace_split = True
3970 rsync_opts.extend(lexer)
3973 for opt in ("--recursive", "--times"):
3974 if opt not in rsync_opts:
3975 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3976 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3977 rsync_opts.append(opt)
3979 for exclude in ("distfiles", "local", "packages"):
3980 opt = "--exclude=/%s" % exclude
3981 if opt not in rsync_opts:
3982 portage.writemsg(yellow("WARNING:") + \
3983 " adding required option %s not included in " % opt + \
3984 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3985 rsync_opts.append(opt)
3987 if settings["RSYNC_TIMEOUT"] != "":
3988 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3989 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3991 mytimeout = int(settings["RSYNC_TIMEOUT"])
3992 rsync_opts.append("--timeout=%d" % mytimeout)
3993 except ValueError, e:
3994 portage.writemsg("!!! %s\n" % str(e))
3996 # TODO: determine options required for official servers
3997 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
3999 def rsync_opt_startswith(opt_prefix):
4000 for x in rsync_opts:
4001 if x.startswith(opt_prefix):
4005 if not rsync_opt_startswith("--timeout="):
4006 rsync_opts.append("--timeout=%d" % mytimeout)
4008 for opt in ("--compress", "--whole-file"):
4009 if opt not in rsync_opts:
4010 portage.writemsg(yellow("WARNING:") + " adding required option " + \
4011 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4012 rsync_opts.append(opt)
4014 if "--quiet" in myopts:
4015 rsync_opts.append("--quiet") # Shut up a lot
4017 rsync_opts.append("--verbose") # Print filelist
4019 if "--verbose" in myopts:
4020 rsync_opts.append("--progress") # Progress meter for each file
4022 if "--debug" in myopts:
4023 rsync_opts.append("--checksum") # Force checksum on all files
4025 if settings["RSYNC_EXCLUDEFROM"] != "":
4026 portage.writemsg(yellow("WARNING:") + \
4027 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
4028 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4029 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
4030 rsync_opts.append("--exclude-from=%s" % \
4031 settings["RSYNC_EXCLUDEFROM"])
4033 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
4034 " but file does not exist.\n")
4036 if settings["RSYNC_RATELIMIT"] != "":
4037 portage.writemsg(yellow("WARNING:") + \
4038 " usage of RSYNC_RATELIMIT is deprecated, use " + \
4039 "PORTAGE_RSYNC_EXTRA_OPTS instead")
4040 rsync_opts.append("--bwlimit=%s" % \
4041 settings["RSYNC_RATELIMIT"])
4043 # Real local timestamp file.
4044 servertimestampfile = os.path.join(
4045 myportdir, "metadata", "timestamp.chk")
4046 # Temporary file for remote server timestamp comparison.
4047 tmpservertimestampfile = os.path.join(
4048 settings["PORTAGE_TMPDIR"], "timestamp.chk")
4050 content = portage.util.grabfile(servertimestampfile)
4054 mytimestamp = time.mktime(time.strptime(content[0],
4055 "%a, %d %b %Y %H:%M:%S +0000"))
4056 except (OverflowError, ValueError):
4061 if settings.has_key("RSYNC_RETRIES"):
4062 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
4063 maxretries=int(settings["RSYNC_RETRIES"])
4065 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
4066 except SystemExit, e:
4067 raise # Needed else can't exit
4069 maxretries=3 #default number of retries
4072 user_name, hostname, port = re.split(
4073 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
4076 if user_name is None:
4078 updatecache_flg=True
4079 all_rsync_opts = set(rsync_opts)
4080 lexer = shlex.shlex(StringIO.StringIO(
4081 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")), posix=True)
4082 lexer.whitespace_split = True
4083 extra_rsync_opts = list(lexer)
4085 all_rsync_opts.update(extra_rsync_opts)
4086 family = socket.AF_INET
4087 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
4088 family = socket.AF_INET
4089 elif socket.has_ipv6 and \
4090 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
4091 family = socket.AF_INET6
4098 for addrinfo in socket.getaddrinfo(
4099 hostname, None, family, socket.SOCK_STREAM):
4100 if addrinfo[0] == socket.AF_INET6:
4101 # IPv6 addresses need to be enclosed in square brackets
4102 ips.append("[%s]" % addrinfo[4][0])
4104 ips.append(addrinfo[4][0])
4105 from random import shuffle
4107 except SystemExit, e:
4108 raise # Needed else can't exit
4109 except Exception, e:
4110 print "Notice:",str(e)
4115 dosyncuri = syncuri.replace(
4116 "//" + user_name + hostname + port + "/",
4117 "//" + user_name + ips[0] + port + "/", 1)
4118 except SystemExit, e:
4119 raise # Needed else can't exit
4120 except Exception, e:
4121 print "Notice:",str(e)
4125 if "--ask" in myopts:
4126 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
4131 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
4132 if "--quiet" not in myopts:
4133 print ">>> Starting rsync with "+dosyncuri+"..."
4135 emergelog(xterm_titles,
4136 ">>> Starting retry %d of %d with %s" % \
4137 (retries,maxretries,dosyncuri))
4138 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
4140 if mytimestamp != 0 and "--quiet" not in myopts:
4141 print ">>> Checking server timestamp ..."
4143 rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
4145 if "--debug" in myopts:
4150 # Even if there's no timestamp available locally, fetch the
4151 # timestamp anyway as an initial probe to verify that the server is
4152 # responsive. This protects us from hanging indefinitely on a
4153 # connection attempt to an unresponsive server which rsync's
4154 # --timeout option does not prevent.
4156 mycommand = rsynccommand[:]
4157 mycommand.append(dosyncuri.rstrip("/") + \
4158 "/metadata/timestamp.chk")
4159 mycommand.append(tmpservertimestampfile)
4163 def timeout_handler(signum, frame):
4164 raise portage.exception.PortageException("timed out")
4165 signal.signal(signal.SIGALRM, timeout_handler)
4166 # Timeout here in case the server is unresponsive. The
4167 # --timeout rsync option doesn't apply to the initial
4168 # connection attempt.
4171 mypids.extend(portage.process.spawn(
4172 mycommand, env=settings.environ(), returnpid=True))
4173 exitcode = os.waitpid(mypids[0], 0)[1]
4174 content = portage.grabfile(tmpservertimestampfile)
4178 os.unlink(tmpservertimestampfile)
4181 except portage.exception.PortageException, e:
4185 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
4186 os.kill(mypids[0], signal.SIGTERM)
4187 os.waitpid(mypids[0], 0)
4188 # This is the same code rsync uses for timeout.
4191 if exitcode != os.EX_OK:
4193 exitcode = (exitcode & 0xff) << 8
4195 exitcode = exitcode >> 8
4197 portage.process.spawned_pids.remove(mypids[0])
4200 servertimestamp = time.mktime(time.strptime(
4201 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
4202 except (OverflowError, ValueError):
4204 del mycommand, mypids, content
4205 if exitcode == os.EX_OK:
4206 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4207 emergelog(xterm_titles,
4208 ">>> Cancelling sync -- Already current.")
4211 print ">>> Timestamps on the server and in the local repository are the same."
4212 print ">>> Cancelling all further sync action. You are already up to date."
4214 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4218 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4219 emergelog(xterm_titles,
4220 ">>> Server out of date: %s" % dosyncuri)
4223 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4225 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4228 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4230 mycommand = rsynccommand + [dosyncuri+"/", myportdir]
4231 exitcode = portage.process.spawn(mycommand,
4232 env=settings.environ())
4233 if exitcode in [0,1,3,4,11,14,20,21]:
4235 elif exitcode in [1,3,4,11,14,20,21]:
4238 # Code 2 indicates protocol incompatibility, which is expected
4239 # for servers with protocol < 29 that don't support
4240 # --prune-empty-directories. Retry for a server that supports
4241 # at least rsync protocol version 29 (>=rsync-2.6.4).
4246 if retries<=maxretries:
4247 print ">>> Retrying..."
4252 updatecache_flg=False
4256 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4260 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4261 print darkred("!!!")+green(" that your SYNC statement is proper.")
4262 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4264 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4265 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4266 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4267 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4268 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4270 print darkred("!!!")+green(" Rsync was killed before it finished.")
4272 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4273 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4274 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4275 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4276 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4279 elif syncuri[:6]=="cvs://":
4280 if not os.path.exists("/usr/bin/cvs"):
4281 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4282 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4285 cvsdir=os.path.dirname(myportdir)
4286 if not os.path.exists(myportdir+"/CVS"):
4288 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4289 if os.path.exists(cvsdir+"/gentoo-x86"):
4290 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4295 if e.errno != errno.ENOENT:
4297 "!!! existing '%s' directory; exiting.\n" % myportdir)
4300 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4301 print "!!! cvs checkout error; exiting."
4303 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4306 print ">>> Starting cvs update with "+syncuri+"..."
4307 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4308 myportdir, settings, free=1)
4309 if retval != os.EX_OK:
4313 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4316 if updatecache_flg and \
4317 myaction != "metadata" and \
4318 "metadata-transfer" not in settings.features:
4319 updatecache_flg = False
4321 # Reload the whole config from scratch.
4322 settings, trees, mtimedb = load_emerge_config(trees=trees)
4323 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4325 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4326 action_metadata(settings, portdb, myopts)
4328 if portage.global_updates(settings, trees, mtimedb["updates"]):
4330 # Reload the whole config from scratch.
4331 settings, trees, mtimedb = load_emerge_config(trees=trees)
4332 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4334 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4335 mypvs = portage.best(
4336 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4338 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4340 if myaction != "metadata":
4341 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4342 retval = portage.process.spawn(
4343 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4344 dosyncuri], env=settings.environ())
4345 if retval != os.EX_OK:
4346 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4348 if(mybestpv != mypvs) and not "--quiet" in myopts:
4350 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4351 print red(" * ")+"that you update portage now, before any other packages are updated."
4352 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4353 print red(" * ")+"configuration files."
4354 print red(" * ")+"To update portage, run 'emerge portage'."
4357 display_news_notification(settings)
4359 def action_metadata(settings, portdb, myopts):
4360 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4361 old_umask = os.umask(0002)
4362 cachedir = os.path.normpath(settings.depcachedir)
4363 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4364 "/lib", "/opt", "/proc", "/root", "/sbin",
4365 "/sys", "/tmp", "/usr", "/var"]:
4366 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4367 "ROOT DIRECTORY ON YOUR SYSTEM."
4368 print >> sys.stderr, \
4369 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4371 if not os.path.exists(cachedir):
4374 ec = portage.eclass_cache.cache(portdb.porttree_root)
4375 myportdir = os.path.realpath(settings["PORTDIR"])
4376 cm = settings.load_best_module("portdbapi.metadbmodule")(
4377 myportdir, "metadata/cache", portage.auxdbkeys[:])
4379 from portage.cache import util
4381 class percentage_noise_maker(util.quiet_mirroring):
4382 def __init__(self, dbapi):
4384 self.cp_all = dbapi.cp_all()
4385 l = len(self.cp_all)
4386 self.call_update_min = 100000000
4387 self.min_cp_all = l/100.0
4392 for x in self.cp_all:
4394 if self.count > self.min_cp_all:
4395 self.call_update_min = 0
4397 for y in self.dbapi.cp_list(x):
4399 self.call_update_mine = 0
4401 def update(self, *arg):
4402 try: self.pstr = int(self.pstr) + 1
4403 except ValueError: self.pstr = 1
4404 sys.stdout.write("%s%i%%" % \
4405 ("\b" * (len(str(self.pstr))+1), self.pstr))
4407 self.call_update_min = 10000000
4409 def finish(self, *arg):
4410 sys.stdout.write("\b\b\b\b100%\n")
4413 if "--quiet" in myopts:
4414 def quicky_cpv_generator(cp_all_list):
4415 for x in cp_all_list:
4416 for y in portdb.cp_list(x):
4418 source = quicky_cpv_generator(portdb.cp_all())
4419 noise_maker = portage.cache.util.quiet_mirroring()
4421 noise_maker = source = percentage_noise_maker(portdb)
4422 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4423 eclass_cache=ec, verbose_instance=noise_maker)
4428 def action_regen(settings, portdb):
4429 xterm_titles = "notitles" not in settings.features
4430 emergelog(xterm_titles, " === regen")
4431 #regenerate cache entries
4432 print "Regenerating cache entries... "
4434 os.close(sys.stdin.fileno())
4435 except SystemExit, e:
4436 raise # Needed else can't exit
4440 mynodes = portdb.cp_all()
4441 from portage.cache.cache_errors import CacheError
4443 for mytree in portdb.porttrees:
4445 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4446 except CacheError, e:
4447 print "\n error listing cache entries for " + \
4448 "'%s': %s, continuing..." % (mytree, e)
4453 mymatches = portdb.cp_list(x)
4454 portage.writemsg_stdout("processing %s\n" % x)
4457 foo = portdb.aux_get(y,["DEPEND"])
4458 except SystemExit, e:
4459 # sys.exit is an exception... And consequently, we can't catch it.
4461 except Exception, e:
4462 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4464 for mytree in portdb.porttrees:
4465 if portdb.findname2(y, mytree=mytree)[0]:
4466 dead_nodes[mytree].discard(y)
4468 for mytree, nodes in dead_nodes.iteritems():
4469 auxdb = portdb.auxdb[mytree]
4473 except (KeyError, CacheError):
4477 def action_config(settings, trees, myopts, myfiles):
4478 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4479 print red("!!! config can only take a single package atom at this time\n")
4481 if not is_valid_package_atom(myfiles[0]):
4482 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4484 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4485 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4489 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4490 except ValueError, e:
4491 # Multiple matches thrown from cpv_expand
4494 print "No packages found.\n"
4497 if "--ask" in myopts:
4499 print "Please select a package to configure:"
4503 options.append(str(idx))
4504 print options[-1]+") "+pkg
4507 idx = userquery("Selection?", options)
4510 pkg = pkgs[int(idx)-1]
4512 print "The following packages available:"
4515 print "\nPlease use a specific atom or the --ask option."
4521 if "--ask" in myopts:
4522 if userquery("Ready to configure "+pkg+"?") == "No":
4525 print "Configuring pkg..."
4527 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4528 mysettings = portage.config(clone=settings)
4529 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4530 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4531 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4534 def action_info(settings, trees, myopts, myfiles):
4535 unameout=commands.getstatusoutput("uname -mrp")[1]
4536 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4537 settings.profile_path, settings["CHOST"],
4538 trees[settings["ROOT"]]["vartree"].dbapi)
4540 header_title = "System Settings"
4542 print header_width * "="
4543 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4544 print header_width * "="
4545 print "System uname: "+unameout
4546 gentoo_release = portage.grabfile(os.path.join(
4547 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4549 print gentoo_release[0]
4551 print "Unknown Host Operating System"
4552 lastSync = portage.grabfile(os.path.join(
4553 settings["PORTDIR"], "metadata", "timestamp.chk"))
4554 print "Timestamp of tree:",
4560 output=commands.getstatusoutput("distcc --version")
4562 print str(output[1].split("\n",1)[0]),
4563 if "distcc" in settings.features:
4568 output=commands.getstatusoutput("ccache -V")
4570 print str(output[1].split("\n",1)[0]),
4571 if "ccache" in settings.features:
4576 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4577 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4578 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4579 myvars = portage.util.unique_array(myvars)
4583 if portage.isvalidatom(x):
4584 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4585 pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
4586 pkg_matches.sort(portage.pkgcmp)
4588 for pn, ver, rev in pkg_matches:
4590 pkgs.append(ver + "-" + rev)
4594 pkgs = ", ".join(pkgs)
4595 print "%-20s %s" % (x+":", pkgs)
4597 print "%-20s %s" % (x+":", "[NOT VALID]")
4599 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4601 if "--verbose" in myopts:
4602 myvars=settings.keys()
4604 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4605 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4606 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4607 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4609 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4611 myvars = portage.util.unique_array(myvars)
4617 print '%s="%s"' % (x, settings[x])
4619 use = set(settings["USE"].split())
4620 use_expand = settings["USE_EXPAND"].split()
4622 for varname in use_expand:
4623 flag_prefix = varname.lower() + "_"
4625 if f.startswith(flag_prefix):
4629 print 'USE="%s"' % " ".join(use),
4630 for varname in use_expand:
4631 myval = settings.get(varname)
4633 print '%s="%s"' % (varname, myval),
4636 unset_vars.append(x)
4638 print "Unset: "+", ".join(unset_vars)
4641 if "--debug" in myopts:
4642 for x in dir(portage):
4643 module = getattr(portage, x)
4644 if "cvs_id_string" in dir(module):
4645 print "%s: %s" % (str(x), str(module.cvs_id_string))
4647 # See if we can find any packages installed matching the strings
4648 # passed on the command line
4650 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4651 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4653 mypkgs.extend(vardb.match(x))
4655 # If some packages were found...
4657 # Get our global settings (we only print stuff if it varies from
4658 # the current config)
4659 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4660 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4662 pkgsettings = portage.config(clone=settings)
4664 for myvar in mydesiredvars:
4665 global_vals[myvar] = set(settings.get(myvar, "").split())
4667 # Loop through each package
4668 # Only print settings if they differ from global settings
4669 header_printed = False
4671 # Get all package specific variables
4672 auxvalues = vardb.aux_get(pkg, auxkeys)
4674 for i in xrange(len(auxkeys)):
4675 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4677 for myvar in mydesiredvars:
4678 # If the package variable doesn't match the
4679 # current global variable, something has changed
4680 # so set diff_found so we know to print
4681 if valuesmap[myvar] != global_vals[myvar]:
4682 diff_values[myvar] = valuesmap[myvar]
4683 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4684 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4686 # If a matching ebuild is no longer available in the tree, maybe it
4687 # would make sense to compare against the flags for the best
4688 # available version with the same slot?
4690 if portdb.cpv_exists(pkg):
4692 pkgsettings.setcpv(pkg, mydb=mydb)
4693 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4695 diff_values["USE"] = valuesmap["USE"]
4696 # If a difference was found, print the info for
4700 # If we have not yet printed the header,
4702 if not header_printed:
4703 header_title = "Package Settings"
4704 print header_width * "="
4705 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4706 print header_width * "="
4707 header_printed = True
4709 # Print package info
4710 print "%s was built with the following:" % pkg
4711 for myvar in mydesiredvars + ["USE"]:
4712 if myvar in diff_values:
4713 mylist = list(diff_values[myvar])
4715 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4718 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4720 print "emerge: no search terms provided."
4722 searchinstance = search(settings, portdb,
4723 vartree, spinner, "--searchdesc" in myopts,
4724 "--quiet" not in myopts)
4725 for mysearch in myfiles:
4727 searchinstance.execute(mysearch)
4728 except re.error, comment:
4729 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4731 searchinstance.output()
4733 def action_depclean(settings, trees, ldpath_mtimes,
4735 # Kill packages that aren't explicitly merged or are required as a
4736 # dependency of another package. World file is explicit.
4738 warn_prefix = colorize("BAD", "*** WARNING *** ")
4740 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4741 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4742 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4744 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4745 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4746 print warn_prefix + "be kept. They can be manually added to this set with"
4747 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4748 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4749 print warn_prefix + "depclean, even if they are part of the world set."
4751 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4752 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4753 print warn_prefix + "consequence, it is often necessary to run "
4754 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4756 xterm_titles = "notitles" not in settings.features
4757 myroot = settings["ROOT"]
4758 dep_check_trees = {}
4759 dep_check_trees[myroot] = {}
4760 dep_check_trees[myroot]["vartree"] = \
4761 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4762 vardb = dep_check_trees[myroot]["vartree"].dbapi
4763 # Constrain dependency selection to the installed packages.
4764 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4765 syslist = getlist(settings, "system")
4766 worldlist = getlist(settings, "world")
4767 system_world_dict = genericdict(worldlist)
4768 system_world_dict.update(genericdict(syslist))
4769 fakedb = portage.fakedbapi(settings=settings)
4770 myvarlist = vardb.cpv_all()
4773 print "\n!!! You have no system list.",
4775 print "\n!!! You have no world file.",
4777 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4779 if not (syslist and worldlist and myvarlist):
4780 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4781 print " break your installation.\n"
4782 if "--pretend" not in myopts:
4783 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4785 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4786 emergelog(xterm_titles, " >>> depclean")
4788 if "--quiet" not in myopts:
4789 print "\nCalculating dependencies ",
4793 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4794 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4796 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4798 while remaining_atoms:
4799 atom, parent, priority = remaining_atoms.pop()
4800 pkgs = vardb.match(atom)
4802 if not atom.startswith("!") and priority == hard:
4803 unresolveable.setdefault(atom, []).append(parent)
4805 if portage.dep_getkey(atom) not in system_world_dict:
4806 # Prune all but the best matching slot, since that's all that a
4807 # deep world update would pull in. Don't prune if the cpv is in
4808 # system or world though, since those sets trigger greedy update
4810 pkgs = [portage.best(pkgs)]
4812 if fakedb.cpv_exists(pkg):
4815 fakedb.cpv_inject(pkg)
4816 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4818 if myopts.get("--with-bdeps", "y") == "y":
4819 mydeps.append((myaux["DEPEND"], soft))
4821 mydeps.append((" ".join(myaux.values()), hard))
4822 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4823 for depstr, priority in mydeps:
4828 if "--debug" in myopts:
4830 print "Parent: ", pkg
4831 print "Depstring:", depstr
4833 if priority == soft:
4839 portage.dep._dep_check_strict = False
4840 success, atoms = portage.dep_check(depstr, None, settings,
4841 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4843 portage.dep._dep_check_strict = True
4845 show_invalid_depstring_notice(
4846 ("installed", myroot, pkg, "nomerge"),
4850 if "--debug" in myopts:
4851 print "Candidates:", atoms
4854 remaining_atoms.append((atom, pkg, priority))
4856 if "--quiet" not in myopts:
4857 print "\b\b... done!\n"
4860 print "Dependencies could not be completely resolved due to"
4861 print "the following required packages not being installed:"
4863 for atom in unresolveable:
4864 print atom, "required by", " ".join(unresolveable[atom])
4866 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4867 print "depclean? It may be necessary to manually uninstall packages that no longer"
4868 print "exist in the portage tree since it may not be possible to satisfy their"
4869 print "dependencies. Also, be aware of the --with-bdeps option that is documented"
4870 print "in " + good("`man emerge`") + "."
4874 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4877 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4878 "unmerge", cleanlist, ldpath_mtimes)
4880 print "Packages installed: "+str(len(myvarlist))
4881 print "Packages in world: "+str(len(worldlist))
4882 print "Packages in system: "+str(len(syslist))
4883 print "Unique package names: "+str(len(myvarlist))
4884 print "Required packages: "+str(len(fakedb.cpv_all()))
4885 if "--pretend" in myopts:
4886 print "Number to remove: "+str(len(cleanlist))
4888 print "Number removed: "+str(len(cleanlist))
4890 def action_build(settings, trees, mtimedb,
4891 myopts, myaction, myfiles, spinner):
4892 ldpath_mtimes = mtimedb["ldpath"]
4894 if "--quiet" not in myopts and \
4895 ("--pretend" in myopts or "--ask" in myopts or \
4896 "--tree" in myopts or "--verbose" in myopts):
4898 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4902 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4904 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4908 print darkgreen("These are the packages that would be %s, in order:") % action
4911 # validate the state of the resume data
4912 # so that we can make assumptions later.
4913 for k in ("resume", "resume_backup"):
4915 if "mergelist" in mtimedb[k]:
4916 if not mtimedb[k]["mergelist"]:
4921 if "--resume" in myopts and \
4922 ("resume" in mtimedb or
4923 "resume_backup" in mtimedb):
4924 if "resume" not in mtimedb:
4925 mtimedb["resume"] = mtimedb["resume_backup"]
4926 del mtimedb["resume_backup"]
4928 # XXX: "myopts" is a list for backward compatibility.
4929 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4931 for opt in ("--skipfirst", "--ask", "--tree"):
4932 myresumeopts.pop(opt, None)
4934 for myopt, myarg in myopts.iteritems():
4935 if myopt not in myresumeopts:
4936 myresumeopts[myopt] = myarg
4939 # Adjust config according to options of the command being resumed.
4940 for myroot in trees:
4941 mysettings = trees[myroot]["vartree"].settings
4943 adjust_config(myopts, mysettings)
4945 del myroot, mysettings
4947 myparams = create_depgraph_params(myopts, myaction)
4948 if "--quiet" not in myopts and "--nodeps" not in myopts:
4949 print "Calculating dependencies ",
4950 mydepgraph = depgraph(settings, trees,
4951 myopts, myparams, spinner)
4952 if "--quiet" not in myopts and "--nodeps" not in myopts:
4953 print "\b\b... done!"
4955 if ("--resume" in myopts):
4956 print darkgreen("emerge: It seems we have nothing to resume...")
4959 myparams = create_depgraph_params(myopts, myaction)
4960 if myaction in ["system","world"]:
4961 if "--quiet" not in myopts and "--nodeps" not in myopts:
4962 print "Calculating",myaction,"dependencies ",
4964 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4965 if not mydepgraph.xcreate(myaction):
4966 print "!!! Depgraph creation failed."
4968 if "--quiet" not in myopts and "--nodeps" not in myopts:
4969 print "\b\b... done!"
4971 if "--quiet" not in myopts and "--nodeps" not in myopts:
4972 print "Calculating dependencies ",
4974 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4976 retval, favorites = mydepgraph.select_files(myfiles)
4977 except portage.exception.PackageNotFound, e:
4978 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4982 if "--quiet" not in myopts and "--nodeps" not in myopts:
4983 print "\b\b... done!"
4985 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4986 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4988 if mydepgraph.missingbins:
4989 for x in mydepgraph.missingbins:
4990 sys.stderr.write(" "+str(x)+"\n")
4991 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4994 if "--pretend" not in myopts and \
4995 ("--ask" in myopts or "--tree" in myopts or \
4996 "--verbose" in myopts) and \
4997 not ("--quiet" in myopts and "--ask" not in myopts):
4998 if "--resume" in myopts:
4999 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5000 mymergelist = mtimedb["resume"]["mergelist"]
5001 if "--skipfirst" in myopts:
5002 mymergelist = mymergelist[1:]
5003 if len(mymergelist) == 0:
5004 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5006 mydepgraph.display(mymergelist)
5007 prompt="Would you like to resume merging these packages?"
5010 mydepgraph.altlist(reversed=("--tree" in myopts)))
5012 for x in mydepgraph.altlist():
5013 if x[0] != "blocks" and x[3] != "nomerge":
5015 #check for blocking dependencies
5016 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
5017 print "\n!!! Error: The above package list contains packages which cannot be installed"
5018 print "!!! at the same time on the same system."
5019 if "--quiet" not in myopts:
5020 show_blocker_docs_link()
5023 if "--noreplace" in myopts and favorites:
5026 print " %s %s" % (good("*"), x)
5027 prompt="Would you like to add these packages to your world favorites?"
5028 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5029 prompt="Nothing to merge; would you like to auto-clean packages?"
5032 print "Nothing to merge; quitting."
5035 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5036 prompt="Would you like to fetch the source files for these packages?"
5038 prompt="Would you like to merge these packages?"
5040 if "--ask" in myopts and userquery(prompt) == "No":
5045 # Don't ask again (e.g. when auto-cleaning packages after merge)
5046 myopts.pop("--ask", None)
5048 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5049 if ("--resume" in myopts):
5050 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5051 mymergelist = mtimedb["resume"]["mergelist"]
5052 if "--skipfirst" in myopts:
5053 mymergelist = mymergelist[1:]
5054 if len(mymergelist) == 0:
5055 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5057 mydepgraph.display(mymergelist)
5060 mydepgraph.altlist(reversed=("--tree" in myopts)))
5061 if ("--buildpkgonly" in myopts):
5062 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5063 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5064 print "!!! You have to merge the dependencies before you can build this package.\n"
5067 if ("--buildpkgonly" in myopts):
5068 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5069 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5070 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
5073 if ("--resume" in myopts):
5074 favorites=mtimedb["resume"]["favorites"]
5075 mergetask = MergeTask(settings, trees, myopts)
5076 if "--fetchonly" in myopts:
5077 """ parallel-fetch uses --resume --fetchonly and we don't want
5078 it to write the mtimedb"""
5079 mtimedb.filename = None
5080 time.sleep(3) # allow the parent to have first fetch
5082 retval = mergetask.merge(
5083 mtimedb["resume"]["mergelist"], favorites, mtimedb)
5084 if retval != os.EX_OK:
5087 if "resume" in mtimedb and \
5088 "mergelist" in mtimedb["resume"] and \
5089 len(mtimedb["resume"]["mergelist"]) > 1:
5090 mtimedb["resume_backup"] = mtimedb["resume"]
5091 del mtimedb["resume"]
5093 mtimedb["resume"]={}
5094 # XXX: Stored as a list for backward compatibility.
5095 mtimedb["resume"]["myopts"] = \
5096 [k for k in myopts if myopts[k] is True]
5097 mtimedb["resume"]["favorites"]=favorites
5098 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5099 for pkgline in mydepgraph.altlist():
5100 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5101 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
5102 tmpsettings = portage.config(clone=settings)
5104 if settings.get("PORTAGE_DEBUG", "") == "1":
5106 retval = portage.doebuild(
5107 y, "digest", settings["ROOT"], tmpsettings, edebug,
5108 ("--pretend" in myopts),
5109 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
5111 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5113 for pkg in mydepgraph.altlist():
5114 if pkg[0] != "blocks":
5117 pkglist = mydepgraph.altlist()
5119 mergetask = MergeTask(settings, trees, myopts)
5120 retval = mergetask.merge(pkglist, favorites, mtimedb)
5121 if retval != os.EX_OK:
5124 if mtimedb.has_key("resume"):
5125 del mtimedb["resume"]
5126 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5127 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5128 vartree = trees[settings["ROOT"]]["vartree"]
5129 unmerge(settings, myopts, vartree, "clean", ["world"],
5130 ldpath_mtimes, autoclean=1)
5132 portage.writemsg_stdout(colorize("WARN", "WARNING:")
5133 + " AUTOCLEAN is disabled. This can cause serious"
5134 + " problems due to overlapping packages.\n")
5136 def multiple_actions(action1, action2):
5137 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
5138 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
5141 def parse_opts(tmpcmdline, silent=False):
5146 global actions, options, shortmapping
5148 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
5149 argument_options = {
5151 "help":"specify the location for portage configuration files",
5155 "help":"enable or disable color output",
5157 "choices":("y", "n")
5160 "help":"include unnecessary build time dependencies",
5162 "choices":("y", "n")
5166 from optparse import OptionParser
5167 parser = OptionParser()
5168 if parser.has_option("--help"):
5169 parser.remove_option("--help")
5171 for action_opt in actions:
5172 parser.add_option("--" + action_opt, action="store_true",
5173 dest=action_opt.replace("-", "_"), default=False)
5174 for myopt in options:
5175 parser.add_option(myopt, action="store_true",
5176 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5177 for shortopt, longopt in shortmapping.iteritems():
5178 parser.add_option("-" + shortopt, action="store_true",
5179 dest=longopt.lstrip("--").replace("-", "_"), default=False)
5180 for myalias, myopt in longopt_aliases.iteritems():
5181 parser.add_option(myalias, action="store_true",
5182 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5184 for myopt, kwargs in argument_options.iteritems():
5185 parser.add_option(myopt,
5186 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
5188 myoptions, myargs = parser.parse_args(args=tmpcmdline)
5190 for myopt in options:
5191 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
5193 myopts[myopt] = True
5195 for myopt in argument_options:
5196 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
5200 for action_opt in actions:
5201 v = getattr(myoptions, action_opt.replace("-", "_"))
5204 multiple_actions(myaction, action_opt)
5206 myaction = action_opt
5209 if x in actions and myaction != "search":
5210 if not silent and x not in ["system", "world"]:
5211 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
5212 # special case "search" so people can search for action terms, e.g. emerge -s sync
5214 multiple_actions(myaction, x)
5220 if "--nocolor" in myopts:
5222 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
5223 "use '--color=n' instead.\n")
5224 del myopts["--nocolor"]
5225 myopts["--color"] = "n"
5227 return myaction, myopts, myfiles
5229 def validate_ebuild_environment(trees):
5230 for myroot in trees:
5231 mysettings = trees[myroot]["vartree"].settings
5232 for var in "ARCH", "USERLAND":
5233 if mysettings.get(var):
5235 print >> sys.stderr, bad(("\a!!! %s is not set... " % var) + \
5236 "Are you missing the '%setc/make.profile' symlink?" % \
5237 mysettings["PORTAGE_CONFIGROOT"])
5238 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5239 "Is your portage tree complete?\n")
5241 del myroot, mysettings
5243 def load_emerge_config(trees=None):
5245 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5246 kwargs[k] = os.environ.get(envvar, None)
5247 trees = portage.create_trees(trees=trees, **kwargs)
5249 settings = trees["/"]["vartree"].settings
5251 for myroot in trees:
5253 settings = trees[myroot]["vartree"].settings
5256 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5257 mtimedb = portage.MtimeDB(mtimedbfile)
5258 return settings, trees, mtimedb
5260 def adjust_config(myopts, settings):
5261 """Make emerge specific adjustments to the config."""
5263 # To enhance usability, make some vars case insensitive by forcing them to
5265 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5266 if myvar in settings:
5267 settings[myvar] = settings[myvar].lower()
5268 settings.backup_changes(myvar)
5271 # Kill noauto as it will break merges otherwise.
5272 if "noauto" in settings.features:
5273 while "noauto" in settings.features:
5274 settings.features.remove("noauto")
5275 settings["FEATURES"] = " ".join(settings.features)
5276 settings.backup_changes("FEATURES")
5280 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5281 except ValueError, e:
5282 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5283 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5284 settings["CLEAN_DELAY"], noiselevel=-1)
5285 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5286 settings.backup_changes("CLEAN_DELAY")
5288 EMERGE_WARNING_DELAY = 10
5290 EMERGE_WARNING_DELAY = int(settings.get(
5291 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5292 except ValueError, e:
5293 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5294 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5295 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5296 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5297 settings.backup_changes("EMERGE_WARNING_DELAY")
5299 if "--quiet" in myopts:
5300 settings["PORTAGE_QUIET"]="1"
5301 settings.backup_changes("PORTAGE_QUIET")
5303 # Set so that configs will be merged regardless of remembered status
5304 if ("--noconfmem" in myopts):
5305 settings["NOCONFMEM"]="1"
5306 settings.backup_changes("NOCONFMEM")
5308 # Set various debug markers... They should be merged somehow.
5311 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5312 if PORTAGE_DEBUG not in (0, 1):
5313 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5314 PORTAGE_DEBUG, noiselevel=-1)
5315 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5318 except ValueError, e:
5319 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5320 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5321 settings["PORTAGE_DEBUG"], noiselevel=-1)
5323 if "--debug" in myopts:
5325 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5326 settings.backup_changes("PORTAGE_DEBUG")
5328 if settings.get("NOCOLOR") not in ("yes","true"):
5329 portage.output.havecolor = 1
5331 """The explicit --color < y | n > option overrides the NOCOLOR environment
5332 variable and stdout auto-detection."""
5333 if "--color" in myopts:
5334 if "y" == myopts["--color"]:
5335 portage.output.havecolor = 1
5336 settings["NOCOLOR"] = "false"
5338 portage.output.havecolor = 0
5339 settings["NOCOLOR"] = "true"
5340 settings.backup_changes("NOCOLOR")
5341 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5342 portage.output.havecolor = 0
5343 settings["NOCOLOR"] = "true"
5344 settings.backup_changes("NOCOLOR")
5347 global portage # NFC why this is necessary now - genone
5348 # Disable color until we're sure that it should be enabled (after
5349 # EMERGE_DEFAULT_OPTS has been parsed).
5350 portage.output.havecolor = 0
5351 # This first pass is just for options that need to be known as early as
5352 # possible, such as --config-root. They will be parsed again later,
5353 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5354 # the value of --config-root).
5355 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5356 if "--debug" in myopts:
5357 os.environ["PORTAGE_DEBUG"] = "1"
5358 if "--config-root" in myopts:
5359 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5361 # Portage needs to ensure a sane umask for the files it creates.
5363 settings, trees, mtimedb = load_emerge_config()
5364 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5367 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5368 except (OSError, ValueError), e:
5369 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5370 settings["PORTAGE_NICENESS"])
5371 portage.writemsg("!!! %s\n" % str(e))
5374 if portage.global_updates(settings, trees, mtimedb["updates"]):
5376 # Reload the whole config from scratch.
5377 settings, trees, mtimedb = load_emerge_config(trees=trees)
5378 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5380 xterm_titles = "notitles" not in settings.features
5383 if "--ignore-default-opts" not in sys.argv:
5384 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5385 tmpcmdline.extend(sys.argv[1:])
5386 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5388 if "--digest" in myopts:
5389 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5390 # Reload the whole config from scratch so that the portdbapi internal
5391 # config is updated with new FEATURES.
5392 settings, trees, mtimedb = load_emerge_config(trees=trees)
5393 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5395 for myroot in trees:
5396 mysettings = trees[myroot]["vartree"].settings
5398 adjust_config(myopts, mysettings)
5400 del myroot, mysettings
5402 spinner = stdout_spinner()
5403 if "candy" in settings.features:
5404 spinner.update = spinner.update_scroll
5406 if "--quiet" not in myopts:
5407 portage.deprecated_profile_check()
5409 #Freeze the portdbapi for enhanced performance:
5410 for myroot in trees:
5411 trees[myroot]["porttree"].dbapi.freeze()
5414 if "moo" in myfiles:
5417 Larry loves Gentoo (""" + os.uname()[0] + """)
5419 _______________________
5420 < Have you mooed today? >
5421 -----------------------
5430 if (myaction in ["world", "system"]) and myfiles:
5431 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5435 ext = os.path.splitext(x)[1]
5436 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5437 print "emerging by path implies --oneshot... adding --oneshot to options."
5438 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5441 if ("--tree" in myopts) and ("--columns" in myopts):
5442 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5445 if ("--quiet" in myopts):
5446 spinner.update = spinner.update_quiet
5447 portage.util.noiselimit = -1
5449 # Always create packages if FEATURES=buildpkg
5450 # Imply --buildpkg if --buildpkgonly
5451 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5452 if "--buildpkg" not in myopts:
5453 myopts["--buildpkg"] = True
5455 # Also allow -S to invoke search action (-sS)
5456 if ("--searchdesc" in myopts):
5457 if myaction and myaction != "search":
5458 myfiles.append(myaction)
5459 if "--search" not in myopts:
5460 myopts["--search"] = True
5463 # Always try and fetch binary packages if FEATURES=getbinpkg
5464 if ("getbinpkg" in settings.features):
5465 myopts["--getbinpkg"] = True
5467 if "--skipfirst" in myopts and "--resume" not in myopts:
5468 myopts["--resume"] = True
5470 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5471 myopts["--usepkgonly"] = True
5473 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5474 myopts["--getbinpkg"] = True
5476 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5477 myopts["--usepkg"] = True
5479 # Also allow -K to apply --usepkg/-k
5480 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5481 myopts["--usepkg"] = True
5483 # Allow -p to remove --ask
5484 if ("--pretend" in myopts) and ("--ask" in myopts):
5485 print ">>> --pretend disables --ask... removing --ask from options."
5488 # forbid --ask when not in a terminal
5489 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5490 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5491 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5495 if settings.get("PORTAGE_DEBUG", "") == "1":
5496 spinner.update = spinner.update_quiet
5498 if "python-trace" in settings.features:
5499 import portage.debug
5500 portage.debug.set_trace(True)
5502 if ("--resume" in myopts):
5503 if "--tree" in myopts:
5504 print "* --tree is currently broken with --resume. Disabling..."
5505 del myopts["--tree"]
5507 if not ("--quiet" in myopts):
5508 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5509 spinner.update = spinner.update_basic
5511 if "--version" in myopts:
5512 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5513 settings.profile_path, settings["CHOST"],
5514 trees[settings["ROOT"]]["vartree"].dbapi)
5516 elif "--help" in myopts:
5517 emerge.help.help(myaction, myopts, portage.output.havecolor)
5520 if portage.wheelgid == portage.portage_gid:
5521 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5522 print " include the portage user as noted above, and then use group portage."
5524 if "--debug" in myopts:
5525 print "myaction", myaction
5526 print "myopts", myopts
5528 if not myaction and not myfiles and "--resume" not in myopts:
5529 emerge.help.help(myaction, myopts, portage.output.havecolor)
5532 # check if root user is the current user for the actions where emerge needs this
5533 if portage.secpass < 2:
5534 # We've already allowed "--version" and "--help" above.
5535 if "--pretend" not in myopts and \
5536 myaction not in ("search","info"):
5537 need_superuser = not \
5538 ("--fetchonly" in myopts or \
5539 "--fetch-all-uri" in myopts or \
5540 myaction in ("metadata", "regen"))
5541 if portage.secpass < 1 or \
5544 access_desc = "superuser"
5546 access_desc = "portage group"
5547 # Always show portage_group_warning() when only portage group
5548 # access is required but the user is not in the portage group.
5549 from portage.data import portage_group_warning
5550 if "--ask" in myopts:
5551 myopts["--pretend"] = True
5553 print ("%s access would be required... " + \
5554 "adding --pretend to options.\n") % access_desc
5555 if portage.secpass < 1 and not need_superuser:
5556 portage_group_warning()
5558 sys.stderr.write(("emerge: %s access would be " + \
5559 "required.\n\n") % access_desc)
5560 if portage.secpass < 1 and not need_superuser:
5561 portage_group_warning()
5564 disable_emergelog = False
5565 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5567 disable_emergelog = True
5569 if myaction in ("search", "info"):
5570 disable_emergelog = True
5571 if disable_emergelog:
5572 """ Disable emergelog for everything except build or unmerge
5573 operations. This helps minimize parallel emerge.log entries that can
5574 confuse log parsers. We especially want it disabled during
5575 parallel-fetch, which uses --resume --fetchonly."""
5577 def emergelog(*pargs, **kargs):
5580 if not "--pretend" in myopts:
5581 emergelog(xterm_titles, "Started emerge on: "+\
5582 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5585 myelogstr=" ".join(myopts)
5587 myelogstr+=" "+myaction
5589 myelogstr+=" "+" ".join(myfiles)
5590 emergelog(xterm_titles, " *** emerge " + myelogstr)
5592 def emergeexitsig(signum, frame):
5593 signal.signal(signal.SIGINT, signal.SIG_IGN)
5594 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5595 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5596 sys.exit(100+signum)
5597 signal.signal(signal.SIGINT, emergeexitsig)
5598 signal.signal(signal.SIGTERM, emergeexitsig)
5601 """This gets out final log message in before we quit."""
5602 if "--pretend" not in myopts:
5603 emergelog(xterm_titles, " *** terminating.")
5604 if "notitles" not in settings.features:
5606 portage.atexit_register(emergeexit)
5608 if myaction in ("config", "metadata", "regen", "sync"):
5609 if "--pretend" in myopts:
5610 sys.stderr.write(("emerge: The '%s' action does " + \
5611 "not support '--pretend'.\n") % myaction)
5613 if "sync" == myaction:
5614 action_sync(settings, trees, mtimedb, myopts, myaction)
5615 elif "metadata" == myaction:
5616 action_metadata(settings, portdb, myopts)
5617 elif myaction=="regen":
5618 validate_ebuild_environment(trees)
5619 action_regen(settings, portdb)
5621 elif "config"==myaction:
5622 validate_ebuild_environment(trees)
5623 action_config(settings, trees, myopts, myfiles)
5626 elif "info"==myaction:
5627 action_info(settings, trees, myopts, myfiles)
5630 elif "search"==myaction:
5631 validate_ebuild_environment(trees)
5632 action_search(settings, portdb, trees["/"]["vartree"],
5633 myopts, myfiles, spinner)
5634 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5635 validate_ebuild_environment(trees)
5636 vartree = trees[settings["ROOT"]]["vartree"]
5637 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5639 if "--pretend" not in myopts:
5640 post_emerge(settings, mtimedb, 0)
5642 elif "depclean"==myaction:
5643 validate_ebuild_environment(trees)
5644 action_depclean(settings, trees, mtimedb["ldpath"],
5646 if "--pretend" not in myopts:
5647 post_emerge(settings, mtimedb, 0)
5648 # "update", "system", or just process files:
5650 validate_ebuild_environment(trees)
5651 if "--pretend" not in myopts:
5652 display_news_notification(settings)
5653 action_build(settings, trees, mtimedb,
5654 myopts, myaction, myfiles, spinner)
5655 if "--pretend" not in myopts:
5656 post_emerge(settings, mtimedb, 0)
5658 display_news_notification(settings)
5660 if __name__ == "__main__":
5661 retval = emerge_main()