2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
7 # This block ensures that ^C interrupts are handled quietly.
11 def exithandler(signum,frame):
12 signal.signal(signal.SIGINT, signal.SIG_IGN)
13 signal.signal(signal.SIGTERM, signal.SIG_IGN)
16 signal.signal(signal.SIGINT, exithandler)
17 signal.signal(signal.SIGTERM, exithandler)
18 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
20 except KeyboardInterrupt:
25 os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
29 sys.path.insert(0, "/usr/lib/portage/pym")
31 del os.environ["PORTAGE_LEGACY_GLOBALS"]
32 from portage import digraph, portdbapi
33 from portage.const import NEWS_LIB_PATH
35 import portage.emergehelp, portage.xpak, commands, errno, re, socket, time, types
37 from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
38 havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
39 xtermTitleReset, yellow
40 from portage.output import create_color_func
41 good = create_color_func("GOOD")
42 bad = create_color_func("BAD")
45 portage.dep._dep_check_strict = True
48 import portage.exception
49 from portage.data import secpass
50 from portage.util import normalize_path as normpath
52 if not hasattr(__builtins__, "set"):
53 from sets import Set as set
54 from itertools import chain, izip
55 from UserDict import DictMixin
60 import pickle as cPickle
62 class stdout_spinner(object):
64 "Gentoo Rocks ("+os.uname()[0]+")",
65 "Thank you for using Gentoo. :)",
66 "Are you actually trying to read this?",
67 "How many times have you stared at this?",
68 "We are generating the cache right now",
69 "You are paying too much attention.",
70 "A theory is better than its explanation.",
71 "Phasers locked on target, Captain.",
72 "Thrashing is just virtual crashing.",
73 "To be is to program.",
74 "Real Users hate Real Programmers.",
75 "When all else fails, read the instructions.",
76 "Functionality breeds Contempt.",
77 "The future lies ahead.",
78 "3.1415926535897932384626433832795028841971694",
79 "Sometimes insanity is the only alternative.",
80 "Inaccuracy saves a world of explanation.",
83 twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
87 self.update = self.update_twirl
88 self.scroll_sequence = self.scroll_msgs[
89 int(time.time() * 100) % len(self.scroll_msgs)]
91 def update_basic(self):
92 self.spinpos = (self.spinpos + 1) % 500
93 if (self.spinpos % 100) == 0:
95 sys.stdout.write(". ")
100 def update_scroll(self):
101 if(self.spinpos >= len(self.scroll_sequence)):
102 sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
103 len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
105 sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
107 self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
109 def update_twirl(self):
110 self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
111 sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
114 def update_quiet(self):
117 def userquery(prompt, responses=None, colours=None):
118 """Displays a prompt and a set of responses, then waits for a response
119 which is checked against the responses and the first to match is
120 returned. An empty response will match the first value in responses. The
121 input buffer is *not* cleared prior to the prompt!
124 responses: a List of Strings.
125 colours: a List of Functions taking and returning a String, used to
126 process the responses for display. Typically these will be functions
127 like red() but could be e.g. lambda x: "DisplayString".
128 If responses is omitted, defaults to ["Yes", "No"], [green, red].
129 If only colours is omitted, defaults to [bold, ...].
131 Returns a member of the List responses. (If called without optional
132 arguments, returns "Yes" or "No".)
133 KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
135 if responses is None:
136 responses, colours = ["Yes", "No"], [green, red]
137 elif colours is None:
139 colours=(colours*len(responses))[:len(responses)]
143 response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
144 for key in responses:
145 # An empty response will match the first value in responses.
146 if response.upper()==key[:len(response)].upper():
148 print "Sorry, response '%s' not understood." % response,
149 except (EOFError, KeyboardInterrupt):
153 def sorted_versions(verlist):
156 verparts = ver.split("-")
157 if len(verparts) == 2:
158 verrev = int(verparts[1][1:])
163 retparts = ret[x].split("-")
164 verdiff = portage.vercmp(retparts[0], verparts[0])
168 if len(retparts) == 2:
169 retrev = int(retparts[1][1:])
180 "clean", "config", "depclean",
182 "prune", "regen", "search",
183 "sync", "system", "unmerge", "world",
186 "--ask", "--alphabetical",
187 "--buildpkg", "--buildpkgonly",
188 "--changelog", "--columns",
192 "--fetchonly", "--fetch-all-uri",
193 "--getbinpkg", "--getbinpkgonly",
194 "--help", "--ignore-default-opts",
196 "--newuse", "--nocolor",
197 "--nodeps", "--noreplace",
198 "--nospinner", "--oneshot",
199 "--onlydeps", "--pretend",
200 "--quiet", "--resume",
201 "--searchdesc", "--selective",
205 "--usepkg", "--usepkgonly",
206 "--verbose", "--version"
212 "b":"--buildpkg", "B":"--buildpkgonly",
213 "c":"--clean", "C":"--unmerge",
214 "d":"--debug", "D":"--deep",
216 "f":"--fetchonly", "F":"--fetch-all-uri",
217 "g":"--getbinpkg", "G":"--getbinpkgonly",
219 "k":"--usepkg", "K":"--usepkgonly",
221 "n":"--noreplace", "N":"--newuse",
222 "o":"--onlydeps", "O":"--nodeps",
223 "p":"--pretend", "P":"--prune",
225 "s":"--search", "S":"--searchdesc",
228 "v":"--verbose", "V":"--version"
231 def emergelog(xterm_titles, mystr, short_msg=None):
234 xtermTitle(short_msg)
238 file_path = "/var/log/emerge.log"
239 mylogfile = open(file_path, "a")
240 portage.util.apply_secpass_permissions(file_path,
241 uid=portage.portage_uid, gid=portage.portage_gid,
245 mylock = portage.locks.lockfile(mylogfile)
246 # seek because we may have gotten held up by the lock.
247 # if so, we may not be positioned at the end of the file.
249 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
253 portage.locks.unlockfile(mylock)
255 except (IOError,OSError,portage.exception.PortageException), e:
257 print >> sys.stderr, "emergelog():",e
259 def countdown(secs=5, doing="Starting"):
261 print ">>> Waiting",secs,"seconds before starting..."
262 print ">>> (Control-C to abort)...\n"+doing+" in: ",
266 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
271 # formats a size given in bytes nicely
272 def format_size(mysize):
273 if type(mysize) not in [types.IntType,types.LongType]:
275 if 0 != mysize % 1024:
276 # Always round up to the next kB so that it doesn't show 0 kB when
277 # some small file still needs to be fetched.
278 mysize += 1024 - mysize % 1024
279 mystr=str(mysize/1024)
283 mystr=mystr[:mycount]+","+mystr[mycount:]
287 def getgccversion(chost):
290 return: the current in-use gcc version
293 gcc_ver_command = 'gcc -dumpversion'
294 gcc_ver_prefix = 'gcc-'
296 gcc_not_found_error = red(
297 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
298 "!!! to update the environment of this terminal and possibly\n" +
299 "!!! other terminals also.\n"
302 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
303 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
304 part1, part2 = myoutput.split("/")
305 if part1.startswith(chost + "-"):
306 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
308 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
309 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
310 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
312 mystatus, myoutput = commands.getstatusoutput(
313 chost + "-" + gcc_ver_command)
314 if mystatus == os.EX_OK:
315 return gcc_ver_prefix + myoutput
317 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
318 if mystatus == os.EX_OK:
319 return gcc_ver_prefix + myoutput
321 portage.writemsg(gcc_not_found_error, noiselevel=-1)
322 return "[unavailable]"
324 def getportageversion(portdir, target_root, profile, chost, vardb):
325 profilever = "unavailable"
327 realpath = os.path.realpath(profile)
328 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
329 if realpath.startswith(basepath):
330 profilever = realpath[1 + len(basepath):]
333 profilever = "!" + os.readlink(profile)
336 del realpath, basepath
339 libclist = vardb.match("virtual/libc")
340 libclist += vardb.match("virtual/glibc")
341 libclist = portage.util.unique_array(libclist)
343 xs=portage.catpkgsplit(x)
345 libcver+=","+"-".join(xs[1:])
347 libcver="-".join(xs[1:])
349 libcver="unavailable"
351 gccver = getgccversion(chost)
352 unameout=os.uname()[2]+" "+os.uname()[4]
354 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
356 def create_depgraph_params(myopts, myaction):
357 #configure emerge engine parameters
359 # self: include _this_ package regardless of if it is merged.
360 # selective: exclude the package if it is merged
361 # recurse: go into the dependencies
362 # deep: go into the dependencies of already merged packages
363 # empty: pretend nothing is merged
364 myparams = ["recurse"]
367 if "--update" in myopts or \
368 "--newuse" in myopts or \
369 "--noreplace" in myopts or \
370 myaction in ("system", "world"):
371 add.extend(["selective"])
372 if "--emptytree" in myopts:
373 add.extend(["empty"])
374 sub.extend(["selective"])
375 if "--nodeps" in myopts:
376 sub.extend(["recurse"])
377 if "--deep" in myopts:
380 if (x not in myparams) and (x not in sub):
387 # search functionality
399 def __init__(self, settings, portdb, vartree, spinner, searchdesc,
401 """Searches the available and installed packages for the supplied search key.
402 The list of available and installed packages is created at object instantiation.
403 This makes successive searches faster."""
404 self.settings = settings
406 self.vartree = vartree
407 self.spinner = spinner
408 self.verbose = verbose
409 self.searchdesc = searchdesc
411 def execute(self,searchkey):
412 """Performs the search for the supplied search key"""
414 self.searchkey=searchkey
415 self.packagematches = []
418 self.matches = {"pkg":[], "desc":[]}
421 self.matches = {"pkg":[]}
422 print "Searching... ",
425 if self.searchkey[0] == '%':
427 self.searchkey = self.searchkey[1:]
428 if self.searchkey[0] == '@':
430 self.searchkey = self.searchkey[1:]
432 self.searchre=re.compile(self.searchkey,re.I)
434 self.searchre=re.compile(re.escape(self.searchkey), re.I)
435 for package in self.portdb.cp_all():
436 self.spinner.update()
439 match_string = package[:]
441 match_string = package.split("/")[-1]
444 if self.searchre.search(match_string):
445 if not self.portdb.xmatch("match-visible", package):
447 self.matches["pkg"].append([package,masked])
448 elif self.searchdesc: # DESCRIPTION searching
449 full_package = self.portdb.xmatch("bestmatch-visible", package)
451 #no match found; we don't want to query description
452 full_package = portage.best(
453 self.portdb.xmatch("match-all", package))
459 full_desc = self.portdb.aux_get(
460 full_package, ["DESCRIPTION"])[0]
462 print "emerge: search: aux_get() failed, skipping"
464 if self.searchre.search(full_desc):
465 self.matches["desc"].append([full_package,masked])
467 for mtype in self.matches.keys():
468 self.matches[mtype].sort()
469 self.mlen += len(self.matches[mtype])
472 """Outputs the results of the search."""
473 print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
474 print "[ Applications found : "+white(str(self.mlen))+" ]"
476 for mtype in self.matches.keys():
477 for match,masked in self.matches[mtype]:
480 full_package = self.portdb.xmatch(
481 "bestmatch-visible", match)
483 #no match found; we don't want to query description
485 full_package = portage.best(
486 self.portdb.xmatch("match-all",match))
489 match = portage.pkgsplit(match)[0]
493 desc, homepage, license = self.portdb.aux_get(
494 full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
496 print "emerge: search: aux_get() failed, skipping"
499 print green("*")+" "+white(match)+" "+red("[ Masked ]")
501 print green("*")+" "+white(match)
502 myversion = self.getVersion(full_package, search.VERSION_RELEASE)
505 mycat = match.split("/")[0]
506 mypkg = match.split("/")[1]
507 mycpv = match + "-" + myversion
508 myebuild = self.portdb.findname(mycpv)
509 pkgdir = os.path.dirname(myebuild)
510 from portage import manifest
511 mf = manifest.Manifest(
512 pkgdir, self.settings["DISTDIR"])
513 fetchlist = self.portdb.getfetchlist(mycpv,
514 mysettings=self.settings, all=True)[1]
516 mysum[0] = mf.getDistfilesSize(fetchlist)
517 mystr = str(mysum[0]/1024)
521 mystr=mystr[:mycount]+","+mystr[mycount:]
524 mysum[0] = "Unknown (missing digest for %s)" % str(e)
527 print " ", darkgreen("Latest version available:"),myversion
528 print " ", self.getInstallationStatus(mycat+'/'+mypkg)
529 print " ", darkgreen("Size of files:"),mysum[0]
530 print " ", darkgreen("Homepage:")+" ",homepage
531 print " ", darkgreen("Description:")+" ",desc
532 print " ", darkgreen("License:")+" ",license
538 def getInstallationStatus(self,package):
539 installed_package = self.vartree.dep_bestmatch(package)
541 version = self.getVersion(installed_package,search.VERSION_RELEASE)
543 result = darkgreen("Latest version installed:")+" "+version
545 result = darkgreen("Latest version installed:")+" [ Not Installed ]"
548 def getVersion(self,full_package,detail):
549 if len(full_package) > 1:
550 package_parts = portage.catpkgsplit(full_package)
551 if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
552 result = package_parts[2]+ "-" + package_parts[3]
554 result = package_parts[2]
560 #build our package digraph
561 def getlist(settings, mode):
563 mylines = settings.packages
566 file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
567 myfile = open(file_path, "r")
568 mylines = myfile.readlines()
570 except (OSError, IOError), e:
571 if e.errno == errno.ENOENT:
572 portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
578 myline=" ".join(x.split())
587 mynewlines.append(myline.strip())
591 def clean_world(vardb, cpv):
592 """Remove a package from the world file when unmerged."""
593 world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
594 worldlist = portage.util.grabfile(world_filename)
595 mykey = portage.cpv_getkey(cpv)
598 if portage.dep_getkey(x) == mykey:
599 matches = vardb.match(x, use_cache=0)
603 elif len(matches) == 1 and matches[0] == cpv:
607 #others are around; keep it.
608 newworldlist.append(x)
610 #this doesn't match the package we're unmerging; keep it.
611 newworldlist.append(x)
613 portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
614 gid=portage.portage_gid, mode=02770)
615 portage.util.write_atomic(world_filename, "\n".join(newworldlist))
617 def genericdict(mylist):
620 mynewdict[portage.dep_getkey(x)]=x
623 def filter_iuse_defaults(iuse):
625 if flag.startswith("+"):
630 class DepPriority(object):
632 This class generates an integer priority level based of various
633 attributes of the dependency relationship. Attributes can be assigned
634 at any time and the new integer value will be generated on calls to the
635 __int__() method. Rich comparison operators are supported.
637 The boolean attributes that affect the integer value are "satisfied",
638 "buildtime", "runtime", and "system". Various combinations of
639 attributes lead to the following priority levels:
641 Combination of properties Priority level
643 not satisfied and buildtime 0
644 not satisfied and runtime -1
645 satisfied and buildtime -2
646 satisfied and runtime -3
647 (none of the above) -4
649 Several integer constants are defined for categorization of priority
652 MEDIUM The upper boundary for medium dependencies.
653 SOFT The upper boundary for soft dependencies.
654 MIN The lower boundary for soft dependencies.
656 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
660 def __init__(self, **kwargs):
661 for myattr in self.__slots__:
662 if myattr == "__weakref__":
664 myvalue = kwargs.get(myattr, False)
665 setattr(self, myattr, myvalue)
667 if not self.satisfied:
677 def __lt__(self, other):
678 return self.__int__() < other
679 def __le__(self, other):
680 return self.__int__() <= other
681 def __eq__(self, other):
682 return self.__int__() == other
683 def __ne__(self, other):
684 return self.__int__() != other
685 def __gt__(self, other):
686 return self.__int__() > other
687 def __ge__(self, other):
688 return self.__int__() >= other
691 return copy.copy(self)
693 myvalue = self.__int__()
694 if myvalue > self.MEDIUM:
696 if myvalue > self.SOFT:
700 class FakeVartree(portage.vartree):
701 """This is implements an in-memory copy of a vartree instance that provides
702 all the interfaces required for use by the depgraph. The vardb is locked
703 during the constructor call just long enough to read a copy of the
704 installed package information. This allows the depgraph to do it's
705 dependency calculations without holding a lock on the vardb. It also
706 allows things like vardb global updates to be done in memory so that the
707 user doesn't necessarily need write access to the vardb in cases where
708 global updates are necessary (updates are performed when necessary if there
709 is not a matching ebuild in the tree)."""
710 def __init__(self, real_vartree, portdb):
711 self.root = real_vartree.root
712 self.settings = real_vartree.settings
713 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
714 vdb_path = os.path.join(self.root, portage.VDB_PATH)
716 # At least the parent needs to exist for the lock file.
717 portage.util.ensure_dirs(vdb_path)
718 except portage.exception.PortageException:
722 if os.access(vdb_path, os.W_OK):
723 vdb_lock = portage.locks.lockdir(vdb_path)
724 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
725 "DEPEND", "RDEPEND", "PDEPEND"]
726 real_dbapi = real_vartree.dbapi
728 for cpv in real_dbapi.cpv_all():
729 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
730 myslot = metadata["SLOT"]
731 mycp = portage.dep_getkey(cpv)
732 myslot_atom = "%s:%s" % (mycp, myslot)
734 mycounter = long(metadata["COUNTER"])
737 metadata["COUNTER"] = str(mycounter)
738 other_counter = slot_counters.get(myslot_atom, None)
739 if other_counter is not None:
740 if other_counter > mycounter:
742 slot_counters[myslot_atom] = mycounter
743 self.dbapi.cpv_inject(cpv, metadata=metadata)
744 real_dbapi.flush_cache()
747 portage.locks.unlockdir(vdb_lock)
748 # Populate the old-style virtuals using the cached values.
749 if not self.settings.treeVirtuals:
750 self.settings.treeVirtuals = portage.util.map_dictlist_vals(
751 portage.getCPFromCPV, self.get_all_provides())
753 # Intialize variables needed for lazy cache pulls of the live ebuild
754 # metadata. This ensures that the vardb lock is released ASAP, without
755 # being delayed in case cache generation is triggered.
756 self._aux_get = self.dbapi.aux_get
757 self.dbapi.aux_get = self._aux_get_wrapper
758 self._aux_get_history = set()
759 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
760 self._portdb = portdb
761 self._global_updates = None
763 def _aux_get_wrapper(self, pkg, wants):
764 if pkg in self._aux_get_history:
765 return self._aux_get(pkg, wants)
766 self._aux_get_history.add(pkg)
768 # Use the live ebuild metadata if possible.
769 live_metadata = dict(izip(self._portdb_keys,
770 self._portdb.aux_get(pkg, self._portdb_keys)))
771 self.dbapi.aux_update(pkg, live_metadata)
772 except (KeyError, portage.exception.PortageException):
773 if self._global_updates is None:
774 self._global_updates = \
775 grab_global_updates(self._portdb.porttree_root)
776 perform_global_updates(
777 pkg, self.dbapi, self._global_updates)
778 return self._aux_get(pkg, wants)
780 def grab_global_updates(portdir):
781 from portage.update import grab_updates, parse_updates
782 updpath = os.path.join(portdir, "profiles", "updates")
784 rawupdates = grab_updates(updpath)
785 except portage.exception.DirectoryNotFound:
788 for mykey, mystat, mycontent in rawupdates:
789 commands, errors = parse_updates(mycontent)
790 upd_commands.extend(commands)
793 def perform_global_updates(mycpv, mydb, mycommands):
794 from portage.update import update_dbentries
795 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
796 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
797 updates = update_dbentries(mycommands, aux_dict)
799 mydb.aux_update(mycpv, updates)
801 class BlockerCache(DictMixin):
802 """This caches blockers of installed packages so that dep_check does not
803 have to be done for every single installed package on every invocation of
804 emerge. The cache is invalidated whenever it is detected that something
805 has changed that might alter the results of dep_check() calls:
806 1) the set of installed packages (including COUNTER) has changed
807 2) the old-style virtuals have changed
809 class BlockerData(object):
810 def __init__(self, counter, atoms):
811 self.counter = counter
814 def __init__(self, myroot, vardb):
816 self._installed_pkgs = set(vardb.cpv_all())
817 self._virtuals = vardb.settings.getvirtuals()
818 self._cache_filename = os.path.join(myroot,
819 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
820 self._cache_version = "1"
821 self._cache_data = None
822 self._modified = False
827 f = open(self._cache_filename)
828 mypickle = cPickle.Unpickler(f)
829 mypickle.find_global = None
830 self._cache_data = mypickle.load()
833 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
835 cache_valid = self._cache_data and \
836 isinstance(self._cache_data, dict) and \
837 self._cache_data.get("version") == self._cache_version and \
838 self._cache_data.get("virtuals") == self._virtuals and \
839 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
841 for pkg in self._installed_pkgs:
842 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
847 self._cache_data = {"version":self._cache_version}
848 self._cache_data["blockers"] = {}
849 self._cache_data["virtuals"] = self._virtuals
850 self._modified = False
853 """If the current user has permission and the internal blocker cache
854 been updated, save it to disk and mark it unmodified. This is called
855 by emerge after it has proccessed blockers for all installed packages.
856 Currently, the cache is only written if the user has superuser
857 privileges (since that's required to obtain a lock), but all users
858 have read access and benefit from faster blocker lookups (as long as
859 the entire cache is still valid). The cache is stored as a pickled
860 dict object with the following format:
864 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
865 "virtuals" : vardb.settings.getvirtuals()
868 if self._modified and \
871 f = portage.util.atomic_ofstream(self._cache_filename)
872 cPickle.dump(self._cache_data, f, -1)
874 portage.util.apply_secpass_permissions(
875 self._cache_filename, gid=portage.portage_gid, mode=0644)
876 except (IOError, OSError), e:
878 self._modified = False
880 def __setitem__(self, cpv, blocker_data):
882 Update the cache and mark it as modified for a future call to
885 @param cpv: Package for which to cache blockers.
887 @param blocker_data: An object with counter and atoms attributes.
888 @type blocker_data: BlockerData
890 self._cache_data["blockers"][cpv] = \
891 (blocker_data.counter, blocker_data.atoms)
892 self._modified = True
894 def __getitem__(self, cpv):
897 @returns: An object with counter and atoms attributes.
899 return self.BlockerData(*self._cache_data["blockers"][cpv])
901 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
903 from formatter import AbstractFormatter, DumbWriter
904 f = AbstractFormatter(DumbWriter(maxcol=72))
906 print "\n\n!!! Invalid or corrupt dependency specification: "
914 p_type, p_root, p_key, p_status = parent_node
916 if p_status == "nomerge":
917 category, pf = portage.catsplit(p_key)
918 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
919 msg.append("Portage is unable to process the dependencies of the ")
920 msg.append("'%s' package. " % p_key)
921 msg.append("In order to correct this problem, the package ")
922 msg.append("should be uninstalled, reinstalled, or upgraded. ")
923 msg.append("As a temporary workaround, the --nodeps option can ")
924 msg.append("be used to ignore all dependencies. For reference, ")
925 msg.append("the problematic dependencies can be found in the ")
926 msg.append("*DEPEND files located in '%s/'." % pkg_location)
928 msg.append("This package can not be installed. ")
929 msg.append("Please notify the '%s' package maintainer " % p_key)
930 msg.append("about this problem.")
933 f.add_flowing_data(x)
941 "installed":"vartree"}
943 def __init__(self, settings, trees, myopts, myparams, spinner):
944 self.settings = settings
945 self.target_root = settings["ROOT"]
947 self.myparams = myparams
949 if settings.get("PORTAGE_DEBUG", "") == "1":
951 self.spinner = spinner
952 self.pkgsettings = {}
953 # Maps cpv to digraph node for all nodes added to the graph.
954 self.pkg_node_map = {}
955 # Maps slot atom to digraph node for all nodes added to the graph.
956 self._slot_node_map = {}
958 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
962 self.trees[myroot] = {}
963 for tree in ("porttree", "bintree"):
964 self.trees[myroot][tree] = trees[myroot][tree]
965 self.trees[myroot]["vartree"] = \
966 FakeVartree(trees[myroot]["vartree"],
967 trees[myroot]["porttree"].dbapi)
968 self.pkgsettings[myroot] = portage.config(
969 clone=self.trees[myroot]["vartree"].settings)
970 self.pkg_node_map[myroot] = {}
971 self._slot_node_map[myroot] = {}
972 vardb = self.trees[myroot]["vartree"].dbapi
973 # This fakedbapi instance will model the state that the vdb will
974 # have after new packages have been installed.
975 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
976 self.mydbapi[myroot] = fakedb
977 if "--nodeps" not in self.myopts and \
978 "--buildpkgonly" not in self.myopts:
979 # --nodeps bypasses this, since it isn't needed in this case
980 # and the cache pulls might trigger (slow) cache generation.
981 for pkg in vardb.cpv_all():
982 self.spinner.update()
983 fakedb.cpv_inject(pkg,
984 metadata=dict(izip(self._mydbapi_keys,
985 vardb.aux_get(pkg, self._mydbapi_keys))))
987 self.useFlags[myroot] = {}
988 if "--usepkg" in self.myopts:
989 self.trees[myroot]["bintree"].populate(
990 "--getbinpkg" in self.myopts,
991 "--getbinpkgonly" in self.myopts)
995 self.digraph=portage.digraph()
996 # Tracks simple parent/child relationships (PDEPEND relationships are
998 self._parent_child_digraph = digraph()
1000 self.outdatedpackages=[]
1002 self.blocker_digraph = digraph()
1003 self.blocker_parents = {}
1004 self._slot_collision_info = []
1005 # Slot collision nodes are not allowed to block other packages since
1006 # blocker validation is only able to account for one package per slot.
1007 self._slot_collision_nodes = set()
1008 self._altlist_cache = {}
1009 self._pprovided_args = []
1011 def _show_slot_collision_notice(self, packages):
1012 """Show an informational message advising the user to mask one of the
1013 the packages. In some cases it may be possible to resolve this
1014 automatically, but support for backtracking (removal nodes that have
1015 already been selected) will be required in order to handle all possible
1019 msg.append("\n!!! Multiple versions within a single " + \
1020 "package slot have been \n")
1021 msg.append("!!! pulled into the dependency graph:\n\n")
1022 for node, parents in packages:
1023 msg.append(str(node))
1025 msg.append(" pulled in by\n")
1026 for parent in parents:
1028 msg.append(str(parent))
1031 msg.append(" (no parents)\n")
1033 sys.stderr.write("".join(msg))
1036 if "--quiet" in self.myopts:
1040 msg.append("It may be possible to solve this problem ")
1041 msg.append("by using package.mask to prevent one of ")
1042 msg.append("those packages from being selected. ")
1043 msg.append("However, it is also possible that conflicting ")
1044 msg.append("dependencies exist such that they are impossible to ")
1045 msg.append("satisfy simultaneously. If such a conflict exists in ")
1046 msg.append("the dependencies of two different packages, then those ")
1047 msg.append("packages can not be installed simultaneously.")
1049 from formatter import AbstractFormatter, DumbWriter
1050 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1052 f.add_flowing_data(x)
1056 msg.append("For more information, see MASKED PACKAGES ")
1057 msg.append("section in the emerge man page or refer ")
1058 msg.append("to the Gentoo Handbook.")
1060 f.add_flowing_data(x)
1064 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1065 priority=DepPriority(), rev_dep=False, arg=None):
1067 Fills the digraph with nodes comprised of packages to merge.
1068 mybigkey is the package spec of the package to merge.
1069 myparent is the package depending on mybigkey ( or None )
1070 addme = Should we add this package to the digraph or are we just looking at it's deps?
1071 Think --onlydeps, we need to ignore packages in that case.
1074 #IUSE-aware emerge -> USE DEP aware depgraph
1075 #"no downgrade" emerge
1077 mytype, myroot, mykey = mybigkey
1078 existing_node = None
1080 existing_node = self.pkg_node_map[myroot].get(mykey)
1082 self._parent_child_digraph.add(existing_node, myparent)
1083 if existing_node != myparent:
1084 # Refuse to make a node depend on itself so that the we don't
1085 # don't create a bogus circular dependency in self.altlist().
1086 if rev_dep and myparent:
1087 self.digraph.addnode(myparent, existing_node,
1090 self.digraph.addnode(existing_node, myparent,
1094 self.spinner.update()
1095 if mytype == "blocks":
1097 "--buildpkgonly" not in self.myopts and \
1098 "--nodeps" not in self.myopts and \
1099 myparent not in self._slot_collision_nodes:
1100 mybigkey[1] = myparent[1]
1101 self.blocker_parents.setdefault(
1102 tuple(mybigkey), set()).add(myparent)
1104 if not arg and myroot == self.target_root:
1105 arg = portage.best_match_to_list(mykey, self.args_keys)
1106 # select the correct /var database that we'll be checking against
1107 vardbapi = self.trees[myroot]["vartree"].dbapi
1108 portdb = self.trees[myroot]["porttree"].dbapi
1109 bindb = self.trees[myroot]["bintree"].dbapi
1110 pkgsettings = self.pkgsettings[myroot]
1112 # if the package is already on the system, we add a "nomerge"
1113 # directive, otherwise we add a "merge" directive.
1115 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1118 self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
1119 myuse = self.pkgsettings[myroot]["USE"].split()
1122 if mytype == "installed":
1124 if addme and mytype != "installed":
1125 # this is where we add the node to the list of packages to merge
1126 if "selective" in self.myparams or not arg:
1127 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1130 """ If we aren't merging, perform the --newuse check.
1131 If the package has new iuse flags or different use flags then if
1132 --newuse is specified, we need to merge the package. """
1133 if merging==0 and "--newuse" in self.myopts and \
1134 vardbapi.cpv_exists(mykey):
1135 pkgsettings.setcpv(mykey, mydb=mydbapi)
1136 forced_flags = set()
1137 forced_flags.update(pkgsettings.useforce)
1138 forced_flags.update(pkgsettings.usemask)
1139 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1140 iuses = set(filter_iuse_defaults(
1141 mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
1142 old_iuse = set(filter_iuse_defaults(
1143 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1144 if iuses.symmetric_difference(
1145 old_iuse).difference(forced_flags):
1147 elif old_iuse.intersection(old_use) != \
1148 iuses.intersection(myuse):
1151 if addme and merging == 1:
1152 mybigkey.append("merge")
1154 mybigkey.append("nomerge")
1155 jbigkey = tuple(mybigkey)
1158 metadata = dict(izip(self._mydbapi_keys,
1159 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1160 if merging == 0 and vardbapi.cpv_exists(mykey):
1161 metadata["USE"] = vardbapi.aux_get(mykey, ["USE"])[0]
1162 myuse = metadata["USE"].split()
1163 metadata["SLOT"] = vardbapi.aux_get(mykey, ["SLOT"])[0]
1164 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1165 existing_node = self._slot_node_map[myroot].get(
1167 slot_collision = False
1169 e_type, myroot, e_cpv, e_status = existing_node
1171 # The existing node can be reused.
1172 self._parent_child_digraph.add(existing_node, myparent)
1173 if rev_dep and myparent:
1174 ptype, proot, pkey, pstatus = myparent
1175 self.digraph.addnode(myparent, existing_node,
1178 self.digraph.addnode(existing_node, myparent,
1182 # A slot collision has occurred. Sometimes this coincides
1183 # with unresolvable blockers, so the slot collision will be
1184 # shown later if there are no unresolvable blockers.
1185 e_parents = self._parent_child_digraph.parent_nodes(
1189 myparents.append(myparent)
1190 self._slot_collision_info.append(
1191 ((jbigkey, myparents), (existing_node, e_parents)))
1192 self._slot_collision_nodes.add(jbigkey)
1193 slot_collision = True
1196 # Now add this node to the graph so that self.display()
1197 # can show use flags and --tree portage.output. This node is
1198 # only being partially added to the graph. It must not be
1199 # allowed to interfere with the other nodes that have been
1200 # added. Do not overwrite data for existing nodes in
1201 # self.pkg_node_map and self.mydbapi since that data will
1202 # be used for blocker validation.
1203 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1204 self.useFlags[myroot].setdefault(mykey, myuse)
1205 # Even though the graph is now invalid, continue to process
1206 # dependencies so that things like --fetchonly can still
1207 # function despite collisions.
1209 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1210 self._slot_node_map[myroot][slot_atom] = jbigkey
1211 self.pkg_node_map[myroot][mykey] = jbigkey
1212 self.useFlags[myroot][mykey] = myuse
1214 if rev_dep and myparent:
1215 self.digraph.addnode(myparent, jbigkey,
1218 self.digraph.addnode(jbigkey, myparent,
1221 # Do this even when addme is False (--onlydeps) so that the
1222 # parent/child relationship is always known in case
1223 # self._show_slot_collision_notice() needs to be called later.
1224 self._parent_child_digraph.add(jbigkey, myparent)
1226 """ This section determines whether we go deeper into dependencies or not.
1227 We want to go deeper on a few occasions:
1228 Installing package A, we need to make sure package A's deps are met.
1229 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1230 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1232 if "deep" not in self.myparams and not merging and \
1233 not ("--update" in self.myopts and arg and merging):
1235 elif "recurse" not in self.myparams:
1238 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1239 Pull from bintree if it's binary package, porttree if it's ebuild.
1240 Binpkg's can be either remote or local. """
1243 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1244 depvalues = mydbapi.aux_get(mykey, depkeys)
1245 for i in xrange(len(depkeys)):
1246 edepend[depkeys[i]] = depvalues[i]
1248 if mytype == "ebuild":
1249 if "--buildpkgonly" in self.myopts:
1250 edepend["RDEPEND"] = ""
1251 edepend["PDEPEND"] = ""
1252 if not (arg and "--onlydeps" in self.myopts and \
1253 mytype == "ebuild") and \
1254 self.myopts.get("--with-bdeps", "n") == "n" and \
1255 (mytype == "binary" or mybigkey[3] == "nomerge"):
1256 edepend["DEPEND"] = ""
1258 """ We have retrieve the dependency information, now we need to recursively
1259 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1261 mp = tuple(mybigkey)
1264 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1265 myuse=myuse, priority=DepPriority(buildtime=True),
1268 """RDEPEND is soft by definition. However, in order to ensure
1269 correct merge order, we make it a hard dependency. Otherwise, a
1270 build time dependency might not be usable due to it's run time
1271 dependencies not being installed yet.
1273 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1274 myuse=myuse, priority=DepPriority(runtime=True),
1277 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1278 # Post Depend -- Add to the list without a parent, as it depends
1279 # on a package being present AND must be built after that package.
1280 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1281 myuse=myuse, priority=DepPriority(), rev_deps=True,
1284 except ValueError, e:
1286 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1287 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1289 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1290 portage.writemsg("\n", noiselevel=-1)
1291 if mytype == "binary":
1293 "!!! This binary package cannot be installed: '%s'\n" % \
1294 mykey, noiselevel=-1)
1295 elif mytype == "ebuild":
1296 myebuild, mylocation = portdb.findname2(mykey)
1297 portage.writemsg("!!! This ebuild cannot be installed: " + \
1298 "'%s'\n" % myebuild, noiselevel=-1)
1299 portage.writemsg("!!! Please notify the package maintainer " + \
1300 "that atoms must be fully-qualified.\n", noiselevel=-1)
1304 def select_files(self,myfiles):
1305 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1307 myroot = self.target_root
1308 portdb = self.trees[myroot]["porttree"].dbapi
1309 bindb = self.trees[myroot]["bintree"].dbapi
1310 pkgsettings = self.pkgsettings[myroot]
1312 def visible(mylist):
1313 matches = portdb.gvisible(portdb.visible(mylist))
1314 return [x for x in mylist \
1315 if x in matches or not portdb.cpv_exists(x)]
1317 ext = os.path.splitext(x)[1]
1319 if not os.path.exists(x):
1321 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1322 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1323 elif os.path.exists(
1324 os.path.join(pkgsettings["PKGDIR"], x)):
1325 x = os.path.join(pkgsettings["PKGDIR"], x)
1327 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1328 print "!!! Please ensure the tbz2 exists as specified.\n"
1330 mytbz2=portage.xpak.tbz2(x)
1331 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1332 if os.path.realpath(x) != \
1333 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1334 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1336 if not self.create(["binary", myroot, mykey],
1337 None, "--onlydeps" not in self.myopts):
1338 return (0,myfavorites)
1339 elif not "--oneshot" in self.myopts:
1340 myfavorites.append(mykey)
1341 elif ext==".ebuild":
1342 x = os.path.realpath(x)
1343 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1344 ebuild_path = portdb.findname(mykey)
1346 if os.path.realpath(ebuild_path) != x:
1347 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1349 if mykey not in portdb.xmatch(
1350 "match-visible", portage.dep_getkey(mykey)):
1351 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1352 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1353 print colorize("BAD", "*** page for details.")
1354 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1357 raise portage.exception.PackageNotFound(
1358 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1359 if not self.create(["ebuild", myroot, mykey],
1360 None, "--onlydeps" not in self.myopts):
1361 return (0,myfavorites)
1362 elif not "--oneshot" in self.myopts:
1363 myfavorites.append(mykey)
1365 if not is_valid_package_atom(x):
1366 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1368 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1369 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1373 if "--usepkg" in self.myopts:
1374 mykey = portage.dep_expand(x, mydb=bindb,
1375 settings=pkgsettings)
1376 if (mykey and not mykey.startswith("null/")) or \
1377 "--usepkgonly" in self.myopts:
1378 arg_atoms.append((x, mykey))
1381 mykey = portage.dep_expand(x,
1382 mydb=portdb, settings=pkgsettings)
1383 arg_atoms.append((x, mykey))
1384 except ValueError, errpkgs:
1385 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1386 print "!!! one of the following fully-qualified ebuild names instead:\n"
1387 for i in errpkgs[0]:
1388 print " " + green(i)
1392 if "--update" in self.myopts:
1393 """Make sure all installed slots are updated when possible. Do this
1394 with --emptytree also, to ensure that all slots are remerged."""
1395 vardb = self.trees[self.target_root]["vartree"].dbapi
1397 for myarg, myatom in arg_atoms:
1398 greedy_atoms.append((myarg, myatom))
1400 for cpv in vardb.match(myatom):
1401 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1404 if "--usepkg" in self.myopts:
1405 mymatches = bindb.match(myatom)
1406 if "--usepkgonly" not in self.myopts:
1407 mymatches = visible(mymatches)
1408 best_pkg = portage.best(mymatches)
1410 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1411 best_pkgs.append(("binary", best_pkg, best_slot))
1412 if "--usepkgonly" not in self.myopts:
1413 best_pkg = portage.best(portdb.match(myatom))
1415 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1416 best_pkgs.append(("ebuild", best_pkg, best_slot))
1418 best_pkg = portage.best([x[1] for x in best_pkgs])
1419 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1420 best_slot = best_pkgs[0][2]
1421 myslots.add(best_slot)
1422 if len(myslots) > 1:
1423 for myslot in myslots:
1424 myslot_atom = "%s:%s" % \
1425 (portage.dep_getkey(myatom), myslot)
1427 if "--usepkgonly" not in self.myopts and \
1428 self.trees[self.target_root][
1429 "porttree"].dbapi.match(myslot_atom):
1431 elif "--usepkg" in self.myopts:
1432 mymatches = bindb.match(myslot_atom)
1433 if "--usepkgonly" not in self.myopts:
1434 mymatches = visible(mymatches)
1438 greedy_atoms.append((myarg, myslot_atom))
1439 arg_atoms = greedy_atoms
1441 """ These are used inside self.create() in order to ensure packages
1442 that happen to match arguments are not incorrectly marked as nomerge."""
1443 self.args_keys = [x[1] for x in arg_atoms]
1444 for myarg, myatom in arg_atoms:
1446 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1447 except portage.exception.MissingSignature, e:
1448 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1449 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1450 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1451 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1452 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1454 except portage.exception.InvalidSignature, e:
1455 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1456 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1457 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1458 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1459 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1461 except SystemExit, e:
1462 raise # Needed else can't exit
1463 except Exception, e:
1464 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1465 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1469 return (0,myfavorites)
1470 elif not "--oneshot" in self.myopts:
1471 mykey = portage.dep_getkey(myatom)
1472 if mykey not in myfavorites:
1473 myfavorites.append(mykey)
1476 if "--usepkgonly" in self.myopts:
1477 for xs in self.digraph.all_nodes():
1478 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1482 print "Missing binary for:",xs[2]
1484 if not self.validate_blockers():
1485 return False, myfavorites
1487 # We're true here unless we are missing binaries.
1488 return (not missing,myfavorites)
1490 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1491 myuse=None, raise_on_missing=False, priority=DepPriority(),
1492 rev_deps=False, parent_arg=None):
1493 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1494 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1495 myparent = the node whose depstring is being passed in
1496 arg = package was specified on the command line, merge even if it's already installed
1497 myuse = USE flags at present
1498 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1499 else continue trying.
1500 return 1 on success, 0 for failure
1503 portdb = self.trees[myroot]["porttree"].dbapi
1504 bindb = self.trees[myroot]["bintree"].dbapi
1505 vardb = self.trees[myroot]["vartree"].dbapi
1506 pkgsettings = self.pkgsettings[myroot]
1508 p_type, p_root, p_key, p_status = myparent
1510 if "--debug" in self.myopts:
1512 print "Parent: ",myparent
1513 print "Depstring:",depstring
1515 print "Reverse:", rev_deps
1516 print "Priority:", priority
1518 #processing dependencies
1519 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1520 dependencies are satisfiable. """
1522 if myparent and p_status == "nomerge":
1523 portage.dep._dep_check_strict = False
1524 mycheck = portage.dep_check(depstring, None,
1525 pkgsettings, myuse=myuse,
1526 use_binaries=("--usepkgonly" in self.myopts),
1527 myroot=myroot, trees=self.trees)
1529 portage.dep._dep_check_strict = True
1533 show_invalid_depstring_notice(myparent, depstring, mycheck[1])
1535 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1537 mymerge = mycheck[1]
1539 if not mymerge and arg and \
1540 portage.best_match_to_list(depstring, self.args_keys):
1541 # A provided package has been specified on the command line. The
1542 # package will not be merged and a warning will be displayed.
1543 self._pprovided_args.append(arg)
1546 # The parent is added after it's own dep_check call so that it
1547 # isn't allowed to satisfy a direct bootstrap dependency on itself
1548 # via an old-style virtual. This isn't a problem with new-style
1549 # virtuals, which are preferenced in dep_zapdeps by looking only at
1550 # the depstring, vdb, and available packages.
1552 p_type, p_root, p_key, p_status = myparent
1553 if p_status == "merge":
1554 # Update old-style virtuals if this package provides any.
1555 # These are needed for dep_virtual calls inside dep_check.
1556 self.pkgsettings[p_root].setinst(p_key,
1557 self.trees[p_root][self.pkg_tree_map[p_type]].dbapi)
1559 if "--debug" in self.myopts:
1560 print "Candidates:",mymerge
1564 selected_pkg = ["blocks", myroot, x[1:], None]
1566 #We are not processing a blocker but a normal dependency
1568 """In some cases, dep_check will return deps that shouldn't
1569 be proccessed any further, so they are identified and
1571 if "empty" not in self.myparams and \
1572 "deep" not in self.myparams and \
1573 not ("--update" in self.myopts and parent_arg) and \
1577 # List of acceptable packages, ordered by type preference.
1578 matched_packages = []
1579 myeb_matches = portdb.xmatch("match-visible", x)
1581 if "--usepkgonly" not in self.myopts:
1582 myeb = portage.best(myeb_matches)
1585 if "--usepkg" in self.myopts:
1586 # The next line assumes the binarytree has been populated.
1587 # XXX: Need to work out how we use the binary tree with roots.
1588 myeb_pkg_matches = bindb.match(x)
1589 if "--usepkgonly" not in self.myopts:
1590 # Remove any binary package entries that are masked in the portage tree (#55871)
1591 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1592 if pkg in myeb_matches or \
1593 not portdb.cpv_exists(pkg)]
1594 if myeb_pkg_matches:
1595 myeb_pkg = portage.best(myeb_pkg_matches)
1597 if myeb_pkg and "--newuse" in self.myopts:
1598 iuses = set(filter_iuse_defaults(
1599 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1600 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1602 if "--usepkgonly" not in self.myopts and myeb:
1605 pkgsettings.setcpv(myeb, mydb=mydb)
1607 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1608 now_use = pkgsettings["USE"].split()
1609 forced_flags = set()
1610 forced_flags.update(pkgsettings.useforce)
1611 forced_flags.update(pkgsettings.usemask)
1613 if "--usepkgonly" not in self.myopts and myeb:
1614 cur_iuse = set(filter_iuse_defaults(
1615 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1616 if iuses.symmetric_difference(
1617 cur_iuse).difference(forced_flags):
1619 elif iuses.intersection(old_use) != \
1620 cur_iuse.intersection(now_use):
1624 self.trees[myroot]["bintree"].dbapi.aux_get(
1625 myeb_pkg, ["USE"])[0].split()
1626 matched_packages.append(
1627 ["binary", myroot, myeb_pkg, binpkguseflags])
1629 if "--usepkgonly" not in self.myopts and myeb_matches:
1630 matched_packages.append(
1631 ["ebuild", myroot, myeb, None])
1633 if not matched_packages and \
1634 not (arg and "selective" not in self.myparams):
1635 """Fall back to the installed package database. This is a
1636 last resort because the metadata tends to diverge from that
1637 of the ebuild in the tree."""
1638 myeb_inst_matches = vardb.match(x)
1639 if "--usepkgonly" not in self.myopts:
1640 """ TODO: Improve masking check for installed and
1641 binary packages. bug #149816"""
1642 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1643 if not portdb.cpv_exists(pkg)]
1645 if myeb_inst_matches:
1646 myeb_inst = portage.best(myeb_inst_matches)
1648 binpkguseflags = vardb.aux_get(
1649 myeb_inst, ["USE"])[0].split()
1650 matched_packages.append(
1651 ["installed", myroot, myeb_inst, binpkguseflags])
1653 if not matched_packages:
1654 if raise_on_missing:
1661 xfrom = '(dependency required by '+ \
1662 green('"%s"' % myparent[2]) + \
1663 red(' [%s]' % myparent[0]) + ')'
1664 alleb = portdb.xmatch("match-all", x)
1666 if "--usepkgonly" not in self.myopts:
1667 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1668 print "!!! One of the following masked packages is required to complete your request:"
1671 mreasons = portage.getmaskingstatus(p,
1672 settings=pkgsettings, portdb=portdb)
1673 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1674 comment = portage.getmaskingreason(p,
1675 settings=pkgsettings, portdb=portdb)
1676 if comment and comment != oldcomment:
1678 oldcomment = comment
1680 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1681 print "refer to the Gentoo Handbook."
1683 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1684 print "!!! Either add a suitable binary package or compile from an ebuild."
1686 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1692 if "--debug" in self.myopts:
1693 for pkg in matched_packages:
1694 print (pkg[0] + ":").rjust(10), pkg[2]
1696 if len(matched_packages) > 1:
1697 bestmatch = portage.best(
1698 [pkg[2] for pkg in matched_packages])
1699 matched_packages = [pkg for pkg in matched_packages \
1700 if pkg[2] == bestmatch]
1702 # ordered by type preference ("ebuild" type is the last resort)
1703 selected_pkg = matched_packages[0]
1704 pkgtype, myroot, mycpv, myuse = selected_pkg
1705 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1706 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1707 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1708 existing_node = self._slot_node_map[myroot].get(
1711 e_type, myroot, e_cpv, e_status = existing_node
1712 if portage.match_from_list(x, [e_cpv]):
1713 # The existing node can be reused.
1714 selected_pkg = [e_type, myroot, e_cpv,
1715 self.useFlags[myroot][e_cpv]]
1718 #we are a dependency, so we want to be unconditionally added
1719 mypriority = priority.copy()
1721 mypriority.satisfied = True
1722 if not self.create(selected_pkg[0:3], myparent,
1723 myuse=selected_pkg[-1], priority=mypriority,
1724 rev_dep=rev_deps, arg=arg):
1727 #if mysource is not set, then we are a command-line dependency and should not be added
1728 #if --onlydeps is specified.
1729 if not self.create(selected_pkg[0:3], myparent,
1730 addme=("--onlydeps" not in self.myopts),
1731 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1734 if "--debug" in self.myopts:
1735 print "Exiting...",myparent
1738 def validate_blockers(self):
1739 """Remove any blockers from the digraph that do not match any of the
1740 packages within the graph. If necessary, create hard deps to ensure
1741 correct merge order such that mutually blocking packages are never
1742 installed simultaneously."""
1744 if "--buildpkgonly" in self.myopts or \
1745 "--nodeps" in self.myopts:
1749 for myroot in self.trees:
1751 modified_slots[myroot] = myslots
1752 final_db = self.mydbapi[myroot]
1753 slot_node_map = self._slot_node_map[myroot]
1754 for slot_atom, mynode in slot_node_map.iteritems():
1755 mytype, myroot, mycpv, mystatus = mynode
1756 if mystatus == "merge":
1757 myslots[slot_atom] = mycpv
1759 #if "deep" in self.myparams:
1761 # Pull in blockers from all installed packages that haven't already
1762 # been pulled into the depgraph. This is not enabled by default
1763 # due to the performance penalty that is incurred by all the
1764 # additional dep_check calls that are required.
1766 # Optimization hack for dep_check calls that minimizes the
1767 # available matches by replacing the portdb with a fakedbapi
1769 class FakePortageTree(object):
1770 def __init__(self, mydb):
1772 dep_check_trees = {}
1773 for myroot in self.trees:
1774 dep_check_trees[myroot] = self.trees[myroot].copy()
1775 dep_check_trees[myroot]["porttree"] = \
1776 FakePortageTree(self.mydbapi[myroot])
1778 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1779 for myroot in self.trees:
1780 pkg_node_map = self.pkg_node_map[myroot]
1781 vardb = self.trees[myroot]["vartree"].dbapi
1782 portdb = self.trees[myroot]["porttree"].dbapi
1783 pkgsettings = self.pkgsettings[myroot]
1784 final_db = self.mydbapi[myroot]
1785 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
1786 blocker_cache = BlockerCache(myroot, vardb)
1787 for pkg in cpv_all_installed:
1788 blocker_atoms = None
1789 matching_node = pkg_node_map.get(pkg, None)
1790 if matching_node and \
1791 matching_node[3] == "nomerge":
1793 # If this node has any blockers, create a "nomerge"
1794 # node for it so that they can be enforced.
1795 self.spinner.update()
1796 blocker_data = blocker_cache.get(pkg)
1798 blocker_atoms = blocker_data.atoms
1800 dep_vals = vardb.aux_get(pkg, dep_keys)
1801 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
1802 depstr = " ".join(dep_vals)
1803 # It is crucial to pass in final_db here in order to
1804 # optimize dep_check calls by eliminating atoms via
1805 # dep_wordreduce and dep_eval calls.
1807 portage.dep._dep_check_strict = False
1809 success, atoms = portage.dep_check(depstr,
1810 final_db, pkgsettings, myuse=myuse,
1811 trees=dep_check_trees, myroot=myroot)
1812 except Exception, e:
1813 if isinstance(e, SystemExit):
1815 # This is helpful, for example, if a ValueError
1816 # is thrown from cpv_expand due to multiple
1817 # matches (this can happen if an atom lacks a
1819 show_invalid_depstring_notice(
1820 ("installed", myroot, pkg, "nomerge"),
1825 portage.dep._dep_check_strict = True
1827 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
1828 vardb.aux_get(pkg, ["SLOT"])[0])
1829 if slot_atom in modified_slots[myroot]:
1830 # This package is being replaced anyway, so
1831 # ignore invalid dependencies so as not to
1832 # annoy the user too much (otherwise they'd be
1833 # forced to manually unmerge it first).
1835 show_invalid_depstring_notice(
1836 ("installed", myroot, pkg, "nomerge"),
1839 blocker_atoms = [myatom for myatom in atoms \
1840 if myatom.startswith("!")]
1841 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
1842 blocker_cache[pkg] = \
1843 blocker_cache.BlockerData(counter, blocker_atoms)
1845 # Don't store this parent in pkg_node_map, because it's
1846 # not needed there and it might overwrite a "merge"
1847 # node with the same cpv.
1848 myparent = ("installed", myroot, pkg, "nomerge")
1849 for myatom in blocker_atoms:
1850 blocker = ("blocks", myroot, myatom[1:])
1852 self.blocker_parents.get(blocker, None)
1855 self.blocker_parents[blocker] = myparents
1856 myparents.add(myparent)
1857 blocker_cache.flush()
1860 for blocker in self.blocker_parents.keys():
1861 mytype, myroot, mydep = blocker
1862 initial_db = self.trees[myroot]["vartree"].dbapi
1863 final_db = self.mydbapi[myroot]
1864 blocked_initial = initial_db.match(mydep)
1865 blocked_final = final_db.match(mydep)
1866 if not blocked_initial and not blocked_final:
1867 del self.blocker_parents[blocker]
1869 blocked_slots_initial = {}
1870 blocked_slots_final = {}
1871 for cpv in blocked_initial:
1872 blocked_slots_initial[cpv] = \
1873 "%s:%s" % (portage.dep_getkey(cpv),
1874 initial_db.aux_get(cpv, ["SLOT"])[0])
1875 for cpv in blocked_final:
1876 blocked_slots_final[cpv] = \
1877 "%s:%s" % (portage.dep_getkey(cpv),
1878 final_db.aux_get(cpv, ["SLOT"])[0])
1879 blocked_slots_final_values = set(blocked_slots_final.itervalues())
1880 for parent in list(self.blocker_parents[blocker]):
1881 ptype, proot, pcpv, pstatus = parent
1882 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1883 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1884 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1885 parent_static = pslot_atom not in modified_slots[proot]
1886 unresolved_blocks = False
1887 depends_on_order = set()
1888 for cpv in blocked_initial:
1889 slot_atom = blocked_slots_initial[cpv]
1890 if slot_atom == pslot_atom:
1891 # The parent blocks an initial package in the same
1892 # slot as itself. The merge/nomerge status of neither
1893 # node matters. In any case, this particular block is
1894 # automatically resolved.
1896 if parent_static and \
1897 slot_atom not in modified_slots[myroot]:
1898 # This blocker will be handled the next time that a
1899 # merge of either package is triggered.
1901 if pstatus == "merge" and \
1902 slot_atom not in blocked_slots_final_values:
1903 upgrade_matches = final_db.match(slot_atom)
1905 # Apparently an upgrade may be able to invalidate
1908 self.pkg_node_map[proot][upgrade_matches[0]]
1909 depends_on_order.add(upgrade_node)
1911 # None of the above blocker resolutions techniques apply,
1912 # so apparently this one is unresolvable.
1913 unresolved_blocks = True
1914 for cpv in blocked_final:
1915 slot_atom = blocked_slots_final[cpv]
1916 if slot_atom == pslot_atom:
1917 # The parent blocks itself, so the merge order does not
1918 # need to be enforced.
1920 if parent_static and \
1921 slot_atom not in modified_slots[myroot]:
1922 # This blocker will be handled the next time that a
1923 # merge of either package is triggered.
1925 # None of the above blocker resolutions techniques apply,
1926 # so apparently this one is unresolvable.
1927 unresolved_blocks = True
1928 if not unresolved_blocks and depends_on_order:
1929 for node in depends_on_order:
1930 # Enforce correct merge order with a hard dep.
1931 self.digraph.addnode(node, parent,
1932 priority=DepPriority(buildtime=True))
1933 # Count references to this blocker so that it can be
1934 # invalidated after nodes referencing it have been
1936 self.blocker_digraph.addnode(node, blocker)
1937 if not unresolved_blocks and not depends_on_order:
1938 self.blocker_parents[blocker].remove(parent)
1939 if not self.blocker_parents[blocker]:
1940 del self.blocker_parents[blocker]
1941 # Validate blockers that depend on merge order.
1942 if not self.blocker_digraph.empty():
1944 if self._slot_collision_info:
1945 # The user is only notified of a slot collision if there are no
1946 # unresolvable blocks.
1947 for x in self.altlist():
1948 if x[0] == "blocks":
1950 self._show_slot_collision_notice(self._slot_collision_info[0])
1951 if not self._accept_collisions():
1955 def _accept_collisions(self):
1957 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
1958 if x in self.myopts:
1963 def altlist(self, reversed=False):
1964 if reversed in self._altlist_cache:
1965 return self._altlist_cache[reversed][:]
1966 mygraph=self.digraph.copy()
1967 myblockers = self.blocker_digraph.copy()
1969 circular_blocks = False
1973 get_nodes = mygraph.root_nodes
1975 get_nodes = mygraph.leaf_nodes
1976 for cpv, node in self.pkg_node_map["/"].iteritems():
1977 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
1978 asap_nodes.append(node)
1980 ignore_priority_range = [None]
1981 ignore_priority_range.extend(
1982 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
1983 while not mygraph.empty():
1984 ignore_priority = None
1987 """ASAP nodes are merged before their soft deps."""
1988 for node in asap_nodes:
1989 if not mygraph.contains(node):
1990 asap_nodes.remove(node)
1992 if not mygraph.child_nodes(node,
1993 ignore_priority=DepPriority.SOFT):
1995 asap_nodes.remove(node)
1998 for ignore_priority in ignore_priority_range:
1999 nodes = get_nodes(ignore_priority=ignore_priority)
2002 selected_nodes = None
2004 if ignore_priority <= DepPriority.SOFT:
2005 if ignore_priority is None and not reversed:
2006 # Greedily pop all of these nodes since no relationship
2007 # has been ignored. This optimization destroys --tree
2008 # output, so it's disabled in reversed mode.
2009 selected_nodes = nodes
2011 # Only pop one node for optimal merge order.
2012 selected_nodes = [nodes[0]]
2014 """Recursively gather a group of nodes that RDEPEND on
2015 eachother. This ensures that they are merged as a group
2016 and get their RDEPENDs satisfied as soon as possible."""
2017 def gather_deps(mergeable_nodes, selected_nodes, node):
2018 if node in selected_nodes:
2020 if node not in mergeable_nodes:
2022 selected_nodes.add(node)
2023 for child in mygraph.child_nodes(node,
2024 ignore_priority=DepPriority.SOFT):
2026 mergeable_nodes, selected_nodes, child):
2029 mergeable_nodes = set(nodes)
2031 selected_nodes = set()
2033 mergeable_nodes, selected_nodes, node):
2036 selected_nodes = None
2038 if not selected_nodes:
2039 if not myblockers.is_empty():
2040 """A blocker couldn't be circumnavigated while keeping all
2041 dependencies satisfied. The user will have to resolve this
2042 manually. This is a panic condition and thus the order
2043 doesn't really matter, so just pop a random node in order
2044 to avoid a circular dependency panic if possible."""
2045 if not circular_blocks:
2046 circular_blocks = True
2047 blocker_deps = myblockers.leaf_nodes()
2049 selected_nodes = [blocker_deps.pop()]
2051 if not selected_nodes:
2053 """The circular deps ouput should have less noise when
2054 altlist is not in reversed mode."""
2056 print "!!! Error: circular dependencies:"
2058 mygraph.debug_print()
2061 for node in selected_nodes:
2062 retlist.append(list(node))
2063 mygraph.remove(node)
2064 if not reversed and not circular_blocks and myblockers.contains(node):
2065 """This node may have invalidated one or more blockers."""
2066 myblockers.remove(node)
2067 for blocker in myblockers.root_nodes():
2068 if not myblockers.child_nodes(blocker):
2069 myblockers.remove(blocker)
2070 del self.blocker_parents[blocker]
2073 """Blocker validation does not work with reverse mode,
2074 so self.altlist() should first be called with reverse disabled
2075 so that blockers are properly validated."""
2076 self.blocker_digraph = myblockers
2078 """ Add any unresolved blocks so that they can be displayed."""
2079 for blocker in self.blocker_parents:
2080 retlist.append(list(blocker))
2081 self._altlist_cache[reversed] = retlist[:]
2084 def xcreate(self,mode="system"):
2085 vardb = self.trees[self.target_root]["vartree"].dbapi
2086 portdb = self.trees[self.target_root]["porttree"].dbapi
2087 bindb = self.trees[self.target_root]["bintree"].dbapi
2088 def visible(mylist):
2089 matches = portdb.gvisible(portdb.visible(mylist))
2090 return [x for x in mylist \
2091 if x in matches or not portdb.cpv_exists(x)]
2092 world_problems = False
2094 mylist = getlist(self.settings, "system")
2097 worldlist = getlist(self.settings, "world")
2098 sysdict = genericdict(getlist(self.settings, "system"))
2099 worlddict=genericdict(worldlist)
2101 for x in worlddict.keys():
2102 if not portage.isvalidatom(x):
2103 world_problems = True
2104 elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
2105 world_problems = True
2107 sysdict[x]=worlddict[x]
2109 mylist = sysdict.keys()
2113 mykey = portage.dep_getkey(atom)
2115 newlist.append(atom)
2116 """Make sure all installed slots are updated when possible.
2117 Do this with --emptytree also, to ensure that all slots are
2120 for cpv in vardb.match(mykey):
2121 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2124 if "--usepkg" in self.myopts:
2125 mymatches = bindb.match(atom)
2126 if "--usepkgonly" not in self.myopts:
2127 mymatches = visible(mymatches)
2128 best_pkg = portage.best(mymatches)
2130 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2131 best_pkgs.append(("binary", best_pkg, best_slot))
2132 if "--usepkgonly" not in self.myopts:
2133 best_pkg = portage.best(portdb.match(atom))
2135 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2136 best_pkgs.append(("ebuild", best_pkg, best_slot))
2138 best_pkg = portage.best([x[1] for x in best_pkgs])
2139 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2140 best_slot = best_pkgs[0][2]
2141 myslots.add(best_slot)
2142 if len(myslots) > 1:
2143 for myslot in myslots:
2144 myslot_atom = "%s:%s" % (mykey, myslot)
2146 if "--usepkgonly" not in self.myopts and \
2147 self.trees[self.target_root][
2148 "porttree"].dbapi.match(myslot_atom):
2150 elif "--usepkg" in self.myopts:
2151 mymatches = bindb.match(myslot_atom)
2152 if "--usepkgonly" not in self.myopts:
2153 mymatches = visible(mymatches)
2157 newlist.append(myslot_atom)
2161 for mydep in mylist:
2163 if not self.select_dep(
2164 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2165 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2168 missing_atoms.append(mydep)
2170 if not self.validate_blockers():
2174 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2175 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2178 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2179 " Ebuilds for the following packages are either all"
2180 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2181 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2185 def display(self,mylist,verbosity=None):
2186 if verbosity is None:
2187 verbosity = ("--quiet" in self.myopts and 1 or \
2188 "--verbose" in self.myopts and 3 or 2)
2192 counters = PackageCounters()
2194 if verbosity == 1 and "--verbose" not in self.myopts:
2195 def create_use_string(*args):
2198 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2200 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2201 alphabetical=("--alphabetical" in self.myopts)):
2209 cur_iuse = set(cur_iuse)
2210 enabled_flags = cur_iuse.intersection(cur_use)
2211 removed_iuse = set(old_iuse).difference(cur_iuse)
2212 any_iuse = cur_iuse.union(old_iuse)
2213 any_iuse = list(any_iuse)
2215 for flag in any_iuse:
2218 if flag in enabled_flags:
2220 if is_new or flag in old_use and all_flags:
2221 flag_str = red(flag)
2222 elif flag not in old_iuse:
2223 flag_str = yellow(flag) + "%*"
2224 elif flag not in old_use:
2225 flag_str = green(flag) + "*"
2226 elif flag in removed_iuse:
2228 flag_str = yellow("-" + flag) + "%"
2231 flag_str = "(" + flag_str + ")"
2232 removed.append(flag_str)
2235 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2236 flag_str = blue("-" + flag)
2237 elif flag not in old_iuse:
2238 flag_str = yellow("-" + flag)
2239 if flag not in iuse_forced:
2241 elif flag in old_use:
2242 flag_str = green("-" + flag) + "*"
2244 if flag in iuse_forced:
2245 flag_str = "(" + flag_str + ")"
2247 enabled.append(flag_str)
2249 disabled.append(flag_str)
2252 ret = " ".join(enabled)
2254 ret = " ".join(enabled + disabled + removed)
2256 ret = '%s="%s" ' % (name, ret)
2260 # FIXME: account for the possibility of different overlays in
2261 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2262 overlays = self.settings["PORTDIR_OVERLAY"].split()
2263 overlays_real = [os.path.realpath(t) \
2264 for t in self.settings["PORTDIR_OVERLAY"].split()]
2271 if "blocks" == x[0]:
2273 graph_key = tuple(x)
2274 if "--tree" in self.myopts:
2275 depth = len(tree_nodes)
2276 while depth and graph_key not in \
2277 self.digraph.child_nodes(tree_nodes[depth-1]):
2279 tree_nodes = tree_nodes[:depth]
2280 tree_nodes.append(graph_key)
2281 node_depth[graph_key] = depth
2283 last_merge_depth = 0
2284 for i in xrange(len(mylist)-1,-1,-1):
2285 if "blocks" == mylist[i][0]:
2287 graph_key = tuple(mylist[i])
2288 if mylist[i][-1] != "nomerge":
2289 last_merge_depth = node_depth[graph_key]
2291 if node_depth[graph_key] >= last_merge_depth or \
2292 i < len(mylist) - 1 and \
2293 node_depth[graph_key] >= node_depth[tuple(mylist[i+1])]:
2295 del node_depth[graph_key]
2298 display_overlays=False
2299 # files to fetch list - avoids counting a same file twice
2300 # in size display (verbose mode)
2306 portdb = self.trees[myroot]["porttree"].dbapi
2307 bindb = self.trees[myroot]["bintree"].dbapi
2308 vardb = self.trees[myroot]["vartree"].dbapi
2309 vartree = self.trees[myroot]["vartree"]
2310 pkgsettings = self.pkgsettings[myroot]
2315 addl=""+red("B")+" "+fetch+" "
2316 counters.blocks += 1
2317 resolved = portage.key_expand(
2318 pkg_key, mydb=vardb, settings=pkgsettings)
2319 if "--columns" in self.myopts and "--quiet" in self.myopts:
2320 print addl,red(resolved),
2322 print "["+x[0]+" "+addl+"]",red(resolved),
2323 block_parents = self.blocker_parents[tuple(x)]
2324 block_parents = set([pnode[2] for pnode in block_parents])
2325 block_parents = ", ".join(block_parents)
2327 print bad("(\"%s\" is blocking %s)") % \
2328 (pkg_key, block_parents)
2330 print bad("(is blocking %s)") % block_parents
2332 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2333 binary_package = True
2334 if "ebuild" == pkg_type:
2335 if "merge" == x[3] or \
2336 not vartree.dbapi.cpv_exists(pkg_key):
2337 """An ebuild "merge" node or a --onlydeps "nomerge"
2339 binary_package = False
2340 pkgsettings.setcpv(pkg_key, mydb=portdb)
2341 if pkg_key not in self.useFlags[myroot]:
2342 self.useFlags[myroot][pkg_key] = \
2343 pkgsettings["USE"].split()
2345 # An ebuild "nomerge" node, so USE come from the vardb.
2346 mydbapi = vartree.dbapi
2347 if pkg_key not in self.useFlags[myroot]:
2348 """If this is a --resume then the USE flags need to be
2349 fetched from the appropriate locations here."""
2350 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2351 pkg_key, ["USE"])[0].split()
2353 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2354 "fetch" in portdb.aux_get(
2355 x[2], ["RESTRICT"])[0].split():
2357 counters.restrict_fetch += 1
2358 if portdb.fetch_check(
2359 pkg_key, self.useFlags[myroot][pkg_key]):
2361 counters.restrict_fetch_satisfied += 1
2363 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2364 #param is used for -u, where you still *do* want to see when something is being upgraded.
2366 if vardb.cpv_exists(pkg_key):
2367 addl=" "+yellow("R")+fetch+" "
2368 if x[3] != "nomerge":
2369 counters.reinst += 1
2370 elif vardb.match(portage.dep_getkey(pkg_key)):
2371 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2372 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2373 portage.pkgsplit(x[2])[0])
2374 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2375 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2377 myoldbest=portage.best(myinslotlist)
2379 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2381 addl+=turquoise("U")+blue("D")
2382 counters.downgrades += 1
2385 addl+=turquoise("U")+" "
2386 counters.upgrades += 1
2388 # New slot, mark it new.
2389 addl=" "+green("NS")+fetch+" "
2390 counters.newslot += 1
2392 if "--changelog" in self.myopts:
2393 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2394 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2395 inst_matches = vardb.match(slot_atom)
2397 changelogs.extend(self.calc_changelog(
2398 portdb.findname(pkg_key),
2399 inst_matches[0], pkg_key))
2401 addl=" "+green("N")+" "+fetch+" "
2406 if pkg_key in self.useFlags[myroot]:
2408 cur_iuse = list(filter_iuse_defaults(
2409 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2411 forced_flags = set()
2412 if not binary_package:
2413 forced_flags.update(pkgsettings.useforce)
2414 forced_flags.update(pkgsettings.usemask)
2416 cur_iuse = portage.unique_array(cur_iuse)
2418 cur_use = self.useFlags[myroot][pkg_key]
2419 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2425 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2426 old_iuse, old_use = \
2427 self.trees[x[1]]["vartree"].dbapi.aux_get(
2428 pkg, ["IUSE", "USE"])
2429 old_iuse = list(set(
2430 filter_iuse_defaults(old_iuse.split())))
2432 old_use = old_use.split()
2439 old_use = [flag for flag in old_use if flag in old_iuse]
2441 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2443 use_expand.reverse()
2444 use_expand_hidden = \
2445 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2447 def map_to_use_expand(myvals, forcedFlags=False):
2450 for exp in use_expand:
2453 for val in myvals[:]:
2454 if val.startswith(exp.lower()+"_"):
2455 if val in forced_flags:
2456 forced[exp].add(val[len(exp)+1:])
2457 ret[exp].append(val[len(exp)+1:])
2460 forced["USE"] = [val for val in myvals \
2461 if val in forced_flags]
2462 for exp in use_expand_hidden:
2469 cur_iuse_map, iuse_forced = \
2470 map_to_use_expand(cur_iuse, forcedFlags=True)
2471 cur_use_map = map_to_use_expand(cur_use)
2472 old_iuse_map = map_to_use_expand(old_iuse)
2473 old_use_map = map_to_use_expand(old_use)
2476 use_expand.insert(0, "USE")
2478 for key in use_expand:
2479 if key in use_expand_hidden:
2481 verboseadd += create_use_string(key.upper(),
2482 cur_iuse_map[key], iuse_forced[key],
2483 cur_use_map[key], old_iuse_map[key],
2484 old_use_map[key], is_new)
2489 if x[0] == "ebuild" and x[-1]!="nomerge":
2491 myfilesdict = portdb.getfetchsizes(pkg_key,
2492 useflags=self.useFlags[myroot][pkg_key],
2494 except portage.exception.InvalidDependString, e:
2495 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2496 show_invalid_depstring_notice(x, src_uri, str(e))
2499 if myfilesdict is None:
2500 myfilesdict="[empty/missing/bad digest]"
2502 for myfetchfile in myfilesdict.keys():
2503 if myfetchfile not in myfetchlist:
2504 mysize+=myfilesdict[myfetchfile]
2505 myfetchlist.append(myfetchfile)
2506 counters.totalsize += mysize
2507 verboseadd+=format_size(mysize)+" "
2510 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2511 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2512 file_name = portdb.findname(pkg_key)
2513 if file_name: # It might not exist in the tree
2514 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2515 if (overlays_real.count(dir_name)>0):
2516 verboseadd+=teal("["+str(overlays_real.index(
2517 os.path.normpath(dir_name))+1)+"]")+" "
2518 display_overlays=True
2520 verboseadd += "[No ebuild?]"
2522 xs=portage.pkgsplit(x[2])
2529 if "COLUMNWIDTH" in self.settings:
2531 mywidth = int(self.settings["COLUMNWIDTH"])
2532 except ValueError, e:
2533 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2535 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2536 self.settings["COLUMNWIDTH"], noiselevel=-1)
2541 indent = " " * node_depth[tuple(x)]
2544 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2545 if myoldbest[-3:]=="-r0":
2546 myoldbest=myoldbest[:-3]
2547 myoldbest=blue("["+myoldbest+"]")
2552 if "--columns" in self.myopts:
2553 if "--quiet" in self.myopts:
2554 myprint=addl+" "+indent+darkgreen(xs[0])
2555 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2556 myprint=myprint+myoldbest
2557 myprint=myprint+darkgreen("to "+x[1])
2559 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2560 if (newlp-nc_len(myprint)) > 0:
2561 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2562 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2563 if (oldlp-nc_len(myprint)) > 0:
2564 myprint=myprint+" "*(oldlp-nc_len(myprint))
2565 myprint=myprint+myoldbest
2566 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2568 if x[3] == "nomerge":
2569 myprint = darkblue("[nomerge ] ")
2571 myprint = "[" + pkg_type + " " + addl + "] "
2572 myprint += indent + darkgreen(pkg_key) + " " + \
2573 myoldbest + darkgreen("to " + myroot) + " " + \
2576 if "--columns" in self.myopts:
2577 if "--quiet" in self.myopts:
2578 myprint=addl+" "+indent+darkgreen(xs[0])
2579 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2580 myprint=myprint+myoldbest
2582 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2583 if (newlp-nc_len(myprint)) > 0:
2584 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2585 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2586 if (oldlp-nc_len(myprint)) > 0:
2587 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2588 myprint=myprint+myoldbest+" "+verboseadd
2591 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2593 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2596 mysplit = portage.pkgsplit(x[2])
2597 if "--tree" not in self.myopts and mysplit and \
2598 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2601 if mysplit[2] == "r0":
2602 myversion = mysplit[1]
2604 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2606 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2607 if mylist.index(x) < len(mylist) - 1 and \
2608 "livecvsportage" not in self.settings.features:
2609 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2610 p.append(colorize("WARN", " then resume the merge."))
2620 if overlays and display_overlays:
2621 print "Portage overlays:"
2625 print " "+teal("["+str(y)+"]"),x
2627 if "--changelog" in self.myopts:
2629 for revision,text in changelogs:
2630 print bold('*'+revision)
2631 sys.stdout.write(text)
2633 if self._pprovided_args:
2635 msg.append(bad("\nWARNING: "))
2636 if len(self._pprovided_args) > 1:
2637 msg.append("Requested packages will not be " + \
2638 "merged because they are listed in\n")
2640 msg.append("A requested package will not be " + \
2641 "merged because it is listed in\n")
2642 msg.append(" package.provided:\n\n")
2643 for arg in self._pprovided_args:
2644 msg.append(" " + arg + "\n")
2646 sys.stderr.write("".join(msg))
2648 def calc_changelog(self,ebuildpath,current,next):
2649 current = '-'.join(portage.catpkgsplit(current)[1:])
2650 if current.endswith('-r0'): current = current[:-3]
2651 next = '-'.join(portage.catpkgsplit(next)[1:])
2652 if next.endswith('-r0'): next = next[:-3]
2653 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2655 changelog = open(changelogpath).read()
2656 except SystemExit, e:
2657 raise # Needed else can't exit
2660 divisions = self.find_changelog_tags(changelog)
2661 #print 'XX from',current,'to',next
2662 #for div,text in divisions: print 'XX',div
2663 # skip entries for all revisions above the one we are about to emerge
2664 for i in range(len(divisions)):
2665 if divisions[i][0]==next:
2666 divisions = divisions[i:]
2668 # find out how many entries we are going to display
2669 for i in range(len(divisions)):
2670 if divisions[i][0]==current:
2671 divisions = divisions[:i]
2674 # couldnt find the current revision in the list. display nothing
2678 def find_changelog_tags(self,changelog):
2682 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2684 if release is not None:
2685 divs.append((release,changelog))
2687 if release is not None:
2688 divs.append((release,changelog[:match.start()]))
2689 changelog = changelog[match.end():]
2690 release = match.group(1)
2691 if release.endswith('.ebuild'):
2692 release = release[:-7]
2693 if release.endswith('-r0'):
2694 release = release[:-3]
2697 return self.outdatedpackages
2699 class PackageCounters(object):
2709 self.restrict_fetch = 0
2710 self.restrict_fetch_satisfied = 0
2713 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2716 myoutput.append("Total: %s package" % total_installs)
2717 if total_installs != 1:
2718 myoutput.append("s")
2719 if total_installs != 0:
2720 myoutput.append(" (")
2721 if self.upgrades > 0:
2722 details.append("%s upgrade" % self.upgrades)
2723 if self.upgrades > 1:
2725 if self.downgrades > 0:
2726 details.append("%s downgrade" % self.downgrades)
2727 if self.downgrades > 1:
2730 details.append("%s new" % self.new)
2731 if self.newslot > 0:
2732 details.append("%s in new slot" % self.newslot)
2733 if self.newslot > 1:
2736 details.append("%s reinstall" % self.reinst)
2740 details.append("%s block" % self.blocks)
2743 myoutput.append(", ".join(details))
2744 if total_installs != 0:
2745 myoutput.append(")")
2746 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2747 if self.restrict_fetch:
2748 myoutput.append("\nFetch Restriction: %s package" % \
2749 self.restrict_fetch)
2750 if self.restrict_fetch > 1:
2751 myoutput.append("s")
2752 if self.restrict_fetch_satisfied < self.restrict_fetch:
2753 myoutput.append(bad(" (%s unsatisfied)") % \
2754 (self.restrict_fetch - self.restrict_fetch_satisfied))
2755 return "".join(myoutput)
2757 class MergeTask(object):
2759 def __init__(self, settings, trees, myopts):
2760 self.settings = settings
2761 self.target_root = settings["ROOT"]
2763 self.myopts = myopts
2765 if settings.get("PORTAGE_DEBUG", "") == "1":
2767 self.pkgsettings = {}
2768 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2769 if self.target_root != "/":
2770 self.pkgsettings["/"] = \
2771 portage.config(clone=trees["/"]["vartree"].settings)
2773 def merge(self, mylist, favorites, mtimedb):
2776 ldpath_mtimes = mtimedb["ldpath"]
2777 xterm_titles = "notitles" not in self.settings.features
2779 #check for blocking dependencies
2780 if "--fetchonly" not in self.myopts and \
2781 "--buildpkgonly" not in self.myopts:
2784 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2785 print "!!! the two packages cannot be installed on the same system together."
2786 print "!!! Please use 'emerge --pretend' to determine blockers."
2787 if "--quiet" not in self.myopts:
2788 show_blocker_docs_link()
2789 if "--pretend" not in self.myopts:
2791 del mtimedb["resume"]
2796 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
2797 mysysdict = genericdict(getlist(self.settings, "system"))
2798 if "--resume" in self.myopts:
2800 print colorize("GOOD", "*** Resuming merge...")
2801 emergelog(xterm_titles, " *** Resuming merge...")
2802 mymergelist=mtimedb["resume"]["mergelist"][:]
2803 if "--skipfirst" in self.myopts and mymergelist:
2804 del mtimedb["resume"]["mergelist"][0]
2807 validate_merge_list(self.trees, mymergelist)
2809 myfavs = portage.grabfile(
2810 os.path.join(self.target_root, portage.WORLD_FILE))
2811 myfavdict=genericdict(myfavs)
2812 for x in range(len(mylist)):
2813 if mylist[x][3]!="nomerge":
2814 # Add to the mergelist
2815 mymergelist.append(mylist[x])
2817 myfavkey=portage.cpv_getkey(mylist[x][2])
2818 if "--onlydeps" in self.myopts:
2820 # Add to the world file. Since we won't be able to later.
2821 if "--fetchonly" not in self.myopts and \
2822 myfavkey in favorites:
2823 #don't record if already in system profile or already recorded
2824 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
2825 #we don't have a favorites entry for this package yet; add one
2826 myfavdict[myfavkey]=myfavkey
2827 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
2828 if not ("--fetchonly" in self.myopts or \
2829 "--fetch-all-uri" in self.myopts or \
2830 "--pretend" in self.myopts):
2831 portage.write_atomic(
2832 os.path.join(self.target_root, portage.WORLD_FILE),
2833 "\n".join(myfavdict.values()))
2835 mtimedb["resume"]["mergelist"]=mymergelist[:]
2838 myfeat = self.settings.features[:]
2839 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
2841 if "parallel-fetch" in myfeat and \
2842 not ("--pretend" in self.myopts or \
2843 "--fetch-all-uri" in self.myopts or \
2844 "--fetchonly" in self.myopts):
2845 if "distlocks" not in myfeat:
2847 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
2848 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
2850 elif len(mymergelist) > 1:
2851 print ">>> starting parallel fetching"
2852 fetch_log = "/var/log/emerge-fetch.log"
2853 logfile = open(fetch_log, "w")
2854 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
2855 portage.util.apply_secpass_permissions(fetch_log,
2856 uid=portage.portage_uid, gid=portage.portage_gid,
2858 fetch_env = os.environ.copy()
2859 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
2860 fetch_env["PORTAGE_NICENESS"] = "0"
2861 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
2862 for myopt, myarg in self.myopts.iteritems():
2863 if myopt not in bad_resume_opts:
2865 fetch_args.append(myopt)
2867 fetch_args.append(myopt +"="+ myarg)
2868 portage.process.spawn(fetch_args, env=fetch_env,
2869 fd_pipes=fd_pipes, returnpid=True)
2870 logfile.close() # belongs to the spawned process
2873 for x in mymergelist:
2878 portdb = self.trees[myroot]["porttree"].dbapi
2879 bindb = self.trees[myroot]["bintree"].dbapi
2880 vartree = self.trees[myroot]["vartree"]
2881 pkgsettings = self.pkgsettings[myroot]
2884 y = portdb.findname(pkg_key)
2885 if "--pretend" not in self.myopts:
2886 print "\n>>> Emerging (" + \
2887 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2888 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
2889 colorize("GOOD", x[pkgindex]) + " to " + x[1]
2890 emergelog(xterm_titles, " >>> emerge ("+\
2891 str(mergecount)+" of "+str(len(mymergelist))+\
2892 ") "+x[pkgindex]+" to "+x[1])
2894 pkgsettings["EMERGE_FROM"] = x[0]
2895 pkgsettings.backup_changes("EMERGE_FROM")
2898 #buildsyspkg: Check if we need to _force_ binary package creation
2899 issyspkg = ("buildsyspkg" in myfeat) \
2900 and x[0] != "blocks" \
2901 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
2902 and "--buildpkg" not in self.myopts
2903 if x[0] in ["ebuild","blocks"]:
2904 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
2905 raise Exception, "Merging a blocker"
2906 elif "--fetchonly" in self.myopts or \
2907 "--fetch-all-uri" in self.myopts:
2908 if "--fetch-all-uri" in self.myopts:
2909 retval = portage.doebuild(y, "fetch", myroot,
2910 pkgsettings, self.edebug,
2911 "--pretend" in self.myopts, fetchonly=1,
2912 fetchall=1, mydbapi=portdb, tree="porttree")
2914 retval = portage.doebuild(y, "fetch", myroot,
2915 pkgsettings, self.edebug,
2916 "--pretend" in self.myopts, fetchonly=1,
2917 mydbapi=portdb, tree="porttree")
2918 if (retval is None) or retval:
2920 print "!!! Fetch for",y,"failed, continuing..."
2922 failed_fetches.append(pkg_key)
2925 portage.doebuild_environment(y, "setup", myroot,
2926 pkgsettings, self.edebug, 1, portdb)
2927 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
2928 portage.util.ensure_dirs(os.path.dirname(catdir),
2929 uid=portage.portage_uid, gid=portage.portage_gid,
2931 builddir_lock = None
2934 catdir_lock = portage.locks.lockdir(catdir)
2935 portage.util.ensure_dirs(catdir,
2936 uid=portage.portage_uid, gid=portage.portage_gid,
2938 builddir_lock = portage.locks.lockdir(
2939 pkgsettings["PORTAGE_BUILDDIR"])
2941 portage.locks.unlockdir(catdir_lock)
2944 msg = " === (%s of %s) Cleaning (%s::%s)" % \
2945 (mergecount, len(mymergelist), pkg_key, y)
2946 short_msg = "emerge: (%s of %s) %s Clean" % \
2947 (mergecount, len(mymergelist), pkg_key)
2948 emergelog(xterm_titles, msg, short_msg=short_msg)
2949 retval = portage.doebuild(y, "clean", myroot,
2950 pkgsettings, self.edebug, cleanup=1,
2951 mydbapi=portdb, tree="porttree")
2952 if retval != os.EX_OK:
2954 if "--buildpkg" in self.myopts or issyspkg:
2956 print ">>> This is a system package, " + \
2957 "let's pack a rescue tarball."
2958 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
2959 (mergecount, len(mymergelist), pkg_key, y)
2960 short_msg = "emerge: (%s of %s) %s Compile" % \
2961 (mergecount, len(mymergelist), pkg_key)
2962 emergelog(xterm_titles, msg, short_msg=short_msg)
2963 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
2964 retval = portage.doebuild(y, "package", myroot,
2965 pkgsettings, self.edebug, mydbapi=portdb,
2967 if retval != os.EX_OK:
2969 if "--buildpkgonly" not in self.myopts:
2970 bintree = self.trees[myroot]["bintree"]
2971 bintree.inject(pkg_key)
2972 mytbz2 = bintree.getname(pkg_key)
2973 msg = " === (%s of %s) Merging (%s::%s)" % \
2974 (mergecount, len(mymergelist), pkg_key, y)
2975 short_msg = "emerge: (%s of %s) %s Merge" % \
2976 (mergecount, len(mymergelist), pkg_key)
2977 emergelog(xterm_titles, msg, short_msg=short_msg)
2978 retval = portage.merge(pkgsettings["CATEGORY"],
2979 pkgsettings["PF"], pkgsettings["D"],
2980 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
2981 "build-info"), myroot, pkgsettings,
2982 myebuild=pkgsettings["EBUILD"],
2983 mytree="porttree", mydbapi=portdb,
2984 vartree=vartree, prev_mtimes=ldpath_mtimes)
2985 if retval != os.EX_OK:
2987 elif "noclean" not in pkgsettings.features:
2988 portage.doebuild(y, "clean", myroot,
2989 pkgsettings, self.edebug, mydbapi=portdb,
2992 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
2993 (mergecount, len(mymergelist), pkg_key, y)
2994 short_msg = "emerge: (%s of %s) %s Compile" % \
2995 (mergecount, len(mymergelist), pkg_key)
2996 emergelog(xterm_titles, msg, short_msg=short_msg)
2997 retval = portage.doebuild(y, "merge", myroot,
2998 pkgsettings, self.edebug, vartree=vartree,
2999 mydbapi=portdb, tree="porttree",
3000 prev_mtimes=ldpath_mtimes)
3001 if retval != os.EX_OK:
3005 portage.locks.unlockdir(builddir_lock)
3008 # Lock catdir for removal if empty.
3009 catdir_lock = portage.locks.lockdir(catdir)
3015 if e.errno not in (errno.ENOENT,
3016 errno.ENOTEMPTY, errno.EEXIST):
3019 portage.locks.unlockdir(catdir_lock)
3021 elif x[0]=="binary":
3023 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3024 if "--getbinpkg" in self.myopts:
3027 if "distlocks" in pkgsettings.features and \
3028 os.access(pkgsettings["PKGDIR"], os.W_OK):
3029 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3030 tbz2_lock = portage.locks.lockfile(mytbz2,
3032 if self.trees[myroot]["bintree"].isremote(pkg_key):
3033 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3034 (mergecount, len(mymergelist), pkg_key, mytbz2)
3035 short_msg = "emerge: (%s of %s) %s Fetch" % \
3036 (mergecount, len(mymergelist), pkg_key)
3037 emergelog(xterm_titles, msg, short_msg=short_msg)
3038 if not self.trees[myroot]["bintree"].gettbz2(
3043 portage.locks.unlockfile(tbz2_lock)
3045 if "--fetchonly" in self.myopts or \
3046 "--fetch-all-uri" in self.myopts:
3049 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3050 emergelog(xterm_titles, " === ("+str(mergecount)+\
3051 " of "+str(len(mymergelist))+") Merging Binary ("+\
3052 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3053 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3055 vartree=self.trees[myroot]["vartree"],
3056 prev_mtimes=ldpath_mtimes)
3057 if retval != os.EX_OK:
3059 #need to check for errors
3060 if "--buildpkgonly" not in self.myopts:
3061 self.trees[x[1]]["vartree"].inject(x[2])
3062 myfavkey=portage.cpv_getkey(x[2])
3063 if "--fetchonly" not in self.myopts and \
3064 "--fetch-all-uri" not in self.myopts and \
3065 myfavkey in favorites:
3066 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3067 myfavdict=genericdict(myfavs)
3068 #don't record if already in system profile or already recorded
3069 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3070 #we don't have a favorites entry for this package yet; add one
3071 myfavdict[myfavkey]=myfavkey
3072 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3073 emergelog(xterm_titles, " === ("+\
3074 str(mergecount)+" of "+\
3075 str(len(mymergelist))+\
3076 ") Updating world file ("+x[pkgindex]+")")
3077 portage.write_atomic(
3078 os.path.join(myroot, portage.WORLD_FILE),
3079 "\n".join(myfavdict.values()))
3081 if "--pretend" not in self.myopts and \
3082 "--fetchonly" not in self.myopts and \
3083 "--fetch-all-uri" not in self.myopts:
3084 # Clean the old package that we have merged over top of it.
3085 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3086 xsplit=portage.pkgsplit(x[2])
3087 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3088 retval = unmerge(pkgsettings, self.myopts, vartree,
3089 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3091 emergelog(xterm_titles,
3092 " --- AUTOCLEAN: Nothing unmerged.")
3094 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3095 + " AUTOCLEAN is disabled. This can cause serious"
3096 + " problems due to overlapping packages.\n")
3098 # Figure out if we need a restart.
3099 mysplit=portage.pkgsplit(x[2])
3100 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3101 myver=mysplit[1]+"-"+mysplit[2]
3102 if myver[-3:]=='-r0':
3104 if (myver != portage.VERSION) and \
3105 "livecvsportage" not in self.settings.features:
3106 if len(mymergelist) > mergecount:
3107 emergelog(xterm_titles,
3108 " ::: completed emerge ("+ \
3109 str(mergecount)+" of "+ \
3110 str(len(mymergelist))+") "+ \
3112 emergelog(xterm_titles, " *** RESTARTING " + \
3113 "emerge via exec() after change of " + \
3115 del mtimedb["resume"]["mergelist"][0]
3117 portage.run_exitfuncs()
3118 mynewargv=[sys.argv[0],"--resume"]
3119 for myopt, myarg in self.myopts.iteritems():
3120 if myopt not in bad_resume_opts:
3122 mynewargv.append(myopt)
3124 mynewargv.append(myopt +"="+ myarg)
3125 # priority only needs to be adjusted on the first run
3126 os.environ["PORTAGE_NICENESS"] = "0"
3127 os.execv(mynewargv[0], mynewargv)
3129 if "--pretend" not in self.myopts and \
3130 "--fetchonly" not in self.myopts and \
3131 "--fetch-all-uri" not in self.myopts:
3132 if "noclean" not in self.settings.features:
3133 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3134 (mergecount, len(mymergelist), x[pkgindex])
3135 emergelog(xterm_titles, (" === (%s of %s) " + \
3136 "Post-Build Cleaning (%s::%s)") % \
3137 (mergecount, len(mymergelist), x[pkgindex], y),
3138 short_msg=short_msg)
3139 emergelog(xterm_titles, " ::: completed emerge ("+\
3140 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3143 # Unsafe for parallel merges
3144 del mtimedb["resume"]["mergelist"][0]
3145 # Commit after each merge so that --resume may still work in
3146 # in the event that portage is not allowed to exit normally
3147 # due to power failure, SIGKILL, etc...
3150 if "--pretend" not in self.myopts:
3151 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3153 # We're out of the loop... We're done. Delete the resume data.
3154 if mtimedb.has_key("resume"):
3155 del mtimedb["resume"]
3158 #by doing an exit this way, --fetchonly can continue to try to
3159 #fetch everything even if a particular download fails.
3160 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3162 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3163 "encountered. Please see above for details.\n\n")
3164 for cpv in failed_fetches:
3165 sys.stderr.write(" ")
3166 sys.stderr.write(cpv)
3167 sys.stderr.write("\n")
3168 sys.stderr.write("\n")
3174 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3175 ldpath_mtimes, autoclean=0):
3176 candidate_catpkgs=[]
3178 xterm_titles = "notitles" not in settings.features
3180 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3182 # At least the parent needs to exist for the lock file.
3183 portage.util.ensure_dirs(vdb_path)
3184 except portage.exception.PortageException:
3188 if os.access(vdb_path, os.W_OK):
3189 vdb_lock = portage.locks.lockdir(vdb_path)
3190 realsyslist = getlist(settings, "system")
3192 for x in realsyslist:
3193 mycp = portage.dep_getkey(x)
3194 if mycp in settings.getvirtuals():
3196 for provider in settings.getvirtuals()[mycp]:
3197 if vartree.dbapi.match(provider):
3198 providers.append(provider)
3199 if len(providers) == 1:
3200 syslist.extend(providers)
3202 syslist.append(mycp)
3204 mysettings = portage.config(clone=settings)
3206 if not unmerge_files or "world" in unmerge_files or \
3207 "system" in unmerge_files:
3208 if "unmerge"==unmerge_action:
3210 print bold("emerge unmerge") + " can only be used with " + \
3211 "specific package names, not with "+bold("world")+" or"
3212 print bold("system")+" targets."
3219 # process all arguments and add all
3220 # valid db entries to candidate_catpkgs
3222 if not unmerge_files or "world" in unmerge_files:
3223 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3224 elif "system" in unmerge_files:
3225 candidate_catpkgs.extend(getlist(settings, "system"))
3227 #we've got command-line arguments
3228 if not unmerge_files:
3229 print "\nNo packages to unmerge have been provided.\n"
3231 for x in unmerge_files:
3232 arg_parts = x.split('/')
3233 if x[0] not in [".","/"] and \
3234 arg_parts[-1][-7:] != ".ebuild":
3235 #possible cat/pkg or dep; treat as such
3236 candidate_catpkgs.append(x)
3237 elif unmerge_action in ["prune","clean"]:
3238 print "\n!!! Prune and clean do not accept individual" + \
3239 " ebuilds as arguments;\n skipping.\n"
3242 # it appears that the user is specifying an installed
3243 # ebuild and we're in "unmerge" mode, so it's ok.
3244 if not os.path.exists(x):
3245 print "\n!!! The path '"+x+"' doesn't exist.\n"
3248 absx = os.path.abspath(x)
3249 sp_absx = absx.split("/")
3250 if sp_absx[-1][-7:] == ".ebuild":
3252 absx = "/".join(sp_absx)
3254 sp_absx_len = len(sp_absx)
3256 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3257 vdb_len = len(vdb_path)
3259 sp_vdb = vdb_path.split("/")
3260 sp_vdb_len = len(sp_vdb)
3262 if not os.path.exists(absx+"/CONTENTS"):
3263 print "!!! Not a valid db dir: "+str(absx)
3266 if sp_absx_len <= sp_vdb_len:
3267 # The Path is shorter... so it can't be inside the vdb.
3270 print "\n!!!",x,"cannot be inside "+ \
3271 vdb_path+"; aborting.\n"
3274 for idx in range(0,sp_vdb_len):
3275 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3278 print "\n!!!", x, "is not inside "+\
3279 vdb_path+"; aborting.\n"
3282 print "="+"/".join(sp_absx[sp_vdb_len:])
3283 candidate_catpkgs.append(
3284 "="+"/".join(sp_absx[sp_vdb_len:]))
3287 if (not "--quiet" in myopts):
3289 if settings["ROOT"] != "/":
3290 print darkgreen(newline+ \
3291 ">>> Using system located in ROOT tree "+settings["ROOT"])
3292 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3293 not ("--quiet" in myopts):
3294 print darkgreen(newline+\
3295 ">>> These are the packages that would be unmerged:")
3299 for x in candidate_catpkgs:
3300 # cycle through all our candidate deps and determine
3301 # what will and will not get unmerged
3303 mymatch=localtree.dep_match(x)
3306 except ValueError, errpkgs:
3307 print "\n\n!!! The short ebuild name \"" + \
3308 x + "\" is ambiguous. Please specify"
3309 print "!!! one of the following fully-qualified " + \
3310 "ebuild names instead:\n"
3311 for i in errpkgs[0]:
3312 print " " + green(i)
3316 if not mymatch and x[0] not in "<>=~":
3317 #add a "=" if missing
3318 mymatch=localtree.dep_match("="+x)
3320 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3321 (x, unmerge_action), noiselevel=-1)
3323 mykey = portage.key_expand(
3325 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3326 if not pkgmap.has_key(mykey):
3327 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3328 if unmerge_action=="unmerge":
3330 if y not in pkgmap[mykey]["selected"]:
3331 pkgmap[mykey]["selected"].append(y)
3332 numselected=numselected+len(mymatch)
3335 #unmerge_action in ["prune", clean"]
3337 for mypkg in mymatch:
3338 if unmerge_action=="clean":
3339 myslot=localtree.getslot(mypkg)
3341 # since we're pruning, we don't care about slots
3342 # and put all the pkgs in together
3344 if not slotmap.has_key(myslot):
3346 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3347 for myslot in slotmap.keys():
3348 counterkeys=slotmap[myslot].keys()
3353 pkgmap[mykey]["protected"].append(
3354 slotmap[myslot][counterkeys[-1]])
3356 #be pretty and get them in order of merge:
3357 for ckey in counterkeys:
3358 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
3359 numselected=numselected+1
3360 # ok, now the last-merged package
3361 # is protected, and the rest are selected
3362 if global_unmerge and not numselected:
3363 print "\n>>> No outdated packages were found on your system.\n"
3367 portage.writemsg_stdout(
3368 "\n>>> No packages selected for removal by " + \
3369 unmerge_action + "\n")
3373 portage.locks.unlockdir(vdb_lock)
3374 for x in pkgmap.keys():
3375 for y in localtree.dep_match(x):
3376 if y not in pkgmap[x]["omitted"] and \
3377 y not in pkgmap[x]["selected"] and \
3378 y not in pkgmap[x]["protected"]:
3379 pkgmap[x]["omitted"].append(y)
3380 if global_unmerge and not pkgmap[x]["selected"]:
3381 #avoid cluttering the preview printout with stuff that isn't getting unmerged
3383 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
3384 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
3385 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
3386 if "--pretend" not in myopts and "--ask" not in myopts:
3387 countdown(int(settings["EMERGE_WARNING_DELAY"]),
3388 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3389 print "\n "+white(x)
3390 for mytype in ["selected","protected","omitted"]:
3391 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
3392 if pkgmap[x][mytype]:
3393 for mypkg in pkgmap[x][mytype]:
3394 mysplit=portage.catpkgsplit(mypkg)
3395 if mysplit[3]=="r0":
3396 myversion=mysplit[2]
3398 myversion=mysplit[2]+"-"+mysplit[3]
3399 if mytype=="selected":
3400 portage.writemsg_stdout(
3401 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
3403 portage.writemsg_stdout(
3404 colorize("GOOD", myversion + " "), noiselevel=-1)
3406 portage.writemsg_stdout("none", noiselevel=-1)
3407 portage.writemsg_stdout("\n", noiselevel=-1)
3409 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3410 " packages are slated for removal.\n")
3411 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
3412 " and " + colorize("GOOD", "'omitted'") + \
3413 " packages will not be removed.\n\n")
3415 if "--pretend" in myopts:
3416 #we're done... return
3418 if "--ask" in myopts:
3419 if userquery("Would you like to unmerge these packages?")=="No":
3420 # enter pretend mode for correct formatting of results
3421 myopts["--pretend"] = True
3426 #the real unmerging begins, after a short delay....
3428 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3430 for x in pkgmap.keys():
3431 for y in pkgmap[x]["selected"]:
3432 print ">>> Unmerging "+y+"..."
3433 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3434 mysplit=y.split("/")
3436 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3437 mysettings, unmerge_action not in ["clean","prune"],
3438 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3439 if retval != os.EX_OK:
3440 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3441 ebuild = vartree.dbapi.findname(y)
3442 show_unmerge_failure_message(y, ebuild, retval)
3445 clean_world(vartree.dbapi, y)
3446 emergelog(xterm_titles, " >>> unmerge success: "+y)
3449 def show_unmerge_failure_message(pkg, ebuild, retval):
3451 from formatter import AbstractFormatter, DumbWriter
3452 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3455 msg.append("A removal phase of the '%s' package " % pkg)
3456 msg.append("has failed with exit value %s. " % retval)
3457 msg.append("The problem occurred while executing ")
3458 msg.append("the ebuild located at '%s'. " % ebuild)
3459 msg.append("If necessary, manually remove the ebuild " )
3460 msg.append("in order to skip the execution of removal phases.")
3464 f.add_flowing_data(x)
3468 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3471 if os.path.exists("/usr/bin/install-info"):
3476 inforoot=normpath(root+z)
3477 if os.path.isdir(inforoot):
3478 infomtime = long(os.stat(inforoot).st_mtime)
3479 if inforoot not in prev_mtimes or \
3480 prev_mtimes[inforoot] != infomtime:
3481 regen_infodirs.append(inforoot)
3483 if not regen_infodirs:
3484 print " "+green("*")+" GNU info directory index is up-to-date."
3486 print " "+green("*")+" Regenerating GNU info directory index..."
3490 for inforoot in regen_infodirs:
3493 for filename in ("dir", "dir.gz", "dir.bz2"):
3494 file_path = os.path.join(inforoot, filename)
3496 os.rename(file_path, file_path + ".old")
3498 if e.errno != errno.ENOENT:
3502 if not os.path.isdir(inforoot):
3505 file_list = os.listdir(inforoot)
3508 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3510 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3511 existsstr="already exists, for file `"
3513 if re.search(existsstr,myso):
3514 # Already exists... Don't increment the count for this.
3516 elif myso[:44]=="install-info: warning: no info dir entry in ":
3517 # This info file doesn't contain a DIR-header: install-info produces this
3518 # (harmless) warning (the --quiet switch doesn't seem to work).
3519 # Don't increment the count for this.
3523 errmsg += myso + "\n"
3526 #update mtime so we can potentially avoid regenerating.
3527 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3530 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3533 print " "+green("*")+" Processed",icount,"info files."
3536 def post_emerge(settings, mtimedb, retval):
3538 Misc. things to run at the end of a merge session.
3546 @param settings: Configuration settings (typically portage.settings)
3547 @type settings: portage.config()
3548 @param mtimedb: The mtimeDB to store data needed across merge invocations
3549 @type mtimedb: MtimeDB class instance
3550 @param retval: Emerge's return value
3554 1. Calls sys.exit(retval)
3556 target_root = settings["ROOT"]
3557 info_mtimes = mtimedb["info"]
3559 # Load the most current variables from ${ROOT}/etc/profile.env
3561 settings.regenerate()
3564 config_protect = settings.get("CONFIG_PROTECT","").split()
3565 infodirs = settings.get("INFOPATH","").split(":") + \
3566 settings.get("INFODIR","").split(":")
3570 emergelog("notitles" not in settings.features,
3571 " *** exiting successfully.")
3573 if "noinfo" not in settings.features:
3574 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3576 chk_updated_cfg_files(target_root, config_protect)
3578 NEWS_PATH = os.path.join( "metadata", "news" )
3579 UNREAD_PATH = os.path.join( target_root, NEWS_LIB_PATH, 'news')
3580 porttree = portdbapi( porttree_root = settings["PORTDIR"], mysettings = settings )
3581 newsReaderDisplay = False
3583 for repo in porttree.getRepositories():
3584 unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
3586 print colorize("WARN", " * IMPORTANT:"),
3587 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
3588 newsReaderDisplay = True
3590 if newsReaderDisplay:
3591 print colorize("WARN", " *"),
3592 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
3598 def chk_updated_cfg_files(target_root, config_protect):
3600 #number of directories with some protect files in them
3602 for x in config_protect:
3603 x = os.path.join(target_root, x.lstrip(os.path.sep))
3605 mymode = os.lstat(x).st_mode
3608 if stat.S_ISDIR(mymode):
3609 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3611 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3612 os.path.split(x.rstrip(os.path.sep))
3613 a = commands.getstatusoutput(mycommand + \
3614 " ! -iname '.*~' ! -iname '.*.bak'")
3616 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3618 files = a[1].split()
3621 print colorize("WARN", " * IMPORTANT:"),
3622 if stat.S_ISDIR(mymode):
3623 print "%d config files in '%s' need updating." % \
3626 print "config file '%s' needs updating." % x
3629 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3630 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3632 def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
3634 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
3635 Returns the number of unread (yet relevent) items.
3647 1. The number of unread but relevant news items.
3650 from portage.news import NewsManager
3651 manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
3652 return manager.getUnreadItems( repo_id, update=True )
3654 def is_valid_package_atom(x):
3656 testkey = portage.dep_getkey(x)
3657 except portage.exception.InvalidData:
3659 if testkey.startswith("null/"):
3660 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3665 return portage.isvalidatom(testatom)
3667 def validate_merge_list(trees, mergelist):
3668 """Validate the list to make sure all the packages are still available.
3669 This is needed for --resume."""
3670 for (pkg_type, myroot, pkg_key, action) in mergelist:
3671 if pkg_type == "binary" and \
3672 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3673 pkg_type == "ebuild" and \
3674 not trees[myroot]["porttree"].dbapi.xmatch(
3675 "match-all", "="+pkg_key):
3676 print red("!!! Error: The resume list contains packages that are no longer")
3677 print red("!!! available to be emerged. Please restart/continue")
3678 print red("!!! the merge operation manually.")
3681 def show_blocker_docs_link():
3683 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3684 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3686 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3689 def action_sync(settings, trees, mtimedb, myopts, myaction):
3690 xterm_titles = "notitles" not in settings.features
3691 emergelog(xterm_titles, " === sync")
3692 myportdir = settings.get("PORTDIR", None)
3694 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3696 if myportdir[-1]=="/":
3697 myportdir=myportdir[:-1]
3698 if not os.path.exists(myportdir):
3699 print ">>>",myportdir,"not found, creating it."
3700 os.makedirs(myportdir,0755)
3701 syncuri=settings["SYNC"].rstrip()
3703 updatecache_flg = False
3704 if myaction == "metadata":
3705 print "skipping sync"
3706 updatecache_flg = True
3707 tmpservertimestampfile = None
3708 elif syncuri[:8]=="rsync://":
3709 if not os.path.exists("/usr/bin/rsync"):
3710 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3711 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3717 if settings["PORTAGE_RSYNC_OPTS"] == "":
3718 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3720 "--recursive", # Recurse directories
3721 "--links", # Consider symlinks
3722 "--safe-links", # Ignore links outside of tree
3723 "--perms", # Preserve permissions
3724 "--times", # Preserive mod times
3725 "--compress", # Compress the data transmitted
3726 "--force", # Force deletion on non-empty dirs
3727 "--whole-file", # Don't do block transfers, only entire files
3728 "--delete", # Delete files that aren't in the master tree
3729 "--delete-after", # Delete only after everything else is done
3730 "--stats", # Show final statistics about what was transfered
3731 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3732 "--exclude='/distfiles'", # Exclude distfiles from consideration
3733 "--exclude='/local'", # Exclude local from consideration
3734 "--exclude='/packages'", # Exclude packages from consideration
3738 # The below validation is not needed when using the above hardcoded
3741 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3742 rsync_opts.extend(settings["PORTAGE_RSYNC_OPTS"].split())
3744 for opt in ("--recursive", "--times"):
3745 if opt not in rsync_opts:
3746 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3747 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3748 rsync_opts.append(opt)
3750 for exclude in ("distfiles", "local", "packages"):
3751 opt = "--exclude=/%s" % exclude
3752 if opt not in rsync_opts:
3753 portage.writemsg(yellow("WARNING:") + \
3754 " adding required option %s not included in " % opt + \
3755 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3756 rsync_opts.append(opt)
3758 if settings["RSYNC_TIMEOUT"] != "":
3759 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3760 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3762 mytimeout = int(settings["RSYNC_TIMEOUT"])
3763 rsync_opts.append("--timeout=%d" % mytimeout)
3764 except ValueError, e:
3765 portage.writemsg("!!! %s\n" % str(e))
3767 # TODO: determine options required for official servers
3768 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
3770 def rsync_opt_startswith(opt_prefix):
3771 for x in rsync_opts:
3772 if x.startswith(opt_prefix):
3776 if not rsync_opt_startswith("--timeout="):
3777 rsync_opts.append("--timeout=%d" % mytimeout)
3779 for opt in ("--compress", "--whole-file"):
3780 if opt not in rsync_opts:
3781 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3782 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3783 rsync_opts.append(opt)
3785 if "--quiet" in myopts:
3786 rsync_opts.append("--quiet") # Shut up a lot
3788 rsync_opts.append("--verbose") # Print filelist
3790 if "--verbose" in myopts:
3791 rsync_opts.append("--progress") # Progress meter for each file
3793 if "--debug" in myopts:
3794 rsync_opts.append("--checksum") # Force checksum on all files
3796 if settings["RSYNC_EXCLUDEFROM"] != "":
3797 portage.writemsg(yellow("WARNING:") + \
3798 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
3799 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3800 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
3801 rsync_opts.append("--exclude-from=%s" % \
3802 settings["RSYNC_EXCLUDEFROM"])
3804 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
3805 " but file does not exist.\n")
3807 if settings["RSYNC_RATELIMIT"] != "":
3808 portage.writemsg(yellow("WARNING:") + \
3809 " usage of RSYNC_RATELIMIT is deprecated, use " + \
3810 "PORTAGE_RSYNC_EXTRA_OPTS instead")
3811 rsync_opts.append("--bwlimit=%s" % \
3812 settings["RSYNC_RATELIMIT"])
3814 # Real local timestamp file.
3815 servertimestampfile = os.path.join(
3816 myportdir, "metadata", "timestamp.chk")
3817 # Temporary file for remote server timestamp comparison.
3818 tmpservertimestampfile = os.path.join(
3819 settings["PORTAGE_TMPDIR"], "timestamp.chk")
3821 content = portage.util.grabfile(servertimestampfile)
3825 mytimestamp = time.mktime(time.strptime(content[0],
3826 "%a, %d %b %Y %H:%M:%S +0000"))
3827 except OverflowError, ValueError:
3832 if settings.has_key("RSYNC_RETRIES"):
3833 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
3834 maxretries=int(settings["RSYNC_RETRIES"])
3836 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
3837 except SystemExit, e:
3838 raise # Needed else can't exit
3840 maxretries=3 #default number of retries
3843 user_name, hostname, port = re.split(
3844 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
3847 if user_name is None:
3849 updatecache_flg=True
3850 all_rsync_opts = set(rsync_opts)
3851 all_rsync_opts.update(
3852 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
3853 family = socket.AF_UNSPEC
3854 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
3855 family = socket.AF_INET
3856 elif socket.has_ipv6 and \
3857 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
3858 family = socket.AF_INET6
3865 for addrinfo in socket.getaddrinfo(
3866 hostname, None, family, socket.SOCK_STREAM):
3867 if addrinfo[0] == socket.AF_INET6:
3868 # IPv6 addresses need to be enclosed in square brackets
3869 ips.append("[%s]" % addrinfo[4][0])
3871 ips.append(addrinfo[4][0])
3872 from random import shuffle
3874 except SystemExit, e:
3875 raise # Needed else can't exit
3876 except Exception, e:
3877 print "Notice:",str(e)
3882 dosyncuri = syncuri.replace(
3883 "//" + user_name + hostname + port + "/",
3884 "//" + user_name + ips[0] + port + "/", 1)
3885 except SystemExit, e:
3886 raise # Needed else can't exit
3887 except Exception, e:
3888 print "Notice:",str(e)
3892 if "--ask" in myopts:
3893 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
3898 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
3899 if "--quiet" not in myopts:
3900 print ">>> Starting rsync with "+dosyncuri+"..."
3902 emergelog(xterm_titles,
3903 ">>> Starting retry %d of %d with %s" % \
3904 (retries,maxretries,dosyncuri))
3905 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
3907 if mytimestamp != 0 and "--quiet" not in myopts:
3908 print ">>> Checking server timestamp ..."
3910 rsynccommand = " ".join(["/usr/bin/rsync", " ".join(rsync_opts),
3911 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
3913 if "--debug" in myopts:
3918 if mytimestamp != 0:
3919 mycommand = rsynccommand.split()
3920 mycommand.append(dosyncuri.rstrip("/") + \
3921 "/metadata/timestamp.chk")
3922 mycommand.append(tmpservertimestampfile)
3924 exitcode = portage.process.spawn(
3925 mycommand, env=settings.environ())
3926 content = portage.grabfile(tmpservertimestampfile)
3929 servertimestamp = time.mktime(time.strptime(
3930 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
3931 except OverflowError, ValueError:
3936 os.unlink(tmpservertimestampfile)
3940 if exitcode == os.EX_OK:
3941 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
3942 emergelog(xterm_titles,
3943 ">>> Cancelling sync -- Already current.")
3946 print ">>> Timestamps on the server and in the local repository are the same."
3947 print ">>> Cancelling all further sync action. You are already up to date."
3949 print ">>> In order to force sync, remove '%s'." % servertimestampfile
3953 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
3954 emergelog(xterm_titles,
3955 ">>> Server out of date: %s" % dosyncuri)
3958 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
3960 print ">>> In order to force sync, remove '%s'." % servertimestampfile
3963 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
3965 mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
3966 exitcode=portage.spawn(mycommand,settings,free=1)
3967 if exitcode in [0,1,2,3,4,11,14,20,21]:
3969 elif exitcode in [0,1,2,3,4,11,14,20,21]:
3974 if retries<=maxretries:
3975 print ">>> Retrying..."
3980 updatecache_flg=False
3984 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
3988 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
3989 print darkred("!!!")+green(" that your SYNC statement is proper.")
3990 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
3992 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
3993 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
3994 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
3995 print darkred("!!!")+green(" and try again after the problem has been fixed.")
3996 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
3998 print darkred("!!!")+green(" Rsync was killed before it finished.")
4000 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4001 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4002 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4003 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4004 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4007 elif syncuri[:6]=="cvs://":
4008 if not os.path.exists("/usr/bin/cvs"):
4009 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4010 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4013 cvsdir=os.path.dirname(myportdir)
4014 if not os.path.exists(myportdir+"/CVS"):
4016 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4017 if os.path.exists(cvsdir+"/gentoo-x86"):
4018 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4023 if e.errno != errno.ENOENT:
4025 "!!! existing '%s' directory; exiting.\n" % myportdir)
4028 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4029 print "!!! cvs checkout error; exiting."
4031 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4034 print ">>> Starting cvs update with "+syncuri+"..."
4035 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4036 myportdir, settings, free=1)
4037 if retval != os.EX_OK:
4041 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4044 if updatecache_flg and \
4045 myaction != "metadata" and \
4046 "metadata-transfer" not in settings.features:
4047 updatecache_flg = False
4049 # Reload the whole config from scratch.
4050 settings, trees, mtimedb = load_emerge_config(trees=trees)
4051 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4053 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4054 action_metadata(settings, portdb, myopts)
4056 if portage.global_updates(settings, trees, mtimedb["updates"]):
4058 # Reload the whole config from scratch.
4059 settings, trees, mtimedb = load_emerge_config(trees=trees)
4060 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4062 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4063 mypvs = portage.best(
4064 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4066 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4068 if myaction != "metadata":
4069 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4070 retval = portage.process.spawn(
4071 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4072 dosyncuri], env=settings.environ())
4073 if retval != os.EX_OK:
4074 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4076 if(mybestpv != mypvs) and not "--quiet" in myopts:
4078 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4079 print red(" * ")+"that you update portage now, before any other packages are updated."
4080 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4081 print red(" * ")+"configuration files."
4082 print red(" * ")+"To update portage, run 'emerge portage'."
4085 def action_metadata(settings, portdb, myopts):
4086 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4087 old_umask = os.umask(0002)
4088 cachedir = os.path.normpath(settings.depcachedir)
4089 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4090 "/lib", "/opt", "/proc", "/root", "/sbin",
4091 "/sys", "/tmp", "/usr", "/var"]:
4092 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4093 "ROOT DIRECTORY ON YOUR SYSTEM."
4094 print >> sys.stderr, \
4095 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4097 if not os.path.exists(cachedir):
4100 ec = portage.eclass_cache.cache(portdb.porttree_root)
4101 myportdir = os.path.realpath(settings["PORTDIR"])
4102 cm = settings.load_best_module("portdbapi.metadbmodule")(
4103 myportdir, "metadata/cache", portage.auxdbkeys[:])
4105 from portage.cache import util
4107 class percentage_noise_maker(util.quiet_mirroring):
4108 def __init__(self, dbapi):
4110 self.cp_all = dbapi.cp_all()
4111 l = len(self.cp_all)
4112 self.call_update_min = 100000000
4113 self.min_cp_all = l/100.0
4118 for x in self.cp_all:
4120 if self.count > self.min_cp_all:
4121 self.call_update_min = 0
4123 for y in self.dbapi.cp_list(x):
4125 self.call_update_mine = 0
4127 def update(self, *arg):
4128 try: self.pstr = int(self.pstr) + 1
4129 except ValueError: self.pstr = 1
4130 sys.stdout.write("%s%i%%" % \
4131 ("\b" * (len(str(self.pstr))+1), self.pstr))
4133 self.call_update_min = 10000000
4135 def finish(self, *arg):
4136 sys.stdout.write("\b\b\b\b100%\n")
4139 if "--quiet" in myopts:
4140 def quicky_cpv_generator(cp_all_list):
4141 for x in cp_all_list:
4142 for y in portdb.cp_list(x):
4144 source = quicky_cpv_generator(portdb.cp_all())
4145 noise_maker = portage.cache.util.quiet_mirroring()
4147 noise_maker = source = percentage_noise_maker(portdb)
4148 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4149 eclass_cache=ec, verbose_instance=noise_maker)
4154 def action_regen(settings, portdb):
4155 xterm_titles = "notitles" not in settings.features
4156 emergelog(xterm_titles, " === regen")
4157 #regenerate cache entries
4158 print "Regenerating cache entries... "
4160 os.close(sys.stdin.fileno())
4161 except SystemExit, e:
4162 raise # Needed else can't exit
4166 mynodes = portdb.cp_all()
4167 from portage.cache.cache_errors import CacheError
4169 for mytree in portdb.porttrees:
4171 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4172 except CacheError, e:
4173 print "\n error listing cache entries for " + \
4174 "'%s': %s, continuing..." % (mytree, e)
4179 mymatches = portdb.xmatch("match-all",x)
4180 portage.writemsg_stdout("processing %s\n" % x)
4183 foo = portdb.aux_get(y,["DEPEND"])
4184 except SystemExit, e:
4185 # sys.exit is an exception... And consequently, we can't catch it.
4187 except Exception, e:
4188 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4190 for mytree in portdb.porttrees:
4191 if portdb.findname2(y, mytree=mytree)[0]:
4192 dead_nodes[mytree].discard(y)
4194 for mytree, nodes in dead_nodes.iteritems():
4195 auxdb = portdb.auxdb[mytree]
4199 except KeyError, CacheError:
4203 def action_config(settings, trees, myopts, myfiles):
4204 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4205 print red("!!! config can only take a single package atom at this time\n")
4207 if not is_valid_package_atom(myfiles[0]):
4208 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4210 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4211 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4215 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4216 except ValueError, e:
4217 # Multiple matches thrown from cpv_expand
4220 print "No packages found.\n"
4223 if "--ask" in myopts:
4225 print "Please select a package to configure:"
4229 options.append(str(idx))
4230 print options[-1]+") "+pkg
4233 idx = userquery("Selection?", options)
4236 pkg = pkgs[int(idx)-1]
4238 print "The following packages available:"
4241 print "\nPlease use a specific atom or the --ask option."
4247 if "--ask" in myopts:
4248 if userquery("Ready to configure "+pkg+"?") == "No":
4251 print "Configuring pkg..."
4253 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4254 mysettings = portage.config(clone=settings)
4255 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4256 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4257 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4260 def action_info(settings, trees, myopts, myfiles):
4261 unameout=commands.getstatusoutput("uname -mrp")[1]
4262 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4263 settings.profile_path, settings["CHOST"],
4264 trees[settings["ROOT"]]["vartree"].dbapi)
4266 header_title = "System Settings"
4268 print header_width * "="
4269 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4270 print header_width * "="
4271 print "System uname: "+unameout
4272 gentoo_release = portage.grabfile(os.path.join(
4273 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4275 print gentoo_release[0]
4277 print "Unknown Host Operating System"
4278 lastSync = portage.grabfile(os.path.join(
4279 settings["PORTDIR"], "metadata", "timestamp.chk"))
4280 print "Timestamp of tree:",
4286 output=commands.getstatusoutput("distcc --version")
4288 print str(output[1].split("\n",1)[0]),
4289 if "distcc" in settings.features:
4294 output=commands.getstatusoutput("ccache -V")
4296 print str(output[1].split("\n",1)[0]),
4297 if "ccache" in settings.features:
4302 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4303 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4304 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4305 myvars = portage.util.unique_array(myvars)
4309 if portage.isvalidatom(x):
4310 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4312 for y in pkg_matches:
4313 mycpv = portage.catpkgsplit(y)
4314 if(mycpv[3] != "r0"):
4315 pkgs += [mycpv[2] + "-" + mycpv[3]]
4319 pkgs = ", ".join(sorted_versions(pkgs))
4320 print "%-20s %s" % (x+":", pkgs)
4322 print "%-20s %s" % (x+":", "[NOT VALID]")
4324 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4326 if "--verbose" in myopts:
4327 myvars=settings.keys()
4329 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4330 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4331 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4332 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4334 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4336 myvars = portage.util.unique_array(myvars)
4342 print '%s="%s"' % (x, settings[x])
4344 use = set(settings["USE"].split())
4345 use_expand = settings["USE_EXPAND"].split()
4347 for varname in use_expand:
4348 flag_prefix = varname.lower() + "_"
4350 if f.startswith(flag_prefix):
4354 print 'USE="%s"' % " ".join(use),
4355 for varname in use_expand:
4356 myval = settings.get(varname)
4358 print '%s="%s"' % (varname, myval),
4361 unset_vars.append(x)
4363 print "Unset: "+", ".join(unset_vars)
4366 if "--debug" in myopts:
4367 for x in dir(portage):
4368 module = getattr(portage, x)
4369 if "cvs_id_string" in dir(module):
4370 print "%s: %s" % (str(x), str(module.cvs_id_string))
4372 # See if we can find any packages installed matching the strings
4373 # passed on the command line
4375 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4376 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4378 mypkgs.extend(vardb.match(x))
4380 # If some packages were found...
4382 # Get our global settings (we only print stuff if it varies from
4383 # the current config)
4384 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4385 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4387 pkgsettings = portage.config(clone=settings)
4389 for myvar in mydesiredvars:
4390 global_vals[myvar] = set(settings.get(myvar, "").split())
4392 # Loop through each package
4393 # Only print settings if they differ from global settings
4394 header_printed = False
4396 # Get all package specific variables
4397 auxvalues = vardb.aux_get(pkg, auxkeys)
4399 for i in xrange(len(auxkeys)):
4400 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4402 for myvar in mydesiredvars:
4403 # If the package variable doesn't match the
4404 # current global variable, something has changed
4405 # so set diff_found so we know to print
4406 if valuesmap[myvar] != global_vals[myvar]:
4407 diff_values[myvar] = valuesmap[myvar]
4408 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4409 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4411 # If a matching ebuild is no longer available in the tree, maybe it
4412 # would make sense to compare against the flags for the best
4413 # available version with the same slot?
4415 if portdb.cpv_exists(pkg):
4417 pkgsettings.setcpv(pkg, mydb=mydb)
4418 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
4420 diff_values["USE"] = valuesmap["USE"]
4421 # If a difference was found, print the info for
4425 # If we have not yet printed the header,
4427 if not header_printed:
4428 header_title = "Package Settings"
4429 print header_width * "="
4430 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4431 print header_width * "="
4432 header_printed = True
4434 # Print package info
4435 print "%s was built with the following:" % pkg
4436 for myvar in mydesiredvars + ["USE"]:
4437 if myvar in diff_values:
4438 mylist = list(diff_values[myvar])
4440 print "%s=\"%s\"" % (myvar, " ".join(mylist))
4443 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
4445 print "emerge: no search terms provided."
4447 searchinstance = search(settings, portdb,
4448 vartree, spinner, "--searchdesc" in myopts,
4449 "--quiet" not in myopts)
4450 for mysearch in myfiles:
4452 searchinstance.execute(mysearch)
4453 except re.error, comment:
4454 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
4456 searchinstance.output()
4458 def action_depclean(settings, trees, ldpath_mtimes,
4460 # Kill packages that aren't explicitly merged or are required as a
4461 # dependency of another package. World file is explicit.
4463 warn_prefix = colorize("BAD", "*** WARNING *** ")
4465 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
4466 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
4467 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
4469 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
4470 print warn_prefix + "mistakes. Packages that are part of the world set will always"
4471 print warn_prefix + "be kept. They can be manually added to this set with"
4472 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
4473 print warn_prefix + "package.provided (see portage(5)) will be removed by"
4474 print warn_prefix + "depclean, even if they are part of the world set."
4476 print warn_prefix + "As a safety measure, depclean will not remove any packages"
4477 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
4478 print warn_prefix + "consequence, it is often necessary to run "
4479 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
4481 xterm_titles = "notitles" not in settings.features
4482 myroot = settings["ROOT"]
4483 dep_check_trees = {}
4484 dep_check_trees[myroot] = {}
4485 dep_check_trees[myroot]["vartree"] = \
4486 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
4487 vardb = dep_check_trees[myroot]["vartree"].dbapi
4488 # Constrain dependency selection to the installed packages.
4489 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
4490 syslist = getlist(settings, "system")
4491 worldlist = getlist(settings, "world")
4492 fakedb = portage.fakedbapi(settings=settings)
4493 myvarlist = vardb.cpv_all()
4496 print "\n!!! You have no system list.",
4498 print "\n!!! You have no world file.",
4500 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
4502 if not (syslist and worldlist and myvarlist):
4503 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
4504 print " break your installation.\n"
4505 if "--pretend" not in myopts:
4506 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
4508 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4509 emergelog(xterm_titles, " >>> depclean")
4511 if "--quiet" not in myopts:
4512 print "\nCalculating dependencies ",
4516 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
4517 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
4519 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
4521 while remaining_atoms:
4522 atom, parent, priority = remaining_atoms.pop()
4523 pkgs = vardb.match(atom)
4525 if not atom.startswith("!") and priority == hard:
4526 unresolveable.setdefault(atom, []).append(parent)
4528 # Could put slot checking here to ensure that there aren't two
4529 # packages with the same slot...
4531 if fakedb.cpv_exists(pkg):
4534 fakedb.cpv_inject(pkg)
4535 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
4537 if myopts.get("--with-bdeps", "y") == "y":
4538 mydeps.append((myaux["DEPEND"], soft))
4540 mydeps.append((" ".join(myaux.values()), hard))
4541 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
4542 for depstr, priority in mydeps:
4547 if "--debug" in myopts:
4549 print "Parent: ", pkg
4550 print "Depstring:", depstr
4552 if priority == soft:
4558 portage.dep._dep_check_strict = False
4559 success, atoms = portage.dep_check(depstr, None, settings,
4560 myuse=usedef, trees=dep_check_trees, myroot=myroot)
4562 portage.dep._dep_check_strict = True
4564 show_invalid_depstring_notice(
4565 ("installed", myroot, pkg, "nomerge"),
4569 if "--debug" in myopts:
4570 print "Candidates:", atoms
4573 remaining_atoms.append((atom, pkg, priority))
4575 if "--quiet" not in myopts:
4576 print "\b\b... done!\n"
4579 print "Dependencies could not be completely resolved due to"
4580 print "the following required packages not being installed:"
4582 for atom in unresolveable:
4583 print atom, "required by", " ".join(unresolveable[atom])
4585 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
4586 print "depclean? It may also be necessary to manually uninstalled packages that no"
4587 print "longer exist in the portage tree since it may not be possible to satisfy their"
4588 print "dependencies."
4592 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
4595 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
4596 "unmerge", cleanlist, ldpath_mtimes)
4598 print "Packages installed: "+str(len(myvarlist))
4599 print "Packages in world: "+str(len(worldlist))
4600 print "Packages in system: "+str(len(syslist))
4601 print "Unique package names: "+str(len(myvarlist))
4602 print "Required packages: "+str(len(fakedb.cpv_all()))
4603 if "--pretend" in myopts:
4604 print "Number to remove: "+str(len(cleanlist))
4606 print "Number removed: "+str(len(cleanlist))
4608 def action_build(settings, trees, mtimedb,
4609 myopts, myaction, myfiles, spinner):
4610 ldpath_mtimes = mtimedb["ldpath"]
4612 if ("--ask" in myopts or "--pretend" in myopts) and not "--quiet" in myopts:
4614 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4618 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
4620 print darkgreen("These are the packages that would be %s, in reverse order:") % action
4624 print darkgreen("These are the packages that would be %s, in order:") % action
4627 # validate the state of the resume data
4628 # so that we can make assumptions later.
4629 for k in ("resume", "resume_backup"):
4631 if "mergelist" in mtimedb[k]:
4632 if not mtimedb[k]["mergelist"]:
4637 if "--resume" in myopts and \
4638 ("resume" in mtimedb or
4639 "resume_backup" in mtimedb):
4640 if "resume" not in mtimedb:
4641 mtimedb["resume"] = mtimedb["resume_backup"]
4642 del mtimedb["resume_backup"]
4644 # XXX: "myopts" is a list for backward compatibility.
4645 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4647 for opt in ("--skipfirst", "--ask", "--tree"):
4648 myresumeopts.pop(opt, None)
4650 for myopt, myarg in myopts.iteritems():
4651 if myopt not in myresumeopts:
4652 myresumeopts[myopt] = myarg
4654 myparams = create_depgraph_params(myopts, myaction)
4655 if not "--quiet" in myopts:
4656 print "Calculating dependencies ",
4657 mydepgraph = depgraph(settings, trees,
4658 myopts, myparams, spinner)
4659 if not "--quiet" in myopts:
4660 print "\b\b... done!"
4662 if ("--resume" in myopts):
4663 print darkgreen("emerge: It seems we have nothing to resume...")
4666 myparams = create_depgraph_params(myopts, myaction)
4667 if myaction in ["system","world"]:
4668 if not ("--quiet" in myopts):
4669 print "Calculating",myaction,"dependencies ",
4671 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4672 if not mydepgraph.xcreate(myaction):
4673 print "!!! Depgraph creation failed."
4675 if not ("--quiet" in myopts):
4676 print "\b\b... done!"
4678 if not ("--quiet" in myopts):
4679 print "Calculating dependencies ",
4681 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4683 retval, favorites = mydepgraph.select_files(myfiles)
4684 except portage.exception.PackageNotFound, e:
4685 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4689 if not ("--quiet" in myopts):
4690 print "\b\b... done!"
4692 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4693 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4695 if mydepgraph.missingbins:
4696 for x in mydepgraph.missingbins:
4697 sys.stderr.write(" "+str(x)+"\n")
4698 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4701 if "--ask" in myopts:
4702 if "--resume" in myopts:
4703 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4704 mymergelist = mtimedb["resume"]["mergelist"]
4705 if "--skipfirst" in myopts:
4706 mymergelist = mymergelist[1:]
4707 if len(mymergelist) == 0:
4708 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4710 mydepgraph.display(mymergelist)
4711 prompt="Would you like to resume merging these packages?"
4714 mydepgraph.altlist(reversed=("--tree" in myopts)))
4716 for x in mydepgraph.altlist():
4717 if x[0] != "blocks" and x[3] != "nomerge":
4719 #check for blocking dependencies
4720 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
4721 print "\n!!! Error: The above package list contains packages which cannot be installed"
4722 print "!!! at the same time on the same system."
4723 if "--quiet" not in myopts:
4724 show_blocker_docs_link()
4727 if "--noreplace" in myopts and favorites:
4730 print " %s %s" % (good("*"), x)
4731 prompt="Would you like to add these packages to your world favorites?"
4732 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4733 prompt="Nothing to merge; would you like to auto-clean packages?"
4736 print "Nothing to merge; quitting."
4739 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4740 prompt="Would you like to fetch the source files for these packages?"
4742 prompt="Would you like to merge these packages?"
4744 if userquery(prompt)=="No":
4749 # Don't ask again (e.g. when auto-cleaning packages after merge)
4752 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4753 if ("--resume" in myopts):
4754 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4755 mymergelist = mtimedb["resume"]["mergelist"]
4756 if "--skipfirst" in myopts:
4757 mymergelist = mymergelist[1:]
4758 if len(mymergelist) == 0:
4759 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4761 mydepgraph.display(mymergelist)
4764 mydepgraph.altlist(reversed=("--tree" in myopts)))
4766 if ("--buildpkgonly" in myopts):
4767 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
4768 print "\n!!! --buildpkgonly requires all dependencies to be merged."
4769 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
4772 if ("--resume" in myopts):
4773 favorites=mtimedb["resume"]["favorites"]
4774 mergetask = MergeTask(settings, trees, myopts)
4775 if "--fetchonly" in myopts:
4776 """ parallel-fetch uses --resume --fetchonly and we don't want
4777 it to write the mtimedb"""
4778 mtimedb.filename = None
4779 time.sleep(3) # allow the parent to have first fetch
4781 retval = mergetask.merge(
4782 mtimedb["resume"]["mergelist"], favorites, mtimedb)
4783 if retval != os.EX_OK:
4786 if "resume" in mtimedb and \
4787 "mergelist" in mtimedb["resume"] and \
4788 len(mtimedb["resume"]["mergelist"]) > 1:
4789 mtimedb["resume_backup"] = mtimedb["resume"]
4790 del mtimedb["resume"]
4792 mtimedb["resume"]={}
4793 # XXX: Stored as a list for backward compatibility.
4794 mtimedb["resume"]["myopts"] = \
4795 [k for k in myopts if myopts[k] is True]
4796 mtimedb["resume"]["favorites"]=favorites
4797 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4798 for pkgline in mydepgraph.altlist():
4799 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
4800 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
4801 tmpsettings = portage.config(clone=settings)
4803 if settings.get("PORTAGE_DEBUG", "") == "1":
4805 retval = portage.doebuild(
4806 y, "digest", settings["ROOT"], tmpsettings, edebug,
4807 ("--pretend" in myopts),
4808 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
4810 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4812 for pkg in mydepgraph.altlist():
4813 if pkg[0] != "blocks":
4816 pkglist = mydepgraph.altlist()
4818 mergetask = MergeTask(settings, trees, myopts)
4819 retval = mergetask.merge(pkglist, favorites, mtimedb)
4820 if retval != os.EX_OK:
4823 if mtimedb.has_key("resume"):
4824 del mtimedb["resume"]
4825 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4826 print ">>> Auto-cleaning packages..."
4827 vartree = trees[settings["ROOT"]]["vartree"]
4828 unmerge(settings, myopts, vartree, "clean", ["world"],
4829 ldpath_mtimes, autoclean=1)
4831 portage.writemsg_stdout(colorize("WARN", "WARNING:")
4832 + " AUTOCLEAN is disabled. This can cause serious"
4833 + " problems due to overlapping packages.\n")
4835 def multiple_actions(action1, action2):
4836 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
4837 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
4840 def parse_opts(tmpcmdline, silent=False):
4845 global actions, options, shortmapping
4847 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
4848 argument_options = {
4850 "help":"specify the location for portage configuration files",
4854 "help":"enable or disable color output",
4856 "choices":("y", "n")
4859 "help":"include unnecessary build time dependencies",
4861 "choices":("y", "n")
4865 from optparse import OptionParser
4866 parser = OptionParser()
4867 if parser.has_option("--help"):
4868 parser.remove_option("--help")
4870 for action_opt in actions:
4871 parser.add_option("--" + action_opt, action="store_true",
4872 dest=action_opt.replace("-", "_"), default=False)
4873 for myopt in options:
4874 parser.add_option(myopt, action="store_true",
4875 dest=myopt.lstrip("--").replace("-", "_"), default=False)
4876 for shortopt, longopt in shortmapping.iteritems():
4877 parser.add_option("-" + shortopt, action="store_true",
4878 dest=longopt.lstrip("--").replace("-", "_"), default=False)
4879 for myalias, myopt in longopt_aliases.iteritems():
4880 parser.add_option(myalias, action="store_true",
4881 dest=myopt.lstrip("--").replace("-", "_"), default=False)
4883 for myopt, kwargs in argument_options.iteritems():
4884 parser.add_option(myopt,
4885 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
4887 myoptions, myargs = parser.parse_args(args=tmpcmdline)
4889 for myopt in options:
4890 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
4892 myopts[myopt] = True
4894 for myopt in argument_options:
4895 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
4899 for action_opt in actions:
4900 v = getattr(myoptions, action_opt.replace("-", "_"))
4903 multiple_actions(myaction, action_opt)
4905 myaction = action_opt
4908 if x in actions and myaction != "search":
4909 if not silent and x not in ["system", "world"]:
4910 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
4911 # special case "search" so people can search for action terms, e.g. emerge -s sync
4913 multiple_actions(myaction, x)
4919 if "--nocolor" in myopts:
4921 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
4922 "use '--color=n' instead.\n")
4923 del myopts["--nocolor"]
4924 myopts["--color"] = "n"
4926 return myaction, myopts, myfiles
4928 def validate_ebuild_environment(trees):
4929 for myroot in trees:
4930 mysettings = trees[myroot]["vartree"].settings
4931 if not mysettings.get("ARCH", None):
4932 print >> sys.stderr, bad("\a!!! ARCH is not set... " + \
4933 "Are you missing the '%setc/make.profile' symlink?" % \
4934 mysettings["PORTAGE_CONFIGROOT"])
4935 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
4936 "Is your portage tree complete?\n")
4938 del myroot, mysettings
4940 def load_emerge_config(trees=None):
4942 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
4943 kwargs[k] = os.environ.get(envvar, None)
4944 trees = portage.create_trees(trees=trees, **kwargs)
4946 settings = trees["/"]["vartree"].settings
4948 for myroot in trees:
4950 settings = trees[myroot]["vartree"].settings
4953 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
4954 mtimedb = portage.MtimeDB(mtimedbfile)
4955 return settings, trees, mtimedb
4957 def adjust_config(myopts, settings):
4958 """Make emerge specific adjustments to the config."""
4960 # To enhance usability, make some vars case insensitive by forcing them to
4962 for myvar in ("AUTOCLEAN", "NOCOLOR"):
4963 if myvar in settings:
4964 settings[myvar] = settings[myvar].lower()
4965 settings.backup_changes(myvar)
4968 # Kill noauto as it will break merges otherwise.
4969 if "noauto" in settings.features:
4970 while "noauto" in settings.features:
4971 settings.features.remove("noauto")
4972 settings["FEATURES"] = " ".join(settings.features)
4973 settings.backup_changes("FEATURES")
4977 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
4978 except ValueError, e:
4979 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4980 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
4981 settings["CLEAN_DELAY"], noiselevel=-1)
4982 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
4983 settings.backup_changes("CLEAN_DELAY")
4985 EMERGE_WARNING_DELAY = 10
4987 EMERGE_WARNING_DELAY = int(settings.get(
4988 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
4989 except ValueError, e:
4990 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4991 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
4992 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
4993 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
4994 settings.backup_changes("EMERGE_WARNING_DELAY")
4996 if "--quiet" in myopts:
4997 settings["PORTAGE_QUIET"]="1"
4998 settings.backup_changes("PORTAGE_QUIET")
5000 # Set so that configs will be merged regardless of remembered status
5001 if ("--noconfmem" in myopts):
5002 settings["NOCONFMEM"]="1"
5003 settings.backup_changes("NOCONFMEM")
5005 # Set various debug markers... They should be merged somehow.
5008 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5009 if PORTAGE_DEBUG not in (0, 1):
5010 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5011 PORTAGE_DEBUG, noiselevel=-1)
5012 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5015 except ValueError, e:
5016 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5017 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5018 settings["PORTAGE_DEBUG"], noiselevel=-1)
5020 if "--debug" in myopts:
5022 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5023 settings.backup_changes("PORTAGE_DEBUG")
5025 if settings.get("NOCOLOR") not in ("yes","true"):
5026 portage.output.havecolor = 1
5028 """The explicit --color < y | n > option overrides the NOCOLOR environment
5029 variable and stdout auto-detection."""
5030 if "--color" in myopts:
5031 if "y" == myopts["--color"]:
5032 portage.output.havecolor = 1
5033 settings["NOCOLOR"] = "false"
5035 portage.output.havecolor = 0
5036 settings["NOCOLOR"] = "true"
5037 settings.backup_changes("NOCOLOR")
5038 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5039 portage.output.havecolor = 0
5040 settings["NOCOLOR"] = "true"
5041 settings.backup_changes("NOCOLOR")
5044 global portage # NFC why this is necessary now - genone
5045 # Disable color until we're sure that it should be enabled (after
5046 # EMERGE_DEFAULT_OPTS has been parsed).
5047 portage.output.havecolor = 0
5048 # This first pass is just for options that need to be known as early as
5049 # possible, such as --config-root. They will be parsed again later,
5050 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5051 # the value of --config-root).
5052 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5053 if "--debug" in myopts:
5054 os.environ["PORTAGE_DEBUG"] = "1"
5055 if "--config-root" in myopts:
5056 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5058 # Portage needs to ensure a sane umask for the files it creates.
5060 settings, trees, mtimedb = load_emerge_config()
5061 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5064 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5065 except (OSError, ValueError), e:
5066 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5067 settings["PORTAGE_NICENESS"])
5068 portage.writemsg("!!! %s\n" % str(e))
5071 if portage.global_updates(settings, trees, mtimedb["updates"]):
5073 # Reload the whole config from scratch.
5074 settings, trees, mtimedb = load_emerge_config(trees=trees)
5075 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5077 xterm_titles = "notitles" not in settings.features
5080 if "--ignore-default-opts" not in sys.argv:
5081 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5082 tmpcmdline.extend(sys.argv[1:])
5083 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5085 if "--digest" in myopts:
5086 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5087 # Reload the whole config from scratch so that the portdbapi internal
5088 # config is updated with new FEATURES.
5089 settings, trees, mtimedb = load_emerge_config(trees=trees)
5090 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5092 for myroot in trees:
5093 mysettings = trees[myroot]["vartree"].settings
5095 adjust_config(myopts, mysettings)
5097 del myroot, mysettings
5099 spinner = stdout_spinner()
5100 if "candy" in settings.features:
5101 spinner.update = spinner.update_scroll
5103 portage.deprecated_profile_check()
5105 #Freeze the portdbapi for enhanced performance:
5106 for myroot in trees:
5107 trees[myroot]["porttree"].dbapi.freeze()
5110 if "moo" in myfiles:
5113 Larry loves Gentoo (""" + os.uname()[0] + """)
5115 _______________________
5116 < Have you mooed today? >
5117 -----------------------
5126 if (myaction in ["world", "system"]) and myfiles:
5127 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5131 ext = os.path.splitext(x)[1]
5132 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5133 print "emerging by path implies --oneshot... adding --oneshot to options."
5134 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5137 if ("--tree" in myopts) and ("--columns" in myopts):
5138 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5141 if ("--quiet" in myopts):
5142 spinner.update = spinner.update_quiet
5143 portage.util.noiselimit = -1
5145 # Always create packages if FEATURES=buildpkg
5146 # Imply --buildpkg if --buildpkgonly
5147 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5148 if "--buildpkg" not in myopts:
5149 myopts["--buildpkg"] = True
5151 # Also allow -S to invoke search action (-sS)
5152 if ("--searchdesc" in myopts):
5153 if myaction and myaction != "search":
5154 myfiles.append(myaction)
5155 if "--search" not in myopts:
5156 myopts["--search"] = True
5159 # Always try and fetch binary packages if FEATURES=getbinpkg
5160 if ("getbinpkg" in settings.features):
5161 myopts["--getbinpkg"] = True
5163 if "--skipfirst" in myopts and "--resume" not in myopts:
5164 myopts["--resume"] = True
5166 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5167 myopts["--usepkgonly"] = True
5169 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5170 myopts["--getbinpkg"] = True
5172 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5173 myopts["--usepkg"] = True
5175 # Also allow -K to apply --usepkg/-k
5176 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5177 myopts["--usepkg"] = True
5179 # Allow -p to remove --ask
5180 if ("--pretend" in myopts) and ("--ask" in myopts):
5181 print ">>> --pretend disables --ask... removing --ask from options."
5184 # forbid --ask when not in a terminal
5185 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5186 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5187 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5191 if settings.get("PORTAGE_DEBUG", "") == "1":
5192 spinner.update = spinner.update_quiet
5194 if "python-trace" in settings.features:
5195 import portage.debug
5196 portage.debug.set_trace(True)
5198 if ("--resume" in myopts):
5199 if "--tree" in myopts:
5200 print "* --tree is currently broken with --resume. Disabling..."
5201 del myopts["--tree"]
5203 if not ("--quiet" in myopts):
5204 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5205 spinner.update = spinner.update_basic
5207 if "--version" in myopts:
5208 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5209 settings.profile_path, settings["CHOST"],
5210 trees[settings["ROOT"]]["vartree"].dbapi)
5212 elif "--help" in myopts:
5213 portage.emergehelp.help(myaction, myopts, portage.output.havecolor)
5216 if portage.wheelgid == portage.portage_gid:
5217 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
5218 print " include the portage user as noted above, and then use group portage."
5220 if "--debug" in myopts:
5221 print "myaction", myaction
5222 print "myopts", myopts
5224 if not myaction and not myfiles and "--resume" not in myopts:
5225 portage.emergehelp.help(myaction, myopts, portage.output.havecolor)
5228 # check if root user is the current user for the actions where emerge needs this
5229 if portage.secpass < 2:
5230 # We've already allowed "--version" and "--help" above.
5231 if "--pretend" not in myopts and \
5232 myaction not in ("search","info"):
5233 need_superuser = not \
5234 ("--fetchonly" in myopts or \
5235 "--fetch-all-uri" in myopts or \
5236 myaction in ("metadata", "regen"))
5237 if portage.secpass < 1 or \
5240 access_desc = "superuser"
5242 access_desc = "portage group"
5243 # Always show portage_group_warning() when only portage group
5244 # access is required but the user is not in the portage group.
5245 from portage.data import portage_group_warning
5246 if "--ask" in myopts:
5247 myopts["--pretend"] = True
5249 print ("%s access would be required... " + \
5250 "adding --pretend to options.\n") % access_desc
5251 if portage.secpass < 1 and not need_superuser:
5252 portage_group_warning()
5254 sys.stderr.write(("emerge: %s access would be " + \
5255 "required.\n\n") % access_desc)
5256 if portage.secpass < 1 and not need_superuser:
5257 portage_group_warning()
5260 disable_emergelog = False
5261 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5263 disable_emergelog = True
5265 if myaction in ("search", "info"):
5266 disable_emergelog = True
5267 if disable_emergelog:
5268 """ Disable emergelog for everything except build or unmerge
5269 operations. This helps minimize parallel emerge.log entries that can
5270 confuse log parsers. We especially want it disabled during
5271 parallel-fetch, which uses --resume --fetchonly."""
5273 def emergelog(*pargs, **kargs):
5276 if not "--pretend" in myopts:
5277 emergelog(xterm_titles, "Started emerge on: "+\
5278 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5281 myelogstr=" ".join(myopts)
5283 myelogstr+=" "+myaction
5285 myelogstr+=" "+" ".join(myfiles)
5286 emergelog(xterm_titles, " *** emerge " + myelogstr)
5288 def emergeexitsig(signum, frame):
5289 signal.signal(signal.SIGINT, signal.SIG_IGN)
5290 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5291 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5292 sys.exit(100+signum)
5293 signal.signal(signal.SIGINT, emergeexitsig)
5294 signal.signal(signal.SIGTERM, emergeexitsig)
5297 """This gets out final log message in before we quit."""
5298 if "--pretend" not in myopts:
5299 emergelog(xterm_titles, " *** terminating.")
5300 if "notitles" not in settings.features:
5302 portage.atexit_register(emergeexit)
5304 if myaction in ("config", "metadata", "regen", "sync"):
5305 if "--pretend" in myopts:
5306 sys.stderr.write(("emerge: The '%s' action does " + \
5307 "not support '--pretend'.\n") % myaction)
5309 if "sync" == myaction:
5310 action_sync(settings, trees, mtimedb, myopts, myaction)
5311 elif "metadata" == myaction:
5312 action_metadata(settings, portdb, myopts)
5313 elif myaction=="regen":
5314 validate_ebuild_environment(trees)
5315 action_regen(settings, portdb)
5317 elif "config"==myaction:
5318 validate_ebuild_environment(trees)
5319 action_config(settings, trees, myopts, myfiles)
5322 elif "info"==myaction:
5323 action_info(settings, trees, myopts, myfiles)
5326 elif "search"==myaction:
5327 validate_ebuild_environment(trees)
5328 action_search(settings, portdb, trees["/"]["vartree"],
5329 myopts, myfiles, spinner)
5330 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5331 validate_ebuild_environment(trees)
5332 vartree = trees[settings["ROOT"]]["vartree"]
5333 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5335 if "--pretend" not in myopts:
5336 post_emerge(settings, mtimedb, 0)
5338 elif "depclean"==myaction:
5339 validate_ebuild_environment(trees)
5340 action_depclean(settings, trees, mtimedb["ldpath"],
5342 if "--pretend" not in myopts:
5343 post_emerge(settings, mtimedb, 0)
5344 # "update", "system", or just process files:
5346 validate_ebuild_environment(trees)
5347 action_build(settings, trees, mtimedb,
5348 myopts, myaction, myfiles, spinner)
5349 if "--pretend" not in myopts:
5350 post_emerge(settings, mtimedb, 0)
5352 if __name__ == "__main__":
5353 retval = emerge_main()