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
52 from portage.util import writemsg
54 if not hasattr(__builtins__, "set"):
55 from sets import Set as set
56 from itertools import chain, izip
57 from UserDict import DictMixin
62 import pickle as cPickle
64 class stdout_spinner(object):
66 "Gentoo Rocks ("+os.uname()[0]+")",
67 "Thank you for using Gentoo. :)",
68 "Are you actually trying to read this?",
69 "How many times have you stared at this?",
70 "We are generating the cache right now",
71 "You are paying too much attention.",
72 "A theory is better than its explanation.",
73 "Phasers locked on target, Captain.",
74 "Thrashing is just virtual crashing.",
75 "To be is to program.",
76 "Real Users hate Real Programmers.",
77 "When all else fails, read the instructions.",
78 "Functionality breeds Contempt.",
79 "The future lies ahead.",
80 "3.1415926535897932384626433832795028841971694",
81 "Sometimes insanity is the only alternative.",
82 "Inaccuracy saves a world of explanation.",
85 twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
89 self.update = self.update_twirl
90 self.scroll_sequence = self.scroll_msgs[
91 int(time.time() * 100) % len(self.scroll_msgs)]
93 def update_basic(self):
94 self.spinpos = (self.spinpos + 1) % 500
95 if (self.spinpos % 100) == 0:
97 sys.stdout.write(". ")
102 def update_scroll(self):
103 if(self.spinpos >= len(self.scroll_sequence)):
104 sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
105 len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
107 sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
109 self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
111 def update_twirl(self):
112 self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
113 sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
116 def update_quiet(self):
119 def userquery(prompt, responses=None, colours=None):
120 """Displays a prompt and a set of responses, then waits for a response
121 which is checked against the responses and the first to match is
122 returned. An empty response will match the first value in responses. The
123 input buffer is *not* cleared prior to the prompt!
126 responses: a List of Strings.
127 colours: a List of Functions taking and returning a String, used to
128 process the responses for display. Typically these will be functions
129 like red() but could be e.g. lambda x: "DisplayString".
130 If responses is omitted, defaults to ["Yes", "No"], [green, red].
131 If only colours is omitted, defaults to [bold, ...].
133 Returns a member of the List responses. (If called without optional
134 arguments, returns "Yes" or "No".)
135 KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
137 if responses is None:
138 responses, colours = ["Yes", "No"], [green, red]
139 elif colours is None:
141 colours=(colours*len(responses))[:len(responses)]
145 response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
146 for key in responses:
147 # An empty response will match the first value in responses.
148 if response.upper()==key[:len(response)].upper():
150 print "Sorry, response '%s' not understood." % response,
151 except (EOFError, KeyboardInterrupt):
156 "clean", "config", "depclean",
158 "prune", "regen", "search",
159 "sync", "system", "unmerge", "world",
162 "--ask", "--alphabetical",
163 "--buildpkg", "--buildpkgonly",
164 "--changelog", "--columns",
168 "--fetchonly", "--fetch-all-uri",
169 "--getbinpkg", "--getbinpkgonly",
170 "--help", "--ignore-default-opts",
172 "--newuse", "--nocolor",
173 "--nodeps", "--noreplace",
174 "--nospinner", "--oneshot",
175 "--onlydeps", "--pretend",
176 "--quiet", "--resume",
177 "--searchdesc", "--selective",
181 "--usepkg", "--usepkgonly",
182 "--verbose", "--version"
188 "b":"--buildpkg", "B":"--buildpkgonly",
189 "c":"--clean", "C":"--unmerge",
190 "d":"--debug", "D":"--deep",
192 "f":"--fetchonly", "F":"--fetch-all-uri",
193 "g":"--getbinpkg", "G":"--getbinpkgonly",
195 "k":"--usepkg", "K":"--usepkgonly",
197 "n":"--noreplace", "N":"--newuse",
198 "o":"--onlydeps", "O":"--nodeps",
199 "p":"--pretend", "P":"--prune",
201 "s":"--search", "S":"--searchdesc",
204 "v":"--verbose", "V":"--version"
207 def emergelog(xterm_titles, mystr, short_msg=None):
209 if short_msg == None:
211 if "HOSTNAME" in os.environ.keys():
212 short_msg = os.environ["HOSTNAME"]+": "+short_msg
213 xtermTitle(short_msg)
215 file_path = "/var/log/emerge.log"
216 mylogfile = open(file_path, "a")
217 portage.util.apply_secpass_permissions(file_path,
218 uid=portage.portage_uid, gid=portage.portage_gid,
222 mylock = portage.locks.lockfile(mylogfile)
223 # seek because we may have gotten held up by the lock.
224 # if so, we may not be positioned at the end of the file.
226 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
230 portage.locks.unlockfile(mylock)
232 except (IOError,OSError,portage.exception.PortageException), e:
234 print >> sys.stderr, "emergelog():",e
236 def countdown(secs=5, doing="Starting"):
238 print ">>> Waiting",secs,"seconds before starting..."
239 print ">>> (Control-C to abort)...\n"+doing+" in: ",
243 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
248 # formats a size given in bytes nicely
249 def format_size(mysize):
250 if type(mysize) not in [types.IntType,types.LongType]:
252 if 0 != mysize % 1024:
253 # Always round up to the next kB so that it doesn't show 0 kB when
254 # some small file still needs to be fetched.
255 mysize += 1024 - mysize % 1024
256 mystr=str(mysize/1024)
260 mystr=mystr[:mycount]+","+mystr[mycount:]
264 def getgccversion(chost):
267 return: the current in-use gcc version
270 gcc_ver_command = 'gcc -dumpversion'
271 gcc_ver_prefix = 'gcc-'
273 gcc_not_found_error = red(
274 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
275 "!!! to update the environment of this terminal and possibly\n" +
276 "!!! other terminals also.\n"
279 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
280 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
281 part1, part2 = myoutput.split("/")
282 if part1.startswith(chost + "-"):
283 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
285 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
286 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
287 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
289 mystatus, myoutput = commands.getstatusoutput(
290 chost + "-" + gcc_ver_command)
291 if mystatus == os.EX_OK:
292 return gcc_ver_prefix + myoutput
294 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
295 if mystatus == os.EX_OK:
296 return gcc_ver_prefix + myoutput
298 portage.writemsg(gcc_not_found_error, noiselevel=-1)
299 return "[unavailable]"
301 def getportageversion(portdir, target_root, profile, chost, vardb):
302 profilever = "unavailable"
304 realpath = os.path.realpath(profile)
305 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
306 if realpath.startswith(basepath):
307 profilever = realpath[1 + len(basepath):]
310 profilever = "!" + os.readlink(profile)
313 del realpath, basepath
316 libclist = vardb.match("virtual/libc")
317 libclist += vardb.match("virtual/glibc")
318 libclist = portage.util.unique_array(libclist)
320 xs=portage.catpkgsplit(x)
322 libcver+=","+"-".join(xs[1:])
324 libcver="-".join(xs[1:])
326 libcver="unavailable"
328 gccver = getgccversion(chost)
329 unameout=os.uname()[2]+" "+os.uname()[4]
331 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
333 def create_depgraph_params(myopts, myaction):
334 #configure emerge engine parameters
336 # self: include _this_ package regardless of if it is merged.
337 # selective: exclude the package if it is merged
338 # recurse: go into the dependencies
339 # deep: go into the dependencies of already merged packages
340 # empty: pretend nothing is merged
341 myparams = ["recurse"]
344 if "--update" in myopts or \
345 "--newuse" in myopts or \
346 "--noreplace" in myopts or \
347 myaction in ("system", "world"):
348 add.extend(["selective"])
349 if "--emptytree" in myopts:
350 add.extend(["empty"])
351 sub.extend(["selective"])
352 if "--nodeps" in myopts:
353 sub.extend(["recurse"])
354 if "--deep" in myopts:
357 if (x not in myparams) and (x not in sub):
364 # search functionality
376 def __init__(self, settings, portdb, vartree, spinner, searchdesc,
378 """Searches the available and installed packages for the supplied search key.
379 The list of available and installed packages is created at object instantiation.
380 This makes successive searches faster."""
381 self.settings = settings
383 self.vartree = vartree
384 self.spinner = spinner
385 self.verbose = verbose
386 self.searchdesc = searchdesc
388 def execute(self,searchkey):
389 """Performs the search for the supplied search key"""
391 self.searchkey=searchkey
392 self.packagematches = []
395 self.matches = {"pkg":[], "desc":[]}
398 self.matches = {"pkg":[]}
399 print "Searching... ",
402 if self.searchkey.startswith('%'):
404 self.searchkey = self.searchkey[1:]
405 if self.searchkey.startswith('@'):
407 self.searchkey = self.searchkey[1:]
409 self.searchre=re.compile(self.searchkey,re.I)
411 self.searchre=re.compile(re.escape(self.searchkey), re.I)
412 for package in self.portdb.cp_all():
413 self.spinner.update()
416 match_string = package[:]
418 match_string = package.split("/")[-1]
421 if self.searchre.search(match_string):
422 if not self.portdb.xmatch("match-visible", package):
424 self.matches["pkg"].append([package,masked])
425 elif self.searchdesc: # DESCRIPTION searching
426 full_package = self.portdb.xmatch("bestmatch-visible", package)
428 #no match found; we don't want to query description
429 full_package = portage.best(
430 self.portdb.xmatch("match-all", package))
436 full_desc = self.portdb.aux_get(
437 full_package, ["DESCRIPTION"])[0]
439 print "emerge: search: aux_get() failed, skipping"
441 if self.searchre.search(full_desc):
442 self.matches["desc"].append([full_package,masked])
444 for mtype in self.matches.keys():
445 self.matches[mtype].sort()
446 self.mlen += len(self.matches[mtype])
449 """Outputs the results of the search."""
450 print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
451 print "[ Applications found : "+white(str(self.mlen))+" ]"
453 for mtype in self.matches.keys():
454 for match,masked in self.matches[mtype]:
457 full_package = self.portdb.xmatch(
458 "bestmatch-visible", match)
460 #no match found; we don't want to query description
462 full_package = portage.best(
463 self.portdb.xmatch("match-all",match))
466 match = portage.pkgsplit(match)[0]
470 desc, homepage, license = self.portdb.aux_get(
471 full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
473 print "emerge: search: aux_get() failed, skipping"
476 print green("*")+" "+white(match)+" "+red("[ Masked ]")
478 print green("*")+" "+white(match)
479 myversion = self.getVersion(full_package, search.VERSION_RELEASE)
482 mycat = match.split("/")[0]
483 mypkg = match.split("/")[1]
484 mycpv = match + "-" + myversion
485 myebuild = self.portdb.findname(mycpv)
486 pkgdir = os.path.dirname(myebuild)
487 from portage import manifest
488 mf = manifest.Manifest(
489 pkgdir, self.settings["DISTDIR"])
490 fetchlist = self.portdb.getfetchlist(mycpv,
491 mysettings=self.settings, all=True)[1]
493 mysum[0] = mf.getDistfilesSize(fetchlist)
494 mystr = str(mysum[0]/1024)
498 mystr=mystr[:mycount]+","+mystr[mycount:]
501 mysum[0] = "Unknown (missing digest for %s)" % str(e)
504 print " ", darkgreen("Latest version available:"),myversion
505 print " ", self.getInstallationStatus(mycat+'/'+mypkg)
506 print " ", darkgreen("Size of files:"),mysum[0]
507 print " ", darkgreen("Homepage:")+" ",homepage
508 print " ", darkgreen("Description:")+" ",desc
509 print " ", darkgreen("License:")+" ",license
515 def getInstallationStatus(self,package):
516 installed_package = self.vartree.dep_bestmatch(package)
518 version = self.getVersion(installed_package,search.VERSION_RELEASE)
520 result = darkgreen("Latest version installed:")+" "+version
522 result = darkgreen("Latest version installed:")+" [ Not Installed ]"
525 def getVersion(self,full_package,detail):
526 if len(full_package) > 1:
527 package_parts = portage.catpkgsplit(full_package)
528 if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
529 result = package_parts[2]+ "-" + package_parts[3]
531 result = package_parts[2]
537 #build our package digraph
538 def getlist(settings, mode):
540 mylines = settings.packages
543 file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
544 myfile = open(file_path, "r")
545 mylines = myfile.readlines()
547 except (OSError, IOError), e:
548 if e.errno == errno.ENOENT:
549 portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
555 myline=" ".join(x.split())
564 mynewlines.append(myline.strip())
568 def clean_world(vardb, cpv):
569 """Remove a package from the world file when unmerged."""
570 world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
571 worldlist = portage.util.grabfile(world_filename)
572 mykey = portage.cpv_getkey(cpv)
575 if portage.dep_getkey(x) == mykey:
576 matches = vardb.match(x, use_cache=0)
580 elif len(matches) == 1 and matches[0] == cpv:
584 #others are around; keep it.
585 newworldlist.append(x)
587 #this doesn't match the package we're unmerging; keep it.
588 newworldlist.append(x)
590 portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
591 gid=portage.portage_gid, mode=02770)
592 portage.util.write_atomic(world_filename, "\n".join(newworldlist))
594 def genericdict(mylist):
597 mynewdict[portage.dep_getkey(x)]=x
600 def filter_iuse_defaults(iuse):
602 if flag.startswith("+") or flag.startswith("-"):
607 class DepPriority(object):
609 This class generates an integer priority level based of various
610 attributes of the dependency relationship. Attributes can be assigned
611 at any time and the new integer value will be generated on calls to the
612 __int__() method. Rich comparison operators are supported.
614 The boolean attributes that affect the integer value are "satisfied",
615 "buildtime", "runtime", and "system". Various combinations of
616 attributes lead to the following priority levels:
618 Combination of properties Priority level
620 not satisfied and buildtime 0
621 not satisfied and runtime -1
622 satisfied and buildtime -2
623 satisfied and runtime -3
624 (none of the above) -4
626 Several integer constants are defined for categorization of priority
629 MEDIUM The upper boundary for medium dependencies.
630 SOFT The upper boundary for soft dependencies.
631 MIN The lower boundary for soft dependencies.
633 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
637 def __init__(self, **kwargs):
638 for myattr in self.__slots__:
639 if myattr == "__weakref__":
641 myvalue = kwargs.get(myattr, False)
642 setattr(self, myattr, myvalue)
644 if not self.satisfied:
654 def __lt__(self, other):
655 return self.__int__() < other
656 def __le__(self, other):
657 return self.__int__() <= other
658 def __eq__(self, other):
659 return self.__int__() == other
660 def __ne__(self, other):
661 return self.__int__() != other
662 def __gt__(self, other):
663 return self.__int__() > other
664 def __ge__(self, other):
665 return self.__int__() >= other
668 return copy.copy(self)
670 myvalue = self.__int__()
671 if myvalue > self.MEDIUM:
673 if myvalue > self.SOFT:
677 class FakeVartree(portage.vartree):
678 """This is implements an in-memory copy of a vartree instance that provides
679 all the interfaces required for use by the depgraph. The vardb is locked
680 during the constructor call just long enough to read a copy of the
681 installed package information. This allows the depgraph to do it's
682 dependency calculations without holding a lock on the vardb. It also
683 allows things like vardb global updates to be done in memory so that the
684 user doesn't necessarily need write access to the vardb in cases where
685 global updates are necessary (updates are performed when necessary if there
686 is not a matching ebuild in the tree)."""
687 def __init__(self, real_vartree, portdb):
688 self.root = real_vartree.root
689 self.settings = real_vartree.settings
690 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
691 vdb_path = os.path.join(self.root, portage.VDB_PATH)
693 # At least the parent needs to exist for the lock file.
694 portage.util.ensure_dirs(vdb_path)
695 except portage.exception.PortageException:
699 if os.access(vdb_path, os.W_OK):
700 vdb_lock = portage.locks.lockdir(vdb_path)
701 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
702 "DEPEND", "RDEPEND", "PDEPEND"]
703 real_dbapi = real_vartree.dbapi
705 for cpv in real_dbapi.cpv_all():
706 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
707 myslot = metadata["SLOT"]
708 mycp = portage.dep_getkey(cpv)
709 myslot_atom = "%s:%s" % (mycp, myslot)
711 mycounter = long(metadata["COUNTER"])
714 metadata["COUNTER"] = str(mycounter)
715 other_counter = slot_counters.get(myslot_atom, None)
716 if other_counter is not None:
717 if other_counter > mycounter:
719 slot_counters[myslot_atom] = mycounter
720 self.dbapi.cpv_inject(cpv, metadata=metadata)
721 real_dbapi.flush_cache()
724 portage.locks.unlockdir(vdb_lock)
725 # Populate the old-style virtuals using the cached values.
726 if not self.settings.treeVirtuals:
727 self.settings.treeVirtuals = portage.util.map_dictlist_vals(
728 portage.getCPFromCPV, self.get_all_provides())
730 # Intialize variables needed for lazy cache pulls of the live ebuild
731 # metadata. This ensures that the vardb lock is released ASAP, without
732 # being delayed in case cache generation is triggered.
733 self._aux_get = self.dbapi.aux_get
734 self.dbapi.aux_get = self._aux_get_wrapper
735 self._aux_get_history = set()
736 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
737 self._portdb = portdb
738 self._global_updates = None
740 def _aux_get_wrapper(self, pkg, wants):
741 if pkg in self._aux_get_history:
742 return self._aux_get(pkg, wants)
743 self._aux_get_history.add(pkg)
745 # Use the live ebuild metadata if possible.
746 live_metadata = dict(izip(self._portdb_keys,
747 self._portdb.aux_get(pkg, self._portdb_keys)))
748 self.dbapi.aux_update(pkg, live_metadata)
749 except (KeyError, portage.exception.PortageException):
750 if self._global_updates is None:
751 self._global_updates = \
752 grab_global_updates(self._portdb.porttree_root)
753 perform_global_updates(
754 pkg, self.dbapi, self._global_updates)
755 return self._aux_get(pkg, wants)
757 def grab_global_updates(portdir):
758 from portage.update import grab_updates, parse_updates
759 updpath = os.path.join(portdir, "profiles", "updates")
761 rawupdates = grab_updates(updpath)
762 except portage.exception.DirectoryNotFound:
765 for mykey, mystat, mycontent in rawupdates:
766 commands, errors = parse_updates(mycontent)
767 upd_commands.extend(commands)
770 def perform_global_updates(mycpv, mydb, mycommands):
771 from portage.update import update_dbentries
772 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
773 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
774 updates = update_dbentries(mycommands, aux_dict)
776 mydb.aux_update(mycpv, updates)
778 class BlockerCache(DictMixin):
779 """This caches blockers of installed packages so that dep_check does not
780 have to be done for every single installed package on every invocation of
781 emerge. The cache is invalidated whenever it is detected that something
782 has changed that might alter the results of dep_check() calls:
783 1) the set of installed packages (including COUNTER) has changed
784 2) the old-style virtuals have changed
786 class BlockerData(object):
787 def __init__(self, counter, atoms):
788 self.counter = counter
791 def __init__(self, myroot, vardb):
793 self._installed_pkgs = set(vardb.cpv_all())
794 self._virtuals = vardb.settings.getvirtuals()
795 self._cache_filename = os.path.join(myroot,
796 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
797 self._cache_version = "1"
798 self._cache_data = None
799 self._modified = False
804 f = open(self._cache_filename)
805 mypickle = cPickle.Unpickler(f)
806 mypickle.find_global = None
807 self._cache_data = mypickle.load()
810 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
812 cache_valid = self._cache_data and \
813 isinstance(self._cache_data, dict) and \
814 self._cache_data.get("version") == self._cache_version and \
815 self._cache_data.get("virtuals") == self._virtuals and \
816 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
818 for pkg in self._installed_pkgs:
819 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
824 self._cache_data = {"version":self._cache_version}
825 self._cache_data["blockers"] = {}
826 self._cache_data["virtuals"] = self._virtuals
827 self._modified = False
830 """If the current user has permission and the internal blocker cache
831 been updated, save it to disk and mark it unmodified. This is called
832 by emerge after it has proccessed blockers for all installed packages.
833 Currently, the cache is only written if the user has superuser
834 privileges (since that's required to obtain a lock), but all users
835 have read access and benefit from faster blocker lookups (as long as
836 the entire cache is still valid). The cache is stored as a pickled
837 dict object with the following format:
841 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
842 "virtuals" : vardb.settings.getvirtuals()
845 if self._modified and \
848 f = portage.util.atomic_ofstream(self._cache_filename)
849 cPickle.dump(self._cache_data, f, -1)
851 portage.util.apply_secpass_permissions(
852 self._cache_filename, gid=portage.portage_gid, mode=0644)
853 except (IOError, OSError), e:
855 self._modified = False
857 def __setitem__(self, cpv, blocker_data):
859 Update the cache and mark it as modified for a future call to
862 @param cpv: Package for which to cache blockers.
864 @param blocker_data: An object with counter and atoms attributes.
865 @type blocker_data: BlockerData
867 self._cache_data["blockers"][cpv] = \
868 (blocker_data.counter, blocker_data.atoms)
869 self._modified = True
871 def __getitem__(self, cpv):
874 @returns: An object with counter and atoms attributes.
876 return self.BlockerData(*self._cache_data["blockers"][cpv])
878 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
880 from formatter import AbstractFormatter, DumbWriter
881 f = AbstractFormatter(DumbWriter(maxcol=72))
883 print "\n\n!!! Invalid or corrupt dependency specification: "
891 p_type, p_root, p_key, p_status = parent_node
893 if p_status == "nomerge":
894 category, pf = portage.catsplit(p_key)
895 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
896 msg.append("Portage is unable to process the dependencies of the ")
897 msg.append("'%s' package. " % p_key)
898 msg.append("In order to correct this problem, the package ")
899 msg.append("should be uninstalled, reinstalled, or upgraded. ")
900 msg.append("As a temporary workaround, the --nodeps option can ")
901 msg.append("be used to ignore all dependencies. For reference, ")
902 msg.append("the problematic dependencies can be found in the ")
903 msg.append("*DEPEND files located in '%s/'." % pkg_location)
905 msg.append("This package can not be installed. ")
906 msg.append("Please notify the '%s' package maintainer " % p_key)
907 msg.append("about this problem.")
910 f.add_flowing_data(x)
918 "installed":"vartree"}
920 def __init__(self, settings, trees, myopts, myparams, spinner):
921 self.settings = settings
922 self.target_root = settings["ROOT"]
924 self.myparams = myparams
926 if settings.get("PORTAGE_DEBUG", "") == "1":
928 self.spinner = spinner
929 self.pkgsettings = {}
930 # Maps cpv to digraph node for all nodes added to the graph.
931 self.pkg_node_map = {}
932 # Maps slot atom to digraph node for all nodes added to the graph.
933 self._slot_node_map = {}
935 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
939 self.trees[myroot] = {}
940 for tree in ("porttree", "bintree"):
941 self.trees[myroot][tree] = trees[myroot][tree]
942 self.trees[myroot]["vartree"] = \
943 FakeVartree(trees[myroot]["vartree"],
944 trees[myroot]["porttree"].dbapi)
945 self.pkgsettings[myroot] = portage.config(
946 clone=self.trees[myroot]["vartree"].settings)
947 self.pkg_node_map[myroot] = {}
948 self._slot_node_map[myroot] = {}
949 vardb = self.trees[myroot]["vartree"].dbapi
950 # This fakedbapi instance will model the state that the vdb will
951 # have after new packages have been installed.
952 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
953 self.mydbapi[myroot] = fakedb
954 if "--nodeps" not in self.myopts and \
955 "--buildpkgonly" not in self.myopts:
956 # --nodeps bypasses this, since it isn't needed in this case
957 # and the cache pulls might trigger (slow) cache generation.
958 for pkg in vardb.cpv_all():
959 self.spinner.update()
960 fakedb.cpv_inject(pkg,
961 metadata=dict(izip(self._mydbapi_keys,
962 vardb.aux_get(pkg, self._mydbapi_keys))))
964 self.useFlags[myroot] = {}
965 if "--usepkg" in self.myopts:
966 self.trees[myroot]["bintree"].populate(
967 "--getbinpkg" in self.myopts,
968 "--getbinpkgonly" in self.myopts)
972 self.digraph=portage.digraph()
973 # Tracks simple parent/child relationships (PDEPEND relationships are
975 self._parent_child_digraph = digraph()
977 self.outdatedpackages=[]
979 self.blocker_digraph = digraph()
980 self.blocker_parents = {}
981 self._unresolved_blocker_parents = {}
982 self._slot_collision_info = []
983 # Slot collision nodes are not allowed to block other packages since
984 # blocker validation is only able to account for one package per slot.
985 self._slot_collision_nodes = set()
986 self._altlist_cache = {}
987 self._pprovided_args = []
989 def _show_slot_collision_notice(self, packages):
990 """Show an informational message advising the user to mask one of the
991 the packages. In some cases it may be possible to resolve this
992 automatically, but support for backtracking (removal nodes that have
993 already been selected) will be required in order to handle all possible
997 msg.append("\n!!! Multiple versions within a single " + \
998 "package slot have been \n")
999 msg.append("!!! pulled into the dependency graph:\n\n")
1000 for node, parents in packages:
1001 msg.append(str(node))
1003 msg.append(" pulled in by\n")
1004 for parent in parents:
1006 msg.append(str(parent))
1009 msg.append(" (no parents)\n")
1011 sys.stderr.write("".join(msg))
1014 if "--quiet" in self.myopts:
1018 msg.append("It may be possible to solve this problem ")
1019 msg.append("by using package.mask to prevent one of ")
1020 msg.append("those packages from being selected. ")
1021 msg.append("However, it is also possible that conflicting ")
1022 msg.append("dependencies exist such that they are impossible to ")
1023 msg.append("satisfy simultaneously. If such a conflict exists in ")
1024 msg.append("the dependencies of two different packages, then those ")
1025 msg.append("packages can not be installed simultaneously.")
1027 from formatter import AbstractFormatter, DumbWriter
1028 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1030 f.add_flowing_data(x)
1034 msg.append("For more information, see MASKED PACKAGES ")
1035 msg.append("section in the emerge man page or refer ")
1036 msg.append("to the Gentoo Handbook.")
1038 f.add_flowing_data(x)
1042 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1043 priority=DepPriority(), rev_dep=False, arg=None):
1045 Fills the digraph with nodes comprised of packages to merge.
1046 mybigkey is the package spec of the package to merge.
1047 myparent is the package depending on mybigkey ( or None )
1048 addme = Should we add this package to the digraph or are we just looking at it's deps?
1049 Think --onlydeps, we need to ignore packages in that case.
1052 #IUSE-aware emerge -> USE DEP aware depgraph
1053 #"no downgrade" emerge
1055 mytype, myroot, mykey = mybigkey
1056 existing_node = None
1058 existing_node = self.pkg_node_map[myroot].get(mykey)
1060 self._parent_child_digraph.add(existing_node, myparent)
1061 if existing_node != myparent:
1062 # Refuse to make a node depend on itself so that the we don't
1063 # don't create a bogus circular dependency in self.altlist().
1064 if rev_dep and myparent:
1065 self.digraph.addnode(myparent, existing_node,
1068 self.digraph.addnode(existing_node, myparent,
1072 if "--nodeps" not in self.myopts:
1073 self.spinner.update()
1074 if mytype == "blocks":
1076 "--buildpkgonly" not in self.myopts and \
1077 "--nodeps" not in self.myopts and \
1078 myparent not in self._slot_collision_nodes:
1079 mybigkey[1] = myparent[1]
1080 self.blocker_parents.setdefault(
1081 tuple(mybigkey), set()).add(myparent)
1083 if not arg and myroot == self.target_root:
1084 arg = portage.best_match_to_list(mykey, self.args_keys)
1085 # select the correct /var database that we'll be checking against
1086 vardbapi = self.trees[myroot]["vartree"].dbapi
1087 portdb = self.trees[myroot]["porttree"].dbapi
1088 bindb = self.trees[myroot]["bintree"].dbapi
1089 pkgsettings = self.pkgsettings[myroot]
1091 # if the package is already on the system, we add a "nomerge"
1092 # directive, otherwise we add a "merge" directive.
1094 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1097 self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
1098 myuse = self.pkgsettings[myroot]["USE"].split()
1101 if mytype == "installed":
1103 if addme and mytype != "installed":
1104 # this is where we add the node to the list of packages to merge
1105 if "selective" in self.myparams or not arg:
1106 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1109 """ If we aren't merging, perform the --newuse check.
1110 If the package has new iuse flags or different use flags then if
1111 --newuse is specified, we need to merge the package. """
1112 if merging==0 and "--newuse" in self.myopts and \
1113 vardbapi.cpv_exists(mykey):
1114 pkgsettings.setcpv(mykey, mydb=mydbapi)
1115 forced_flags = set()
1116 forced_flags.update(pkgsettings.useforce)
1117 forced_flags.update(pkgsettings.usemask)
1118 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1119 iuses = set(filter_iuse_defaults(
1120 mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
1121 old_iuse = set(filter_iuse_defaults(
1122 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1123 if iuses.symmetric_difference(
1124 old_iuse).difference(forced_flags):
1126 elif old_iuse.intersection(old_use) != \
1127 iuses.intersection(myuse):
1130 if addme and merging == 1:
1131 mybigkey.append("merge")
1133 mybigkey.append("nomerge")
1134 jbigkey = tuple(mybigkey)
1137 metadata = dict(izip(self._mydbapi_keys,
1138 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1139 if merging == 0 and vardbapi.cpv_exists(mykey) and \
1140 mytype != "installed":
1141 mybigkey[0] = "installed"
1143 jbigkey = tuple(mybigkey)
1144 metadata = dict(izip(self._mydbapi_keys,
1145 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1146 myuse = mydbapi.aux_get(mykey, ["USE"])[0].split()
1147 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1148 existing_node = self._slot_node_map[myroot].get(
1150 slot_collision = False
1152 e_type, myroot, e_cpv, e_status = existing_node
1154 # The existing node can be reused.
1155 self._parent_child_digraph.add(existing_node, myparent)
1156 if rev_dep and myparent:
1157 ptype, proot, pkey, pstatus = myparent
1158 self.digraph.addnode(myparent, existing_node,
1161 self.digraph.addnode(existing_node, myparent,
1165 # A slot collision has occurred. Sometimes this coincides
1166 # with unresolvable blockers, so the slot collision will be
1167 # shown later if there are no unresolvable blockers.
1168 e_parents = self._parent_child_digraph.parent_nodes(
1172 myparents.append(myparent)
1173 self._slot_collision_info.append(
1174 ((jbigkey, myparents), (existing_node, e_parents)))
1175 self._slot_collision_nodes.add(jbigkey)
1176 slot_collision = True
1179 # Now add this node to the graph so that self.display()
1180 # can show use flags and --tree portage.output. This node is
1181 # only being partially added to the graph. It must not be
1182 # allowed to interfere with the other nodes that have been
1183 # added. Do not overwrite data for existing nodes in
1184 # self.pkg_node_map and self.mydbapi since that data will
1185 # be used for blocker validation.
1186 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1187 self.useFlags[myroot].setdefault(mykey, myuse)
1188 # Even though the graph is now invalid, continue to process
1189 # dependencies so that things like --fetchonly can still
1190 # function despite collisions.
1192 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1193 self._slot_node_map[myroot][slot_atom] = jbigkey
1194 self.pkg_node_map[myroot][mykey] = jbigkey
1195 self.useFlags[myroot][mykey] = myuse
1197 if rev_dep and myparent:
1198 self.digraph.addnode(myparent, jbigkey,
1201 self.digraph.addnode(jbigkey, myparent,
1204 # Do this even when addme is False (--onlydeps) so that the
1205 # parent/child relationship is always known in case
1206 # self._show_slot_collision_notice() needs to be called later.
1207 self._parent_child_digraph.add(jbigkey, myparent)
1209 """ This section determines whether we go deeper into dependencies or not.
1210 We want to go deeper on a few occasions:
1211 Installing package A, we need to make sure package A's deps are met.
1212 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1213 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1215 if "deep" not in self.myparams and not merging and \
1216 not ("--update" in self.myopts and arg and merging):
1218 elif "recurse" not in self.myparams:
1221 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1222 Pull from bintree if it's binary package, porttree if it's ebuild.
1223 Binpkg's can be either remote or local. """
1226 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1227 depvalues = mydbapi.aux_get(mykey, depkeys)
1228 for i in xrange(len(depkeys)):
1229 edepend[depkeys[i]] = depvalues[i]
1231 if mytype == "ebuild":
1232 if "--buildpkgonly" in self.myopts:
1233 edepend["RDEPEND"] = ""
1234 edepend["PDEPEND"] = ""
1235 if not (arg and "--onlydeps" in self.myopts and \
1236 mytype == "ebuild") and \
1237 self.myopts.get("--with-bdeps", "n") == "n" and \
1238 (mytype == "binary" or mybigkey[3] == "nomerge"):
1239 edepend["DEPEND"] = ""
1241 """ We have retrieve the dependency information, now we need to recursively
1242 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1244 mp = tuple(mybigkey)
1247 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1248 myuse=myuse, priority=DepPriority(buildtime=True),
1251 """RDEPEND is soft by definition. However, in order to ensure
1252 correct merge order, we make it a hard dependency. Otherwise, a
1253 build time dependency might not be usable due to it's run time
1254 dependencies not being installed yet.
1256 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1257 myuse=myuse, priority=DepPriority(runtime=True),
1260 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1261 # Post Depend -- Add to the list without a parent, as it depends
1262 # on a package being present AND must be built after that package.
1263 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1264 myuse=myuse, priority=DepPriority(), rev_deps=True,
1267 except ValueError, e:
1269 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1270 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1272 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1273 portage.writemsg("\n", noiselevel=-1)
1274 if mytype == "binary":
1276 "!!! This binary package cannot be installed: '%s'\n" % \
1277 mykey, noiselevel=-1)
1278 elif mytype == "ebuild":
1279 myebuild, mylocation = portdb.findname2(mykey)
1280 portage.writemsg("!!! This ebuild cannot be installed: " + \
1281 "'%s'\n" % myebuild, noiselevel=-1)
1282 portage.writemsg("!!! Please notify the package maintainer " + \
1283 "that atoms must be fully-qualified.\n", noiselevel=-1)
1287 def select_files(self,myfiles):
1288 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1290 myroot = self.target_root
1291 portdb = self.trees[myroot]["porttree"].dbapi
1292 bindb = self.trees[myroot]["bintree"].dbapi
1293 pkgsettings = self.pkgsettings[myroot]
1295 def visible(mylist):
1296 matches = portdb.gvisible(portdb.visible(mylist))
1297 return [x for x in mylist \
1298 if x in matches or not portdb.cpv_exists(x)]
1300 ext = os.path.splitext(x)[1]
1302 if not os.path.exists(x):
1304 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1305 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1306 elif os.path.exists(
1307 os.path.join(pkgsettings["PKGDIR"], x)):
1308 x = os.path.join(pkgsettings["PKGDIR"], x)
1310 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1311 print "!!! Please ensure the tbz2 exists as specified.\n"
1313 mytbz2=portage.xpak.tbz2(x)
1314 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1315 if os.path.realpath(x) != \
1316 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1317 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1319 if not self.create(["binary", myroot, mykey],
1320 None, "--onlydeps" not in self.myopts):
1321 return (0,myfavorites)
1322 elif not "--oneshot" in self.myopts:
1323 myfavorites.append(mykey)
1324 elif ext==".ebuild":
1325 x = os.path.realpath(x)
1326 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1327 ebuild_path = portdb.findname(mykey)
1329 if os.path.realpath(ebuild_path) != x:
1330 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1332 if mykey not in portdb.xmatch(
1333 "match-visible", portage.dep_getkey(mykey)):
1334 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1335 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1336 print colorize("BAD", "*** page for details.")
1337 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1340 raise portage.exception.PackageNotFound(
1341 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1342 if not self.create(["ebuild", myroot, mykey],
1343 None, "--onlydeps" not in self.myopts):
1344 return (0,myfavorites)
1345 elif not "--oneshot" in self.myopts:
1346 myfavorites.append(mykey)
1348 if not is_valid_package_atom(x):
1349 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1351 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1352 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1356 if "--usepkg" in self.myopts:
1357 mykey = portage.dep_expand(x, mydb=bindb,
1358 settings=pkgsettings)
1359 if (mykey and not mykey.startswith("null/")) or \
1360 "--usepkgonly" in self.myopts:
1361 arg_atoms.append((x, mykey))
1364 mykey = portage.dep_expand(x,
1365 mydb=portdb, settings=pkgsettings)
1366 arg_atoms.append((x, mykey))
1367 except ValueError, errpkgs:
1368 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1369 print "!!! one of the following fully-qualified ebuild names instead:\n"
1370 for i in errpkgs[0]:
1371 print " " + green(i)
1375 if "--update" in self.myopts:
1376 """Make sure all installed slots are updated when possible. Do this
1377 with --emptytree also, to ensure that all slots are remerged."""
1378 vardb = self.trees[self.target_root]["vartree"].dbapi
1380 for myarg, myatom in arg_atoms:
1381 greedy_atoms.append((myarg, myatom))
1383 for cpv in vardb.match(myatom):
1384 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1387 if "--usepkg" in self.myopts:
1388 mymatches = bindb.match(myatom)
1389 if "--usepkgonly" not in self.myopts:
1390 mymatches = visible(mymatches)
1391 best_pkg = portage.best(mymatches)
1393 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1394 best_pkgs.append(("binary", best_pkg, best_slot))
1395 if "--usepkgonly" not in self.myopts:
1396 best_pkg = portage.best(portdb.match(myatom))
1398 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1399 best_pkgs.append(("ebuild", best_pkg, best_slot))
1401 best_pkg = portage.best([x[1] for x in best_pkgs])
1402 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1403 best_slot = best_pkgs[0][2]
1404 myslots.add(best_slot)
1405 if len(myslots) > 1:
1406 for myslot in myslots:
1407 myslot_atom = "%s:%s" % \
1408 (portage.dep_getkey(myatom), myslot)
1410 if "--usepkgonly" not in self.myopts and \
1411 self.trees[self.target_root][
1412 "porttree"].dbapi.match(myslot_atom):
1414 elif "--usepkg" in self.myopts:
1415 mymatches = bindb.match(myslot_atom)
1416 if "--usepkgonly" not in self.myopts:
1417 mymatches = visible(mymatches)
1421 greedy_atoms.append((myarg, myslot_atom))
1422 arg_atoms = greedy_atoms
1424 """ These are used inside self.create() in order to ensure packages
1425 that happen to match arguments are not incorrectly marked as nomerge."""
1426 self.args_keys = [x[1] for x in arg_atoms]
1427 for myarg, myatom in arg_atoms:
1429 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1430 except portage.exception.MissingSignature, e:
1431 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1432 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1433 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1434 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1435 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1437 except portage.exception.InvalidSignature, e:
1438 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1439 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1440 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1441 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1442 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1444 except SystemExit, e:
1445 raise # Needed else can't exit
1446 except Exception, e:
1447 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1448 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1452 return (0,myfavorites)
1453 elif not "--oneshot" in self.myopts:
1454 mykey = portage.dep_getkey(myatom)
1455 if mykey not in myfavorites:
1456 myfavorites.append(mykey)
1459 if "--usepkgonly" in self.myopts:
1460 for xs in self.digraph.all_nodes():
1461 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1465 print "Missing binary for:",xs[2]
1467 if not self.validate_blockers():
1468 return False, myfavorites
1470 # We're true here unless we are missing binaries.
1471 return (not missing,myfavorites)
1473 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1474 myuse=None, raise_on_missing=False, priority=DepPriority(),
1475 rev_deps=False, parent_arg=None):
1476 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1477 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1478 myparent = the node whose depstring is being passed in
1479 arg = package was specified on the command line, merge even if it's already installed
1480 myuse = USE flags at present
1481 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1482 else continue trying.
1483 return 1 on success, 0 for failure
1486 portdb = self.trees[myroot]["porttree"].dbapi
1487 bindb = self.trees[myroot]["bintree"].dbapi
1488 vardb = self.trees[myroot]["vartree"].dbapi
1489 pkgsettings = self.pkgsettings[myroot]
1491 p_type, p_root, p_key, p_status = myparent
1493 if "--debug" in self.myopts:
1495 print "Parent: ",myparent
1496 print "Depstring:",depstring
1498 print "Reverse:", rev_deps
1499 print "Priority:", priority
1501 #processing dependencies
1502 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1503 dependencies are satisfiable. """
1505 mymerge = [depstring]
1506 pprovided = pkgsettings.pprovideddict.get(
1507 portage.dep_getkey(depstring))
1508 if pprovided and portage.match_from_list(depstring, pprovided):
1512 if myparent and p_status == "nomerge":
1513 portage.dep._dep_check_strict = False
1514 mycheck = portage.dep_check(depstring, None,
1515 pkgsettings, myuse=myuse,
1516 use_binaries=("--usepkgonly" in self.myopts),
1517 myroot=myroot, trees=self.trees)
1519 portage.dep._dep_check_strict = True
1523 show_invalid_depstring_notice(
1524 myparent, depstring, mycheck[1])
1526 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1528 mymerge = mycheck[1]
1530 if not mymerge and arg and \
1531 portage.best_match_to_list(depstring, self.args_keys):
1532 # A provided package has been specified on the command line. The
1533 # package will not be merged and a warning will be displayed.
1534 self._pprovided_args.append(arg)
1537 # The parent is added after it's own dep_check call so that it
1538 # isn't allowed to satisfy a direct bootstrap dependency on itself
1539 # via an old-style virtual. This isn't a problem with new-style
1540 # virtuals, which are preferenced in dep_zapdeps by looking only at
1541 # the depstring, vdb, and available packages.
1543 p_type, p_root, p_key, p_status = myparent
1544 if p_status == "merge":
1545 # Update old-style virtuals if this package provides any.
1546 # These are needed for dep_virtual calls inside dep_check.
1547 p_db = self.trees[p_root][self.pkg_tree_map[p_type]].dbapi
1549 self.pkgsettings[p_root].setinst(p_key, p_db)
1550 except portage.exception.InvalidDependString, e:
1551 provide = p_db.aux_get(p_key, ["PROVIDE"])[0]
1552 show_invalid_depstring_notice(myparent, provide, str(e))
1556 if "--debug" in self.myopts:
1557 print "Candidates:",mymerge
1561 selected_pkg = ["blocks", myroot, x[1:], None]
1563 #We are not processing a blocker but a normal dependency
1565 """In some cases, dep_check will return deps that shouldn't
1566 be proccessed any further, so they are identified and
1568 if "empty" not in self.myparams and \
1569 "deep" not in self.myparams and \
1570 not ("--update" in self.myopts and parent_arg) and \
1574 # List of acceptable packages, ordered by type preference.
1575 matched_packages = []
1576 myeb_matches = portdb.xmatch("match-visible", x)
1578 if "--usepkgonly" not in self.myopts:
1579 myeb = portage.best(myeb_matches)
1582 if "--usepkg" in self.myopts:
1583 # The next line assumes the binarytree has been populated.
1584 # XXX: Need to work out how we use the binary tree with roots.
1585 myeb_pkg_matches = bindb.match(x)
1586 if "--usepkgonly" not in self.myopts:
1587 # Remove any binary package entries that are masked in the portage tree (#55871)
1588 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1589 if pkg in myeb_matches or \
1590 not portdb.cpv_exists(pkg)]
1591 if myeb_pkg_matches:
1592 myeb_pkg = portage.best(myeb_pkg_matches)
1594 if myeb_pkg and "--newuse" in self.myopts:
1595 iuses = set(filter_iuse_defaults(
1596 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1597 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1599 if "--usepkgonly" not in self.myopts and myeb:
1602 pkgsettings.setcpv(myeb, mydb=mydb)
1604 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1605 now_use = pkgsettings["USE"].split()
1606 forced_flags = set()
1607 forced_flags.update(pkgsettings.useforce)
1608 forced_flags.update(pkgsettings.usemask)
1610 if "--usepkgonly" not in self.myopts and myeb:
1611 cur_iuse = set(filter_iuse_defaults(
1612 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1613 if iuses.symmetric_difference(
1614 cur_iuse).difference(forced_flags):
1616 elif iuses.intersection(old_use) != \
1617 cur_iuse.intersection(now_use):
1621 self.trees[myroot]["bintree"].dbapi.aux_get(
1622 myeb_pkg, ["USE"])[0].split()
1623 matched_packages.append(
1624 ["binary", myroot, myeb_pkg, binpkguseflags])
1626 if "--usepkgonly" not in self.myopts and myeb_matches:
1627 matched_packages.append(
1628 ["ebuild", myroot, myeb, None])
1630 if not matched_packages and \
1631 not (arg and "selective" not in self.myparams):
1632 """Fall back to the installed package database. This is a
1633 last resort because the metadata tends to diverge from that
1634 of the ebuild in the tree."""
1635 myeb_inst_matches = vardb.match(x)
1636 if "--usepkgonly" not in self.myopts:
1637 """ TODO: Improve masking check for installed and
1638 binary packages. bug #149816"""
1639 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1640 if not portdb.cpv_exists(pkg)]
1642 if myeb_inst_matches:
1643 myeb_inst = portage.best(myeb_inst_matches)
1645 binpkguseflags = vardb.aux_get(
1646 myeb_inst, ["USE"])[0].split()
1647 matched_packages.append(
1648 ["installed", myroot, myeb_inst, binpkguseflags])
1650 if not matched_packages:
1651 if raise_on_missing:
1658 xfrom = '(dependency required by '+ \
1659 green('"%s"' % myparent[2]) + \
1660 red(' [%s]' % myparent[0]) + ')'
1661 alleb = portdb.xmatch("match-all", x)
1663 if "--usepkgonly" not in self.myopts:
1664 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1665 print "!!! One of the following masked packages is required to complete your request:"
1669 mreasons = portage.getmaskingstatus(p,
1670 settings=pkgsettings, portdb=portdb)
1671 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1672 if "package.mask" in mreasons:
1673 comment, filename = \
1674 portage.getmaskingreason(p,
1675 settings=pkgsettings, portdb=portdb,
1676 return_location=True)
1677 if comment and comment != oldcomment:
1680 oldcomment = comment
1682 licenses = portdb.aux_get(p, ["LICENSE"])[0]
1684 # Corruption will have been reported above.
1688 pkgsettings.setcpv(p, mydb=portdb)
1689 uselist = pkgsettings.get("USE", "").split()
1690 missing_licenses = []
1692 missing_licenses = \
1693 pkgsettings.getMissingLicenses(
1694 licenses, p, uselist)
1695 except portage.exception.InvalidDependString:
1696 # This will have already been reported
1697 # above via mreasons.
1699 for l in missing_licenses:
1700 l_path = portdb.findLicensePath(l)
1701 if l in shown_licenses:
1703 msg = ("A copy of the '%s' license" + \
1704 " is located at '%s'.") % (l, l_path)
1707 shown_licenses.append(l)
1709 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1710 print "refer to the Gentoo Handbook."
1712 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1713 print "!!! Either add a suitable binary package or compile from an ebuild."
1715 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1721 if "--debug" in self.myopts:
1722 for pkg in matched_packages:
1723 print (pkg[0] + ":").rjust(10), pkg[2]
1725 if len(matched_packages) > 1:
1726 bestmatch = portage.best(
1727 [pkg[2] for pkg in matched_packages])
1728 matched_packages = [pkg for pkg in matched_packages \
1729 if pkg[2] == bestmatch]
1731 # ordered by type preference ("ebuild" type is the last resort)
1732 selected_pkg = matched_packages[0]
1733 pkgtype, myroot, mycpv, myuse = selected_pkg
1734 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1735 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1736 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1737 existing_node = self._slot_node_map[myroot].get(
1740 e_type, myroot, e_cpv, e_status = existing_node
1741 if portage.match_from_list(x, [e_cpv]):
1742 # The existing node can be reused.
1743 selected_pkg = [e_type, myroot, e_cpv,
1744 self.useFlags[myroot][e_cpv]]
1747 #we are a dependency, so we want to be unconditionally added
1748 mypriority = priority.copy()
1750 mypriority.satisfied = True
1751 if not self.create(selected_pkg[0:3], myparent,
1752 myuse=selected_pkg[-1], priority=mypriority,
1753 rev_dep=rev_deps, arg=arg):
1756 #if mysource is not set, then we are a command-line dependency and should not be added
1757 #if --onlydeps is specified.
1758 if not self.create(selected_pkg[0:3], myparent,
1759 addme=("--onlydeps" not in self.myopts),
1760 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1763 if "--debug" in self.myopts:
1764 print "Exiting...",myparent
1767 def validate_blockers(self):
1768 """Remove any blockers from the digraph that do not match any of the
1769 packages within the graph. If necessary, create hard deps to ensure
1770 correct merge order such that mutually blocking packages are never
1771 installed simultaneously."""
1773 if "--buildpkgonly" in self.myopts or \
1774 "--nodeps" in self.myopts:
1778 for myroot in self.trees:
1780 modified_slots[myroot] = myslots
1781 final_db = self.mydbapi[myroot]
1782 slot_node_map = self._slot_node_map[myroot]
1783 for slot_atom, mynode in slot_node_map.iteritems():
1784 mytype, myroot, mycpv, mystatus = mynode
1785 if mystatus == "merge":
1786 myslots[slot_atom] = mycpv
1788 #if "deep" in self.myparams:
1790 # Pull in blockers from all installed packages that haven't already
1791 # been pulled into the depgraph. This is not enabled by default
1792 # due to the performance penalty that is incurred by all the
1793 # additional dep_check calls that are required.
1795 # Optimization hack for dep_check calls that minimizes the
1796 # available matches by replacing the portdb with a fakedbapi
1798 class FakePortageTree(object):
1799 def __init__(self, mydb):
1801 dep_check_trees = {}
1802 for myroot in self.trees:
1803 dep_check_trees[myroot] = self.trees[myroot].copy()
1804 dep_check_trees[myroot]["porttree"] = \
1805 FakePortageTree(self.mydbapi[myroot])
1807 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1808 for myroot in self.trees:
1809 pkg_node_map = self.pkg_node_map[myroot]
1810 vardb = self.trees[myroot]["vartree"].dbapi
1811 portdb = self.trees[myroot]["porttree"].dbapi
1812 pkgsettings = self.pkgsettings[myroot]
1813 final_db = self.mydbapi[myroot]
1814 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
1815 blocker_cache = BlockerCache(myroot, vardb)
1816 for pkg in cpv_all_installed:
1817 blocker_atoms = None
1818 matching_node = pkg_node_map.get(pkg, None)
1819 if matching_node and \
1820 matching_node[3] == "nomerge":
1822 # If this node has any blockers, create a "nomerge"
1823 # node for it so that they can be enforced.
1824 self.spinner.update()
1825 blocker_data = blocker_cache.get(pkg)
1827 blocker_atoms = blocker_data.atoms
1829 dep_vals = vardb.aux_get(pkg, dep_keys)
1830 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
1831 depstr = " ".join(dep_vals)
1832 # It is crucial to pass in final_db here in order to
1833 # optimize dep_check calls by eliminating atoms via
1834 # dep_wordreduce and dep_eval calls.
1836 portage.dep._dep_check_strict = False
1838 success, atoms = portage.dep_check(depstr,
1839 final_db, pkgsettings, myuse=myuse,
1840 trees=dep_check_trees, myroot=myroot)
1841 except Exception, e:
1842 if isinstance(e, SystemExit):
1844 # This is helpful, for example, if a ValueError
1845 # is thrown from cpv_expand due to multiple
1846 # matches (this can happen if an atom lacks a
1848 show_invalid_depstring_notice(
1849 ("installed", myroot, pkg, "nomerge"),
1854 portage.dep._dep_check_strict = True
1856 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
1857 vardb.aux_get(pkg, ["SLOT"])[0])
1858 if slot_atom in modified_slots[myroot]:
1859 # This package is being replaced anyway, so
1860 # ignore invalid dependencies so as not to
1861 # annoy the user too much (otherwise they'd be
1862 # forced to manually unmerge it first).
1864 show_invalid_depstring_notice(
1865 ("installed", myroot, pkg, "nomerge"),
1868 blocker_atoms = [myatom for myatom in atoms \
1869 if myatom.startswith("!")]
1870 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
1871 blocker_cache[pkg] = \
1872 blocker_cache.BlockerData(counter, blocker_atoms)
1874 # Don't store this parent in pkg_node_map, because it's
1875 # not needed there and it might overwrite a "merge"
1876 # node with the same cpv.
1877 myparent = ("installed", myroot, pkg, "nomerge")
1878 for myatom in blocker_atoms:
1879 blocker = ("blocks", myroot, myatom[1:])
1881 self.blocker_parents.get(blocker, None)
1884 self.blocker_parents[blocker] = myparents
1885 myparents.add(myparent)
1886 blocker_cache.flush()
1889 for blocker in self.blocker_parents.keys():
1890 mytype, myroot, mydep = blocker
1891 initial_db = self.trees[myroot]["vartree"].dbapi
1892 final_db = self.mydbapi[myroot]
1893 blocked_initial = initial_db.match(mydep)
1894 blocked_final = final_db.match(mydep)
1895 if not blocked_initial and not blocked_final:
1896 del self.blocker_parents[blocker]
1898 blocked_slots_initial = {}
1899 blocked_slots_final = {}
1900 for cpv in blocked_initial:
1901 blocked_slots_initial[cpv] = \
1902 "%s:%s" % (portage.dep_getkey(cpv),
1903 initial_db.aux_get(cpv, ["SLOT"])[0])
1904 for cpv in blocked_final:
1905 blocked_slots_final[cpv] = \
1906 "%s:%s" % (portage.dep_getkey(cpv),
1907 final_db.aux_get(cpv, ["SLOT"])[0])
1908 for parent in list(self.blocker_parents[blocker]):
1909 ptype, proot, pcpv, pstatus = parent
1910 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1911 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1912 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1913 parent_static = pslot_atom not in modified_slots[proot]
1914 unresolved_blocks = False
1915 depends_on_order = set()
1916 for cpv in blocked_initial:
1917 slot_atom = blocked_slots_initial[cpv]
1918 if slot_atom == pslot_atom:
1919 # TODO: Support blocks within slots in cases where it
1920 # might make sense. For example, a new version might
1921 # require that the old version be uninstalled at build
1924 if parent_static and \
1925 slot_atom not in modified_slots[myroot]:
1926 # This blocker will be handled the next time that a
1927 # merge of either package is triggered.
1929 if pstatus == "merge" and \
1930 slot_atom in modified_slots[myroot]:
1931 replacement = final_db.match(slot_atom)
1933 if not portage.match_from_list(mydep, replacement):
1934 # Apparently a replacement may be able to
1935 # invalidate this block.
1936 replacement_node = \
1937 self.pkg_node_map[proot][replacement[0]]
1938 depends_on_order.add((replacement_node, parent))
1940 # None of the above blocker resolutions techniques apply,
1941 # so apparently this one is unresolvable.
1942 unresolved_blocks = True
1943 for cpv in blocked_final:
1944 slot_atom = blocked_slots_final[cpv]
1945 if slot_atom == pslot_atom:
1946 # TODO: Support blocks within slots.
1948 if parent_static and \
1949 slot_atom not in modified_slots[myroot]:
1950 # This blocker will be handled the next time that a
1951 # merge of either package is triggered.
1953 if not parent_static and pstatus == "nomerge" and \
1954 slot_atom in modified_slots[myroot]:
1955 replacement = final_db.match(pslot_atom)
1957 replacement_node = \
1958 self.pkg_node_map[proot][replacement[0]]
1959 if replacement_node not in \
1960 self.blocker_parents[blocker]:
1961 # Apparently a replacement may be able to
1962 # invalidate this block.
1963 blocked_node = self.pkg_node_map[proot][cpv]
1964 depends_on_order.add(
1965 (replacement_node, blocked_node))
1967 # None of the above blocker resolutions techniques apply,
1968 # so apparently this one is unresolvable.
1969 unresolved_blocks = True
1970 if not unresolved_blocks and depends_on_order:
1971 for node, pnode in depends_on_order:
1972 # Enforce correct merge order with a hard dep.
1973 self.digraph.addnode(node, pnode,
1974 priority=DepPriority(buildtime=True))
1975 # Count references to this blocker so that it can be
1976 # invalidated after nodes referencing it have been
1978 self.blocker_digraph.addnode(node, blocker)
1979 if not unresolved_blocks and not depends_on_order:
1980 self.blocker_parents[blocker].remove(parent)
1981 if unresolved_blocks:
1982 self._unresolved_blocker_parents.setdefault(
1983 blocker, set()).add(parent)
1984 if not self.blocker_parents[blocker]:
1985 del self.blocker_parents[blocker]
1986 # Validate blockers that depend on merge order.
1987 if not self.blocker_digraph.empty():
1989 if self._slot_collision_info:
1990 # The user is only notified of a slot collision if there are no
1991 # unresolvable blocks.
1992 for x in self.altlist():
1993 if x[0] == "blocks":
1995 self._show_slot_collision_notice(self._slot_collision_info[0])
1996 if not self._accept_collisions():
2000 def _accept_collisions(self):
2002 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
2003 if x in self.myopts:
2008 def _merge_order_bias(self, mygraph):
2009 """Order nodes from highest to lowest overall reference count for
2010 optimal leaf node selection."""
2012 for node in mygraph.order:
2013 node_info[node] = len(mygraph.parent_nodes(node))
2014 def cmp_merge_preference(node1, node2):
2015 return node_info[node2] - node_info[node1]
2016 mygraph.order.sort(cmp_merge_preference)
2018 def altlist(self, reversed=False):
2019 if reversed in self._altlist_cache:
2020 return self._altlist_cache[reversed][:]
2022 retlist = self.altlist()
2024 self._altlist_cache[reversed] = retlist[:]
2026 mygraph=self.digraph.copy()
2027 self._merge_order_bias(mygraph)
2028 myblockers = self.blocker_digraph.copy()
2030 circular_blocks = False
2034 get_nodes = mygraph.root_nodes
2036 get_nodes = mygraph.leaf_nodes
2037 for cpv, node in self.pkg_node_map["/"].iteritems():
2038 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
2039 asap_nodes.append(node)
2041 ignore_priority_range = [None]
2042 ignore_priority_range.extend(
2043 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2044 tree_mode = "--tree" in self.myopts
2045 while not mygraph.empty():
2046 ignore_priority = None
2049 """ASAP nodes are merged before their soft deps."""
2050 for node in asap_nodes:
2051 if not mygraph.contains(node):
2052 asap_nodes.remove(node)
2054 if not mygraph.child_nodes(node,
2055 ignore_priority=DepPriority.SOFT):
2057 asap_nodes.remove(node)
2060 for ignore_priority in ignore_priority_range:
2061 nodes = get_nodes(ignore_priority=ignore_priority)
2064 selected_nodes = None
2066 if ignore_priority <= DepPriority.SOFT:
2067 if ignore_priority is None and not tree_mode:
2068 # Greedily pop all of these nodes since no relationship
2069 # has been ignored. This optimization destroys --tree
2070 # output, so it's disabled in reversed mode.
2071 selected_nodes = nodes
2073 # For optimal merge order:
2074 # * Only pop one node.
2075 # * Removing a root node (node without a parent)
2076 # will not produce a leaf node, so avoid it.
2078 if mygraph.parent_nodes(node):
2079 # found a non-root node
2080 selected_nodes = [node]
2082 if not selected_nodes:
2083 # settle for a root node
2084 selected_nodes = [nodes[0]]
2086 """Recursively gather a group of nodes that RDEPEND on
2087 eachother. This ensures that they are merged as a group
2088 and get their RDEPENDs satisfied as soon as possible."""
2089 def gather_deps(mergeable_nodes, selected_nodes, node):
2090 if node in selected_nodes:
2092 if node not in mergeable_nodes:
2094 selected_nodes.add(node)
2095 for child in mygraph.child_nodes(node,
2096 ignore_priority=DepPriority.SOFT):
2098 mergeable_nodes, selected_nodes, child):
2101 mergeable_nodes = set(nodes)
2103 selected_nodes = set()
2105 mergeable_nodes, selected_nodes, node):
2108 selected_nodes = None
2110 if not selected_nodes:
2111 if not myblockers.is_empty():
2112 """A blocker couldn't be circumnavigated while keeping all
2113 dependencies satisfied. The user will have to resolve this
2114 manually. This is a panic condition and thus the order
2115 doesn't really matter, so just pop a random node in order
2116 to avoid a circular dependency panic if possible."""
2117 if not circular_blocks:
2118 circular_blocks = True
2119 blocker_deps = myblockers.leaf_nodes()
2121 selected_nodes = [blocker_deps.pop()]
2123 if not selected_nodes:
2124 # No leaf nodes are available, so we have a circular
2125 # dependency panic situation. Reduce the noise level to a
2126 # minimum via repeated elimination of root nodes since they
2127 # have no parents and thus can not be part of a cycle.
2129 root_nodes = mygraph.root_nodes(
2130 ignore_priority=DepPriority.SOFT)
2133 for node in root_nodes:
2134 mygraph.remove(node)
2135 # Display the USE flags that are enabled on nodes that are part
2136 # of dependency cycles in case that helps the user decide to
2137 # disable some of them.
2139 tempgraph = mygraph.copy()
2140 while not tempgraph.empty():
2141 nodes = tempgraph.leaf_nodes()
2143 node = tempgraph.order[0]
2146 display_order.append(list(node))
2147 tempgraph.remove(node)
2148 display_order.reverse()
2149 self.myopts.pop("--quiet", None)
2150 self.myopts.pop("--verbose", None)
2151 self.myopts["--tree"] = True
2152 self.display(display_order)
2153 print "!!! Error: circular dependencies:"
2155 mygraph.debug_print()
2157 print "!!! Note that circular dependencies can often be avoided by temporarily"
2158 print "!!! disabling USE flags that trigger optional dependencies."
2161 for node in selected_nodes:
2162 retlist.append(list(node))
2163 mygraph.remove(node)
2164 if not reversed and not circular_blocks and myblockers.contains(node):
2165 """This node may have invalidated one or more blockers."""
2166 myblockers.remove(node)
2167 for blocker in myblockers.root_nodes():
2168 if not myblockers.child_nodes(blocker):
2169 myblockers.remove(blocker)
2171 self._unresolved_blocker_parents.get(blocker)
2173 self.blocker_parents[blocker] = unresolved
2175 del self.blocker_parents[blocker]
2178 """Blocker validation does not work with reverse mode,
2179 so self.altlist() should first be called with reverse disabled
2180 so that blockers are properly validated."""
2181 self.blocker_digraph = myblockers
2183 """ Add any unresolved blocks so that they can be displayed."""
2184 for blocker in self.blocker_parents:
2185 retlist.append(list(blocker))
2186 self._altlist_cache[reversed] = retlist[:]
2189 def xcreate(self,mode="system"):
2190 vardb = self.trees[self.target_root]["vartree"].dbapi
2191 portdb = self.trees[self.target_root]["porttree"].dbapi
2192 bindb = self.trees[self.target_root]["bintree"].dbapi
2193 def visible(mylist):
2194 matches = portdb.gvisible(portdb.visible(mylist))
2195 return [x for x in mylist \
2196 if x in matches or not portdb.cpv_exists(x)]
2197 world_problems = False
2199 mylist = getlist(self.settings, "system")
2202 worldlist = getlist(self.settings, "world")
2203 mylist = getlist(self.settings, "system")
2204 worlddict=genericdict(worldlist)
2206 for x in worlddict.keys():
2207 if not portage.isvalidatom(x):
2208 world_problems = True
2209 elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
2210 world_problems = True
2216 mykey = portage.dep_getkey(atom)
2218 newlist.append(atom)
2219 """Make sure all installed slots are updated when possible.
2220 Do this with --emptytree also, to ensure that all slots are
2223 for cpv in vardb.match(mykey):
2224 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2227 if "--usepkg" in self.myopts:
2228 mymatches = bindb.match(atom)
2229 if "--usepkgonly" not in self.myopts:
2230 mymatches = visible(mymatches)
2231 best_pkg = portage.best(mymatches)
2233 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2234 best_pkgs.append(("binary", best_pkg, best_slot))
2235 if "--usepkgonly" not in self.myopts:
2236 best_pkg = portage.best(portdb.match(atom))
2238 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2239 best_pkgs.append(("ebuild", best_pkg, best_slot))
2241 best_pkg = portage.best([x[1] for x in best_pkgs])
2242 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2243 best_slot = best_pkgs[0][2]
2244 myslots.add(best_slot)
2245 if len(myslots) > 1:
2246 for myslot in myslots:
2247 myslot_atom = "%s:%s" % (mykey, myslot)
2249 if "--usepkgonly" not in self.myopts and \
2250 self.trees[self.target_root][
2251 "porttree"].dbapi.match(myslot_atom):
2253 elif "--usepkg" in self.myopts:
2254 mymatches = bindb.match(myslot_atom)
2255 if "--usepkgonly" not in self.myopts:
2256 mymatches = visible(mymatches)
2260 newlist.append(myslot_atom)
2264 for mydep in mylist:
2266 if not self.select_dep(
2267 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2268 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2271 missing_atoms.append(mydep)
2273 if not self.validate_blockers():
2277 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2278 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2281 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2282 " Ebuilds for the following packages are either all"
2283 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2284 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2288 def display(self,mylist,verbosity=None):
2289 if verbosity is None:
2290 verbosity = ("--quiet" in self.myopts and 1 or \
2291 "--verbose" in self.myopts and 3 or 2)
2296 counters = PackageCounters()
2298 if verbosity == 1 and "--verbose" not in self.myopts:
2299 def create_use_string(*args):
2302 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2304 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2305 alphabetical=("--alphabetical" in self.myopts)):
2313 cur_iuse = set(cur_iuse)
2314 enabled_flags = cur_iuse.intersection(cur_use)
2315 removed_iuse = set(old_iuse).difference(cur_iuse)
2316 any_iuse = cur_iuse.union(old_iuse)
2317 any_iuse = list(any_iuse)
2319 for flag in any_iuse:
2322 if flag in enabled_flags:
2324 if is_new or flag in old_use and all_flags:
2325 flag_str = red(flag)
2326 elif flag not in old_iuse:
2327 flag_str = yellow(flag) + "%*"
2328 elif flag not in old_use:
2329 flag_str = green(flag) + "*"
2330 elif flag in removed_iuse:
2332 flag_str = yellow("-" + flag) + "%"
2335 flag_str = "(" + flag_str + ")"
2336 removed.append(flag_str)
2339 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2340 flag_str = blue("-" + flag)
2341 elif flag not in old_iuse:
2342 flag_str = yellow("-" + flag)
2343 if flag not in iuse_forced:
2345 elif flag in old_use:
2346 flag_str = green("-" + flag) + "*"
2348 if flag in iuse_forced:
2349 flag_str = "(" + flag_str + ")"
2351 enabled.append(flag_str)
2353 disabled.append(flag_str)
2356 ret = " ".join(enabled)
2358 ret = " ".join(enabled + disabled + removed)
2360 ret = '%s="%s" ' % (name, ret)
2364 # FIXME: account for the possibility of different overlays in
2365 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2366 overlays = self.settings["PORTDIR_OVERLAY"].split()
2367 overlays_real = [os.path.realpath(t) \
2368 for t in self.settings["PORTDIR_OVERLAY"].split()]
2372 mygraph = self._parent_child_digraph
2377 if "blocks" == x[0]:
2378 display_list.append((x, 0, True))
2380 graph_key = tuple(x)
2381 if "--tree" in self.myopts:
2382 depth = len(tree_nodes)
2383 while depth and graph_key not in \
2384 mygraph.child_nodes(tree_nodes[depth-1]):
2387 tree_nodes = tree_nodes[:depth]
2388 tree_nodes.append(graph_key)
2389 display_list.append((x, depth, True))
2390 shown_edges.add((graph_key, tree_nodes[depth-1]))
2392 traversed_nodes = set() # prevent endless circles
2393 traversed_nodes.add(graph_key)
2394 def add_parents(current_node, ordered):
2395 parent_nodes = mygraph.parent_nodes(current_node)
2397 child_nodes = set(mygraph.child_nodes(current_node))
2398 selected_parent = None
2399 # First, try to avoid a direct cycle.
2400 for node in parent_nodes:
2401 if node not in traversed_nodes and \
2402 node not in child_nodes:
2403 edge = (current_node, node)
2404 if edge in shown_edges:
2406 selected_parent = node
2408 if not selected_parent:
2409 # A direct cycle is unavoidable.
2410 for node in parent_nodes:
2411 if node not in traversed_nodes:
2412 edge = (current_node, node)
2413 if edge in shown_edges:
2415 selected_parent = node
2418 shown_edges.add((current_node, selected_parent))
2419 traversed_nodes.add(selected_parent)
2420 add_parents(selected_parent, False)
2421 display_list.append((list(current_node),
2422 len(tree_nodes), ordered))
2423 tree_nodes.append(current_node)
2425 add_parents(graph_key, True)
2427 display_list.append((x, depth, True))
2428 mylist = display_list
2430 last_merge_depth = 0
2431 for i in xrange(len(mylist)-1,-1,-1):
2432 graph_key, depth, ordered = mylist[i]
2433 if not ordered and depth == 0 and i > 0 \
2434 and graph_key == mylist[i-1][0] and \
2435 mylist[i-1][1] == 0:
2436 # An ordered node got a consecutive duplicate when the tree was
2440 if "blocks" == graph_key[0]:
2442 if ordered and graph_key[-1] != "nomerge":
2443 last_merge_depth = depth
2445 if depth >= last_merge_depth or \
2446 i < len(mylist) - 1 and \
2447 depth >= mylist[i+1][1]:
2450 display_overlays=False
2451 # files to fetch list - avoids counting a same file twice
2452 # in size display (verbose mode)
2454 for mylist_index in xrange(len(mylist)):
2455 x, depth, ordered = mylist[mylist_index]
2459 portdb = self.trees[myroot]["porttree"].dbapi
2460 bindb = self.trees[myroot]["bintree"].dbapi
2461 vardb = self.trees[myroot]["vartree"].dbapi
2462 vartree = self.trees[myroot]["vartree"]
2463 pkgsettings = self.pkgsettings[myroot]
2468 addl=""+red("B")+" "+fetch+" "
2470 counters.blocks += 1
2471 resolved = portage.key_expand(
2472 pkg_key, mydb=vardb, settings=pkgsettings)
2473 if "--columns" in self.myopts and "--quiet" in self.myopts:
2474 addl = addl + " " + red(resolved)
2476 addl = "[blocks " + addl + "] " + red(resolved)
2477 block_parents = self.blocker_parents[tuple(x)]
2478 block_parents = set([pnode[2] for pnode in block_parents])
2479 block_parents = ", ".join(block_parents)
2481 addl += bad(" (\"%s\" is blocking %s)") % \
2482 (pkg_key, block_parents)
2484 addl += bad(" (is blocking %s)") % block_parents
2485 blockers.append(addl)
2487 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2488 binary_package = True
2489 if "ebuild" == pkg_type:
2490 if "merge" == x[3] or \
2491 not vartree.dbapi.cpv_exists(pkg_key):
2492 """An ebuild "merge" node or a --onlydeps "nomerge"
2494 binary_package = False
2495 pkgsettings.setcpv(pkg_key, mydb=portdb)
2496 if pkg_key not in self.useFlags[myroot]:
2497 self.useFlags[myroot][pkg_key] = \
2498 pkgsettings["USE"].split()
2500 # An ebuild "nomerge" node, so USE come from the vardb.
2501 mydbapi = vartree.dbapi
2502 if pkg_key not in self.useFlags[myroot]:
2503 """If this is a --resume then the USE flags need to be
2504 fetched from the appropriate locations here."""
2505 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2506 pkg_key, ["USE"])[0].split()
2508 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2509 "fetch" in portdb.aux_get(
2510 x[2], ["RESTRICT"])[0].split():
2513 counters.restrict_fetch += 1
2514 if portdb.fetch_check(
2515 pkg_key, self.useFlags[myroot][pkg_key]):
2518 counters.restrict_fetch_satisfied += 1
2520 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2521 #param is used for -u, where you still *do* want to see when something is being upgraded.
2523 if vardb.cpv_exists(pkg_key):
2524 addl=" "+yellow("R")+fetch+" "
2525 if x[3] != "nomerge":
2527 counters.reinst += 1
2528 elif vardb.match(portage.dep_getkey(pkg_key)):
2529 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2530 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2531 portage.pkgsplit(x[2])[0])
2532 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2533 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2535 myoldbest=portage.best(myinslotlist)
2537 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2539 addl+=turquoise("U")+blue("D")
2541 counters.downgrades += 1
2544 addl+=turquoise("U")+" "
2546 counters.upgrades += 1
2548 # New slot, mark it new.
2549 addl=" "+green("NS")+fetch+" "
2551 counters.newslot += 1
2553 if "--changelog" in self.myopts:
2554 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2555 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2556 inst_matches = vardb.match(slot_atom)
2558 changelogs.extend(self.calc_changelog(
2559 portdb.findname(pkg_key),
2560 inst_matches[0], pkg_key))
2562 addl=" "+green("N")+" "+fetch+" "
2568 if pkg_key in self.useFlags[myroot]:
2570 cur_iuse = list(filter_iuse_defaults(
2571 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2573 forced_flags = set()
2574 if not binary_package:
2575 forced_flags.update(pkgsettings.useforce)
2576 forced_flags.update(pkgsettings.usemask)
2578 cur_iuse = portage.unique_array(cur_iuse)
2580 cur_use = self.useFlags[myroot][pkg_key]
2581 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2587 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2588 old_iuse, old_use = \
2589 self.trees[x[1]]["vartree"].dbapi.aux_get(
2590 pkg, ["IUSE", "USE"])
2591 old_iuse = list(set(
2592 filter_iuse_defaults(old_iuse.split())))
2594 old_use = old_use.split()
2601 old_use = [flag for flag in old_use if flag in old_iuse]
2603 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2605 use_expand.reverse()
2606 use_expand_hidden = \
2607 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2609 def map_to_use_expand(myvals, forcedFlags=False):
2612 for exp in use_expand:
2615 for val in myvals[:]:
2616 if val.startswith(exp.lower()+"_"):
2617 if val in forced_flags:
2618 forced[exp].add(val[len(exp)+1:])
2619 ret[exp].append(val[len(exp)+1:])
2622 forced["USE"] = [val for val in myvals \
2623 if val in forced_flags]
2624 for exp in use_expand_hidden:
2631 cur_iuse_map, iuse_forced = \
2632 map_to_use_expand(cur_iuse, forcedFlags=True)
2633 cur_use_map = map_to_use_expand(cur_use)
2634 old_iuse_map = map_to_use_expand(old_iuse)
2635 old_use_map = map_to_use_expand(old_use)
2638 use_expand.insert(0, "USE")
2640 for key in use_expand:
2641 if key in use_expand_hidden:
2643 verboseadd += create_use_string(key.upper(),
2644 cur_iuse_map[key], iuse_forced[key],
2645 cur_use_map[key], old_iuse_map[key],
2646 old_use_map[key], is_new)
2651 if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
2653 myfilesdict = portdb.getfetchsizes(pkg_key,
2654 useflags=self.useFlags[myroot][pkg_key],
2656 except portage.exception.InvalidDependString, e:
2657 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2658 show_invalid_depstring_notice(x, src_uri, str(e))
2661 if myfilesdict is None:
2662 myfilesdict="[empty/missing/bad digest]"
2664 for myfetchfile in myfilesdict.keys():
2665 if myfetchfile not in myfetchlist:
2666 mysize+=myfilesdict[myfetchfile]
2667 myfetchlist.append(myfetchfile)
2668 counters.totalsize += mysize
2669 verboseadd+=format_size(mysize)+" "
2672 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2673 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2674 file_name = portdb.findname(pkg_key)
2675 if file_name: # It might not exist in the tree
2676 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2677 if (overlays_real.count(dir_name)>0):
2678 verboseadd+=teal("["+str(overlays_real.index(
2679 os.path.normpath(dir_name))+1)+"]")+" "
2680 display_overlays=True
2682 verboseadd += "[No ebuild?]"
2684 xs=portage.pkgsplit(x[2])
2691 if "COLUMNWIDTH" in self.settings:
2693 mywidth = int(self.settings["COLUMNWIDTH"])
2694 except ValueError, e:
2695 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2697 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2698 self.settings["COLUMNWIDTH"], noiselevel=-1)
2703 indent = " " * depth
2706 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2707 if myoldbest[-3:]=="-r0":
2708 myoldbest=myoldbest[:-3]
2709 myoldbest=blue("["+myoldbest+"]")
2714 if "--columns" in self.myopts:
2715 if "--quiet" in self.myopts:
2716 myprint=addl+" "+indent+darkgreen(xs[0])
2717 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2718 myprint=myprint+myoldbest
2719 myprint=myprint+darkgreen("to "+x[1])
2721 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2722 if (newlp-nc_len(myprint)) > 0:
2723 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2724 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2725 if (oldlp-nc_len(myprint)) > 0:
2726 myprint=myprint+" "*(oldlp-nc_len(myprint))
2727 myprint=myprint+myoldbest
2728 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2730 if x[-1] == "nomerge" or not ordered:
2731 myprint = darkblue("[nomerge ] ")
2733 myprint = "[" + pkg_type + " " + addl + "] "
2734 myprint += indent + darkgreen(pkg_key) + " " + \
2735 myoldbest + darkgreen("to " + myroot) + " " + \
2738 if "--columns" in self.myopts:
2739 if "--quiet" in self.myopts:
2740 myprint=addl+" "+indent+darkgreen(xs[0])
2741 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2742 myprint=myprint+myoldbest
2744 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2745 if (newlp-nc_len(myprint)) > 0:
2746 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2747 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2748 if (oldlp-nc_len(myprint)) > 0:
2749 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2750 myprint=myprint+myoldbest+" "+verboseadd
2752 if x[-1] == "nomerge" or not ordered:
2753 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2755 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2758 mysplit = portage.pkgsplit(x[2])
2759 if "--tree" not in self.myopts and mysplit and \
2760 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2763 if mysplit[2] == "r0":
2764 myversion = mysplit[1]
2766 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2768 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2769 if mylist_index < len(mylist) - 1 and \
2770 "livecvsportage" not in self.settings.features:
2771 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2772 p.append(colorize("WARN", " then resume the merge."))
2784 if overlays and display_overlays:
2785 print "Portage overlays:"
2789 print " "+teal("["+str(y)+"]"),x
2791 if "--changelog" in self.myopts:
2793 for revision,text in changelogs:
2794 print bold('*'+revision)
2795 sys.stdout.write(text)
2797 if self._pprovided_args:
2799 msg.append(bad("\nWARNING: "))
2800 if len(self._pprovided_args) > 1:
2801 msg.append("Requested packages will not be " + \
2802 "merged because they are listed in\n")
2804 msg.append("A requested package will not be " + \
2805 "merged because it is listed in\n")
2806 msg.append(" package.provided:\n\n")
2807 for arg in self._pprovided_args:
2808 msg.append(" " + arg + "\n")
2810 sys.stderr.write("".join(msg))
2812 def calc_changelog(self,ebuildpath,current,next):
2813 if ebuildpath == None or not os.path.exists(ebuildpath):
2815 current = '-'.join(portage.catpkgsplit(current)[1:])
2816 if current.endswith('-r0'):
2817 current = current[:-3]
2818 next = '-'.join(portage.catpkgsplit(next)[1:])
2819 if next.endswith('-r0'):
2821 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2823 changelog = open(changelogpath).read()
2824 except SystemExit, e:
2825 raise # Needed else can't exit
2828 divisions = self.find_changelog_tags(changelog)
2829 #print 'XX from',current,'to',next
2830 #for div,text in divisions: print 'XX',div
2831 # skip entries for all revisions above the one we are about to emerge
2832 for i in range(len(divisions)):
2833 if divisions[i][0]==next:
2834 divisions = divisions[i:]
2836 # find out how many entries we are going to display
2837 for i in range(len(divisions)):
2838 if divisions[i][0]==current:
2839 divisions = divisions[:i]
2842 # couldnt find the current revision in the list. display nothing
2846 def find_changelog_tags(self,changelog):
2850 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2852 if release is not None:
2853 divs.append((release,changelog))
2855 if release is not None:
2856 divs.append((release,changelog[:match.start()]))
2857 changelog = changelog[match.end():]
2858 release = match.group(1)
2859 if release.endswith('.ebuild'):
2860 release = release[:-7]
2861 if release.endswith('-r0'):
2862 release = release[:-3]
2865 return self.outdatedpackages
2867 class PackageCounters(object):
2877 self.restrict_fetch = 0
2878 self.restrict_fetch_satisfied = 0
2881 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2884 myoutput.append("Total: %s package" % total_installs)
2885 if total_installs != 1:
2886 myoutput.append("s")
2887 if total_installs != 0:
2888 myoutput.append(" (")
2889 if self.upgrades > 0:
2890 details.append("%s upgrade" % self.upgrades)
2891 if self.upgrades > 1:
2893 if self.downgrades > 0:
2894 details.append("%s downgrade" % self.downgrades)
2895 if self.downgrades > 1:
2898 details.append("%s new" % self.new)
2899 if self.newslot > 0:
2900 details.append("%s in new slot" % self.newslot)
2901 if self.newslot > 1:
2904 details.append("%s reinstall" % self.reinst)
2908 details.append("%s block" % self.blocks)
2911 myoutput.append(", ".join(details))
2912 if total_installs != 0:
2913 myoutput.append(")")
2914 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2915 if self.restrict_fetch:
2916 myoutput.append("\nFetch Restriction: %s package" % \
2917 self.restrict_fetch)
2918 if self.restrict_fetch > 1:
2919 myoutput.append("s")
2920 if self.restrict_fetch_satisfied < self.restrict_fetch:
2921 myoutput.append(bad(" (%s unsatisfied)") % \
2922 (self.restrict_fetch - self.restrict_fetch_satisfied))
2923 return "".join(myoutput)
2925 class MergeTask(object):
2927 def __init__(self, settings, trees, myopts):
2928 self.settings = settings
2929 self.target_root = settings["ROOT"]
2931 self.myopts = myopts
2933 if settings.get("PORTAGE_DEBUG", "") == "1":
2935 self.pkgsettings = {}
2936 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2937 if self.target_root != "/":
2938 self.pkgsettings["/"] = \
2939 portage.config(clone=trees["/"]["vartree"].settings)
2941 def merge(self, mylist, favorites, mtimedb):
2943 fetchonly = "--fetchonly" in self.myopts or \
2944 "--fetch-all-uri" in self.myopts
2946 ldpath_mtimes = mtimedb["ldpath"]
2947 xterm_titles = "notitles" not in self.settings.features
2949 #check for blocking dependencies
2950 if "--fetchonly" not in self.myopts and \
2951 "--fetch-all-uri" not in self.myopts and \
2952 "--buildpkgonly" not in self.myopts:
2955 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2956 print "!!! the two packages cannot be installed on the same system together."
2957 print "!!! Please use 'emerge --pretend' to determine blockers."
2958 if "--quiet" not in self.myopts:
2959 show_blocker_docs_link()
2962 if "--resume" in self.myopts:
2964 print colorize("GOOD", "*** Resuming merge...")
2965 emergelog(xterm_titles, " *** Resuming merge...")
2966 mylist = mtimedb["resume"]["mergelist"][:]
2967 if "--skipfirst" in self.myopts and mylist:
2968 del mtimedb["resume"]["mergelist"][0]
2971 validate_merge_list(self.trees, mylist)
2972 mymergelist = mylist
2974 # Verify all the manifests now so that the user is notified of failure
2975 # as soon as possible.
2976 if "--fetchonly" not in self.myopts and \
2977 "--fetch-all-uri" not in self.myopts and \
2978 "strict" in self.settings.features:
2979 shown_verifying_msg = False
2981 for myroot, pkgsettings in self.pkgsettings.iteritems():
2982 quiet_config = portage.config(clone=pkgsettings)
2983 quiet_config["PORTAGE_QUIET"] = "1"
2984 quiet_config.backup_changes("PORTAGE_QUIET")
2985 quiet_settings[myroot] = quiet_config
2988 if x[0] != "ebuild" or x[-1] == "nomerge":
2990 if not shown_verifying_msg:
2991 shown_verifying_msg = True
2992 print ">>> Verifying ebuild Manifests..."
2993 mytype, myroot, mycpv, mystatus = x
2994 portdb = self.trees[myroot]["porttree"].dbapi
2995 quiet_config = quiet_settings[myroot]
2996 quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
2997 if not portage.digestcheck([], quiet_config, strict=True):
2999 del x, mytype, myroot, mycpv, mystatus, quiet_config
3000 del shown_verifying_msg, quiet_settings
3002 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
3003 mysysdict = genericdict(getlist(self.settings, "system"))
3004 if "--resume" not in self.myopts:
3005 myfavs = portage.grabfile(
3006 os.path.join(self.target_root, portage.WORLD_FILE))
3007 myfavdict=genericdict(myfavs)
3008 for x in range(len(mylist)):
3009 if mylist[x][3]!="nomerge":
3010 # Add to the mergelist
3011 mymergelist.append(mylist[x])
3013 myfavkey=portage.cpv_getkey(mylist[x][2])
3014 if "--onlydeps" in self.myopts:
3016 # Add to the world file. Since we won't be able to later.
3017 if "--fetchonly" not in self.myopts and \
3018 myfavkey in favorites:
3019 #don't record if already in system profile or already recorded
3020 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3021 #we don't have a favorites entry for this package yet; add one
3022 myfavdict[myfavkey]=myfavkey
3023 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3024 if not ("--fetchonly" in self.myopts or \
3025 "--fetch-all-uri" in self.myopts or \
3026 "--pretend" in self.myopts):
3027 portage.write_atomic(
3028 os.path.join(self.target_root, portage.WORLD_FILE),
3029 "\n".join(myfavdict.values()))
3031 mtimedb["resume"]["mergelist"]=mymergelist[:]
3034 myfeat = self.settings.features[:]
3035 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3037 if "parallel-fetch" in myfeat and \
3038 not ("--pretend" in self.myopts or \
3039 "--fetch-all-uri" in self.myopts or \
3040 "--fetchonly" in self.myopts):
3041 if "distlocks" not in myfeat:
3043 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
3044 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
3046 elif len(mymergelist) > 1:
3047 print ">>> starting parallel fetching"
3048 fetch_log = "/var/log/emerge-fetch.log"
3049 logfile = open(fetch_log, "w")
3050 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3051 portage.util.apply_secpass_permissions(fetch_log,
3052 uid=portage.portage_uid, gid=portage.portage_gid,
3054 fetch_env = os.environ.copy()
3055 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3056 fetch_env["PORTAGE_NICENESS"] = "0"
3057 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3058 resume_opts = self.myopts.copy()
3059 # For automatic resume, we need to prevent
3060 # any of bad_resume_opts from leaking in
3061 # via EMERGE_DEFAULT_OPTS.
3062 resume_opts["--ignore-default-opts"] = True
3063 for myopt, myarg in resume_opts.iteritems():
3064 if myopt not in bad_resume_opts:
3066 fetch_args.append(myopt)
3068 fetch_args.append(myopt +"="+ myarg)
3069 portage.process.spawn(fetch_args, env=fetch_env,
3070 fd_pipes=fd_pipes, returnpid=True)
3071 logfile.close() # belongs to the spawned process
3072 del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3076 for x in mymergelist:
3081 portdb = self.trees[myroot]["porttree"].dbapi
3082 bindb = self.trees[myroot]["bintree"].dbapi
3083 vartree = self.trees[myroot]["vartree"]
3084 pkgsettings = self.pkgsettings[myroot]
3087 y = portdb.findname(pkg_key)
3088 if "--pretend" not in self.myopts:
3089 print "\n>>> Emerging (" + \
3090 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3091 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3092 colorize("GOOD", x[pkgindex]) + " to " + x[1]
3093 emergelog(xterm_titles, " >>> emerge ("+\
3094 str(mergecount)+" of "+str(len(mymergelist))+\
3095 ") "+x[pkgindex]+" to "+x[1])
3097 pkgsettings["EMERGE_FROM"] = x[0]
3098 pkgsettings.backup_changes("EMERGE_FROM")
3101 #buildsyspkg: Check if we need to _force_ binary package creation
3102 issyspkg = ("buildsyspkg" in myfeat) \
3103 and x[0] != "blocks" \
3104 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3105 and "--buildpkg" not in self.myopts
3106 if x[0] in ["ebuild","blocks"]:
3107 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3108 raise Exception, "Merging a blocker"
3109 elif "--fetchonly" in self.myopts or \
3110 "--fetch-all-uri" in self.myopts:
3111 if "--fetch-all-uri" in self.myopts:
3112 retval = portage.doebuild(y, "fetch", myroot,
3113 pkgsettings, self.edebug,
3114 "--pretend" in self.myopts, fetchonly=1,
3115 fetchall=1, mydbapi=portdb, tree="porttree")
3117 retval = portage.doebuild(y, "fetch", myroot,
3118 pkgsettings, self.edebug,
3119 "--pretend" in self.myopts, fetchonly=1,
3120 mydbapi=portdb, tree="porttree")
3121 if (retval is None) or retval:
3123 print "!!! Fetch for",y,"failed, continuing..."
3125 failed_fetches.append(pkg_key)
3128 portage.doebuild_environment(y, "setup", myroot,
3129 pkgsettings, self.edebug, 1, portdb)
3130 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3131 portage.util.ensure_dirs(os.path.dirname(catdir),
3132 uid=portage.portage_uid, gid=portage.portage_gid,
3134 builddir_lock = None
3137 catdir_lock = portage.locks.lockdir(catdir)
3138 portage.util.ensure_dirs(catdir,
3139 uid=portage.portage_uid, gid=portage.portage_gid,
3141 builddir_lock = portage.locks.lockdir(
3142 pkgsettings["PORTAGE_BUILDDIR"])
3144 portage.locks.unlockdir(catdir_lock)
3147 msg = " === (%s of %s) Cleaning (%s::%s)" % \
3148 (mergecount, len(mymergelist), pkg_key, y)
3149 short_msg = "emerge: (%s of %s) %s Clean" % \
3150 (mergecount, len(mymergelist), pkg_key)
3151 emergelog(xterm_titles, msg, short_msg=short_msg)
3152 retval = portage.doebuild(y, "clean", myroot,
3153 pkgsettings, self.edebug, cleanup=1,
3154 mydbapi=portdb, tree="porttree")
3155 if retval != os.EX_OK:
3157 if "--buildpkg" in self.myopts or issyspkg:
3159 print ">>> This is a system package, " + \
3160 "let's pack a rescue tarball."
3161 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3162 (mergecount, len(mymergelist), pkg_key, y)
3163 short_msg = "emerge: (%s of %s) %s Compile" % \
3164 (mergecount, len(mymergelist), pkg_key)
3165 emergelog(xterm_titles, msg, short_msg=short_msg)
3166 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3167 binpkg_tmpfile = os.path.join(pkgsettings["PKGDIR"],
3168 pkg_key + ".tbz2." + str(os.getpid()))
3169 pkgsettings["PORTAGE_BINPKG_TMPFILE"] = binpkg_tmpfile
3170 pkgsettings.backup_changes("PORTAGE_BINPKG_TMPFILE")
3171 retval = portage.doebuild(y, "package", myroot,
3172 pkgsettings, self.edebug, mydbapi=portdb,
3174 del pkgsettings["PORTAGE_BINPKG_TMPFILE"]
3175 if retval != os.EX_OK:
3177 bintree = self.trees[myroot]["bintree"]
3178 bintree.inject(pkg_key, filename=binpkg_tmpfile)
3179 if "--buildpkgonly" not in self.myopts:
3180 msg = " === (%s of %s) Merging (%s::%s)" % \
3181 (mergecount, len(mymergelist), pkg_key, y)
3182 short_msg = "emerge: (%s of %s) %s Merge" % \
3183 (mergecount, len(mymergelist), pkg_key)
3184 emergelog(xterm_titles, msg, short_msg=short_msg)
3185 retval = portage.merge(pkgsettings["CATEGORY"],
3186 pkgsettings["PF"], pkgsettings["D"],
3187 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3188 "build-info"), myroot, pkgsettings,
3189 myebuild=pkgsettings["EBUILD"],
3190 mytree="porttree", mydbapi=portdb,
3191 vartree=vartree, prev_mtimes=ldpath_mtimes)
3192 if retval != os.EX_OK:
3194 elif "noclean" not in pkgsettings.features:
3195 portage.doebuild(y, "clean", myroot,
3196 pkgsettings, self.edebug, mydbapi=portdb,
3199 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3200 (mergecount, len(mymergelist), pkg_key, y)
3201 short_msg = "emerge: (%s of %s) %s Compile" % \
3202 (mergecount, len(mymergelist), pkg_key)
3203 emergelog(xterm_titles, msg, short_msg=short_msg)
3204 retval = portage.doebuild(y, "merge", myroot,
3205 pkgsettings, self.edebug, vartree=vartree,
3206 mydbapi=portdb, tree="porttree",
3207 prev_mtimes=ldpath_mtimes)
3208 if retval != os.EX_OK:
3212 portage.locks.unlockdir(builddir_lock)
3215 # Lock catdir for removal if empty.
3216 catdir_lock = portage.locks.lockdir(catdir)
3222 if e.errno not in (errno.ENOENT,
3223 errno.ENOTEMPTY, errno.EEXIST):
3226 portage.locks.unlockdir(catdir_lock)
3228 elif x[0]=="binary":
3230 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3231 if "--getbinpkg" in self.myopts:
3234 if "distlocks" in pkgsettings.features and \
3235 os.access(pkgsettings["PKGDIR"], os.W_OK):
3236 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3237 tbz2_lock = portage.locks.lockfile(mytbz2,
3239 if self.trees[myroot]["bintree"].isremote(pkg_key):
3240 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3241 (mergecount, len(mymergelist), pkg_key, mytbz2)
3242 short_msg = "emerge: (%s of %s) %s Fetch" % \
3243 (mergecount, len(mymergelist), pkg_key)
3244 emergelog(xterm_titles, msg, short_msg=short_msg)
3246 self.trees[myroot]["bintree"].gettbz2(pkg_key)
3247 except portage.exception.FileNotFound:
3248 writemsg("!!! Fetching Binary failed " + \
3249 "for '%s'\n" % pkg_key, noiselevel=-1)
3252 failed_fetches.append(pkg_key)
3253 except portage.exception.DigestException, e:
3254 writemsg("\n!!! Digest verification failed:\n",
3256 writemsg("!!! %s\n" % e.value[0],
3258 writemsg("!!! Reason: %s\n" % e.value[1],
3260 writemsg("!!! Got: %s\n" % e.value[2],
3262 writemsg("!!! Expected: %s\n" % e.value[3],
3267 failed_fetches.append(pkg_key)
3270 portage.locks.unlockfile(tbz2_lock)
3272 if "--fetchonly" in self.myopts or \
3273 "--fetch-all-uri" in self.myopts:
3276 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3277 emergelog(xterm_titles, " === ("+str(mergecount)+\
3278 " of "+str(len(mymergelist))+") Merging Binary ("+\
3279 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3280 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3282 vartree=self.trees[myroot]["vartree"],
3283 prev_mtimes=ldpath_mtimes)
3284 if retval != os.EX_OK:
3286 #need to check for errors
3287 if "--buildpkgonly" not in self.myopts:
3288 self.trees[x[1]]["vartree"].inject(x[2])
3289 myfavkey=portage.cpv_getkey(x[2])
3290 if "--fetchonly" not in self.myopts and \
3291 "--fetch-all-uri" not in self.myopts and \
3292 myfavkey in favorites:
3293 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3294 myfavdict=genericdict(myfavs)
3295 #don't record if already in system profile or already recorded
3296 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3297 #we don't have a favorites entry for this package yet; add one
3298 myfavdict[myfavkey]=myfavkey
3299 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3300 emergelog(xterm_titles, " === ("+\
3301 str(mergecount)+" of "+\
3302 str(len(mymergelist))+\
3303 ") Updating world file ("+x[pkgindex]+")")
3304 portage.write_atomic(
3305 os.path.join(myroot, portage.WORLD_FILE),
3306 "\n".join(myfavdict.values()))
3308 if "--pretend" not in self.myopts and \
3309 "--fetchonly" not in self.myopts and \
3310 "--fetch-all-uri" not in self.myopts:
3311 # Clean the old package that we have merged over top of it.
3312 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3313 xsplit=portage.pkgsplit(x[2])
3314 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3315 retval = unmerge(pkgsettings, self.myopts, vartree,
3316 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3318 emergelog(xterm_titles,
3319 " --- AUTOCLEAN: Nothing unmerged.")
3321 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3322 + " AUTOCLEAN is disabled. This can cause serious"
3323 + " problems due to overlapping packages.\n")
3325 # Figure out if we need a restart.
3326 mysplit=portage.pkgsplit(x[2])
3327 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3328 myver=mysplit[1]+"-"+mysplit[2]
3329 if myver[-3:]=='-r0':
3331 if (myver != portage.VERSION) and \
3332 "livecvsportage" not in self.settings.features:
3333 if len(mymergelist) > mergecount:
3334 emergelog(xterm_titles,
3335 " ::: completed emerge ("+ \
3336 str(mergecount)+" of "+ \
3337 str(len(mymergelist))+") "+ \
3339 emergelog(xterm_titles, " *** RESTARTING " + \
3340 "emerge via exec() after change of " + \
3342 del mtimedb["resume"]["mergelist"][0]
3344 portage.run_exitfuncs()
3345 mynewargv=[sys.argv[0],"--resume"]
3346 resume_opts = self.myopts.copy()
3347 # For automatic resume, we need to prevent
3348 # any of bad_resume_opts from leaking in
3349 # via EMERGE_DEFAULT_OPTS.
3350 resume_opts["--ignore-default-opts"] = True
3351 for myopt, myarg in resume_opts.iteritems():
3352 if myopt not in bad_resume_opts:
3354 mynewargv.append(myopt)
3356 mynewargv.append(myopt +"="+ myarg)
3357 # priority only needs to be adjusted on the first run
3358 os.environ["PORTAGE_NICENESS"] = "0"
3359 os.execv(mynewargv[0], mynewargv)
3361 if "--pretend" not in self.myopts and \
3362 "--fetchonly" not in self.myopts and \
3363 "--fetch-all-uri" not in self.myopts:
3364 if "noclean" not in self.settings.features:
3365 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3366 (mergecount, len(mymergelist), x[pkgindex])
3367 emergelog(xterm_titles, (" === (%s of %s) " + \
3368 "Post-Build Cleaning (%s::%s)") % \
3369 (mergecount, len(mymergelist), x[pkgindex], y),
3370 short_msg=short_msg)
3371 emergelog(xterm_titles, " ::: completed emerge ("+\
3372 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3375 # Unsafe for parallel merges
3376 del mtimedb["resume"]["mergelist"][0]
3377 # Commit after each merge so that --resume may still work in
3378 # in the event that portage is not allowed to exit normally
3379 # due to power failure, SIGKILL, etc...
3382 if "--pretend" not in self.myopts:
3383 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3385 # We're out of the loop... We're done. Delete the resume data.
3386 if mtimedb.has_key("resume"):
3387 del mtimedb["resume"]
3390 #by doing an exit this way, --fetchonly can continue to try to
3391 #fetch everything even if a particular download fails.
3392 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3394 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3395 "encountered. Please see above for details.\n\n")
3396 for cpv in failed_fetches:
3397 sys.stderr.write(" ")
3398 sys.stderr.write(cpv)
3399 sys.stderr.write("\n")
3400 sys.stderr.write("\n")
3406 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3407 ldpath_mtimes, autoclean=0):
3408 candidate_catpkgs=[]
3410 xterm_titles = "notitles" not in settings.features
3412 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3414 # At least the parent needs to exist for the lock file.
3415 portage.util.ensure_dirs(vdb_path)
3416 except portage.exception.PortageException:
3420 if os.access(vdb_path, os.W_OK):
3421 vdb_lock = portage.locks.lockdir(vdb_path)
3422 realsyslist = getlist(settings, "system")
3424 for x in realsyslist:
3425 mycp = portage.dep_getkey(x)
3426 if mycp in settings.getvirtuals():
3428 for provider in settings.getvirtuals()[mycp]:
3429 if vartree.dbapi.match(provider):
3430 providers.append(provider)
3431 if len(providers) == 1:
3432 syslist.extend(providers)
3434 syslist.append(mycp)
3436 mysettings = portage.config(clone=settings)
3438 if not unmerge_files or "world" in unmerge_files or \
3439 "system" in unmerge_files:
3440 if "unmerge"==unmerge_action:
3442 print bold("emerge unmerge") + " can only be used with " + \
3443 "specific package names, not with "+bold("world")+" or"
3444 print bold("system")+" targets."
3451 # process all arguments and add all
3452 # valid db entries to candidate_catpkgs
3454 if not unmerge_files or "world" in unmerge_files:
3455 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3456 elif "system" in unmerge_files:
3457 candidate_catpkgs.extend(getlist(settings, "system"))
3459 #we've got command-line arguments
3460 if not unmerge_files:
3461 print "\nNo packages to unmerge have been provided.\n"
3463 for x in unmerge_files:
3464 arg_parts = x.split('/')
3465 if x[0] not in [".","/"] and \
3466 arg_parts[-1][-7:] != ".ebuild":
3467 #possible cat/pkg or dep; treat as such
3468 candidate_catpkgs.append(x)
3469 elif unmerge_action in ["prune","clean"]:
3470 print "\n!!! Prune and clean do not accept individual" + \
3471 " ebuilds as arguments;\n skipping.\n"
3474 # it appears that the user is specifying an installed
3475 # ebuild and we're in "unmerge" mode, so it's ok.
3476 if not os.path.exists(x):
3477 print "\n!!! The path '"+x+"' doesn't exist.\n"
3480 absx = os.path.abspath(x)
3481 sp_absx = absx.split("/")
3482 if sp_absx[-1][-7:] == ".ebuild":
3484 absx = "/".join(sp_absx)
3486 sp_absx_len = len(sp_absx)
3488 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3489 vdb_len = len(vdb_path)
3491 sp_vdb = vdb_path.split("/")
3492 sp_vdb_len = len(sp_vdb)
3494 if not os.path.exists(absx+"/CONTENTS"):
3495 print "!!! Not a valid db dir: "+str(absx)
3498 if sp_absx_len <= sp_vdb_len:
3499 # The Path is shorter... so it can't be inside the vdb.
3502 print "\n!!!",x,"cannot be inside "+ \
3503 vdb_path+"; aborting.\n"
3506 for idx in range(0,sp_vdb_len):
3507 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3510 print "\n!!!", x, "is not inside "+\
3511 vdb_path+"; aborting.\n"
3514 print "="+"/".join(sp_absx[sp_vdb_len:])
3515 candidate_catpkgs.append(
3516 "="+"/".join(sp_absx[sp_vdb_len:]))
3519 if (not "--quiet" in myopts):
3521 if settings["ROOT"] != "/":
3522 print darkgreen(newline+ \
3523 ">>> Using system located in ROOT tree "+settings["ROOT"])
3524 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3525 not ("--quiet" in myopts):
3526 print darkgreen(newline+\
3527 ">>> These are the packages that would be unmerged:")
3531 for x in candidate_catpkgs:
3532 # cycle through all our candidate deps and determine
3533 # what will and will not get unmerged
3535 mymatch=localtree.dep_match(x)
3538 except ValueError, errpkgs:
3539 print "\n\n!!! The short ebuild name \"" + \
3540 x + "\" is ambiguous. Please specify"
3541 print "!!! one of the following fully-qualified " + \
3542 "ebuild names instead:\n"
3543 for i in errpkgs[0]:
3544 print " " + green(i)
3548 if not mymatch and x[0] not in "<>=~":
3549 #add a "=" if missing
3550 mymatch=localtree.dep_match("="+x)
3552 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3553 (x, unmerge_action), noiselevel=-1)
3555 mykey = portage.key_expand(
3557 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3558 if not pkgmap.has_key(mykey):
3559 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3560 if unmerge_action=="unmerge":
3562 if y not in pkgmap[mykey]["selected"]:
3563 pkgmap[mykey]["selected"].append(y)
3564 numselected=numselected+len(mymatch)
3567 #unmerge_action in ["prune", clean"]
3569 for mypkg in mymatch:
3570 if unmerge_action=="clean":
3571 myslot=localtree.getslot(mypkg)
3573 # since we're pruning, we don't care about slots
3574 # and put all the pkgs in together
3576 if not slotmap.has_key(myslot):
3578 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3579 for myslot in slotmap.keys():
3580 counterkeys=slotmap[myslot].keys()
3585 pkgmap[mykey]["protected"].append(
3586 slotmap[myslot][counterkeys[-1]])
3588 #be pretty and get them in order of merge:
3589 for ckey in counterkeys:
3590 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
3591 numselected=numselected+1
3592 # ok, now the last-merged package
3593 # is protected, and the rest are selected
3594 if global_unmerge and not numselected:
3595 portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
3599 portage.writemsg_stdout(
3600 "\n>>> No packages selected for removal by " + \
3601 unmerge_action + "\n")
3605 portage.locks.unlockdir(vdb_lock)
3606 for x in pkgmap.keys():
3607 for y in localtree.dep_match(x):
3608 if y not in pkgmap[x]["omitted"] and \
3609 y not in pkgmap[x]["selected"] and \
3610 y not in pkgmap[x]["protected"]:
3611 pkgmap[x]["omitted"].append(y)
3612 if global_unmerge and not pkgmap[x]["selected"]:
3613 #avoid cluttering the preview printout with stuff that isn't getting unmerged
3615 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
3616 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
3617 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
3618 if "--pretend" not in myopts and "--ask" not in myopts:
3619 countdown(int(settings["EMERGE_WARNING_DELAY"]),
3620 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3621 print "\n "+white(x)
3622 for mytype in ["selected","protected","omitted"]:
3623 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
3624 if pkgmap[x][mytype]:
3625 for mypkg in pkgmap[x][mytype]:
3626 mysplit=portage.catpkgsplit(mypkg)
3627 if mysplit[3]=="r0":
3628 myversion=mysplit[2]
3630 myversion=mysplit[2]+"-"+mysplit[3]
3631 if mytype=="selected":
3632 portage.writemsg_stdout(
3633 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
3635 portage.writemsg_stdout(
3636 colorize("GOOD", myversion + " "), noiselevel=-1)
3638 portage.writemsg_stdout("none", noiselevel=-1)
3639 portage.writemsg_stdout("\n", noiselevel=-1)
3641 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3642 " packages are slated for removal.\n")
3643 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
3644 " and " + colorize("GOOD", "'omitted'") + \
3645 " packages will not be removed.\n\n")
3647 if "--pretend" in myopts:
3648 #we're done... return
3650 if "--ask" in myopts:
3651 if userquery("Would you like to unmerge these packages?")=="No":
3652 # enter pretend mode for correct formatting of results
3653 myopts["--pretend"] = True
3658 #the real unmerging begins, after a short delay....
3660 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3662 for x in pkgmap.keys():
3663 for y in pkgmap[x]["selected"]:
3664 print ">>> Unmerging "+y+"..."
3665 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3666 mysplit=y.split("/")
3668 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3669 mysettings, unmerge_action not in ["clean","prune"],
3670 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3671 if retval != os.EX_OK:
3672 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3673 ebuild = vartree.dbapi.findname(y)
3674 show_unmerge_failure_message(y, ebuild, retval)
3677 clean_world(vartree.dbapi, y)
3678 emergelog(xterm_titles, " >>> unmerge success: "+y)
3681 def show_unmerge_failure_message(pkg, ebuild, retval):
3683 from formatter import AbstractFormatter, DumbWriter
3684 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3687 msg.append("A removal phase of the '%s' package " % pkg)
3688 msg.append("has failed with exit value %s. " % retval)
3689 msg.append("The problem occurred while executing ")
3690 msg.append("the ebuild located at '%s'. " % ebuild)
3691 msg.append("If necessary, manually remove the ebuild " )
3692 msg.append("in order to skip the execution of removal phases.")
3696 f.add_flowing_data(x)
3700 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3702 if os.path.exists("/usr/bin/install-info"):
3707 inforoot=normpath(root+z)
3708 if os.path.isdir(inforoot):
3709 infomtime = long(os.stat(inforoot).st_mtime)
3710 if inforoot not in prev_mtimes or \
3711 prev_mtimes[inforoot] != infomtime:
3712 regen_infodirs.append(inforoot)
3714 if not regen_infodirs:
3715 portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
3717 portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
3721 for inforoot in regen_infodirs:
3724 for filename in ("dir", "dir.gz", "dir.bz2"):
3725 file_path = os.path.join(inforoot, filename)
3727 os.rename(file_path, file_path + ".old")
3729 if e.errno != errno.ENOENT:
3733 if not os.path.isdir(inforoot):
3736 file_list = os.listdir(inforoot)
3739 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3741 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3742 existsstr="already exists, for file `"
3744 if re.search(existsstr,myso):
3745 # Already exists... Don't increment the count for this.
3747 elif myso[:44]=="install-info: warning: no info dir entry in ":
3748 # This info file doesn't contain a DIR-header: install-info produces this
3749 # (harmless) warning (the --quiet switch doesn't seem to work).
3750 # Don't increment the count for this.
3754 errmsg += myso + "\n"
3757 #update mtime so we can potentially avoid regenerating.
3758 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3761 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3764 print " "+green("*")+" Processed",icount,"info files."
3767 def display_news_notification(settings):
3768 target_root = settings["ROOT"]
3769 NEWS_PATH = os.path.join("metadata", "news")
3770 UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
3771 porttree = portdbapi(porttree_root=settings["PORTDIR"], mysettings=settings)
3772 newsReaderDisplay = False
3774 for repo in porttree.getRepositories():
3775 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3777 if not newsReaderDisplay:
3778 newsReaderDisplay = True
3780 print colorize("WARN", " * IMPORTANT:"),
3781 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3784 if newsReaderDisplay:
3785 print colorize("WARN", " *"),
3786 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3789 def post_emerge(settings, mtimedb, retval):
3791 Misc. things to run at the end of a merge session.
3797 Display preserved libs warnings
3800 @param settings: Configuration settings (typically portage.settings)
3801 @type settings: portage.config()
3802 @param mtimedb: The mtimeDB to store data needed across merge invocations
3803 @type mtimedb: MtimeDB class instance
3804 @param retval: Emerge's return value
3808 1. Calls sys.exit(retval)
3810 target_root = settings["ROOT"]
3811 info_mtimes = mtimedb["info"]
3813 # Load the most current variables from ${ROOT}/etc/profile.env
3815 settings.regenerate()
3818 config_protect = settings.get("CONFIG_PROTECT","").split()
3819 infodirs = settings.get("INFOPATH","").split(":") + \
3820 settings.get("INFODIR","").split(":")
3824 emergelog("notitles" not in settings.features,
3825 " *** exiting successfully.")
3827 if "noinfo" not in settings.features:
3828 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3830 chk_updated_cfg_files(target_root, config_protect)
3832 display_news_notification(settings)
3834 from portage.dbapi.vartree import PreservedLibsRegistry
3835 plib_registry = PreservedLibsRegistry(os.path.join(target_root, CACHE_PATH, "preserved_libs_registry"))
3836 if plib_registry.hasEntries():
3837 print colorize("WARN", "!!!") + " existing preserved libs:"
3838 plibdata = plib_registry.getPreservedLibs()
3839 for cpv in plibdata.keys():
3840 print colorize("WARN", ">>>") + " package: %s" % cpv
3841 for f in plibdata[cpv]:
3842 print colorize("WARN", " * ") + " - %s" % f
3843 print "Use " + colorize("GOOD", "revdep-rebuild") + " to rebuild packages using these libraries"
3844 print "and then remerge the packages listed above."
3850 def chk_updated_cfg_files(target_root, config_protect):
3852 #number of directories with some protect files in them
3854 for x in config_protect:
3855 x = os.path.join(target_root, x.lstrip(os.path.sep))
3857 mymode = os.lstat(x).st_mode
3860 if stat.S_ISDIR(mymode):
3861 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3863 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3864 os.path.split(x.rstrip(os.path.sep))
3865 a = commands.getstatusoutput(mycommand + \
3866 " ! -iname '.*~' ! -iname '.*.bak'")
3868 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3870 files = a[1].split()
3873 print colorize("WARN", " * IMPORTANT:"),
3874 if stat.S_ISDIR(mymode):
3875 print "%d config files in '%s' need updating." % \
3878 print "config file '%s' needs updating." % x
3881 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3882 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3884 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3886 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3887 Returns the number of unread (yet relevent) items.
3899 1. The number of unread but relevant news items.
3902 from portage.news import NewsManager
3903 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3904 return manager.getUnreadItems( repo_id, update=True )
3906 def is_valid_package_atom(x):
3908 testkey = portage.dep_getkey(x)
3909 except portage.exception.InvalidData:
3911 if testkey.startswith("null/"):
3912 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3917 return portage.isvalidatom(testatom)
3919 def validate_merge_list(trees, mergelist):
3920 """Validate the list to make sure all the packages are still available.
3921 This is needed for --resume."""
3922 for (pkg_type, myroot, pkg_key, action) in mergelist:
3923 if pkg_type == "binary" and \
3924 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3925 pkg_type == "ebuild" and \
3926 not trees[myroot]["porttree"].dbapi.xmatch(
3927 "match-all", "="+pkg_key):
3928 print red("!!! Error: The resume list contains packages that are no longer")
3929 print red("!!! available to be emerged. Please restart/continue")
3930 print red("!!! the merge operation manually.")
3933 def show_blocker_docs_link():
3935 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3936 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3938 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3941 def action_sync(settings, trees, mtimedb, myopts, myaction):
3942 xterm_titles = "notitles" not in settings.features
3943 emergelog(xterm_titles, " === sync")
3944 myportdir = settings.get("PORTDIR", None)
3946 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3948 if myportdir[-1]=="/":
3949 myportdir=myportdir[:-1]
3950 if not os.path.exists(myportdir):
3951 print ">>>",myportdir,"not found, creating it."
3952 os.makedirs(myportdir,0755)
3953 syncuri=settings["SYNC"].rstrip()
3955 updatecache_flg = False
3956 if myaction == "metadata":
3957 print "skipping sync"
3958 updatecache_flg = True
3959 tmpservertimestampfile = None
3960 elif syncuri[:8]=="rsync://":
3961 if not os.path.exists("/usr/bin/rsync"):
3962 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3963 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3968 import shlex, StringIO
3969 if settings["PORTAGE_RSYNC_OPTS"] == "":
3970 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3972 "--recursive", # Recurse directories
3973 "--links", # Consider symlinks
3974 "--safe-links", # Ignore links outside of tree
3975 "--perms", # Preserve permissions
3976 "--times", # Preserive mod times
3977 "--compress", # Compress the data transmitted
3978 "--force", # Force deletion on non-empty dirs
3979 "--whole-file", # Don't do block transfers, only entire files
3980 "--delete", # Delete files that aren't in the master tree
3981 "--delete-after", # Delete only after everything else is done
3982 "--stats", # Show final statistics about what was transfered
3983 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3984 "--exclude=/distfiles", # Exclude distfiles from consideration
3985 "--exclude=/local", # Exclude local from consideration
3986 "--exclude=/packages", # Exclude packages from consideration
3987 "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
3991 # The below validation is not needed when using the above hardcoded
3994 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3995 lexer = shlex.shlex(StringIO.StringIO(
3996 settings.get("PORTAGE_RSYNC_OPTS","")), posix=True)
3997 lexer.whitespace_split = True
3998 rsync_opts.extend(lexer)
4001 for opt in ("--recursive", "--times"):
4002 if opt not in rsync_opts:
4003 portage.writemsg(yellow("WARNING:") + " adding required option " + \
4004 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4005 rsync_opts.append(opt)
4007 for exclude in ("distfiles", "local", "packages"):
4008 opt = "--exclude=/%s" % exclude
4009 if opt not in rsync_opts:
4010 portage.writemsg(yellow("WARNING:") + \
4011 " adding required option %s not included in " % opt + \
4012 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
4013 rsync_opts.append(opt)
4015 if settings["RSYNC_TIMEOUT"] != "":
4016 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
4017 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4019 mytimeout = int(settings["RSYNC_TIMEOUT"])
4020 rsync_opts.append("--timeout=%d" % mytimeout)
4021 except ValueError, e:
4022 portage.writemsg("!!! %s\n" % str(e))
4024 # TODO: determine options required for official servers
4025 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
4027 def rsync_opt_startswith(opt_prefix):
4028 for x in rsync_opts:
4029 if x.startswith(opt_prefix):
4033 if not rsync_opt_startswith("--timeout="):
4034 rsync_opts.append("--timeout=%d" % mytimeout)
4036 for opt in ("--compress", "--whole-file"):
4037 if opt not in rsync_opts:
4038 portage.writemsg(yellow("WARNING:") + " adding required option " + \
4039 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4040 rsync_opts.append(opt)
4042 if "--quiet" in myopts:
4043 rsync_opts.append("--quiet") # Shut up a lot
4045 rsync_opts.append("--verbose") # Print filelist
4047 if "--verbose" in myopts:
4048 rsync_opts.append("--progress") # Progress meter for each file
4050 if "--debug" in myopts:
4051 rsync_opts.append("--checksum") # Force checksum on all files
4053 if settings["RSYNC_EXCLUDEFROM"] != "":
4054 portage.writemsg(yellow("WARNING:") + \
4055 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
4056 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4057 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
4058 rsync_opts.append("--exclude-from=%s" % \
4059 settings["RSYNC_EXCLUDEFROM"])
4061 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
4062 " but file does not exist.\n")
4064 if settings["RSYNC_RATELIMIT"] != "":
4065 portage.writemsg(yellow("WARNING:") + \
4066 " usage of RSYNC_RATELIMIT is deprecated, use " + \
4067 "PORTAGE_RSYNC_EXTRA_OPTS instead")
4068 rsync_opts.append("--bwlimit=%s" % \
4069 settings["RSYNC_RATELIMIT"])
4071 # Real local timestamp file.
4072 servertimestampfile = os.path.join(
4073 myportdir, "metadata", "timestamp.chk")
4074 # Temporary file for remote server timestamp comparison.
4075 tmpservertimestampfile = os.path.join(
4076 settings["PORTAGE_TMPDIR"], "timestamp.chk")
4078 content = portage.util.grabfile(servertimestampfile)
4082 mytimestamp = time.mktime(time.strptime(content[0],
4083 "%a, %d %b %Y %H:%M:%S +0000"))
4084 except (OverflowError, ValueError):
4089 rsync_initial_timeout = \
4090 int(settings.get("PORTAGE_RSYNC_INITIAL_TIMEOUT", "15"))
4092 rsync_initial_timeout = 15
4095 if settings.has_key("RSYNC_RETRIES"):
4096 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
4097 maxretries=int(settings["RSYNC_RETRIES"])
4099 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
4100 except SystemExit, e:
4101 raise # Needed else can't exit
4103 maxretries=3 #default number of retries
4106 user_name, hostname, port = re.split(
4107 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
4110 if user_name is None:
4112 updatecache_flg=True
4113 all_rsync_opts = set(rsync_opts)
4114 lexer = shlex.shlex(StringIO.StringIO(
4115 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")), posix=True)
4116 lexer.whitespace_split = True
4117 extra_rsync_opts = list(lexer)
4119 all_rsync_opts.update(extra_rsync_opts)
4120 family = socket.AF_INET
4121 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
4122 family = socket.AF_INET
4123 elif socket.has_ipv6 and \
4124 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
4125 family = socket.AF_INET6
4132 for addrinfo in socket.getaddrinfo(
4133 hostname, None, family, socket.SOCK_STREAM):
4134 if addrinfo[0] == socket.AF_INET6:
4135 # IPv6 addresses need to be enclosed in square brackets
4136 ips.append("[%s]" % addrinfo[4][0])
4138 ips.append(addrinfo[4][0])
4139 from random import shuffle
4141 except SystemExit, e:
4142 raise # Needed else can't exit
4143 except Exception, e:
4144 print "Notice:",str(e)
4149 dosyncuri = syncuri.replace(
4150 "//" + user_name + hostname + port + "/",
4151 "//" + user_name + ips[0] + port + "/", 1)
4152 except SystemExit, e:
4153 raise # Needed else can't exit
4154 except Exception, e:
4155 print "Notice:",str(e)
4159 if "--ask" in myopts:
4160 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
4165 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
4166 if "--quiet" not in myopts:
4167 print ">>> Starting rsync with "+dosyncuri+"..."
4169 emergelog(xterm_titles,
4170 ">>> Starting retry %d of %d with %s" % \
4171 (retries,maxretries,dosyncuri))
4172 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
4174 if mytimestamp != 0 and "--quiet" not in myopts:
4175 print ">>> Checking server timestamp ..."
4177 rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
4179 if "--debug" in myopts:
4184 # Even if there's no timestamp available locally, fetch the
4185 # timestamp anyway as an initial probe to verify that the server is
4186 # responsive. This protects us from hanging indefinitely on a
4187 # connection attempt to an unresponsive server which rsync's
4188 # --timeout option does not prevent.
4190 mycommand = rsynccommand[:]
4191 mycommand.append(dosyncuri.rstrip("/") + \
4192 "/metadata/timestamp.chk")
4193 mycommand.append(tmpservertimestampfile)
4197 def timeout_handler(signum, frame):
4198 raise portage.exception.PortageException("timed out")
4199 signal.signal(signal.SIGALRM, timeout_handler)
4200 # Timeout here in case the server is unresponsive. The
4201 # --timeout rsync option doesn't apply to the initial
4202 # connection attempt.
4203 if rsync_initial_timeout:
4204 signal.alarm(rsync_initial_timeout)
4206 mypids.extend(portage.process.spawn(
4207 mycommand, env=settings.environ(), returnpid=True))
4208 exitcode = os.waitpid(mypids[0], 0)[1]
4209 content = portage.grabfile(tmpservertimestampfile)
4211 if rsync_initial_timeout:
4214 os.unlink(tmpservertimestampfile)
4217 except portage.exception.PortageException, e:
4221 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
4222 os.kill(mypids[0], signal.SIGTERM)
4223 os.waitpid(mypids[0], 0)
4224 # This is the same code rsync uses for timeout.
4227 if exitcode != os.EX_OK:
4229 exitcode = (exitcode & 0xff) << 8
4231 exitcode = exitcode >> 8
4233 portage.process.spawned_pids.remove(mypids[0])
4236 servertimestamp = time.mktime(time.strptime(
4237 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
4238 except (OverflowError, ValueError):
4240 del mycommand, mypids, content
4241 if exitcode == os.EX_OK:
4242 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4243 emergelog(xterm_titles,
4244 ">>> Cancelling sync -- Already current.")
4247 print ">>> Timestamps on the server and in the local repository are the same."
4248 print ">>> Cancelling all further sync action. You are already up to date."
4250 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4254 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4255 emergelog(xterm_titles,
4256 ">>> Server out of date: %s" % dosyncuri)
4259 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4261 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4264 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4266 mycommand = rsynccommand + [dosyncuri+"/", myportdir]
4267 exitcode = portage.process.spawn(mycommand,
4268 env=settings.environ())
4269 if exitcode in [0,1,3,4,11,14,20,21]:
4271 elif exitcode in [1,3,4,11,14,20,21]:
4274 # Code 2 indicates protocol incompatibility, which is expected
4275 # for servers with protocol < 29 that don't support
4276 # --prune-empty-directories. Retry for a server that supports
4277 # at least rsync protocol version 29 (>=rsync-2.6.4).
4282 if retries<=maxretries:
4283 print ">>> Retrying..."
4288 updatecache_flg=False
4292 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4296 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4297 print darkred("!!!")+green(" that your SYNC statement is proper.")
4298 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4300 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4301 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4302 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4303 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4304 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4306 print darkred("!!!")+green(" Rsync was killed before it finished.")
4308 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4309 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4310 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4311 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4312 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4315 elif syncuri[:6]=="cvs://":
4316 if not os.path.exists("/usr/bin/cvs"):
4317 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4318 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4321 cvsdir=os.path.dirname(myportdir)
4322 if not os.path.exists(myportdir+"/CVS"):
4324 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4325 if os.path.exists(cvsdir+"/gentoo-x86"):
4326 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4331 if e.errno != errno.ENOENT:
4333 "!!! existing '%s' directory; exiting.\n" % myportdir)
4336 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4337 print "!!! cvs checkout error; exiting."
4339 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4342 print ">>> Starting cvs update with "+syncuri+"..."
4343 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4344 myportdir, settings, free=1)
4345 if retval != os.EX_OK:
4349 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4352 if updatecache_flg and \
4353 myaction != "metadata" and \
4354 "metadata-transfer" not in settings.features:
4355 updatecache_flg = False
4357 # Reload the whole config from scratch.
4358 settings, trees, mtimedb = load_emerge_config(trees=trees)
4359 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4361 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4362 action_metadata(settings, portdb, myopts)
4364 if portage._global_updates(trees, mtimedb["updates"]):
4366 # Reload the whole config from scratch.
4367 settings, trees, mtimedb = load_emerge_config(trees=trees)
4368 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4370 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4371 mypvs = portage.best(
4372 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4374 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4376 if myaction != "metadata":
4377 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4378 retval = portage.process.spawn(
4379 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4380 dosyncuri], env=settings.environ())
4381 if retval != os.EX_OK:
4382 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4384 if(mybestpv != mypvs) and not "--quiet" in myopts:
4386 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4387 print red(" * ")+"that you update portage now, before any other packages are updated."
4388 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4389 print red(" * ")+"configuration files."
4390 print red(" * ")+"To update portage, run 'emerge portage'."
4393 display_news_notification(settings)
4395 def action_metadata(settings, portdb, myopts):
4396 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4397 old_umask = os.umask(0002)
4398 cachedir = os.path.normpath(settings.depcachedir)
4399 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4400 "/lib", "/opt", "/proc", "/root", "/sbin",
4401 "/sys", "/tmp", "/usr", "/var"]:
4402 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4403 "ROOT DIRECTORY ON YOUR SYSTEM."
4404 print >> sys.stderr, \
4405 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4407 if not os.path.exists(cachedir):
4410 ec = portage.eclass_cache.cache(portdb.porttree_root)
4411 myportdir = os.path.realpath(settings["PORTDIR"])
4412 cm = settings.load_best_module("portdbapi.metadbmodule")(
4413 myportdir, "metadata/cache", portage.auxdbkeys[:])
4415 from portage.cache import util
4417 class percentage_noise_maker(util.quiet_mirroring):
4418 def __init__(self, dbapi):
4420 self.cp_all = dbapi.cp_all()
4421 l = len(self.cp_all)
4422 self.call_update_min = 100000000
4423 self.min_cp_all = l/100.0
4428 for x in self.cp_all:
4430 if self.count > self.min_cp_all:
4431 self.call_update_min = 0
4433 for y in self.dbapi.cp_list(x):
4435 self.call_update_mine = 0
4437 def update(self, *arg):
4438 try: self.pstr = int(self.pstr) + 1
4439 except ValueError: self.pstr = 1
4440 sys.stdout.write("%s%i%%" % \
4441 ("\b" * (len(str(self.pstr))+1), self.pstr))
4443 self.call_update_min = 10000000
4445 def finish(self, *arg):
4446 sys.stdout.write("\b\b\b\b100%\n")
4449 if "--quiet" in myopts:
4450 def quicky_cpv_generator(cp_all_list):
4451 for x in cp_all_list:
4452 for y in portdb.cp_list(x):
4454 source = quicky_cpv_generator(portdb.cp_all())
4455 noise_maker = portage.cache.util.quiet_mirroring()
4457 noise_maker = source = percentage_noise_maker(portdb)
4458 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4459 eclass_cache=ec, verbose_instance=noise_maker)
4464 def action_regen(settings, portdb):
4465 xterm_titles = "notitles" not in settings.features
4466 emergelog(xterm_titles, " === regen")
4467 #regenerate cache entries
4468 print "Regenerating cache entries... "
4470 os.close(sys.stdin.fileno())
4471 except SystemExit, e:
4472 raise # Needed else can't exit
4476 mynodes = portdb.cp_all()
4477 from portage.cache.cache_errors import CacheError
4479 for mytree in portdb.porttrees:
4481 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4482 except CacheError, e:
4483 print "\n error listing cache entries for " + \
4484 "'%s': %s, continuing..." % (mytree, e)
4489 mymatches = portdb.cp_list(x)
4490 portage.writemsg_stdout("processing %s\n" % x)
4493 foo = portdb.aux_get(y,["DEPEND"])
4494 except SystemExit, e:
4495 # sys.exit is an exception... And consequently, we can't catch it.
4497 except Exception, e:
4498 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4500 for mytree in portdb.porttrees:
4501 if portdb.findname2(y, mytree=mytree)[0]:
4502 dead_nodes[mytree].discard(y)
4504 for mytree, nodes in dead_nodes.iteritems():
4505 auxdb = portdb.auxdb[mytree]
4509 except (KeyError, CacheError):
4513 def action_config(settings, trees, myopts, myfiles):
4514 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4515 print red("!!! config can only take a single package atom at this time\n")
4517 if not is_valid_package_atom(myfiles[0]):
4518 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4520 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4521 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4525 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4526 except ValueError, e:
4527 # Multiple matches thrown from cpv_expand
4530 print "No packages found.\n"
4533 if "--ask" in myopts:
4535 print "Please select a package to configure:"
4539 options.append(str(idx))
4540 print options[-1]+") "+pkg
4543 idx = userquery("Selection?", options)
4546 pkg = pkgs[int(idx)-1]
4548 print "The following packages available:"
4551 print "\nPlease use a specific atom or the --ask option."
4557 if "--ask" in myopts:
4558 if userquery("Ready to configure "+pkg+"?") == "No":
4561 print "Configuring pkg..."
4563 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4564 mysettings = portage.config(clone=settings)
4565 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4566 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4567 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4570 def action_info(settings, trees, myopts, myfiles):
4571 unameout=commands.getstatusoutput("uname -mrp")[1]
4572 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4573 settings.profile_path, settings["CHOST"],
4574 trees[settings["ROOT"]]["vartree"].dbapi)
4576 header_title = "System Settings"
4578 print header_width * "="
4579 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4580 print header_width * "="
4581 print "System uname: "+unameout
4582 gentoo_release = portage.grabfile(os.path.join(
4583 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4585 print gentoo_release[0]
4587 print "Unknown Host Operating System"
4588 lastSync = portage.grabfile(os.path.join(
4589 settings["PORTDIR"], "metadata", "timestamp.chk"))
4590 print "Timestamp of tree:",
4596 output=commands.getstatusoutput("distcc --version")
4598 print str(output[1].split("\n",1)[0]),
4599 if "distcc" in settings.features:
4604 output=commands.getstatusoutput("ccache -V")
4606 print str(output[1].split("\n",1)[0]),
4607 if "ccache" in settings.features:
4612 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4613 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4614 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4615 myvars = portage.util.unique_array(myvars)
4619 if portage.isvalidatom(x):
4620 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4621 pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
4622 pkg_matches.sort(portage.pkgcmp)
4624 for pn, ver, rev in pkg_matches:
4626 pkgs.append(ver + "-" + rev)
4630 pkgs = ", ".join(pkgs)
4631 print "%-20s %s" % (x+":", pkgs)
4633 print "%-20s %s" % (x+":", "[NOT VALID]")
4635 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4637 if "--verbose" in myopts:
4638 myvars=settings.keys()
4640 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4641 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4642 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4643 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4645 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4647 myvars = portage.util.unique_array(myvars)
4653 print '%s="%s"' % (x, settings[x])
4655 use = set(settings["USE"].split())
4656 use_expand = settings["USE_EXPAND"].split()
4658 for varname in use_expand:
4659 flag_prefix = varname.lower() + "_"
4661 if f.startswith(flag_prefix):
4665 print 'USE="%s"' % " ".join(use),
4666 for varname in use_expand:
4667 myval = settings.get(varname)
4669 print '%s="%s"' % (varname, myval),
4672 unset_vars.append(x)
4674 print "Unset: "+", ".join(unset_vars)
4677 if "--debug" in myopts:
4678 for x in dir(portage):
4679 module = getattr(portage, x)
4680 if "cvs_id_string" in dir(module):
4681 print "%s: %s" % (str(x), str(module.cvs_id_string))
4683 # See if we can find any packages installed matching the strings
4684 # passed on the command line
4686 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4687 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4689 mypkgs.extend(vardb.match(x))
4691 # If some packages were found...
4693 # Get our global settings (we only print stuff if it varies from
4694 # the current config)
4695 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4696 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4698 pkgsettings = portage.config(clone=settings)
4700 for myvar in mydesiredvars:
4701 global_vals[myvar] = set(settings.get(myvar, "").split())
4703 # Loop through each package
4704 # Only print settings if they differ from global settings
4705 header_printed = False
4707 # Get all package specific variables
4708 auxvalues = vardb.aux_get(pkg, auxkeys)
4710 for i in xrange(len(auxkeys)):
4711 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4713 for myvar in mydesiredvars:
4714 # If the package variable doesn't match the
4715 # current global variable, something has changed
4716 # so set diff_found so we know to print
4717 if valuesmap[myvar] != global_vals[myvar]:
4718 diff_values[myvar] = valuesmap[myvar]
4719 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4720 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4722 # If a matching ebuild is no longer available in the tree, maybe it
4723 # would make sense to compare against the flags for the best
4724 # available version with the same slot?
4726 if portdb.cpv_exists(pkg):
4728 pkgsettings.setcpv(pkg, mydb=mydb)
4729 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4731 diff_values["USE"] = valuesmap["USE"]
4732 # If a difference was found, print the info for
4736 # If we have not yet printed the header,
4738 if not header_printed:
4739 header_title = "Package Settings"
4740 print header_width * "="
4741 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4742 print header_width * "="
4743 header_printed = True
4745 # Print package info
4746 print "%s was built with the following:" % pkg
4747 for myvar in mydesiredvars + ["USE"]:
4748 if myvar in diff_values:
4749 mylist = list(diff_values[myvar])
4751 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4754 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4756 print "emerge: no search terms provided."
4758 searchinstance = search(settings, portdb,
4759 vartree, spinner, "--searchdesc" in myopts,
4760 "--quiet" not in myopts)
4761 for mysearch in myfiles:
4763 searchinstance.execute(mysearch)
4764 except re.error, comment:
4765 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4767 searchinstance.output()
4769 def action_depclean(settings, trees, ldpath_mtimes,
4771 # Kill packages that aren't explicitly merged or are required as a
4772 # dependency of another package. World file is explicit.
4774 warn_prefix = colorize("BAD", "*** WARNING *** ")
4776 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4777 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4778 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4780 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4781 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4782 print warn_prefix + "be kept. They can be manually added to this set with"
4783 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4784 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4785 print warn_prefix + "depclean, even if they are part of the world set."
4787 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4788 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4789 print warn_prefix + "consequence, it is often necessary to run "
4790 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4792 xterm_titles = "notitles" not in settings.features
4793 myroot = settings["ROOT"]
4794 dep_check_trees = {}
4795 dep_check_trees[myroot] = {}
4796 dep_check_trees[myroot]["vartree"] = \
4797 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4798 vardb = dep_check_trees[myroot]["vartree"].dbapi
4799 # Constrain dependency selection to the installed packages.
4800 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4801 syslist = getlist(settings, "system")
4802 worldlist = getlist(settings, "world")
4803 system_world_dict = genericdict(worldlist)
4804 system_world_dict.update(genericdict(syslist))
4805 fakedb = portage.fakedbapi(settings=settings)
4806 myvarlist = vardb.cpv_all()
4809 print "\n!!! You have no system list.",
4811 print "\n!!! You have no world file.",
4813 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4815 if not (syslist and worldlist and myvarlist):
4816 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4817 print " break your installation.\n"
4818 if "--pretend" not in myopts:
4819 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4821 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4822 emergelog(xterm_titles, " >>> depclean")
4824 if "--quiet" not in myopts:
4825 print "\nCalculating dependencies ",
4829 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4830 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4832 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4834 while remaining_atoms:
4835 atom, parent, priority = remaining_atoms.pop()
4836 pkgs = vardb.match(atom)
4838 if not atom.startswith("!") and priority == hard:
4839 unresolveable.setdefault(atom, []).append(parent)
4841 if portage.dep_getkey(atom) not in system_world_dict:
4842 # Prune all but the best matching slot, since that's all that a
4843 # deep world update would pull in. Don't prune if the cpv is in
4844 # system or world though, since those sets trigger greedy update
4846 pkgs = [portage.best(pkgs)]
4848 if fakedb.cpv_exists(pkg):
4851 fakedb.cpv_inject(pkg)
4852 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4854 if myopts.get("--with-bdeps", "y") == "y":
4855 mydeps.append((myaux["DEPEND"], soft))
4857 mydeps.append((" ".join(myaux.values()), hard))
4858 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4859 for depstr, priority in mydeps:
4864 if "--debug" in myopts:
4866 print "Parent: ", pkg
4867 print "Depstring:", depstr
4869 if priority == soft:
4875 portage.dep._dep_check_strict = False
4876 success, atoms = portage.dep_check(depstr, None, settings,
4877 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4879 portage.dep._dep_check_strict = True
4881 show_invalid_depstring_notice(
4882 ("installed", myroot, pkg, "nomerge"),
4886 if "--debug" in myopts:
4887 print "Candidates:", atoms
4890 remaining_atoms.append((atom, pkg, priority))
4892 if "--quiet" not in myopts:
4893 print "\b\b... done!\n"
4896 print "Dependencies could not be completely resolved due to"
4897 print "the following required packages not being installed:"
4899 for atom in unresolveable:
4900 print atom, "required by", " ".join(unresolveable[atom])
4902 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4903 print "depclean? It may be necessary to manually uninstall packages that no longer"
4904 print "exist in the portage tree since it may not be possible to satisfy their"
4905 print "dependencies. Also, be aware of the --with-bdeps option that is documented"
4906 print "in " + good("`man emerge`") + "."
4910 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4913 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4914 "unmerge", cleanlist, ldpath_mtimes)
4916 print "Packages installed: "+str(len(myvarlist))
4917 print "Packages in world: "+str(len(worldlist))
4918 print "Packages in system: "+str(len(syslist))
4919 print "Unique package names: "+str(len(myvarlist))
4920 print "Required packages: "+str(len(fakedb.cpv_all()))
4921 if "--pretend" in myopts:
4922 print "Number to remove: "+str(len(cleanlist))
4924 print "Number removed: "+str(len(cleanlist))
4926 def action_build(settings, trees, mtimedb,
4927 myopts, myaction, myfiles, spinner):
4928 ldpath_mtimes = mtimedb["ldpath"]
4930 if "--quiet" not in myopts and \
4931 ("--pretend" in myopts or "--ask" in myopts or \
4932 "--tree" in myopts or "--verbose" in myopts):
4934 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4938 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4940 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4944 print darkgreen("These are the packages that would be %s, in order:") % action
4947 # validate the state of the resume data
4948 # so that we can make assumptions later.
4949 for k in ("resume", "resume_backup"):
4951 if "mergelist" in mtimedb[k]:
4952 if not mtimedb[k]["mergelist"]:
4957 if "--resume" in myopts and \
4958 ("resume" in mtimedb or
4959 "resume_backup" in mtimedb):
4960 if "resume" not in mtimedb:
4961 mtimedb["resume"] = mtimedb["resume_backup"]
4962 del mtimedb["resume_backup"]
4964 # XXX: "myopts" is a list for backward compatibility.
4965 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4967 for opt in ("--skipfirst", "--ask", "--tree"):
4968 myresumeopts.pop(opt, None)
4970 for myopt, myarg in myopts.iteritems():
4971 if myopt not in myresumeopts:
4972 myresumeopts[myopt] = myarg
4975 # Adjust config according to options of the command being resumed.
4976 for myroot in trees:
4977 mysettings = trees[myroot]["vartree"].settings
4979 adjust_config(myopts, mysettings)
4981 del myroot, mysettings
4983 myparams = create_depgraph_params(myopts, myaction)
4984 if "--quiet" not in myopts and "--nodeps" not in myopts:
4985 print "Calculating dependencies ",
4986 mydepgraph = depgraph(settings, trees,
4987 myopts, myparams, spinner)
4988 if "--quiet" not in myopts and "--nodeps" not in myopts:
4989 print "\b\b... done!"
4991 if ("--resume" in myopts):
4992 print darkgreen("emerge: It seems we have nothing to resume...")
4995 myparams = create_depgraph_params(myopts, myaction)
4996 if myaction in ["system","world"]:
4997 if "--quiet" not in myopts and "--nodeps" not in myopts:
4998 print "Calculating",myaction,"dependencies ",
5000 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
5001 if not mydepgraph.xcreate(myaction):
5002 print "!!! Depgraph creation failed."
5004 if "--quiet" not in myopts and "--nodeps" not in myopts:
5005 print "\b\b... done!"
5007 if "--quiet" not in myopts and "--nodeps" not in myopts:
5008 print "Calculating dependencies ",
5010 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
5012 retval, favorites = mydepgraph.select_files(myfiles)
5013 except portage.exception.PackageNotFound, e:
5014 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
5018 if "--quiet" not in myopts and "--nodeps" not in myopts:
5019 print "\b\b... done!"
5021 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
5022 sys.stderr.write(red("The following binaries are not available for merging...\n"))
5024 if mydepgraph.missingbins:
5025 for x in mydepgraph.missingbins:
5026 sys.stderr.write(" "+str(x)+"\n")
5027 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
5030 if "--pretend" not in myopts and \
5031 ("--ask" in myopts or "--tree" in myopts or \
5032 "--verbose" in myopts) and \
5033 not ("--quiet" in myopts and "--ask" not in myopts):
5034 if "--resume" in myopts:
5035 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5036 mymergelist = mtimedb["resume"]["mergelist"]
5037 if "--skipfirst" in myopts:
5038 mymergelist = mymergelist[1:]
5039 if len(mymergelist) == 0:
5040 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5042 mydepgraph.display(mymergelist)
5043 prompt="Would you like to resume merging these packages?"
5046 mydepgraph.altlist(reversed=("--tree" in myopts)))
5048 for x in mydepgraph.altlist():
5049 if x[0] != "blocks" and x[3] != "nomerge":
5051 #check for blocking dependencies
5052 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
5053 print "\n!!! Error: The above package list contains packages which cannot be installed"
5054 print "!!! at the same time on the same system."
5055 if "--quiet" not in myopts:
5056 show_blocker_docs_link()
5059 if "--noreplace" in myopts and favorites:
5062 print " %s %s" % (good("*"), x)
5063 prompt="Would you like to add these packages to your world favorites?"
5064 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5065 prompt="Nothing to merge; would you like to auto-clean packages?"
5068 print "Nothing to merge; quitting."
5071 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5072 prompt="Would you like to fetch the source files for these packages?"
5074 prompt="Would you like to merge these packages?"
5076 if "--ask" in myopts and userquery(prompt) == "No":
5081 # Don't ask again (e.g. when auto-cleaning packages after merge)
5082 myopts.pop("--ask", None)
5084 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5085 if ("--resume" in myopts):
5086 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5087 mymergelist = mtimedb["resume"]["mergelist"]
5088 if "--skipfirst" in myopts:
5089 mymergelist = mymergelist[1:]
5090 if len(mymergelist) == 0:
5091 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5093 mydepgraph.display(mymergelist)
5096 mydepgraph.altlist(reversed=("--tree" in myopts)))
5097 if ("--buildpkgonly" in myopts):
5098 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5099 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5100 print "!!! You have to merge the dependencies before you can build this package.\n"
5103 if ("--buildpkgonly" in myopts):
5104 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5105 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5106 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
5109 if ("--resume" in myopts):
5110 favorites=mtimedb["resume"]["favorites"]
5111 mergetask = MergeTask(settings, trees, myopts)
5112 if "--fetchonly" in myopts:
5113 """ parallel-fetch uses --resume --fetchonly and we don't want
5114 it to write the mtimedb"""
5115 mtimedb.filename = None
5116 time.sleep(3) # allow the parent to have first fetch
5118 retval = mergetask.merge(
5119 mtimedb["resume"]["mergelist"], favorites, mtimedb)
5120 if retval != os.EX_OK:
5123 if "resume" in mtimedb and \
5124 "mergelist" in mtimedb["resume"] and \
5125 len(mtimedb["resume"]["mergelist"]) > 1:
5126 mtimedb["resume_backup"] = mtimedb["resume"]
5127 del mtimedb["resume"]
5129 mtimedb["resume"]={}
5130 # XXX: Stored as a list for backward compatibility.
5131 mtimedb["resume"]["myopts"] = \
5132 [k for k in myopts if myopts[k] is True]
5133 mtimedb["resume"]["favorites"]=favorites
5134 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5135 for pkgline in mydepgraph.altlist():
5136 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5137 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
5138 tmpsettings = portage.config(clone=settings)
5140 if settings.get("PORTAGE_DEBUG", "") == "1":
5142 retval = portage.doebuild(
5143 y, "digest", settings["ROOT"], tmpsettings, edebug,
5144 ("--pretend" in myopts),
5145 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
5147 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5149 for pkg in mydepgraph.altlist():
5150 if pkg[0] != "blocks":
5153 pkglist = mydepgraph.altlist()
5155 mergetask = MergeTask(settings, trees, myopts)
5156 retval = mergetask.merge(pkglist, favorites, mtimedb)
5157 if retval != os.EX_OK:
5160 if mtimedb.has_key("resume"):
5161 del mtimedb["resume"]
5162 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5163 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5164 vartree = trees[settings["ROOT"]]["vartree"]
5165 unmerge(settings, myopts, vartree, "clean", ["world"],
5166 ldpath_mtimes, autoclean=1)
5168 portage.writemsg_stdout(colorize("WARN", "WARNING:")
5169 + " AUTOCLEAN is disabled. This can cause serious"
5170 + " problems due to overlapping packages.\n")
5172 def multiple_actions(action1, action2):
5173 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
5174 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
5177 def parse_opts(tmpcmdline, silent=False):
5182 global actions, options, shortmapping
5184 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
5185 argument_options = {
5187 "help":"specify the location for portage configuration files",
5191 "help":"enable or disable color output",
5193 "choices":("y", "n")
5196 "help":"include unnecessary build time dependencies",
5198 "choices":("y", "n")
5202 from optparse import OptionParser
5203 parser = OptionParser()
5204 if parser.has_option("--help"):
5205 parser.remove_option("--help")
5207 for action_opt in actions:
5208 parser.add_option("--" + action_opt, action="store_true",
5209 dest=action_opt.replace("-", "_"), default=False)
5210 for myopt in options:
5211 parser.add_option(myopt, action="store_true",
5212 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5213 for shortopt, longopt in shortmapping.iteritems():
5214 parser.add_option("-" + shortopt, action="store_true",
5215 dest=longopt.lstrip("--").replace("-", "_"), default=False)
5216 for myalias, myopt in longopt_aliases.iteritems():
5217 parser.add_option(myalias, action="store_true",
5218 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5220 for myopt, kwargs in argument_options.iteritems():
5221 parser.add_option(myopt,
5222 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
5224 myoptions, myargs = parser.parse_args(args=tmpcmdline)
5226 for myopt in options:
5227 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
5229 myopts[myopt] = True
5231 for myopt in argument_options:
5232 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
5236 for action_opt in actions:
5237 v = getattr(myoptions, action_opt.replace("-", "_"))
5240 multiple_actions(myaction, action_opt)
5242 myaction = action_opt
5245 if x in actions and myaction != "search":
5246 if not silent and x not in ["system", "world"]:
5247 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
5248 # special case "search" so people can search for action terms, e.g. emerge -s sync
5250 multiple_actions(myaction, x)
5256 if "--nocolor" in myopts:
5258 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
5259 "use '--color=n' instead.\n")
5260 del myopts["--nocolor"]
5261 myopts["--color"] = "n"
5263 return myaction, myopts, myfiles
5265 def validate_ebuild_environment(trees):
5266 for myroot in trees:
5267 mysettings = trees[myroot]["vartree"].settings
5268 for var in "ARCH", "USERLAND":
5269 if mysettings.get(var):
5271 print >> sys.stderr, bad(("\a!!! %s is not set... " % var) + \
5272 "Are you missing the '%setc/make.profile' symlink?" % \
5273 mysettings["PORTAGE_CONFIGROOT"])
5274 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5275 "Is your portage tree complete?\n")
5277 del myroot, mysettings
5279 def load_emerge_config(trees=None):
5281 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5282 kwargs[k] = os.environ.get(envvar, None)
5283 trees = portage.create_trees(trees=trees, **kwargs)
5285 settings = trees["/"]["vartree"].settings
5287 for myroot in trees:
5289 settings = trees[myroot]["vartree"].settings
5292 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5293 mtimedb = portage.MtimeDB(mtimedbfile)
5294 return settings, trees, mtimedb
5296 def adjust_config(myopts, settings):
5297 """Make emerge specific adjustments to the config."""
5299 # To enhance usability, make some vars case insensitive by forcing them to
5301 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5302 if myvar in settings:
5303 settings[myvar] = settings[myvar].lower()
5304 settings.backup_changes(myvar)
5307 # Kill noauto as it will break merges otherwise.
5308 if "noauto" in settings.features:
5309 while "noauto" in settings.features:
5310 settings.features.remove("noauto")
5311 settings["FEATURES"] = " ".join(settings.features)
5312 settings.backup_changes("FEATURES")
5316 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5317 except ValueError, e:
5318 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5319 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5320 settings["CLEAN_DELAY"], noiselevel=-1)
5321 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5322 settings.backup_changes("CLEAN_DELAY")
5324 EMERGE_WARNING_DELAY = 10
5326 EMERGE_WARNING_DELAY = int(settings.get(
5327 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5328 except ValueError, e:
5329 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5330 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5331 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5332 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5333 settings.backup_changes("EMERGE_WARNING_DELAY")
5335 if "--quiet" in myopts:
5336 settings["PORTAGE_QUIET"]="1"
5337 settings.backup_changes("PORTAGE_QUIET")
5339 # Set so that configs will be merged regardless of remembered status
5340 if ("--noconfmem" in myopts):
5341 settings["NOCONFMEM"]="1"
5342 settings.backup_changes("NOCONFMEM")
5344 # Set various debug markers... They should be merged somehow.
5347 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5348 if PORTAGE_DEBUG not in (0, 1):
5349 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5350 PORTAGE_DEBUG, noiselevel=-1)
5351 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5354 except ValueError, e:
5355 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5356 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5357 settings["PORTAGE_DEBUG"], noiselevel=-1)
5359 if "--debug" in myopts:
5361 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5362 settings.backup_changes("PORTAGE_DEBUG")
5364 if settings.get("NOCOLOR") not in ("yes","true"):
5365 portage.output.havecolor = 1
5367 """The explicit --color < y | n > option overrides the NOCOLOR environment
5368 variable and stdout auto-detection."""
5369 if "--color" in myopts:
5370 if "y" == myopts["--color"]:
5371 portage.output.havecolor = 1
5372 settings["NOCOLOR"] = "false"
5374 portage.output.havecolor = 0
5375 settings["NOCOLOR"] = "true"
5376 settings.backup_changes("NOCOLOR")
5377 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5378 portage.output.havecolor = 0
5379 settings["NOCOLOR"] = "true"
5380 settings.backup_changes("NOCOLOR")
5383 global portage # NFC why this is necessary now - genone
5384 # Disable color until we're sure that it should be enabled (after
5385 # EMERGE_DEFAULT_OPTS has been parsed).
5386 portage.output.havecolor = 0
5387 # This first pass is just for options that need to be known as early as
5388 # possible, such as --config-root. They will be parsed again later,
5389 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5390 # the value of --config-root).
5391 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5392 if "--debug" in myopts:
5393 os.environ["PORTAGE_DEBUG"] = "1"
5394 if "--config-root" in myopts:
5395 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5397 # Portage needs to ensure a sane umask for the files it creates.
5399 settings, trees, mtimedb = load_emerge_config()
5400 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5403 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5404 except (OSError, ValueError), e:
5405 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5406 settings["PORTAGE_NICENESS"])
5407 portage.writemsg("!!! %s\n" % str(e))
5410 if portage._global_updates(trees, mtimedb["updates"]):
5412 # Reload the whole config from scratch.
5413 settings, trees, mtimedb = load_emerge_config(trees=trees)
5414 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5416 xterm_titles = "notitles" not in settings.features
5419 if "--ignore-default-opts" not in sys.argv:
5420 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5421 tmpcmdline.extend(sys.argv[1:])
5422 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5424 if "--digest" in myopts:
5425 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5426 # Reload the whole config from scratch so that the portdbapi internal
5427 # config is updated with new FEATURES.
5428 settings, trees, mtimedb = load_emerge_config(trees=trees)
5429 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5431 for myroot in trees:
5432 mysettings = trees[myroot]["vartree"].settings
5434 adjust_config(myopts, mysettings)
5436 del myroot, mysettings
5438 spinner = stdout_spinner()
5439 if "candy" in settings.features:
5440 spinner.update = spinner.update_scroll
5442 if "--quiet" not in myopts:
5443 portage.deprecated_profile_check()
5445 #Freeze the portdbapi for enhanced performance:
5446 for myroot in trees:
5447 trees[myroot]["porttree"].dbapi.freeze()
5450 if "moo" in myfiles:
5453 Larry loves Gentoo (""" + os.uname()[0] + """)
5455 _______________________
5456 < Have you mooed today? >
5457 -----------------------
5466 if (myaction in ["world", "system"]) and myfiles:
5467 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5471 ext = os.path.splitext(x)[1]
5472 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5473 print "emerging by path implies --oneshot... adding --oneshot to options."
5474 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5477 if ("--tree" in myopts) and ("--columns" in myopts):
5478 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5481 if ("--quiet" in myopts):
5482 spinner.update = spinner.update_quiet
5483 portage.util.noiselimit = -1
5485 # Always create packages if FEATURES=buildpkg
5486 # Imply --buildpkg if --buildpkgonly
5487 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5488 if "--buildpkg" not in myopts:
5489 myopts["--buildpkg"] = True
5491 # Also allow -S to invoke search action (-sS)
5492 if ("--searchdesc" in myopts):
5493 if myaction and myaction != "search":
5494 myfiles.append(myaction)
5495 if "--search" not in myopts:
5496 myopts["--search"] = True
5499 # Always try and fetch binary packages if FEATURES=getbinpkg
5500 if ("getbinpkg" in settings.features):
5501 myopts["--getbinpkg"] = True
5503 if "--skipfirst" in myopts and "--resume" not in myopts:
5504 myopts["--resume"] = True
5506 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5507 myopts["--usepkgonly"] = True
5509 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5510 myopts["--getbinpkg"] = True
5512 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5513 myopts["--usepkg"] = True
5515 # Also allow -K to apply --usepkg/-k
5516 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5517 myopts["--usepkg"] = True
5519 # Allow -p to remove --ask
5520 if ("--pretend" in myopts) and ("--ask" in myopts):
5521 print ">>> --pretend disables --ask... removing --ask from options."
5524 # forbid --ask when not in a terminal
5525 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5526 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5527 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5531 if settings.get("PORTAGE_DEBUG", "") == "1":
5532 spinner.update = spinner.update_quiet
5534 if "python-trace" in settings.features:
5535 import portage.debug
5536 portage.debug.set_trace(True)
5538 if ("--resume" in myopts):
5539 if "--tree" in myopts:
5540 print "* --tree is currently broken with --resume. Disabling..."
5541 del myopts["--tree"]
5543 if not ("--quiet" in myopts):
5544 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5545 spinner.update = spinner.update_basic
5547 if "--version" in myopts:
5548 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5549 settings.profile_path, settings["CHOST"],
5550 trees[settings["ROOT"]]["vartree"].dbapi)
5552 elif "--help" in myopts:
5553 emerge.help.help(myaction, myopts, portage.output.havecolor)
5556 if portage.wheelgid == portage.portage_gid:
5557 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5558 print " include the portage user as noted above, and then use group portage."
5560 if "--debug" in myopts:
5561 print "myaction", myaction
5562 print "myopts", myopts
5564 if not myaction and not myfiles and "--resume" not in myopts:
5565 emerge.help.help(myaction, myopts, portage.output.havecolor)
5568 # check if root user is the current user for the actions where emerge needs this
5569 if portage.secpass < 2:
5570 # We've already allowed "--version" and "--help" above.
5571 if "--pretend" not in myopts and \
5572 myaction not in ("search","info"):
5573 need_superuser = not \
5574 ("--fetchonly" in myopts or \
5575 "--fetch-all-uri" in myopts or \
5576 myaction in ("metadata", "regen"))
5577 if portage.secpass < 1 or \
5580 access_desc = "superuser"
5582 access_desc = "portage group"
5583 # Always show portage_group_warning() when only portage group
5584 # access is required but the user is not in the portage group.
5585 from portage.data import portage_group_warning
5586 if "--ask" in myopts:
5587 myopts["--pretend"] = True
5589 print ("%s access would be required... " + \
5590 "adding --pretend to options.\n") % access_desc
5591 if portage.secpass < 1 and not need_superuser:
5592 portage_group_warning()
5594 sys.stderr.write(("emerge: %s access would be " + \
5595 "required.\n\n") % access_desc)
5596 if portage.secpass < 1 and not need_superuser:
5597 portage_group_warning()
5600 disable_emergelog = False
5601 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5603 disable_emergelog = True
5605 if myaction in ("search", "info"):
5606 disable_emergelog = True
5607 if disable_emergelog:
5608 """ Disable emergelog for everything except build or unmerge
5609 operations. This helps minimize parallel emerge.log entries that can
5610 confuse log parsers. We especially want it disabled during
5611 parallel-fetch, which uses --resume --fetchonly."""
5613 def emergelog(*pargs, **kargs):
5616 if not "--pretend" in myopts:
5617 emergelog(xterm_titles, "Started emerge on: "+\
5618 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5621 myelogstr=" ".join(myopts)
5623 myelogstr+=" "+myaction
5625 myelogstr+=" "+" ".join(myfiles)
5626 emergelog(xterm_titles, " *** emerge " + myelogstr)
5628 def emergeexitsig(signum, frame):
5629 signal.signal(signal.SIGINT, signal.SIG_IGN)
5630 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5631 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5632 sys.exit(100+signum)
5633 signal.signal(signal.SIGINT, emergeexitsig)
5634 signal.signal(signal.SIGTERM, emergeexitsig)
5637 """This gets out final log message in before we quit."""
5638 if "--pretend" not in myopts:
5639 emergelog(xterm_titles, " *** terminating.")
5640 if "notitles" not in settings.features:
5642 portage.atexit_register(emergeexit)
5644 if myaction in ("config", "metadata", "regen", "sync"):
5645 if "--pretend" in myopts:
5646 sys.stderr.write(("emerge: The '%s' action does " + \
5647 "not support '--pretend'.\n") % myaction)
5649 if "sync" == myaction:
5650 action_sync(settings, trees, mtimedb, myopts, myaction)
5651 elif "metadata" == myaction:
5652 action_metadata(settings, portdb, myopts)
5653 elif myaction=="regen":
5654 validate_ebuild_environment(trees)
5655 action_regen(settings, portdb)
5657 elif "config"==myaction:
5658 validate_ebuild_environment(trees)
5659 action_config(settings, trees, myopts, myfiles)
5662 elif "info"==myaction:
5663 action_info(settings, trees, myopts, myfiles)
5666 elif "search"==myaction:
5667 validate_ebuild_environment(trees)
5668 action_search(settings, portdb, trees["/"]["vartree"],
5669 myopts, myfiles, spinner)
5670 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5671 validate_ebuild_environment(trees)
5672 vartree = trees[settings["ROOT"]]["vartree"]
5673 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5675 if "--pretend" not in myopts:
5676 post_emerge(settings, mtimedb, 0)
5678 elif "depclean"==myaction:
5679 validate_ebuild_environment(trees)
5680 action_depclean(settings, trees, mtimedb["ldpath"],
5682 if "--pretend" not in myopts:
5683 post_emerge(settings, mtimedb, 0)
5684 # "update", "system", or just process files:
5686 validate_ebuild_environment(trees)
5687 if "--pretend" not in myopts:
5688 display_news_notification(settings)
5689 action_build(settings, trees, mtimedb,
5690 myopts, myaction, myfiles, spinner)
5691 if "--pretend" not in myopts:
5692 post_emerge(settings, mtimedb, 0)
5694 display_news_notification(settings)
5696 if __name__ == "__main__":
5697 retval = emerge_main()