2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4 # $Id: emerge 5976 2007-02-17 09:14:53Z genone $
7 # This block ensures that ^C interrupts are handled quietly.
11 def exithandler(signum,frame):
12 signal.signal(signal.SIGINT, signal.SIG_IGN)
13 signal.signal(signal.SIGTERM, signal.SIG_IGN)
16 signal.signal(signal.SIGINT, exithandler)
17 signal.signal(signal.SIGTERM, exithandler)
18 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
20 except KeyboardInterrupt:
25 os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
29 from os import path as osp
30 sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
32 del os.environ["PORTAGE_LEGACY_GLOBALS"]
33 from portage import digraph, portdbapi
34 from portage.const import NEWS_LIB_PATH
37 import portage.xpak, commands, errno, re, socket, time, types
38 from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
39 havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
40 xtermTitleReset, yellow
41 from portage.output import create_color_func
42 good = create_color_func("GOOD")
43 bad = create_color_func("BAD")
46 portage.dep._dep_check_strict = True
49 import portage.exception
50 from portage.data import secpass
51 from portage.util import normalize_path as normpath
53 if not hasattr(__builtins__, "set"):
54 from sets import Set as set
55 from itertools import chain, izip
56 from UserDict import DictMixin
61 import pickle as cPickle
63 class stdout_spinner(object):
65 "Gentoo Rocks ("+os.uname()[0]+")",
66 "Thank you for using Gentoo. :)",
67 "Are you actually trying to read this?",
68 "How many times have you stared at this?",
69 "We are generating the cache right now",
70 "You are paying too much attention.",
71 "A theory is better than its explanation.",
72 "Phasers locked on target, Captain.",
73 "Thrashing is just virtual crashing.",
74 "To be is to program.",
75 "Real Users hate Real Programmers.",
76 "When all else fails, read the instructions.",
77 "Functionality breeds Contempt.",
78 "The future lies ahead.",
79 "3.1415926535897932384626433832795028841971694",
80 "Sometimes insanity is the only alternative.",
81 "Inaccuracy saves a world of explanation.",
84 twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
88 self.update = self.update_twirl
89 self.scroll_sequence = self.scroll_msgs[
90 int(time.time() * 100) % len(self.scroll_msgs)]
92 def update_basic(self):
93 self.spinpos = (self.spinpos + 1) % 500
94 if (self.spinpos % 100) == 0:
96 sys.stdout.write(". ")
101 def update_scroll(self):
102 if(self.spinpos >= len(self.scroll_sequence)):
103 sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
104 len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
106 sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
108 self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
110 def update_twirl(self):
111 self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
112 sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
115 def update_quiet(self):
118 def userquery(prompt, responses=None, colours=None):
119 """Displays a prompt and a set of responses, then waits for a response
120 which is checked against the responses and the first to match is
121 returned. An empty response will match the first value in responses. The
122 input buffer is *not* cleared prior to the prompt!
125 responses: a List of Strings.
126 colours: a List of Functions taking and returning a String, used to
127 process the responses for display. Typically these will be functions
128 like red() but could be e.g. lambda x: "DisplayString".
129 If responses is omitted, defaults to ["Yes", "No"], [green, red].
130 If only colours is omitted, defaults to [bold, ...].
132 Returns a member of the List responses. (If called without optional
133 arguments, returns "Yes" or "No".)
134 KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
136 if responses is None:
137 responses, colours = ["Yes", "No"], [green, red]
138 elif colours is None:
140 colours=(colours*len(responses))[:len(responses)]
144 response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
145 for key in responses:
146 # An empty response will match the first value in responses.
147 if response.upper()==key[:len(response)].upper():
149 print "Sorry, response '%s' not understood." % response,
150 except (EOFError, KeyboardInterrupt):
154 def sorted_versions(verlist):
157 verparts = ver.split("-")
158 if len(verparts) == 2:
159 verrev = int(verparts[1][1:])
164 retparts = ret[x].split("-")
165 verdiff = portage.vercmp(retparts[0], verparts[0])
169 if len(retparts) == 2:
170 retrev = int(retparts[1][1:])
181 "clean", "config", "depclean",
183 "prune", "regen", "search",
184 "sync", "system", "unmerge", "world",
187 "--ask", "--alphabetical",
188 "--buildpkg", "--buildpkgonly",
189 "--changelog", "--columns",
193 "--fetchonly", "--fetch-all-uri",
194 "--getbinpkg", "--getbinpkgonly",
195 "--help", "--ignore-default-opts",
197 "--newuse", "--nocolor",
198 "--nodeps", "--noreplace",
199 "--nospinner", "--oneshot",
200 "--onlydeps", "--pretend",
201 "--quiet", "--resume",
202 "--searchdesc", "--selective",
206 "--usepkg", "--usepkgonly",
207 "--verbose", "--version"
213 "b":"--buildpkg", "B":"--buildpkgonly",
214 "c":"--clean", "C":"--unmerge",
215 "d":"--debug", "D":"--deep",
217 "f":"--fetchonly", "F":"--fetch-all-uri",
218 "g":"--getbinpkg", "G":"--getbinpkgonly",
220 "k":"--usepkg", "K":"--usepkgonly",
222 "n":"--noreplace", "N":"--newuse",
223 "o":"--onlydeps", "O":"--nodeps",
224 "p":"--pretend", "P":"--prune",
226 "s":"--search", "S":"--searchdesc",
229 "v":"--verbose", "V":"--version"
232 def emergelog(xterm_titles, mystr, short_msg=None):
234 if short_msg == None:
236 if "HOSTNAME" in os.environ.keys():
237 short_msg = os.environ["HOSTNAME"]+": "+short_msg
238 xtermTitle(short_msg)
240 file_path = "/var/log/emerge.log"
241 mylogfile = open(file_path, "a")
242 portage.util.apply_secpass_permissions(file_path,
243 uid=portage.portage_uid, gid=portage.portage_gid,
247 mylock = portage.locks.lockfile(mylogfile)
248 # seek because we may have gotten held up by the lock.
249 # if so, we may not be positioned at the end of the file.
251 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
255 portage.locks.unlockfile(mylock)
257 except (IOError,OSError,portage.exception.PortageException), e:
259 print >> sys.stderr, "emergelog():",e
261 def countdown(secs=5, doing="Starting"):
263 print ">>> Waiting",secs,"seconds before starting..."
264 print ">>> (Control-C to abort)...\n"+doing+" in: ",
268 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
273 # formats a size given in bytes nicely
274 def format_size(mysize):
275 if type(mysize) not in [types.IntType,types.LongType]:
277 if 0 != mysize % 1024:
278 # Always round up to the next kB so that it doesn't show 0 kB when
279 # some small file still needs to be fetched.
280 mysize += 1024 - mysize % 1024
281 mystr=str(mysize/1024)
285 mystr=mystr[:mycount]+","+mystr[mycount:]
289 def getgccversion(chost):
292 return: the current in-use gcc version
295 gcc_ver_command = 'gcc -dumpversion'
296 gcc_ver_prefix = 'gcc-'
298 gcc_not_found_error = red(
299 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
300 "!!! to update the environment of this terminal and possibly\n" +
301 "!!! other terminals also.\n"
304 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
305 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
306 part1, part2 = myoutput.split("/")
307 if part1.startswith(chost + "-"):
308 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
310 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
311 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
312 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
314 mystatus, myoutput = commands.getstatusoutput(
315 chost + "-" + gcc_ver_command)
316 if mystatus == os.EX_OK:
317 return gcc_ver_prefix + myoutput
319 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
320 if mystatus == os.EX_OK:
321 return gcc_ver_prefix + myoutput
323 portage.writemsg(gcc_not_found_error, noiselevel=-1)
324 return "[unavailable]"
326 def getportageversion(portdir, target_root, profile, chost, vardb):
327 profilever = "unavailable"
329 realpath = os.path.realpath(profile)
330 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
331 if realpath.startswith(basepath):
332 profilever = realpath[1 + len(basepath):]
335 profilever = "!" + os.readlink(profile)
338 del realpath, basepath
341 libclist = vardb.match("virtual/libc")
342 libclist += vardb.match("virtual/glibc")
343 libclist = portage.util.unique_array(libclist)
345 xs=portage.catpkgsplit(x)
347 libcver+=","+"-".join(xs[1:])
349 libcver="-".join(xs[1:])
351 libcver="unavailable"
353 gccver = getgccversion(chost)
354 unameout=os.uname()[2]+" "+os.uname()[4]
356 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
358 def create_depgraph_params(myopts, myaction):
359 #configure emerge engine parameters
361 # self: include _this_ package regardless of if it is merged.
362 # selective: exclude the package if it is merged
363 # recurse: go into the dependencies
364 # deep: go into the dependencies of already merged packages
365 # empty: pretend nothing is merged
366 myparams = ["recurse"]
369 if "--update" in myopts or \
370 "--newuse" in myopts or \
371 "--noreplace" in myopts or \
372 myaction in ("system", "world"):
373 add.extend(["selective"])
374 if "--emptytree" in myopts:
375 add.extend(["empty"])
376 sub.extend(["selective"])
377 if "--nodeps" in myopts:
378 sub.extend(["recurse"])
379 if "--deep" in myopts:
382 if (x not in myparams) and (x not in sub):
389 # search functionality
401 def __init__(self, settings, portdb, vartree, spinner, searchdesc,
403 """Searches the available and installed packages for the supplied search key.
404 The list of available and installed packages is created at object instantiation.
405 This makes successive searches faster."""
406 self.settings = settings
408 self.vartree = vartree
409 self.spinner = spinner
410 self.verbose = verbose
411 self.searchdesc = searchdesc
413 def execute(self,searchkey):
414 """Performs the search for the supplied search key"""
416 self.searchkey=searchkey
417 self.packagematches = []
420 self.matches = {"pkg":[], "desc":[]}
423 self.matches = {"pkg":[]}
424 print "Searching... ",
427 if self.searchkey[0] == '%':
429 self.searchkey = self.searchkey[1:]
430 if self.searchkey[0] == '@':
432 self.searchkey = self.searchkey[1:]
434 self.searchre=re.compile(self.searchkey,re.I)
436 self.searchre=re.compile(re.escape(self.searchkey), re.I)
437 for package in self.portdb.cp_all():
438 self.spinner.update()
441 match_string = package[:]
443 match_string = package.split("/")[-1]
446 if self.searchre.search(match_string):
447 if not self.portdb.xmatch("match-visible", package):
449 self.matches["pkg"].append([package,masked])
450 elif self.searchdesc: # DESCRIPTION searching
451 full_package = self.portdb.xmatch("bestmatch-visible", package)
453 #no match found; we don't want to query description
454 full_package = portage.best(
455 self.portdb.xmatch("match-all", package))
461 full_desc = self.portdb.aux_get(
462 full_package, ["DESCRIPTION"])[0]
464 print "emerge: search: aux_get() failed, skipping"
466 if self.searchre.search(full_desc):
467 self.matches["desc"].append([full_package,masked])
469 for mtype in self.matches.keys():
470 self.matches[mtype].sort()
471 self.mlen += len(self.matches[mtype])
474 """Outputs the results of the search."""
475 print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
476 print "[ Applications found : "+white(str(self.mlen))+" ]"
478 for mtype in self.matches.keys():
479 for match,masked in self.matches[mtype]:
482 full_package = self.portdb.xmatch(
483 "bestmatch-visible", match)
485 #no match found; we don't want to query description
487 full_package = portage.best(
488 self.portdb.xmatch("match-all",match))
491 match = portage.pkgsplit(match)[0]
495 desc, homepage, license = self.portdb.aux_get(
496 full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
498 print "emerge: search: aux_get() failed, skipping"
501 print green("*")+" "+white(match)+" "+red("[ Masked ]")
503 print green("*")+" "+white(match)
504 myversion = self.getVersion(full_package, search.VERSION_RELEASE)
507 mycat = match.split("/")[0]
508 mypkg = match.split("/")[1]
509 mycpv = match + "-" + myversion
510 myebuild = self.portdb.findname(mycpv)
511 pkgdir = os.path.dirname(myebuild)
512 from portage import manifest
513 mf = manifest.Manifest(
514 pkgdir, self.settings["DISTDIR"])
515 fetchlist = self.portdb.getfetchlist(mycpv,
516 mysettings=self.settings, all=True)[1]
518 mysum[0] = mf.getDistfilesSize(fetchlist)
519 mystr = str(mysum[0]/1024)
523 mystr=mystr[:mycount]+","+mystr[mycount:]
526 mysum[0] = "Unknown (missing digest for %s)" % str(e)
529 print " ", darkgreen("Latest version available:"),myversion
530 print " ", self.getInstallationStatus(mycat+'/'+mypkg)
531 print " ", darkgreen("Size of files:"),mysum[0]
532 print " ", darkgreen("Homepage:")+" ",homepage
533 print " ", darkgreen("Description:")+" ",desc
534 print " ", darkgreen("License:")+" ",license
540 def getInstallationStatus(self,package):
541 installed_package = self.vartree.dep_bestmatch(package)
543 version = self.getVersion(installed_package,search.VERSION_RELEASE)
545 result = darkgreen("Latest version installed:")+" "+version
547 result = darkgreen("Latest version installed:")+" [ Not Installed ]"
550 def getVersion(self,full_package,detail):
551 if len(full_package) > 1:
552 package_parts = portage.catpkgsplit(full_package)
553 if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
554 result = package_parts[2]+ "-" + package_parts[3]
556 result = package_parts[2]
562 #build our package digraph
563 def getlist(settings, mode):
565 mylines = settings.packages
568 file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
569 myfile = open(file_path, "r")
570 mylines = myfile.readlines()
572 except (OSError, IOError), e:
573 if e.errno == errno.ENOENT:
574 portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
580 myline=" ".join(x.split())
589 mynewlines.append(myline.strip())
593 def clean_world(vardb, cpv):
594 """Remove a package from the world file when unmerged."""
595 world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
596 worldlist = portage.util.grabfile(world_filename)
597 mykey = portage.cpv_getkey(cpv)
600 if portage.dep_getkey(x) == mykey:
601 matches = vardb.match(x, use_cache=0)
605 elif len(matches) == 1 and matches[0] == cpv:
609 #others are around; keep it.
610 newworldlist.append(x)
612 #this doesn't match the package we're unmerging; keep it.
613 newworldlist.append(x)
615 portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
616 gid=portage.portage_gid, mode=02770)
617 portage.util.write_atomic(world_filename, "\n".join(newworldlist))
619 def genericdict(mylist):
622 mynewdict[portage.dep_getkey(x)]=x
625 def filter_iuse_defaults(iuse):
627 if flag.startswith("+"):
632 class DepPriority(object):
634 This class generates an integer priority level based of various
635 attributes of the dependency relationship. Attributes can be assigned
636 at any time and the new integer value will be generated on calls to the
637 __int__() method. Rich comparison operators are supported.
639 The boolean attributes that affect the integer value are "satisfied",
640 "buildtime", "runtime", and "system". Various combinations of
641 attributes lead to the following priority levels:
643 Combination of properties Priority level
645 not satisfied and buildtime 0
646 not satisfied and runtime -1
647 satisfied and buildtime -2
648 satisfied and runtime -3
649 (none of the above) -4
651 Several integer constants are defined for categorization of priority
654 MEDIUM The upper boundary for medium dependencies.
655 SOFT The upper boundary for soft dependencies.
656 MIN The lower boundary for soft dependencies.
658 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
662 def __init__(self, **kwargs):
663 for myattr in self.__slots__:
664 if myattr == "__weakref__":
666 myvalue = kwargs.get(myattr, False)
667 setattr(self, myattr, myvalue)
669 if not self.satisfied:
679 def __lt__(self, other):
680 return self.__int__() < other
681 def __le__(self, other):
682 return self.__int__() <= other
683 def __eq__(self, other):
684 return self.__int__() == other
685 def __ne__(self, other):
686 return self.__int__() != other
687 def __gt__(self, other):
688 return self.__int__() > other
689 def __ge__(self, other):
690 return self.__int__() >= other
693 return copy.copy(self)
695 myvalue = self.__int__()
696 if myvalue > self.MEDIUM:
698 if myvalue > self.SOFT:
702 class FakeVartree(portage.vartree):
703 """This is implements an in-memory copy of a vartree instance that provides
704 all the interfaces required for use by the depgraph. The vardb is locked
705 during the constructor call just long enough to read a copy of the
706 installed package information. This allows the depgraph to do it's
707 dependency calculations without holding a lock on the vardb. It also
708 allows things like vardb global updates to be done in memory so that the
709 user doesn't necessarily need write access to the vardb in cases where
710 global updates are necessary (updates are performed when necessary if there
711 is not a matching ebuild in the tree)."""
712 def __init__(self, real_vartree, portdb):
713 self.root = real_vartree.root
714 self.settings = real_vartree.settings
715 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
716 vdb_path = os.path.join(self.root, portage.VDB_PATH)
718 # At least the parent needs to exist for the lock file.
719 portage.util.ensure_dirs(vdb_path)
720 except portage.exception.PortageException:
724 if os.access(vdb_path, os.W_OK):
725 vdb_lock = portage.locks.lockdir(vdb_path)
726 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
727 "DEPEND", "RDEPEND", "PDEPEND"]
728 real_dbapi = real_vartree.dbapi
730 for cpv in real_dbapi.cpv_all():
731 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
732 myslot = metadata["SLOT"]
733 mycp = portage.dep_getkey(cpv)
734 myslot_atom = "%s:%s" % (mycp, myslot)
736 mycounter = long(metadata["COUNTER"])
739 metadata["COUNTER"] = str(mycounter)
740 other_counter = slot_counters.get(myslot_atom, None)
741 if other_counter is not None:
742 if other_counter > mycounter:
744 slot_counters[myslot_atom] = mycounter
745 self.dbapi.cpv_inject(cpv, metadata=metadata)
746 real_dbapi.flush_cache()
749 portage.locks.unlockdir(vdb_lock)
750 # Populate the old-style virtuals using the cached values.
751 if not self.settings.treeVirtuals:
752 self.settings.treeVirtuals = portage.util.map_dictlist_vals(
753 portage.getCPFromCPV, self.get_all_provides())
755 # Intialize variables needed for lazy cache pulls of the live ebuild
756 # metadata. This ensures that the vardb lock is released ASAP, without
757 # being delayed in case cache generation is triggered.
758 self._aux_get = self.dbapi.aux_get
759 self.dbapi.aux_get = self._aux_get_wrapper
760 self._aux_get_history = set()
761 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
762 self._portdb = portdb
763 self._global_updates = None
765 def _aux_get_wrapper(self, pkg, wants):
766 if pkg in self._aux_get_history:
767 return self._aux_get(pkg, wants)
768 self._aux_get_history.add(pkg)
770 # Use the live ebuild metadata if possible.
771 live_metadata = dict(izip(self._portdb_keys,
772 self._portdb.aux_get(pkg, self._portdb_keys)))
773 self.dbapi.aux_update(pkg, live_metadata)
774 except (KeyError, portage.exception.PortageException):
775 if self._global_updates is None:
776 self._global_updates = \
777 grab_global_updates(self._portdb.porttree_root)
778 perform_global_updates(
779 pkg, self.dbapi, self._global_updates)
780 return self._aux_get(pkg, wants)
782 def grab_global_updates(portdir):
783 from portage.update import grab_updates, parse_updates
784 updpath = os.path.join(portdir, "profiles", "updates")
786 rawupdates = grab_updates(updpath)
787 except portage.exception.DirectoryNotFound:
790 for mykey, mystat, mycontent in rawupdates:
791 commands, errors = parse_updates(mycontent)
792 upd_commands.extend(commands)
795 def perform_global_updates(mycpv, mydb, mycommands):
796 from portage.update import update_dbentries
797 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
798 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
799 updates = update_dbentries(mycommands, aux_dict)
801 mydb.aux_update(mycpv, updates)
803 class BlockerCache(DictMixin):
804 """This caches blockers of installed packages so that dep_check does not
805 have to be done for every single installed package on every invocation of
806 emerge. The cache is invalidated whenever it is detected that something
807 has changed that might alter the results of dep_check() calls:
808 1) the set of installed packages (including COUNTER) has changed
809 2) the old-style virtuals have changed
811 class BlockerData(object):
812 def __init__(self, counter, atoms):
813 self.counter = counter
816 def __init__(self, myroot, vardb):
818 self._installed_pkgs = set(vardb.cpv_all())
819 self._virtuals = vardb.settings.getvirtuals()
820 self._cache_filename = os.path.join(myroot,
821 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
822 self._cache_version = "1"
823 self._cache_data = None
824 self._modified = False
829 f = open(self._cache_filename)
830 mypickle = cPickle.Unpickler(f)
831 mypickle.find_global = None
832 self._cache_data = mypickle.load()
835 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
837 cache_valid = self._cache_data and \
838 isinstance(self._cache_data, dict) and \
839 self._cache_data.get("version") == self._cache_version and \
840 self._cache_data.get("virtuals") == self._virtuals and \
841 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
843 for pkg in self._installed_pkgs:
844 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
849 self._cache_data = {"version":self._cache_version}
850 self._cache_data["blockers"] = {}
851 self._cache_data["virtuals"] = self._virtuals
852 self._modified = False
855 """If the current user has permission and the internal blocker cache
856 been updated, save it to disk and mark it unmodified. This is called
857 by emerge after it has proccessed blockers for all installed packages.
858 Currently, the cache is only written if the user has superuser
859 privileges (since that's required to obtain a lock), but all users
860 have read access and benefit from faster blocker lookups (as long as
861 the entire cache is still valid). The cache is stored as a pickled
862 dict object with the following format:
866 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
867 "virtuals" : vardb.settings.getvirtuals()
870 if self._modified and \
873 f = portage.util.atomic_ofstream(self._cache_filename)
874 cPickle.dump(self._cache_data, f, -1)
876 portage.util.apply_secpass_permissions(
877 self._cache_filename, gid=portage.portage_gid, mode=0644)
878 except (IOError, OSError), e:
880 self._modified = False
882 def __setitem__(self, cpv, blocker_data):
884 Update the cache and mark it as modified for a future call to
887 @param cpv: Package for which to cache blockers.
889 @param blocker_data: An object with counter and atoms attributes.
890 @type blocker_data: BlockerData
892 self._cache_data["blockers"][cpv] = \
893 (blocker_data.counter, blocker_data.atoms)
894 self._modified = True
896 def __getitem__(self, cpv):
899 @returns: An object with counter and atoms attributes.
901 return self.BlockerData(*self._cache_data["blockers"][cpv])
903 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
905 from formatter import AbstractFormatter, DumbWriter
906 f = AbstractFormatter(DumbWriter(maxcol=72))
908 print "\n\n!!! Invalid or corrupt dependency specification: "
916 p_type, p_root, p_key, p_status = parent_node
918 if p_status == "nomerge":
919 category, pf = portage.catsplit(p_key)
920 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
921 msg.append("Portage is unable to process the dependencies of the ")
922 msg.append("'%s' package. " % p_key)
923 msg.append("In order to correct this problem, the package ")
924 msg.append("should be uninstalled, reinstalled, or upgraded. ")
925 msg.append("As a temporary workaround, the --nodeps option can ")
926 msg.append("be used to ignore all dependencies. For reference, ")
927 msg.append("the problematic dependencies can be found in the ")
928 msg.append("*DEPEND files located in '%s/'." % pkg_location)
930 msg.append("This package can not be installed. ")
931 msg.append("Please notify the '%s' package maintainer " % p_key)
932 msg.append("about this problem.")
935 f.add_flowing_data(x)
943 "installed":"vartree"}
945 def __init__(self, settings, trees, myopts, myparams, spinner):
946 self.settings = settings
947 self.target_root = settings["ROOT"]
949 self.myparams = myparams
951 if settings.get("PORTAGE_DEBUG", "") == "1":
953 self.spinner = spinner
954 self.pkgsettings = {}
955 # Maps cpv to digraph node for all nodes added to the graph.
956 self.pkg_node_map = {}
957 # Maps slot atom to digraph node for all nodes added to the graph.
958 self._slot_node_map = {}
960 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
964 self.trees[myroot] = {}
965 for tree in ("porttree", "bintree"):
966 self.trees[myroot][tree] = trees[myroot][tree]
967 self.trees[myroot]["vartree"] = \
968 FakeVartree(trees[myroot]["vartree"],
969 trees[myroot]["porttree"].dbapi)
970 self.pkgsettings[myroot] = portage.config(
971 clone=self.trees[myroot]["vartree"].settings)
972 self.pkg_node_map[myroot] = {}
973 self._slot_node_map[myroot] = {}
974 vardb = self.trees[myroot]["vartree"].dbapi
975 # This fakedbapi instance will model the state that the vdb will
976 # have after new packages have been installed.
977 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
978 self.mydbapi[myroot] = fakedb
979 if "--nodeps" not in self.myopts and \
980 "--buildpkgonly" not in self.myopts:
981 # --nodeps bypasses this, since it isn't needed in this case
982 # and the cache pulls might trigger (slow) cache generation.
983 for pkg in vardb.cpv_all():
984 self.spinner.update()
985 fakedb.cpv_inject(pkg,
986 metadata=dict(izip(self._mydbapi_keys,
987 vardb.aux_get(pkg, self._mydbapi_keys))))
989 self.useFlags[myroot] = {}
990 if "--usepkg" in self.myopts:
991 self.trees[myroot]["bintree"].populate(
992 "--getbinpkg" in self.myopts,
993 "--getbinpkgonly" in self.myopts)
997 self.digraph=portage.digraph()
998 # Tracks simple parent/child relationships (PDEPEND relationships are
1000 self._parent_child_digraph = digraph()
1002 self.outdatedpackages=[]
1004 self.blocker_digraph = digraph()
1005 self.blocker_parents = {}
1006 self._slot_collision_info = []
1007 # Slot collision nodes are not allowed to block other packages since
1008 # blocker validation is only able to account for one package per slot.
1009 self._slot_collision_nodes = set()
1010 self._altlist_cache = {}
1011 self._pprovided_args = []
1013 def _show_slot_collision_notice(self, packages):
1014 """Show an informational message advising the user to mask one of the
1015 the packages. In some cases it may be possible to resolve this
1016 automatically, but support for backtracking (removal nodes that have
1017 already been selected) will be required in order to handle all possible
1021 msg.append("\n!!! Multiple versions within a single " + \
1022 "package slot have been \n")
1023 msg.append("!!! pulled into the dependency graph:\n\n")
1024 for node, parents in packages:
1025 msg.append(str(node))
1027 msg.append(" pulled in by\n")
1028 for parent in parents:
1030 msg.append(str(parent))
1033 msg.append(" (no parents)\n")
1035 sys.stderr.write("".join(msg))
1038 if "--quiet" in self.myopts:
1042 msg.append("It may be possible to solve this problem ")
1043 msg.append("by using package.mask to prevent one of ")
1044 msg.append("those packages from being selected. ")
1045 msg.append("However, it is also possible that conflicting ")
1046 msg.append("dependencies exist such that they are impossible to ")
1047 msg.append("satisfy simultaneously. If such a conflict exists in ")
1048 msg.append("the dependencies of two different packages, then those ")
1049 msg.append("packages can not be installed simultaneously.")
1051 from formatter import AbstractFormatter, DumbWriter
1052 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1054 f.add_flowing_data(x)
1058 msg.append("For more information, see MASKED PACKAGES ")
1059 msg.append("section in the emerge man page or refer ")
1060 msg.append("to the Gentoo Handbook.")
1062 f.add_flowing_data(x)
1066 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1067 priority=DepPriority(), rev_dep=False, arg=None):
1069 Fills the digraph with nodes comprised of packages to merge.
1070 mybigkey is the package spec of the package to merge.
1071 myparent is the package depending on mybigkey ( or None )
1072 addme = Should we add this package to the digraph or are we just looking at it's deps?
1073 Think --onlydeps, we need to ignore packages in that case.
1076 #IUSE-aware emerge -> USE DEP aware depgraph
1077 #"no downgrade" emerge
1079 mytype, myroot, mykey = mybigkey
1080 existing_node = None
1082 existing_node = self.pkg_node_map[myroot].get(mykey)
1084 self._parent_child_digraph.add(existing_node, myparent)
1085 if existing_node != myparent:
1086 # Refuse to make a node depend on itself so that the we don't
1087 # don't create a bogus circular dependency in self.altlist().
1088 if rev_dep and myparent:
1089 self.digraph.addnode(myparent, existing_node,
1092 self.digraph.addnode(existing_node, myparent,
1096 self.spinner.update()
1097 if mytype == "blocks":
1099 "--buildpkgonly" not in self.myopts and \
1100 "--nodeps" not in self.myopts and \
1101 myparent not in self._slot_collision_nodes:
1102 mybigkey[1] = myparent[1]
1103 self.blocker_parents.setdefault(
1104 tuple(mybigkey), set()).add(myparent)
1106 if not arg and myroot == self.target_root:
1107 arg = portage.best_match_to_list(mykey, self.args_keys)
1108 # select the correct /var database that we'll be checking against
1109 vardbapi = self.trees[myroot]["vartree"].dbapi
1110 portdb = self.trees[myroot]["porttree"].dbapi
1111 bindb = self.trees[myroot]["bintree"].dbapi
1112 pkgsettings = self.pkgsettings[myroot]
1114 # if the package is already on the system, we add a "nomerge"
1115 # directive, otherwise we add a "merge" directive.
1117 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1120 self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
1121 myuse = self.pkgsettings[myroot]["USE"].split()
1124 if mytype == "installed":
1126 if addme and mytype != "installed":
1127 # this is where we add the node to the list of packages to merge
1128 if "selective" in self.myparams or not arg:
1129 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1132 """ If we aren't merging, perform the --newuse check.
1133 If the package has new iuse flags or different use flags then if
1134 --newuse is specified, we need to merge the package. """
1135 if merging==0 and "--newuse" in self.myopts and \
1136 vardbapi.cpv_exists(mykey):
1137 pkgsettings.setcpv(mykey, mydb=mydbapi)
1138 forced_flags = set()
1139 forced_flags.update(pkgsettings.useforce)
1140 forced_flags.update(pkgsettings.usemask)
1141 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1142 iuses = set(filter_iuse_defaults(
1143 mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
1144 old_iuse = set(filter_iuse_defaults(
1145 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1146 if iuses.symmetric_difference(
1147 old_iuse).difference(forced_flags):
1149 elif old_iuse.intersection(old_use) != \
1150 iuses.intersection(myuse):
1153 if addme and merging == 1:
1154 mybigkey.append("merge")
1156 mybigkey.append("nomerge")
1157 jbigkey = tuple(mybigkey)
1160 metadata = dict(izip(self._mydbapi_keys,
1161 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1162 if merging == 0 and vardbapi.cpv_exists(mykey):
1163 metadata["USE"] = vardbapi.aux_get(mykey, ["USE"])[0]
1164 myuse = metadata["USE"].split()
1165 metadata["SLOT"] = vardbapi.aux_get(mykey, ["SLOT"])[0]
1166 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1167 existing_node = self._slot_node_map[myroot].get(
1169 slot_collision = False
1171 e_type, myroot, e_cpv, e_status = existing_node
1173 # The existing node can be reused.
1174 self._parent_child_digraph.add(existing_node, myparent)
1175 if rev_dep and myparent:
1176 ptype, proot, pkey, pstatus = myparent
1177 self.digraph.addnode(myparent, existing_node,
1180 self.digraph.addnode(existing_node, myparent,
1184 # A slot collision has occurred. Sometimes this coincides
1185 # with unresolvable blockers, so the slot collision will be
1186 # shown later if there are no unresolvable blockers.
1187 e_parents = self._parent_child_digraph.parent_nodes(
1191 myparents.append(myparent)
1192 self._slot_collision_info.append(
1193 ((jbigkey, myparents), (existing_node, e_parents)))
1194 self._slot_collision_nodes.add(jbigkey)
1195 slot_collision = True
1198 # Now add this node to the graph so that self.display()
1199 # can show use flags and --tree portage.output. This node is
1200 # only being partially added to the graph. It must not be
1201 # allowed to interfere with the other nodes that have been
1202 # added. Do not overwrite data for existing nodes in
1203 # self.pkg_node_map and self.mydbapi since that data will
1204 # be used for blocker validation.
1205 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1206 self.useFlags[myroot].setdefault(mykey, myuse)
1207 # Even though the graph is now invalid, continue to process
1208 # dependencies so that things like --fetchonly can still
1209 # function despite collisions.
1211 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1212 self._slot_node_map[myroot][slot_atom] = jbigkey
1213 self.pkg_node_map[myroot][mykey] = jbigkey
1214 self.useFlags[myroot][mykey] = myuse
1216 if rev_dep and myparent:
1217 self.digraph.addnode(myparent, jbigkey,
1220 self.digraph.addnode(jbigkey, myparent,
1223 # Do this even when addme is False (--onlydeps) so that the
1224 # parent/child relationship is always known in case
1225 # self._show_slot_collision_notice() needs to be called later.
1226 self._parent_child_digraph.add(jbigkey, myparent)
1228 """ This section determines whether we go deeper into dependencies or not.
1229 We want to go deeper on a few occasions:
1230 Installing package A, we need to make sure package A's deps are met.
1231 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1232 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1234 if "deep" not in self.myparams and not merging and \
1235 not ("--update" in self.myopts and arg and merging):
1237 elif "recurse" not in self.myparams:
1240 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1241 Pull from bintree if it's binary package, porttree if it's ebuild.
1242 Binpkg's can be either remote or local. """
1245 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1246 depvalues = mydbapi.aux_get(mykey, depkeys)
1247 for i in xrange(len(depkeys)):
1248 edepend[depkeys[i]] = depvalues[i]
1250 if mytype == "ebuild":
1251 if "--buildpkgonly" in self.myopts:
1252 edepend["RDEPEND"] = ""
1253 edepend["PDEPEND"] = ""
1254 if not (arg and "--onlydeps" in self.myopts and \
1255 mytype == "ebuild") and \
1256 self.myopts.get("--with-bdeps", "n") == "n" and \
1257 (mytype == "binary" or mybigkey[3] == "nomerge"):
1258 edepend["DEPEND"] = ""
1260 """ We have retrieve the dependency information, now we need to recursively
1261 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1263 mp = tuple(mybigkey)
1266 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1267 myuse=myuse, priority=DepPriority(buildtime=True),
1270 """RDEPEND is soft by definition. However, in order to ensure
1271 correct merge order, we make it a hard dependency. Otherwise, a
1272 build time dependency might not be usable due to it's run time
1273 dependencies not being installed yet.
1275 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1276 myuse=myuse, priority=DepPriority(runtime=True),
1279 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1280 # Post Depend -- Add to the list without a parent, as it depends
1281 # on a package being present AND must be built after that package.
1282 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1283 myuse=myuse, priority=DepPriority(), rev_deps=True,
1286 except ValueError, e:
1288 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1289 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1291 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1292 portage.writemsg("\n", noiselevel=-1)
1293 if mytype == "binary":
1295 "!!! This binary package cannot be installed: '%s'\n" % \
1296 mykey, noiselevel=-1)
1297 elif mytype == "ebuild":
1298 myebuild, mylocation = portdb.findname2(mykey)
1299 portage.writemsg("!!! This ebuild cannot be installed: " + \
1300 "'%s'\n" % myebuild, noiselevel=-1)
1301 portage.writemsg("!!! Please notify the package maintainer " + \
1302 "that atoms must be fully-qualified.\n", noiselevel=-1)
1306 def select_files(self,myfiles):
1307 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1309 myroot = self.target_root
1310 portdb = self.trees[myroot]["porttree"].dbapi
1311 bindb = self.trees[myroot]["bintree"].dbapi
1312 pkgsettings = self.pkgsettings[myroot]
1314 def visible(mylist):
1315 matches = portdb.gvisible(portdb.visible(mylist))
1316 return [x for x in mylist \
1317 if x in matches or not portdb.cpv_exists(x)]
1319 ext = os.path.splitext(x)[1]
1321 if not os.path.exists(x):
1323 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1324 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1325 elif os.path.exists(
1326 os.path.join(pkgsettings["PKGDIR"], x)):
1327 x = os.path.join(pkgsettings["PKGDIR"], x)
1329 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1330 print "!!! Please ensure the tbz2 exists as specified.\n"
1332 mytbz2=portage.xpak.tbz2(x)
1333 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1334 if os.path.realpath(x) != \
1335 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1336 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1338 if not self.create(["binary", myroot, mykey],
1339 None, "--onlydeps" not in self.myopts):
1340 return (0,myfavorites)
1341 elif not "--oneshot" in self.myopts:
1342 myfavorites.append(mykey)
1343 elif ext==".ebuild":
1344 x = os.path.realpath(x)
1345 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1346 ebuild_path = portdb.findname(mykey)
1348 if os.path.realpath(ebuild_path) != x:
1349 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1351 if mykey not in portdb.xmatch(
1352 "match-visible", portage.dep_getkey(mykey)):
1353 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1354 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1355 print colorize("BAD", "*** page for details.")
1356 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1359 raise portage.exception.PackageNotFound(
1360 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1361 if not self.create(["ebuild", myroot, mykey],
1362 None, "--onlydeps" not in self.myopts):
1363 return (0,myfavorites)
1364 elif not "--oneshot" in self.myopts:
1365 myfavorites.append(mykey)
1367 if not is_valid_package_atom(x):
1368 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1370 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1371 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1375 if "--usepkg" in self.myopts:
1376 mykey = portage.dep_expand(x, mydb=bindb,
1377 settings=pkgsettings)
1378 if (mykey and not mykey.startswith("null/")) or \
1379 "--usepkgonly" in self.myopts:
1380 arg_atoms.append((x, mykey))
1383 mykey = portage.dep_expand(x,
1384 mydb=portdb, settings=pkgsettings)
1385 arg_atoms.append((x, mykey))
1386 except ValueError, errpkgs:
1387 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1388 print "!!! one of the following fully-qualified ebuild names instead:\n"
1389 for i in errpkgs[0]:
1390 print " " + green(i)
1394 if "--update" in self.myopts:
1395 """Make sure all installed slots are updated when possible. Do this
1396 with --emptytree also, to ensure that all slots are remerged."""
1397 vardb = self.trees[self.target_root]["vartree"].dbapi
1399 for myarg, myatom in arg_atoms:
1400 greedy_atoms.append((myarg, myatom))
1402 for cpv in vardb.match(myatom):
1403 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1406 if "--usepkg" in self.myopts:
1407 mymatches = bindb.match(myatom)
1408 if "--usepkgonly" not in self.myopts:
1409 mymatches = visible(mymatches)
1410 best_pkg = portage.best(mymatches)
1412 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1413 best_pkgs.append(("binary", best_pkg, best_slot))
1414 if "--usepkgonly" not in self.myopts:
1415 best_pkg = portage.best(portdb.match(myatom))
1417 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1418 best_pkgs.append(("ebuild", best_pkg, best_slot))
1420 best_pkg = portage.best([x[1] for x in best_pkgs])
1421 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1422 best_slot = best_pkgs[0][2]
1423 myslots.add(best_slot)
1424 if len(myslots) > 1:
1425 for myslot in myslots:
1426 myslot_atom = "%s:%s" % \
1427 (portage.dep_getkey(myatom), myslot)
1429 if "--usepkgonly" not in self.myopts and \
1430 self.trees[self.target_root][
1431 "porttree"].dbapi.match(myslot_atom):
1433 elif "--usepkg" in self.myopts:
1434 mymatches = bindb.match(myslot_atom)
1435 if "--usepkgonly" not in self.myopts:
1436 mymatches = visible(mymatches)
1440 greedy_atoms.append((myarg, myslot_atom))
1441 arg_atoms = greedy_atoms
1443 """ These are used inside self.create() in order to ensure packages
1444 that happen to match arguments are not incorrectly marked as nomerge."""
1445 self.args_keys = [x[1] for x in arg_atoms]
1446 for myarg, myatom in arg_atoms:
1448 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1449 except portage.exception.MissingSignature, e:
1450 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1451 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1452 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1453 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1454 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1456 except portage.exception.InvalidSignature, e:
1457 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1458 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1459 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1460 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1461 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1463 except SystemExit, e:
1464 raise # Needed else can't exit
1465 except Exception, e:
1466 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1467 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1471 return (0,myfavorites)
1472 elif not "--oneshot" in self.myopts:
1473 mykey = portage.dep_getkey(myatom)
1474 if mykey not in myfavorites:
1475 myfavorites.append(mykey)
1478 if "--usepkgonly" in self.myopts:
1479 for xs in self.digraph.all_nodes():
1480 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1484 print "Missing binary for:",xs[2]
1486 if not self.validate_blockers():
1487 return False, myfavorites
1489 # We're true here unless we are missing binaries.
1490 return (not missing,myfavorites)
1492 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1493 myuse=None, raise_on_missing=False, priority=DepPriority(),
1494 rev_deps=False, parent_arg=None):
1495 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1496 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1497 myparent = the node whose depstring is being passed in
1498 arg = package was specified on the command line, merge even if it's already installed
1499 myuse = USE flags at present
1500 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1501 else continue trying.
1502 return 1 on success, 0 for failure
1505 portdb = self.trees[myroot]["porttree"].dbapi
1506 bindb = self.trees[myroot]["bintree"].dbapi
1507 vardb = self.trees[myroot]["vartree"].dbapi
1508 pkgsettings = self.pkgsettings[myroot]
1510 p_type, p_root, p_key, p_status = myparent
1512 if "--debug" in self.myopts:
1514 print "Parent: ",myparent
1515 print "Depstring:",depstring
1517 print "Reverse:", rev_deps
1518 print "Priority:", priority
1520 #processing dependencies
1521 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1522 dependencies are satisfiable. """
1524 mymerge = [depstring]
1525 pprovided = pkgsettings.pprovideddict.get(
1526 portage.dep_getkey(depstring))
1527 if pprovided and portage.match_from_list(depstring, pprovided):
1531 if myparent and p_status == "nomerge":
1532 portage.dep._dep_check_strict = False
1533 mycheck = portage.dep_check(depstring, None,
1534 pkgsettings, myuse=myuse,
1535 use_binaries=("--usepkgonly" in self.myopts),
1536 myroot=myroot, trees=self.trees)
1538 portage.dep._dep_check_strict = True
1542 show_invalid_depstring_notice(
1543 myparent, depstring, mycheck[1])
1545 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1547 mymerge = mycheck[1]
1549 if not mymerge and arg and \
1550 portage.best_match_to_list(depstring, self.args_keys):
1551 # A provided package has been specified on the command line. The
1552 # package will not be merged and a warning will be displayed.
1553 self._pprovided_args.append(arg)
1556 # The parent is added after it's own dep_check call so that it
1557 # isn't allowed to satisfy a direct bootstrap dependency on itself
1558 # via an old-style virtual. This isn't a problem with new-style
1559 # virtuals, which are preferenced in dep_zapdeps by looking only at
1560 # the depstring, vdb, and available packages.
1562 p_type, p_root, p_key, p_status = myparent
1563 if p_status == "merge":
1564 # Update old-style virtuals if this package provides any.
1565 # These are needed for dep_virtual calls inside dep_check.
1566 self.pkgsettings[p_root].setinst(p_key,
1567 self.trees[p_root][self.pkg_tree_map[p_type]].dbapi)
1569 if "--debug" in self.myopts:
1570 print "Candidates:",mymerge
1574 selected_pkg = ["blocks", myroot, x[1:], None]
1576 #We are not processing a blocker but a normal dependency
1578 """In some cases, dep_check will return deps that shouldn't
1579 be proccessed any further, so they are identified and
1581 if "empty" not in self.myparams and \
1582 "deep" not in self.myparams and \
1583 not ("--update" in self.myopts and parent_arg) and \
1587 # List of acceptable packages, ordered by type preference.
1588 matched_packages = []
1589 myeb_matches = portdb.xmatch("match-visible", x)
1591 if "--usepkgonly" not in self.myopts:
1592 myeb = portage.best(myeb_matches)
1595 if "--usepkg" in self.myopts:
1596 # The next line assumes the binarytree has been populated.
1597 # XXX: Need to work out how we use the binary tree with roots.
1598 myeb_pkg_matches = bindb.match(x)
1599 if "--usepkgonly" not in self.myopts:
1600 # Remove any binary package entries that are masked in the portage tree (#55871)
1601 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1602 if pkg in myeb_matches or \
1603 not portdb.cpv_exists(pkg)]
1604 if myeb_pkg_matches:
1605 myeb_pkg = portage.best(myeb_pkg_matches)
1607 if myeb_pkg and "--newuse" in self.myopts:
1608 iuses = set(filter_iuse_defaults(
1609 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1610 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1612 if "--usepkgonly" not in self.myopts and myeb:
1615 pkgsettings.setcpv(myeb, mydb=mydb)
1617 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1618 now_use = pkgsettings["USE"].split()
1619 forced_flags = set()
1620 forced_flags.update(pkgsettings.useforce)
1621 forced_flags.update(pkgsettings.usemask)
1623 if "--usepkgonly" not in self.myopts and myeb:
1624 cur_iuse = set(filter_iuse_defaults(
1625 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1626 if iuses.symmetric_difference(
1627 cur_iuse).difference(forced_flags):
1629 elif iuses.intersection(old_use) != \
1630 cur_iuse.intersection(now_use):
1634 self.trees[myroot]["bintree"].dbapi.aux_get(
1635 myeb_pkg, ["USE"])[0].split()
1636 matched_packages.append(
1637 ["binary", myroot, myeb_pkg, binpkguseflags])
1639 if "--usepkgonly" not in self.myopts and myeb_matches:
1640 matched_packages.append(
1641 ["ebuild", myroot, myeb, None])
1643 if not matched_packages and \
1644 not (arg and "selective" not in self.myparams):
1645 """Fall back to the installed package database. This is a
1646 last resort because the metadata tends to diverge from that
1647 of the ebuild in the tree."""
1648 myeb_inst_matches = vardb.match(x)
1649 if "--usepkgonly" not in self.myopts:
1650 """ TODO: Improve masking check for installed and
1651 binary packages. bug #149816"""
1652 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1653 if not portdb.cpv_exists(pkg)]
1655 if myeb_inst_matches:
1656 myeb_inst = portage.best(myeb_inst_matches)
1658 binpkguseflags = vardb.aux_get(
1659 myeb_inst, ["USE"])[0].split()
1660 matched_packages.append(
1661 ["installed", myroot, myeb_inst, binpkguseflags])
1663 if not matched_packages:
1664 if raise_on_missing:
1671 xfrom = '(dependency required by '+ \
1672 green('"%s"' % myparent[2]) + \
1673 red(' [%s]' % myparent[0]) + ')'
1674 alleb = portdb.xmatch("match-all", x)
1676 if "--usepkgonly" not in self.myopts:
1677 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1678 print "!!! One of the following masked packages is required to complete your request:"
1681 mreasons = portage.getmaskingstatus(p,
1682 settings=pkgsettings, portdb=portdb)
1683 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1684 comment, filename = portage.getmaskingreason(p,
1685 settings=pkgsettings, portdb=portdb, return_location=True)
1686 if comment and comment != oldcomment:
1689 oldcomment = comment
1691 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1692 print "refer to the Gentoo Handbook."
1694 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1695 print "!!! Either add a suitable binary package or compile from an ebuild."
1697 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1703 if "--debug" in self.myopts:
1704 for pkg in matched_packages:
1705 print (pkg[0] + ":").rjust(10), pkg[2]
1707 if len(matched_packages) > 1:
1708 bestmatch = portage.best(
1709 [pkg[2] for pkg in matched_packages])
1710 matched_packages = [pkg for pkg in matched_packages \
1711 if pkg[2] == bestmatch]
1713 # ordered by type preference ("ebuild" type is the last resort)
1714 selected_pkg = matched_packages[0]
1715 pkgtype, myroot, mycpv, myuse = selected_pkg
1716 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1717 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1718 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1719 existing_node = self._slot_node_map[myroot].get(
1722 e_type, myroot, e_cpv, e_status = existing_node
1723 if portage.match_from_list(x, [e_cpv]):
1724 # The existing node can be reused.
1725 selected_pkg = [e_type, myroot, e_cpv,
1726 self.useFlags[myroot][e_cpv]]
1729 #we are a dependency, so we want to be unconditionally added
1730 mypriority = priority.copy()
1732 mypriority.satisfied = True
1733 if not self.create(selected_pkg[0:3], myparent,
1734 myuse=selected_pkg[-1], priority=mypriority,
1735 rev_dep=rev_deps, arg=arg):
1738 #if mysource is not set, then we are a command-line dependency and should not be added
1739 #if --onlydeps is specified.
1740 if not self.create(selected_pkg[0:3], myparent,
1741 addme=("--onlydeps" not in self.myopts),
1742 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1745 if "--debug" in self.myopts:
1746 print "Exiting...",myparent
1749 def validate_blockers(self):
1750 """Remove any blockers from the digraph that do not match any of the
1751 packages within the graph. If necessary, create hard deps to ensure
1752 correct merge order such that mutually blocking packages are never
1753 installed simultaneously."""
1755 if "--buildpkgonly" in self.myopts or \
1756 "--nodeps" in self.myopts:
1760 for myroot in self.trees:
1762 modified_slots[myroot] = myslots
1763 final_db = self.mydbapi[myroot]
1764 slot_node_map = self._slot_node_map[myroot]
1765 for slot_atom, mynode in slot_node_map.iteritems():
1766 mytype, myroot, mycpv, mystatus = mynode
1767 if mystatus == "merge":
1768 myslots[slot_atom] = mycpv
1770 #if "deep" in self.myparams:
1772 # Pull in blockers from all installed packages that haven't already
1773 # been pulled into the depgraph. This is not enabled by default
1774 # due to the performance penalty that is incurred by all the
1775 # additional dep_check calls that are required.
1777 # Optimization hack for dep_check calls that minimizes the
1778 # available matches by replacing the portdb with a fakedbapi
1780 class FakePortageTree(object):
1781 def __init__(self, mydb):
1783 dep_check_trees = {}
1784 for myroot in self.trees:
1785 dep_check_trees[myroot] = self.trees[myroot].copy()
1786 dep_check_trees[myroot]["porttree"] = \
1787 FakePortageTree(self.mydbapi[myroot])
1789 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1790 for myroot in self.trees:
1791 pkg_node_map = self.pkg_node_map[myroot]
1792 vardb = self.trees[myroot]["vartree"].dbapi
1793 portdb = self.trees[myroot]["porttree"].dbapi
1794 pkgsettings = self.pkgsettings[myroot]
1795 final_db = self.mydbapi[myroot]
1796 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
1797 blocker_cache = BlockerCache(myroot, vardb)
1798 for pkg in cpv_all_installed:
1799 blocker_atoms = None
1800 matching_node = pkg_node_map.get(pkg, None)
1801 if matching_node and \
1802 matching_node[3] == "nomerge":
1804 # If this node has any blockers, create a "nomerge"
1805 # node for it so that they can be enforced.
1806 self.spinner.update()
1807 blocker_data = blocker_cache.get(pkg)
1809 blocker_atoms = blocker_data.atoms
1811 dep_vals = vardb.aux_get(pkg, dep_keys)
1812 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
1813 depstr = " ".join(dep_vals)
1814 # It is crucial to pass in final_db here in order to
1815 # optimize dep_check calls by eliminating atoms via
1816 # dep_wordreduce and dep_eval calls.
1818 portage.dep._dep_check_strict = False
1820 success, atoms = portage.dep_check(depstr,
1821 final_db, pkgsettings, myuse=myuse,
1822 trees=dep_check_trees, myroot=myroot)
1823 except Exception, e:
1824 if isinstance(e, SystemExit):
1826 # This is helpful, for example, if a ValueError
1827 # is thrown from cpv_expand due to multiple
1828 # matches (this can happen if an atom lacks a
1830 show_invalid_depstring_notice(
1831 ("installed", myroot, pkg, "nomerge"),
1836 portage.dep._dep_check_strict = True
1838 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
1839 vardb.aux_get(pkg, ["SLOT"])[0])
1840 if slot_atom in modified_slots[myroot]:
1841 # This package is being replaced anyway, so
1842 # ignore invalid dependencies so as not to
1843 # annoy the user too much (otherwise they'd be
1844 # forced to manually unmerge it first).
1846 show_invalid_depstring_notice(
1847 ("installed", myroot, pkg, "nomerge"),
1850 blocker_atoms = [myatom for myatom in atoms \
1851 if myatom.startswith("!")]
1852 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
1853 blocker_cache[pkg] = \
1854 blocker_cache.BlockerData(counter, blocker_atoms)
1856 # Don't store this parent in pkg_node_map, because it's
1857 # not needed there and it might overwrite a "merge"
1858 # node with the same cpv.
1859 myparent = ("installed", myroot, pkg, "nomerge")
1860 for myatom in blocker_atoms:
1861 blocker = ("blocks", myroot, myatom[1:])
1863 self.blocker_parents.get(blocker, None)
1866 self.blocker_parents[blocker] = myparents
1867 myparents.add(myparent)
1868 blocker_cache.flush()
1871 for blocker in self.blocker_parents.keys():
1872 mytype, myroot, mydep = blocker
1873 initial_db = self.trees[myroot]["vartree"].dbapi
1874 final_db = self.mydbapi[myroot]
1875 blocked_initial = initial_db.match(mydep)
1876 blocked_final = final_db.match(mydep)
1877 if not blocked_initial and not blocked_final:
1878 del self.blocker_parents[blocker]
1880 blocked_slots_initial = {}
1881 blocked_slots_final = {}
1882 for cpv in blocked_initial:
1883 blocked_slots_initial[cpv] = \
1884 "%s:%s" % (portage.dep_getkey(cpv),
1885 initial_db.aux_get(cpv, ["SLOT"])[0])
1886 for cpv in blocked_final:
1887 blocked_slots_final[cpv] = \
1888 "%s:%s" % (portage.dep_getkey(cpv),
1889 final_db.aux_get(cpv, ["SLOT"])[0])
1890 blocked_slots_final_values = set(blocked_slots_final.itervalues())
1891 for parent in list(self.blocker_parents[blocker]):
1892 ptype, proot, pcpv, pstatus = parent
1893 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1894 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1895 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1896 parent_static = pslot_atom not in modified_slots[proot]
1897 unresolved_blocks = False
1898 depends_on_order = set()
1899 for cpv in blocked_initial:
1900 slot_atom = blocked_slots_initial[cpv]
1901 if slot_atom == pslot_atom:
1902 # The parent blocks an initial package in the same
1903 # slot as itself. The merge/nomerge status of neither
1904 # node matters. In any case, this particular block is
1905 # automatically resolved.
1907 if parent_static and \
1908 slot_atom not in modified_slots[myroot]:
1909 # This blocker will be handled the next time that a
1910 # merge of either package is triggered.
1912 if pstatus == "merge" and \
1913 slot_atom not in blocked_slots_final_values:
1914 upgrade_matches = final_db.match(slot_atom)
1916 # Apparently an upgrade may be able to invalidate
1919 self.pkg_node_map[proot][upgrade_matches[0]]
1920 depends_on_order.add(upgrade_node)
1922 # None of the above blocker resolutions techniques apply,
1923 # so apparently this one is unresolvable.
1924 unresolved_blocks = True
1925 for cpv in blocked_final:
1926 slot_atom = blocked_slots_final[cpv]
1927 if slot_atom == pslot_atom:
1928 # The parent blocks itself, so the merge order does not
1929 # need to be enforced.
1931 if parent_static and \
1932 slot_atom not in modified_slots[myroot]:
1933 # This blocker will be handled the next time that a
1934 # merge of either package is triggered.
1936 # None of the above blocker resolutions techniques apply,
1937 # so apparently this one is unresolvable.
1938 unresolved_blocks = True
1939 if not unresolved_blocks and depends_on_order:
1940 for node in depends_on_order:
1941 # Enforce correct merge order with a hard dep.
1942 self.digraph.addnode(node, parent,
1943 priority=DepPriority(buildtime=True))
1944 # Count references to this blocker so that it can be
1945 # invalidated after nodes referencing it have been
1947 self.blocker_digraph.addnode(node, blocker)
1948 if not unresolved_blocks and not depends_on_order:
1949 self.blocker_parents[blocker].remove(parent)
1950 if not self.blocker_parents[blocker]:
1951 del self.blocker_parents[blocker]
1952 # Validate blockers that depend on merge order.
1953 if not self.blocker_digraph.empty():
1955 if self._slot_collision_info:
1956 # The user is only notified of a slot collision if there are no
1957 # unresolvable blocks.
1958 for x in self.altlist():
1959 if x[0] == "blocks":
1961 self._show_slot_collision_notice(self._slot_collision_info[0])
1962 if not self._accept_collisions():
1966 def _accept_collisions(self):
1968 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
1969 if x in self.myopts:
1974 def _merge_order_bias(self, mygraph):
1975 """Order nodes from highest to lowest overall reference count for
1976 optimal leaf node selection."""
1978 for node in mygraph.order:
1979 node_info[node] = len(mygraph.parent_nodes(node))
1980 def cmp_merge_preference(node1, node2):
1981 return node_info[node2] - node_info[node1]
1982 mygraph.order.sort(cmp_merge_preference)
1984 def altlist(self, reversed=False):
1985 if reversed in self._altlist_cache:
1986 return self._altlist_cache[reversed][:]
1988 retlist = self.altlist()
1990 self._altlist_cache[reversed] = retlist[:]
1992 mygraph=self.digraph.copy()
1993 self._merge_order_bias(mygraph)
1994 myblockers = self.blocker_digraph.copy()
1996 circular_blocks = False
2000 get_nodes = mygraph.root_nodes
2002 get_nodes = mygraph.leaf_nodes
2003 for cpv, node in self.pkg_node_map["/"].iteritems():
2004 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
2005 asap_nodes.append(node)
2007 ignore_priority_range = [None]
2008 ignore_priority_range.extend(
2009 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2010 tree_mode = "--tree" in self.myopts
2011 while not mygraph.empty():
2012 ignore_priority = None
2015 """ASAP nodes are merged before their soft deps."""
2016 for node in asap_nodes:
2017 if not mygraph.contains(node):
2018 asap_nodes.remove(node)
2020 if not mygraph.child_nodes(node,
2021 ignore_priority=DepPriority.SOFT):
2023 asap_nodes.remove(node)
2026 for ignore_priority in ignore_priority_range:
2027 nodes = get_nodes(ignore_priority=ignore_priority)
2030 selected_nodes = None
2032 if ignore_priority <= DepPriority.SOFT:
2033 if ignore_priority is None and not tree_mode:
2034 # Greedily pop all of these nodes since no relationship
2035 # has been ignored. This optimization destroys --tree
2036 # output, so it's disabled in reversed mode.
2037 selected_nodes = nodes
2039 # For optimal merge order:
2040 # * Only pop one node.
2041 # * Removing a root node (node without a parent)
2042 # will not produce a leaf node, so avoid it.
2044 if mygraph.parent_nodes(node):
2045 # found a non-root node
2046 selected_nodes = [node]
2048 if not selected_nodes:
2049 # settle for a root node
2050 selected_nodes = [nodes[0]]
2052 """Recursively gather a group of nodes that RDEPEND on
2053 eachother. This ensures that they are merged as a group
2054 and get their RDEPENDs satisfied as soon as possible."""
2055 def gather_deps(mergeable_nodes, selected_nodes, node):
2056 if node in selected_nodes:
2058 if node not in mergeable_nodes:
2060 selected_nodes.add(node)
2061 for child in mygraph.child_nodes(node,
2062 ignore_priority=DepPriority.SOFT):
2064 mergeable_nodes, selected_nodes, child):
2067 mergeable_nodes = set(nodes)
2069 selected_nodes = set()
2071 mergeable_nodes, selected_nodes, node):
2074 selected_nodes = None
2076 if not selected_nodes:
2077 if not myblockers.is_empty():
2078 """A blocker couldn't be circumnavigated while keeping all
2079 dependencies satisfied. The user will have to resolve this
2080 manually. This is a panic condition and thus the order
2081 doesn't really matter, so just pop a random node in order
2082 to avoid a circular dependency panic if possible."""
2083 if not circular_blocks:
2084 circular_blocks = True
2085 blocker_deps = myblockers.leaf_nodes()
2087 selected_nodes = [blocker_deps.pop()]
2089 if not selected_nodes:
2090 # No leaf nodes are available, so we have a circular
2091 # dependency panic situation. Reduce the noise level to a
2092 # minimum via repeated elimination of root nodes since they
2093 # have no parents and thus can not be part of a cycle.
2095 root_nodes = mygraph.root_nodes(
2096 ignore_priority=DepPriority.SOFT)
2099 for node in root_nodes:
2100 mygraph.remove(node)
2101 # Display the USE flags that are enabled on nodes that are part
2102 # of dependency cycles in case that helps the user decide to
2103 # disable some of them.
2105 tempgraph = mygraph.copy()
2106 while not tempgraph.empty():
2107 nodes = tempgraph.leaf_nodes()
2109 node = tempgraph.order[0]
2112 display_order.append(list(node))
2113 tempgraph.remove(node)
2114 display_order.reverse()
2115 self.myopts.pop("--quiet", None)
2116 self.myopts.pop("--verbose", None)
2117 self.myopts["--tree"] = True
2118 self.display(display_order)
2119 print "!!! Error: circular dependencies:"
2121 mygraph.debug_print()
2123 print "!!! Note that circular dependencies can often be avoided by temporarily"
2124 print "!!! disabling USE flags that trigger optional dependencies."
2127 for node in selected_nodes:
2128 retlist.append(list(node))
2129 mygraph.remove(node)
2130 if not reversed and not circular_blocks and myblockers.contains(node):
2131 """This node may have invalidated one or more blockers."""
2132 myblockers.remove(node)
2133 for blocker in myblockers.root_nodes():
2134 if not myblockers.child_nodes(blocker):
2135 myblockers.remove(blocker)
2136 del self.blocker_parents[blocker]
2139 """Blocker validation does not work with reverse mode,
2140 so self.altlist() should first be called with reverse disabled
2141 so that blockers are properly validated."""
2142 self.blocker_digraph = myblockers
2144 """ Add any unresolved blocks so that they can be displayed."""
2145 for blocker in self.blocker_parents:
2146 retlist.append(list(blocker))
2147 self._altlist_cache[reversed] = retlist[:]
2150 def xcreate(self,mode="system"):
2151 vardb = self.trees[self.target_root]["vartree"].dbapi
2152 portdb = self.trees[self.target_root]["porttree"].dbapi
2153 bindb = self.trees[self.target_root]["bintree"].dbapi
2154 def visible(mylist):
2155 matches = portdb.gvisible(portdb.visible(mylist))
2156 return [x for x in mylist \
2157 if x in matches or not portdb.cpv_exists(x)]
2158 world_problems = False
2160 mylist = getlist(self.settings, "system")
2163 worldlist = getlist(self.settings, "world")
2164 sysdict = genericdict(getlist(self.settings, "system"))
2165 worlddict=genericdict(worldlist)
2167 for x in worlddict.keys():
2168 if not portage.isvalidatom(x):
2169 world_problems = True
2170 elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
2171 world_problems = True
2173 sysdict[x]=worlddict[x]
2175 mylist = sysdict.keys()
2179 mykey = portage.dep_getkey(atom)
2181 newlist.append(atom)
2182 """Make sure all installed slots are updated when possible.
2183 Do this with --emptytree also, to ensure that all slots are
2186 for cpv in vardb.match(mykey):
2187 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2190 if "--usepkg" in self.myopts:
2191 mymatches = bindb.match(atom)
2192 if "--usepkgonly" not in self.myopts:
2193 mymatches = visible(mymatches)
2194 best_pkg = portage.best(mymatches)
2196 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2197 best_pkgs.append(("binary", best_pkg, best_slot))
2198 if "--usepkgonly" not in self.myopts:
2199 best_pkg = portage.best(portdb.match(atom))
2201 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2202 best_pkgs.append(("ebuild", best_pkg, best_slot))
2204 best_pkg = portage.best([x[1] for x in best_pkgs])
2205 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2206 best_slot = best_pkgs[0][2]
2207 myslots.add(best_slot)
2208 if len(myslots) > 1:
2209 for myslot in myslots:
2210 myslot_atom = "%s:%s" % (mykey, myslot)
2212 if "--usepkgonly" not in self.myopts and \
2213 self.trees[self.target_root][
2214 "porttree"].dbapi.match(myslot_atom):
2216 elif "--usepkg" in self.myopts:
2217 mymatches = bindb.match(myslot_atom)
2218 if "--usepkgonly" not in self.myopts:
2219 mymatches = visible(mymatches)
2223 newlist.append(myslot_atom)
2227 for mydep in mylist:
2229 if not self.select_dep(
2230 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2231 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2234 missing_atoms.append(mydep)
2236 if not self.validate_blockers():
2240 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2241 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2244 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2245 " Ebuilds for the following packages are either all"
2246 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2247 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2251 def display(self,mylist,verbosity=None):
2252 if verbosity is None:
2253 verbosity = ("--quiet" in self.myopts and 1 or \
2254 "--verbose" in self.myopts and 3 or 2)
2258 counters = PackageCounters()
2260 if verbosity == 1 and "--verbose" not in self.myopts:
2261 def create_use_string(*args):
2264 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2266 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2267 alphabetical=("--alphabetical" in self.myopts)):
2275 cur_iuse = set(cur_iuse)
2276 enabled_flags = cur_iuse.intersection(cur_use)
2277 removed_iuse = set(old_iuse).difference(cur_iuse)
2278 any_iuse = cur_iuse.union(old_iuse)
2279 any_iuse = list(any_iuse)
2281 for flag in any_iuse:
2284 if flag in enabled_flags:
2286 if is_new or flag in old_use and all_flags:
2287 flag_str = red(flag)
2288 elif flag not in old_iuse:
2289 flag_str = yellow(flag) + "%*"
2290 elif flag not in old_use:
2291 flag_str = green(flag) + "*"
2292 elif flag in removed_iuse:
2294 flag_str = yellow("-" + flag) + "%"
2297 flag_str = "(" + flag_str + ")"
2298 removed.append(flag_str)
2301 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2302 flag_str = blue("-" + flag)
2303 elif flag not in old_iuse:
2304 flag_str = yellow("-" + flag)
2305 if flag not in iuse_forced:
2307 elif flag in old_use:
2308 flag_str = green("-" + flag) + "*"
2310 if flag in iuse_forced:
2311 flag_str = "(" + flag_str + ")"
2313 enabled.append(flag_str)
2315 disabled.append(flag_str)
2318 ret = " ".join(enabled)
2320 ret = " ".join(enabled + disabled + removed)
2322 ret = '%s="%s" ' % (name, ret)
2326 # FIXME: account for the possibility of different overlays in
2327 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2328 overlays = self.settings["PORTDIR_OVERLAY"].split()
2329 overlays_real = [os.path.realpath(t) \
2330 for t in self.settings["PORTDIR_OVERLAY"].split()]
2337 if "blocks" == x[0]:
2339 graph_key = tuple(x)
2340 if "--tree" in self.myopts:
2341 depth = len(tree_nodes)
2342 while depth and graph_key not in \
2343 self.digraph.child_nodes(tree_nodes[depth-1]):
2345 tree_nodes = tree_nodes[:depth]
2346 tree_nodes.append(graph_key)
2347 node_depth[graph_key] = depth
2349 last_merge_depth = 0
2350 for i in xrange(len(mylist)-1,-1,-1):
2351 if "blocks" == mylist[i][0]:
2353 graph_key = tuple(mylist[i])
2354 if mylist[i][-1] != "nomerge":
2355 last_merge_depth = node_depth[graph_key]
2357 if node_depth[graph_key] >= last_merge_depth or \
2358 i < len(mylist) - 1 and \
2359 node_depth[graph_key] >= node_depth[tuple(mylist[i+1])]:
2361 del node_depth[graph_key]
2364 display_overlays=False
2365 # files to fetch list - avoids counting a same file twice
2366 # in size display (verbose mode)
2372 portdb = self.trees[myroot]["porttree"].dbapi
2373 bindb = self.trees[myroot]["bintree"].dbapi
2374 vardb = self.trees[myroot]["vartree"].dbapi
2375 vartree = self.trees[myroot]["vartree"]
2376 pkgsettings = self.pkgsettings[myroot]
2381 addl=""+red("B")+" "+fetch+" "
2382 counters.blocks += 1
2383 resolved = portage.key_expand(
2384 pkg_key, mydb=vardb, settings=pkgsettings)
2385 if "--columns" in self.myopts and "--quiet" in self.myopts:
2386 print addl,red(resolved),
2388 print "["+x[0]+" "+addl+"]",red(resolved),
2389 block_parents = self.blocker_parents[tuple(x)]
2390 block_parents = set([pnode[2] for pnode in block_parents])
2391 block_parents = ", ".join(block_parents)
2393 print bad("(\"%s\" is blocking %s)") % \
2394 (pkg_key, block_parents)
2396 print bad("(is blocking %s)") % block_parents
2398 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2399 binary_package = True
2400 if "ebuild" == pkg_type:
2401 if "merge" == x[3] or \
2402 not vartree.dbapi.cpv_exists(pkg_key):
2403 """An ebuild "merge" node or a --onlydeps "nomerge"
2405 binary_package = False
2406 pkgsettings.setcpv(pkg_key, mydb=portdb)
2407 if pkg_key not in self.useFlags[myroot]:
2408 self.useFlags[myroot][pkg_key] = \
2409 pkgsettings["USE"].split()
2411 # An ebuild "nomerge" node, so USE come from the vardb.
2412 mydbapi = vartree.dbapi
2413 if pkg_key not in self.useFlags[myroot]:
2414 """If this is a --resume then the USE flags need to be
2415 fetched from the appropriate locations here."""
2416 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2417 pkg_key, ["USE"])[0].split()
2419 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2420 "fetch" in portdb.aux_get(
2421 x[2], ["RESTRICT"])[0].split():
2423 counters.restrict_fetch += 1
2424 if portdb.fetch_check(
2425 pkg_key, self.useFlags[myroot][pkg_key]):
2427 counters.restrict_fetch_satisfied += 1
2429 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2430 #param is used for -u, where you still *do* want to see when something is being upgraded.
2432 if vardb.cpv_exists(pkg_key):
2433 addl=" "+yellow("R")+fetch+" "
2434 if x[3] != "nomerge":
2435 counters.reinst += 1
2436 elif vardb.match(portage.dep_getkey(pkg_key)):
2437 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2438 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2439 portage.pkgsplit(x[2])[0])
2440 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2441 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2443 myoldbest=portage.best(myinslotlist)
2445 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2447 addl+=turquoise("U")+blue("D")
2448 counters.downgrades += 1
2451 addl+=turquoise("U")+" "
2452 counters.upgrades += 1
2454 # New slot, mark it new.
2455 addl=" "+green("NS")+fetch+" "
2456 counters.newslot += 1
2458 if "--changelog" in self.myopts:
2459 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2460 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2461 inst_matches = vardb.match(slot_atom)
2463 changelogs.extend(self.calc_changelog(
2464 portdb.findname(pkg_key),
2465 inst_matches[0], pkg_key))
2467 addl=" "+green("N")+" "+fetch+" "
2472 if pkg_key in self.useFlags[myroot]:
2474 cur_iuse = list(filter_iuse_defaults(
2475 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2477 forced_flags = set()
2478 if not binary_package:
2479 forced_flags.update(pkgsettings.useforce)
2480 forced_flags.update(pkgsettings.usemask)
2482 cur_iuse = portage.unique_array(cur_iuse)
2484 cur_use = self.useFlags[myroot][pkg_key]
2485 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2491 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2492 old_iuse, old_use = \
2493 self.trees[x[1]]["vartree"].dbapi.aux_get(
2494 pkg, ["IUSE", "USE"])
2495 old_iuse = list(set(
2496 filter_iuse_defaults(old_iuse.split())))
2498 old_use = old_use.split()
2505 old_use = [flag for flag in old_use if flag in old_iuse]
2507 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2509 use_expand.reverse()
2510 use_expand_hidden = \
2511 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2513 def map_to_use_expand(myvals, forcedFlags=False):
2516 for exp in use_expand:
2519 for val in myvals[:]:
2520 if val.startswith(exp.lower()+"_"):
2521 if val in forced_flags:
2522 forced[exp].add(val[len(exp)+1:])
2523 ret[exp].append(val[len(exp)+1:])
2526 forced["USE"] = [val for val in myvals \
2527 if val in forced_flags]
2528 for exp in use_expand_hidden:
2535 cur_iuse_map, iuse_forced = \
2536 map_to_use_expand(cur_iuse, forcedFlags=True)
2537 cur_use_map = map_to_use_expand(cur_use)
2538 old_iuse_map = map_to_use_expand(old_iuse)
2539 old_use_map = map_to_use_expand(old_use)
2542 use_expand.insert(0, "USE")
2544 for key in use_expand:
2545 if key in use_expand_hidden:
2547 verboseadd += create_use_string(key.upper(),
2548 cur_iuse_map[key], iuse_forced[key],
2549 cur_use_map[key], old_iuse_map[key],
2550 old_use_map[key], is_new)
2555 if x[0] == "ebuild" and x[-1]!="nomerge":
2557 myfilesdict = portdb.getfetchsizes(pkg_key,
2558 useflags=self.useFlags[myroot][pkg_key],
2560 except portage.exception.InvalidDependString, e:
2561 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2562 show_invalid_depstring_notice(x, src_uri, str(e))
2565 if myfilesdict is None:
2566 myfilesdict="[empty/missing/bad digest]"
2568 for myfetchfile in myfilesdict.keys():
2569 if myfetchfile not in myfetchlist:
2570 mysize+=myfilesdict[myfetchfile]
2571 myfetchlist.append(myfetchfile)
2572 counters.totalsize += mysize
2573 verboseadd+=format_size(mysize)+" "
2576 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2577 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2578 file_name = portdb.findname(pkg_key)
2579 if file_name: # It might not exist in the tree
2580 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2581 if (overlays_real.count(dir_name)>0):
2582 verboseadd+=teal("["+str(overlays_real.index(
2583 os.path.normpath(dir_name))+1)+"]")+" "
2584 display_overlays=True
2586 verboseadd += "[No ebuild?]"
2588 xs=portage.pkgsplit(x[2])
2595 if "COLUMNWIDTH" in self.settings:
2597 mywidth = int(self.settings["COLUMNWIDTH"])
2598 except ValueError, e:
2599 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2601 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2602 self.settings["COLUMNWIDTH"], noiselevel=-1)
2607 indent = " " * node_depth[tuple(x)]
2610 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2611 if myoldbest[-3:]=="-r0":
2612 myoldbest=myoldbest[:-3]
2613 myoldbest=blue("["+myoldbest+"]")
2618 if "--columns" in self.myopts:
2619 if "--quiet" in self.myopts:
2620 myprint=addl+" "+indent+darkgreen(xs[0])
2621 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2622 myprint=myprint+myoldbest
2623 myprint=myprint+darkgreen("to "+x[1])
2625 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2626 if (newlp-nc_len(myprint)) > 0:
2627 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2628 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2629 if (oldlp-nc_len(myprint)) > 0:
2630 myprint=myprint+" "*(oldlp-nc_len(myprint))
2631 myprint=myprint+myoldbest
2632 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2634 if x[3] == "nomerge":
2635 myprint = darkblue("[nomerge ] ")
2637 myprint = "[" + pkg_type + " " + addl + "] "
2638 myprint += indent + darkgreen(pkg_key) + " " + \
2639 myoldbest + darkgreen("to " + myroot) + " " + \
2642 if "--columns" in self.myopts:
2643 if "--quiet" in self.myopts:
2644 myprint=addl+" "+indent+darkgreen(xs[0])
2645 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2646 myprint=myprint+myoldbest
2648 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2649 if (newlp-nc_len(myprint)) > 0:
2650 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2651 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2652 if (oldlp-nc_len(myprint)) > 0:
2653 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2654 myprint=myprint+myoldbest+" "+verboseadd
2657 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2659 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2662 mysplit = portage.pkgsplit(x[2])
2663 if "--tree" not in self.myopts and mysplit and \
2664 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2667 if mysplit[2] == "r0":
2668 myversion = mysplit[1]
2670 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2672 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2673 if mylist.index(x) < len(mylist) - 1 and \
2674 "livecvsportage" not in self.settings.features:
2675 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2676 p.append(colorize("WARN", " then resume the merge."))
2686 if overlays and display_overlays:
2687 print "Portage overlays:"
2691 print " "+teal("["+str(y)+"]"),x
2693 if "--changelog" in self.myopts:
2695 for revision,text in changelogs:
2696 print bold('*'+revision)
2697 sys.stdout.write(text)
2699 if self._pprovided_args:
2701 msg.append(bad("\nWARNING: "))
2702 if len(self._pprovided_args) > 1:
2703 msg.append("Requested packages will not be " + \
2704 "merged because they are listed in\n")
2706 msg.append("A requested package will not be " + \
2707 "merged because it is listed in\n")
2708 msg.append(" package.provided:\n\n")
2709 for arg in self._pprovided_args:
2710 msg.append(" " + arg + "\n")
2712 sys.stderr.write("".join(msg))
2714 def calc_changelog(self,ebuildpath,current,next):
2715 current = '-'.join(portage.catpkgsplit(current)[1:])
2716 if current.endswith('-r0'): current = current[:-3]
2717 next = '-'.join(portage.catpkgsplit(next)[1:])
2718 if next.endswith('-r0'): next = next[:-3]
2719 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2721 changelog = open(changelogpath).read()
2722 except SystemExit, e:
2723 raise # Needed else can't exit
2726 divisions = self.find_changelog_tags(changelog)
2727 #print 'XX from',current,'to',next
2728 #for div,text in divisions: print 'XX',div
2729 # skip entries for all revisions above the one we are about to emerge
2730 for i in range(len(divisions)):
2731 if divisions[i][0]==next:
2732 divisions = divisions[i:]
2734 # find out how many entries we are going to display
2735 for i in range(len(divisions)):
2736 if divisions[i][0]==current:
2737 divisions = divisions[:i]
2740 # couldnt find the current revision in the list. display nothing
2744 def find_changelog_tags(self,changelog):
2748 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2750 if release is not None:
2751 divs.append((release,changelog))
2753 if release is not None:
2754 divs.append((release,changelog[:match.start()]))
2755 changelog = changelog[match.end():]
2756 release = match.group(1)
2757 if release.endswith('.ebuild'):
2758 release = release[:-7]
2759 if release.endswith('-r0'):
2760 release = release[:-3]
2763 return self.outdatedpackages
2765 class PackageCounters(object):
2775 self.restrict_fetch = 0
2776 self.restrict_fetch_satisfied = 0
2779 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2782 myoutput.append("Total: %s package" % total_installs)
2783 if total_installs != 1:
2784 myoutput.append("s")
2785 if total_installs != 0:
2786 myoutput.append(" (")
2787 if self.upgrades > 0:
2788 details.append("%s upgrade" % self.upgrades)
2789 if self.upgrades > 1:
2791 if self.downgrades > 0:
2792 details.append("%s downgrade" % self.downgrades)
2793 if self.downgrades > 1:
2796 details.append("%s new" % self.new)
2797 if self.newslot > 0:
2798 details.append("%s in new slot" % self.newslot)
2799 if self.newslot > 1:
2802 details.append("%s reinstall" % self.reinst)
2806 details.append("%s block" % self.blocks)
2809 myoutput.append(", ".join(details))
2810 if total_installs != 0:
2811 myoutput.append(")")
2812 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2813 if self.restrict_fetch:
2814 myoutput.append("\nFetch Restriction: %s package" % \
2815 self.restrict_fetch)
2816 if self.restrict_fetch > 1:
2817 myoutput.append("s")
2818 if self.restrict_fetch_satisfied < self.restrict_fetch:
2819 myoutput.append(bad(" (%s unsatisfied)") % \
2820 (self.restrict_fetch - self.restrict_fetch_satisfied))
2821 return "".join(myoutput)
2823 class MergeTask(object):
2825 def __init__(self, settings, trees, myopts):
2826 self.settings = settings
2827 self.target_root = settings["ROOT"]
2829 self.myopts = myopts
2831 if settings.get("PORTAGE_DEBUG", "") == "1":
2833 self.pkgsettings = {}
2834 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2835 if self.target_root != "/":
2836 self.pkgsettings["/"] = \
2837 portage.config(clone=trees["/"]["vartree"].settings)
2839 def merge(self, mylist, favorites, mtimedb):
2842 ldpath_mtimes = mtimedb["ldpath"]
2843 xterm_titles = "notitles" not in self.settings.features
2845 #check for blocking dependencies
2846 if "--fetchonly" not in self.myopts and \
2847 "--buildpkgonly" not in self.myopts:
2850 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2851 print "!!! the two packages cannot be installed on the same system together."
2852 print "!!! Please use 'emerge --pretend' to determine blockers."
2853 if "--quiet" not in self.myopts:
2854 show_blocker_docs_link()
2855 if "--pretend" not in self.myopts:
2857 del mtimedb["resume"]
2862 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
2863 mysysdict = genericdict(getlist(self.settings, "system"))
2864 if "--resume" in self.myopts:
2866 print colorize("GOOD", "*** Resuming merge...")
2867 emergelog(xterm_titles, " *** Resuming merge...")
2868 mymergelist=mtimedb["resume"]["mergelist"][:]
2869 if "--skipfirst" in self.myopts and mymergelist:
2870 del mtimedb["resume"]["mergelist"][0]
2873 validate_merge_list(self.trees, mymergelist)
2875 myfavs = portage.grabfile(
2876 os.path.join(self.target_root, portage.WORLD_FILE))
2877 myfavdict=genericdict(myfavs)
2878 for x in range(len(mylist)):
2879 if mylist[x][3]!="nomerge":
2880 # Add to the mergelist
2881 mymergelist.append(mylist[x])
2883 myfavkey=portage.cpv_getkey(mylist[x][2])
2884 if "--onlydeps" in self.myopts:
2886 # Add to the world file. Since we won't be able to later.
2887 if "--fetchonly" not in self.myopts and \
2888 myfavkey in favorites:
2889 #don't record if already in system profile or already recorded
2890 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
2891 #we don't have a favorites entry for this package yet; add one
2892 myfavdict[myfavkey]=myfavkey
2893 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
2894 if not ("--fetchonly" in self.myopts or \
2895 "--fetch-all-uri" in self.myopts or \
2896 "--pretend" in self.myopts):
2897 portage.write_atomic(
2898 os.path.join(self.target_root, portage.WORLD_FILE),
2899 "\n".join(myfavdict.values()))
2901 mtimedb["resume"]["mergelist"]=mymergelist[:]
2904 myfeat = self.settings.features[:]
2905 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
2907 if "parallel-fetch" in myfeat and \
2908 not ("--pretend" in self.myopts or \
2909 "--fetch-all-uri" in self.myopts or \
2910 "--fetchonly" in self.myopts):
2911 if "distlocks" not in myfeat:
2913 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
2914 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
2916 elif len(mymergelist) > 1:
2917 print ">>> starting parallel fetching"
2918 fetch_log = "/var/log/emerge-fetch.log"
2919 logfile = open(fetch_log, "w")
2920 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
2921 portage.util.apply_secpass_permissions(fetch_log,
2922 uid=portage.portage_uid, gid=portage.portage_gid,
2924 fetch_env = os.environ.copy()
2925 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
2926 fetch_env["PORTAGE_NICENESS"] = "0"
2927 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
2928 for myopt, myarg in self.myopts.iteritems():
2929 if myopt not in bad_resume_opts:
2931 fetch_args.append(myopt)
2933 fetch_args.append(myopt +"="+ myarg)
2934 portage.process.spawn(fetch_args, env=fetch_env,
2935 fd_pipes=fd_pipes, returnpid=True)
2936 logfile.close() # belongs to the spawned process
2939 for x in mymergelist:
2944 portdb = self.trees[myroot]["porttree"].dbapi
2945 bindb = self.trees[myroot]["bintree"].dbapi
2946 vartree = self.trees[myroot]["vartree"]
2947 pkgsettings = self.pkgsettings[myroot]
2950 y = portdb.findname(pkg_key)
2951 if "--pretend" not in self.myopts:
2952 print "\n>>> Emerging (" + \
2953 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2954 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
2955 colorize("GOOD", x[pkgindex]) + " to " + x[1]
2956 emergelog(xterm_titles, " >>> emerge ("+\
2957 str(mergecount)+" of "+str(len(mymergelist))+\
2958 ") "+x[pkgindex]+" to "+x[1])
2960 pkgsettings["EMERGE_FROM"] = x[0]
2961 pkgsettings.backup_changes("EMERGE_FROM")
2964 #buildsyspkg: Check if we need to _force_ binary package creation
2965 issyspkg = ("buildsyspkg" in myfeat) \
2966 and x[0] != "blocks" \
2967 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
2968 and "--buildpkg" not in self.myopts
2969 if x[0] in ["ebuild","blocks"]:
2970 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
2971 raise Exception, "Merging a blocker"
2972 elif "--fetchonly" in self.myopts or \
2973 "--fetch-all-uri" in self.myopts:
2974 if "--fetch-all-uri" in self.myopts:
2975 retval = portage.doebuild(y, "fetch", myroot,
2976 pkgsettings, self.edebug,
2977 "--pretend" in self.myopts, fetchonly=1,
2978 fetchall=1, mydbapi=portdb, tree="porttree")
2980 retval = portage.doebuild(y, "fetch", myroot,
2981 pkgsettings, self.edebug,
2982 "--pretend" in self.myopts, fetchonly=1,
2983 mydbapi=portdb, tree="porttree")
2984 if (retval is None) or retval:
2986 print "!!! Fetch for",y,"failed, continuing..."
2988 failed_fetches.append(pkg_key)
2991 portage.doebuild_environment(y, "setup", myroot,
2992 pkgsettings, self.edebug, 1, portdb)
2993 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
2994 portage.util.ensure_dirs(os.path.dirname(catdir),
2995 uid=portage.portage_uid, gid=portage.portage_gid,
2997 builddir_lock = None
3000 catdir_lock = portage.locks.lockdir(catdir)
3001 portage.util.ensure_dirs(catdir,
3002 uid=portage.portage_uid, gid=portage.portage_gid,
3004 builddir_lock = portage.locks.lockdir(
3005 pkgsettings["PORTAGE_BUILDDIR"])
3007 portage.locks.unlockdir(catdir_lock)
3010 msg = " === (%s of %s) Cleaning (%s::%s)" % \
3011 (mergecount, len(mymergelist), pkg_key, y)
3012 short_msg = "emerge: (%s of %s) %s Clean" % \
3013 (mergecount, len(mymergelist), pkg_key)
3014 emergelog(xterm_titles, msg, short_msg=short_msg)
3015 retval = portage.doebuild(y, "clean", myroot,
3016 pkgsettings, self.edebug, cleanup=1,
3017 mydbapi=portdb, tree="porttree")
3018 if retval != os.EX_OK:
3020 if "--buildpkg" in self.myopts or issyspkg:
3022 print ">>> This is a system package, " + \
3023 "let's pack a rescue tarball."
3024 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3025 (mergecount, len(mymergelist), pkg_key, y)
3026 short_msg = "emerge: (%s of %s) %s Compile" % \
3027 (mergecount, len(mymergelist), pkg_key)
3028 emergelog(xterm_titles, msg, short_msg=short_msg)
3029 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3030 retval = portage.doebuild(y, "package", myroot,
3031 pkgsettings, self.edebug, mydbapi=portdb,
3033 if retval != os.EX_OK:
3035 if "--buildpkgonly" not in self.myopts:
3036 bintree = self.trees[myroot]["bintree"]
3037 bintree.inject(pkg_key)
3038 mytbz2 = bintree.getname(pkg_key)
3039 msg = " === (%s of %s) Merging (%s::%s)" % \
3040 (mergecount, len(mymergelist), pkg_key, y)
3041 short_msg = "emerge: (%s of %s) %s Merge" % \
3042 (mergecount, len(mymergelist), pkg_key)
3043 emergelog(xterm_titles, msg, short_msg=short_msg)
3044 retval = portage.merge(pkgsettings["CATEGORY"],
3045 pkgsettings["PF"], pkgsettings["D"],
3046 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3047 "build-info"), myroot, pkgsettings,
3048 myebuild=pkgsettings["EBUILD"],
3049 mytree="porttree", mydbapi=portdb,
3050 vartree=vartree, prev_mtimes=ldpath_mtimes)
3051 if retval != os.EX_OK:
3053 elif "noclean" not in pkgsettings.features:
3054 portage.doebuild(y, "clean", myroot,
3055 pkgsettings, self.edebug, mydbapi=portdb,
3058 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3059 (mergecount, len(mymergelist), pkg_key, y)
3060 short_msg = "emerge: (%s of %s) %s Compile" % \
3061 (mergecount, len(mymergelist), pkg_key)
3062 emergelog(xterm_titles, msg, short_msg=short_msg)
3063 retval = portage.doebuild(y, "merge", myroot,
3064 pkgsettings, self.edebug, vartree=vartree,
3065 mydbapi=portdb, tree="porttree",
3066 prev_mtimes=ldpath_mtimes)
3067 if retval != os.EX_OK:
3071 portage.locks.unlockdir(builddir_lock)
3074 # Lock catdir for removal if empty.
3075 catdir_lock = portage.locks.lockdir(catdir)
3081 if e.errno not in (errno.ENOENT,
3082 errno.ENOTEMPTY, errno.EEXIST):
3085 portage.locks.unlockdir(catdir_lock)
3087 elif x[0]=="binary":
3089 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3090 if "--getbinpkg" in self.myopts:
3093 if "distlocks" in pkgsettings.features and \
3094 os.access(pkgsettings["PKGDIR"], os.W_OK):
3095 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3096 tbz2_lock = portage.locks.lockfile(mytbz2,
3098 if self.trees[myroot]["bintree"].isremote(pkg_key):
3099 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3100 (mergecount, len(mymergelist), pkg_key, mytbz2)
3101 short_msg = "emerge: (%s of %s) %s Fetch" % \
3102 (mergecount, len(mymergelist), pkg_key)
3103 emergelog(xterm_titles, msg, short_msg=short_msg)
3104 if not self.trees[myroot]["bintree"].gettbz2(
3109 portage.locks.unlockfile(tbz2_lock)
3111 if "--fetchonly" in self.myopts or \
3112 "--fetch-all-uri" in self.myopts:
3115 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3116 emergelog(xterm_titles, " === ("+str(mergecount)+\
3117 " of "+str(len(mymergelist))+") Merging Binary ("+\
3118 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3119 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3121 vartree=self.trees[myroot]["vartree"],
3122 prev_mtimes=ldpath_mtimes)
3123 if retval != os.EX_OK:
3125 #need to check for errors
3126 if "--buildpkgonly" not in self.myopts:
3127 self.trees[x[1]]["vartree"].inject(x[2])
3128 myfavkey=portage.cpv_getkey(x[2])
3129 if "--fetchonly" not in self.myopts and \
3130 "--fetch-all-uri" not in self.myopts and \
3131 myfavkey in favorites:
3132 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3133 myfavdict=genericdict(myfavs)
3134 #don't record if already in system profile or already recorded
3135 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3136 #we don't have a favorites entry for this package yet; add one
3137 myfavdict[myfavkey]=myfavkey
3138 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3139 emergelog(xterm_titles, " === ("+\
3140 str(mergecount)+" of "+\
3141 str(len(mymergelist))+\
3142 ") Updating world file ("+x[pkgindex]+")")
3143 portage.write_atomic(
3144 os.path.join(myroot, portage.WORLD_FILE),
3145 "\n".join(myfavdict.values()))
3147 if "--pretend" not in self.myopts and \
3148 "--fetchonly" not in self.myopts and \
3149 "--fetch-all-uri" not in self.myopts:
3150 # Clean the old package that we have merged over top of it.
3151 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3152 xsplit=portage.pkgsplit(x[2])
3153 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3154 retval = unmerge(pkgsettings, self.myopts, vartree,
3155 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3157 emergelog(xterm_titles,
3158 " --- AUTOCLEAN: Nothing unmerged.")
3160 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3161 + " AUTOCLEAN is disabled. This can cause serious"
3162 + " problems due to overlapping packages.\n")
3164 # Figure out if we need a restart.
3165 mysplit=portage.pkgsplit(x[2])
3166 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3167 myver=mysplit[1]+"-"+mysplit[2]
3168 if myver[-3:]=='-r0':
3170 if (myver != portage.VERSION) and \
3171 "livecvsportage" not in self.settings.features:
3172 if len(mymergelist) > mergecount:
3173 emergelog(xterm_titles,
3174 " ::: completed emerge ("+ \
3175 str(mergecount)+" of "+ \
3176 str(len(mymergelist))+") "+ \
3178 emergelog(xterm_titles, " *** RESTARTING " + \
3179 "emerge via exec() after change of " + \
3181 del mtimedb["resume"]["mergelist"][0]
3183 portage.run_exitfuncs()
3184 mynewargv=[sys.argv[0],"--resume"]
3185 for myopt, myarg in self.myopts.iteritems():
3186 if myopt not in bad_resume_opts:
3188 mynewargv.append(myopt)
3190 mynewargv.append(myopt +"="+ myarg)
3191 # priority only needs to be adjusted on the first run
3192 os.environ["PORTAGE_NICENESS"] = "0"
3193 os.execv(mynewargv[0], mynewargv)
3195 if "--pretend" not in self.myopts and \
3196 "--fetchonly" not in self.myopts and \
3197 "--fetch-all-uri" not in self.myopts:
3198 if "noclean" not in self.settings.features:
3199 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3200 (mergecount, len(mymergelist), x[pkgindex])
3201 emergelog(xterm_titles, (" === (%s of %s) " + \
3202 "Post-Build Cleaning (%s::%s)") % \
3203 (mergecount, len(mymergelist), x[pkgindex], y),
3204 short_msg=short_msg)
3205 emergelog(xterm_titles, " ::: completed emerge ("+\
3206 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3209 # Unsafe for parallel merges
3210 del mtimedb["resume"]["mergelist"][0]
3211 # Commit after each merge so that --resume may still work in
3212 # in the event that portage is not allowed to exit normally
3213 # due to power failure, SIGKILL, etc...
3216 if "--pretend" not in self.myopts:
3217 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3219 # We're out of the loop... We're done. Delete the resume data.
3220 if mtimedb.has_key("resume"):
3221 del mtimedb["resume"]
3224 #by doing an exit this way, --fetchonly can continue to try to
3225 #fetch everything even if a particular download fails.
3226 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3228 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3229 "encountered. Please see above for details.\n\n")
3230 for cpv in failed_fetches:
3231 sys.stderr.write(" ")
3232 sys.stderr.write(cpv)
3233 sys.stderr.write("\n")
3234 sys.stderr.write("\n")
3240 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3241 ldpath_mtimes, autoclean=0):
3242 candidate_catpkgs=[]
3244 xterm_titles = "notitles" not in settings.features
3246 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3248 # At least the parent needs to exist for the lock file.
3249 portage.util.ensure_dirs(vdb_path)
3250 except portage.exception.PortageException:
3254 if os.access(vdb_path, os.W_OK):
3255 vdb_lock = portage.locks.lockdir(vdb_path)
3256 realsyslist = getlist(settings, "system")
3258 for x in realsyslist:
3259 mycp = portage.dep_getkey(x)
3260 if mycp in settings.getvirtuals():
3262 for provider in settings.getvirtuals()[mycp]:
3263 if vartree.dbapi.match(provider):
3264 providers.append(provider)
3265 if len(providers) == 1:
3266 syslist.extend(providers)
3268 syslist.append(mycp)
3270 mysettings = portage.config(clone=settings)
3272 if not unmerge_files or "world" in unmerge_files or \
3273 "system" in unmerge_files:
3274 if "unmerge"==unmerge_action:
3276 print bold("emerge unmerge") + " can only be used with " + \
3277 "specific package names, not with "+bold("world")+" or"
3278 print bold("system")+" targets."
3285 # process all arguments and add all
3286 # valid db entries to candidate_catpkgs
3288 if not unmerge_files or "world" in unmerge_files:
3289 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3290 elif "system" in unmerge_files:
3291 candidate_catpkgs.extend(getlist(settings, "system"))
3293 #we've got command-line arguments
3294 if not unmerge_files:
3295 print "\nNo packages to unmerge have been provided.\n"
3297 for x in unmerge_files:
3298 arg_parts = x.split('/')
3299 if x[0] not in [".","/"] and \
3300 arg_parts[-1][-7:] != ".ebuild":
3301 #possible cat/pkg or dep; treat as such
3302 candidate_catpkgs.append(x)
3303 elif unmerge_action in ["prune","clean"]:
3304 print "\n!!! Prune and clean do not accept individual" + \
3305 " ebuilds as arguments;\n skipping.\n"
3308 # it appears that the user is specifying an installed
3309 # ebuild and we're in "unmerge" mode, so it's ok.
3310 if not os.path.exists(x):
3311 print "\n!!! The path '"+x+"' doesn't exist.\n"
3314 absx = os.path.abspath(x)
3315 sp_absx = absx.split("/")
3316 if sp_absx[-1][-7:] == ".ebuild":
3318 absx = "/".join(sp_absx)
3320 sp_absx_len = len(sp_absx)
3322 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3323 vdb_len = len(vdb_path)
3325 sp_vdb = vdb_path.split("/")
3326 sp_vdb_len = len(sp_vdb)
3328 if not os.path.exists(absx+"/CONTENTS"):
3329 print "!!! Not a valid db dir: "+str(absx)
3332 if sp_absx_len <= sp_vdb_len:
3333 # The Path is shorter... so it can't be inside the vdb.
3336 print "\n!!!",x,"cannot be inside "+ \
3337 vdb_path+"; aborting.\n"
3340 for idx in range(0,sp_vdb_len):
3341 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3344 print "\n!!!", x, "is not inside "+\
3345 vdb_path+"; aborting.\n"
3348 print "="+"/".join(sp_absx[sp_vdb_len:])
3349 candidate_catpkgs.append(
3350 "="+"/".join(sp_absx[sp_vdb_len:]))
3353 if (not "--quiet" in myopts):
3355 if settings["ROOT"] != "/":
3356 print darkgreen(newline+ \
3357 ">>> Using system located in ROOT tree "+settings["ROOT"])
3358 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3359 not ("--quiet" in myopts):
3360 print darkgreen(newline+\
3361 ">>> These are the packages that would be unmerged:")
3365 for x in candidate_catpkgs:
3366 # cycle through all our candidate deps and determine
3367 # what will and will not get unmerged
3369 mymatch=localtree.dep_match(x)
3372 except ValueError, errpkgs:
3373 print "\n\n!!! The short ebuild name \"" + \
3374 x + "\" is ambiguous. Please specify"
3375 print "!!! one of the following fully-qualified " + \
3376 "ebuild names instead:\n"
3377 for i in errpkgs[0]:
3378 print " " + green(i)
3382 if not mymatch and x[0] not in "<>=~":
3383 #add a "=" if missing
3384 mymatch=localtree.dep_match("="+x)
3386 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3387 (x, unmerge_action), noiselevel=-1)
3389 mykey = portage.key_expand(
3391 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3392 if not pkgmap.has_key(mykey):
3393 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3394 if unmerge_action=="unmerge":
3396 if y not in pkgmap[mykey]["selected"]:
3397 pkgmap[mykey]["selected"].append(y)
3398 numselected=numselected+len(mymatch)
3401 #unmerge_action in ["prune", clean"]
3403 for mypkg in mymatch:
3404 if unmerge_action=="clean":
3405 myslot=localtree.getslot(mypkg)
3407 # since we're pruning, we don't care about slots
3408 # and put all the pkgs in together
3410 if not slotmap.has_key(myslot):
3412 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3413 for myslot in slotmap.keys():
3414 counterkeys=slotmap[myslot].keys()
3419 pkgmap[mykey]["protected"].append(
3420 slotmap[myslot][counterkeys[-1]])
3422 #be pretty and get them in order of merge:
3423 for ckey in counterkeys:
3424 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
3425 numselected=numselected+1
3426 # ok, now the last-merged package
3427 # is protected, and the rest are selected
3428 if global_unmerge and not numselected:
3429 print "\n>>> No outdated packages were found on your system.\n"
3433 portage.writemsg_stdout(
3434 "\n>>> No packages selected for removal by " + \
3435 unmerge_action + "\n")
3439 portage.locks.unlockdir(vdb_lock)
3440 for x in pkgmap.keys():
3441 for y in localtree.dep_match(x):
3442 if y not in pkgmap[x]["omitted"] and \
3443 y not in pkgmap[x]["selected"] and \
3444 y not in pkgmap[x]["protected"]:
3445 pkgmap[x]["omitted"].append(y)
3446 if global_unmerge and not pkgmap[x]["selected"]:
3447 #avoid cluttering the preview printout with stuff that isn't getting unmerged
3449 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
3450 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
3451 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
3452 if "--pretend" not in myopts and "--ask" not in myopts:
3453 countdown(int(settings["EMERGE_WARNING_DELAY"]),
3454 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3455 print "\n "+white(x)
3456 for mytype in ["selected","protected","omitted"]:
3457 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
3458 if pkgmap[x][mytype]:
3459 for mypkg in pkgmap[x][mytype]:
3460 mysplit=portage.catpkgsplit(mypkg)
3461 if mysplit[3]=="r0":
3462 myversion=mysplit[2]
3464 myversion=mysplit[2]+"-"+mysplit[3]
3465 if mytype=="selected":
3466 portage.writemsg_stdout(
3467 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
3469 portage.writemsg_stdout(
3470 colorize("GOOD", myversion + " "), noiselevel=-1)
3472 portage.writemsg_stdout("none", noiselevel=-1)
3473 portage.writemsg_stdout("\n", noiselevel=-1)
3475 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3476 " packages are slated for removal.\n")
3477 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
3478 " and " + colorize("GOOD", "'omitted'") + \
3479 " packages will not be removed.\n\n")
3481 if "--pretend" in myopts:
3482 #we're done... return
3484 if "--ask" in myopts:
3485 if userquery("Would you like to unmerge these packages?")=="No":
3486 # enter pretend mode for correct formatting of results
3487 myopts["--pretend"] = True
3492 #the real unmerging begins, after a short delay....
3494 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3496 for x in pkgmap.keys():
3497 for y in pkgmap[x]["selected"]:
3498 print ">>> Unmerging "+y+"..."
3499 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3500 mysplit=y.split("/")
3502 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3503 mysettings, unmerge_action not in ["clean","prune"],
3504 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3505 if retval != os.EX_OK:
3506 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3507 ebuild = vartree.dbapi.findname(y)
3508 show_unmerge_failure_message(y, ebuild, retval)
3511 clean_world(vartree.dbapi, y)
3512 emergelog(xterm_titles, " >>> unmerge success: "+y)
3515 def show_unmerge_failure_message(pkg, ebuild, retval):
3517 from formatter import AbstractFormatter, DumbWriter
3518 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3521 msg.append("A removal phase of the '%s' package " % pkg)
3522 msg.append("has failed with exit value %s. " % retval)
3523 msg.append("The problem occurred while executing ")
3524 msg.append("the ebuild located at '%s'. " % ebuild)
3525 msg.append("If necessary, manually remove the ebuild " )
3526 msg.append("in order to skip the execution of removal phases.")
3530 f.add_flowing_data(x)
3534 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3537 if os.path.exists("/usr/bin/install-info"):
3542 inforoot=normpath(root+z)
3543 if os.path.isdir(inforoot):
3544 infomtime = long(os.stat(inforoot).st_mtime)
3545 if inforoot not in prev_mtimes or \
3546 prev_mtimes[inforoot] != infomtime:
3547 regen_infodirs.append(inforoot)
3549 if not regen_infodirs:
3550 print " "+green("*")+" GNU info directory index is up-to-date."
3552 print " "+green("*")+" Regenerating GNU info directory index..."
3556 for inforoot in regen_infodirs:
3559 for filename in ("dir", "dir.gz", "dir.bz2"):
3560 file_path = os.path.join(inforoot, filename)
3562 os.rename(file_path, file_path + ".old")
3564 if e.errno != errno.ENOENT:
3568 if not os.path.isdir(inforoot):
3571 file_list = os.listdir(inforoot)
3574 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3576 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3577 existsstr="already exists, for file `"
3579 if re.search(existsstr,myso):
3580 # Already exists... Don't increment the count for this.
3582 elif myso[:44]=="install-info: warning: no info dir entry in ":
3583 # This info file doesn't contain a DIR-header: install-info produces this
3584 # (harmless) warning (the --quiet switch doesn't seem to work).
3585 # Don't increment the count for this.
3589 errmsg += myso + "\n"
3592 #update mtime so we can potentially avoid regenerating.
3593 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3596 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3599 print " "+green("*")+" Processed",icount,"info files."
3602 def post_emerge(settings, mtimedb, retval):
3604 Misc. things to run at the end of a merge session.
3612 @param settings: Configuration settings (typically portage.settings)
3613 @type settings: portage.config()
3614 @param mtimedb: The mtimeDB to store data needed across merge invocations
3615 @type mtimedb: MtimeDB class instance
3616 @param retval: Emerge's return value
3620 1. Calls sys.exit(retval)
3622 target_root = settings["ROOT"]
3623 info_mtimes = mtimedb["info"]
3625 # Load the most current variables from ${ROOT}/etc/profile.env
3627 settings.regenerate()
3630 config_protect = settings.get("CONFIG_PROTECT","").split()
3631 infodirs = settings.get("INFOPATH","").split(":") + \
3632 settings.get("INFODIR","").split(":")
3636 emergelog("notitles" not in settings.features,
3637 " *** exiting successfully.")
3639 if "noinfo" not in settings.features:
3640 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3642 chk_updated_cfg_files(target_root, config_protect)
3644 NEWS_PATH = os.path.join( "metadata", "news" )
3645 UNREAD_PATH = os.path.join( target_root, NEWS_LIB_PATH, 'news')
3646 porttree = portdbapi( porttree_root = settings["PORTDIR"], mysettings = settings )
3647 newsReaderDisplay = False
3649 for repo in porttree.getRepositories():
3650 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3652 print colorize("WARN", " * IMPORTANT:"),
3653 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3654 newsReaderDisplay = True
3656 if newsReaderDisplay:
3657 print colorize("WARN", " *"),
3658 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3664 def chk_updated_cfg_files(target_root, config_protect):
3666 #number of directories with some protect files in them
3668 for x in config_protect:
3669 x = os.path.join(target_root, x.lstrip(os.path.sep))
3671 mymode = os.lstat(x).st_mode
3674 if stat.S_ISDIR(mymode):
3675 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3677 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3678 os.path.split(x.rstrip(os.path.sep))
3679 a = commands.getstatusoutput(mycommand + \
3680 " ! -iname '.*~' ! -iname '.*.bak'")
3682 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3684 files = a[1].split()
3687 print colorize("WARN", " * IMPORTANT:"),
3688 if stat.S_ISDIR(mymode):
3689 print "%d config files in '%s' need updating." % \
3692 print "config file '%s' needs updating." % x
3695 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3696 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3698 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3700 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3701 Returns the number of unread (yet relevent) items.
3713 1. The number of unread but relevant news items.
3716 from portage.news import NewsManager
3717 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3718 return manager.getUnreadItems( repo_id, update=True )
3720 def is_valid_package_atom(x):
3722 testkey = portage.dep_getkey(x)
3723 except portage.exception.InvalidData:
3725 if testkey.startswith("null/"):
3726 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3731 return portage.isvalidatom(testatom)
3733 def validate_merge_list(trees, mergelist):
3734 """Validate the list to make sure all the packages are still available.
3735 This is needed for --resume."""
3736 for (pkg_type, myroot, pkg_key, action) in mergelist:
3737 if pkg_type == "binary" and \
3738 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3739 pkg_type == "ebuild" and \
3740 not trees[myroot]["porttree"].dbapi.xmatch(
3741 "match-all", "="+pkg_key):
3742 print red("!!! Error: The resume list contains packages that are no longer")
3743 print red("!!! available to be emerged. Please restart/continue")
3744 print red("!!! the merge operation manually.")
3747 def show_blocker_docs_link():
3749 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3750 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3752 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3755 def action_sync(settings, trees, mtimedb, myopts, myaction):
3756 xterm_titles = "notitles" not in settings.features
3757 emergelog(xterm_titles, " === sync")
3758 myportdir = settings.get("PORTDIR", None)
3760 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3762 if myportdir[-1]=="/":
3763 myportdir=myportdir[:-1]
3764 if not os.path.exists(myportdir):
3765 print ">>>",myportdir,"not found, creating it."
3766 os.makedirs(myportdir,0755)
3767 syncuri=settings["SYNC"].rstrip()
3769 updatecache_flg = False
3770 if myaction == "metadata":
3771 print "skipping sync"
3772 updatecache_flg = True
3773 tmpservertimestampfile = None
3774 elif syncuri[:8]=="rsync://":
3775 if not os.path.exists("/usr/bin/rsync"):
3776 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3777 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3783 if settings["PORTAGE_RSYNC_OPTS"] == "":
3784 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3786 "--recursive", # Recurse directories
3787 "--links", # Consider symlinks
3788 "--safe-links", # Ignore links outside of tree
3789 "--perms", # Preserve permissions
3790 "--times", # Preserive mod times
3791 "--compress", # Compress the data transmitted
3792 "--force", # Force deletion on non-empty dirs
3793 "--whole-file", # Don't do block transfers, only entire files
3794 "--delete", # Delete files that aren't in the master tree
3795 "--delete-after", # Delete only after everything else is done
3796 "--stats", # Show final statistics about what was transfered
3797 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3798 "--exclude=/distfiles", # Exclude distfiles from consideration
3799 "--exclude=/local", # Exclude local from consideration
3800 "--exclude=/packages", # Exclude packages from consideration
3801 "--filter=H_**/files/digest-*" # Exclude manifest1 digests and delete on the receiving side
3805 # The below validation is not needed when using the above hardcoded
3808 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3809 rsync_opts.extend(settings["PORTAGE_RSYNC_OPTS"].split())
3811 for opt in ("--recursive", "--times"):
3812 if opt not in rsync_opts:
3813 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3814 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3815 rsync_opts.append(opt)
3817 for exclude in ("distfiles", "local", "packages"):
3818 opt = "--exclude=/%s" % exclude
3819 if opt not in rsync_opts:
3820 portage.writemsg(yellow("WARNING:") + \
3821 " adding required option %s not included in " % opt + \
3822 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3823 rsync_opts.append(opt)
3825 if settings["RSYNC_TIMEOUT"] != "":
3826 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3827 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3829 mytimeout = int(settings["RSYNC_TIMEOUT"])
3830 rsync_opts.append("--timeout=%d" % mytimeout)
3831 except ValueError, e:
3832 portage.writemsg("!!! %s\n" % str(e))
3834 # TODO: determine options required for official servers
3835 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
3837 def rsync_opt_startswith(opt_prefix):
3838 for x in rsync_opts:
3839 if x.startswith(opt_prefix):
3843 if not rsync_opt_startswith("--timeout="):
3844 rsync_opts.append("--timeout=%d" % mytimeout)
3846 for opt in ("--compress", "--whole-file"):
3847 if opt not in rsync_opts:
3848 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3849 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3850 rsync_opts.append(opt)
3852 if "--quiet" in myopts:
3853 rsync_opts.append("--quiet") # Shut up a lot
3855 rsync_opts.append("--verbose") # Print filelist
3857 if "--verbose" in myopts:
3858 rsync_opts.append("--progress") # Progress meter for each file
3860 if "--debug" in myopts:
3861 rsync_opts.append("--checksum") # Force checksum on all files
3863 if settings["RSYNC_EXCLUDEFROM"] != "":
3864 portage.writemsg(yellow("WARNING:") + \
3865 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
3866 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3867 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
3868 rsync_opts.append("--exclude-from=%s" % \
3869 settings["RSYNC_EXCLUDEFROM"])
3871 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
3872 " but file does not exist.\n")
3874 if settings["RSYNC_RATELIMIT"] != "":
3875 portage.writemsg(yellow("WARNING:") + \
3876 " usage of RSYNC_RATELIMIT is deprecated, use " + \
3877 "PORTAGE_RSYNC_EXTRA_OPTS instead")
3878 rsync_opts.append("--bwlimit=%s" % \
3879 settings["RSYNC_RATELIMIT"])
3881 # Real local timestamp file.
3882 servertimestampfile = os.path.join(
3883 myportdir, "metadata", "timestamp.chk")
3884 # Temporary file for remote server timestamp comparison.
3885 tmpservertimestampfile = os.path.join(
3886 settings["PORTAGE_TMPDIR"], "timestamp.chk")
3888 content = portage.util.grabfile(servertimestampfile)
3892 mytimestamp = time.mktime(time.strptime(content[0],
3893 "%a, %d %b %Y %H:%M:%S +0000"))
3894 except OverflowError, ValueError:
3899 if settings.has_key("RSYNC_RETRIES"):
3900 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
3901 maxretries=int(settings["RSYNC_RETRIES"])
3903 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
3904 except SystemExit, e:
3905 raise # Needed else can't exit
3907 maxretries=3 #default number of retries
3910 user_name, hostname, port = re.split(
3911 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
3914 if user_name is None:
3916 updatecache_flg=True
3917 all_rsync_opts = set(rsync_opts)
3918 all_rsync_opts.update(
3919 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
3920 family = socket.AF_UNSPEC
3921 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
3922 family = socket.AF_INET
3923 elif socket.has_ipv6 and \
3924 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
3925 family = socket.AF_INET6
3932 for addrinfo in socket.getaddrinfo(
3933 hostname, None, family, socket.SOCK_STREAM):
3934 if addrinfo[0] == socket.AF_INET6:
3935 # IPv6 addresses need to be enclosed in square brackets
3936 ips.append("[%s]" % addrinfo[4][0])
3938 ips.append(addrinfo[4][0])
3939 from random import shuffle
3941 except SystemExit, e:
3942 raise # Needed else can't exit
3943 except Exception, e:
3944 print "Notice:",str(e)
3949 dosyncuri = syncuri.replace(
3950 "//" + user_name + hostname + port + "/",
3951 "//" + user_name + ips[0] + port + "/", 1)
3952 except SystemExit, e:
3953 raise # Needed else can't exit
3954 except Exception, e:
3955 print "Notice:",str(e)
3959 if "--ask" in myopts:
3960 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
3965 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
3966 if "--quiet" not in myopts:
3967 print ">>> Starting rsync with "+dosyncuri+"..."
3969 emergelog(xterm_titles,
3970 ">>> Starting retry %d of %d with %s" % \
3971 (retries,maxretries,dosyncuri))
3972 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
3974 if mytimestamp != 0 and "--quiet" not in myopts:
3975 print ">>> Checking server timestamp ..."
3977 rsynccommand = " ".join(["/usr/bin/rsync", " ".join(rsync_opts),
3978 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
3980 if "--debug" in myopts:
3985 if mytimestamp != 0:
3986 mycommand = rsynccommand.split()
3987 mycommand.append(dosyncuri.rstrip("/") + \
3988 "/metadata/timestamp.chk")
3989 mycommand.append(tmpservertimestampfile)
3991 exitcode = portage.process.spawn(
3992 mycommand, env=settings.environ())
3993 content = portage.grabfile(tmpservertimestampfile)
3996 servertimestamp = time.mktime(time.strptime(
3997 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
3998 except OverflowError, ValueError:
4003 os.unlink(tmpservertimestampfile)
4007 if exitcode == os.EX_OK:
4008 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4009 emergelog(xterm_titles,
4010 ">>> Cancelling sync -- Already current.")
4013 print ">>> Timestamps on the server and in the local repository are the same."
4014 print ">>> Cancelling all further sync action. You are already up to date."
4016 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4020 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4021 emergelog(xterm_titles,
4022 ">>> Server out of date: %s" % dosyncuri)
4025 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4027 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4030 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4032 mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
4033 exitcode=portage.spawn(mycommand,settings,free=1)
4034 if exitcode in [0,1,2,3,4,11,14,20,21]:
4036 elif exitcode in [0,1,2,3,4,11,14,20,21]:
4041 if retries<=maxretries:
4042 print ">>> Retrying..."
4047 updatecache_flg=False
4051 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4055 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4056 print darkred("!!!")+green(" that your SYNC statement is proper.")
4057 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4059 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4060 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4061 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4062 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4063 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4065 print darkred("!!!")+green(" Rsync was killed before it finished.")
4067 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4068 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4069 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4070 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4071 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4074 elif syncuri[:6]=="cvs://":
4075 if not os.path.exists("/usr/bin/cvs"):
4076 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4077 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4080 cvsdir=os.path.dirname(myportdir)
4081 if not os.path.exists(myportdir+"/CVS"):
4083 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4084 if os.path.exists(cvsdir+"/gentoo-x86"):
4085 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4090 if e.errno != errno.ENOENT:
4092 "!!! existing '%s' directory; exiting.\n" % myportdir)
4095 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4096 print "!!! cvs checkout error; exiting."
4098 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4101 print ">>> Starting cvs update with "+syncuri+"..."
4102 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4103 myportdir, settings, free=1)
4104 if retval != os.EX_OK:
4108 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4111 if updatecache_flg and \
4112 myaction != "metadata" and \
4113 "metadata-transfer" not in settings.features:
4114 updatecache_flg = False
4116 # Reload the whole config from scratch.
4117 settings, trees, mtimedb = load_emerge_config(trees=trees)
4118 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4120 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4121 action_metadata(settings, portdb, myopts)
4123 if portage.global_updates(settings, trees, mtimedb["updates"]):
4125 # Reload the whole config from scratch.
4126 settings, trees, mtimedb = load_emerge_config(trees=trees)
4127 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4129 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4130 mypvs = portage.best(
4131 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4133 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4135 if myaction != "metadata":
4136 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4137 retval = portage.process.spawn(
4138 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4139 dosyncuri], env=settings.environ())
4140 if retval != os.EX_OK:
4141 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4143 if(mybestpv != mypvs) and not "--quiet" in myopts:
4145 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4146 print red(" * ")+"that you update portage now, before any other packages are updated."
4147 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4148 print red(" * ")+"configuration files."
4149 print red(" * ")+"To update portage, run 'emerge portage'."
4152 def action_metadata(settings, portdb, myopts):
4153 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4154 old_umask = os.umask(0002)
4155 cachedir = os.path.normpath(settings.depcachedir)
4156 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4157 "/lib", "/opt", "/proc", "/root", "/sbin",
4158 "/sys", "/tmp", "/usr", "/var"]:
4159 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4160 "ROOT DIRECTORY ON YOUR SYSTEM."
4161 print >> sys.stderr, \
4162 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4164 if not os.path.exists(cachedir):
4167 ec = portage.eclass_cache.cache(portdb.porttree_root)
4168 myportdir = os.path.realpath(settings["PORTDIR"])
4169 cm = settings.load_best_module("portdbapi.metadbmodule")(
4170 myportdir, "metadata/cache", portage.auxdbkeys[:])
4172 from portage.cache import util
4174 class percentage_noise_maker(util.quiet_mirroring):
4175 def __init__(self, dbapi):
4177 self.cp_all = dbapi.cp_all()
4178 l = len(self.cp_all)
4179 self.call_update_min = 100000000
4180 self.min_cp_all = l/100.0
4185 for x in self.cp_all:
4187 if self.count > self.min_cp_all:
4188 self.call_update_min = 0
4190 for y in self.dbapi.cp_list(x):
4192 self.call_update_mine = 0
4194 def update(self, *arg):
4195 try: self.pstr = int(self.pstr) + 1
4196 except ValueError: self.pstr = 1
4197 sys.stdout.write("%s%i%%" % \
4198 ("\b" * (len(str(self.pstr))+1), self.pstr))
4200 self.call_update_min = 10000000
4202 def finish(self, *arg):
4203 sys.stdout.write("\b\b\b\b100%\n")
4206 if "--quiet" in myopts:
4207 def quicky_cpv_generator(cp_all_list):
4208 for x in cp_all_list:
4209 for y in portdb.cp_list(x):
4211 source = quicky_cpv_generator(portdb.cp_all())
4212 noise_maker = portage.cache.util.quiet_mirroring()
4214 noise_maker = source = percentage_noise_maker(portdb)
4215 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4216 eclass_cache=ec, verbose_instance=noise_maker)
4221 def action_regen(settings, portdb):
4222 xterm_titles = "notitles" not in settings.features
4223 emergelog(xterm_titles, " === regen")
4224 #regenerate cache entries
4225 print "Regenerating cache entries... "
4227 os.close(sys.stdin.fileno())
4228 except SystemExit, e:
4229 raise # Needed else can't exit
4233 mynodes = portdb.cp_all()
4234 from portage.cache.cache_errors import CacheError
4236 for mytree in portdb.porttrees:
4238 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4239 except CacheError, e:
4240 print "\n error listing cache entries for " + \
4241 "'%s': %s, continuing..." % (mytree, e)
4246 mymatches = portdb.xmatch("match-all",x)
4247 portage.writemsg_stdout("processing %s\n" % x)
4250 foo = portdb.aux_get(y,["DEPEND"])
4251 except SystemExit, e:
4252 # sys.exit is an exception... And consequently, we can't catch it.
4254 except Exception, e:
4255 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4257 for mytree in portdb.porttrees:
4258 if portdb.findname2(y, mytree=mytree)[0]:
4259 dead_nodes[mytree].discard(y)
4261 for mytree, nodes in dead_nodes.iteritems():
4262 auxdb = portdb.auxdb[mytree]
4266 except KeyError, CacheError:
4270 def action_config(settings, trees, myopts, myfiles):
4271 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4272 print red("!!! config can only take a single package atom at this time\n")
4274 if not is_valid_package_atom(myfiles[0]):
4275 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4277 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4278 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4282 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4283 except ValueError, e:
4284 # Multiple matches thrown from cpv_expand
4287 print "No packages found.\n"
4290 if "--ask" in myopts:
4292 print "Please select a package to configure:"
4296 options.append(str(idx))
4297 print options[-1]+") "+pkg
4300 idx = userquery("Selection?", options)
4303 pkg = pkgs[int(idx)-1]
4305 print "The following packages available:"
4308 print "\nPlease use a specific atom or the --ask option."
4314 if "--ask" in myopts:
4315 if userquery("Ready to configure "+pkg+"?") == "No":
4318 print "Configuring pkg..."
4320 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4321 mysettings = portage.config(clone=settings)
4322 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4323 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4324 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4327 def action_info(settings, trees, myopts, myfiles):
4328 unameout=commands.getstatusoutput("uname -mrp")[1]
4329 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4330 settings.profile_path, settings["CHOST"],
4331 trees[settings["ROOT"]]["vartree"].dbapi)
4333 header_title = "System Settings"
4335 print header_width * "="
4336 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4337 print header_width * "="
4338 print "System uname: "+unameout
4339 gentoo_release = portage.grabfile(os.path.join(
4340 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4342 print gentoo_release[0]
4344 print "Unknown Host Operating System"
4345 lastSync = portage.grabfile(os.path.join(
4346 settings["PORTDIR"], "metadata", "timestamp.chk"))
4347 print "Timestamp of tree:",
4353 output=commands.getstatusoutput("distcc --version")
4355 print str(output[1].split("\n",1)[0]),
4356 if "distcc" in settings.features:
4361 output=commands.getstatusoutput("ccache -V")
4363 print str(output[1].split("\n",1)[0]),
4364 if "ccache" in settings.features:
4369 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4370 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4371 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4372 myvars = portage.util.unique_array(myvars)
4376 if portage.isvalidatom(x):
4377 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4379 for y in pkg_matches:
4380 mycpv = portage.catpkgsplit(y)
4381 if(mycpv[3] != "r0"):
4382 pkgs += [mycpv[2] + "-" + mycpv[3]]
4386 pkgs = ", ".join(sorted_versions(pkgs))
4387 print "%-20s %s" % (x+":", pkgs)
4389 print "%-20s %s" % (x+":", "[NOT VALID]")
4391 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4393 if "--verbose" in myopts:
4394 myvars=settings.keys()
4396 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4397 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4398 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4399 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4401 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4403 myvars = portage.util.unique_array(myvars)
4409 print '%s="%s"' % (x, settings[x])
4411 use = set(settings["USE"].split())
4412 use_expand = settings["USE_EXPAND"].split()
4414 for varname in use_expand:
4415 flag_prefix = varname.lower() + "_"
4417 if f.startswith(flag_prefix):
4421 print 'USE="%s"' % " ".join(use),
4422 for varname in use_expand:
4423 myval = settings.get(varname)
4425 print '%s="%s"' % (varname, myval),
4428 unset_vars.append(x)
4430 print "Unset: "+", ".join(unset_vars)
4433 if "--debug" in myopts:
4434 for x in dir(portage):
4435 module = getattr(portage, x)
4436 if "cvs_id_string" in dir(module):
4437 print "%s: %s" % (str(x), str(module.cvs_id_string))
4439 # See if we can find any packages installed matching the strings
4440 # passed on the command line
4442 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4443 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4445 mypkgs.extend(vardb.match(x))
4447 # If some packages were found...
4449 # Get our global settings (we only print stuff if it varies from
4450 # the current config)
4451 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4452 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4454 pkgsettings = portage.config(clone=settings)
4456 for myvar in mydesiredvars:
4457 global_vals[myvar] = set(settings.get(myvar, "").split())
4459 # Loop through each package
4460 # Only print settings if they differ from global settings
4461 header_printed = False
4463 # Get all package specific variables
4464 auxvalues = vardb.aux_get(pkg, auxkeys)
4466 for i in xrange(len(auxkeys)):
4467 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4469 for myvar in mydesiredvars:
4470 # If the package variable doesn't match the
4471 # current global variable, something has changed
4472 # so set diff_found so we know to print
4473 if valuesmap[myvar] != global_vals[myvar]:
4474 diff_values[myvar] = valuesmap[myvar]
4475 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4476 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4478 # If a matching ebuild is no longer available in the tree, maybe it
4479 # would make sense to compare against the flags for the best
4480 # available version with the same slot?
4482 if portdb.cpv_exists(pkg):
4484 pkgsettings.setcpv(pkg, mydb=mydb)
4485 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4487 diff_values["USE"] = valuesmap["USE"]
4488 # If a difference was found, print the info for
4492 # If we have not yet printed the header,
4494 if not header_printed:
4495 header_title = "Package Settings"
4496 print header_width * "="
4497 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4498 print header_width * "="
4499 header_printed = True
4501 # Print package info
4502 print "%s was built with the following:" % pkg
4503 for myvar in mydesiredvars + ["USE"]:
4504 if myvar in diff_values:
4505 mylist = list(diff_values[myvar])
4507 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4510 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4512 print "emerge: no search terms provided."
4514 searchinstance = search(settings, portdb,
4515 vartree, spinner, "--searchdesc" in myopts,
4516 "--quiet" not in myopts)
4517 for mysearch in myfiles:
4519 searchinstance.execute(mysearch)
4520 except re.error, comment:
4521 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4523 searchinstance.output()
4525 def action_depclean(settings, trees, ldpath_mtimes,
4527 # Kill packages that aren't explicitly merged or are required as a
4528 # dependency of another package. World file is explicit.
4530 warn_prefix = colorize("BAD", "*** WARNING *** ")
4532 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4533 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4534 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4536 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4537 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4538 print warn_prefix + "be kept. They can be manually added to this set with"
4539 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4540 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4541 print warn_prefix + "depclean, even if they are part of the world set."
4543 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4544 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4545 print warn_prefix + "consequence, it is often necessary to run "
4546 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4548 xterm_titles = "notitles" not in settings.features
4549 myroot = settings["ROOT"]
4550 dep_check_trees = {}
4551 dep_check_trees[myroot] = {}
4552 dep_check_trees[myroot]["vartree"] = \
4553 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4554 vardb = dep_check_trees[myroot]["vartree"].dbapi
4555 # Constrain dependency selection to the installed packages.
4556 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4557 syslist = getlist(settings, "system")
4558 worldlist = getlist(settings, "world")
4559 fakedb = portage.fakedbapi(settings=settings)
4560 myvarlist = vardb.cpv_all()
4563 print "\n!!! You have no system list.",
4565 print "\n!!! You have no world file.",
4567 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4569 if not (syslist and worldlist and myvarlist):
4570 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4571 print " break your installation.\n"
4572 if "--pretend" not in myopts:
4573 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4575 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4576 emergelog(xterm_titles, " >>> depclean")
4578 if "--quiet" not in myopts:
4579 print "\nCalculating dependencies ",
4583 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4584 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4586 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4588 while remaining_atoms:
4589 atom, parent, priority = remaining_atoms.pop()
4590 pkgs = vardb.match(atom)
4592 if not atom.startswith("!") and priority == hard:
4593 unresolveable.setdefault(atom, []).append(parent)
4595 # Could put slot checking here to ensure that there aren't two
4596 # packages with the same slot...
4598 if fakedb.cpv_exists(pkg):
4601 fakedb.cpv_inject(pkg)
4602 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4604 if myopts.get("--with-bdeps", "y") == "y":
4605 mydeps.append((myaux["DEPEND"], soft))
4607 mydeps.append((" ".join(myaux.values()), hard))
4608 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4609 for depstr, priority in mydeps:
4614 if "--debug" in myopts:
4616 print "Parent: ", pkg
4617 print "Depstring:", depstr
4619 if priority == soft:
4625 portage.dep._dep_check_strict = False
4626 success, atoms = portage.dep_check(depstr, None, settings,
4627 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4629 portage.dep._dep_check_strict = True
4631 show_invalid_depstring_notice(
4632 ("installed", myroot, pkg, "nomerge"),
4636 if "--debug" in myopts:
4637 print "Candidates:", atoms
4640 remaining_atoms.append((atom, pkg, priority))
4642 if "--quiet" not in myopts:
4643 print "\b\b... done!\n"
4646 print "Dependencies could not be completely resolved due to"
4647 print "the following required packages not being installed:"
4649 for atom in unresolveable:
4650 print atom, "required by", " ".join(unresolveable[atom])
4652 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4653 print "depclean? It may also be necessary to manually uninstalled packages that no"
4654 print "longer exist in the portage tree since it may not be possible to satisfy their"
4655 print "dependencies."
4659 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4662 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4663 "unmerge", cleanlist, ldpath_mtimes)
4665 print "Packages installed: "+str(len(myvarlist))
4666 print "Packages in world: "+str(len(worldlist))
4667 print "Packages in system: "+str(len(syslist))
4668 print "Unique package names: "+str(len(myvarlist))
4669 print "Required packages: "+str(len(fakedb.cpv_all()))
4670 if "--pretend" in myopts:
4671 print "Number to remove: "+str(len(cleanlist))
4673 print "Number removed: "+str(len(cleanlist))
4675 def action_build(settings, trees, mtimedb,
4676 myopts, myaction, myfiles, spinner):
4677 ldpath_mtimes = mtimedb["ldpath"]
4679 if "--quiet" not in myopts:
4681 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4685 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4687 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4691 print darkgreen("These are the packages that would be %s, in order:") % action
4694 # validate the state of the resume data
4695 # so that we can make assumptions later.
4696 for k in ("resume", "resume_backup"):
4698 if "mergelist" in mtimedb[k]:
4699 if not mtimedb[k]["mergelist"]:
4704 if "--resume" in myopts and \
4705 ("resume" in mtimedb or
4706 "resume_backup" in mtimedb):
4707 if "resume" not in mtimedb:
4708 mtimedb["resume"] = mtimedb["resume_backup"]
4709 del mtimedb["resume_backup"]
4711 # XXX: "myopts" is a list for backward compatibility.
4712 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4714 for opt in ("--skipfirst", "--ask", "--tree"):
4715 myresumeopts.pop(opt, None)
4717 for myopt, myarg in myopts.iteritems():
4718 if myopt not in myresumeopts:
4719 myresumeopts[myopt] = myarg
4721 myparams = create_depgraph_params(myopts, myaction)
4722 if not "--quiet" in myopts:
4723 print "Calculating dependencies ",
4724 mydepgraph = depgraph(settings, trees,
4725 myopts, myparams, spinner)
4726 if not "--quiet" in myopts:
4727 print "\b\b... done!"
4729 if ("--resume" in myopts):
4730 print darkgreen("emerge: It seems we have nothing to resume...")
4733 myparams = create_depgraph_params(myopts, myaction)
4734 if myaction in ["system","world"]:
4735 if not ("--quiet" in myopts):
4736 print "Calculating",myaction,"dependencies ",
4738 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4739 if not mydepgraph.xcreate(myaction):
4740 print "!!! Depgraph creation failed."
4742 if not ("--quiet" in myopts):
4743 print "\b\b... done!"
4745 if not ("--quiet" in myopts):
4746 print "Calculating dependencies ",
4748 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4750 retval, favorites = mydepgraph.select_files(myfiles)
4751 except portage.exception.PackageNotFound, e:
4752 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4756 if not ("--quiet" in myopts):
4757 print "\b\b... done!"
4759 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4760 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4762 if mydepgraph.missingbins:
4763 for x in mydepgraph.missingbins:
4764 sys.stderr.write(" "+str(x)+"\n")
4765 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4768 if "--pretend" not in myopts and \
4769 not ("--quiet" in myopts and "--ask" not in myopts):
4770 if "--resume" in myopts:
4771 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4772 mymergelist = mtimedb["resume"]["mergelist"]
4773 if "--skipfirst" in myopts:
4774 mymergelist = mymergelist[1:]
4775 if len(mymergelist) == 0:
4776 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4778 mydepgraph.display(mymergelist)
4779 prompt="Would you like to resume merging these packages?"
4782 mydepgraph.altlist(reversed=("--tree" in myopts)))
4784 for x in mydepgraph.altlist():
4785 if x[0] != "blocks" and x[3] != "nomerge":
4787 #check for blocking dependencies
4788 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
4789 print "\n!!! Error: The above package list contains packages which cannot be installed"
4790 print "!!! at the same time on the same system."
4791 if "--quiet" not in myopts:
4792 show_blocker_docs_link()
4795 if "--noreplace" in myopts and favorites:
4798 print " %s %s" % (good("*"), x)
4799 prompt="Would you like to add these packages to your world favorites?"
4800 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4801 prompt="Nothing to merge; would you like to auto-clean packages?"
4804 print "Nothing to merge; quitting."
4807 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4808 prompt="Would you like to fetch the source files for these packages?"
4810 prompt="Would you like to merge these packages?"
4812 if "--ask" in myopts and userquery(prompt) == "No":
4817 # Don't ask again (e.g. when auto-cleaning packages after merge)
4818 myopts.pop("--ask", None)
4820 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4821 if ("--resume" in myopts):
4822 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4823 mymergelist = mtimedb["resume"]["mergelist"]
4824 if "--skipfirst" in myopts:
4825 mymergelist = mymergelist[1:]
4826 if len(mymergelist) == 0:
4827 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4829 mydepgraph.display(mymergelist)
4832 mydepgraph.altlist(reversed=("--tree" in myopts)))
4834 if ("--buildpkgonly" in myopts):
4835 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
4836 print "\n!!! --buildpkgonly requires all dependencies to be merged."
4837 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
4840 if ("--resume" in myopts):
4841 favorites=mtimedb["resume"]["favorites"]
4842 mergetask = MergeTask(settings, trees, myopts)
4843 if "--fetchonly" in myopts:
4844 """ parallel-fetch uses --resume --fetchonly and we don't want
4845 it to write the mtimedb"""
4846 mtimedb.filename = None
4847 time.sleep(3) # allow the parent to have first fetch
4849 retval = mergetask.merge(
4850 mtimedb["resume"]["mergelist"], favorites, mtimedb)
4851 if retval != os.EX_OK:
4854 if "resume" in mtimedb and \
4855 "mergelist" in mtimedb["resume"] and \
4856 len(mtimedb["resume"]["mergelist"]) > 1:
4857 mtimedb["resume_backup"] = mtimedb["resume"]
4858 del mtimedb["resume"]
4860 mtimedb["resume"]={}
4861 # XXX: Stored as a list for backward compatibility.
4862 mtimedb["resume"]["myopts"] = \
4863 [k for k in myopts if myopts[k] is True]
4864 mtimedb["resume"]["favorites"]=favorites
4865 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4866 for pkgline in mydepgraph.altlist():
4867 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
4868 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
4869 tmpsettings = portage.config(clone=settings)
4871 if settings.get("PORTAGE_DEBUG", "") == "1":
4873 retval = portage.doebuild(
4874 y, "digest", settings["ROOT"], tmpsettings, edebug,
4875 ("--pretend" in myopts),
4876 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
4878 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4880 for pkg in mydepgraph.altlist():
4881 if pkg[0] != "blocks":
4884 pkglist = mydepgraph.altlist()
4886 mergetask = MergeTask(settings, trees, myopts)
4887 retval = mergetask.merge(pkglist, favorites, mtimedb)
4888 if retval != os.EX_OK:
4891 if mtimedb.has_key("resume"):
4892 del mtimedb["resume"]
4893 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4894 print ">>> Auto-cleaning packages..."
4895 vartree = trees[settings["ROOT"]]["vartree"]
4896 unmerge(settings, myopts, vartree, "clean", ["world"],
4897 ldpath_mtimes, autoclean=1)
4899 portage.writemsg_stdout(colorize("WARN", "WARNING:")
4900 + " AUTOCLEAN is disabled. This can cause serious"
4901 + " problems due to overlapping packages.\n")
4903 def multiple_actions(action1, action2):
4904 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
4905 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
4908 def parse_opts(tmpcmdline, silent=False):
4913 global actions, options, shortmapping
4915 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
4916 argument_options = {
4918 "help":"specify the location for portage configuration files",
4922 "help":"enable or disable color output",
4924 "choices":("y", "n")
4927 "help":"include unnecessary build time dependencies",
4929 "choices":("y", "n")
4933 from optparse import OptionParser
4934 parser = OptionParser()
4935 if parser.has_option("--help"):
4936 parser.remove_option("--help")
4938 for action_opt in actions:
4939 parser.add_option("--" + action_opt, action="store_true",
4940 dest=action_opt.replace("-", "_"), default=False)
4941 for myopt in options:
4942 parser.add_option(myopt, action="store_true",
4943 dest=myopt.lstrip("--").replace("-", "_"), default=False)
4944 for shortopt, longopt in shortmapping.iteritems():
4945 parser.add_option("-" + shortopt, action="store_true",
4946 dest=longopt.lstrip("--").replace("-", "_"), default=False)
4947 for myalias, myopt in longopt_aliases.iteritems():
4948 parser.add_option(myalias, action="store_true",
4949 dest=myopt.lstrip("--").replace("-", "_"), default=False)
4951 for myopt, kwargs in argument_options.iteritems():
4952 parser.add_option(myopt,
4953 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
4955 myoptions, myargs = parser.parse_args(args=tmpcmdline)
4957 for myopt in options:
4958 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
4960 myopts[myopt] = True
4962 for myopt in argument_options:
4963 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
4967 for action_opt in actions:
4968 v = getattr(myoptions, action_opt.replace("-", "_"))
4971 multiple_actions(myaction, action_opt)
4973 myaction = action_opt
4976 if x in actions and myaction != "search":
4977 if not silent and x not in ["system", "world"]:
4978 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
4979 # special case "search" so people can search for action terms, e.g. emerge -s sync
4981 multiple_actions(myaction, x)
4987 if "--nocolor" in myopts:
4989 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
4990 "use '--color=n' instead.\n")
4991 del myopts["--nocolor"]
4992 myopts["--color"] = "n"
4994 return myaction, myopts, myfiles
4996 def validate_ebuild_environment(trees):
4997 for myroot in trees:
4998 mysettings = trees[myroot]["vartree"].settings
4999 if not mysettings.get("ARCH", None):
5000 print >> sys.stderr, bad("\a!!! ARCH is not set... " + \
5001 "Are you missing the '%setc/make.profile' symlink?" % \
5002 mysettings["PORTAGE_CONFIGROOT"])
5003 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5004 "Is your portage tree complete?\n")
5006 del myroot, mysettings
5008 def load_emerge_config(trees=None):
5010 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5011 kwargs[k] = os.environ.get(envvar, None)
5012 trees = portage.create_trees(trees=trees, **kwargs)
5014 settings = trees["/"]["vartree"].settings
5016 for myroot in trees:
5018 settings = trees[myroot]["vartree"].settings
5021 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5022 mtimedb = portage.MtimeDB(mtimedbfile)
5023 return settings, trees, mtimedb
5025 def adjust_config(myopts, settings):
5026 """Make emerge specific adjustments to the config."""
5028 # To enhance usability, make some vars case insensitive by forcing them to
5030 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5031 if myvar in settings:
5032 settings[myvar] = settings[myvar].lower()
5033 settings.backup_changes(myvar)
5036 # Kill noauto as it will break merges otherwise.
5037 if "noauto" in settings.features:
5038 while "noauto" in settings.features:
5039 settings.features.remove("noauto")
5040 settings["FEATURES"] = " ".join(settings.features)
5041 settings.backup_changes("FEATURES")
5045 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5046 except ValueError, e:
5047 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5048 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5049 settings["CLEAN_DELAY"], noiselevel=-1)
5050 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5051 settings.backup_changes("CLEAN_DELAY")
5053 EMERGE_WARNING_DELAY = 10
5055 EMERGE_WARNING_DELAY = int(settings.get(
5056 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5057 except ValueError, e:
5058 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5059 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5060 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5061 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5062 settings.backup_changes("EMERGE_WARNING_DELAY")
5064 if "--quiet" in myopts:
5065 settings["PORTAGE_QUIET"]="1"
5066 settings.backup_changes("PORTAGE_QUIET")
5068 # Set so that configs will be merged regardless of remembered status
5069 if ("--noconfmem" in myopts):
5070 settings["NOCONFMEM"]="1"
5071 settings.backup_changes("NOCONFMEM")
5073 # Set various debug markers... They should be merged somehow.
5076 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5077 if PORTAGE_DEBUG not in (0, 1):
5078 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5079 PORTAGE_DEBUG, noiselevel=-1)
5080 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5083 except ValueError, e:
5084 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5085 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5086 settings["PORTAGE_DEBUG"], noiselevel=-1)
5088 if "--debug" in myopts:
5090 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5091 settings.backup_changes("PORTAGE_DEBUG")
5093 if settings.get("NOCOLOR") not in ("yes","true"):
5094 portage.output.havecolor = 1
5096 """The explicit --color < y | n > option overrides the NOCOLOR environment
5097 variable and stdout auto-detection."""
5098 if "--color" in myopts:
5099 if "y" == myopts["--color"]:
5100 portage.output.havecolor = 1
5101 settings["NOCOLOR"] = "false"
5103 portage.output.havecolor = 0
5104 settings["NOCOLOR"] = "true"
5105 settings.backup_changes("NOCOLOR")
5106 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5107 portage.output.havecolor = 0
5108 settings["NOCOLOR"] = "true"
5109 settings.backup_changes("NOCOLOR")
5112 global portage # NFC why this is necessary now - genone
5113 # Disable color until we're sure that it should be enabled (after
5114 # EMERGE_DEFAULT_OPTS has been parsed).
5115 portage.output.havecolor = 0
5116 # This first pass is just for options that need to be known as early as
5117 # possible, such as --config-root. They will be parsed again later,
5118 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5119 # the value of --config-root).
5120 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5121 if "--debug" in myopts:
5122 os.environ["PORTAGE_DEBUG"] = "1"
5123 if "--config-root" in myopts:
5124 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5126 # Portage needs to ensure a sane umask for the files it creates.
5128 settings, trees, mtimedb = load_emerge_config()
5129 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5132 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5133 except (OSError, ValueError), e:
5134 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5135 settings["PORTAGE_NICENESS"])
5136 portage.writemsg("!!! %s\n" % str(e))
5139 if portage.global_updates(settings, trees, mtimedb["updates"]):
5141 # Reload the whole config from scratch.
5142 settings, trees, mtimedb = load_emerge_config(trees=trees)
5143 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5145 xterm_titles = "notitles" not in settings.features
5148 if "--ignore-default-opts" not in sys.argv:
5149 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5150 tmpcmdline.extend(sys.argv[1:])
5151 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5153 if "--digest" in myopts:
5154 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5155 # Reload the whole config from scratch so that the portdbapi internal
5156 # config is updated with new FEATURES.
5157 settings, trees, mtimedb = load_emerge_config(trees=trees)
5158 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5160 for myroot in trees:
5161 mysettings = trees[myroot]["vartree"].settings
5163 adjust_config(myopts, mysettings)
5165 del myroot, mysettings
5167 spinner = stdout_spinner()
5168 if "candy" in settings.features:
5169 spinner.update = spinner.update_scroll
5171 portage.deprecated_profile_check()
5173 #Freeze the portdbapi for enhanced performance:
5174 for myroot in trees:
5175 trees[myroot]["porttree"].dbapi.freeze()
5178 if "moo" in myfiles:
5181 Larry loves Gentoo (""" + os.uname()[0] + """)
5183 _______________________
5184 < Have you mooed today? >
5185 -----------------------
5194 if (myaction in ["world", "system"]) and myfiles:
5195 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5199 ext = os.path.splitext(x)[1]
5200 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5201 print "emerging by path implies --oneshot... adding --oneshot to options."
5202 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5205 if ("--tree" in myopts) and ("--columns" in myopts):
5206 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5209 if ("--quiet" in myopts):
5210 spinner.update = spinner.update_quiet
5211 portage.util.noiselimit = -1
5213 # Always create packages if FEATURES=buildpkg
5214 # Imply --buildpkg if --buildpkgonly
5215 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5216 if "--buildpkg" not in myopts:
5217 myopts["--buildpkg"] = True
5219 # Also allow -S to invoke search action (-sS)
5220 if ("--searchdesc" in myopts):
5221 if myaction and myaction != "search":
5222 myfiles.append(myaction)
5223 if "--search" not in myopts:
5224 myopts["--search"] = True
5227 # Always try and fetch binary packages if FEATURES=getbinpkg
5228 if ("getbinpkg" in settings.features):
5229 myopts["--getbinpkg"] = True
5231 if "--skipfirst" in myopts and "--resume" not in myopts:
5232 myopts["--resume"] = True
5234 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5235 myopts["--usepkgonly"] = True
5237 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5238 myopts["--getbinpkg"] = True
5240 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5241 myopts["--usepkg"] = True
5243 # Also allow -K to apply --usepkg/-k
5244 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5245 myopts["--usepkg"] = True
5247 # Allow -p to remove --ask
5248 if ("--pretend" in myopts) and ("--ask" in myopts):
5249 print ">>> --pretend disables --ask... removing --ask from options."
5252 # forbid --ask when not in a terminal
5253 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5254 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5255 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5259 if settings.get("PORTAGE_DEBUG", "") == "1":
5260 spinner.update = spinner.update_quiet
5262 if "python-trace" in settings.features:
5263 import portage.debug
5264 portage.debug.set_trace(True)
5266 if ("--resume" in myopts):
5267 if "--tree" in myopts:
5268 print "* --tree is currently broken with --resume. Disabling..."
5269 del myopts["--tree"]
5271 if not ("--quiet" in myopts):
5272 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5273 spinner.update = spinner.update_basic
5275 if "--version" in myopts:
5276 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5277 settings.profile_path, settings["CHOST"],
5278 trees[settings["ROOT"]]["vartree"].dbapi)
5280 elif "--help" in myopts:
5281 emerge.help.help(myaction, myopts, portage.output.havecolor)
5284 if portage.wheelgid == portage.portage_gid:
5285 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5286 print " include the portage user as noted above, and then use group portage."
5288 if "--debug" in myopts:
5289 print "myaction", myaction
5290 print "myopts", myopts
5292 if not myaction and not myfiles and "--resume" not in myopts:
5293 emerge.help.help(myaction, myopts, portage.output.havecolor)
5296 # check if root user is the current user for the actions where emerge needs this
5297 if portage.secpass < 2:
5298 # We've already allowed "--version" and "--help" above.
5299 if "--pretend" not in myopts and \
5300 myaction not in ("search","info"):
5301 need_superuser = not \
5302 ("--fetchonly" in myopts or \
5303 "--fetch-all-uri" in myopts or \
5304 myaction in ("metadata", "regen"))
5305 if portage.secpass < 1 or \
5308 access_desc = "superuser"
5310 access_desc = "portage group"
5311 # Always show portage_group_warning() when only portage group
5312 # access is required but the user is not in the portage group.
5313 from portage.data import portage_group_warning
5314 if "--ask" in myopts:
5315 myopts["--pretend"] = True
5317 print ("%s access would be required... " + \
5318 "adding --pretend to options.\n") % access_desc
5319 if portage.secpass < 1 and not need_superuser:
5320 portage_group_warning()
5322 sys.stderr.write(("emerge: %s access would be " + \
5323 "required.\n\n") % access_desc)
5324 if portage.secpass < 1 and not need_superuser:
5325 portage_group_warning()
5328 disable_emergelog = False
5329 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5331 disable_emergelog = True
5333 if myaction in ("search", "info"):
5334 disable_emergelog = True
5335 if disable_emergelog:
5336 """ Disable emergelog for everything except build or unmerge
5337 operations. This helps minimize parallel emerge.log entries that can
5338 confuse log parsers. We especially want it disabled during
5339 parallel-fetch, which uses --resume --fetchonly."""
5341 def emergelog(*pargs, **kargs):
5344 if not "--pretend" in myopts:
5345 emergelog(xterm_titles, "Started emerge on: "+\
5346 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5349 myelogstr=" ".join(myopts)
5351 myelogstr+=" "+myaction
5353 myelogstr+=" "+" ".join(myfiles)
5354 emergelog(xterm_titles, " *** emerge " + myelogstr)
5356 def emergeexitsig(signum, frame):
5357 signal.signal(signal.SIGINT, signal.SIG_IGN)
5358 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5359 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5360 sys.exit(100+signum)
5361 signal.signal(signal.SIGINT, emergeexitsig)
5362 signal.signal(signal.SIGTERM, emergeexitsig)
5365 """This gets out final log message in before we quit."""
5366 if "--pretend" not in myopts:
5367 emergelog(xterm_titles, " *** terminating.")
5368 if "notitles" not in settings.features:
5370 portage.atexit_register(emergeexit)
5372 if myaction in ("config", "metadata", "regen", "sync"):
5373 if "--pretend" in myopts:
5374 sys.stderr.write(("emerge: The '%s' action does " + \
5375 "not support '--pretend'.\n") % myaction)
5377 if "sync" == myaction:
5378 action_sync(settings, trees, mtimedb, myopts, myaction)
5379 elif "metadata" == myaction:
5380 action_metadata(settings, portdb, myopts)
5381 elif myaction=="regen":
5382 validate_ebuild_environment(trees)
5383 action_regen(settings, portdb)
5385 elif "config"==myaction:
5386 validate_ebuild_environment(trees)
5387 action_config(settings, trees, myopts, myfiles)
5390 elif "info"==myaction:
5391 action_info(settings, trees, myopts, myfiles)
5394 elif "search"==myaction:
5395 validate_ebuild_environment(trees)
5396 action_search(settings, portdb, trees["/"]["vartree"],
5397 myopts, myfiles, spinner)
5398 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5399 validate_ebuild_environment(trees)
5400 vartree = trees[settings["ROOT"]]["vartree"]
5401 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5403 if "--pretend" not in myopts:
5404 post_emerge(settings, mtimedb, 0)
5406 elif "depclean"==myaction:
5407 validate_ebuild_environment(trees)
5408 action_depclean(settings, trees, mtimedb["ldpath"],
5410 if "--pretend" not in myopts:
5411 post_emerge(settings, mtimedb, 0)
5412 # "update", "system", or just process files:
5414 validate_ebuild_environment(trees)
5415 action_build(settings, trees, mtimedb,
5416 myopts, myaction, myfiles, spinner)
5417 if "--pretend" not in myopts:
5418 post_emerge(settings, mtimedb, 0)
5420 if __name__ == "__main__":
5421 retval = emerge_main()