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 portage.emergehelp, portage.xpak, commands, errno, re, socket, time, types
37 from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
38 havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
39 xtermTitleReset, yellow
40 from portage.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 vardbapi.cpv_exists(mykey):
1134 pkgsettings.setcpv(mykey, mydb=mydbapi)
1135 forced_flags = set()
1136 forced_flags.update(pkgsettings.useforce)
1137 forced_flags.update(pkgsettings.usemask)
1138 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1139 iuses = set(filter_iuse_defaults(
1140 mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
1141 old_iuse = set(filter_iuse_defaults(
1142 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1143 if iuses.symmetric_difference(
1144 old_iuse).difference(forced_flags):
1146 elif old_iuse.intersection(old_use) != \
1147 iuses.intersection(myuse):
1150 if addme and merging == 1:
1151 mybigkey.append("merge")
1153 mybigkey.append("nomerge")
1154 jbigkey = tuple(mybigkey)
1157 metadata = dict(izip(self._mydbapi_keys,
1158 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1159 if merging == 0 and vardbapi.cpv_exists(mykey):
1160 metadata["USE"] = vardbapi.aux_get(mykey, ["USE"])[0]
1161 myuse = metadata["USE"].split()
1162 metadata["SLOT"] = vardbapi.aux_get(mykey, ["SLOT"])[0]
1163 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1164 existing_node = self._slot_node_map[myroot].get(
1166 slot_collision = False
1168 e_type, myroot, e_cpv, e_status = existing_node
1170 # The existing node can be reused.
1171 self._parent_child_digraph.add(existing_node, myparent)
1172 if rev_dep and myparent:
1173 ptype, proot, pkey, pstatus = myparent
1174 self.digraph.addnode(myparent, existing_node,
1177 self.digraph.addnode(existing_node, myparent,
1181 # A slot collision has occurred. Sometimes this coincides
1182 # with unresolvable blockers, so the slot collision will be
1183 # shown later if there are no unresolvable blockers.
1184 e_parents = self._parent_child_digraph.parent_nodes(
1188 myparents.append(myparent)
1189 self._slot_collision_info.append(
1190 ((jbigkey, myparents), (existing_node, e_parents)))
1191 self._slot_collision_nodes.add(jbigkey)
1192 slot_collision = True
1195 # Now add this node to the graph so that self.display()
1196 # can show use flags and --tree portage.output. This node is
1197 # only being partially added to the graph. It must not be
1198 # allowed to interfere with the other nodes that have been
1199 # added. Do not overwrite data for existing nodes in
1200 # self.pkg_node_map and self.mydbapi since that data will
1201 # be used for blocker validation.
1202 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1203 self.useFlags[myroot].setdefault(mykey, myuse)
1204 # Even though the graph is now invalid, continue to process
1205 # dependencies so that things like --fetchonly can still
1206 # function despite collisions.
1208 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1209 self._slot_node_map[myroot][slot_atom] = jbigkey
1210 self.pkg_node_map[myroot][mykey] = jbigkey
1211 self.useFlags[myroot][mykey] = myuse
1213 if rev_dep and myparent:
1214 self.digraph.addnode(myparent, jbigkey,
1217 self.digraph.addnode(jbigkey, myparent,
1220 # Do this even when addme is False (--onlydeps) so that the
1221 # parent/child relationship is always known in case
1222 # self._show_slot_collision_notice() needs to be called later.
1223 self._parent_child_digraph.add(jbigkey, myparent)
1225 """ This section determines whether we go deeper into dependencies or not.
1226 We want to go deeper on a few occasions:
1227 Installing package A, we need to make sure package A's deps are met.
1228 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1229 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1231 if "deep" not in self.myparams and not merging and \
1232 not ("--update" in self.myopts and arg and merging):
1234 elif "recurse" not in self.myparams:
1237 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1238 Pull from bintree if it's binary package, porttree if it's ebuild.
1239 Binpkg's can be either remote or local. """
1242 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1243 depvalues = mydbapi.aux_get(mykey, depkeys)
1244 for i in xrange(len(depkeys)):
1245 edepend[depkeys[i]] = depvalues[i]
1247 if mytype == "ebuild":
1248 if "--buildpkgonly" in self.myopts:
1249 edepend["RDEPEND"] = ""
1250 edepend["PDEPEND"] = ""
1251 if not (arg and "--onlydeps" in self.myopts and \
1252 mytype == "ebuild") and \
1253 self.myopts.get("--with-bdeps", "n") == "n" and \
1254 (mytype == "binary" or mybigkey[3] == "nomerge"):
1255 edepend["DEPEND"] = ""
1257 """ We have retrieve the dependency information, now we need to recursively
1258 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1260 mp = tuple(mybigkey)
1263 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1264 myuse=myuse, priority=DepPriority(buildtime=True),
1267 """RDEPEND is soft by definition. However, in order to ensure
1268 correct merge order, we make it a hard dependency. Otherwise, a
1269 build time dependency might not be usable due to it's run time
1270 dependencies not being installed yet.
1272 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1273 myuse=myuse, priority=DepPriority(runtime=True),
1276 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1277 # Post Depend -- Add to the list without a parent, as it depends
1278 # on a package being present AND must be built after that package.
1279 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1280 myuse=myuse, priority=DepPriority(), rev_deps=True,
1283 except ValueError, e:
1285 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1286 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1288 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1289 portage.writemsg("\n", noiselevel=-1)
1290 if mytype == "binary":
1292 "!!! This binary package cannot be installed: '%s'\n" % \
1293 mykey, noiselevel=-1)
1294 elif mytype == "ebuild":
1295 myebuild, mylocation = portdb.findname2(mykey)
1296 portage.writemsg("!!! This ebuild cannot be installed: " + \
1297 "'%s'\n" % myebuild, noiselevel=-1)
1298 portage.writemsg("!!! Please notify the package maintainer " + \
1299 "that atoms must be fully-qualified.\n", noiselevel=-1)
1303 def select_files(self,myfiles):
1304 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1306 myroot = self.target_root
1307 portdb = self.trees[myroot]["porttree"].dbapi
1308 bindb = self.trees[myroot]["bintree"].dbapi
1309 pkgsettings = self.pkgsettings[myroot]
1311 def visible(mylist):
1312 matches = portdb.gvisible(portdb.visible(mylist))
1313 return [x for x in mylist \
1314 if x in matches or not portdb.cpv_exists(x)]
1316 ext = os.path.splitext(x)[1]
1318 if not os.path.exists(x):
1320 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1321 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1322 elif os.path.exists(
1323 os.path.join(pkgsettings["PKGDIR"], x)):
1324 x = os.path.join(pkgsettings["PKGDIR"], x)
1326 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1327 print "!!! Please ensure the tbz2 exists as specified.\n"
1329 mytbz2=portage.xpak.tbz2(x)
1330 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1331 if os.path.realpath(x) != \
1332 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1333 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1335 if not self.create(["binary", myroot, mykey],
1336 None, "--onlydeps" not in self.myopts):
1337 return (0,myfavorites)
1338 elif not "--oneshot" in self.myopts:
1339 myfavorites.append(mykey)
1340 elif ext==".ebuild":
1341 x = os.path.realpath(x)
1342 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1343 ebuild_path = portdb.findname(mykey)
1345 if os.path.realpath(ebuild_path) != x:
1346 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1348 if mykey not in portdb.xmatch(
1349 "match-visible", portage.dep_getkey(mykey)):
1350 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1351 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1352 print colorize("BAD", "*** page for details.")
1353 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1356 raise portage.exception.PackageNotFound(
1357 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1358 if not self.create(["ebuild", myroot, mykey],
1359 None, "--onlydeps" not in self.myopts):
1360 return (0,myfavorites)
1361 elif not "--oneshot" in self.myopts:
1362 myfavorites.append(mykey)
1364 if not is_valid_package_atom(x):
1365 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1367 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1368 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1372 if "--usepkg" in self.myopts:
1373 mykey = portage.dep_expand(x, mydb=bindb,
1374 settings=pkgsettings)
1375 if (mykey and not mykey.startswith("null/")) or \
1376 "--usepkgonly" in self.myopts:
1377 arg_atoms.append((x, mykey))
1380 mykey = portage.dep_expand(x,
1381 mydb=portdb, settings=pkgsettings)
1382 arg_atoms.append((x, mykey))
1383 except ValueError, errpkgs:
1384 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1385 print "!!! one of the following fully-qualified ebuild names instead:\n"
1386 for i in errpkgs[0]:
1387 print " " + green(i)
1391 if "--update" in self.myopts:
1392 """Make sure all installed slots are updated when possible. Do this
1393 with --emptytree also, to ensure that all slots are remerged."""
1394 vardb = self.trees[self.target_root]["vartree"].dbapi
1396 for myarg, myatom in arg_atoms:
1397 greedy_atoms.append((myarg, myatom))
1399 for cpv in vardb.match(myatom):
1400 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1403 if "--usepkg" in self.myopts:
1404 mymatches = bindb.match(myatom)
1405 if "--usepkgonly" not in self.myopts:
1406 mymatches = visible(mymatches)
1407 best_pkg = portage.best(mymatches)
1409 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1410 best_pkgs.append(("binary", best_pkg, best_slot))
1411 if "--usepkgonly" not in self.myopts:
1412 best_pkg = portage.best(portdb.match(myatom))
1414 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1415 best_pkgs.append(("ebuild", best_pkg, best_slot))
1417 best_pkg = portage.best([x[1] for x in best_pkgs])
1418 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1419 best_slot = best_pkgs[0][2]
1420 myslots.add(best_slot)
1421 if len(myslots) > 1:
1422 for myslot in myslots:
1423 myslot_atom = "%s:%s" % \
1424 (portage.dep_getkey(myatom), myslot)
1426 if "--usepkgonly" not in self.myopts and \
1427 self.trees[self.target_root][
1428 "porttree"].dbapi.match(myslot_atom):
1430 elif "--usepkg" in self.myopts:
1431 mymatches = bindb.match(myslot_atom)
1432 if "--usepkgonly" not in self.myopts:
1433 mymatches = visible(mymatches)
1437 greedy_atoms.append((myarg, myslot_atom))
1438 arg_atoms = greedy_atoms
1440 """ These are used inside self.create() in order to ensure packages
1441 that happen to match arguments are not incorrectly marked as nomerge."""
1442 self.args_keys = [x[1] for x in arg_atoms]
1443 for myarg, myatom in arg_atoms:
1445 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1446 except portage.exception.MissingSignature, e:
1447 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1448 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1449 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1450 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1451 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1453 except portage.exception.InvalidSignature, e:
1454 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1455 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1456 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1457 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1458 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1460 except SystemExit, e:
1461 raise # Needed else can't exit
1462 except Exception, e:
1463 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1464 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1468 return (0,myfavorites)
1469 elif not "--oneshot" in self.myopts:
1470 mykey = portage.dep_getkey(myatom)
1471 if mykey not in myfavorites:
1472 myfavorites.append(mykey)
1475 if "--usepkgonly" in self.myopts:
1476 for xs in self.digraph.all_nodes():
1477 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1481 print "Missing binary for:",xs[2]
1483 if not self.validate_blockers():
1484 return False, myfavorites
1486 # We're true here unless we are missing binaries.
1487 return (not missing,myfavorites)
1489 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1490 myuse=None, raise_on_missing=False, priority=DepPriority(),
1491 rev_deps=False, parent_arg=None):
1492 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1493 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1494 myparent = the node whose depstring is being passed in
1495 arg = package was specified on the command line, merge even if it's already installed
1496 myuse = USE flags at present
1497 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1498 else continue trying.
1499 return 1 on success, 0 for failure
1502 portdb = self.trees[myroot]["porttree"].dbapi
1503 bindb = self.trees[myroot]["bintree"].dbapi
1504 vardb = self.trees[myroot]["vartree"].dbapi
1505 pkgsettings = self.pkgsettings[myroot]
1507 p_type, p_root, p_key, p_status = myparent
1509 if "--debug" in self.myopts:
1511 print "Parent: ",myparent
1512 print "Depstring:",depstring
1514 print "Reverse:", rev_deps
1515 print "Priority:", priority
1517 #processing dependencies
1518 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1519 dependencies are satisfiable. """
1521 if myparent and p_status == "nomerge":
1522 portage.dep._dep_check_strict = False
1523 mycheck = portage.dep_check(depstring, None,
1524 pkgsettings, myuse=myuse,
1525 use_binaries=("--usepkgonly" in self.myopts),
1526 myroot=myroot, trees=self.trees)
1528 portage.dep._dep_check_strict = True
1532 show_invalid_depstring_notice(myparent, depstring, mycheck[1])
1534 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1536 mymerge = mycheck[1]
1538 if not mymerge and arg and \
1539 portage.best_match_to_list(depstring, self.args_keys):
1540 # A provided package has been specified on the command line. The
1541 # package will not be merged and a warning will be displayed.
1542 self._pprovided_args.append(arg)
1545 # The parent is added after it's own dep_check call so that it
1546 # isn't allowed to satisfy a direct bootstrap dependency on itself
1547 # via an old-style virtual. This isn't a problem with new-style
1548 # virtuals, which are preferenced in dep_zapdeps by looking only at
1549 # the depstring, vdb, and available packages.
1551 p_type, p_root, p_key, p_status = myparent
1552 if p_status == "merge":
1553 # Update old-style virtuals if this package provides any.
1554 # These are needed for dep_virtual calls inside dep_check.
1555 self.pkgsettings[p_root].setinst(p_key,
1556 self.trees[p_root][self.pkg_tree_map[p_type]].dbapi)
1558 if "--debug" in self.myopts:
1559 print "Candidates:",mymerge
1563 selected_pkg = ["blocks", myroot, x[1:], None]
1565 #We are not processing a blocker but a normal dependency
1567 """In some cases, dep_check will return deps that shouldn't
1568 be proccessed any further, so they are identified and
1570 if "empty" not in self.myparams and \
1571 "deep" not in self.myparams and \
1572 not ("--update" in self.myopts and parent_arg) and \
1576 # List of acceptable packages, ordered by type preference.
1577 matched_packages = []
1578 myeb_matches = portdb.xmatch("match-visible", x)
1580 if "--usepkgonly" not in self.myopts:
1581 myeb = portage.best(myeb_matches)
1584 if "--usepkg" in self.myopts:
1585 # The next line assumes the binarytree has been populated.
1586 # XXX: Need to work out how we use the binary tree with roots.
1587 myeb_pkg_matches = bindb.match(x)
1588 if "--usepkgonly" not in self.myopts:
1589 # Remove any binary package entries that are masked in the portage tree (#55871)
1590 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1591 if pkg in myeb_matches or \
1592 not portdb.cpv_exists(pkg)]
1593 if myeb_pkg_matches:
1594 myeb_pkg = portage.best(myeb_pkg_matches)
1596 if myeb_pkg and "--newuse" in self.myopts:
1597 iuses = set(filter_iuse_defaults(
1598 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1599 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1601 if "--usepkgonly" not in self.myopts and myeb:
1604 pkgsettings.setcpv(myeb, mydb=mydb)
1606 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1607 now_use = pkgsettings["USE"].split()
1608 forced_flags = set()
1609 forced_flags.update(pkgsettings.useforce)
1610 forced_flags.update(pkgsettings.usemask)
1612 if "--usepkgonly" not in self.myopts and myeb:
1613 cur_iuse = set(filter_iuse_defaults(
1614 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1615 if iuses.symmetric_difference(
1616 cur_iuse).difference(forced_flags):
1618 elif iuses.intersection(old_use) != \
1619 cur_iuse.intersection(now_use):
1623 self.trees[myroot]["bintree"].dbapi.aux_get(
1624 myeb_pkg, ["USE"])[0].split()
1625 matched_packages.append(
1626 ["binary", myroot, myeb_pkg, binpkguseflags])
1628 if "--usepkgonly" not in self.myopts and myeb_matches:
1629 matched_packages.append(
1630 ["ebuild", myroot, myeb, None])
1632 if not matched_packages and \
1633 not (arg and "selective" not in self.myparams):
1634 """Fall back to the installed package database. This is a
1635 last resort because the metadata tends to diverge from that
1636 of the ebuild in the tree."""
1637 myeb_inst_matches = vardb.match(x)
1638 if "--usepkgonly" not in self.myopts:
1639 """ TODO: Improve masking check for installed and
1640 binary packages. bug #149816"""
1641 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1642 if not portdb.cpv_exists(pkg)]
1644 if myeb_inst_matches:
1645 myeb_inst = portage.best(myeb_inst_matches)
1647 binpkguseflags = vardb.aux_get(
1648 myeb_inst, ["USE"])[0].split()
1649 matched_packages.append(
1650 ["installed", myroot, myeb_inst, binpkguseflags])
1652 if not matched_packages:
1653 if raise_on_missing:
1660 xfrom = '(dependency required by '+ \
1661 green('"%s"' % myparent[2]) + \
1662 red(' [%s]' % myparent[0]) + ')'
1663 alleb = portdb.xmatch("match-all", x)
1665 if "--usepkgonly" not in self.myopts:
1666 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1667 print "!!! One of the following masked packages is required to complete your request:"
1670 mreasons = portage.getmaskingstatus(p,
1671 settings=pkgsettings, portdb=portdb)
1672 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1673 comment = portage.getmaskingreason(p,
1674 settings=pkgsettings, portdb=portdb)
1675 if comment and comment != oldcomment:
1677 oldcomment = comment
1679 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1680 print "refer to the Gentoo Handbook."
1682 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1683 print "!!! Either add a suitable binary package or compile from an ebuild."
1685 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1691 if "--debug" in self.myopts:
1692 for pkg in matched_packages:
1693 print (pkg[0] + ":").rjust(10), pkg[2]
1695 if len(matched_packages) > 1:
1696 bestmatch = portage.best(
1697 [pkg[2] for pkg in matched_packages])
1698 matched_packages = [pkg for pkg in matched_packages \
1699 if pkg[2] == bestmatch]
1701 # ordered by type preference ("ebuild" type is the last resort)
1702 selected_pkg = matched_packages[0]
1703 pkgtype, myroot, mycpv, myuse = selected_pkg
1704 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1705 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1706 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1707 existing_node = self._slot_node_map[myroot].get(
1710 e_type, myroot, e_cpv, e_status = existing_node
1711 if portage.match_from_list(x, [e_cpv]):
1712 # The existing node can be reused.
1713 selected_pkg = [e_type, myroot, e_cpv,
1714 self.useFlags[myroot][e_cpv]]
1717 #we are a dependency, so we want to be unconditionally added
1718 mypriority = priority.copy()
1720 mypriority.satisfied = True
1721 if not self.create(selected_pkg[0:3], myparent,
1722 myuse=selected_pkg[-1], priority=mypriority,
1723 rev_dep=rev_deps, arg=arg):
1726 #if mysource is not set, then we are a command-line dependency and should not be added
1727 #if --onlydeps is specified.
1728 if not self.create(selected_pkg[0:3], myparent,
1729 addme=("--onlydeps" not in self.myopts),
1730 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1733 if "--debug" in self.myopts:
1734 print "Exiting...",myparent
1737 def validate_blockers(self):
1738 """Remove any blockers from the digraph that do not match any of the
1739 packages within the graph. If necessary, create hard deps to ensure
1740 correct merge order such that mutually blocking packages are never
1741 installed simultaneously."""
1743 if "--buildpkgonly" in self.myopts or \
1744 "--nodeps" in self.myopts:
1748 for myroot in self.trees:
1750 modified_slots[myroot] = myslots
1751 final_db = self.mydbapi[myroot]
1752 slot_node_map = self._slot_node_map[myroot]
1753 for slot_atom, mynode in slot_node_map.iteritems():
1754 mytype, myroot, mycpv, mystatus = mynode
1755 if mystatus == "merge":
1756 myslots[slot_atom] = mycpv
1758 #if "deep" in self.myparams:
1760 # Pull in blockers from all installed packages that haven't already
1761 # been pulled into the depgraph. This is not enabled by default
1762 # due to the performance penalty that is incurred by all the
1763 # additional dep_check calls that are required.
1765 # Optimization hack for dep_check calls that minimizes the
1766 # available matches by replacing the portdb with a fakedbapi
1768 class FakePortageTree(object):
1769 def __init__(self, mydb):
1771 dep_check_trees = {}
1772 for myroot in self.trees:
1773 dep_check_trees[myroot] = self.trees[myroot].copy()
1774 dep_check_trees[myroot]["porttree"] = \
1775 FakePortageTree(self.mydbapi[myroot])
1777 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1778 for myroot in self.trees:
1779 pkg_node_map = self.pkg_node_map[myroot]
1780 vardb = self.trees[myroot]["vartree"].dbapi
1781 portdb = self.trees[myroot]["porttree"].dbapi
1782 pkgsettings = self.pkgsettings[myroot]
1783 final_db = self.mydbapi[myroot]
1784 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
1785 blocker_cache = BlockerCache(myroot, vardb)
1786 for pkg in cpv_all_installed:
1787 blocker_atoms = None
1788 matching_node = pkg_node_map.get(pkg, None)
1789 if matching_node and \
1790 matching_node[3] == "nomerge":
1792 # If this node has any blockers, create a "nomerge"
1793 # node for it so that they can be enforced.
1794 self.spinner.update()
1795 blocker_data = blocker_cache.get(pkg)
1797 blocker_atoms = blocker_data.atoms
1799 dep_vals = vardb.aux_get(pkg, dep_keys)
1800 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
1801 depstr = " ".join(dep_vals)
1802 # It is crucial to pass in final_db here in order to
1803 # optimize dep_check calls by eliminating atoms via
1804 # dep_wordreduce and dep_eval calls.
1806 portage.dep._dep_check_strict = False
1807 success, atoms = portage.dep_check(depstr,
1808 final_db, pkgsettings, myuse=myuse,
1809 trees=dep_check_trees, myroot=myroot)
1811 portage.dep._dep_check_strict = True
1813 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
1814 vardb.aux_get(pkg, ["SLOT"])[0])
1815 if slot_atom in modified_slots[myroot]:
1816 # This package is being replaced anyway, so
1817 # ignore invalid dependencies so as not to
1818 # annoy the user too much (otherwise they'd be
1819 # forced to manually unmerge it first).
1821 show_invalid_depstring_notice(
1822 ("installed", myroot, pkg, "nomerge"),
1825 blocker_atoms = [myatom for myatom in atoms \
1826 if myatom.startswith("!")]
1827 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
1828 blocker_cache[pkg] = \
1829 blocker_cache.BlockerData(counter, blocker_atoms)
1831 # Don't store this parent in pkg_node_map, because it's
1832 # not needed there and it might overwrite a "merge"
1833 # node with the same cpv.
1834 myparent = ("installed", myroot, pkg, "nomerge")
1835 for myatom in blocker_atoms:
1836 blocker = ("blocks", myroot, myatom[1:])
1838 self.blocker_parents.get(blocker, None)
1841 self.blocker_parents[blocker] = myparents
1842 myparents.add(myparent)
1843 blocker_cache.flush()
1846 for blocker in self.blocker_parents.keys():
1847 mytype, myroot, mydep = blocker
1848 initial_db = self.trees[myroot]["vartree"].dbapi
1849 final_db = self.mydbapi[myroot]
1850 blocked_initial = initial_db.match(mydep)
1851 blocked_final = final_db.match(mydep)
1852 if not blocked_initial and not blocked_final:
1853 del self.blocker_parents[blocker]
1855 blocked_slots_initial = {}
1856 blocked_slots_final = {}
1857 for cpv in blocked_initial:
1858 blocked_slots_initial[cpv] = \
1859 "%s:%s" % (portage.dep_getkey(cpv),
1860 initial_db.aux_get(cpv, ["SLOT"])[0])
1861 for cpv in blocked_final:
1862 blocked_slots_final[cpv] = \
1863 "%s:%s" % (portage.dep_getkey(cpv),
1864 final_db.aux_get(cpv, ["SLOT"])[0])
1865 blocked_slots_final_values = set(blocked_slots_final.itervalues())
1866 for parent in list(self.blocker_parents[blocker]):
1867 ptype, proot, pcpv, pstatus = parent
1868 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1869 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1870 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1871 parent_static = pslot_atom not in modified_slots[proot]
1872 unresolved_blocks = False
1873 depends_on_order = set()
1874 for cpv in blocked_initial:
1875 slot_atom = blocked_slots_initial[cpv]
1876 if slot_atom == pslot_atom:
1877 # The parent blocks an initial package in the same
1878 # slot as itself. The merge/nomerge status of neither
1879 # node matters. In any case, this particular block is
1880 # automatically resolved.
1882 if parent_static and \
1883 slot_atom not in modified_slots[myroot]:
1884 # This blocker will be handled the next time that a
1885 # merge of either package is triggered.
1887 if pstatus == "merge" and \
1888 slot_atom not in blocked_slots_final_values:
1889 upgrade_matches = final_db.match(slot_atom)
1891 # Apparently an upgrade may be able to invalidate
1894 self.pkg_node_map[proot][upgrade_matches[0]]
1895 depends_on_order.add(upgrade_node)
1897 # None of the above blocker resolutions techniques apply,
1898 # so apparently this one is unresolvable.
1899 unresolved_blocks = True
1900 for cpv in blocked_final:
1901 slot_atom = blocked_slots_final[cpv]
1902 if slot_atom == pslot_atom:
1903 # The parent blocks itself, so the merge order does not
1904 # need to be enforced.
1906 if parent_static and \
1907 slot_atom not in modified_slots[myroot]:
1908 # This blocker will be handled the next time that a
1909 # merge of either package is triggered.
1911 # None of the above blocker resolutions techniques apply,
1912 # so apparently this one is unresolvable.
1913 unresolved_blocks = True
1914 if not unresolved_blocks and depends_on_order:
1915 for node in depends_on_order:
1916 # Enforce correct merge order with a hard dep.
1917 self.digraph.addnode(node, parent,
1918 priority=DepPriority(buildtime=True))
1919 # Count references to this blocker so that it can be
1920 # invalidated after nodes referencing it have been
1922 self.blocker_digraph.addnode(node, blocker)
1923 if not unresolved_blocks and not depends_on_order:
1924 self.blocker_parents[blocker].remove(parent)
1925 if not self.blocker_parents[blocker]:
1926 del self.blocker_parents[blocker]
1927 # Validate blockers that depend on merge order.
1928 if not self.blocker_digraph.empty():
1930 if self._slot_collision_info:
1931 # The user is only notified of a slot collision if there are no
1932 # unresolvable blocks.
1933 for x in self.altlist():
1934 if x[0] == "blocks":
1936 self._show_slot_collision_notice(self._slot_collision_info[0])
1937 if not self._accept_collisions():
1941 def _accept_collisions(self):
1943 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
1944 if x in self.myopts:
1949 def altlist(self, reversed=False):
1950 if reversed in self._altlist_cache:
1951 return self._altlist_cache[reversed][:]
1952 mygraph=self.digraph.copy()
1953 myblockers = self.blocker_digraph.copy()
1955 circular_blocks = False
1959 get_nodes = mygraph.root_nodes
1961 get_nodes = mygraph.leaf_nodes
1962 for cpv, node in self.pkg_node_map["/"].iteritems():
1963 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
1964 asap_nodes.append(node)
1966 ignore_priority_range = [None]
1967 ignore_priority_range.extend(
1968 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
1969 while not mygraph.empty():
1970 ignore_priority = None
1973 """ASAP nodes are merged before their soft deps."""
1974 for node in asap_nodes:
1975 if not mygraph.contains(node):
1976 asap_nodes.remove(node)
1978 if not mygraph.child_nodes(node,
1979 ignore_priority=DepPriority.SOFT):
1981 asap_nodes.remove(node)
1984 for ignore_priority in ignore_priority_range:
1985 nodes = get_nodes(ignore_priority=ignore_priority)
1988 selected_nodes = None
1990 if ignore_priority <= DepPriority.SOFT:
1991 if ignore_priority is None and not reversed:
1992 # Greedily pop all of these nodes since no relationship
1993 # has been ignored. This optimization destroys --tree
1994 # output, so it's disabled in reversed mode.
1995 selected_nodes = nodes
1997 # Only pop one node for optimal merge order.
1998 selected_nodes = [nodes[0]]
2000 """Recursively gather a group of nodes that RDEPEND on
2001 eachother. This ensures that they are merged as a group
2002 and get their RDEPENDs satisfied as soon as possible."""
2003 def gather_deps(mergeable_nodes, selected_nodes, node):
2004 if node in selected_nodes:
2006 if node not in mergeable_nodes:
2008 selected_nodes.add(node)
2009 for child in mygraph.child_nodes(node,
2010 ignore_priority=DepPriority.SOFT):
2012 mergeable_nodes, selected_nodes, child):
2015 mergeable_nodes = set(nodes)
2017 selected_nodes = set()
2019 mergeable_nodes, selected_nodes, node):
2022 selected_nodes = None
2024 if not selected_nodes:
2025 if not myblockers.is_empty():
2026 """A blocker couldn't be circumnavigated while keeping all
2027 dependencies satisfied. The user will have to resolve this
2028 manually. This is a panic condition and thus the order
2029 doesn't really matter, so just pop a random node in order
2030 to avoid a circular dependency panic if possible."""
2031 if not circular_blocks:
2032 circular_blocks = True
2033 blocker_deps = myblockers.leaf_nodes()
2035 selected_nodes = [blocker_deps.pop()]
2037 if not selected_nodes:
2039 """The circular deps ouput should have less noise when
2040 altlist is not in reversed mode."""
2042 print "!!! Error: circular dependencies:"
2044 mygraph.debug_print()
2047 for node in selected_nodes:
2048 retlist.append(list(node))
2049 mygraph.remove(node)
2050 if not reversed and not circular_blocks and myblockers.contains(node):
2051 """This node may have invalidated one or more blockers."""
2052 myblockers.remove(node)
2053 for blocker in myblockers.root_nodes():
2054 if not myblockers.child_nodes(blocker):
2055 myblockers.remove(blocker)
2056 del self.blocker_parents[blocker]
2059 """Blocker validation does not work with reverse mode,
2060 so self.altlist() should first be called with reverse disabled
2061 so that blockers are properly validated."""
2062 self.blocker_digraph = myblockers
2064 """ Add any unresolved blocks so that they can be displayed."""
2065 for blocker in self.blocker_parents:
2066 retlist.append(list(blocker))
2067 self._altlist_cache[reversed] = retlist[:]
2070 def xcreate(self,mode="system"):
2071 vardb = self.trees[self.target_root]["vartree"].dbapi
2072 portdb = self.trees[self.target_root]["porttree"].dbapi
2073 bindb = self.trees[self.target_root]["bintree"].dbapi
2074 def visible(mylist):
2075 matches = portdb.gvisible(portdb.visible(mylist))
2076 return [x for x in mylist \
2077 if x in matches or not portdb.cpv_exists(x)]
2078 world_problems = False
2080 mylist = getlist(self.settings, "system")
2083 worldlist = getlist(self.settings, "world")
2084 sysdict = genericdict(getlist(self.settings, "system"))
2085 worlddict=genericdict(worldlist)
2087 for x in worlddict.keys():
2088 if not portage.isvalidatom(x):
2089 world_problems = True
2090 elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
2091 world_problems = True
2093 sysdict[x]=worlddict[x]
2095 mylist = sysdict.keys()
2099 mykey = portage.dep_getkey(atom)
2101 newlist.append(atom)
2102 """Make sure all installed slots are updated when possible.
2103 Do this with --emptytree also, to ensure that all slots are
2106 for cpv in vardb.match(mykey):
2107 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2110 if "--usepkg" in self.myopts:
2111 mymatches = bindb.match(atom)
2112 if "--usepkgonly" not in self.myopts:
2113 mymatches = visible(mymatches)
2114 best_pkg = portage.best(mymatches)
2116 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2117 best_pkgs.append(("binary", best_pkg, best_slot))
2118 if "--usepkgonly" not in self.myopts:
2119 best_pkg = portage.best(portdb.match(atom))
2121 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2122 best_pkgs.append(("ebuild", best_pkg, best_slot))
2124 best_pkg = portage.best([x[1] for x in best_pkgs])
2125 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2126 best_slot = best_pkgs[0][2]
2127 myslots.add(best_slot)
2128 if len(myslots) > 1:
2129 for myslot in myslots:
2130 myslot_atom = "%s:%s" % (mykey, myslot)
2132 if "--usepkgonly" not in self.myopts and \
2133 self.trees[self.target_root][
2134 "porttree"].dbapi.match(myslot_atom):
2136 elif "--usepkg" in self.myopts:
2137 mymatches = bindb.match(myslot_atom)
2138 if "--usepkgonly" not in self.myopts:
2139 mymatches = visible(mymatches)
2143 newlist.append(myslot_atom)
2147 for mydep in mylist:
2149 if not self.select_dep(
2150 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2151 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2154 missing_atoms.append(mydep)
2156 if not self.validate_blockers():
2160 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2161 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2164 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2165 " Ebuilds for the following packages are either all"
2166 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2167 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2171 def display(self,mylist,verbosity=None):
2172 if verbosity is None:
2173 verbosity = ("--quiet" in self.myopts and 1 or \
2174 "--verbose" in self.myopts and 3 or 2)
2178 counters = PackageCounters()
2180 if verbosity == 1 and "--verbose" not in self.myopts:
2181 def create_use_string(*args):
2184 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2186 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2187 alphabetical=("--alphabetical" in self.myopts)):
2195 cur_iuse = set(cur_iuse)
2196 enabled_flags = cur_iuse.intersection(cur_use)
2197 removed_iuse = set(old_iuse).difference(cur_iuse)
2198 any_iuse = cur_iuse.union(old_iuse)
2199 any_iuse = list(any_iuse)
2201 for flag in any_iuse:
2204 if flag in enabled_flags:
2206 if is_new or flag in old_use and all_flags:
2207 flag_str = red(flag)
2208 elif flag not in old_iuse:
2209 flag_str = yellow(flag) + "%*"
2210 elif flag not in old_use:
2211 flag_str = green(flag) + "*"
2212 elif flag in removed_iuse:
2214 flag_str = yellow("-" + flag) + "%"
2217 flag_str = "(" + flag_str + ")"
2218 removed.append(flag_str)
2221 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2222 flag_str = blue("-" + flag)
2223 elif flag not in old_iuse:
2224 flag_str = yellow("-" + flag)
2225 if flag not in iuse_forced:
2227 elif flag in old_use:
2228 flag_str = green("-" + flag) + "*"
2230 if flag in iuse_forced:
2231 flag_str = "(" + flag_str + ")"
2233 enabled.append(flag_str)
2235 disabled.append(flag_str)
2238 ret = " ".join(enabled)
2240 ret = " ".join(enabled + disabled + removed)
2242 ret = '%s="%s" ' % (name, ret)
2246 # FIXME: account for the possibility of different overlays in
2247 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2248 overlays = self.settings["PORTDIR_OVERLAY"].split()
2249 overlays_real = [os.path.realpath(t) \
2250 for t in self.settings["PORTDIR_OVERLAY"].split()]
2257 if "blocks" == x[0]:
2259 graph_key = tuple(x)
2260 if "--tree" in self.myopts:
2261 depth = len(tree_nodes)
2262 while depth and graph_key not in \
2263 self.digraph.child_nodes(tree_nodes[depth-1]):
2265 tree_nodes = tree_nodes[:depth]
2266 tree_nodes.append(graph_key)
2267 node_depth[graph_key] = depth
2269 last_merge_depth = 0
2270 for i in xrange(len(mylist)-1,-1,-1):
2271 if "blocks" == mylist[i][0]:
2273 graph_key = tuple(mylist[i])
2274 if mylist[i][-1] != "nomerge":
2275 last_merge_depth = node_depth[graph_key]
2277 if node_depth[graph_key] >= last_merge_depth or \
2278 i < len(mylist) - 1 and \
2279 node_depth[graph_key] >= node_depth[tuple(mylist[i+1])]:
2281 del node_depth[graph_key]
2284 display_overlays=False
2285 # files to fetch list - avoids counting a same file twice
2286 # in size display (verbose mode)
2292 portdb = self.trees[myroot]["porttree"].dbapi
2293 bindb = self.trees[myroot]["bintree"].dbapi
2294 vardb = self.trees[myroot]["vartree"].dbapi
2295 vartree = self.trees[myroot]["vartree"]
2296 pkgsettings = self.pkgsettings[myroot]
2301 addl=""+red("B")+" "+fetch+" "
2302 counters.blocks += 1
2303 resolved = portage.key_expand(
2304 pkg_key, mydb=vardb, settings=pkgsettings)
2305 if "--columns" in self.myopts and "--quiet" in self.myopts:
2306 print addl,red(resolved),
2308 print "["+x[0]+" "+addl+"]",red(resolved),
2309 block_parents = self.blocker_parents[tuple(x)]
2310 block_parents = set([pnode[2] for pnode in block_parents])
2311 block_parents = ", ".join(block_parents)
2313 print bad("(\"%s\" is blocking %s)") % \
2314 (pkg_key, block_parents)
2316 print bad("(is blocking %s)") % block_parents
2318 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2319 binary_package = True
2320 if "ebuild" == pkg_type:
2321 if "merge" == x[3] or \
2322 not vartree.dbapi.cpv_exists(pkg_key):
2323 """An ebuild "merge" node or a --onlydeps "nomerge"
2325 binary_package = False
2326 pkgsettings.setcpv(pkg_key, mydb=portdb)
2327 if pkg_key not in self.useFlags[myroot]:
2328 self.useFlags[myroot][pkg_key] = \
2329 pkgsettings["USE"].split()
2331 # An ebuild "nomerge" node, so USE come from the vardb.
2332 mydbapi = vartree.dbapi
2333 if pkg_key not in self.useFlags[myroot]:
2334 """If this is a --resume then the USE flags need to be
2335 fetched from the appropriate locations here."""
2336 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2337 pkg_key, ["USE"])[0].split()
2339 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2340 "fetch" in portdb.aux_get(
2341 x[2], ["RESTRICT"])[0].split():
2343 counters.restrict_fetch += 1
2344 if portdb.fetch_check(
2345 pkg_key, self.useFlags[myroot][pkg_key]):
2347 counters.restrict_fetch_satisfied += 1
2349 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2350 #param is used for -u, where you still *do* want to see when something is being upgraded.
2352 if vardb.cpv_exists(pkg_key):
2353 addl=" "+yellow("R")+fetch+" "
2354 if x[3] != "nomerge":
2355 counters.reinst += 1
2356 elif vardb.match(portage.dep_getkey(pkg_key)):
2357 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2358 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2359 portage.pkgsplit(x[2])[0])
2360 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2361 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2363 myoldbest=portage.best(myinslotlist)
2365 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2367 addl+=turquoise("U")+blue("D")
2368 counters.downgrades += 1
2371 addl+=turquoise("U")+" "
2372 counters.upgrades += 1
2374 # New slot, mark it new.
2375 addl=" "+green("NS")+fetch+" "
2376 counters.newslot += 1
2378 if "--changelog" in self.myopts:
2379 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2380 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2381 inst_matches = vardb.match(slot_atom)
2383 changelogs.extend(self.calc_changelog(
2384 portdb.findname(pkg_key),
2385 inst_matches[0], pkg_key))
2387 addl=" "+green("N")+" "+fetch+" "
2392 if pkg_key in self.useFlags[myroot]:
2394 cur_iuse = list(filter_iuse_defaults(
2395 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2397 forced_flags = set()
2398 if not binary_package:
2399 forced_flags.update(pkgsettings.useforce)
2400 forced_flags.update(pkgsettings.usemask)
2402 cur_iuse = portage.unique_array(cur_iuse)
2404 cur_use = self.useFlags[myroot][pkg_key]
2405 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2411 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2412 old_iuse, old_use = \
2413 self.trees[x[1]]["vartree"].dbapi.aux_get(
2414 pkg, ["IUSE", "USE"])
2415 old_iuse = list(set(
2416 filter_iuse_defaults(old_iuse.split())))
2418 old_use = old_use.split()
2425 old_use = [flag for flag in old_use if flag in old_iuse]
2427 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2429 use_expand.reverse()
2430 use_expand_hidden = \
2431 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2433 def map_to_use_expand(myvals, forcedFlags=False):
2436 for exp in use_expand:
2439 for val in myvals[:]:
2440 if val.startswith(exp.lower()+"_"):
2441 if val in forced_flags:
2442 forced[exp].add(val[len(exp)+1:])
2443 ret[exp].append(val[len(exp)+1:])
2446 forced["USE"] = [val for val in myvals \
2447 if val in forced_flags]
2448 for exp in use_expand_hidden:
2455 cur_iuse_map, iuse_forced = \
2456 map_to_use_expand(cur_iuse, forcedFlags=True)
2457 cur_use_map = map_to_use_expand(cur_use)
2458 old_iuse_map = map_to_use_expand(old_iuse)
2459 old_use_map = map_to_use_expand(old_use)
2462 use_expand.insert(0, "USE")
2464 for key in use_expand:
2465 if key in use_expand_hidden:
2467 verboseadd += create_use_string(key.upper(),
2468 cur_iuse_map[key], iuse_forced[key],
2469 cur_use_map[key], old_iuse_map[key],
2470 old_use_map[key], is_new)
2475 if x[0] == "ebuild" and x[-1]!="nomerge":
2476 myfilesdict = portdb.getfetchsizes(
2477 pkg_key, useflags=self.useFlags[myroot][pkg_key],
2479 if myfilesdict is None:
2480 myfilesdict="[empty/missing/bad digest]"
2482 for myfetchfile in myfilesdict.keys():
2483 if myfetchfile not in myfetchlist:
2484 mysize+=myfilesdict[myfetchfile]
2485 myfetchlist.append(myfetchfile)
2486 counters.totalsize += mysize
2487 verboseadd+=format_size(mysize)+" "
2490 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2491 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2492 file_name = portdb.findname(pkg_key)
2493 if file_name: # It might not exist in the tree
2494 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2495 if (overlays_real.count(dir_name)>0):
2496 verboseadd+=teal("["+str(overlays_real.index(
2497 os.path.normpath(dir_name))+1)+"]")+" "
2498 display_overlays=True
2500 verboseadd += "[No ebuild?]"
2502 xs=portage.pkgsplit(x[2])
2509 if "COLUMNWIDTH" in self.settings:
2511 mywidth = int(self.settings["COLUMNWIDTH"])
2512 except ValueError, e:
2513 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2515 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2516 self.settings["COLUMNWIDTH"], noiselevel=-1)
2521 indent = " " * node_depth[tuple(x)]
2524 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2525 if myoldbest[-3:]=="-r0":
2526 myoldbest=myoldbest[:-3]
2527 myoldbest=blue("["+myoldbest+"]")
2532 if "--columns" in self.myopts:
2533 if "--quiet" in self.myopts:
2534 myprint=addl+" "+indent+darkgreen(xs[0])
2535 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2536 myprint=myprint+myoldbest
2537 myprint=myprint+darkgreen("to "+x[1])
2539 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2540 if (newlp-nc_len(myprint)) > 0:
2541 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2542 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2543 if (oldlp-nc_len(myprint)) > 0:
2544 myprint=myprint+" "*(oldlp-nc_len(myprint))
2545 myprint=myprint+myoldbest
2546 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2548 if x[3] == "nomerge":
2549 myprint = darkblue("[nomerge ] ")
2551 myprint = "[" + pkg_type + " " + addl + "] "
2552 myprint += indent + darkgreen(pkg_key) + " " + \
2553 myoldbest + darkgreen("to " + myroot) + " " + \
2556 if "--columns" in self.myopts:
2557 if "--quiet" in self.myopts:
2558 myprint=addl+" "+indent+darkgreen(xs[0])
2559 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2560 myprint=myprint+myoldbest
2562 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2563 if (newlp-nc_len(myprint)) > 0:
2564 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2565 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2566 if (oldlp-nc_len(myprint)) > 0:
2567 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2568 myprint=myprint+myoldbest+" "+verboseadd
2571 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2573 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2576 mysplit = portage.pkgsplit(x[2])
2577 if "--tree" not in self.myopts and mysplit and \
2578 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2581 if mysplit[2] == "r0":
2582 myversion = mysplit[1]
2584 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2586 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2587 if mylist.index(x) < len(mylist) - 1 and \
2588 "livecvsportage" not in self.settings.features:
2589 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2590 p.append(colorize("WARN", " then resume the merge."))
2600 if overlays and display_overlays:
2601 print "Portage overlays:"
2605 print " "+teal("["+str(y)+"]"),x
2607 if "--changelog" in self.myopts:
2609 for revision,text in changelogs:
2610 print bold('*'+revision)
2611 sys.stdout.write(text)
2613 if self._pprovided_args:
2615 msg.append(bad("\nWARNING: "))
2616 if len(self._pprovided_args) > 1:
2617 msg.append("Requested packages will not be " + \
2618 "merged because they are listed in\n")
2620 msg.append("A requested package will not be " + \
2621 "merged because it is listed in\n")
2622 msg.append(" package.provided:\n\n")
2623 for arg in self._pprovided_args:
2624 msg.append(" " + arg + "\n")
2626 sys.stderr.write("".join(msg))
2628 def calc_changelog(self,ebuildpath,current,next):
2629 current = '-'.join(portage.catpkgsplit(current)[1:])
2630 if current.endswith('-r0'): current = current[:-3]
2631 next = '-'.join(portage.catpkgsplit(next)[1:])
2632 if next.endswith('-r0'): next = next[:-3]
2633 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2635 changelog = open(changelogpath).read()
2636 except SystemExit, e:
2637 raise # Needed else can't exit
2640 divisions = self.find_changelog_tags(changelog)
2641 #print 'XX from',current,'to',next
2642 #for div,text in divisions: print 'XX',div
2643 # skip entries for all revisions above the one we are about to emerge
2644 for i in range(len(divisions)):
2645 if divisions[i][0]==next:
2646 divisions = divisions[i:]
2648 # find out how many entries we are going to display
2649 for i in range(len(divisions)):
2650 if divisions[i][0]==current:
2651 divisions = divisions[:i]
2654 # couldnt find the current revision in the list. display nothing
2658 def find_changelog_tags(self,changelog):
2662 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2664 if release is not None:
2665 divs.append((release,changelog))
2667 if release is not None:
2668 divs.append((release,changelog[:match.start()]))
2669 changelog = changelog[match.end():]
2670 release = match.group(1)
2671 if release.endswith('.ebuild'):
2672 release = release[:-7]
2673 if release.endswith('-r0'):
2674 release = release[:-3]
2677 return self.outdatedpackages
2679 class PackageCounters(object):
2689 self.restrict_fetch = 0
2690 self.restrict_fetch_satisfied = 0
2693 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2696 myoutput.append("Total: %s package" % total_installs)
2697 if total_installs != 1:
2698 myoutput.append("s")
2699 if total_installs != 0:
2700 myoutput.append(" (")
2701 if self.upgrades > 0:
2702 details.append("%s upgrade" % self.upgrades)
2703 if self.upgrades > 1:
2705 if self.downgrades > 0:
2706 details.append("%s downgrade" % self.downgrades)
2707 if self.downgrades > 1:
2710 details.append("%s new" % self.new)
2711 if self.newslot > 0:
2712 details.append("%s in new slot" % self.newslot)
2713 if self.newslot > 1:
2716 details.append("%s reinstall" % self.reinst)
2720 details.append("%s block" % self.blocks)
2723 myoutput.append(", ".join(details))
2724 if total_installs != 0:
2725 myoutput.append(")")
2726 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2727 if self.restrict_fetch:
2728 myoutput.append("\nFetch Restriction: %s package" % \
2729 self.restrict_fetch)
2730 if self.restrict_fetch > 1:
2731 myoutput.append("s")
2732 if self.restrict_fetch_satisfied < self.restrict_fetch:
2733 myoutput.append(bad(" (%s unsatisfied)") % \
2734 (self.restrict_fetch - self.restrict_fetch_satisfied))
2735 return "".join(myoutput)
2737 class MergeTask(object):
2739 def __init__(self, settings, trees, myopts):
2740 self.settings = settings
2741 self.target_root = settings["ROOT"]
2743 self.myopts = myopts
2745 if settings.get("PORTAGE_DEBUG", "") == "1":
2747 self.pkgsettings = {}
2748 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2749 if self.target_root != "/":
2750 self.pkgsettings["/"] = \
2751 portage.config(clone=trees["/"]["vartree"].settings)
2753 def merge(self, mylist, favorites, mtimedb):
2756 ldpath_mtimes = mtimedb["ldpath"]
2757 xterm_titles = "notitles" not in self.settings.features
2759 #check for blocking dependencies
2760 if "--fetchonly" not in self.myopts and \
2761 "--buildpkgonly" not in self.myopts:
2764 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2765 print "!!! the two packages cannot be installed on the same system together."
2766 print "!!! Please use 'emerge --pretend' to determine blockers."
2767 if "--quiet" not in self.myopts:
2768 show_blocker_docs_link()
2769 if "--pretend" not in self.myopts:
2771 del mtimedb["resume"]
2776 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
2777 mysysdict = genericdict(getlist(self.settings, "system"))
2778 if "--resume" in self.myopts:
2780 print colorize("GOOD", "*** Resuming merge...")
2781 emergelog(xterm_titles, " *** Resuming merge...")
2782 mymergelist=mtimedb["resume"]["mergelist"][:]
2783 if "--skipfirst" in self.myopts and mymergelist:
2784 del mtimedb["resume"]["mergelist"][0]
2787 validate_merge_list(self.trees, mymergelist)
2789 myfavs = portage.grabfile(
2790 os.path.join(self.target_root, portage.WORLD_FILE))
2791 myfavdict=genericdict(myfavs)
2792 for x in range(len(mylist)):
2793 if mylist[x][3]!="nomerge":
2794 # Add to the mergelist
2795 mymergelist.append(mylist[x])
2797 myfavkey=portage.cpv_getkey(mylist[x][2])
2798 if "--onlydeps" in self.myopts:
2800 # Add to the world file. Since we won't be able to later.
2801 if "--fetchonly" not in self.myopts and \
2802 myfavkey in favorites:
2803 #don't record if already in system profile or already recorded
2804 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
2805 #we don't have a favorites entry for this package yet; add one
2806 myfavdict[myfavkey]=myfavkey
2807 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
2808 if not ("--fetchonly" in self.myopts or \
2809 "--fetch-all-uri" in self.myopts or \
2810 "--pretend" in self.myopts):
2811 portage.write_atomic(
2812 os.path.join(self.target_root, portage.WORLD_FILE),
2813 "\n".join(myfavdict.values()))
2815 mtimedb["resume"]["mergelist"]=mymergelist[:]
2818 myfeat = self.settings.features[:]
2819 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
2821 if "parallel-fetch" in myfeat and \
2822 not ("--pretend" in self.myopts or \
2823 "--fetch-all-uri" in self.myopts or \
2824 "--fetchonly" in self.myopts):
2825 if "distlocks" not in myfeat:
2827 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
2828 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
2830 elif len(mymergelist) > 1:
2831 print ">>> starting parallel fetching"
2832 fetch_log = "/var/log/emerge-fetch.log"
2833 logfile = open(fetch_log, "w")
2834 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
2835 portage.util.apply_secpass_permissions(fetch_log,
2836 uid=portage.portage_uid, gid=portage.portage_gid,
2838 fetch_env = os.environ.copy()
2839 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
2840 fetch_env["PORTAGE_NICENESS"] = "0"
2841 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
2842 for myopt, myarg in self.myopts.iteritems():
2843 if myopt not in bad_resume_opts:
2845 fetch_args.append(myopt)
2847 fetch_args.append(myopt +"="+ myarg)
2848 portage.process.spawn(fetch_args, env=fetch_env,
2849 fd_pipes=fd_pipes, returnpid=True)
2850 logfile.close() # belongs to the spawned process
2853 for x in mymergelist:
2858 portdb = self.trees[myroot]["porttree"].dbapi
2859 bindb = self.trees[myroot]["bintree"].dbapi
2860 vartree = self.trees[myroot]["vartree"]
2861 pkgsettings = self.pkgsettings[myroot]
2864 y = portdb.findname(pkg_key)
2865 if "--pretend" not in self.myopts:
2866 print "\n>>> Emerging (" + \
2867 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2868 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
2869 colorize("GOOD", x[pkgindex]) + " to " + x[1]
2870 emergelog(xterm_titles, " >>> emerge ("+\
2871 str(mergecount)+" of "+str(len(mymergelist))+\
2872 ") "+x[pkgindex]+" to "+x[1])
2874 pkgsettings["EMERGE_FROM"] = x[0]
2875 pkgsettings.backup_changes("EMERGE_FROM")
2878 #buildsyspkg: Check if we need to _force_ binary package creation
2879 issyspkg = ("buildsyspkg" in myfeat) \
2880 and x[0] != "blocks" \
2881 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
2882 and "--buildpkg" not in self.myopts
2883 if x[0] in ["ebuild","blocks"]:
2884 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
2885 raise Exception, "Merging a blocker"
2886 elif "--fetchonly" in self.myopts or \
2887 "--fetch-all-uri" in self.myopts:
2888 if "--fetch-all-uri" in self.myopts:
2889 retval = portage.doebuild(y, "fetch", myroot,
2890 pkgsettings, self.edebug,
2891 "--pretend" in self.myopts, fetchonly=1,
2892 fetchall=1, mydbapi=portdb, tree="porttree")
2894 retval = portage.doebuild(y, "fetch", myroot,
2895 pkgsettings, self.edebug,
2896 "--pretend" in self.myopts, fetchonly=1,
2897 mydbapi=portdb, tree="porttree")
2898 if (retval is None) or retval:
2900 print "!!! Fetch for",y,"failed, continuing..."
2902 failed_fetches.append(pkg_key)
2905 portage.doebuild_environment(y, "setup", myroot,
2906 pkgsettings, self.edebug, 1, portdb)
2907 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
2908 portage.util.ensure_dirs(os.path.dirname(catdir),
2909 uid=portage.portage_uid, gid=portage.portage_gid,
2911 builddir_lock = None
2914 catdir_lock = portage.locks.lockdir(catdir)
2915 portage.util.ensure_dirs(catdir,
2916 uid=portage.portage_uid, gid=portage.portage_gid,
2918 builddir_lock = portage.locks.lockdir(
2919 pkgsettings["PORTAGE_BUILDDIR"])
2921 portage.locks.unlockdir(catdir_lock)
2924 msg = " === (%s of %s) Cleaning (%s::%s)" % \
2925 (mergecount, len(mymergelist), pkg_key, y)
2926 short_msg = "emerge: (%s of %s) %s Clean" % \
2927 (mergecount, len(mymergelist), pkg_key)
2928 emergelog(xterm_titles, msg, short_msg=short_msg)
2929 retval = portage.doebuild(y, "clean", myroot,
2930 pkgsettings, self.edebug, cleanup=1,
2931 mydbapi=portdb, tree="porttree")
2932 if retval != os.EX_OK:
2934 if "--buildpkg" in self.myopts or issyspkg:
2936 print ">>> This is a system package, " + \
2937 "let's pack a rescue tarball."
2938 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
2939 (mergecount, len(mymergelist), pkg_key, y)
2940 short_msg = "emerge: (%s of %s) %s Compile" % \
2941 (mergecount, len(mymergelist), pkg_key)
2942 emergelog(xterm_titles, msg, short_msg=short_msg)
2943 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
2944 retval = portage.doebuild(y, "package", myroot,
2945 pkgsettings, self.edebug, mydbapi=portdb,
2947 if retval != os.EX_OK:
2949 if "--buildpkgonly" not in self.myopts:
2950 bintree = self.trees[myroot]["bintree"]
2951 bintree.inject(pkg_key)
2952 mytbz2 = bintree.getname(pkg_key)
2953 msg = " === (%s of %s) Merging (%s::%s)" % \
2954 (mergecount, len(mymergelist), pkg_key, y)
2955 short_msg = "emerge: (%s of %s) %s Merge" % \
2956 (mergecount, len(mymergelist), pkg_key)
2957 emergelog(xterm_titles, msg, short_msg=short_msg)
2958 retval = portage.merge(pkgsettings["CATEGORY"],
2959 pkgsettings["PF"], pkgsettings["D"],
2960 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
2961 "build-info"), myroot, pkgsettings,
2962 myebuild=pkgsettings["EBUILD"],
2963 mytree="porttree", mydbapi=portdb,
2964 vartree=vartree, prev_mtimes=ldpath_mtimes)
2965 if retval != os.EX_OK:
2967 elif "noclean" not in pkgsettings.features:
2968 portage.doebuild(y, "clean", myroot,
2969 pkgsettings, self.edebug, mydbapi=portdb,
2972 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
2973 (mergecount, len(mymergelist), pkg_key, y)
2974 short_msg = "emerge: (%s of %s) %s Compile" % \
2975 (mergecount, len(mymergelist), pkg_key)
2976 emergelog(xterm_titles, msg, short_msg=short_msg)
2977 retval = portage.doebuild(y, "merge", myroot,
2978 pkgsettings, self.edebug, vartree=vartree,
2979 mydbapi=portdb, tree="porttree",
2980 prev_mtimes=ldpath_mtimes)
2981 if retval != os.EX_OK:
2985 portage.locks.unlockdir(builddir_lock)
2988 # Lock catdir for removal if empty.
2989 catdir_lock = portage.locks.lockdir(catdir)
2995 if e.errno not in (errno.ENOENT,
2996 errno.ENOTEMPTY, errno.EEXIST):
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, autoclean=1)
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,
3155 ldpath_mtimes, autoclean=0):
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....
3408 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3410 for x in pkgmap.keys():
3411 for y in pkgmap[x]["selected"]:
3412 print ">>> Unmerging "+y+"..."
3413 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3414 mysplit=y.split("/")
3416 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3417 mysettings, unmerge_action not in ["clean","prune"],
3418 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3419 if retval != os.EX_OK:
3420 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3421 ebuild = vartree.dbapi.findname(y)
3422 show_unmerge_failure_message(y, ebuild, retval)
3425 clean_world(vartree.dbapi, y)
3426 emergelog(xterm_titles, " >>> unmerge success: "+y)
3429 def show_unmerge_failure_message(pkg, ebuild, retval):
3431 from formatter import AbstractFormatter, DumbWriter
3432 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3435 msg.append("A removal phase of the '%s' package " % pkg)
3436 msg.append("has failed with exit value %s. " % retval)
3437 msg.append("The problem occurred while executing ")
3438 msg.append("the ebuild located at '%s'. " % ebuild)
3439 msg.append("If necessary, manually remove the ebuild " )
3440 msg.append("in order to skip the execution of removal phases.")
3444 f.add_flowing_data(x)
3448 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3451 if os.path.exists("/usr/bin/install-info"):
3456 inforoot=normpath(root+z)
3457 if os.path.isdir(inforoot):
3458 infomtime = long(os.stat(inforoot).st_mtime)
3459 if inforoot not in prev_mtimes or \
3460 prev_mtimes[inforoot] != infomtime:
3461 regen_infodirs.append(inforoot)
3463 if not regen_infodirs:
3464 print " "+green("*")+" GNU info directory index is up-to-date."
3466 print " "+green("*")+" Regenerating GNU info directory index..."
3470 for inforoot in regen_infodirs:
3473 for filename in ("dir", "dir.gz", "dir.bz2"):
3474 file_path = os.path.join(inforoot, filename)
3476 os.rename(file_path, file_path + ".old")
3478 if e.errno != errno.ENOENT:
3482 if not os.path.isdir(inforoot):
3485 file_list = os.listdir(inforoot)
3488 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3490 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3491 existsstr="already exists, for file `"
3493 if re.search(existsstr,myso):
3494 # Already exists... Don't increment the count for this.
3496 elif myso[:44]=="install-info: warning: no info dir entry in ":
3497 # This info file doesn't contain a DIR-header: install-info produces this
3498 # (harmless) warning (the --quiet switch doesn't seem to work).
3499 # Don't increment the count for this.
3503 errmsg += myso + "\n"
3506 #update mtime so we can potentially avoid regenerating.
3507 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3510 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3513 print " "+green("*")+" Processed",icount,"info files."
3516 def post_emerge(settings, mtimedb, retval):
3518 Misc. things to run at the end of a merge session.
3526 @param settings: Configuration settings (typically portage.settings)
3527 @type settings: portage.config()
3528 @param mtimedb: The mtimeDB to store data needed across merge invocations
3529 @type mtimedb: MtimeDB class instance
3530 @param retval: Emerge's return value
3534 1. Calls sys.exit(retval)
3536 target_root = settings["ROOT"]
3537 info_mtimes = mtimedb["info"]
3539 # Load the most current variables from ${ROOT}/etc/profile.env
3541 settings.regenerate()
3544 config_protect = settings.get("CONFIG_PROTECT","").split()
3545 infodirs = settings.get("INFOPATH","").split(":") + \
3546 settings.get("INFODIR","").split(":")
3550 emergelog("notitles" not in settings.features,
3551 " *** exiting successfully.")
3553 if "noinfo" not in settings.features:
3554 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3556 chk_updated_cfg_files(target_root, config_protect)
3558 NEWS_PATH = os.path.join( "metadata", "news" )
3559 UNREAD_PATH = os.path.join( target_root, NEWS_LIB_PATH, 'news')
3560 porttree = portdbapi( porttree_root = settings["PORTDIR"], mysettings = settings )
3561 newsReaderDisplay = False
3563 for repo in porttree.getRepositories():
3564 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3566 print colorize("WARN", " * IMPORTANT:"),
3567 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3568 newsReaderDisplay = True
3570 if newsReaderDisplay:
3571 print colorize("WARN", " *"),
3572 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3578 def chk_updated_cfg_files(target_root, config_protect):
3580 #number of directories with some protect files in them
3582 for x in config_protect:
3583 x = os.path.join(target_root, x.lstrip(os.path.sep))
3585 mymode = os.lstat(x).st_mode
3588 if stat.S_ISDIR(mymode):
3589 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3591 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3592 os.path.split(x.rstrip(os.path.sep))
3593 a = commands.getstatusoutput(mycommand)
3595 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3597 files = a[1].split()
3600 print colorize("WARN", " * IMPORTANT:"),
3601 if stat.S_ISDIR(mymode):
3602 print "%d config files in '%s' need updating." % \
3605 print "config file '%s' needs updating." % x
3608 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3609 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3611 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3613 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3614 Returns the number of unread (yet relevent) items.
3626 1. The number of unread but relevant news items.
3629 from portage.news import NewsManager
3630 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3631 return manager.getUnreadItems( repo_id, update=True )
3633 def is_valid_package_atom(x):
3635 testkey = portage.dep_getkey(x)
3636 except portage.exception.InvalidData:
3638 if testkey.startswith("null/"):
3639 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3644 return portage.isvalidatom(testatom)
3646 def validate_merge_list(trees, mergelist):
3647 """Validate the list to make sure all the packages are still available.
3648 This is needed for --resume."""
3649 for (pkg_type, myroot, pkg_key, action) in mergelist:
3650 if pkg_type == "binary" and \
3651 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3652 pkg_type == "ebuild" and \
3653 not trees[myroot]["porttree"].dbapi.xmatch(
3654 "match-all", "="+pkg_key):
3655 print red("!!! Error: The resume list contains packages that are no longer")
3656 print red("!!! available to be emerged. Please restart/continue")
3657 print red("!!! the merge operation manually.")
3660 def show_blocker_docs_link():
3662 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3663 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3665 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3668 def action_sync(settings, trees, mtimedb, myopts, myaction):
3669 xterm_titles = "notitles" not in settings.features
3670 emergelog(xterm_titles, " === sync")
3671 myportdir = settings.get("PORTDIR", None)
3673 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3675 if myportdir[-1]=="/":
3676 myportdir=myportdir[:-1]
3677 if not os.path.exists(myportdir):
3678 print ">>>",myportdir,"not found, creating it."
3679 os.makedirs(myportdir,0755)
3680 syncuri=settings["SYNC"].rstrip()
3682 updatecache_flg = False
3683 if myaction == "metadata":
3684 print "skipping sync"
3685 updatecache_flg = True
3686 tmpservertimestampfile = None
3687 elif syncuri[:8]=="rsync://":
3688 if not os.path.exists("/usr/bin/rsync"):
3689 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3690 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3696 if settings["PORTAGE_RSYNC_OPTS"] == "":
3697 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3699 "--recursive", # Recurse directories
3700 "--links", # Consider symlinks
3701 "--safe-links", # Ignore links outside of tree
3702 "--perms", # Preserve permissions
3703 "--times", # Preserive mod times
3704 "--compress", # Compress the data transmitted
3705 "--force", # Force deletion on non-empty dirs
3706 "--whole-file", # Don't do block transfers, only entire files
3707 "--delete", # Delete files that aren't in the master tree
3708 "--delete-after", # Delete only after everything else is done
3709 "--stats", # Show final statistics about what was transfered
3710 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3711 "--exclude='/distfiles'", # Exclude distfiles from consideration
3712 "--exclude='/local'", # Exclude local from consideration
3713 "--exclude='/packages'", # Exclude packages from consideration
3717 # The below validation is not needed when using the above hardcoded
3720 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3721 rsync_opts.extend(settings["PORTAGE_RSYNC_OPTS"].split())
3723 for opt in ("--recursive", "--times"):
3724 if opt not in rsync_opts:
3725 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3726 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3727 rsync_opts.append(opt)
3729 for exclude in ("distfiles", "local", "packages"):
3730 opt = "--exclude=/%s" % exclude
3731 if opt not in rsync_opts:
3732 portage.writemsg(yellow("WARNING:") + \
3733 " adding required option %s not included in " % opt + \
3734 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3735 rsync_opts.append(opt)
3737 if settings["RSYNC_TIMEOUT"] != "":
3738 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3739 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3741 mytimeout = int(settings["RSYNC_TIMEOUT"])
3742 rsync_opts.append("--timeout=%d" % mytimeout)
3743 except ValueError, e:
3744 portage.writemsg("!!! %s\n" % str(e))
3746 # TODO: determine options required for official servers
3747 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
3749 def rsync_opt_startswith(opt_prefix):
3750 for x in rsync_opts:
3751 if x.startswith(opt_prefix):
3755 if not rsync_opt_startswith("--timeout="):
3756 rsync_opts.append("--timeout=%d" % mytimeout)
3758 for opt in ("--compress", "--whole-file"):
3759 if opt not in rsync_opts:
3760 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3761 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3762 rsync_opts.append(opt)
3764 if "--quiet" in myopts:
3765 rsync_opts.append("--quiet") # Shut up a lot
3767 rsync_opts.append("--verbose") # Print filelist
3769 if "--verbose" in myopts:
3770 rsync_opts.append("--progress") # Progress meter for each file
3772 if "--debug" in myopts:
3773 rsync_opts.append("--checksum") # Force checksum on all files
3775 if settings["RSYNC_EXCLUDEFROM"] != "":
3776 portage.writemsg(yellow("WARNING:") + \
3777 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
3778 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3779 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
3780 rsync_opts.append("--exclude-from=%s" % \
3781 settings["RSYNC_EXCLUDEFROM"])
3783 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
3784 " but file does not exist.\n")
3786 if settings["RSYNC_RATELIMIT"] != "":
3787 portage.writemsg(yellow("WARNING:") + \
3788 " usage of RSYNC_RATELIMIT is deprecated, use " + \
3789 "PORTAGE_RSYNC_EXTRA_OPTS instead")
3790 rsync_opts.append("--bwlimit=%s" % \
3791 settings["RSYNC_RATELIMIT"])
3793 # Real local timestamp file.
3794 servertimestampfile = os.path.join(
3795 myportdir, "metadata", "timestamp.chk")
3796 # Temporary file for remote server timestamp comparison.
3797 tmpservertimestampfile = os.path.join(
3798 settings["PORTAGE_TMPDIR"], "timestamp.chk")
3800 content = portage.util.grabfile(servertimestampfile)
3804 mytimestamp = time.mktime(time.strptime(content[0],
3805 "%a, %d %b %Y %H:%M:%S +0000"))
3806 except OverflowError, ValueError:
3811 if settings.has_key("RSYNC_RETRIES"):
3812 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
3813 maxretries=int(settings["RSYNC_RETRIES"])
3815 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
3816 except SystemExit, e:
3817 raise # Needed else can't exit
3819 maxretries=3 #default number of retries
3822 user_name, hostname, port = re.split(
3823 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
3826 if user_name is None:
3828 updatecache_flg=True
3829 all_rsync_opts = set(rsync_opts)
3830 all_rsync_opts.update(
3831 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
3832 family = socket.AF_UNSPEC
3833 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
3834 family = socket.AF_INET
3835 elif socket.has_ipv6 and \
3836 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
3837 family = socket.AF_INET6
3844 for addrinfo in socket.getaddrinfo(
3845 hostname, None, family, socket.SOCK_STREAM):
3846 if addrinfo[0] == socket.AF_INET6:
3847 # IPv6 addresses need to be enclosed in square brackets
3848 ips.append("[%s]" % addrinfo[4][0])
3850 ips.append(addrinfo[4][0])
3851 from random import shuffle
3853 except SystemExit, e:
3854 raise # Needed else can't exit
3855 except Exception, e:
3856 print "Notice:",str(e)
3861 dosyncuri = syncuri.replace(
3862 "//" + user_name + hostname + port + "/",
3863 "//" + user_name + ips[0] + port + "/", 1)
3864 except SystemExit, e:
3865 raise # Needed else can't exit
3866 except Exception, e:
3867 print "Notice:",str(e)
3871 if "--ask" in myopts:
3872 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
3877 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
3878 if "--quiet" not in myopts:
3879 print ">>> Starting rsync with "+dosyncuri+"..."
3881 emergelog(xterm_titles,
3882 ">>> Starting retry %d of %d with %s" % \
3883 (retries,maxretries,dosyncuri))
3884 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
3886 if mytimestamp != 0 and "--quiet" not in myopts:
3887 print ">>> Checking server timestamp ..."
3889 rsynccommand = " ".join(["/usr/bin/rsync", " ".join(rsync_opts),
3890 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
3892 if "--debug" in myopts:
3897 if mytimestamp != 0:
3898 mycommand = rsynccommand.split()
3899 mycommand.append(dosyncuri.rstrip("/") + \
3900 "/metadata/timestamp.chk")
3901 mycommand.append(tmpservertimestampfile)
3903 exitcode = portage.process.spawn(
3904 mycommand, env=settings.environ())
3905 content = portage.grabfile(tmpservertimestampfile)
3908 servertimestamp = time.mktime(time.strptime(
3909 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
3910 except OverflowError, ValueError:
3915 os.unlink(tmpservertimestampfile)
3919 if exitcode == os.EX_OK:
3920 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
3921 emergelog(xterm_titles,
3922 ">>> Cancelling sync -- Already current.")
3925 print ">>> Timestamps on the server and in the local repository are the same."
3926 print ">>> Cancelling all further sync action. You are already up to date."
3928 print ">>> In order to force sync, remove '%s'." % servertimestampfile
3932 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
3933 emergelog(xterm_titles,
3934 ">>> Server out of date: %s" % dosyncuri)
3937 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
3939 print ">>> In order to force sync, remove '%s'." % servertimestampfile
3942 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
3944 mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
3945 exitcode=portage.spawn(mycommand,settings,free=1)
3946 if exitcode in [0,1,2,3,4,11,14,20,21]:
3948 elif exitcode in [0,1,2,3,4,11,14,20,21]:
3953 if retries<=maxretries:
3954 print ">>> Retrying..."
3959 updatecache_flg=False
3963 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
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.process.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[:])
4084 from portage.cache import util
4086 class percentage_noise_maker(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 = portage.cache.util.quiet_mirroring()
4126 noise_maker = source = percentage_noise_maker(portdb)
4127 portage.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 portage.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"],
4808 ldpath_mtimes, autoclean=1)
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 portage.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 portage.output.havecolor = 1
5012 settings["NOCOLOR"] = "false"
5014 portage.output.havecolor = 0
5015 settings["NOCOLOR"] = "true"
5016 settings.backup_changes("NOCOLOR")
5017 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5018 portage.output.havecolor = 0
5019 settings["NOCOLOR"] = "true"
5020 settings.backup_changes("NOCOLOR")
5023 global portage # NFC why this is necessary now - genone
5024 # Disable color until we're sure that it should be enabled (after
5025 # EMERGE_DEFAULT_OPTS has been parsed).
5026 portage.output.havecolor = 0
5027 # This first pass is just for options that need to be known as early as
5028 # possible, such as --config-root. They will be parsed again later,
5029 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5030 # the value of --config-root).
5031 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5032 if "--debug" in myopts:
5033 os.environ["PORTAGE_DEBUG"] = "1"
5034 if "--config-root" in myopts:
5035 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5037 # Portage needs to ensure a sane umask for the files it creates.
5039 settings, trees, mtimedb = load_emerge_config()
5040 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5043 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5044 except (OSError, ValueError), e:
5045 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5046 settings["PORTAGE_NICENESS"])
5047 portage.writemsg("!!! %s\n" % str(e))
5050 if portage.global_updates(settings, trees, mtimedb["updates"]):
5052 # Reload the whole config from scratch.
5053 settings, trees, mtimedb = load_emerge_config(trees=trees)
5054 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5056 xterm_titles = "notitles" not in settings.features
5059 if "--ignore-default-opts" not in sys.argv:
5060 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5061 tmpcmdline.extend(sys.argv[1:])
5062 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5064 if "--digest" in myopts:
5065 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5066 # Reload the whole config from scratch so that the portdbapi internal
5067 # config is updated with new FEATURES.
5068 settings, trees, mtimedb = load_emerge_config(trees=trees)
5069 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5071 for myroot in trees:
5072 mysettings = trees[myroot]["vartree"].settings
5074 adjust_config(myopts, mysettings)
5076 del myroot, mysettings
5078 spinner = stdout_spinner()
5079 if "candy" in settings.features:
5080 spinner.update = spinner.update_scroll
5082 portage.deprecated_profile_check()
5084 #Freeze the portdbapi for enhanced performance:
5085 for myroot in trees:
5086 trees[myroot]["porttree"].dbapi.freeze()
5089 if "moo" in myfiles:
5092 Larry loves Gentoo (""" + os.uname()[0] + """)
5094 _______________________
5095 < Have you mooed today? >
5096 -----------------------
5105 if (myaction in ["world", "system"]) and myfiles:
5106 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5110 ext = os.path.splitext(x)[1]
5111 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5112 print "emerging by path implies --oneshot... adding --oneshot to options."
5113 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5116 if ("--tree" in myopts) and ("--columns" in myopts):
5117 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5120 if ("--quiet" in myopts):
5121 spinner.update = spinner.update_quiet
5122 portage.util.noiselimit = -1
5124 # Always create packages if FEATURES=buildpkg
5125 # Imply --buildpkg if --buildpkgonly
5126 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5127 if "--buildpkg" not in myopts:
5128 myopts["--buildpkg"] = True
5130 # Also allow -S to invoke search action (-sS)
5131 if ("--searchdesc" in myopts):
5132 if myaction and myaction != "search":
5133 myfiles.append(myaction)
5134 if "--search" not in myopts:
5135 myopts["--search"] = True
5138 # Always try and fetch binary packages if FEATURES=getbinpkg
5139 if ("getbinpkg" in settings.features):
5140 myopts["--getbinpkg"] = True
5142 if "--skipfirst" in myopts and "--resume" not in myopts:
5143 myopts["--resume"] = True
5145 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5146 myopts["--usepkgonly"] = True
5148 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5149 myopts["--getbinpkg"] = True
5151 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5152 myopts["--usepkg"] = True
5154 # Also allow -K to apply --usepkg/-k
5155 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5156 myopts["--usepkg"] = True
5158 # Allow -p to remove --ask
5159 if ("--pretend" in myopts) and ("--ask" in myopts):
5160 print ">>> --pretend disables --ask... removing --ask from options."
5163 # forbid --ask when not in a terminal
5164 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5165 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5166 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5170 if settings.get("PORTAGE_DEBUG", "") == "1":
5171 spinner.update = spinner.update_quiet
5173 if "python-trace" in settings.features:
5174 import portage.debug
5175 portage.debug.set_trace(True)
5177 if ("--resume" in myopts):
5178 if "--tree" in myopts:
5179 print "* --tree is currently broken with --resume. Disabling..."
5180 del myopts["--tree"]
5182 if not ("--quiet" in myopts):
5183 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5184 spinner.update = spinner.update_basic
5186 if "--version" in myopts:
5187 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5188 settings.profile_path, settings["CHOST"],
5189 trees[settings["ROOT"]]["vartree"].dbapi)
5191 elif "--help" in myopts:
5192 portage.emergehelp.help(myaction, myopts, portage.output.havecolor)
5195 if portage.wheelgid == portage.portage_gid:
5196 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5197 print " include the portage user as noted above, and then use group portage."
5199 if "--debug" in myopts:
5200 print "myaction", myaction
5201 print "myopts", myopts
5203 if not myaction and not myfiles and "--resume" not in myopts:
5204 portage.emergehelp.help(myaction, myopts, portage.output.havecolor)
5207 # check if root user is the current user for the actions where emerge needs this
5208 if portage.secpass < 2:
5209 # We've already allowed "--version" and "--help" above.
5210 if "--pretend" not in myopts and \
5211 myaction not in ("search","info"):
5212 need_superuser = not \
5213 ("--fetchonly" in myopts or \
5214 "--fetch-all-uri" in myopts or \
5215 myaction in ("metadata", "regen"))
5216 if portage.secpass < 1 or \
5219 access_desc = "superuser"
5221 access_desc = "portage group"
5222 # Always show portage_group_warning() when only portage group
5223 # access is required but the user is not in the portage group.
5224 from portage.data import portage_group_warning
5225 if "--ask" in myopts:
5226 myopts["--pretend"] = True
5228 print ("%s access would be required... " + \
5229 "adding --pretend to options.\n") % access_desc
5230 if portage.secpass < 1 and not need_superuser:
5231 portage_group_warning()
5233 sys.stderr.write(("emerge: %s access would be " + \
5234 "required.\n\n") % access_desc)
5235 if portage.secpass < 1 and not need_superuser:
5236 portage_group_warning()
5239 disable_emergelog = False
5240 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5242 disable_emergelog = True
5244 if myaction in ("search", "info"):
5245 disable_emergelog = True
5246 if disable_emergelog:
5247 """ Disable emergelog for everything except build or unmerge
5248 operations. This helps minimize parallel emerge.log entries that can
5249 confuse log parsers. We especially want it disabled during
5250 parallel-fetch, which uses --resume --fetchonly."""
5252 def emergelog(*pargs, **kargs):
5255 if not "--pretend" in myopts:
5256 emergelog(xterm_titles, "Started emerge on: "+\
5257 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5260 myelogstr=" ".join(myopts)
5262 myelogstr+=" "+myaction
5264 myelogstr+=" "+" ".join(myfiles)
5265 emergelog(xterm_titles, " *** emerge " + myelogstr)
5267 def emergeexitsig(signum, frame):
5268 signal.signal(signal.SIGINT, signal.SIG_IGN)
5269 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5270 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5271 sys.exit(100+signum)
5272 signal.signal(signal.SIGINT, emergeexitsig)
5273 signal.signal(signal.SIGTERM, emergeexitsig)
5276 """This gets out final log message in before we quit."""
5277 if "--pretend" not in myopts:
5278 emergelog(xterm_titles, " *** terminating.")
5279 if "notitles" not in settings.features:
5281 portage.atexit_register(emergeexit)
5283 if myaction in ("config", "metadata", "regen", "sync"):
5284 if "--pretend" in myopts:
5285 sys.stderr.write(("emerge: The '%s' action does " + \
5286 "not support '--pretend'.\n") % myaction)
5288 if "sync" == myaction:
5289 action_sync(settings, trees, mtimedb, myopts, myaction)
5290 elif "metadata" == myaction:
5291 action_metadata(settings, portdb, myopts)
5292 elif myaction=="regen":
5293 validate_ebuild_environment(trees)
5294 action_regen(settings, portdb)
5296 elif "config"==myaction:
5297 validate_ebuild_environment(trees)
5298 action_config(settings, trees, myopts, myfiles)
5301 elif "info"==myaction:
5302 action_info(settings, trees, myopts, myfiles)
5305 elif "search"==myaction:
5306 validate_ebuild_environment(trees)
5307 action_search(settings, portdb, trees["/"]["vartree"],
5308 myopts, myfiles, spinner)
5309 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5310 validate_ebuild_environment(trees)
5311 vartree = trees[settings["ROOT"]]["vartree"]
5312 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5314 if "--pretend" not in myopts:
5315 post_emerge(settings, mtimedb, 0)
5317 elif "depclean"==myaction:
5318 validate_ebuild_environment(trees)
5319 action_depclean(settings, trees, mtimedb["ldpath"],
5321 if "--pretend" not in myopts:
5322 post_emerge(settings, mtimedb, 0)
5323 # "update", "system", or just process files:
5325 validate_ebuild_environment(trees)
5326 action_build(settings, trees, mtimedb,
5327 myopts, myaction, myfiles, spinner)
5328 if "--pretend" not in myopts:
5329 post_emerge(settings, mtimedb, 0)
5331 if __name__ == "__main__":
5332 retval = emerge_main()