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.
723 # Unlike world atoms, system atoms are not greedy for slots, so they
724 # can't be safely excluded from world if they are slotted.
725 system_atom = sets["system"].findAtomForPackage(pkg_key, metadata)
727 not portage.dep_getkey(system_atom).startswith("virtual/"):
728 # System virtuals aren't safe to exclude from world since they can
729 # match multiple old-style virtuals but only one of them will be
730 # pulled in by update or depclean.
732 return new_world_atom
734 def filter_iuse_defaults(iuse):
736 if flag.startswith("+") or flag.startswith("-"):
741 class DepPriority(object):
743 This class generates an integer priority level based of various
744 attributes of the dependency relationship. Attributes can be assigned
745 at any time and the new integer value will be generated on calls to the
746 __int__() method. Rich comparison operators are supported.
748 The boolean attributes that affect the integer value are "satisfied",
749 "buildtime", "runtime", and "system". Various combinations of
750 attributes lead to the following priority levels:
752 Combination of properties Priority level
754 not satisfied and buildtime 0
755 not satisfied and runtime -1
756 satisfied and buildtime -2
757 satisfied and runtime -3
758 (none of the above) -4
760 Several integer constants are defined for categorization of priority
763 MEDIUM The upper boundary for medium dependencies.
764 MEDIUM_SOFT The upper boundary for medium-soft dependencies.
765 SOFT The upper boundary for soft dependencies.
766 MIN The lower boundary for soft dependencies.
768 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime", "runtime_post")
773 def __init__(self, **kwargs):
774 for myattr in self.__slots__:
775 if myattr == "__weakref__":
777 myvalue = kwargs.get(myattr, False)
778 setattr(self, myattr, myvalue)
780 if not self.satisfied:
785 if self.runtime_post:
791 if self.runtime_post:
794 def __lt__(self, other):
795 return self.__int__() < other
796 def __le__(self, other):
797 return self.__int__() <= other
798 def __eq__(self, other):
799 return self.__int__() == other
800 def __ne__(self, other):
801 return self.__int__() != other
802 def __gt__(self, other):
803 return self.__int__() > other
804 def __ge__(self, other):
805 return self.__int__() >= other
808 return copy.copy(self)
810 myvalue = self.__int__()
811 if myvalue > self.MEDIUM:
813 if myvalue > self.MEDIUM_SOFT:
815 if myvalue > self.SOFT:
819 class FakeVartree(portage.vartree):
820 """This is implements an in-memory copy of a vartree instance that provides
821 all the interfaces required for use by the depgraph. The vardb is locked
822 during the constructor call just long enough to read a copy of the
823 installed package information. This allows the depgraph to do it's
824 dependency calculations without holding a lock on the vardb. It also
825 allows things like vardb global updates to be done in memory so that the
826 user doesn't necessarily need write access to the vardb in cases where
827 global updates are necessary (updates are performed when necessary if there
828 is not a matching ebuild in the tree)."""
829 def __init__(self, real_vartree, portdb):
830 self.root = real_vartree.root
831 self.settings = real_vartree.settings
832 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
833 vdb_path = os.path.join(self.root, portage.VDB_PATH)
835 # At least the parent needs to exist for the lock file.
836 portage.util.ensure_dirs(vdb_path)
837 except portage.exception.PortageException:
841 if os.access(vdb_path, os.W_OK):
842 vdb_lock = portage.locks.lockdir(vdb_path)
843 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
844 "RESTRICT", "DEPEND", "RDEPEND", "PDEPEND", "repository"]
845 real_dbapi = real_vartree.dbapi
847 for cpv in real_dbapi.cpv_all():
848 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
849 myslot = metadata["SLOT"]
850 mycp = portage.dep_getkey(cpv)
851 myslot_atom = "%s:%s" % (mycp, myslot)
853 mycounter = long(metadata["COUNTER"])
856 metadata["COUNTER"] = str(mycounter)
857 other_counter = slot_counters.get(myslot_atom, None)
858 if other_counter is not None:
859 if other_counter > mycounter:
861 slot_counters[myslot_atom] = mycounter
862 self.dbapi.cpv_inject(cpv, metadata=metadata)
863 real_dbapi.flush_cache()
866 portage.locks.unlockdir(vdb_lock)
867 # Populate the old-style virtuals using the cached values.
868 if not self.settings.treeVirtuals:
869 self.settings.treeVirtuals = portage.util.map_dictlist_vals(
870 portage.getCPFromCPV, self.get_all_provides())
872 # Intialize variables needed for lazy cache pulls of the live ebuild
873 # metadata. This ensures that the vardb lock is released ASAP, without
874 # being delayed in case cache generation is triggered.
875 self._aux_get = self.dbapi.aux_get
876 self.dbapi.aux_get = self._aux_get_wrapper
877 self._aux_get_history = set()
878 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
879 self._portdb = portdb
880 self._global_updates = None
882 def _aux_get_wrapper(self, pkg, wants):
883 if pkg in self._aux_get_history:
884 return self._aux_get(pkg, wants)
885 self._aux_get_history.add(pkg)
887 # Use the live ebuild metadata if possible.
888 live_metadata = dict(izip(self._portdb_keys,
889 self._portdb.aux_get(pkg, self._portdb_keys)))
890 self.dbapi.aux_update(pkg, live_metadata)
891 except (KeyError, portage.exception.PortageException):
892 if self._global_updates is None:
893 self._global_updates = \
894 grab_global_updates(self._portdb.porttree_root)
895 perform_global_updates(
896 pkg, self.dbapi, self._global_updates)
897 return self._aux_get(pkg, wants)
899 def grab_global_updates(portdir):
900 from portage.update import grab_updates, parse_updates
901 updpath = os.path.join(portdir, "profiles", "updates")
903 rawupdates = grab_updates(updpath)
904 except portage.exception.DirectoryNotFound:
907 for mykey, mystat, mycontent in rawupdates:
908 commands, errors = parse_updates(mycontent)
909 upd_commands.extend(commands)
912 def perform_global_updates(mycpv, mydb, mycommands):
913 from portage.update import update_dbentries
914 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
915 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
916 updates = update_dbentries(mycommands, aux_dict)
918 mydb.aux_update(mycpv, updates)
920 class BlockerCache(DictMixin):
921 """This caches blockers of installed packages so that dep_check does not
922 have to be done for every single installed package on every invocation of
923 emerge. The cache is invalidated whenever it is detected that something
924 has changed that might alter the results of dep_check() calls:
925 1) the set of installed packages (including COUNTER) has changed
926 2) the old-style virtuals have changed
928 class BlockerData(object):
929 def __init__(self, counter, atoms):
930 self.counter = counter
933 def __init__(self, myroot, vardb):
935 self._installed_pkgs = set(vardb.cpv_all())
936 self._virtuals = vardb.settings.getvirtuals()
937 self._cache_filename = os.path.join(myroot,
938 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
939 self._cache_version = "1"
940 self._cache_data = None
941 self._modified = False
946 f = open(self._cache_filename)
947 mypickle = cPickle.Unpickler(f)
948 mypickle.find_global = None
949 self._cache_data = mypickle.load()
952 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
954 cache_valid = self._cache_data and \
955 isinstance(self._cache_data, dict) and \
956 self._cache_data.get("version") == self._cache_version and \
957 self._cache_data.get("virtuals") == self._virtuals and \
958 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
960 for pkg in self._installed_pkgs:
961 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
966 self._cache_data = {"version":self._cache_version}
967 self._cache_data["blockers"] = {}
968 self._cache_data["virtuals"] = self._virtuals
969 self._modified = False
972 """If the current user has permission and the internal blocker cache
973 been updated, save it to disk and mark it unmodified. This is called
974 by emerge after it has proccessed blockers for all installed packages.
975 Currently, the cache is only written if the user has superuser
976 privileges (since that's required to obtain a lock), but all users
977 have read access and benefit from faster blocker lookups (as long as
978 the entire cache is still valid). The cache is stored as a pickled
979 dict object with the following format:
983 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
984 "virtuals" : vardb.settings.getvirtuals()
987 if self._modified and \
990 f = portage.util.atomic_ofstream(self._cache_filename)
991 cPickle.dump(self._cache_data, f, -1)
993 portage.util.apply_secpass_permissions(
994 self._cache_filename, gid=portage.portage_gid, mode=0644)
995 except (IOError, OSError), e:
997 self._modified = False
999 def __setitem__(self, cpv, blocker_data):
1001 Update the cache and mark it as modified for a future call to
1004 @param cpv: Package for which to cache blockers.
1006 @param blocker_data: An object with counter and atoms attributes.
1007 @type blocker_data: BlockerData
1009 self._cache_data["blockers"][cpv] = \
1010 (blocker_data.counter, blocker_data.atoms)
1011 self._modified = True
1013 def __getitem__(self, cpv):
1016 @returns: An object with counter and atoms attributes.
1018 return self.BlockerData(*self._cache_data["blockers"][cpv])
1021 """This needs to be implemented so that self.__repr__() doesn't raise
1022 an AttributeError."""
1023 if self._cache_data and "blockers" in self._cache_data:
1024 return self._cache_data["blockers"].keys()
1027 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
1029 from formatter import AbstractFormatter, DumbWriter
1030 f = AbstractFormatter(DumbWriter(maxcol=72))
1032 print "\n\n!!! Invalid or corrupt dependency specification: "
1040 p_type, p_root, p_key, p_status = parent_node
1042 if p_status == "nomerge":
1043 category, pf = portage.catsplit(p_key)
1044 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
1045 msg.append("Portage is unable to process the dependencies of the ")
1046 msg.append("'%s' package. " % p_key)
1047 msg.append("In order to correct this problem, the package ")
1048 msg.append("should be uninstalled, reinstalled, or upgraded. ")
1049 msg.append("As a temporary workaround, the --nodeps option can ")
1050 msg.append("be used to ignore all dependencies. For reference, ")
1051 msg.append("the problematic dependencies can be found in the ")
1052 msg.append("*DEPEND files located in '%s/'." % pkg_location)
1054 msg.append("This package can not be installed. ")
1055 msg.append("Please notify the '%s' package maintainer " % p_key)
1056 msg.append("about this problem.")
1059 f.add_flowing_data(x)
1062 class depgraph(object):
1065 "ebuild":"porttree",
1067 "installed":"vartree"}
1069 def __init__(self, settings, trees, myopts, myparams, spinner):
1070 self.settings = settings
1071 self.target_root = settings["ROOT"]
1072 self.myopts = myopts
1073 self.myparams = myparams
1075 if settings.get("PORTAGE_DEBUG", "") == "1":
1077 self.spinner = spinner
1078 self.pkgsettings = {}
1079 # Maps cpv to digraph node for all nodes added to the graph.
1080 self.pkg_node_map = {}
1081 # Maps slot atom to digraph node for all nodes added to the graph.
1082 self._slot_node_map = {}
1084 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND",
1085 "USE", "IUSE", "PROVIDE", "RESTRICT", "repository"]
1089 for myroot in trees:
1090 self.trees[myroot] = {}
1091 for tree in ("porttree", "bintree"):
1092 self.trees[myroot][tree] = trees[myroot][tree]
1093 self.trees[myroot]["vartree"] = \
1094 FakeVartree(trees[myroot]["vartree"],
1095 trees[myroot]["porttree"].dbapi)
1096 self.pkgsettings[myroot] = portage.config(
1097 clone=self.trees[myroot]["vartree"].settings)
1098 self.pkg_node_map[myroot] = {}
1099 self._slot_node_map[myroot] = {}
1100 vardb = self.trees[myroot]["vartree"].dbapi
1101 self.roots[myroot] = RootConfig(self.trees[myroot])
1102 # This fakedbapi instance will model the state that the vdb will
1103 # have after new packages have been installed.
1104 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
1105 self.mydbapi[myroot] = fakedb
1106 if "--nodeps" not in self.myopts and \
1107 "--buildpkgonly" not in self.myopts:
1108 # --nodeps bypasses this, since it isn't needed in this case
1109 # and the cache pulls might trigger (slow) cache generation.
1110 for pkg in vardb.cpv_all():
1111 self.spinner.update()
1112 fakedb.cpv_inject(pkg,
1113 metadata=dict(izip(self._mydbapi_keys,
1114 vardb.aux_get(pkg, self._mydbapi_keys))))
1116 self.useFlags[myroot] = {}
1117 if "--usepkg" in self.myopts:
1118 self.trees[myroot]["bintree"].populate(
1119 "--getbinpkg" in self.myopts,
1120 "--getbinpkgonly" in self.myopts)
1124 self.digraph=portage.digraph()
1125 # Tracks simple parent/child relationships (PDEPEND relationships are
1127 self._parent_child_digraph = digraph()
1129 self.outdatedpackages=[]
1130 # contains all sets added to the graph
1132 # contains atoms given as arguments
1133 self._sets["args"] = AtomSet()
1134 # contains all atoms from all sets added to the graph, including
1135 # atoms given as arguments
1136 self._set_atoms = AtomSet()
1137 # contains all nodes pulled in by self._set_atoms
1138 self._set_nodes = set()
1139 self.blocker_digraph = digraph()
1140 self.blocker_parents = {}
1141 self._unresolved_blocker_parents = {}
1142 self._slot_collision_info = []
1143 # Slot collision nodes are not allowed to block other packages since
1144 # blocker validation is only able to account for one package per slot.
1145 self._slot_collision_nodes = set()
1146 self._altlist_cache = {}
1147 self._pprovided_args = []
1149 def _show_slot_collision_notice(self, packages):
1150 """Show an informational message advising the user to mask one of the
1151 the packages. In some cases it may be possible to resolve this
1152 automatically, but support for backtracking (removal nodes that have
1153 already been selected) will be required in order to handle all possible
1157 msg.append("\n!!! Multiple versions within a single " + \
1158 "package slot have been \n")
1159 msg.append("!!! pulled into the dependency graph:\n\n")
1160 for node, parents in packages:
1161 msg.append(str(node))
1163 msg.append(" pulled in by\n")
1164 for parent in parents:
1166 msg.append(str(parent))
1169 msg.append(" (no parents)\n")
1171 sys.stderr.write("".join(msg))
1174 if "--quiet" in self.myopts:
1178 msg.append("It may be possible to solve this problem ")
1179 msg.append("by using package.mask to prevent one of ")
1180 msg.append("those packages from being selected. ")
1181 msg.append("However, it is also possible that conflicting ")
1182 msg.append("dependencies exist such that they are impossible to ")
1183 msg.append("satisfy simultaneously. If such a conflict exists in ")
1184 msg.append("the dependencies of two different packages, then those ")
1185 msg.append("packages can not be installed simultaneously.")
1187 from formatter import AbstractFormatter, DumbWriter
1188 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1190 f.add_flowing_data(x)
1194 msg.append("For more information, see MASKED PACKAGES ")
1195 msg.append("section in the emerge man page or refer ")
1196 msg.append("to the Gentoo Handbook.")
1198 f.add_flowing_data(x)
1202 def _reinstall_for_flags(self, forced_flags,
1203 orig_use, orig_iuse, cur_use, cur_iuse):
1204 if "--newuse" in self.myopts:
1205 if orig_iuse.symmetric_difference(
1206 cur_iuse).difference(forced_flags):
1208 elif orig_iuse.intersection(orig_use) != \
1209 cur_iuse.intersection(cur_use):
1211 elif "changed-use" == self.myopts.get("--reinstall"):
1212 if orig_iuse.intersection(orig_use) != \
1213 cur_iuse.intersection(cur_use):
1217 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1218 priority=DepPriority(), rev_dep=False, arg=None):
1220 Fills the digraph with nodes comprised of packages to merge.
1221 mybigkey is the package spec of the package to merge.
1222 myparent is the package depending on mybigkey ( or None )
1223 addme = Should we add this package to the digraph or are we just looking at it's deps?
1224 Think --onlydeps, we need to ignore packages in that case.
1227 #IUSE-aware emerge -> USE DEP aware depgraph
1228 #"no downgrade" emerge
1230 mytype, myroot, mykey = mybigkey
1231 existing_node = None
1233 existing_node = self.pkg_node_map[myroot].get(mykey)
1235 self._parent_child_digraph.add(existing_node, myparent)
1236 if existing_node != myparent:
1237 # Refuse to make a node depend on itself so that the we don't
1238 # don't create a bogus circular dependency in self.altlist().
1239 if rev_dep and myparent:
1240 self.digraph.addnode(myparent, existing_node,
1243 self.digraph.addnode(existing_node, myparent,
1247 if "--nodeps" not in self.myopts:
1248 self.spinner.update()
1249 if mytype == "blocks":
1251 "--buildpkgonly" not in self.myopts and \
1252 "--nodeps" not in self.myopts and \
1253 myparent not in self._slot_collision_nodes:
1254 mybigkey[1] = myparent[1]
1255 self.blocker_parents.setdefault(
1256 tuple(mybigkey), set()).add(myparent)
1259 # select the correct /var database that we'll be checking against
1260 vardbapi = self.trees[myroot]["vartree"].dbapi
1261 portdb = self.trees[myroot]["porttree"].dbapi
1262 bindb = self.trees[myroot]["bintree"].dbapi
1263 pkgsettings = self.pkgsettings[myroot]
1265 # if the package is already on the system, we add a "nomerge"
1266 # directive, otherwise we add a "merge" directive.
1268 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1269 metadata = dict(izip(self._mydbapi_keys,
1270 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1271 if mytype == "ebuild":
1272 pkgsettings.setcpv(mykey, mydb=portdb)
1273 metadata["USE"] = pkgsettings["USE"]
1274 myuse = pkgsettings["USE"].split()
1276 if not arg and myroot == self.target_root:
1278 arg = self._set_atoms.findAtomForPackage(mykey, metadata)
1279 except portage.exception.InvalidDependString, e:
1280 if mytype != "installed":
1281 show_invalid_depstring_notice(tuple(mybigkey+["merge"]),
1282 metadata["PROVIDE"], str(e))
1287 if mytype == "installed":
1289 if addme and mytype != "installed":
1290 # this is where we add the node to the list of packages to merge
1291 if "selective" in self.myparams or not arg:
1292 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1295 """ If we aren't merging, perform the --newuse check.
1296 If the package has new iuse flags or different use flags then if
1297 --newuse is specified, we need to merge the package. """
1298 if merging == 0 and \
1299 ("--newuse" in self.myopts or
1300 "--reinstall" in self.myopts) and \
1301 vardbapi.cpv_exists(mykey):
1302 pkgsettings.setcpv(mykey, mydb=mydbapi)
1303 forced_flags = set()
1304 forced_flags.update(pkgsettings.useforce)
1305 forced_flags.update(pkgsettings.usemask)
1306 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1307 iuses = set(filter_iuse_defaults(metadata["IUSE"].split()))
1308 old_iuse = set(filter_iuse_defaults(
1309 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1310 if self._reinstall_for_flags(
1311 forced_flags, old_use, old_iuse, myuse, iuses):
1314 if addme and merging == 1:
1315 mybigkey.append("merge")
1317 mybigkey.append("nomerge")
1318 jbigkey = tuple(mybigkey)
1321 if merging == 0 and vardbapi.cpv_exists(mykey) and \
1322 mytype != "installed":
1323 mytype = "installed"
1324 mybigkey[0] = "installed"
1326 jbigkey = tuple(mybigkey)
1327 metadata = dict(izip(self._mydbapi_keys,
1328 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1329 myuse = metadata["USE"].split()
1330 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1331 existing_node = self._slot_node_map[myroot].get(
1333 slot_collision = False
1335 e_type, myroot, e_cpv, e_status = existing_node
1337 # The existing node can be reused.
1338 self._parent_child_digraph.add(existing_node, myparent)
1339 if rev_dep and myparent:
1340 ptype, proot, pkey, pstatus = myparent
1341 self.digraph.addnode(myparent, existing_node,
1344 self.digraph.addnode(existing_node, myparent,
1348 # A slot collision has occurred. Sometimes this coincides
1349 # with unresolvable blockers, so the slot collision will be
1350 # shown later if there are no unresolvable blockers.
1351 e_parents = self._parent_child_digraph.parent_nodes(
1355 myparents.append(myparent)
1356 self._slot_collision_info.append(
1357 ((jbigkey, myparents), (existing_node, e_parents)))
1358 self._slot_collision_nodes.add(jbigkey)
1359 slot_collision = True
1362 # Now add this node to the graph so that self.display()
1363 # can show use flags and --tree portage.output. This node is
1364 # only being partially added to the graph. It must not be
1365 # allowed to interfere with the other nodes that have been
1366 # added. Do not overwrite data for existing nodes in
1367 # self.pkg_node_map and self.mydbapi since that data will
1368 # be used for blocker validation.
1369 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1370 self.useFlags[myroot].setdefault(mykey, myuse)
1371 # Even though the graph is now invalid, continue to process
1372 # dependencies so that things like --fetchonly can still
1373 # function despite collisions.
1375 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1376 self._slot_node_map[myroot][slot_atom] = jbigkey
1377 self.pkg_node_map[myroot][mykey] = jbigkey
1378 self.useFlags[myroot][mykey] = myuse
1380 if rev_dep and myparent:
1381 self.digraph.addnode(myparent, jbigkey,
1384 self.digraph.addnode(jbigkey, myparent,
1388 self._set_nodes.add(jbigkey)
1390 # Do this even when addme is False (--onlydeps) so that the
1391 # parent/child relationship is always known in case
1392 # self._show_slot_collision_notice() needs to be called later.
1393 self._parent_child_digraph.add(jbigkey, myparent)
1395 """ This section determines whether we go deeper into dependencies or not.
1396 We want to go deeper on a few occasions:
1397 Installing package A, we need to make sure package A's deps are met.
1398 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1399 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1401 if "deep" not in self.myparams and not merging and \
1402 not ("--update" in self.myopts and arg and merging):
1404 elif "recurse" not in self.myparams:
1407 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1408 Pull from bintree if it's binary package, porttree if it's ebuild.
1409 Binpkg's can be either remote or local. """
1412 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1414 edepend[k] = metadata[k]
1416 if mytype == "ebuild":
1417 if "--buildpkgonly" in self.myopts:
1418 edepend["RDEPEND"] = ""
1419 edepend["PDEPEND"] = ""
1420 if not (arg and "--onlydeps" in self.myopts and \
1421 mytype == "ebuild") and \
1422 self.myopts.get("--with-bdeps", "n") == "n" and \
1423 (mytype == "binary" or mybigkey[3] == "nomerge"):
1424 edepend["DEPEND"] = ""
1426 """ We have retrieve the dependency information, now we need to recursively
1427 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1429 mp = tuple(mybigkey)
1432 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1433 myuse=myuse, priority=DepPriority(buildtime=True),
1436 """RDEPEND is soft by definition. However, in order to ensure
1437 correct merge order, we make it a hard dependency. Otherwise, a
1438 build time dependency might not be usable due to it's run time
1439 dependencies not being installed yet.
1441 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1442 myuse=myuse, priority=DepPriority(runtime=True),
1445 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1446 # Post Depend -- Add to the list without a parent, as it depends
1447 # on a package being present AND must be built after that package.
1448 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1449 myuse=myuse, priority=DepPriority(runtime_post=True),
1452 except ValueError, e:
1454 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1455 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1457 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1458 portage.writemsg("\n", noiselevel=-1)
1459 if mytype == "binary":
1461 "!!! This binary package cannot be installed: '%s'\n" % \
1462 mykey, noiselevel=-1)
1463 elif mytype == "ebuild":
1464 myebuild, mylocation = portdb.findname2(mykey)
1465 portage.writemsg("!!! This ebuild cannot be installed: " + \
1466 "'%s'\n" % myebuild, noiselevel=-1)
1467 portage.writemsg("!!! Please notify the package maintainer " + \
1468 "that atoms must be fully-qualified.\n", noiselevel=-1)
1472 def select_files(self,myfiles):
1473 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1475 myroot = self.target_root
1476 portdb = self.trees[myroot]["porttree"].dbapi
1477 bindb = self.trees[myroot]["bintree"].dbapi
1478 pkgsettings = self.pkgsettings[myroot]
1480 def visible(mylist):
1481 matches = portdb.gvisible(portdb.visible(mylist))
1482 return [x for x in mylist \
1483 if x in matches or not portdb.cpv_exists(x)]
1485 ext = os.path.splitext(x)[1]
1487 if not os.path.exists(x):
1489 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1490 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1491 elif os.path.exists(
1492 os.path.join(pkgsettings["PKGDIR"], x)):
1493 x = os.path.join(pkgsettings["PKGDIR"], x)
1495 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1496 print "!!! Please ensure the tbz2 exists as specified.\n"
1497 return 0, myfavorites
1498 mytbz2=portage.xpak.tbz2(x)
1499 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1500 if os.path.realpath(x) != \
1501 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1502 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1503 return 0, myfavorites
1504 if not self.create(["binary", myroot, mykey],
1505 None, "--onlydeps" not in self.myopts,
1506 myuse=mytbz2.getelements("USE"), arg=x):
1507 return (0,myfavorites)
1508 arg_atoms.append((x, "="+mykey))
1509 elif ext==".ebuild":
1510 ebuild_path = portage.util.normalize_path(os.path.abspath(x))
1511 pkgdir = os.path.dirname(ebuild_path)
1512 tree_root = os.path.dirname(os.path.dirname(pkgdir))
1513 cp = pkgdir[len(tree_root)+1:]
1514 e = portage.exception.PackageNotFound(
1515 ("%s is not in a valid portage tree " + \
1516 "hierarchy or does not exist") % x)
1517 if not portage.isvalidatom(cp):
1519 cat = portage.catsplit(cp)[0]
1520 mykey = cat + "/" + os.path.basename(ebuild_path[:-7])
1521 if not portage.isvalidatom("="+mykey):
1523 ebuild_path = portdb.findname(mykey)
1525 if ebuild_path != os.path.join(os.path.realpath(tree_root),
1526 cp, os.path.basename(ebuild_path)):
1527 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1528 return 0, myfavorites
1529 if mykey not in portdb.xmatch(
1530 "match-visible", portage.dep_getkey(mykey)):
1531 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1532 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1533 print colorize("BAD", "*** page for details.")
1534 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1537 raise portage.exception.PackageNotFound(
1538 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1539 if not self.create(["ebuild", myroot, mykey],
1540 None, "--onlydeps" not in self.myopts, arg=x):
1541 return (0,myfavorites)
1542 arg_atoms.append((x, "="+mykey))
1544 if not is_valid_package_atom(x):
1545 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1547 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1548 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1552 if "--usepkg" in self.myopts:
1553 mykey = portage.dep_expand(x, mydb=bindb,
1554 settings=pkgsettings)
1555 if (mykey and not mykey.startswith("null/")) or \
1556 "--usepkgonly" in self.myopts:
1557 arg_atoms.append((x, mykey))
1560 mykey = portage.dep_expand(x,
1561 mydb=portdb, settings=pkgsettings)
1562 arg_atoms.append((x, mykey))
1563 except ValueError, errpkgs:
1564 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1565 print "!!! one of the following fully-qualified ebuild names instead:\n"
1566 for i in errpkgs[0]:
1567 print " " + green(i)
1571 if "--update" in self.myopts:
1572 """Make sure all installed slots are updated when possible. Do this
1573 with --emptytree also, to ensure that all slots are remerged."""
1574 vardb = self.trees[self.target_root]["vartree"].dbapi
1576 for myarg, myatom in arg_atoms:
1577 greedy_atoms.append((myarg, myatom))
1579 for cpv in vardb.match(myatom):
1580 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1583 if "--usepkg" in self.myopts:
1584 mymatches = bindb.match(myatom)
1585 if "--usepkgonly" not in self.myopts:
1586 mymatches = visible(mymatches)
1587 best_pkg = portage.best(mymatches)
1589 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1590 best_pkgs.append(("binary", best_pkg, best_slot))
1591 if "--usepkgonly" not in self.myopts:
1592 best_pkg = portage.best(portdb.match(myatom))
1594 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1595 best_pkgs.append(("ebuild", best_pkg, best_slot))
1597 best_pkg = portage.best([x[1] for x in best_pkgs])
1598 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1599 best_slot = best_pkgs[0][2]
1600 myslots.add(best_slot)
1601 if len(myslots) > 1:
1602 for myslot in myslots:
1603 myslot_atom = "%s:%s" % \
1604 (portage.dep_getkey(myatom), myslot)
1606 if "--usepkgonly" not in self.myopts and \
1607 self.trees[self.target_root][
1608 "porttree"].dbapi.match(myslot_atom):
1610 elif "--usepkg" in self.myopts:
1611 mymatches = bindb.match(myslot_atom)
1612 if "--usepkgonly" not in self.myopts:
1613 mymatches = visible(mymatches)
1617 greedy_atoms.append((myarg, myslot_atom))
1618 arg_atoms = greedy_atoms
1620 oneshot = "--oneshot" in self.myopts or "--onlydeps" in self.myopts
1621 """ These are used inside self.create() in order to ensure packages
1622 that happen to match arguments are not incorrectly marked as nomerge."""
1623 args_set = self._sets["args"]
1624 for myarg, myatom in arg_atoms:
1625 if myatom in args_set:
1627 args_set.add(myatom)
1628 self._set_atoms.add(myatom)
1630 myfavorites.append(myatom)
1631 for myarg, myatom in arg_atoms:
1633 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1634 except portage.exception.MissingSignature, e:
1635 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1636 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1637 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1638 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1639 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1641 except portage.exception.InvalidSignature, e:
1642 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1643 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1644 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1645 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1646 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1648 except SystemExit, e:
1649 raise # Needed else can't exit
1650 except Exception, e:
1651 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1652 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1656 return (0,myfavorites)
1659 if "--usepkgonly" in self.myopts:
1660 for xs in self.digraph.all_nodes():
1661 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1665 print "Missing binary for:",xs[2]
1667 if not self.validate_blockers():
1668 return False, myfavorites
1670 # We're true here unless we are missing binaries.
1671 return (not missing,myfavorites)
1673 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1674 myuse=None, raise_on_missing=False, priority=DepPriority(),
1675 rev_deps=False, parent_arg=None):
1676 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1677 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1678 myparent = the node whose depstring is being passed in
1679 arg = package was specified on the command line, merge even if it's already installed
1680 myuse = USE flags at present
1681 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1682 else continue trying.
1683 return 1 on success, 0 for failure
1686 portdb = self.trees[myroot]["porttree"].dbapi
1687 bindb = self.trees[myroot]["bintree"].dbapi
1688 vardb = self.trees[myroot]["vartree"].dbapi
1689 pkgsettings = self.pkgsettings[myroot]
1691 p_type, p_root, p_key, p_status = myparent
1693 if "--debug" in self.myopts:
1695 print "Parent: ",myparent
1696 print "Depstring:",depstring
1698 print "Reverse:", rev_deps
1699 print "Priority:", priority
1701 #processing dependencies
1702 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1703 dependencies are satisfiable. """
1705 mymerge = [depstring]
1706 pprovided = pkgsettings.pprovideddict.get(
1707 portage.dep_getkey(depstring))
1708 if pprovided and portage.match_from_list(depstring, pprovided):
1712 if myparent and p_status == "nomerge":
1713 portage.dep._dep_check_strict = False
1714 mycheck = portage.dep_check(depstring, None,
1715 pkgsettings, myuse=myuse,
1716 use_binaries=("--usepkgonly" in self.myopts),
1717 myroot=myroot, trees=self.trees)
1719 portage.dep._dep_check_strict = True
1723 show_invalid_depstring_notice(
1724 myparent, depstring, mycheck[1])
1726 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1728 mymerge = mycheck[1]
1730 if not mymerge and arg:
1731 # A provided package has been specified on the command line. The
1732 # package will not be merged and a warning will be displayed.
1733 if depstring in self._set_atoms:
1734 self._pprovided_args.append((arg, depstring))
1737 # The parent is added after it's own dep_check call so that it
1738 # isn't allowed to satisfy a direct bootstrap dependency on itself
1739 # via an old-style virtual. This isn't a problem with new-style
1740 # virtuals, which are preferenced in dep_zapdeps by looking only at
1741 # the depstring, vdb, and available packages.
1743 p_type, p_root, p_key, p_status = myparent
1744 if p_status == "merge":
1745 # Update old-style virtuals if this package provides any.
1746 # These are needed for dep_virtual calls inside dep_check.
1747 p_db = self.trees[p_root][self.pkg_tree_map[p_type]].dbapi
1749 self.pkgsettings[p_root].setinst(p_key, p_db)
1750 except portage.exception.InvalidDependString, e:
1751 provide = p_db.aux_get(p_key, ["PROVIDE"])[0]
1752 show_invalid_depstring_notice(myparent, provide, str(e))
1756 if "--debug" in self.myopts:
1757 print "Candidates:",mymerge
1761 selected_pkg = ["blocks", myroot, x[1:], None]
1763 #We are not processing a blocker but a normal dependency
1765 """In some cases, dep_check will return deps that shouldn't
1766 be proccessed any further, so they are identified and
1768 if "empty" not in self.myparams and \
1769 "deep" not in self.myparams and \
1770 not ("--update" in self.myopts and parent_arg) and \
1774 # List of acceptable packages, ordered by type preference.
1775 matched_packages = []
1776 myeb_matches = portdb.xmatch("match-visible", x)
1778 if "--usepkgonly" not in self.myopts:
1779 myeb = portage.best(myeb_matches)
1782 if "--usepkg" in self.myopts:
1783 # The next line assumes the binarytree has been populated.
1784 # XXX: Need to work out how we use the binary tree with roots.
1785 myeb_pkg_matches = bindb.match(x)
1786 if "--usepkgonly" not in self.myopts:
1787 # Remove any binary package entries that are masked in the portage tree (#55871)
1788 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1789 if pkg in myeb_matches or \
1790 not portdb.cpv_exists(pkg)]
1791 if myeb_pkg_matches:
1792 myeb_pkg = portage.best(myeb_pkg_matches)
1795 ("--newuse" in self.myopts or \
1796 "--reinstall" in self.myopts):
1797 iuses = set(filter_iuse_defaults(
1798 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1799 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1801 if "--usepkgonly" not in self.myopts and myeb:
1804 pkgsettings.setcpv(myeb, mydb=mydb)
1806 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1807 now_use = pkgsettings["USE"].split()
1808 forced_flags = set()
1809 forced_flags.update(pkgsettings.useforce)
1810 forced_flags.update(pkgsettings.usemask)
1812 if "--usepkgonly" not in self.myopts and myeb:
1813 cur_iuse = set(filter_iuse_defaults(
1814 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1815 if self._reinstall_for_flags(
1816 forced_flags, old_use, iuses, now_use, cur_iuse):
1820 self.trees[myroot]["bintree"].dbapi.aux_get(
1821 myeb_pkg, ["USE"])[0].split()
1822 matched_packages.append(
1823 ["binary", myroot, myeb_pkg, binpkguseflags])
1825 if "--usepkgonly" not in self.myopts and myeb_matches:
1826 matched_packages.append(
1827 ["ebuild", myroot, myeb, None])
1829 if not matched_packages and \
1830 not (arg and "selective" not in self.myparams):
1831 """Fall back to the installed package database. This is a
1832 last resort because the metadata tends to diverge from that
1833 of the ebuild in the tree."""
1834 myeb_inst_matches = vardb.match(x)
1835 if "--usepkgonly" not in self.myopts:
1836 """ TODO: Improve masking check for installed and
1837 binary packages. bug #149816"""
1838 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1839 if not portdb.cpv_exists(pkg)]
1841 if myeb_inst_matches:
1842 myeb_inst = portage.best(myeb_inst_matches)
1844 binpkguseflags = vardb.aux_get(
1845 myeb_inst, ["USE"])[0].split()
1846 matched_packages.append(
1847 ["installed", myroot, myeb_inst, binpkguseflags])
1849 if not matched_packages:
1850 if raise_on_missing:
1857 xfrom = '(dependency required by '+ \
1858 green('"%s"' % myparent[2]) + \
1859 red(' [%s]' % myparent[0]) + ')'
1860 alleb = portdb.xmatch("match-all", x)
1862 if "--usepkgonly" not in self.myopts:
1863 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1864 print "!!! One of the following masked packages is required to complete your request:"
1868 mreasons = portage.getmaskingstatus(p,
1869 settings=pkgsettings, portdb=portdb)
1870 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1871 if "package.mask" in mreasons:
1872 comment, filename = \
1873 portage.getmaskingreason(p,
1874 settings=pkgsettings, portdb=portdb,
1875 return_location=True)
1876 if comment and comment != oldcomment:
1879 oldcomment = comment
1881 licenses = portdb.aux_get(p, ["LICENSE"])[0]
1883 # Corruption will have been reported above.
1887 pkgsettings.setcpv(p, mydb=portdb)
1888 uselist = pkgsettings.get("USE", "").split()
1889 missing_licenses = []
1891 missing_licenses = \
1892 pkgsettings.getMissingLicenses(
1893 licenses, p, uselist)
1894 except portage.exception.InvalidDependString:
1895 # This will have already been reported
1896 # above via mreasons.
1898 for l in missing_licenses:
1899 l_path = portdb.findLicensePath(l)
1900 if l in shown_licenses:
1902 msg = ("A copy of the '%s' license" + \
1903 " is located at '%s'.") % (l, l_path)
1906 shown_licenses.append(l)
1908 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1909 print "refer to the Gentoo Handbook."
1911 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1912 print "!!! Either add a suitable binary package or compile from an ebuild."
1914 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1920 if "--debug" in self.myopts:
1921 for pkg in matched_packages:
1922 print (pkg[0] + ":").rjust(10), pkg[2]
1924 if len(matched_packages) > 1:
1925 bestmatch = portage.best(
1926 [pkg[2] for pkg in matched_packages])
1927 matched_packages = [pkg for pkg in matched_packages \
1928 if pkg[2] == bestmatch]
1930 # ordered by type preference ("ebuild" type is the last resort)
1931 selected_pkg = matched_packages[0]
1932 pkgtype, myroot, mycpv, myuse = selected_pkg
1933 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1934 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1935 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1936 existing_node = self._slot_node_map[myroot].get(
1939 e_type, myroot, e_cpv, e_status = existing_node
1940 if portage.match_from_list(x, [e_cpv]):
1941 # The existing node can be reused.
1942 selected_pkg = [e_type, myroot, e_cpv,
1943 self.useFlags[myroot][e_cpv]]
1946 #we are a dependency, so we want to be unconditionally added
1947 mypriority = priority.copy()
1949 mypriority.satisfied = True
1950 if not self.create(selected_pkg[0:3], myparent,
1951 myuse=selected_pkg[-1], priority=mypriority,
1952 rev_dep=rev_deps, arg=arg):
1955 #if mysource is not set, then we are a command-line dependency and should not be added
1956 #if --onlydeps is specified.
1957 if not self.create(selected_pkg[0:3], myparent,
1958 addme=("--onlydeps" not in self.myopts),
1959 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1962 if "--debug" in self.myopts:
1963 print "Exiting...",myparent
1966 def validate_blockers(self):
1967 """Remove any blockers from the digraph that do not match any of the
1968 packages within the graph. If necessary, create hard deps to ensure
1969 correct merge order such that mutually blocking packages are never
1970 installed simultaneously."""
1972 if "--buildpkgonly" in self.myopts or \
1973 "--nodeps" in self.myopts:
1977 for myroot in self.trees:
1979 modified_slots[myroot] = myslots
1980 final_db = self.mydbapi[myroot]
1981 slot_node_map = self._slot_node_map[myroot]
1982 for slot_atom, mynode in slot_node_map.iteritems():
1983 mytype, myroot, mycpv, mystatus = mynode
1984 if mystatus == "merge":
1985 myslots[slot_atom] = mycpv
1987 #if "deep" in self.myparams:
1989 # Pull in blockers from all installed packages that haven't already
1990 # been pulled into the depgraph. This is not enabled by default
1991 # due to the performance penalty that is incurred by all the
1992 # additional dep_check calls that are required.
1994 # Optimization hack for dep_check calls that minimizes the
1995 # available matches by replacing the portdb with a fakedbapi
1997 class FakePortageTree(object):
1998 def __init__(self, mydb):
2000 dep_check_trees = {}
2001 for myroot in self.trees:
2002 dep_check_trees[myroot] = self.trees[myroot].copy()
2003 dep_check_trees[myroot]["porttree"] = \
2004 FakePortageTree(self.mydbapi[myroot])
2006 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
2007 for myroot in self.trees:
2008 pkg_node_map = self.pkg_node_map[myroot]
2009 vardb = self.trees[myroot]["vartree"].dbapi
2010 portdb = self.trees[myroot]["porttree"].dbapi
2011 pkgsettings = self.pkgsettings[myroot]
2012 final_db = self.mydbapi[myroot]
2013 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
2014 blocker_cache = BlockerCache(myroot, vardb)
2015 for pkg in cpv_all_installed:
2016 blocker_atoms = None
2017 matching_node = pkg_node_map.get(pkg, None)
2018 if matching_node and \
2019 matching_node[3] == "nomerge":
2021 # If this node has any blockers, create a "nomerge"
2022 # node for it so that they can be enforced.
2023 self.spinner.update()
2024 blocker_data = blocker_cache.get(pkg)
2026 blocker_atoms = blocker_data.atoms
2028 dep_vals = vardb.aux_get(pkg, dep_keys)
2029 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
2030 depstr = " ".join(dep_vals)
2031 # It is crucial to pass in final_db here in order to
2032 # optimize dep_check calls by eliminating atoms via
2033 # dep_wordreduce and dep_eval calls.
2035 portage.dep._dep_check_strict = False
2037 success, atoms = portage.dep_check(depstr,
2038 final_db, pkgsettings, myuse=myuse,
2039 trees=dep_check_trees, myroot=myroot)
2040 except Exception, e:
2041 if isinstance(e, SystemExit):
2043 # This is helpful, for example, if a ValueError
2044 # is thrown from cpv_expand due to multiple
2045 # matches (this can happen if an atom lacks a
2047 show_invalid_depstring_notice(
2048 ("installed", myroot, pkg, "nomerge"),
2053 portage.dep._dep_check_strict = True
2055 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
2056 vardb.aux_get(pkg, ["SLOT"])[0])
2057 if slot_atom in modified_slots[myroot]:
2058 # This package is being replaced anyway, so
2059 # ignore invalid dependencies so as not to
2060 # annoy the user too much (otherwise they'd be
2061 # forced to manually unmerge it first).
2063 show_invalid_depstring_notice(
2064 ("installed", myroot, pkg, "nomerge"),
2067 blocker_atoms = [myatom for myatom in atoms \
2068 if myatom.startswith("!")]
2069 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
2070 blocker_cache[pkg] = \
2071 blocker_cache.BlockerData(counter, blocker_atoms)
2073 # Don't store this parent in pkg_node_map, because it's
2074 # not needed there and it might overwrite a "merge"
2075 # node with the same cpv.
2076 myparent = ("installed", myroot, pkg, "nomerge")
2077 for myatom in blocker_atoms:
2078 blocker = ("blocks", myroot, myatom[1:])
2080 self.blocker_parents.get(blocker, None)
2083 self.blocker_parents[blocker] = myparents
2084 myparents.add(myparent)
2085 blocker_cache.flush()
2088 for blocker in self.blocker_parents.keys():
2089 mytype, myroot, mydep = blocker
2090 initial_db = self.trees[myroot]["vartree"].dbapi
2091 final_db = self.mydbapi[myroot]
2092 blocked_initial = initial_db.match(mydep)
2093 blocked_final = final_db.match(mydep)
2094 if not blocked_initial and not blocked_final:
2095 del self.blocker_parents[blocker]
2097 blocked_slots_initial = {}
2098 blocked_slots_final = {}
2099 for cpv in blocked_initial:
2100 blocked_slots_initial[cpv] = \
2101 "%s:%s" % (portage.dep_getkey(cpv),
2102 initial_db.aux_get(cpv, ["SLOT"])[0])
2103 for cpv in blocked_final:
2104 blocked_slots_final[cpv] = \
2105 "%s:%s" % (portage.dep_getkey(cpv),
2106 final_db.aux_get(cpv, ["SLOT"])[0])
2107 for parent in list(self.blocker_parents[blocker]):
2108 ptype, proot, pcpv, pstatus = parent
2109 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
2110 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
2111 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
2112 parent_static = pslot_atom not in modified_slots[proot]
2113 unresolved_blocks = False
2114 depends_on_order = set()
2115 for cpv in blocked_initial:
2116 slot_atom = blocked_slots_initial[cpv]
2117 if slot_atom == pslot_atom:
2118 # TODO: Support blocks within slots in cases where it
2119 # might make sense. For example, a new version might
2120 # require that the old version be uninstalled at build
2123 if parent_static and \
2124 slot_atom not in modified_slots[myroot]:
2125 # This blocker will be handled the next time that a
2126 # merge of either package is triggered.
2128 if pstatus == "merge" and \
2129 slot_atom in modified_slots[myroot]:
2130 replacement = final_db.match(slot_atom)
2132 if not portage.match_from_list(mydep, replacement):
2133 # Apparently a replacement may be able to
2134 # invalidate this block.
2135 replacement_node = \
2136 self.pkg_node_map[proot][replacement[0]]
2137 depends_on_order.add((replacement_node, parent))
2139 # None of the above blocker resolutions techniques apply,
2140 # so apparently this one is unresolvable.
2141 unresolved_blocks = True
2142 for cpv in blocked_final:
2143 slot_atom = blocked_slots_final[cpv]
2144 if slot_atom == pslot_atom:
2145 # TODO: Support blocks within slots.
2147 if parent_static and \
2148 slot_atom not in modified_slots[myroot]:
2149 # This blocker will be handled the next time that a
2150 # merge of either package is triggered.
2152 if not parent_static and pstatus == "nomerge" and \
2153 slot_atom in modified_slots[myroot]:
2154 replacement = final_db.match(pslot_atom)
2156 replacement_node = \
2157 self.pkg_node_map[proot][replacement[0]]
2158 if replacement_node not in \
2159 self.blocker_parents[blocker]:
2160 # Apparently a replacement may be able to
2161 # invalidate this block.
2162 blocked_node = self.pkg_node_map[proot][cpv]
2163 depends_on_order.add(
2164 (replacement_node, blocked_node))
2166 # None of the above blocker resolutions techniques apply,
2167 # so apparently this one is unresolvable.
2168 unresolved_blocks = True
2169 if not unresolved_blocks and depends_on_order:
2170 for node, pnode in depends_on_order:
2171 # Enforce correct merge order with a hard dep.
2172 self.digraph.addnode(node, pnode,
2173 priority=DepPriority(buildtime=True))
2174 # Count references to this blocker so that it can be
2175 # invalidated after nodes referencing it have been
2177 self.blocker_digraph.addnode(node, blocker)
2178 if not unresolved_blocks and not depends_on_order:
2179 self.blocker_parents[blocker].remove(parent)
2180 if unresolved_blocks:
2181 self._unresolved_blocker_parents.setdefault(
2182 blocker, set()).add(parent)
2183 if not self.blocker_parents[blocker]:
2184 del self.blocker_parents[blocker]
2185 # Validate blockers that depend on merge order.
2186 if not self.blocker_digraph.empty():
2188 if self._slot_collision_info:
2189 # The user is only notified of a slot collision if there are no
2190 # unresolvable blocks.
2191 for x in self.altlist():
2192 if x[0] == "blocks":
2194 self._show_slot_collision_notice(self._slot_collision_info[0])
2195 if not self._accept_collisions():
2199 def _accept_collisions(self):
2201 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
2202 if x in self.myopts:
2207 def _merge_order_bias(self, mygraph):
2208 """Order nodes from highest to lowest overall reference count for
2209 optimal leaf node selection."""
2211 for node in mygraph.order:
2212 node_info[node] = len(mygraph.parent_nodes(node))
2213 def cmp_merge_preference(node1, node2):
2214 return node_info[node2] - node_info[node1]
2215 mygraph.order.sort(cmp_merge_preference)
2217 def altlist(self, reversed=False):
2218 if reversed in self._altlist_cache:
2219 return self._altlist_cache[reversed][:]
2221 retlist = self.altlist()
2223 self._altlist_cache[reversed] = retlist[:]
2225 mygraph=self.digraph.copy()
2226 for node in mygraph.order[:]:
2227 if node[-1] == "nomerge":
2228 mygraph.remove(node)
2229 self._merge_order_bias(mygraph)
2230 myblockers = self.blocker_digraph.copy()
2232 circular_blocks = False
2236 get_nodes = mygraph.root_nodes
2238 get_nodes = mygraph.leaf_nodes
2239 for cpv, node in self.pkg_node_map["/"].iteritems():
2240 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
2241 asap_nodes.append(node)
2243 ignore_priority_soft_range = [None]
2244 ignore_priority_soft_range.extend(
2245 xrange(DepPriority.MIN, DepPriority.SOFT + 1))
2246 tree_mode = "--tree" in self.myopts
2247 # Tracks whether or not the current iteration should prefer asap_nodes
2248 # if available. This is set to False when the previous iteration
2249 # failed to select any nodes. It is reset whenever nodes are
2250 # successfully selected.
2252 while not mygraph.empty():
2253 selected_nodes = None
2254 if prefer_asap and asap_nodes:
2255 """ASAP nodes are merged before their soft deps."""
2256 asap_nodes = [node for node in asap_nodes \
2257 if mygraph.contains(node)]
2258 for node in asap_nodes:
2259 if not mygraph.child_nodes(node,
2260 ignore_priority=DepPriority.SOFT):
2261 selected_nodes = [node]
2262 asap_nodes.remove(node)
2264 if not selected_nodes and \
2265 not (prefer_asap and asap_nodes):
2266 for ignore_priority in ignore_priority_soft_range:
2267 nodes = get_nodes(ignore_priority=ignore_priority)
2271 if ignore_priority is None and not tree_mode:
2272 # Greedily pop all of these nodes since no relationship
2273 # has been ignored. This optimization destroys --tree
2274 # output, so it's disabled in reversed mode.
2275 selected_nodes = nodes
2277 # For optimal merge order:
2278 # * Only pop one node.
2279 # * Removing a root node (node without a parent)
2280 # will not produce a leaf node, so avoid it.
2282 if mygraph.parent_nodes(node):
2283 # found a non-root node
2284 selected_nodes = [node]
2286 if not selected_nodes:
2287 # settle for a root node
2288 selected_nodes = [nodes[0]]
2289 if not selected_nodes:
2290 nodes = get_nodes(ignore_priority=DepPriority.MEDIUM)
2292 """Recursively gather a group of nodes that RDEPEND on
2293 eachother. This ensures that they are merged as a group
2294 and get their RDEPENDs satisfied as soon as possible."""
2295 def gather_deps(ignore_priority,
2296 mergeable_nodes, selected_nodes, node):
2297 if node in selected_nodes:
2299 if node not in mergeable_nodes:
2301 selected_nodes.add(node)
2302 for child in mygraph.child_nodes(node,
2303 ignore_priority=ignore_priority):
2304 if not gather_deps(ignore_priority,
2305 mergeable_nodes, selected_nodes, child):
2308 mergeable_nodes = set(nodes)
2309 if prefer_asap and asap_nodes:
2311 for ignore_priority in xrange(DepPriority.SOFT,
2312 DepPriority.MEDIUM_SOFT + 1):
2314 selected_nodes = set()
2315 if gather_deps(ignore_priority,
2316 mergeable_nodes, selected_nodes, node):
2319 selected_nodes = None
2323 if prefer_asap and asap_nodes and not selected_nodes:
2324 # We failed to find any asap nodes to merge, so ignore
2325 # them for the next iteration.
2329 if selected_nodes and ignore_priority > DepPriority.SOFT:
2330 # Try to merge ignored medium deps as soon as possible.
2331 for node in selected_nodes:
2332 children = set(mygraph.child_nodes(node))
2333 soft = children.difference(
2334 mygraph.child_nodes(node,
2335 ignore_priority=DepPriority.SOFT))
2336 medium_soft = children.difference(
2337 mygraph.child_nodes(node,
2338 ignore_priority=DepPriority.MEDIUM_SOFT))
2339 medium_soft.difference_update(soft)
2340 for child in medium_soft:
2341 if child in selected_nodes:
2343 if child in asap_nodes:
2345 # TODO: Try harder to make these nodes get
2346 # merged absolutely as soon as possible.
2347 asap_nodes.append(child)
2349 if not selected_nodes:
2350 if not myblockers.is_empty():
2351 """A blocker couldn't be circumnavigated while keeping all
2352 dependencies satisfied. The user will have to resolve this
2353 manually. This is a panic condition and thus the order
2354 doesn't really matter, so just pop a random node in order
2355 to avoid a circular dependency panic if possible."""
2356 if not circular_blocks:
2357 circular_blocks = True
2358 blocker_deps = myblockers.leaf_nodes()
2360 # Some of these nodes might have already been selected
2361 # by the normal node selection process after the
2362 # circular_blocks flag has been set. Therefore, we
2363 # have to verify that they're still in the graph so
2364 # that they're not selected more than once.
2365 node = blocker_deps.pop()
2366 if mygraph.contains(node):
2367 selected_nodes = [node]
2370 if not selected_nodes:
2371 # No leaf nodes are available, so we have a circular
2372 # dependency panic situation. Reduce the noise level to a
2373 # minimum via repeated elimination of root nodes since they
2374 # have no parents and thus can not be part of a cycle.
2376 root_nodes = mygraph.root_nodes(
2377 ignore_priority=DepPriority.SOFT)
2380 for node in root_nodes:
2381 mygraph.remove(node)
2382 # Display the USE flags that are enabled on nodes that are part
2383 # of dependency cycles in case that helps the user decide to
2384 # disable some of them.
2386 tempgraph = mygraph.copy()
2387 while not tempgraph.empty():
2388 nodes = tempgraph.leaf_nodes()
2390 node = tempgraph.order[0]
2393 display_order.append(list(node))
2394 tempgraph.remove(node)
2395 display_order.reverse()
2396 self.myopts.pop("--quiet", None)
2397 self.myopts.pop("--verbose", None)
2398 self.myopts["--tree"] = True
2399 self.display(display_order)
2400 print "!!! Error: circular dependencies:"
2402 mygraph.debug_print()
2404 print "!!! Note that circular dependencies can often be avoided by temporarily"
2405 print "!!! disabling USE flags that trigger optional dependencies."
2408 # At this point, we've succeeded in selecting one or more nodes, so
2409 # it's now safe to reset the prefer_asap to it's default state.
2412 for node in selected_nodes:
2413 retlist.append(list(node))
2414 mygraph.remove(node)
2415 if not reversed and not circular_blocks and myblockers.contains(node):
2416 """This node may have invalidated one or more blockers."""
2417 myblockers.remove(node)
2418 for blocker in myblockers.root_nodes():
2419 if not myblockers.child_nodes(blocker):
2420 myblockers.remove(blocker)
2422 self._unresolved_blocker_parents.get(blocker)
2424 self.blocker_parents[blocker] = unresolved
2426 del self.blocker_parents[blocker]
2429 """Blocker validation does not work with reverse mode,
2430 so self.altlist() should first be called with reverse disabled
2431 so that blockers are properly validated."""
2432 self.blocker_digraph = myblockers
2434 """ Add any unresolved blocks so that they can be displayed."""
2435 for blocker in self.blocker_parents:
2436 retlist.append(list(blocker))
2437 self._altlist_cache[reversed] = retlist[:]
2440 def xcreate(self,mode="system"):
2441 vardb = self.trees[self.target_root]["vartree"].dbapi
2442 portdb = self.trees[self.target_root]["porttree"].dbapi
2443 bindb = self.trees[self.target_root]["bintree"].dbapi
2444 def visible(mylist):
2445 matches = portdb.gvisible(portdb.visible(mylist))
2446 return [x for x in mylist \
2447 if x in matches or not portdb.cpv_exists(x)]
2448 world_problems = False
2450 root_config = self.roots[self.target_root]
2451 world_set = root_config.sets["world"]
2452 system_set = root_config.sets["system"]
2453 mylist = list(system_set)
2454 self._sets["system"] = system_set
2456 self._sets["world"] = world_set
2458 if not portage.isvalidatom(x):
2459 world_problems = True
2461 elif not vardb.match(x):
2462 world_problems = True
2464 if "--usepkgonly" not in self.myopts and \
2467 elif "--usepkg" in self.myopts:
2468 mymatches = bindb.match(x)
2469 if "--usepkgonly" not in self.myopts:
2470 mymatches = visible(mymatches)
2479 mykey = portage.dep_getkey(atom)
2481 newlist.append(atom)
2482 if mode == "system" or atom not in world_set:
2483 # only world is greedy for slots, not system
2485 # Make sure all installed slots are updated when possible.
2486 # Do this with --emptytree also, to ensure that all slots are
2489 for cpv in vardb.match(mykey):
2490 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2493 if "--usepkg" in self.myopts:
2494 mymatches = bindb.match(atom)
2495 if "--usepkgonly" not in self.myopts:
2496 mymatches = visible(mymatches)
2497 best_pkg = portage.best(mymatches)
2499 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2500 best_pkgs.append(("binary", best_pkg, best_slot))
2501 if "--usepkgonly" not in self.myopts:
2502 best_pkg = portage.best(portdb.match(atom))
2504 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2505 best_pkgs.append(("ebuild", best_pkg, best_slot))
2507 best_pkg = portage.best([x[1] for x in best_pkgs])
2508 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2509 best_slot = best_pkgs[0][2]
2510 myslots.add(best_slot)
2511 if len(myslots) > 1:
2512 for myslot in myslots:
2513 myslot_atom = "%s:%s" % (mykey, myslot)
2515 if "--usepkgonly" not in self.myopts and \
2516 self.trees[self.target_root][
2517 "porttree"].dbapi.match(myslot_atom):
2519 elif "--usepkg" in self.myopts:
2520 mymatches = bindb.match(myslot_atom)
2521 if "--usepkgonly" not in self.myopts:
2522 mymatches = visible(mymatches)
2526 newlist.append(myslot_atom)
2529 for myatom in mylist:
2530 self._set_atoms.add(myatom)
2533 for mydep in mylist:
2535 if not self.select_dep(
2536 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2537 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2540 missing_atoms.append(mydep)
2542 if not self.validate_blockers():
2546 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2547 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2550 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2551 " Ebuilds for the following packages are either all"
2552 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2553 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2557 def display(self, mylist, favorites=[], verbosity=None):
2558 if verbosity is None:
2559 verbosity = ("--quiet" in self.myopts and 1 or \
2560 "--verbose" in self.myopts and 3 or 2)
2561 if "--resume" in self.myopts and favorites:
2562 self._sets["args"].update(favorites)
2563 favorites_set = AtomSet()
2564 favorites_set.update(favorites)
2569 counters = PackageCounters()
2571 if verbosity == 1 and "--verbose" not in self.myopts:
2572 def create_use_string(*args):
2575 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2577 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2578 alphabetical=("--alphabetical" in self.myopts)):
2586 cur_iuse = set(cur_iuse)
2587 enabled_flags = cur_iuse.intersection(cur_use)
2588 removed_iuse = set(old_iuse).difference(cur_iuse)
2589 any_iuse = cur_iuse.union(old_iuse)
2590 any_iuse = list(any_iuse)
2592 for flag in any_iuse:
2595 if flag in enabled_flags:
2597 if is_new or flag in old_use and all_flags:
2598 flag_str = red(flag)
2599 elif flag not in old_iuse:
2600 flag_str = yellow(flag) + "%*"
2601 elif flag not in old_use:
2602 flag_str = green(flag) + "*"
2603 elif flag in removed_iuse:
2605 flag_str = yellow("-" + flag) + "%"
2608 flag_str = "(" + flag_str + ")"
2609 removed.append(flag_str)
2612 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2613 flag_str = blue("-" + flag)
2614 elif flag not in old_iuse:
2615 flag_str = yellow("-" + flag)
2616 if flag not in iuse_forced:
2618 elif flag in old_use:
2619 flag_str = green("-" + flag) + "*"
2621 if flag in iuse_forced:
2622 flag_str = "(" + flag_str + ")"
2624 enabled.append(flag_str)
2626 disabled.append(flag_str)
2629 ret = " ".join(enabled)
2631 ret = " ".join(enabled + disabled + removed)
2633 ret = '%s="%s" ' % (name, ret)
2637 # FIXME: account for the possibility of different overlays in
2638 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2639 overlays = self.settings["PORTDIR_OVERLAY"].split()
2640 overlays_real = [os.path.realpath(t) \
2641 for t in self.settings["PORTDIR_OVERLAY"].split()]
2645 mygraph = self._parent_child_digraph
2650 if "blocks" == x[0]:
2651 display_list.append((x, 0, True))
2653 graph_key = tuple(x)
2654 if "--tree" in self.myopts:
2655 depth = len(tree_nodes)
2656 while depth and graph_key not in \
2657 mygraph.child_nodes(tree_nodes[depth-1]):
2660 tree_nodes = tree_nodes[:depth]
2661 tree_nodes.append(graph_key)
2662 display_list.append((x, depth, True))
2663 shown_edges.add((graph_key, tree_nodes[depth-1]))
2665 traversed_nodes = set() # prevent endless circles
2666 traversed_nodes.add(graph_key)
2667 def add_parents(current_node, ordered):
2669 # Do not traverse to parents if this node is an
2670 # an argument or a direct member of a set that has
2671 # been specified as an argument (system or world).
2672 if current_node not in self._set_nodes:
2673 parent_nodes = mygraph.parent_nodes(current_node)
2675 child_nodes = set(mygraph.child_nodes(current_node))
2676 selected_parent = None
2677 # First, try to avoid a direct cycle.
2678 for node in parent_nodes:
2679 if node not in traversed_nodes and \
2680 node not in child_nodes:
2681 edge = (current_node, node)
2682 if edge in shown_edges:
2684 selected_parent = node
2686 if not selected_parent:
2687 # A direct cycle is unavoidable.
2688 for node in parent_nodes:
2689 if node not in traversed_nodes:
2690 edge = (current_node, node)
2691 if edge in shown_edges:
2693 selected_parent = node
2696 shown_edges.add((current_node, selected_parent))
2697 traversed_nodes.add(selected_parent)
2698 add_parents(selected_parent, False)
2699 display_list.append((list(current_node),
2700 len(tree_nodes), ordered))
2701 tree_nodes.append(current_node)
2703 add_parents(graph_key, True)
2705 display_list.append((x, depth, True))
2706 mylist = display_list
2708 last_merge_depth = 0
2709 for i in xrange(len(mylist)-1,-1,-1):
2710 graph_key, depth, ordered = mylist[i]
2711 if not ordered and depth == 0 and i > 0 \
2712 and graph_key == mylist[i-1][0] and \
2713 mylist[i-1][1] == 0:
2714 # An ordered node got a consecutive duplicate when the tree was
2718 if "blocks" == graph_key[0]:
2720 if ordered and graph_key[-1] != "nomerge":
2721 last_merge_depth = depth
2723 if depth >= last_merge_depth or \
2724 i < len(mylist) - 1 and \
2725 depth >= mylist[i+1][1]:
2728 from portage import flatten
2729 from portage.dep import use_reduce, paren_reduce
2730 display_overlays=False
2731 # files to fetch list - avoids counting a same file twice
2732 # in size display (verbose mode)
2735 for mylist_index in xrange(len(mylist)):
2736 x, depth, ordered = mylist[mylist_index]
2740 portdb = self.trees[myroot]["porttree"].dbapi
2741 bindb = self.trees[myroot]["bintree"].dbapi
2742 vardb = self.trees[myroot]["vartree"].dbapi
2743 vartree = self.trees[myroot]["vartree"]
2744 pkgsettings = self.pkgsettings[myroot]
2749 addl=""+red("B")+" "+fetch+" "
2751 counters.blocks += 1
2752 resolved = portage.key_expand(
2753 pkg_key, mydb=vardb, settings=pkgsettings)
2754 if "--columns" in self.myopts and "--quiet" in self.myopts:
2755 addl = addl + " " + red(resolved)
2757 addl = "[blocks " + addl + "] " + red(resolved)
2758 block_parents = self.blocker_parents[tuple(x)]
2759 block_parents = set([pnode[2] for pnode in block_parents])
2760 block_parents = ", ".join(block_parents)
2762 addl += bad(" (\"%s\" is blocking %s)") % \
2763 (pkg_key, block_parents)
2765 addl += bad(" (is blocking %s)") % block_parents
2766 blockers.append(addl)
2768 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2770 pkg_merge = ordered and pkg_status != "nomerge"
2771 binary_package = True
2772 if "ebuild" == pkg_type:
2773 if "merge" == x[3] or \
2774 not vartree.dbapi.cpv_exists(pkg_key):
2775 """An ebuild "merge" node or a --onlydeps "nomerge"
2777 binary_package = False
2778 pkgsettings.setcpv(pkg_key, mydb=portdb)
2779 if pkg_key not in self.useFlags[myroot]:
2780 self.useFlags[myroot][pkg_key] = \
2781 pkgsettings["USE"].split()
2783 # An ebuild "nomerge" node, so USE come from the vardb.
2784 mydbapi = vartree.dbapi
2785 # reuse cached metadata from when the depgraph was built
2786 if "--resume" in self.myopts:
2787 # Populate the fakedb with relevant metadata, just like
2788 # would have happened when the depgraph was originally
2790 metadata = dict(izip(self._mydbapi_keys,
2791 mydbapi.aux_get(pkg_key, self._mydbapi_keys)))
2792 self.mydbapi[myroot].cpv_inject(pkg_key, metadata=metadata)
2794 metadata = dict(izip(self._mydbapi_keys,
2795 self.mydbapi[myroot].aux_get(
2796 pkg_key, self._mydbapi_keys)))
2797 mydbapi = self.mydbapi[myroot] # use the cached metadata
2798 if pkg_key not in self.useFlags[myroot]:
2799 """If this is a --resume then the USE flags need to be
2800 fetched from the appropriate locations here."""
2801 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2802 pkg_key, ["USE"])[0].split()
2805 restrict = flatten(use_reduce(paren_reduce(
2806 mydbapi.aux_get(pkg_key, ["RESTRICT"])[0]),
2807 uselist=self.useFlags[myroot][pkg_key]))
2808 except portage.exception.InvalidDependString, e:
2809 if pkg_status != "nomerge":
2810 restrict = mydbapi.aux_get(pkg_key, ["RESTRICT"])[0]
2811 show_invalid_depstring_notice(x, restrict, str(e))
2815 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2816 "fetch" in restrict:
2819 counters.restrict_fetch += 1
2820 if portdb.fetch_check(
2821 pkg_key, self.useFlags[myroot][pkg_key]):
2824 counters.restrict_fetch_satisfied += 1
2826 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2827 #param is used for -u, where you still *do* want to see when something is being upgraded.
2829 if vardb.cpv_exists(pkg_key):
2830 addl=" "+yellow("R")+fetch+" "
2831 if x[3] != "nomerge":
2833 counters.reinst += 1
2834 elif vardb.match(portage.dep_getkey(pkg_key)):
2835 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2836 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2837 portage.pkgsplit(x[2])[0])
2838 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2839 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2841 myoldbest=portage.best(myinslotlist)
2843 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2845 addl+=turquoise("U")+blue("D")
2847 counters.downgrades += 1
2850 addl+=turquoise("U")+" "
2852 counters.upgrades += 1
2854 # New slot, mark it new.
2855 addl=" "+green("NS")+fetch+" "
2857 counters.newslot += 1
2859 if "--changelog" in self.myopts:
2860 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2861 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2862 inst_matches = vardb.match(slot_atom)
2864 changelogs.extend(self.calc_changelog(
2865 portdb.findname(pkg_key),
2866 inst_matches[0], pkg_key))
2868 addl=" "+green("N")+" "+fetch+" "
2874 if pkg_key in self.useFlags[myroot]:
2876 cur_iuse = list(filter_iuse_defaults(
2877 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2879 forced_flags = set()
2880 if not binary_package:
2881 forced_flags.update(pkgsettings.useforce)
2882 forced_flags.update(pkgsettings.usemask)
2884 cur_iuse = portage.unique_array(cur_iuse)
2886 cur_use = self.useFlags[myroot][pkg_key]
2887 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2893 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2894 old_iuse, old_use = \
2895 self.trees[x[1]]["vartree"].dbapi.aux_get(
2896 pkg, ["IUSE", "USE"])
2897 old_iuse = list(set(
2898 filter_iuse_defaults(old_iuse.split())))
2900 old_use = old_use.split()
2907 old_use = [flag for flag in old_use if flag in old_iuse]
2909 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2911 use_expand.reverse()
2912 use_expand_hidden = \
2913 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2915 def map_to_use_expand(myvals, forcedFlags=False):
2918 for exp in use_expand:
2921 for val in myvals[:]:
2922 if val.startswith(exp.lower()+"_"):
2923 if val in forced_flags:
2924 forced[exp].add(val[len(exp)+1:])
2925 ret[exp].append(val[len(exp)+1:])
2928 forced["USE"] = [val for val in myvals \
2929 if val in forced_flags]
2930 for exp in use_expand_hidden:
2937 cur_iuse_map, iuse_forced = \
2938 map_to_use_expand(cur_iuse, forcedFlags=True)
2939 cur_use_map = map_to_use_expand(cur_use)
2940 old_iuse_map = map_to_use_expand(old_iuse)
2941 old_use_map = map_to_use_expand(old_use)
2944 use_expand.insert(0, "USE")
2946 for key in use_expand:
2947 if key in use_expand_hidden:
2949 verboseadd += create_use_string(key.upper(),
2950 cur_iuse_map[key], iuse_forced[key],
2951 cur_use_map[key], old_iuse_map[key],
2952 old_use_map[key], is_new)
2957 if pkg_type == "ebuild" and pkg_merge:
2959 myfilesdict = portdb.getfetchsizes(pkg_key,
2960 useflags=self.useFlags[myroot][pkg_key],
2962 except portage.exception.InvalidDependString, e:
2963 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2964 show_invalid_depstring_notice(x, src_uri, str(e))
2967 if myfilesdict is None:
2968 myfilesdict="[empty/missing/bad digest]"
2970 for myfetchfile in myfilesdict:
2971 if myfetchfile not in myfetchlist:
2972 mysize+=myfilesdict[myfetchfile]
2973 myfetchlist.append(myfetchfile)
2974 counters.totalsize += mysize
2975 verboseadd+=format_size(mysize)+" "
2978 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2979 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2980 file_name = portdb.findname(pkg_key)
2981 if file_name: # It might not exist in the tree
2982 newrepo = pkgsettings["PORTDIR"]
2984 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2985 oldrepo = self.trees[x[1]]["vartree"].dbapi.aux_get(pkg, ["repository"])[0]
2989 oldrepo = portdb.getRepositoryPath(oldrepo)
2990 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2991 if (overlays_real.count(dir_name) > 0):
2992 newrepoindex = overlays_real.index(os.path.normpath(dir_name))
2993 newrepo = overlays_real[newrepoindex]
2996 # assing lookup indexes
2999 elif oldrepo == pkgsettings["PORTDIR"]:
3002 oldrepoindex = str(overlays_real.index(os.path.normpath(oldrepo)) + 1)
3003 if oldrepoindex == newrepoindex \
3004 or not self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
3005 repoadd = newrepoindex
3007 repoadd = "%s=>%s" % (oldrepoindex, newrepoindex)
3009 verboseadd+=teal("[%s]" % repoadd)+" "
3010 display_overlays=True
3012 verboseadd += "[No ebuild?]"
3014 xs = list(portage.pkgsplit(x[2]))
3021 if "COLUMNWIDTH" in self.settings:
3023 mywidth = int(self.settings["COLUMNWIDTH"])
3024 except ValueError, e:
3025 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
3027 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
3028 self.settings["COLUMNWIDTH"], noiselevel=-1)
3033 indent = " " * depth
3036 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
3037 if myoldbest[-3:]=="-r0":
3038 myoldbest=myoldbest[:-3]
3039 myoldbest=blue("["+myoldbest+"]")
3042 root_config = self.roots[myroot]
3043 system_set = root_config.sets["system"]
3044 world_set = root_config.sets["world"]
3049 pkg_system = system_set.findAtomForPackage(pkg_key, metadata)
3050 pkg_world = world_set.findAtomForPackage(pkg_key, metadata)
3051 if not pkg_world and myroot == self.target_root and \
3052 favorites_set.findAtomForPackage(pkg_key, metadata):
3053 # Maybe it will be added to world now.
3054 if create_world_atom(pkg_key, metadata,
3055 favorites_set, root_config.sets, portdb):
3057 except portage.exception.InvalidDependString:
3058 # This is reported elsewhere if relevant.
3064 return colorize("PKG_MERGE_WORLD", pkg)
3066 return colorize("PKG_MERGE_SYSTEM", pkg)
3068 return colorize("PKG_MERGE", pkg)
3071 return colorize("PKG_NOMERGE_WORLD", pkg)
3073 return colorize("PKG_NOMERGE_SYSTEM", pkg)
3075 return colorize("PKG_NOMERGE", pkg)
3080 if "--columns" in self.myopts:
3081 if "--quiet" in self.myopts:
3082 myprint=addl+" "+indent+pkgprint(pkg_cp)
3083 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
3084 myprint=myprint+myoldbest
3085 myprint=myprint+darkgreen("to "+x[1])
3087 myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_cp)
3088 if (newlp-nc_len(myprint)) > 0:
3089 myprint=myprint+(" "*(newlp-nc_len(myprint)))
3090 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
3091 if (oldlp-nc_len(myprint)) > 0:
3092 myprint=myprint+" "*(oldlp-nc_len(myprint))
3093 myprint=myprint+myoldbest
3094 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
3097 myprint = "[%s ] " % pkgprint("nomerge")
3099 myprint = "[" + pkg_type + " " + addl + "] "
3100 myprint += indent + pkgprint(pkg_key) + " " + \
3101 myoldbest + darkgreen("to " + myroot) + " " + \
3104 if "--columns" in self.myopts:
3105 if "--quiet" in self.myopts:
3106 myprint=addl+" "+indent+pkgprint(pkg_cp)
3107 myprint=myprint+" "+green(xs[1]+xs[2])+" "
3108 myprint=myprint+myoldbest
3110 myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_cp)
3111 if (newlp-nc_len(myprint)) > 0:
3112 myprint=myprint+(" "*(newlp-nc_len(myprint)))
3113 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
3114 if (oldlp-nc_len(myprint)) > 0:
3115 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
3116 myprint=myprint+myoldbest+" "+verboseadd
3119 myprint="["+pkgprint("nomerge")+" ] "+indent+pkgprint(pkg_key)+" "+myoldbest+" "+verboseadd
3121 myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_key)+" "+myoldbest+" "+verboseadd
3124 mysplit = portage.pkgsplit(x[2])
3125 if "--tree" not in self.myopts and mysplit and \
3126 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
3129 if mysplit[2] == "r0":
3130 myversion = mysplit[1]
3132 myversion = "%s-%s" % (mysplit[1], mysplit[2])
3134 if myversion != portage.VERSION and "--quiet" not in self.myopts:
3135 if mylist_index < len(mylist) - 1 and \
3136 "livecvsportage" not in self.settings.features:
3137 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
3138 p.append(colorize("WARN", " then resume the merge."))
3150 if overlays and display_overlays:
3151 print "Portage tree and overlays:"
3153 print " "+teal("[0]"), self.settings["PORTDIR"]
3156 print " "+teal("["+str(y)+"]"),x
3157 print " "+teal("[?]"), "indicates that the source repository could not be determined"
3159 if "--changelog" in self.myopts:
3161 for revision,text in changelogs:
3162 print bold('*'+revision)
3163 sys.stdout.write(text)
3165 if self._pprovided_args:
3167 for arg_atom in self._pprovided_args:
3168 arg, atom = arg_atom
3169 arg_refs[arg_atom] = []
3170 cp = portage.dep_getkey(atom)
3171 for set_name, atom_set in self._sets.iteritems():
3172 if atom in atom_set:
3173 arg_refs[arg_atom].append(set_name)
3175 msg.append(bad("\nWARNING: "))
3176 if len(self._pprovided_args) > 1:
3177 msg.append("Requested packages will not be " + \
3178 "merged because they are listed in\n")
3180 msg.append("A requested package will not be " + \
3181 "merged because it is listed in\n")
3182 msg.append("package.provided:\n\n")
3183 problems_sets = set()
3184 for (arg, atom), refs in arg_refs.iteritems():
3187 problems_sets.update(refs)
3189 ref_string = ", ".join(["'%s'" % name for name in refs])
3190 ref_string = " pulled in by " + ref_string
3191 msg.append(" %s%s\n" % (colorize("INFORM", arg), ref_string))
3193 if "world" in problems_sets:
3194 msg.append("This problem can be solved in one of the following ways:\n\n")
3195 msg.append(" A) Use emaint to clean offending packages from world (if not installed).\n")
3196 msg.append(" B) Uninstall offending packages (cleans them from world).\n")
3197 msg.append(" C) Remove offending entries from package.provided.\n\n")
3198 msg.append("The best course of action depends on the reason that an offending\n")
3199 msg.append("package.provided entry exists.\n\n")
3200 sys.stderr.write("".join(msg))
3203 def calc_changelog(self,ebuildpath,current,next):
3204 if ebuildpath == None or not os.path.exists(ebuildpath):
3206 current = '-'.join(portage.catpkgsplit(current)[1:])
3207 if current.endswith('-r0'):
3208 current = current[:-3]
3209 next = '-'.join(portage.catpkgsplit(next)[1:])
3210 if next.endswith('-r0'):
3212 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
3214 changelog = open(changelogpath).read()
3215 except SystemExit, e:
3216 raise # Needed else can't exit
3219 divisions = self.find_changelog_tags(changelog)
3220 #print 'XX from',current,'to',next
3221 #for div,text in divisions: print 'XX',div
3222 # skip entries for all revisions above the one we are about to emerge
3223 for i in range(len(divisions)):
3224 if divisions[i][0]==next:
3225 divisions = divisions[i:]
3227 # find out how many entries we are going to display
3228 for i in range(len(divisions)):
3229 if divisions[i][0]==current:
3230 divisions = divisions[:i]
3233 # couldnt find the current revision in the list. display nothing
3237 def find_changelog_tags(self,changelog):
3241 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
3243 if release is not None:
3244 divs.append((release,changelog))
3246 if release is not None:
3247 divs.append((release,changelog[:match.start()]))
3248 changelog = changelog[match.end():]
3249 release = match.group(1)
3250 if release.endswith('.ebuild'):
3251 release = release[:-7]
3252 if release.endswith('-r0'):
3253 release = release[:-3]
3255 def saveNomergeFavorites(self):
3256 """Find atoms in favorites that are not in the mergelist and add them
3257 to the world file if necessary."""
3258 for x in ("--fetchonly", "--fetch-all-uri",
3259 "--oneshot", "--onlydeps", "--pretend"):
3260 if x in self.myopts:
3262 root_config = self.roots[self.target_root]
3263 world_set = root_config.sets["world"]
3266 args_set = self._sets["args"]
3267 portdb = self.trees[self.target_root]["porttree"].dbapi
3268 added_favorites = set()
3269 for x in self._set_nodes:
3270 pkg_type, root, pkg_key, pkg_status = x
3271 if pkg_status != "nomerge":
3273 metadata = dict(izip(self._mydbapi_keys,
3274 self.mydbapi[root].aux_get(pkg_key, self._mydbapi_keys)))
3276 myfavkey = create_world_atom(pkg_key, metadata,
3277 args_set, root_config.sets, portdb)
3279 if myfavkey in added_favorites:
3281 added_favorites.add(myfavkey)
3282 world_set.add(myfavkey)
3283 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3284 except portage.exception.InvalidDependString, e:
3285 writemsg("\n\n!!! '%s' has invalid PROVIDE: %s\n" % \
3286 (pkg_key, str(e)), noiselevel=-1)
3287 writemsg("!!! see '%s'\n\n" % os.path.join(
3288 root, portage.VDB_PATH, pkg_key, "PROVIDE"), noiselevel=-1)
3294 class PackageCounters(object):
3304 self.restrict_fetch = 0
3305 self.restrict_fetch_satisfied = 0
3308 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
3311 myoutput.append("Total: %s package" % total_installs)
3312 if total_installs != 1:
3313 myoutput.append("s")
3314 if total_installs != 0:
3315 myoutput.append(" (")
3316 if self.upgrades > 0:
3317 details.append("%s upgrade" % self.upgrades)
3318 if self.upgrades > 1:
3320 if self.downgrades > 0:
3321 details.append("%s downgrade" % self.downgrades)
3322 if self.downgrades > 1:
3325 details.append("%s new" % self.new)
3326 if self.newslot > 0:
3327 details.append("%s in new slot" % self.newslot)
3328 if self.newslot > 1:
3331 details.append("%s reinstall" % self.reinst)
3335 details.append("%s block" % self.blocks)
3338 myoutput.append(", ".join(details))
3339 if total_installs != 0:
3340 myoutput.append(")")
3341 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
3342 if self.restrict_fetch:
3343 myoutput.append("\nFetch Restriction: %s package" % \
3344 self.restrict_fetch)
3345 if self.restrict_fetch > 1:
3346 myoutput.append("s")
3347 if self.restrict_fetch_satisfied < self.restrict_fetch:
3348 myoutput.append(bad(" (%s unsatisfied)") % \
3349 (self.restrict_fetch - self.restrict_fetch_satisfied))
3350 return "".join(myoutput)
3352 class MergeTask(object):
3354 def __init__(self, settings, trees, myopts):
3355 self.settings = settings
3356 self.target_root = settings["ROOT"]
3358 self.myopts = myopts
3360 if settings.get("PORTAGE_DEBUG", "") == "1":
3362 self.pkgsettings = {}
3363 self.pkgsettings[self.target_root] = portage.config(clone=settings)
3364 if self.target_root != "/":
3365 self.pkgsettings["/"] = \
3366 portage.config(clone=trees["/"]["vartree"].settings)
3369 def merge(self, mylist, favorites, mtimedb):
3370 from portage.elog import elog_process
3371 from portage.elog.filtering import filter_mergephases
3373 fetchonly = "--fetchonly" in self.myopts or \
3374 "--fetch-all-uri" in self.myopts
3375 pretend = "--pretend" in self.myopts
3377 ldpath_mtimes = mtimedb["ldpath"]
3378 xterm_titles = "notitles" not in self.settings.features
3380 #check for blocking dependencies
3381 if "--fetchonly" not in self.myopts and \
3382 "--fetch-all-uri" not in self.myopts and \
3383 "--buildpkgonly" not in self.myopts:
3386 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
3387 print "!!! the two packages cannot be installed on the same system together."
3388 print "!!! Please use 'emerge --pretend' to determine blockers."
3389 if "--quiet" not in self.myopts:
3390 show_blocker_docs_link()
3393 if "--resume" in self.myopts:
3395 print colorize("GOOD", "*** Resuming merge...")
3396 emergelog(xterm_titles, " *** Resuming merge...")
3397 mylist = mtimedb["resume"]["mergelist"][:]
3398 if "--skipfirst" in self.myopts and mylist:
3399 del mtimedb["resume"]["mergelist"][0]
3402 validate_merge_list(self.trees, mylist)
3403 mymergelist = mylist
3405 # Verify all the manifests now so that the user is notified of failure
3406 # as soon as possible.
3407 if "--fetchonly" not in self.myopts and \
3408 "--fetch-all-uri" not in self.myopts and \
3409 "strict" in self.settings.features:
3410 shown_verifying_msg = False
3412 for myroot, pkgsettings in self.pkgsettings.iteritems():
3413 quiet_config = portage.config(clone=pkgsettings)
3414 quiet_config["PORTAGE_QUIET"] = "1"
3415 quiet_config.backup_changes("PORTAGE_QUIET")
3416 quiet_settings[myroot] = quiet_config
3419 if x[0] != "ebuild" or x[-1] == "nomerge":
3421 if not shown_verifying_msg:
3422 shown_verifying_msg = True
3423 print ">>> Verifying ebuild Manifests..."
3424 mytype, myroot, mycpv, mystatus = x
3425 portdb = self.trees[myroot]["porttree"].dbapi
3426 quiet_config = quiet_settings[myroot]
3427 quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
3428 if not portage.digestcheck([], quiet_config, strict=True):
3430 del x, mytype, myroot, mycpv, mystatus, quiet_config
3431 del shown_verifying_msg, quiet_settings
3433 system_set = SystemSet(self.settings)
3434 args_set = AtomSet(favorites)
3435 world_set = WorldSet(self.settings)
3436 if "--resume" not in self.myopts:
3437 mymergelist = mylist
3438 mtimedb["resume"]["mergelist"]=mymergelist[:]
3441 myfeat = self.settings.features[:]
3442 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3444 if "parallel-fetch" in myfeat and \
3445 not ("--pretend" in self.myopts or \
3446 "--fetch-all-uri" in self.myopts or \
3447 "--fetchonly" in self.myopts):
3448 if "distlocks" not in myfeat:
3450 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
3451 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
3453 elif len(mymergelist) > 1:
3454 print ">>> starting parallel fetching"
3455 fetch_log = "/var/log/emerge-fetch.log"
3456 logfile = open(fetch_log, "w")
3457 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3458 portage.util.apply_secpass_permissions(fetch_log,
3459 uid=portage.portage_uid, gid=portage.portage_gid,
3461 fetch_env = os.environ.copy()
3462 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3463 fetch_env["PORTAGE_NICENESS"] = "0"
3464 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3465 resume_opts = self.myopts.copy()
3466 # For automatic resume, we need to prevent
3467 # any of bad_resume_opts from leaking in
3468 # via EMERGE_DEFAULT_OPTS.
3469 resume_opts["--ignore-default-opts"] = True
3470 for myopt, myarg in resume_opts.iteritems():
3471 if myopt not in bad_resume_opts:
3473 fetch_args.append(myopt)
3475 fetch_args.append(myopt +"="+ myarg)
3476 portage.process.spawn(fetch_args, env=fetch_env,
3477 fd_pipes=fd_pipes, returnpid=True)
3478 logfile.close() # belongs to the spawned process
3479 del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3482 metadata_keys = [k for k in portage.auxdbkeys \
3483 if not k.startswith("UNUSED_")] + ["USE"]
3486 for x in mymergelist:
3492 portdb = self.trees[myroot]["porttree"].dbapi
3493 bindb = self.trees[myroot]["bintree"].dbapi
3494 vartree = self.trees[myroot]["vartree"]
3495 pkgsettings = self.pkgsettings[myroot]
3497 if pkg_type == "blocks":
3499 elif pkg_type == "ebuild":
3501 metadata.update(izip(metadata_keys,
3502 mydbapi.aux_get(pkg_key, metadata_keys)))
3503 pkgsettings.setcpv(pkg_key, mydb=mydbapi)
3504 metadata["USE"] = pkgsettings["USE"]
3506 if pkg_type == "binary":
3509 raise AssertionError("Package type: '%s'" % pkg_type)
3510 metadata.update(izip(metadata_keys,
3511 mydbapi.aux_get(pkg_key, metadata_keys)))
3514 y = portdb.findname(pkg_key)
3515 if "--pretend" not in self.myopts:
3516 print "\n>>> Emerging (" + \
3517 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3518 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3519 colorize("GOOD", x[pkgindex]) + " to " + x[1]
3520 emergelog(xterm_titles, " >>> emerge ("+\
3521 str(mergecount)+" of "+str(len(mymergelist))+\
3522 ") "+x[pkgindex]+" to "+x[1])
3524 pkgsettings["EMERGE_FROM"] = x[0]
3525 pkgsettings.backup_changes("EMERGE_FROM")
3528 #buildsyspkg: Check if we need to _force_ binary package creation
3529 issyspkg = ("buildsyspkg" in myfeat) \
3530 and x[0] != "blocks" \
3531 and system_set.findAtomForPackage(pkg_key, metadata) \
3532 and "--buildpkg" not in self.myopts
3533 if x[0] in ["ebuild","blocks"]:
3534 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3535 raise Exception, "Merging a blocker"
3536 elif "--fetchonly" in self.myopts or \
3537 "--fetch-all-uri" in self.myopts:
3538 if "--fetch-all-uri" in self.myopts:
3539 retval = portage.doebuild(y, "fetch", myroot,
3540 pkgsettings, self.edebug,
3541 "--pretend" in self.myopts, fetchonly=1,
3542 fetchall=1, mydbapi=portdb, tree="porttree")
3544 retval = portage.doebuild(y, "fetch", myroot,
3545 pkgsettings, self.edebug,
3546 "--pretend" in self.myopts, fetchonly=1,
3547 mydbapi=portdb, tree="porttree")
3548 if (retval is None) or retval:
3550 print "!!! Fetch for",y,"failed, continuing..."
3552 failed_fetches.append(pkg_key)
3556 portage.doebuild_environment(y, "setup", myroot,
3557 pkgsettings, self.edebug, 1, portdb)
3558 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3559 portage.util.ensure_dirs(os.path.dirname(catdir),
3560 uid=portage.portage_uid, gid=portage.portage_gid,
3562 builddir_lock = None
3565 catdir_lock = portage.locks.lockdir(catdir)
3566 portage.util.ensure_dirs(catdir,
3567 uid=portage.portage_uid, gid=portage.portage_gid,
3569 builddir_lock = portage.locks.lockdir(
3570 pkgsettings["PORTAGE_BUILDDIR"])
3572 portage.locks.unlockdir(catdir_lock)
3575 msg = " === (%s of %s) Cleaning (%s::%s)" % \
3576 (mergecount, len(mymergelist), pkg_key, y)
3577 short_msg = "emerge: (%s of %s) %s Clean" % \
3578 (mergecount, len(mymergelist), pkg_key)
3579 emergelog(xterm_titles, msg, short_msg=short_msg)
3580 retval = portage.doebuild(y, "clean", myroot,
3581 pkgsettings, self.edebug, cleanup=1,
3582 mydbapi=portdb, tree="porttree")
3583 if retval != os.EX_OK:
3585 if "--buildpkg" in self.myopts or issyspkg:
3587 print ">>> This is a system package, " + \
3588 "let's pack a rescue tarball."
3589 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3590 (mergecount, len(mymergelist), pkg_key, y)
3591 short_msg = "emerge: (%s of %s) %s Compile" % \
3592 (mergecount, len(mymergelist), pkg_key)
3593 emergelog(xterm_titles, msg, short_msg=short_msg)
3594 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3595 binpkg_tmpfile = os.path.join(pkgsettings["PKGDIR"],
3596 pkg_key + ".tbz2." + str(os.getpid()))
3597 pkgsettings["PORTAGE_BINPKG_TMPFILE"] = binpkg_tmpfile
3598 pkgsettings.backup_changes("PORTAGE_BINPKG_TMPFILE")
3599 retval = portage.doebuild(y, "package", myroot,
3600 pkgsettings, self.edebug, mydbapi=portdb,
3602 del pkgsettings["PORTAGE_BINPKG_TMPFILE"]
3603 if retval != os.EX_OK or \
3604 "--buildpkgonly" in self.myopts:
3605 elog_process(pkg_key, pkgsettings, phasefilter=filter_mergephases)
3606 if retval != os.EX_OK:
3608 bintree = self.trees[myroot]["bintree"]
3609 bintree.inject(pkg_key, filename=binpkg_tmpfile)
3610 if "--buildpkgonly" not in self.myopts:
3611 msg = " === (%s of %s) Merging (%s::%s)" % \
3612 (mergecount, len(mymergelist), pkg_key, y)
3613 short_msg = "emerge: (%s of %s) %s Merge" % \
3614 (mergecount, len(mymergelist), pkg_key)
3615 emergelog(xterm_titles, msg, short_msg=short_msg)
3616 retval = portage.merge(pkgsettings["CATEGORY"],
3617 pkgsettings["PF"], pkgsettings["D"],
3618 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3619 "build-info"), myroot, pkgsettings,
3620 myebuild=pkgsettings["EBUILD"],
3621 mytree="porttree", mydbapi=portdb,
3622 vartree=vartree, prev_mtimes=ldpath_mtimes)
3623 if retval != os.EX_OK:
3625 elif "noclean" not in pkgsettings.features:
3626 portage.doebuild(y, "clean", myroot,
3627 pkgsettings, self.edebug, mydbapi=portdb,
3630 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3631 (mergecount, len(mymergelist), pkg_key, y)
3632 short_msg = "emerge: (%s of %s) %s Compile" % \
3633 (mergecount, len(mymergelist), pkg_key)
3634 emergelog(xterm_titles, msg, short_msg=short_msg)
3635 retval = portage.doebuild(y, "merge", myroot,
3636 pkgsettings, self.edebug, vartree=vartree,
3637 mydbapi=portdb, tree="porttree",
3638 prev_mtimes=ldpath_mtimes)
3639 if retval != os.EX_OK:
3643 portage.locks.unlockdir(builddir_lock)
3646 # Lock catdir for removal if empty.
3647 catdir_lock = portage.locks.lockdir(catdir)
3653 if e.errno not in (errno.ENOENT,
3654 errno.ENOTEMPTY, errno.EEXIST):
3657 portage.locks.unlockdir(catdir_lock)
3659 elif x[0]=="binary":
3661 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3662 if "--getbinpkg" in self.myopts:
3665 if "distlocks" in pkgsettings.features and \
3666 os.access(pkgsettings["PKGDIR"], os.W_OK):
3667 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3668 tbz2_lock = portage.locks.lockfile(mytbz2,
3670 if self.trees[myroot]["bintree"].isremote(pkg_key):
3671 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3672 (mergecount, len(mymergelist), pkg_key, mytbz2)
3673 short_msg = "emerge: (%s of %s) %s Fetch" % \
3674 (mergecount, len(mymergelist), pkg_key)
3675 emergelog(xterm_titles, msg, short_msg=short_msg)
3677 self.trees[myroot]["bintree"].gettbz2(pkg_key)
3678 except portage.exception.FileNotFound:
3679 writemsg("!!! Fetching Binary failed " + \
3680 "for '%s'\n" % pkg_key, noiselevel=-1)
3683 failed_fetches.append(pkg_key)
3684 except portage.exception.DigestException, e:
3685 writemsg("\n!!! Digest verification failed:\n",
3687 writemsg("!!! %s\n" % e.value[0],
3689 writemsg("!!! Reason: %s\n" % e.value[1],
3691 writemsg("!!! Got: %s\n" % e.value[2],
3693 writemsg("!!! Expected: %s\n" % e.value[3],
3698 failed_fetches.append(pkg_key)
3701 portage.locks.unlockfile(tbz2_lock)
3703 if "--fetchonly" in self.myopts or \
3704 "--fetch-all-uri" in self.myopts:
3708 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3709 emergelog(xterm_titles, " === ("+str(mergecount)+\
3710 " of "+str(len(mymergelist))+") Merging Binary ("+\
3711 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3712 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3714 vartree=self.trees[myroot]["vartree"],
3715 prev_mtimes=ldpath_mtimes)
3716 if retval != os.EX_OK:
3718 #need to check for errors
3719 if "--buildpkgonly" not in self.myopts:
3720 self.trees[x[1]]["vartree"].inject(x[2])
3721 myfavkey = portage.cpv_getkey(x[2])
3722 if not fetchonly and not pretend and \
3723 args_set.findAtomForPackage(pkg_key, metadata):
3726 myfavkey = create_world_atom(pkg_key, metadata,
3727 args_set, {"world":world_set, "system":system_set},
3730 world_set.add(myfavkey)
3731 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3732 emergelog(xterm_titles, " === ("+\
3733 str(mergecount)+" of "+\
3734 str(len(mymergelist))+\
3735 ") Updating world file ("+x[pkgindex]+")")
3739 if "--pretend" not in self.myopts and \
3740 "--fetchonly" not in self.myopts and \
3741 "--fetch-all-uri" not in self.myopts:
3742 # Clean the old package that we have merged over top of it.
3743 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3744 xsplit=portage.pkgsplit(x[2])
3745 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3746 retval = unmerge(pkgsettings, self.myopts, vartree,
3747 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3749 emergelog(xterm_titles,
3750 " --- AUTOCLEAN: Nothing unmerged.")
3752 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3753 + " AUTOCLEAN is disabled. This can cause serious"
3754 + " problems due to overlapping packages.\n")
3756 # Figure out if we need a restart.
3757 mysplit=portage.pkgsplit(x[2])
3758 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3759 myver=mysplit[1]+"-"+mysplit[2]
3760 if myver[-3:]=='-r0':
3762 if (myver != portage.VERSION) and \
3763 "livecvsportage" not in self.settings.features:
3764 if len(mymergelist) > mergecount:
3765 emergelog(xterm_titles,
3766 " ::: completed emerge ("+ \
3767 str(mergecount)+" of "+ \
3768 str(len(mymergelist))+") "+ \
3770 emergelog(xterm_titles, " *** RESTARTING " + \
3771 "emerge via exec() after change of " + \
3773 del mtimedb["resume"]["mergelist"][0]
3775 portage.run_exitfuncs()
3776 mynewargv=[sys.argv[0],"--resume"]
3777 resume_opts = self.myopts.copy()
3778 # For automatic resume, we need to prevent
3779 # any of bad_resume_opts from leaking in
3780 # via EMERGE_DEFAULT_OPTS.
3781 resume_opts["--ignore-default-opts"] = True
3782 for myopt, myarg in resume_opts.iteritems():
3783 if myopt not in bad_resume_opts:
3785 mynewargv.append(myopt)
3787 mynewargv.append(myopt +"="+ myarg)
3788 # priority only needs to be adjusted on the first run
3789 os.environ["PORTAGE_NICENESS"] = "0"
3790 os.execv(mynewargv[0], mynewargv)
3792 if "--pretend" not in self.myopts and \
3793 "--fetchonly" not in self.myopts and \
3794 "--fetch-all-uri" not in self.myopts:
3795 if "noclean" not in self.settings.features:
3796 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3797 (mergecount, len(mymergelist), x[pkgindex])
3798 emergelog(xterm_titles, (" === (%s of %s) " + \
3799 "Post-Build Cleaning (%s::%s)") % \
3800 (mergecount, len(mymergelist), x[pkgindex], y),
3801 short_msg=short_msg)
3802 emergelog(xterm_titles, " ::: completed emerge ("+\
3803 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3806 # Unsafe for parallel merges
3807 del mtimedb["resume"]["mergelist"][0]
3808 # Commit after each merge so that --resume may still work in
3809 # in the event that portage is not allowed to exit normally
3810 # due to power failure, SIGKILL, etc...
3814 if "--pretend" not in self.myopts:
3815 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3817 # We're out of the loop... We're done. Delete the resume data.
3818 if mtimedb.has_key("resume"):
3819 del mtimedb["resume"]
3822 #by doing an exit this way, --fetchonly can continue to try to
3823 #fetch everything even if a particular download fails.
3824 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3826 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3827 "encountered. Please see above for details.\n\n")
3828 for cpv in failed_fetches:
3829 sys.stderr.write(" ")
3830 sys.stderr.write(cpv)
3831 sys.stderr.write("\n")
3832 sys.stderr.write("\n")
3838 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3839 ldpath_mtimes, autoclean=0):
3840 candidate_catpkgs=[]
3842 xterm_titles = "notitles" not in settings.features
3844 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3846 # At least the parent needs to exist for the lock file.
3847 portage.util.ensure_dirs(vdb_path)
3848 except portage.exception.PortageException:
3852 if os.access(vdb_path, os.W_OK):
3853 vdb_lock = portage.locks.lockdir(vdb_path)
3854 realsyslist = getlist(settings, "system")
3856 for x in realsyslist:
3857 mycp = portage.dep_getkey(x)
3858 if mycp in settings.getvirtuals():
3860 for provider in settings.getvirtuals()[mycp]:
3861 if vartree.dbapi.match(provider):
3862 providers.append(provider)
3863 if len(providers) == 1:
3864 syslist.extend(providers)
3866 syslist.append(mycp)
3868 mysettings = portage.config(clone=settings)
3870 if not unmerge_files or "world" in unmerge_files or \
3871 "system" in unmerge_files:
3872 if "unmerge"==unmerge_action:
3874 print bold("emerge unmerge") + " can only be used with " + \
3875 "specific package names, not with "+bold("world")+" or"
3876 print bold("system")+" targets."
3883 # process all arguments and add all
3884 # valid db entries to candidate_catpkgs
3886 if not unmerge_files or "world" in unmerge_files:
3887 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3888 elif "system" in unmerge_files:
3889 candidate_catpkgs.extend(getlist(settings, "system"))
3891 #we've got command-line arguments
3892 if not unmerge_files:
3893 print "\nNo packages to unmerge have been provided.\n"
3895 for x in unmerge_files:
3896 arg_parts = x.split('/')
3897 if x[0] not in [".","/"] and \
3898 arg_parts[-1][-7:] != ".ebuild":
3899 #possible cat/pkg or dep; treat as such
3900 candidate_catpkgs.append(x)
3901 elif unmerge_action in ["prune","clean"]:
3902 print "\n!!! Prune and clean do not accept individual" + \
3903 " ebuilds as arguments;\n skipping.\n"
3906 # it appears that the user is specifying an installed
3907 # ebuild and we're in "unmerge" mode, so it's ok.
3908 if not os.path.exists(x):
3909 print "\n!!! The path '"+x+"' doesn't exist.\n"
3912 absx = os.path.abspath(x)
3913 sp_absx = absx.split("/")
3914 if sp_absx[-1][-7:] == ".ebuild":
3916 absx = "/".join(sp_absx)
3918 sp_absx_len = len(sp_absx)
3920 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3921 vdb_len = len(vdb_path)
3923 sp_vdb = vdb_path.split("/")
3924 sp_vdb_len = len(sp_vdb)
3926 if not os.path.exists(absx+"/CONTENTS"):
3927 print "!!! Not a valid db dir: "+str(absx)
3930 if sp_absx_len <= sp_vdb_len:
3931 # The Path is shorter... so it can't be inside the vdb.
3934 print "\n!!!",x,"cannot be inside "+ \
3935 vdb_path+"; aborting.\n"
3938 for idx in range(0,sp_vdb_len):
3939 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3942 print "\n!!!", x, "is not inside "+\
3943 vdb_path+"; aborting.\n"
3946 print "="+"/".join(sp_absx[sp_vdb_len:])
3947 candidate_catpkgs.append(
3948 "="+"/".join(sp_absx[sp_vdb_len:]))
3951 if (not "--quiet" in myopts):
3953 if settings["ROOT"] != "/":
3954 print darkgreen(newline+ \
3955 ">>> Using system located in ROOT tree "+settings["ROOT"])
3956 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3957 not ("--quiet" in myopts):
3958 print darkgreen(newline+\
3959 ">>> These are the packages that would be unmerged:")
3963 for x in candidate_catpkgs:
3964 # cycle through all our candidate deps and determine
3965 # what will and will not get unmerged
3967 mymatch=localtree.dep_match(x)
3970 except ValueError, errpkgs:
3971 print "\n\n!!! The short ebuild name \"" + \
3972 x + "\" is ambiguous. Please specify"
3973 print "!!! one of the following fully-qualified " + \
3974 "ebuild names instead:\n"
3975 for i in errpkgs[0]:
3976 print " " + green(i)
3980 if not mymatch and x[0] not in "<>=~":
3981 #add a "=" if missing
3982 mymatch=localtree.dep_match("="+x)
3984 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3985 (x, unmerge_action), noiselevel=-1)
3987 mykey = portage.key_expand(
3989 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3990 if not pkgmap.has_key(mykey):
3991 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3992 if unmerge_action=="unmerge":
3994 if y not in pkgmap[mykey]["selected"]:
3995 pkgmap[mykey]["selected"].append(y)
3996 numselected=numselected+len(mymatch)
3999 #unmerge_action in ["prune", clean"]
4001 for mypkg in mymatch:
4002 if unmerge_action=="clean":
4003 myslot=localtree.getslot(mypkg)
4005 # since we're pruning, we don't care about slots
4006 # and put all the pkgs in together
4008 if not slotmap.has_key(myslot):
4010 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
4011 for myslot in slotmap:
4012 counterkeys=slotmap[myslot].keys()
4017 pkgmap[mykey]["protected"].append(
4018 slotmap[myslot][counterkeys[-1]])
4020 #be pretty and get them in order of merge:
4021 for ckey in counterkeys:
4022 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
4023 numselected=numselected+1
4024 # ok, now the last-merged package
4025 # is protected, and the rest are selected
4026 if global_unmerge and not numselected:
4027 portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
4031 portage.writemsg_stdout(
4032 "\n>>> No packages selected for removal by " + \
4033 unmerge_action + "\n")
4037 portage.locks.unlockdir(vdb_lock)
4039 for y in localtree.dep_match(x):
4040 if y not in pkgmap[x]["omitted"] and \
4041 y not in pkgmap[x]["selected"] and \
4042 y not in pkgmap[x]["protected"]:
4043 pkgmap[x]["omitted"].append(y)
4044 if global_unmerge and not pkgmap[x]["selected"]:
4045 #avoid cluttering the preview printout with stuff that isn't getting unmerged
4047 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
4048 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
4049 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
4050 if "--pretend" not in myopts and "--ask" not in myopts:
4051 countdown(int(settings["EMERGE_WARNING_DELAY"]),
4052 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
4053 if "--quiet" not in myopts:
4054 print "\n "+white(x)
4056 print white(x)+": ",
4057 for mytype in ["selected","protected","omitted"]:
4058 if "--quiet" not in myopts:
4059 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
4060 if pkgmap[x][mytype]:
4061 for mypkg in pkgmap[x][mytype]:
4062 mysplit=portage.catpkgsplit(mypkg)
4063 if mysplit[3]=="r0":
4064 myversion=mysplit[2]
4066 myversion=mysplit[2]+"-"+mysplit[3]
4067 if mytype=="selected":
4068 portage.writemsg_stdout(
4069 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
4071 portage.writemsg_stdout(
4072 colorize("GOOD", myversion + " "), noiselevel=-1)
4074 portage.writemsg_stdout("none ", noiselevel=-1)
4075 if "--quiet" not in myopts:
4076 portage.writemsg_stdout("\n", noiselevel=-1)
4077 if "--quiet" in myopts:
4078 portage.writemsg_stdout("\n", noiselevel=-1)
4080 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
4081 " packages are slated for removal.\n")
4082 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
4083 " and " + colorize("GOOD", "'omitted'") + \
4084 " packages will not be removed.\n\n")
4086 if "--pretend" in myopts:
4087 #we're done... return
4089 if "--ask" in myopts:
4090 if userquery("Would you like to unmerge these packages?")=="No":
4091 # enter pretend mode for correct formatting of results
4092 myopts["--pretend"] = True
4097 #the real unmerging begins, after a short delay....
4099 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
4102 for y in pkgmap[x]["selected"]:
4103 print ">>> Unmerging "+y+"..."
4104 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
4105 mysplit=y.split("/")
4107 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
4108 mysettings, unmerge_action not in ["clean","prune"],
4109 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
4110 if retval != os.EX_OK:
4111 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
4112 ebuild = vartree.dbapi.findname(y)
4113 show_unmerge_failure_message(y, ebuild, retval)
4116 clean_world(vartree.dbapi, y)
4117 emergelog(xterm_titles, " >>> unmerge success: "+y)
4120 def show_unmerge_failure_message(pkg, ebuild, retval):
4122 from formatter import AbstractFormatter, DumbWriter
4123 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
4126 msg.append("A removal phase of the '%s' package " % pkg)
4127 msg.append("has failed with exit value %s. " % retval)
4128 msg.append("The problem occurred while executing ")
4129 msg.append("the ebuild located at '%s'. " % ebuild)
4130 msg.append("If necessary, manually remove the ebuild " )
4131 msg.append("in order to skip the execution of removal phases.")
4135 f.add_flowing_data(x)
4139 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
4141 if os.path.exists("/usr/bin/install-info"):
4146 inforoot=normpath(root+z)
4147 if os.path.isdir(inforoot):
4148 infomtime = long(os.stat(inforoot).st_mtime)
4149 if inforoot not in prev_mtimes or \
4150 prev_mtimes[inforoot] != infomtime:
4151 regen_infodirs.append(inforoot)
4153 if not regen_infodirs:
4154 portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
4156 portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
4160 for inforoot in regen_infodirs:
4163 for filename in ("dir", "dir.gz", "dir.bz2"):
4164 file_path = os.path.join(inforoot, filename)
4166 os.rename(file_path, file_path + ".old")
4168 if e.errno != errno.ENOENT:
4172 if not os.path.isdir(inforoot):
4175 file_list = os.listdir(inforoot)
4178 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
4180 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
4181 existsstr="already exists, for file `"
4183 if re.search(existsstr,myso):
4184 # Already exists... Don't increment the count for this.
4186 elif myso[:44]=="install-info: warning: no info dir entry in ":
4187 # This info file doesn't contain a DIR-header: install-info produces this
4188 # (harmless) warning (the --quiet switch doesn't seem to work).
4189 # Don't increment the count for this.
4193 errmsg += myso + "\n"
4196 #update mtime so we can potentially avoid regenerating.
4197 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
4200 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
4203 print " "+green("*")+" Processed",icount,"info files."
4206 def display_news_notification(trees):
4207 for target_root in trees:
4208 if len(trees) > 1 and target_root != "/":
4210 settings = trees[target_root]["vartree"].settings
4211 portdb = trees[target_root]["porttree"].dbapi
4212 vardb = trees[target_root]["vartree"].dbapi
4213 NEWS_PATH = os.path.join("metadata", "news")
4214 UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
4215 newsReaderDisplay = False
4217 for repo in portdb.getRepositories():
4218 unreadItems = checkUpdatedNewsItems(
4219 portdb, vardb, NEWS_PATH, UNREAD_PATH, repo)
4221 if not newsReaderDisplay:
4222 newsReaderDisplay = True
4224 print colorize("WARN", " * IMPORTANT:"),
4225 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
4228 if newsReaderDisplay:
4229 print colorize("WARN", " *"),
4230 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
4233 def post_emerge(trees, mtimedb, retval):
4235 Misc. things to run at the end of a merge session.
4241 Display preserved libs warnings
4244 @param trees: A dictionary mapping each ROOT to it's package databases
4246 @param mtimedb: The mtimeDB to store data needed across merge invocations
4247 @type mtimedb: MtimeDB class instance
4248 @param retval: Emerge's return value
4252 1. Calls sys.exit(retval)
4254 for target_root in trees:
4255 if len(trees) > 1 and target_root != "/":
4257 vardbapi = trees[target_root]["vartree"].dbapi
4258 settings = vardbapi.settings
4259 info_mtimes = mtimedb["info"]
4261 # Load the most current variables from ${ROOT}/etc/profile.env
4263 settings.regenerate()
4266 config_protect = settings.get("CONFIG_PROTECT","").split()
4267 infodirs = settings.get("INFOPATH","").split(":") + \
4268 settings.get("INFODIR","").split(":")
4272 emergelog("notitles" not in settings.features,
4273 " *** exiting successfully.")
4275 # Dump the mod_echo output now so that our other notifications are shown
4277 from portage.elog import mod_echo
4280 if "noinfo" not in settings.features:
4281 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
4283 chk_updated_cfg_files(target_root, config_protect)
4285 display_news_notification(trees)
4287 if vardbapi.plib_registry.hasEntries():
4288 print colorize("WARN", "!!!") + " existing preserved libs:"
4289 plibdata = vardbapi.plib_registry.getPreservedLibs()
4290 for cpv in plibdata:
4291 print colorize("WARN", ">>>") + " package: %s" % cpv
4292 for f in plibdata[cpv]:
4293 print colorize("WARN", " * ") + " - %s" % f
4294 print "Use " + colorize("GOOD", "revdep-rebuild") + " to rebuild packages using these libraries"
4295 print "and then remerge the packages listed above."
4301 def chk_updated_cfg_files(target_root, config_protect):
4303 #number of directories with some protect files in them
4305 for x in config_protect:
4306 x = os.path.join(target_root, x.lstrip(os.path.sep))
4308 mymode = os.lstat(x).st_mode
4311 if stat.S_ISDIR(mymode):
4312 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
4314 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
4315 os.path.split(x.rstrip(os.path.sep))
4316 a = commands.getstatusoutput(mycommand + \
4317 " ! -iname '.*~' ! -iname '.*.bak'")
4319 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
4321 files = a[1].split()
4324 print colorize("WARN", " * IMPORTANT:"),
4325 if stat.S_ISDIR(mymode):
4326 print "%d config files in '%s' need updating." % \
4329 print "config file '%s' needs updating." % x
4332 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
4333 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
4335 def checkUpdatedNewsItems(portdb, vardb, NEWS_PATH, UNREAD_PATH, repo_id):
4337 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
4338 Returns the number of unread (yet relevent) items.
4340 @param portdb: a portage tree database
4341 @type portdb: pordbapi
4342 @param vardb: an installed package database
4343 @type vardb: vardbapi
4352 1. The number of unread but relevant news items.
4355 from portage.news import NewsManager
4356 manager = NewsManager(portdb, vardb, NEWS_PATH, UNREAD_PATH)
4357 return manager.getUnreadItems( repo_id, update=True )
4359 def is_valid_package_atom(x):
4361 testkey = portage.dep_getkey(x)
4362 except portage.exception.InvalidData:
4364 if testkey.startswith("null/"):
4365 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
4370 return portage.isvalidatom(testatom)
4372 def validate_merge_list(trees, mergelist):
4373 """Validate the list to make sure all the packages are still available.
4374 This is needed for --resume."""
4375 for (pkg_type, myroot, pkg_key, action) in mergelist:
4376 if pkg_type == "binary" and \
4377 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
4378 pkg_type == "ebuild" and \
4379 not trees[myroot]["porttree"].dbapi.xmatch(
4380 "match-all", "="+pkg_key):
4381 print red("!!! Error: The resume list contains packages that are no longer")
4382 print red("!!! available to be emerged. Please restart/continue")
4383 print red("!!! the merge operation manually.")
4386 def show_blocker_docs_link():
4388 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
4389 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
4391 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
4394 def action_sync(settings, trees, mtimedb, myopts, myaction):
4395 xterm_titles = "notitles" not in settings.features
4396 emergelog(xterm_titles, " === sync")
4397 myportdir = settings.get("PORTDIR", None)
4399 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
4401 if myportdir[-1]=="/":
4402 myportdir=myportdir[:-1]
4403 if not os.path.exists(myportdir):
4404 print ">>>",myportdir,"not found, creating it."
4405 os.makedirs(myportdir,0755)
4406 syncuri=settings["SYNC"].rstrip()
4408 updatecache_flg = False
4409 if myaction == "metadata":
4410 print "skipping sync"
4411 updatecache_flg = True
4412 tmpservertimestampfile = None
4413 elif syncuri[:8]=="rsync://":
4414 if not os.path.exists("/usr/bin/rsync"):
4415 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
4416 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
4421 import shlex, StringIO
4422 if settings["PORTAGE_RSYNC_OPTS"] == "":
4423 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
4425 "--recursive", # Recurse directories
4426 "--links", # Consider symlinks
4427 "--safe-links", # Ignore links outside of tree
4428 "--perms", # Preserve permissions
4429 "--times", # Preserive mod times
4430 "--compress", # Compress the data transmitted
4431 "--force", # Force deletion on non-empty dirs
4432 "--whole-file", # Don't do block transfers, only entire files
4433 "--delete", # Delete files that aren't in the master tree
4434 "--delete-after", # Delete only after everything else is done
4435 "--stats", # Show final statistics about what was transfered
4436 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
4437 "--exclude=/distfiles", # Exclude distfiles from consideration
4438 "--exclude=/local", # Exclude local from consideration
4439 "--exclude=/packages", # Exclude packages from consideration
4440 "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
4444 # The below validation is not needed when using the above hardcoded
4447 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
4448 lexer = shlex.shlex(StringIO.StringIO(
4449 settings.get("PORTAGE_RSYNC_OPTS","")), posix=True)
4450 lexer.whitespace_split = True
4451 rsync_opts.extend(lexer)
4454 for opt in ("--recursive", "--times"):
4455 if opt not in rsync_opts:
4456 portage.writemsg(yellow("WARNING:") + " adding required option " + \
4457 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4458 rsync_opts.append(opt)
4460 for exclude in ("distfiles", "local", "packages"):
4461 opt = "--exclude=/%s" % exclude
4462 if opt not in rsync_opts:
4463 portage.writemsg(yellow("WARNING:") + \
4464 " adding required option %s not included in " % opt + \
4465 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
4466 rsync_opts.append(opt)
4468 if settings["RSYNC_TIMEOUT"] != "":
4469 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
4470 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4472 mytimeout = int(settings["RSYNC_TIMEOUT"])
4473 rsync_opts.append("--timeout=%d" % mytimeout)
4474 except ValueError, e:
4475 portage.writemsg("!!! %s\n" % str(e))
4477 # TODO: determine options required for official servers
4478 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
4480 def rsync_opt_startswith(opt_prefix):
4481 for x in rsync_opts:
4482 if x.startswith(opt_prefix):
4486 if not rsync_opt_startswith("--timeout="):
4487 rsync_opts.append("--timeout=%d" % mytimeout)
4489 for opt in ("--compress", "--whole-file"):
4490 if opt not in rsync_opts:
4491 portage.writemsg(yellow("WARNING:") + " adding required option " + \
4492 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4493 rsync_opts.append(opt)
4495 if "--quiet" in myopts:
4496 rsync_opts.append("--quiet") # Shut up a lot
4498 rsync_opts.append("--verbose") # Print filelist
4500 if "--verbose" in myopts:
4501 rsync_opts.append("--progress") # Progress meter for each file
4503 if "--debug" in myopts:
4504 rsync_opts.append("--checksum") # Force checksum on all files
4506 if settings["RSYNC_EXCLUDEFROM"] != "":
4507 portage.writemsg(yellow("WARNING:") + \
4508 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
4509 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4510 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
4511 rsync_opts.append("--exclude-from=%s" % \
4512 settings["RSYNC_EXCLUDEFROM"])
4514 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
4515 " but file does not exist.\n")
4517 if settings["RSYNC_RATELIMIT"] != "":
4518 portage.writemsg(yellow("WARNING:") + \
4519 " usage of RSYNC_RATELIMIT is deprecated, use " + \
4520 "PORTAGE_RSYNC_EXTRA_OPTS instead")
4521 rsync_opts.append("--bwlimit=%s" % \
4522 settings["RSYNC_RATELIMIT"])
4524 # Real local timestamp file.
4525 servertimestampfile = os.path.join(
4526 myportdir, "metadata", "timestamp.chk")
4527 # Temporary file for remote server timestamp comparison.
4528 tmpservertimestampfile = os.path.join(
4529 settings["PORTAGE_TMPDIR"], "timestamp.chk")
4531 content = portage.util.grabfile(servertimestampfile)
4535 mytimestamp = time.mktime(time.strptime(content[0],
4536 "%a, %d %b %Y %H:%M:%S +0000"))
4537 except (OverflowError, ValueError):
4542 rsync_initial_timeout = \
4543 int(settings.get("PORTAGE_RSYNC_INITIAL_TIMEOUT", "15"))
4545 rsync_initial_timeout = 15
4548 if settings.has_key("RSYNC_RETRIES"):
4549 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
4550 maxretries=int(settings["RSYNC_RETRIES"])
4552 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
4553 except SystemExit, e:
4554 raise # Needed else can't exit
4556 maxretries=3 #default number of retries
4559 user_name, hostname, port = re.split(
4560 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
4563 if user_name is None:
4565 updatecache_flg=True
4566 all_rsync_opts = set(rsync_opts)
4567 lexer = shlex.shlex(StringIO.StringIO(
4568 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")), posix=True)
4569 lexer.whitespace_split = True
4570 extra_rsync_opts = list(lexer)
4572 all_rsync_opts.update(extra_rsync_opts)
4573 family = socket.AF_INET
4574 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
4575 family = socket.AF_INET
4576 elif socket.has_ipv6 and \
4577 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
4578 family = socket.AF_INET6
4585 for addrinfo in socket.getaddrinfo(
4586 hostname, None, family, socket.SOCK_STREAM):
4587 if addrinfo[0] == socket.AF_INET6:
4588 # IPv6 addresses need to be enclosed in square brackets
4589 ips.append("[%s]" % addrinfo[4][0])
4591 ips.append(addrinfo[4][0])
4592 from random import shuffle
4594 except SystemExit, e:
4595 raise # Needed else can't exit
4596 except Exception, e:
4597 print "Notice:",str(e)
4602 dosyncuri = syncuri.replace(
4603 "//" + user_name + hostname + port + "/",
4604 "//" + user_name + ips[0] + port + "/", 1)
4605 except SystemExit, e:
4606 raise # Needed else can't exit
4607 except Exception, e:
4608 print "Notice:",str(e)
4612 if "--ask" in myopts:
4613 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
4618 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
4619 if "--quiet" not in myopts:
4620 print ">>> Starting rsync with "+dosyncuri+"..."
4622 emergelog(xterm_titles,
4623 ">>> Starting retry %d of %d with %s" % \
4624 (retries,maxretries,dosyncuri))
4625 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
4627 if mytimestamp != 0 and "--quiet" not in myopts:
4628 print ">>> Checking server timestamp ..."
4630 rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
4632 if "--debug" in myopts:
4637 # Even if there's no timestamp available locally, fetch the
4638 # timestamp anyway as an initial probe to verify that the server is
4639 # responsive. This protects us from hanging indefinitely on a
4640 # connection attempt to an unresponsive server which rsync's
4641 # --timeout option does not prevent.
4643 mycommand = rsynccommand[:]
4644 mycommand.append(dosyncuri.rstrip("/") + \
4645 "/metadata/timestamp.chk")
4646 mycommand.append(tmpservertimestampfile)
4650 def timeout_handler(signum, frame):
4651 raise portage.exception.PortageException("timed out")
4652 signal.signal(signal.SIGALRM, timeout_handler)
4653 # Timeout here in case the server is unresponsive. The
4654 # --timeout rsync option doesn't apply to the initial
4655 # connection attempt.
4656 if rsync_initial_timeout:
4657 signal.alarm(rsync_initial_timeout)
4659 mypids.extend(portage.process.spawn(
4660 mycommand, env=settings.environ(), returnpid=True))
4661 exitcode = os.waitpid(mypids[0], 0)[1]
4662 content = portage.grabfile(tmpservertimestampfile)
4664 if rsync_initial_timeout:
4667 os.unlink(tmpservertimestampfile)
4670 except portage.exception.PortageException, e:
4674 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
4675 os.kill(mypids[0], signal.SIGTERM)
4676 os.waitpid(mypids[0], 0)
4677 # This is the same code rsync uses for timeout.
4680 if exitcode != os.EX_OK:
4682 exitcode = (exitcode & 0xff) << 8
4684 exitcode = exitcode >> 8
4686 portage.process.spawned_pids.remove(mypids[0])
4689 servertimestamp = time.mktime(time.strptime(
4690 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
4691 except (OverflowError, ValueError):
4693 del mycommand, mypids, content
4694 if exitcode == os.EX_OK:
4695 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4696 emergelog(xterm_titles,
4697 ">>> Cancelling sync -- Already current.")
4700 print ">>> Timestamps on the server and in the local repository are the same."
4701 print ">>> Cancelling all further sync action. You are already up to date."
4703 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4707 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4708 emergelog(xterm_titles,
4709 ">>> Server out of date: %s" % dosyncuri)
4712 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4714 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4717 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4719 mycommand = rsynccommand + [dosyncuri+"/", myportdir]
4720 exitcode = portage.process.spawn(mycommand,
4721 env=settings.environ())
4722 if exitcode in [0,1,3,4,11,14,20,21]:
4724 elif exitcode in [1,3,4,11,14,20,21]:
4727 # Code 2 indicates protocol incompatibility, which is expected
4728 # for servers with protocol < 29 that don't support
4729 # --prune-empty-directories. Retry for a server that supports
4730 # at least rsync protocol version 29 (>=rsync-2.6.4).
4735 if retries<=maxretries:
4736 print ">>> Retrying..."
4741 updatecache_flg=False
4745 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4749 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4750 print darkred("!!!")+green(" that your SYNC statement is proper.")
4751 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4753 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4754 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4755 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4756 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4757 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4759 print darkred("!!!")+green(" Rsync was killed before it finished.")
4761 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4762 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4763 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4764 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4765 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4768 elif syncuri[:6]=="cvs://":
4769 if not os.path.exists("/usr/bin/cvs"):
4770 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4771 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4774 cvsdir=os.path.dirname(myportdir)
4775 if not os.path.exists(myportdir+"/CVS"):
4777 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4778 if os.path.exists(cvsdir+"/gentoo-x86"):
4779 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4784 if e.errno != errno.ENOENT:
4786 "!!! existing '%s' directory; exiting.\n" % myportdir)
4789 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4790 print "!!! cvs checkout error; exiting."
4792 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4795 print ">>> Starting cvs update with "+syncuri+"..."
4796 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4797 myportdir, settings, free=1)
4798 if retval != os.EX_OK:
4802 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4805 if updatecache_flg and \
4806 myaction != "metadata" and \
4807 "metadata-transfer" not in settings.features:
4808 updatecache_flg = False
4810 # Reload the whole config from scratch.
4811 settings, trees, mtimedb = load_emerge_config(trees=trees)
4812 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4814 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4815 action_metadata(settings, portdb, myopts)
4817 if portage._global_updates(trees, mtimedb["updates"]):
4819 # Reload the whole config from scratch.
4820 settings, trees, mtimedb = load_emerge_config(trees=trees)
4821 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4823 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4824 mypvs = portage.best(
4825 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4827 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4829 if myaction != "metadata":
4830 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4831 retval = portage.process.spawn(
4832 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4833 dosyncuri], env=settings.environ())
4834 if retval != os.EX_OK:
4835 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4837 if(mybestpv != mypvs) and not "--quiet" in myopts:
4839 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4840 print red(" * ")+"that you update portage now, before any other packages are updated."
4842 print red(" * ")+"To update portage, run 'emerge portage' now."
4845 display_news_notification(trees)
4847 def action_metadata(settings, portdb, myopts):
4848 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4849 old_umask = os.umask(0002)
4850 cachedir = os.path.normpath(settings.depcachedir)
4851 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4852 "/lib", "/opt", "/proc", "/root", "/sbin",
4853 "/sys", "/tmp", "/usr", "/var"]:
4854 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4855 "ROOT DIRECTORY ON YOUR SYSTEM."
4856 print >> sys.stderr, \
4857 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4859 if not os.path.exists(cachedir):
4862 ec = portage.eclass_cache.cache(portdb.porttree_root)
4863 myportdir = os.path.realpath(settings["PORTDIR"])
4864 cm = settings.load_best_module("portdbapi.metadbmodule")(
4865 myportdir, "metadata/cache", portage.auxdbkeys[:])
4867 from portage.cache import util
4869 class percentage_noise_maker(util.quiet_mirroring):
4870 def __init__(self, dbapi):
4872 self.cp_all = dbapi.cp_all()
4873 l = len(self.cp_all)
4874 self.call_update_min = 100000000
4875 self.min_cp_all = l/100.0
4880 for x in self.cp_all:
4882 if self.count > self.min_cp_all:
4883 self.call_update_min = 0
4885 for y in self.dbapi.cp_list(x):
4887 self.call_update_mine = 0
4889 def update(self, *arg):
4890 try: self.pstr = int(self.pstr) + 1
4891 except ValueError: self.pstr = 1
4892 sys.stdout.write("%s%i%%" % \
4893 ("\b" * (len(str(self.pstr))+1), self.pstr))
4895 self.call_update_min = 10000000
4897 def finish(self, *arg):
4898 sys.stdout.write("\b\b\b\b100%\n")
4901 if "--quiet" in myopts:
4902 def quicky_cpv_generator(cp_all_list):
4903 for x in cp_all_list:
4904 for y in portdb.cp_list(x):
4906 source = quicky_cpv_generator(portdb.cp_all())
4907 noise_maker = portage.cache.util.quiet_mirroring()
4909 noise_maker = source = percentage_noise_maker(portdb)
4910 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4911 eclass_cache=ec, verbose_instance=noise_maker)
4916 def action_regen(settings, portdb):
4917 xterm_titles = "notitles" not in settings.features
4918 emergelog(xterm_titles, " === regen")
4919 #regenerate cache entries
4920 print "Regenerating cache entries... "
4922 os.close(sys.stdin.fileno())
4923 except SystemExit, e:
4924 raise # Needed else can't exit
4928 mynodes = portdb.cp_all()
4929 from portage.cache.cache_errors import CacheError
4931 for mytree in portdb.porttrees:
4933 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4934 except CacheError, e:
4935 print "\n error listing cache entries for " + \
4936 "'%s': %s, continuing..." % (mytree, e)
4941 mymatches = portdb.cp_list(x)
4942 portage.writemsg_stdout("processing %s\n" % x)
4945 foo = portdb.aux_get(y,["DEPEND"])
4946 except SystemExit, e:
4947 # sys.exit is an exception... And consequently, we can't catch it.
4949 except Exception, e:
4950 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4952 for mytree in portdb.porttrees:
4953 if portdb.findname2(y, mytree=mytree)[0]:
4954 dead_nodes[mytree].discard(y)
4956 for mytree, nodes in dead_nodes.iteritems():
4957 auxdb = portdb.auxdb[mytree]
4961 except (KeyError, CacheError):
4965 def action_config(settings, trees, myopts, myfiles):
4966 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4967 print red("!!! config can only take a single package atom at this time\n")
4969 if not is_valid_package_atom(myfiles[0]):
4970 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4972 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4973 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4977 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4978 except ValueError, e:
4979 # Multiple matches thrown from cpv_expand
4982 print "No packages found.\n"
4985 if "--ask" in myopts:
4987 print "Please select a package to configure:"
4991 options.append(str(idx))
4992 print options[-1]+") "+pkg
4995 idx = userquery("Selection?", options)
4998 pkg = pkgs[int(idx)-1]
5000 print "The following packages available:"
5003 print "\nPlease use a specific atom or the --ask option."
5009 if "--ask" in myopts:
5010 if userquery("Ready to configure "+pkg+"?") == "No":
5013 print "Configuring pkg..."
5015 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
5016 mysettings = portage.config(clone=settings)
5017 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
5018 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
5019 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
5022 def action_info(settings, trees, myopts, myfiles):
5023 unameout=commands.getstatusoutput("uname -mrp")[1]
5024 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5025 settings.profile_path, settings["CHOST"],
5026 trees[settings["ROOT"]]["vartree"].dbapi)
5028 header_title = "System Settings"
5030 print header_width * "="
5031 print header_title.rjust(int(header_width/2 + len(header_title)/2))
5032 print header_width * "="
5033 print "System uname: "+unameout
5034 gentoo_release = portage.grabfile(os.path.join(
5035 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
5037 print gentoo_release[0]
5039 print "Unknown Host Operating System"
5040 lastSync = portage.grabfile(os.path.join(
5041 settings["PORTDIR"], "metadata", "timestamp.chk"))
5042 print "Timestamp of tree:",
5048 output=commands.getstatusoutput("distcc --version")
5050 print str(output[1].split("\n",1)[0]),
5051 if "distcc" in settings.features:
5056 output=commands.getstatusoutput("ccache -V")
5058 print str(output[1].split("\n",1)[0]),
5059 if "ccache" in settings.features:
5064 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
5065 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
5066 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
5067 myvars = portage.util.unique_array(myvars)
5071 if portage.isvalidatom(x):
5072 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
5073 pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
5074 pkg_matches.sort(portage.pkgcmp)
5076 for pn, ver, rev in pkg_matches:
5078 pkgs.append(ver + "-" + rev)
5082 pkgs = ", ".join(pkgs)
5083 print "%-20s %s" % (x+":", pkgs)
5085 print "%-20s %s" % (x+":", "[NOT VALID]")
5087 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
5089 if "--verbose" in myopts:
5090 myvars=settings.keys()
5092 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
5093 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
5094 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
5095 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
5097 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
5099 myvars = portage.util.unique_array(myvars)
5105 print '%s="%s"' % (x, settings[x])
5107 use = set(settings["USE"].split())
5108 use_expand = settings["USE_EXPAND"].split()
5110 for varname in use_expand:
5111 flag_prefix = varname.lower() + "_"
5113 if f.startswith(flag_prefix):
5117 print 'USE="%s"' % " ".join(use),
5118 for varname in use_expand:
5119 myval = settings.get(varname)
5121 print '%s="%s"' % (varname, myval),
5124 unset_vars.append(x)
5126 print "Unset: "+", ".join(unset_vars)
5129 if "--debug" in myopts:
5130 for x in dir(portage):
5131 module = getattr(portage, x)
5132 if "cvs_id_string" in dir(module):
5133 print "%s: %s" % (str(x), str(module.cvs_id_string))
5135 # See if we can find any packages installed matching the strings
5136 # passed on the command line
5138 vardb = trees[settings["ROOT"]]["vartree"].dbapi
5139 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5141 mypkgs.extend(vardb.match(x))
5143 # If some packages were found...
5145 # Get our global settings (we only print stuff if it varies from
5146 # the current config)
5147 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
5148 auxkeys = mydesiredvars + [ "USE", "IUSE"]
5150 pkgsettings = portage.config(clone=settings)
5152 for myvar in mydesiredvars:
5153 global_vals[myvar] = set(settings.get(myvar, "").split())
5155 # Loop through each package
5156 # Only print settings if they differ from global settings
5157 header_printed = False
5159 # Get all package specific variables
5160 auxvalues = vardb.aux_get(pkg, auxkeys)
5162 for i in xrange(len(auxkeys)):
5163 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
5165 for myvar in mydesiredvars:
5166 # If the package variable doesn't match the
5167 # current global variable, something has changed
5168 # so set diff_found so we know to print
5169 if valuesmap[myvar] != global_vals[myvar]:
5170 diff_values[myvar] = valuesmap[myvar]
5171 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
5172 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
5174 # If a matching ebuild is no longer available in the tree, maybe it
5175 # would make sense to compare against the flags for the best
5176 # available version with the same slot?
5178 if portdb.cpv_exists(pkg):
5180 pkgsettings.setcpv(pkg, mydb=mydb)
5181 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
5183 diff_values["USE"] = valuesmap["USE"]
5184 # If a difference was found, print the info for
5188 # If we have not yet printed the header,
5190 if not header_printed:
5191 header_title = "Package Settings"
5192 print header_width * "="
5193 print header_title.rjust(int(header_width/2 + len(header_title)/2))
5194 print header_width * "="
5195 header_printed = True
5197 # Print package info
5198 print "%s was built with the following:" % pkg
5199 for myvar in mydesiredvars + ["USE"]:
5200 if myvar in diff_values:
5201 mylist = list(diff_values[myvar])
5203 print "%s=\"%s\"" % (myvar, " ".join(mylist))
5206 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
5208 print "emerge: no search terms provided."
5210 searchinstance = search(settings, portdb,
5211 vartree, spinner, "--searchdesc" in myopts,
5212 "--quiet" not in myopts)
5213 for mysearch in myfiles:
5215 searchinstance.execute(mysearch)
5216 except re.error, comment:
5217 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
5219 searchinstance.output()
5221 def action_depclean(settings, trees, ldpath_mtimes,
5223 # Kill packages that aren't explicitly merged or are required as a
5224 # dependency of another package. World file is explicit.
5226 warn_prefix = colorize("BAD", "*** WARNING *** ")
5228 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
5229 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
5230 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
5232 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
5233 print warn_prefix + "mistakes. Packages that are part of the world set will always"
5234 print warn_prefix + "be kept. They can be manually added to this set with"
5235 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
5236 print warn_prefix + "package.provided (see portage(5)) will be removed by"
5237 print warn_prefix + "depclean, even if they are part of the world set."
5239 print warn_prefix + "As a safety measure, depclean will not remove any packages"
5240 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
5241 print warn_prefix + "consequence, it is often necessary to run "
5242 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
5244 xterm_titles = "notitles" not in settings.features
5245 myroot = settings["ROOT"]
5246 dep_check_trees = {}
5247 dep_check_trees[myroot] = {}
5248 dep_check_trees[myroot]["vartree"] = \
5249 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
5250 vardb = dep_check_trees[myroot]["vartree"].dbapi
5251 # Constrain dependency selection to the installed packages.
5252 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
5253 system_set = SystemSet(settings)
5254 syslist = list(system_set)
5255 world_set = WorldSet(settings)
5257 worldlist = list(world_set)
5258 fakedb = portage.fakedbapi(settings=settings)
5259 myvarlist = vardb.cpv_all()
5262 print "\n!!! You have no system list.",
5264 print "\n!!! You have no world file.",
5266 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
5268 if not (syslist and worldlist and myvarlist):
5269 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
5270 print " break your installation.\n"
5271 if "--pretend" not in myopts:
5272 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
5274 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
5275 emergelog(xterm_titles, " >>> depclean")
5277 if "--quiet" not in myopts:
5278 print "\nCalculating dependencies ",
5282 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
5283 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
5285 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
5286 metadata_keys = ["PROVIDE", "SLOT", "USE"]
5288 while remaining_atoms:
5289 atom, parent, priority = remaining_atoms.pop()
5290 pkgs = vardb.match(atom)
5292 if not atom.startswith("!") and priority == hard:
5293 unresolveable.setdefault(atom, []).append(parent)
5295 if len(pkgs) > 1 and parent != "world":
5296 # Prune all but the best matching slot, since that's all that a
5297 # deep world update would pull in. Don't prune if this atom comes
5298 # directly from world though, since world atoms are greedy when
5299 # they don't specify a slot.
5300 pkgs = [portage.best(pkgs)]
5302 if fakedb.cpv_exists(pkg):
5305 fakedb.cpv_inject(pkg)
5306 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
5308 if myopts.get("--with-bdeps", "y") == "y":
5309 mydeps.append((myaux["DEPEND"], soft))
5311 mydeps.append((" ".join(myaux.values()), hard))
5312 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
5313 for depstr, priority in mydeps:
5318 if "--debug" in myopts:
5320 print "Parent: ", pkg
5321 print "Depstring:", depstr
5323 if priority == soft:
5329 portage.dep._dep_check_strict = False
5330 success, atoms = portage.dep_check(depstr, None, settings,
5331 myuse=usedef, trees=dep_check_trees, myroot=myroot)
5333 portage.dep._dep_check_strict = True
5335 show_invalid_depstring_notice(
5336 ("installed", myroot, pkg, "nomerge"),
5340 if "--debug" in myopts:
5341 print "Candidates:", atoms
5344 remaining_atoms.append((atom, pkg, priority))
5346 if "--quiet" not in myopts:
5347 print "\b\b... done!\n"
5350 print "Dependencies could not be completely resolved due to"
5351 print "the following required packages not being installed:"
5353 for atom in unresolveable:
5354 print atom, "required by", " ".join(unresolveable[atom])
5356 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
5357 print "depclean? It may be necessary to manually uninstall packages that no longer"
5358 print "exist in the portage tree since it may not be possible to satisfy their"
5359 print "dependencies. Also, be aware of the --with-bdeps option that is documented"
5360 print "in " + good("`man emerge`") + "."
5364 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
5367 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
5368 "unmerge", cleanlist, ldpath_mtimes)
5370 print "Packages installed: "+str(len(myvarlist))
5371 print "Packages in world: "+str(len(worldlist))
5372 print "Packages in system: "+str(len(syslist))
5373 print "Unique package names: "+str(len(myvarlist))
5374 print "Required packages: "+str(len(fakedb.cpv_all()))
5375 if "--pretend" in myopts:
5376 print "Number to remove: "+str(len(cleanlist))
5378 print "Number removed: "+str(len(cleanlist))
5380 def action_build(settings, trees, mtimedb,
5381 myopts, myaction, myfiles, spinner):
5382 ldpath_mtimes = mtimedb["ldpath"]
5385 pretend = "--pretend" in myopts
5386 fetchonly = "--fetchonly" in myopts or "--fetch-all-uri" in myopts
5387 if pretend or fetchonly:
5388 # make the mtimedb readonly
5389 mtimedb.filename = None
5390 if "--quiet" not in myopts and \
5391 ("--pretend" in myopts or "--ask" in myopts or \
5392 "--tree" in myopts or "--verbose" in myopts):
5394 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5398 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
5400 print darkgreen("These are the packages that would be %s, in reverse order:") % action
5404 print darkgreen("These are the packages that would be %s, in order:") % action
5407 # validate the state of the resume data
5408 # so that we can make assumptions later.
5409 for k in ("resume", "resume_backup"):
5411 if "mergelist" in mtimedb[k]:
5412 if not mtimedb[k]["mergelist"]:
5417 if "--resume" in myopts and \
5418 ("resume" in mtimedb or
5419 "resume_backup" in mtimedb):
5420 if "resume" not in mtimedb:
5421 mtimedb["resume"] = mtimedb["resume_backup"]
5422 del mtimedb["resume_backup"]
5424 # XXX: "myopts" is a list for backward compatibility.
5425 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
5427 for opt in ("--skipfirst", "--ask", "--tree"):
5428 myresumeopts.pop(opt, None)
5430 for myopt, myarg in myopts.iteritems():
5431 if myopt not in myresumeopts:
5432 myresumeopts[myopt] = myarg
5435 # Adjust config according to options of the command being resumed.
5436 for myroot in trees:
5437 mysettings = trees[myroot]["vartree"].settings
5439 adjust_config(myopts, mysettings)
5441 del myroot, mysettings
5443 myparams = create_depgraph_params(myopts, myaction)
5444 if "--quiet" not in myopts and "--nodeps" not in myopts:
5445 print "Calculating dependencies ",
5446 mydepgraph = depgraph(settings, trees,
5447 myopts, myparams, spinner)
5448 if "--quiet" not in myopts and "--nodeps" not in myopts:
5449 print "\b\b... done!"
5451 if ("--resume" in myopts):
5452 print darkgreen("emerge: It seems we have nothing to resume...")
5455 myparams = create_depgraph_params(myopts, myaction)
5456 if myaction in ["system","world"]:
5457 if "--quiet" not in myopts and "--nodeps" not in myopts:
5458 print "Calculating",myaction,"dependencies ",
5460 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
5461 if not mydepgraph.xcreate(myaction):
5462 print "!!! Depgraph creation failed."
5464 if "--quiet" not in myopts and "--nodeps" not in myopts:
5465 print "\b\b... done!"
5467 if "--quiet" not in myopts and "--nodeps" not in myopts:
5468 print "Calculating dependencies ",
5470 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
5472 retval, favorites = mydepgraph.select_files(myfiles)
5473 except portage.exception.PackageNotFound, e:
5474 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
5478 if "--quiet" not in myopts and "--nodeps" not in myopts:
5479 print "\b\b... done!"
5481 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
5482 sys.stderr.write(red("The following binaries are not available for merging...\n"))
5484 if mydepgraph.missingbins:
5485 for x in mydepgraph.missingbins:
5486 sys.stderr.write(" "+str(x)+"\n")
5487 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
5490 if "--pretend" not in myopts and \
5491 ("--ask" in myopts or "--tree" in myopts or \
5492 "--verbose" in myopts) and \
5493 not ("--quiet" in myopts and "--ask" not in myopts):
5494 if "--resume" in myopts:
5495 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5496 mymergelist = mtimedb["resume"]["mergelist"]
5497 if "--skipfirst" in myopts:
5498 mymergelist = mymergelist[1:]
5499 if len(mymergelist) == 0:
5500 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5502 favorites = mtimedb["resume"]["favorites"]
5503 retval = mydepgraph.display(mymergelist, favorites=favorites)
5504 if retval != os.EX_OK:
5506 prompt="Would you like to resume merging these packages?"
5508 retval = mydepgraph.display(
5509 mydepgraph.altlist(reversed=("--tree" in myopts)),
5510 favorites=favorites)
5511 if retval != os.EX_OK:
5514 for x in mydepgraph.altlist():
5515 if x[0] != "blocks" and x[3] != "nomerge":
5517 #check for blocking dependencies
5518 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
5519 print "\n!!! Error: The above package list contains packages which cannot be installed"
5520 print "!!! at the same time on the same system."
5521 if "--quiet" not in myopts:
5522 show_blocker_docs_link()
5525 if "--noreplace" in myopts and favorites:
5528 print " %s %s" % (good("*"), x)
5529 prompt="Would you like to add these packages to your world favorites?"
5530 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5531 prompt="Nothing to merge; would you like to auto-clean packages?"
5534 print "Nothing to merge; quitting."
5537 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5538 prompt="Would you like to fetch the source files for these packages?"
5540 prompt="Would you like to merge these packages?"
5542 if "--ask" in myopts and userquery(prompt) == "No":
5547 # Don't ask again (e.g. when auto-cleaning packages after merge)
5548 myopts.pop("--ask", None)
5550 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5551 if ("--resume" in myopts):
5552 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5553 mymergelist = mtimedb["resume"]["mergelist"]
5554 if "--skipfirst" in myopts:
5555 mymergelist = mymergelist[1:]
5556 if len(mymergelist) == 0:
5557 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5559 favorites = mtimedb["resume"]["favorites"]
5560 retval = mydepgraph.display(mymergelist, favorites=favorites)
5561 if retval != os.EX_OK:
5564 retval = mydepgraph.display(
5565 mydepgraph.altlist(reversed=("--tree" in myopts)),
5566 favorites=favorites)
5567 if retval != os.EX_OK:
5569 if "--buildpkgonly" in myopts and \
5570 not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5571 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5572 print "!!! You have to merge the dependencies before you can build this package.\n"
5575 if ("--buildpkgonly" in myopts):
5576 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5577 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5578 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
5581 if ("--resume" in myopts):
5582 favorites=mtimedb["resume"]["favorites"]
5583 mergetask = MergeTask(settings, trees, myopts)
5584 if "--fetchonly" in myopts:
5585 """ parallel-fetch uses --resume --fetchonly and we don't want
5586 it to write the mtimedb"""
5587 mtimedb.filename = None
5588 time.sleep(3) # allow the parent to have first fetch
5590 retval = mergetask.merge(
5591 mtimedb["resume"]["mergelist"], favorites, mtimedb)
5592 merge_count = mergetask.curval
5594 if "resume" in mtimedb and \
5595 "mergelist" in mtimedb["resume"] and \
5596 len(mtimedb["resume"]["mergelist"]) > 1:
5597 mtimedb["resume_backup"] = mtimedb["resume"]
5598 del mtimedb["resume"]
5600 mtimedb["resume"]={}
5601 # XXX: Stored as a list for backward compatibility.
5602 mtimedb["resume"]["myopts"] = \
5603 [k for k in myopts if myopts[k] is True]
5604 mtimedb["resume"]["favorites"]=favorites
5605 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5606 for pkgline in mydepgraph.altlist():
5607 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5608 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
5609 tmpsettings = portage.config(clone=settings)
5611 if settings.get("PORTAGE_DEBUG", "") == "1":
5613 retval = portage.doebuild(
5614 y, "digest", settings["ROOT"], tmpsettings, edebug,
5615 ("--pretend" in myopts),
5616 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
5618 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5620 for pkg in mydepgraph.altlist():
5621 if pkg[0] != "blocks":
5624 pkglist = mydepgraph.altlist()
5626 mydepgraph.saveNomergeFavorites()
5628 mergetask = MergeTask(settings, trees, myopts)
5629 retval = mergetask.merge(pkglist, favorites, mtimedb)
5630 merge_count = mergetask.curval
5632 if retval == os.EX_OK and not (pretend or fetchonly):
5633 mtimedb.pop("resume", None)
5634 if "yes" == settings.get("AUTOCLEAN"):
5635 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5636 vartree = trees[settings["ROOT"]]["vartree"]
5637 unmerge(settings, myopts, vartree, "clean", ["world"],
5638 ldpath_mtimes, autoclean=1)
5640 portage.writemsg_stdout(colorize("WARN", "WARNING:")
5641 + " AUTOCLEAN is disabled. This can cause serious"
5642 + " problems due to overlapping packages.\n")
5644 if merge_count and not (pretend or fetchonly):
5645 post_emerge(trees, mtimedb, retval)
5648 def multiple_actions(action1, action2):
5649 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
5650 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
5653 def parse_opts(tmpcmdline, silent=False):
5658 global actions, options, shortmapping
5660 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
5661 argument_options = {
5663 "help":"specify the location for portage configuration files",
5667 "help":"enable or disable color output",
5669 "choices":("y", "n")
5672 "help":"include unnecessary build time dependencies",
5674 "choices":("y", "n")
5677 "help":"specify conditions to trigger package reinstallation",
5679 "choices":["changed-use"]
5683 from optparse import OptionParser
5684 parser = OptionParser()
5685 if parser.has_option("--help"):
5686 parser.remove_option("--help")
5688 for action_opt in actions:
5689 parser.add_option("--" + action_opt, action="store_true",
5690 dest=action_opt.replace("-", "_"), default=False)
5691 for myopt in options:
5692 parser.add_option(myopt, action="store_true",
5693 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5694 for shortopt, longopt in shortmapping.iteritems():
5695 parser.add_option("-" + shortopt, action="store_true",
5696 dest=longopt.lstrip("--").replace("-", "_"), default=False)
5697 for myalias, myopt in longopt_aliases.iteritems():
5698 parser.add_option(myalias, action="store_true",
5699 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5701 for myopt, kwargs in argument_options.iteritems():
5702 parser.add_option(myopt,
5703 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
5705 myoptions, myargs = parser.parse_args(args=tmpcmdline)
5707 for myopt in options:
5708 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
5710 myopts[myopt] = True
5712 for myopt in argument_options:
5713 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
5717 for action_opt in actions:
5718 v = getattr(myoptions, action_opt.replace("-", "_"))
5721 multiple_actions(myaction, action_opt)
5723 myaction = action_opt
5726 if x in actions and myaction != "search":
5727 if not silent and x not in ["system", "world"]:
5728 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
5729 # special case "search" so people can search for action terms, e.g. emerge -s sync
5731 multiple_actions(myaction, x)
5737 if "--nocolor" in myopts:
5739 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
5740 "use '--color=n' instead.\n")
5741 del myopts["--nocolor"]
5742 myopts["--color"] = "n"
5744 return myaction, myopts, myfiles
5746 def validate_ebuild_environment(trees):
5747 for myroot in trees:
5748 mysettings = trees[myroot]["vartree"].settings
5749 for var in "ARCH", "USERLAND":
5750 if mysettings.get(var):
5752 print >> sys.stderr, bad(("\a!!! %s is not set... " % var) + \
5753 "Are you missing the '%setc/make.profile' symlink?" % \
5754 mysettings["PORTAGE_CONFIGROOT"])
5755 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5756 "Is your portage tree complete?\n")
5758 del myroot, mysettings
5760 def load_emerge_config(trees=None):
5762 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5763 kwargs[k] = os.environ.get(envvar, None)
5764 trees = portage.create_trees(trees=trees, **kwargs)
5766 settings = trees["/"]["vartree"].settings
5768 for myroot in trees:
5770 settings = trees[myroot]["vartree"].settings
5773 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5774 mtimedb = portage.MtimeDB(mtimedbfile)
5775 return settings, trees, mtimedb
5777 def adjust_config(myopts, settings):
5778 """Make emerge specific adjustments to the config."""
5780 # To enhance usability, make some vars case insensitive by forcing them to
5782 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5783 if myvar in settings:
5784 settings[myvar] = settings[myvar].lower()
5785 settings.backup_changes(myvar)
5788 # Kill noauto as it will break merges otherwise.
5789 if "noauto" in settings.features:
5790 while "noauto" in settings.features:
5791 settings.features.remove("noauto")
5792 settings["FEATURES"] = " ".join(settings.features)
5793 settings.backup_changes("FEATURES")
5797 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5798 except ValueError, e:
5799 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5800 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5801 settings["CLEAN_DELAY"], noiselevel=-1)
5802 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5803 settings.backup_changes("CLEAN_DELAY")
5805 EMERGE_WARNING_DELAY = 10
5807 EMERGE_WARNING_DELAY = int(settings.get(
5808 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5809 except ValueError, e:
5810 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5811 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5812 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5813 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5814 settings.backup_changes("EMERGE_WARNING_DELAY")
5816 if "--quiet" in myopts:
5817 settings["PORTAGE_QUIET"]="1"
5818 settings.backup_changes("PORTAGE_QUIET")
5820 # Set so that configs will be merged regardless of remembered status
5821 if ("--noconfmem" in myopts):
5822 settings["NOCONFMEM"]="1"
5823 settings.backup_changes("NOCONFMEM")
5825 # Set various debug markers... They should be merged somehow.
5828 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5829 if PORTAGE_DEBUG not in (0, 1):
5830 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5831 PORTAGE_DEBUG, noiselevel=-1)
5832 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5835 except ValueError, e:
5836 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5837 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5838 settings["PORTAGE_DEBUG"], noiselevel=-1)
5840 if "--debug" in myopts:
5842 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5843 settings.backup_changes("PORTAGE_DEBUG")
5845 if settings.get("NOCOLOR") not in ("yes","true"):
5846 portage.output.havecolor = 1
5848 """The explicit --color < y | n > option overrides the NOCOLOR environment
5849 variable and stdout auto-detection."""
5850 if "--color" in myopts:
5851 if "y" == myopts["--color"]:
5852 portage.output.havecolor = 1
5853 settings["NOCOLOR"] = "false"
5855 portage.output.havecolor = 0
5856 settings["NOCOLOR"] = "true"
5857 settings.backup_changes("NOCOLOR")
5858 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5859 portage.output.havecolor = 0
5860 settings["NOCOLOR"] = "true"
5861 settings.backup_changes("NOCOLOR")
5864 global portage # NFC why this is necessary now - genone
5865 # Disable color until we're sure that it should be enabled (after
5866 # EMERGE_DEFAULT_OPTS has been parsed).
5867 portage.output.havecolor = 0
5868 # This first pass is just for options that need to be known as early as
5869 # possible, such as --config-root. They will be parsed again later,
5870 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5871 # the value of --config-root).
5872 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5873 if "--debug" in myopts:
5874 os.environ["PORTAGE_DEBUG"] = "1"
5875 if "--config-root" in myopts:
5876 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5878 # Portage needs to ensure a sane umask for the files it creates.
5880 settings, trees, mtimedb = load_emerge_config()
5881 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5884 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5885 except (OSError, ValueError), e:
5886 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5887 settings["PORTAGE_NICENESS"])
5888 portage.writemsg("!!! %s\n" % str(e))
5891 if portage._global_updates(trees, mtimedb["updates"]):
5893 # Reload the whole config from scratch.
5894 settings, trees, mtimedb = load_emerge_config(trees=trees)
5895 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5897 xterm_titles = "notitles" not in settings.features
5900 if "--ignore-default-opts" not in myopts:
5901 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5902 tmpcmdline.extend(sys.argv[1:])
5903 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5905 if "--digest" in myopts:
5906 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5907 # Reload the whole config from scratch so that the portdbapi internal
5908 # config is updated with new FEATURES.
5909 settings, trees, mtimedb = load_emerge_config(trees=trees)
5910 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5912 for myroot in trees:
5913 mysettings = trees[myroot]["vartree"].settings
5915 adjust_config(myopts, mysettings)
5917 del myroot, mysettings
5919 spinner = stdout_spinner()
5920 if "candy" in settings.features:
5921 spinner.update = spinner.update_scroll
5923 if "--quiet" not in myopts:
5924 portage.deprecated_profile_check()
5926 #Freeze the portdbapi for enhanced performance:
5927 for myroot in trees:
5928 trees[myroot]["porttree"].dbapi.freeze()
5931 if "moo" in myfiles:
5934 Larry loves Gentoo (""" + os.uname()[0] + """)
5936 _______________________
5937 < Have you mooed today? >
5938 -----------------------
5947 if (myaction in ["world", "system"]) and myfiles:
5948 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5952 ext = os.path.splitext(x)[1]
5953 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5954 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5957 if ("--tree" in myopts) and ("--columns" in myopts):
5958 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5961 if ("--quiet" in myopts):
5962 spinner.update = spinner.update_quiet
5963 portage.util.noiselimit = -1
5965 # Always create packages if FEATURES=buildpkg
5966 # Imply --buildpkg if --buildpkgonly
5967 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5968 if "--buildpkg" not in myopts:
5969 myopts["--buildpkg"] = True
5971 # Also allow -S to invoke search action (-sS)
5972 if ("--searchdesc" in myopts):
5973 if myaction and myaction != "search":
5974 myfiles.append(myaction)
5975 if "--search" not in myopts:
5976 myopts["--search"] = True
5979 # Always try and fetch binary packages if FEATURES=getbinpkg
5980 if ("getbinpkg" in settings.features):
5981 myopts["--getbinpkg"] = True
5983 if "--skipfirst" in myopts and "--resume" not in myopts:
5984 myopts["--resume"] = True
5986 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5987 myopts["--usepkgonly"] = True
5989 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5990 myopts["--getbinpkg"] = True
5992 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5993 myopts["--usepkg"] = True
5995 # Also allow -K to apply --usepkg/-k
5996 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5997 myopts["--usepkg"] = True
5999 # Allow -p to remove --ask
6000 if ("--pretend" in myopts) and ("--ask" in myopts):
6001 print ">>> --pretend disables --ask... removing --ask from options."
6004 # forbid --ask when not in a terminal
6005 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
6006 if ("--ask" in myopts) and (not sys.stdin.isatty()):
6007 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
6011 if settings.get("PORTAGE_DEBUG", "") == "1":
6012 spinner.update = spinner.update_quiet
6014 if "python-trace" in settings.features:
6015 import portage.debug
6016 portage.debug.set_trace(True)
6018 if ("--resume" in myopts):
6019 if "--tree" in myopts:
6020 print "* --tree is currently broken with --resume. Disabling..."
6021 del myopts["--tree"]
6023 if not ("--quiet" in myopts):
6024 if not sys.stdout.isatty() or ("--nospinner" in myopts):
6025 spinner.update = spinner.update_basic
6027 if "--version" in myopts:
6028 print getportageversion(settings["PORTDIR"], settings["ROOT"],
6029 settings.profile_path, settings["CHOST"],
6030 trees[settings["ROOT"]]["vartree"].dbapi)
6032 elif "--help" in myopts:
6033 emerge.help.help(myaction, myopts, portage.output.havecolor)
6036 if "--debug" in myopts:
6037 print "myaction", myaction
6038 print "myopts", myopts
6040 if not myaction and not myfiles and "--resume" not in myopts:
6041 emerge.help.help(myaction, myopts, portage.output.havecolor)
6044 # check if root user is the current user for the actions where emerge needs this
6045 if portage.secpass < 2:
6046 # We've already allowed "--version" and "--help" above.
6047 if "--pretend" not in myopts and myaction not in ("search","info"):
6048 need_superuser = not \
6049 ("--fetchonly" in myopts or \
6050 "--fetch-all-uri" in myopts or \
6051 myaction in ("metadata", "regen") or \
6052 (myaction == "sync" and os.access(settings["PORTDIR"], os.W_OK)))
6053 if portage.secpass < 1 or \
6056 access_desc = "superuser"
6058 access_desc = "portage group"
6059 # Always show portage_group_warning() when only portage group
6060 # access is required but the user is not in the portage group.
6061 from portage.data import portage_group_warning
6062 if "--ask" in myopts:
6063 myopts["--pretend"] = True
6065 print ("%s access is required... " + \
6066 "adding --pretend to options.\n") % access_desc
6067 if portage.secpass < 1 and not need_superuser:
6068 portage_group_warning()
6070 sys.stderr.write(("emerge: %s access is " + \
6071 "required.\n\n") % access_desc)
6072 if portage.secpass < 1 and not need_superuser:
6073 portage_group_warning()
6076 disable_emergelog = False
6077 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
6079 disable_emergelog = True
6081 if myaction in ("search", "info"):
6082 disable_emergelog = True
6083 if disable_emergelog:
6084 """ Disable emergelog for everything except build or unmerge
6085 operations. This helps minimize parallel emerge.log entries that can
6086 confuse log parsers. We especially want it disabled during
6087 parallel-fetch, which uses --resume --fetchonly."""
6089 def emergelog(*pargs, **kargs):
6092 if not "--pretend" in myopts:
6093 emergelog(xterm_titles, "Started emerge on: "+\
6094 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
6097 myelogstr=" ".join(myopts)
6099 myelogstr+=" "+myaction
6101 myelogstr+=" "+" ".join(myfiles)
6102 emergelog(xterm_titles, " *** emerge " + myelogstr)
6104 def emergeexitsig(signum, frame):
6105 signal.signal(signal.SIGINT, signal.SIG_IGN)
6106 signal.signal(signal.SIGTERM, signal.SIG_IGN)
6107 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
6108 sys.exit(100+signum)
6109 signal.signal(signal.SIGINT, emergeexitsig)
6110 signal.signal(signal.SIGTERM, emergeexitsig)
6113 """This gets out final log message in before we quit."""
6114 if "--pretend" not in myopts:
6115 emergelog(xterm_titles, " *** terminating.")
6116 if "notitles" not in settings.features:
6118 portage.atexit_register(emergeexit)
6120 if myaction in ("config", "metadata", "regen", "sync"):
6121 if "--pretend" in myopts:
6122 sys.stderr.write(("emerge: The '%s' action does " + \
6123 "not support '--pretend'.\n") % myaction)
6125 if "sync" == myaction:
6126 action_sync(settings, trees, mtimedb, myopts, myaction)
6127 elif "metadata" == myaction:
6128 action_metadata(settings, portdb, myopts)
6129 elif myaction=="regen":
6130 validate_ebuild_environment(trees)
6131 action_regen(settings, portdb)
6133 elif "config"==myaction:
6134 validate_ebuild_environment(trees)
6135 action_config(settings, trees, myopts, myfiles)
6138 elif "info"==myaction:
6139 action_info(settings, trees, myopts, myfiles)
6142 elif "search"==myaction:
6143 validate_ebuild_environment(trees)
6144 action_search(settings, portdb, trees["/"]["vartree"],
6145 myopts, myfiles, spinner)
6146 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
6147 validate_ebuild_environment(trees)
6148 vartree = trees[settings["ROOT"]]["vartree"]
6149 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
6151 if "--pretend" not in myopts:
6152 post_emerge(trees, mtimedb, os.EX_OK)
6154 elif "depclean"==myaction:
6155 validate_ebuild_environment(trees)
6156 action_depclean(settings, trees, mtimedb["ldpath"],
6158 if "--pretend" not in myopts:
6159 post_emerge(trees, mtimedb, os.EX_OK)
6160 # "update", "system", or just process files:
6162 validate_ebuild_environment(trees)
6163 if "--pretend" not in myopts:
6164 display_news_notification(trees)
6165 retval = action_build(settings, trees, mtimedb,
6166 myopts, myaction, myfiles, spinner)
6167 if "--pretend" in myopts:
6168 display_news_notification(trees)
6171 if __name__ == "__main__":
6172 retval = emerge_main()