2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4 # $Id: emerge 5976 2007-02-17 09:14:53Z genone $
7 # This block ensures that ^C interrupts are handled quietly.
11 def exithandler(signum,frame):
12 signal.signal(signal.SIGINT, signal.SIG_IGN)
13 signal.signal(signal.SIGTERM, signal.SIG_IGN)
16 signal.signal(signal.SIGINT, exithandler)
17 signal.signal(signal.SIGTERM, exithandler)
18 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
20 except KeyboardInterrupt:
25 os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
29 from os import path as osp
30 sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
32 del os.environ["PORTAGE_LEGACY_GLOBALS"]
33 from portage import digraph, portdbapi
34 from portage.const import NEWS_LIB_PATH, CACHE_PATH
37 import portage.xpak, commands, errno, re, socket, time, types
38 from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
39 havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
40 xtermTitleReset, yellow
41 from portage.output import create_color_func
42 good = create_color_func("GOOD")
43 bad = create_color_func("BAD")
46 portage.dep._dep_check_strict = True
49 import portage.exception
50 from portage.data import secpass
51 from portage.util import normalize_path as normpath
53 if not hasattr(__builtins__, "set"):
54 from sets import Set as set
55 from itertools import chain, izip
56 from UserDict import DictMixin
61 import pickle as cPickle
63 class stdout_spinner(object):
65 "Gentoo Rocks ("+os.uname()[0]+")",
66 "Thank you for using Gentoo. :)",
67 "Are you actually trying to read this?",
68 "How many times have you stared at this?",
69 "We are generating the cache right now",
70 "You are paying too much attention.",
71 "A theory is better than its explanation.",
72 "Phasers locked on target, Captain.",
73 "Thrashing is just virtual crashing.",
74 "To be is to program.",
75 "Real Users hate Real Programmers.",
76 "When all else fails, read the instructions.",
77 "Functionality breeds Contempt.",
78 "The future lies ahead.",
79 "3.1415926535897932384626433832795028841971694",
80 "Sometimes insanity is the only alternative.",
81 "Inaccuracy saves a world of explanation.",
84 twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
88 self.update = self.update_twirl
89 self.scroll_sequence = self.scroll_msgs[
90 int(time.time() * 100) % len(self.scroll_msgs)]
92 def update_basic(self):
93 self.spinpos = (self.spinpos + 1) % 500
94 if (self.spinpos % 100) == 0:
96 sys.stdout.write(". ")
101 def update_scroll(self):
102 if(self.spinpos >= len(self.scroll_sequence)):
103 sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
104 len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
106 sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
108 self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
110 def update_twirl(self):
111 self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
112 sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
115 def update_quiet(self):
118 def userquery(prompt, responses=None, colours=None):
119 """Displays a prompt and a set of responses, then waits for a response
120 which is checked against the responses and the first to match is
121 returned. An empty response will match the first value in responses. The
122 input buffer is *not* cleared prior to the prompt!
125 responses: a List of Strings.
126 colours: a List of Functions taking and returning a String, used to
127 process the responses for display. Typically these will be functions
128 like red() but could be e.g. lambda x: "DisplayString".
129 If responses is omitted, defaults to ["Yes", "No"], [green, red].
130 If only colours is omitted, defaults to [bold, ...].
132 Returns a member of the List responses. (If called without optional
133 arguments, returns "Yes" or "No".)
134 KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
136 if responses is None:
137 responses, colours = ["Yes", "No"], [green, red]
138 elif colours is None:
140 colours=(colours*len(responses))[:len(responses)]
144 response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
145 for key in responses:
146 # An empty response will match the first value in responses.
147 if response.upper()==key[:len(response)].upper():
149 print "Sorry, response '%s' not understood." % response,
150 except (EOFError, KeyboardInterrupt):
155 "clean", "config", "depclean",
157 "prune", "regen", "search",
158 "sync", "system", "unmerge", "world",
161 "--ask", "--alphabetical",
162 "--buildpkg", "--buildpkgonly",
163 "--changelog", "--columns",
167 "--fetchonly", "--fetch-all-uri",
168 "--getbinpkg", "--getbinpkgonly",
169 "--help", "--ignore-default-opts",
171 "--newuse", "--nocolor",
172 "--nodeps", "--noreplace",
173 "--nospinner", "--oneshot",
174 "--onlydeps", "--pretend",
175 "--quiet", "--resume",
176 "--searchdesc", "--selective",
180 "--usepkg", "--usepkgonly",
181 "--verbose", "--version"
187 "b":"--buildpkg", "B":"--buildpkgonly",
188 "c":"--clean", "C":"--unmerge",
189 "d":"--debug", "D":"--deep",
191 "f":"--fetchonly", "F":"--fetch-all-uri",
192 "g":"--getbinpkg", "G":"--getbinpkgonly",
194 "k":"--usepkg", "K":"--usepkgonly",
196 "n":"--noreplace", "N":"--newuse",
197 "o":"--onlydeps", "O":"--nodeps",
198 "p":"--pretend", "P":"--prune",
200 "s":"--search", "S":"--searchdesc",
203 "v":"--verbose", "V":"--version"
206 def emergelog(xterm_titles, mystr, short_msg=None):
208 if short_msg == None:
210 if "HOSTNAME" in os.environ.keys():
211 short_msg = os.environ["HOSTNAME"]+": "+short_msg
212 xtermTitle(short_msg)
214 file_path = "/var/log/emerge.log"
215 mylogfile = open(file_path, "a")
216 portage.util.apply_secpass_permissions(file_path,
217 uid=portage.portage_uid, gid=portage.portage_gid,
221 mylock = portage.locks.lockfile(mylogfile)
222 # seek because we may have gotten held up by the lock.
223 # if so, we may not be positioned at the end of the file.
225 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
229 portage.locks.unlockfile(mylock)
231 except (IOError,OSError,portage.exception.PortageException), e:
233 print >> sys.stderr, "emergelog():",e
235 def countdown(secs=5, doing="Starting"):
237 print ">>> Waiting",secs,"seconds before starting..."
238 print ">>> (Control-C to abort)...\n"+doing+" in: ",
242 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
247 # formats a size given in bytes nicely
248 def format_size(mysize):
249 if type(mysize) not in [types.IntType,types.LongType]:
251 if 0 != mysize % 1024:
252 # Always round up to the next kB so that it doesn't show 0 kB when
253 # some small file still needs to be fetched.
254 mysize += 1024 - mysize % 1024
255 mystr=str(mysize/1024)
259 mystr=mystr[:mycount]+","+mystr[mycount:]
263 def getgccversion(chost):
266 return: the current in-use gcc version
269 gcc_ver_command = 'gcc -dumpversion'
270 gcc_ver_prefix = 'gcc-'
272 gcc_not_found_error = red(
273 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
274 "!!! to update the environment of this terminal and possibly\n" +
275 "!!! other terminals also.\n"
278 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
279 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
280 part1, part2 = myoutput.split("/")
281 if part1.startswith(chost + "-"):
282 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
284 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
285 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
286 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
288 mystatus, myoutput = commands.getstatusoutput(
289 chost + "-" + gcc_ver_command)
290 if mystatus == os.EX_OK:
291 return gcc_ver_prefix + myoutput
293 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
294 if mystatus == os.EX_OK:
295 return gcc_ver_prefix + myoutput
297 portage.writemsg(gcc_not_found_error, noiselevel=-1)
298 return "[unavailable]"
300 def getportageversion(portdir, target_root, profile, chost, vardb):
301 profilever = "unavailable"
303 realpath = os.path.realpath(profile)
304 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
305 if realpath.startswith(basepath):
306 profilever = realpath[1 + len(basepath):]
309 profilever = "!" + os.readlink(profile)
312 del realpath, basepath
315 libclist = vardb.match("virtual/libc")
316 libclist += vardb.match("virtual/glibc")
317 libclist = portage.util.unique_array(libclist)
319 xs=portage.catpkgsplit(x)
321 libcver+=","+"-".join(xs[1:])
323 libcver="-".join(xs[1:])
325 libcver="unavailable"
327 gccver = getgccversion(chost)
328 unameout=os.uname()[2]+" "+os.uname()[4]
330 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
332 def create_depgraph_params(myopts, myaction):
333 #configure emerge engine parameters
335 # self: include _this_ package regardless of if it is merged.
336 # selective: exclude the package if it is merged
337 # recurse: go into the dependencies
338 # deep: go into the dependencies of already merged packages
339 # empty: pretend nothing is merged
340 myparams = ["recurse"]
343 if "--update" in myopts or \
344 "--newuse" in myopts or \
345 "--noreplace" in myopts or \
346 myaction in ("system", "world"):
347 add.extend(["selective"])
348 if "--emptytree" in myopts:
349 add.extend(["empty"])
350 sub.extend(["selective"])
351 if "--nodeps" in myopts:
352 sub.extend(["recurse"])
353 if "--deep" in myopts:
356 if (x not in myparams) and (x not in sub):
363 # search functionality
375 def __init__(self, settings, portdb, vartree, spinner, searchdesc,
377 """Searches the available and installed packages for the supplied search key.
378 The list of available and installed packages is created at object instantiation.
379 This makes successive searches faster."""
380 self.settings = settings
382 self.vartree = vartree
383 self.spinner = spinner
384 self.verbose = verbose
385 self.searchdesc = searchdesc
387 def execute(self,searchkey):
388 """Performs the search for the supplied search key"""
390 self.searchkey=searchkey
391 self.packagematches = []
394 self.matches = {"pkg":[], "desc":[]}
397 self.matches = {"pkg":[]}
398 print "Searching... ",
401 if self.searchkey.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.keys():
444 self.matches[mtype].sort()
445 self.mlen += len(self.matches[mtype])
448 """Outputs the results of the search."""
449 print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
450 print "[ Applications found : "+white(str(self.mlen))+" ]"
452 for mtype in self.matches.keys():
453 for match,masked in self.matches[mtype]:
456 full_package = self.portdb.xmatch(
457 "bestmatch-visible", match)
459 #no match found; we don't want to query description
461 full_package = portage.best(
462 self.portdb.xmatch("match-all",match))
465 match = portage.pkgsplit(match)[0]
469 desc, homepage, license = self.portdb.aux_get(
470 full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
472 print "emerge: search: aux_get() failed, skipping"
475 print green("*")+" "+white(match)+" "+red("[ Masked ]")
477 print green("*")+" "+white(match)
478 myversion = self.getVersion(full_package, search.VERSION_RELEASE)
481 mycat = match.split("/")[0]
482 mypkg = match.split("/")[1]
483 mycpv = match + "-" + myversion
484 myebuild = self.portdb.findname(mycpv)
485 pkgdir = os.path.dirname(myebuild)
486 from portage import manifest
487 mf = manifest.Manifest(
488 pkgdir, self.settings["DISTDIR"])
489 fetchlist = self.portdb.getfetchlist(mycpv,
490 mysettings=self.settings, all=True)[1]
492 mysum[0] = mf.getDistfilesSize(fetchlist)
493 mystr = str(mysum[0]/1024)
497 mystr=mystr[:mycount]+","+mystr[mycount:]
500 mysum[0] = "Unknown (missing digest for %s)" % str(e)
503 print " ", darkgreen("Latest version available:"),myversion
504 print " ", self.getInstallationStatus(mycat+'/'+mypkg)
505 print " ", darkgreen("Size of files:"),mysum[0]
506 print " ", darkgreen("Homepage:")+" ",homepage
507 print " ", darkgreen("Description:")+" ",desc
508 print " ", darkgreen("License:")+" ",license
514 def getInstallationStatus(self,package):
515 installed_package = self.vartree.dep_bestmatch(package)
517 version = self.getVersion(installed_package,search.VERSION_RELEASE)
519 result = darkgreen("Latest version installed:")+" "+version
521 result = darkgreen("Latest version installed:")+" [ Not Installed ]"
524 def getVersion(self,full_package,detail):
525 if len(full_package) > 1:
526 package_parts = portage.catpkgsplit(full_package)
527 if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
528 result = package_parts[2]+ "-" + package_parts[3]
530 result = package_parts[2]
536 #build our package digraph
537 def getlist(settings, mode):
539 mylines = settings.packages
542 file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
543 myfile = open(file_path, "r")
544 mylines = myfile.readlines()
546 except (OSError, IOError), e:
547 if e.errno == errno.ENOENT:
548 portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
554 myline=" ".join(x.split())
563 mynewlines.append(myline.strip())
567 def clean_world(vardb, cpv):
568 """Remove a package from the world file when unmerged."""
569 world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
570 worldlist = portage.util.grabfile(world_filename)
571 mykey = portage.cpv_getkey(cpv)
574 if portage.dep_getkey(x) == mykey:
575 matches = vardb.match(x, use_cache=0)
579 elif len(matches) == 1 and matches[0] == cpv:
583 #others are around; keep it.
584 newworldlist.append(x)
586 #this doesn't match the package we're unmerging; keep it.
587 newworldlist.append(x)
589 portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
590 gid=portage.portage_gid, mode=02770)
591 portage.util.write_atomic(world_filename, "\n".join(newworldlist))
593 def genericdict(mylist):
596 mynewdict[portage.dep_getkey(x)]=x
599 def filter_iuse_defaults(iuse):
601 if flag.startswith("+"):
606 class DepPriority(object):
608 This class generates an integer priority level based of various
609 attributes of the dependency relationship. Attributes can be assigned
610 at any time and the new integer value will be generated on calls to the
611 __int__() method. Rich comparison operators are supported.
613 The boolean attributes that affect the integer value are "satisfied",
614 "buildtime", "runtime", and "system". Various combinations of
615 attributes lead to the following priority levels:
617 Combination of properties Priority level
619 not satisfied and buildtime 0
620 not satisfied and runtime -1
621 satisfied and buildtime -2
622 satisfied and runtime -3
623 (none of the above) -4
625 Several integer constants are defined for categorization of priority
628 MEDIUM The upper boundary for medium dependencies.
629 SOFT The upper boundary for soft dependencies.
630 MIN The lower boundary for soft dependencies.
632 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
636 def __init__(self, **kwargs):
637 for myattr in self.__slots__:
638 if myattr == "__weakref__":
640 myvalue = kwargs.get(myattr, False)
641 setattr(self, myattr, myvalue)
643 if not self.satisfied:
653 def __lt__(self, other):
654 return self.__int__() < other
655 def __le__(self, other):
656 return self.__int__() <= other
657 def __eq__(self, other):
658 return self.__int__() == other
659 def __ne__(self, other):
660 return self.__int__() != other
661 def __gt__(self, other):
662 return self.__int__() > other
663 def __ge__(self, other):
664 return self.__int__() >= other
667 return copy.copy(self)
669 myvalue = self.__int__()
670 if myvalue > self.MEDIUM:
672 if myvalue > self.SOFT:
676 class FakeVartree(portage.vartree):
677 """This is implements an in-memory copy of a vartree instance that provides
678 all the interfaces required for use by the depgraph. The vardb is locked
679 during the constructor call just long enough to read a copy of the
680 installed package information. This allows the depgraph to do it's
681 dependency calculations without holding a lock on the vardb. It also
682 allows things like vardb global updates to be done in memory so that the
683 user doesn't necessarily need write access to the vardb in cases where
684 global updates are necessary (updates are performed when necessary if there
685 is not a matching ebuild in the tree)."""
686 def __init__(self, real_vartree, portdb):
687 self.root = real_vartree.root
688 self.settings = real_vartree.settings
689 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
690 vdb_path = os.path.join(self.root, portage.VDB_PATH)
692 # At least the parent needs to exist for the lock file.
693 portage.util.ensure_dirs(vdb_path)
694 except portage.exception.PortageException:
698 if os.access(vdb_path, os.W_OK):
699 vdb_lock = portage.locks.lockdir(vdb_path)
700 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
701 "DEPEND", "RDEPEND", "PDEPEND"]
702 real_dbapi = real_vartree.dbapi
704 for cpv in real_dbapi.cpv_all():
705 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
706 myslot = metadata["SLOT"]
707 mycp = portage.dep_getkey(cpv)
708 myslot_atom = "%s:%s" % (mycp, myslot)
710 mycounter = long(metadata["COUNTER"])
713 metadata["COUNTER"] = str(mycounter)
714 other_counter = slot_counters.get(myslot_atom, None)
715 if other_counter is not None:
716 if other_counter > mycounter:
718 slot_counters[myslot_atom] = mycounter
719 self.dbapi.cpv_inject(cpv, metadata=metadata)
720 real_dbapi.flush_cache()
723 portage.locks.unlockdir(vdb_lock)
724 # Populate the old-style virtuals using the cached values.
725 if not self.settings.treeVirtuals:
726 self.settings.treeVirtuals = portage.util.map_dictlist_vals(
727 portage.getCPFromCPV, self.get_all_provides())
729 # Intialize variables needed for lazy cache pulls of the live ebuild
730 # metadata. This ensures that the vardb lock is released ASAP, without
731 # being delayed in case cache generation is triggered.
732 self._aux_get = self.dbapi.aux_get
733 self.dbapi.aux_get = self._aux_get_wrapper
734 self._aux_get_history = set()
735 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
736 self._portdb = portdb
737 self._global_updates = None
739 def _aux_get_wrapper(self, pkg, wants):
740 if pkg in self._aux_get_history:
741 return self._aux_get(pkg, wants)
742 self._aux_get_history.add(pkg)
744 # Use the live ebuild metadata if possible.
745 live_metadata = dict(izip(self._portdb_keys,
746 self._portdb.aux_get(pkg, self._portdb_keys)))
747 self.dbapi.aux_update(pkg, live_metadata)
748 except (KeyError, portage.exception.PortageException):
749 if self._global_updates is None:
750 self._global_updates = \
751 grab_global_updates(self._portdb.porttree_root)
752 perform_global_updates(
753 pkg, self.dbapi, self._global_updates)
754 return self._aux_get(pkg, wants)
756 def grab_global_updates(portdir):
757 from portage.update import grab_updates, parse_updates
758 updpath = os.path.join(portdir, "profiles", "updates")
760 rawupdates = grab_updates(updpath)
761 except portage.exception.DirectoryNotFound:
764 for mykey, mystat, mycontent in rawupdates:
765 commands, errors = parse_updates(mycontent)
766 upd_commands.extend(commands)
769 def perform_global_updates(mycpv, mydb, mycommands):
770 from portage.update import update_dbentries
771 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
772 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
773 updates = update_dbentries(mycommands, aux_dict)
775 mydb.aux_update(mycpv, updates)
777 class BlockerCache(DictMixin):
778 """This caches blockers of installed packages so that dep_check does not
779 have to be done for every single installed package on every invocation of
780 emerge. The cache is invalidated whenever it is detected that something
781 has changed that might alter the results of dep_check() calls:
782 1) the set of installed packages (including COUNTER) has changed
783 2) the old-style virtuals have changed
785 class BlockerData(object):
786 def __init__(self, counter, atoms):
787 self.counter = counter
790 def __init__(self, myroot, vardb):
792 self._installed_pkgs = set(vardb.cpv_all())
793 self._virtuals = vardb.settings.getvirtuals()
794 self._cache_filename = os.path.join(myroot,
795 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
796 self._cache_version = "1"
797 self._cache_data = None
798 self._modified = False
803 f = open(self._cache_filename)
804 mypickle = cPickle.Unpickler(f)
805 mypickle.find_global = None
806 self._cache_data = mypickle.load()
809 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
811 cache_valid = self._cache_data and \
812 isinstance(self._cache_data, dict) and \
813 self._cache_data.get("version") == self._cache_version and \
814 self._cache_data.get("virtuals") == self._virtuals and \
815 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
817 for pkg in self._installed_pkgs:
818 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
823 self._cache_data = {"version":self._cache_version}
824 self._cache_data["blockers"] = {}
825 self._cache_data["virtuals"] = self._virtuals
826 self._modified = False
829 """If the current user has permission and the internal blocker cache
830 been updated, save it to disk and mark it unmodified. This is called
831 by emerge after it has proccessed blockers for all installed packages.
832 Currently, the cache is only written if the user has superuser
833 privileges (since that's required to obtain a lock), but all users
834 have read access and benefit from faster blocker lookups (as long as
835 the entire cache is still valid). The cache is stored as a pickled
836 dict object with the following format:
840 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
841 "virtuals" : vardb.settings.getvirtuals()
844 if self._modified and \
847 f = portage.util.atomic_ofstream(self._cache_filename)
848 cPickle.dump(self._cache_data, f, -1)
850 portage.util.apply_secpass_permissions(
851 self._cache_filename, gid=portage.portage_gid, mode=0644)
852 except (IOError, OSError), e:
854 self._modified = False
856 def __setitem__(self, cpv, blocker_data):
858 Update the cache and mark it as modified for a future call to
861 @param cpv: Package for which to cache blockers.
863 @param blocker_data: An object with counter and atoms attributes.
864 @type blocker_data: BlockerData
866 self._cache_data["blockers"][cpv] = \
867 (blocker_data.counter, blocker_data.atoms)
868 self._modified = True
870 def __getitem__(self, cpv):
873 @returns: An object with counter and atoms attributes.
875 return self.BlockerData(*self._cache_data["blockers"][cpv])
877 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
879 from formatter import AbstractFormatter, DumbWriter
880 f = AbstractFormatter(DumbWriter(maxcol=72))
882 print "\n\n!!! Invalid or corrupt dependency specification: "
890 p_type, p_root, p_key, p_status = parent_node
892 if p_status == "nomerge":
893 category, pf = portage.catsplit(p_key)
894 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
895 msg.append("Portage is unable to process the dependencies of the ")
896 msg.append("'%s' package. " % p_key)
897 msg.append("In order to correct this problem, the package ")
898 msg.append("should be uninstalled, reinstalled, or upgraded. ")
899 msg.append("As a temporary workaround, the --nodeps option can ")
900 msg.append("be used to ignore all dependencies. For reference, ")
901 msg.append("the problematic dependencies can be found in the ")
902 msg.append("*DEPEND files located in '%s/'." % pkg_location)
904 msg.append("This package can not be installed. ")
905 msg.append("Please notify the '%s' package maintainer " % p_key)
906 msg.append("about this problem.")
909 f.add_flowing_data(x)
917 "installed":"vartree"}
919 def __init__(self, settings, trees, myopts, myparams, spinner):
920 self.settings = settings
921 self.target_root = settings["ROOT"]
923 self.myparams = myparams
925 if settings.get("PORTAGE_DEBUG", "") == "1":
927 self.spinner = spinner
928 self.pkgsettings = {}
929 # Maps cpv to digraph node for all nodes added to the graph.
930 self.pkg_node_map = {}
931 # Maps slot atom to digraph node for all nodes added to the graph.
932 self._slot_node_map = {}
934 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
938 self.trees[myroot] = {}
939 for tree in ("porttree", "bintree"):
940 self.trees[myroot][tree] = trees[myroot][tree]
941 self.trees[myroot]["vartree"] = \
942 FakeVartree(trees[myroot]["vartree"],
943 trees[myroot]["porttree"].dbapi)
944 self.pkgsettings[myroot] = portage.config(
945 clone=self.trees[myroot]["vartree"].settings)
946 self.pkg_node_map[myroot] = {}
947 self._slot_node_map[myroot] = {}
948 vardb = self.trees[myroot]["vartree"].dbapi
949 # This fakedbapi instance will model the state that the vdb will
950 # have after new packages have been installed.
951 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
952 self.mydbapi[myroot] = fakedb
953 if "--nodeps" not in self.myopts and \
954 "--buildpkgonly" not in self.myopts:
955 # --nodeps bypasses this, since it isn't needed in this case
956 # and the cache pulls might trigger (slow) cache generation.
957 for pkg in vardb.cpv_all():
958 self.spinner.update()
959 fakedb.cpv_inject(pkg,
960 metadata=dict(izip(self._mydbapi_keys,
961 vardb.aux_get(pkg, self._mydbapi_keys))))
963 self.useFlags[myroot] = {}
964 if "--usepkg" in self.myopts:
965 self.trees[myroot]["bintree"].populate(
966 "--getbinpkg" in self.myopts,
967 "--getbinpkgonly" in self.myopts)
971 self.digraph=portage.digraph()
972 # Tracks simple parent/child relationships (PDEPEND relationships are
974 self._parent_child_digraph = digraph()
976 self.outdatedpackages=[]
978 self.blocker_digraph = digraph()
979 self.blocker_parents = {}
980 self._unresolved_blocker_parents = {}
981 self._slot_collision_info = []
982 # Slot collision nodes are not allowed to block other packages since
983 # blocker validation is only able to account for one package per slot.
984 self._slot_collision_nodes = set()
985 self._altlist_cache = {}
986 self._pprovided_args = []
988 def _show_slot_collision_notice(self, packages):
989 """Show an informational message advising the user to mask one of the
990 the packages. In some cases it may be possible to resolve this
991 automatically, but support for backtracking (removal nodes that have
992 already been selected) will be required in order to handle all possible
996 msg.append("\n!!! Multiple versions within a single " + \
997 "package slot have been \n")
998 msg.append("!!! pulled into the dependency graph:\n\n")
999 for node, parents in packages:
1000 msg.append(str(node))
1002 msg.append(" pulled in by\n")
1003 for parent in parents:
1005 msg.append(str(parent))
1008 msg.append(" (no parents)\n")
1010 sys.stderr.write("".join(msg))
1013 if "--quiet" in self.myopts:
1017 msg.append("It may be possible to solve this problem ")
1018 msg.append("by using package.mask to prevent one of ")
1019 msg.append("those packages from being selected. ")
1020 msg.append("However, it is also possible that conflicting ")
1021 msg.append("dependencies exist such that they are impossible to ")
1022 msg.append("satisfy simultaneously. If such a conflict exists in ")
1023 msg.append("the dependencies of two different packages, then those ")
1024 msg.append("packages can not be installed simultaneously.")
1026 from formatter import AbstractFormatter, DumbWriter
1027 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1029 f.add_flowing_data(x)
1033 msg.append("For more information, see MASKED PACKAGES ")
1034 msg.append("section in the emerge man page or refer ")
1035 msg.append("to the Gentoo Handbook.")
1037 f.add_flowing_data(x)
1041 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1042 priority=DepPriority(), rev_dep=False, arg=None):
1044 Fills the digraph with nodes comprised of packages to merge.
1045 mybigkey is the package spec of the package to merge.
1046 myparent is the package depending on mybigkey ( or None )
1047 addme = Should we add this package to the digraph or are we just looking at it's deps?
1048 Think --onlydeps, we need to ignore packages in that case.
1051 #IUSE-aware emerge -> USE DEP aware depgraph
1052 #"no downgrade" emerge
1054 mytype, myroot, mykey = mybigkey
1055 existing_node = None
1057 existing_node = self.pkg_node_map[myroot].get(mykey)
1059 self._parent_child_digraph.add(existing_node, myparent)
1060 if existing_node != myparent:
1061 # Refuse to make a node depend on itself so that the we don't
1062 # don't create a bogus circular dependency in self.altlist().
1063 if rev_dep and myparent:
1064 self.digraph.addnode(myparent, existing_node,
1067 self.digraph.addnode(existing_node, myparent,
1071 if "--nodeps" not in self.myopts:
1072 self.spinner.update()
1073 if mytype == "blocks":
1075 "--buildpkgonly" not in self.myopts and \
1076 "--nodeps" not in self.myopts and \
1077 myparent not in self._slot_collision_nodes:
1078 mybigkey[1] = myparent[1]
1079 self.blocker_parents.setdefault(
1080 tuple(mybigkey), set()).add(myparent)
1082 if not arg and myroot == self.target_root:
1083 arg = portage.best_match_to_list(mykey, self.args_keys)
1084 # select the correct /var database that we'll be checking against
1085 vardbapi = self.trees[myroot]["vartree"].dbapi
1086 portdb = self.trees[myroot]["porttree"].dbapi
1087 bindb = self.trees[myroot]["bintree"].dbapi
1088 pkgsettings = self.pkgsettings[myroot]
1090 # if the package is already on the system, we add a "nomerge"
1091 # directive, otherwise we add a "merge" directive.
1093 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1096 self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
1097 myuse = self.pkgsettings[myroot]["USE"].split()
1100 if mytype == "installed":
1102 if addme and mytype != "installed":
1103 # this is where we add the node to the list of packages to merge
1104 if "selective" in self.myparams or not arg:
1105 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1108 """ If we aren't merging, perform the --newuse check.
1109 If the package has new iuse flags or different use flags then if
1110 --newuse is specified, we need to merge the package. """
1111 if merging==0 and "--newuse" in self.myopts and \
1112 vardbapi.cpv_exists(mykey):
1113 pkgsettings.setcpv(mykey, mydb=mydbapi)
1114 forced_flags = set()
1115 forced_flags.update(pkgsettings.useforce)
1116 forced_flags.update(pkgsettings.usemask)
1117 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1118 iuses = set(filter_iuse_defaults(
1119 mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
1120 old_iuse = set(filter_iuse_defaults(
1121 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1122 if iuses.symmetric_difference(
1123 old_iuse).difference(forced_flags):
1125 elif old_iuse.intersection(old_use) != \
1126 iuses.intersection(myuse):
1129 if addme and merging == 1:
1130 mybigkey.append("merge")
1132 mybigkey.append("nomerge")
1133 jbigkey = tuple(mybigkey)
1136 metadata = dict(izip(self._mydbapi_keys,
1137 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1138 if merging == 0 and vardbapi.cpv_exists(mykey) and \
1139 mytype != "installed":
1140 mybigkey[0] = "installed"
1142 jbigkey = tuple(mybigkey)
1143 metadata = dict(izip(self._mydbapi_keys,
1144 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1145 myuse = mydbapi.aux_get(mykey, ["USE"])[0].split()
1146 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1147 existing_node = self._slot_node_map[myroot].get(
1149 slot_collision = False
1151 e_type, myroot, e_cpv, e_status = existing_node
1153 # The existing node can be reused.
1154 self._parent_child_digraph.add(existing_node, myparent)
1155 if rev_dep and myparent:
1156 ptype, proot, pkey, pstatus = myparent
1157 self.digraph.addnode(myparent, existing_node,
1160 self.digraph.addnode(existing_node, myparent,
1164 # A slot collision has occurred. Sometimes this coincides
1165 # with unresolvable blockers, so the slot collision will be
1166 # shown later if there are no unresolvable blockers.
1167 e_parents = self._parent_child_digraph.parent_nodes(
1171 myparents.append(myparent)
1172 self._slot_collision_info.append(
1173 ((jbigkey, myparents), (existing_node, e_parents)))
1174 self._slot_collision_nodes.add(jbigkey)
1175 slot_collision = True
1178 # Now add this node to the graph so that self.display()
1179 # can show use flags and --tree portage.output. This node is
1180 # only being partially added to the graph. It must not be
1181 # allowed to interfere with the other nodes that have been
1182 # added. Do not overwrite data for existing nodes in
1183 # self.pkg_node_map and self.mydbapi since that data will
1184 # be used for blocker validation.
1185 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1186 self.useFlags[myroot].setdefault(mykey, myuse)
1187 # Even though the graph is now invalid, continue to process
1188 # dependencies so that things like --fetchonly can still
1189 # function despite collisions.
1191 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1192 self._slot_node_map[myroot][slot_atom] = jbigkey
1193 self.pkg_node_map[myroot][mykey] = jbigkey
1194 self.useFlags[myroot][mykey] = myuse
1196 if rev_dep and myparent:
1197 self.digraph.addnode(myparent, jbigkey,
1200 self.digraph.addnode(jbigkey, myparent,
1203 # Do this even when addme is False (--onlydeps) so that the
1204 # parent/child relationship is always known in case
1205 # self._show_slot_collision_notice() needs to be called later.
1206 self._parent_child_digraph.add(jbigkey, myparent)
1208 """ This section determines whether we go deeper into dependencies or not.
1209 We want to go deeper on a few occasions:
1210 Installing package A, we need to make sure package A's deps are met.
1211 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1212 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1214 if "deep" not in self.myparams and not merging and \
1215 not ("--update" in self.myopts and arg and merging):
1217 elif "recurse" not in self.myparams:
1220 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1221 Pull from bintree if it's binary package, porttree if it's ebuild.
1222 Binpkg's can be either remote or local. """
1225 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1226 depvalues = mydbapi.aux_get(mykey, depkeys)
1227 for i in xrange(len(depkeys)):
1228 edepend[depkeys[i]] = depvalues[i]
1230 if mytype == "ebuild":
1231 if "--buildpkgonly" in self.myopts:
1232 edepend["RDEPEND"] = ""
1233 edepend["PDEPEND"] = ""
1234 if not (arg and "--onlydeps" in self.myopts and \
1235 mytype == "ebuild") and \
1236 self.myopts.get("--with-bdeps", "n") == "n" and \
1237 (mytype == "binary" or mybigkey[3] == "nomerge"):
1238 edepend["DEPEND"] = ""
1240 """ We have retrieve the dependency information, now we need to recursively
1241 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1243 mp = tuple(mybigkey)
1246 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1247 myuse=myuse, priority=DepPriority(buildtime=True),
1250 """RDEPEND is soft by definition. However, in order to ensure
1251 correct merge order, we make it a hard dependency. Otherwise, a
1252 build time dependency might not be usable due to it's run time
1253 dependencies not being installed yet.
1255 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1256 myuse=myuse, priority=DepPriority(runtime=True),
1259 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1260 # Post Depend -- Add to the list without a parent, as it depends
1261 # on a package being present AND must be built after that package.
1262 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1263 myuse=myuse, priority=DepPriority(), rev_deps=True,
1266 except ValueError, e:
1268 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1269 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1271 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1272 portage.writemsg("\n", noiselevel=-1)
1273 if mytype == "binary":
1275 "!!! This binary package cannot be installed: '%s'\n" % \
1276 mykey, noiselevel=-1)
1277 elif mytype == "ebuild":
1278 myebuild, mylocation = portdb.findname2(mykey)
1279 portage.writemsg("!!! This ebuild cannot be installed: " + \
1280 "'%s'\n" % myebuild, noiselevel=-1)
1281 portage.writemsg("!!! Please notify the package maintainer " + \
1282 "that atoms must be fully-qualified.\n", noiselevel=-1)
1286 def select_files(self,myfiles):
1287 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1289 myroot = self.target_root
1290 portdb = self.trees[myroot]["porttree"].dbapi
1291 bindb = self.trees[myroot]["bintree"].dbapi
1292 pkgsettings = self.pkgsettings[myroot]
1294 def visible(mylist):
1295 matches = portdb.gvisible(portdb.visible(mylist))
1296 return [x for x in mylist \
1297 if x in matches or not portdb.cpv_exists(x)]
1299 ext = os.path.splitext(x)[1]
1301 if not os.path.exists(x):
1303 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1304 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1305 elif os.path.exists(
1306 os.path.join(pkgsettings["PKGDIR"], x)):
1307 x = os.path.join(pkgsettings["PKGDIR"], x)
1309 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1310 print "!!! Please ensure the tbz2 exists as specified.\n"
1312 mytbz2=portage.xpak.tbz2(x)
1313 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1314 if os.path.realpath(x) != \
1315 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1316 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1318 if not self.create(["binary", myroot, mykey],
1319 None, "--onlydeps" not in self.myopts):
1320 return (0,myfavorites)
1321 elif not "--oneshot" in self.myopts:
1322 myfavorites.append(mykey)
1323 elif ext==".ebuild":
1324 x = os.path.realpath(x)
1325 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1326 ebuild_path = portdb.findname(mykey)
1328 if os.path.realpath(ebuild_path) != x:
1329 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1331 if mykey not in portdb.xmatch(
1332 "match-visible", portage.dep_getkey(mykey)):
1333 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1334 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1335 print colorize("BAD", "*** page for details.")
1336 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1339 raise portage.exception.PackageNotFound(
1340 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1341 if not self.create(["ebuild", myroot, mykey],
1342 None, "--onlydeps" not in self.myopts):
1343 return (0,myfavorites)
1344 elif not "--oneshot" in self.myopts:
1345 myfavorites.append(mykey)
1347 if not is_valid_package_atom(x):
1348 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1350 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1351 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1355 if "--usepkg" in self.myopts:
1356 mykey = portage.dep_expand(x, mydb=bindb,
1357 settings=pkgsettings)
1358 if (mykey and not mykey.startswith("null/")) or \
1359 "--usepkgonly" in self.myopts:
1360 arg_atoms.append((x, mykey))
1363 mykey = portage.dep_expand(x,
1364 mydb=portdb, settings=pkgsettings)
1365 arg_atoms.append((x, mykey))
1366 except ValueError, errpkgs:
1367 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1368 print "!!! one of the following fully-qualified ebuild names instead:\n"
1369 for i in errpkgs[0]:
1370 print " " + green(i)
1374 if "--update" in self.myopts:
1375 """Make sure all installed slots are updated when possible. Do this
1376 with --emptytree also, to ensure that all slots are remerged."""
1377 vardb = self.trees[self.target_root]["vartree"].dbapi
1379 for myarg, myatom in arg_atoms:
1380 greedy_atoms.append((myarg, myatom))
1382 for cpv in vardb.match(myatom):
1383 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1386 if "--usepkg" in self.myopts:
1387 mymatches = bindb.match(myatom)
1388 if "--usepkgonly" not in self.myopts:
1389 mymatches = visible(mymatches)
1390 best_pkg = portage.best(mymatches)
1392 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1393 best_pkgs.append(("binary", best_pkg, best_slot))
1394 if "--usepkgonly" not in self.myopts:
1395 best_pkg = portage.best(portdb.match(myatom))
1397 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1398 best_pkgs.append(("ebuild", best_pkg, best_slot))
1400 best_pkg = portage.best([x[1] for x in best_pkgs])
1401 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1402 best_slot = best_pkgs[0][2]
1403 myslots.add(best_slot)
1404 if len(myslots) > 1:
1405 for myslot in myslots:
1406 myslot_atom = "%s:%s" % \
1407 (portage.dep_getkey(myatom), myslot)
1409 if "--usepkgonly" not in self.myopts and \
1410 self.trees[self.target_root][
1411 "porttree"].dbapi.match(myslot_atom):
1413 elif "--usepkg" in self.myopts:
1414 mymatches = bindb.match(myslot_atom)
1415 if "--usepkgonly" not in self.myopts:
1416 mymatches = visible(mymatches)
1420 greedy_atoms.append((myarg, myslot_atom))
1421 arg_atoms = greedy_atoms
1423 """ These are used inside self.create() in order to ensure packages
1424 that happen to match arguments are not incorrectly marked as nomerge."""
1425 self.args_keys = [x[1] for x in arg_atoms]
1426 for myarg, myatom in arg_atoms:
1428 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1429 except portage.exception.MissingSignature, e:
1430 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1431 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1432 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1433 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1434 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1436 except portage.exception.InvalidSignature, e:
1437 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1438 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1439 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1440 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1441 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1443 except SystemExit, e:
1444 raise # Needed else can't exit
1445 except Exception, e:
1446 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1447 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1451 return (0,myfavorites)
1452 elif not "--oneshot" in self.myopts:
1453 mykey = portage.dep_getkey(myatom)
1454 if mykey not in myfavorites:
1455 myfavorites.append(mykey)
1458 if "--usepkgonly" in self.myopts:
1459 for xs in self.digraph.all_nodes():
1460 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1464 print "Missing binary for:",xs[2]
1466 if not self.validate_blockers():
1467 return False, myfavorites
1469 # We're true here unless we are missing binaries.
1470 return (not missing,myfavorites)
1472 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1473 myuse=None, raise_on_missing=False, priority=DepPriority(),
1474 rev_deps=False, parent_arg=None):
1475 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1476 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1477 myparent = the node whose depstring is being passed in
1478 arg = package was specified on the command line, merge even if it's already installed
1479 myuse = USE flags at present
1480 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1481 else continue trying.
1482 return 1 on success, 0 for failure
1485 portdb = self.trees[myroot]["porttree"].dbapi
1486 bindb = self.trees[myroot]["bintree"].dbapi
1487 vardb = self.trees[myroot]["vartree"].dbapi
1488 pkgsettings = self.pkgsettings[myroot]
1490 p_type, p_root, p_key, p_status = myparent
1492 if "--debug" in self.myopts:
1494 print "Parent: ",myparent
1495 print "Depstring:",depstring
1497 print "Reverse:", rev_deps
1498 print "Priority:", priority
1500 #processing dependencies
1501 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1502 dependencies are satisfiable. """
1504 mymerge = [depstring]
1505 pprovided = pkgsettings.pprovideddict.get(
1506 portage.dep_getkey(depstring))
1507 if pprovided and portage.match_from_list(depstring, pprovided):
1511 if myparent and p_status == "nomerge":
1512 portage.dep._dep_check_strict = False
1513 mycheck = portage.dep_check(depstring, None,
1514 pkgsettings, myuse=myuse,
1515 use_binaries=("--usepkgonly" in self.myopts),
1516 myroot=myroot, trees=self.trees)
1518 portage.dep._dep_check_strict = True
1522 show_invalid_depstring_notice(
1523 myparent, depstring, mycheck[1])
1525 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1527 mymerge = mycheck[1]
1529 if not mymerge and arg and \
1530 portage.best_match_to_list(depstring, self.args_keys):
1531 # A provided package has been specified on the command line. The
1532 # package will not be merged and a warning will be displayed.
1533 self._pprovided_args.append(arg)
1536 # The parent is added after it's own dep_check call so that it
1537 # isn't allowed to satisfy a direct bootstrap dependency on itself
1538 # via an old-style virtual. This isn't a problem with new-style
1539 # virtuals, which are preferenced in dep_zapdeps by looking only at
1540 # the depstring, vdb, and available packages.
1542 p_type, p_root, p_key, p_status = myparent
1543 if p_status == "merge":
1544 # Update old-style virtuals if this package provides any.
1545 # These are needed for dep_virtual calls inside dep_check.
1546 p_db = self.trees[p_root][self.pkg_tree_map[p_type]].dbapi
1548 self.pkgsettings[p_root].setinst(p_key, p_db)
1549 except portage.exception.InvalidDependString, e:
1550 provide = p_db.aux_get(p_key, ["PROVIDE"])[0]
1551 show_invalid_depstring_notice(myparent, provide, str(e))
1555 if "--debug" in self.myopts:
1556 print "Candidates:",mymerge
1560 selected_pkg = ["blocks", myroot, x[1:], None]
1562 #We are not processing a blocker but a normal dependency
1564 """In some cases, dep_check will return deps that shouldn't
1565 be proccessed any further, so they are identified and
1567 if "empty" not in self.myparams and \
1568 "deep" not in self.myparams and \
1569 not ("--update" in self.myopts and parent_arg) and \
1573 # List of acceptable packages, ordered by type preference.
1574 matched_packages = []
1575 myeb_matches = portdb.xmatch("match-visible", x)
1577 if "--usepkgonly" not in self.myopts:
1578 myeb = portage.best(myeb_matches)
1581 if "--usepkg" in self.myopts:
1582 # The next line assumes the binarytree has been populated.
1583 # XXX: Need to work out how we use the binary tree with roots.
1584 myeb_pkg_matches = bindb.match(x)
1585 if "--usepkgonly" not in self.myopts:
1586 # Remove any binary package entries that are masked in the portage tree (#55871)
1587 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1588 if pkg in myeb_matches or \
1589 not portdb.cpv_exists(pkg)]
1590 if myeb_pkg_matches:
1591 myeb_pkg = portage.best(myeb_pkg_matches)
1593 if myeb_pkg and "--newuse" in self.myopts:
1594 iuses = set(filter_iuse_defaults(
1595 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1596 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1598 if "--usepkgonly" not in self.myopts and myeb:
1601 pkgsettings.setcpv(myeb, mydb=mydb)
1603 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1604 now_use = pkgsettings["USE"].split()
1605 forced_flags = set()
1606 forced_flags.update(pkgsettings.useforce)
1607 forced_flags.update(pkgsettings.usemask)
1609 if "--usepkgonly" not in self.myopts and myeb:
1610 cur_iuse = set(filter_iuse_defaults(
1611 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1612 if iuses.symmetric_difference(
1613 cur_iuse).difference(forced_flags):
1615 elif iuses.intersection(old_use) != \
1616 cur_iuse.intersection(now_use):
1620 self.trees[myroot]["bintree"].dbapi.aux_get(
1621 myeb_pkg, ["USE"])[0].split()
1622 matched_packages.append(
1623 ["binary", myroot, myeb_pkg, binpkguseflags])
1625 if "--usepkgonly" not in self.myopts and myeb_matches:
1626 matched_packages.append(
1627 ["ebuild", myroot, myeb, None])
1629 if not matched_packages and \
1630 not (arg and "selective" not in self.myparams):
1631 """Fall back to the installed package database. This is a
1632 last resort because the metadata tends to diverge from that
1633 of the ebuild in the tree."""
1634 myeb_inst_matches = vardb.match(x)
1635 if "--usepkgonly" not in self.myopts:
1636 """ TODO: Improve masking check for installed and
1637 binary packages. bug #149816"""
1638 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1639 if not portdb.cpv_exists(pkg)]
1641 if myeb_inst_matches:
1642 myeb_inst = portage.best(myeb_inst_matches)
1644 binpkguseflags = vardb.aux_get(
1645 myeb_inst, ["USE"])[0].split()
1646 matched_packages.append(
1647 ["installed", myroot, myeb_inst, binpkguseflags])
1649 if not matched_packages:
1650 if raise_on_missing:
1657 xfrom = '(dependency required by '+ \
1658 green('"%s"' % myparent[2]) + \
1659 red(' [%s]' % myparent[0]) + ')'
1660 alleb = portdb.xmatch("match-all", x)
1662 if "--usepkgonly" not in self.myopts:
1663 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1664 print "!!! One of the following masked packages is required to complete your request:"
1668 mreasons = portage.getmaskingstatus(p,
1669 settings=pkgsettings, portdb=portdb)
1670 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1671 if "package.mask" in mreasons:
1672 comment, filename = \
1673 portage.getmaskingreason(p,
1674 settings=pkgsettings, portdb=portdb,
1675 return_location=True)
1676 if comment and comment != oldcomment:
1679 oldcomment = comment
1681 licenses = portdb.aux_get(p, ["LICENSE"])[0]
1683 # Corruption will have been reported above.
1687 pkgsettings.setcpv(p, mydb=portdb)
1688 uselist = pkgsettings.get("USE", "").split()
1689 missing_licenses = []
1691 missing_licenses = \
1692 pkgsettings.getMissingLicenses(
1693 licenses, p, uselist)
1694 except portage.exception.InvalidDependString:
1695 # This will have already been reported
1696 # above via mreasons.
1698 for l in missing_licenses:
1699 l_path = portdb.findLicensePath(l)
1700 if l in shown_licenses:
1702 msg = ("A copy of the '%s' license" + \
1703 " is located at '%s'.") % (l, l_path)
1706 shown_licenses.append(l)
1708 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1709 print "refer to the Gentoo Handbook."
1711 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1712 print "!!! Either add a suitable binary package or compile from an ebuild."
1714 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1720 if "--debug" in self.myopts:
1721 for pkg in matched_packages:
1722 print (pkg[0] + ":").rjust(10), pkg[2]
1724 if len(matched_packages) > 1:
1725 bestmatch = portage.best(
1726 [pkg[2] for pkg in matched_packages])
1727 matched_packages = [pkg for pkg in matched_packages \
1728 if pkg[2] == bestmatch]
1730 # ordered by type preference ("ebuild" type is the last resort)
1731 selected_pkg = matched_packages[0]
1732 pkgtype, myroot, mycpv, myuse = selected_pkg
1733 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1734 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1735 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1736 existing_node = self._slot_node_map[myroot].get(
1739 e_type, myroot, e_cpv, e_status = existing_node
1740 if portage.match_from_list(x, [e_cpv]):
1741 # The existing node can be reused.
1742 selected_pkg = [e_type, myroot, e_cpv,
1743 self.useFlags[myroot][e_cpv]]
1746 #we are a dependency, so we want to be unconditionally added
1747 mypriority = priority.copy()
1749 mypriority.satisfied = True
1750 if not self.create(selected_pkg[0:3], myparent,
1751 myuse=selected_pkg[-1], priority=mypriority,
1752 rev_dep=rev_deps, arg=arg):
1755 #if mysource is not set, then we are a command-line dependency and should not be added
1756 #if --onlydeps is specified.
1757 if not self.create(selected_pkg[0:3], myparent,
1758 addme=("--onlydeps" not in self.myopts),
1759 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1762 if "--debug" in self.myopts:
1763 print "Exiting...",myparent
1766 def validate_blockers(self):
1767 """Remove any blockers from the digraph that do not match any of the
1768 packages within the graph. If necessary, create hard deps to ensure
1769 correct merge order such that mutually blocking packages are never
1770 installed simultaneously."""
1772 if "--buildpkgonly" in self.myopts or \
1773 "--nodeps" in self.myopts:
1777 for myroot in self.trees:
1779 modified_slots[myroot] = myslots
1780 final_db = self.mydbapi[myroot]
1781 slot_node_map = self._slot_node_map[myroot]
1782 for slot_atom, mynode in slot_node_map.iteritems():
1783 mytype, myroot, mycpv, mystatus = mynode
1784 if mystatus == "merge":
1785 myslots[slot_atom] = mycpv
1787 #if "deep" in self.myparams:
1789 # Pull in blockers from all installed packages that haven't already
1790 # been pulled into the depgraph. This is not enabled by default
1791 # due to the performance penalty that is incurred by all the
1792 # additional dep_check calls that are required.
1794 # Optimization hack for dep_check calls that minimizes the
1795 # available matches by replacing the portdb with a fakedbapi
1797 class FakePortageTree(object):
1798 def __init__(self, mydb):
1800 dep_check_trees = {}
1801 for myroot in self.trees:
1802 dep_check_trees[myroot] = self.trees[myroot].copy()
1803 dep_check_trees[myroot]["porttree"] = \
1804 FakePortageTree(self.mydbapi[myroot])
1806 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1807 for myroot in self.trees:
1808 pkg_node_map = self.pkg_node_map[myroot]
1809 vardb = self.trees[myroot]["vartree"].dbapi
1810 portdb = self.trees[myroot]["porttree"].dbapi
1811 pkgsettings = self.pkgsettings[myroot]
1812 final_db = self.mydbapi[myroot]
1813 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
1814 blocker_cache = BlockerCache(myroot, vardb)
1815 for pkg in cpv_all_installed:
1816 blocker_atoms = None
1817 matching_node = pkg_node_map.get(pkg, None)
1818 if matching_node and \
1819 matching_node[3] == "nomerge":
1821 # If this node has any blockers, create a "nomerge"
1822 # node for it so that they can be enforced.
1823 self.spinner.update()
1824 blocker_data = blocker_cache.get(pkg)
1826 blocker_atoms = blocker_data.atoms
1828 dep_vals = vardb.aux_get(pkg, dep_keys)
1829 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
1830 depstr = " ".join(dep_vals)
1831 # It is crucial to pass in final_db here in order to
1832 # optimize dep_check calls by eliminating atoms via
1833 # dep_wordreduce and dep_eval calls.
1835 portage.dep._dep_check_strict = False
1837 success, atoms = portage.dep_check(depstr,
1838 final_db, pkgsettings, myuse=myuse,
1839 trees=dep_check_trees, myroot=myroot)
1840 except Exception, e:
1841 if isinstance(e, SystemExit):
1843 # This is helpful, for example, if a ValueError
1844 # is thrown from cpv_expand due to multiple
1845 # matches (this can happen if an atom lacks a
1847 show_invalid_depstring_notice(
1848 ("installed", myroot, pkg, "nomerge"),
1853 portage.dep._dep_check_strict = True
1855 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
1856 vardb.aux_get(pkg, ["SLOT"])[0])
1857 if slot_atom in modified_slots[myroot]:
1858 # This package is being replaced anyway, so
1859 # ignore invalid dependencies so as not to
1860 # annoy the user too much (otherwise they'd be
1861 # forced to manually unmerge it first).
1863 show_invalid_depstring_notice(
1864 ("installed", myroot, pkg, "nomerge"),
1867 blocker_atoms = [myatom for myatom in atoms \
1868 if myatom.startswith("!")]
1869 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
1870 blocker_cache[pkg] = \
1871 blocker_cache.BlockerData(counter, blocker_atoms)
1873 # Don't store this parent in pkg_node_map, because it's
1874 # not needed there and it might overwrite a "merge"
1875 # node with the same cpv.
1876 myparent = ("installed", myroot, pkg, "nomerge")
1877 for myatom in blocker_atoms:
1878 blocker = ("blocks", myroot, myatom[1:])
1880 self.blocker_parents.get(blocker, None)
1883 self.blocker_parents[blocker] = myparents
1884 myparents.add(myparent)
1885 blocker_cache.flush()
1888 for blocker in self.blocker_parents.keys():
1889 mytype, myroot, mydep = blocker
1890 initial_db = self.trees[myroot]["vartree"].dbapi
1891 final_db = self.mydbapi[myroot]
1892 blocked_initial = initial_db.match(mydep)
1893 blocked_final = final_db.match(mydep)
1894 if not blocked_initial and not blocked_final:
1895 del self.blocker_parents[blocker]
1897 blocked_slots_initial = {}
1898 blocked_slots_final = {}
1899 for cpv in blocked_initial:
1900 blocked_slots_initial[cpv] = \
1901 "%s:%s" % (portage.dep_getkey(cpv),
1902 initial_db.aux_get(cpv, ["SLOT"])[0])
1903 for cpv in blocked_final:
1904 blocked_slots_final[cpv] = \
1905 "%s:%s" % (portage.dep_getkey(cpv),
1906 final_db.aux_get(cpv, ["SLOT"])[0])
1907 for parent in list(self.blocker_parents[blocker]):
1908 ptype, proot, pcpv, pstatus = parent
1909 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1910 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1911 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1912 parent_static = pslot_atom not in modified_slots[proot]
1913 unresolved_blocks = False
1914 depends_on_order = set()
1915 for cpv in blocked_initial:
1916 slot_atom = blocked_slots_initial[cpv]
1917 if slot_atom == pslot_atom:
1918 # TODO: Support blocks within slots in cases where it
1919 # might make sense. For example, a new version might
1920 # require that the old version be uninstalled at build
1923 if parent_static and \
1924 slot_atom not in modified_slots[myroot]:
1925 # This blocker will be handled the next time that a
1926 # merge of either package is triggered.
1928 if pstatus == "merge" and \
1929 slot_atom in modified_slots[myroot]:
1930 replacement = final_db.match(slot_atom)
1932 if not portage.match_from_list(mydep, replacement):
1933 # Apparently a replacement may be able to
1934 # invalidate this block.
1935 replacement_node = \
1936 self.pkg_node_map[proot][replacement[0]]
1937 depends_on_order.add((replacement_node, parent))
1939 # None of the above blocker resolutions techniques apply,
1940 # so apparently this one is unresolvable.
1941 unresolved_blocks = True
1942 for cpv in blocked_final:
1943 slot_atom = blocked_slots_final[cpv]
1944 if slot_atom == pslot_atom:
1945 # TODO: Support blocks within slots.
1947 if parent_static and \
1948 slot_atom not in modified_slots[myroot]:
1949 # This blocker will be handled the next time that a
1950 # merge of either package is triggered.
1952 if not parent_static and pstatus == "nomerge" and \
1953 slot_atom in modified_slots[myroot]:
1954 replacement = final_db.match(pslot_atom)
1956 replacement_node = \
1957 self.pkg_node_map[proot][replacement[0]]
1958 if replacement_node not in \
1959 self.blocker_parents[blocker]:
1960 # Apparently a replacement may be able to
1961 # invalidate this block.
1962 blocked_node = self.pkg_node_map[proot][cpv]
1963 depends_on_order.add(
1964 (replacement_node, blocked_node))
1966 # None of the above blocker resolutions techniques apply,
1967 # so apparently this one is unresolvable.
1968 unresolved_blocks = True
1969 if not unresolved_blocks and depends_on_order:
1970 for node, pnode in depends_on_order:
1971 # Enforce correct merge order with a hard dep.
1972 self.digraph.addnode(node, pnode,
1973 priority=DepPriority(buildtime=True))
1974 # Count references to this blocker so that it can be
1975 # invalidated after nodes referencing it have been
1977 self.blocker_digraph.addnode(node, blocker)
1978 if not unresolved_blocks and not depends_on_order:
1979 self.blocker_parents[blocker].remove(parent)
1980 if unresolved_blocks:
1981 self._unresolved_blocker_parents.setdefault(
1982 blocker, set()).add(parent)
1983 if not self.blocker_parents[blocker]:
1984 del self.blocker_parents[blocker]
1985 # Validate blockers that depend on merge order.
1986 if not self.blocker_digraph.empty():
1988 if self._slot_collision_info:
1989 # The user is only notified of a slot collision if there are no
1990 # unresolvable blocks.
1991 for x in self.altlist():
1992 if x[0] == "blocks":
1994 self._show_slot_collision_notice(self._slot_collision_info[0])
1995 if not self._accept_collisions():
1999 def _accept_collisions(self):
2001 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
2002 if x in self.myopts:
2007 def _merge_order_bias(self, mygraph):
2008 """Order nodes from highest to lowest overall reference count for
2009 optimal leaf node selection."""
2011 for node in mygraph.order:
2012 node_info[node] = len(mygraph.parent_nodes(node))
2013 def cmp_merge_preference(node1, node2):
2014 return node_info[node2] - node_info[node1]
2015 mygraph.order.sort(cmp_merge_preference)
2017 def altlist(self, reversed=False):
2018 if reversed in self._altlist_cache:
2019 return self._altlist_cache[reversed][:]
2021 retlist = self.altlist()
2023 self._altlist_cache[reversed] = retlist[:]
2025 mygraph=self.digraph.copy()
2026 self._merge_order_bias(mygraph)
2027 myblockers = self.blocker_digraph.copy()
2029 circular_blocks = False
2033 get_nodes = mygraph.root_nodes
2035 get_nodes = mygraph.leaf_nodes
2036 for cpv, node in self.pkg_node_map["/"].iteritems():
2037 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
2038 asap_nodes.append(node)
2040 ignore_priority_range = [None]
2041 ignore_priority_range.extend(
2042 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2043 tree_mode = "--tree" in self.myopts
2044 while not mygraph.empty():
2045 ignore_priority = None
2048 """ASAP nodes are merged before their soft deps."""
2049 for node in asap_nodes:
2050 if not mygraph.contains(node):
2051 asap_nodes.remove(node)
2053 if not mygraph.child_nodes(node,
2054 ignore_priority=DepPriority.SOFT):
2056 asap_nodes.remove(node)
2059 for ignore_priority in ignore_priority_range:
2060 nodes = get_nodes(ignore_priority=ignore_priority)
2063 selected_nodes = None
2065 if ignore_priority <= DepPriority.SOFT:
2066 if ignore_priority is None and not tree_mode:
2067 # Greedily pop all of these nodes since no relationship
2068 # has been ignored. This optimization destroys --tree
2069 # output, so it's disabled in reversed mode.
2070 selected_nodes = nodes
2072 # For optimal merge order:
2073 # * Only pop one node.
2074 # * Removing a root node (node without a parent)
2075 # will not produce a leaf node, so avoid it.
2077 if mygraph.parent_nodes(node):
2078 # found a non-root node
2079 selected_nodes = [node]
2081 if not selected_nodes:
2082 # settle for a root node
2083 selected_nodes = [nodes[0]]
2085 """Recursively gather a group of nodes that RDEPEND on
2086 eachother. This ensures that they are merged as a group
2087 and get their RDEPENDs satisfied as soon as possible."""
2088 def gather_deps(mergeable_nodes, selected_nodes, node):
2089 if node in selected_nodes:
2091 if node not in mergeable_nodes:
2093 selected_nodes.add(node)
2094 for child in mygraph.child_nodes(node,
2095 ignore_priority=DepPriority.SOFT):
2097 mergeable_nodes, selected_nodes, child):
2100 mergeable_nodes = set(nodes)
2102 selected_nodes = set()
2104 mergeable_nodes, selected_nodes, node):
2107 selected_nodes = None
2109 if not selected_nodes:
2110 if not myblockers.is_empty():
2111 """A blocker couldn't be circumnavigated while keeping all
2112 dependencies satisfied. The user will have to resolve this
2113 manually. This is a panic condition and thus the order
2114 doesn't really matter, so just pop a random node in order
2115 to avoid a circular dependency panic if possible."""
2116 if not circular_blocks:
2117 circular_blocks = True
2118 blocker_deps = myblockers.leaf_nodes()
2120 selected_nodes = [blocker_deps.pop()]
2122 if not selected_nodes:
2123 # No leaf nodes are available, so we have a circular
2124 # dependency panic situation. Reduce the noise level to a
2125 # minimum via repeated elimination of root nodes since they
2126 # have no parents and thus can not be part of a cycle.
2128 root_nodes = mygraph.root_nodes(
2129 ignore_priority=DepPriority.SOFT)
2132 for node in root_nodes:
2133 mygraph.remove(node)
2134 # Display the USE flags that are enabled on nodes that are part
2135 # of dependency cycles in case that helps the user decide to
2136 # disable some of them.
2138 tempgraph = mygraph.copy()
2139 while not tempgraph.empty():
2140 nodes = tempgraph.leaf_nodes()
2142 node = tempgraph.order[0]
2145 display_order.append(list(node))
2146 tempgraph.remove(node)
2147 display_order.reverse()
2148 self.myopts.pop("--quiet", None)
2149 self.myopts.pop("--verbose", None)
2150 self.myopts["--tree"] = True
2151 self.display(display_order)
2152 print "!!! Error: circular dependencies:"
2154 mygraph.debug_print()
2156 print "!!! Note that circular dependencies can often be avoided by temporarily"
2157 print "!!! disabling USE flags that trigger optional dependencies."
2160 for node in selected_nodes:
2161 retlist.append(list(node))
2162 mygraph.remove(node)
2163 if not reversed and not circular_blocks and myblockers.contains(node):
2164 """This node may have invalidated one or more blockers."""
2165 myblockers.remove(node)
2166 for blocker in myblockers.root_nodes():
2167 if not myblockers.child_nodes(blocker):
2168 myblockers.remove(blocker)
2170 self._unresolved_blocker_parents.get(blocker)
2172 self.blocker_parents[blocker] = unresolved
2174 del self.blocker_parents[blocker]
2177 """Blocker validation does not work with reverse mode,
2178 so self.altlist() should first be called with reverse disabled
2179 so that blockers are properly validated."""
2180 self.blocker_digraph = myblockers
2182 """ Add any unresolved blocks so that they can be displayed."""
2183 for blocker in self.blocker_parents:
2184 retlist.append(list(blocker))
2185 self._altlist_cache[reversed] = retlist[:]
2188 def xcreate(self,mode="system"):
2189 vardb = self.trees[self.target_root]["vartree"].dbapi
2190 portdb = self.trees[self.target_root]["porttree"].dbapi
2191 bindb = self.trees[self.target_root]["bintree"].dbapi
2192 def visible(mylist):
2193 matches = portdb.gvisible(portdb.visible(mylist))
2194 return [x for x in mylist \
2195 if x in matches or not portdb.cpv_exists(x)]
2196 world_problems = False
2198 mylist = getlist(self.settings, "system")
2201 worldlist = getlist(self.settings, "world")
2202 mylist = getlist(self.settings, "system")
2203 worlddict=genericdict(worldlist)
2205 for x in worlddict.keys():
2206 if not portage.isvalidatom(x):
2207 world_problems = True
2208 elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
2209 world_problems = True
2215 mykey = portage.dep_getkey(atom)
2217 newlist.append(atom)
2218 """Make sure all installed slots are updated when possible.
2219 Do this with --emptytree also, to ensure that all slots are
2222 for cpv in vardb.match(mykey):
2223 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2226 if "--usepkg" in self.myopts:
2227 mymatches = bindb.match(atom)
2228 if "--usepkgonly" not in self.myopts:
2229 mymatches = visible(mymatches)
2230 best_pkg = portage.best(mymatches)
2232 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2233 best_pkgs.append(("binary", best_pkg, best_slot))
2234 if "--usepkgonly" not in self.myopts:
2235 best_pkg = portage.best(portdb.match(atom))
2237 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2238 best_pkgs.append(("ebuild", best_pkg, best_slot))
2240 best_pkg = portage.best([x[1] for x in best_pkgs])
2241 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2242 best_slot = best_pkgs[0][2]
2243 myslots.add(best_slot)
2244 if len(myslots) > 1:
2245 for myslot in myslots:
2246 myslot_atom = "%s:%s" % (mykey, myslot)
2248 if "--usepkgonly" not in self.myopts and \
2249 self.trees[self.target_root][
2250 "porttree"].dbapi.match(myslot_atom):
2252 elif "--usepkg" in self.myopts:
2253 mymatches = bindb.match(myslot_atom)
2254 if "--usepkgonly" not in self.myopts:
2255 mymatches = visible(mymatches)
2259 newlist.append(myslot_atom)
2263 for mydep in mylist:
2265 if not self.select_dep(
2266 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2267 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2270 missing_atoms.append(mydep)
2272 if not self.validate_blockers():
2276 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2277 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2280 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2281 " Ebuilds for the following packages are either all"
2282 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2283 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2287 def display(self,mylist,verbosity=None):
2288 if verbosity is None:
2289 verbosity = ("--quiet" in self.myopts and 1 or \
2290 "--verbose" in self.myopts and 3 or 2)
2295 counters = PackageCounters()
2297 if verbosity == 1 and "--verbose" not in self.myopts:
2298 def create_use_string(*args):
2301 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2303 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2304 alphabetical=("--alphabetical" in self.myopts)):
2312 cur_iuse = set(cur_iuse)
2313 enabled_flags = cur_iuse.intersection(cur_use)
2314 removed_iuse = set(old_iuse).difference(cur_iuse)
2315 any_iuse = cur_iuse.union(old_iuse)
2316 any_iuse = list(any_iuse)
2318 for flag in any_iuse:
2321 if flag in enabled_flags:
2323 if is_new or flag in old_use and all_flags:
2324 flag_str = red(flag)
2325 elif flag not in old_iuse:
2326 flag_str = yellow(flag) + "%*"
2327 elif flag not in old_use:
2328 flag_str = green(flag) + "*"
2329 elif flag in removed_iuse:
2331 flag_str = yellow("-" + flag) + "%"
2334 flag_str = "(" + flag_str + ")"
2335 removed.append(flag_str)
2338 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2339 flag_str = blue("-" + flag)
2340 elif flag not in old_iuse:
2341 flag_str = yellow("-" + flag)
2342 if flag not in iuse_forced:
2344 elif flag in old_use:
2345 flag_str = green("-" + flag) + "*"
2347 if flag in iuse_forced:
2348 flag_str = "(" + flag_str + ")"
2350 enabled.append(flag_str)
2352 disabled.append(flag_str)
2355 ret = " ".join(enabled)
2357 ret = " ".join(enabled + disabled + removed)
2359 ret = '%s="%s" ' % (name, ret)
2363 # FIXME: account for the possibility of different overlays in
2364 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2365 overlays = self.settings["PORTDIR_OVERLAY"].split()
2366 overlays_real = [os.path.realpath(t) \
2367 for t in self.settings["PORTDIR_OVERLAY"].split()]
2371 mygraph = self._parent_child_digraph
2376 if "blocks" == x[0]:
2377 display_list.append((x, 0, True))
2379 graph_key = tuple(x)
2380 if "--tree" in self.myopts:
2381 depth = len(tree_nodes)
2382 while depth and graph_key not in \
2383 mygraph.child_nodes(tree_nodes[depth-1]):
2386 tree_nodes = tree_nodes[:depth]
2387 tree_nodes.append(graph_key)
2388 display_list.append((x, depth, True))
2389 shown_edges.add((graph_key, tree_nodes[depth-1]))
2391 traversed_nodes = set() # prevent endless circles
2392 traversed_nodes.add(graph_key)
2393 def add_parents(current_node, ordered):
2394 parent_nodes = mygraph.parent_nodes(current_node)
2396 child_nodes = set(mygraph.child_nodes(current_node))
2397 selected_parent = None
2398 # First, try to avoid a direct cycle.
2399 for node in parent_nodes:
2400 if node not in traversed_nodes and \
2401 node not in child_nodes:
2402 edge = (current_node, node)
2403 if edge in shown_edges:
2405 selected_parent = node
2407 if not selected_parent:
2408 # A direct cycle is unavoidable.
2409 for node in parent_nodes:
2410 if node not in traversed_nodes:
2411 edge = (current_node, node)
2412 if edge in shown_edges:
2414 selected_parent = node
2417 shown_edges.add((current_node, selected_parent))
2418 traversed_nodes.add(selected_parent)
2419 add_parents(selected_parent, False)
2420 display_list.append((list(current_node),
2421 len(tree_nodes), ordered))
2422 tree_nodes.append(current_node)
2424 add_parents(graph_key, True)
2426 display_list.append((x, depth, True))
2427 mylist = display_list
2429 last_merge_depth = 0
2430 for i in xrange(len(mylist)-1,-1,-1):
2431 graph_key, depth, ordered = mylist[i]
2432 if not ordered and depth == 0 and i > 0 \
2433 and graph_key == mylist[i-1][0] and \
2434 mylist[i-1][1] == 0:
2435 # An ordered node got a consecutive duplicate when the tree was
2439 if "blocks" == graph_key[0]:
2441 if ordered and graph_key[-1] != "nomerge":
2442 last_merge_depth = depth
2444 if depth >= last_merge_depth or \
2445 i < len(mylist) - 1 and \
2446 depth >= mylist[i+1][1]:
2449 display_overlays=False
2450 # files to fetch list - avoids counting a same file twice
2451 # in size display (verbose mode)
2453 for mylist_index in xrange(len(mylist)):
2454 x, depth, ordered = mylist[mylist_index]
2458 portdb = self.trees[myroot]["porttree"].dbapi
2459 bindb = self.trees[myroot]["bintree"].dbapi
2460 vardb = self.trees[myroot]["vartree"].dbapi
2461 vartree = self.trees[myroot]["vartree"]
2462 pkgsettings = self.pkgsettings[myroot]
2467 addl=""+red("B")+" "+fetch+" "
2469 counters.blocks += 1
2470 resolved = portage.key_expand(
2471 pkg_key, mydb=vardb, settings=pkgsettings)
2472 if "--columns" in self.myopts and "--quiet" in self.myopts:
2473 addl = addl + " " + red(resolved)
2475 addl = "[blocks " + addl + "] " + red(resolved)
2476 block_parents = self.blocker_parents[tuple(x)]
2477 block_parents = set([pnode[2] for pnode in block_parents])
2478 block_parents = ", ".join(block_parents)
2480 addl += bad(" (\"%s\" is blocking %s)") % \
2481 (pkg_key, block_parents)
2483 addl += bad(" (is blocking %s)") % block_parents
2484 blockers.append(addl)
2486 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2487 binary_package = True
2488 if "ebuild" == pkg_type:
2489 if "merge" == x[3] or \
2490 not vartree.dbapi.cpv_exists(pkg_key):
2491 """An ebuild "merge" node or a --onlydeps "nomerge"
2493 binary_package = False
2494 pkgsettings.setcpv(pkg_key, mydb=portdb)
2495 if pkg_key not in self.useFlags[myroot]:
2496 self.useFlags[myroot][pkg_key] = \
2497 pkgsettings["USE"].split()
2499 # An ebuild "nomerge" node, so USE come from the vardb.
2500 mydbapi = vartree.dbapi
2501 if pkg_key not in self.useFlags[myroot]:
2502 """If this is a --resume then the USE flags need to be
2503 fetched from the appropriate locations here."""
2504 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2505 pkg_key, ["USE"])[0].split()
2507 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2508 "fetch" in portdb.aux_get(
2509 x[2], ["RESTRICT"])[0].split():
2512 counters.restrict_fetch += 1
2513 if portdb.fetch_check(
2514 pkg_key, self.useFlags[myroot][pkg_key]):
2517 counters.restrict_fetch_satisfied += 1
2519 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2520 #param is used for -u, where you still *do* want to see when something is being upgraded.
2522 if vardb.cpv_exists(pkg_key):
2523 addl=" "+yellow("R")+fetch+" "
2524 if x[3] != "nomerge":
2526 counters.reinst += 1
2527 elif vardb.match(portage.dep_getkey(pkg_key)):
2528 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2529 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2530 portage.pkgsplit(x[2])[0])
2531 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2532 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2534 myoldbest=portage.best(myinslotlist)
2536 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2538 addl+=turquoise("U")+blue("D")
2540 counters.downgrades += 1
2543 addl+=turquoise("U")+" "
2545 counters.upgrades += 1
2547 # New slot, mark it new.
2548 addl=" "+green("NS")+fetch+" "
2550 counters.newslot += 1
2552 if "--changelog" in self.myopts:
2553 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2554 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2555 inst_matches = vardb.match(slot_atom)
2557 changelogs.extend(self.calc_changelog(
2558 portdb.findname(pkg_key),
2559 inst_matches[0], pkg_key))
2561 addl=" "+green("N")+" "+fetch+" "
2567 if pkg_key in self.useFlags[myroot]:
2569 cur_iuse = list(filter_iuse_defaults(
2570 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2572 forced_flags = set()
2573 if not binary_package:
2574 forced_flags.update(pkgsettings.useforce)
2575 forced_flags.update(pkgsettings.usemask)
2577 cur_iuse = portage.unique_array(cur_iuse)
2579 cur_use = self.useFlags[myroot][pkg_key]
2580 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2586 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2587 old_iuse, old_use = \
2588 self.trees[x[1]]["vartree"].dbapi.aux_get(
2589 pkg, ["IUSE", "USE"])
2590 old_iuse = list(set(
2591 filter_iuse_defaults(old_iuse.split())))
2593 old_use = old_use.split()
2600 old_use = [flag for flag in old_use if flag in old_iuse]
2602 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2604 use_expand.reverse()
2605 use_expand_hidden = \
2606 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2608 def map_to_use_expand(myvals, forcedFlags=False):
2611 for exp in use_expand:
2614 for val in myvals[:]:
2615 if val.startswith(exp.lower()+"_"):
2616 if val in forced_flags:
2617 forced[exp].add(val[len(exp)+1:])
2618 ret[exp].append(val[len(exp)+1:])
2621 forced["USE"] = [val for val in myvals \
2622 if val in forced_flags]
2623 for exp in use_expand_hidden:
2630 cur_iuse_map, iuse_forced = \
2631 map_to_use_expand(cur_iuse, forcedFlags=True)
2632 cur_use_map = map_to_use_expand(cur_use)
2633 old_iuse_map = map_to_use_expand(old_iuse)
2634 old_use_map = map_to_use_expand(old_use)
2637 use_expand.insert(0, "USE")
2639 for key in use_expand:
2640 if key in use_expand_hidden:
2642 verboseadd += create_use_string(key.upper(),
2643 cur_iuse_map[key], iuse_forced[key],
2644 cur_use_map[key], old_iuse_map[key],
2645 old_use_map[key], is_new)
2650 if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
2652 myfilesdict = portdb.getfetchsizes(pkg_key,
2653 useflags=self.useFlags[myroot][pkg_key],
2655 except portage.exception.InvalidDependString, e:
2656 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2657 show_invalid_depstring_notice(x, src_uri, str(e))
2660 if myfilesdict is None:
2661 myfilesdict="[empty/missing/bad digest]"
2663 for myfetchfile in myfilesdict.keys():
2664 if myfetchfile not in myfetchlist:
2665 mysize+=myfilesdict[myfetchfile]
2666 myfetchlist.append(myfetchfile)
2667 counters.totalsize += mysize
2668 verboseadd+=format_size(mysize)+" "
2671 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2672 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2673 file_name = portdb.findname(pkg_key)
2674 if file_name: # It might not exist in the tree
2675 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2676 if (overlays_real.count(dir_name)>0):
2677 verboseadd+=teal("["+str(overlays_real.index(
2678 os.path.normpath(dir_name))+1)+"]")+" "
2679 display_overlays=True
2681 verboseadd += "[No ebuild?]"
2683 xs=portage.pkgsplit(x[2])
2690 if "COLUMNWIDTH" in self.settings:
2692 mywidth = int(self.settings["COLUMNWIDTH"])
2693 except ValueError, e:
2694 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2696 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2697 self.settings["COLUMNWIDTH"], noiselevel=-1)
2702 indent = " " * depth
2705 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2706 if myoldbest[-3:]=="-r0":
2707 myoldbest=myoldbest[:-3]
2708 myoldbest=blue("["+myoldbest+"]")
2713 if "--columns" in self.myopts:
2714 if "--quiet" in self.myopts:
2715 myprint=addl+" "+indent+darkgreen(xs[0])
2716 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2717 myprint=myprint+myoldbest
2718 myprint=myprint+darkgreen("to "+x[1])
2720 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2721 if (newlp-nc_len(myprint)) > 0:
2722 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2723 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2724 if (oldlp-nc_len(myprint)) > 0:
2725 myprint=myprint+" "*(oldlp-nc_len(myprint))
2726 myprint=myprint+myoldbest
2727 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2729 if x[-1] == "nomerge" or not ordered:
2730 myprint = darkblue("[nomerge ] ")
2732 myprint = "[" + pkg_type + " " + addl + "] "
2733 myprint += indent + darkgreen(pkg_key) + " " + \
2734 myoldbest + darkgreen("to " + myroot) + " " + \
2737 if "--columns" in self.myopts:
2738 if "--quiet" in self.myopts:
2739 myprint=addl+" "+indent+darkgreen(xs[0])
2740 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2741 myprint=myprint+myoldbest
2743 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2744 if (newlp-nc_len(myprint)) > 0:
2745 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2746 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2747 if (oldlp-nc_len(myprint)) > 0:
2748 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2749 myprint=myprint+myoldbest+" "+verboseadd
2751 if x[-1] == "nomerge" or not ordered:
2752 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2754 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2757 mysplit = portage.pkgsplit(x[2])
2758 if "--tree" not in self.myopts and mysplit and \
2759 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2762 if mysplit[2] == "r0":
2763 myversion = mysplit[1]
2765 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2767 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2768 if mylist_index < len(mylist) - 1 and \
2769 "livecvsportage" not in self.settings.features:
2770 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2771 p.append(colorize("WARN", " then resume the merge."))
2783 if overlays and display_overlays:
2784 print "Portage overlays:"
2788 print " "+teal("["+str(y)+"]"),x
2790 if "--changelog" in self.myopts:
2792 for revision,text in changelogs:
2793 print bold('*'+revision)
2794 sys.stdout.write(text)
2796 if self._pprovided_args:
2798 msg.append(bad("\nWARNING: "))
2799 if len(self._pprovided_args) > 1:
2800 msg.append("Requested packages will not be " + \
2801 "merged because they are listed in\n")
2803 msg.append("A requested package will not be " + \
2804 "merged because it is listed in\n")
2805 msg.append(" package.provided:\n\n")
2806 for arg in self._pprovided_args:
2807 msg.append(" " + arg + "\n")
2809 sys.stderr.write("".join(msg))
2811 def calc_changelog(self,ebuildpath,current,next):
2812 current = '-'.join(portage.catpkgsplit(current)[1:])
2813 if current.endswith('-r0'): current = current[:-3]
2814 next = '-'.join(portage.catpkgsplit(next)[1:])
2815 if next.endswith('-r0'): next = next[:-3]
2816 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2818 changelog = open(changelogpath).read()
2819 except SystemExit, e:
2820 raise # Needed else can't exit
2823 divisions = self.find_changelog_tags(changelog)
2824 #print 'XX from',current,'to',next
2825 #for div,text in divisions: print 'XX',div
2826 # skip entries for all revisions above the one we are about to emerge
2827 for i in range(len(divisions)):
2828 if divisions[i][0]==next:
2829 divisions = divisions[i:]
2831 # find out how many entries we are going to display
2832 for i in range(len(divisions)):
2833 if divisions[i][0]==current:
2834 divisions = divisions[:i]
2837 # couldnt find the current revision in the list. display nothing
2841 def find_changelog_tags(self,changelog):
2845 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2847 if release is not None:
2848 divs.append((release,changelog))
2850 if release is not None:
2851 divs.append((release,changelog[:match.start()]))
2852 changelog = changelog[match.end():]
2853 release = match.group(1)
2854 if release.endswith('.ebuild'):
2855 release = release[:-7]
2856 if release.endswith('-r0'):
2857 release = release[:-3]
2860 return self.outdatedpackages
2862 class PackageCounters(object):
2872 self.restrict_fetch = 0
2873 self.restrict_fetch_satisfied = 0
2876 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2879 myoutput.append("Total: %s package" % total_installs)
2880 if total_installs != 1:
2881 myoutput.append("s")
2882 if total_installs != 0:
2883 myoutput.append(" (")
2884 if self.upgrades > 0:
2885 details.append("%s upgrade" % self.upgrades)
2886 if self.upgrades > 1:
2888 if self.downgrades > 0:
2889 details.append("%s downgrade" % self.downgrades)
2890 if self.downgrades > 1:
2893 details.append("%s new" % self.new)
2894 if self.newslot > 0:
2895 details.append("%s in new slot" % self.newslot)
2896 if self.newslot > 1:
2899 details.append("%s reinstall" % self.reinst)
2903 details.append("%s block" % self.blocks)
2906 myoutput.append(", ".join(details))
2907 if total_installs != 0:
2908 myoutput.append(")")
2909 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2910 if self.restrict_fetch:
2911 myoutput.append("\nFetch Restriction: %s package" % \
2912 self.restrict_fetch)
2913 if self.restrict_fetch > 1:
2914 myoutput.append("s")
2915 if self.restrict_fetch_satisfied < self.restrict_fetch:
2916 myoutput.append(bad(" (%s unsatisfied)") % \
2917 (self.restrict_fetch - self.restrict_fetch_satisfied))
2918 return "".join(myoutput)
2920 class MergeTask(object):
2922 def __init__(self, settings, trees, myopts):
2923 self.settings = settings
2924 self.target_root = settings["ROOT"]
2926 self.myopts = myopts
2928 if settings.get("PORTAGE_DEBUG", "") == "1":
2930 self.pkgsettings = {}
2931 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2932 if self.target_root != "/":
2933 self.pkgsettings["/"] = \
2934 portage.config(clone=trees["/"]["vartree"].settings)
2936 def merge(self, mylist, favorites, mtimedb):
2939 ldpath_mtimes = mtimedb["ldpath"]
2940 xterm_titles = "notitles" not in self.settings.features
2942 #check for blocking dependencies
2943 if "--fetchonly" not in self.myopts and \
2944 "--fetch-all-uri" not in self.myopts and \
2945 "--buildpkgonly" not in self.myopts:
2948 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2949 print "!!! the two packages cannot be installed on the same system together."
2950 print "!!! Please use 'emerge --pretend' to determine blockers."
2951 if "--quiet" not in self.myopts:
2952 show_blocker_docs_link()
2955 if "--resume" in self.myopts:
2957 print colorize("GOOD", "*** Resuming merge...")
2958 emergelog(xterm_titles, " *** Resuming merge...")
2959 mylist = mtimedb["resume"]["mergelist"][:]
2960 if "--skipfirst" in self.myopts and mylist:
2961 del mtimedb["resume"]["mergelist"][0]
2964 validate_merge_list(self.trees, mylist)
2965 mymergelist = mylist
2967 # Verify all the manifests now so that the user is notified of failure
2968 # as soon as possible.
2969 if "--fetchonly" not in self.myopts and \
2970 "--fetch-all-uri" not in self.myopts and \
2971 "strict" in self.settings.features:
2972 shown_verifying_msg = False
2974 for myroot, pkgsettings in self.pkgsettings.iteritems():
2975 quiet_config = portage.config(clone=pkgsettings)
2976 quiet_config["PORTAGE_QUIET"] = "1"
2977 quiet_config.backup_changes("PORTAGE_QUIET")
2978 quiet_settings[myroot] = quiet_config
2981 if x[0] != "ebuild" or x[-1] == "nomerge":
2983 if not shown_verifying_msg:
2984 shown_verifying_msg = True
2985 print ">>> Verifying ebuild Manifests..."
2986 mytype, myroot, mycpv, mystatus = x
2987 portdb = self.trees[myroot]["porttree"].dbapi
2988 quiet_config = quiet_settings[myroot]
2989 quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
2990 if not portage.digestcheck([], quiet_config, strict=True):
2992 del x, mytype, myroot, mycpv, mystatus, quiet_config
2993 del shown_verifying_msg, quiet_settings
2995 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
2996 mysysdict = genericdict(getlist(self.settings, "system"))
2997 if "--resume" not in self.myopts:
2998 myfavs = portage.grabfile(
2999 os.path.join(self.target_root, portage.WORLD_FILE))
3000 myfavdict=genericdict(myfavs)
3001 for x in range(len(mylist)):
3002 if mylist[x][3]!="nomerge":
3003 # Add to the mergelist
3004 mymergelist.append(mylist[x])
3006 myfavkey=portage.cpv_getkey(mylist[x][2])
3007 if "--onlydeps" in self.myopts:
3009 # Add to the world file. Since we won't be able to later.
3010 if "--fetchonly" not in self.myopts and \
3011 myfavkey in favorites:
3012 #don't record if already in system profile or already recorded
3013 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3014 #we don't have a favorites entry for this package yet; add one
3015 myfavdict[myfavkey]=myfavkey
3016 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3017 if not ("--fetchonly" in self.myopts or \
3018 "--fetch-all-uri" in self.myopts or \
3019 "--pretend" in self.myopts):
3020 portage.write_atomic(
3021 os.path.join(self.target_root, portage.WORLD_FILE),
3022 "\n".join(myfavdict.values()))
3024 mtimedb["resume"]["mergelist"]=mymergelist[:]
3027 myfeat = self.settings.features[:]
3028 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3030 if "parallel-fetch" in myfeat and \
3031 not ("--pretend" in self.myopts or \
3032 "--fetch-all-uri" in self.myopts or \
3033 "--fetchonly" in self.myopts):
3034 if "distlocks" not in myfeat:
3036 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
3037 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
3039 elif len(mymergelist) > 1:
3040 print ">>> starting parallel fetching"
3041 fetch_log = "/var/log/emerge-fetch.log"
3042 logfile = open(fetch_log, "w")
3043 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3044 portage.util.apply_secpass_permissions(fetch_log,
3045 uid=portage.portage_uid, gid=portage.portage_gid,
3047 fetch_env = os.environ.copy()
3048 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3049 fetch_env["PORTAGE_NICENESS"] = "0"
3050 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3051 resume_opts = self.myopts.copy()
3052 # For automatic resume, we need to prevent
3053 # any of bad_resume_opts from leaking in
3054 # via EMERGE_DEFAULT_OPTS.
3055 resume_opts["--ignore-default-opts"] = True
3056 for myopt, myarg in resume_opts.iteritems():
3057 if myopt not in bad_resume_opts:
3059 fetch_args.append(myopt)
3061 fetch_args.append(myopt +"="+ myarg)
3062 portage.process.spawn(fetch_args, env=fetch_env,
3063 fd_pipes=fd_pipes, returnpid=True)
3064 logfile.close() # belongs to the spawned process
3065 del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3069 for x in mymergelist:
3074 portdb = self.trees[myroot]["porttree"].dbapi
3075 bindb = self.trees[myroot]["bintree"].dbapi
3076 vartree = self.trees[myroot]["vartree"]
3077 pkgsettings = self.pkgsettings[myroot]
3080 y = portdb.findname(pkg_key)
3081 if "--pretend" not in self.myopts:
3082 print "\n>>> Emerging (" + \
3083 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3084 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3085 colorize("GOOD", x[pkgindex]) + " to " + x[1]
3086 emergelog(xterm_titles, " >>> emerge ("+\
3087 str(mergecount)+" of "+str(len(mymergelist))+\
3088 ") "+x[pkgindex]+" to "+x[1])
3090 pkgsettings["EMERGE_FROM"] = x[0]
3091 pkgsettings.backup_changes("EMERGE_FROM")
3094 #buildsyspkg: Check if we need to _force_ binary package creation
3095 issyspkg = ("buildsyspkg" in myfeat) \
3096 and x[0] != "blocks" \
3097 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3098 and "--buildpkg" not in self.myopts
3099 if x[0] in ["ebuild","blocks"]:
3100 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3101 raise Exception, "Merging a blocker"
3102 elif "--fetchonly" in self.myopts or \
3103 "--fetch-all-uri" in self.myopts:
3104 if "--fetch-all-uri" in self.myopts:
3105 retval = portage.doebuild(y, "fetch", myroot,
3106 pkgsettings, self.edebug,
3107 "--pretend" in self.myopts, fetchonly=1,
3108 fetchall=1, mydbapi=portdb, tree="porttree")
3110 retval = portage.doebuild(y, "fetch", myroot,
3111 pkgsettings, self.edebug,
3112 "--pretend" in self.myopts, fetchonly=1,
3113 mydbapi=portdb, tree="porttree")
3114 if (retval is None) or retval:
3116 print "!!! Fetch for",y,"failed, continuing..."
3118 failed_fetches.append(pkg_key)
3121 portage.doebuild_environment(y, "setup", myroot,
3122 pkgsettings, self.edebug, 1, portdb)
3123 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3124 portage.util.ensure_dirs(os.path.dirname(catdir),
3125 uid=portage.portage_uid, gid=portage.portage_gid,
3127 builddir_lock = None
3130 catdir_lock = portage.locks.lockdir(catdir)
3131 portage.util.ensure_dirs(catdir,
3132 uid=portage.portage_uid, gid=portage.portage_gid,
3134 builddir_lock = portage.locks.lockdir(
3135 pkgsettings["PORTAGE_BUILDDIR"])
3137 portage.locks.unlockdir(catdir_lock)
3140 msg = " === (%s of %s) Cleaning (%s::%s)" % \
3141 (mergecount, len(mymergelist), pkg_key, y)
3142 short_msg = "emerge: (%s of %s) %s Clean" % \
3143 (mergecount, len(mymergelist), pkg_key)
3144 emergelog(xterm_titles, msg, short_msg=short_msg)
3145 retval = portage.doebuild(y, "clean", myroot,
3146 pkgsettings, self.edebug, cleanup=1,
3147 mydbapi=portdb, tree="porttree")
3148 if retval != os.EX_OK:
3150 if "--buildpkg" in self.myopts or issyspkg:
3152 print ">>> This is a system package, " + \
3153 "let's pack a rescue tarball."
3154 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3155 (mergecount, len(mymergelist), pkg_key, y)
3156 short_msg = "emerge: (%s of %s) %s Compile" % \
3157 (mergecount, len(mymergelist), pkg_key)
3158 emergelog(xterm_titles, msg, short_msg=short_msg)
3159 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3160 binpkg_tmpfile = os.path.join(pkgsettings["PKGDIR"],
3161 pkg_key + ".tbz2." + str(os.getpid()))
3162 pkgsettings["PORTAGE_BINPKG_TMPFILE"] = binpkg_tmpfile
3163 pkgsettings.backup_changes("PORTAGE_BINPKG_TMPFILE")
3164 retval = portage.doebuild(y, "package", myroot,
3165 pkgsettings, self.edebug, mydbapi=portdb,
3167 del pkgsettings["PORTAGE_BINPKG_TMPFILE"]
3168 if retval != os.EX_OK:
3170 bintree = self.trees[myroot]["bintree"]
3171 bintree.inject(pkg_key, filename=binpkg_tmpfile)
3172 if "--buildpkgonly" not in self.myopts:
3173 msg = " === (%s of %s) Merging (%s::%s)" % \
3174 (mergecount, len(mymergelist), pkg_key, y)
3175 short_msg = "emerge: (%s of %s) %s Merge" % \
3176 (mergecount, len(mymergelist), pkg_key)
3177 emergelog(xterm_titles, msg, short_msg=short_msg)
3178 retval = portage.merge(pkgsettings["CATEGORY"],
3179 pkgsettings["PF"], pkgsettings["D"],
3180 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3181 "build-info"), myroot, pkgsettings,
3182 myebuild=pkgsettings["EBUILD"],
3183 mytree="porttree", mydbapi=portdb,
3184 vartree=vartree, prev_mtimes=ldpath_mtimes)
3185 if retval != os.EX_OK:
3187 elif "noclean" not in pkgsettings.features:
3188 portage.doebuild(y, "clean", myroot,
3189 pkgsettings, self.edebug, mydbapi=portdb,
3192 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3193 (mergecount, len(mymergelist), pkg_key, y)
3194 short_msg = "emerge: (%s of %s) %s Compile" % \
3195 (mergecount, len(mymergelist), pkg_key)
3196 emergelog(xterm_titles, msg, short_msg=short_msg)
3197 retval = portage.doebuild(y, "merge", myroot,
3198 pkgsettings, self.edebug, vartree=vartree,
3199 mydbapi=portdb, tree="porttree",
3200 prev_mtimes=ldpath_mtimes)
3201 if retval != os.EX_OK:
3205 portage.locks.unlockdir(builddir_lock)
3208 # Lock catdir for removal if empty.
3209 catdir_lock = portage.locks.lockdir(catdir)
3215 if e.errno not in (errno.ENOENT,
3216 errno.ENOTEMPTY, errno.EEXIST):
3219 portage.locks.unlockdir(catdir_lock)
3221 elif x[0]=="binary":
3223 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3224 if "--getbinpkg" in self.myopts:
3227 if "distlocks" in pkgsettings.features and \
3228 os.access(pkgsettings["PKGDIR"], os.W_OK):
3229 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3230 tbz2_lock = portage.locks.lockfile(mytbz2,
3232 if self.trees[myroot]["bintree"].isremote(pkg_key):
3233 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3234 (mergecount, len(mymergelist), pkg_key, mytbz2)
3235 short_msg = "emerge: (%s of %s) %s Fetch" % \
3236 (mergecount, len(mymergelist), pkg_key)
3237 emergelog(xterm_titles, msg, short_msg=short_msg)
3238 if not self.trees[myroot]["bintree"].gettbz2(
3243 portage.locks.unlockfile(tbz2_lock)
3245 if "--fetchonly" in self.myopts or \
3246 "--fetch-all-uri" in self.myopts:
3249 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3250 emergelog(xterm_titles, " === ("+str(mergecount)+\
3251 " of "+str(len(mymergelist))+") Merging Binary ("+\
3252 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3253 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3255 vartree=self.trees[myroot]["vartree"],
3256 prev_mtimes=ldpath_mtimes)
3257 if retval != os.EX_OK:
3259 #need to check for errors
3260 if "--buildpkgonly" not in self.myopts:
3261 self.trees[x[1]]["vartree"].inject(x[2])
3262 myfavkey=portage.cpv_getkey(x[2])
3263 if "--fetchonly" not in self.myopts and \
3264 "--fetch-all-uri" not in self.myopts and \
3265 myfavkey in favorites:
3266 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3267 myfavdict=genericdict(myfavs)
3268 #don't record if already in system profile or already recorded
3269 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3270 #we don't have a favorites entry for this package yet; add one
3271 myfavdict[myfavkey]=myfavkey
3272 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3273 emergelog(xterm_titles, " === ("+\
3274 str(mergecount)+" of "+\
3275 str(len(mymergelist))+\
3276 ") Updating world file ("+x[pkgindex]+")")
3277 portage.write_atomic(
3278 os.path.join(myroot, portage.WORLD_FILE),
3279 "\n".join(myfavdict.values()))
3281 if "--pretend" not in self.myopts and \
3282 "--fetchonly" not in self.myopts and \
3283 "--fetch-all-uri" not in self.myopts:
3284 # Clean the old package that we have merged over top of it.
3285 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3286 xsplit=portage.pkgsplit(x[2])
3287 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3288 retval = unmerge(pkgsettings, self.myopts, vartree,
3289 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3291 emergelog(xterm_titles,
3292 " --- AUTOCLEAN: Nothing unmerged.")
3294 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3295 + " AUTOCLEAN is disabled. This can cause serious"
3296 + " problems due to overlapping packages.\n")
3298 # Figure out if we need a restart.
3299 mysplit=portage.pkgsplit(x[2])
3300 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3301 myver=mysplit[1]+"-"+mysplit[2]
3302 if myver[-3:]=='-r0':
3304 if (myver != portage.VERSION) and \
3305 "livecvsportage" not in self.settings.features:
3306 if len(mymergelist) > mergecount:
3307 emergelog(xterm_titles,
3308 " ::: completed emerge ("+ \
3309 str(mergecount)+" of "+ \
3310 str(len(mymergelist))+") "+ \
3312 emergelog(xterm_titles, " *** RESTARTING " + \
3313 "emerge via exec() after change of " + \
3315 del mtimedb["resume"]["mergelist"][0]
3317 portage.run_exitfuncs()
3318 mynewargv=[sys.argv[0],"--resume"]
3319 resume_opts = self.myopts.copy()
3320 # For automatic resume, we need to prevent
3321 # any of bad_resume_opts from leaking in
3322 # via EMERGE_DEFAULT_OPTS.
3323 resume_opts["--ignore-default-opts"] = True
3324 for myopt, myarg in resume_opts.iteritems():
3325 if myopt not in bad_resume_opts:
3327 mynewargv.append(myopt)
3329 mynewargv.append(myopt +"="+ myarg)
3330 # priority only needs to be adjusted on the first run
3331 os.environ["PORTAGE_NICENESS"] = "0"
3332 os.execv(mynewargv[0], mynewargv)
3334 if "--pretend" not in self.myopts and \
3335 "--fetchonly" not in self.myopts and \
3336 "--fetch-all-uri" not in self.myopts:
3337 if "noclean" not in self.settings.features:
3338 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3339 (mergecount, len(mymergelist), x[pkgindex])
3340 emergelog(xterm_titles, (" === (%s of %s) " + \
3341 "Post-Build Cleaning (%s::%s)") % \
3342 (mergecount, len(mymergelist), x[pkgindex], y),
3343 short_msg=short_msg)
3344 emergelog(xterm_titles, " ::: completed emerge ("+\
3345 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3348 # Unsafe for parallel merges
3349 del mtimedb["resume"]["mergelist"][0]
3350 # Commit after each merge so that --resume may still work in
3351 # in the event that portage is not allowed to exit normally
3352 # due to power failure, SIGKILL, etc...
3355 if "--pretend" not in self.myopts:
3356 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3358 # We're out of the loop... We're done. Delete the resume data.
3359 if mtimedb.has_key("resume"):
3360 del mtimedb["resume"]
3363 #by doing an exit this way, --fetchonly can continue to try to
3364 #fetch everything even if a particular download fails.
3365 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3367 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3368 "encountered. Please see above for details.\n\n")
3369 for cpv in failed_fetches:
3370 sys.stderr.write(" ")
3371 sys.stderr.write(cpv)
3372 sys.stderr.write("\n")
3373 sys.stderr.write("\n")
3379 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3380 ldpath_mtimes, autoclean=0):
3381 candidate_catpkgs=[]
3383 xterm_titles = "notitles" not in settings.features
3385 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3387 # At least the parent needs to exist for the lock file.
3388 portage.util.ensure_dirs(vdb_path)
3389 except portage.exception.PortageException:
3393 if os.access(vdb_path, os.W_OK):
3394 vdb_lock = portage.locks.lockdir(vdb_path)
3395 realsyslist = getlist(settings, "system")
3397 for x in realsyslist:
3398 mycp = portage.dep_getkey(x)
3399 if mycp in settings.getvirtuals():
3401 for provider in settings.getvirtuals()[mycp]:
3402 if vartree.dbapi.match(provider):
3403 providers.append(provider)
3404 if len(providers) == 1:
3405 syslist.extend(providers)
3407 syslist.append(mycp)
3409 mysettings = portage.config(clone=settings)
3411 if not unmerge_files or "world" in unmerge_files or \
3412 "system" in unmerge_files:
3413 if "unmerge"==unmerge_action:
3415 print bold("emerge unmerge") + " can only be used with " + \
3416 "specific package names, not with "+bold("world")+" or"
3417 print bold("system")+" targets."
3424 # process all arguments and add all
3425 # valid db entries to candidate_catpkgs
3427 if not unmerge_files or "world" in unmerge_files:
3428 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3429 elif "system" in unmerge_files:
3430 candidate_catpkgs.extend(getlist(settings, "system"))
3432 #we've got command-line arguments
3433 if not unmerge_files:
3434 print "\nNo packages to unmerge have been provided.\n"
3436 for x in unmerge_files:
3437 arg_parts = x.split('/')
3438 if x[0] not in [".","/"] and \
3439 arg_parts[-1][-7:] != ".ebuild":
3440 #possible cat/pkg or dep; treat as such
3441 candidate_catpkgs.append(x)
3442 elif unmerge_action in ["prune","clean"]:
3443 print "\n!!! Prune and clean do not accept individual" + \
3444 " ebuilds as arguments;\n skipping.\n"
3447 # it appears that the user is specifying an installed
3448 # ebuild and we're in "unmerge" mode, so it's ok.
3449 if not os.path.exists(x):
3450 print "\n!!! The path '"+x+"' doesn't exist.\n"
3453 absx = os.path.abspath(x)
3454 sp_absx = absx.split("/")
3455 if sp_absx[-1][-7:] == ".ebuild":
3457 absx = "/".join(sp_absx)
3459 sp_absx_len = len(sp_absx)
3461 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3462 vdb_len = len(vdb_path)
3464 sp_vdb = vdb_path.split("/")
3465 sp_vdb_len = len(sp_vdb)
3467 if not os.path.exists(absx+"/CONTENTS"):
3468 print "!!! Not a valid db dir: "+str(absx)
3471 if sp_absx_len <= sp_vdb_len:
3472 # The Path is shorter... so it can't be inside the vdb.
3475 print "\n!!!",x,"cannot be inside "+ \
3476 vdb_path+"; aborting.\n"
3479 for idx in range(0,sp_vdb_len):
3480 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3483 print "\n!!!", x, "is not inside "+\
3484 vdb_path+"; aborting.\n"
3487 print "="+"/".join(sp_absx[sp_vdb_len:])
3488 candidate_catpkgs.append(
3489 "="+"/".join(sp_absx[sp_vdb_len:]))
3492 if (not "--quiet" in myopts):
3494 if settings["ROOT"] != "/":
3495 print darkgreen(newline+ \
3496 ">>> Using system located in ROOT tree "+settings["ROOT"])
3497 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3498 not ("--quiet" in myopts):
3499 print darkgreen(newline+\
3500 ">>> These are the packages that would be unmerged:")
3504 for x in candidate_catpkgs:
3505 # cycle through all our candidate deps and determine
3506 # what will and will not get unmerged
3508 mymatch=localtree.dep_match(x)
3511 except ValueError, errpkgs:
3512 print "\n\n!!! The short ebuild name \"" + \
3513 x + "\" is ambiguous. Please specify"
3514 print "!!! one of the following fully-qualified " + \
3515 "ebuild names instead:\n"
3516 for i in errpkgs[0]:
3517 print " " + green(i)
3521 if not mymatch and x[0] not in "<>=~":
3522 #add a "=" if missing
3523 mymatch=localtree.dep_match("="+x)
3525 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3526 (x, unmerge_action), noiselevel=-1)
3528 mykey = portage.key_expand(
3530 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3531 if not pkgmap.has_key(mykey):
3532 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3533 if unmerge_action=="unmerge":
3535 if y not in pkgmap[mykey]["selected"]:
3536 pkgmap[mykey]["selected"].append(y)
3537 numselected=numselected+len(mymatch)
3540 #unmerge_action in ["prune", clean"]
3542 for mypkg in mymatch:
3543 if unmerge_action=="clean":
3544 myslot=localtree.getslot(mypkg)
3546 # since we're pruning, we don't care about slots
3547 # and put all the pkgs in together
3549 if not slotmap.has_key(myslot):
3551 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3552 for myslot in slotmap.keys():
3553 counterkeys=slotmap[myslot].keys()
3558 pkgmap[mykey]["protected"].append(
3559 slotmap[myslot][counterkeys[-1]])
3561 #be pretty and get them in order of merge:
3562 for ckey in counterkeys:
3563 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
3564 numselected=numselected+1
3565 # ok, now the last-merged package
3566 # is protected, and the rest are selected
3567 if global_unmerge and not numselected:
3568 portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
3572 portage.writemsg_stdout(
3573 "\n>>> No packages selected for removal by " + \
3574 unmerge_action + "\n")
3578 portage.locks.unlockdir(vdb_lock)
3579 for x in pkgmap.keys():
3580 for y in localtree.dep_match(x):
3581 if y not in pkgmap[x]["omitted"] and \
3582 y not in pkgmap[x]["selected"] and \
3583 y not in pkgmap[x]["protected"]:
3584 pkgmap[x]["omitted"].append(y)
3585 if global_unmerge and not pkgmap[x]["selected"]:
3586 #avoid cluttering the preview printout with stuff that isn't getting unmerged
3588 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
3589 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
3590 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
3591 if "--pretend" not in myopts and "--ask" not in myopts:
3592 countdown(int(settings["EMERGE_WARNING_DELAY"]),
3593 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3594 print "\n "+white(x)
3595 for mytype in ["selected","protected","omitted"]:
3596 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
3597 if pkgmap[x][mytype]:
3598 for mypkg in pkgmap[x][mytype]:
3599 mysplit=portage.catpkgsplit(mypkg)
3600 if mysplit[3]=="r0":
3601 myversion=mysplit[2]
3603 myversion=mysplit[2]+"-"+mysplit[3]
3604 if mytype=="selected":
3605 portage.writemsg_stdout(
3606 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
3608 portage.writemsg_stdout(
3609 colorize("GOOD", myversion + " "), noiselevel=-1)
3611 portage.writemsg_stdout("none", noiselevel=-1)
3612 portage.writemsg_stdout("\n", noiselevel=-1)
3614 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3615 " packages are slated for removal.\n")
3616 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
3617 " and " + colorize("GOOD", "'omitted'") + \
3618 " packages will not be removed.\n\n")
3620 if "--pretend" in myopts:
3621 #we're done... return
3623 if "--ask" in myopts:
3624 if userquery("Would you like to unmerge these packages?")=="No":
3625 # enter pretend mode for correct formatting of results
3626 myopts["--pretend"] = True
3631 #the real unmerging begins, after a short delay....
3633 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3635 for x in pkgmap.keys():
3636 for y in pkgmap[x]["selected"]:
3637 print ">>> Unmerging "+y+"..."
3638 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3639 mysplit=y.split("/")
3641 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3642 mysettings, unmerge_action not in ["clean","prune"],
3643 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3644 if retval != os.EX_OK:
3645 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3646 ebuild = vartree.dbapi.findname(y)
3647 show_unmerge_failure_message(y, ebuild, retval)
3650 clean_world(vartree.dbapi, y)
3651 emergelog(xterm_titles, " >>> unmerge success: "+y)
3654 def show_unmerge_failure_message(pkg, ebuild, retval):
3656 from formatter import AbstractFormatter, DumbWriter
3657 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3660 msg.append("A removal phase of the '%s' package " % pkg)
3661 msg.append("has failed with exit value %s. " % retval)
3662 msg.append("The problem occurred while executing ")
3663 msg.append("the ebuild located at '%s'. " % ebuild)
3664 msg.append("If necessary, manually remove the ebuild " )
3665 msg.append("in order to skip the execution of removal phases.")
3669 f.add_flowing_data(x)
3673 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3675 if os.path.exists("/usr/bin/install-info"):
3680 inforoot=normpath(root+z)
3681 if os.path.isdir(inforoot):
3682 infomtime = long(os.stat(inforoot).st_mtime)
3683 if inforoot not in prev_mtimes or \
3684 prev_mtimes[inforoot] != infomtime:
3685 regen_infodirs.append(inforoot)
3687 if not regen_infodirs:
3688 portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
3690 portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
3694 for inforoot in regen_infodirs:
3697 for filename in ("dir", "dir.gz", "dir.bz2"):
3698 file_path = os.path.join(inforoot, filename)
3700 os.rename(file_path, file_path + ".old")
3702 if e.errno != errno.ENOENT:
3706 if not os.path.isdir(inforoot):
3709 file_list = os.listdir(inforoot)
3712 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3714 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3715 existsstr="already exists, for file `"
3717 if re.search(existsstr,myso):
3718 # Already exists... Don't increment the count for this.
3720 elif myso[:44]=="install-info: warning: no info dir entry in ":
3721 # This info file doesn't contain a DIR-header: install-info produces this
3722 # (harmless) warning (the --quiet switch doesn't seem to work).
3723 # Don't increment the count for this.
3727 errmsg += myso + "\n"
3730 #update mtime so we can potentially avoid regenerating.
3731 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3734 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3737 print " "+green("*")+" Processed",icount,"info files."
3740 def display_news_notification(settings):
3741 target_root = settings["ROOT"]
3742 NEWS_PATH = os.path.join("metadata", "news")
3743 UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
3744 porttree = portdbapi(porttree_root=settings["PORTDIR"], mysettings=settings)
3745 newsReaderDisplay = False
3747 for repo in porttree.getRepositories():
3748 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3750 if not newsReaderDisplay:
3751 newsReaderDisplay = True
3753 print colorize("WARN", " * IMPORTANT:"),
3754 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3757 if newsReaderDisplay:
3758 print colorize("WARN", " *"),
3759 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3762 def post_emerge(settings, mtimedb, retval):
3764 Misc. things to run at the end of a merge session.
3770 Display preserved libs warnings
3773 @param settings: Configuration settings (typically portage.settings)
3774 @type settings: portage.config()
3775 @param mtimedb: The mtimeDB to store data needed across merge invocations
3776 @type mtimedb: MtimeDB class instance
3777 @param retval: Emerge's return value
3781 1. Calls sys.exit(retval)
3783 target_root = settings["ROOT"]
3784 info_mtimes = mtimedb["info"]
3786 # Load the most current variables from ${ROOT}/etc/profile.env
3788 settings.regenerate()
3791 config_protect = settings.get("CONFIG_PROTECT","").split()
3792 infodirs = settings.get("INFOPATH","").split(":") + \
3793 settings.get("INFODIR","").split(":")
3797 emergelog("notitles" not in settings.features,
3798 " *** exiting successfully.")
3800 if "noinfo" not in settings.features:
3801 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3803 chk_updated_cfg_files(target_root, config_protect)
3805 display_news_notification(settings)
3807 from portage.dbapi.vartree import PreservedLibsRegistry
3808 plib_registry = PreservedLibsRegistry(os.path.join(target_root, CACHE_PATH, "preserved_libs_registry"))
3809 if plib_registry.hasEntries():
3810 print colorize("WARN", "!!!") + " existing preserved libs:"
3811 plibdata = plib_registry.getPreservedLibs()
3812 for cpv in plibdata.keys():
3813 print colorize("WARN", ">>>") + " package: %s" % cpv
3814 for f in plibdata[cpv]:
3815 print colorize("WARN", " * ") + " - %s" % f
3816 print "Use " + colorize("GOOD", "revdep-rebuild") + " to rebuild packages using these libraries"
3817 print "and then remerge the packages listed above."
3823 def chk_updated_cfg_files(target_root, config_protect):
3825 #number of directories with some protect files in them
3827 for x in config_protect:
3828 x = os.path.join(target_root, x.lstrip(os.path.sep))
3830 mymode = os.lstat(x).st_mode
3833 if stat.S_ISDIR(mymode):
3834 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3836 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3837 os.path.split(x.rstrip(os.path.sep))
3838 a = commands.getstatusoutput(mycommand + \
3839 " ! -iname '.*~' ! -iname '.*.bak'")
3841 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3843 files = a[1].split()
3846 print colorize("WARN", " * IMPORTANT:"),
3847 if stat.S_ISDIR(mymode):
3848 print "%d config files in '%s' need updating." % \
3851 print "config file '%s' needs updating." % x
3854 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3855 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3857 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3859 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3860 Returns the number of unread (yet relevent) items.
3872 1. The number of unread but relevant news items.
3875 from portage.news import NewsManager
3876 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3877 return manager.getUnreadItems( repo_id, update=True )
3879 def is_valid_package_atom(x):
3881 testkey = portage.dep_getkey(x)
3882 except portage.exception.InvalidData:
3884 if testkey.startswith("null/"):
3885 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3890 return portage.isvalidatom(testatom)
3892 def validate_merge_list(trees, mergelist):
3893 """Validate the list to make sure all the packages are still available.
3894 This is needed for --resume."""
3895 for (pkg_type, myroot, pkg_key, action) in mergelist:
3896 if pkg_type == "binary" and \
3897 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3898 pkg_type == "ebuild" and \
3899 not trees[myroot]["porttree"].dbapi.xmatch(
3900 "match-all", "="+pkg_key):
3901 print red("!!! Error: The resume list contains packages that are no longer")
3902 print red("!!! available to be emerged. Please restart/continue")
3903 print red("!!! the merge operation manually.")
3906 def show_blocker_docs_link():
3908 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3909 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3911 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3914 def action_sync(settings, trees, mtimedb, myopts, myaction):
3915 xterm_titles = "notitles" not in settings.features
3916 emergelog(xterm_titles, " === sync")
3917 myportdir = settings.get("PORTDIR", None)
3919 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3921 if myportdir[-1]=="/":
3922 myportdir=myportdir[:-1]
3923 if not os.path.exists(myportdir):
3924 print ">>>",myportdir,"not found, creating it."
3925 os.makedirs(myportdir,0755)
3926 syncuri=settings["SYNC"].rstrip()
3928 updatecache_flg = False
3929 if myaction == "metadata":
3930 print "skipping sync"
3931 updatecache_flg = True
3932 tmpservertimestampfile = None
3933 elif syncuri[:8]=="rsync://":
3934 if not os.path.exists("/usr/bin/rsync"):
3935 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3936 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3941 import shlex, StringIO
3942 if settings["PORTAGE_RSYNC_OPTS"] == "":
3943 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3945 "--recursive", # Recurse directories
3946 "--links", # Consider symlinks
3947 "--safe-links", # Ignore links outside of tree
3948 "--perms", # Preserve permissions
3949 "--times", # Preserive mod times
3950 "--compress", # Compress the data transmitted
3951 "--force", # Force deletion on non-empty dirs
3952 "--whole-file", # Don't do block transfers, only entire files
3953 "--delete", # Delete files that aren't in the master tree
3954 "--delete-after", # Delete only after everything else is done
3955 "--stats", # Show final statistics about what was transfered
3956 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3957 "--exclude=/distfiles", # Exclude distfiles from consideration
3958 "--exclude=/local", # Exclude local from consideration
3959 "--exclude=/packages", # Exclude packages from consideration
3960 "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
3964 # The below validation is not needed when using the above hardcoded
3967 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3968 lexer = shlex.shlex(StringIO.StringIO(
3969 settings.get("PORTAGE_RSYNC_OPTS","")), posix=True)
3970 lexer.whitespace_split = True
3971 rsync_opts.extend(lexer)
3974 for opt in ("--recursive", "--times"):
3975 if opt not in rsync_opts:
3976 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3977 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3978 rsync_opts.append(opt)
3980 for exclude in ("distfiles", "local", "packages"):
3981 opt = "--exclude=/%s" % exclude
3982 if opt not in rsync_opts:
3983 portage.writemsg(yellow("WARNING:") + \
3984 " adding required option %s not included in " % opt + \
3985 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3986 rsync_opts.append(opt)
3988 if settings["RSYNC_TIMEOUT"] != "":
3989 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3990 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3992 mytimeout = int(settings["RSYNC_TIMEOUT"])
3993 rsync_opts.append("--timeout=%d" % mytimeout)
3994 except ValueError, e:
3995 portage.writemsg("!!! %s\n" % str(e))
3997 # TODO: determine options required for official servers
3998 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
4000 def rsync_opt_startswith(opt_prefix):
4001 for x in rsync_opts:
4002 if x.startswith(opt_prefix):
4006 if not rsync_opt_startswith("--timeout="):
4007 rsync_opts.append("--timeout=%d" % mytimeout)
4009 for opt in ("--compress", "--whole-file"):
4010 if opt not in rsync_opts:
4011 portage.writemsg(yellow("WARNING:") + " adding required option " + \
4012 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4013 rsync_opts.append(opt)
4015 if "--quiet" in myopts:
4016 rsync_opts.append("--quiet") # Shut up a lot
4018 rsync_opts.append("--verbose") # Print filelist
4020 if "--verbose" in myopts:
4021 rsync_opts.append("--progress") # Progress meter for each file
4023 if "--debug" in myopts:
4024 rsync_opts.append("--checksum") # Force checksum on all files
4026 if settings["RSYNC_EXCLUDEFROM"] != "":
4027 portage.writemsg(yellow("WARNING:") + \
4028 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
4029 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4030 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
4031 rsync_opts.append("--exclude-from=%s" % \
4032 settings["RSYNC_EXCLUDEFROM"])
4034 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
4035 " but file does not exist.\n")
4037 if settings["RSYNC_RATELIMIT"] != "":
4038 portage.writemsg(yellow("WARNING:") + \
4039 " usage of RSYNC_RATELIMIT is deprecated, use " + \
4040 "PORTAGE_RSYNC_EXTRA_OPTS instead")
4041 rsync_opts.append("--bwlimit=%s" % \
4042 settings["RSYNC_RATELIMIT"])
4044 # Real local timestamp file.
4045 servertimestampfile = os.path.join(
4046 myportdir, "metadata", "timestamp.chk")
4047 # Temporary file for remote server timestamp comparison.
4048 tmpservertimestampfile = os.path.join(
4049 settings["PORTAGE_TMPDIR"], "timestamp.chk")
4051 content = portage.util.grabfile(servertimestampfile)
4055 mytimestamp = time.mktime(time.strptime(content[0],
4056 "%a, %d %b %Y %H:%M:%S +0000"))
4057 except (OverflowError, ValueError):
4062 if settings.has_key("RSYNC_RETRIES"):
4063 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
4064 maxretries=int(settings["RSYNC_RETRIES"])
4066 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
4067 except SystemExit, e:
4068 raise # Needed else can't exit
4070 maxretries=3 #default number of retries
4073 user_name, hostname, port = re.split(
4074 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
4077 if user_name is None:
4079 updatecache_flg=True
4080 all_rsync_opts = set(rsync_opts)
4081 lexer = shlex.shlex(StringIO.StringIO(
4082 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")), posix=True)
4083 lexer.whitespace_split = True
4084 extra_rsync_opts = list(lexer)
4086 all_rsync_opts.update(extra_rsync_opts)
4087 family = socket.AF_INET
4088 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
4089 family = socket.AF_INET
4090 elif socket.has_ipv6 and \
4091 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
4092 family = socket.AF_INET6
4099 for addrinfo in socket.getaddrinfo(
4100 hostname, None, family, socket.SOCK_STREAM):
4101 if addrinfo[0] == socket.AF_INET6:
4102 # IPv6 addresses need to be enclosed in square brackets
4103 ips.append("[%s]" % addrinfo[4][0])
4105 ips.append(addrinfo[4][0])
4106 from random import shuffle
4108 except SystemExit, e:
4109 raise # Needed else can't exit
4110 except Exception, e:
4111 print "Notice:",str(e)
4116 dosyncuri = syncuri.replace(
4117 "//" + user_name + hostname + port + "/",
4118 "//" + user_name + ips[0] + port + "/", 1)
4119 except SystemExit, e:
4120 raise # Needed else can't exit
4121 except Exception, e:
4122 print "Notice:",str(e)
4126 if "--ask" in myopts:
4127 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
4132 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
4133 if "--quiet" not in myopts:
4134 print ">>> Starting rsync with "+dosyncuri+"..."
4136 emergelog(xterm_titles,
4137 ">>> Starting retry %d of %d with %s" % \
4138 (retries,maxretries,dosyncuri))
4139 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
4141 if mytimestamp != 0 and "--quiet" not in myopts:
4142 print ">>> Checking server timestamp ..."
4144 rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
4146 if "--debug" in myopts:
4151 # Even if there's no timestamp available locally, fetch the
4152 # timestamp anyway as an initial probe to verify that the server is
4153 # responsive. This protects us from hanging indefinitely on a
4154 # connection attempt to an unresponsive server which rsync's
4155 # --timeout option does not prevent.
4157 mycommand = rsynccommand[:]
4158 mycommand.append(dosyncuri.rstrip("/") + \
4159 "/metadata/timestamp.chk")
4160 mycommand.append(tmpservertimestampfile)
4164 def timeout_handler(signum, frame):
4165 raise portage.exception.PortageException("timed out")
4166 signal.signal(signal.SIGALRM, timeout_handler)
4167 # Timeout here in case the server is unresponsive. The
4168 # --timeout rsync option doesn't apply to the initial
4169 # connection attempt.
4172 mypids.extend(portage.process.spawn(
4173 mycommand, env=settings.environ(), returnpid=True))
4174 exitcode = os.waitpid(mypids[0], 0)[1]
4175 content = portage.grabfile(tmpservertimestampfile)
4179 os.unlink(tmpservertimestampfile)
4182 except portage.exception.PortageException, e:
4186 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
4187 os.kill(mypids[0], signal.SIGTERM)
4188 os.waitpid(mypids[0], 0)
4189 # This is the same code rsync uses for timeout.
4192 if exitcode != os.EX_OK:
4194 exitcode = (exitcode & 0xff) << 8
4196 exitcode = exitcode >> 8
4198 portage.process.spawned_pids.remove(mypids[0])
4201 servertimestamp = time.mktime(time.strptime(
4202 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
4203 except (OverflowError, ValueError):
4205 del mycommand, mypids, content
4206 if exitcode == os.EX_OK:
4207 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4208 emergelog(xterm_titles,
4209 ">>> Cancelling sync -- Already current.")
4212 print ">>> Timestamps on the server and in the local repository are the same."
4213 print ">>> Cancelling all further sync action. You are already up to date."
4215 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4219 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4220 emergelog(xterm_titles,
4221 ">>> Server out of date: %s" % dosyncuri)
4224 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4226 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4229 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4231 mycommand = rsynccommand + [dosyncuri+"/", myportdir]
4232 exitcode = portage.process.spawn(mycommand,
4233 env=settings.environ())
4234 if exitcode in [0,1,3,4,11,14,20,21]:
4236 elif exitcode in [1,3,4,11,14,20,21]:
4239 # Code 2 indicates protocol incompatibility, which is expected
4240 # for servers with protocol < 29 that don't support
4241 # --prune-empty-directories. Retry for a server that supports
4242 # at least rsync protocol version 29 (>=rsync-2.6.4).
4247 if retries<=maxretries:
4248 print ">>> Retrying..."
4253 updatecache_flg=False
4257 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4261 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4262 print darkred("!!!")+green(" that your SYNC statement is proper.")
4263 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4265 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4266 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4267 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4268 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4269 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4271 print darkred("!!!")+green(" Rsync was killed before it finished.")
4273 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4274 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4275 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4276 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4277 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4280 elif syncuri[:6]=="cvs://":
4281 if not os.path.exists("/usr/bin/cvs"):
4282 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4283 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4286 cvsdir=os.path.dirname(myportdir)
4287 if not os.path.exists(myportdir+"/CVS"):
4289 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4290 if os.path.exists(cvsdir+"/gentoo-x86"):
4291 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4296 if e.errno != errno.ENOENT:
4298 "!!! existing '%s' directory; exiting.\n" % myportdir)
4301 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4302 print "!!! cvs checkout error; exiting."
4304 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4307 print ">>> Starting cvs update with "+syncuri+"..."
4308 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4309 myportdir, settings, free=1)
4310 if retval != os.EX_OK:
4314 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4317 if updatecache_flg and \
4318 myaction != "metadata" and \
4319 "metadata-transfer" not in settings.features:
4320 updatecache_flg = False
4322 # Reload the whole config from scratch.
4323 settings, trees, mtimedb = load_emerge_config(trees=trees)
4324 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4326 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4327 action_metadata(settings, portdb, myopts)
4329 if portage.global_updates(settings, trees, mtimedb["updates"]):
4331 # Reload the whole config from scratch.
4332 settings, trees, mtimedb = load_emerge_config(trees=trees)
4333 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4335 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4336 mypvs = portage.best(
4337 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4339 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4341 if myaction != "metadata":
4342 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4343 retval = portage.process.spawn(
4344 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4345 dosyncuri], env=settings.environ())
4346 if retval != os.EX_OK:
4347 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4349 if(mybestpv != mypvs) and not "--quiet" in myopts:
4351 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4352 print red(" * ")+"that you update portage now, before any other packages are updated."
4353 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4354 print red(" * ")+"configuration files."
4355 print red(" * ")+"To update portage, run 'emerge portage'."
4358 display_news_notification(settings)
4360 def action_metadata(settings, portdb, myopts):
4361 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4362 old_umask = os.umask(0002)
4363 cachedir = os.path.normpath(settings.depcachedir)
4364 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4365 "/lib", "/opt", "/proc", "/root", "/sbin",
4366 "/sys", "/tmp", "/usr", "/var"]:
4367 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4368 "ROOT DIRECTORY ON YOUR SYSTEM."
4369 print >> sys.stderr, \
4370 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4372 if not os.path.exists(cachedir):
4375 ec = portage.eclass_cache.cache(portdb.porttree_root)
4376 myportdir = os.path.realpath(settings["PORTDIR"])
4377 cm = settings.load_best_module("portdbapi.metadbmodule")(
4378 myportdir, "metadata/cache", portage.auxdbkeys[:])
4380 from portage.cache import util
4382 class percentage_noise_maker(util.quiet_mirroring):
4383 def __init__(self, dbapi):
4385 self.cp_all = dbapi.cp_all()
4386 l = len(self.cp_all)
4387 self.call_update_min = 100000000
4388 self.min_cp_all = l/100.0
4393 for x in self.cp_all:
4395 if self.count > self.min_cp_all:
4396 self.call_update_min = 0
4398 for y in self.dbapi.cp_list(x):
4400 self.call_update_mine = 0
4402 def update(self, *arg):
4403 try: self.pstr = int(self.pstr) + 1
4404 except ValueError: self.pstr = 1
4405 sys.stdout.write("%s%i%%" % \
4406 ("\b" * (len(str(self.pstr))+1), self.pstr))
4408 self.call_update_min = 10000000
4410 def finish(self, *arg):
4411 sys.stdout.write("\b\b\b\b100%\n")
4414 if "--quiet" in myopts:
4415 def quicky_cpv_generator(cp_all_list):
4416 for x in cp_all_list:
4417 for y in portdb.cp_list(x):
4419 source = quicky_cpv_generator(portdb.cp_all())
4420 noise_maker = portage.cache.util.quiet_mirroring()
4422 noise_maker = source = percentage_noise_maker(portdb)
4423 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4424 eclass_cache=ec, verbose_instance=noise_maker)
4429 def action_regen(settings, portdb):
4430 xterm_titles = "notitles" not in settings.features
4431 emergelog(xterm_titles, " === regen")
4432 #regenerate cache entries
4433 print "Regenerating cache entries... "
4435 os.close(sys.stdin.fileno())
4436 except SystemExit, e:
4437 raise # Needed else can't exit
4441 mynodes = portdb.cp_all()
4442 from portage.cache.cache_errors import CacheError
4444 for mytree in portdb.porttrees:
4446 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4447 except CacheError, e:
4448 print "\n error listing cache entries for " + \
4449 "'%s': %s, continuing..." % (mytree, e)
4454 mymatches = portdb.cp_list(x)
4455 portage.writemsg_stdout("processing %s\n" % x)
4458 foo = portdb.aux_get(y,["DEPEND"])
4459 except SystemExit, e:
4460 # sys.exit is an exception... And consequently, we can't catch it.
4462 except Exception, e:
4463 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4465 for mytree in portdb.porttrees:
4466 if portdb.findname2(y, mytree=mytree)[0]:
4467 dead_nodes[mytree].discard(y)
4469 for mytree, nodes in dead_nodes.iteritems():
4470 auxdb = portdb.auxdb[mytree]
4474 except (KeyError, CacheError):
4478 def action_config(settings, trees, myopts, myfiles):
4479 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4480 print red("!!! config can only take a single package atom at this time\n")
4482 if not is_valid_package_atom(myfiles[0]):
4483 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4485 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4486 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4490 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4491 except ValueError, e:
4492 # Multiple matches thrown from cpv_expand
4495 print "No packages found.\n"
4498 if "--ask" in myopts:
4500 print "Please select a package to configure:"
4504 options.append(str(idx))
4505 print options[-1]+") "+pkg
4508 idx = userquery("Selection?", options)
4511 pkg = pkgs[int(idx)-1]
4513 print "The following packages available:"
4516 print "\nPlease use a specific atom or the --ask option."
4522 if "--ask" in myopts:
4523 if userquery("Ready to configure "+pkg+"?") == "No":
4526 print "Configuring pkg..."
4528 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4529 mysettings = portage.config(clone=settings)
4530 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4531 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4532 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4535 def action_info(settings, trees, myopts, myfiles):
4536 unameout=commands.getstatusoutput("uname -mrp")[1]
4537 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4538 settings.profile_path, settings["CHOST"],
4539 trees[settings["ROOT"]]["vartree"].dbapi)
4541 header_title = "System Settings"
4543 print header_width * "="
4544 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4545 print header_width * "="
4546 print "System uname: "+unameout
4547 gentoo_release = portage.grabfile(os.path.join(
4548 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4550 print gentoo_release[0]
4552 print "Unknown Host Operating System"
4553 lastSync = portage.grabfile(os.path.join(
4554 settings["PORTDIR"], "metadata", "timestamp.chk"))
4555 print "Timestamp of tree:",
4561 output=commands.getstatusoutput("distcc --version")
4563 print str(output[1].split("\n",1)[0]),
4564 if "distcc" in settings.features:
4569 output=commands.getstatusoutput("ccache -V")
4571 print str(output[1].split("\n",1)[0]),
4572 if "ccache" in settings.features:
4577 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4578 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4579 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4580 myvars = portage.util.unique_array(myvars)
4584 if portage.isvalidatom(x):
4585 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4586 pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
4587 pkg_matches.sort(portage.pkgcmp)
4589 for pn, ver, rev in pkg_matches:
4591 pkgs.append(ver + "-" + rev)
4595 pkgs = ", ".join(pkgs)
4596 print "%-20s %s" % (x+":", pkgs)
4598 print "%-20s %s" % (x+":", "[NOT VALID]")
4600 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4602 if "--verbose" in myopts:
4603 myvars=settings.keys()
4605 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4606 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4607 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4608 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4610 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4612 myvars = portage.util.unique_array(myvars)
4618 print '%s="%s"' % (x, settings[x])
4620 use = set(settings["USE"].split())
4621 use_expand = settings["USE_EXPAND"].split()
4623 for varname in use_expand:
4624 flag_prefix = varname.lower() + "_"
4626 if f.startswith(flag_prefix):
4630 print 'USE="%s"' % " ".join(use),
4631 for varname in use_expand:
4632 myval = settings.get(varname)
4634 print '%s="%s"' % (varname, myval),
4637 unset_vars.append(x)
4639 print "Unset: "+", ".join(unset_vars)
4642 if "--debug" in myopts:
4643 for x in dir(portage):
4644 module = getattr(portage, x)
4645 if "cvs_id_string" in dir(module):
4646 print "%s: %s" % (str(x), str(module.cvs_id_string))
4648 # See if we can find any packages installed matching the strings
4649 # passed on the command line
4651 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4652 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4654 mypkgs.extend(vardb.match(x))
4656 # If some packages were found...
4658 # Get our global settings (we only print stuff if it varies from
4659 # the current config)
4660 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4661 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4663 pkgsettings = portage.config(clone=settings)
4665 for myvar in mydesiredvars:
4666 global_vals[myvar] = set(settings.get(myvar, "").split())
4668 # Loop through each package
4669 # Only print settings if they differ from global settings
4670 header_printed = False
4672 # Get all package specific variables
4673 auxvalues = vardb.aux_get(pkg, auxkeys)
4675 for i in xrange(len(auxkeys)):
4676 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4678 for myvar in mydesiredvars:
4679 # If the package variable doesn't match the
4680 # current global variable, something has changed
4681 # so set diff_found so we know to print
4682 if valuesmap[myvar] != global_vals[myvar]:
4683 diff_values[myvar] = valuesmap[myvar]
4684 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4685 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4687 # If a matching ebuild is no longer available in the tree, maybe it
4688 # would make sense to compare against the flags for the best
4689 # available version with the same slot?
4691 if portdb.cpv_exists(pkg):
4693 pkgsettings.setcpv(pkg, mydb=mydb)
4694 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4696 diff_values["USE"] = valuesmap["USE"]
4697 # If a difference was found, print the info for
4701 # If we have not yet printed the header,
4703 if not header_printed:
4704 header_title = "Package Settings"
4705 print header_width * "="
4706 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4707 print header_width * "="
4708 header_printed = True
4710 # Print package info
4711 print "%s was built with the following:" % pkg
4712 for myvar in mydesiredvars + ["USE"]:
4713 if myvar in diff_values:
4714 mylist = list(diff_values[myvar])
4716 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4719 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4721 print "emerge: no search terms provided."
4723 searchinstance = search(settings, portdb,
4724 vartree, spinner, "--searchdesc" in myopts,
4725 "--quiet" not in myopts)
4726 for mysearch in myfiles:
4728 searchinstance.execute(mysearch)
4729 except re.error, comment:
4730 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4732 searchinstance.output()
4734 def action_depclean(settings, trees, ldpath_mtimes,
4736 # Kill packages that aren't explicitly merged or are required as a
4737 # dependency of another package. World file is explicit.
4739 warn_prefix = colorize("BAD", "*** WARNING *** ")
4741 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4742 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4743 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4745 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4746 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4747 print warn_prefix + "be kept. They can be manually added to this set with"
4748 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4749 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4750 print warn_prefix + "depclean, even if they are part of the world set."
4752 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4753 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4754 print warn_prefix + "consequence, it is often necessary to run "
4755 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4757 xterm_titles = "notitles" not in settings.features
4758 myroot = settings["ROOT"]
4759 dep_check_trees = {}
4760 dep_check_trees[myroot] = {}
4761 dep_check_trees[myroot]["vartree"] = \
4762 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4763 vardb = dep_check_trees[myroot]["vartree"].dbapi
4764 # Constrain dependency selection to the installed packages.
4765 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4766 syslist = getlist(settings, "system")
4767 worldlist = getlist(settings, "world")
4768 system_world_dict = genericdict(worldlist)
4769 system_world_dict.update(genericdict(syslist))
4770 fakedb = portage.fakedbapi(settings=settings)
4771 myvarlist = vardb.cpv_all()
4774 print "\n!!! You have no system list.",
4776 print "\n!!! You have no world file.",
4778 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4780 if not (syslist and worldlist and myvarlist):
4781 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4782 print " break your installation.\n"
4783 if "--pretend" not in myopts:
4784 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4786 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4787 emergelog(xterm_titles, " >>> depclean")
4789 if "--quiet" not in myopts:
4790 print "\nCalculating dependencies ",
4794 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4795 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4797 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4799 while remaining_atoms:
4800 atom, parent, priority = remaining_atoms.pop()
4801 pkgs = vardb.match(atom)
4803 if not atom.startswith("!") and priority == hard:
4804 unresolveable.setdefault(atom, []).append(parent)
4806 if portage.dep_getkey(atom) not in system_world_dict:
4807 # Prune all but the best matching slot, since that's all that a
4808 # deep world update would pull in. Don't prune if the cpv is in
4809 # system or world though, since those sets trigger greedy update
4811 pkgs = [portage.best(pkgs)]
4813 if fakedb.cpv_exists(pkg):
4816 fakedb.cpv_inject(pkg)
4817 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4819 if myopts.get("--with-bdeps", "y") == "y":
4820 mydeps.append((myaux["DEPEND"], soft))
4822 mydeps.append((" ".join(myaux.values()), hard))
4823 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4824 for depstr, priority in mydeps:
4829 if "--debug" in myopts:
4831 print "Parent: ", pkg
4832 print "Depstring:", depstr
4834 if priority == soft:
4840 portage.dep._dep_check_strict = False
4841 success, atoms = portage.dep_check(depstr, None, settings,
4842 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4844 portage.dep._dep_check_strict = True
4846 show_invalid_depstring_notice(
4847 ("installed", myroot, pkg, "nomerge"),
4851 if "--debug" in myopts:
4852 print "Candidates:", atoms
4855 remaining_atoms.append((atom, pkg, priority))
4857 if "--quiet" not in myopts:
4858 print "\b\b... done!\n"
4861 print "Dependencies could not be completely resolved due to"
4862 print "the following required packages not being installed:"
4864 for atom in unresolveable:
4865 print atom, "required by", " ".join(unresolveable[atom])
4867 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4868 print "depclean? It may be necessary to manually uninstall packages that no longer"
4869 print "exist in the portage tree since it may not be possible to satisfy their"
4870 print "dependencies. Also, be aware of the --with-bdeps option that is documented"
4871 print "in " + good("`man emerge`") + "."
4875 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4878 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4879 "unmerge", cleanlist, ldpath_mtimes)
4881 print "Packages installed: "+str(len(myvarlist))
4882 print "Packages in world: "+str(len(worldlist))
4883 print "Packages in system: "+str(len(syslist))
4884 print "Unique package names: "+str(len(myvarlist))
4885 print "Required packages: "+str(len(fakedb.cpv_all()))
4886 if "--pretend" in myopts:
4887 print "Number to remove: "+str(len(cleanlist))
4889 print "Number removed: "+str(len(cleanlist))
4891 def action_build(settings, trees, mtimedb,
4892 myopts, myaction, myfiles, spinner):
4893 ldpath_mtimes = mtimedb["ldpath"]
4895 if "--quiet" not in myopts and \
4896 ("--pretend" in myopts or "--ask" in myopts or \
4897 "--tree" in myopts or "--verbose" in myopts):
4899 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4903 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4905 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4909 print darkgreen("These are the packages that would be %s, in order:") % action
4912 # validate the state of the resume data
4913 # so that we can make assumptions later.
4914 for k in ("resume", "resume_backup"):
4916 if "mergelist" in mtimedb[k]:
4917 if not mtimedb[k]["mergelist"]:
4922 if "--resume" in myopts and \
4923 ("resume" in mtimedb or
4924 "resume_backup" in mtimedb):
4925 if "resume" not in mtimedb:
4926 mtimedb["resume"] = mtimedb["resume_backup"]
4927 del mtimedb["resume_backup"]
4929 # XXX: "myopts" is a list for backward compatibility.
4930 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4932 for opt in ("--skipfirst", "--ask", "--tree"):
4933 myresumeopts.pop(opt, None)
4935 for myopt, myarg in myopts.iteritems():
4936 if myopt not in myresumeopts:
4937 myresumeopts[myopt] = myarg
4940 # Adjust config according to options of the command being resumed.
4941 for myroot in trees:
4942 mysettings = trees[myroot]["vartree"].settings
4944 adjust_config(myopts, mysettings)
4946 del myroot, mysettings
4948 myparams = create_depgraph_params(myopts, myaction)
4949 if "--quiet" not in myopts and "--nodeps" not in myopts:
4950 print "Calculating dependencies ",
4951 mydepgraph = depgraph(settings, trees,
4952 myopts, myparams, spinner)
4953 if "--quiet" not in myopts and "--nodeps" not in myopts:
4954 print "\b\b... done!"
4956 if ("--resume" in myopts):
4957 print darkgreen("emerge: It seems we have nothing to resume...")
4960 myparams = create_depgraph_params(myopts, myaction)
4961 if myaction in ["system","world"]:
4962 if "--quiet" not in myopts and "--nodeps" not in myopts:
4963 print "Calculating",myaction,"dependencies ",
4965 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4966 if not mydepgraph.xcreate(myaction):
4967 print "!!! Depgraph creation failed."
4969 if "--quiet" not in myopts and "--nodeps" not in myopts:
4970 print "\b\b... done!"
4972 if "--quiet" not in myopts and "--nodeps" not in myopts:
4973 print "Calculating dependencies ",
4975 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4977 retval, favorites = mydepgraph.select_files(myfiles)
4978 except portage.exception.PackageNotFound, e:
4979 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4983 if "--quiet" not in myopts and "--nodeps" not in myopts:
4984 print "\b\b... done!"
4986 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4987 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4989 if mydepgraph.missingbins:
4990 for x in mydepgraph.missingbins:
4991 sys.stderr.write(" "+str(x)+"\n")
4992 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4995 if "--pretend" not in myopts and \
4996 ("--ask" in myopts or "--tree" in myopts or \
4997 "--verbose" in myopts) and \
4998 not ("--quiet" in myopts and "--ask" not in myopts):
4999 if "--resume" in myopts:
5000 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5001 mymergelist = mtimedb["resume"]["mergelist"]
5002 if "--skipfirst" in myopts:
5003 mymergelist = mymergelist[1:]
5004 if len(mymergelist) == 0:
5005 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5007 mydepgraph.display(mymergelist)
5008 prompt="Would you like to resume merging these packages?"
5011 mydepgraph.altlist(reversed=("--tree" in myopts)))
5013 for x in mydepgraph.altlist():
5014 if x[0] != "blocks" and x[3] != "nomerge":
5016 #check for blocking dependencies
5017 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
5018 print "\n!!! Error: The above package list contains packages which cannot be installed"
5019 print "!!! at the same time on the same system."
5020 if "--quiet" not in myopts:
5021 show_blocker_docs_link()
5024 if "--noreplace" in myopts and favorites:
5027 print " %s %s" % (good("*"), x)
5028 prompt="Would you like to add these packages to your world favorites?"
5029 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5030 prompt="Nothing to merge; would you like to auto-clean packages?"
5033 print "Nothing to merge; quitting."
5036 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5037 prompt="Would you like to fetch the source files for these packages?"
5039 prompt="Would you like to merge these packages?"
5041 if "--ask" in myopts and userquery(prompt) == "No":
5046 # Don't ask again (e.g. when auto-cleaning packages after merge)
5047 myopts.pop("--ask", None)
5049 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5050 if ("--resume" in myopts):
5051 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5052 mymergelist = mtimedb["resume"]["mergelist"]
5053 if "--skipfirst" in myopts:
5054 mymergelist = mymergelist[1:]
5055 if len(mymergelist) == 0:
5056 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5058 mydepgraph.display(mymergelist)
5061 mydepgraph.altlist(reversed=("--tree" in myopts)))
5062 if ("--buildpkgonly" in myopts):
5063 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5064 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5065 print "!!! You have to merge the dependencies before you can build this package.\n"
5068 if ("--buildpkgonly" in myopts):
5069 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5070 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5071 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
5074 if ("--resume" in myopts):
5075 favorites=mtimedb["resume"]["favorites"]
5076 mergetask = MergeTask(settings, trees, myopts)
5077 if "--fetchonly" in myopts:
5078 """ parallel-fetch uses --resume --fetchonly and we don't want
5079 it to write the mtimedb"""
5080 mtimedb.filename = None
5081 time.sleep(3) # allow the parent to have first fetch
5083 retval = mergetask.merge(
5084 mtimedb["resume"]["mergelist"], favorites, mtimedb)
5085 if retval != os.EX_OK:
5088 if "resume" in mtimedb and \
5089 "mergelist" in mtimedb["resume"] and \
5090 len(mtimedb["resume"]["mergelist"]) > 1:
5091 mtimedb["resume_backup"] = mtimedb["resume"]
5092 del mtimedb["resume"]
5094 mtimedb["resume"]={}
5095 # XXX: Stored as a list for backward compatibility.
5096 mtimedb["resume"]["myopts"] = \
5097 [k for k in myopts if myopts[k] is True]
5098 mtimedb["resume"]["favorites"]=favorites
5099 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5100 for pkgline in mydepgraph.altlist():
5101 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5102 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
5103 tmpsettings = portage.config(clone=settings)
5105 if settings.get("PORTAGE_DEBUG", "") == "1":
5107 retval = portage.doebuild(
5108 y, "digest", settings["ROOT"], tmpsettings, edebug,
5109 ("--pretend" in myopts),
5110 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
5112 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5114 for pkg in mydepgraph.altlist():
5115 if pkg[0] != "blocks":
5118 pkglist = mydepgraph.altlist()
5120 mergetask = MergeTask(settings, trees, myopts)
5121 retval = mergetask.merge(pkglist, favorites, mtimedb)
5122 if retval != os.EX_OK:
5125 if mtimedb.has_key("resume"):
5126 del mtimedb["resume"]
5127 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5128 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5129 vartree = trees[settings["ROOT"]]["vartree"]
5130 unmerge(settings, myopts, vartree, "clean", ["world"],
5131 ldpath_mtimes, autoclean=1)
5133 portage.writemsg_stdout(colorize("WARN", "WARNING:")
5134 + " AUTOCLEAN is disabled. This can cause serious"
5135 + " problems due to overlapping packages.\n")
5137 def multiple_actions(action1, action2):
5138 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
5139 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
5142 def parse_opts(tmpcmdline, silent=False):
5147 global actions, options, shortmapping
5149 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
5150 argument_options = {
5152 "help":"specify the location for portage configuration files",
5156 "help":"enable or disable color output",
5158 "choices":("y", "n")
5161 "help":"include unnecessary build time dependencies",
5163 "choices":("y", "n")
5167 from optparse import OptionParser
5168 parser = OptionParser()
5169 if parser.has_option("--help"):
5170 parser.remove_option("--help")
5172 for action_opt in actions:
5173 parser.add_option("--" + action_opt, action="store_true",
5174 dest=action_opt.replace("-", "_"), default=False)
5175 for myopt in options:
5176 parser.add_option(myopt, action="store_true",
5177 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5178 for shortopt, longopt in shortmapping.iteritems():
5179 parser.add_option("-" + shortopt, action="store_true",
5180 dest=longopt.lstrip("--").replace("-", "_"), default=False)
5181 for myalias, myopt in longopt_aliases.iteritems():
5182 parser.add_option(myalias, action="store_true",
5183 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5185 for myopt, kwargs in argument_options.iteritems():
5186 parser.add_option(myopt,
5187 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
5189 myoptions, myargs = parser.parse_args(args=tmpcmdline)
5191 for myopt in options:
5192 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
5194 myopts[myopt] = True
5196 for myopt in argument_options:
5197 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
5201 for action_opt in actions:
5202 v = getattr(myoptions, action_opt.replace("-", "_"))
5205 multiple_actions(myaction, action_opt)
5207 myaction = action_opt
5210 if x in actions and myaction != "search":
5211 if not silent and x not in ["system", "world"]:
5212 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
5213 # special case "search" so people can search for action terms, e.g. emerge -s sync
5215 multiple_actions(myaction, x)
5221 if "--nocolor" in myopts:
5223 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
5224 "use '--color=n' instead.\n")
5225 del myopts["--nocolor"]
5226 myopts["--color"] = "n"
5228 return myaction, myopts, myfiles
5230 def validate_ebuild_environment(trees):
5231 for myroot in trees:
5232 mysettings = trees[myroot]["vartree"].settings
5233 for var in "ARCH", "USERLAND":
5234 if mysettings.get(var):
5236 print >> sys.stderr, bad(("\a!!! %s is not set... " % var) + \
5237 "Are you missing the '%setc/make.profile' symlink?" % \
5238 mysettings["PORTAGE_CONFIGROOT"])
5239 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5240 "Is your portage tree complete?\n")
5242 del myroot, mysettings
5244 def load_emerge_config(trees=None):
5246 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5247 kwargs[k] = os.environ.get(envvar, None)
5248 trees = portage.create_trees(trees=trees, **kwargs)
5250 settings = trees["/"]["vartree"].settings
5252 for myroot in trees:
5254 settings = trees[myroot]["vartree"].settings
5257 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5258 mtimedb = portage.MtimeDB(mtimedbfile)
5259 return settings, trees, mtimedb
5261 def adjust_config(myopts, settings):
5262 """Make emerge specific adjustments to the config."""
5264 # To enhance usability, make some vars case insensitive by forcing them to
5266 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5267 if myvar in settings:
5268 settings[myvar] = settings[myvar].lower()
5269 settings.backup_changes(myvar)
5272 # Kill noauto as it will break merges otherwise.
5273 if "noauto" in settings.features:
5274 while "noauto" in settings.features:
5275 settings.features.remove("noauto")
5276 settings["FEATURES"] = " ".join(settings.features)
5277 settings.backup_changes("FEATURES")
5281 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5282 except ValueError, e:
5283 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5284 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5285 settings["CLEAN_DELAY"], noiselevel=-1)
5286 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5287 settings.backup_changes("CLEAN_DELAY")
5289 EMERGE_WARNING_DELAY = 10
5291 EMERGE_WARNING_DELAY = int(settings.get(
5292 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5293 except ValueError, e:
5294 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5295 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5296 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5297 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5298 settings.backup_changes("EMERGE_WARNING_DELAY")
5300 if "--quiet" in myopts:
5301 settings["PORTAGE_QUIET"]="1"
5302 settings.backup_changes("PORTAGE_QUIET")
5304 # Set so that configs will be merged regardless of remembered status
5305 if ("--noconfmem" in myopts):
5306 settings["NOCONFMEM"]="1"
5307 settings.backup_changes("NOCONFMEM")
5309 # Set various debug markers... They should be merged somehow.
5312 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5313 if PORTAGE_DEBUG not in (0, 1):
5314 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5315 PORTAGE_DEBUG, noiselevel=-1)
5316 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5319 except ValueError, e:
5320 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5321 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5322 settings["PORTAGE_DEBUG"], noiselevel=-1)
5324 if "--debug" in myopts:
5326 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5327 settings.backup_changes("PORTAGE_DEBUG")
5329 if settings.get("NOCOLOR") not in ("yes","true"):
5330 portage.output.havecolor = 1
5332 """The explicit --color < y | n > option overrides the NOCOLOR environment
5333 variable and stdout auto-detection."""
5334 if "--color" in myopts:
5335 if "y" == myopts["--color"]:
5336 portage.output.havecolor = 1
5337 settings["NOCOLOR"] = "false"
5339 portage.output.havecolor = 0
5340 settings["NOCOLOR"] = "true"
5341 settings.backup_changes("NOCOLOR")
5342 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5343 portage.output.havecolor = 0
5344 settings["NOCOLOR"] = "true"
5345 settings.backup_changes("NOCOLOR")
5348 global portage # NFC why this is necessary now - genone
5349 # Disable color until we're sure that it should be enabled (after
5350 # EMERGE_DEFAULT_OPTS has been parsed).
5351 portage.output.havecolor = 0
5352 # This first pass is just for options that need to be known as early as
5353 # possible, such as --config-root. They will be parsed again later,
5354 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5355 # the value of --config-root).
5356 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5357 if "--debug" in myopts:
5358 os.environ["PORTAGE_DEBUG"] = "1"
5359 if "--config-root" in myopts:
5360 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5362 # Portage needs to ensure a sane umask for the files it creates.
5364 settings, trees, mtimedb = load_emerge_config()
5365 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5368 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5369 except (OSError, ValueError), e:
5370 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5371 settings["PORTAGE_NICENESS"])
5372 portage.writemsg("!!! %s\n" % str(e))
5375 if portage.global_updates(settings, trees, mtimedb["updates"]):
5377 # Reload the whole config from scratch.
5378 settings, trees, mtimedb = load_emerge_config(trees=trees)
5379 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5381 xterm_titles = "notitles" not in settings.features
5384 if "--ignore-default-opts" not in sys.argv:
5385 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5386 tmpcmdline.extend(sys.argv[1:])
5387 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5389 if "--digest" in myopts:
5390 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5391 # Reload the whole config from scratch so that the portdbapi internal
5392 # config is updated with new FEATURES.
5393 settings, trees, mtimedb = load_emerge_config(trees=trees)
5394 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5396 for myroot in trees:
5397 mysettings = trees[myroot]["vartree"].settings
5399 adjust_config(myopts, mysettings)
5401 del myroot, mysettings
5403 spinner = stdout_spinner()
5404 if "candy" in settings.features:
5405 spinner.update = spinner.update_scroll
5407 if "--quiet" not in myopts:
5408 portage.deprecated_profile_check()
5410 #Freeze the portdbapi for enhanced performance:
5411 for myroot in trees:
5412 trees[myroot]["porttree"].dbapi.freeze()
5415 if "moo" in myfiles:
5418 Larry loves Gentoo (""" + os.uname()[0] + """)
5420 _______________________
5421 < Have you mooed today? >
5422 -----------------------
5431 if (myaction in ["world", "system"]) and myfiles:
5432 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5436 ext = os.path.splitext(x)[1]
5437 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5438 print "emerging by path implies --oneshot... adding --oneshot to options."
5439 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5442 if ("--tree" in myopts) and ("--columns" in myopts):
5443 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5446 if ("--quiet" in myopts):
5447 spinner.update = spinner.update_quiet
5448 portage.util.noiselimit = -1
5450 # Always create packages if FEATURES=buildpkg
5451 # Imply --buildpkg if --buildpkgonly
5452 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5453 if "--buildpkg" not in myopts:
5454 myopts["--buildpkg"] = True
5456 # Also allow -S to invoke search action (-sS)
5457 if ("--searchdesc" in myopts):
5458 if myaction and myaction != "search":
5459 myfiles.append(myaction)
5460 if "--search" not in myopts:
5461 myopts["--search"] = True
5464 # Always try and fetch binary packages if FEATURES=getbinpkg
5465 if ("getbinpkg" in settings.features):
5466 myopts["--getbinpkg"] = True
5468 if "--skipfirst" in myopts and "--resume" not in myopts:
5469 myopts["--resume"] = True
5471 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5472 myopts["--usepkgonly"] = True
5474 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5475 myopts["--getbinpkg"] = True
5477 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5478 myopts["--usepkg"] = True
5480 # Also allow -K to apply --usepkg/-k
5481 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5482 myopts["--usepkg"] = True
5484 # Allow -p to remove --ask
5485 if ("--pretend" in myopts) and ("--ask" in myopts):
5486 print ">>> --pretend disables --ask... removing --ask from options."
5489 # forbid --ask when not in a terminal
5490 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5491 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5492 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5496 if settings.get("PORTAGE_DEBUG", "") == "1":
5497 spinner.update = spinner.update_quiet
5499 if "python-trace" in settings.features:
5500 import portage.debug
5501 portage.debug.set_trace(True)
5503 if ("--resume" in myopts):
5504 if "--tree" in myopts:
5505 print "* --tree is currently broken with --resume. Disabling..."
5506 del myopts["--tree"]
5508 if not ("--quiet" in myopts):
5509 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5510 spinner.update = spinner.update_basic
5512 if "--version" in myopts:
5513 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5514 settings.profile_path, settings["CHOST"],
5515 trees[settings["ROOT"]]["vartree"].dbapi)
5517 elif "--help" in myopts:
5518 emerge.help.help(myaction, myopts, portage.output.havecolor)
5521 if portage.wheelgid == portage.portage_gid:
5522 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5523 print " include the portage user as noted above, and then use group portage."
5525 if "--debug" in myopts:
5526 print "myaction", myaction
5527 print "myopts", myopts
5529 if not myaction and not myfiles and "--resume" not in myopts:
5530 emerge.help.help(myaction, myopts, portage.output.havecolor)
5533 # check if root user is the current user for the actions where emerge needs this
5534 if portage.secpass < 2:
5535 # We've already allowed "--version" and "--help" above.
5536 if "--pretend" not in myopts and \
5537 myaction not in ("search","info"):
5538 need_superuser = not \
5539 ("--fetchonly" in myopts or \
5540 "--fetch-all-uri" in myopts or \
5541 myaction in ("metadata", "regen"))
5542 if portage.secpass < 1 or \
5545 access_desc = "superuser"
5547 access_desc = "portage group"
5548 # Always show portage_group_warning() when only portage group
5549 # access is required but the user is not in the portage group.
5550 from portage.data import portage_group_warning
5551 if "--ask" in myopts:
5552 myopts["--pretend"] = True
5554 print ("%s access would be required... " + \
5555 "adding --pretend to options.\n") % access_desc
5556 if portage.secpass < 1 and not need_superuser:
5557 portage_group_warning()
5559 sys.stderr.write(("emerge: %s access would be " + \
5560 "required.\n\n") % access_desc)
5561 if portage.secpass < 1 and not need_superuser:
5562 portage_group_warning()
5565 disable_emergelog = False
5566 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5568 disable_emergelog = True
5570 if myaction in ("search", "info"):
5571 disable_emergelog = True
5572 if disable_emergelog:
5573 """ Disable emergelog for everything except build or unmerge
5574 operations. This helps minimize parallel emerge.log entries that can
5575 confuse log parsers. We especially want it disabled during
5576 parallel-fetch, which uses --resume --fetchonly."""
5578 def emergelog(*pargs, **kargs):
5581 if not "--pretend" in myopts:
5582 emergelog(xterm_titles, "Started emerge on: "+\
5583 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5586 myelogstr=" ".join(myopts)
5588 myelogstr+=" "+myaction
5590 myelogstr+=" "+" ".join(myfiles)
5591 emergelog(xterm_titles, " *** emerge " + myelogstr)
5593 def emergeexitsig(signum, frame):
5594 signal.signal(signal.SIGINT, signal.SIG_IGN)
5595 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5596 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5597 sys.exit(100+signum)
5598 signal.signal(signal.SIGINT, emergeexitsig)
5599 signal.signal(signal.SIGTERM, emergeexitsig)
5602 """This gets out final log message in before we quit."""
5603 if "--pretend" not in myopts:
5604 emergelog(xterm_titles, " *** terminating.")
5605 if "notitles" not in settings.features:
5607 portage.atexit_register(emergeexit)
5609 if myaction in ("config", "metadata", "regen", "sync"):
5610 if "--pretend" in myopts:
5611 sys.stderr.write(("emerge: The '%s' action does " + \
5612 "not support '--pretend'.\n") % myaction)
5614 if "sync" == myaction:
5615 action_sync(settings, trees, mtimedb, myopts, myaction)
5616 elif "metadata" == myaction:
5617 action_metadata(settings, portdb, myopts)
5618 elif myaction=="regen":
5619 validate_ebuild_environment(trees)
5620 action_regen(settings, portdb)
5622 elif "config"==myaction:
5623 validate_ebuild_environment(trees)
5624 action_config(settings, trees, myopts, myfiles)
5627 elif "info"==myaction:
5628 action_info(settings, trees, myopts, myfiles)
5631 elif "search"==myaction:
5632 validate_ebuild_environment(trees)
5633 action_search(settings, portdb, trees["/"]["vartree"],
5634 myopts, myfiles, spinner)
5635 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5636 validate_ebuild_environment(trees)
5637 vartree = trees[settings["ROOT"]]["vartree"]
5638 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5640 if "--pretend" not in myopts:
5641 post_emerge(settings, mtimedb, 0)
5643 elif "depclean"==myaction:
5644 validate_ebuild_environment(trees)
5645 action_depclean(settings, trees, mtimedb["ldpath"],
5647 if "--pretend" not in myopts:
5648 post_emerge(settings, mtimedb, 0)
5649 # "update", "system", or just process files:
5651 validate_ebuild_environment(trees)
5652 if "--pretend" not in myopts:
5653 display_news_notification(settings)
5654 action_build(settings, trees, mtimedb,
5655 myopts, myaction, myfiles, spinner)
5656 if "--pretend" not in myopts:
5657 post_emerge(settings, mtimedb, 0)
5659 display_news_notification(settings)
5661 if __name__ == "__main__":
5662 retval = emerge_main()