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, PRIVATE_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
52 from portage.util import writemsg
54 from itertools import chain, izip
55 from UserDict import DictMixin
60 import pickle as cPickle
62 class stdout_spinner(object):
64 "Gentoo Rocks ("+os.uname()[0]+")",
65 "Thank you for using Gentoo. :)",
66 "Are you actually trying to read this?",
67 "How many times have you stared at this?",
68 "We are generating the cache right now",
69 "You are paying too much attention.",
70 "A theory is better than its explanation.",
71 "Phasers locked on target, Captain.",
72 "Thrashing is just virtual crashing.",
73 "To be is to program.",
74 "Real Users hate Real Programmers.",
75 "When all else fails, read the instructions.",
76 "Functionality breeds Contempt.",
77 "The future lies ahead.",
78 "3.1415926535897932384626433832795028841971694",
79 "Sometimes insanity is the only alternative.",
80 "Inaccuracy saves a world of explanation.",
83 twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
87 self.update = self.update_twirl
88 self.scroll_sequence = self.scroll_msgs[
89 int(time.time() * 100) % len(self.scroll_msgs)]
91 def update_basic(self):
92 self.spinpos = (self.spinpos + 1) % 500
93 if (self.spinpos % 100) == 0:
95 sys.stdout.write(". ")
100 def update_scroll(self):
101 if(self.spinpos >= len(self.scroll_sequence)):
102 sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
103 len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
105 sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
107 self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
109 def update_twirl(self):
110 self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
111 sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
114 def update_quiet(self):
117 def userquery(prompt, responses=None, colours=None):
118 """Displays a prompt and a set of responses, then waits for a response
119 which is checked against the responses and the first to match is
120 returned. An empty response will match the first value in responses. The
121 input buffer is *not* cleared prior to the prompt!
124 responses: a List of Strings.
125 colours: a List of Functions taking and returning a String, used to
126 process the responses for display. Typically these will be functions
127 like red() but could be e.g. lambda x: "DisplayString".
128 If responses is omitted, defaults to ["Yes", "No"], [green, red].
129 If only colours is omitted, defaults to [bold, ...].
131 Returns a member of the List responses. (If called without optional
132 arguments, returns "Yes" or "No".)
133 KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
135 if responses is None:
136 responses, colours = ["Yes", "No"], [green, red]
137 elif colours is None:
139 colours=(colours*len(responses))[:len(responses)]
143 response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
144 for key in responses:
145 # An empty response will match the first value in responses.
146 if response.upper()==key[:len(response)].upper():
148 print "Sorry, response '%s' not understood." % response,
149 except (EOFError, KeyboardInterrupt):
154 "clean", "config", "depclean",
156 "prune", "regen", "search",
157 "sync", "system", "unmerge", "world",
160 "--ask", "--alphabetical",
161 "--buildpkg", "--buildpkgonly",
162 "--changelog", "--columns",
166 "--fetchonly", "--fetch-all-uri",
167 "--getbinpkg", "--getbinpkgonly",
168 "--help", "--ignore-default-opts",
170 "--newuse", "--nocolor",
171 "--nodeps", "--noreplace",
172 "--nospinner", "--oneshot",
173 "--onlydeps", "--pretend",
174 "--quiet", "--resume",
175 "--searchdesc", "--selective",
179 "--usepkg", "--usepkgonly",
180 "--verbose", "--version"
186 "b":"--buildpkg", "B":"--buildpkgonly",
187 "c":"--clean", "C":"--unmerge",
188 "d":"--debug", "D":"--deep",
190 "f":"--fetchonly", "F":"--fetch-all-uri",
191 "g":"--getbinpkg", "G":"--getbinpkgonly",
193 "k":"--usepkg", "K":"--usepkgonly",
195 "n":"--noreplace", "N":"--newuse",
196 "o":"--onlydeps", "O":"--nodeps",
197 "p":"--pretend", "P":"--prune",
199 "s":"--search", "S":"--searchdesc",
202 "v":"--verbose", "V":"--version"
205 def emergelog(xterm_titles, mystr, short_msg=None):
207 if short_msg == None:
209 if "HOSTNAME" in os.environ:
210 short_msg = os.environ["HOSTNAME"]+": "+short_msg
211 xtermTitle(short_msg)
213 file_path = "/var/log/emerge.log"
214 mylogfile = open(file_path, "a")
215 portage.util.apply_secpass_permissions(file_path,
216 uid=portage.portage_uid, gid=portage.portage_gid,
220 mylock = portage.locks.lockfile(mylogfile)
221 # seek because we may have gotten held up by the lock.
222 # if so, we may not be positioned at the end of the file.
224 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
228 portage.locks.unlockfile(mylock)
230 except (IOError,OSError,portage.exception.PortageException), e:
232 print >> sys.stderr, "emergelog():",e
234 def countdown(secs=5, doing="Starting"):
236 print ">>> Waiting",secs,"seconds before starting..."
237 print ">>> (Control-C to abort)...\n"+doing+" in: ",
241 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
246 # formats a size given in bytes nicely
247 def format_size(mysize):
248 if type(mysize) not in [types.IntType,types.LongType]:
250 if 0 != mysize % 1024:
251 # Always round up to the next kB so that it doesn't show 0 kB when
252 # some small file still needs to be fetched.
253 mysize += 1024 - mysize % 1024
254 mystr=str(mysize/1024)
258 mystr=mystr[:mycount]+","+mystr[mycount:]
262 def getgccversion(chost):
265 return: the current in-use gcc version
268 gcc_ver_command = 'gcc -dumpversion'
269 gcc_ver_prefix = 'gcc-'
271 gcc_not_found_error = red(
272 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
273 "!!! to update the environment of this terminal and possibly\n" +
274 "!!! other terminals also.\n"
277 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
278 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
279 part1, part2 = myoutput.split("/")
280 if part1.startswith(chost + "-"):
281 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
283 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
284 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
285 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
287 mystatus, myoutput = commands.getstatusoutput(
288 chost + "-" + gcc_ver_command)
289 if mystatus == os.EX_OK:
290 return gcc_ver_prefix + myoutput
292 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
293 if mystatus == os.EX_OK:
294 return gcc_ver_prefix + myoutput
296 portage.writemsg(gcc_not_found_error, noiselevel=-1)
297 return "[unavailable]"
299 def getportageversion(portdir, target_root, profile, chost, vardb):
300 profilever = "unavailable"
302 realpath = os.path.realpath(profile)
303 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
304 if realpath.startswith(basepath):
305 profilever = realpath[1 + len(basepath):]
308 profilever = "!" + os.readlink(profile)
311 del realpath, basepath
314 libclist = vardb.match("virtual/libc")
315 libclist += vardb.match("virtual/glibc")
316 libclist = portage.util.unique_array(libclist)
318 xs=portage.catpkgsplit(x)
320 libcver+=","+"-".join(xs[1:])
322 libcver="-".join(xs[1:])
324 libcver="unavailable"
326 gccver = getgccversion(chost)
327 unameout=os.uname()[2]+" "+os.uname()[4]
329 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
331 def create_depgraph_params(myopts, myaction):
332 #configure emerge engine parameters
334 # self: include _this_ package regardless of if it is merged.
335 # selective: exclude the package if it is merged
336 # recurse: go into the dependencies
337 # deep: go into the dependencies of already merged packages
338 # empty: pretend nothing is merged
339 myparams = ["recurse"]
342 if "--update" in myopts or \
343 "--newuse" in myopts or \
344 "--reinstall" 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
364 class search(object):
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.startswith('%'):
403 self.searchkey = self.searchkey[1:]
404 if self.searchkey.startswith('@'):
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:
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:
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_set = WorldSet(vardb.settings)
572 worldlist = list(world_set)
573 mykey = portage.cpv_getkey(cpv)
576 if portage.dep_getkey(x) == mykey:
577 matches = vardb.match(x, use_cache=0)
581 elif len(matches) == 1 and matches[0] == cpv:
585 #others are around; keep it.
586 newworldlist.append(x)
588 #this doesn't match the package we're unmerging; keep it.
589 newworldlist.append(x)
592 world_set.update(newworldlist)
596 class AtomSet(object):
597 def __init__(self, atoms=None):
604 cp = portage.dep_getkey(atom)
605 cp_list = self._atoms.get(cp)
608 self._atoms[cp] = cp_list
609 if atom not in cp_list:
611 def update(self, atoms):
614 def __contains__(self, atom):
615 cp = portage.dep_getkey(atom)
616 if cp in self._atoms and atom in self._atoms[cp]:
619 def findAtomForPackage(self, cpv, metadata):
620 """Return the best match for a given package from the arguments, or
621 None if there are no matches. This matches virtual arguments against
622 the PROVIDE metadata. This can raise an InvalidDependString exception
623 if an error occurs while parsing PROVIDE."""
624 cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
625 cp = portage.dep_getkey(cpv)
626 atoms = self._atoms.get(cp)
628 best_match = portage.best_match_to_list(cpv_slot, atoms)
631 if not metadata["PROVIDE"]:
633 provides = portage.flatten(portage.dep.use_reduce(
634 portage.dep.paren_reduce(metadata["PROVIDE"]),
635 uselist=metadata["USE"].split()))
636 for provide in provides:
637 provided_cp = portage.dep_getkey(provide)
638 atoms = self._atoms.get(provided_cp)
640 transformed_atoms = [atom.replace(provided_cp, cp) for atom in atoms]
641 best_match = portage.best_match_to_list(cpv_slot, transformed_atoms)
643 return atoms[transformed_atoms.index(best_match)]
646 for atoms in self._atoms.itervalues():
650 class SystemSet(AtomSet):
651 def __init__(self, settings, **kwargs):
652 AtomSet.__init__(self, **kwargs)
653 self.update(getlist(settings, "system"))
655 class WorldSet(AtomSet):
656 def __init__(self, settings, **kwargs):
657 AtomSet.__init__(self, **kwargs)
658 self.world_file = os.path.join(settings["ROOT"], portage.WORLD_FILE)
660 def _ensure_dirs(self):
661 portage.util.ensure_dirs(os.path.dirname(self.world_file),
662 gid=portage.portage_gid, mode=02750, mask=02)
665 self.update(portage.util.grabfile_package(self.world_file))
668 portage.write_atomic(self.world_file,
669 "\n".join(sorted(self)) + "\n")
672 self._lock = portage.locks.lockfile(self.world_file, wantnewlockfile=1)
674 portage.locks.unlockfile(self._lock)
677 class RootConfig(object):
678 """This is used internally by depgraph to track information about a
680 def __init__(self, trees):
682 self.settings = trees["vartree"].settings
683 self.root = self.settings["ROOT"]
685 world_set = WorldSet(self.settings)
687 self.sets["world"] = world_set
688 system_set = SystemSet(self.settings)
689 self.sets["system"] = system_set
691 def create_world_atom(pkg_key, metadata, args_set, sets, portdb):
692 """Create a new atom for the world file if one does not exist. If the
693 argument atom is precise enough to identify a specific slot then a slot
694 atom will be returned. Atoms that are in the system set may also be stored
695 in world since system atoms can only match one slot while world atoms can
696 be greedy with respect to slots. Unslotted system packages will not be
697 not be stored in world."""
698 arg_atom = args_set.findAtomForPackage(pkg_key, metadata)
699 cp = portage.dep_getkey(arg_atom)
701 available_slots = set(portdb.aux_get(cpv, ["SLOT"])[0] \
702 for cpv in portdb.match(cp))
703 slotted = len(available_slots) > 1 or "0" not in available_slots
704 if slotted and arg_atom != cp:
705 # If the user gave a specific atom, store it as a
706 # slot atom in the world file.
707 slot_atom = "%s:%s" % (cp, metadata["SLOT"])
708 # First verify the slot is in the portage tree to avoid
709 # adding a bogus slot like that produced by multislot.
710 if portdb.match(slot_atom):
711 # Now verify that the argument is precise enough to identify a
713 matches = portdb.match(arg_atom)
714 matched_slots = set()
716 matched_slots.add(portdb.aux_get(cpv, ["SLOT"])[0])
717 if len(matched_slots) == 1:
718 new_world_atom = slot_atom
719 if new_world_atom == sets["world"].findAtomForPackage(pkg_key, metadata):
720 # Both atoms would be identical, so there's nothing to add.
722 if not slotted and sets["system"].findAtomForPackage(pkg_key, metadata):
724 return new_world_atom
726 def filter_iuse_defaults(iuse):
728 if flag.startswith("+") or flag.startswith("-"):
733 class DepPriority(object):
735 This class generates an integer priority level based of various
736 attributes of the dependency relationship. Attributes can be assigned
737 at any time and the new integer value will be generated on calls to the
738 __int__() method. Rich comparison operators are supported.
740 The boolean attributes that affect the integer value are "satisfied",
741 "buildtime", "runtime", and "system". Various combinations of
742 attributes lead to the following priority levels:
744 Combination of properties Priority level
746 not satisfied and buildtime 0
747 not satisfied and runtime -1
748 satisfied and buildtime -2
749 satisfied and runtime -3
750 (none of the above) -4
752 Several integer constants are defined for categorization of priority
755 MEDIUM The upper boundary for medium dependencies.
756 MEDIUM_SOFT The upper boundary for medium-soft dependencies.
757 SOFT The upper boundary for soft dependencies.
758 MIN The lower boundary for soft dependencies.
760 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime", "runtime_post")
765 def __init__(self, **kwargs):
766 for myattr in self.__slots__:
767 if myattr == "__weakref__":
769 myvalue = kwargs.get(myattr, False)
770 setattr(self, myattr, myvalue)
772 if not self.satisfied:
777 if self.runtime_post:
783 if self.runtime_post:
786 def __lt__(self, other):
787 return self.__int__() < other
788 def __le__(self, other):
789 return self.__int__() <= other
790 def __eq__(self, other):
791 return self.__int__() == other
792 def __ne__(self, other):
793 return self.__int__() != other
794 def __gt__(self, other):
795 return self.__int__() > other
796 def __ge__(self, other):
797 return self.__int__() >= other
800 return copy.copy(self)
802 myvalue = self.__int__()
803 if myvalue > self.MEDIUM:
805 if myvalue > self.MEDIUM_SOFT:
807 if myvalue > self.SOFT:
811 class FakeVartree(portage.vartree):
812 """This is implements an in-memory copy of a vartree instance that provides
813 all the interfaces required for use by the depgraph. The vardb is locked
814 during the constructor call just long enough to read a copy of the
815 installed package information. This allows the depgraph to do it's
816 dependency calculations without holding a lock on the vardb. It also
817 allows things like vardb global updates to be done in memory so that the
818 user doesn't necessarily need write access to the vardb in cases where
819 global updates are necessary (updates are performed when necessary if there
820 is not a matching ebuild in the tree)."""
821 def __init__(self, real_vartree, portdb):
822 self.root = real_vartree.root
823 self.settings = real_vartree.settings
824 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
825 vdb_path = os.path.join(self.root, portage.VDB_PATH)
827 # At least the parent needs to exist for the lock file.
828 portage.util.ensure_dirs(vdb_path)
829 except portage.exception.PortageException:
833 if os.access(vdb_path, os.W_OK):
834 vdb_lock = portage.locks.lockdir(vdb_path)
835 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
836 "RESTRICT", "DEPEND", "RDEPEND", "PDEPEND", "repository"]
837 real_dbapi = real_vartree.dbapi
839 for cpv in real_dbapi.cpv_all():
840 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
841 myslot = metadata["SLOT"]
842 mycp = portage.dep_getkey(cpv)
843 myslot_atom = "%s:%s" % (mycp, myslot)
845 mycounter = long(metadata["COUNTER"])
848 metadata["COUNTER"] = str(mycounter)
849 other_counter = slot_counters.get(myslot_atom, None)
850 if other_counter is not None:
851 if other_counter > mycounter:
853 slot_counters[myslot_atom] = mycounter
854 self.dbapi.cpv_inject(cpv, metadata=metadata)
855 real_dbapi.flush_cache()
858 portage.locks.unlockdir(vdb_lock)
859 # Populate the old-style virtuals using the cached values.
860 if not self.settings.treeVirtuals:
861 self.settings.treeVirtuals = portage.util.map_dictlist_vals(
862 portage.getCPFromCPV, self.get_all_provides())
864 # Intialize variables needed for lazy cache pulls of the live ebuild
865 # metadata. This ensures that the vardb lock is released ASAP, without
866 # being delayed in case cache generation is triggered.
867 self._aux_get = self.dbapi.aux_get
868 self.dbapi.aux_get = self._aux_get_wrapper
869 self._aux_get_history = set()
870 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
871 self._portdb = portdb
872 self._global_updates = None
874 def _aux_get_wrapper(self, pkg, wants):
875 if pkg in self._aux_get_history:
876 return self._aux_get(pkg, wants)
877 self._aux_get_history.add(pkg)
879 # Use the live ebuild metadata if possible.
880 live_metadata = dict(izip(self._portdb_keys,
881 self._portdb.aux_get(pkg, self._portdb_keys)))
882 self.dbapi.aux_update(pkg, live_metadata)
883 except (KeyError, portage.exception.PortageException):
884 if self._global_updates is None:
885 self._global_updates = \
886 grab_global_updates(self._portdb.porttree_root)
887 perform_global_updates(
888 pkg, self.dbapi, self._global_updates)
889 return self._aux_get(pkg, wants)
891 def grab_global_updates(portdir):
892 from portage.update import grab_updates, parse_updates
893 updpath = os.path.join(portdir, "profiles", "updates")
895 rawupdates = grab_updates(updpath)
896 except portage.exception.DirectoryNotFound:
899 for mykey, mystat, mycontent in rawupdates:
900 commands, errors = parse_updates(mycontent)
901 upd_commands.extend(commands)
904 def perform_global_updates(mycpv, mydb, mycommands):
905 from portage.update import update_dbentries
906 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
907 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
908 updates = update_dbentries(mycommands, aux_dict)
910 mydb.aux_update(mycpv, updates)
912 class BlockerCache(DictMixin):
913 """This caches blockers of installed packages so that dep_check does not
914 have to be done for every single installed package on every invocation of
915 emerge. The cache is invalidated whenever it is detected that something
916 has changed that might alter the results of dep_check() calls:
917 1) the set of installed packages (including COUNTER) has changed
918 2) the old-style virtuals have changed
920 class BlockerData(object):
921 def __init__(self, counter, atoms):
922 self.counter = counter
925 def __init__(self, myroot, vardb):
927 self._installed_pkgs = set(vardb.cpv_all())
928 self._virtuals = vardb.settings.getvirtuals()
929 self._cache_filename = os.path.join(myroot,
930 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
931 self._cache_version = "1"
932 self._cache_data = None
933 self._modified = False
938 f = open(self._cache_filename)
939 mypickle = cPickle.Unpickler(f)
940 mypickle.find_global = None
941 self._cache_data = mypickle.load()
944 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
946 cache_valid = self._cache_data and \
947 isinstance(self._cache_data, dict) and \
948 self._cache_data.get("version") == self._cache_version and \
949 self._cache_data.get("virtuals") == self._virtuals and \
950 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
952 for pkg in self._installed_pkgs:
953 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
958 self._cache_data = {"version":self._cache_version}
959 self._cache_data["blockers"] = {}
960 self._cache_data["virtuals"] = self._virtuals
961 self._modified = False
964 """If the current user has permission and the internal blocker cache
965 been updated, save it to disk and mark it unmodified. This is called
966 by emerge after it has proccessed blockers for all installed packages.
967 Currently, the cache is only written if the user has superuser
968 privileges (since that's required to obtain a lock), but all users
969 have read access and benefit from faster blocker lookups (as long as
970 the entire cache is still valid). The cache is stored as a pickled
971 dict object with the following format:
975 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
976 "virtuals" : vardb.settings.getvirtuals()
979 if self._modified and \
982 f = portage.util.atomic_ofstream(self._cache_filename)
983 cPickle.dump(self._cache_data, f, -1)
985 portage.util.apply_secpass_permissions(
986 self._cache_filename, gid=portage.portage_gid, mode=0644)
987 except (IOError, OSError), e:
989 self._modified = False
991 def __setitem__(self, cpv, blocker_data):
993 Update the cache and mark it as modified for a future call to
996 @param cpv: Package for which to cache blockers.
998 @param blocker_data: An object with counter and atoms attributes.
999 @type blocker_data: BlockerData
1001 self._cache_data["blockers"][cpv] = \
1002 (blocker_data.counter, blocker_data.atoms)
1003 self._modified = True
1005 def __getitem__(self, cpv):
1008 @returns: An object with counter and atoms attributes.
1010 return self.BlockerData(*self._cache_data["blockers"][cpv])
1013 """This needs to be implemented so that self.__repr__() doesn't raise
1014 an AttributeError."""
1015 if self._cache_data and "blockers" in self._cache_data:
1016 return self._cache_data["blockers"].keys()
1019 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
1021 from formatter import AbstractFormatter, DumbWriter
1022 f = AbstractFormatter(DumbWriter(maxcol=72))
1024 print "\n\n!!! Invalid or corrupt dependency specification: "
1032 p_type, p_root, p_key, p_status = parent_node
1034 if p_status == "nomerge":
1035 category, pf = portage.catsplit(p_key)
1036 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
1037 msg.append("Portage is unable to process the dependencies of the ")
1038 msg.append("'%s' package. " % p_key)
1039 msg.append("In order to correct this problem, the package ")
1040 msg.append("should be uninstalled, reinstalled, or upgraded. ")
1041 msg.append("As a temporary workaround, the --nodeps option can ")
1042 msg.append("be used to ignore all dependencies. For reference, ")
1043 msg.append("the problematic dependencies can be found in the ")
1044 msg.append("*DEPEND files located in '%s/'." % pkg_location)
1046 msg.append("This package can not be installed. ")
1047 msg.append("Please notify the '%s' package maintainer " % p_key)
1048 msg.append("about this problem.")
1051 f.add_flowing_data(x)
1054 class depgraph(object):
1057 "ebuild":"porttree",
1059 "installed":"vartree"}
1061 def __init__(self, settings, trees, myopts, myparams, spinner):
1062 self.settings = settings
1063 self.target_root = settings["ROOT"]
1064 self.myopts = myopts
1065 self.myparams = myparams
1067 if settings.get("PORTAGE_DEBUG", "") == "1":
1069 self.spinner = spinner
1070 self.pkgsettings = {}
1071 # Maps cpv to digraph node for all nodes added to the graph.
1072 self.pkg_node_map = {}
1073 # Maps slot atom to digraph node for all nodes added to the graph.
1074 self._slot_node_map = {}
1076 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND",
1077 "USE", "IUSE", "PROVIDE", "RESTRICT", "repository"]
1081 for myroot in trees:
1082 self.trees[myroot] = {}
1083 for tree in ("porttree", "bintree"):
1084 self.trees[myroot][tree] = trees[myroot][tree]
1085 self.trees[myroot]["vartree"] = \
1086 FakeVartree(trees[myroot]["vartree"],
1087 trees[myroot]["porttree"].dbapi)
1088 self.pkgsettings[myroot] = portage.config(
1089 clone=self.trees[myroot]["vartree"].settings)
1090 self.pkg_node_map[myroot] = {}
1091 self._slot_node_map[myroot] = {}
1092 vardb = self.trees[myroot]["vartree"].dbapi
1093 self.roots[myroot] = RootConfig(self.trees[myroot])
1094 # This fakedbapi instance will model the state that the vdb will
1095 # have after new packages have been installed.
1096 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
1097 self.mydbapi[myroot] = fakedb
1098 if "--nodeps" not in self.myopts and \
1099 "--buildpkgonly" not in self.myopts:
1100 # --nodeps bypasses this, since it isn't needed in this case
1101 # and the cache pulls might trigger (slow) cache generation.
1102 for pkg in vardb.cpv_all():
1103 self.spinner.update()
1104 fakedb.cpv_inject(pkg,
1105 metadata=dict(izip(self._mydbapi_keys,
1106 vardb.aux_get(pkg, self._mydbapi_keys))))
1108 self.useFlags[myroot] = {}
1109 if "--usepkg" in self.myopts:
1110 self.trees[myroot]["bintree"].populate(
1111 "--getbinpkg" in self.myopts,
1112 "--getbinpkgonly" in self.myopts)
1116 self.digraph=portage.digraph()
1117 # Tracks simple parent/child relationships (PDEPEND relationships are
1119 self._parent_child_digraph = digraph()
1121 self.outdatedpackages=[]
1122 # contains all sets added to the graph
1124 # contains atoms given as arguments
1125 self._sets["args"] = AtomSet()
1126 # contains all atoms from all sets added to the graph, including
1127 # atoms given as arguments
1128 self._set_atoms = AtomSet()
1129 # contains all nodes pulled in by self._set_atoms
1130 self._set_nodes = set()
1131 self.blocker_digraph = digraph()
1132 self.blocker_parents = {}
1133 self._unresolved_blocker_parents = {}
1134 self._slot_collision_info = []
1135 # Slot collision nodes are not allowed to block other packages since
1136 # blocker validation is only able to account for one package per slot.
1137 self._slot_collision_nodes = set()
1138 self._altlist_cache = {}
1139 self._pprovided_args = []
1141 def _show_slot_collision_notice(self, packages):
1142 """Show an informational message advising the user to mask one of the
1143 the packages. In some cases it may be possible to resolve this
1144 automatically, but support for backtracking (removal nodes that have
1145 already been selected) will be required in order to handle all possible
1149 msg.append("\n!!! Multiple versions within a single " + \
1150 "package slot have been \n")
1151 msg.append("!!! pulled into the dependency graph:\n\n")
1152 for node, parents in packages:
1153 msg.append(str(node))
1155 msg.append(" pulled in by\n")
1156 for parent in parents:
1158 msg.append(str(parent))
1161 msg.append(" (no parents)\n")
1163 sys.stderr.write("".join(msg))
1166 if "--quiet" in self.myopts:
1170 msg.append("It may be possible to solve this problem ")
1171 msg.append("by using package.mask to prevent one of ")
1172 msg.append("those packages from being selected. ")
1173 msg.append("However, it is also possible that conflicting ")
1174 msg.append("dependencies exist such that they are impossible to ")
1175 msg.append("satisfy simultaneously. If such a conflict exists in ")
1176 msg.append("the dependencies of two different packages, then those ")
1177 msg.append("packages can not be installed simultaneously.")
1179 from formatter import AbstractFormatter, DumbWriter
1180 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1182 f.add_flowing_data(x)
1186 msg.append("For more information, see MASKED PACKAGES ")
1187 msg.append("section in the emerge man page or refer ")
1188 msg.append("to the Gentoo Handbook.")
1190 f.add_flowing_data(x)
1194 def _reinstall_for_flags(self, forced_flags,
1195 orig_use, orig_iuse, cur_use, cur_iuse):
1196 if "--newuse" in self.myopts:
1197 if orig_iuse.symmetric_difference(
1198 cur_iuse).difference(forced_flags):
1200 elif orig_iuse.intersection(orig_use) != \
1201 cur_iuse.intersection(cur_use):
1203 elif "changed-use" == self.myopts.get("--reinstall"):
1204 if orig_iuse.intersection(orig_use) != \
1205 cur_iuse.intersection(cur_use):
1209 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1210 priority=DepPriority(), rev_dep=False, arg=None):
1212 Fills the digraph with nodes comprised of packages to merge.
1213 mybigkey is the package spec of the package to merge.
1214 myparent is the package depending on mybigkey ( or None )
1215 addme = Should we add this package to the digraph or are we just looking at it's deps?
1216 Think --onlydeps, we need to ignore packages in that case.
1219 #IUSE-aware emerge -> USE DEP aware depgraph
1220 #"no downgrade" emerge
1222 mytype, myroot, mykey = mybigkey
1223 existing_node = None
1225 existing_node = self.pkg_node_map[myroot].get(mykey)
1227 self._parent_child_digraph.add(existing_node, myparent)
1228 if existing_node != myparent:
1229 # Refuse to make a node depend on itself so that the we don't
1230 # don't create a bogus circular dependency in self.altlist().
1231 if rev_dep and myparent:
1232 self.digraph.addnode(myparent, existing_node,
1235 self.digraph.addnode(existing_node, myparent,
1239 if "--nodeps" not in self.myopts:
1240 self.spinner.update()
1241 if mytype == "blocks":
1243 "--buildpkgonly" not in self.myopts and \
1244 "--nodeps" not in self.myopts and \
1245 myparent not in self._slot_collision_nodes:
1246 mybigkey[1] = myparent[1]
1247 self.blocker_parents.setdefault(
1248 tuple(mybigkey), set()).add(myparent)
1251 # select the correct /var database that we'll be checking against
1252 vardbapi = self.trees[myroot]["vartree"].dbapi
1253 portdb = self.trees[myroot]["porttree"].dbapi
1254 bindb = self.trees[myroot]["bintree"].dbapi
1255 pkgsettings = self.pkgsettings[myroot]
1257 # if the package is already on the system, we add a "nomerge"
1258 # directive, otherwise we add a "merge" directive.
1260 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1261 metadata = dict(izip(self._mydbapi_keys,
1262 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1263 if mytype == "ebuild":
1264 pkgsettings.setcpv(mykey, mydb=portdb)
1265 metadata["USE"] = pkgsettings["USE"]
1266 myuse = pkgsettings["USE"].split()
1268 if not arg and myroot == self.target_root:
1270 arg = self._set_atoms.findAtomForPackage(mykey, metadata)
1271 except portage.exception.InvalidDependString, e:
1272 if mytype != "installed":
1273 show_invalid_depstring_notice(tuple(mybigkey+["merge"]),
1274 metadata["PROVIDE"], str(e))
1279 if mytype == "installed":
1281 if addme and mytype != "installed":
1282 # this is where we add the node to the list of packages to merge
1283 if "selective" in self.myparams or not arg:
1284 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1287 """ If we aren't merging, perform the --newuse check.
1288 If the package has new iuse flags or different use flags then if
1289 --newuse is specified, we need to merge the package. """
1290 if merging == 0 and \
1291 ("--newuse" in self.myopts or
1292 "--reinstall" in self.myopts) and \
1293 vardbapi.cpv_exists(mykey):
1294 pkgsettings.setcpv(mykey, mydb=mydbapi)
1295 forced_flags = set()
1296 forced_flags.update(pkgsettings.useforce)
1297 forced_flags.update(pkgsettings.usemask)
1298 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1299 iuses = set(filter_iuse_defaults(metadata["IUSE"].split()))
1300 old_iuse = set(filter_iuse_defaults(
1301 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1302 if self._reinstall_for_flags(
1303 forced_flags, old_use, old_iuse, myuse, iuses):
1306 if addme and merging == 1:
1307 mybigkey.append("merge")
1309 mybigkey.append("nomerge")
1310 jbigkey = tuple(mybigkey)
1313 if merging == 0 and vardbapi.cpv_exists(mykey) and \
1314 mytype != "installed":
1315 mytype = "installed"
1316 mybigkey[0] = "installed"
1318 jbigkey = tuple(mybigkey)
1319 metadata = dict(izip(self._mydbapi_keys,
1320 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1321 myuse = metadata["USE"].split()
1322 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1323 existing_node = self._slot_node_map[myroot].get(
1325 slot_collision = False
1327 e_type, myroot, e_cpv, e_status = existing_node
1329 # The existing node can be reused.
1330 self._parent_child_digraph.add(existing_node, myparent)
1331 if rev_dep and myparent:
1332 ptype, proot, pkey, pstatus = myparent
1333 self.digraph.addnode(myparent, existing_node,
1336 self.digraph.addnode(existing_node, myparent,
1340 # A slot collision has occurred. Sometimes this coincides
1341 # with unresolvable blockers, so the slot collision will be
1342 # shown later if there are no unresolvable blockers.
1343 e_parents = self._parent_child_digraph.parent_nodes(
1347 myparents.append(myparent)
1348 self._slot_collision_info.append(
1349 ((jbigkey, myparents), (existing_node, e_parents)))
1350 self._slot_collision_nodes.add(jbigkey)
1351 slot_collision = True
1354 # Now add this node to the graph so that self.display()
1355 # can show use flags and --tree portage.output. This node is
1356 # only being partially added to the graph. It must not be
1357 # allowed to interfere with the other nodes that have been
1358 # added. Do not overwrite data for existing nodes in
1359 # self.pkg_node_map and self.mydbapi since that data will
1360 # be used for blocker validation.
1361 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1362 self.useFlags[myroot].setdefault(mykey, myuse)
1363 # Even though the graph is now invalid, continue to process
1364 # dependencies so that things like --fetchonly can still
1365 # function despite collisions.
1367 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1368 self._slot_node_map[myroot][slot_atom] = jbigkey
1369 self.pkg_node_map[myroot][mykey] = jbigkey
1370 self.useFlags[myroot][mykey] = myuse
1372 if rev_dep and myparent:
1373 self.digraph.addnode(myparent, jbigkey,
1376 self.digraph.addnode(jbigkey, myparent,
1380 self._set_nodes.add(jbigkey)
1382 # Do this even when addme is False (--onlydeps) so that the
1383 # parent/child relationship is always known in case
1384 # self._show_slot_collision_notice() needs to be called later.
1385 self._parent_child_digraph.add(jbigkey, myparent)
1387 """ This section determines whether we go deeper into dependencies or not.
1388 We want to go deeper on a few occasions:
1389 Installing package A, we need to make sure package A's deps are met.
1390 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1391 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1393 if "deep" not in self.myparams and not merging and \
1394 not ("--update" in self.myopts and arg and merging):
1396 elif "recurse" not in self.myparams:
1399 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1400 Pull from bintree if it's binary package, porttree if it's ebuild.
1401 Binpkg's can be either remote or local. """
1404 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1406 edepend[k] = metadata[k]
1408 if mytype == "ebuild":
1409 if "--buildpkgonly" in self.myopts:
1410 edepend["RDEPEND"] = ""
1411 edepend["PDEPEND"] = ""
1412 if not (arg and "--onlydeps" in self.myopts and \
1413 mytype == "ebuild") and \
1414 self.myopts.get("--with-bdeps", "n") == "n" and \
1415 (mytype == "binary" or mybigkey[3] == "nomerge"):
1416 edepend["DEPEND"] = ""
1418 """ We have retrieve the dependency information, now we need to recursively
1419 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1421 mp = tuple(mybigkey)
1424 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1425 myuse=myuse, priority=DepPriority(buildtime=True),
1428 """RDEPEND is soft by definition. However, in order to ensure
1429 correct merge order, we make it a hard dependency. Otherwise, a
1430 build time dependency might not be usable due to it's run time
1431 dependencies not being installed yet.
1433 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1434 myuse=myuse, priority=DepPriority(runtime=True),
1437 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1438 # Post Depend -- Add to the list without a parent, as it depends
1439 # on a package being present AND must be built after that package.
1440 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1441 myuse=myuse, priority=DepPriority(runtime_post=True),
1444 except ValueError, e:
1446 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1447 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1449 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1450 portage.writemsg("\n", noiselevel=-1)
1451 if mytype == "binary":
1453 "!!! This binary package cannot be installed: '%s'\n" % \
1454 mykey, noiselevel=-1)
1455 elif mytype == "ebuild":
1456 myebuild, mylocation = portdb.findname2(mykey)
1457 portage.writemsg("!!! This ebuild cannot be installed: " + \
1458 "'%s'\n" % myebuild, noiselevel=-1)
1459 portage.writemsg("!!! Please notify the package maintainer " + \
1460 "that atoms must be fully-qualified.\n", noiselevel=-1)
1464 def select_files(self,myfiles):
1465 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1467 myroot = self.target_root
1468 portdb = self.trees[myroot]["porttree"].dbapi
1469 bindb = self.trees[myroot]["bintree"].dbapi
1470 pkgsettings = self.pkgsettings[myroot]
1472 def visible(mylist):
1473 matches = portdb.gvisible(portdb.visible(mylist))
1474 return [x for x in mylist \
1475 if x in matches or not portdb.cpv_exists(x)]
1477 ext = os.path.splitext(x)[1]
1479 if not os.path.exists(x):
1481 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1482 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1483 elif os.path.exists(
1484 os.path.join(pkgsettings["PKGDIR"], x)):
1485 x = os.path.join(pkgsettings["PKGDIR"], x)
1487 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1488 print "!!! Please ensure the tbz2 exists as specified.\n"
1489 return 0, myfavorites
1490 mytbz2=portage.xpak.tbz2(x)
1491 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1492 if os.path.realpath(x) != \
1493 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1494 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1495 return 0, myfavorites
1496 if not self.create(["binary", myroot, mykey],
1497 None, "--onlydeps" not in self.myopts,
1498 myuse=mytbz2.getelements("USE"), arg=x):
1499 return (0,myfavorites)
1500 arg_atoms.append((x, "="+mykey))
1501 elif ext==".ebuild":
1502 ebuild_path = portage.util.normalize_path(os.path.abspath(x))
1503 pkgdir = os.path.dirname(ebuild_path)
1504 tree_root = os.path.dirname(os.path.dirname(pkgdir))
1505 cp = pkgdir[len(tree_root)+1:]
1506 e = portage.exception.PackageNotFound(
1507 ("%s is not in a valid portage tree " + \
1508 "hierarchy or does not exist") % x)
1509 if not portage.isvalidatom(cp):
1511 cat = portage.catsplit(cp)[0]
1512 mykey = cat + "/" + os.path.basename(ebuild_path[:-7])
1513 if not portage.isvalidatom("="+mykey):
1515 ebuild_path = portdb.findname(mykey)
1517 if ebuild_path != os.path.join(os.path.realpath(tree_root),
1518 cp, os.path.basename(ebuild_path)):
1519 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1520 return 0, myfavorites
1521 if mykey not in portdb.xmatch(
1522 "match-visible", portage.dep_getkey(mykey)):
1523 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1524 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1525 print colorize("BAD", "*** page for details.")
1526 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1529 raise portage.exception.PackageNotFound(
1530 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1531 if not self.create(["ebuild", myroot, mykey],
1532 None, "--onlydeps" not in self.myopts, arg=x):
1533 return (0,myfavorites)
1534 arg_atoms.append((x, "="+mykey))
1536 if not is_valid_package_atom(x):
1537 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1539 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1540 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1544 if "--usepkg" in self.myopts:
1545 mykey = portage.dep_expand(x, mydb=bindb,
1546 settings=pkgsettings)
1547 if (mykey and not mykey.startswith("null/")) or \
1548 "--usepkgonly" in self.myopts:
1549 arg_atoms.append((x, mykey))
1552 mykey = portage.dep_expand(x,
1553 mydb=portdb, settings=pkgsettings)
1554 arg_atoms.append((x, mykey))
1555 except ValueError, errpkgs:
1556 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1557 print "!!! one of the following fully-qualified ebuild names instead:\n"
1558 for i in errpkgs[0]:
1559 print " " + green(i)
1563 if "--update" in self.myopts:
1564 """Make sure all installed slots are updated when possible. Do this
1565 with --emptytree also, to ensure that all slots are remerged."""
1566 vardb = self.trees[self.target_root]["vartree"].dbapi
1568 for myarg, myatom in arg_atoms:
1569 greedy_atoms.append((myarg, myatom))
1571 for cpv in vardb.match(myatom):
1572 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1575 if "--usepkg" in self.myopts:
1576 mymatches = bindb.match(myatom)
1577 if "--usepkgonly" not in self.myopts:
1578 mymatches = visible(mymatches)
1579 best_pkg = portage.best(mymatches)
1581 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1582 best_pkgs.append(("binary", best_pkg, best_slot))
1583 if "--usepkgonly" not in self.myopts:
1584 best_pkg = portage.best(portdb.match(myatom))
1586 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1587 best_pkgs.append(("ebuild", best_pkg, best_slot))
1589 best_pkg = portage.best([x[1] for x in best_pkgs])
1590 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1591 best_slot = best_pkgs[0][2]
1592 myslots.add(best_slot)
1593 if len(myslots) > 1:
1594 for myslot in myslots:
1595 myslot_atom = "%s:%s" % \
1596 (portage.dep_getkey(myatom), myslot)
1598 if "--usepkgonly" not in self.myopts and \
1599 self.trees[self.target_root][
1600 "porttree"].dbapi.match(myslot_atom):
1602 elif "--usepkg" in self.myopts:
1603 mymatches = bindb.match(myslot_atom)
1604 if "--usepkgonly" not in self.myopts:
1605 mymatches = visible(mymatches)
1609 greedy_atoms.append((myarg, myslot_atom))
1610 arg_atoms = greedy_atoms
1612 oneshot = "--oneshot" in self.myopts or "--onlydeps" in self.myopts
1613 """ These are used inside self.create() in order to ensure packages
1614 that happen to match arguments are not incorrectly marked as nomerge."""
1615 args_set = self._sets["args"]
1616 for myarg, myatom in arg_atoms:
1617 if myatom in args_set:
1619 args_set.add(myatom)
1620 self._set_atoms.add(myatom)
1622 myfavorites.append(myatom)
1623 for myarg, myatom in arg_atoms:
1625 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1626 except portage.exception.MissingSignature, e:
1627 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1628 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1629 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1630 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1631 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1633 except portage.exception.InvalidSignature, e:
1634 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1635 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1636 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1637 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1638 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1640 except SystemExit, e:
1641 raise # Needed else can't exit
1642 except Exception, e:
1643 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1644 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1648 return (0,myfavorites)
1651 if "--usepkgonly" in self.myopts:
1652 for xs in self.digraph.all_nodes():
1653 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1657 print "Missing binary for:",xs[2]
1659 if not self.validate_blockers():
1660 return False, myfavorites
1662 # We're true here unless we are missing binaries.
1663 return (not missing,myfavorites)
1665 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1666 myuse=None, raise_on_missing=False, priority=DepPriority(),
1667 rev_deps=False, parent_arg=None):
1668 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1669 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1670 myparent = the node whose depstring is being passed in
1671 arg = package was specified on the command line, merge even if it's already installed
1672 myuse = USE flags at present
1673 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1674 else continue trying.
1675 return 1 on success, 0 for failure
1678 portdb = self.trees[myroot]["porttree"].dbapi
1679 bindb = self.trees[myroot]["bintree"].dbapi
1680 vardb = self.trees[myroot]["vartree"].dbapi
1681 pkgsettings = self.pkgsettings[myroot]
1683 p_type, p_root, p_key, p_status = myparent
1685 if "--debug" in self.myopts:
1687 print "Parent: ",myparent
1688 print "Depstring:",depstring
1690 print "Reverse:", rev_deps
1691 print "Priority:", priority
1693 #processing dependencies
1694 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1695 dependencies are satisfiable. """
1697 mymerge = [depstring]
1698 pprovided = pkgsettings.pprovideddict.get(
1699 portage.dep_getkey(depstring))
1700 if pprovided and portage.match_from_list(depstring, pprovided):
1704 if myparent and p_status == "nomerge":
1705 portage.dep._dep_check_strict = False
1706 mycheck = portage.dep_check(depstring, None,
1707 pkgsettings, myuse=myuse,
1708 use_binaries=("--usepkgonly" in self.myopts),
1709 myroot=myroot, trees=self.trees)
1711 portage.dep._dep_check_strict = True
1715 show_invalid_depstring_notice(
1716 myparent, depstring, mycheck[1])
1718 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1720 mymerge = mycheck[1]
1722 if not mymerge and arg:
1723 # A provided package has been specified on the command line. The
1724 # package will not be merged and a warning will be displayed.
1725 if depstring in self._set_atoms:
1726 self._pprovided_args.append((arg, depstring))
1729 # The parent is added after it's own dep_check call so that it
1730 # isn't allowed to satisfy a direct bootstrap dependency on itself
1731 # via an old-style virtual. This isn't a problem with new-style
1732 # virtuals, which are preferenced in dep_zapdeps by looking only at
1733 # the depstring, vdb, and available packages.
1735 p_type, p_root, p_key, p_status = myparent
1736 if p_status == "merge":
1737 # Update old-style virtuals if this package provides any.
1738 # These are needed for dep_virtual calls inside dep_check.
1739 p_db = self.trees[p_root][self.pkg_tree_map[p_type]].dbapi
1741 self.pkgsettings[p_root].setinst(p_key, p_db)
1742 except portage.exception.InvalidDependString, e:
1743 provide = p_db.aux_get(p_key, ["PROVIDE"])[0]
1744 show_invalid_depstring_notice(myparent, provide, str(e))
1748 if "--debug" in self.myopts:
1749 print "Candidates:",mymerge
1753 selected_pkg = ["blocks", myroot, x[1:], None]
1755 #We are not processing a blocker but a normal dependency
1757 """In some cases, dep_check will return deps that shouldn't
1758 be proccessed any further, so they are identified and
1760 if "empty" not in self.myparams and \
1761 "deep" not in self.myparams and \
1762 not ("--update" in self.myopts and parent_arg) and \
1766 # List of acceptable packages, ordered by type preference.
1767 matched_packages = []
1768 myeb_matches = portdb.xmatch("match-visible", x)
1770 if "--usepkgonly" not in self.myopts:
1771 myeb = portage.best(myeb_matches)
1774 if "--usepkg" in self.myopts:
1775 # The next line assumes the binarytree has been populated.
1776 # XXX: Need to work out how we use the binary tree with roots.
1777 myeb_pkg_matches = bindb.match(x)
1778 if "--usepkgonly" not in self.myopts:
1779 # Remove any binary package entries that are masked in the portage tree (#55871)
1780 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1781 if pkg in myeb_matches or \
1782 not portdb.cpv_exists(pkg)]
1783 if myeb_pkg_matches:
1784 myeb_pkg = portage.best(myeb_pkg_matches)
1787 ("--newuse" in self.myopts or \
1788 "--reinstall" in self.myopts):
1789 iuses = set(filter_iuse_defaults(
1790 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1791 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1793 if "--usepkgonly" not in self.myopts and myeb:
1796 pkgsettings.setcpv(myeb, mydb=mydb)
1798 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1799 now_use = pkgsettings["USE"].split()
1800 forced_flags = set()
1801 forced_flags.update(pkgsettings.useforce)
1802 forced_flags.update(pkgsettings.usemask)
1804 if "--usepkgonly" not in self.myopts and myeb:
1805 cur_iuse = set(filter_iuse_defaults(
1806 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1807 if self._reinstall_for_flags(
1808 forced_flags, old_use, iuses, now_use, cur_iuse):
1812 self.trees[myroot]["bintree"].dbapi.aux_get(
1813 myeb_pkg, ["USE"])[0].split()
1814 matched_packages.append(
1815 ["binary", myroot, myeb_pkg, binpkguseflags])
1817 if "--usepkgonly" not in self.myopts and myeb_matches:
1818 matched_packages.append(
1819 ["ebuild", myroot, myeb, None])
1821 if not matched_packages and \
1822 not (arg and "selective" not in self.myparams):
1823 """Fall back to the installed package database. This is a
1824 last resort because the metadata tends to diverge from that
1825 of the ebuild in the tree."""
1826 myeb_inst_matches = vardb.match(x)
1827 if "--usepkgonly" not in self.myopts:
1828 """ TODO: Improve masking check for installed and
1829 binary packages. bug #149816"""
1830 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1831 if not portdb.cpv_exists(pkg)]
1833 if myeb_inst_matches:
1834 myeb_inst = portage.best(myeb_inst_matches)
1836 binpkguseflags = vardb.aux_get(
1837 myeb_inst, ["USE"])[0].split()
1838 matched_packages.append(
1839 ["installed", myroot, myeb_inst, binpkguseflags])
1841 if not matched_packages:
1842 if raise_on_missing:
1849 xfrom = '(dependency required by '+ \
1850 green('"%s"' % myparent[2]) + \
1851 red(' [%s]' % myparent[0]) + ')'
1852 alleb = portdb.xmatch("match-all", x)
1854 if "--usepkgonly" not in self.myopts:
1855 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1856 print "!!! One of the following masked packages is required to complete your request:"
1860 mreasons = portage.getmaskingstatus(p,
1861 settings=pkgsettings, portdb=portdb)
1862 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1863 if "package.mask" in mreasons:
1864 comment, filename = \
1865 portage.getmaskingreason(p,
1866 settings=pkgsettings, portdb=portdb,
1867 return_location=True)
1868 if comment and comment != oldcomment:
1871 oldcomment = comment
1873 licenses = portdb.aux_get(p, ["LICENSE"])[0]
1875 # Corruption will have been reported above.
1879 pkgsettings.setcpv(p, mydb=portdb)
1880 uselist = pkgsettings.get("USE", "").split()
1881 missing_licenses = []
1883 missing_licenses = \
1884 pkgsettings.getMissingLicenses(
1885 licenses, p, uselist)
1886 except portage.exception.InvalidDependString:
1887 # This will have already been reported
1888 # above via mreasons.
1890 for l in missing_licenses:
1891 l_path = portdb.findLicensePath(l)
1892 if l in shown_licenses:
1894 msg = ("A copy of the '%s' license" + \
1895 " is located at '%s'.") % (l, l_path)
1898 shown_licenses.append(l)
1900 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1901 print "refer to the Gentoo Handbook."
1903 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1904 print "!!! Either add a suitable binary package or compile from an ebuild."
1906 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1912 if "--debug" in self.myopts:
1913 for pkg in matched_packages:
1914 print (pkg[0] + ":").rjust(10), pkg[2]
1916 if len(matched_packages) > 1:
1917 bestmatch = portage.best(
1918 [pkg[2] for pkg in matched_packages])
1919 matched_packages = [pkg for pkg in matched_packages \
1920 if pkg[2] == bestmatch]
1922 # ordered by type preference ("ebuild" type is the last resort)
1923 selected_pkg = matched_packages[0]
1924 pkgtype, myroot, mycpv, myuse = selected_pkg
1925 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1926 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1927 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1928 existing_node = self._slot_node_map[myroot].get(
1931 e_type, myroot, e_cpv, e_status = existing_node
1932 if portage.match_from_list(x, [e_cpv]):
1933 # The existing node can be reused.
1934 selected_pkg = [e_type, myroot, e_cpv,
1935 self.useFlags[myroot][e_cpv]]
1938 #we are a dependency, so we want to be unconditionally added
1939 mypriority = priority.copy()
1941 mypriority.satisfied = True
1942 if not self.create(selected_pkg[0:3], myparent,
1943 myuse=selected_pkg[-1], priority=mypriority,
1944 rev_dep=rev_deps, arg=arg):
1947 #if mysource is not set, then we are a command-line dependency and should not be added
1948 #if --onlydeps is specified.
1949 if not self.create(selected_pkg[0:3], myparent,
1950 addme=("--onlydeps" not in self.myopts),
1951 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1954 if "--debug" in self.myopts:
1955 print "Exiting...",myparent
1958 def validate_blockers(self):
1959 """Remove any blockers from the digraph that do not match any of the
1960 packages within the graph. If necessary, create hard deps to ensure
1961 correct merge order such that mutually blocking packages are never
1962 installed simultaneously."""
1964 if "--buildpkgonly" in self.myopts or \
1965 "--nodeps" in self.myopts:
1969 for myroot in self.trees:
1971 modified_slots[myroot] = myslots
1972 final_db = self.mydbapi[myroot]
1973 slot_node_map = self._slot_node_map[myroot]
1974 for slot_atom, mynode in slot_node_map.iteritems():
1975 mytype, myroot, mycpv, mystatus = mynode
1976 if mystatus == "merge":
1977 myslots[slot_atom] = mycpv
1979 #if "deep" in self.myparams:
1981 # Pull in blockers from all installed packages that haven't already
1982 # been pulled into the depgraph. This is not enabled by default
1983 # due to the performance penalty that is incurred by all the
1984 # additional dep_check calls that are required.
1986 # Optimization hack for dep_check calls that minimizes the
1987 # available matches by replacing the portdb with a fakedbapi
1989 class FakePortageTree(object):
1990 def __init__(self, mydb):
1992 dep_check_trees = {}
1993 for myroot in self.trees:
1994 dep_check_trees[myroot] = self.trees[myroot].copy()
1995 dep_check_trees[myroot]["porttree"] = \
1996 FakePortageTree(self.mydbapi[myroot])
1998 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1999 for myroot in self.trees:
2000 pkg_node_map = self.pkg_node_map[myroot]
2001 vardb = self.trees[myroot]["vartree"].dbapi
2002 portdb = self.trees[myroot]["porttree"].dbapi
2003 pkgsettings = self.pkgsettings[myroot]
2004 final_db = self.mydbapi[myroot]
2005 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
2006 blocker_cache = BlockerCache(myroot, vardb)
2007 for pkg in cpv_all_installed:
2008 blocker_atoms = None
2009 matching_node = pkg_node_map.get(pkg, None)
2010 if matching_node and \
2011 matching_node[3] == "nomerge":
2013 # If this node has any blockers, create a "nomerge"
2014 # node for it so that they can be enforced.
2015 self.spinner.update()
2016 blocker_data = blocker_cache.get(pkg)
2018 blocker_atoms = blocker_data.atoms
2020 dep_vals = vardb.aux_get(pkg, dep_keys)
2021 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
2022 depstr = " ".join(dep_vals)
2023 # It is crucial to pass in final_db here in order to
2024 # optimize dep_check calls by eliminating atoms via
2025 # dep_wordreduce and dep_eval calls.
2027 portage.dep._dep_check_strict = False
2029 success, atoms = portage.dep_check(depstr,
2030 final_db, pkgsettings, myuse=myuse,
2031 trees=dep_check_trees, myroot=myroot)
2032 except Exception, e:
2033 if isinstance(e, SystemExit):
2035 # This is helpful, for example, if a ValueError
2036 # is thrown from cpv_expand due to multiple
2037 # matches (this can happen if an atom lacks a
2039 show_invalid_depstring_notice(
2040 ("installed", myroot, pkg, "nomerge"),
2045 portage.dep._dep_check_strict = True
2047 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
2048 vardb.aux_get(pkg, ["SLOT"])[0])
2049 if slot_atom in modified_slots[myroot]:
2050 # This package is being replaced anyway, so
2051 # ignore invalid dependencies so as not to
2052 # annoy the user too much (otherwise they'd be
2053 # forced to manually unmerge it first).
2055 show_invalid_depstring_notice(
2056 ("installed", myroot, pkg, "nomerge"),
2059 blocker_atoms = [myatom for myatom in atoms \
2060 if myatom.startswith("!")]
2061 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
2062 blocker_cache[pkg] = \
2063 blocker_cache.BlockerData(counter, blocker_atoms)
2065 # Don't store this parent in pkg_node_map, because it's
2066 # not needed there and it might overwrite a "merge"
2067 # node with the same cpv.
2068 myparent = ("installed", myroot, pkg, "nomerge")
2069 for myatom in blocker_atoms:
2070 blocker = ("blocks", myroot, myatom[1:])
2072 self.blocker_parents.get(blocker, None)
2075 self.blocker_parents[blocker] = myparents
2076 myparents.add(myparent)
2077 blocker_cache.flush()
2080 for blocker in self.blocker_parents.keys():
2081 mytype, myroot, mydep = blocker
2082 initial_db = self.trees[myroot]["vartree"].dbapi
2083 final_db = self.mydbapi[myroot]
2084 blocked_initial = initial_db.match(mydep)
2085 blocked_final = final_db.match(mydep)
2086 if not blocked_initial and not blocked_final:
2087 del self.blocker_parents[blocker]
2089 blocked_slots_initial = {}
2090 blocked_slots_final = {}
2091 for cpv in blocked_initial:
2092 blocked_slots_initial[cpv] = \
2093 "%s:%s" % (portage.dep_getkey(cpv),
2094 initial_db.aux_get(cpv, ["SLOT"])[0])
2095 for cpv in blocked_final:
2096 blocked_slots_final[cpv] = \
2097 "%s:%s" % (portage.dep_getkey(cpv),
2098 final_db.aux_get(cpv, ["SLOT"])[0])
2099 for parent in list(self.blocker_parents[blocker]):
2100 ptype, proot, pcpv, pstatus = parent
2101 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
2102 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
2103 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
2104 parent_static = pslot_atom not in modified_slots[proot]
2105 unresolved_blocks = False
2106 depends_on_order = set()
2107 for cpv in blocked_initial:
2108 slot_atom = blocked_slots_initial[cpv]
2109 if slot_atom == pslot_atom:
2110 # TODO: Support blocks within slots in cases where it
2111 # might make sense. For example, a new version might
2112 # require that the old version be uninstalled at build
2115 if parent_static and \
2116 slot_atom not in modified_slots[myroot]:
2117 # This blocker will be handled the next time that a
2118 # merge of either package is triggered.
2120 if pstatus == "merge" and \
2121 slot_atom in modified_slots[myroot]:
2122 replacement = final_db.match(slot_atom)
2124 if not portage.match_from_list(mydep, replacement):
2125 # Apparently a replacement may be able to
2126 # invalidate this block.
2127 replacement_node = \
2128 self.pkg_node_map[proot][replacement[0]]
2129 depends_on_order.add((replacement_node, parent))
2131 # None of the above blocker resolutions techniques apply,
2132 # so apparently this one is unresolvable.
2133 unresolved_blocks = True
2134 for cpv in blocked_final:
2135 slot_atom = blocked_slots_final[cpv]
2136 if slot_atom == pslot_atom:
2137 # TODO: Support blocks within slots.
2139 if parent_static and \
2140 slot_atom not in modified_slots[myroot]:
2141 # This blocker will be handled the next time that a
2142 # merge of either package is triggered.
2144 if not parent_static and pstatus == "nomerge" and \
2145 slot_atom in modified_slots[myroot]:
2146 replacement = final_db.match(pslot_atom)
2148 replacement_node = \
2149 self.pkg_node_map[proot][replacement[0]]
2150 if replacement_node not in \
2151 self.blocker_parents[blocker]:
2152 # Apparently a replacement may be able to
2153 # invalidate this block.
2154 blocked_node = self.pkg_node_map[proot][cpv]
2155 depends_on_order.add(
2156 (replacement_node, blocked_node))
2158 # None of the above blocker resolutions techniques apply,
2159 # so apparently this one is unresolvable.
2160 unresolved_blocks = True
2161 if not unresolved_blocks and depends_on_order:
2162 for node, pnode in depends_on_order:
2163 # Enforce correct merge order with a hard dep.
2164 self.digraph.addnode(node, pnode,
2165 priority=DepPriority(buildtime=True))
2166 # Count references to this blocker so that it can be
2167 # invalidated after nodes referencing it have been
2169 self.blocker_digraph.addnode(node, blocker)
2170 if not unresolved_blocks and not depends_on_order:
2171 self.blocker_parents[blocker].remove(parent)
2172 if unresolved_blocks:
2173 self._unresolved_blocker_parents.setdefault(
2174 blocker, set()).add(parent)
2175 if not self.blocker_parents[blocker]:
2176 del self.blocker_parents[blocker]
2177 # Validate blockers that depend on merge order.
2178 if not self.blocker_digraph.empty():
2180 if self._slot_collision_info:
2181 # The user is only notified of a slot collision if there are no
2182 # unresolvable blocks.
2183 for x in self.altlist():
2184 if x[0] == "blocks":
2186 self._show_slot_collision_notice(self._slot_collision_info[0])
2187 if not self._accept_collisions():
2191 def _accept_collisions(self):
2193 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
2194 if x in self.myopts:
2199 def _merge_order_bias(self, mygraph):
2200 """Order nodes from highest to lowest overall reference count for
2201 optimal leaf node selection."""
2203 for node in mygraph.order:
2204 node_info[node] = len(mygraph.parent_nodes(node))
2205 def cmp_merge_preference(node1, node2):
2206 return node_info[node2] - node_info[node1]
2207 mygraph.order.sort(cmp_merge_preference)
2209 def altlist(self, reversed=False):
2210 if reversed in self._altlist_cache:
2211 return self._altlist_cache[reversed][:]
2213 retlist = self.altlist()
2215 self._altlist_cache[reversed] = retlist[:]
2217 mygraph=self.digraph.copy()
2218 for node in mygraph.order[:]:
2219 if node[-1] == "nomerge":
2220 mygraph.remove(node)
2221 self._merge_order_bias(mygraph)
2222 myblockers = self.blocker_digraph.copy()
2224 circular_blocks = False
2228 get_nodes = mygraph.root_nodes
2230 get_nodes = mygraph.leaf_nodes
2231 for cpv, node in self.pkg_node_map["/"].iteritems():
2232 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
2233 asap_nodes.append(node)
2235 ignore_priority_soft_range = [None]
2236 ignore_priority_soft_range.extend(
2237 xrange(DepPriority.MIN, DepPriority.SOFT + 1))
2238 tree_mode = "--tree" in self.myopts
2239 # Tracks whether or not the current iteration should prefer asap_nodes
2240 # if available. This is set to False when the previous iteration
2241 # failed to select any nodes. It is reset whenever nodes are
2242 # successfully selected.
2244 while not mygraph.empty():
2245 selected_nodes = None
2246 if prefer_asap and asap_nodes:
2247 """ASAP nodes are merged before their soft deps."""
2248 asap_nodes = [node for node in asap_nodes \
2249 if mygraph.contains(node)]
2250 for node in asap_nodes:
2251 if not mygraph.child_nodes(node,
2252 ignore_priority=DepPriority.SOFT):
2253 selected_nodes = [node]
2254 asap_nodes.remove(node)
2256 if not selected_nodes and \
2257 not (prefer_asap and asap_nodes):
2258 for ignore_priority in ignore_priority_soft_range:
2259 nodes = get_nodes(ignore_priority=ignore_priority)
2263 if ignore_priority is None and not tree_mode:
2264 # Greedily pop all of these nodes since no relationship
2265 # has been ignored. This optimization destroys --tree
2266 # output, so it's disabled in reversed mode.
2267 selected_nodes = nodes
2269 # For optimal merge order:
2270 # * Only pop one node.
2271 # * Removing a root node (node without a parent)
2272 # will not produce a leaf node, so avoid it.
2274 if mygraph.parent_nodes(node):
2275 # found a non-root node
2276 selected_nodes = [node]
2278 if not selected_nodes:
2279 # settle for a root node
2280 selected_nodes = [nodes[0]]
2281 if not selected_nodes:
2282 nodes = get_nodes(ignore_priority=DepPriority.MEDIUM)
2284 """Recursively gather a group of nodes that RDEPEND on
2285 eachother. This ensures that they are merged as a group
2286 and get their RDEPENDs satisfied as soon as possible."""
2287 def gather_deps(ignore_priority,
2288 mergeable_nodes, selected_nodes, node):
2289 if node in selected_nodes:
2291 if node not in mergeable_nodes:
2293 selected_nodes.add(node)
2294 for child in mygraph.child_nodes(node,
2295 ignore_priority=ignore_priority):
2296 if not gather_deps(ignore_priority,
2297 mergeable_nodes, selected_nodes, child):
2300 mergeable_nodes = set(nodes)
2301 if prefer_asap and asap_nodes:
2303 for ignore_priority in xrange(DepPriority.SOFT,
2304 DepPriority.MEDIUM_SOFT + 1):
2306 selected_nodes = set()
2307 if gather_deps(ignore_priority,
2308 mergeable_nodes, selected_nodes, node):
2311 selected_nodes = None
2315 if prefer_asap and asap_nodes and not selected_nodes:
2316 # We failed to find any asap nodes to merge, so ignore
2317 # them for the next iteration.
2321 if selected_nodes and ignore_priority > DepPriority.SOFT:
2322 # Try to merge ignored medium deps as soon as possible.
2323 for node in selected_nodes:
2324 children = set(mygraph.child_nodes(node))
2325 soft = children.difference(
2326 mygraph.child_nodes(node,
2327 ignore_priority=DepPriority.SOFT))
2328 medium_soft = children.difference(
2329 mygraph.child_nodes(node,
2330 ignore_priority=DepPriority.MEDIUM_SOFT))
2331 medium_soft.difference_update(soft)
2332 for child in medium_soft:
2333 if child in selected_nodes:
2335 if child in asap_nodes:
2337 # TODO: Try harder to make these nodes get
2338 # merged absolutely as soon as possible.
2339 asap_nodes.append(child)
2341 if not selected_nodes:
2342 if not myblockers.is_empty():
2343 """A blocker couldn't be circumnavigated while keeping all
2344 dependencies satisfied. The user will have to resolve this
2345 manually. This is a panic condition and thus the order
2346 doesn't really matter, so just pop a random node in order
2347 to avoid a circular dependency panic if possible."""
2348 if not circular_blocks:
2349 circular_blocks = True
2350 blocker_deps = myblockers.leaf_nodes()
2352 # Some of these nodes might have already been selected
2353 # by the normal node selection process after the
2354 # circular_blocks flag has been set. Therefore, we
2355 # have to verify that they're still in the graph so
2356 # that they're not selected more than once.
2357 node = blocker_deps.pop()
2358 if mygraph.contains(node):
2359 selected_nodes = [node]
2362 if not selected_nodes:
2363 # No leaf nodes are available, so we have a circular
2364 # dependency panic situation. Reduce the noise level to a
2365 # minimum via repeated elimination of root nodes since they
2366 # have no parents and thus can not be part of a cycle.
2368 root_nodes = mygraph.root_nodes(
2369 ignore_priority=DepPriority.SOFT)
2372 for node in root_nodes:
2373 mygraph.remove(node)
2374 # Display the USE flags that are enabled on nodes that are part
2375 # of dependency cycles in case that helps the user decide to
2376 # disable some of them.
2378 tempgraph = mygraph.copy()
2379 while not tempgraph.empty():
2380 nodes = tempgraph.leaf_nodes()
2382 node = tempgraph.order[0]
2385 display_order.append(list(node))
2386 tempgraph.remove(node)
2387 display_order.reverse()
2388 self.myopts.pop("--quiet", None)
2389 self.myopts.pop("--verbose", None)
2390 self.myopts["--tree"] = True
2391 self.display(display_order)
2392 print "!!! Error: circular dependencies:"
2394 mygraph.debug_print()
2396 print "!!! Note that circular dependencies can often be avoided by temporarily"
2397 print "!!! disabling USE flags that trigger optional dependencies."
2400 # At this point, we've succeeded in selecting one or more nodes, so
2401 # it's now safe to reset the prefer_asap to it's default state.
2404 for node in selected_nodes:
2405 retlist.append(list(node))
2406 mygraph.remove(node)
2407 if not reversed and not circular_blocks and myblockers.contains(node):
2408 """This node may have invalidated one or more blockers."""
2409 myblockers.remove(node)
2410 for blocker in myblockers.root_nodes():
2411 if not myblockers.child_nodes(blocker):
2412 myblockers.remove(blocker)
2414 self._unresolved_blocker_parents.get(blocker)
2416 self.blocker_parents[blocker] = unresolved
2418 del self.blocker_parents[blocker]
2421 """Blocker validation does not work with reverse mode,
2422 so self.altlist() should first be called with reverse disabled
2423 so that blockers are properly validated."""
2424 self.blocker_digraph = myblockers
2426 """ Add any unresolved blocks so that they can be displayed."""
2427 for blocker in self.blocker_parents:
2428 retlist.append(list(blocker))
2429 self._altlist_cache[reversed] = retlist[:]
2432 def xcreate(self,mode="system"):
2433 vardb = self.trees[self.target_root]["vartree"].dbapi
2434 portdb = self.trees[self.target_root]["porttree"].dbapi
2435 bindb = self.trees[self.target_root]["bintree"].dbapi
2436 def visible(mylist):
2437 matches = portdb.gvisible(portdb.visible(mylist))
2438 return [x for x in mylist \
2439 if x in matches or not portdb.cpv_exists(x)]
2440 world_problems = False
2442 root_config = self.roots[self.target_root]
2443 world_set = root_config.sets["world"]
2444 system_set = root_config.sets["system"]
2445 mylist = list(system_set)
2446 self._sets["system"] = system_set
2448 self._sets["world"] = world_set
2450 if not portage.isvalidatom(x):
2451 world_problems = True
2453 elif not vardb.match(x):
2454 world_problems = True
2456 if "--usepkgonly" not in self.myopts and \
2459 elif "--usepkg" in self.myopts:
2460 mymatches = bindb.match(x)
2461 if "--usepkgonly" not in self.myopts:
2462 mymatches = visible(mymatches)
2471 mykey = portage.dep_getkey(atom)
2473 newlist.append(atom)
2474 if mode == "system" or atom not in world_set:
2475 # only world is greedy for slots, not system
2477 # Make sure all installed slots are updated when possible.
2478 # Do this with --emptytree also, to ensure that all slots are
2481 for cpv in vardb.match(mykey):
2482 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2485 if "--usepkg" in self.myopts:
2486 mymatches = bindb.match(atom)
2487 if "--usepkgonly" not in self.myopts:
2488 mymatches = visible(mymatches)
2489 best_pkg = portage.best(mymatches)
2491 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2492 best_pkgs.append(("binary", best_pkg, best_slot))
2493 if "--usepkgonly" not in self.myopts:
2494 best_pkg = portage.best(portdb.match(atom))
2496 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2497 best_pkgs.append(("ebuild", best_pkg, best_slot))
2499 best_pkg = portage.best([x[1] for x in best_pkgs])
2500 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2501 best_slot = best_pkgs[0][2]
2502 myslots.add(best_slot)
2503 if len(myslots) > 1:
2504 for myslot in myslots:
2505 myslot_atom = "%s:%s" % (mykey, myslot)
2507 if "--usepkgonly" not in self.myopts and \
2508 self.trees[self.target_root][
2509 "porttree"].dbapi.match(myslot_atom):
2511 elif "--usepkg" in self.myopts:
2512 mymatches = bindb.match(myslot_atom)
2513 if "--usepkgonly" not in self.myopts:
2514 mymatches = visible(mymatches)
2518 newlist.append(myslot_atom)
2521 for myatom in mylist:
2522 self._set_atoms.add(myatom)
2525 for mydep in mylist:
2527 if not self.select_dep(
2528 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2529 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2532 missing_atoms.append(mydep)
2534 if not self.validate_blockers():
2538 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2539 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2542 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2543 " Ebuilds for the following packages are either all"
2544 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2545 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2549 def display(self, mylist, favorites=[], verbosity=None):
2550 if verbosity is None:
2551 verbosity = ("--quiet" in self.myopts and 1 or \
2552 "--verbose" in self.myopts and 3 or 2)
2553 if "--resume" in self.myopts and favorites:
2554 self._sets["args"].update(favorites)
2555 favorites_set = AtomSet()
2556 favorites_set.update(favorites)
2561 counters = PackageCounters()
2563 if verbosity == 1 and "--verbose" not in self.myopts:
2564 def create_use_string(*args):
2567 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2569 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2570 alphabetical=("--alphabetical" in self.myopts)):
2578 cur_iuse = set(cur_iuse)
2579 enabled_flags = cur_iuse.intersection(cur_use)
2580 removed_iuse = set(old_iuse).difference(cur_iuse)
2581 any_iuse = cur_iuse.union(old_iuse)
2582 any_iuse = list(any_iuse)
2584 for flag in any_iuse:
2587 if flag in enabled_flags:
2589 if is_new or flag in old_use and all_flags:
2590 flag_str = red(flag)
2591 elif flag not in old_iuse:
2592 flag_str = yellow(flag) + "%*"
2593 elif flag not in old_use:
2594 flag_str = green(flag) + "*"
2595 elif flag in removed_iuse:
2597 flag_str = yellow("-" + flag) + "%"
2600 flag_str = "(" + flag_str + ")"
2601 removed.append(flag_str)
2604 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2605 flag_str = blue("-" + flag)
2606 elif flag not in old_iuse:
2607 flag_str = yellow("-" + flag)
2608 if flag not in iuse_forced:
2610 elif flag in old_use:
2611 flag_str = green("-" + flag) + "*"
2613 if flag in iuse_forced:
2614 flag_str = "(" + flag_str + ")"
2616 enabled.append(flag_str)
2618 disabled.append(flag_str)
2621 ret = " ".join(enabled)
2623 ret = " ".join(enabled + disabled + removed)
2625 ret = '%s="%s" ' % (name, ret)
2629 # FIXME: account for the possibility of different overlays in
2630 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2631 overlays = self.settings["PORTDIR_OVERLAY"].split()
2632 overlays_real = [os.path.realpath(t) \
2633 for t in self.settings["PORTDIR_OVERLAY"].split()]
2637 mygraph = self._parent_child_digraph
2642 if "blocks" == x[0]:
2643 display_list.append((x, 0, True))
2645 graph_key = tuple(x)
2646 if "--tree" in self.myopts:
2647 depth = len(tree_nodes)
2648 while depth and graph_key not in \
2649 mygraph.child_nodes(tree_nodes[depth-1]):
2652 tree_nodes = tree_nodes[:depth]
2653 tree_nodes.append(graph_key)
2654 display_list.append((x, depth, True))
2655 shown_edges.add((graph_key, tree_nodes[depth-1]))
2657 traversed_nodes = set() # prevent endless circles
2658 traversed_nodes.add(graph_key)
2659 def add_parents(current_node, ordered):
2661 # Do not traverse to parents if this node is an
2662 # an argument or a direct member of a set that has
2663 # been specified as an argument (system or world).
2664 if current_node not in self._set_nodes:
2665 parent_nodes = mygraph.parent_nodes(current_node)
2667 child_nodes = set(mygraph.child_nodes(current_node))
2668 selected_parent = None
2669 # First, try to avoid a direct cycle.
2670 for node in parent_nodes:
2671 if node not in traversed_nodes and \
2672 node not in child_nodes:
2673 edge = (current_node, node)
2674 if edge in shown_edges:
2676 selected_parent = node
2678 if not selected_parent:
2679 # A direct cycle is unavoidable.
2680 for node in parent_nodes:
2681 if node not in traversed_nodes:
2682 edge = (current_node, node)
2683 if edge in shown_edges:
2685 selected_parent = node
2688 shown_edges.add((current_node, selected_parent))
2689 traversed_nodes.add(selected_parent)
2690 add_parents(selected_parent, False)
2691 display_list.append((list(current_node),
2692 len(tree_nodes), ordered))
2693 tree_nodes.append(current_node)
2695 add_parents(graph_key, True)
2697 display_list.append((x, depth, True))
2698 mylist = display_list
2700 last_merge_depth = 0
2701 for i in xrange(len(mylist)-1,-1,-1):
2702 graph_key, depth, ordered = mylist[i]
2703 if not ordered and depth == 0 and i > 0 \
2704 and graph_key == mylist[i-1][0] and \
2705 mylist[i-1][1] == 0:
2706 # An ordered node got a consecutive duplicate when the tree was
2710 if "blocks" == graph_key[0]:
2712 if ordered and graph_key[-1] != "nomerge":
2713 last_merge_depth = depth
2715 if depth >= last_merge_depth or \
2716 i < len(mylist) - 1 and \
2717 depth >= mylist[i+1][1]:
2720 from portage import flatten
2721 from portage.dep import use_reduce, paren_reduce
2722 display_overlays=False
2723 # files to fetch list - avoids counting a same file twice
2724 # in size display (verbose mode)
2727 for mylist_index in xrange(len(mylist)):
2728 x, depth, ordered = mylist[mylist_index]
2732 portdb = self.trees[myroot]["porttree"].dbapi
2733 bindb = self.trees[myroot]["bintree"].dbapi
2734 vardb = self.trees[myroot]["vartree"].dbapi
2735 vartree = self.trees[myroot]["vartree"]
2736 pkgsettings = self.pkgsettings[myroot]
2741 addl=""+red("B")+" "+fetch+" "
2743 counters.blocks += 1
2744 resolved = portage.key_expand(
2745 pkg_key, mydb=vardb, settings=pkgsettings)
2746 if "--columns" in self.myopts and "--quiet" in self.myopts:
2747 addl = addl + " " + red(resolved)
2749 addl = "[blocks " + addl + "] " + red(resolved)
2750 block_parents = self.blocker_parents[tuple(x)]
2751 block_parents = set([pnode[2] for pnode in block_parents])
2752 block_parents = ", ".join(block_parents)
2754 addl += bad(" (\"%s\" is blocking %s)") % \
2755 (pkg_key, block_parents)
2757 addl += bad(" (is blocking %s)") % block_parents
2758 blockers.append(addl)
2760 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2762 pkg_merge = ordered and pkg_status != "nomerge"
2763 binary_package = True
2764 if "ebuild" == pkg_type:
2765 if "merge" == x[3] or \
2766 not vartree.dbapi.cpv_exists(pkg_key):
2767 """An ebuild "merge" node or a --onlydeps "nomerge"
2769 binary_package = False
2770 pkgsettings.setcpv(pkg_key, mydb=portdb)
2771 if pkg_key not in self.useFlags[myroot]:
2772 self.useFlags[myroot][pkg_key] = \
2773 pkgsettings["USE"].split()
2775 # An ebuild "nomerge" node, so USE come from the vardb.
2776 mydbapi = vartree.dbapi
2777 # reuse cached metadata from when the depgraph was built
2778 if "--resume" in self.myopts:
2779 # Populate the fakedb with relevant metadata, just like
2780 # would have happened when the depgraph was originally
2782 metadata = dict(izip(self._mydbapi_keys,
2783 mydbapi.aux_get(pkg_key, self._mydbapi_keys)))
2784 self.mydbapi[myroot].cpv_inject(pkg_key, metadata=metadata)
2786 metadata = dict(izip(self._mydbapi_keys,
2787 self.mydbapi[myroot].aux_get(
2788 pkg_key, self._mydbapi_keys)))
2789 mydbapi = self.mydbapi[myroot] # use the cached metadata
2790 if pkg_key not in self.useFlags[myroot]:
2791 """If this is a --resume then the USE flags need to be
2792 fetched from the appropriate locations here."""
2793 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2794 pkg_key, ["USE"])[0].split()
2797 restrict = flatten(use_reduce(paren_reduce(
2798 mydbapi.aux_get(pkg_key, ["RESTRICT"])[0]),
2799 uselist=self.useFlags[myroot][pkg_key]))
2800 except portage.exception.InvalidDependString, e:
2801 if pkg_status != "nomerge":
2802 restrict = mydbapi.aux_get(pkg_key, ["RESTRICT"])[0]
2803 show_invalid_depstring_notice(x, restrict, str(e))
2807 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2808 "fetch" in restrict:
2811 counters.restrict_fetch += 1
2812 if portdb.fetch_check(
2813 pkg_key, self.useFlags[myroot][pkg_key]):
2816 counters.restrict_fetch_satisfied += 1
2818 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2819 #param is used for -u, where you still *do* want to see when something is being upgraded.
2821 if vardb.cpv_exists(pkg_key):
2822 addl=" "+yellow("R")+fetch+" "
2823 if x[3] != "nomerge":
2825 counters.reinst += 1
2826 elif vardb.match(portage.dep_getkey(pkg_key)):
2827 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2828 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2829 portage.pkgsplit(x[2])[0])
2830 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2831 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2833 myoldbest=portage.best(myinslotlist)
2835 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2837 addl+=turquoise("U")+blue("D")
2839 counters.downgrades += 1
2842 addl+=turquoise("U")+" "
2844 counters.upgrades += 1
2846 # New slot, mark it new.
2847 addl=" "+green("NS")+fetch+" "
2849 counters.newslot += 1
2851 if "--changelog" in self.myopts:
2852 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2853 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2854 inst_matches = vardb.match(slot_atom)
2856 changelogs.extend(self.calc_changelog(
2857 portdb.findname(pkg_key),
2858 inst_matches[0], pkg_key))
2860 addl=" "+green("N")+" "+fetch+" "
2866 if pkg_key in self.useFlags[myroot]:
2868 cur_iuse = list(filter_iuse_defaults(
2869 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2871 forced_flags = set()
2872 if not binary_package:
2873 forced_flags.update(pkgsettings.useforce)
2874 forced_flags.update(pkgsettings.usemask)
2876 cur_iuse = portage.unique_array(cur_iuse)
2878 cur_use = self.useFlags[myroot][pkg_key]
2879 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2885 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2886 old_iuse, old_use = \
2887 self.trees[x[1]]["vartree"].dbapi.aux_get(
2888 pkg, ["IUSE", "USE"])
2889 old_iuse = list(set(
2890 filter_iuse_defaults(old_iuse.split())))
2892 old_use = old_use.split()
2899 old_use = [flag for flag in old_use if flag in old_iuse]
2901 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2903 use_expand.reverse()
2904 use_expand_hidden = \
2905 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2907 def map_to_use_expand(myvals, forcedFlags=False):
2910 for exp in use_expand:
2913 for val in myvals[:]:
2914 if val.startswith(exp.lower()+"_"):
2915 if val in forced_flags:
2916 forced[exp].add(val[len(exp)+1:])
2917 ret[exp].append(val[len(exp)+1:])
2920 forced["USE"] = [val for val in myvals \
2921 if val in forced_flags]
2922 for exp in use_expand_hidden:
2929 cur_iuse_map, iuse_forced = \
2930 map_to_use_expand(cur_iuse, forcedFlags=True)
2931 cur_use_map = map_to_use_expand(cur_use)
2932 old_iuse_map = map_to_use_expand(old_iuse)
2933 old_use_map = map_to_use_expand(old_use)
2936 use_expand.insert(0, "USE")
2938 for key in use_expand:
2939 if key in use_expand_hidden:
2941 verboseadd += create_use_string(key.upper(),
2942 cur_iuse_map[key], iuse_forced[key],
2943 cur_use_map[key], old_iuse_map[key],
2944 old_use_map[key], is_new)
2949 if pkg_type == "ebuild" and pkg_merge:
2951 myfilesdict = portdb.getfetchsizes(pkg_key,
2952 useflags=self.useFlags[myroot][pkg_key],
2954 except portage.exception.InvalidDependString, e:
2955 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2956 show_invalid_depstring_notice(x, src_uri, str(e))
2959 if myfilesdict is None:
2960 myfilesdict="[empty/missing/bad digest]"
2962 for myfetchfile in myfilesdict:
2963 if myfetchfile not in myfetchlist:
2964 mysize+=myfilesdict[myfetchfile]
2965 myfetchlist.append(myfetchfile)
2966 counters.totalsize += mysize
2967 verboseadd+=format_size(mysize)+" "
2970 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2971 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2972 file_name = portdb.findname(pkg_key)
2973 if file_name: # It might not exist in the tree
2974 newrepo = pkgsettings["PORTDIR"]
2976 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2977 oldrepo = self.trees[x[1]]["vartree"].dbapi.aux_get(pkg, ["repository"])[0]
2981 oldrepo = portdb.getRepositoryPath(oldrepo)
2982 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2983 if (overlays_real.count(dir_name) > 0):
2984 newrepoindex = overlays_real.index(os.path.normpath(dir_name))
2985 newrepo = overlays_real[newrepoindex]
2988 # assing lookup indexes
2991 elif oldrepo == pkgsettings["PORTDIR"]:
2994 oldrepoindex = str(overlays_real.index(os.path.normpath(oldrepo)) + 1)
2995 if oldrepoindex == newrepoindex \
2996 or not self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2997 repoadd = newrepoindex
2999 repoadd = "%s=>%s" % (oldrepoindex, newrepoindex)
3001 verboseadd+=teal("[%s]" % repoadd)+" "
3002 display_overlays=True
3004 verboseadd += "[No ebuild?]"
3006 xs = list(portage.pkgsplit(x[2]))
3013 if "COLUMNWIDTH" in self.settings:
3015 mywidth = int(self.settings["COLUMNWIDTH"])
3016 except ValueError, e:
3017 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
3019 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
3020 self.settings["COLUMNWIDTH"], noiselevel=-1)
3025 indent = " " * depth
3028 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
3029 if myoldbest[-3:]=="-r0":
3030 myoldbest=myoldbest[:-3]
3031 myoldbest=blue("["+myoldbest+"]")
3034 root_config = self.roots[myroot]
3035 system_set = root_config.sets["system"]
3036 world_set = root_config.sets["world"]
3041 pkg_system = system_set.findAtomForPackage(pkg_key, metadata)
3042 pkg_world = world_set.findAtomForPackage(pkg_key, metadata)
3043 if not pkg_world and myroot == self.target_root and \
3044 favorites_set.findAtomForPackage(pkg_key, metadata):
3045 # Maybe it will be added to world now.
3046 if create_world_atom(pkg_key, metadata,
3047 favorites_set, root_config.sets, portdb):
3049 except portage.exception.InvalidDependString:
3050 # This is reported elsewhere if relevant.
3056 return colorize("PKG_MERGE_WORLD", pkg)
3058 return colorize("PKG_MERGE_SYSTEM", pkg)
3060 return colorize("PKG_MERGE", pkg)
3063 return colorize("PKG_NOMERGE_WORLD", pkg)
3065 return colorize("PKG_NOMERGE_SYSTEM", pkg)
3067 return colorize("PKG_NOMERGE", pkg)
3072 if "--columns" in self.myopts:
3073 if "--quiet" in self.myopts:
3074 myprint=addl+" "+indent+pkgprint(pkg_cp)
3075 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
3076 myprint=myprint+myoldbest
3077 myprint=myprint+darkgreen("to "+x[1])
3079 myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_cp)
3080 if (newlp-nc_len(myprint)) > 0:
3081 myprint=myprint+(" "*(newlp-nc_len(myprint)))
3082 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
3083 if (oldlp-nc_len(myprint)) > 0:
3084 myprint=myprint+" "*(oldlp-nc_len(myprint))
3085 myprint=myprint+myoldbest
3086 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
3089 myprint = "[%s ] " % pkgprint("nomerge")
3091 myprint = "[" + pkg_type + " " + addl + "] "
3092 myprint += indent + pkgprint(pkg_key) + " " + \
3093 myoldbest + darkgreen("to " + myroot) + " " + \
3096 if "--columns" in self.myopts:
3097 if "--quiet" in self.myopts:
3098 myprint=addl+" "+indent+pkgprint(pkg_cp)
3099 myprint=myprint+" "+green(xs[1]+xs[2])+" "
3100 myprint=myprint+myoldbest
3102 myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_cp)
3103 if (newlp-nc_len(myprint)) > 0:
3104 myprint=myprint+(" "*(newlp-nc_len(myprint)))
3105 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
3106 if (oldlp-nc_len(myprint)) > 0:
3107 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
3108 myprint=myprint+myoldbest+" "+verboseadd
3111 myprint="["+pkgprint("nomerge")+" ] "+indent+pkgprint(pkg_key)+" "+myoldbest+" "+verboseadd
3113 myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_key)+" "+myoldbest+" "+verboseadd
3116 mysplit = portage.pkgsplit(x[2])
3117 if "--tree" not in self.myopts and mysplit and \
3118 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
3121 if mysplit[2] == "r0":
3122 myversion = mysplit[1]
3124 myversion = "%s-%s" % (mysplit[1], mysplit[2])
3126 if myversion != portage.VERSION and "--quiet" not in self.myopts:
3127 if mylist_index < len(mylist) - 1 and \
3128 "livecvsportage" not in self.settings.features:
3129 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
3130 p.append(colorize("WARN", " then resume the merge."))
3142 if overlays and display_overlays:
3143 print "Portage tree and overlays:"
3145 print " "+teal("[0]"), self.settings["PORTDIR"]
3148 print " "+teal("["+str(y)+"]"),x
3149 print " "+teal("[?]"), "indicates that the source repository could not be determined"
3151 if "--changelog" in self.myopts:
3153 for revision,text in changelogs:
3154 print bold('*'+revision)
3155 sys.stdout.write(text)
3157 if self._pprovided_args:
3159 for arg_atom in self._pprovided_args:
3160 arg, atom = arg_atom
3161 arg_refs[arg_atom] = []
3162 cp = portage.dep_getkey(atom)
3163 for set_name, atom_set in self._sets.iteritems():
3164 if atom in atom_set:
3165 arg_refs[arg_atom].append(set_name)
3167 msg.append(bad("\nWARNING: "))
3168 if len(self._pprovided_args) > 1:
3169 msg.append("Requested packages will not be " + \
3170 "merged because they are listed in\n")
3172 msg.append("A requested package will not be " + \
3173 "merged because it is listed in\n")
3174 msg.append("package.provided:\n\n")
3175 problems_sets = set()
3176 for (arg, atom), refs in arg_refs.iteritems():
3179 problems_sets.update(refs)
3181 ref_string = ", ".join(["'%s'" % name for name in refs])
3182 ref_string = " pulled in by " + ref_string
3183 msg.append(" %s%s\n" % (colorize("INFORM", arg), ref_string))
3185 if "world" in problems_sets:
3186 msg.append("This problem can be solved in one of the following ways:\n\n")
3187 msg.append(" A) Use emaint to clean offending packages from world (if not installed).\n")
3188 msg.append(" B) Uninstall offending packages (cleans them from world).\n")
3189 msg.append(" C) Remove offending entries from package.provided.\n\n")
3190 msg.append("The best course of action depends on the reason that an offending\n")
3191 msg.append("package.provided entry exists.\n\n")
3192 sys.stderr.write("".join(msg))
3195 def calc_changelog(self,ebuildpath,current,next):
3196 if ebuildpath == None or not os.path.exists(ebuildpath):
3198 current = '-'.join(portage.catpkgsplit(current)[1:])
3199 if current.endswith('-r0'):
3200 current = current[:-3]
3201 next = '-'.join(portage.catpkgsplit(next)[1:])
3202 if next.endswith('-r0'):
3204 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
3206 changelog = open(changelogpath).read()
3207 except SystemExit, e:
3208 raise # Needed else can't exit
3211 divisions = self.find_changelog_tags(changelog)
3212 #print 'XX from',current,'to',next
3213 #for div,text in divisions: print 'XX',div
3214 # skip entries for all revisions above the one we are about to emerge
3215 for i in range(len(divisions)):
3216 if divisions[i][0]==next:
3217 divisions = divisions[i:]
3219 # find out how many entries we are going to display
3220 for i in range(len(divisions)):
3221 if divisions[i][0]==current:
3222 divisions = divisions[:i]
3225 # couldnt find the current revision in the list. display nothing
3229 def find_changelog_tags(self,changelog):
3233 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
3235 if release is not None:
3236 divs.append((release,changelog))
3238 if release is not None:
3239 divs.append((release,changelog[:match.start()]))
3240 changelog = changelog[match.end():]
3241 release = match.group(1)
3242 if release.endswith('.ebuild'):
3243 release = release[:-7]
3244 if release.endswith('-r0'):
3245 release = release[:-3]
3247 def saveNomergeFavorites(self):
3248 """Find atoms in favorites that are not in the mergelist and add them
3249 to the world file if necessary."""
3250 for x in ("--fetchonly", "--fetch-all-uri",
3251 "--oneshot", "--onlydeps", "--pretend"):
3252 if x in self.myopts:
3254 root_config = self.roots[self.target_root]
3255 world_set = root_config.sets["world"]
3258 args_set = self._sets["args"]
3259 portdb = self.trees[self.target_root]["porttree"].dbapi
3260 added_favorites = set()
3261 for x in self._set_nodes:
3262 pkg_type, root, pkg_key, pkg_status = x
3263 if pkg_status != "nomerge":
3265 metadata = dict(izip(self._mydbapi_keys,
3266 self.mydbapi[root].aux_get(pkg_key, self._mydbapi_keys)))
3268 myfavkey = create_world_atom(pkg_key, metadata,
3269 args_set, root_config.sets, portdb)
3271 if myfavkey in added_favorites:
3273 added_favorites.add(myfavkey)
3274 world_set.add(myfavkey)
3275 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3276 except portage.exception.InvalidDependString, e:
3277 writemsg("\n\n!!! '%s' has invalid PROVIDE: %s\n" % \
3278 (pkg_key, str(e)), noiselevel=-1)
3279 writemsg("!!! see '%s'\n\n" % os.path.join(
3280 root, portage.VDB_PATH, pkg_key, "PROVIDE"), noiselevel=-1)
3286 class PackageCounters(object):
3296 self.restrict_fetch = 0
3297 self.restrict_fetch_satisfied = 0
3300 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
3303 myoutput.append("Total: %s package" % total_installs)
3304 if total_installs != 1:
3305 myoutput.append("s")
3306 if total_installs != 0:
3307 myoutput.append(" (")
3308 if self.upgrades > 0:
3309 details.append("%s upgrade" % self.upgrades)
3310 if self.upgrades > 1:
3312 if self.downgrades > 0:
3313 details.append("%s downgrade" % self.downgrades)
3314 if self.downgrades > 1:
3317 details.append("%s new" % self.new)
3318 if self.newslot > 0:
3319 details.append("%s in new slot" % self.newslot)
3320 if self.newslot > 1:
3323 details.append("%s reinstall" % self.reinst)
3327 details.append("%s block" % self.blocks)
3330 myoutput.append(", ".join(details))
3331 if total_installs != 0:
3332 myoutput.append(")")
3333 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
3334 if self.restrict_fetch:
3335 myoutput.append("\nFetch Restriction: %s package" % \
3336 self.restrict_fetch)
3337 if self.restrict_fetch > 1:
3338 myoutput.append("s")
3339 if self.restrict_fetch_satisfied < self.restrict_fetch:
3340 myoutput.append(bad(" (%s unsatisfied)") % \
3341 (self.restrict_fetch - self.restrict_fetch_satisfied))
3342 return "".join(myoutput)
3344 class MergeTask(object):
3346 def __init__(self, settings, trees, myopts):
3347 self.settings = settings
3348 self.target_root = settings["ROOT"]
3350 self.myopts = myopts
3352 if settings.get("PORTAGE_DEBUG", "") == "1":
3354 self.pkgsettings = {}
3355 self.pkgsettings[self.target_root] = portage.config(clone=settings)
3356 if self.target_root != "/":
3357 self.pkgsettings["/"] = \
3358 portage.config(clone=trees["/"]["vartree"].settings)
3360 def merge(self, mylist, favorites, mtimedb):
3361 from portage.elog import elog_process
3362 from portage.elog.filtering import filter_mergephases
3364 fetchonly = "--fetchonly" in self.myopts or \
3365 "--fetch-all-uri" in self.myopts
3366 pretend = "--pretend" in self.myopts
3368 ldpath_mtimes = mtimedb["ldpath"]
3369 xterm_titles = "notitles" not in self.settings.features
3371 #check for blocking dependencies
3372 if "--fetchonly" not in self.myopts and \
3373 "--fetch-all-uri" not in self.myopts and \
3374 "--buildpkgonly" not in self.myopts:
3377 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
3378 print "!!! the two packages cannot be installed on the same system together."
3379 print "!!! Please use 'emerge --pretend' to determine blockers."
3380 if "--quiet" not in self.myopts:
3381 show_blocker_docs_link()
3384 if "--resume" in self.myopts:
3386 print colorize("GOOD", "*** Resuming merge...")
3387 emergelog(xterm_titles, " *** Resuming merge...")
3388 mylist = mtimedb["resume"]["mergelist"][:]
3389 if "--skipfirst" in self.myopts and mylist:
3390 del mtimedb["resume"]["mergelist"][0]
3393 validate_merge_list(self.trees, mylist)
3394 mymergelist = mylist
3396 # Verify all the manifests now so that the user is notified of failure
3397 # as soon as possible.
3398 if "--fetchonly" not in self.myopts and \
3399 "--fetch-all-uri" not in self.myopts and \
3400 "strict" in self.settings.features:
3401 shown_verifying_msg = False
3403 for myroot, pkgsettings in self.pkgsettings.iteritems():
3404 quiet_config = portage.config(clone=pkgsettings)
3405 quiet_config["PORTAGE_QUIET"] = "1"
3406 quiet_config.backup_changes("PORTAGE_QUIET")
3407 quiet_settings[myroot] = quiet_config
3410 if x[0] != "ebuild" or x[-1] == "nomerge":
3412 if not shown_verifying_msg:
3413 shown_verifying_msg = True
3414 print ">>> Verifying ebuild Manifests..."
3415 mytype, myroot, mycpv, mystatus = x
3416 portdb = self.trees[myroot]["porttree"].dbapi
3417 quiet_config = quiet_settings[myroot]
3418 quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
3419 if not portage.digestcheck([], quiet_config, strict=True):
3421 del x, mytype, myroot, mycpv, mystatus, quiet_config
3422 del shown_verifying_msg, quiet_settings
3424 system_set = SystemSet(self.settings)
3425 args_set = AtomSet(favorites)
3426 world_set = WorldSet(self.settings)
3427 if "--resume" not in self.myopts:
3428 mymergelist = mylist
3429 mtimedb["resume"]["mergelist"]=mymergelist[:]
3432 myfeat = self.settings.features[:]
3433 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3435 if "parallel-fetch" in myfeat and \
3436 not ("--pretend" in self.myopts or \
3437 "--fetch-all-uri" in self.myopts or \
3438 "--fetchonly" in self.myopts):
3439 if "distlocks" not in myfeat:
3441 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
3442 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
3444 elif len(mymergelist) > 1:
3445 print ">>> starting parallel fetching"
3446 fetch_log = "/var/log/emerge-fetch.log"
3447 logfile = open(fetch_log, "w")
3448 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3449 portage.util.apply_secpass_permissions(fetch_log,
3450 uid=portage.portage_uid, gid=portage.portage_gid,
3452 fetch_env = os.environ.copy()
3453 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3454 fetch_env["PORTAGE_NICENESS"] = "0"
3455 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3456 resume_opts = self.myopts.copy()
3457 # For automatic resume, we need to prevent
3458 # any of bad_resume_opts from leaking in
3459 # via EMERGE_DEFAULT_OPTS.
3460 resume_opts["--ignore-default-opts"] = True
3461 for myopt, myarg in resume_opts.iteritems():
3462 if myopt not in bad_resume_opts:
3464 fetch_args.append(myopt)
3466 fetch_args.append(myopt +"="+ myarg)
3467 portage.process.spawn(fetch_args, env=fetch_env,
3468 fd_pipes=fd_pipes, returnpid=True)
3469 logfile.close() # belongs to the spawned process
3470 del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3473 metadata_keys = [k for k in portage.auxdbkeys \
3474 if not k.startswith("UNUSED_")] + ["USE"]
3477 for x in mymergelist:
3483 portdb = self.trees[myroot]["porttree"].dbapi
3484 bindb = self.trees[myroot]["bintree"].dbapi
3485 vartree = self.trees[myroot]["vartree"]
3486 pkgsettings = self.pkgsettings[myroot]
3488 if pkg_type == "blocks":
3490 elif pkg_type == "ebuild":
3492 metadata.update(izip(metadata_keys,
3493 mydbapi.aux_get(pkg_key, metadata_keys)))
3494 pkgsettings.setcpv(pkg_key, mydb=mydbapi)
3495 metadata["USE"] = pkgsettings["USE"]
3497 if pkg_type == "binary":
3500 raise AssertionError("Package type: '%s'" % pkg_type)
3501 metadata.update(izip(metadata_keys,
3502 mydbapi.aux_get(pkg_key, metadata_keys)))
3505 y = portdb.findname(pkg_key)
3506 if "--pretend" not in self.myopts:
3507 print "\n>>> Emerging (" + \
3508 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3509 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3510 colorize("GOOD", x[pkgindex]) + " to " + x[1]
3511 emergelog(xterm_titles, " >>> emerge ("+\
3512 str(mergecount)+" of "+str(len(mymergelist))+\
3513 ") "+x[pkgindex]+" to "+x[1])
3515 pkgsettings["EMERGE_FROM"] = x[0]
3516 pkgsettings.backup_changes("EMERGE_FROM")
3519 #buildsyspkg: Check if we need to _force_ binary package creation
3520 issyspkg = ("buildsyspkg" in myfeat) \
3521 and x[0] != "blocks" \
3522 and system_set.findAtomForPackage(pkg_key, metadata) \
3523 and "--buildpkg" not in self.myopts
3524 if x[0] in ["ebuild","blocks"]:
3525 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3526 raise Exception, "Merging a blocker"
3527 elif "--fetchonly" in self.myopts or \
3528 "--fetch-all-uri" in self.myopts:
3529 if "--fetch-all-uri" in self.myopts:
3530 retval = portage.doebuild(y, "fetch", myroot,
3531 pkgsettings, self.edebug,
3532 "--pretend" in self.myopts, fetchonly=1,
3533 fetchall=1, mydbapi=portdb, tree="porttree")
3535 retval = portage.doebuild(y, "fetch", myroot,
3536 pkgsettings, self.edebug,
3537 "--pretend" in self.myopts, fetchonly=1,
3538 mydbapi=portdb, tree="porttree")
3539 if (retval is None) or retval:
3541 print "!!! Fetch for",y,"failed, continuing..."
3543 failed_fetches.append(pkg_key)
3546 portage.doebuild_environment(y, "setup", myroot,
3547 pkgsettings, self.edebug, 1, portdb)
3548 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3549 portage.util.ensure_dirs(os.path.dirname(catdir),
3550 uid=portage.portage_uid, gid=portage.portage_gid,
3552 builddir_lock = None
3555 catdir_lock = portage.locks.lockdir(catdir)
3556 portage.util.ensure_dirs(catdir,
3557 uid=portage.portage_uid, gid=portage.portage_gid,
3559 builddir_lock = portage.locks.lockdir(
3560 pkgsettings["PORTAGE_BUILDDIR"])
3562 portage.locks.unlockdir(catdir_lock)
3565 msg = " === (%s of %s) Cleaning (%s::%s)" % \
3566 (mergecount, len(mymergelist), pkg_key, y)
3567 short_msg = "emerge: (%s of %s) %s Clean" % \
3568 (mergecount, len(mymergelist), pkg_key)
3569 emergelog(xterm_titles, msg, short_msg=short_msg)
3570 retval = portage.doebuild(y, "clean", myroot,
3571 pkgsettings, self.edebug, cleanup=1,
3572 mydbapi=portdb, tree="porttree")
3573 if retval != os.EX_OK:
3575 if "--buildpkg" in self.myopts or issyspkg:
3577 print ">>> This is a system package, " + \
3578 "let's pack a rescue tarball."
3579 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3580 (mergecount, len(mymergelist), pkg_key, y)
3581 short_msg = "emerge: (%s of %s) %s Compile" % \
3582 (mergecount, len(mymergelist), pkg_key)
3583 emergelog(xterm_titles, msg, short_msg=short_msg)
3584 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3585 binpkg_tmpfile = os.path.join(pkgsettings["PKGDIR"],
3586 pkg_key + ".tbz2." + str(os.getpid()))
3587 pkgsettings["PORTAGE_BINPKG_TMPFILE"] = binpkg_tmpfile
3588 pkgsettings.backup_changes("PORTAGE_BINPKG_TMPFILE")
3589 retval = portage.doebuild(y, "package", myroot,
3590 pkgsettings, self.edebug, mydbapi=portdb,
3592 del pkgsettings["PORTAGE_BINPKG_TMPFILE"]
3593 if retval != os.EX_OK or \
3594 "--buildpkgonly" in self.myopts:
3595 elog_process(pkg_key, pkgsettings, phasefilter=filter_mergephases)
3596 if retval != os.EX_OK:
3598 bintree = self.trees[myroot]["bintree"]
3599 bintree.inject(pkg_key, filename=binpkg_tmpfile)
3600 if "--buildpkgonly" not in self.myopts:
3601 msg = " === (%s of %s) Merging (%s::%s)" % \
3602 (mergecount, len(mymergelist), pkg_key, y)
3603 short_msg = "emerge: (%s of %s) %s Merge" % \
3604 (mergecount, len(mymergelist), pkg_key)
3605 emergelog(xterm_titles, msg, short_msg=short_msg)
3606 retval = portage.merge(pkgsettings["CATEGORY"],
3607 pkgsettings["PF"], pkgsettings["D"],
3608 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3609 "build-info"), myroot, pkgsettings,
3610 myebuild=pkgsettings["EBUILD"],
3611 mytree="porttree", mydbapi=portdb,
3612 vartree=vartree, prev_mtimes=ldpath_mtimes)
3613 if retval != os.EX_OK:
3615 elif "noclean" not in pkgsettings.features:
3616 portage.doebuild(y, "clean", myroot,
3617 pkgsettings, self.edebug, mydbapi=portdb,
3620 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3621 (mergecount, len(mymergelist), pkg_key, y)
3622 short_msg = "emerge: (%s of %s) %s Compile" % \
3623 (mergecount, len(mymergelist), pkg_key)
3624 emergelog(xterm_titles, msg, short_msg=short_msg)
3625 retval = portage.doebuild(y, "merge", myroot,
3626 pkgsettings, self.edebug, vartree=vartree,
3627 mydbapi=portdb, tree="porttree",
3628 prev_mtimes=ldpath_mtimes)
3629 if retval != os.EX_OK:
3633 portage.locks.unlockdir(builddir_lock)
3636 # Lock catdir for removal if empty.
3637 catdir_lock = portage.locks.lockdir(catdir)
3643 if e.errno not in (errno.ENOENT,
3644 errno.ENOTEMPTY, errno.EEXIST):
3647 portage.locks.unlockdir(catdir_lock)
3649 elif x[0]=="binary":
3651 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3652 if "--getbinpkg" in self.myopts:
3655 if "distlocks" in pkgsettings.features and \
3656 os.access(pkgsettings["PKGDIR"], os.W_OK):
3657 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3658 tbz2_lock = portage.locks.lockfile(mytbz2,
3660 if self.trees[myroot]["bintree"].isremote(pkg_key):
3661 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3662 (mergecount, len(mymergelist), pkg_key, mytbz2)
3663 short_msg = "emerge: (%s of %s) %s Fetch" % \
3664 (mergecount, len(mymergelist), pkg_key)
3665 emergelog(xterm_titles, msg, short_msg=short_msg)
3667 self.trees[myroot]["bintree"].gettbz2(pkg_key)
3668 except portage.exception.FileNotFound:
3669 writemsg("!!! Fetching Binary failed " + \
3670 "for '%s'\n" % pkg_key, noiselevel=-1)
3673 failed_fetches.append(pkg_key)
3674 except portage.exception.DigestException, e:
3675 writemsg("\n!!! Digest verification failed:\n",
3677 writemsg("!!! %s\n" % e.value[0],
3679 writemsg("!!! Reason: %s\n" % e.value[1],
3681 writemsg("!!! Got: %s\n" % e.value[2],
3683 writemsg("!!! Expected: %s\n" % e.value[3],
3688 failed_fetches.append(pkg_key)
3691 portage.locks.unlockfile(tbz2_lock)
3693 if "--fetchonly" in self.myopts or \
3694 "--fetch-all-uri" in self.myopts:
3697 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3698 emergelog(xterm_titles, " === ("+str(mergecount)+\
3699 " of "+str(len(mymergelist))+") Merging Binary ("+\
3700 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3701 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3703 vartree=self.trees[myroot]["vartree"],
3704 prev_mtimes=ldpath_mtimes)
3705 if retval != os.EX_OK:
3707 #need to check for errors
3708 if "--buildpkgonly" not in self.myopts:
3709 self.trees[x[1]]["vartree"].inject(x[2])
3710 myfavkey = portage.cpv_getkey(x[2])
3711 if not fetchonly and not pretend and \
3712 args_set.findAtomForPackage(pkg_key, metadata):
3715 myfavkey = create_world_atom(pkg_key, metadata,
3716 args_set, {"world":world_set, "system":system_set},
3719 world_set.add(myfavkey)
3720 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3721 emergelog(xterm_titles, " === ("+\
3722 str(mergecount)+" of "+\
3723 str(len(mymergelist))+\
3724 ") Updating world file ("+x[pkgindex]+")")
3728 if "--pretend" not in self.myopts and \
3729 "--fetchonly" not in self.myopts and \
3730 "--fetch-all-uri" not in self.myopts:
3731 # Clean the old package that we have merged over top of it.
3732 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3733 xsplit=portage.pkgsplit(x[2])
3734 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3735 retval = unmerge(pkgsettings, self.myopts, vartree,
3736 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3738 emergelog(xterm_titles,
3739 " --- AUTOCLEAN: Nothing unmerged.")
3741 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3742 + " AUTOCLEAN is disabled. This can cause serious"
3743 + " problems due to overlapping packages.\n")
3745 # Figure out if we need a restart.
3746 mysplit=portage.pkgsplit(x[2])
3747 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3748 myver=mysplit[1]+"-"+mysplit[2]
3749 if myver[-3:]=='-r0':
3751 if (myver != portage.VERSION) and \
3752 "livecvsportage" not in self.settings.features:
3753 if len(mymergelist) > mergecount:
3754 emergelog(xterm_titles,
3755 " ::: completed emerge ("+ \
3756 str(mergecount)+" of "+ \
3757 str(len(mymergelist))+") "+ \
3759 emergelog(xterm_titles, " *** RESTARTING " + \
3760 "emerge via exec() after change of " + \
3762 del mtimedb["resume"]["mergelist"][0]
3764 portage.run_exitfuncs()
3765 mynewargv=[sys.argv[0],"--resume"]
3766 resume_opts = self.myopts.copy()
3767 # For automatic resume, we need to prevent
3768 # any of bad_resume_opts from leaking in
3769 # via EMERGE_DEFAULT_OPTS.
3770 resume_opts["--ignore-default-opts"] = True
3771 for myopt, myarg in resume_opts.iteritems():
3772 if myopt not in bad_resume_opts:
3774 mynewargv.append(myopt)
3776 mynewargv.append(myopt +"="+ myarg)
3777 # priority only needs to be adjusted on the first run
3778 os.environ["PORTAGE_NICENESS"] = "0"
3779 os.execv(mynewargv[0], mynewargv)
3781 if "--pretend" not in self.myopts and \
3782 "--fetchonly" not in self.myopts and \
3783 "--fetch-all-uri" not in self.myopts:
3784 if "noclean" not in self.settings.features:
3785 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3786 (mergecount, len(mymergelist), x[pkgindex])
3787 emergelog(xterm_titles, (" === (%s of %s) " + \
3788 "Post-Build Cleaning (%s::%s)") % \
3789 (mergecount, len(mymergelist), x[pkgindex], y),
3790 short_msg=short_msg)
3791 emergelog(xterm_titles, " ::: completed emerge ("+\
3792 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3795 # Unsafe for parallel merges
3796 del mtimedb["resume"]["mergelist"][0]
3797 # Commit after each merge so that --resume may still work in
3798 # in the event that portage is not allowed to exit normally
3799 # due to power failure, SIGKILL, etc...
3802 if "--pretend" not in self.myopts:
3803 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3805 # We're out of the loop... We're done. Delete the resume data.
3806 if mtimedb.has_key("resume"):
3807 del mtimedb["resume"]
3810 #by doing an exit this way, --fetchonly can continue to try to
3811 #fetch everything even if a particular download fails.
3812 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3814 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3815 "encountered. Please see above for details.\n\n")
3816 for cpv in failed_fetches:
3817 sys.stderr.write(" ")
3818 sys.stderr.write(cpv)
3819 sys.stderr.write("\n")
3820 sys.stderr.write("\n")
3826 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3827 ldpath_mtimes, autoclean=0):
3828 candidate_catpkgs=[]
3830 xterm_titles = "notitles" not in settings.features
3832 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3834 # At least the parent needs to exist for the lock file.
3835 portage.util.ensure_dirs(vdb_path)
3836 except portage.exception.PortageException:
3840 if os.access(vdb_path, os.W_OK):
3841 vdb_lock = portage.locks.lockdir(vdb_path)
3842 realsyslist = getlist(settings, "system")
3844 for x in realsyslist:
3845 mycp = portage.dep_getkey(x)
3846 if mycp in settings.getvirtuals():
3848 for provider in settings.getvirtuals()[mycp]:
3849 if vartree.dbapi.match(provider):
3850 providers.append(provider)
3851 if len(providers) == 1:
3852 syslist.extend(providers)
3854 syslist.append(mycp)
3856 mysettings = portage.config(clone=settings)
3858 if not unmerge_files or "world" in unmerge_files or \
3859 "system" in unmerge_files:
3860 if "unmerge"==unmerge_action:
3862 print bold("emerge unmerge") + " can only be used with " + \
3863 "specific package names, not with "+bold("world")+" or"
3864 print bold("system")+" targets."
3871 # process all arguments and add all
3872 # valid db entries to candidate_catpkgs
3874 if not unmerge_files or "world" in unmerge_files:
3875 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3876 elif "system" in unmerge_files:
3877 candidate_catpkgs.extend(getlist(settings, "system"))
3879 #we've got command-line arguments
3880 if not unmerge_files:
3881 print "\nNo packages to unmerge have been provided.\n"
3883 for x in unmerge_files:
3884 arg_parts = x.split('/')
3885 if x[0] not in [".","/"] and \
3886 arg_parts[-1][-7:] != ".ebuild":
3887 #possible cat/pkg or dep; treat as such
3888 candidate_catpkgs.append(x)
3889 elif unmerge_action in ["prune","clean"]:
3890 print "\n!!! Prune and clean do not accept individual" + \
3891 " ebuilds as arguments;\n skipping.\n"
3894 # it appears that the user is specifying an installed
3895 # ebuild and we're in "unmerge" mode, so it's ok.
3896 if not os.path.exists(x):
3897 print "\n!!! The path '"+x+"' doesn't exist.\n"
3900 absx = os.path.abspath(x)
3901 sp_absx = absx.split("/")
3902 if sp_absx[-1][-7:] == ".ebuild":
3904 absx = "/".join(sp_absx)
3906 sp_absx_len = len(sp_absx)
3908 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3909 vdb_len = len(vdb_path)
3911 sp_vdb = vdb_path.split("/")
3912 sp_vdb_len = len(sp_vdb)
3914 if not os.path.exists(absx+"/CONTENTS"):
3915 print "!!! Not a valid db dir: "+str(absx)
3918 if sp_absx_len <= sp_vdb_len:
3919 # The Path is shorter... so it can't be inside the vdb.
3922 print "\n!!!",x,"cannot be inside "+ \
3923 vdb_path+"; aborting.\n"
3926 for idx in range(0,sp_vdb_len):
3927 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3930 print "\n!!!", x, "is not inside "+\
3931 vdb_path+"; aborting.\n"
3934 print "="+"/".join(sp_absx[sp_vdb_len:])
3935 candidate_catpkgs.append(
3936 "="+"/".join(sp_absx[sp_vdb_len:]))
3939 if (not "--quiet" in myopts):
3941 if settings["ROOT"] != "/":
3942 print darkgreen(newline+ \
3943 ">>> Using system located in ROOT tree "+settings["ROOT"])
3944 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3945 not ("--quiet" in myopts):
3946 print darkgreen(newline+\
3947 ">>> These are the packages that would be unmerged:")
3951 for x in candidate_catpkgs:
3952 # cycle through all our candidate deps and determine
3953 # what will and will not get unmerged
3955 mymatch=localtree.dep_match(x)
3958 except ValueError, errpkgs:
3959 print "\n\n!!! The short ebuild name \"" + \
3960 x + "\" is ambiguous. Please specify"
3961 print "!!! one of the following fully-qualified " + \
3962 "ebuild names instead:\n"
3963 for i in errpkgs[0]:
3964 print " " + green(i)
3968 if not mymatch and x[0] not in "<>=~":
3969 #add a "=" if missing
3970 mymatch=localtree.dep_match("="+x)
3972 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3973 (x, unmerge_action), noiselevel=-1)
3975 mykey = portage.key_expand(
3977 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3978 if not pkgmap.has_key(mykey):
3979 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3980 if unmerge_action=="unmerge":
3982 if y not in pkgmap[mykey]["selected"]:
3983 pkgmap[mykey]["selected"].append(y)
3984 numselected=numselected+len(mymatch)
3987 #unmerge_action in ["prune", clean"]
3989 for mypkg in mymatch:
3990 if unmerge_action=="clean":
3991 myslot=localtree.getslot(mypkg)
3993 # since we're pruning, we don't care about slots
3994 # and put all the pkgs in together
3996 if not slotmap.has_key(myslot):
3998 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3999 for myslot in slotmap:
4000 counterkeys=slotmap[myslot].keys()
4005 pkgmap[mykey]["protected"].append(
4006 slotmap[myslot][counterkeys[-1]])
4008 #be pretty and get them in order of merge:
4009 for ckey in counterkeys:
4010 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
4011 numselected=numselected+1
4012 # ok, now the last-merged package
4013 # is protected, and the rest are selected
4014 if global_unmerge and not numselected:
4015 portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
4019 portage.writemsg_stdout(
4020 "\n>>> No packages selected for removal by " + \
4021 unmerge_action + "\n")
4025 portage.locks.unlockdir(vdb_lock)
4027 for y in localtree.dep_match(x):
4028 if y not in pkgmap[x]["omitted"] and \
4029 y not in pkgmap[x]["selected"] and \
4030 y not in pkgmap[x]["protected"]:
4031 pkgmap[x]["omitted"].append(y)
4032 if global_unmerge and not pkgmap[x]["selected"]:
4033 #avoid cluttering the preview printout with stuff that isn't getting unmerged
4035 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
4036 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
4037 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
4038 if "--pretend" not in myopts and "--ask" not in myopts:
4039 countdown(int(settings["EMERGE_WARNING_DELAY"]),
4040 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
4041 if "--quiet" not in myopts:
4042 print "\n "+white(x)
4044 print white(x)+": ",
4045 for mytype in ["selected","protected","omitted"]:
4046 if "--quiet" not in myopts:
4047 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
4048 if pkgmap[x][mytype]:
4049 for mypkg in pkgmap[x][mytype]:
4050 mysplit=portage.catpkgsplit(mypkg)
4051 if mysplit[3]=="r0":
4052 myversion=mysplit[2]
4054 myversion=mysplit[2]+"-"+mysplit[3]
4055 if mytype=="selected":
4056 portage.writemsg_stdout(
4057 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
4059 portage.writemsg_stdout(
4060 colorize("GOOD", myversion + " "), noiselevel=-1)
4062 portage.writemsg_stdout("none ", noiselevel=-1)
4063 if "--quiet" not in myopts:
4064 portage.writemsg_stdout("\n", noiselevel=-1)
4065 if "--quiet" in myopts:
4066 portage.writemsg_stdout("\n", noiselevel=-1)
4068 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
4069 " packages are slated for removal.\n")
4070 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
4071 " and " + colorize("GOOD", "'omitted'") + \
4072 " packages will not be removed.\n\n")
4074 if "--pretend" in myopts:
4075 #we're done... return
4077 if "--ask" in myopts:
4078 if userquery("Would you like to unmerge these packages?")=="No":
4079 # enter pretend mode for correct formatting of results
4080 myopts["--pretend"] = True
4085 #the real unmerging begins, after a short delay....
4087 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
4090 for y in pkgmap[x]["selected"]:
4091 print ">>> Unmerging "+y+"..."
4092 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
4093 mysplit=y.split("/")
4095 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
4096 mysettings, unmerge_action not in ["clean","prune"],
4097 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
4098 if retval != os.EX_OK:
4099 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
4100 ebuild = vartree.dbapi.findname(y)
4101 show_unmerge_failure_message(y, ebuild, retval)
4104 clean_world(vartree.dbapi, y)
4105 emergelog(xterm_titles, " >>> unmerge success: "+y)
4108 def show_unmerge_failure_message(pkg, ebuild, retval):
4110 from formatter import AbstractFormatter, DumbWriter
4111 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
4114 msg.append("A removal phase of the '%s' package " % pkg)
4115 msg.append("has failed with exit value %s. " % retval)
4116 msg.append("The problem occurred while executing ")
4117 msg.append("the ebuild located at '%s'. " % ebuild)
4118 msg.append("If necessary, manually remove the ebuild " )
4119 msg.append("in order to skip the execution of removal phases.")
4123 f.add_flowing_data(x)
4127 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
4129 if os.path.exists("/usr/bin/install-info"):
4134 inforoot=normpath(root+z)
4135 if os.path.isdir(inforoot):
4136 infomtime = long(os.stat(inforoot).st_mtime)
4137 if inforoot not in prev_mtimes or \
4138 prev_mtimes[inforoot] != infomtime:
4139 regen_infodirs.append(inforoot)
4141 if not regen_infodirs:
4142 portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
4144 portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
4148 for inforoot in regen_infodirs:
4151 for filename in ("dir", "dir.gz", "dir.bz2"):
4152 file_path = os.path.join(inforoot, filename)
4154 os.rename(file_path, file_path + ".old")
4156 if e.errno != errno.ENOENT:
4160 if not os.path.isdir(inforoot):
4163 file_list = os.listdir(inforoot)
4166 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
4168 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
4169 existsstr="already exists, for file `"
4171 if re.search(existsstr,myso):
4172 # Already exists... Don't increment the count for this.
4174 elif myso[:44]=="install-info: warning: no info dir entry in ":
4175 # This info file doesn't contain a DIR-header: install-info produces this
4176 # (harmless) warning (the --quiet switch doesn't seem to work).
4177 # Don't increment the count for this.
4181 errmsg += myso + "\n"
4184 #update mtime so we can potentially avoid regenerating.
4185 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
4188 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
4191 print " "+green("*")+" Processed",icount,"info files."
4194 def display_news_notification(trees):
4195 for target_root in trees:
4196 if len(trees) > 1 and target_root != "/":
4198 settings = trees[target_root]["vartree"].settings
4199 portdb = trees[target_root]["porttree"].dbapi
4200 vardb = trees[target_root]["vartree"].dbapi
4201 NEWS_PATH = os.path.join("metadata", "news")
4202 UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
4203 newsReaderDisplay = False
4205 for repo in portdb.getRepositories():
4206 unreadItems = checkUpdatedNewsItems(
4207 portdb, vardb, NEWS_PATH, UNREAD_PATH, repo)
4209 if not newsReaderDisplay:
4210 newsReaderDisplay = True
4212 print colorize("WARN", " * IMPORTANT:"),
4213 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
4216 if newsReaderDisplay:
4217 print colorize("WARN", " *"),
4218 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
4221 def post_emerge(trees, mtimedb, retval):
4223 Misc. things to run at the end of a merge session.
4229 Display preserved libs warnings
4232 @param trees: A dictionary mapping each ROOT to it's package databases
4234 @param mtimedb: The mtimeDB to store data needed across merge invocations
4235 @type mtimedb: MtimeDB class instance
4236 @param retval: Emerge's return value
4240 1. Calls sys.exit(retval)
4242 for target_root in trees:
4243 if len(trees) > 1 and target_root != "/":
4245 vardbapi = trees[target_root]["vartree"].dbapi
4246 settings = vardbapi.settings
4247 info_mtimes = mtimedb["info"]
4249 # Load the most current variables from ${ROOT}/etc/profile.env
4251 settings.regenerate()
4254 config_protect = settings.get("CONFIG_PROTECT","").split()
4255 infodirs = settings.get("INFOPATH","").split(":") + \
4256 settings.get("INFODIR","").split(":")
4260 emergelog("notitles" not in settings.features,
4261 " *** exiting successfully.")
4263 # Dump the mod_echo output now so that our other notifications are shown
4265 from portage.elog import mod_echo
4268 if "noinfo" not in settings.features:
4269 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
4271 chk_updated_cfg_files(target_root, config_protect)
4273 display_news_notification(trees)
4275 if vardbapi.plib_registry.hasEntries():
4276 print colorize("WARN", "!!!") + " existing preserved libs:"
4277 plibdata = vardbapi.plib_registry.getPreservedLibs()
4278 for cpv in plibdata:
4279 print colorize("WARN", ">>>") + " package: %s" % cpv
4280 for f in plibdata[cpv]:
4281 print colorize("WARN", " * ") + " - %s" % f
4282 print "Use " + colorize("GOOD", "revdep-rebuild") + " to rebuild packages using these libraries"
4283 print "and then remerge the packages listed above."
4289 def chk_updated_cfg_files(target_root, config_protect):
4291 #number of directories with some protect files in them
4293 for x in config_protect:
4294 x = os.path.join(target_root, x.lstrip(os.path.sep))
4296 mymode = os.lstat(x).st_mode
4299 if stat.S_ISDIR(mymode):
4300 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
4302 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
4303 os.path.split(x.rstrip(os.path.sep))
4304 a = commands.getstatusoutput(mycommand + \
4305 " ! -iname '.*~' ! -iname '.*.bak'")
4307 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
4309 files = a[1].split()
4312 print colorize("WARN", " * IMPORTANT:"),
4313 if stat.S_ISDIR(mymode):
4314 print "%d config files in '%s' need updating." % \
4317 print "config file '%s' needs updating." % x
4320 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
4321 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
4323 def checkUpdatedNewsItems(portdb, vardb, NEWS_PATH, UNREAD_PATH, repo_id):
4325 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
4326 Returns the number of unread (yet relevent) items.
4328 @param portdb: a portage tree database
4329 @type portdb: pordbapi
4330 @param vardb: an installed package database
4331 @type vardb: vardbapi
4340 1. The number of unread but relevant news items.
4343 from portage.news import NewsManager
4344 manager = NewsManager(portdb, vardb, NEWS_PATH, UNREAD_PATH)
4345 return manager.getUnreadItems( repo_id, update=True )
4347 def is_valid_package_atom(x):
4349 testkey = portage.dep_getkey(x)
4350 except portage.exception.InvalidData:
4352 if testkey.startswith("null/"):
4353 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
4358 return portage.isvalidatom(testatom)
4360 def validate_merge_list(trees, mergelist):
4361 """Validate the list to make sure all the packages are still available.
4362 This is needed for --resume."""
4363 for (pkg_type, myroot, pkg_key, action) in mergelist:
4364 if pkg_type == "binary" and \
4365 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
4366 pkg_type == "ebuild" and \
4367 not trees[myroot]["porttree"].dbapi.xmatch(
4368 "match-all", "="+pkg_key):
4369 print red("!!! Error: The resume list contains packages that are no longer")
4370 print red("!!! available to be emerged. Please restart/continue")
4371 print red("!!! the merge operation manually.")
4374 def show_blocker_docs_link():
4376 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
4377 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
4379 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
4382 def action_sync(settings, trees, mtimedb, myopts, myaction):
4383 xterm_titles = "notitles" not in settings.features
4384 emergelog(xterm_titles, " === sync")
4385 myportdir = settings.get("PORTDIR", None)
4387 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
4389 if myportdir[-1]=="/":
4390 myportdir=myportdir[:-1]
4391 if not os.path.exists(myportdir):
4392 print ">>>",myportdir,"not found, creating it."
4393 os.makedirs(myportdir,0755)
4394 syncuri=settings["SYNC"].rstrip()
4396 updatecache_flg = False
4397 if myaction == "metadata":
4398 print "skipping sync"
4399 updatecache_flg = True
4400 tmpservertimestampfile = None
4401 elif syncuri[:8]=="rsync://":
4402 if not os.path.exists("/usr/bin/rsync"):
4403 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
4404 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
4409 import shlex, StringIO
4410 if settings["PORTAGE_RSYNC_OPTS"] == "":
4411 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
4413 "--recursive", # Recurse directories
4414 "--links", # Consider symlinks
4415 "--safe-links", # Ignore links outside of tree
4416 "--perms", # Preserve permissions
4417 "--times", # Preserive mod times
4418 "--compress", # Compress the data transmitted
4419 "--force", # Force deletion on non-empty dirs
4420 "--whole-file", # Don't do block transfers, only entire files
4421 "--delete", # Delete files that aren't in the master tree
4422 "--delete-after", # Delete only after everything else is done
4423 "--stats", # Show final statistics about what was transfered
4424 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
4425 "--exclude=/distfiles", # Exclude distfiles from consideration
4426 "--exclude=/local", # Exclude local from consideration
4427 "--exclude=/packages", # Exclude packages from consideration
4428 "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
4432 # The below validation is not needed when using the above hardcoded
4435 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
4436 lexer = shlex.shlex(StringIO.StringIO(
4437 settings.get("PORTAGE_RSYNC_OPTS","")), posix=True)
4438 lexer.whitespace_split = True
4439 rsync_opts.extend(lexer)
4442 for opt in ("--recursive", "--times"):
4443 if opt not in rsync_opts:
4444 portage.writemsg(yellow("WARNING:") + " adding required option " + \
4445 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4446 rsync_opts.append(opt)
4448 for exclude in ("distfiles", "local", "packages"):
4449 opt = "--exclude=/%s" % exclude
4450 if opt not in rsync_opts:
4451 portage.writemsg(yellow("WARNING:") + \
4452 " adding required option %s not included in " % opt + \
4453 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
4454 rsync_opts.append(opt)
4456 if settings["RSYNC_TIMEOUT"] != "":
4457 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
4458 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4460 mytimeout = int(settings["RSYNC_TIMEOUT"])
4461 rsync_opts.append("--timeout=%d" % mytimeout)
4462 except ValueError, e:
4463 portage.writemsg("!!! %s\n" % str(e))
4465 # TODO: determine options required for official servers
4466 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
4468 def rsync_opt_startswith(opt_prefix):
4469 for x in rsync_opts:
4470 if x.startswith(opt_prefix):
4474 if not rsync_opt_startswith("--timeout="):
4475 rsync_opts.append("--timeout=%d" % mytimeout)
4477 for opt in ("--compress", "--whole-file"):
4478 if opt not in rsync_opts:
4479 portage.writemsg(yellow("WARNING:") + " adding required option " + \
4480 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4481 rsync_opts.append(opt)
4483 if "--quiet" in myopts:
4484 rsync_opts.append("--quiet") # Shut up a lot
4486 rsync_opts.append("--verbose") # Print filelist
4488 if "--verbose" in myopts:
4489 rsync_opts.append("--progress") # Progress meter for each file
4491 if "--debug" in myopts:
4492 rsync_opts.append("--checksum") # Force checksum on all files
4494 if settings["RSYNC_EXCLUDEFROM"] != "":
4495 portage.writemsg(yellow("WARNING:") + \
4496 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
4497 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4498 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
4499 rsync_opts.append("--exclude-from=%s" % \
4500 settings["RSYNC_EXCLUDEFROM"])
4502 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
4503 " but file does not exist.\n")
4505 if settings["RSYNC_RATELIMIT"] != "":
4506 portage.writemsg(yellow("WARNING:") + \
4507 " usage of RSYNC_RATELIMIT is deprecated, use " + \
4508 "PORTAGE_RSYNC_EXTRA_OPTS instead")
4509 rsync_opts.append("--bwlimit=%s" % \
4510 settings["RSYNC_RATELIMIT"])
4512 # Real local timestamp file.
4513 servertimestampfile = os.path.join(
4514 myportdir, "metadata", "timestamp.chk")
4515 # Temporary file for remote server timestamp comparison.
4516 tmpservertimestampfile = os.path.join(
4517 settings["PORTAGE_TMPDIR"], "timestamp.chk")
4519 content = portage.util.grabfile(servertimestampfile)
4523 mytimestamp = time.mktime(time.strptime(content[0],
4524 "%a, %d %b %Y %H:%M:%S +0000"))
4525 except (OverflowError, ValueError):
4530 rsync_initial_timeout = \
4531 int(settings.get("PORTAGE_RSYNC_INITIAL_TIMEOUT", "15"))
4533 rsync_initial_timeout = 15
4536 if settings.has_key("RSYNC_RETRIES"):
4537 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
4538 maxretries=int(settings["RSYNC_RETRIES"])
4540 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
4541 except SystemExit, e:
4542 raise # Needed else can't exit
4544 maxretries=3 #default number of retries
4547 user_name, hostname, port = re.split(
4548 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
4551 if user_name is None:
4553 updatecache_flg=True
4554 all_rsync_opts = set(rsync_opts)
4555 lexer = shlex.shlex(StringIO.StringIO(
4556 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")), posix=True)
4557 lexer.whitespace_split = True
4558 extra_rsync_opts = list(lexer)
4560 all_rsync_opts.update(extra_rsync_opts)
4561 family = socket.AF_INET
4562 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
4563 family = socket.AF_INET
4564 elif socket.has_ipv6 and \
4565 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
4566 family = socket.AF_INET6
4573 for addrinfo in socket.getaddrinfo(
4574 hostname, None, family, socket.SOCK_STREAM):
4575 if addrinfo[0] == socket.AF_INET6:
4576 # IPv6 addresses need to be enclosed in square brackets
4577 ips.append("[%s]" % addrinfo[4][0])
4579 ips.append(addrinfo[4][0])
4580 from random import shuffle
4582 except SystemExit, e:
4583 raise # Needed else can't exit
4584 except Exception, e:
4585 print "Notice:",str(e)
4590 dosyncuri = syncuri.replace(
4591 "//" + user_name + hostname + port + "/",
4592 "//" + user_name + ips[0] + port + "/", 1)
4593 except SystemExit, e:
4594 raise # Needed else can't exit
4595 except Exception, e:
4596 print "Notice:",str(e)
4600 if "--ask" in myopts:
4601 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
4606 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
4607 if "--quiet" not in myopts:
4608 print ">>> Starting rsync with "+dosyncuri+"..."
4610 emergelog(xterm_titles,
4611 ">>> Starting retry %d of %d with %s" % \
4612 (retries,maxretries,dosyncuri))
4613 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
4615 if mytimestamp != 0 and "--quiet" not in myopts:
4616 print ">>> Checking server timestamp ..."
4618 rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
4620 if "--debug" in myopts:
4625 # Even if there's no timestamp available locally, fetch the
4626 # timestamp anyway as an initial probe to verify that the server is
4627 # responsive. This protects us from hanging indefinitely on a
4628 # connection attempt to an unresponsive server which rsync's
4629 # --timeout option does not prevent.
4631 mycommand = rsynccommand[:]
4632 mycommand.append(dosyncuri.rstrip("/") + \
4633 "/metadata/timestamp.chk")
4634 mycommand.append(tmpservertimestampfile)
4638 def timeout_handler(signum, frame):
4639 raise portage.exception.PortageException("timed out")
4640 signal.signal(signal.SIGALRM, timeout_handler)
4641 # Timeout here in case the server is unresponsive. The
4642 # --timeout rsync option doesn't apply to the initial
4643 # connection attempt.
4644 if rsync_initial_timeout:
4645 signal.alarm(rsync_initial_timeout)
4647 mypids.extend(portage.process.spawn(
4648 mycommand, env=settings.environ(), returnpid=True))
4649 exitcode = os.waitpid(mypids[0], 0)[1]
4650 content = portage.grabfile(tmpservertimestampfile)
4652 if rsync_initial_timeout:
4655 os.unlink(tmpservertimestampfile)
4658 except portage.exception.PortageException, e:
4662 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
4663 os.kill(mypids[0], signal.SIGTERM)
4664 os.waitpid(mypids[0], 0)
4665 # This is the same code rsync uses for timeout.
4668 if exitcode != os.EX_OK:
4670 exitcode = (exitcode & 0xff) << 8
4672 exitcode = exitcode >> 8
4674 portage.process.spawned_pids.remove(mypids[0])
4677 servertimestamp = time.mktime(time.strptime(
4678 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
4679 except (OverflowError, ValueError):
4681 del mycommand, mypids, content
4682 if exitcode == os.EX_OK:
4683 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4684 emergelog(xterm_titles,
4685 ">>> Cancelling sync -- Already current.")
4688 print ">>> Timestamps on the server and in the local repository are the same."
4689 print ">>> Cancelling all further sync action. You are already up to date."
4691 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4695 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4696 emergelog(xterm_titles,
4697 ">>> Server out of date: %s" % dosyncuri)
4700 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4702 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4705 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4707 mycommand = rsynccommand + [dosyncuri+"/", myportdir]
4708 exitcode = portage.process.spawn(mycommand,
4709 env=settings.environ())
4710 if exitcode in [0,1,3,4,11,14,20,21]:
4712 elif exitcode in [1,3,4,11,14,20,21]:
4715 # Code 2 indicates protocol incompatibility, which is expected
4716 # for servers with protocol < 29 that don't support
4717 # --prune-empty-directories. Retry for a server that supports
4718 # at least rsync protocol version 29 (>=rsync-2.6.4).
4723 if retries<=maxretries:
4724 print ">>> Retrying..."
4729 updatecache_flg=False
4733 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4737 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4738 print darkred("!!!")+green(" that your SYNC statement is proper.")
4739 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4741 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4742 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4743 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4744 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4745 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4747 print darkred("!!!")+green(" Rsync was killed before it finished.")
4749 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4750 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4751 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4752 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4753 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4756 elif syncuri[:6]=="cvs://":
4757 if not os.path.exists("/usr/bin/cvs"):
4758 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4759 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4762 cvsdir=os.path.dirname(myportdir)
4763 if not os.path.exists(myportdir+"/CVS"):
4765 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4766 if os.path.exists(cvsdir+"/gentoo-x86"):
4767 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4772 if e.errno != errno.ENOENT:
4774 "!!! existing '%s' directory; exiting.\n" % myportdir)
4777 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4778 print "!!! cvs checkout error; exiting."
4780 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4783 print ">>> Starting cvs update with "+syncuri+"..."
4784 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4785 myportdir, settings, free=1)
4786 if retval != os.EX_OK:
4790 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4793 if updatecache_flg and \
4794 myaction != "metadata" and \
4795 "metadata-transfer" not in settings.features:
4796 updatecache_flg = False
4798 # Reload the whole config from scratch.
4799 settings, trees, mtimedb = load_emerge_config(trees=trees)
4800 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4802 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4803 action_metadata(settings, portdb, myopts)
4805 if portage._global_updates(trees, mtimedb["updates"]):
4807 # Reload the whole config from scratch.
4808 settings, trees, mtimedb = load_emerge_config(trees=trees)
4809 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4811 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4812 mypvs = portage.best(
4813 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4815 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4817 if myaction != "metadata":
4818 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4819 retval = portage.process.spawn(
4820 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4821 dosyncuri], env=settings.environ())
4822 if retval != os.EX_OK:
4823 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4825 if(mybestpv != mypvs) and not "--quiet" in myopts:
4827 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4828 print red(" * ")+"that you update portage now, before any other packages are updated."
4830 print red(" * ")+"To update portage, run 'emerge portage' now."
4833 display_news_notification(trees)
4835 def action_metadata(settings, portdb, myopts):
4836 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4837 old_umask = os.umask(0002)
4838 cachedir = os.path.normpath(settings.depcachedir)
4839 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4840 "/lib", "/opt", "/proc", "/root", "/sbin",
4841 "/sys", "/tmp", "/usr", "/var"]:
4842 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4843 "ROOT DIRECTORY ON YOUR SYSTEM."
4844 print >> sys.stderr, \
4845 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4847 if not os.path.exists(cachedir):
4850 ec = portage.eclass_cache.cache(portdb.porttree_root)
4851 myportdir = os.path.realpath(settings["PORTDIR"])
4852 cm = settings.load_best_module("portdbapi.metadbmodule")(
4853 myportdir, "metadata/cache", portage.auxdbkeys[:])
4855 from portage.cache import util
4857 class percentage_noise_maker(util.quiet_mirroring):
4858 def __init__(self, dbapi):
4860 self.cp_all = dbapi.cp_all()
4861 l = len(self.cp_all)
4862 self.call_update_min = 100000000
4863 self.min_cp_all = l/100.0
4868 for x in self.cp_all:
4870 if self.count > self.min_cp_all:
4871 self.call_update_min = 0
4873 for y in self.dbapi.cp_list(x):
4875 self.call_update_mine = 0
4877 def update(self, *arg):
4878 try: self.pstr = int(self.pstr) + 1
4879 except ValueError: self.pstr = 1
4880 sys.stdout.write("%s%i%%" % \
4881 ("\b" * (len(str(self.pstr))+1), self.pstr))
4883 self.call_update_min = 10000000
4885 def finish(self, *arg):
4886 sys.stdout.write("\b\b\b\b100%\n")
4889 if "--quiet" in myopts:
4890 def quicky_cpv_generator(cp_all_list):
4891 for x in cp_all_list:
4892 for y in portdb.cp_list(x):
4894 source = quicky_cpv_generator(portdb.cp_all())
4895 noise_maker = portage.cache.util.quiet_mirroring()
4897 noise_maker = source = percentage_noise_maker(portdb)
4898 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4899 eclass_cache=ec, verbose_instance=noise_maker)
4904 def action_regen(settings, portdb):
4905 xterm_titles = "notitles" not in settings.features
4906 emergelog(xterm_titles, " === regen")
4907 #regenerate cache entries
4908 print "Regenerating cache entries... "
4910 os.close(sys.stdin.fileno())
4911 except SystemExit, e:
4912 raise # Needed else can't exit
4916 mynodes = portdb.cp_all()
4917 from portage.cache.cache_errors import CacheError
4919 for mytree in portdb.porttrees:
4921 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4922 except CacheError, e:
4923 print "\n error listing cache entries for " + \
4924 "'%s': %s, continuing..." % (mytree, e)
4929 mymatches = portdb.cp_list(x)
4930 portage.writemsg_stdout("processing %s\n" % x)
4933 foo = portdb.aux_get(y,["DEPEND"])
4934 except SystemExit, e:
4935 # sys.exit is an exception... And consequently, we can't catch it.
4937 except Exception, e:
4938 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4940 for mytree in portdb.porttrees:
4941 if portdb.findname2(y, mytree=mytree)[0]:
4942 dead_nodes[mytree].discard(y)
4944 for mytree, nodes in dead_nodes.iteritems():
4945 auxdb = portdb.auxdb[mytree]
4949 except (KeyError, CacheError):
4953 def action_config(settings, trees, myopts, myfiles):
4954 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4955 print red("!!! config can only take a single package atom at this time\n")
4957 if not is_valid_package_atom(myfiles[0]):
4958 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4960 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4961 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4965 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4966 except ValueError, e:
4967 # Multiple matches thrown from cpv_expand
4970 print "No packages found.\n"
4973 if "--ask" in myopts:
4975 print "Please select a package to configure:"
4979 options.append(str(idx))
4980 print options[-1]+") "+pkg
4983 idx = userquery("Selection?", options)
4986 pkg = pkgs[int(idx)-1]
4988 print "The following packages available:"
4991 print "\nPlease use a specific atom or the --ask option."
4997 if "--ask" in myopts:
4998 if userquery("Ready to configure "+pkg+"?") == "No":
5001 print "Configuring pkg..."
5003 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
5004 mysettings = portage.config(clone=settings)
5005 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
5006 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
5007 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
5010 def action_info(settings, trees, myopts, myfiles):
5011 unameout=commands.getstatusoutput("uname -mrp")[1]
5012 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5013 settings.profile_path, settings["CHOST"],
5014 trees[settings["ROOT"]]["vartree"].dbapi)
5016 header_title = "System Settings"
5018 print header_width * "="
5019 print header_title.rjust(int(header_width/2 + len(header_title)/2))
5020 print header_width * "="
5021 print "System uname: "+unameout
5022 gentoo_release = portage.grabfile(os.path.join(
5023 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
5025 print gentoo_release[0]
5027 print "Unknown Host Operating System"
5028 lastSync = portage.grabfile(os.path.join(
5029 settings["PORTDIR"], "metadata", "timestamp.chk"))
5030 print "Timestamp of tree:",
5036 output=commands.getstatusoutput("distcc --version")
5038 print str(output[1].split("\n",1)[0]),
5039 if "distcc" in settings.features:
5044 output=commands.getstatusoutput("ccache -V")
5046 print str(output[1].split("\n",1)[0]),
5047 if "ccache" in settings.features:
5052 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
5053 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
5054 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
5055 myvars = portage.util.unique_array(myvars)
5059 if portage.isvalidatom(x):
5060 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
5061 pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
5062 pkg_matches.sort(portage.pkgcmp)
5064 for pn, ver, rev in pkg_matches:
5066 pkgs.append(ver + "-" + rev)
5070 pkgs = ", ".join(pkgs)
5071 print "%-20s %s" % (x+":", pkgs)
5073 print "%-20s %s" % (x+":", "[NOT VALID]")
5075 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
5077 if "--verbose" in myopts:
5078 myvars=settings.keys()
5080 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
5081 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
5082 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
5083 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
5085 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
5087 myvars = portage.util.unique_array(myvars)
5093 print '%s="%s"' % (x, settings[x])
5095 use = set(settings["USE"].split())
5096 use_expand = settings["USE_EXPAND"].split()
5098 for varname in use_expand:
5099 flag_prefix = varname.lower() + "_"
5101 if f.startswith(flag_prefix):
5105 print 'USE="%s"' % " ".join(use),
5106 for varname in use_expand:
5107 myval = settings.get(varname)
5109 print '%s="%s"' % (varname, myval),
5112 unset_vars.append(x)
5114 print "Unset: "+", ".join(unset_vars)
5117 if "--debug" in myopts:
5118 for x in dir(portage):
5119 module = getattr(portage, x)
5120 if "cvs_id_string" in dir(module):
5121 print "%s: %s" % (str(x), str(module.cvs_id_string))
5123 # See if we can find any packages installed matching the strings
5124 # passed on the command line
5126 vardb = trees[settings["ROOT"]]["vartree"].dbapi
5127 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5129 mypkgs.extend(vardb.match(x))
5131 # If some packages were found...
5133 # Get our global settings (we only print stuff if it varies from
5134 # the current config)
5135 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
5136 auxkeys = mydesiredvars + [ "USE", "IUSE"]
5138 pkgsettings = portage.config(clone=settings)
5140 for myvar in mydesiredvars:
5141 global_vals[myvar] = set(settings.get(myvar, "").split())
5143 # Loop through each package
5144 # Only print settings if they differ from global settings
5145 header_printed = False
5147 # Get all package specific variables
5148 auxvalues = vardb.aux_get(pkg, auxkeys)
5150 for i in xrange(len(auxkeys)):
5151 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
5153 for myvar in mydesiredvars:
5154 # If the package variable doesn't match the
5155 # current global variable, something has changed
5156 # so set diff_found so we know to print
5157 if valuesmap[myvar] != global_vals[myvar]:
5158 diff_values[myvar] = valuesmap[myvar]
5159 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
5160 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
5162 # If a matching ebuild is no longer available in the tree, maybe it
5163 # would make sense to compare against the flags for the best
5164 # available version with the same slot?
5166 if portdb.cpv_exists(pkg):
5168 pkgsettings.setcpv(pkg, mydb=mydb)
5169 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
5171 diff_values["USE"] = valuesmap["USE"]
5172 # If a difference was found, print the info for
5176 # If we have not yet printed the header,
5178 if not header_printed:
5179 header_title = "Package Settings"
5180 print header_width * "="
5181 print header_title.rjust(int(header_width/2 + len(header_title)/2))
5182 print header_width * "="
5183 header_printed = True
5185 # Print package info
5186 print "%s was built with the following:" % pkg
5187 for myvar in mydesiredvars + ["USE"]:
5188 if myvar in diff_values:
5189 mylist = list(diff_values[myvar])
5191 print "%s=\"%s\"" % (myvar, " ".join(mylist))
5194 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
5196 print "emerge: no search terms provided."
5198 searchinstance = search(settings, portdb,
5199 vartree, spinner, "--searchdesc" in myopts,
5200 "--quiet" not in myopts)
5201 for mysearch in myfiles:
5203 searchinstance.execute(mysearch)
5204 except re.error, comment:
5205 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
5207 searchinstance.output()
5209 def action_depclean(settings, trees, ldpath_mtimes,
5211 # Kill packages that aren't explicitly merged or are required as a
5212 # dependency of another package. World file is explicit.
5214 warn_prefix = colorize("BAD", "*** WARNING *** ")
5216 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
5217 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
5218 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
5220 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
5221 print warn_prefix + "mistakes. Packages that are part of the world set will always"
5222 print warn_prefix + "be kept. They can be manually added to this set with"
5223 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
5224 print warn_prefix + "package.provided (see portage(5)) will be removed by"
5225 print warn_prefix + "depclean, even if they are part of the world set."
5227 print warn_prefix + "As a safety measure, depclean will not remove any packages"
5228 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
5229 print warn_prefix + "consequence, it is often necessary to run "
5230 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
5232 xterm_titles = "notitles" not in settings.features
5233 myroot = settings["ROOT"]
5234 dep_check_trees = {}
5235 dep_check_trees[myroot] = {}
5236 dep_check_trees[myroot]["vartree"] = \
5237 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
5238 vardb = dep_check_trees[myroot]["vartree"].dbapi
5239 # Constrain dependency selection to the installed packages.
5240 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
5241 system_set = SystemSet(settings)
5242 syslist = list(system_set)
5243 world_set = WorldSet(settings)
5245 worldlist = list(world_set)
5246 fakedb = portage.fakedbapi(settings=settings)
5247 myvarlist = vardb.cpv_all()
5250 print "\n!!! You have no system list.",
5252 print "\n!!! You have no world file.",
5254 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
5256 if not (syslist and worldlist and myvarlist):
5257 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
5258 print " break your installation.\n"
5259 if "--pretend" not in myopts:
5260 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
5262 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
5263 emergelog(xterm_titles, " >>> depclean")
5265 if "--quiet" not in myopts:
5266 print "\nCalculating dependencies ",
5270 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
5271 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
5273 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
5274 metadata_keys = ["PROVIDE", "SLOT", "USE"]
5276 while remaining_atoms:
5277 atom, parent, priority = remaining_atoms.pop()
5278 pkgs = vardb.match(atom)
5280 if not atom.startswith("!") and priority == hard:
5281 unresolveable.setdefault(atom, []).append(parent)
5283 if len(pkgs) > 1 and parent != "world":
5284 # Prune all but the best matching slot, since that's all that a
5285 # deep world update would pull in. Don't prune if this atom comes
5286 # directly from world though, since world atoms are greedy when
5287 # they don't specify a slot.
5288 pkgs = [portage.best(pkgs)]
5290 if fakedb.cpv_exists(pkg):
5293 fakedb.cpv_inject(pkg)
5294 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
5296 if myopts.get("--with-bdeps", "y") == "y":
5297 mydeps.append((myaux["DEPEND"], soft))
5299 mydeps.append((" ".join(myaux.values()), hard))
5300 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
5301 for depstr, priority in mydeps:
5306 if "--debug" in myopts:
5308 print "Parent: ", pkg
5309 print "Depstring:", depstr
5311 if priority == soft:
5317 portage.dep._dep_check_strict = False
5318 success, atoms = portage.dep_check(depstr, None, settings,
5319 myuse=usedef, trees=dep_check_trees, myroot=myroot)
5321 portage.dep._dep_check_strict = True
5323 show_invalid_depstring_notice(
5324 ("installed", myroot, pkg, "nomerge"),
5328 if "--debug" in myopts:
5329 print "Candidates:", atoms
5332 remaining_atoms.append((atom, pkg, priority))
5334 if "--quiet" not in myopts:
5335 print "\b\b... done!\n"
5338 print "Dependencies could not be completely resolved due to"
5339 print "the following required packages not being installed:"
5341 for atom in unresolveable:
5342 print atom, "required by", " ".join(unresolveable[atom])
5344 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
5345 print "depclean? It may be necessary to manually uninstall packages that no longer"
5346 print "exist in the portage tree since it may not be possible to satisfy their"
5347 print "dependencies. Also, be aware of the --with-bdeps option that is documented"
5348 print "in " + good("`man emerge`") + "."
5352 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
5355 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
5356 "unmerge", cleanlist, ldpath_mtimes)
5358 print "Packages installed: "+str(len(myvarlist))
5359 print "Packages in world: "+str(len(worldlist))
5360 print "Packages in system: "+str(len(syslist))
5361 print "Unique package names: "+str(len(myvarlist))
5362 print "Required packages: "+str(len(fakedb.cpv_all()))
5363 if "--pretend" in myopts:
5364 print "Number to remove: "+str(len(cleanlist))
5366 print "Number removed: "+str(len(cleanlist))
5368 def action_build(settings, trees, mtimedb,
5369 myopts, myaction, myfiles, spinner):
5370 ldpath_mtimes = mtimedb["ldpath"]
5372 if "--quiet" not in myopts and \
5373 ("--pretend" in myopts or "--ask" in myopts or \
5374 "--tree" in myopts or "--verbose" in myopts):
5376 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5380 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
5382 print darkgreen("These are the packages that would be %s, in reverse order:") % action
5386 print darkgreen("These are the packages that would be %s, in order:") % action
5389 # validate the state of the resume data
5390 # so that we can make assumptions later.
5391 for k in ("resume", "resume_backup"):
5393 if "mergelist" in mtimedb[k]:
5394 if not mtimedb[k]["mergelist"]:
5399 if "--resume" in myopts and \
5400 ("resume" in mtimedb or
5401 "resume_backup" in mtimedb):
5402 if "resume" not in mtimedb:
5403 mtimedb["resume"] = mtimedb["resume_backup"]
5404 del mtimedb["resume_backup"]
5406 # XXX: "myopts" is a list for backward compatibility.
5407 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
5409 for opt in ("--skipfirst", "--ask", "--tree"):
5410 myresumeopts.pop(opt, None)
5412 for myopt, myarg in myopts.iteritems():
5413 if myopt not in myresumeopts:
5414 myresumeopts[myopt] = myarg
5417 # Adjust config according to options of the command being resumed.
5418 for myroot in trees:
5419 mysettings = trees[myroot]["vartree"].settings
5421 adjust_config(myopts, mysettings)
5423 del myroot, mysettings
5425 myparams = create_depgraph_params(myopts, myaction)
5426 if "--quiet" not in myopts and "--nodeps" not in myopts:
5427 print "Calculating dependencies ",
5428 mydepgraph = depgraph(settings, trees,
5429 myopts, myparams, spinner)
5430 if "--quiet" not in myopts and "--nodeps" not in myopts:
5431 print "\b\b... done!"
5433 if ("--resume" in myopts):
5434 print darkgreen("emerge: It seems we have nothing to resume...")
5437 myparams = create_depgraph_params(myopts, myaction)
5438 if myaction in ["system","world"]:
5439 if "--quiet" not in myopts and "--nodeps" not in myopts:
5440 print "Calculating",myaction,"dependencies ",
5442 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
5443 if not mydepgraph.xcreate(myaction):
5444 print "!!! Depgraph creation failed."
5446 if "--quiet" not in myopts and "--nodeps" not in myopts:
5447 print "\b\b... done!"
5449 if "--quiet" not in myopts and "--nodeps" not in myopts:
5450 print "Calculating dependencies ",
5452 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
5454 retval, favorites = mydepgraph.select_files(myfiles)
5455 except portage.exception.PackageNotFound, e:
5456 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
5460 if "--quiet" not in myopts and "--nodeps" not in myopts:
5461 print "\b\b... done!"
5463 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
5464 sys.stderr.write(red("The following binaries are not available for merging...\n"))
5466 if mydepgraph.missingbins:
5467 for x in mydepgraph.missingbins:
5468 sys.stderr.write(" "+str(x)+"\n")
5469 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
5472 if "--pretend" not in myopts and \
5473 ("--ask" in myopts or "--tree" in myopts or \
5474 "--verbose" in myopts) and \
5475 not ("--quiet" in myopts and "--ask" not in myopts):
5476 if "--resume" in myopts:
5477 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5478 mymergelist = mtimedb["resume"]["mergelist"]
5479 if "--skipfirst" in myopts:
5480 mymergelist = mymergelist[1:]
5481 if len(mymergelist) == 0:
5482 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5484 favorites = mtimedb["resume"]["favorites"]
5485 retval = mydepgraph.display(mymergelist, favorites=favorites)
5486 if retval != os.EX_OK:
5488 prompt="Would you like to resume merging these packages?"
5490 retval = mydepgraph.display(
5491 mydepgraph.altlist(reversed=("--tree" in myopts)),
5492 favorites=favorites)
5493 if retval != os.EX_OK:
5496 for x in mydepgraph.altlist():
5497 if x[0] != "blocks" and x[3] != "nomerge":
5499 #check for blocking dependencies
5500 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
5501 print "\n!!! Error: The above package list contains packages which cannot be installed"
5502 print "!!! at the same time on the same system."
5503 if "--quiet" not in myopts:
5504 show_blocker_docs_link()
5507 if "--noreplace" in myopts and favorites:
5510 print " %s %s" % (good("*"), x)
5511 prompt="Would you like to add these packages to your world favorites?"
5512 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5513 prompt="Nothing to merge; would you like to auto-clean packages?"
5516 print "Nothing to merge; quitting."
5519 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5520 prompt="Would you like to fetch the source files for these packages?"
5522 prompt="Would you like to merge these packages?"
5524 if "--ask" in myopts and userquery(prompt) == "No":
5529 # Don't ask again (e.g. when auto-cleaning packages after merge)
5530 myopts.pop("--ask", None)
5532 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5533 if ("--resume" in myopts):
5534 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5535 mymergelist = mtimedb["resume"]["mergelist"]
5536 if "--skipfirst" in myopts:
5537 mymergelist = mymergelist[1:]
5538 if len(mymergelist) == 0:
5539 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5541 favorites = mtimedb["resume"]["favorites"]
5542 retval = mydepgraph.display(mymergelist, favorites=favorites)
5543 if retval != os.EX_OK:
5546 retval = mydepgraph.display(
5547 mydepgraph.altlist(reversed=("--tree" in myopts)),
5548 favorites=favorites)
5549 if retval != os.EX_OK:
5551 if "--buildpkgonly" in myopts and \
5552 not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5553 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5554 print "!!! You have to merge the dependencies before you can build this package.\n"
5557 if ("--buildpkgonly" in myopts):
5558 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5559 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5560 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
5563 if ("--resume" in myopts):
5564 favorites=mtimedb["resume"]["favorites"]
5565 mergetask = MergeTask(settings, trees, myopts)
5566 if "--fetchonly" in myopts:
5567 """ parallel-fetch uses --resume --fetchonly and we don't want
5568 it to write the mtimedb"""
5569 mtimedb.filename = None
5570 time.sleep(3) # allow the parent to have first fetch
5572 retval = mergetask.merge(
5573 mtimedb["resume"]["mergelist"], favorites, mtimedb)
5574 if retval != os.EX_OK:
5577 if "resume" in mtimedb and \
5578 "mergelist" in mtimedb["resume"] and \
5579 len(mtimedb["resume"]["mergelist"]) > 1:
5580 mtimedb["resume_backup"] = mtimedb["resume"]
5581 del mtimedb["resume"]
5583 mtimedb["resume"]={}
5584 # XXX: Stored as a list for backward compatibility.
5585 mtimedb["resume"]["myopts"] = \
5586 [k for k in myopts if myopts[k] is True]
5587 mtimedb["resume"]["favorites"]=favorites
5588 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5589 for pkgline in mydepgraph.altlist():
5590 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5591 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
5592 tmpsettings = portage.config(clone=settings)
5594 if settings.get("PORTAGE_DEBUG", "") == "1":
5596 retval = portage.doebuild(
5597 y, "digest", settings["ROOT"], tmpsettings, edebug,
5598 ("--pretend" in myopts),
5599 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
5601 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5603 for pkg in mydepgraph.altlist():
5604 if pkg[0] != "blocks":
5607 pkglist = mydepgraph.altlist()
5609 mydepgraph.saveNomergeFavorites()
5611 mergetask = MergeTask(settings, trees, myopts)
5612 retval = mergetask.merge(pkglist, favorites, mtimedb)
5613 if retval != os.EX_OK:
5616 if mtimedb.has_key("resume"):
5617 del mtimedb["resume"]
5618 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5619 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5620 vartree = trees[settings["ROOT"]]["vartree"]
5621 unmerge(settings, myopts, vartree, "clean", ["world"],
5622 ldpath_mtimes, autoclean=1)
5624 portage.writemsg_stdout(colorize("WARN", "WARNING:")
5625 + " AUTOCLEAN is disabled. This can cause serious"
5626 + " problems due to overlapping packages.\n")
5628 def multiple_actions(action1, action2):
5629 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
5630 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
5633 def parse_opts(tmpcmdline, silent=False):
5638 global actions, options, shortmapping
5640 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
5641 argument_options = {
5643 "help":"specify the location for portage configuration files",
5647 "help":"enable or disable color output",
5649 "choices":("y", "n")
5652 "help":"include unnecessary build time dependencies",
5654 "choices":("y", "n")
5657 "help":"specify conditions to trigger package reinstallation",
5659 "choices":["changed-use"]
5663 from optparse import OptionParser
5664 parser = OptionParser()
5665 if parser.has_option("--help"):
5666 parser.remove_option("--help")
5668 for action_opt in actions:
5669 parser.add_option("--" + action_opt, action="store_true",
5670 dest=action_opt.replace("-", "_"), default=False)
5671 for myopt in options:
5672 parser.add_option(myopt, action="store_true",
5673 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5674 for shortopt, longopt in shortmapping.iteritems():
5675 parser.add_option("-" + shortopt, action="store_true",
5676 dest=longopt.lstrip("--").replace("-", "_"), default=False)
5677 for myalias, myopt in longopt_aliases.iteritems():
5678 parser.add_option(myalias, action="store_true",
5679 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5681 for myopt, kwargs in argument_options.iteritems():
5682 parser.add_option(myopt,
5683 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
5685 myoptions, myargs = parser.parse_args(args=tmpcmdline)
5687 for myopt in options:
5688 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
5690 myopts[myopt] = True
5692 for myopt in argument_options:
5693 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
5697 for action_opt in actions:
5698 v = getattr(myoptions, action_opt.replace("-", "_"))
5701 multiple_actions(myaction, action_opt)
5703 myaction = action_opt
5706 if x in actions and myaction != "search":
5707 if not silent and x not in ["system", "world"]:
5708 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
5709 # special case "search" so people can search for action terms, e.g. emerge -s sync
5711 multiple_actions(myaction, x)
5717 if "--nocolor" in myopts:
5719 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
5720 "use '--color=n' instead.\n")
5721 del myopts["--nocolor"]
5722 myopts["--color"] = "n"
5724 return myaction, myopts, myfiles
5726 def validate_ebuild_environment(trees):
5727 for myroot in trees:
5728 mysettings = trees[myroot]["vartree"].settings
5729 for var in "ARCH", "USERLAND":
5730 if mysettings.get(var):
5732 print >> sys.stderr, bad(("\a!!! %s is not set... " % var) + \
5733 "Are you missing the '%setc/make.profile' symlink?" % \
5734 mysettings["PORTAGE_CONFIGROOT"])
5735 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5736 "Is your portage tree complete?\n")
5738 del myroot, mysettings
5740 def load_emerge_config(trees=None):
5742 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5743 kwargs[k] = os.environ.get(envvar, None)
5744 trees = portage.create_trees(trees=trees, **kwargs)
5746 settings = trees["/"]["vartree"].settings
5748 for myroot in trees:
5750 settings = trees[myroot]["vartree"].settings
5753 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5754 mtimedb = portage.MtimeDB(mtimedbfile)
5755 return settings, trees, mtimedb
5757 def adjust_config(myopts, settings):
5758 """Make emerge specific adjustments to the config."""
5760 # To enhance usability, make some vars case insensitive by forcing them to
5762 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5763 if myvar in settings:
5764 settings[myvar] = settings[myvar].lower()
5765 settings.backup_changes(myvar)
5768 # Kill noauto as it will break merges otherwise.
5769 if "noauto" in settings.features:
5770 while "noauto" in settings.features:
5771 settings.features.remove("noauto")
5772 settings["FEATURES"] = " ".join(settings.features)
5773 settings.backup_changes("FEATURES")
5777 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5778 except ValueError, e:
5779 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5780 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5781 settings["CLEAN_DELAY"], noiselevel=-1)
5782 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5783 settings.backup_changes("CLEAN_DELAY")
5785 EMERGE_WARNING_DELAY = 10
5787 EMERGE_WARNING_DELAY = int(settings.get(
5788 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5789 except ValueError, e:
5790 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5791 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5792 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5793 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5794 settings.backup_changes("EMERGE_WARNING_DELAY")
5796 if "--quiet" in myopts:
5797 settings["PORTAGE_QUIET"]="1"
5798 settings.backup_changes("PORTAGE_QUIET")
5800 # Set so that configs will be merged regardless of remembered status
5801 if ("--noconfmem" in myopts):
5802 settings["NOCONFMEM"]="1"
5803 settings.backup_changes("NOCONFMEM")
5805 # Set various debug markers... They should be merged somehow.
5808 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5809 if PORTAGE_DEBUG not in (0, 1):
5810 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5811 PORTAGE_DEBUG, noiselevel=-1)
5812 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5815 except ValueError, e:
5816 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5817 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5818 settings["PORTAGE_DEBUG"], noiselevel=-1)
5820 if "--debug" in myopts:
5822 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5823 settings.backup_changes("PORTAGE_DEBUG")
5825 if settings.get("NOCOLOR") not in ("yes","true"):
5826 portage.output.havecolor = 1
5828 """The explicit --color < y | n > option overrides the NOCOLOR environment
5829 variable and stdout auto-detection."""
5830 if "--color" in myopts:
5831 if "y" == myopts["--color"]:
5832 portage.output.havecolor = 1
5833 settings["NOCOLOR"] = "false"
5835 portage.output.havecolor = 0
5836 settings["NOCOLOR"] = "true"
5837 settings.backup_changes("NOCOLOR")
5838 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5839 portage.output.havecolor = 0
5840 settings["NOCOLOR"] = "true"
5841 settings.backup_changes("NOCOLOR")
5844 global portage # NFC why this is necessary now - genone
5845 # Disable color until we're sure that it should be enabled (after
5846 # EMERGE_DEFAULT_OPTS has been parsed).
5847 portage.output.havecolor = 0
5848 # This first pass is just for options that need to be known as early as
5849 # possible, such as --config-root. They will be parsed again later,
5850 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5851 # the value of --config-root).
5852 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5853 if "--debug" in myopts:
5854 os.environ["PORTAGE_DEBUG"] = "1"
5855 if "--config-root" in myopts:
5856 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5858 # Portage needs to ensure a sane umask for the files it creates.
5860 settings, trees, mtimedb = load_emerge_config()
5861 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5864 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5865 except (OSError, ValueError), e:
5866 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5867 settings["PORTAGE_NICENESS"])
5868 portage.writemsg("!!! %s\n" % str(e))
5871 if portage._global_updates(trees, mtimedb["updates"]):
5873 # Reload the whole config from scratch.
5874 settings, trees, mtimedb = load_emerge_config(trees=trees)
5875 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5877 xterm_titles = "notitles" not in settings.features
5880 if "--ignore-default-opts" not in myopts:
5881 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5882 tmpcmdline.extend(sys.argv[1:])
5883 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5885 if "--digest" in myopts:
5886 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5887 # Reload the whole config from scratch so that the portdbapi internal
5888 # config is updated with new FEATURES.
5889 settings, trees, mtimedb = load_emerge_config(trees=trees)
5890 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5892 for myroot in trees:
5893 mysettings = trees[myroot]["vartree"].settings
5895 adjust_config(myopts, mysettings)
5897 del myroot, mysettings
5899 spinner = stdout_spinner()
5900 if "candy" in settings.features:
5901 spinner.update = spinner.update_scroll
5903 if "--quiet" not in myopts:
5904 portage.deprecated_profile_check()
5906 #Freeze the portdbapi for enhanced performance:
5907 for myroot in trees:
5908 trees[myroot]["porttree"].dbapi.freeze()
5911 if "moo" in myfiles:
5914 Larry loves Gentoo (""" + os.uname()[0] + """)
5916 _______________________
5917 < Have you mooed today? >
5918 -----------------------
5927 if (myaction in ["world", "system"]) and myfiles:
5928 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5932 ext = os.path.splitext(x)[1]
5933 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5934 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5937 if ("--tree" in myopts) and ("--columns" in myopts):
5938 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5941 if ("--quiet" in myopts):
5942 spinner.update = spinner.update_quiet
5943 portage.util.noiselimit = -1
5945 # Always create packages if FEATURES=buildpkg
5946 # Imply --buildpkg if --buildpkgonly
5947 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5948 if "--buildpkg" not in myopts:
5949 myopts["--buildpkg"] = True
5951 # Also allow -S to invoke search action (-sS)
5952 if ("--searchdesc" in myopts):
5953 if myaction and myaction != "search":
5954 myfiles.append(myaction)
5955 if "--search" not in myopts:
5956 myopts["--search"] = True
5959 # Always try and fetch binary packages if FEATURES=getbinpkg
5960 if ("getbinpkg" in settings.features):
5961 myopts["--getbinpkg"] = True
5963 if "--skipfirst" in myopts and "--resume" not in myopts:
5964 myopts["--resume"] = True
5966 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5967 myopts["--usepkgonly"] = True
5969 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5970 myopts["--getbinpkg"] = True
5972 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5973 myopts["--usepkg"] = True
5975 # Also allow -K to apply --usepkg/-k
5976 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5977 myopts["--usepkg"] = True
5979 # Allow -p to remove --ask
5980 if ("--pretend" in myopts) and ("--ask" in myopts):
5981 print ">>> --pretend disables --ask... removing --ask from options."
5984 # forbid --ask when not in a terminal
5985 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5986 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5987 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5991 if settings.get("PORTAGE_DEBUG", "") == "1":
5992 spinner.update = spinner.update_quiet
5994 if "python-trace" in settings.features:
5995 import portage.debug
5996 portage.debug.set_trace(True)
5998 if ("--resume" in myopts):
5999 if "--tree" in myopts:
6000 print "* --tree is currently broken with --resume. Disabling..."
6001 del myopts["--tree"]
6003 if not ("--quiet" in myopts):
6004 if not sys.stdout.isatty() or ("--nospinner" in myopts):
6005 spinner.update = spinner.update_basic
6007 if "--version" in myopts:
6008 print getportageversion(settings["PORTDIR"], settings["ROOT"],
6009 settings.profile_path, settings["CHOST"],
6010 trees[settings["ROOT"]]["vartree"].dbapi)
6012 elif "--help" in myopts:
6013 emerge.help.help(myaction, myopts, portage.output.havecolor)
6016 if "--debug" in myopts:
6017 print "myaction", myaction
6018 print "myopts", myopts
6020 if not myaction and not myfiles and "--resume" not in myopts:
6021 emerge.help.help(myaction, myopts, portage.output.havecolor)
6024 # check if root user is the current user for the actions where emerge needs this
6025 if portage.secpass < 2:
6026 # We've already allowed "--version" and "--help" above.
6027 if "--pretend" not in myopts and myaction not in ("search","info"):
6028 need_superuser = not \
6029 ("--fetchonly" in myopts or \
6030 "--fetch-all-uri" in myopts or \
6031 myaction in ("metadata", "regen") or \
6032 (myaction == "sync" and os.access(settings["PORTDIR"], os.W_OK)))
6033 if portage.secpass < 1 or \
6036 access_desc = "superuser"
6038 access_desc = "portage group"
6039 # Always show portage_group_warning() when only portage group
6040 # access is required but the user is not in the portage group.
6041 from portage.data import portage_group_warning
6042 if "--ask" in myopts:
6043 myopts["--pretend"] = True
6045 print ("%s access is required... " + \
6046 "adding --pretend to options.\n") % access_desc
6047 if portage.secpass < 1 and not need_superuser:
6048 portage_group_warning()
6050 sys.stderr.write(("emerge: %s access is " + \
6051 "required.\n\n") % access_desc)
6052 if portage.secpass < 1 and not need_superuser:
6053 portage_group_warning()
6056 disable_emergelog = False
6057 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
6059 disable_emergelog = True
6061 if myaction in ("search", "info"):
6062 disable_emergelog = True
6063 if disable_emergelog:
6064 """ Disable emergelog for everything except build or unmerge
6065 operations. This helps minimize parallel emerge.log entries that can
6066 confuse log parsers. We especially want it disabled during
6067 parallel-fetch, which uses --resume --fetchonly."""
6069 def emergelog(*pargs, **kargs):
6072 if not "--pretend" in myopts:
6073 emergelog(xterm_titles, "Started emerge on: "+\
6074 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
6077 myelogstr=" ".join(myopts)
6079 myelogstr+=" "+myaction
6081 myelogstr+=" "+" ".join(myfiles)
6082 emergelog(xterm_titles, " *** emerge " + myelogstr)
6084 def emergeexitsig(signum, frame):
6085 signal.signal(signal.SIGINT, signal.SIG_IGN)
6086 signal.signal(signal.SIGTERM, signal.SIG_IGN)
6087 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
6088 sys.exit(100+signum)
6089 signal.signal(signal.SIGINT, emergeexitsig)
6090 signal.signal(signal.SIGTERM, emergeexitsig)
6093 """This gets out final log message in before we quit."""
6094 if "--pretend" not in myopts:
6095 emergelog(xterm_titles, " *** terminating.")
6096 if "notitles" not in settings.features:
6098 portage.atexit_register(emergeexit)
6100 if myaction in ("config", "metadata", "regen", "sync"):
6101 if "--pretend" in myopts:
6102 sys.stderr.write(("emerge: The '%s' action does " + \
6103 "not support '--pretend'.\n") % myaction)
6105 if "sync" == myaction:
6106 action_sync(settings, trees, mtimedb, myopts, myaction)
6107 elif "metadata" == myaction:
6108 action_metadata(settings, portdb, myopts)
6109 elif myaction=="regen":
6110 validate_ebuild_environment(trees)
6111 action_regen(settings, portdb)
6113 elif "config"==myaction:
6114 validate_ebuild_environment(trees)
6115 action_config(settings, trees, myopts, myfiles)
6118 elif "info"==myaction:
6119 action_info(settings, trees, myopts, myfiles)
6122 elif "search"==myaction:
6123 validate_ebuild_environment(trees)
6124 action_search(settings, portdb, trees["/"]["vartree"],
6125 myopts, myfiles, spinner)
6126 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
6127 validate_ebuild_environment(trees)
6128 vartree = trees[settings["ROOT"]]["vartree"]
6129 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
6131 if "--pretend" not in myopts:
6132 post_emerge(trees, mtimedb, os.EX_OK)
6134 elif "depclean"==myaction:
6135 validate_ebuild_environment(trees)
6136 action_depclean(settings, trees, mtimedb["ldpath"],
6138 if "--pretend" not in myopts:
6139 post_emerge(trees, mtimedb, os.EX_OK)
6140 # "update", "system", or just process files:
6142 validate_ebuild_environment(trees)
6143 if "--pretend" not in myopts:
6144 display_news_notification(trees)
6145 retval = action_build(settings, trees, mtimedb,
6146 myopts, myaction, myfiles, spinner)
6147 if "--pretend" not in myopts:
6148 post_emerge(trees, mtimedb, retval)
6150 display_news_notification(trees)
6153 if __name__ == "__main__":
6154 retval = emerge_main()