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), e.__module__
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 servertimestampdir = settings.depcachedir+"/"
3788 servertimestampfile = settings.depcachedir+"/timestamp.chk"
3789 tmpservertimestampdir = settings["PORTAGE_TMPDIR"]+"/"
3790 tmpservertimestampfile = settings["PORTAGE_TMPDIR"]+"/timestamp.chk"
3792 # We only use the backup if a timestamp exists in the portdir.
3794 if os.path.exists(myportdir+"/metadata/timestamp.chk"):
3795 content=portage.grabfile(servertimestampfile)
3797 content=portage.grabfile(myportdir+"/metadata/timestamp.chk")
3801 mytimestamp=time.mktime(time.strptime(content[0], "%a, %d %b %Y %H:%M:%S +0000"))
3807 if not os.path.exists(servertimestampdir):
3808 os.mkdir(servertimestampdir)
3809 os.chown(servertimestampdir, os.getuid(), portage.portage_gid)
3810 os.chmod(servertimestampdir, 02775)
3814 if settings.has_key("RSYNC_RETRIES"):
3815 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
3816 maxretries=int(settings["RSYNC_RETRIES"])
3818 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
3819 except SystemExit, e:
3820 raise # Needed else can't exit
3822 maxretries=3 #default number of retries
3825 user_name, hostname, port = re.split(
3826 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
3829 if user_name is None:
3831 updatecache_flg=True
3832 all_rsync_opts = set(rsync_opts)
3833 all_rsync_opts.update(
3834 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
3835 family = socket.AF_UNSPEC
3836 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
3837 family = socket.AF_INET
3838 elif socket.has_ipv6 and \
3839 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
3840 family = socket.AF_INET6
3847 for addrinfo in socket.getaddrinfo(
3848 hostname, None, family, socket.SOCK_STREAM):
3849 if addrinfo[0] == socket.AF_INET6:
3850 # IPv6 addresses need to be enclosed in square brackets
3851 ips.append("[%s]" % addrinfo[4][0])
3853 ips.append(addrinfo[4][0])
3854 except SystemExit, e:
3855 raise # Needed else can't exit
3856 except Exception, e:
3857 print "Notice:",str(e)
3862 dosyncuri = syncuri.replace(
3863 "//" + user_name + hostname + port + "/",
3864 "//" + user_name + ips[0] + port + "/", 1)
3865 except SystemExit, e:
3866 raise # Needed else can't exit
3867 except Exception, e:
3868 print "Notice:",str(e)
3872 if "--ask" in myopts:
3873 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
3878 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
3879 if "--quiet" not in myopts:
3880 print ">>> Starting rsync with "+dosyncuri+"..."
3882 emergelog(xterm_titles,
3883 ">>> Starting retry %d of %d with %s" % \
3884 (retries,maxretries,dosyncuri))
3885 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
3887 if "--quiet" not in myopts:
3888 print ">>> Checking server timestamp ..."
3890 rsynccommand = " ".join(["/usr/bin/rsync", " ".join(rsync_opts),
3891 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
3893 if "--debug" in myopts:
3896 mycommand = " ".join([rsynccommand,
3897 dosyncuri + "/metadata/timestamp.chk",
3898 tmpservertimestampdir])
3899 exitcode=portage.spawn(mycommand,settings,free=1)
3902 servertimestamp = time.mktime(time.strptime(portage.grabfile(tmpservertimestampfile)[0], "%a, %d %b %Y %H:%M:%S +0000"))
3903 except SystemExit, e:
3904 raise # Needed else can't exit
3908 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
3909 emergelog(xterm_titles,
3910 ">>> Cancelling sync -- Already current.")
3913 print ">>> Timestamps on the server and in the local repository are the same."
3914 print ">>> Cancelling all further sync action. You are already up to date."
3916 print ">>> In order to force sync, remove '%s'." % tmpservertimestampfile
3920 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
3921 emergelog(xterm_titles,
3922 ">>> Server out of date: %s" % dosyncuri)
3925 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
3927 print ">>> In order to force sync, remove '%s'." % tmpservertimestampfile
3930 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
3932 mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
3933 exitcode=portage.spawn(mycommand,settings,free=1)
3934 if exitcode in [0,1,2,3,4,11,14,20,21]:
3936 elif exitcode in [0,1,2,3,4,11,14,20,21]:
3941 if retries<=maxretries:
3942 print ">>> Retrying..."
3947 updatecache_flg=False
3951 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
3952 # save timestamp.chk for next timestamp check.
3954 if tmpservertimestampfile is not None:
3955 portage.movefile(tmpservertimestampfile,
3956 servertimestampfile, mysettings=settings)
3957 except SystemExit, e:
3959 except Exception, e:
3960 portage.writemsg("!!! Failed to save current timestamp.\n",
3962 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
3967 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
3968 print darkred("!!!")+green(" that your SYNC statement is proper.")
3969 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
3971 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
3972 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
3973 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
3974 print darkred("!!!")+green(" and try again after the problem has been fixed.")
3975 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
3977 print darkred("!!!")+green(" Rsync was killed before it finished.")
3979 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
3980 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
3981 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
3982 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
3983 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
3986 elif syncuri[:6]=="cvs://":
3987 if not os.path.exists("/usr/bin/cvs"):
3988 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
3989 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
3992 cvsdir=os.path.dirname(myportdir)
3993 if not os.path.exists(myportdir+"/CVS"):
3995 print ">>> Starting initial cvs checkout with "+syncuri+"..."
3996 if os.path.exists(cvsdir+"/gentoo-x86"):
3997 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4002 if e.errno != errno.ENOENT:
4004 "!!! existing '%s' directory; exiting.\n" % myportdir)
4007 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4008 print "!!! cvs checkout error; exiting."
4010 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4013 print ">>> Starting cvs update with "+syncuri+"..."
4014 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4015 myportdir, settings, free=1)
4016 if retval != os.EX_OK:
4020 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4023 if updatecache_flg and \
4024 myaction != "metadata" and \
4025 "metadata-transfer" not in settings.features:
4026 updatecache_flg = False
4028 # Reload the whole config from scratch.
4029 settings, trees, mtimedb = load_emerge_config(trees=trees)
4030 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4032 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4033 action_metadata(settings, portdb, myopts)
4035 if portage.global_updates(settings, trees, mtimedb["updates"]):
4037 # Reload the whole config from scratch.
4038 settings, trees, mtimedb = load_emerge_config(trees=trees)
4039 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4041 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4042 mypvs = portage.best(
4043 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4045 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4047 if myaction != "metadata":
4048 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4049 retval = portage.portage_exec.spawn(
4050 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4051 dosyncuri], env=settings.environ())
4052 if retval != os.EX_OK:
4053 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4055 if(mybestpv != mypvs) and not "--quiet" in myopts:
4057 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4058 print red(" * ")+"that you update portage now, before any other packages are updated."
4059 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4060 print red(" * ")+"configuration files."
4061 print red(" * ")+"To update portage, run 'emerge portage'."
4064 def action_metadata(settings, portdb, myopts):
4065 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4066 old_umask = os.umask(0002)
4067 cachedir = os.path.normpath(settings.depcachedir)
4068 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4069 "/lib", "/opt", "/proc", "/root", "/sbin",
4070 "/sys", "/tmp", "/usr", "/var"]:
4071 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4072 "ROOT DIRECTORY ON YOUR SYSTEM."
4073 print >> sys.stderr, \
4074 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4076 if not os.path.exists(cachedir):
4079 ec = portage.eclass_cache.cache(portdb.porttree_root)
4080 myportdir = os.path.realpath(settings["PORTDIR"])
4081 cm = settings.load_best_module("portdbapi.metadbmodule")(
4082 myportdir, "metadata/cache", portage.auxdbkeys[:])
4086 class percentage_noise_maker(cache.util.quiet_mirroring):
4087 def __init__(self, dbapi):
4089 self.cp_all = dbapi.cp_all()
4090 l = len(self.cp_all)
4091 self.call_update_min = 100000000
4092 self.min_cp_all = l/100.0
4097 for x in self.cp_all:
4099 if self.count > self.min_cp_all:
4100 self.call_update_min = 0
4102 for y in self.dbapi.cp_list(x):
4104 self.call_update_mine = 0
4106 def update(self, *arg):
4107 try: self.pstr = int(self.pstr) + 1
4108 except ValueError: self.pstr = 1
4109 sys.stdout.write("%s%i%%" % \
4110 ("\b" * (len(str(self.pstr))+1), self.pstr))
4112 self.call_update_min = 10000000
4114 def finish(self, *arg):
4115 sys.stdout.write("\b\b\b\b100%\n")
4118 if "--quiet" in myopts:
4119 def quicky_cpv_generator(cp_all_list):
4120 for x in cp_all_list:
4121 for y in portdb.cp_list(x):
4123 source = quicky_cpv_generator(portdb.cp_all())
4124 noise_maker = cache.util.quiet_mirroring()
4126 noise_maker = source = percentage_noise_maker(portdb)
4127 cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4128 eclass_cache=ec, verbose_instance=noise_maker)
4133 def action_regen(settings, portdb):
4134 xterm_titles = "notitles" not in settings.features
4135 emergelog(xterm_titles, " === regen")
4136 #regenerate cache entries
4137 print "Regenerating cache entries... "
4139 os.close(sys.stdin.fileno())
4140 except SystemExit, e:
4141 raise # Needed else can't exit
4145 mynodes = portdb.cp_all()
4146 from cache.cache_errors import CacheError
4148 for mytree in portdb.porttrees:
4150 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4151 except CacheError, e:
4152 print "\n error listing cache entries for " + \
4153 "'%s': %s, continuing..." % (mytree, e)
4158 mymatches = portdb.xmatch("match-all",x)
4159 portage.writemsg_stdout("processing %s\n" % x)
4162 foo = portdb.aux_get(y,["DEPEND"])
4163 except SystemExit, e:
4164 # sys.exit is an exception... And consequently, we can't catch it.
4166 except Exception, e:
4167 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4169 for mytree in portdb.porttrees:
4170 if portdb.findname2(y, mytree=mytree)[0]:
4171 dead_nodes[mytree].discard(y)
4173 for mytree, nodes in dead_nodes.iteritems():
4174 auxdb = portdb.auxdb[mytree]
4178 except KeyError, CacheError:
4182 def action_config(settings, trees, myopts, myfiles):
4183 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4184 print red("!!! config can only take a single package atom at this time\n")
4186 if not is_valid_package_atom(myfiles[0]):
4187 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4189 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4190 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4194 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4195 except ValueError, e:
4196 # Multiple matches thrown from cpv_expand
4199 print "No packages found.\n"
4202 if "--ask" in myopts:
4204 print "Please select a package to configure:"
4208 options.append(str(idx))
4209 print options[-1]+") "+pkg
4212 idx = userquery("Selection?", options)
4215 pkg = pkgs[int(idx)-1]
4217 print "The following packages available:"
4220 print "\nPlease use a specific atom or the --ask option."
4226 if "--ask" in myopts:
4227 if userquery("Ready to configure "+pkg+"?") == "No":
4230 print "Configuring pkg..."
4232 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4233 mysettings = portage.config(clone=settings)
4234 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4235 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4236 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4239 def action_info(settings, trees, myopts, myfiles):
4240 unameout=commands.getstatusoutput("uname -mrp")[1]
4241 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4242 settings.profile_path, settings["CHOST"],
4243 trees[settings["ROOT"]]["vartree"].dbapi)
4245 header_title = "System Settings"
4247 print header_width * "="
4248 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4249 print header_width * "="
4250 print "System uname: "+unameout
4251 gentoo_release = portage.grabfile(os.path.join(
4252 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4254 print gentoo_release[0]
4256 print "Unknown Host Operating System"
4257 lastSync = portage.grabfile(os.path.join(
4258 settings["PORTDIR"], "metadata", "timestamp.chk"))
4259 print "Timestamp of tree:",
4265 output=commands.getstatusoutput("distcc --version")
4267 print str(output[1].split("\n",1)[0]),
4268 if "distcc" in settings.features:
4273 output=commands.getstatusoutput("ccache -V")
4275 print str(output[1].split("\n",1)[0]),
4276 if "ccache" in settings.features:
4281 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4282 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4283 myvars += portage_util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4284 myvars = portage_util.unique_array(myvars)
4288 if portage.isvalidatom(x):
4289 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4291 for y in pkg_matches:
4292 mycpv = portage.catpkgsplit(y)
4293 if(mycpv[3] != "r0"):
4294 pkgs += [mycpv[2] + "-" + mycpv[3]]
4298 pkgs = ", ".join(sorted_versions(pkgs))
4299 print "%-20s %s" % (x+":", pkgs)
4301 print "%-20s %s" % (x+":", "[NOT VALID]")
4303 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4305 if "--verbose" in myopts:
4306 myvars=settings.keys()
4308 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4309 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4310 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4311 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4313 myvars.extend(portage_util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4315 myvars = portage_util.unique_array(myvars)
4321 print '%s="%s"' % (x, settings[x])
4323 use = set(settings["USE"].split())
4324 use_expand = settings["USE_EXPAND"].split()
4326 for varname in use_expand:
4327 flag_prefix = varname.lower() + "_"
4329 if f.startswith(flag_prefix):
4333 print 'USE="%s"' % " ".join(use),
4334 for varname in use_expand:
4335 myval = settings.get(varname)
4337 print '%s="%s"' % (varname, myval),
4340 unset_vars.append(x)
4342 print "Unset: "+", ".join(unset_vars)
4345 if "--debug" in myopts:
4346 for x in dir(portage):
4347 module = getattr(portage, x)
4348 if "cvs_id_string" in dir(module):
4349 print "%s: %s" % (str(x), str(module.cvs_id_string))
4351 # See if we can find any packages installed matching the strings
4352 # passed on the command line
4354 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4355 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4357 mypkgs.extend(vardb.match(x))
4359 # If some packages were found...
4361 # Get our global settings (we only print stuff if it varies from
4362 # the current config)
4363 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4364 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4366 pkgsettings = portage.config(clone=settings)
4368 for myvar in mydesiredvars:
4369 global_vals[myvar] = set(settings.get(myvar, "").split())
4371 # Loop through each package
4372 # Only print settings if they differ from global settings
4373 header_printed = False
4375 # Get all package specific variables
4376 auxvalues = vardb.aux_get(pkg, auxkeys)
4378 for i in xrange(len(auxkeys)):
4379 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4381 for myvar in mydesiredvars:
4382 # If the package variable doesn't match the
4383 # current global variable, something has changed
4384 # so set diff_found so we know to print
4385 if valuesmap[myvar] != global_vals[myvar]:
4386 diff_values[myvar] = valuesmap[myvar]
4387 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4388 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4390 # If a matching ebuild is no longer available in the tree, maybe it
4391 # would make sense to compare against the flags for the best
4392 # available version with the same slot?
4394 if portdb.cpv_exists(pkg):
4396 pkgsettings.setcpv(pkg, mydb=mydb)
4397 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4399 diff_values["USE"] = valuesmap["USE"]
4400 # If a difference was found, print the info for
4404 # If we have not yet printed the header,
4406 if not header_printed:
4407 header_title = "Package Settings"
4408 print header_width * "="
4409 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4410 print header_width * "="
4411 header_printed = True
4413 # Print package info
4414 print "%s was built with the following:" % pkg
4415 for myvar in mydesiredvars + ["USE"]:
4416 if myvar in diff_values:
4417 mylist = list(diff_values[myvar])
4419 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4422 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4424 print "emerge: no search terms provided."
4426 searchinstance = search(settings, portdb,
4427 vartree, spinner, "--searchdesc" in myopts,
4428 "--quiet" not in myopts)
4429 for mysearch in myfiles:
4431 searchinstance.execute(mysearch)
4432 except re.error, comment:
4433 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4435 searchinstance.output()
4437 def action_depclean(settings, trees, ldpath_mtimes,
4439 # Kill packages that aren't explicitly merged or are required as a
4440 # dependency of another package. World file is explicit.
4442 warn_prefix = colorize("BAD", "*** WARNING *** ")
4444 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4445 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4446 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4448 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4449 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4450 print warn_prefix + "be kept. They can be manually added to this set with"
4451 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4452 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4453 print warn_prefix + "depclean, even if they are part of the world set."
4455 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4456 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4457 print warn_prefix + "consequence, it is often necessary to run "
4458 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4460 xterm_titles = "notitles" not in settings.features
4461 myroot = settings["ROOT"]
4462 dep_check_trees = {}
4463 dep_check_trees[myroot] = {}
4464 dep_check_trees[myroot]["vartree"] = \
4465 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4466 vardb = dep_check_trees[myroot]["vartree"].dbapi
4467 # Constrain dependency selection to the installed packages.
4468 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4469 syslist = getlist(settings, "system")
4470 worldlist = getlist(settings, "world")
4471 fakedb = portage.fakedbapi(settings=settings)
4472 myvarlist = vardb.cpv_all()
4475 print "\n!!! You have no system list.",
4477 print "\n!!! You have no world file.",
4479 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4481 if not (syslist and worldlist and myvarlist):
4482 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4483 print " break your installation.\n"
4484 if "--pretend" not in myopts:
4485 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4487 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4488 emergelog(xterm_titles, " >>> depclean")
4490 if "--quiet" not in myopts:
4491 print "\nCalculating dependencies ",
4495 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4496 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4498 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4500 while remaining_atoms:
4501 atom, parent, priority = remaining_atoms.pop()
4502 pkgs = vardb.match(atom)
4504 if not atom.startswith("!") and priority == hard:
4505 unresolveable.setdefault(atom, []).append(parent)
4507 # Could put slot checking here to ensure that there aren't two
4508 # packages with the same slot...
4510 if fakedb.cpv_exists(pkg):
4513 fakedb.cpv_inject(pkg)
4514 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4516 if myopts.get("--with-bdeps", "y") == "y":
4517 mydeps.append((myaux["DEPEND"], soft))
4519 mydeps.append((" ".join(myaux.values()), hard))
4520 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4521 for depstr, priority in mydeps:
4526 if "--debug" in myopts:
4528 print "Parent: ", pkg
4529 print "Depstring:", depstr
4531 if priority == soft:
4537 portage_dep._dep_check_strict = False
4538 success, atoms = portage.dep_check(depstr, None, settings,
4539 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4541 portage_dep._dep_check_strict = True
4543 show_invalid_depstring_notice(
4544 ("installed", myroot, pkg, "nomerge"),
4548 if "--debug" in myopts:
4549 print "Candidates:", atoms
4552 remaining_atoms.append((atom, pkg, priority))
4554 if "--quiet" not in myopts:
4555 print "\b\b... done!\n"
4558 print "Dependencies could not be completely resolved due to"
4559 print "the following required packages not being installed:"
4561 for atom in unresolveable:
4562 print atom, "required by", " ".join(unresolveable[atom])
4564 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4565 print "depclean? It may also be necessary to manually uninstalled packages that no"
4566 print "longer exist in the portage tree since it may not be possible to satisfy their"
4567 print "dependencies."
4571 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4574 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4575 "unmerge", cleanlist, ldpath_mtimes)
4577 print "Packages installed: "+str(len(myvarlist))
4578 print "Packages in world: "+str(len(worldlist))
4579 print "Packages in system: "+str(len(syslist))
4580 print "Unique package names: "+str(len(myvarlist))
4581 print "Required packages: "+str(len(fakedb.cpv_all()))
4582 if "--pretend" in myopts:
4583 print "Number to remove: "+str(len(cleanlist))
4585 print "Number removed: "+str(len(cleanlist))
4587 def action_build(settings, trees, mtimedb,
4588 myopts, myaction, myfiles, spinner):
4589 ldpath_mtimes = mtimedb["ldpath"]
4591 if ("--ask" in myopts or "--pretend" in myopts) and not "--quiet" in myopts:
4593 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4597 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4599 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4603 print darkgreen("These are the packages that would be %s, in order:") % action
4606 # validate the state of the resume data
4607 # so that we can make assumptions later.
4608 for k in ("resume", "resume_backup"):
4610 if "mergelist" in mtimedb[k]:
4611 if not mtimedb[k]["mergelist"]:
4616 if "--resume" in myopts and \
4617 ("resume" in mtimedb or
4618 "resume_backup" in mtimedb):
4619 if "resume" not in mtimedb:
4620 mtimedb["resume"] = mtimedb["resume_backup"]
4621 del mtimedb["resume_backup"]
4623 # XXX: "myopts" is a list for backward compatibility.
4624 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4626 for opt in ("--skipfirst", "--ask", "--tree"):
4627 myresumeopts.pop(opt, None)
4629 for myopt, myarg in myopts.iteritems():
4630 if myopt not in myresumeopts:
4631 myresumeopts[myopt] = myarg
4633 myparams = create_depgraph_params(myopts, myaction)
4634 if not "--quiet" in myopts:
4635 print "Calculating dependencies ",
4636 mydepgraph = depgraph(settings, trees,
4637 myopts, myparams, spinner)
4638 if not "--quiet" in myopts:
4639 print "\b\b... done!"
4641 if ("--resume" in myopts):
4642 print darkgreen("emerge: It seems we have nothing to resume...")
4645 myparams = create_depgraph_params(myopts, myaction)
4646 if myaction in ["system","world"]:
4647 if not ("--quiet" in myopts):
4648 print "Calculating",myaction,"dependencies ",
4650 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4651 if not mydepgraph.xcreate(myaction):
4652 print "!!! Depgraph creation failed."
4654 if not ("--quiet" in myopts):
4655 print "\b\b... done!"
4657 if not ("--quiet" in myopts):
4658 print "Calculating dependencies ",
4660 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4662 retval, favorites = mydepgraph.select_files(myfiles)
4663 except portage_exception.PackageNotFound, e:
4664 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4668 if not ("--quiet" in myopts):
4669 print "\b\b... done!"
4671 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4672 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4674 if mydepgraph.missingbins:
4675 for x in mydepgraph.missingbins:
4676 sys.stderr.write(" "+str(x)+"\n")
4677 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4680 if "--ask" in myopts:
4681 if "--resume" in myopts:
4682 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4683 mymergelist = mtimedb["resume"]["mergelist"]
4684 if "--skipfirst" in myopts:
4685 mymergelist = mymergelist[1:]
4686 if len(mymergelist) == 0:
4687 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4689 mydepgraph.display(mymergelist)
4690 prompt="Would you like to resume merging these packages?"
4693 mydepgraph.altlist(reversed=("--tree" in myopts)))
4695 for x in mydepgraph.altlist():
4696 if x[0] != "blocks" and x[3] != "nomerge":
4698 #check for blocking dependencies
4699 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
4700 print "\n!!! Error: The above package list contains packages which cannot be installed"
4701 print "!!! at the same time on the same system."
4702 if "--quiet" not in myopts:
4703 show_blocker_docs_link()
4706 if "--noreplace" in myopts and favorites:
4709 print " %s %s" % (good("*"), x)
4710 prompt="Would you like to add these packages to your world favorites?"
4711 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4712 prompt="Nothing to merge; would you like to auto-clean packages?"
4715 print "Nothing to merge; quitting."
4718 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4719 prompt="Would you like to fetch the source files for these packages?"
4721 prompt="Would you like to merge these packages?"
4723 if userquery(prompt)=="No":
4728 # Don't ask again (e.g. when auto-cleaning packages after merge)
4731 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4732 if ("--resume" in myopts):
4733 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4734 mymergelist = mtimedb["resume"]["mergelist"]
4735 if "--skipfirst" in myopts:
4736 mymergelist = mymergelist[1:]
4737 if len(mymergelist) == 0:
4738 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4740 mydepgraph.display(mymergelist)
4743 mydepgraph.altlist(reversed=("--tree" in myopts)))
4745 if ("--buildpkgonly" in myopts):
4746 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
4747 print "\n!!! --buildpkgonly requires all dependencies to be merged."
4748 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
4751 if ("--resume" in myopts):
4752 favorites=mtimedb["resume"]["favorites"]
4753 mergetask = MergeTask(settings, trees, myopts)
4754 if "--fetchonly" in myopts:
4755 """ parallel-fetch uses --resume --fetchonly and we don't want
4756 it to write the mtimedb"""
4757 mtimedb.filename = None
4758 time.sleep(3) # allow the parent to have first fetch
4760 retval = mergetask.merge(
4761 mtimedb["resume"]["mergelist"], favorites, mtimedb)
4762 if retval != os.EX_OK:
4765 if "resume" in mtimedb and \
4766 "mergelist" in mtimedb["resume"] and \
4767 len(mtimedb["resume"]["mergelist"]) > 1:
4768 mtimedb["resume_backup"] = mtimedb["resume"]
4769 del mtimedb["resume"]
4771 mtimedb["resume"]={}
4772 # XXX: Stored as a list for backward compatibility.
4773 mtimedb["resume"]["myopts"] = \
4774 [k for k in myopts if myopts[k] is True]
4775 mtimedb["resume"]["favorites"]=favorites
4776 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4777 for pkgline in mydepgraph.altlist():
4778 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
4779 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
4780 tmpsettings = portage.config(clone=settings)
4782 if settings.get("PORTAGE_DEBUG", "") == "1":
4784 retval = portage.doebuild(
4785 y, "digest", settings["ROOT"], tmpsettings, edebug,
4786 ("--pretend" in myopts),
4787 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
4789 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4791 for pkg in mydepgraph.altlist():
4792 if pkg[0] != "blocks":
4795 pkglist = mydepgraph.altlist()
4797 mergetask = MergeTask(settings, trees, myopts)
4798 retval = mergetask.merge(pkglist, favorites, mtimedb)
4799 if retval != os.EX_OK:
4802 if mtimedb.has_key("resume"):
4803 del mtimedb["resume"]
4804 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4805 print ">>> Auto-cleaning packages..."
4806 vartree = trees[settings["ROOT"]]["vartree"]
4807 unmerge(settings, myopts, vartree, "clean", ["world"],
4810 portage.writemsg_stdout(colorize("WARN", "WARNING:")
4811 + " AUTOCLEAN is disabled. This can cause serious"
4812 + " problems due to overlapping packages.\n")
4814 def multiple_actions(action1, action2):
4815 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
4816 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
4819 def parse_opts(tmpcmdline, silent=False):
4824 global actions, options, shortmapping
4826 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
4827 argument_options = {
4829 "help":"specify the location for portage configuration files",
4833 "help":"enable or disable color output",
4835 "choices":("y", "n")
4838 "help":"include unnecessary build time dependencies",
4840 "choices":("y", "n")
4844 from optparse import OptionParser
4845 parser = OptionParser()
4846 if parser.has_option("--help"):
4847 parser.remove_option("--help")
4849 for action_opt in actions:
4850 parser.add_option("--" + action_opt, action="store_true",
4851 dest=action_opt.replace("-", "_"), default=False)
4852 for myopt in options:
4853 parser.add_option(myopt, action="store_true",
4854 dest=myopt.lstrip("--").replace("-", "_"), default=False)
4855 for shortopt, longopt in shortmapping.iteritems():
4856 parser.add_option("-" + shortopt, action="store_true",
4857 dest=longopt.lstrip("--").replace("-", "_"), default=False)
4858 for myalias, myopt in longopt_aliases.iteritems():
4859 parser.add_option(myalias, action="store_true",
4860 dest=myopt.lstrip("--").replace("-", "_"), default=False)
4862 for myopt, kwargs in argument_options.iteritems():
4863 parser.add_option(myopt,
4864 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
4866 myoptions, myargs = parser.parse_args(args=tmpcmdline)
4868 for myopt in options:
4869 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
4871 myopts[myopt] = True
4873 for myopt in argument_options:
4874 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
4878 for action_opt in actions:
4879 v = getattr(myoptions, action_opt.replace("-", "_"))
4882 multiple_actions(myaction, action_opt)
4884 myaction = action_opt
4887 if x in actions and myaction != "search":
4888 if not silent and x not in ["system", "world"]:
4889 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
4890 # special case "search" so people can search for action terms, e.g. emerge -s sync
4892 multiple_actions(myaction, x)
4898 if "--nocolor" in myopts:
4900 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
4901 "use '--color=n' instead.\n")
4902 del myopts["--nocolor"]
4903 myopts["--color"] = "n"
4905 return myaction, myopts, myfiles
4907 def validate_ebuild_environment(trees):
4908 for myroot in trees:
4909 mysettings = trees[myroot]["vartree"].settings
4910 if not mysettings.get("ARCH", None):
4911 print >> sys.stderr, bad("\a!!! ARCH is not set... " + \
4912 "Are you missing the '%setc/make.profile' symlink?" % \
4913 mysettings["PORTAGE_CONFIGROOT"])
4914 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
4915 "Is your portage tree complete?\n")
4917 del myroot, mysettings
4919 def load_emerge_config(trees=None):
4921 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
4922 kwargs[k] = os.environ.get(envvar, None)
4923 trees = portage.create_trees(trees=trees, **kwargs)
4925 settings = trees["/"]["vartree"].settings
4927 for myroot in trees:
4929 settings = trees[myroot]["vartree"].settings
4932 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
4933 mtimedb = portage.MtimeDB(mtimedbfile)
4934 return settings, trees, mtimedb
4936 def adjust_config(myopts, settings):
4937 """Make emerge specific adjustments to the config."""
4939 # To enhance usability, make some vars case insensitive by forcing them to
4941 for myvar in ("AUTOCLEAN", "NOCOLOR"):
4942 if myvar in settings:
4943 settings[myvar] = settings[myvar].lower()
4944 settings.backup_changes(myvar)
4947 # Kill noauto as it will break merges otherwise.
4948 if "noauto" in settings.features:
4949 while "noauto" in settings.features:
4950 settings.features.remove("noauto")
4951 settings["FEATURES"] = " ".join(settings.features)
4952 settings.backup_changes("FEATURES")
4956 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
4957 except ValueError, e:
4958 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4959 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
4960 settings["CLEAN_DELAY"], noiselevel=-1)
4961 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
4962 settings.backup_changes("CLEAN_DELAY")
4964 EMERGE_WARNING_DELAY = 10
4966 EMERGE_WARNING_DELAY = int(settings.get(
4967 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
4968 except ValueError, e:
4969 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4970 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
4971 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
4972 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
4973 settings.backup_changes("EMERGE_WARNING_DELAY")
4975 if "--quiet" in myopts:
4976 settings["PORTAGE_QUIET"]="1"
4977 settings.backup_changes("PORTAGE_QUIET")
4979 # Set so that configs will be merged regardless of remembered status
4980 if ("--noconfmem" in myopts):
4981 settings["NOCONFMEM"]="1"
4982 settings.backup_changes("NOCONFMEM")
4984 # Set various debug markers... They should be merged somehow.
4987 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
4988 if PORTAGE_DEBUG not in (0, 1):
4989 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
4990 PORTAGE_DEBUG, noiselevel=-1)
4991 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
4994 except ValueError, e:
4995 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4996 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
4997 settings["PORTAGE_DEBUG"], noiselevel=-1)
4999 if "--debug" in myopts:
5001 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5002 settings.backup_changes("PORTAGE_DEBUG")
5004 if settings.get("NOCOLOR") not in ("yes","true"):
5005 output.havecolor = 1
5007 """The explicit --color < y | n > option overrides the NOCOLOR environment
5008 variable and stdout auto-detection."""
5009 if "--color" in myopts:
5010 if "y" == myopts["--color"]:
5011 output.havecolor = 1
5012 settings["NOCOLOR"] = "false"
5014 output.havecolor = 0
5015 settings["NOCOLOR"] = "true"
5016 settings.backup_changes("NOCOLOR")
5017 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5018 output.havecolor = 0
5019 settings["NOCOLOR"] = "true"
5020 settings.backup_changes("NOCOLOR")
5023 # Disable color until we're sure that it should be enabled (after
5024 # EMERGE_DEFAULT_OPTS has been parsed).
5025 output.havecolor = 0
5026 # This first pass is just for options that need to be known as early as
5027 # possible, such as --config-root. They will be parsed again later,
5028 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5029 # the value of --config-root).
5030 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5031 if "--debug" in myopts:
5032 os.environ["PORTAGE_DEBUG"] = "1"
5033 if "--config-root" in myopts:
5034 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5036 # Portage needs to ensure a sane umask for the files it creates.
5038 settings, trees, mtimedb = load_emerge_config()
5039 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5042 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5043 except (OSError, ValueError), e:
5044 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5045 settings["PORTAGE_NICENESS"])
5046 portage.writemsg("!!! %s\n" % str(e))
5049 if portage.global_updates(settings, trees, mtimedb["updates"]):
5051 # Reload the whole config from scratch.
5052 settings, trees, mtimedb = load_emerge_config(trees=trees)
5053 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5055 xterm_titles = "notitles" not in settings.features
5058 if "--ignore-default-opts" not in sys.argv:
5059 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5060 tmpcmdline.extend(sys.argv[1:])
5061 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5063 if "--digest" in myopts:
5064 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5065 # Reload the whole config from scratch so that the portdbapi internal
5066 # config is updated with new FEATURES.
5067 settings, trees, mtimedb = load_emerge_config(trees=trees)
5068 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5070 for myroot in trees:
5071 mysettings = trees[myroot]["vartree"].settings
5073 adjust_config(myopts, mysettings)
5075 del myroot, mysettings
5077 spinner = stdout_spinner()
5078 if "candy" in settings.features:
5079 spinner.update = spinner.update_scroll
5081 portage.deprecated_profile_check()
5083 #Freeze the portdbapi for enhanced performance:
5084 for myroot in trees:
5085 trees[myroot]["porttree"].dbapi.freeze()
5088 if "moo" in myfiles:
5091 Larry loves Gentoo (""" + os.uname()[0] + """)
5093 _______________________
5094 < Have you mooed today? >
5095 -----------------------
5104 if (myaction in ["world", "system"]) and myfiles:
5105 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5109 ext = os.path.splitext(x)[1]
5110 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5111 print "emerging by path implies --oneshot... adding --oneshot to options."
5112 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5115 if ("--tree" in myopts) and ("--columns" in myopts):
5116 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5119 if ("--quiet" in myopts):
5120 spinner.update = spinner.update_quiet
5121 portage_util.noiselimit = -1
5123 # Always create packages if FEATURES=buildpkg
5124 # Imply --buildpkg if --buildpkgonly
5125 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5126 if "--buildpkg" not in myopts:
5127 myopts["--buildpkg"] = True
5129 # Also allow -S to invoke search action (-sS)
5130 if ("--searchdesc" in myopts):
5131 if myaction and myaction != "search":
5132 myfiles.append(myaction)
5133 if "--search" not in myopts:
5134 myopts["--search"] = True
5137 # Always try and fetch binary packages if FEATURES=getbinpkg
5138 if ("getbinpkg" in settings.features):
5139 myopts["--getbinpkg"] = True
5141 if "--skipfirst" in myopts and "--resume" not in myopts:
5142 myopts["--resume"] = True
5144 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5145 myopts["--usepkgonly"] = True
5147 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5148 myopts["--getbinpkg"] = True
5150 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5151 myopts["--usepkg"] = True
5153 # Also allow -K to apply --usepkg/-k
5154 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5155 myopts["--usepkg"] = True
5157 # Also allow -l to apply --pretend/-p, but if already in --ask mode
5158 if ("--changelog" in myopts) and not (("--pretend" in myopts) or ("--ask" in myopts)):
5159 print ">>> --changelog implies --pretend... adding --pretend to options."
5160 myopts["--pretend"] = True
5162 # Allow -p to remove --ask
5163 if ("--pretend" in myopts) and ("--ask" in myopts):
5164 print ">>> --pretend disables --ask... removing --ask from options."
5167 # forbid --ask when not in a terminal
5168 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5169 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5170 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5174 if settings.get("PORTAGE_DEBUG", "") == "1":
5175 spinner.update = spinner.update_quiet
5177 if "python-trace" in settings.features:
5178 import portage_debug
5179 portage_debug.set_trace(True)
5181 if ("--resume" in myopts):
5182 if "--tree" in myopts:
5183 print "* --tree is currently broken with --resume. Disabling..."
5184 del myopts["--tree"]
5186 if not ("--quiet" in myopts):
5187 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5188 spinner.update = spinner.update_basic
5190 if "--version" in myopts:
5191 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5192 settings.profile_path, settings["CHOST"],
5193 trees[settings["ROOT"]]["vartree"].dbapi)
5195 elif "--help" in myopts:
5196 emergehelp.help(myaction, myopts, output.havecolor)
5199 if portage.wheelgid == portage.portage_gid:
5200 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5201 print " include the portage user as noted above, and then use group portage."
5203 if "--debug" in myopts:
5204 print "myaction", myaction
5205 print "myopts", myopts
5207 if not myaction and not myfiles and "--resume" not in myopts:
5208 emergehelp.help(myaction, myopts, output.havecolor)
5211 # check if root user is the current user for the actions where emerge needs this
5212 if portage.secpass < 2:
5213 # We've already allowed "--version" and "--help" above.
5214 if "--pretend" not in myopts and \
5215 myaction not in ("search","info"):
5216 need_superuser = not \
5217 ("--fetchonly" in myopts or \
5218 "--fetch-all-uri" in myopts or \
5219 myaction in ("metadata", "regen"))
5220 if portage.secpass < 1 or \
5223 access_desc = "superuser"
5225 access_desc = "portage group"
5226 # Always show portage_group_warning() when only portage group
5227 # access is required but the user is not in the portage group.
5228 from portage_data import portage_group_warning
5229 if "--ask" in myopts:
5230 myopts["--pretend"] = True
5232 print ("%s access would be required... " + \
5233 "adding --pretend to options.\n") % access_desc
5234 if portage.secpass < 1 and not need_superuser:
5235 portage_group_warning()
5237 sys.stderr.write(("emerge: %s access would be " + \
5238 "required.\n\n") % access_desc)
5239 if portage.secpass < 1 and not need_superuser:
5240 portage_group_warning()
5243 disable_emergelog = False
5244 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5246 disable_emergelog = True
5248 if myaction in ("search", "info"):
5249 disable_emergelog = True
5250 if disable_emergelog:
5251 """ Disable emergelog for everything except build or unmerge
5252 operations. This helps minimize parallel emerge.log entries that can
5253 confuse log parsers. We especially want it disabled during
5254 parallel-fetch, which uses --resume --fetchonly."""
5256 def emergelog(*pargs, **kargs):
5259 if not "--pretend" in myopts:
5260 emergelog(xterm_titles, "Started emerge on: "+\
5261 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5264 myelogstr=" ".join(myopts)
5266 myelogstr+=" "+myaction
5268 myelogstr+=" "+" ".join(myfiles)
5269 emergelog(xterm_titles, " *** emerge " + myelogstr)
5271 def emergeexitsig(signum, frame):
5272 signal.signal(signal.SIGINT, signal.SIG_IGN)
5273 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5274 portage_util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5275 sys.exit(100+signum)
5276 signal.signal(signal.SIGINT, emergeexitsig)
5277 signal.signal(signal.SIGTERM, emergeexitsig)
5280 """This gets out final log message in before we quit."""
5281 if "--pretend" not in myopts:
5282 emergelog(xterm_titles, " *** terminating.")
5283 if "notitles" not in settings.features:
5285 portage.atexit_register(emergeexit)
5287 if myaction in ("config", "metadata", "regen", "sync"):
5288 if "--pretend" in myopts:
5289 sys.stderr.write(("emerge: The '%s' action does " + \
5290 "not support '--pretend'.\n") % myaction)
5292 if "sync" == myaction:
5293 action_sync(settings, trees, mtimedb, myopts, myaction)
5294 elif "metadata" == myaction:
5295 action_metadata(settings, portdb, myopts)
5296 elif myaction=="regen":
5297 validate_ebuild_environment(trees)
5298 action_regen(settings, portdb)
5300 elif "config"==myaction:
5301 validate_ebuild_environment(trees)
5302 action_config(settings, trees, myopts, myfiles)
5305 elif "info"==myaction:
5306 action_info(settings, trees, myopts, myfiles)
5309 elif "search"==myaction:
5310 validate_ebuild_environment(trees)
5311 action_search(settings, portdb, trees["/"]["vartree"],
5312 myopts, myfiles, spinner)
5313 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5314 validate_ebuild_environment(trees)
5315 vartree = trees[settings["ROOT"]]["vartree"]
5316 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5318 if "--pretend" not in myopts:
5319 post_emerge(settings, mtimedb, 0)
5321 elif "depclean"==myaction:
5322 validate_ebuild_environment(trees)
5323 action_depclean(settings, trees, mtimedb["ldpath"],
5325 if "--pretend" not in myopts:
5326 post_emerge(settings, mtimedb, 0)
5327 # "update", "system", or just process files:
5329 validate_ebuild_environment(trees)
5330 action_build(settings, trees, mtimedb,
5331 myopts, myaction, myfiles, spinner)
5332 if "--pretend" not in myopts:
5333 post_emerge(settings, mtimedb, 0)
5335 if __name__ == "__main__":
5336 retval = emerge_main()