2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
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 sys.path.insert(0, "/usr/lib/portage/pym")
31 del os.environ["PORTAGE_LEGACY_GLOBALS"]
32 from portage import digraph, portdbapi
33 from portage_const import NEWS_LIB_PATH
35 import emergehelp, xpak, commands, errno, re, socket, time, types
37 from output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
38 havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
39 xtermTitleReset, yellow
40 from output import create_color_func
41 good = create_color_func("GOOD")
42 bad = create_color_func("BAD")
47 import portage_exception
48 from portage_data import secpass
49 from portage_util import normalize_path as normpath
51 if not hasattr(__builtins__, "set"):
52 from sets import Set as set
53 from itertools import chain, izip
54 from UserDict import DictMixin
59 import pickle as cPickle
61 class stdout_spinner(object):
63 "Gentoo Rocks ("+os.uname()[0]+")",
64 "Thank you for using Gentoo. :)",
65 "Are you actually trying to read this?",
66 "How many times have you stared at this?",
67 "We are generating the cache right now",
68 "You are paying too much attention.",
69 "A theory is better than its explanation.",
70 "Phasers locked on target, Captain.",
71 "Thrashing is just virtual crashing.",
72 "To be is to program.",
73 "Real Users hate Real Programmers.",
74 "When all else fails, read the instructions.",
75 "Functionality breeds Contempt.",
76 "The future lies ahead.",
77 "3.1415926535897932384626433832795028841971694",
78 "Sometimes insanity is the only alternative.",
79 "Inaccuracy saves a world of explanation.",
82 twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
86 self.update = self.update_twirl
87 self.scroll_sequence = self.scroll_msgs[
88 int(time.time() * 100) % len(self.scroll_msgs)]
90 def update_basic(self):
91 self.spinpos = (self.spinpos + 1) % 500
92 if (self.spinpos % 100) == 0:
94 sys.stdout.write(". ")
99 def update_scroll(self):
100 if(self.spinpos >= len(self.scroll_sequence)):
101 sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
102 len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
104 sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
106 self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
108 def update_twirl(self):
109 self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
110 sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
113 def update_quiet(self):
116 def userquery(prompt, responses=None, colours=None):
117 """Displays a prompt and a set of responses, then waits for a response
118 which is checked against the responses and the first to match is
119 returned. An empty response will match the first value in responses. The
120 input buffer is *not* cleared prior to the prompt!
123 responses: a List of Strings.
124 colours: a List of Functions taking and returning a String, used to
125 process the responses for display. Typically these will be functions
126 like red() but could be e.g. lambda x: "DisplayString".
127 If responses is omitted, defaults to ["Yes", "No"], [green, red].
128 If only colours is omitted, defaults to [bold, ...].
130 Returns a member of the List responses. (If called without optional
131 arguments, returns "Yes" or "No".)
132 KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
134 if responses is None:
135 responses, colours = ["Yes", "No"], [green, red]
136 elif colours is None:
138 colours=(colours*len(responses))[:len(responses)]
142 response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
143 for key in responses:
144 # An empty response will match the first value in responses.
145 if response.upper()==key[:len(response)].upper():
147 print "Sorry, response '%s' not understood." % response,
148 except (EOFError, KeyboardInterrupt):
152 def sorted_versions(verlist):
155 verparts = ver.split("-")
156 if len(verparts) == 2:
157 verrev = int(verparts[1][1:])
162 retparts = ret[x].split("-")
163 verdiff = portage.vercmp(retparts[0], verparts[0])
167 if len(retparts) == 2:
168 retrev = int(retparts[1][1:])
179 "clean", "config", "depclean",
181 "prune", "regen", "search",
182 "sync", "system", "unmerge", "world",
185 "--ask", "--alphabetical",
186 "--buildpkg", "--buildpkgonly",
187 "--changelog", "--columns",
191 "--fetchonly", "--fetch-all-uri",
192 "--getbinpkg", "--getbinpkgonly",
193 "--help", "--ignore-default-opts",
195 "--newuse", "--nocolor",
196 "--nodeps", "--noreplace",
197 "--nospinner", "--oneshot",
198 "--onlydeps", "--pretend",
199 "--quiet", "--resume",
200 "--searchdesc", "--selective",
204 "--usepkg", "--usepkgonly",
205 "--verbose", "--version"
211 "b":"--buildpkg", "B":"--buildpkgonly",
212 "c":"--clean", "C":"--unmerge",
213 "d":"--debug", "D":"--deep",
215 "f":"--fetchonly", "F":"--fetch-all-uri",
216 "g":"--getbinpkg", "G":"--getbinpkgonly",
218 "k":"--usepkg", "K":"--usepkgonly",
220 "n":"--noreplace", "N":"--newuse",
221 "o":"--onlydeps", "O":"--nodeps",
222 "p":"--pretend", "P":"--prune",
224 "s":"--search", "S":"--searchdesc",
227 "v":"--verbose", "V":"--version"
230 def emergelog(xterm_titles, mystr, short_msg=None):
233 xtermTitle(short_msg)
237 file_path = "/var/log/emerge.log"
238 mylogfile = open(file_path, "a")
239 portage_util.apply_secpass_permissions(file_path,
240 uid=portage.portage_uid, gid=portage.portage_gid,
244 mylock = portage_locks.lockfile(mylogfile)
245 # seek because we may have gotten held up by the lock.
246 # if so, we may not be positioned at the end of the file.
248 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
252 portage_locks.unlockfile(mylock)
254 except (IOError,OSError,portage_exception.PortageException), e:
256 print >> sys.stderr, "emergelog():",e
258 def countdown(secs=5, doing="Starting"):
260 print ">>> Waiting",secs,"seconds before starting..."
261 print ">>> (Control-C to abort)...\n"+doing+" in: ",
265 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
270 # formats a size given in bytes nicely
271 def format_size(mysize):
272 if type(mysize) not in [types.IntType,types.LongType]:
274 if 0 != mysize % 1024:
275 # Always round up to the next kB so that it doesn't show 0 kB when
276 # some small file still needs to be fetched.
277 mysize += 1024 - mysize % 1024
278 mystr=str(mysize/1024)
282 mystr=mystr[:mycount]+","+mystr[mycount:]
286 def getgccversion(chost):
289 return: the current in-use gcc version
292 gcc_ver_command = 'gcc -dumpversion'
293 gcc_ver_prefix = 'gcc-'
295 gcc_not_found_error = red(
296 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
297 "!!! to update the environment of this terminal and possibly\n" +
298 "!!! other terminals also.\n"
301 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
302 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
303 part1, part2 = myoutput.split("/")
304 if part1.startswith(chost + "-"):
305 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
307 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
308 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
309 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
311 mystatus, myoutput = commands.getstatusoutput(
312 chost + "-" + gcc_ver_command)
313 if mystatus == os.EX_OK:
314 return gcc_ver_prefix + myoutput
316 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
317 if mystatus == os.EX_OK:
318 return gcc_ver_prefix + myoutput
320 portage.writemsg(gcc_not_found_error, noiselevel=-1)
321 return "[unavailable]"
323 def getportageversion(portdir, target_root, profile, chost, vardb):
324 profilever = "unavailable"
326 realpath = os.path.realpath(profile)
327 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
328 if realpath.startswith(basepath):
329 profilever = realpath[1 + len(basepath):]
332 profilever = "!" + os.readlink(profile)
335 del realpath, basepath
338 libclist = vardb.match("virtual/libc")
339 libclist += vardb.match("virtual/glibc")
340 libclist = portage_util.unique_array(libclist)
342 xs=portage.catpkgsplit(x)
344 libcver+=","+"-".join(xs[1:])
346 libcver="-".join(xs[1:])
348 libcver="unavailable"
350 gccver = getgccversion(chost)
351 unameout=os.uname()[2]+" "+os.uname()[4]
353 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
355 def create_depgraph_params(myopts, myaction):
356 #configure emerge engine parameters
358 # self: include _this_ package regardless of if it is merged.
359 # selective: exclude the package if it is merged
360 # recurse: go into the dependencies
361 # deep: go into the dependencies of already merged packages
362 # empty: pretend nothing is merged
363 myparams = ["recurse"]
366 if "--update" in myopts or \
367 "--newuse" in myopts or \
368 "--noreplace" in myopts or \
369 myaction in ("system", "world"):
370 add.extend(["selective"])
371 if "--emptytree" in myopts:
372 add.extend(["empty"])
373 sub.extend(["selective"])
374 if "--nodeps" in myopts:
375 sub.extend(["recurse"])
376 if "--deep" in myopts:
379 if (x not in myparams) and (x not in sub):
386 # search functionality
398 def __init__(self, settings, portdb, vartree, spinner, searchdesc,
400 """Searches the available and installed packages for the supplied search key.
401 The list of available and installed packages is created at object instantiation.
402 This makes successive searches faster."""
403 self.settings = settings
405 self.vartree = vartree
406 self.spinner = spinner
407 self.verbose = verbose
408 self.searchdesc = searchdesc
410 def execute(self,searchkey):
411 """Performs the search for the supplied search key"""
413 self.searchkey=searchkey
414 self.packagematches = []
417 self.matches = {"pkg":[], "desc":[]}
420 self.matches = {"pkg":[]}
421 print "Searching... ",
424 if self.searchkey[0] == '%':
426 self.searchkey = self.searchkey[1:]
427 if self.searchkey[0] == '@':
429 self.searchkey = self.searchkey[1:]
431 self.searchre=re.compile(self.searchkey,re.I)
433 self.searchre=re.compile(re.escape(self.searchkey), re.I)
434 for package in self.portdb.cp_all():
435 self.spinner.update()
438 match_string = package[:]
440 match_string = package.split("/")[-1]
443 if self.searchre.search(match_string):
444 if not self.portdb.xmatch("match-visible", package):
446 self.matches["pkg"].append([package,masked])
447 elif self.searchdesc: # DESCRIPTION searching
448 full_package = self.portdb.xmatch("bestmatch-visible", package)
450 #no match found; we don't want to query description
451 full_package = portage.best(
452 self.portdb.xmatch("match-all", package))
458 full_desc = self.portdb.aux_get(
459 full_package, ["DESCRIPTION"])[0]
461 print "emerge: search: aux_get() failed, skipping"
463 if self.searchre.search(full_desc):
464 self.matches["desc"].append([full_package,masked])
466 for mtype in self.matches.keys():
467 self.matches[mtype].sort()
468 self.mlen += len(self.matches[mtype])
471 """Outputs the results of the search."""
472 print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
473 print "[ Applications found : "+white(str(self.mlen))+" ]"
475 for mtype in self.matches.keys():
476 for match,masked in self.matches[mtype]:
479 full_package = self.portdb.xmatch(
480 "bestmatch-visible", match)
482 #no match found; we don't want to query description
484 full_package = portage.best(
485 self.portdb.xmatch("match-all",match))
488 match = portage.pkgsplit(match)[0]
492 desc, homepage, license = self.portdb.aux_get(
493 full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
495 print "emerge: search: aux_get() failed, skipping"
498 print green("*")+" "+white(match)+" "+red("[ Masked ]")
500 print green("*")+" "+white(match)
501 myversion = self.getVersion(full_package, search.VERSION_RELEASE)
504 mycat = match.split("/")[0]
505 mypkg = match.split("/")[1]
506 mycpv = match + "-" + myversion
507 myebuild = self.portdb.findname(mycpv)
508 pkgdir = os.path.dirname(myebuild)
509 import portage_manifest
510 mf = portage_manifest.Manifest(
511 pkgdir, self.settings["DISTDIR"])
512 fetchlist = self.portdb.getfetchlist(mycpv,
513 mysettings=self.settings, all=True)[1]
515 mysum[0] = mf.getDistfilesSize(fetchlist)
516 mystr = str(mysum[0]/1024)
520 mystr=mystr[:mycount]+","+mystr[mycount:]
523 mysum[0] = "Unknown (missing digest for %s)" % str(e)
526 print " ", darkgreen("Latest version available:"),myversion
527 print " ", self.getInstallationStatus(mycat+'/'+mypkg)
528 print " ", darkgreen("Size of files:"),mysum[0]
529 print " ", darkgreen("Homepage:")+" ",homepage
530 print " ", darkgreen("Description:")+" ",desc
531 print " ", darkgreen("License:")+" ",license
537 def getInstallationStatus(self,package):
538 installed_package = self.vartree.dep_bestmatch(package)
540 version = self.getVersion(installed_package,search.VERSION_RELEASE)
542 result = darkgreen("Latest version installed:")+" "+version
544 result = darkgreen("Latest version installed:")+" [ Not Installed ]"
547 def getVersion(self,full_package,detail):
548 if len(full_package) > 1:
549 package_parts = portage.catpkgsplit(full_package)
550 if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
551 result = package_parts[2]+ "-" + package_parts[3]
553 result = package_parts[2]
559 #build our package digraph
560 def getlist(settings, mode):
562 mylines = settings.packages
565 file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
566 myfile = open(file_path, "r")
567 mylines = myfile.readlines()
569 except (OSError, IOError), e:
570 if e.errno == errno.ENOENT:
571 portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
577 myline=" ".join(x.split())
586 mynewlines.append(myline.strip())
590 def clean_world(vardb, cpv):
591 """Remove a package from the world file when unmerged."""
592 world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
593 worldlist = portage_util.grabfile(world_filename)
594 mykey = portage.cpv_getkey(cpv)
597 if portage.dep_getkey(x) == mykey:
598 matches = vardb.match(x, use_cache=0)
602 elif len(matches) == 1 and matches[0] == cpv:
606 #others are around; keep it.
607 newworldlist.append(x)
609 #this doesn't match the package we're unmerging; keep it.
610 newworldlist.append(x)
612 portage_util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
613 gid=portage.portage_gid, mode=02770)
614 portage_util.write_atomic(world_filename, "\n".join(newworldlist))
616 def genericdict(mylist):
619 mynewdict[portage.dep_getkey(x)]=x
622 def filter_iuse_defaults(iuse):
624 if flag.startswith("+"):
629 class DepPriority(object):
631 This class generates an integer priority level based of various
632 attributes of the dependency relationship. Attributes can be assigned
633 at any time and the new integer value will be generated on calls to the
634 __int__() method. Rich comparison operators are supported.
636 The boolean attributes that affect the integer value are "satisfied",
637 "buildtime", "runtime", and "system". Various combinations of
638 attributes lead to the following priority levels:
640 Combination of properties Priority level
642 not satisfied and buildtime 0
643 not satisfied and runtime -1
644 satisfied and buildtime -2
645 satisfied and runtime -3
646 (none of the above) -4
648 Several integer constants are defined for categorization of priority
651 MEDIUM The upper boundary for medium dependencies.
652 SOFT The upper boundary for soft dependencies.
653 MIN The lower boundary for soft dependencies.
655 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
659 def __init__(self, **kwargs):
660 for myattr in self.__slots__:
661 if myattr == "__weakref__":
663 myvalue = kwargs.get(myattr, False)
664 setattr(self, myattr, myvalue)
666 if not self.satisfied:
676 def __lt__(self, other):
677 return self.__int__() < other
678 def __le__(self, other):
679 return self.__int__() <= other
680 def __eq__(self, other):
681 return self.__int__() == other
682 def __ne__(self, other):
683 return self.__int__() != other
684 def __gt__(self, other):
685 return self.__int__() > other
686 def __ge__(self, other):
687 return self.__int__() >= other
690 return copy.copy(self)
692 myvalue = self.__int__()
693 if myvalue > self.MEDIUM:
695 if myvalue > self.SOFT:
699 class FakeVartree(portage.vartree):
700 """This is implements an in-memory copy of a vartree instance that provides
701 all the interfaces required for use by the depgraph. The vardb is locked
702 during the constructor call just long enough to read a copy of the
703 installed package information. This allows the depgraph to do it's
704 dependency calculations without holding a lock on the vardb. It also
705 allows things like vardb global updates to be done in memory so that the
706 user doesn't necessarily need write access to the vardb in cases where
707 global updates are necessary (updates are performed when necessary if there
708 is not a matching ebuild in the tree)."""
709 def __init__(self, real_vartree, portdb):
710 self.root = real_vartree.root
711 self.settings = real_vartree.settings
712 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
713 vdb_path = os.path.join(self.root, portage.VDB_PATH)
715 # At least the parent needs to exist for the lock file.
716 portage_util.ensure_dirs(vdb_path)
717 except portage_exception.PortageException:
721 if os.access(vdb_path, os.W_OK):
722 vdb_lock = portage_locks.lockdir(vdb_path)
723 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
724 "DEPEND", "RDEPEND", "PDEPEND"]
725 real_dbapi = real_vartree.dbapi
727 for cpv in real_dbapi.cpv_all():
728 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
729 myslot = metadata["SLOT"]
730 mycp = portage.dep_getkey(cpv)
731 myslot_atom = "%s:%s" % (mycp, myslot)
733 mycounter = long(metadata["COUNTER"])
736 metadata["COUNTER"] = str(mycounter)
737 other_counter = slot_counters.get(myslot_atom, None)
738 if other_counter is not None:
739 if other_counter > mycounter:
741 slot_counters[myslot_atom] = mycounter
742 self.dbapi.cpv_inject(cpv, metadata=metadata)
743 real_dbapi.flush_cache()
746 portage_locks.unlockdir(vdb_lock)
747 # Populate the old-style virtuals using the cached values.
748 if not self.settings.treeVirtuals:
749 self.settings.treeVirtuals = portage_util.map_dictlist_vals(
750 portage.getCPFromCPV, self.get_all_provides())
752 # Intialize variables needed for lazy cache pulls of the live ebuild
753 # metadata. This ensures that the vardb lock is released ASAP, without
754 # being delayed in case cache generation is triggered.
755 self._aux_get = self.dbapi.aux_get
756 self.dbapi.aux_get = self._aux_get_wrapper
757 self._aux_get_history = set()
758 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
759 self._portdb = portdb
760 self._global_updates = None
762 def _aux_get_wrapper(self, pkg, wants):
763 if pkg in self._aux_get_history:
764 return self._aux_get(pkg, wants)
765 self._aux_get_history.add(pkg)
767 # Use the live ebuild metadata if possible.
768 live_metadata = dict(izip(self._portdb_keys,
769 self._portdb.aux_get(pkg, self._portdb_keys)))
770 self.dbapi.aux_update(pkg, live_metadata)
771 except (KeyError, portage_exception.PortageException):
772 if self._global_updates is None:
773 self._global_updates = \
774 grab_global_updates(self._portdb.porttree_root)
775 perform_global_updates(
776 pkg, self.dbapi, self._global_updates)
777 return self._aux_get(pkg, wants)
779 def grab_global_updates(portdir):
780 from portage_update import grab_updates, parse_updates
781 updpath = os.path.join(portdir, "profiles", "updates")
783 rawupdates = grab_updates(updpath)
784 except portage_exception.DirectoryNotFound:
787 for mykey, mystat, mycontent in rawupdates:
788 commands, errors = parse_updates(mycontent)
789 upd_commands.extend(commands)
792 def perform_global_updates(mycpv, mydb, mycommands):
793 from portage_update import update_dbentries
794 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
795 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
796 updates = update_dbentries(mycommands, aux_dict)
798 mydb.aux_update(mycpv, updates)
800 class BlockerCache(DictMixin):
801 """This caches blockers of installed packages so that dep_check does not
802 have to be done for every single installed package on every invocation of
803 emerge. The cache is invalidated whenever it is detected that something
804 has changed that might alter the results of dep_check() calls:
805 1) the set of installed packages (including COUNTER) has changed
806 2) the old-style virtuals have changed
808 class BlockerData(object):
809 def __init__(self, counter, atoms):
810 self.counter = counter
813 def __init__(self, myroot, vardb):
815 self._installed_pkgs = set(vardb.cpv_all())
816 self._virtuals = vardb.settings.getvirtuals()
817 self._cache_filename = os.path.join(myroot,
818 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
819 self._cache_version = "1"
820 self._cache_data = None
821 self._modified = False
826 f = open(self._cache_filename)
827 mypickle = cPickle.Unpickler(f)
828 mypickle.find_global = None
829 self._cache_data = mypickle.load()
832 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
834 cache_valid = self._cache_data and \
835 isinstance(self._cache_data, dict) and \
836 self._cache_data.get("version") == self._cache_version and \
837 self._cache_data.get("virtuals") == self._virtuals and \
838 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
840 for pkg in self._installed_pkgs:
841 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
846 self._cache_data = {"version":self._cache_version}
847 self._cache_data["blockers"] = {}
848 self._cache_data["virtuals"] = self._virtuals
849 self._modified = False
852 """If the current user has permission and the internal blocker cache
853 been updated, save it to disk and mark it unmodified. This is called
854 by emerge after it has proccessed blockers for all installed packages.
855 Currently, the cache is only written if the user has superuser
856 privileges (since that's required to obtain a lock), but all users
857 have read access and benefit from faster blocker lookups (as long as
858 the entire cache is still valid). The cache is stored as a pickled
859 dict object with the following format:
863 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
864 "virtuals" : vardb.settings.getvirtuals()
867 if self._modified and \
870 f = portage_util.atomic_ofstream(self._cache_filename)
871 cPickle.dump(self._cache_data, f, -1)
873 portage_util.apply_secpass_permissions(
874 self._cache_filename, gid=portage.portage_gid, mode=0644)
875 except (IOError, OSError), e:
877 self._modified = False
879 def __setitem__(self, cpv, blocker_data):
881 Update the cache and mark it as modified for a future call to
884 @param cpv: Package for which to cache blockers.
886 @param blocker_data: An object with counter and atoms attributes.
887 @type blocker_data: BlockerData
889 self._cache_data["blockers"][cpv] = \
890 (blocker_data.counter, blocker_data.atoms)
891 self._modified = True
893 def __getitem__(self, cpv):
896 @returns: An object with counter and atoms attributes.
898 return self.BlockerData(*self._cache_data["blockers"][cpv])
900 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
902 from formatter import AbstractFormatter, DumbWriter
903 f = AbstractFormatter(DumbWriter(maxcol=72))
905 print "\n\n!!! Invalid or corrupt dependency specification: "
913 p_type, p_root, p_key, p_status = parent_node
915 if p_status == "nomerge":
916 category, pf = portage.catsplit(p_key)
917 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
918 msg.append("Portage is unable to process the dependencies of the ")
919 msg.append("'%s' package. " % p_key)
920 msg.append("In order to correct this problem, the package ")
921 msg.append("should be uninstalled, reinstalled, or upgraded. ")
922 msg.append("As a temporary workaround, the --nodeps option can ")
923 msg.append("be used to ignore all dependencies. For reference, ")
924 msg.append("the problematic dependencies can be found in the ")
925 msg.append("*DEPEND files located in '%s/'." % pkg_location)
927 msg.append("This package can not be installed. ")
928 msg.append("Please notify the '%s' package maintainer " % p_key)
929 msg.append("about this problem.")
932 f.add_flowing_data(x)
940 "installed":"vartree"}
942 def __init__(self, settings, trees, myopts, myparams, spinner):
943 self.settings = settings
944 self.target_root = settings["ROOT"]
946 self.myparams = myparams
948 if settings.get("PORTAGE_DEBUG", "") == "1":
950 self.spinner = spinner
951 self.pkgsettings = {}
952 # Maps cpv to digraph node for all nodes added to the graph.
953 self.pkg_node_map = {}
954 # Maps slot atom to digraph node for all nodes added to the graph.
955 self._slot_node_map = {}
957 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
961 self.trees[myroot] = {}
962 for tree in ("porttree", "bintree"):
963 self.trees[myroot][tree] = trees[myroot][tree]
964 self.trees[myroot]["vartree"] = \
965 FakeVartree(trees[myroot]["vartree"],
966 trees[myroot]["porttree"].dbapi)
967 self.pkgsettings[myroot] = portage.config(
968 clone=self.trees[myroot]["vartree"].settings)
969 self.pkg_node_map[myroot] = {}
970 self._slot_node_map[myroot] = {}
971 vardb = self.trees[myroot]["vartree"].dbapi
972 # This fakedbapi instance will model the state that the vdb will
973 # have after new packages have been installed.
974 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
975 self.mydbapi[myroot] = fakedb
976 if "--nodeps" not in self.myopts and \
977 "--buildpkgonly" not in self.myopts:
978 # --nodeps bypasses this, since it isn't needed in this case
979 # and the cache pulls might trigger (slow) cache generation.
980 for pkg in vardb.cpv_all():
981 self.spinner.update()
982 fakedb.cpv_inject(pkg,
983 metadata=dict(izip(self._mydbapi_keys,
984 vardb.aux_get(pkg, self._mydbapi_keys))))
986 self.useFlags[myroot] = {}
987 if "--usepkg" in self.myopts:
988 self.trees[myroot]["bintree"].populate(
989 "--getbinpkg" in self.myopts,
990 "--getbinpkgonly" in self.myopts)
994 self.digraph=portage.digraph()
995 # Tracks simple parent/child relationships (PDEPEND relationships are
997 self._parent_child_digraph = digraph()
999 self.outdatedpackages=[]
1001 self.blocker_digraph = digraph()
1002 self.blocker_parents = {}
1003 self._slot_collision_info = []
1004 # Slot collision nodes are not allowed to block other packages since
1005 # blocker validation is only able to account for one package per slot.
1006 self._slot_collision_nodes = set()
1007 self._altlist_cache = {}
1008 self._pprovided_args = []
1010 def _show_slot_collision_notice(self, packages):
1011 """Show an informational message advising the user to mask one of the
1012 the packages. In some cases it may be possible to resolve this
1013 automatically, but support for backtracking (removal nodes that have
1014 already been selected) will be required in order to handle all possible
1018 msg.append("\n!!! Multiple versions within a single " + \
1019 "package slot have been \n")
1020 msg.append("!!! pulled into the dependency graph:\n\n")
1021 for node, parents in packages:
1022 msg.append(str(node))
1024 msg.append(" pulled in by\n")
1025 for parent in parents:
1027 msg.append(str(parent))
1030 msg.append(" (no parents)\n")
1032 sys.stderr.write("".join(msg))
1035 if "--quiet" in self.myopts:
1039 msg.append("It may be possible to solve this problem ")
1040 msg.append("by using package.mask to prevent one of ")
1041 msg.append("those packages from being selected. ")
1042 msg.append("However, it is also possible that conflicting ")
1043 msg.append("dependencies exist such that they are impossible to ")
1044 msg.append("satisfy simultaneously. If such a conflict exists in ")
1045 msg.append("the dependencies of two different packages, then those ")
1046 msg.append("packages can not be installed simultaneously.")
1048 from formatter import AbstractFormatter, DumbWriter
1049 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1051 f.add_flowing_data(x)
1055 msg.append("For more information, see MASKED PACKAGES ")
1056 msg.append("section in the emerge man page or refer ")
1057 msg.append("to the Gentoo Handbook.")
1059 f.add_flowing_data(x)
1063 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1064 priority=DepPriority(), rev_dep=False, arg=None):
1066 Fills the digraph with nodes comprised of packages to merge.
1067 mybigkey is the package spec of the package to merge.
1068 myparent is the package depending on mybigkey ( or None )
1069 addme = Should we add this package to the digraph or are we just looking at it's deps?
1070 Think --onlydeps, we need to ignore packages in that case.
1073 #IUSE-aware emerge -> USE DEP aware depgraph
1074 #"no downgrade" emerge
1076 mytype, myroot, mykey = mybigkey
1077 existing_node = None
1079 existing_node = self.pkg_node_map[myroot].get(mykey)
1081 self._parent_child_digraph.add(existing_node, myparent)
1082 if existing_node != myparent:
1083 # Refuse to make a node depend on itself so that the we don't
1084 # don't create a bogus circular dependency in self.altlist().
1085 if rev_dep and myparent:
1086 self.digraph.addnode(myparent, existing_node,
1089 self.digraph.addnode(existing_node, myparent,
1093 self.spinner.update()
1094 if mytype == "blocks":
1096 "--buildpkgonly" not in self.myopts and \
1097 "--nodeps" not in self.myopts and \
1098 myparent not in self._slot_collision_nodes:
1099 mybigkey[1] = myparent[1]
1100 self.blocker_parents.setdefault(
1101 tuple(mybigkey), set()).add(myparent)
1103 if not arg and myroot == self.target_root:
1104 arg = portage.best_match_to_list(mykey, self.args_keys)
1105 # select the correct /var database that we'll be checking against
1106 vardbapi = self.trees[myroot]["vartree"].dbapi
1107 portdb = self.trees[myroot]["porttree"].dbapi
1108 bindb = self.trees[myroot]["bintree"].dbapi
1109 pkgsettings = self.pkgsettings[myroot]
1111 # if the package is already on the system, we add a "nomerge"
1112 # directive, otherwise we add a "merge" directive.
1114 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1117 self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
1118 myuse = self.pkgsettings[myroot]["USE"].split()
1121 if mytype == "installed":
1123 if addme and mytype != "installed":
1124 # this is where we add the node to the list of packages to merge
1125 if "selective" in self.myparams or not arg:
1126 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1129 """ If we aren't merging, perform the --newuse check.
1130 If the package has new iuse flags or different use flags then if
1131 --newuse is specified, we need to merge the package. """
1132 if merging==0 and "--newuse" in self.myopts and \
1133 mytype == "ebuild" and \
1134 vardbapi.cpv_exists(mykey):
1135 pkgsettings.setcpv(mykey, mydb=portdb)
1136 forced_flags = set()
1137 forced_flags.update(pkgsettings.useforce)
1138 forced_flags.update(pkgsettings.usemask)
1139 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1140 iuses = set(filter_iuse_defaults(
1141 mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
1142 old_iuse = set(filter_iuse_defaults(
1143 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1144 if iuses.symmetric_difference(
1145 old_iuse).difference(forced_flags):
1147 elif old_iuse.intersection(old_use) != \
1148 iuses.intersection(myuse):
1151 if addme and merging == 1:
1152 mybigkey.append("merge")
1154 mybigkey.append("nomerge")
1155 jbigkey = tuple(mybigkey)
1158 metadata = dict(izip(self._mydbapi_keys,
1159 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1160 if merging == 0 and vardbapi.cpv_exists(mykey):
1161 metadata["USE"] = vardbapi.aux_get(mykey, ["USE"])[0]
1162 myuse = metadata["USE"].split()
1163 metadata["SLOT"] = vardbapi.aux_get(mykey, ["SLOT"])[0]
1164 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1165 existing_node = self._slot_node_map[myroot].get(
1167 slot_collision = False
1169 e_type, myroot, e_cpv, e_status = existing_node
1171 # The existing node can be reused.
1172 self._parent_child_digraph.add(existing_node, myparent)
1173 if rev_dep and myparent:
1174 ptype, proot, pkey, pstatus = myparent
1175 self.digraph.addnode(myparent, existing_node,
1178 self.digraph.addnode(existing_node, myparent,
1182 # A slot collision has occurred. Sometimes this coincides
1183 # with unresolvable blockers, so the slot collision will be
1184 # shown later if there are no unresolvable blockers.
1185 e_parents = self._parent_child_digraph.parent_nodes(
1189 myparents.append(myparent)
1190 self._slot_collision_info.append(
1191 ((jbigkey, myparents), (existing_node, e_parents)))
1192 self._slot_collision_nodes.add(jbigkey)
1193 slot_collision = True
1196 # Now add this node to the graph so that self.display()
1197 # can show use flags and --tree output. This node is
1198 # only being partially added to the graph. It must not be
1199 # allowed to interfere with the other nodes that have been
1200 # added. Do not overwrite data for existing nodes in
1201 # self.pkg_node_map and self.mydbapi since that data will
1202 # be used for blocker validation.
1203 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1204 self.useFlags[myroot].setdefault(mykey, myuse)
1205 # Even though the graph is now invalid, continue to process
1206 # dependencies so that things like --fetchonly can still
1207 # function despite collisions.
1209 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1210 self._slot_node_map[myroot][slot_atom] = jbigkey
1211 self.pkg_node_map[myroot][mykey] = jbigkey
1212 self.useFlags[myroot][mykey] = myuse
1214 if rev_dep and myparent:
1215 self.digraph.addnode(myparent, jbigkey,
1218 self.digraph.addnode(jbigkey, myparent,
1221 # Do this even when addme is False (--onlydeps) so that the
1222 # parent/child relationship is always known in case
1223 # self._show_slot_collision_notice() needs to be called later.
1224 self._parent_child_digraph.add(jbigkey, myparent)
1226 """ This section determines whether we go deeper into dependencies or not.
1227 We want to go deeper on a few occasions:
1228 Installing package A, we need to make sure package A's deps are met.
1229 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1230 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1232 if "deep" not in self.myparams and not merging and \
1233 not ("--update" in self.myopts and arg and merging):
1235 elif "recurse" not in self.myparams:
1238 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1239 Pull from bintree if it's binary package, porttree if it's ebuild.
1240 Binpkg's can be either remote or local. """
1243 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1244 depvalues = mydbapi.aux_get(mykey, depkeys)
1245 for i in xrange(len(depkeys)):
1246 edepend[depkeys[i]] = depvalues[i]
1248 if mytype == "ebuild":
1249 if "--buildpkgonly" in self.myopts:
1250 edepend["RDEPEND"] = ""
1251 edepend["PDEPEND"] = ""
1252 if not (arg and "--onlydeps" in self.myopts and \
1253 mytype == "ebuild") and \
1254 self.myopts.get("--with-bdeps", "n") == "n" and \
1255 (mytype == "binary" or mybigkey[3] == "nomerge"):
1256 edepend["DEPEND"] = ""
1258 """ We have retrieve the dependency information, now we need to recursively
1259 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1261 mp = tuple(mybigkey)
1264 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1265 myuse=myuse, priority=DepPriority(buildtime=True),
1268 """RDEPEND is soft by definition. However, in order to ensure
1269 correct merge order, we make it a hard dependency. Otherwise, a
1270 build time dependency might not be usable due to it's run time
1271 dependencies not being installed yet.
1273 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1274 myuse=myuse, priority=DepPriority(runtime=True),
1277 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1278 # Post Depend -- Add to the list without a parent, as it depends
1279 # on a package being present AND must be built after that package.
1280 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1281 myuse=myuse, priority=DepPriority(), rev_deps=True,
1284 except ValueError, e:
1286 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1287 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1289 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1290 portage.writemsg("\n", noiselevel=-1)
1291 if mytype == "binary":
1293 "!!! This binary package cannot be installed: '%s'\n" % \
1294 mykey, noiselevel=-1)
1295 elif mytype == "ebuild":
1296 myebuild, mylocation = portdb.findname2(mykey)
1297 portage.writemsg("!!! This ebuild cannot be installed: " + \
1298 "'%s'\n" % myebuild, noiselevel=-1)
1299 portage.writemsg("!!! Please notify the package maintainer " + \
1300 "that atoms must be fully-qualified.\n", noiselevel=-1)
1304 def select_files(self,myfiles):
1305 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1307 myroot = self.target_root
1308 portdb = self.trees[myroot]["porttree"].dbapi
1309 bindb = self.trees[myroot]["bintree"].dbapi
1310 pkgsettings = self.pkgsettings[myroot]
1312 def visible(mylist):
1313 matches = portdb.gvisible(portdb.visible(mylist))
1314 return [x for x in mylist \
1315 if x in matches or not portdb.cpv_exists(x)]
1317 ext = os.path.splitext(x)[1]
1319 if not os.path.exists(x):
1321 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1322 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1323 elif os.path.exists(
1324 os.path.join(pkgsettings["PKGDIR"], x)):
1325 x = os.path.join(pkgsettings["PKGDIR"], x)
1327 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1328 print "!!! Please ensure the tbz2 exists as specified.\n"
1331 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1332 if os.path.realpath(x) != \
1333 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1334 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1336 if not self.create(["binary", myroot, mykey],
1337 None, "--onlydeps" not in self.myopts):
1338 return (0,myfavorites)
1339 elif not "--oneshot" in self.myopts:
1340 myfavorites.append(mykey)
1341 elif ext==".ebuild":
1342 x = os.path.realpath(x)
1343 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1344 ebuild_path = portdb.findname(mykey)
1346 if os.path.realpath(ebuild_path) != x:
1347 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1349 if mykey not in portdb.xmatch(
1350 "match-visible", portage.dep_getkey(mykey)):
1351 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1352 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1353 print colorize("BAD", "*** page for details.")
1354 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1357 raise portage_exception.PackageNotFound(
1358 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1359 if not self.create(["ebuild", myroot, mykey],
1360 None, "--onlydeps" not in self.myopts):
1361 return (0,myfavorites)
1362 elif not "--oneshot" in self.myopts:
1363 myfavorites.append(mykey)
1365 if not is_valid_package_atom(x):
1366 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1368 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1369 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1373 if "--usepkg" in self.myopts:
1374 mykey = portage.dep_expand(x, mydb=bindb,
1375 settings=pkgsettings)
1376 if (mykey and not mykey.startswith("null/")) or \
1377 "--usepkgonly" in self.myopts:
1378 arg_atoms.append((x, mykey))
1381 mykey = portage.dep_expand(x,
1382 mydb=portdb, settings=pkgsettings)
1383 arg_atoms.append((x, mykey))
1384 except ValueError, errpkgs:
1385 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1386 print "!!! one of the following fully-qualified ebuild names instead:\n"
1387 for i in errpkgs[0]:
1388 print " " + green(i)
1392 if "--update" in self.myopts:
1393 """Make sure all installed slots are updated when possible. Do this
1394 with --emptytree also, to ensure that all slots are remerged."""
1395 vardb = self.trees[self.target_root]["vartree"].dbapi
1397 for myarg, myatom in arg_atoms:
1398 greedy_atoms.append((myarg, myatom))
1400 for cpv in vardb.match(myatom):
1401 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1404 if "--usepkg" in self.myopts:
1405 mymatches = bindb.match(myatom)
1406 if "--usepkgonly" not in self.myopts:
1407 mymatches = visible(mymatches)
1408 best_pkg = portage.best(mymatches)
1410 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1411 best_pkgs.append(("binary", best_pkg, best_slot))
1412 if "--usepkgonly" not in self.myopts:
1413 best_pkg = portage.best(portdb.match(myatom))
1415 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1416 best_pkgs.append(("ebuild", best_pkg, best_slot))
1418 best_pkg = portage.best([x[1] for x in best_pkgs])
1419 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1420 best_slot = best_pkgs[0][2]
1421 myslots.add(best_slot)
1422 if len(myslots) > 1:
1423 for myslot in myslots:
1424 myslot_atom = "%s:%s" % \
1425 (portage.dep_getkey(myatom), myslot)
1427 if "--usepkgonly" not in self.myopts and \
1428 self.trees[self.target_root][
1429 "porttree"].dbapi.match(myslot_atom):
1431 elif "--usepkg" in self.myopts:
1432 mymatches = bindb.match(myslot_atom)
1433 if "--usepkgonly" not in self.myopts:
1434 mymatches = visible(mymatches)
1438 greedy_atoms.append((myarg, myslot_atom))
1439 arg_atoms = greedy_atoms
1441 """ These are used inside self.create() in order to ensure packages
1442 that happen to match arguments are not incorrectly marked as nomerge."""
1443 self.args_keys = [x[1] for x in arg_atoms]
1444 for myarg, myatom in arg_atoms:
1446 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1447 except portage_exception.MissingSignature, e:
1448 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1449 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1450 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1451 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1452 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1454 except portage_exception.InvalidSignature, e:
1455 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1456 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1457 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1458 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1459 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1461 except SystemExit, e:
1462 raise # Needed else can't exit
1463 except Exception, e:
1464 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1465 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1469 return (0,myfavorites)
1470 elif not "--oneshot" in self.myopts:
1471 mykey = portage.dep_getkey(myatom)
1472 if mykey not in myfavorites:
1473 myfavorites.append(mykey)
1476 if "--usepkgonly" in self.myopts:
1477 for xs in self.digraph.all_nodes():
1478 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1482 print "Missing binary for:",xs[2]
1484 if not self.validate_blockers():
1485 return False, myfavorites
1487 # We're true here unless we are missing binaries.
1488 return (not missing,myfavorites)
1490 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1491 myuse=None, raise_on_missing=False, priority=DepPriority(),
1492 rev_deps=False, parent_arg=None):
1493 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1494 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1495 myparent = the node whose depstring is being passed in
1496 arg = package was specified on the command line, merge even if it's already installed
1497 myuse = USE flags at present
1498 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1499 else continue trying.
1500 return 1 on success, 0 for failure
1503 portdb = self.trees[myroot]["porttree"].dbapi
1504 bindb = self.trees[myroot]["bintree"].dbapi
1505 vardb = self.trees[myroot]["vartree"].dbapi
1506 pkgsettings = self.pkgsettings[myroot]
1508 p_type, p_root, p_key, p_status = myparent
1510 if "--debug" in self.myopts:
1512 print "Parent: ",myparent
1513 print "Depstring:",depstring
1515 print "Reverse:", rev_deps
1516 print "Priority:", priority
1518 #processing dependencies
1519 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1520 dependencies are satisfiable. """
1522 if myparent and p_status == "nomerge":
1523 portage_dep._dep_check_strict = False
1524 mycheck = portage.dep_check(depstring, None,
1525 pkgsettings, myuse=myuse,
1526 use_binaries=("--usepkgonly" in self.myopts),
1527 myroot=myroot, trees=self.trees)
1529 portage_dep._dep_check_strict = True
1533 show_invalid_depstring_notice(myparent, depstring, mycheck[1])
1535 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1537 mymerge = mycheck[1]
1539 if not mymerge and arg and \
1540 portage.best_match_to_list(depstring, self.args_keys):
1541 # A provided package has been specified on the command line. The
1542 # package will not be merged and a warning will be displayed.
1543 self._pprovided_args.append(arg)
1546 # The parent is added after it's own dep_check call so that it
1547 # isn't allowed to satisfy a direct bootstrap dependency on itself
1548 # via an old-style virtual. This isn't a problem with new-style
1549 # virtuals, which are preferenced in dep_zapdeps by looking only at
1550 # the depstring, vdb, and available packages.
1552 p_type, p_root, p_key, p_status = myparent
1553 if p_status == "merge":
1554 # Update old-style virtuals if this package provides any.
1555 # These are needed for dep_virtual calls inside dep_check.
1556 self.pkgsettings[p_root].setinst(p_key,
1557 self.trees[p_root][self.pkg_tree_map[p_type]].dbapi)
1559 if "--debug" in self.myopts:
1560 print "Candidates:",mymerge
1564 selected_pkg = ["blocks", myroot, x[1:], None]
1566 #We are not processing a blocker but a normal dependency
1568 """In some cases, dep_check will return deps that shouldn't
1569 be proccessed any further, so they are identified and
1571 if "empty" not in self.myparams and \
1572 "deep" not in self.myparams and \
1573 not ("--update" in self.myopts and parent_arg) and \
1577 # List of acceptable packages, ordered by type preference.
1578 matched_packages = []
1579 myeb_matches = portdb.xmatch("match-visible", x)
1581 if "--usepkgonly" not in self.myopts:
1582 myeb = portage.best(myeb_matches)
1585 if "--usepkg" in self.myopts:
1586 # The next line assumes the binarytree has been populated.
1587 # XXX: Need to work out how we use the binary tree with roots.
1588 myeb_pkg_matches = bindb.match(x)
1589 if "--usepkgonly" not in self.myopts:
1590 # Remove any binary package entries that are masked in the portage tree (#55871)
1591 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1592 if pkg in myeb_matches or \
1593 not portdb.cpv_exists(pkg)]
1594 if myeb_pkg_matches:
1595 myeb_pkg = portage.best(myeb_pkg_matches)
1597 if myeb_pkg and "--newuse" in self.myopts:
1598 iuses = set(filter_iuse_defaults(
1599 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1600 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1602 if "--usepkgonly" not in self.myopts and myeb:
1605 pkgsettings.setcpv(myeb, mydb=mydb)
1607 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1608 now_use = pkgsettings["USE"].split()
1609 forced_flags = set()
1610 forced_flags.update(pkgsettings.useforce)
1611 forced_flags.update(pkgsettings.usemask)
1613 if "--usepkgonly" not in self.myopts and myeb:
1614 cur_iuse = set(filter_iuse_defaults(
1615 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1616 if iuses.symmetric_difference(
1617 cur_iuse).difference(forced_flags):
1619 elif iuses.intersection(old_use) != \
1620 cur_iuse.intersection(now_use):
1624 self.trees[myroot]["bintree"].dbapi.aux_get(
1625 myeb_pkg, ["USE"])[0].split()
1626 matched_packages.append(
1627 ["binary", myroot, myeb_pkg, binpkguseflags])
1629 if "--usepkgonly" not in self.myopts and myeb_matches:
1630 matched_packages.append(
1631 ["ebuild", myroot, myeb, None])
1633 if not matched_packages and \
1634 not (arg and "selective" not in self.myparams):
1635 """Fall back to the installed package database. This is a
1636 last resort because the metadata tends to diverge from that
1637 of the ebuild in the tree."""
1638 myeb_inst_matches = vardb.match(x)
1639 if "--usepkgonly" not in self.myopts:
1640 """ TODO: Improve masking check for installed and
1641 binary packages. bug #149816"""
1642 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1643 if not portdb.cpv_exists(pkg)]
1645 if myeb_inst_matches:
1646 myeb_inst = portage.best(myeb_inst_matches)
1648 binpkguseflags = vardb.aux_get(
1649 myeb_inst, ["USE"])[0].split()
1650 matched_packages.append(
1651 ["installed", myroot, myeb_inst, binpkguseflags])
1653 if not matched_packages:
1654 if raise_on_missing:
1661 xfrom = '(dependency required by '+ \
1662 green('"%s"' % myparent[2]) + \
1663 red(' [%s]' % myparent[0]) + ')'
1664 alleb = portdb.xmatch("match-all", x)
1666 if "--usepkgonly" not in self.myopts:
1667 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1668 print "!!! One of the following masked packages is required to complete your request:"
1671 mreasons = portage.getmaskingstatus(p,
1672 settings=pkgsettings, portdb=portdb)
1673 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1674 comment = portage.getmaskingreason(p,
1675 settings=pkgsettings, portdb=portdb)
1676 if comment and comment != oldcomment:
1678 oldcomment = comment
1680 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1681 print "refer to the Gentoo Handbook."
1683 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1684 print "!!! Either add a suitable binary package or compile from an ebuild."
1686 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1692 if "--debug" in self.myopts:
1693 for pkg in matched_packages:
1694 print (pkg[0] + ":").rjust(10), pkg[2]
1696 if len(matched_packages) > 1:
1697 bestmatch = portage.best(
1698 [pkg[2] for pkg in matched_packages])
1699 matched_packages = [pkg for pkg in matched_packages \
1700 if pkg[2] == bestmatch]
1702 # ordered by type preference ("ebuild" type is the last resort)
1703 selected_pkg = matched_packages[0]
1704 pkgtype, myroot, mycpv, myuse = selected_pkg
1705 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1706 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1707 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1708 existing_node = self._slot_node_map[myroot].get(
1711 e_type, myroot, e_cpv, e_status = existing_node
1712 if portage.match_from_list(x, [e_cpv]):
1713 # The existing node can be reused.
1714 selected_pkg = [e_type, myroot, e_cpv,
1715 self.useFlags[myroot][e_cpv]]
1718 #we are a dependency, so we want to be unconditionally added
1719 mypriority = priority.copy()
1721 mypriority.satisfied = True
1722 if not self.create(selected_pkg[0:3], myparent,
1723 myuse=selected_pkg[-1], priority=mypriority,
1724 rev_dep=rev_deps, arg=arg):
1727 #if mysource is not set, then we are a command-line dependency and should not be added
1728 #if --onlydeps is specified.
1729 if not self.create(selected_pkg[0:3], myparent,
1730 addme=("--onlydeps" not in self.myopts),
1731 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1734 if "--debug" in self.myopts:
1735 print "Exiting...",myparent
1738 def validate_blockers(self):
1739 """Remove any blockers from the digraph that do not match any of the
1740 packages within the graph. If necessary, create hard deps to ensure
1741 correct merge order such that mutually blocking packages are never
1742 installed simultaneously."""
1744 if "--buildpkgonly" in self.myopts or \
1745 "--nodeps" in self.myopts:
1749 for myroot in self.trees:
1751 modified_slots[myroot] = myslots
1752 final_db = self.mydbapi[myroot]
1753 slot_node_map = self._slot_node_map[myroot]
1754 for slot_atom, mynode in slot_node_map.iteritems():
1755 mytype, myroot, mycpv, mystatus = mynode
1756 if mystatus == "merge":
1757 myslots[slot_atom] = mycpv
1759 #if "deep" in self.myparams:
1761 # Pull in blockers from all installed packages that haven't already
1762 # been pulled into the depgraph. This is not enabled by default
1763 # due to the performance penalty that is incurred by all the
1764 # additional dep_check calls that are required.
1766 # Optimization hack for dep_check calls that minimizes the
1767 # available matches by replacing the portdb with a fakedbapi
1769 class FakePortageTree(object):
1770 def __init__(self, mydb):
1772 dep_check_trees = {}
1773 for myroot in self.trees:
1774 dep_check_trees[myroot] = self.trees[myroot].copy()
1775 dep_check_trees[myroot]["porttree"] = \
1776 FakePortageTree(self.mydbapi[myroot])
1778 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1779 for myroot in self.trees:
1780 pkg_node_map = self.pkg_node_map[myroot]
1781 vardb = self.trees[myroot]["vartree"].dbapi
1782 portdb = self.trees[myroot]["porttree"].dbapi
1783 pkgsettings = self.pkgsettings[myroot]
1784 final_db = self.mydbapi[myroot]
1785 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
1786 blocker_cache = BlockerCache(myroot, vardb)
1787 for pkg in cpv_all_installed:
1788 blocker_atoms = None
1789 matching_node = pkg_node_map.get(pkg, None)
1790 if matching_node and \
1791 matching_node[3] == "nomerge":
1793 # If this node has any blockers, create a "nomerge"
1794 # node for it so that they can be enforced.
1795 self.spinner.update()
1796 blocker_data = blocker_cache.get(pkg)
1798 blocker_atoms = blocker_data.atoms
1800 dep_vals = vardb.aux_get(pkg, dep_keys)
1801 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
1802 depstr = " ".join(dep_vals)
1803 # It is crucial to pass in final_db here in order to
1804 # optimize dep_check calls by eliminating atoms via
1805 # dep_wordreduce and dep_eval calls.
1807 portage_dep._dep_check_strict = False
1808 success, atoms = portage.dep_check(depstr,
1809 final_db, pkgsettings, myuse=myuse,
1810 trees=dep_check_trees, myroot=myroot)
1812 portage_dep._dep_check_strict = True
1814 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
1815 vardb.aux_get(pkg, ["SLOT"])[0])
1816 if slot_atom in modified_slots[myroot]:
1817 # This package is being replaced anyway, so
1818 # ignore invalid dependencies so as not to
1819 # annoy the user too much (otherwise they'd be
1820 # forced to manually unmerge it first).
1822 show_invalid_depstring_notice(
1823 ("installed", myroot, pkg, "nomerge"),
1826 blocker_atoms = [myatom for myatom in atoms \
1827 if myatom.startswith("!")]
1828 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
1829 blocker_cache[pkg] = \
1830 blocker_cache.BlockerData(counter, blocker_atoms)
1832 # Don't store this parent in pkg_node_map, because it's
1833 # not needed there and it might overwrite a "merge"
1834 # node with the same cpv.
1835 myparent = ("installed", myroot, pkg, "nomerge")
1836 for myatom in blocker_atoms:
1837 blocker = ("blocks", myroot, myatom[1:])
1839 self.blocker_parents.get(blocker, None)
1842 self.blocker_parents[blocker] = myparents
1843 myparents.add(myparent)
1844 blocker_cache.flush()
1847 for blocker in self.blocker_parents.keys():
1848 mytype, myroot, mydep = blocker
1849 initial_db = self.trees[myroot]["vartree"].dbapi
1850 final_db = self.mydbapi[myroot]
1851 blocked_initial = initial_db.match(mydep)
1852 blocked_final = final_db.match(mydep)
1853 if not blocked_initial and not blocked_final:
1854 del self.blocker_parents[blocker]
1856 blocked_slots_initial = {}
1857 blocked_slots_final = {}
1858 for cpv in blocked_initial:
1859 blocked_slots_initial[cpv] = \
1860 "%s:%s" % (portage.dep_getkey(cpv),
1861 initial_db.aux_get(cpv, ["SLOT"])[0])
1862 for cpv in blocked_final:
1863 blocked_slots_final[cpv] = \
1864 "%s:%s" % (portage.dep_getkey(cpv),
1865 final_db.aux_get(cpv, ["SLOT"])[0])
1866 blocked_slots_final_values = set(blocked_slots_final.itervalues())
1867 for parent in list(self.blocker_parents[blocker]):
1868 ptype, proot, pcpv, pstatus = parent
1869 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1870 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1871 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1872 parent_static = pslot_atom not in modified_slots[proot]
1873 unresolved_blocks = False
1874 depends_on_order = set()
1875 for cpv in blocked_initial:
1876 slot_atom = blocked_slots_initial[cpv]
1877 if slot_atom == pslot_atom:
1878 # The parent blocks an initial package in the same
1879 # slot as itself. The merge/nomerge status of neither
1880 # node matters. In any case, this particular block is
1881 # automatically resolved.
1883 if parent_static and \
1884 slot_atom not in modified_slots[myroot]:
1885 # This blocker will be handled the next time that a
1886 # merge of either package is triggered.
1888 if pstatus == "merge" and \
1889 slot_atom not in blocked_slots_final_values:
1890 upgrade_matches = final_db.match(slot_atom)
1892 # Apparently an upgrade may be able to invalidate
1895 self.pkg_node_map[proot][upgrade_matches[0]]
1896 depends_on_order.add(upgrade_node)
1898 # None of the above blocker resolutions techniques apply,
1899 # so apparently this one is unresolvable.
1900 unresolved_blocks = True
1901 for cpv in blocked_final:
1902 slot_atom = blocked_slots_final[cpv]
1903 if slot_atom == pslot_atom:
1904 # The parent blocks itself, so the merge order does not
1905 # need to be enforced.
1907 if parent_static and \
1908 slot_atom not in modified_slots[myroot]:
1909 # This blocker will be handled the next time that a
1910 # merge of either package is triggered.
1912 # None of the above blocker resolutions techniques apply,
1913 # so apparently this one is unresolvable.
1914 unresolved_blocks = True
1915 if not unresolved_blocks and depends_on_order:
1916 for node in depends_on_order:
1917 # Enforce correct merge order with a hard dep.
1918 self.digraph.addnode(node, parent,
1919 priority=DepPriority(buildtime=True))
1920 # Count references to this blocker so that it can be
1921 # invalidated after nodes referencing it have been
1923 self.blocker_digraph.addnode(node, blocker)
1924 if not unresolved_blocks and not depends_on_order:
1925 self.blocker_parents[blocker].remove(parent)
1926 if not self.blocker_parents[blocker]:
1927 del self.blocker_parents[blocker]
1928 # Validate blockers that depend on merge order.
1929 if not self.blocker_digraph.empty():
1931 if self._slot_collision_info:
1932 # The user is only notified of a slot collision if there are no
1933 # unresolvable blocks.
1934 for x in self.altlist():
1935 if x[0] == "blocks":
1937 self._show_slot_collision_notice(self._slot_collision_info[0])
1938 if not self._accept_collisions():
1942 def _accept_collisions(self):
1944 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
1945 if x in self.myopts:
1950 def altlist(self, reversed=False):
1951 if reversed in self._altlist_cache:
1952 return self._altlist_cache[reversed][:]
1953 mygraph=self.digraph.copy()
1954 myblockers = self.blocker_digraph.copy()
1956 circular_blocks = False
1960 get_nodes = mygraph.root_nodes
1962 get_nodes = mygraph.leaf_nodes
1963 for cpv, node in self.pkg_node_map["/"].iteritems():
1964 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
1965 asap_nodes.append(node)
1967 ignore_priority_range = [None]
1968 ignore_priority_range.extend(
1969 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
1970 while not mygraph.empty():
1971 ignore_priority = None
1974 """ASAP nodes are merged before their soft deps."""
1975 for node in asap_nodes:
1976 if not mygraph.contains(node):
1977 asap_nodes.remove(node)
1979 if not mygraph.child_nodes(node,
1980 ignore_priority=DepPriority.SOFT):
1982 asap_nodes.remove(node)
1985 for ignore_priority in ignore_priority_range:
1986 nodes = get_nodes(ignore_priority=ignore_priority)
1989 selected_nodes = None
1991 if ignore_priority <= DepPriority.SOFT:
1992 if ignore_priority is None and not reversed:
1993 # Greedily pop all of these nodes since no relationship
1994 # has been ignored. This optimization destroys --tree
1995 # output, so it's disabled in reversed mode.
1996 selected_nodes = nodes
1998 # Only pop one node for optimal merge order.
1999 selected_nodes = [nodes[0]]
2001 """Recursively gather a group of nodes that RDEPEND on
2002 eachother. This ensures that they are merged as a group
2003 and get their RDEPENDs satisfied as soon as possible."""
2004 def gather_deps(mergeable_nodes, selected_nodes, node):
2005 if node in selected_nodes:
2007 if node not in mergeable_nodes:
2009 selected_nodes.add(node)
2010 for child in mygraph.child_nodes(node,
2011 ignore_priority=DepPriority.SOFT):
2013 mergeable_nodes, selected_nodes, child):
2016 mergeable_nodes = set(nodes)
2018 selected_nodes = set()
2020 mergeable_nodes, selected_nodes, node):
2023 selected_nodes = None
2025 if not selected_nodes:
2026 if not myblockers.is_empty():
2027 """A blocker couldn't be circumnavigated while keeping all
2028 dependencies satisfied. The user will have to resolve this
2029 manually. This is a panic condition and thus the order
2030 doesn't really matter, so just pop a random node in order
2031 to avoid a circular dependency panic if possible."""
2032 if not circular_blocks:
2033 circular_blocks = True
2034 blocker_deps = myblockers.leaf_nodes()
2036 selected_nodes = [blocker_deps.pop()]
2038 if not selected_nodes:
2040 """The circular deps ouput should have less noise when
2041 altlist is not in reversed mode."""
2043 print "!!! Error: circular dependencies:"
2045 mygraph.debug_print()
2048 for node in selected_nodes:
2049 retlist.append(list(node))
2050 mygraph.remove(node)
2051 if not reversed and not circular_blocks and myblockers.contains(node):
2052 """This node may have invalidated one or more blockers."""
2053 myblockers.remove(node)
2054 for blocker in myblockers.root_nodes():
2055 if not myblockers.child_nodes(blocker):
2056 myblockers.remove(blocker)
2057 del self.blocker_parents[blocker]
2060 """Blocker validation does not work with reverse mode,
2061 so self.altlist() should first be called with reverse disabled
2062 so that blockers are properly validated."""
2063 self.blocker_digraph = myblockers
2065 """ Add any unresolved blocks so that they can be displayed."""
2066 for blocker in self.blocker_parents:
2067 retlist.append(list(blocker))
2068 self._altlist_cache[reversed] = retlist[:]
2071 def xcreate(self,mode="system"):
2072 vardb = self.trees[self.target_root]["vartree"].dbapi
2073 portdb = self.trees[self.target_root]["porttree"].dbapi
2074 bindb = self.trees[self.target_root]["bintree"].dbapi
2075 def visible(mylist):
2076 matches = portdb.gvisible(portdb.visible(mylist))
2077 return [x for x in mylist \
2078 if x in matches or not portdb.cpv_exists(x)]
2079 world_problems = False
2081 mylist = getlist(self.settings, "system")
2084 worldlist = getlist(self.settings, "world")
2085 sysdict = genericdict(getlist(self.settings, "system"))
2086 worlddict=genericdict(worldlist)
2088 for x in worlddict.keys():
2089 if not portage.isvalidatom(x):
2090 world_problems = True
2091 elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
2092 world_problems = True
2094 sysdict[x]=worlddict[x]
2096 mylist = sysdict.keys()
2100 mykey = portage.dep_getkey(atom)
2102 newlist.append(atom)
2103 """Make sure all installed slots are updated when possible.
2104 Do this with --emptytree also, to ensure that all slots are
2107 for cpv in vardb.match(mykey):
2108 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2111 if "--usepkg" in self.myopts:
2112 mymatches = bindb.match(atom)
2113 if "--usepkgonly" not in self.myopts:
2114 mymatches = visible(mymatches)
2115 best_pkg = portage.best(mymatches)
2117 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2118 best_pkgs.append(("binary", best_pkg, best_slot))
2119 if "--usepkgonly" not in self.myopts:
2120 best_pkg = portage.best(portdb.match(atom))
2122 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2123 best_pkgs.append(("ebuild", best_pkg, best_slot))
2125 best_pkg = portage.best([x[1] for x in best_pkgs])
2126 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2127 best_slot = best_pkgs[0][2]
2128 myslots.add(best_slot)
2129 if len(myslots) > 1:
2130 for myslot in myslots:
2131 myslot_atom = "%s:%s" % (mykey, myslot)
2133 if "--usepkgonly" not in self.myopts and \
2134 self.trees[self.target_root][
2135 "porttree"].dbapi.match(myslot_atom):
2137 elif "--usepkg" in self.myopts:
2138 mymatches = bindb.match(myslot_atom)
2139 if "--usepkgonly" not in self.myopts:
2140 mymatches = visible(mymatches)
2144 newlist.append(myslot_atom)
2148 for mydep in mylist:
2150 if not self.select_dep(
2151 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2152 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2155 missing_atoms.append(mydep)
2157 if not self.validate_blockers():
2161 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2162 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2165 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2166 " Ebuilds for the following packages are either all"
2167 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2168 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2172 def display(self,mylist,verbosity=None):
2173 if verbosity is None:
2174 verbosity = ("--quiet" in self.myopts and 1 or \
2175 "--verbose" in self.myopts and 3 or 2)
2179 counters = PackageCounters()
2181 if verbosity == 1 and "--verbose" not in self.myopts:
2182 def create_use_string(*args):
2185 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2187 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2188 alphabetical=("--alphabetical" in self.myopts)):
2196 cur_iuse = set(cur_iuse)
2197 enabled_flags = cur_iuse.intersection(cur_use)
2198 removed_iuse = set(old_iuse).difference(cur_iuse)
2199 any_iuse = cur_iuse.union(old_iuse)
2200 any_iuse = list(any_iuse)
2202 for flag in any_iuse:
2205 if flag in enabled_flags:
2207 if is_new or flag in old_use and all_flags:
2208 flag_str = red(flag)
2209 elif flag not in old_iuse:
2210 flag_str = yellow(flag) + "%*"
2211 elif flag not in old_use:
2212 flag_str = green(flag) + "*"
2213 elif flag in removed_iuse:
2215 flag_str = yellow("-" + flag) + "%"
2218 flag_str = "(" + flag_str + ")"
2219 removed.append(flag_str)
2222 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2223 flag_str = blue("-" + flag)
2224 elif flag not in old_iuse:
2225 flag_str = yellow("-" + flag)
2226 if flag not in iuse_forced:
2228 elif flag in old_use:
2229 flag_str = green("-" + flag) + "*"
2231 if flag in iuse_forced:
2232 flag_str = "(" + flag_str + ")"
2234 enabled.append(flag_str)
2236 disabled.append(flag_str)
2239 ret = " ".join(enabled)
2241 ret = " ".join(enabled + disabled + removed)
2243 ret = '%s="%s" ' % (name, ret)
2247 # FIXME: account for the possibility of different overlays in
2248 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2249 overlays = self.settings["PORTDIR_OVERLAY"].split()
2250 overlays_real = [os.path.realpath(t) \
2251 for t in self.settings["PORTDIR_OVERLAY"].split()]
2258 if "blocks" == x[0]:
2260 graph_key = tuple(x)
2261 if "--tree" in self.myopts:
2262 depth = len(tree_nodes)
2263 while depth and graph_key not in \
2264 self.digraph.child_nodes(tree_nodes[depth-1]):
2266 tree_nodes = tree_nodes[:depth]
2267 tree_nodes.append(graph_key)
2268 node_depth[graph_key] = depth
2270 last_merge_depth = 0
2271 for i in xrange(len(mylist)-1,-1,-1):
2272 if "blocks" == mylist[i][0]:
2274 graph_key = tuple(mylist[i])
2275 if mylist[i][-1] != "nomerge":
2276 last_merge_depth = node_depth[graph_key]
2278 if node_depth[graph_key] >= last_merge_depth or \
2279 i < len(mylist) - 1 and \
2280 node_depth[graph_key] >= node_depth[tuple(mylist[i+1])]:
2282 del node_depth[graph_key]
2285 display_overlays=False
2286 # files to fetch list - avoids counting a same file twice
2287 # in size display (verbose mode)
2293 portdb = self.trees[myroot]["porttree"].dbapi
2294 bindb = self.trees[myroot]["bintree"].dbapi
2295 vardb = self.trees[myroot]["vartree"].dbapi
2296 vartree = self.trees[myroot]["vartree"]
2297 pkgsettings = self.pkgsettings[myroot]
2302 addl=""+red("B")+" "+fetch+" "
2303 counters.blocks += 1
2304 resolved = portage.key_expand(
2305 pkg_key, mydb=vardb, settings=pkgsettings)
2306 if "--columns" in self.myopts and "--quiet" in self.myopts:
2307 print addl,red(resolved),
2309 print "["+x[0]+" "+addl+"]",red(resolved),
2310 block_parents = self.blocker_parents[tuple(x)]
2311 block_parents = set([pnode[2] for pnode in block_parents])
2312 block_parents = ", ".join(block_parents)
2314 print bad("(\"%s\" is blocking %s)") % \
2315 (pkg_key, block_parents)
2317 print bad("(is blocking %s)") % block_parents
2319 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2320 binary_package = True
2321 if "ebuild" == pkg_type:
2322 if "merge" == x[3] or \
2323 not vartree.dbapi.cpv_exists(pkg_key):
2324 """An ebuild "merge" node or a --onlydeps "nomerge"
2326 binary_package = False
2327 pkgsettings.setcpv(pkg_key, mydb=portdb)
2328 if pkg_key not in self.useFlags[myroot]:
2329 self.useFlags[myroot][pkg_key] = \
2330 pkgsettings["USE"].split()
2332 # An ebuild "nomerge" node, so USE come from the vardb.
2333 mydbapi = vartree.dbapi
2334 if pkg_key not in self.useFlags[myroot]:
2335 """If this is a --resume then the USE flags need to be
2336 fetched from the appropriate locations here."""
2337 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2338 pkg_key, ["USE"])[0].split()
2340 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2341 "fetch" in portdb.aux_get(
2342 x[2], ["RESTRICT"])[0].split():
2344 counters.restrict_fetch += 1
2345 if portdb.fetch_check(
2346 pkg_key, self.useFlags[myroot][pkg_key]):
2348 counters.restrict_fetch_satisfied += 1
2350 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2351 #param is used for -u, where you still *do* want to see when something is being upgraded.
2353 if vardb.cpv_exists(pkg_key):
2354 addl=" "+yellow("R")+fetch+" "
2355 if x[3] != "nomerge":
2356 counters.reinst += 1
2357 elif vardb.match(portage.dep_getkey(pkg_key)):
2358 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2359 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2360 portage.pkgsplit(x[2])[0])
2361 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2362 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2364 myoldbest=portage.best(myinslotlist)
2366 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2368 addl+=turquoise("U")+blue("D")
2369 counters.downgrades += 1
2372 addl+=turquoise("U")+" "
2373 counters.upgrades += 1
2375 # New slot, mark it new.
2376 addl=" "+green("NS")+fetch+" "
2377 counters.newslot += 1
2379 if "--changelog" in self.myopts:
2380 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2381 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2382 inst_matches = vardb.match(slot_atom)
2384 changelogs.extend(self.calc_changelog(
2385 portdb.findname(pkg_key),
2386 inst_matches[0], pkg_key))
2388 addl=" "+green("N")+" "+fetch+" "
2393 if pkg_key in self.useFlags[myroot]:
2395 cur_iuse = list(filter_iuse_defaults(
2396 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2398 forced_flags = set()
2399 if not binary_package:
2400 forced_flags.update(pkgsettings.useforce)
2401 forced_flags.update(pkgsettings.usemask)
2403 cur_iuse = portage.unique_array(cur_iuse)
2405 cur_use = self.useFlags[myroot][pkg_key]
2406 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2412 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2413 old_iuse, old_use = \
2414 self.trees[x[1]]["vartree"].dbapi.aux_get(
2415 pkg, ["IUSE", "USE"])
2416 old_iuse = list(set(
2417 filter_iuse_defaults(old_iuse.split())))
2419 old_use = old_use.split()
2426 old_use = [flag for flag in old_use if flag in old_iuse]
2428 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2430 use_expand.reverse()
2431 use_expand_hidden = \
2432 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2434 def map_to_use_expand(myvals, forcedFlags=False):
2437 for exp in use_expand:
2440 for val in myvals[:]:
2441 if val.startswith(exp.lower()+"_"):
2442 if val in forced_flags:
2443 forced[exp].add(val[len(exp)+1:])
2444 ret[exp].append(val[len(exp)+1:])
2447 forced["USE"] = [val for val in myvals \
2448 if val in forced_flags]
2449 for exp in use_expand_hidden:
2456 cur_iuse_map, iuse_forced = \
2457 map_to_use_expand(cur_iuse, forcedFlags=True)
2458 cur_use_map = map_to_use_expand(cur_use)
2459 old_iuse_map = map_to_use_expand(old_iuse)
2460 old_use_map = map_to_use_expand(old_use)
2463 use_expand.insert(0, "USE")
2465 for key in use_expand:
2466 if key in use_expand_hidden:
2468 verboseadd += create_use_string(key.upper(),
2469 cur_iuse_map[key], iuse_forced[key],
2470 cur_use_map[key], old_iuse_map[key],
2471 old_use_map[key], is_new)
2476 if x[0] == "ebuild" and x[-1]!="nomerge":
2477 myfilesdict = portdb.getfetchsizes(
2478 pkg_key, useflags=self.useFlags[myroot][pkg_key],
2480 if myfilesdict is None:
2481 myfilesdict="[empty/missing/bad digest]"
2483 for myfetchfile in myfilesdict.keys():
2484 if myfetchfile not in myfetchlist:
2485 mysize+=myfilesdict[myfetchfile]
2486 myfetchlist.append(myfetchfile)
2487 counters.totalsize += mysize
2488 verboseadd+=format_size(mysize)+" "
2491 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2492 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2493 file_name = portdb.findname(pkg_key)
2494 if file_name: # It might not exist in the tree
2495 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2496 if (overlays_real.count(dir_name)>0):
2497 verboseadd+=teal("["+str(overlays_real.index(
2498 os.path.normpath(dir_name))+1)+"]")+" "
2499 display_overlays=True
2501 verboseadd += "[No ebuild?]"
2503 xs=portage.pkgsplit(x[2])
2510 if "COLUMNWIDTH" in self.settings:
2512 mywidth = int(self.settings["COLUMNWIDTH"])
2513 except ValueError, e:
2514 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2516 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2517 self.settings["COLUMNWIDTH"], noiselevel=-1)
2522 indent = " " * node_depth[tuple(x)]
2525 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2526 if myoldbest[-3:]=="-r0":
2527 myoldbest=myoldbest[:-3]
2528 myoldbest=blue("["+myoldbest+"]")
2533 if "--columns" in self.myopts:
2534 if "--quiet" in self.myopts:
2535 myprint=addl+" "+indent+darkgreen(xs[0])
2536 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2537 myprint=myprint+myoldbest
2538 myprint=myprint+darkgreen("to "+x[1])
2540 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2541 if (newlp-nc_len(myprint)) > 0:
2542 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2543 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2544 if (oldlp-nc_len(myprint)) > 0:
2545 myprint=myprint+" "*(oldlp-nc_len(myprint))
2546 myprint=myprint+myoldbest
2547 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2549 if x[3] == "nomerge":
2550 myprint = darkblue("[nomerge ] ")
2552 myprint = "[" + pkg_type + " " + addl + "] "
2553 myprint += indent + darkgreen(pkg_key) + " " + \
2554 myoldbest + darkgreen("to " + myroot) + " " + \
2557 if "--columns" in self.myopts:
2558 if "--quiet" in self.myopts:
2559 myprint=addl+" "+indent+darkgreen(xs[0])
2560 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2561 myprint=myprint+myoldbest
2563 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2564 if (newlp-nc_len(myprint)) > 0:
2565 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2566 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2567 if (oldlp-nc_len(myprint)) > 0:
2568 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2569 myprint=myprint+myoldbest+" "+verboseadd
2572 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2574 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2577 mysplit = portage.pkgsplit(x[2])
2578 if "--tree" not in self.myopts and mysplit and \
2579 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2582 if mysplit[2] == "r0":
2583 myversion = mysplit[1]
2585 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2587 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2588 if mylist.index(x) < len(mylist) - 1 and \
2589 "livecvsportage" not in self.settings.features:
2590 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2591 p.append(colorize("WARN", " then resume the merge."))
2601 if overlays and display_overlays:
2602 print "Portage overlays:"
2606 print " "+teal("["+str(y)+"]"),x
2608 if "--changelog" in self.myopts:
2610 for revision,text in changelogs:
2611 print bold('*'+revision)
2612 sys.stdout.write(text)
2614 if self._pprovided_args:
2616 msg.append(bad("\nWARNING: "))
2617 if len(self._pprovided_args) > 1:
2618 msg.append("Requested packages will not be " + \
2619 "merged because they are listed in\n")
2621 msg.append("A requested package will not be " + \
2622 "merged because it is listed in\n")
2623 msg.append(" package.provided:\n\n")
2624 for arg in self._pprovided_args:
2625 msg.append(" " + arg + "\n")
2627 sys.stderr.write("".join(msg))
2629 def calc_changelog(self,ebuildpath,current,next):
2630 current = '-'.join(portage.catpkgsplit(current)[1:])
2631 if current.endswith('-r0'): current = current[:-3]
2632 next = '-'.join(portage.catpkgsplit(next)[1:])
2633 if next.endswith('-r0'): next = next[:-3]
2634 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2636 changelog = open(changelogpath).read()
2637 except SystemExit, e:
2638 raise # Needed else can't exit
2641 divisions = self.find_changelog_tags(changelog)
2642 #print 'XX from',current,'to',next
2643 #for div,text in divisions: print 'XX',div
2644 # skip entries for all revisions above the one we are about to emerge
2645 for i in range(len(divisions)):
2646 if divisions[i][0]==next:
2647 divisions = divisions[i:]
2649 # find out how many entries we are going to display
2650 for i in range(len(divisions)):
2651 if divisions[i][0]==current:
2652 divisions = divisions[:i]
2655 # couldnt find the current revision in the list. display nothing
2659 def find_changelog_tags(self,changelog):
2663 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2665 if release is not None:
2666 divs.append((release,changelog))
2668 if release is not None:
2669 divs.append((release,changelog[:match.start()]))
2670 changelog = changelog[match.end():]
2671 release = match.group(1)
2672 if release.endswith('.ebuild'):
2673 release = release[:-7]
2674 if release.endswith('-r0'):
2675 release = release[:-3]
2678 return self.outdatedpackages
2680 class PackageCounters(object):
2690 self.restrict_fetch = 0
2691 self.restrict_fetch_satisfied = 0
2694 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2697 myoutput.append("Total: %s package" % total_installs)
2698 if total_installs != 1:
2699 myoutput.append("s")
2700 if total_installs != 0:
2701 myoutput.append(" (")
2702 if self.upgrades > 0:
2703 details.append("%s upgrade" % self.upgrades)
2704 if self.upgrades > 1:
2706 if self.downgrades > 0:
2707 details.append("%s downgrade" % self.downgrades)
2708 if self.downgrades > 1:
2711 details.append("%s new" % self.new)
2712 if self.newslot > 0:
2713 details.append("%s in new slot" % self.newslot)
2714 if self.newslot > 1:
2717 details.append("%s reinstall" % self.reinst)
2721 details.append("%s block" % self.blocks)
2724 myoutput.append(", ".join(details))
2725 if total_installs != 0:
2726 myoutput.append(")")
2727 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2728 if self.restrict_fetch:
2729 myoutput.append("\nFetch Restriction: %s package" % \
2730 self.restrict_fetch)
2731 if self.restrict_fetch > 1:
2732 myoutput.append("s")
2733 if self.restrict_fetch_satisfied < self.restrict_fetch:
2734 myoutput.append(bad(" (%s unsatisfied)") % \
2735 (self.restrict_fetch - self.restrict_fetch_satisfied))
2736 return "".join(myoutput)
2738 class MergeTask(object):
2740 def __init__(self, settings, trees, myopts):
2741 self.settings = settings
2742 self.target_root = settings["ROOT"]
2744 self.myopts = myopts
2746 if settings.get("PORTAGE_DEBUG", "") == "1":
2748 self.pkgsettings = {}
2749 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2750 if self.target_root != "/":
2751 self.pkgsettings["/"] = \
2752 portage.config(clone=trees["/"]["vartree"].settings)
2754 def merge(self, mylist, favorites, mtimedb):
2757 ldpath_mtimes = mtimedb["ldpath"]
2758 xterm_titles = "notitles" not in self.settings.features
2760 #check for blocking dependencies
2761 if "--fetchonly" not in self.myopts and \
2762 "--buildpkgonly" not in self.myopts:
2765 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2766 print "!!! the two packages cannot be installed on the same system together."
2767 print "!!! Please use 'emerge --pretend' to determine blockers."
2768 if "--quiet" not in self.myopts:
2769 show_blocker_docs_link()
2770 if "--pretend" not in self.myopts:
2772 del mtimedb["resume"]
2777 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
2778 mysysdict = genericdict(getlist(self.settings, "system"))
2779 if "--resume" in self.myopts:
2781 print colorize("GOOD", "*** Resuming merge...")
2782 emergelog(xterm_titles, " *** Resuming merge...")
2783 mymergelist=mtimedb["resume"]["mergelist"][:]
2784 if "--skipfirst" in self.myopts and mymergelist:
2785 del mtimedb["resume"]["mergelist"][0]
2788 validate_merge_list(self.trees, mymergelist)
2790 myfavs = portage.grabfile(
2791 os.path.join(self.target_root, portage.WORLD_FILE))
2792 myfavdict=genericdict(myfavs)
2793 for x in range(len(mylist)):
2794 if mylist[x][3]!="nomerge":
2795 # Add to the mergelist
2796 mymergelist.append(mylist[x])
2798 myfavkey=portage.cpv_getkey(mylist[x][2])
2799 if "--onlydeps" in self.myopts:
2801 # Add to the world file. Since we won't be able to later.
2802 if "--fetchonly" not in self.myopts and \
2803 myfavkey in favorites:
2804 #don't record if already in system profile or already recorded
2805 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
2806 #we don't have a favorites entry for this package yet; add one
2807 myfavdict[myfavkey]=myfavkey
2808 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
2809 if not ("--fetchonly" in self.myopts or \
2810 "--fetch-all-uri" in self.myopts or \
2811 "--pretend" in self.myopts):
2812 portage.write_atomic(
2813 os.path.join(self.target_root, portage.WORLD_FILE),
2814 "\n".join(myfavdict.values()))
2816 mtimedb["resume"]["mergelist"]=mymergelist[:]
2819 myfeat = self.settings.features[:]
2820 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
2822 if "parallel-fetch" in myfeat and \
2823 not ("--pretend" in self.myopts or \
2824 "--fetch-all-uri" in self.myopts or \
2825 "--fetchonly" in self.myopts):
2826 if "distlocks" not in myfeat:
2828 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
2829 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
2831 elif len(mymergelist) > 1:
2832 print ">>> starting parallel fetching"
2833 fetch_log = "/var/log/emerge-fetch.log"
2834 logfile = open(fetch_log, "w")
2835 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
2836 portage_util.apply_secpass_permissions(fetch_log,
2837 uid=portage.portage_uid, gid=portage.portage_gid,
2839 fetch_env = os.environ.copy()
2840 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
2841 fetch_env["PORTAGE_NICENESS"] = "0"
2842 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
2843 for myopt, myarg in self.myopts.iteritems():
2844 if myopt not in bad_resume_opts:
2846 fetch_args.append(myopt)
2848 fetch_args.append(myopt +"="+ myarg)
2849 portage.portage_exec.spawn(fetch_args, env=fetch_env,
2850 fd_pipes=fd_pipes, returnpid=True)
2851 logfile.close() # belongs to the spawned process
2854 for x in mymergelist:
2859 portdb = self.trees[myroot]["porttree"].dbapi
2860 bindb = self.trees[myroot]["bintree"].dbapi
2861 vartree = self.trees[myroot]["vartree"]
2862 pkgsettings = self.pkgsettings[myroot]
2865 y = portdb.findname(pkg_key)
2866 if "--pretend" not in self.myopts:
2867 print "\n>>> Emerging (" + \
2868 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2869 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
2870 colorize("GOOD", x[pkgindex]) + " to " + x[1]
2871 emergelog(xterm_titles, " >>> emerge ("+\
2872 str(mergecount)+" of "+str(len(mymergelist))+\
2873 ") "+x[pkgindex]+" to "+x[1])
2875 pkgsettings["EMERGE_FROM"] = x[0]
2876 pkgsettings.backup_changes("EMERGE_FROM")
2879 #buildsyspkg: Check if we need to _force_ binary package creation
2880 issyspkg = ("buildsyspkg" in myfeat) \
2881 and x[0] != "blocks" \
2882 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
2883 and "--buildpkg" not in self.myopts
2884 if x[0] in ["ebuild","blocks"]:
2885 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
2886 raise Exception, "Merging a blocker"
2887 elif "--fetchonly" in self.myopts or \
2888 "--fetch-all-uri" in self.myopts:
2889 if "--fetch-all-uri" in self.myopts:
2890 retval = portage.doebuild(y, "fetch", myroot,
2891 pkgsettings, self.edebug,
2892 "--pretend" in self.myopts, fetchonly=1,
2893 fetchall=1, mydbapi=portdb, tree="porttree")
2895 retval = portage.doebuild(y, "fetch", myroot,
2896 pkgsettings, self.edebug,
2897 "--pretend" in self.myopts, fetchonly=1,
2898 mydbapi=portdb, tree="porttree")
2899 if (retval is None) or retval:
2901 print "!!! Fetch for",y,"failed, continuing..."
2903 failed_fetches.append(pkg_key)
2906 portage.doebuild_environment(y, "setup", myroot,
2907 pkgsettings, self.edebug, 1, portdb)
2908 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
2909 portage_util.ensure_dirs(os.path.dirname(catdir),
2910 uid=portage.portage_uid, gid=portage.portage_gid,
2912 builddir_lock = None
2915 catdir_lock = portage_locks.lockdir(catdir)
2916 portage_util.ensure_dirs(catdir,
2917 uid=portage.portage_uid, gid=portage.portage_gid,
2919 builddir_lock = portage_locks.lockdir(
2920 pkgsettings["PORTAGE_BUILDDIR"])
2922 portage_locks.unlockdir(catdir_lock)
2925 msg = " === (%s of %s) Cleaning (%s::%s)" % \
2926 (mergecount, len(mymergelist), pkg_key, y)
2927 short_msg = "emerge: (%s of %s) %s Clean" % \
2928 (mergecount, len(mymergelist), pkg_key)
2929 emergelog(xterm_titles, msg, short_msg=short_msg)
2930 retval = portage.doebuild(y, "clean", myroot,
2931 pkgsettings, self.edebug, cleanup=1,
2932 mydbapi=portdb, tree="porttree")
2933 if retval != os.EX_OK:
2935 if "--buildpkg" in self.myopts or issyspkg:
2937 print ">>> This is a system package, " + \
2938 "let's pack a rescue tarball."
2939 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
2940 (mergecount, len(mymergelist), pkg_key, y)
2941 short_msg = "emerge: (%s of %s) %s Compile" % \
2942 (mergecount, len(mymergelist), pkg_key)
2943 emergelog(xterm_titles, msg, short_msg=short_msg)
2944 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
2945 retval = portage.doebuild(y, "package", myroot,
2946 pkgsettings, self.edebug, mydbapi=portdb,
2948 if retval != os.EX_OK:
2950 if "--buildpkgonly" not in self.myopts:
2951 bintree = self.trees[myroot]["bintree"]
2952 bintree.inject(pkg_key)
2953 mytbz2 = bintree.getname(pkg_key)
2954 msg = " === (%s of %s) Merging (%s::%s)" % \
2955 (mergecount, len(mymergelist), pkg_key, y)
2956 short_msg = "emerge: (%s of %s) %s Merge" % \
2957 (mergecount, len(mymergelist), pkg_key)
2958 emergelog(xterm_titles, msg, short_msg=short_msg)
2959 retval = portage.merge(pkgsettings["CATEGORY"],
2960 pkgsettings["PF"], pkgsettings["D"],
2961 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
2962 "build-info"), myroot, pkgsettings,
2963 myebuild=pkgsettings["EBUILD"],
2964 mytree="porttree", mydbapi=portdb,
2965 vartree=vartree, prev_mtimes=ldpath_mtimes)
2966 if retval != os.EX_OK:
2968 elif "noclean" not in pkgsettings.features:
2969 portage.doebuild(y, "clean", myroot,
2970 pkgsettings, self.edebug, mydbapi=portdb,
2973 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
2974 (mergecount, len(mymergelist), pkg_key, y)
2975 short_msg = "emerge: (%s of %s) %s Compile" % \
2976 (mergecount, len(mymergelist), pkg_key)
2977 emergelog(xterm_titles, msg, short_msg=short_msg)
2978 retval = portage.doebuild(y, "merge", myroot,
2979 pkgsettings, self.edebug, vartree=vartree,
2980 mydbapi=portdb, tree="porttree",
2981 prev_mtimes=ldpath_mtimes)
2982 if retval != os.EX_OK:
2986 portage_locks.unlockdir(builddir_lock)
2989 # Lock catdir for removal if empty.
2990 catdir_lock = portage_locks.lockdir(catdir)
2996 if e.errno != errno.ENOTEMPTY:
2999 portage_locks.unlockdir(catdir_lock)
3001 elif x[0]=="binary":
3003 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3004 if "--getbinpkg" in self.myopts:
3007 if "distlocks" in pkgsettings.features and \
3008 os.access(pkgsettings["PKGDIR"], os.W_OK):
3009 portage_util.ensure_dirs(os.path.dirname(mytbz2))
3010 tbz2_lock = portage_locks.lockfile(mytbz2,
3012 if self.trees[myroot]["bintree"].isremote(pkg_key):
3013 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3014 (mergecount, len(mymergelist), pkg_key, mytbz2)
3015 short_msg = "emerge: (%s of %s) %s Fetch" % \
3016 (mergecount, len(mymergelist), pkg_key)
3017 emergelog(xterm_titles, msg, short_msg=short_msg)
3018 if not self.trees[myroot]["bintree"].gettbz2(
3023 portage_locks.unlockfile(tbz2_lock)
3025 if "--fetchonly" in self.myopts or \
3026 "--fetch-all-uri" in self.myopts:
3029 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3030 emergelog(xterm_titles, " === ("+str(mergecount)+\
3031 " of "+str(len(mymergelist))+") Merging Binary ("+\
3032 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3033 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3035 vartree=self.trees[myroot]["vartree"],
3036 prev_mtimes=ldpath_mtimes)
3037 if retval != os.EX_OK:
3039 #need to check for errors
3040 if "--buildpkgonly" not in self.myopts:
3041 self.trees[x[1]]["vartree"].inject(x[2])
3042 myfavkey=portage.cpv_getkey(x[2])
3043 if "--fetchonly" not in self.myopts and \
3044 "--fetch-all-uri" not in self.myopts and \
3045 myfavkey in favorites:
3046 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3047 myfavdict=genericdict(myfavs)
3048 #don't record if already in system profile or already recorded
3049 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3050 #we don't have a favorites entry for this package yet; add one
3051 myfavdict[myfavkey]=myfavkey
3052 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3053 emergelog(xterm_titles, " === ("+\
3054 str(mergecount)+" of "+\
3055 str(len(mymergelist))+\
3056 ") Updating world file ("+x[pkgindex]+")")
3057 portage.write_atomic(
3058 os.path.join(myroot, portage.WORLD_FILE),
3059 "\n".join(myfavdict.values()))
3061 if "--pretend" not in self.myopts and \
3062 "--fetchonly" not in self.myopts and \
3063 "--fetch-all-uri" not in self.myopts:
3064 # Clean the old package that we have merged over top of it.
3065 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3066 xsplit=portage.pkgsplit(x[2])
3067 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3068 retval = unmerge(pkgsettings, self.myopts, vartree,
3069 "clean", [xsplit[0]], ldpath_mtimes)
3071 emergelog(xterm_titles,
3072 " --- AUTOCLEAN: Nothing unmerged.")
3074 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3075 + " AUTOCLEAN is disabled. This can cause serious"
3076 + " problems due to overlapping packages.\n")
3078 # Figure out if we need a restart.
3079 mysplit=portage.pkgsplit(x[2])
3080 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3081 myver=mysplit[1]+"-"+mysplit[2]
3082 if myver[-3:]=='-r0':
3084 if (myver != portage.VERSION) and \
3085 "livecvsportage" not in self.settings.features:
3086 if len(mymergelist) > mergecount:
3087 emergelog(xterm_titles,
3088 " ::: completed emerge ("+ \
3089 str(mergecount)+" of "+ \
3090 str(len(mymergelist))+") "+ \
3092 emergelog(xterm_titles, " *** RESTARTING " + \
3093 "emerge via exec() after change of " + \
3095 del mtimedb["resume"]["mergelist"][0]
3097 portage.run_exitfuncs()
3098 mynewargv=[sys.argv[0],"--resume"]
3099 for myopt, myarg in self.myopts.iteritems():
3100 if myopt not in bad_resume_opts:
3102 mynewargv.append(myopt)
3104 mynewargv.append(myopt +"="+ myarg)
3105 # priority only needs to be adjusted on the first run
3106 os.environ["PORTAGE_NICENESS"] = "0"
3107 os.execv(mynewargv[0], mynewargv)
3109 if "--pretend" not in self.myopts and \
3110 "--fetchonly" not in self.myopts and \
3111 "--fetch-all-uri" not in self.myopts:
3112 if "noclean" not in self.settings.features:
3113 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3114 (mergecount, len(mymergelist), x[pkgindex])
3115 emergelog(xterm_titles, (" === (%s of %s) " + \
3116 "Post-Build Cleaning (%s::%s)") % \
3117 (mergecount, len(mymergelist), x[pkgindex], y),
3118 short_msg=short_msg)
3119 emergelog(xterm_titles, " ::: completed emerge ("+\
3120 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3123 # Unsafe for parallel merges
3124 del mtimedb["resume"]["mergelist"][0]
3125 # Commit after each merge so that --resume may still work in
3126 # in the event that portage is not allowed to exit normally
3127 # due to power failure, SIGKILL, etc...
3130 if "--pretend" not in self.myopts:
3131 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3133 # We're out of the loop... We're done. Delete the resume data.
3134 if mtimedb.has_key("resume"):
3135 del mtimedb["resume"]
3138 #by doing an exit this way, --fetchonly can continue to try to
3139 #fetch everything even if a particular download fails.
3140 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3142 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3143 "encountered. Please see above for details.\n\n")
3144 for cpv in failed_fetches:
3145 sys.stderr.write(" ")
3146 sys.stderr.write(cpv)
3147 sys.stderr.write("\n")
3148 sys.stderr.write("\n")
3154 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3156 candidate_catpkgs=[]
3158 xterm_titles = "notitles" not in settings.features
3160 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3162 # At least the parent needs to exist for the lock file.
3163 portage_util.ensure_dirs(vdb_path)
3164 except portage_exception.PortageException:
3168 if os.access(vdb_path, os.W_OK):
3169 vdb_lock = portage_locks.lockdir(vdb_path)
3170 realsyslist = getlist(settings, "system")
3172 for x in realsyslist:
3173 mycp = portage.dep_getkey(x)
3174 if mycp in settings.getvirtuals():
3176 for provider in settings.getvirtuals()[mycp]:
3177 if vartree.dbapi.match(provider):
3178 providers.append(provider)
3179 if len(providers) == 1:
3180 syslist.extend(providers)
3182 syslist.append(mycp)
3184 mysettings = portage.config(clone=settings)
3186 if not unmerge_files or "world" in unmerge_files or \
3187 "system" in unmerge_files:
3188 if "unmerge"==unmerge_action:
3190 print bold("emerge unmerge") + " can only be used with " + \
3191 "specific package names, not with "+bold("world")+" or"
3192 print bold("system")+" targets."
3199 # process all arguments and add all
3200 # valid db entries to candidate_catpkgs
3202 if not unmerge_files or "world" in unmerge_files:
3203 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3204 elif "system" in unmerge_files:
3205 candidate_catpkgs.extend(getlist(settings, "system"))
3207 #we've got command-line arguments
3208 if not unmerge_files:
3209 print "\nNo packages to unmerge have been provided.\n"
3211 for x in unmerge_files:
3212 arg_parts = x.split('/')
3213 if x[0] not in [".","/"] and \
3214 arg_parts[-1][-7:] != ".ebuild":
3215 #possible cat/pkg or dep; treat as such
3216 candidate_catpkgs.append(x)
3217 elif unmerge_action in ["prune","clean"]:
3218 print "\n!!! Prune and clean do not accept individual" + \
3219 " ebuilds as arguments;\n skipping.\n"
3222 # it appears that the user is specifying an installed
3223 # ebuild and we're in "unmerge" mode, so it's ok.
3224 if not os.path.exists(x):
3225 print "\n!!! The path '"+x+"' doesn't exist.\n"
3228 absx = os.path.abspath(x)
3229 sp_absx = absx.split("/")
3230 if sp_absx[-1][-7:] == ".ebuild":
3232 absx = "/".join(sp_absx)
3234 sp_absx_len = len(sp_absx)
3236 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3237 vdb_len = len(vdb_path)
3239 sp_vdb = vdb_path.split("/")
3240 sp_vdb_len = len(sp_vdb)
3242 if not os.path.exists(absx+"/CONTENTS"):
3243 print "!!! Not a valid db dir: "+str(absx)
3246 if sp_absx_len <= sp_vdb_len:
3247 # The Path is shorter... so it can't be inside the vdb.
3250 print "\n!!!",x,"cannot be inside "+ \
3251 vdb_path+"; aborting.\n"
3254 for idx in range(0,sp_vdb_len):
3255 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3258 print "\n!!!", x, "is not inside "+\
3259 vdb_path+"; aborting.\n"
3262 print "="+"/".join(sp_absx[sp_vdb_len:])
3263 candidate_catpkgs.append(
3264 "="+"/".join(sp_absx[sp_vdb_len:]))
3267 if (not "--quiet" in myopts):
3269 if settings["ROOT"] != "/":
3270 print darkgreen(newline+ \
3271 ">>> Using system located in ROOT tree "+settings["ROOT"])
3272 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3273 not ("--quiet" in myopts):
3274 print darkgreen(newline+\
3275 ">>> These are the packages that would be unmerged:")
3279 for x in candidate_catpkgs:
3280 # cycle through all our candidate deps and determine
3281 # what will and will not get unmerged
3283 mymatch=localtree.dep_match(x)
3286 except ValueError, errpkgs:
3287 print "\n\n!!! The short ebuild name \"" + \
3288 x + "\" is ambiguous. Please specify"
3289 print "!!! one of the following fully-qualified " + \
3290 "ebuild names instead:\n"
3291 for i in errpkgs[0]:
3292 print " " + green(i)
3296 if not mymatch and x[0] not in "<>=~":
3297 #add a "=" if missing
3298 mymatch=localtree.dep_match("="+x)
3300 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3301 (x, unmerge_action), noiselevel=-1)
3303 mykey = portage.key_expand(
3305 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3306 if not pkgmap.has_key(mykey):
3307 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3308 if unmerge_action=="unmerge":
3310 if y not in pkgmap[mykey]["selected"]:
3311 pkgmap[mykey]["selected"].append(y)
3312 numselected=numselected+len(mymatch)
3315 #unmerge_action in ["prune", clean"]
3317 for mypkg in mymatch:
3318 if unmerge_action=="clean":
3319 myslot=localtree.getslot(mypkg)
3321 # since we're pruning, we don't care about slots
3322 # and put all the pkgs in together
3324 if not slotmap.has_key(myslot):
3326 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3327 for myslot in slotmap.keys():
3328 counterkeys=slotmap[myslot].keys()
3333 pkgmap[mykey]["protected"].append(
3334 slotmap[myslot][counterkeys[-1]])
3336 #be pretty and get them in order of merge:
3337 for ckey in counterkeys:
3338 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
3339 numselected=numselected+1
3340 # ok, now the last-merged package
3341 # is protected, and the rest are selected
3342 if global_unmerge and not numselected:
3343 print "\n>>> No outdated packages were found on your system.\n"
3347 portage.writemsg_stdout(
3348 "\n>>> No packages selected for removal by " + \
3349 unmerge_action + "\n")
3353 portage_locks.unlockdir(vdb_lock)
3354 for x in pkgmap.keys():
3355 for y in localtree.dep_match(x):
3356 if y not in pkgmap[x]["omitted"] and \
3357 y not in pkgmap[x]["selected"] and \
3358 y not in pkgmap[x]["protected"]:
3359 pkgmap[x]["omitted"].append(y)
3360 if global_unmerge and not pkgmap[x]["selected"]:
3361 #avoid cluttering the preview printout with stuff that isn't getting unmerged
3363 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
3364 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
3365 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
3366 if "--pretend" not in myopts and "--ask" not in myopts:
3367 countdown(int(settings["EMERGE_WARNING_DELAY"]),
3368 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3369 print "\n "+white(x)
3370 for mytype in ["selected","protected","omitted"]:
3371 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
3372 if pkgmap[x][mytype]:
3373 for mypkg in pkgmap[x][mytype]:
3374 mysplit=portage.catpkgsplit(mypkg)
3375 if mysplit[3]=="r0":
3376 myversion=mysplit[2]
3378 myversion=mysplit[2]+"-"+mysplit[3]
3379 if mytype=="selected":
3380 portage.writemsg_stdout(
3381 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
3383 portage.writemsg_stdout(
3384 colorize("GOOD", myversion + " "), noiselevel=-1)
3386 portage.writemsg_stdout("none", noiselevel=-1)
3387 portage.writemsg_stdout("\n", noiselevel=-1)
3389 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3390 " packages are slated for removal.\n")
3391 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
3392 " and " + colorize("GOOD", "'omitted'") + \
3393 " packages will not be removed.\n\n")
3395 if "--pretend" in myopts:
3396 #we're done... return
3398 if "--ask" in myopts:
3399 if userquery("Would you like to unmerge these packages?")=="No":
3400 # enter pretend mode for correct formatting of results
3401 myopts["--pretend"] = True
3406 #the real unmerging begins, after a short delay....
3407 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3409 for x in pkgmap.keys():
3410 for y in pkgmap[x]["selected"]:
3411 print ">>> Unmerging "+y+"..."
3412 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3413 mysplit=y.split("/")
3415 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3416 mysettings, unmerge_action not in ["clean","prune"],
3417 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3418 if retval != os.EX_OK:
3419 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3420 ebuild = vartree.dbapi.findname(y)
3421 show_unmerge_failure_message(y, ebuild, retval)
3424 clean_world(vartree.dbapi, y)
3425 emergelog(xterm_titles, " >>> unmerge success: "+y)
3428 def show_unmerge_failure_message(pkg, ebuild, retval):
3430 from formatter import AbstractFormatter, DumbWriter
3431 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3434 msg.append("A removal phase of the '%s' package " % pkg)
3435 msg.append("has failed with exit value %s. " % retval)
3436 msg.append("The problem occurred while executing ")
3437 msg.append("the ebuild located at '%s'. " % ebuild)
3438 msg.append("If necessary, manually remove the ebuild " )
3439 msg.append("in order to skip the execution of removal phases.")
3443 f.add_flowing_data(x)
3447 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3450 if os.path.exists("/usr/bin/install-info"):
3455 inforoot=normpath(root+z)
3456 if os.path.isdir(inforoot):
3457 infomtime = long(os.stat(inforoot).st_mtime)
3458 if inforoot not in prev_mtimes or \
3459 prev_mtimes[inforoot] != infomtime:
3460 regen_infodirs.append(inforoot)
3462 if not regen_infodirs:
3463 print " "+green("*")+" GNU info directory index is up-to-date."
3465 print " "+green("*")+" Regenerating GNU info directory index..."
3469 for inforoot in regen_infodirs:
3472 for filename in ("dir", "dir.gz"):
3473 file_path = os.path.join(inforoot, filename)
3475 os.rename(file_path, file_path + ".old")
3477 if e.errno != errno.ENOENT:
3481 if not os.path.isdir(inforoot):
3484 file_list = os.listdir(inforoot)
3487 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3489 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3490 existsstr="already exists, for file `"
3492 if re.search(existsstr,myso):
3493 # Already exists... Don't increment the count for this.
3495 elif myso[:44]=="install-info: warning: no info dir entry in ":
3496 # This info file doesn't contain a DIR-header: install-info produces this
3497 # (harmless) warning (the --quiet switch doesn't seem to work).
3498 # Don't increment the count for this.
3502 errmsg += myso + "\n"
3505 #update mtime so we can potentially avoid regenerating.
3506 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3509 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3512 print " "+green("*")+" Processed",icount,"info files."
3515 def post_emerge(settings, mtimedb, retval):
3517 Misc. things to run at the end of a merge session.
3525 @param settings: Configuration settings (typically portage.settings)
3526 @type settings: portage.config()
3527 @param mtimedb: The mtimeDB to store data needed across merge invocations
3528 @type mtimedb: MtimeDB class instance
3529 @param retval: Emerge's return value
3533 1. Calls sys.exit(retval)
3535 target_root = settings["ROOT"]
3536 info_mtimes = mtimedb["info"]
3537 config_protect = settings.get("CONFIG_PROTECT","").split()
3538 infodirs = settings.get("INFOPATH","").split(":") + \
3539 settings.get("INFODIR","").split(":")
3543 emergelog("notitles" not in settings.features,
3544 " *** exiting successfully.")
3546 if "noinfo" not in settings.features:
3547 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3549 chk_updated_cfg_files(target_root, config_protect)
3551 NEWS_PATH = os.path.join( "metadata", "news" )
3552 UNREAD_PATH = os.path.join( target_root, NEWS_LIB_PATH, 'news')
3553 porttree = portdbapi( porttree_root = settings["PORTDIR"], mysettings = settings )
3554 newsReaderDisplay = False
3556 for repo in porttree.getRepositories():
3557 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3559 print colorize("WARN", " * IMPORTANT:"),
3560 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3561 newsReaderDisplay = True
3563 if newsReaderDisplay:
3564 print colorize("WARN", " *"),
3565 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3571 def chk_updated_cfg_files(target_root, config_protect):
3573 #number of directories with some protect files in them
3575 for x in config_protect:
3576 x = os.path.join(target_root, x.lstrip(os.path.sep))
3578 mymode = os.lstat(x).st_mode
3581 if stat.S_ISDIR(mymode):
3582 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3584 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3585 os.path.split(x.rstrip(os.path.sep))
3586 a = commands.getstatusoutput(mycommand)
3588 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3590 files = a[1].split()
3593 print colorize("WARN", " * IMPORTANT:"),
3594 if stat.S_ISDIR(mymode):
3595 print "%d config files in '%s' need updating." % \
3598 print "config file '%s' needs updating." % x
3601 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3602 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3605 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3607 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3608 Returns the number of unread (yet relevent) items.
3620 1. The number of unread but relevant news items.
3623 from portage_news import NewsManager
3624 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3625 return manager.getUnreadItems( repo_id, update=True )
3627 def is_valid_package_atom(x):
3629 testkey = portage.dep_getkey(x)
3630 except portage_exception.InvalidData:
3632 if testkey.startswith("null/"):
3633 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3638 return portage.isvalidatom(testatom)
3640 def validate_merge_list(trees, mergelist):
3641 """Validate the list to make sure all the packages are still available.
3642 This is needed for --resume."""
3643 for (pkg_type, myroot, pkg_key, action) in mergelist:
3644 if pkg_type == "binary" and \
3645 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3646 pkg_type == "ebuild" and \
3647 not trees[myroot]["porttree"].dbapi.xmatch(
3648 "match-all", "="+pkg_key):
3649 print red("!!! Error: The resume list contains packages that are no longer")
3650 print red("!!! available to be emerged. Please restart/continue")
3651 print red("!!! the merge operation manually.")
3654 def show_blocker_docs_link():
3656 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3657 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3659 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3662 def action_sync(settings, trees, mtimedb, myopts, myaction):
3663 xterm_titles = "notitles" not in settings.features
3664 emergelog(xterm_titles, " === sync")
3665 myportdir = settings.get("PORTDIR", None)
3667 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3669 if myportdir[-1]=="/":
3670 myportdir=myportdir[:-1]
3671 if not os.path.exists(myportdir):
3672 print ">>>",myportdir,"not found, creating it."
3673 os.makedirs(myportdir,0755)
3674 syncuri=settings["SYNC"].rstrip()
3676 updatecache_flg = False
3677 if myaction == "metadata":
3678 print "skipping sync"
3679 updatecache_flg = True
3680 tmpservertimestampfile = None
3681 elif syncuri[:8]=="rsync://":
3682 if not os.path.exists("/usr/bin/rsync"):
3683 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3684 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3690 if settings["PORTAGE_RSYNC_OPTS"] == "":
3691 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3693 "--recursive", # Recurse directories
3694 "--links", # Consider symlinks
3695 "--safe-links", # Ignore links outside of tree
3696 "--perms", # Preserve permissions
3697 "--times", # Preserive mod times
3698 "--compress", # Compress the data transmitted
3699 "--force", # Force deletion on non-empty dirs
3700 "--whole-file", # Don't do block transfers, only entire files
3701 "--delete", # Delete files that aren't in the master tree
3702 "--delete-after", # Delete only after everything else is done
3703 "--stats", # Show final statistics about what was transfered
3704 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3705 "--exclude='/distfiles'", # Exclude distfiles from consideration
3706 "--exclude='/local'", # Exclude local from consideration
3707 "--exclude='/packages'", # Exclude packages from consideration
3711 # The below validation is not needed when using the above hardcoded
3714 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3715 rsync_opts.extend(settings["PORTAGE_RSYNC_OPTS"].split())
3717 for opt in ("--recursive", "--times"):
3718 if opt not in rsync_opts:
3719 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3720 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3721 rsync_opts.append(opt)
3723 for exclude in ("distfiles", "local", "packages"):
3724 opt = "--exclude=/%s" % exclude
3725 if opt not in rsync_opts:
3726 portage.writemsg(yellow("WARNING:") + \
3727 " adding required option %s not included in " % opt + \
3728 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3729 rsync_opts.append(opt)
3731 if settings["RSYNC_TIMEOUT"] != "":
3732 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3733 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3735 mytimeout = int(settings["RSYNC_TIMEOUT"])
3736 rsync_opts.append("--timeout=%d" % mytimeout)
3737 except ValueError, e:
3738 portage.writemsg("!!! %s\n" % str(e))
3740 # TODO: determine options required for official servers
3741 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
3743 def rsync_opt_startswith(opt_prefix):
3744 for x in rsync_opts:
3745 if x.startswith(opt_prefix):
3749 if not rsync_opt_startswith("--timeout="):
3750 rsync_opts.append("--timeout=%d" % mytimeout)
3752 for opt in ("--compress", "--whole-file"):
3753 if opt not in rsync_opts:
3754 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3755 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3756 rsync_opts.append(opt)
3758 if "--quiet" in myopts:
3759 rsync_opts.append("--quiet") # Shut up a lot
3761 rsync_opts.append("--verbose") # Print filelist
3763 if "--verbose" in myopts:
3764 rsync_opts.append("--progress") # Progress meter for each file
3766 if "--debug" in myopts:
3767 rsync_opts.append("--checksum") # Force checksum on all files
3769 if settings["RSYNC_EXCLUDEFROM"] != "":
3770 portage.writemsg(yellow("WARNING:") + \
3771 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
3772 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3773 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
3774 rsync_opts.append("--exclude-from=%s" % \
3775 settings["RSYNC_EXCLUDEFROM"])
3777 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
3778 " but file does not exist.\n")
3780 if settings["RSYNC_RATELIMIT"] != "":
3781 portage.writemsg(yellow("WARNING:") + \
3782 " usage of RSYNC_RATELIMIT is deprecated, use " + \
3783 "PORTAGE_RSYNC_EXTRA_OPTS instead")
3784 rsync_opts.append("--bwlimit=%s" % \
3785 settings["RSYNC_RATELIMIT"])
3787 # Real local timestamp file.
3788 servertimestampfile = os.path.join(
3789 myportdir, "metadata", "timestamp.chk")
3790 # Temporary file for remote server timestamp comparison.
3791 tmpservertimestampfile = os.path.join(
3792 settings["PORTAGE_TMPDIR"], "timestamp.chk")
3794 content = portage_util.grabfile(servertimestampfile)
3798 mytimestamp = time.mktime(time.strptime(content[0],
3799 "%a, %d %b %Y %H:%M:%S +0000"))
3800 except OverflowError, ValueError:
3805 if settings.has_key("RSYNC_RETRIES"):
3806 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
3807 maxretries=int(settings["RSYNC_RETRIES"])
3809 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
3810 except SystemExit, e:
3811 raise # Needed else can't exit
3813 maxretries=3 #default number of retries
3816 user_name, hostname, port = re.split(
3817 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
3820 if user_name is None:
3822 updatecache_flg=True
3823 all_rsync_opts = set(rsync_opts)
3824 all_rsync_opts.update(
3825 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
3826 family = socket.AF_UNSPEC
3827 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
3828 family = socket.AF_INET
3829 elif socket.has_ipv6 and \
3830 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
3831 family = socket.AF_INET6
3838 for addrinfo in socket.getaddrinfo(
3839 hostname, None, family, socket.SOCK_STREAM):
3840 if addrinfo[0] == socket.AF_INET6:
3841 # IPv6 addresses need to be enclosed in square brackets
3842 ips.append("[%s]" % addrinfo[4][0])
3844 ips.append(addrinfo[4][0])
3845 except SystemExit, e:
3846 raise # Needed else can't exit
3847 except Exception, e:
3848 print "Notice:",str(e)
3853 dosyncuri = syncuri.replace(
3854 "//" + user_name + hostname + port + "/",
3855 "//" + user_name + ips[0] + port + "/", 1)
3856 except SystemExit, e:
3857 raise # Needed else can't exit
3858 except Exception, e:
3859 print "Notice:",str(e)
3863 if "--ask" in myopts:
3864 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
3869 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
3870 if "--quiet" not in myopts:
3871 print ">>> Starting rsync with "+dosyncuri+"..."
3873 emergelog(xterm_titles,
3874 ">>> Starting retry %d of %d with %s" % \
3875 (retries,maxretries,dosyncuri))
3876 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
3878 if mytimestamp != 0 and "--quiet" not in myopts:
3879 print ">>> Checking server timestamp ..."
3881 rsynccommand = " ".join(["/usr/bin/rsync", " ".join(rsync_opts),
3882 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
3884 if "--debug" in myopts:
3889 if mytimestamp != 0:
3890 mycommand = rsynccommand.split()
3891 mycommand.append(dosyncuri.rstrip("/") + \
3892 "/metadata/timestamp.chk")
3893 mycommand.append(tmpservertimestampfile)
3896 exitcode = portage_exec.spawn(
3897 mycommand, env=settings.environ())
3898 content = portage.grabfile(tmpservertimestampfile)
3901 servertimestamp = time.mktime(time.strptime(
3902 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
3903 except OverflowError, ValueError:
3908 os.unlink(tmpservertimestampfile)
3912 if exitcode == os.EX_OK:
3913 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
3914 emergelog(xterm_titles,
3915 ">>> Cancelling sync -- Already current.")
3918 print ">>> Timestamps on the server and in the local repository are the same."
3919 print ">>> Cancelling all further sync action. You are already up to date."
3921 print ">>> In order to force sync, remove '%s'." % servertimestampfile
3925 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
3926 emergelog(xterm_titles,
3927 ">>> Server out of date: %s" % dosyncuri)
3930 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
3932 print ">>> In order to force sync, remove '%s'." % servertimestampfile
3935 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
3937 mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
3938 exitcode=portage.spawn(mycommand,settings,free=1)
3939 if exitcode in [0,1,2,3,4,11,14,20,21]:
3941 elif exitcode in [0,1,2,3,4,11,14,20,21]:
3946 if retries<=maxretries:
3947 print ">>> Retrying..."
3952 updatecache_flg=False
3956 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
3960 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
3961 print darkred("!!!")+green(" that your SYNC statement is proper.")
3962 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
3964 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
3965 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
3966 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
3967 print darkred("!!!")+green(" and try again after the problem has been fixed.")
3968 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
3970 print darkred("!!!")+green(" Rsync was killed before it finished.")
3972 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
3973 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
3974 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
3975 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
3976 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
3979 elif syncuri[:6]=="cvs://":
3980 if not os.path.exists("/usr/bin/cvs"):
3981 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
3982 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
3985 cvsdir=os.path.dirname(myportdir)
3986 if not os.path.exists(myportdir+"/CVS"):
3988 print ">>> Starting initial cvs checkout with "+syncuri+"..."
3989 if os.path.exists(cvsdir+"/gentoo-x86"):
3990 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
3995 if e.errno != errno.ENOENT:
3997 "!!! existing '%s' directory; exiting.\n" % myportdir)
4000 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4001 print "!!! cvs checkout error; exiting."
4003 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4006 print ">>> Starting cvs update with "+syncuri+"..."
4007 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4008 myportdir, settings, free=1)
4009 if retval != os.EX_OK:
4013 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4016 if updatecache_flg and \
4017 myaction != "metadata" and \
4018 "metadata-transfer" not in settings.features:
4019 updatecache_flg = False
4021 # Reload the whole config from scratch.
4022 settings, trees, mtimedb = load_emerge_config(trees=trees)
4023 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4025 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4026 action_metadata(settings, portdb, myopts)
4028 if portage.global_updates(settings, trees, mtimedb["updates"]):
4030 # Reload the whole config from scratch.
4031 settings, trees, mtimedb = load_emerge_config(trees=trees)
4032 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4034 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4035 mypvs = portage.best(
4036 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4038 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4040 if myaction != "metadata":
4041 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4042 retval = portage.portage_exec.spawn(
4043 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4044 dosyncuri], env=settings.environ())
4045 if retval != os.EX_OK:
4046 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4048 if(mybestpv != mypvs) and not "--quiet" in myopts:
4050 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4051 print red(" * ")+"that you update portage now, before any other packages are updated."
4052 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4053 print red(" * ")+"configuration files."
4054 print red(" * ")+"To update portage, run 'emerge portage'."
4057 def action_metadata(settings, portdb, myopts):
4058 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4059 old_umask = os.umask(0002)
4060 cachedir = os.path.normpath(settings.depcachedir)
4061 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4062 "/lib", "/opt", "/proc", "/root", "/sbin",
4063 "/sys", "/tmp", "/usr", "/var"]:
4064 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4065 "ROOT DIRECTORY ON YOUR SYSTEM."
4066 print >> sys.stderr, \
4067 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4069 if not os.path.exists(cachedir):
4072 ec = portage.eclass_cache.cache(portdb.porttree_root)
4073 myportdir = os.path.realpath(settings["PORTDIR"])
4074 cm = settings.load_best_module("portdbapi.metadbmodule")(
4075 myportdir, "metadata/cache", portage.auxdbkeys[:])
4079 class percentage_noise_maker(cache.util.quiet_mirroring):
4080 def __init__(self, dbapi):
4082 self.cp_all = dbapi.cp_all()
4083 l = len(self.cp_all)
4084 self.call_update_min = 100000000
4085 self.min_cp_all = l/100.0
4090 for x in self.cp_all:
4092 if self.count > self.min_cp_all:
4093 self.call_update_min = 0
4095 for y in self.dbapi.cp_list(x):
4097 self.call_update_mine = 0
4099 def update(self, *arg):
4100 try: self.pstr = int(self.pstr) + 1
4101 except ValueError: self.pstr = 1
4102 sys.stdout.write("%s%i%%" % \
4103 ("\b" * (len(str(self.pstr))+1), self.pstr))
4105 self.call_update_min = 10000000
4107 def finish(self, *arg):
4108 sys.stdout.write("\b\b\b\b100%\n")
4111 if "--quiet" in myopts:
4112 def quicky_cpv_generator(cp_all_list):
4113 for x in cp_all_list:
4114 for y in portdb.cp_list(x):
4116 source = quicky_cpv_generator(portdb.cp_all())
4117 noise_maker = cache.util.quiet_mirroring()
4119 noise_maker = source = percentage_noise_maker(portdb)
4120 cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4121 eclass_cache=ec, verbose_instance=noise_maker)
4126 def action_regen(settings, portdb):
4127 xterm_titles = "notitles" not in settings.features
4128 emergelog(xterm_titles, " === regen")
4129 #regenerate cache entries
4130 print "Regenerating cache entries... "
4132 os.close(sys.stdin.fileno())
4133 except SystemExit, e:
4134 raise # Needed else can't exit
4138 mynodes = portdb.cp_all()
4139 from cache.cache_errors import CacheError
4141 for mytree in portdb.porttrees:
4143 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4144 except CacheError, e:
4145 print "\n error listing cache entries for " + \
4146 "'%s': %s, continuing..." % (mytree, e)
4151 mymatches = portdb.xmatch("match-all",x)
4152 portage.writemsg_stdout("processing %s\n" % x)
4155 foo = portdb.aux_get(y,["DEPEND"])
4156 except SystemExit, e:
4157 # sys.exit is an exception... And consequently, we can't catch it.
4159 except Exception, e:
4160 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4162 for mytree in portdb.porttrees:
4163 if portdb.findname2(y, mytree=mytree)[0]:
4164 dead_nodes[mytree].discard(y)
4166 for mytree, nodes in dead_nodes.iteritems():
4167 auxdb = portdb.auxdb[mytree]
4171 except KeyError, CacheError:
4175 def action_config(settings, trees, myopts, myfiles):
4176 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4177 print red("!!! config can only take a single package atom at this time\n")
4179 if not is_valid_package_atom(myfiles[0]):
4180 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4182 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4183 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4187 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4188 except ValueError, e:
4189 # Multiple matches thrown from cpv_expand
4192 print "No packages found.\n"
4195 if "--ask" in myopts:
4197 print "Please select a package to configure:"
4201 options.append(str(idx))
4202 print options[-1]+") "+pkg
4205 idx = userquery("Selection?", options)
4208 pkg = pkgs[int(idx)-1]
4210 print "The following packages available:"
4213 print "\nPlease use a specific atom or the --ask option."
4219 if "--ask" in myopts:
4220 if userquery("Ready to configure "+pkg+"?") == "No":
4223 print "Configuring pkg..."
4225 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4226 mysettings = portage.config(clone=settings)
4227 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4228 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4229 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4232 def action_info(settings, trees, myopts, myfiles):
4233 unameout=commands.getstatusoutput("uname -mrp")[1]
4234 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4235 settings.profile_path, settings["CHOST"],
4236 trees[settings["ROOT"]]["vartree"].dbapi)
4238 header_title = "System Settings"
4240 print header_width * "="
4241 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4242 print header_width * "="
4243 print "System uname: "+unameout
4244 gentoo_release = portage.grabfile(os.path.join(
4245 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4247 print gentoo_release[0]
4249 print "Unknown Host Operating System"
4250 lastSync = portage.grabfile(os.path.join(
4251 settings["PORTDIR"], "metadata", "timestamp.chk"))
4252 print "Timestamp of tree:",
4258 output=commands.getstatusoutput("distcc --version")
4260 print str(output[1].split("\n",1)[0]),
4261 if "distcc" in settings.features:
4266 output=commands.getstatusoutput("ccache -V")
4268 print str(output[1].split("\n",1)[0]),
4269 if "ccache" in settings.features:
4274 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4275 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4276 myvars += portage_util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4277 myvars = portage_util.unique_array(myvars)
4281 if portage.isvalidatom(x):
4282 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4284 for y in pkg_matches:
4285 mycpv = portage.catpkgsplit(y)
4286 if(mycpv[3] != "r0"):
4287 pkgs += [mycpv[2] + "-" + mycpv[3]]
4291 pkgs = ", ".join(sorted_versions(pkgs))
4292 print "%-20s %s" % (x+":", pkgs)
4294 print "%-20s %s" % (x+":", "[NOT VALID]")
4296 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4298 if "--verbose" in myopts:
4299 myvars=settings.keys()
4301 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4302 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4303 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4304 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4306 myvars.extend(portage_util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4308 myvars = portage_util.unique_array(myvars)
4314 print '%s="%s"' % (x, settings[x])
4316 use = set(settings["USE"].split())
4317 use_expand = settings["USE_EXPAND"].split()
4319 for varname in use_expand:
4320 flag_prefix = varname.lower() + "_"
4322 if f.startswith(flag_prefix):
4326 print 'USE="%s"' % " ".join(use),
4327 for varname in use_expand:
4328 myval = settings.get(varname)
4330 print '%s="%s"' % (varname, myval),
4333 unset_vars.append(x)
4335 print "Unset: "+", ".join(unset_vars)
4338 if "--debug" in myopts:
4339 for x in dir(portage):
4340 module = getattr(portage, x)
4341 if "cvs_id_string" in dir(module):
4342 print "%s: %s" % (str(x), str(module.cvs_id_string))
4344 # See if we can find any packages installed matching the strings
4345 # passed on the command line
4347 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4348 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4350 mypkgs.extend(vardb.match(x))
4352 # If some packages were found...
4354 # Get our global settings (we only print stuff if it varies from
4355 # the current config)
4356 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4357 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4359 pkgsettings = portage.config(clone=settings)
4361 for myvar in mydesiredvars:
4362 global_vals[myvar] = set(settings.get(myvar, "").split())
4364 # Loop through each package
4365 # Only print settings if they differ from global settings
4366 header_printed = False
4368 # Get all package specific variables
4369 auxvalues = vardb.aux_get(pkg, auxkeys)
4371 for i in xrange(len(auxkeys)):
4372 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4374 for myvar in mydesiredvars:
4375 # If the package variable doesn't match the
4376 # current global variable, something has changed
4377 # so set diff_found so we know to print
4378 if valuesmap[myvar] != global_vals[myvar]:
4379 diff_values[myvar] = valuesmap[myvar]
4380 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4381 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4383 # If a matching ebuild is no longer available in the tree, maybe it
4384 # would make sense to compare against the flags for the best
4385 # available version with the same slot?
4387 if portdb.cpv_exists(pkg):
4389 pkgsettings.setcpv(pkg, mydb=mydb)
4390 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4392 diff_values["USE"] = valuesmap["USE"]
4393 # If a difference was found, print the info for
4397 # If we have not yet printed the header,
4399 if not header_printed:
4400 header_title = "Package Settings"
4401 print header_width * "="
4402 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4403 print header_width * "="
4404 header_printed = True
4406 # Print package info
4407 print "%s was built with the following:" % pkg
4408 for myvar in mydesiredvars + ["USE"]:
4409 if myvar in diff_values:
4410 mylist = list(diff_values[myvar])
4412 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4415 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4417 print "emerge: no search terms provided."
4419 searchinstance = search(settings, portdb,
4420 vartree, spinner, "--searchdesc" in myopts,
4421 "--quiet" not in myopts)
4422 for mysearch in myfiles:
4424 searchinstance.execute(mysearch)
4425 except re.error, comment:
4426 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4428 searchinstance.output()
4430 def action_depclean(settings, trees, ldpath_mtimes,
4432 # Kill packages that aren't explicitly merged or are required as a
4433 # dependency of another package. World file is explicit.
4435 warn_prefix = colorize("BAD", "*** WARNING *** ")
4437 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4438 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4439 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4441 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4442 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4443 print warn_prefix + "be kept. They can be manually added to this set with"
4444 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4445 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4446 print warn_prefix + "depclean, even if they are part of the world set."
4448 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4449 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4450 print warn_prefix + "consequence, it is often necessary to run "
4451 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4453 xterm_titles = "notitles" not in settings.features
4454 myroot = settings["ROOT"]
4455 dep_check_trees = {}
4456 dep_check_trees[myroot] = {}
4457 dep_check_trees[myroot]["vartree"] = \
4458 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4459 vardb = dep_check_trees[myroot]["vartree"].dbapi
4460 # Constrain dependency selection to the installed packages.
4461 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4462 syslist = getlist(settings, "system")
4463 worldlist = getlist(settings, "world")
4464 fakedb = portage.fakedbapi(settings=settings)
4465 myvarlist = vardb.cpv_all()
4468 print "\n!!! You have no system list.",
4470 print "\n!!! You have no world file.",
4472 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4474 if not (syslist and worldlist and myvarlist):
4475 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4476 print " break your installation.\n"
4477 if "--pretend" not in myopts:
4478 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4480 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4481 emergelog(xterm_titles, " >>> depclean")
4483 if "--quiet" not in myopts:
4484 print "\nCalculating dependencies ",
4488 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4489 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4491 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4493 while remaining_atoms:
4494 atom, parent, priority = remaining_atoms.pop()
4495 pkgs = vardb.match(atom)
4497 if not atom.startswith("!") and priority == hard:
4498 unresolveable.setdefault(atom, []).append(parent)
4500 # Could put slot checking here to ensure that there aren't two
4501 # packages with the same slot...
4503 if fakedb.cpv_exists(pkg):
4506 fakedb.cpv_inject(pkg)
4507 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4509 if myopts.get("--with-bdeps", "y") == "y":
4510 mydeps.append((myaux["DEPEND"], soft))
4512 mydeps.append((" ".join(myaux.values()), hard))
4513 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4514 for depstr, priority in mydeps:
4519 if "--debug" in myopts:
4521 print "Parent: ", pkg
4522 print "Depstring:", depstr
4524 if priority == soft:
4530 portage_dep._dep_check_strict = False
4531 success, atoms = portage.dep_check(depstr, None, settings,
4532 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4534 portage_dep._dep_check_strict = True
4536 show_invalid_depstring_notice(
4537 ("installed", myroot, pkg, "nomerge"),
4541 if "--debug" in myopts:
4542 print "Candidates:", atoms
4545 remaining_atoms.append((atom, pkg, priority))
4547 if "--quiet" not in myopts:
4548 print "\b\b... done!\n"
4551 print "Dependencies could not be completely resolved due to"
4552 print "the following required packages not being installed:"
4554 for atom in unresolveable:
4555 print atom, "required by", " ".join(unresolveable[atom])
4557 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4558 print "depclean? It may also be necessary to manually uninstalled packages that no"
4559 print "longer exist in the portage tree since it may not be possible to satisfy their"
4560 print "dependencies."
4564 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4567 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4568 "unmerge", cleanlist, ldpath_mtimes)
4570 print "Packages installed: "+str(len(myvarlist))
4571 print "Packages in world: "+str(len(worldlist))
4572 print "Packages in system: "+str(len(syslist))
4573 print "Unique package names: "+str(len(myvarlist))
4574 print "Required packages: "+str(len(fakedb.cpv_all()))
4575 if "--pretend" in myopts:
4576 print "Number to remove: "+str(len(cleanlist))
4578 print "Number removed: "+str(len(cleanlist))
4580 def action_build(settings, trees, mtimedb,
4581 myopts, myaction, myfiles, spinner):
4582 ldpath_mtimes = mtimedb["ldpath"]
4584 if ("--ask" in myopts or "--pretend" in myopts) and not "--quiet" in myopts:
4586 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4590 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4592 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4596 print darkgreen("These are the packages that would be %s, in order:") % action
4599 # validate the state of the resume data
4600 # so that we can make assumptions later.
4601 for k in ("resume", "resume_backup"):
4603 if "mergelist" in mtimedb[k]:
4604 if not mtimedb[k]["mergelist"]:
4609 if "--resume" in myopts and \
4610 ("resume" in mtimedb or
4611 "resume_backup" in mtimedb):
4612 if "resume" not in mtimedb:
4613 mtimedb["resume"] = mtimedb["resume_backup"]
4614 del mtimedb["resume_backup"]
4616 # XXX: "myopts" is a list for backward compatibility.
4617 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4619 for opt in ("--skipfirst", "--ask", "--tree"):
4620 myresumeopts.pop(opt, None)
4622 for myopt, myarg in myopts.iteritems():
4623 if myopt not in myresumeopts:
4624 myresumeopts[myopt] = myarg
4626 myparams = create_depgraph_params(myopts, myaction)
4627 if not "--quiet" in myopts:
4628 print "Calculating dependencies ",
4629 mydepgraph = depgraph(settings, trees,
4630 myopts, myparams, spinner)
4631 if not "--quiet" in myopts:
4632 print "\b\b... done!"
4634 if ("--resume" in myopts):
4635 print darkgreen("emerge: It seems we have nothing to resume...")
4638 myparams = create_depgraph_params(myopts, myaction)
4639 if myaction in ["system","world"]:
4640 if not ("--quiet" in myopts):
4641 print "Calculating",myaction,"dependencies ",
4643 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4644 if not mydepgraph.xcreate(myaction):
4645 print "!!! Depgraph creation failed."
4647 if not ("--quiet" in myopts):
4648 print "\b\b... done!"
4650 if not ("--quiet" in myopts):
4651 print "Calculating dependencies ",
4653 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4655 retval, favorites = mydepgraph.select_files(myfiles)
4656 except portage_exception.PackageNotFound, e:
4657 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4661 if not ("--quiet" in myopts):
4662 print "\b\b... done!"
4664 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4665 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4667 if mydepgraph.missingbins:
4668 for x in mydepgraph.missingbins:
4669 sys.stderr.write(" "+str(x)+"\n")
4670 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4673 if "--ask" in myopts:
4674 if "--resume" in myopts:
4675 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4676 mymergelist = mtimedb["resume"]["mergelist"]
4677 if "--skipfirst" in myopts:
4678 mymergelist = mymergelist[1:]
4679 if len(mymergelist) == 0:
4680 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4682 mydepgraph.display(mymergelist)
4683 prompt="Would you like to resume merging these packages?"
4686 mydepgraph.altlist(reversed=("--tree" in myopts)))
4688 for x in mydepgraph.altlist():
4689 if x[0] != "blocks" and x[3] != "nomerge":
4691 #check for blocking dependencies
4692 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
4693 print "\n!!! Error: The above package list contains packages which cannot be installed"
4694 print "!!! at the same time on the same system."
4695 if "--quiet" not in myopts:
4696 show_blocker_docs_link()
4699 if "--noreplace" in myopts and favorites:
4702 print " %s %s" % (good("*"), x)
4703 prompt="Would you like to add these packages to your world favorites?"
4704 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4705 prompt="Nothing to merge; would you like to auto-clean packages?"
4708 print "Nothing to merge; quitting."
4711 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4712 prompt="Would you like to fetch the source files for these packages?"
4714 prompt="Would you like to merge these packages?"
4716 if userquery(prompt)=="No":
4721 # Don't ask again (e.g. when auto-cleaning packages after merge)
4724 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4725 if ("--resume" in myopts):
4726 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4727 mymergelist = mtimedb["resume"]["mergelist"]
4728 if "--skipfirst" in myopts:
4729 mymergelist = mymergelist[1:]
4730 if len(mymergelist) == 0:
4731 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4733 mydepgraph.display(mymergelist)
4736 mydepgraph.altlist(reversed=("--tree" in myopts)))
4738 if ("--buildpkgonly" in myopts):
4739 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
4740 print "\n!!! --buildpkgonly requires all dependencies to be merged."
4741 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
4744 if ("--resume" in myopts):
4745 favorites=mtimedb["resume"]["favorites"]
4746 mergetask = MergeTask(settings, trees, myopts)
4747 if "--fetchonly" in myopts:
4748 """ parallel-fetch uses --resume --fetchonly and we don't want
4749 it to write the mtimedb"""
4750 mtimedb.filename = None
4751 time.sleep(3) # allow the parent to have first fetch
4753 retval = mergetask.merge(
4754 mtimedb["resume"]["mergelist"], favorites, mtimedb)
4755 if retval != os.EX_OK:
4758 if "resume" in mtimedb and \
4759 "mergelist" in mtimedb["resume"] and \
4760 len(mtimedb["resume"]["mergelist"]) > 1:
4761 mtimedb["resume_backup"] = mtimedb["resume"]
4762 del mtimedb["resume"]
4764 mtimedb["resume"]={}
4765 # XXX: Stored as a list for backward compatibility.
4766 mtimedb["resume"]["myopts"] = \
4767 [k for k in myopts if myopts[k] is True]
4768 mtimedb["resume"]["favorites"]=favorites
4769 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4770 for pkgline in mydepgraph.altlist():
4771 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
4772 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
4773 tmpsettings = portage.config(clone=settings)
4775 if settings.get("PORTAGE_DEBUG", "") == "1":
4777 retval = portage.doebuild(
4778 y, "digest", settings["ROOT"], tmpsettings, edebug,
4779 ("--pretend" in myopts),
4780 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
4782 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4784 for pkg in mydepgraph.altlist():
4785 if pkg[0] != "blocks":
4788 pkglist = mydepgraph.altlist()
4790 mergetask = MergeTask(settings, trees, myopts)
4791 retval = mergetask.merge(pkglist, favorites, mtimedb)
4792 if retval != os.EX_OK:
4795 if mtimedb.has_key("resume"):
4796 del mtimedb["resume"]
4797 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4798 print ">>> Auto-cleaning packages..."
4799 vartree = trees[settings["ROOT"]]["vartree"]
4800 unmerge(settings, myopts, vartree, "clean", ["world"],
4803 portage.writemsg_stdout(colorize("WARN", "WARNING:")
4804 + " AUTOCLEAN is disabled. This can cause serious"
4805 + " problems due to overlapping packages.\n")
4807 def multiple_actions(action1, action2):
4808 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
4809 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
4812 def parse_opts(tmpcmdline, silent=False):
4817 global actions, options, shortmapping
4819 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
4820 argument_options = {
4822 "help":"specify the location for portage configuration files",
4826 "help":"enable or disable color output",
4828 "choices":("y", "n")
4831 "help":"include unnecessary build time dependencies",
4833 "choices":("y", "n")
4837 from optparse import OptionParser
4838 parser = OptionParser()
4839 if parser.has_option("--help"):
4840 parser.remove_option("--help")
4842 for action_opt in actions:
4843 parser.add_option("--" + action_opt, action="store_true",
4844 dest=action_opt.replace("-", "_"), default=False)
4845 for myopt in options:
4846 parser.add_option(myopt, action="store_true",
4847 dest=myopt.lstrip("--").replace("-", "_"), default=False)
4848 for shortopt, longopt in shortmapping.iteritems():
4849 parser.add_option("-" + shortopt, action="store_true",
4850 dest=longopt.lstrip("--").replace("-", "_"), default=False)
4851 for myalias, myopt in longopt_aliases.iteritems():
4852 parser.add_option(myalias, action="store_true",
4853 dest=myopt.lstrip("--").replace("-", "_"), default=False)
4855 for myopt, kwargs in argument_options.iteritems():
4856 parser.add_option(myopt,
4857 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
4859 myoptions, myargs = parser.parse_args(args=tmpcmdline)
4861 for myopt in options:
4862 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
4864 myopts[myopt] = True
4866 for myopt in argument_options:
4867 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
4871 for action_opt in actions:
4872 v = getattr(myoptions, action_opt.replace("-", "_"))
4875 multiple_actions(myaction, action_opt)
4877 myaction = action_opt
4880 if x in actions and myaction != "search":
4881 if not silent and x not in ["system", "world"]:
4882 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
4883 # special case "search" so people can search for action terms, e.g. emerge -s sync
4885 multiple_actions(myaction, x)
4891 if "--nocolor" in myopts:
4893 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
4894 "use '--color=n' instead.\n")
4895 del myopts["--nocolor"]
4896 myopts["--color"] = "n"
4898 return myaction, myopts, myfiles
4900 def validate_ebuild_environment(trees):
4901 for myroot in trees:
4902 mysettings = trees[myroot]["vartree"].settings
4903 if not mysettings.get("ARCH", None):
4904 print >> sys.stderr, bad("\a!!! ARCH is not set... " + \
4905 "Are you missing the '%setc/make.profile' symlink?" % \
4906 mysettings["PORTAGE_CONFIGROOT"])
4907 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
4908 "Is your portage tree complete?\n")
4910 del myroot, mysettings
4912 def load_emerge_config(trees=None):
4914 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
4915 kwargs[k] = os.environ.get(envvar, None)
4916 trees = portage.create_trees(trees=trees, **kwargs)
4918 settings = trees["/"]["vartree"].settings
4920 for myroot in trees:
4922 settings = trees[myroot]["vartree"].settings
4925 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
4926 mtimedb = portage.MtimeDB(mtimedbfile)
4927 return settings, trees, mtimedb
4929 def adjust_config(myopts, settings):
4930 """Make emerge specific adjustments to the config."""
4932 # To enhance usability, make some vars case insensitive by forcing them to
4934 for myvar in ("AUTOCLEAN", "NOCOLOR"):
4935 if myvar in settings:
4936 settings[myvar] = settings[myvar].lower()
4937 settings.backup_changes(myvar)
4940 # Kill noauto as it will break merges otherwise.
4941 if "noauto" in settings.features:
4942 while "noauto" in settings.features:
4943 settings.features.remove("noauto")
4944 settings["FEATURES"] = " ".join(settings.features)
4945 settings.backup_changes("FEATURES")
4949 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
4950 except ValueError, e:
4951 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4952 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
4953 settings["CLEAN_DELAY"], noiselevel=-1)
4954 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
4955 settings.backup_changes("CLEAN_DELAY")
4957 EMERGE_WARNING_DELAY = 10
4959 EMERGE_WARNING_DELAY = int(settings.get(
4960 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
4961 except ValueError, e:
4962 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4963 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
4964 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
4965 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
4966 settings.backup_changes("EMERGE_WARNING_DELAY")
4968 if "--quiet" in myopts:
4969 settings["PORTAGE_QUIET"]="1"
4970 settings.backup_changes("PORTAGE_QUIET")
4972 # Set so that configs will be merged regardless of remembered status
4973 if ("--noconfmem" in myopts):
4974 settings["NOCONFMEM"]="1"
4975 settings.backup_changes("NOCONFMEM")
4977 # Set various debug markers... They should be merged somehow.
4980 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
4981 if PORTAGE_DEBUG not in (0, 1):
4982 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
4983 PORTAGE_DEBUG, noiselevel=-1)
4984 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
4987 except ValueError, e:
4988 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4989 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
4990 settings["PORTAGE_DEBUG"], noiselevel=-1)
4992 if "--debug" in myopts:
4994 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
4995 settings.backup_changes("PORTAGE_DEBUG")
4997 if settings.get("NOCOLOR") not in ("yes","true"):
4998 output.havecolor = 1
5000 """The explicit --color < y | n > option overrides the NOCOLOR environment
5001 variable and stdout auto-detection."""
5002 if "--color" in myopts:
5003 if "y" == myopts["--color"]:
5004 output.havecolor = 1
5005 settings["NOCOLOR"] = "false"
5007 output.havecolor = 0
5008 settings["NOCOLOR"] = "true"
5009 settings.backup_changes("NOCOLOR")
5010 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5011 output.havecolor = 0
5012 settings["NOCOLOR"] = "true"
5013 settings.backup_changes("NOCOLOR")
5016 # Disable color until we're sure that it should be enabled (after
5017 # EMERGE_DEFAULT_OPTS has been parsed).
5018 output.havecolor = 0
5019 # This first pass is just for options that need to be known as early as
5020 # possible, such as --config-root. They will be parsed again later,
5021 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5022 # the value of --config-root).
5023 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5024 if "--debug" in myopts:
5025 os.environ["PORTAGE_DEBUG"] = "1"
5026 if "--config-root" in myopts:
5027 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5029 # Portage needs to ensure a sane umask for the files it creates.
5031 settings, trees, mtimedb = load_emerge_config()
5032 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5035 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5036 except (OSError, ValueError), e:
5037 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5038 settings["PORTAGE_NICENESS"])
5039 portage.writemsg("!!! %s\n" % str(e))
5042 if portage.global_updates(settings, trees, mtimedb["updates"]):
5044 # Reload the whole config from scratch.
5045 settings, trees, mtimedb = load_emerge_config(trees=trees)
5046 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5048 xterm_titles = "notitles" not in settings.features
5051 if "--ignore-default-opts" not in sys.argv:
5052 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5053 tmpcmdline.extend(sys.argv[1:])
5054 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5056 if "--digest" in myopts:
5057 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5058 # Reload the whole config from scratch so that the portdbapi internal
5059 # config is updated with new FEATURES.
5060 settings, trees, mtimedb = load_emerge_config(trees=trees)
5061 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5063 for myroot in trees:
5064 mysettings = trees[myroot]["vartree"].settings
5066 adjust_config(myopts, mysettings)
5068 del myroot, mysettings
5070 spinner = stdout_spinner()
5071 if "candy" in settings.features:
5072 spinner.update = spinner.update_scroll
5074 portage.deprecated_profile_check()
5076 #Freeze the portdbapi for enhanced performance:
5077 for myroot in trees:
5078 trees[myroot]["porttree"].dbapi.freeze()
5081 if "moo" in myfiles:
5084 Larry loves Gentoo (""" + os.uname()[0] + """)
5086 _______________________
5087 < Have you mooed today? >
5088 -----------------------
5097 if (myaction in ["world", "system"]) and myfiles:
5098 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5102 ext = os.path.splitext(x)[1]
5103 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5104 print "emerging by path implies --oneshot... adding --oneshot to options."
5105 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5108 if ("--tree" in myopts) and ("--columns" in myopts):
5109 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5112 if ("--quiet" in myopts):
5113 spinner.update = spinner.update_quiet
5114 portage_util.noiselimit = -1
5116 # Always create packages if FEATURES=buildpkg
5117 # Imply --buildpkg if --buildpkgonly
5118 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5119 if "--buildpkg" not in myopts:
5120 myopts["--buildpkg"] = True
5122 # Also allow -S to invoke search action (-sS)
5123 if ("--searchdesc" in myopts):
5124 if myaction and myaction != "search":
5125 myfiles.append(myaction)
5126 if "--search" not in myopts:
5127 myopts["--search"] = True
5130 # Always try and fetch binary packages if FEATURES=getbinpkg
5131 if ("getbinpkg" in settings.features):
5132 myopts["--getbinpkg"] = True
5134 if "--skipfirst" in myopts and "--resume" not in myopts:
5135 myopts["--resume"] = True
5137 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5138 myopts["--usepkgonly"] = True
5140 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5141 myopts["--getbinpkg"] = True
5143 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5144 myopts["--usepkg"] = True
5146 # Also allow -K to apply --usepkg/-k
5147 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5148 myopts["--usepkg"] = True
5150 # Also allow -l to apply --pretend/-p, but if already in --ask mode
5151 if ("--changelog" in myopts) and not (("--pretend" in myopts) or ("--ask" in myopts)):
5152 print ">>> --changelog implies --pretend... adding --pretend to options."
5153 myopts["--pretend"] = True
5155 # Allow -p to remove --ask
5156 if ("--pretend" in myopts) and ("--ask" in myopts):
5157 print ">>> --pretend disables --ask... removing --ask from options."
5160 # forbid --ask when not in a terminal
5161 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5162 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5163 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5167 if settings.get("PORTAGE_DEBUG", "") == "1":
5168 spinner.update = spinner.update_quiet
5170 if "python-trace" in settings.features:
5171 import portage_debug
5172 portage_debug.set_trace(True)
5174 if ("--resume" in myopts):
5175 if "--tree" in myopts:
5176 print "* --tree is currently broken with --resume. Disabling..."
5177 del myopts["--tree"]
5179 if not ("--quiet" in myopts):
5180 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5181 spinner.update = spinner.update_basic
5183 if "--version" in myopts:
5184 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5185 settings.profile_path, settings["CHOST"],
5186 trees[settings["ROOT"]]["vartree"].dbapi)
5188 elif "--help" in myopts:
5189 emergehelp.help(myaction, myopts, output.havecolor)
5192 if portage.wheelgid == portage.portage_gid:
5193 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5194 print " include the portage user as noted above, and then use group portage."
5196 if "--debug" in myopts:
5197 print "myaction", myaction
5198 print "myopts", myopts
5200 if not myaction and not myfiles and "--resume" not in myopts:
5201 emergehelp.help(myaction, myopts, output.havecolor)
5204 # check if root user is the current user for the actions where emerge needs this
5205 if portage.secpass < 2:
5206 # We've already allowed "--version" and "--help" above.
5207 if "--pretend" not in myopts and \
5208 myaction not in ("search","info"):
5209 need_superuser = not \
5210 ("--fetchonly" in myopts or \
5211 "--fetch-all-uri" in myopts or \
5212 myaction in ("metadata", "regen"))
5213 if portage.secpass < 1 or \
5216 access_desc = "superuser"
5218 access_desc = "portage group"
5219 # Always show portage_group_warning() when only portage group
5220 # access is required but the user is not in the portage group.
5221 from portage_data import portage_group_warning
5222 if "--ask" in myopts:
5223 myopts["--pretend"] = True
5225 print ("%s access would be required... " + \
5226 "adding --pretend to options.\n") % access_desc
5227 if portage.secpass < 1 and not need_superuser:
5228 portage_group_warning()
5230 sys.stderr.write(("emerge: %s access would be " + \
5231 "required.\n\n") % access_desc)
5232 if portage.secpass < 1 and not need_superuser:
5233 portage_group_warning()
5236 disable_emergelog = False
5237 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5239 disable_emergelog = True
5241 if myaction in ("search", "info"):
5242 disable_emergelog = True
5243 if disable_emergelog:
5244 """ Disable emergelog for everything except build or unmerge
5245 operations. This helps minimize parallel emerge.log entries that can
5246 confuse log parsers. We especially want it disabled during
5247 parallel-fetch, which uses --resume --fetchonly."""
5249 def emergelog(*pargs, **kargs):
5252 if not "--pretend" in myopts:
5253 emergelog(xterm_titles, "Started emerge on: "+\
5254 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5257 myelogstr=" ".join(myopts)
5259 myelogstr+=" "+myaction
5261 myelogstr+=" "+" ".join(myfiles)
5262 emergelog(xterm_titles, " *** emerge " + myelogstr)
5264 def emergeexitsig(signum, frame):
5265 signal.signal(signal.SIGINT, signal.SIG_IGN)
5266 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5267 portage_util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5268 sys.exit(100+signum)
5269 signal.signal(signal.SIGINT, emergeexitsig)
5270 signal.signal(signal.SIGTERM, emergeexitsig)
5273 """This gets out final log message in before we quit."""
5274 if "--pretend" not in myopts:
5275 emergelog(xterm_titles, " *** terminating.")
5276 if "notitles" not in settings.features:
5278 portage.atexit_register(emergeexit)
5280 if myaction in ("config", "metadata", "regen", "sync"):
5281 if "--pretend" in myopts:
5282 sys.stderr.write(("emerge: The '%s' action does " + \
5283 "not support '--pretend'.\n") % myaction)
5285 if "sync" == myaction:
5286 action_sync(settings, trees, mtimedb, myopts, myaction)
5287 elif "metadata" == myaction:
5288 action_metadata(settings, portdb, myopts)
5289 elif myaction=="regen":
5290 validate_ebuild_environment(trees)
5291 action_regen(settings, portdb)
5293 elif "config"==myaction:
5294 validate_ebuild_environment(trees)
5295 action_config(settings, trees, myopts, myfiles)
5298 elif "info"==myaction:
5299 action_info(settings, trees, myopts, myfiles)
5302 elif "search"==myaction:
5303 validate_ebuild_environment(trees)
5304 action_search(settings, portdb, trees["/"]["vartree"],
5305 myopts, myfiles, spinner)
5306 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5307 validate_ebuild_environment(trees)
5308 vartree = trees[settings["ROOT"]]["vartree"]
5309 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5311 if "--pretend" not in myopts:
5312 post_emerge(settings, mtimedb, 0)
5314 elif "depclean"==myaction:
5315 validate_ebuild_environment(trees)
5316 action_depclean(settings, trees, mtimedb["ldpath"],
5318 if "--pretend" not in myopts:
5319 post_emerge(settings, mtimedb, 0)
5320 # "update", "system", or just process files:
5322 validate_ebuild_environment(trees)
5323 action_build(settings, trees, mtimedb,
5324 myopts, myaction, myfiles, spinner)
5325 if "--pretend" not in myopts:
5326 post_emerge(settings, mtimedb, 0)
5328 if __name__ == "__main__":
5329 retval = emerge_main()