2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4 # $Id: emerge 5976 2007-02-17 09:14:53Z genone $
7 # This block ensures that ^C interrupts are handled quietly.
11 def exithandler(signum,frame):
12 signal.signal(signal.SIGINT, signal.SIG_IGN)
13 signal.signal(signal.SIGTERM, signal.SIG_IGN)
16 signal.signal(signal.SIGINT, exithandler)
17 signal.signal(signal.SIGTERM, exithandler)
18 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
20 except KeyboardInterrupt:
25 os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
29 from os import path as osp
30 sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
32 del os.environ["PORTAGE_LEGACY_GLOBALS"]
33 from portage import digraph, portdbapi
34 from portage.const import NEWS_LIB_PATH, CACHE_PATH, PRIVATE_PATH
37 import portage.xpak, commands, errno, re, socket, time, types
38 from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
39 havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
40 xtermTitleReset, yellow
41 from portage.output import create_color_func
42 good = create_color_func("GOOD")
43 bad = create_color_func("BAD")
46 portage.dep._dep_check_strict = True
49 import portage.exception
50 from portage.data import secpass
51 from portage.util import normalize_path as normpath
52 from portage.util import writemsg
54 if not hasattr(__builtins__, "set"):
55 from sets import Set as set
56 from itertools import chain, izip
57 from UserDict import DictMixin
62 import pickle as cPickle
64 class stdout_spinner(object):
66 "Gentoo Rocks ("+os.uname()[0]+")",
67 "Thank you for using Gentoo. :)",
68 "Are you actually trying to read this?",
69 "How many times have you stared at this?",
70 "We are generating the cache right now",
71 "You are paying too much attention.",
72 "A theory is better than its explanation.",
73 "Phasers locked on target, Captain.",
74 "Thrashing is just virtual crashing.",
75 "To be is to program.",
76 "Real Users hate Real Programmers.",
77 "When all else fails, read the instructions.",
78 "Functionality breeds Contempt.",
79 "The future lies ahead.",
80 "3.1415926535897932384626433832795028841971694",
81 "Sometimes insanity is the only alternative.",
82 "Inaccuracy saves a world of explanation.",
85 twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
89 self.update = self.update_twirl
90 self.scroll_sequence = self.scroll_msgs[
91 int(time.time() * 100) % len(self.scroll_msgs)]
93 def update_basic(self):
94 self.spinpos = (self.spinpos + 1) % 500
95 if (self.spinpos % 100) == 0:
97 sys.stdout.write(". ")
102 def update_scroll(self):
103 if(self.spinpos >= len(self.scroll_sequence)):
104 sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
105 len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
107 sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
109 self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
111 def update_twirl(self):
112 self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
113 sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
116 def update_quiet(self):
119 def userquery(prompt, responses=None, colours=None):
120 """Displays a prompt and a set of responses, then waits for a response
121 which is checked against the responses and the first to match is
122 returned. An empty response will match the first value in responses. The
123 input buffer is *not* cleared prior to the prompt!
126 responses: a List of Strings.
127 colours: a List of Functions taking and returning a String, used to
128 process the responses for display. Typically these will be functions
129 like red() but could be e.g. lambda x: "DisplayString".
130 If responses is omitted, defaults to ["Yes", "No"], [green, red].
131 If only colours is omitted, defaults to [bold, ...].
133 Returns a member of the List responses. (If called without optional
134 arguments, returns "Yes" or "No".)
135 KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
137 if responses is None:
138 responses, colours = ["Yes", "No"], [green, red]
139 elif colours is None:
141 colours=(colours*len(responses))[:len(responses)]
145 response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
146 for key in responses:
147 # An empty response will match the first value in responses.
148 if response.upper()==key[:len(response)].upper():
150 print "Sorry, response '%s' not understood." % response,
151 except (EOFError, KeyboardInterrupt):
156 "clean", "config", "depclean",
158 "prune", "regen", "search",
159 "sync", "system", "unmerge", "world",
162 "--ask", "--alphabetical",
163 "--buildpkg", "--buildpkgonly",
164 "--changelog", "--columns",
168 "--fetchonly", "--fetch-all-uri",
169 "--getbinpkg", "--getbinpkgonly",
170 "--help", "--ignore-default-opts",
172 "--newuse", "--nocolor",
173 "--nodeps", "--noreplace",
174 "--nospinner", "--oneshot",
175 "--onlydeps", "--pretend",
176 "--quiet", "--resume",
177 "--searchdesc", "--selective",
181 "--usepkg", "--usepkgonly",
182 "--verbose", "--version"
188 "b":"--buildpkg", "B":"--buildpkgonly",
189 "c":"--clean", "C":"--unmerge",
190 "d":"--debug", "D":"--deep",
192 "f":"--fetchonly", "F":"--fetch-all-uri",
193 "g":"--getbinpkg", "G":"--getbinpkgonly",
195 "k":"--usepkg", "K":"--usepkgonly",
197 "n":"--noreplace", "N":"--newuse",
198 "o":"--onlydeps", "O":"--nodeps",
199 "p":"--pretend", "P":"--prune",
201 "s":"--search", "S":"--searchdesc",
204 "v":"--verbose", "V":"--version"
207 def emergelog(xterm_titles, mystr, short_msg=None):
209 if short_msg == None:
211 if "HOSTNAME" in os.environ:
212 short_msg = os.environ["HOSTNAME"]+": "+short_msg
213 xtermTitle(short_msg)
215 file_path = "/var/log/emerge.log"
216 mylogfile = open(file_path, "a")
217 portage.util.apply_secpass_permissions(file_path,
218 uid=portage.portage_uid, gid=portage.portage_gid,
222 mylock = portage.locks.lockfile(mylogfile)
223 # seek because we may have gotten held up by the lock.
224 # if so, we may not be positioned at the end of the file.
226 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
230 portage.locks.unlockfile(mylock)
232 except (IOError,OSError,portage.exception.PortageException), e:
234 print >> sys.stderr, "emergelog():",e
236 def countdown(secs=5, doing="Starting"):
238 print ">>> Waiting",secs,"seconds before starting..."
239 print ">>> (Control-C to abort)...\n"+doing+" in: ",
243 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
248 # formats a size given in bytes nicely
249 def format_size(mysize):
250 if type(mysize) not in [types.IntType,types.LongType]:
252 if 0 != mysize % 1024:
253 # Always round up to the next kB so that it doesn't show 0 kB when
254 # some small file still needs to be fetched.
255 mysize += 1024 - mysize % 1024
256 mystr=str(mysize/1024)
260 mystr=mystr[:mycount]+","+mystr[mycount:]
264 def getgccversion(chost):
267 return: the current in-use gcc version
270 gcc_ver_command = 'gcc -dumpversion'
271 gcc_ver_prefix = 'gcc-'
273 gcc_not_found_error = red(
274 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
275 "!!! to update the environment of this terminal and possibly\n" +
276 "!!! other terminals also.\n"
279 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
280 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
281 part1, part2 = myoutput.split("/")
282 if part1.startswith(chost + "-"):
283 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
285 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
286 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
287 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
289 mystatus, myoutput = commands.getstatusoutput(
290 chost + "-" + gcc_ver_command)
291 if mystatus == os.EX_OK:
292 return gcc_ver_prefix + myoutput
294 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
295 if mystatus == os.EX_OK:
296 return gcc_ver_prefix + myoutput
298 portage.writemsg(gcc_not_found_error, noiselevel=-1)
299 return "[unavailable]"
301 def getportageversion(portdir, target_root, profile, chost, vardb):
302 profilever = "unavailable"
304 realpath = os.path.realpath(profile)
305 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
306 if realpath.startswith(basepath):
307 profilever = realpath[1 + len(basepath):]
310 profilever = "!" + os.readlink(profile)
313 del realpath, basepath
316 libclist = vardb.match("virtual/libc")
317 libclist += vardb.match("virtual/glibc")
318 libclist = portage.util.unique_array(libclist)
320 xs=portage.catpkgsplit(x)
322 libcver+=","+"-".join(xs[1:])
324 libcver="-".join(xs[1:])
326 libcver="unavailable"
328 gccver = getgccversion(chost)
329 unameout=os.uname()[2]+" "+os.uname()[4]
331 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
333 def create_depgraph_params(myopts, myaction):
334 #configure emerge engine parameters
336 # self: include _this_ package regardless of if it is merged.
337 # selective: exclude the package if it is merged
338 # recurse: go into the dependencies
339 # deep: go into the dependencies of already merged packages
340 # empty: pretend nothing is merged
341 myparams = ["recurse"]
344 if "--update" in myopts or \
345 "--newuse" in myopts or \
346 "--reinstall" in myopts or \
347 "--noreplace" in myopts or \
348 myaction in ("system", "world"):
349 add.extend(["selective"])
350 if "--emptytree" in myopts:
351 add.extend(["empty"])
352 sub.extend(["selective"])
353 if "--nodeps" in myopts:
354 sub.extend(["recurse"])
355 if "--deep" in myopts:
358 if (x not in myparams) and (x not in sub):
365 # search functionality
366 class search(object):
377 def __init__(self, settings, portdb, vartree, spinner, searchdesc,
379 """Searches the available and installed packages for the supplied search key.
380 The list of available and installed packages is created at object instantiation.
381 This makes successive searches faster."""
382 self.settings = settings
384 self.vartree = vartree
385 self.spinner = spinner
386 self.verbose = verbose
387 self.searchdesc = searchdesc
389 def execute(self,searchkey):
390 """Performs the search for the supplied search key"""
392 self.searchkey=searchkey
393 self.packagematches = []
396 self.matches = {"pkg":[], "desc":[]}
399 self.matches = {"pkg":[]}
400 print "Searching... ",
403 if self.searchkey.startswith('%'):
405 self.searchkey = self.searchkey[1:]
406 if self.searchkey.startswith('@'):
408 self.searchkey = self.searchkey[1:]
410 self.searchre=re.compile(self.searchkey,re.I)
412 self.searchre=re.compile(re.escape(self.searchkey), re.I)
413 for package in self.portdb.cp_all():
414 self.spinner.update()
417 match_string = package[:]
419 match_string = package.split("/")[-1]
422 if self.searchre.search(match_string):
423 if not self.portdb.xmatch("match-visible", package):
425 self.matches["pkg"].append([package,masked])
426 elif self.searchdesc: # DESCRIPTION searching
427 full_package = self.portdb.xmatch("bestmatch-visible", package)
429 #no match found; we don't want to query description
430 full_package = portage.best(
431 self.portdb.xmatch("match-all", package))
437 full_desc = self.portdb.aux_get(
438 full_package, ["DESCRIPTION"])[0]
440 print "emerge: search: aux_get() failed, skipping"
442 if self.searchre.search(full_desc):
443 self.matches["desc"].append([full_package,masked])
445 for mtype in self.matches:
446 self.matches[mtype].sort()
447 self.mlen += len(self.matches[mtype])
450 """Outputs the results of the search."""
451 print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
452 print "[ Applications found : "+white(str(self.mlen))+" ]"
454 for mtype in self.matches:
455 for match,masked in self.matches[mtype]:
458 full_package = self.portdb.xmatch(
459 "bestmatch-visible", match)
461 #no match found; we don't want to query description
463 full_package = portage.best(
464 self.portdb.xmatch("match-all",match))
467 match = portage.pkgsplit(match)[0]
471 desc, homepage, license = self.portdb.aux_get(
472 full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
474 print "emerge: search: aux_get() failed, skipping"
477 print green("*")+" "+white(match)+" "+red("[ Masked ]")
479 print green("*")+" "+white(match)
480 myversion = self.getVersion(full_package, search.VERSION_RELEASE)
483 mycat = match.split("/")[0]
484 mypkg = match.split("/")[1]
485 mycpv = match + "-" + myversion
486 myebuild = self.portdb.findname(mycpv)
487 pkgdir = os.path.dirname(myebuild)
488 from portage import manifest
489 mf = manifest.Manifest(
490 pkgdir, self.settings["DISTDIR"])
491 fetchlist = self.portdb.getfetchlist(mycpv,
492 mysettings=self.settings, all=True)[1]
494 mysum[0] = mf.getDistfilesSize(fetchlist)
495 mystr = str(mysum[0]/1024)
499 mystr=mystr[:mycount]+","+mystr[mycount:]
502 mysum[0] = "Unknown (missing digest for %s)" % str(e)
505 print " ", darkgreen("Latest version available:"),myversion
506 print " ", self.getInstallationStatus(mycat+'/'+mypkg)
507 print " ", darkgreen("Size of files:"),mysum[0]
508 print " ", darkgreen("Homepage:")+" ",homepage
509 print " ", darkgreen("Description:")+" ",desc
510 print " ", darkgreen("License:")+" ",license
516 def getInstallationStatus(self,package):
517 installed_package = self.vartree.dep_bestmatch(package)
519 version = self.getVersion(installed_package,search.VERSION_RELEASE)
521 result = darkgreen("Latest version installed:")+" "+version
523 result = darkgreen("Latest version installed:")+" [ Not Installed ]"
526 def getVersion(self,full_package,detail):
527 if len(full_package) > 1:
528 package_parts = portage.catpkgsplit(full_package)
529 if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
530 result = package_parts[2]+ "-" + package_parts[3]
532 result = package_parts[2]
538 #build our package digraph
539 def getlist(settings, mode):
541 mylines = settings.packages
544 file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
545 myfile = open(file_path, "r")
546 mylines = myfile.readlines()
548 except (OSError, IOError), e:
549 if e.errno == errno.ENOENT:
550 portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
556 myline=" ".join(x.split())
565 mynewlines.append(myline.strip())
569 def clean_world(vardb, cpv):
570 """Remove a package from the world file when unmerged."""
571 world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
572 worldlist = portage.util.grabfile(world_filename)
573 mykey = portage.cpv_getkey(cpv)
576 if portage.dep_getkey(x) == mykey:
577 matches = vardb.match(x, use_cache=0)
581 elif len(matches) == 1 and matches[0] == cpv:
585 #others are around; keep it.
586 newworldlist.append(x)
588 #this doesn't match the package we're unmerging; keep it.
589 newworldlist.append(x)
593 portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
594 gid=portage.portage_gid, mode=02770)
595 portage.util.write_atomic(world_filename, "\n".join(newworldlist)+"\n")
597 def genericdict(mylist):
600 mynewdict[portage.dep_getkey(x)]=x
603 def filter_iuse_defaults(iuse):
605 if flag.startswith("+") or flag.startswith("-"):
610 class DepPriority(object):
612 This class generates an integer priority level based of various
613 attributes of the dependency relationship. Attributes can be assigned
614 at any time and the new integer value will be generated on calls to the
615 __int__() method. Rich comparison operators are supported.
617 The boolean attributes that affect the integer value are "satisfied",
618 "buildtime", "runtime", and "system". Various combinations of
619 attributes lead to the following priority levels:
621 Combination of properties Priority level
623 not satisfied and buildtime 0
624 not satisfied and runtime -1
625 satisfied and buildtime -2
626 satisfied and runtime -3
627 (none of the above) -4
629 Several integer constants are defined for categorization of priority
632 MEDIUM The upper boundary for medium dependencies.
633 MEDIUM_SOFT The upper boundary for medium-soft dependencies.
634 SOFT The upper boundary for soft dependencies.
635 MIN The lower boundary for soft dependencies.
637 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime", "runtime_post")
642 def __init__(self, **kwargs):
643 for myattr in self.__slots__:
644 if myattr == "__weakref__":
646 myvalue = kwargs.get(myattr, False)
647 setattr(self, myattr, myvalue)
649 if not self.satisfied:
654 if self.runtime_post:
660 if self.runtime_post:
663 def __lt__(self, other):
664 return self.__int__() < other
665 def __le__(self, other):
666 return self.__int__() <= other
667 def __eq__(self, other):
668 return self.__int__() == other
669 def __ne__(self, other):
670 return self.__int__() != other
671 def __gt__(self, other):
672 return self.__int__() > other
673 def __ge__(self, other):
674 return self.__int__() >= other
677 return copy.copy(self)
679 myvalue = self.__int__()
680 if myvalue > self.MEDIUM:
682 if myvalue > self.MEDIUM_SOFT:
684 if myvalue > self.SOFT:
688 class FakeVartree(portage.vartree):
689 """This is implements an in-memory copy of a vartree instance that provides
690 all the interfaces required for use by the depgraph. The vardb is locked
691 during the constructor call just long enough to read a copy of the
692 installed package information. This allows the depgraph to do it's
693 dependency calculations without holding a lock on the vardb. It also
694 allows things like vardb global updates to be done in memory so that the
695 user doesn't necessarily need write access to the vardb in cases where
696 global updates are necessary (updates are performed when necessary if there
697 is not a matching ebuild in the tree)."""
698 def __init__(self, real_vartree, portdb):
699 self.root = real_vartree.root
700 self.settings = real_vartree.settings
701 self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
702 vdb_path = os.path.join(self.root, portage.VDB_PATH)
704 # At least the parent needs to exist for the lock file.
705 portage.util.ensure_dirs(vdb_path)
706 except portage.exception.PortageException:
710 if os.access(vdb_path, os.W_OK):
711 vdb_lock = portage.locks.lockdir(vdb_path)
712 mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
713 "DEPEND", "RDEPEND", "PDEPEND", "repository"]
714 real_dbapi = real_vartree.dbapi
716 for cpv in real_dbapi.cpv_all():
717 metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
718 myslot = metadata["SLOT"]
719 mycp = portage.dep_getkey(cpv)
720 myslot_atom = "%s:%s" % (mycp, myslot)
722 mycounter = long(metadata["COUNTER"])
725 metadata["COUNTER"] = str(mycounter)
726 other_counter = slot_counters.get(myslot_atom, None)
727 if other_counter is not None:
728 if other_counter > mycounter:
730 slot_counters[myslot_atom] = mycounter
731 self.dbapi.cpv_inject(cpv, metadata=metadata)
732 real_dbapi.flush_cache()
735 portage.locks.unlockdir(vdb_lock)
736 # Populate the old-style virtuals using the cached values.
737 if not self.settings.treeVirtuals:
738 self.settings.treeVirtuals = portage.util.map_dictlist_vals(
739 portage.getCPFromCPV, self.get_all_provides())
741 # Intialize variables needed for lazy cache pulls of the live ebuild
742 # metadata. This ensures that the vardb lock is released ASAP, without
743 # being delayed in case cache generation is triggered.
744 self._aux_get = self.dbapi.aux_get
745 self.dbapi.aux_get = self._aux_get_wrapper
746 self._aux_get_history = set()
747 self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
748 self._portdb = portdb
749 self._global_updates = None
751 def _aux_get_wrapper(self, pkg, wants):
752 if pkg in self._aux_get_history:
753 return self._aux_get(pkg, wants)
754 self._aux_get_history.add(pkg)
756 # Use the live ebuild metadata if possible.
757 live_metadata = dict(izip(self._portdb_keys,
758 self._portdb.aux_get(pkg, self._portdb_keys)))
759 self.dbapi.aux_update(pkg, live_metadata)
760 except (KeyError, portage.exception.PortageException):
761 if self._global_updates is None:
762 self._global_updates = \
763 grab_global_updates(self._portdb.porttree_root)
764 perform_global_updates(
765 pkg, self.dbapi, self._global_updates)
766 return self._aux_get(pkg, wants)
768 def grab_global_updates(portdir):
769 from portage.update import grab_updates, parse_updates
770 updpath = os.path.join(portdir, "profiles", "updates")
772 rawupdates = grab_updates(updpath)
773 except portage.exception.DirectoryNotFound:
776 for mykey, mystat, mycontent in rawupdates:
777 commands, errors = parse_updates(mycontent)
778 upd_commands.extend(commands)
781 def perform_global_updates(mycpv, mydb, mycommands):
782 from portage.update import update_dbentries
783 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
784 aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
785 updates = update_dbentries(mycommands, aux_dict)
787 mydb.aux_update(mycpv, updates)
789 class BlockerCache(DictMixin):
790 """This caches blockers of installed packages so that dep_check does not
791 have to be done for every single installed package on every invocation of
792 emerge. The cache is invalidated whenever it is detected that something
793 has changed that might alter the results of dep_check() calls:
794 1) the set of installed packages (including COUNTER) has changed
795 2) the old-style virtuals have changed
797 class BlockerData(object):
798 def __init__(self, counter, atoms):
799 self.counter = counter
802 def __init__(self, myroot, vardb):
804 self._installed_pkgs = set(vardb.cpv_all())
805 self._virtuals = vardb.settings.getvirtuals()
806 self._cache_filename = os.path.join(myroot,
807 portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
808 self._cache_version = "1"
809 self._cache_data = None
810 self._modified = False
815 f = open(self._cache_filename)
816 mypickle = cPickle.Unpickler(f)
817 mypickle.find_global = None
818 self._cache_data = mypickle.load()
821 except (IOError, OSError, EOFError, cPickle.UnpicklingError):
823 cache_valid = self._cache_data and \
824 isinstance(self._cache_data, dict) and \
825 self._cache_data.get("version") == self._cache_version and \
826 self._cache_data.get("virtuals") == self._virtuals and \
827 set(self._cache_data.get("blockers", [])) == self._installed_pkgs
829 for pkg in self._installed_pkgs:
830 if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
835 self._cache_data = {"version":self._cache_version}
836 self._cache_data["blockers"] = {}
837 self._cache_data["virtuals"] = self._virtuals
838 self._modified = False
841 """If the current user has permission and the internal blocker cache
842 been updated, save it to disk and mark it unmodified. This is called
843 by emerge after it has proccessed blockers for all installed packages.
844 Currently, the cache is only written if the user has superuser
845 privileges (since that's required to obtain a lock), but all users
846 have read access and benefit from faster blocker lookups (as long as
847 the entire cache is still valid). The cache is stored as a pickled
848 dict object with the following format:
852 "blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
853 "virtuals" : vardb.settings.getvirtuals()
856 if self._modified and \
859 f = portage.util.atomic_ofstream(self._cache_filename)
860 cPickle.dump(self._cache_data, f, -1)
862 portage.util.apply_secpass_permissions(
863 self._cache_filename, gid=portage.portage_gid, mode=0644)
864 except (IOError, OSError), e:
866 self._modified = False
868 def __setitem__(self, cpv, blocker_data):
870 Update the cache and mark it as modified for a future call to
873 @param cpv: Package for which to cache blockers.
875 @param blocker_data: An object with counter and atoms attributes.
876 @type blocker_data: BlockerData
878 self._cache_data["blockers"][cpv] = \
879 (blocker_data.counter, blocker_data.atoms)
880 self._modified = True
882 def __getitem__(self, cpv):
885 @returns: An object with counter and atoms attributes.
887 return self.BlockerData(*self._cache_data["blockers"][cpv])
889 def show_invalid_depstring_notice(parent_node, depstring, error_msg):
891 from formatter import AbstractFormatter, DumbWriter
892 f = AbstractFormatter(DumbWriter(maxcol=72))
894 print "\n\n!!! Invalid or corrupt dependency specification: "
902 p_type, p_root, p_key, p_status = parent_node
904 if p_status == "nomerge":
905 category, pf = portage.catsplit(p_key)
906 pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
907 msg.append("Portage is unable to process the dependencies of the ")
908 msg.append("'%s' package. " % p_key)
909 msg.append("In order to correct this problem, the package ")
910 msg.append("should be uninstalled, reinstalled, or upgraded. ")
911 msg.append("As a temporary workaround, the --nodeps option can ")
912 msg.append("be used to ignore all dependencies. For reference, ")
913 msg.append("the problematic dependencies can be found in the ")
914 msg.append("*DEPEND files located in '%s/'." % pkg_location)
916 msg.append("This package can not be installed. ")
917 msg.append("Please notify the '%s' package maintainer " % p_key)
918 msg.append("about this problem.")
921 f.add_flowing_data(x)
924 class depgraph(object):
929 "installed":"vartree"}
931 def __init__(self, settings, trees, myopts, myparams, spinner):
932 self.settings = settings
933 self.target_root = settings["ROOT"]
935 self.myparams = myparams
937 if settings.get("PORTAGE_DEBUG", "") == "1":
939 self.spinner = spinner
940 self.pkgsettings = {}
941 # Maps cpv to digraph node for all nodes added to the graph.
942 self.pkg_node_map = {}
943 # Maps slot atom to digraph node for all nodes added to the graph.
944 self._slot_node_map = {}
946 self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND",
947 "USE", "IUSE", "PROVIDE", "repository"]
951 self.trees[myroot] = {}
952 for tree in ("porttree", "bintree"):
953 self.trees[myroot][tree] = trees[myroot][tree]
954 self.trees[myroot]["vartree"] = \
955 FakeVartree(trees[myroot]["vartree"],
956 trees[myroot]["porttree"].dbapi)
957 self.pkgsettings[myroot] = portage.config(
958 clone=self.trees[myroot]["vartree"].settings)
959 self.pkg_node_map[myroot] = {}
960 self._slot_node_map[myroot] = {}
961 vardb = self.trees[myroot]["vartree"].dbapi
962 # This fakedbapi instance will model the state that the vdb will
963 # have after new packages have been installed.
964 fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
965 self.mydbapi[myroot] = fakedb
966 if "--nodeps" not in self.myopts and \
967 "--buildpkgonly" not in self.myopts:
968 # --nodeps bypasses this, since it isn't needed in this case
969 # and the cache pulls might trigger (slow) cache generation.
970 for pkg in vardb.cpv_all():
971 self.spinner.update()
972 fakedb.cpv_inject(pkg,
973 metadata=dict(izip(self._mydbapi_keys,
974 vardb.aux_get(pkg, self._mydbapi_keys))))
976 self.useFlags[myroot] = {}
977 if "--usepkg" in self.myopts:
978 self.trees[myroot]["bintree"].populate(
979 "--getbinpkg" in self.myopts,
980 "--getbinpkgonly" in self.myopts)
984 self.digraph=portage.digraph()
985 # Tracks simple parent/child relationships (PDEPEND relationships are
987 self._parent_child_digraph = digraph()
989 self.outdatedpackages=[]
990 self._args_atoms = {}
991 self._args_nodes = set()
993 self._sets_nodes = {}
994 self.blocker_digraph = digraph()
995 self.blocker_parents = {}
996 self._unresolved_blocker_parents = {}
997 self._slot_collision_info = []
998 # Slot collision nodes are not allowed to block other packages since
999 # blocker validation is only able to account for one package per slot.
1000 self._slot_collision_nodes = set()
1001 self._altlist_cache = {}
1002 self._pprovided_args = []
1004 def _show_slot_collision_notice(self, packages):
1005 """Show an informational message advising the user to mask one of the
1006 the packages. In some cases it may be possible to resolve this
1007 automatically, but support for backtracking (removal nodes that have
1008 already been selected) will be required in order to handle all possible
1012 msg.append("\n!!! Multiple versions within a single " + \
1013 "package slot have been \n")
1014 msg.append("!!! pulled into the dependency graph:\n\n")
1015 for node, parents in packages:
1016 msg.append(str(node))
1018 msg.append(" pulled in by\n")
1019 for parent in parents:
1021 msg.append(str(parent))
1024 msg.append(" (no parents)\n")
1026 sys.stderr.write("".join(msg))
1029 if "--quiet" in self.myopts:
1033 msg.append("It may be possible to solve this problem ")
1034 msg.append("by using package.mask to prevent one of ")
1035 msg.append("those packages from being selected. ")
1036 msg.append("However, it is also possible that conflicting ")
1037 msg.append("dependencies exist such that they are impossible to ")
1038 msg.append("satisfy simultaneously. If such a conflict exists in ")
1039 msg.append("the dependencies of two different packages, then those ")
1040 msg.append("packages can not be installed simultaneously.")
1042 from formatter import AbstractFormatter, DumbWriter
1043 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
1045 f.add_flowing_data(x)
1049 msg.append("For more information, see MASKED PACKAGES ")
1050 msg.append("section in the emerge man page or refer ")
1051 msg.append("to the Gentoo Handbook.")
1053 f.add_flowing_data(x)
1057 def _reinstall_for_flags(self, forced_flags,
1058 orig_use, orig_iuse, cur_use, cur_iuse):
1059 if "--newuse" in self.myopts:
1060 if orig_iuse.symmetric_difference(
1061 cur_iuse).difference(forced_flags):
1063 elif orig_iuse.intersection(orig_use) != \
1064 cur_iuse.intersection(cur_use):
1066 elif "changed-use" == self.myopts.get("--reinstall"):
1067 if orig_iuse.intersection(orig_use) != \
1068 cur_iuse.intersection(cur_use):
1072 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
1073 priority=DepPriority(), rev_dep=False, arg=None):
1075 Fills the digraph with nodes comprised of packages to merge.
1076 mybigkey is the package spec of the package to merge.
1077 myparent is the package depending on mybigkey ( or None )
1078 addme = Should we add this package to the digraph or are we just looking at it's deps?
1079 Think --onlydeps, we need to ignore packages in that case.
1082 #IUSE-aware emerge -> USE DEP aware depgraph
1083 #"no downgrade" emerge
1085 mytype, myroot, mykey = mybigkey
1086 existing_node = None
1088 existing_node = self.pkg_node_map[myroot].get(mykey)
1090 self._parent_child_digraph.add(existing_node, myparent)
1091 if existing_node != myparent:
1092 # Refuse to make a node depend on itself so that the we don't
1093 # don't create a bogus circular dependency in self.altlist().
1094 if rev_dep and myparent:
1095 self.digraph.addnode(myparent, existing_node,
1098 self.digraph.addnode(existing_node, myparent,
1102 if "--nodeps" not in self.myopts:
1103 self.spinner.update()
1104 if mytype == "blocks":
1106 "--buildpkgonly" not in self.myopts and \
1107 "--nodeps" not in self.myopts and \
1108 myparent not in self._slot_collision_nodes:
1109 mybigkey[1] = myparent[1]
1110 self.blocker_parents.setdefault(
1111 tuple(mybigkey), set()).add(myparent)
1114 # select the correct /var database that we'll be checking against
1115 vardbapi = self.trees[myroot]["vartree"].dbapi
1116 portdb = self.trees[myroot]["porttree"].dbapi
1117 bindb = self.trees[myroot]["bintree"].dbapi
1118 pkgsettings = self.pkgsettings[myroot]
1120 # if the package is already on the system, we add a "nomerge"
1121 # directive, otherwise we add a "merge" directive.
1123 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
1124 metadata = dict(izip(self._mydbapi_keys,
1125 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1126 if mytype == "ebuild":
1127 pkgsettings.setcpv(mykey, mydb=portdb)
1128 metadata["USE"] = pkgsettings["USE"]
1129 myuse = pkgsettings["USE"].split()
1131 if not arg and myroot == self.target_root:
1133 arg = self._find_atom_for_pkg(self._args_atoms, mykey, metadata)
1134 except portage.exception.InvalidDependString, e:
1135 if mytype != "installed":
1136 show_invalid_depstring_notice(tuple(mybigkey+["merge"]),
1137 metadata["PROVIDE"], str(e))
1142 if mytype == "installed":
1144 if addme and mytype != "installed":
1145 # this is where we add the node to the list of packages to merge
1146 if "selective" in self.myparams or not arg:
1147 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
1150 """ If we aren't merging, perform the --newuse check.
1151 If the package has new iuse flags or different use flags then if
1152 --newuse is specified, we need to merge the package. """
1153 if merging == 0 and \
1154 ("--newuse" in self.myopts or
1155 "--reinstall" in self.myopts) and \
1156 vardbapi.cpv_exists(mykey):
1157 pkgsettings.setcpv(mykey, mydb=mydbapi)
1158 forced_flags = set()
1159 forced_flags.update(pkgsettings.useforce)
1160 forced_flags.update(pkgsettings.usemask)
1161 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
1162 iuses = set(filter_iuse_defaults(metadata["IUSE"].split()))
1163 old_iuse = set(filter_iuse_defaults(
1164 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
1165 if self._reinstall_for_flags(
1166 forced_flags, old_use, old_iuse, myuse, iuses):
1169 if addme and merging == 1:
1170 mybigkey.append("merge")
1172 mybigkey.append("nomerge")
1173 jbigkey = tuple(mybigkey)
1176 if merging == 0 and vardbapi.cpv_exists(mykey) and \
1177 mytype != "installed":
1178 mytype = "installed"
1179 mybigkey[0] = "installed"
1181 jbigkey = tuple(mybigkey)
1182 metadata = dict(izip(self._mydbapi_keys,
1183 mydbapi.aux_get(mykey, self._mydbapi_keys)))
1184 myuse = metadata["USE"].split()
1185 slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
1186 existing_node = self._slot_node_map[myroot].get(
1188 slot_collision = False
1190 e_type, myroot, e_cpv, e_status = existing_node
1192 # The existing node can be reused.
1193 self._parent_child_digraph.add(existing_node, myparent)
1194 if rev_dep and myparent:
1195 ptype, proot, pkey, pstatus = myparent
1196 self.digraph.addnode(myparent, existing_node,
1199 self.digraph.addnode(existing_node, myparent,
1203 # A slot collision has occurred. Sometimes this coincides
1204 # with unresolvable blockers, so the slot collision will be
1205 # shown later if there are no unresolvable blockers.
1206 e_parents = self._parent_child_digraph.parent_nodes(
1210 myparents.append(myparent)
1211 self._slot_collision_info.append(
1212 ((jbigkey, myparents), (existing_node, e_parents)))
1213 self._slot_collision_nodes.add(jbigkey)
1214 slot_collision = True
1217 # Now add this node to the graph so that self.display()
1218 # can show use flags and --tree portage.output. This node is
1219 # only being partially added to the graph. It must not be
1220 # allowed to interfere with the other nodes that have been
1221 # added. Do not overwrite data for existing nodes in
1222 # self.pkg_node_map and self.mydbapi since that data will
1223 # be used for blocker validation.
1224 self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
1225 self.useFlags[myroot].setdefault(mykey, myuse)
1226 # Even though the graph is now invalid, continue to process
1227 # dependencies so that things like --fetchonly can still
1228 # function despite collisions.
1230 self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
1231 self._slot_node_map[myroot][slot_atom] = jbigkey
1232 self.pkg_node_map[myroot][mykey] = jbigkey
1233 self.useFlags[myroot][mykey] = myuse
1235 if rev_dep and myparent:
1236 self.digraph.addnode(myparent, jbigkey,
1239 self.digraph.addnode(jbigkey, myparent,
1243 self._args_nodes.add(jbigkey)
1245 for set_name, pkg_set in self._sets.iteritems():
1246 atom = self._find_atom_for_pkg(pkg_set, mykey, metadata)
1248 self._sets_nodes[set_name].add(jbigkey)
1249 except portage.exception.InvalidDependString, e:
1250 if mytype != "installed":
1251 show_invalid_depstring_notice(jbigkey,
1252 metadata["PROVIDE"], str(e))
1256 # Do this even when addme is False (--onlydeps) so that the
1257 # parent/child relationship is always known in case
1258 # self._show_slot_collision_notice() needs to be called later.
1259 self._parent_child_digraph.add(jbigkey, myparent)
1261 """ This section determines whether we go deeper into dependencies or not.
1262 We want to go deeper on a few occasions:
1263 Installing package A, we need to make sure package A's deps are met.
1264 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
1265 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
1267 if "deep" not in self.myparams and not merging and \
1268 not ("--update" in self.myopts and arg and merging):
1270 elif "recurse" not in self.myparams:
1273 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
1274 Pull from bintree if it's binary package, porttree if it's ebuild.
1275 Binpkg's can be either remote or local. """
1278 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
1280 edepend[k] = metadata[k]
1282 if mytype == "ebuild":
1283 if "--buildpkgonly" in self.myopts:
1284 edepend["RDEPEND"] = ""
1285 edepend["PDEPEND"] = ""
1286 if not (arg and "--onlydeps" in self.myopts and \
1287 mytype == "ebuild") and \
1288 self.myopts.get("--with-bdeps", "n") == "n" and \
1289 (mytype == "binary" or mybigkey[3] == "nomerge"):
1290 edepend["DEPEND"] = ""
1292 """ We have retrieve the dependency information, now we need to recursively
1293 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
1295 mp = tuple(mybigkey)
1298 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
1299 myuse=myuse, priority=DepPriority(buildtime=True),
1302 """RDEPEND is soft by definition. However, in order to ensure
1303 correct merge order, we make it a hard dependency. Otherwise, a
1304 build time dependency might not be usable due to it's run time
1305 dependencies not being installed yet.
1307 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
1308 myuse=myuse, priority=DepPriority(runtime=True),
1311 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
1312 # Post Depend -- Add to the list without a parent, as it depends
1313 # on a package being present AND must be built after that package.
1314 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
1315 myuse=myuse, priority=DepPriority(runtime_post=True),
1318 except ValueError, e:
1320 portage.writemsg("\n\n!!! An atom in the dependencies " + \
1321 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
1323 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
1324 portage.writemsg("\n", noiselevel=-1)
1325 if mytype == "binary":
1327 "!!! This binary package cannot be installed: '%s'\n" % \
1328 mykey, noiselevel=-1)
1329 elif mytype == "ebuild":
1330 myebuild, mylocation = portdb.findname2(mykey)
1331 portage.writemsg("!!! This ebuild cannot be installed: " + \
1332 "'%s'\n" % myebuild, noiselevel=-1)
1333 portage.writemsg("!!! Please notify the package maintainer " + \
1334 "that atoms must be fully-qualified.\n", noiselevel=-1)
1338 def select_files(self,myfiles):
1339 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
1341 myroot = self.target_root
1342 portdb = self.trees[myroot]["porttree"].dbapi
1343 bindb = self.trees[myroot]["bintree"].dbapi
1344 pkgsettings = self.pkgsettings[myroot]
1346 def visible(mylist):
1347 matches = portdb.gvisible(portdb.visible(mylist))
1348 return [x for x in mylist \
1349 if x in matches or not portdb.cpv_exists(x)]
1351 ext = os.path.splitext(x)[1]
1353 if not os.path.exists(x):
1355 os.path.join(pkgsettings["PKGDIR"], "All", x)):
1356 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
1357 elif os.path.exists(
1358 os.path.join(pkgsettings["PKGDIR"], x)):
1359 x = os.path.join(pkgsettings["PKGDIR"], x)
1361 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
1362 print "!!! Please ensure the tbz2 exists as specified.\n"
1364 mytbz2=portage.xpak.tbz2(x)
1365 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
1366 if os.path.realpath(x) != \
1367 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1368 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1370 if not self.create(["binary", myroot, mykey],
1371 None, "--onlydeps" not in self.myopts):
1372 return (0,myfavorites)
1373 elif not "--oneshot" in self.myopts:
1374 myfavorites.append(mykey)
1375 elif ext==".ebuild":
1376 x = os.path.realpath(x)
1377 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1378 ebuild_path = portdb.findname(mykey)
1380 if os.path.realpath(ebuild_path) != x:
1381 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1383 if mykey not in portdb.xmatch(
1384 "match-visible", portage.dep_getkey(mykey)):
1385 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1386 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1387 print colorize("BAD", "*** page for details.")
1388 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1391 raise portage.exception.PackageNotFound(
1392 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1393 if not self.create(["ebuild", myroot, mykey],
1394 None, "--onlydeps" not in self.myopts):
1395 return (0,myfavorites)
1396 elif not "--oneshot" in self.myopts:
1397 myfavorites.append(mykey)
1399 if not is_valid_package_atom(x):
1400 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1402 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1403 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1407 if "--usepkg" in self.myopts:
1408 mykey = portage.dep_expand(x, mydb=bindb,
1409 settings=pkgsettings)
1410 if (mykey and not mykey.startswith("null/")) or \
1411 "--usepkgonly" in self.myopts:
1412 arg_atoms.append((x, mykey))
1415 mykey = portage.dep_expand(x,
1416 mydb=portdb, settings=pkgsettings)
1417 arg_atoms.append((x, mykey))
1418 except ValueError, errpkgs:
1419 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1420 print "!!! one of the following fully-qualified ebuild names instead:\n"
1421 for i in errpkgs[0]:
1422 print " " + green(i)
1426 if "--update" in self.myopts:
1427 """Make sure all installed slots are updated when possible. Do this
1428 with --emptytree also, to ensure that all slots are remerged."""
1429 vardb = self.trees[self.target_root]["vartree"].dbapi
1431 for myarg, myatom in arg_atoms:
1432 greedy_atoms.append((myarg, myatom))
1434 for cpv in vardb.match(myatom):
1435 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1438 if "--usepkg" in self.myopts:
1439 mymatches = bindb.match(myatom)
1440 if "--usepkgonly" not in self.myopts:
1441 mymatches = visible(mymatches)
1442 best_pkg = portage.best(mymatches)
1444 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1445 best_pkgs.append(("binary", best_pkg, best_slot))
1446 if "--usepkgonly" not in self.myopts:
1447 best_pkg = portage.best(portdb.match(myatom))
1449 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1450 best_pkgs.append(("ebuild", best_pkg, best_slot))
1452 best_pkg = portage.best([x[1] for x in best_pkgs])
1453 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1454 best_slot = best_pkgs[0][2]
1455 myslots.add(best_slot)
1456 if len(myslots) > 1:
1457 for myslot in myslots:
1458 myslot_atom = "%s:%s" % \
1459 (portage.dep_getkey(myatom), myslot)
1461 if "--usepkgonly" not in self.myopts and \
1462 self.trees[self.target_root][
1463 "porttree"].dbapi.match(myslot_atom):
1465 elif "--usepkg" in self.myopts:
1466 mymatches = bindb.match(myslot_atom)
1467 if "--usepkgonly" not in self.myopts:
1468 mymatches = visible(mymatches)
1472 greedy_atoms.append((myarg, myslot_atom))
1473 arg_atoms = greedy_atoms
1475 """ These are used inside self.create() in order to ensure packages
1476 that happen to match arguments are not incorrectly marked as nomerge."""
1477 for myarg, myatom in arg_atoms:
1478 self._args_atoms.setdefault(
1479 portage.dep_getkey(myatom), []).append(myatom)
1480 for myarg, myatom in arg_atoms:
1482 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1483 except portage.exception.MissingSignature, e:
1484 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1485 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1486 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1487 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1488 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1490 except portage.exception.InvalidSignature, e:
1491 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1492 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1493 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1494 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1495 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1497 except SystemExit, e:
1498 raise # Needed else can't exit
1499 except Exception, e:
1500 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1501 print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
1505 return (0,myfavorites)
1506 elif not "--oneshot" in self.myopts:
1507 mykey = portage.dep_getkey(myatom)
1508 if mykey not in myfavorites:
1509 myfavorites.append(mykey)
1512 if "--usepkgonly" in self.myopts:
1513 for xs in self.digraph.all_nodes():
1514 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1518 print "Missing binary for:",xs[2]
1520 if not self.validate_blockers():
1521 return False, myfavorites
1523 # We're true here unless we are missing binaries.
1524 return (not missing,myfavorites)
1526 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1527 myuse=None, raise_on_missing=False, priority=DepPriority(),
1528 rev_deps=False, parent_arg=None):
1529 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1530 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1531 myparent = the node whose depstring is being passed in
1532 arg = package was specified on the command line, merge even if it's already installed
1533 myuse = USE flags at present
1534 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1535 else continue trying.
1536 return 1 on success, 0 for failure
1539 portdb = self.trees[myroot]["porttree"].dbapi
1540 bindb = self.trees[myroot]["bintree"].dbapi
1541 vardb = self.trees[myroot]["vartree"].dbapi
1542 pkgsettings = self.pkgsettings[myroot]
1544 p_type, p_root, p_key, p_status = myparent
1546 if "--debug" in self.myopts:
1548 print "Parent: ",myparent
1549 print "Depstring:",depstring
1551 print "Reverse:", rev_deps
1552 print "Priority:", priority
1554 #processing dependencies
1555 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1556 dependencies are satisfiable. """
1558 mymerge = [depstring]
1559 pprovided = pkgsettings.pprovideddict.get(
1560 portage.dep_getkey(depstring))
1561 if pprovided and portage.match_from_list(depstring, pprovided):
1565 if myparent and p_status == "nomerge":
1566 portage.dep._dep_check_strict = False
1567 mycheck = portage.dep_check(depstring, None,
1568 pkgsettings, myuse=myuse,
1569 use_binaries=("--usepkgonly" in self.myopts),
1570 myroot=myroot, trees=self.trees)
1572 portage.dep._dep_check_strict = True
1576 show_invalid_depstring_notice(
1577 myparent, depstring, mycheck[1])
1579 sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
1581 mymerge = mycheck[1]
1583 if not mymerge and arg:
1584 # A provided package has been specified on the command line. The
1585 # package will not be merged and a warning will be displayed.
1586 cp = portage.dep_getkey(depstring)
1587 if cp in self._args_atoms and depstring in self._args_atoms[cp]:
1588 self._pprovided_args.append((arg, depstring))
1591 # The parent is added after it's own dep_check call so that it
1592 # isn't allowed to satisfy a direct bootstrap dependency on itself
1593 # via an old-style virtual. This isn't a problem with new-style
1594 # virtuals, which are preferenced in dep_zapdeps by looking only at
1595 # the depstring, vdb, and available packages.
1597 p_type, p_root, p_key, p_status = myparent
1598 if p_status == "merge":
1599 # Update old-style virtuals if this package provides any.
1600 # These are needed for dep_virtual calls inside dep_check.
1601 p_db = self.trees[p_root][self.pkg_tree_map[p_type]].dbapi
1603 self.pkgsettings[p_root].setinst(p_key, p_db)
1604 except portage.exception.InvalidDependString, e:
1605 provide = p_db.aux_get(p_key, ["PROVIDE"])[0]
1606 show_invalid_depstring_notice(myparent, provide, str(e))
1610 if "--debug" in self.myopts:
1611 print "Candidates:",mymerge
1615 selected_pkg = ["blocks", myroot, x[1:], None]
1617 #We are not processing a blocker but a normal dependency
1619 """In some cases, dep_check will return deps that shouldn't
1620 be proccessed any further, so they are identified and
1622 if "empty" not in self.myparams and \
1623 "deep" not in self.myparams and \
1624 not ("--update" in self.myopts and parent_arg) and \
1628 # List of acceptable packages, ordered by type preference.
1629 matched_packages = []
1630 myeb_matches = portdb.xmatch("match-visible", x)
1632 if "--usepkgonly" not in self.myopts:
1633 myeb = portage.best(myeb_matches)
1636 if "--usepkg" in self.myopts:
1637 # The next line assumes the binarytree has been populated.
1638 # XXX: Need to work out how we use the binary tree with roots.
1639 myeb_pkg_matches = bindb.match(x)
1640 if "--usepkgonly" not in self.myopts:
1641 # Remove any binary package entries that are masked in the portage tree (#55871)
1642 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1643 if pkg in myeb_matches or \
1644 not portdb.cpv_exists(pkg)]
1645 if myeb_pkg_matches:
1646 myeb_pkg = portage.best(myeb_pkg_matches)
1649 ("--newuse" in self.myopts or \
1650 "--reinstall" in self.myopts):
1651 iuses = set(filter_iuse_defaults(
1652 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1653 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1655 if "--usepkgonly" not in self.myopts and myeb:
1658 pkgsettings.setcpv(myeb, mydb=mydb)
1660 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1661 now_use = pkgsettings["USE"].split()
1662 forced_flags = set()
1663 forced_flags.update(pkgsettings.useforce)
1664 forced_flags.update(pkgsettings.usemask)
1666 if "--usepkgonly" not in self.myopts and myeb:
1667 cur_iuse = set(filter_iuse_defaults(
1668 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1669 if self._reinstall_for_flags(
1670 forced_flags, old_use, iuses, now_use, cur_iuse):
1674 self.trees[myroot]["bintree"].dbapi.aux_get(
1675 myeb_pkg, ["USE"])[0].split()
1676 matched_packages.append(
1677 ["binary", myroot, myeb_pkg, binpkguseflags])
1679 if "--usepkgonly" not in self.myopts and myeb_matches:
1680 matched_packages.append(
1681 ["ebuild", myroot, myeb, None])
1683 if not matched_packages and \
1684 not (arg and "selective" not in self.myparams):
1685 """Fall back to the installed package database. This is a
1686 last resort because the metadata tends to diverge from that
1687 of the ebuild in the tree."""
1688 myeb_inst_matches = vardb.match(x)
1689 if "--usepkgonly" not in self.myopts:
1690 """ TODO: Improve masking check for installed and
1691 binary packages. bug #149816"""
1692 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1693 if not portdb.cpv_exists(pkg)]
1695 if myeb_inst_matches:
1696 myeb_inst = portage.best(myeb_inst_matches)
1698 binpkguseflags = vardb.aux_get(
1699 myeb_inst, ["USE"])[0].split()
1700 matched_packages.append(
1701 ["installed", myroot, myeb_inst, binpkguseflags])
1703 if not matched_packages:
1704 if raise_on_missing:
1711 xfrom = '(dependency required by '+ \
1712 green('"%s"' % myparent[2]) + \
1713 red(' [%s]' % myparent[0]) + ')'
1714 alleb = portdb.xmatch("match-all", x)
1716 if "--usepkgonly" not in self.myopts:
1717 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1718 print "!!! One of the following masked packages is required to complete your request:"
1722 mreasons = portage.getmaskingstatus(p,
1723 settings=pkgsettings, portdb=portdb)
1724 print "- "+p+" (masked by: "+", ".join(mreasons)+")"
1725 if "package.mask" in mreasons:
1726 comment, filename = \
1727 portage.getmaskingreason(p,
1728 settings=pkgsettings, portdb=portdb,
1729 return_location=True)
1730 if comment and comment != oldcomment:
1733 oldcomment = comment
1735 licenses = portdb.aux_get(p, ["LICENSE"])[0]
1737 # Corruption will have been reported above.
1741 pkgsettings.setcpv(p, mydb=portdb)
1742 uselist = pkgsettings.get("USE", "").split()
1743 missing_licenses = []
1745 missing_licenses = \
1746 pkgsettings.getMissingLicenses(
1747 licenses, p, uselist)
1748 except portage.exception.InvalidDependString:
1749 # This will have already been reported
1750 # above via mreasons.
1752 for l in missing_licenses:
1753 l_path = portdb.findLicensePath(l)
1754 if l in shown_licenses:
1756 msg = ("A copy of the '%s' license" + \
1757 " is located at '%s'.") % (l, l_path)
1760 shown_licenses.append(l)
1762 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1763 print "refer to the Gentoo Handbook."
1765 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1766 print "!!! Either add a suitable binary package or compile from an ebuild."
1768 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1774 if "--debug" in self.myopts:
1775 for pkg in matched_packages:
1776 print (pkg[0] + ":").rjust(10), pkg[2]
1778 if len(matched_packages) > 1:
1779 bestmatch = portage.best(
1780 [pkg[2] for pkg in matched_packages])
1781 matched_packages = [pkg for pkg in matched_packages \
1782 if pkg[2] == bestmatch]
1784 # ordered by type preference ("ebuild" type is the last resort)
1785 selected_pkg = matched_packages[0]
1786 pkgtype, myroot, mycpv, myuse = selected_pkg
1787 mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
1788 slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
1789 mydbapi.aux_get(mycpv, ["SLOT"])[0])
1790 existing_node = self._slot_node_map[myroot].get(
1793 e_type, myroot, e_cpv, e_status = existing_node
1794 if portage.match_from_list(x, [e_cpv]):
1795 # The existing node can be reused.
1796 selected_pkg = [e_type, myroot, e_cpv,
1797 self.useFlags[myroot][e_cpv]]
1800 #we are a dependency, so we want to be unconditionally added
1801 mypriority = priority.copy()
1803 mypriority.satisfied = True
1804 if not self.create(selected_pkg[0:3], myparent,
1805 myuse=selected_pkg[-1], priority=mypriority,
1806 rev_dep=rev_deps, arg=arg):
1809 #if mysource is not set, then we are a command-line dependency and should not be added
1810 #if --onlydeps is specified.
1811 if not self.create(selected_pkg[0:3], myparent,
1812 addme=("--onlydeps" not in self.myopts),
1813 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1816 if "--debug" in self.myopts:
1817 print "Exiting...",myparent
1820 def validate_blockers(self):
1821 """Remove any blockers from the digraph that do not match any of the
1822 packages within the graph. If necessary, create hard deps to ensure
1823 correct merge order such that mutually blocking packages are never
1824 installed simultaneously."""
1826 if "--buildpkgonly" in self.myopts or \
1827 "--nodeps" in self.myopts:
1831 for myroot in self.trees:
1833 modified_slots[myroot] = myslots
1834 final_db = self.mydbapi[myroot]
1835 slot_node_map = self._slot_node_map[myroot]
1836 for slot_atom, mynode in slot_node_map.iteritems():
1837 mytype, myroot, mycpv, mystatus = mynode
1838 if mystatus == "merge":
1839 myslots[slot_atom] = mycpv
1841 #if "deep" in self.myparams:
1843 # Pull in blockers from all installed packages that haven't already
1844 # been pulled into the depgraph. This is not enabled by default
1845 # due to the performance penalty that is incurred by all the
1846 # additional dep_check calls that are required.
1848 # Optimization hack for dep_check calls that minimizes the
1849 # available matches by replacing the portdb with a fakedbapi
1851 class FakePortageTree(object):
1852 def __init__(self, mydb):
1854 dep_check_trees = {}
1855 for myroot in self.trees:
1856 dep_check_trees[myroot] = self.trees[myroot].copy()
1857 dep_check_trees[myroot]["porttree"] = \
1858 FakePortageTree(self.mydbapi[myroot])
1860 dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
1861 for myroot in self.trees:
1862 pkg_node_map = self.pkg_node_map[myroot]
1863 vardb = self.trees[myroot]["vartree"].dbapi
1864 portdb = self.trees[myroot]["porttree"].dbapi
1865 pkgsettings = self.pkgsettings[myroot]
1866 final_db = self.mydbapi[myroot]
1867 cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
1868 blocker_cache = BlockerCache(myroot, vardb)
1869 for pkg in cpv_all_installed:
1870 blocker_atoms = None
1871 matching_node = pkg_node_map.get(pkg, None)
1872 if matching_node and \
1873 matching_node[3] == "nomerge":
1875 # If this node has any blockers, create a "nomerge"
1876 # node for it so that they can be enforced.
1877 self.spinner.update()
1878 blocker_data = blocker_cache.get(pkg)
1880 blocker_atoms = blocker_data.atoms
1882 dep_vals = vardb.aux_get(pkg, dep_keys)
1883 myuse = vardb.aux_get(pkg, ["USE"])[0].split()
1884 depstr = " ".join(dep_vals)
1885 # It is crucial to pass in final_db here in order to
1886 # optimize dep_check calls by eliminating atoms via
1887 # dep_wordreduce and dep_eval calls.
1889 portage.dep._dep_check_strict = False
1891 success, atoms = portage.dep_check(depstr,
1892 final_db, pkgsettings, myuse=myuse,
1893 trees=dep_check_trees, myroot=myroot)
1894 except Exception, e:
1895 if isinstance(e, SystemExit):
1897 # This is helpful, for example, if a ValueError
1898 # is thrown from cpv_expand due to multiple
1899 # matches (this can happen if an atom lacks a
1901 show_invalid_depstring_notice(
1902 ("installed", myroot, pkg, "nomerge"),
1907 portage.dep._dep_check_strict = True
1909 slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
1910 vardb.aux_get(pkg, ["SLOT"])[0])
1911 if slot_atom in modified_slots[myroot]:
1912 # This package is being replaced anyway, so
1913 # ignore invalid dependencies so as not to
1914 # annoy the user too much (otherwise they'd be
1915 # forced to manually unmerge it first).
1917 show_invalid_depstring_notice(
1918 ("installed", myroot, pkg, "nomerge"),
1921 blocker_atoms = [myatom for myatom in atoms \
1922 if myatom.startswith("!")]
1923 counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
1924 blocker_cache[pkg] = \
1925 blocker_cache.BlockerData(counter, blocker_atoms)
1927 # Don't store this parent in pkg_node_map, because it's
1928 # not needed there and it might overwrite a "merge"
1929 # node with the same cpv.
1930 myparent = ("installed", myroot, pkg, "nomerge")
1931 for myatom in blocker_atoms:
1932 blocker = ("blocks", myroot, myatom[1:])
1934 self.blocker_parents.get(blocker, None)
1937 self.blocker_parents[blocker] = myparents
1938 myparents.add(myparent)
1939 blocker_cache.flush()
1942 for blocker in self.blocker_parents.keys():
1943 mytype, myroot, mydep = blocker
1944 initial_db = self.trees[myroot]["vartree"].dbapi
1945 final_db = self.mydbapi[myroot]
1946 blocked_initial = initial_db.match(mydep)
1947 blocked_final = final_db.match(mydep)
1948 if not blocked_initial and not blocked_final:
1949 del self.blocker_parents[blocker]
1951 blocked_slots_initial = {}
1952 blocked_slots_final = {}
1953 for cpv in blocked_initial:
1954 blocked_slots_initial[cpv] = \
1955 "%s:%s" % (portage.dep_getkey(cpv),
1956 initial_db.aux_get(cpv, ["SLOT"])[0])
1957 for cpv in blocked_final:
1958 blocked_slots_final[cpv] = \
1959 "%s:%s" % (portage.dep_getkey(cpv),
1960 final_db.aux_get(cpv, ["SLOT"])[0])
1961 for parent in list(self.blocker_parents[blocker]):
1962 ptype, proot, pcpv, pstatus = parent
1963 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1964 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1965 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1966 parent_static = pslot_atom not in modified_slots[proot]
1967 unresolved_blocks = False
1968 depends_on_order = set()
1969 for cpv in blocked_initial:
1970 slot_atom = blocked_slots_initial[cpv]
1971 if slot_atom == pslot_atom:
1972 # TODO: Support blocks within slots in cases where it
1973 # might make sense. For example, a new version might
1974 # require that the old version be uninstalled at build
1977 if parent_static and \
1978 slot_atom not in modified_slots[myroot]:
1979 # This blocker will be handled the next time that a
1980 # merge of either package is triggered.
1982 if pstatus == "merge" and \
1983 slot_atom in modified_slots[myroot]:
1984 replacement = final_db.match(slot_atom)
1986 if not portage.match_from_list(mydep, replacement):
1987 # Apparently a replacement may be able to
1988 # invalidate this block.
1989 replacement_node = \
1990 self.pkg_node_map[proot][replacement[0]]
1991 depends_on_order.add((replacement_node, parent))
1993 # None of the above blocker resolutions techniques apply,
1994 # so apparently this one is unresolvable.
1995 unresolved_blocks = True
1996 for cpv in blocked_final:
1997 slot_atom = blocked_slots_final[cpv]
1998 if slot_atom == pslot_atom:
1999 # TODO: Support blocks within slots.
2001 if parent_static and \
2002 slot_atom not in modified_slots[myroot]:
2003 # This blocker will be handled the next time that a
2004 # merge of either package is triggered.
2006 if not parent_static and pstatus == "nomerge" and \
2007 slot_atom in modified_slots[myroot]:
2008 replacement = final_db.match(pslot_atom)
2010 replacement_node = \
2011 self.pkg_node_map[proot][replacement[0]]
2012 if replacement_node not in \
2013 self.blocker_parents[blocker]:
2014 # Apparently a replacement may be able to
2015 # invalidate this block.
2016 blocked_node = self.pkg_node_map[proot][cpv]
2017 depends_on_order.add(
2018 (replacement_node, blocked_node))
2020 # None of the above blocker resolutions techniques apply,
2021 # so apparently this one is unresolvable.
2022 unresolved_blocks = True
2023 if not unresolved_blocks and depends_on_order:
2024 for node, pnode in depends_on_order:
2025 # Enforce correct merge order with a hard dep.
2026 self.digraph.addnode(node, pnode,
2027 priority=DepPriority(buildtime=True))
2028 # Count references to this blocker so that it can be
2029 # invalidated after nodes referencing it have been
2031 self.blocker_digraph.addnode(node, blocker)
2032 if not unresolved_blocks and not depends_on_order:
2033 self.blocker_parents[blocker].remove(parent)
2034 if unresolved_blocks:
2035 self._unresolved_blocker_parents.setdefault(
2036 blocker, set()).add(parent)
2037 if not self.blocker_parents[blocker]:
2038 del self.blocker_parents[blocker]
2039 # Validate blockers that depend on merge order.
2040 if not self.blocker_digraph.empty():
2042 if self._slot_collision_info:
2043 # The user is only notified of a slot collision if there are no
2044 # unresolvable blocks.
2045 for x in self.altlist():
2046 if x[0] == "blocks":
2048 self._show_slot_collision_notice(self._slot_collision_info[0])
2049 if not self._accept_collisions():
2053 def _accept_collisions(self):
2055 for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
2056 if x in self.myopts:
2061 def _merge_order_bias(self, mygraph):
2062 """Order nodes from highest to lowest overall reference count for
2063 optimal leaf node selection."""
2065 for node in mygraph.order:
2066 node_info[node] = len(mygraph.parent_nodes(node))
2067 def cmp_merge_preference(node1, node2):
2068 return node_info[node2] - node_info[node1]
2069 mygraph.order.sort(cmp_merge_preference)
2071 def altlist(self, reversed=False):
2072 if reversed in self._altlist_cache:
2073 return self._altlist_cache[reversed][:]
2075 retlist = self.altlist()
2077 self._altlist_cache[reversed] = retlist[:]
2079 mygraph=self.digraph.copy()
2080 for node in mygraph.order[:]:
2081 if node[-1] == "nomerge":
2082 mygraph.remove(node)
2083 self._merge_order_bias(mygraph)
2084 myblockers = self.blocker_digraph.copy()
2086 circular_blocks = False
2090 get_nodes = mygraph.root_nodes
2092 get_nodes = mygraph.leaf_nodes
2093 for cpv, node in self.pkg_node_map["/"].iteritems():
2094 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
2095 asap_nodes.append(node)
2097 ignore_priority_range = [None]
2098 ignore_priority_range.extend(
2099 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2100 tree_mode = "--tree" in self.myopts
2101 while not mygraph.empty():
2102 ignore_priority = None
2105 """ASAP nodes are merged before their soft deps."""
2106 for node in asap_nodes:
2107 if not mygraph.contains(node):
2108 asap_nodes.remove(node)
2110 if not mygraph.child_nodes(node,
2111 ignore_priority=DepPriority.SOFT):
2113 asap_nodes.remove(node)
2116 for ignore_priority in ignore_priority_range:
2117 nodes = get_nodes(ignore_priority=ignore_priority)
2120 selected_nodes = None
2122 if ignore_priority <= DepPriority.SOFT:
2123 if ignore_priority is None and not tree_mode:
2124 # Greedily pop all of these nodes since no relationship
2125 # has been ignored. This optimization destroys --tree
2126 # output, so it's disabled in reversed mode.
2127 selected_nodes = nodes
2129 # For optimal merge order:
2130 # * Only pop one node.
2131 # * Removing a root node (node without a parent)
2132 # will not produce a leaf node, so avoid it.
2134 if mygraph.parent_nodes(node):
2135 # found a non-root node
2136 selected_nodes = [node]
2138 if not selected_nodes:
2139 # settle for a root node
2140 selected_nodes = [nodes[0]]
2142 """Recursively gather a group of nodes that RDEPEND on
2143 eachother. This ensures that they are merged as a group
2144 and get their RDEPENDs satisfied as soon as possible."""
2145 def gather_deps(ignore_priority,
2146 mergeable_nodes, selected_nodes, node):
2147 if node in selected_nodes:
2149 if node not in mergeable_nodes:
2151 selected_nodes.add(node)
2152 for child in mygraph.child_nodes(node,
2153 ignore_priority=ignore_priority):
2154 if not gather_deps(ignore_priority,
2155 mergeable_nodes, selected_nodes, child):
2158 # If necessary, resample the leaf nodes so that they
2159 # include all nodes whose hard deps are satisfied.
2160 if ignore_priority < DepPriority.MEDIUM:
2161 nodes = get_nodes(ignore_priority=DepPriority.MEDIUM)
2162 mergeable_nodes = set(nodes)
2163 for ignore_priority in xrange(DepPriority.SOFT,
2164 DepPriority.MEDIUM_SOFT + 1):
2166 selected_nodes = set()
2167 if gather_deps(ignore_priority,
2168 mergeable_nodes, selected_nodes, node):
2171 selected_nodes = None
2175 if selected_nodes and ignore_priority > DepPriority.SOFT:
2176 # Try to merge ignored medium deps as soon as possible.
2177 for node in selected_nodes:
2178 children = set(mygraph.child_nodes(node))
2179 soft = children.difference(
2180 mygraph.child_nodes(node,
2181 ignore_priority=DepPriority.SOFT))
2182 medium_soft = children.difference(
2183 mygraph.child_nodes(node,
2184 ignore_priority=DepPriority.MEDIUM_SOFT))
2185 medium_soft.difference_update(soft)
2186 for child in medium_soft:
2187 if child in selected_nodes:
2189 if child in asap_nodes:
2191 # TODO: Try harder to make these nodes get
2192 # merged absolutely as soon as possible.
2193 asap_nodes.append(child)
2195 if not selected_nodes:
2196 if not myblockers.is_empty():
2197 """A blocker couldn't be circumnavigated while keeping all
2198 dependencies satisfied. The user will have to resolve this
2199 manually. This is a panic condition and thus the order
2200 doesn't really matter, so just pop a random node in order
2201 to avoid a circular dependency panic if possible."""
2202 if not circular_blocks:
2203 circular_blocks = True
2204 blocker_deps = myblockers.leaf_nodes()
2206 # Some of these nodes might have already been selected
2207 # by the normal node selection process after the
2208 # circular_blocks flag has been set. Therefore, we
2209 # have to verify that they're still in the graph so
2210 # that they're not selected more than once.
2211 node = blocker_deps.pop()
2212 if mygraph.contains(node):
2213 selected_nodes = [node]
2216 if not selected_nodes:
2217 # No leaf nodes are available, so we have a circular
2218 # dependency panic situation. Reduce the noise level to a
2219 # minimum via repeated elimination of root nodes since they
2220 # have no parents and thus can not be part of a cycle.
2222 root_nodes = mygraph.root_nodes(
2223 ignore_priority=DepPriority.SOFT)
2226 for node in root_nodes:
2227 mygraph.remove(node)
2228 # Display the USE flags that are enabled on nodes that are part
2229 # of dependency cycles in case that helps the user decide to
2230 # disable some of them.
2232 tempgraph = mygraph.copy()
2233 while not tempgraph.empty():
2234 nodes = tempgraph.leaf_nodes()
2236 node = tempgraph.order[0]
2239 display_order.append(list(node))
2240 tempgraph.remove(node)
2241 display_order.reverse()
2242 self.myopts.pop("--quiet", None)
2243 self.myopts.pop("--verbose", None)
2244 self.myopts["--tree"] = True
2245 self.display(display_order)
2246 print "!!! Error: circular dependencies:"
2248 mygraph.debug_print()
2250 print "!!! Note that circular dependencies can often be avoided by temporarily"
2251 print "!!! disabling USE flags that trigger optional dependencies."
2254 for node in selected_nodes:
2255 retlist.append(list(node))
2256 mygraph.remove(node)
2257 if not reversed and not circular_blocks and myblockers.contains(node):
2258 """This node may have invalidated one or more blockers."""
2259 myblockers.remove(node)
2260 for blocker in myblockers.root_nodes():
2261 if not myblockers.child_nodes(blocker):
2262 myblockers.remove(blocker)
2264 self._unresolved_blocker_parents.get(blocker)
2266 self.blocker_parents[blocker] = unresolved
2268 del self.blocker_parents[blocker]
2271 """Blocker validation does not work with reverse mode,
2272 so self.altlist() should first be called with reverse disabled
2273 so that blockers are properly validated."""
2274 self.blocker_digraph = myblockers
2276 """ Add any unresolved blocks so that they can be displayed."""
2277 for blocker in self.blocker_parents:
2278 retlist.append(list(blocker))
2279 self._altlist_cache[reversed] = retlist[:]
2282 def xcreate(self,mode="system"):
2283 vardb = self.trees[self.target_root]["vartree"].dbapi
2284 portdb = self.trees[self.target_root]["porttree"].dbapi
2285 bindb = self.trees[self.target_root]["bintree"].dbapi
2286 def visible(mylist):
2287 matches = portdb.gvisible(portdb.visible(mylist))
2288 return [x for x in mylist \
2289 if x in matches or not portdb.cpv_exists(x)]
2290 def create_cp_dict(atom_list):
2292 for atom in atom_list:
2293 cp_dict.setdefault(portage.dep_getkey(atom), []).append(atom)
2295 world_problems = False
2297 mylist = getlist(self.settings, "system")
2298 self._sets["system"] = create_cp_dict(mylist)
2299 self._sets_nodes["system"] = set()
2302 worldlist = getlist(self.settings, "world")
2303 self._sets["world"] = create_cp_dict(worldlist)
2304 self._sets_nodes["world"] = set()
2305 mylist = getlist(self.settings, "system")
2306 self._sets["system"] = create_cp_dict(mylist)
2307 self._sets_nodes["system"] = set()
2308 worlddict=genericdict(worldlist)
2311 if not portage.isvalidatom(x):
2312 world_problems = True
2314 elif not vardb.match(x):
2315 world_problems = True
2317 if "--usepkgonly" not in self.myopts and \
2320 elif "--usepkg" in self.myopts:
2321 mymatches = bindb.match(x)
2322 if "--usepkgonly" not in self.myopts:
2323 mymatches = visible(mymatches)
2332 mykey = portage.dep_getkey(atom)
2334 newlist.append(atom)
2335 """Make sure all installed slots are updated when possible.
2336 Do this with --emptytree also, to ensure that all slots are
2339 for cpv in vardb.match(mykey):
2340 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
2343 if "--usepkg" in self.myopts:
2344 mymatches = bindb.match(atom)
2345 if "--usepkgonly" not in self.myopts:
2346 mymatches = visible(mymatches)
2347 best_pkg = portage.best(mymatches)
2349 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
2350 best_pkgs.append(("binary", best_pkg, best_slot))
2351 if "--usepkgonly" not in self.myopts:
2352 best_pkg = portage.best(portdb.match(atom))
2354 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
2355 best_pkgs.append(("ebuild", best_pkg, best_slot))
2357 best_pkg = portage.best([x[1] for x in best_pkgs])
2358 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
2359 best_slot = best_pkgs[0][2]
2360 myslots.add(best_slot)
2361 if len(myslots) > 1:
2362 for myslot in myslots:
2363 myslot_atom = "%s:%s" % (mykey, myslot)
2365 if "--usepkgonly" not in self.myopts and \
2366 self.trees[self.target_root][
2367 "porttree"].dbapi.match(myslot_atom):
2369 elif "--usepkg" in self.myopts:
2370 mymatches = bindb.match(myslot_atom)
2371 if "--usepkgonly" not in self.myopts:
2372 mymatches = visible(mymatches)
2376 newlist.append(myslot_atom)
2379 for myatom in mylist:
2380 self._args_atoms.setdefault(
2381 portage.dep_getkey(myatom), []).append(myatom)
2384 for mydep in mylist:
2386 if not self.select_dep(
2387 self.target_root, mydep, raise_on_missing=True, arg=mydep):
2388 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
2391 missing_atoms.append(mydep)
2393 if not self.validate_blockers():
2397 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
2398 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
2401 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
2402 " Ebuilds for the following packages are either all"
2403 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
2404 print >> sys.stderr, " ".join(missing_atoms) + "\n"
2408 def _find_atom_for_pkg(self, pkg_set, cpv, metadata):
2409 """Return the best match for a given package from the arguments, or
2410 None if there are no matches. This matches virtual arguments against
2411 the PROVIDE metadata. This can raise an InvalidDependString exception
2412 if an error occurs while parsing PROVIDE."""
2413 cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
2414 cp = portage.dep_getkey(cpv)
2415 atoms = pkg_set.get(cp)
2417 best_match = portage.best_match_to_list(cpv_slot, atoms)
2420 provides = portage.flatten(portage.dep.use_reduce(
2421 portage.dep.paren_reduce(metadata["PROVIDE"]),
2422 uselist=metadata["USE"].split()))
2423 for provide in provides:
2424 provided_cp = portage.dep_getkey(provide)
2425 atoms = pkg_set.get(provided_cp)
2427 transformed_atoms = [atom.replace(provided_cp, cp) for atom in atoms]
2428 best_match = portage.best_match_to_list(cpv_slot, transformed_atoms)
2430 return atoms[transformed_atoms.index(best_match)]
2433 def display(self,mylist,verbosity=None):
2434 if verbosity is None:
2435 verbosity = ("--quiet" in self.myopts and 1 or \
2436 "--verbose" in self.myopts and 3 or 2)
2441 counters = PackageCounters()
2443 if verbosity == 1 and "--verbose" not in self.myopts:
2444 def create_use_string(*args):
2447 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
2449 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
2450 alphabetical=("--alphabetical" in self.myopts)):
2458 cur_iuse = set(cur_iuse)
2459 enabled_flags = cur_iuse.intersection(cur_use)
2460 removed_iuse = set(old_iuse).difference(cur_iuse)
2461 any_iuse = cur_iuse.union(old_iuse)
2462 any_iuse = list(any_iuse)
2464 for flag in any_iuse:
2467 if flag in enabled_flags:
2469 if is_new or flag in old_use and all_flags:
2470 flag_str = red(flag)
2471 elif flag not in old_iuse:
2472 flag_str = yellow(flag) + "%*"
2473 elif flag not in old_use:
2474 flag_str = green(flag) + "*"
2475 elif flag in removed_iuse:
2477 flag_str = yellow("-" + flag) + "%"
2480 flag_str = "(" + flag_str + ")"
2481 removed.append(flag_str)
2484 if is_new or flag in old_iuse and flag not in old_use and all_flags:
2485 flag_str = blue("-" + flag)
2486 elif flag not in old_iuse:
2487 flag_str = yellow("-" + flag)
2488 if flag not in iuse_forced:
2490 elif flag in old_use:
2491 flag_str = green("-" + flag) + "*"
2493 if flag in iuse_forced:
2494 flag_str = "(" + flag_str + ")"
2496 enabled.append(flag_str)
2498 disabled.append(flag_str)
2501 ret = " ".join(enabled)
2503 ret = " ".join(enabled + disabled + removed)
2505 ret = '%s="%s" ' % (name, ret)
2509 # FIXME: account for the possibility of different overlays in
2510 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
2511 overlays = self.settings["PORTDIR_OVERLAY"].split()
2512 overlays_real = [os.path.realpath(t) \
2513 for t in self.settings["PORTDIR_OVERLAY"].split()]
2517 mygraph = self._parent_child_digraph
2522 if "blocks" == x[0]:
2523 display_list.append((x, 0, True))
2525 graph_key = tuple(x)
2526 if "--tree" in self.myopts:
2527 depth = len(tree_nodes)
2528 while depth and graph_key not in \
2529 mygraph.child_nodes(tree_nodes[depth-1]):
2532 tree_nodes = tree_nodes[:depth]
2533 tree_nodes.append(graph_key)
2534 display_list.append((x, depth, True))
2535 shown_edges.add((graph_key, tree_nodes[depth-1]))
2537 traversed_nodes = set() # prevent endless circles
2538 traversed_nodes.add(graph_key)
2539 def add_parents(current_node, ordered):
2541 # Do not traverse to parents if this node is an
2542 # an argument or a direct member of a set that has
2543 # been specified as an argument (system or world).
2544 if current_node not in self._args_nodes:
2545 parent_nodes = mygraph.parent_nodes(current_node)
2547 child_nodes = set(mygraph.child_nodes(current_node))
2548 selected_parent = None
2549 # First, try to avoid a direct cycle.
2550 for node in parent_nodes:
2551 if node not in traversed_nodes and \
2552 node not in child_nodes:
2553 edge = (current_node, node)
2554 if edge in shown_edges:
2556 selected_parent = node
2558 if not selected_parent:
2559 # A direct cycle is unavoidable.
2560 for node in parent_nodes:
2561 if node not in traversed_nodes:
2562 edge = (current_node, node)
2563 if edge in shown_edges:
2565 selected_parent = node
2568 shown_edges.add((current_node, selected_parent))
2569 traversed_nodes.add(selected_parent)
2570 add_parents(selected_parent, False)
2571 display_list.append((list(current_node),
2572 len(tree_nodes), ordered))
2573 tree_nodes.append(current_node)
2575 add_parents(graph_key, True)
2577 display_list.append((x, depth, True))
2578 mylist = display_list
2580 last_merge_depth = 0
2581 for i in xrange(len(mylist)-1,-1,-1):
2582 graph_key, depth, ordered = mylist[i]
2583 if not ordered and depth == 0 and i > 0 \
2584 and graph_key == mylist[i-1][0] and \
2585 mylist[i-1][1] == 0:
2586 # An ordered node got a consecutive duplicate when the tree was
2590 if "blocks" == graph_key[0]:
2592 if ordered and graph_key[-1] != "nomerge":
2593 last_merge_depth = depth
2595 if depth >= last_merge_depth or \
2596 i < len(mylist) - 1 and \
2597 depth >= mylist[i+1][1]:
2600 from portage import flatten
2601 from portage.dep import use_reduce, paren_reduce
2602 display_overlays=False
2603 # files to fetch list - avoids counting a same file twice
2604 # in size display (verbose mode)
2607 for mylist_index in xrange(len(mylist)):
2608 x, depth, ordered = mylist[mylist_index]
2612 portdb = self.trees[myroot]["porttree"].dbapi
2613 bindb = self.trees[myroot]["bintree"].dbapi
2614 vardb = self.trees[myroot]["vartree"].dbapi
2615 vartree = self.trees[myroot]["vartree"]
2616 pkgsettings = self.pkgsettings[myroot]
2621 addl=""+red("B")+" "+fetch+" "
2623 counters.blocks += 1
2624 resolved = portage.key_expand(
2625 pkg_key, mydb=vardb, settings=pkgsettings)
2626 if "--columns" in self.myopts and "--quiet" in self.myopts:
2627 addl = addl + " " + red(resolved)
2629 addl = "[blocks " + addl + "] " + red(resolved)
2630 block_parents = self.blocker_parents[tuple(x)]
2631 block_parents = set([pnode[2] for pnode in block_parents])
2632 block_parents = ", ".join(block_parents)
2634 addl += bad(" (\"%s\" is blocking %s)") % \
2635 (pkg_key, block_parents)
2637 addl += bad(" (is blocking %s)") % block_parents
2638 blockers.append(addl)
2640 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
2642 pkg_merge = ordered and pkg_status != "nomerge"
2643 binary_package = True
2644 if "ebuild" == pkg_type:
2645 if "merge" == x[3] or \
2646 not vartree.dbapi.cpv_exists(pkg_key):
2647 """An ebuild "merge" node or a --onlydeps "nomerge"
2649 binary_package = False
2650 pkgsettings.setcpv(pkg_key, mydb=portdb)
2651 if pkg_key not in self.useFlags[myroot]:
2652 self.useFlags[myroot][pkg_key] = \
2653 pkgsettings["USE"].split()
2655 # An ebuild "nomerge" node, so USE come from the vardb.
2656 mydbapi = vartree.dbapi
2657 if pkg_key not in self.useFlags[myroot]:
2658 """If this is a --resume then the USE flags need to be
2659 fetched from the appropriate locations here."""
2660 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
2661 pkg_key, ["USE"])[0].split()
2664 restrict = flatten(use_reduce(paren_reduce(
2665 mydbapi.aux_get(pkg_key, ["RESTRICT"])[0]),
2666 uselist=self.useFlags[myroot][pkg_key]))
2667 except portage.exception.InvalidDependString, e:
2668 if pkg_status != "nomerge":
2669 restrict = mydbapi.aux_get(pkg_key, ["RESTRICT"])[0]
2670 show_invalid_depstring_notice(x, restrict, str(e))
2674 if "ebuild" == pkg_type and x[3] != "nomerge" and \
2675 "fetch" in restrict:
2678 counters.restrict_fetch += 1
2679 if portdb.fetch_check(
2680 pkg_key, self.useFlags[myroot][pkg_key]):
2683 counters.restrict_fetch_satisfied += 1
2685 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
2686 #param is used for -u, where you still *do* want to see when something is being upgraded.
2688 if vardb.cpv_exists(pkg_key):
2689 addl=" "+yellow("R")+fetch+" "
2690 if x[3] != "nomerge":
2692 counters.reinst += 1
2693 elif vardb.match(portage.dep_getkey(pkg_key)):
2694 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
2695 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
2696 portage.pkgsplit(x[2])[0])
2697 myinslotlist = [inst_pkg for inst_pkg in myoldlist
2698 if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
2700 myoldbest=portage.best(myinslotlist)
2702 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
2704 addl+=turquoise("U")+blue("D")
2706 counters.downgrades += 1
2709 addl+=turquoise("U")+" "
2711 counters.upgrades += 1
2713 # New slot, mark it new.
2714 addl=" "+green("NS")+fetch+" "
2716 counters.newslot += 1
2718 if "--changelog" in self.myopts:
2719 slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
2720 mydbapi.aux_get(pkg_key, ["SLOT"])[0])
2721 inst_matches = vardb.match(slot_atom)
2723 changelogs.extend(self.calc_changelog(
2724 portdb.findname(pkg_key),
2725 inst_matches[0], pkg_key))
2727 addl=" "+green("N")+" "+fetch+" "
2733 if pkg_key in self.useFlags[myroot]:
2735 cur_iuse = list(filter_iuse_defaults(
2736 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
2738 forced_flags = set()
2739 if not binary_package:
2740 forced_flags.update(pkgsettings.useforce)
2741 forced_flags.update(pkgsettings.usemask)
2743 cur_iuse = portage.unique_array(cur_iuse)
2745 cur_use = self.useFlags[myroot][pkg_key]
2746 cur_use = [flag for flag in cur_use if flag in cur_iuse]
2752 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2753 old_iuse, old_use = \
2754 self.trees[x[1]]["vartree"].dbapi.aux_get(
2755 pkg, ["IUSE", "USE"])
2756 old_iuse = list(set(
2757 filter_iuse_defaults(old_iuse.split())))
2759 old_use = old_use.split()
2766 old_use = [flag for flag in old_use if flag in old_iuse]
2768 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2770 use_expand.reverse()
2771 use_expand_hidden = \
2772 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2774 def map_to_use_expand(myvals, forcedFlags=False):
2777 for exp in use_expand:
2780 for val in myvals[:]:
2781 if val.startswith(exp.lower()+"_"):
2782 if val in forced_flags:
2783 forced[exp].add(val[len(exp)+1:])
2784 ret[exp].append(val[len(exp)+1:])
2787 forced["USE"] = [val for val in myvals \
2788 if val in forced_flags]
2789 for exp in use_expand_hidden:
2796 cur_iuse_map, iuse_forced = \
2797 map_to_use_expand(cur_iuse, forcedFlags=True)
2798 cur_use_map = map_to_use_expand(cur_use)
2799 old_iuse_map = map_to_use_expand(old_iuse)
2800 old_use_map = map_to_use_expand(old_use)
2803 use_expand.insert(0, "USE")
2805 for key in use_expand:
2806 if key in use_expand_hidden:
2808 verboseadd += create_use_string(key.upper(),
2809 cur_iuse_map[key], iuse_forced[key],
2810 cur_use_map[key], old_iuse_map[key],
2811 old_use_map[key], is_new)
2816 if pkg_type == "ebuild" and pkg_merge:
2818 myfilesdict = portdb.getfetchsizes(pkg_key,
2819 useflags=self.useFlags[myroot][pkg_key],
2821 except portage.exception.InvalidDependString, e:
2822 src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
2823 show_invalid_depstring_notice(x, src_uri, str(e))
2826 if myfilesdict is None:
2827 myfilesdict="[empty/missing/bad digest]"
2829 for myfetchfile in myfilesdict:
2830 if myfetchfile not in myfetchlist:
2831 mysize+=myfilesdict[myfetchfile]
2832 myfetchlist.append(myfetchfile)
2833 counters.totalsize += mysize
2834 verboseadd+=format_size(mysize)+" "
2837 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2838 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2839 file_name = portdb.findname(pkg_key)
2840 if file_name: # It might not exist in the tree
2841 newrepo = pkgsettings["PORTDIR"]
2843 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2844 oldrepo = self.trees[x[1]]["vartree"].dbapi.aux_get(pkg, ["repository"])[0]
2848 oldrepo = portdb.getRepositoryPath(oldrepo)
2849 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2850 if (overlays_real.count(dir_name) > 0):
2851 newrepoindex = overlays_real.index(os.path.normpath(dir_name))
2852 newrepo = overlays_real[newrepoindex]
2855 # assing lookup indexes
2858 elif oldrepo == pkgsettings["PORTDIR"]:
2861 oldrepoindex = str(overlays_real.index(os.path.normpath(oldrepo)) + 1)
2862 if oldrepoindex == newrepoindex \
2863 or not self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
2864 repoadd = newrepoindex
2866 repoadd = "%s=>%s" % (oldrepoindex, newrepoindex)
2868 verboseadd+=teal("[%s]" % repoadd)+" "
2869 display_overlays=True
2871 verboseadd += "[No ebuild?]"
2873 xs = list(portage.pkgsplit(x[2]))
2880 if "COLUMNWIDTH" in self.settings:
2882 mywidth = int(self.settings["COLUMNWIDTH"])
2883 except ValueError, e:
2884 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2886 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2887 self.settings["COLUMNWIDTH"], noiselevel=-1)
2892 indent = " " * depth
2895 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2896 if myoldbest[-3:]=="-r0":
2897 myoldbest=myoldbest[:-3]
2898 myoldbest=blue("["+myoldbest+"]")
2905 if pkg_node in self._args_nodes:
2907 world_nodes = self._sets_nodes.get("world")
2908 if world_nodes and pkg_node in world_nodes:
2910 if world_nodes is None:
2911 # Don't colorize system package when in "world" mode.
2912 system_nodes = self._sets_nodes.get("system")
2913 if system_nodes and pkg_node in system_nodes:
2920 return colorize("PKG_MERGE_WORLD", pkg)
2922 return colorize("PKG_MERGE_SYSTEM", pkg)
2924 return colorize("PKG_MERGE_ARG", pkg)
2926 return colorize("PKG_MERGE", pkg)
2930 return colorize("PKG_NOMERGE_WORLD", pkg)
2932 return colorize("PKG_NOMERGE_SYSTEM", pkg)
2934 return colorize("PKG_NOMERGE_ARG", pkg)
2936 return colorize("PKG_NOMERGE", pkg)
2941 if "--columns" in self.myopts:
2942 if "--quiet" in self.myopts:
2943 myprint=addl+" "+indent+pkgprint(pkg_cp)
2944 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2945 myprint=myprint+myoldbest
2946 myprint=myprint+darkgreen("to "+x[1])
2948 myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_cp)
2949 if (newlp-nc_len(myprint)) > 0:
2950 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2951 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2952 if (oldlp-nc_len(myprint)) > 0:
2953 myprint=myprint+" "*(oldlp-nc_len(myprint))
2954 myprint=myprint+myoldbest
2955 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2958 myprint = "[%s ] " % pkgprint("nomerge")
2960 myprint = "[" + pkg_type + " " + addl + "] "
2961 myprint += indent + pkgprint(pkg_key) + " " + \
2962 myoldbest + darkgreen("to " + myroot) + " " + \
2965 if "--columns" in self.myopts:
2966 if "--quiet" in self.myopts:
2967 myprint=addl+" "+indent+pkgprint(pkg_cp)
2968 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2969 myprint=myprint+myoldbest
2971 myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_cp)
2972 if (newlp-nc_len(myprint)) > 0:
2973 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2974 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2975 if (oldlp-nc_len(myprint)) > 0:
2976 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2977 myprint=myprint+myoldbest+" "+verboseadd
2980 myprint="["+pkgprint("nomerge")+" ] "+indent+pkgprint(pkg_key)+" "+myoldbest+" "+verboseadd
2982 myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_key)+" "+myoldbest+" "+verboseadd
2985 mysplit = portage.pkgsplit(x[2])
2986 if "--tree" not in self.myopts and mysplit and \
2987 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2990 if mysplit[2] == "r0":
2991 myversion = mysplit[1]
2993 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2995 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2996 if mylist_index < len(mylist) - 1 and \
2997 "livecvsportage" not in self.settings.features:
2998 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2999 p.append(colorize("WARN", " then resume the merge."))
3011 if overlays and display_overlays:
3012 print "Portage tree and overlays:"
3014 print " "+teal("[0]"), self.settings["PORTDIR"]
3017 print " "+teal("["+str(y)+"]"),x
3018 print " "+teal("[?]"), "indicates that the source repository could not be determined"
3020 if "--changelog" in self.myopts:
3022 for revision,text in changelogs:
3023 print bold('*'+revision)
3024 sys.stdout.write(text)
3026 if self._pprovided_args:
3028 for arg_atom in self._pprovided_args:
3029 arg, atom = arg_atom
3030 arg_refs[arg_atom] = []
3031 cp = portage.dep_getkey(atom)
3032 for set_name, pkg_set in self._sets.iteritems():
3033 if cp in pkg_set and atom in pkg_set[cp]:
3034 arg_refs[arg_atom].append(set_name)
3036 msg.append(bad("\nWARNING: "))
3037 if len(self._pprovided_args) > 1:
3038 msg.append("Requested packages will not be " + \
3039 "merged because they are listed in\n")
3041 msg.append("A requested package will not be " + \
3042 "merged because it is listed in\n")
3043 msg.append("package.provided:\n\n")
3044 problems_sets = set()
3045 for (arg, atom), refs in arg_refs.iteritems():
3048 problems_sets.update(refs)
3050 ref_string = ", ".join(["'%s'" % name for name in refs])
3051 ref_string = " pulled in by " + ref_string
3052 msg.append(" %s%s\n" % (colorize("INFORM", arg), ref_string))
3054 if "world" in problems_sets:
3055 msg.append("This problem can be solved in one of the following ways:\n\n")
3056 msg.append(" A) Use emaint to clean offending packages from world (if not installed).\n")
3057 msg.append(" B) Uninstall offending packages (cleans them from world).\n")
3058 msg.append(" C) Remove offending entries from package.provided.\n\n")
3059 msg.append("The best course of action depends on the reason that an offending\n")
3060 msg.append("package.provided entry exists.\n\n")
3061 sys.stderr.write("".join(msg))
3063 def calc_changelog(self,ebuildpath,current,next):
3064 if ebuildpath == None or not os.path.exists(ebuildpath):
3066 current = '-'.join(portage.catpkgsplit(current)[1:])
3067 if current.endswith('-r0'):
3068 current = current[:-3]
3069 next = '-'.join(portage.catpkgsplit(next)[1:])
3070 if next.endswith('-r0'):
3072 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
3074 changelog = open(changelogpath).read()
3075 except SystemExit, e:
3076 raise # Needed else can't exit
3079 divisions = self.find_changelog_tags(changelog)
3080 #print 'XX from',current,'to',next
3081 #for div,text in divisions: print 'XX',div
3082 # skip entries for all revisions above the one we are about to emerge
3083 for i in range(len(divisions)):
3084 if divisions[i][0]==next:
3085 divisions = divisions[i:]
3087 # find out how many entries we are going to display
3088 for i in range(len(divisions)):
3089 if divisions[i][0]==current:
3090 divisions = divisions[:i]
3093 # couldnt find the current revision in the list. display nothing
3097 def find_changelog_tags(self,changelog):
3101 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
3103 if release is not None:
3104 divs.append((release,changelog))
3106 if release is not None:
3107 divs.append((release,changelog[:match.start()]))
3108 changelog = changelog[match.end():]
3109 release = match.group(1)
3110 if release.endswith('.ebuild'):
3111 release = release[:-7]
3112 if release.endswith('-r0'):
3113 release = release[:-3]
3116 return self.outdatedpackages
3118 class PackageCounters(object):
3128 self.restrict_fetch = 0
3129 self.restrict_fetch_satisfied = 0
3132 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
3135 myoutput.append("Total: %s package" % total_installs)
3136 if total_installs != 1:
3137 myoutput.append("s")
3138 if total_installs != 0:
3139 myoutput.append(" (")
3140 if self.upgrades > 0:
3141 details.append("%s upgrade" % self.upgrades)
3142 if self.upgrades > 1:
3144 if self.downgrades > 0:
3145 details.append("%s downgrade" % self.downgrades)
3146 if self.downgrades > 1:
3149 details.append("%s new" % self.new)
3150 if self.newslot > 0:
3151 details.append("%s in new slot" % self.newslot)
3152 if self.newslot > 1:
3155 details.append("%s reinstall" % self.reinst)
3159 details.append("%s block" % self.blocks)
3162 myoutput.append(", ".join(details))
3163 if total_installs != 0:
3164 myoutput.append(")")
3165 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
3166 if self.restrict_fetch:
3167 myoutput.append("\nFetch Restriction: %s package" % \
3168 self.restrict_fetch)
3169 if self.restrict_fetch > 1:
3170 myoutput.append("s")
3171 if self.restrict_fetch_satisfied < self.restrict_fetch:
3172 myoutput.append(bad(" (%s unsatisfied)") % \
3173 (self.restrict_fetch - self.restrict_fetch_satisfied))
3174 return "".join(myoutput)
3176 class MergeTask(object):
3178 def __init__(self, settings, trees, myopts):
3179 self.settings = settings
3180 self.target_root = settings["ROOT"]
3182 self.myopts = myopts
3184 if settings.get("PORTAGE_DEBUG", "") == "1":
3186 self.pkgsettings = {}
3187 self.pkgsettings[self.target_root] = portage.config(clone=settings)
3188 if self.target_root != "/":
3189 self.pkgsettings["/"] = \
3190 portage.config(clone=trees["/"]["vartree"].settings)
3192 def merge(self, mylist, favorites, mtimedb):
3193 from portage.elog import elog_process
3195 fetchonly = "--fetchonly" in self.myopts or \
3196 "--fetch-all-uri" in self.myopts
3198 ldpath_mtimes = mtimedb["ldpath"]
3199 xterm_titles = "notitles" not in self.settings.features
3201 #check for blocking dependencies
3202 if "--fetchonly" not in self.myopts and \
3203 "--fetch-all-uri" not in self.myopts and \
3204 "--buildpkgonly" not in self.myopts:
3207 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
3208 print "!!! the two packages cannot be installed on the same system together."
3209 print "!!! Please use 'emerge --pretend' to determine blockers."
3210 if "--quiet" not in self.myopts:
3211 show_blocker_docs_link()
3214 if "--resume" in self.myopts:
3216 print colorize("GOOD", "*** Resuming merge...")
3217 emergelog(xterm_titles, " *** Resuming merge...")
3218 mylist = mtimedb["resume"]["mergelist"][:]
3219 if "--skipfirst" in self.myopts and mylist:
3220 del mtimedb["resume"]["mergelist"][0]
3223 validate_merge_list(self.trees, mylist)
3224 mymergelist = mylist
3226 # Verify all the manifests now so that the user is notified of failure
3227 # as soon as possible.
3228 if "--fetchonly" not in self.myopts and \
3229 "--fetch-all-uri" not in self.myopts and \
3230 "strict" in self.settings.features:
3231 shown_verifying_msg = False
3233 for myroot, pkgsettings in self.pkgsettings.iteritems():
3234 quiet_config = portage.config(clone=pkgsettings)
3235 quiet_config["PORTAGE_QUIET"] = "1"
3236 quiet_config.backup_changes("PORTAGE_QUIET")
3237 quiet_settings[myroot] = quiet_config
3240 if x[0] != "ebuild" or x[-1] == "nomerge":
3242 if not shown_verifying_msg:
3243 shown_verifying_msg = True
3244 print ">>> Verifying ebuild Manifests..."
3245 mytype, myroot, mycpv, mystatus = x
3246 portdb = self.trees[myroot]["porttree"].dbapi
3247 quiet_config = quiet_settings[myroot]
3248 quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
3249 if not portage.digestcheck([], quiet_config, strict=True):
3251 del x, mytype, myroot, mycpv, mystatus, quiet_config
3252 del shown_verifying_msg, quiet_settings
3254 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
3255 mysysdict = genericdict(getlist(self.settings, "system"))
3256 if "--resume" not in self.myopts:
3257 myfavs = portage.grabfile(
3258 os.path.join(self.target_root, portage.WORLD_FILE))
3259 myfavdict=genericdict(myfavs)
3260 for x in range(len(mylist)):
3261 if mylist[x][3]!="nomerge":
3262 # Add to the mergelist
3263 mymergelist.append(mylist[x])
3265 myfavkey=portage.cpv_getkey(mylist[x][2])
3266 if "--onlydeps" in self.myopts:
3268 # Add to the world file. Since we won't be able to later.
3269 if "--fetchonly" not in self.myopts and \
3270 myfavkey in favorites:
3271 #don't record if already in system profile or already recorded
3272 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3273 #we don't have a favorites entry for this package yet; add one
3274 myfavdict[myfavkey]=myfavkey
3275 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3276 if not ("--fetchonly" in self.myopts or \
3277 "--fetch-all-uri" in self.myopts or \
3278 "--pretend" in self.myopts):
3279 portage.write_atomic(
3280 os.path.join(self.target_root, portage.WORLD_FILE),
3281 "\n".join(sorted(myfavdict.values())) + "\n")
3283 mtimedb["resume"]["mergelist"]=mymergelist[:]
3286 myfeat = self.settings.features[:]
3287 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3289 if "parallel-fetch" in myfeat and \
3290 not ("--pretend" in self.myopts or \
3291 "--fetch-all-uri" in self.myopts or \
3292 "--fetchonly" in self.myopts):
3293 if "distlocks" not in myfeat:
3295 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
3296 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
3298 elif len(mymergelist) > 1:
3299 print ">>> starting parallel fetching"
3300 fetch_log = "/var/log/emerge-fetch.log"
3301 logfile = open(fetch_log, "w")
3302 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3303 portage.util.apply_secpass_permissions(fetch_log,
3304 uid=portage.portage_uid, gid=portage.portage_gid,
3306 fetch_env = os.environ.copy()
3307 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3308 fetch_env["PORTAGE_NICENESS"] = "0"
3309 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3310 resume_opts = self.myopts.copy()
3311 # For automatic resume, we need to prevent
3312 # any of bad_resume_opts from leaking in
3313 # via EMERGE_DEFAULT_OPTS.
3314 resume_opts["--ignore-default-opts"] = True
3315 for myopt, myarg in resume_opts.iteritems():
3316 if myopt not in bad_resume_opts:
3318 fetch_args.append(myopt)
3320 fetch_args.append(myopt +"="+ myarg)
3321 portage.process.spawn(fetch_args, env=fetch_env,
3322 fd_pipes=fd_pipes, returnpid=True)
3323 logfile.close() # belongs to the spawned process
3324 del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3328 for x in mymergelist:
3333 portdb = self.trees[myroot]["porttree"].dbapi
3334 bindb = self.trees[myroot]["bintree"].dbapi
3335 vartree = self.trees[myroot]["vartree"]
3336 pkgsettings = self.pkgsettings[myroot]
3339 y = portdb.findname(pkg_key)
3340 if "--pretend" not in self.myopts:
3341 print "\n>>> Emerging (" + \
3342 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3343 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3344 colorize("GOOD", x[pkgindex]) + " to " + x[1]
3345 emergelog(xterm_titles, " >>> emerge ("+\
3346 str(mergecount)+" of "+str(len(mymergelist))+\
3347 ") "+x[pkgindex]+" to "+x[1])
3349 pkgsettings["EMERGE_FROM"] = x[0]
3350 pkgsettings.backup_changes("EMERGE_FROM")
3353 #buildsyspkg: Check if we need to _force_ binary package creation
3354 issyspkg = ("buildsyspkg" in myfeat) \
3355 and x[0] != "blocks" \
3356 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3357 and "--buildpkg" not in self.myopts
3358 if x[0] in ["ebuild","blocks"]:
3359 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3360 raise Exception, "Merging a blocker"
3361 elif "--fetchonly" in self.myopts or \
3362 "--fetch-all-uri" in self.myopts:
3363 if "--fetch-all-uri" in self.myopts:
3364 retval = portage.doebuild(y, "fetch", myroot,
3365 pkgsettings, self.edebug,
3366 "--pretend" in self.myopts, fetchonly=1,
3367 fetchall=1, mydbapi=portdb, tree="porttree")
3369 retval = portage.doebuild(y, "fetch", myroot,
3370 pkgsettings, self.edebug,
3371 "--pretend" in self.myopts, fetchonly=1,
3372 mydbapi=portdb, tree="porttree")
3373 if (retval is None) or retval:
3375 print "!!! Fetch for",y,"failed, continuing..."
3377 failed_fetches.append(pkg_key)
3380 portage.doebuild_environment(y, "setup", myroot,
3381 pkgsettings, self.edebug, 1, portdb)
3382 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3383 portage.util.ensure_dirs(os.path.dirname(catdir),
3384 uid=portage.portage_uid, gid=portage.portage_gid,
3386 builddir_lock = None
3389 catdir_lock = portage.locks.lockdir(catdir)
3390 portage.util.ensure_dirs(catdir,
3391 uid=portage.portage_uid, gid=portage.portage_gid,
3393 builddir_lock = portage.locks.lockdir(
3394 pkgsettings["PORTAGE_BUILDDIR"])
3396 portage.locks.unlockdir(catdir_lock)
3399 msg = " === (%s of %s) Cleaning (%s::%s)" % \
3400 (mergecount, len(mymergelist), pkg_key, y)
3401 short_msg = "emerge: (%s of %s) %s Clean" % \
3402 (mergecount, len(mymergelist), pkg_key)
3403 emergelog(xterm_titles, msg, short_msg=short_msg)
3404 retval = portage.doebuild(y, "clean", myroot,
3405 pkgsettings, self.edebug, cleanup=1,
3406 mydbapi=portdb, tree="porttree")
3407 if retval != os.EX_OK:
3409 if "--buildpkg" in self.myopts or issyspkg:
3411 print ">>> This is a system package, " + \
3412 "let's pack a rescue tarball."
3413 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3414 (mergecount, len(mymergelist), pkg_key, y)
3415 short_msg = "emerge: (%s of %s) %s Compile" % \
3416 (mergecount, len(mymergelist), pkg_key)
3417 emergelog(xterm_titles, msg, short_msg=short_msg)
3418 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3419 binpkg_tmpfile = os.path.join(pkgsettings["PKGDIR"],
3420 pkg_key + ".tbz2." + str(os.getpid()))
3421 pkgsettings["PORTAGE_BINPKG_TMPFILE"] = binpkg_tmpfile
3422 pkgsettings.backup_changes("PORTAGE_BINPKG_TMPFILE")
3423 retval = portage.doebuild(y, "package", myroot,
3424 pkgsettings, self.edebug, mydbapi=portdb,
3426 del pkgsettings["PORTAGE_BINPKG_TMPFILE"]
3427 if retval != os.EX_OK or \
3428 "--buildpkgonly" in self.myopts:
3429 elog_process(pkg_key, pkgsettings)
3430 if retval != os.EX_OK:
3432 bintree = self.trees[myroot]["bintree"]
3433 bintree.inject(pkg_key, filename=binpkg_tmpfile)
3434 if "--buildpkgonly" not in self.myopts:
3435 msg = " === (%s of %s) Merging (%s::%s)" % \
3436 (mergecount, len(mymergelist), pkg_key, y)
3437 short_msg = "emerge: (%s of %s) %s Merge" % \
3438 (mergecount, len(mymergelist), pkg_key)
3439 emergelog(xterm_titles, msg, short_msg=short_msg)
3440 retval = portage.merge(pkgsettings["CATEGORY"],
3441 pkgsettings["PF"], pkgsettings["D"],
3442 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3443 "build-info"), myroot, pkgsettings,
3444 myebuild=pkgsettings["EBUILD"],
3445 mytree="porttree", mydbapi=portdb,
3446 vartree=vartree, prev_mtimes=ldpath_mtimes)
3447 if retval != os.EX_OK:
3449 elif "noclean" not in pkgsettings.features:
3450 portage.doebuild(y, "clean", myroot,
3451 pkgsettings, self.edebug, mydbapi=portdb,
3454 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3455 (mergecount, len(mymergelist), pkg_key, y)
3456 short_msg = "emerge: (%s of %s) %s Compile" % \
3457 (mergecount, len(mymergelist), pkg_key)
3458 emergelog(xterm_titles, msg, short_msg=short_msg)
3459 retval = portage.doebuild(y, "merge", myroot,
3460 pkgsettings, self.edebug, vartree=vartree,
3461 mydbapi=portdb, tree="porttree",
3462 prev_mtimes=ldpath_mtimes)
3463 if retval != os.EX_OK:
3467 portage.locks.unlockdir(builddir_lock)
3470 # Lock catdir for removal if empty.
3471 catdir_lock = portage.locks.lockdir(catdir)
3477 if e.errno not in (errno.ENOENT,
3478 errno.ENOTEMPTY, errno.EEXIST):
3481 portage.locks.unlockdir(catdir_lock)
3483 elif x[0]=="binary":
3485 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3486 if "--getbinpkg" in self.myopts:
3489 if "distlocks" in pkgsettings.features and \
3490 os.access(pkgsettings["PKGDIR"], os.W_OK):
3491 portage.util.ensure_dirs(os.path.dirname(mytbz2))
3492 tbz2_lock = portage.locks.lockfile(mytbz2,
3494 if self.trees[myroot]["bintree"].isremote(pkg_key):
3495 msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3496 (mergecount, len(mymergelist), pkg_key, mytbz2)
3497 short_msg = "emerge: (%s of %s) %s Fetch" % \
3498 (mergecount, len(mymergelist), pkg_key)
3499 emergelog(xterm_titles, msg, short_msg=short_msg)
3501 self.trees[myroot]["bintree"].gettbz2(pkg_key)
3502 except portage.exception.FileNotFound:
3503 writemsg("!!! Fetching Binary failed " + \
3504 "for '%s'\n" % pkg_key, noiselevel=-1)
3507 failed_fetches.append(pkg_key)
3508 except portage.exception.DigestException, e:
3509 writemsg("\n!!! Digest verification failed:\n",
3511 writemsg("!!! %s\n" % e.value[0],
3513 writemsg("!!! Reason: %s\n" % e.value[1],
3515 writemsg("!!! Got: %s\n" % e.value[2],
3517 writemsg("!!! Expected: %s\n" % e.value[3],
3522 failed_fetches.append(pkg_key)
3525 portage.locks.unlockfile(tbz2_lock)
3527 if "--fetchonly" in self.myopts or \
3528 "--fetch-all-uri" in self.myopts:
3531 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3532 emergelog(xterm_titles, " === ("+str(mergecount)+\
3533 " of "+str(len(mymergelist))+") Merging Binary ("+\
3534 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3535 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3537 vartree=self.trees[myroot]["vartree"],
3538 prev_mtimes=ldpath_mtimes)
3539 if retval != os.EX_OK:
3541 #need to check for errors
3542 if "--buildpkgonly" not in self.myopts:
3543 self.trees[x[1]]["vartree"].inject(x[2])
3544 myfavkey=portage.cpv_getkey(x[2])
3545 if "--fetchonly" not in self.myopts and \
3546 "--fetch-all-uri" not in self.myopts and \
3547 myfavkey in favorites:
3548 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3549 myfavdict=genericdict(myfavs)
3550 #don't record if already in system profile or already recorded
3551 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3552 #we don't have a favorites entry for this package yet; add one
3553 myfavdict[myfavkey]=myfavkey
3554 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3555 emergelog(xterm_titles, " === ("+\
3556 str(mergecount)+" of "+\
3557 str(len(mymergelist))+\
3558 ") Updating world file ("+x[pkgindex]+")")
3559 portage.write_atomic(
3560 os.path.join(myroot, portage.WORLD_FILE),
3561 "\n".join(sorted(myfavdict.values()))+"\n")
3563 if "--pretend" not in self.myopts and \
3564 "--fetchonly" not in self.myopts and \
3565 "--fetch-all-uri" not in self.myopts:
3566 # Clean the old package that we have merged over top of it.
3567 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3568 xsplit=portage.pkgsplit(x[2])
3569 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3570 retval = unmerge(pkgsettings, self.myopts, vartree,
3571 "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3573 emergelog(xterm_titles,
3574 " --- AUTOCLEAN: Nothing unmerged.")
3576 portage.writemsg_stdout(colorize("WARN", "WARNING:")
3577 + " AUTOCLEAN is disabled. This can cause serious"
3578 + " problems due to overlapping packages.\n")
3580 # Figure out if we need a restart.
3581 mysplit=portage.pkgsplit(x[2])
3582 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3583 myver=mysplit[1]+"-"+mysplit[2]
3584 if myver[-3:]=='-r0':
3586 if (myver != portage.VERSION) and \
3587 "livecvsportage" not in self.settings.features:
3588 if len(mymergelist) > mergecount:
3589 emergelog(xterm_titles,
3590 " ::: completed emerge ("+ \
3591 str(mergecount)+" of "+ \
3592 str(len(mymergelist))+") "+ \
3594 emergelog(xterm_titles, " *** RESTARTING " + \
3595 "emerge via exec() after change of " + \
3597 del mtimedb["resume"]["mergelist"][0]
3599 portage.run_exitfuncs()
3600 mynewargv=[sys.argv[0],"--resume"]
3601 resume_opts = self.myopts.copy()
3602 # For automatic resume, we need to prevent
3603 # any of bad_resume_opts from leaking in
3604 # via EMERGE_DEFAULT_OPTS.
3605 resume_opts["--ignore-default-opts"] = True
3606 for myopt, myarg in resume_opts.iteritems():
3607 if myopt not in bad_resume_opts:
3609 mynewargv.append(myopt)
3611 mynewargv.append(myopt +"="+ myarg)
3612 # priority only needs to be adjusted on the first run
3613 os.environ["PORTAGE_NICENESS"] = "0"
3614 os.execv(mynewargv[0], mynewargv)
3616 if "--pretend" not in self.myopts and \
3617 "--fetchonly" not in self.myopts and \
3618 "--fetch-all-uri" not in self.myopts:
3619 if "noclean" not in self.settings.features:
3620 short_msg = "emerge: (%s of %s) %s Clean Post" % \
3621 (mergecount, len(mymergelist), x[pkgindex])
3622 emergelog(xterm_titles, (" === (%s of %s) " + \
3623 "Post-Build Cleaning (%s::%s)") % \
3624 (mergecount, len(mymergelist), x[pkgindex], y),
3625 short_msg=short_msg)
3626 emergelog(xterm_titles, " ::: completed emerge ("+\
3627 str(mergecount)+" of "+str(len(mymergelist))+") "+\
3630 # Unsafe for parallel merges
3631 del mtimedb["resume"]["mergelist"][0]
3632 # Commit after each merge so that --resume may still work in
3633 # in the event that portage is not allowed to exit normally
3634 # due to power failure, SIGKILL, etc...
3637 if "--pretend" not in self.myopts:
3638 emergelog(xterm_titles, " *** Finished. Cleaning up...")
3640 # We're out of the loop... We're done. Delete the resume data.
3641 if mtimedb.has_key("resume"):
3642 del mtimedb["resume"]
3645 #by doing an exit this way, --fetchonly can continue to try to
3646 #fetch everything even if a particular download fails.
3647 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3649 sys.stderr.write("\n\n!!! Some fetch errors were " + \
3650 "encountered. Please see above for details.\n\n")
3651 for cpv in failed_fetches:
3652 sys.stderr.write(" ")
3653 sys.stderr.write(cpv)
3654 sys.stderr.write("\n")
3655 sys.stderr.write("\n")
3661 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3662 ldpath_mtimes, autoclean=0):
3663 candidate_catpkgs=[]
3665 xterm_titles = "notitles" not in settings.features
3667 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3669 # At least the parent needs to exist for the lock file.
3670 portage.util.ensure_dirs(vdb_path)
3671 except portage.exception.PortageException:
3675 if os.access(vdb_path, os.W_OK):
3676 vdb_lock = portage.locks.lockdir(vdb_path)
3677 realsyslist = getlist(settings, "system")
3679 for x in realsyslist:
3680 mycp = portage.dep_getkey(x)
3681 if mycp in settings.getvirtuals():
3683 for provider in settings.getvirtuals()[mycp]:
3684 if vartree.dbapi.match(provider):
3685 providers.append(provider)
3686 if len(providers) == 1:
3687 syslist.extend(providers)
3689 syslist.append(mycp)
3691 mysettings = portage.config(clone=settings)
3693 if not unmerge_files or "world" in unmerge_files or \
3694 "system" in unmerge_files:
3695 if "unmerge"==unmerge_action:
3697 print bold("emerge unmerge") + " can only be used with " + \
3698 "specific package names, not with "+bold("world")+" or"
3699 print bold("system")+" targets."
3706 # process all arguments and add all
3707 # valid db entries to candidate_catpkgs
3709 if not unmerge_files or "world" in unmerge_files:
3710 candidate_catpkgs.extend(vartree.dbapi.cp_all())
3711 elif "system" in unmerge_files:
3712 candidate_catpkgs.extend(getlist(settings, "system"))
3714 #we've got command-line arguments
3715 if not unmerge_files:
3716 print "\nNo packages to unmerge have been provided.\n"
3718 for x in unmerge_files:
3719 arg_parts = x.split('/')
3720 if x[0] not in [".","/"] and \
3721 arg_parts[-1][-7:] != ".ebuild":
3722 #possible cat/pkg or dep; treat as such
3723 candidate_catpkgs.append(x)
3724 elif unmerge_action in ["prune","clean"]:
3725 print "\n!!! Prune and clean do not accept individual" + \
3726 " ebuilds as arguments;\n skipping.\n"
3729 # it appears that the user is specifying an installed
3730 # ebuild and we're in "unmerge" mode, so it's ok.
3731 if not os.path.exists(x):
3732 print "\n!!! The path '"+x+"' doesn't exist.\n"
3735 absx = os.path.abspath(x)
3736 sp_absx = absx.split("/")
3737 if sp_absx[-1][-7:] == ".ebuild":
3739 absx = "/".join(sp_absx)
3741 sp_absx_len = len(sp_absx)
3743 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
3744 vdb_len = len(vdb_path)
3746 sp_vdb = vdb_path.split("/")
3747 sp_vdb_len = len(sp_vdb)
3749 if not os.path.exists(absx+"/CONTENTS"):
3750 print "!!! Not a valid db dir: "+str(absx)
3753 if sp_absx_len <= sp_vdb_len:
3754 # The Path is shorter... so it can't be inside the vdb.
3757 print "\n!!!",x,"cannot be inside "+ \
3758 vdb_path+"; aborting.\n"
3761 for idx in range(0,sp_vdb_len):
3762 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
3765 print "\n!!!", x, "is not inside "+\
3766 vdb_path+"; aborting.\n"
3769 print "="+"/".join(sp_absx[sp_vdb_len:])
3770 candidate_catpkgs.append(
3771 "="+"/".join(sp_absx[sp_vdb_len:]))
3774 if (not "--quiet" in myopts):
3776 if settings["ROOT"] != "/":
3777 print darkgreen(newline+ \
3778 ">>> Using system located in ROOT tree "+settings["ROOT"])
3779 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
3780 not ("--quiet" in myopts):
3781 print darkgreen(newline+\
3782 ">>> These are the packages that would be unmerged:")
3786 for x in candidate_catpkgs:
3787 # cycle through all our candidate deps and determine
3788 # what will and will not get unmerged
3790 mymatch=localtree.dep_match(x)
3793 except ValueError, errpkgs:
3794 print "\n\n!!! The short ebuild name \"" + \
3795 x + "\" is ambiguous. Please specify"
3796 print "!!! one of the following fully-qualified " + \
3797 "ebuild names instead:\n"
3798 for i in errpkgs[0]:
3799 print " " + green(i)
3803 if not mymatch and x[0] not in "<>=~":
3804 #add a "=" if missing
3805 mymatch=localtree.dep_match("="+x)
3807 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
3808 (x, unmerge_action), noiselevel=-1)
3810 mykey = portage.key_expand(
3812 mymatch[0]), mydb=vartree.dbapi, settings=settings)
3813 if not pkgmap.has_key(mykey):
3814 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
3815 if unmerge_action=="unmerge":
3817 if y not in pkgmap[mykey]["selected"]:
3818 pkgmap[mykey]["selected"].append(y)
3819 numselected=numselected+len(mymatch)
3822 #unmerge_action in ["prune", clean"]
3824 for mypkg in mymatch:
3825 if unmerge_action=="clean":
3826 myslot=localtree.getslot(mypkg)
3828 # since we're pruning, we don't care about slots
3829 # and put all the pkgs in together
3831 if not slotmap.has_key(myslot):
3833 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
3834 for myslot in slotmap:
3835 counterkeys=slotmap[myslot].keys()
3840 pkgmap[mykey]["protected"].append(
3841 slotmap[myslot][counterkeys[-1]])
3843 #be pretty and get them in order of merge:
3844 for ckey in counterkeys:
3845 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
3846 numselected=numselected+1
3847 # ok, now the last-merged package
3848 # is protected, and the rest are selected
3849 if global_unmerge and not numselected:
3850 portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
3854 portage.writemsg_stdout(
3855 "\n>>> No packages selected for removal by " + \
3856 unmerge_action + "\n")
3860 portage.locks.unlockdir(vdb_lock)
3862 for y in localtree.dep_match(x):
3863 if y not in pkgmap[x]["omitted"] and \
3864 y not in pkgmap[x]["selected"] and \
3865 y not in pkgmap[x]["protected"]:
3866 pkgmap[x]["omitted"].append(y)
3867 if global_unmerge and not pkgmap[x]["selected"]:
3868 #avoid cluttering the preview printout with stuff that isn't getting unmerged
3870 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
3871 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
3872 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
3873 if "--pretend" not in myopts and "--ask" not in myopts:
3874 countdown(int(settings["EMERGE_WARNING_DELAY"]),
3875 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
3876 print "\n "+white(x)
3877 for mytype in ["selected","protected","omitted"]:
3878 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
3879 if pkgmap[x][mytype]:
3880 for mypkg in pkgmap[x][mytype]:
3881 mysplit=portage.catpkgsplit(mypkg)
3882 if mysplit[3]=="r0":
3883 myversion=mysplit[2]
3885 myversion=mysplit[2]+"-"+mysplit[3]
3886 if mytype=="selected":
3887 portage.writemsg_stdout(
3888 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
3890 portage.writemsg_stdout(
3891 colorize("GOOD", myversion + " "), noiselevel=-1)
3893 portage.writemsg_stdout("none", noiselevel=-1)
3894 portage.writemsg_stdout("\n", noiselevel=-1)
3896 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
3897 " packages are slated for removal.\n")
3898 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
3899 " and " + colorize("GOOD", "'omitted'") + \
3900 " packages will not be removed.\n\n")
3902 if "--pretend" in myopts:
3903 #we're done... return
3905 if "--ask" in myopts:
3906 if userquery("Would you like to unmerge these packages?")=="No":
3907 # enter pretend mode for correct formatting of results
3908 myopts["--pretend"] = True
3913 #the real unmerging begins, after a short delay....
3915 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
3918 for y in pkgmap[x]["selected"]:
3919 print ">>> Unmerging "+y+"..."
3920 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
3921 mysplit=y.split("/")
3923 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
3924 mysettings, unmerge_action not in ["clean","prune"],
3925 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
3926 if retval != os.EX_OK:
3927 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
3928 ebuild = vartree.dbapi.findname(y)
3929 show_unmerge_failure_message(y, ebuild, retval)
3932 clean_world(vartree.dbapi, y)
3933 emergelog(xterm_titles, " >>> unmerge success: "+y)
3936 def show_unmerge_failure_message(pkg, ebuild, retval):
3938 from formatter import AbstractFormatter, DumbWriter
3939 f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
3942 msg.append("A removal phase of the '%s' package " % pkg)
3943 msg.append("has failed with exit value %s. " % retval)
3944 msg.append("The problem occurred while executing ")
3945 msg.append("the ebuild located at '%s'. " % ebuild)
3946 msg.append("If necessary, manually remove the ebuild " )
3947 msg.append("in order to skip the execution of removal phases.")
3951 f.add_flowing_data(x)
3955 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
3957 if os.path.exists("/usr/bin/install-info"):
3962 inforoot=normpath(root+z)
3963 if os.path.isdir(inforoot):
3964 infomtime = long(os.stat(inforoot).st_mtime)
3965 if inforoot not in prev_mtimes or \
3966 prev_mtimes[inforoot] != infomtime:
3967 regen_infodirs.append(inforoot)
3969 if not regen_infodirs:
3970 portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
3972 portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
3976 for inforoot in regen_infodirs:
3979 for filename in ("dir", "dir.gz", "dir.bz2"):
3980 file_path = os.path.join(inforoot, filename)
3982 os.rename(file_path, file_path + ".old")
3984 if e.errno != errno.ENOENT:
3988 if not os.path.isdir(inforoot):
3991 file_list = os.listdir(inforoot)
3994 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3996 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3997 existsstr="already exists, for file `"
3999 if re.search(existsstr,myso):
4000 # Already exists... Don't increment the count for this.
4002 elif myso[:44]=="install-info: warning: no info dir entry in ":
4003 # This info file doesn't contain a DIR-header: install-info produces this
4004 # (harmless) warning (the --quiet switch doesn't seem to work).
4005 # Don't increment the count for this.
4009 errmsg += myso + "\n"
4012 #update mtime so we can potentially avoid regenerating.
4013 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
4016 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
4019 print " "+green("*")+" Processed",icount,"info files."
4022 def display_news_notification(trees):
4023 for target_root in trees:
4024 if len(trees) > 1 and target_root != "/":
4026 settings = trees[target_root]["vartree"].settings
4027 portdb = trees[target_root]["porttree"].dbapi
4028 vardb = trees[target_root]["vartree"].dbapi
4029 NEWS_PATH = os.path.join("metadata", "news")
4030 UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
4031 newsReaderDisplay = False
4033 for repo in portdb.getRepositories():
4034 unreadItems = checkUpdatedNewsItems(
4035 portdb, vardb, NEWS_PATH, UNREAD_PATH, repo)
4037 if not newsReaderDisplay:
4038 newsReaderDisplay = True
4040 print colorize("WARN", " * IMPORTANT:"),
4041 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
4044 if newsReaderDisplay:
4045 print colorize("WARN", " *"),
4046 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
4049 def post_emerge(trees, mtimedb, retval):
4051 Misc. things to run at the end of a merge session.
4057 Display preserved libs warnings
4060 @param trees: A dictionary mapping each ROOT to it's package databases
4062 @param mtimedb: The mtimeDB to store data needed across merge invocations
4063 @type mtimedb: MtimeDB class instance
4064 @param retval: Emerge's return value
4068 1. Calls sys.exit(retval)
4070 for target_root in trees:
4071 if len(trees) > 1 and target_root != "/":
4073 vardbapi = trees[target_root]["vartree"].dbapi
4074 settings = vardbapi.settings
4075 info_mtimes = mtimedb["info"]
4077 # Load the most current variables from ${ROOT}/etc/profile.env
4079 settings.regenerate()
4082 config_protect = settings.get("CONFIG_PROTECT","").split()
4083 infodirs = settings.get("INFOPATH","").split(":") + \
4084 settings.get("INFODIR","").split(":")
4088 emergelog("notitles" not in settings.features,
4089 " *** exiting successfully.")
4091 # Dump the mod_echo output now so that our other notifications are shown
4093 from portage.elog import mod_echo
4096 if "noinfo" not in settings.features:
4097 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
4099 chk_updated_cfg_files(target_root, config_protect)
4101 display_news_notification(trees)
4103 if vardbapi.plib_registry.hasEntries():
4104 print colorize("WARN", "!!!") + " existing preserved libs:"
4105 plibdata = vardbapi.plib_registry.getPreservedLibs()
4106 for cpv in plibdata:
4107 print colorize("WARN", ">>>") + " package: %s" % cpv
4108 for f in plibdata[cpv]:
4109 print colorize("WARN", " * ") + " - %s" % f
4110 print "Use " + colorize("GOOD", "revdep-rebuild") + " to rebuild packages using these libraries"
4111 print "and then remerge the packages listed above."
4117 def chk_updated_cfg_files(target_root, config_protect):
4119 #number of directories with some protect files in them
4121 for x in config_protect:
4122 x = os.path.join(target_root, x.lstrip(os.path.sep))
4124 mymode = os.lstat(x).st_mode
4127 if stat.S_ISDIR(mymode):
4128 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
4130 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
4131 os.path.split(x.rstrip(os.path.sep))
4132 a = commands.getstatusoutput(mycommand + \
4133 " ! -iname '.*~' ! -iname '.*.bak'")
4135 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
4137 files = a[1].split()
4140 print colorize("WARN", " * IMPORTANT:"),
4141 if stat.S_ISDIR(mymode):
4142 print "%d config files in '%s' need updating." % \
4145 print "config file '%s' needs updating." % x
4148 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
4149 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
4151 def checkUpdatedNewsItems(portdb, vardb, NEWS_PATH, UNREAD_PATH, repo_id):
4153 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
4154 Returns the number of unread (yet relevent) items.
4156 @param portdb: a portage tree database
4157 @type portdb: pordbapi
4158 @param vardb: an installed package database
4159 @type vardb: vardbapi
4168 1. The number of unread but relevant news items.
4171 from portage.news import NewsManager
4172 manager = NewsManager(portdb, vardb, NEWS_PATH, UNREAD_PATH)
4173 return manager.getUnreadItems( repo_id, update=True )
4175 def is_valid_package_atom(x):
4177 testkey = portage.dep_getkey(x)
4178 except portage.exception.InvalidData:
4180 if testkey.startswith("null/"):
4181 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
4186 return portage.isvalidatom(testatom)
4188 def validate_merge_list(trees, mergelist):
4189 """Validate the list to make sure all the packages are still available.
4190 This is needed for --resume."""
4191 for (pkg_type, myroot, pkg_key, action) in mergelist:
4192 if pkg_type == "binary" and \
4193 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
4194 pkg_type == "ebuild" and \
4195 not trees[myroot]["porttree"].dbapi.xmatch(
4196 "match-all", "="+pkg_key):
4197 print red("!!! Error: The resume list contains packages that are no longer")
4198 print red("!!! available to be emerged. Please restart/continue")
4199 print red("!!! the merge operation manually.")
4202 def show_blocker_docs_link():
4204 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
4205 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
4207 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
4210 def action_sync(settings, trees, mtimedb, myopts, myaction):
4211 xterm_titles = "notitles" not in settings.features
4212 emergelog(xterm_titles, " === sync")
4213 myportdir = settings.get("PORTDIR", None)
4215 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
4217 if myportdir[-1]=="/":
4218 myportdir=myportdir[:-1]
4219 if not os.path.exists(myportdir):
4220 print ">>>",myportdir,"not found, creating it."
4221 os.makedirs(myportdir,0755)
4222 syncuri=settings["SYNC"].rstrip()
4224 updatecache_flg = False
4225 if myaction == "metadata":
4226 print "skipping sync"
4227 updatecache_flg = True
4228 tmpservertimestampfile = None
4229 elif syncuri[:8]=="rsync://":
4230 if not os.path.exists("/usr/bin/rsync"):
4231 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
4232 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
4237 import shlex, StringIO
4238 if settings["PORTAGE_RSYNC_OPTS"] == "":
4239 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
4241 "--recursive", # Recurse directories
4242 "--links", # Consider symlinks
4243 "--safe-links", # Ignore links outside of tree
4244 "--perms", # Preserve permissions
4245 "--times", # Preserive mod times
4246 "--compress", # Compress the data transmitted
4247 "--force", # Force deletion on non-empty dirs
4248 "--whole-file", # Don't do block transfers, only entire files
4249 "--delete", # Delete files that aren't in the master tree
4250 "--delete-after", # Delete only after everything else is done
4251 "--stats", # Show final statistics about what was transfered
4252 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
4253 "--exclude=/distfiles", # Exclude distfiles from consideration
4254 "--exclude=/local", # Exclude local from consideration
4255 "--exclude=/packages", # Exclude packages from consideration
4256 "--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
4260 # The below validation is not needed when using the above hardcoded
4263 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
4264 lexer = shlex.shlex(StringIO.StringIO(
4265 settings.get("PORTAGE_RSYNC_OPTS","")), posix=True)
4266 lexer.whitespace_split = True
4267 rsync_opts.extend(lexer)
4270 for opt in ("--recursive", "--times"):
4271 if opt not in rsync_opts:
4272 portage.writemsg(yellow("WARNING:") + " adding required option " + \
4273 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4274 rsync_opts.append(opt)
4276 for exclude in ("distfiles", "local", "packages"):
4277 opt = "--exclude=/%s" % exclude
4278 if opt not in rsync_opts:
4279 portage.writemsg(yellow("WARNING:") + \
4280 " adding required option %s not included in " % opt + \
4281 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
4282 rsync_opts.append(opt)
4284 if settings["RSYNC_TIMEOUT"] != "":
4285 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
4286 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4288 mytimeout = int(settings["RSYNC_TIMEOUT"])
4289 rsync_opts.append("--timeout=%d" % mytimeout)
4290 except ValueError, e:
4291 portage.writemsg("!!! %s\n" % str(e))
4293 # TODO: determine options required for official servers
4294 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
4296 def rsync_opt_startswith(opt_prefix):
4297 for x in rsync_opts:
4298 if x.startswith(opt_prefix):
4302 if not rsync_opt_startswith("--timeout="):
4303 rsync_opts.append("--timeout=%d" % mytimeout)
4305 for opt in ("--compress", "--whole-file"):
4306 if opt not in rsync_opts:
4307 portage.writemsg(yellow("WARNING:") + " adding required option " + \
4308 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
4309 rsync_opts.append(opt)
4311 if "--quiet" in myopts:
4312 rsync_opts.append("--quiet") # Shut up a lot
4314 rsync_opts.append("--verbose") # Print filelist
4316 if "--verbose" in myopts:
4317 rsync_opts.append("--progress") # Progress meter for each file
4319 if "--debug" in myopts:
4320 rsync_opts.append("--checksum") # Force checksum on all files
4322 if settings["RSYNC_EXCLUDEFROM"] != "":
4323 portage.writemsg(yellow("WARNING:") + \
4324 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
4325 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
4326 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
4327 rsync_opts.append("--exclude-from=%s" % \
4328 settings["RSYNC_EXCLUDEFROM"])
4330 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
4331 " but file does not exist.\n")
4333 if settings["RSYNC_RATELIMIT"] != "":
4334 portage.writemsg(yellow("WARNING:") + \
4335 " usage of RSYNC_RATELIMIT is deprecated, use " + \
4336 "PORTAGE_RSYNC_EXTRA_OPTS instead")
4337 rsync_opts.append("--bwlimit=%s" % \
4338 settings["RSYNC_RATELIMIT"])
4340 # Real local timestamp file.
4341 servertimestampfile = os.path.join(
4342 myportdir, "metadata", "timestamp.chk")
4343 # Temporary file for remote server timestamp comparison.
4344 tmpservertimestampfile = os.path.join(
4345 settings["PORTAGE_TMPDIR"], "timestamp.chk")
4347 content = portage.util.grabfile(servertimestampfile)
4351 mytimestamp = time.mktime(time.strptime(content[0],
4352 "%a, %d %b %Y %H:%M:%S +0000"))
4353 except (OverflowError, ValueError):
4358 rsync_initial_timeout = \
4359 int(settings.get("PORTAGE_RSYNC_INITIAL_TIMEOUT", "15"))
4361 rsync_initial_timeout = 15
4364 if settings.has_key("RSYNC_RETRIES"):
4365 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
4366 maxretries=int(settings["RSYNC_RETRIES"])
4368 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
4369 except SystemExit, e:
4370 raise # Needed else can't exit
4372 maxretries=3 #default number of retries
4375 user_name, hostname, port = re.split(
4376 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
4379 if user_name is None:
4381 updatecache_flg=True
4382 all_rsync_opts = set(rsync_opts)
4383 lexer = shlex.shlex(StringIO.StringIO(
4384 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")), posix=True)
4385 lexer.whitespace_split = True
4386 extra_rsync_opts = list(lexer)
4388 all_rsync_opts.update(extra_rsync_opts)
4389 family = socket.AF_INET
4390 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
4391 family = socket.AF_INET
4392 elif socket.has_ipv6 and \
4393 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
4394 family = socket.AF_INET6
4401 for addrinfo in socket.getaddrinfo(
4402 hostname, None, family, socket.SOCK_STREAM):
4403 if addrinfo[0] == socket.AF_INET6:
4404 # IPv6 addresses need to be enclosed in square brackets
4405 ips.append("[%s]" % addrinfo[4][0])
4407 ips.append(addrinfo[4][0])
4408 from random import shuffle
4410 except SystemExit, e:
4411 raise # Needed else can't exit
4412 except Exception, e:
4413 print "Notice:",str(e)
4418 dosyncuri = syncuri.replace(
4419 "//" + user_name + hostname + port + "/",
4420 "//" + user_name + ips[0] + port + "/", 1)
4421 except SystemExit, e:
4422 raise # Needed else can't exit
4423 except Exception, e:
4424 print "Notice:",str(e)
4428 if "--ask" in myopts:
4429 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
4434 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
4435 if "--quiet" not in myopts:
4436 print ">>> Starting rsync with "+dosyncuri+"..."
4438 emergelog(xterm_titles,
4439 ">>> Starting retry %d of %d with %s" % \
4440 (retries,maxretries,dosyncuri))
4441 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
4443 if mytimestamp != 0 and "--quiet" not in myopts:
4444 print ">>> Checking server timestamp ..."
4446 rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
4448 if "--debug" in myopts:
4453 # Even if there's no timestamp available locally, fetch the
4454 # timestamp anyway as an initial probe to verify that the server is
4455 # responsive. This protects us from hanging indefinitely on a
4456 # connection attempt to an unresponsive server which rsync's
4457 # --timeout option does not prevent.
4459 mycommand = rsynccommand[:]
4460 mycommand.append(dosyncuri.rstrip("/") + \
4461 "/metadata/timestamp.chk")
4462 mycommand.append(tmpservertimestampfile)
4466 def timeout_handler(signum, frame):
4467 raise portage.exception.PortageException("timed out")
4468 signal.signal(signal.SIGALRM, timeout_handler)
4469 # Timeout here in case the server is unresponsive. The
4470 # --timeout rsync option doesn't apply to the initial
4471 # connection attempt.
4472 if rsync_initial_timeout:
4473 signal.alarm(rsync_initial_timeout)
4475 mypids.extend(portage.process.spawn(
4476 mycommand, env=settings.environ(), returnpid=True))
4477 exitcode = os.waitpid(mypids[0], 0)[1]
4478 content = portage.grabfile(tmpservertimestampfile)
4480 if rsync_initial_timeout:
4483 os.unlink(tmpservertimestampfile)
4486 except portage.exception.PortageException, e:
4490 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
4491 os.kill(mypids[0], signal.SIGTERM)
4492 os.waitpid(mypids[0], 0)
4493 # This is the same code rsync uses for timeout.
4496 if exitcode != os.EX_OK:
4498 exitcode = (exitcode & 0xff) << 8
4500 exitcode = exitcode >> 8
4502 portage.process.spawned_pids.remove(mypids[0])
4505 servertimestamp = time.mktime(time.strptime(
4506 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
4507 except (OverflowError, ValueError):
4509 del mycommand, mypids, content
4510 if exitcode == os.EX_OK:
4511 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
4512 emergelog(xterm_titles,
4513 ">>> Cancelling sync -- Already current.")
4516 print ">>> Timestamps on the server and in the local repository are the same."
4517 print ">>> Cancelling all further sync action. You are already up to date."
4519 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4523 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
4524 emergelog(xterm_titles,
4525 ">>> Server out of date: %s" % dosyncuri)
4528 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
4530 print ">>> In order to force sync, remove '%s'." % servertimestampfile
4533 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
4535 mycommand = rsynccommand + [dosyncuri+"/", myportdir]
4536 exitcode = portage.process.spawn(mycommand,
4537 env=settings.environ())
4538 if exitcode in [0,1,3,4,11,14,20,21]:
4540 elif exitcode in [1,3,4,11,14,20,21]:
4543 # Code 2 indicates protocol incompatibility, which is expected
4544 # for servers with protocol < 29 that don't support
4545 # --prune-empty-directories. Retry for a server that supports
4546 # at least rsync protocol version 29 (>=rsync-2.6.4).
4551 if retries<=maxretries:
4552 print ">>> Retrying..."
4557 updatecache_flg=False
4561 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
4565 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
4566 print darkred("!!!")+green(" that your SYNC statement is proper.")
4567 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
4569 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
4570 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
4571 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
4572 print darkred("!!!")+green(" and try again after the problem has been fixed.")
4573 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
4575 print darkred("!!!")+green(" Rsync was killed before it finished.")
4577 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
4578 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
4579 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
4580 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
4581 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
4584 elif syncuri[:6]=="cvs://":
4585 if not os.path.exists("/usr/bin/cvs"):
4586 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
4587 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
4590 cvsdir=os.path.dirname(myportdir)
4591 if not os.path.exists(myportdir+"/CVS"):
4593 print ">>> Starting initial cvs checkout with "+syncuri+"..."
4594 if os.path.exists(cvsdir+"/gentoo-x86"):
4595 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
4600 if e.errno != errno.ENOENT:
4602 "!!! existing '%s' directory; exiting.\n" % myportdir)
4605 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
4606 print "!!! cvs checkout error; exiting."
4608 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
4611 print ">>> Starting cvs update with "+syncuri+"..."
4612 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
4613 myportdir, settings, free=1)
4614 if retval != os.EX_OK:
4618 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
4621 if updatecache_flg and \
4622 myaction != "metadata" and \
4623 "metadata-transfer" not in settings.features:
4624 updatecache_flg = False
4626 # Reload the whole config from scratch.
4627 settings, trees, mtimedb = load_emerge_config(trees=trees)
4628 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4630 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
4631 action_metadata(settings, portdb, myopts)
4633 if portage._global_updates(trees, mtimedb["updates"]):
4635 # Reload the whole config from scratch.
4636 settings, trees, mtimedb = load_emerge_config(trees=trees)
4637 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4639 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
4640 mypvs = portage.best(
4641 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
4643 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
4645 if myaction != "metadata":
4646 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
4647 retval = portage.process.spawn(
4648 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
4649 dosyncuri], env=settings.environ())
4650 if retval != os.EX_OK:
4651 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
4653 if(mybestpv != mypvs) and not "--quiet" in myopts:
4655 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
4656 print red(" * ")+"that you update portage now, before any other packages are updated."
4657 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
4658 print red(" * ")+"configuration files."
4659 print red(" * ")+"To update portage, run 'emerge portage'."
4662 display_news_notification(trees)
4664 def action_metadata(settings, portdb, myopts):
4665 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
4666 old_umask = os.umask(0002)
4667 cachedir = os.path.normpath(settings.depcachedir)
4668 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
4669 "/lib", "/opt", "/proc", "/root", "/sbin",
4670 "/sys", "/tmp", "/usr", "/var"]:
4671 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
4672 "ROOT DIRECTORY ON YOUR SYSTEM."
4673 print >> sys.stderr, \
4674 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
4676 if not os.path.exists(cachedir):
4679 ec = portage.eclass_cache.cache(portdb.porttree_root)
4680 myportdir = os.path.realpath(settings["PORTDIR"])
4681 cm = settings.load_best_module("portdbapi.metadbmodule")(
4682 myportdir, "metadata/cache", portage.auxdbkeys[:])
4684 from portage.cache import util
4686 class percentage_noise_maker(util.quiet_mirroring):
4687 def __init__(self, dbapi):
4689 self.cp_all = dbapi.cp_all()
4690 l = len(self.cp_all)
4691 self.call_update_min = 100000000
4692 self.min_cp_all = l/100.0
4697 for x in self.cp_all:
4699 if self.count > self.min_cp_all:
4700 self.call_update_min = 0
4702 for y in self.dbapi.cp_list(x):
4704 self.call_update_mine = 0
4706 def update(self, *arg):
4707 try: self.pstr = int(self.pstr) + 1
4708 except ValueError: self.pstr = 1
4709 sys.stdout.write("%s%i%%" % \
4710 ("\b" * (len(str(self.pstr))+1), self.pstr))
4712 self.call_update_min = 10000000
4714 def finish(self, *arg):
4715 sys.stdout.write("\b\b\b\b100%\n")
4718 if "--quiet" in myopts:
4719 def quicky_cpv_generator(cp_all_list):
4720 for x in cp_all_list:
4721 for y in portdb.cp_list(x):
4723 source = quicky_cpv_generator(portdb.cp_all())
4724 noise_maker = portage.cache.util.quiet_mirroring()
4726 noise_maker = source = percentage_noise_maker(portdb)
4727 portage.cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
4728 eclass_cache=ec, verbose_instance=noise_maker)
4733 def action_regen(settings, portdb):
4734 xterm_titles = "notitles" not in settings.features
4735 emergelog(xterm_titles, " === regen")
4736 #regenerate cache entries
4737 print "Regenerating cache entries... "
4739 os.close(sys.stdin.fileno())
4740 except SystemExit, e:
4741 raise # Needed else can't exit
4745 mynodes = portdb.cp_all()
4746 from portage.cache.cache_errors import CacheError
4748 for mytree in portdb.porttrees:
4750 dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
4751 except CacheError, e:
4752 print "\n error listing cache entries for " + \
4753 "'%s': %s, continuing..." % (mytree, e)
4758 mymatches = portdb.cp_list(x)
4759 portage.writemsg_stdout("processing %s\n" % x)
4762 foo = portdb.aux_get(y,["DEPEND"])
4763 except SystemExit, e:
4764 # sys.exit is an exception... And consequently, we can't catch it.
4766 except Exception, e:
4767 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
4769 for mytree in portdb.porttrees:
4770 if portdb.findname2(y, mytree=mytree)[0]:
4771 dead_nodes[mytree].discard(y)
4773 for mytree, nodes in dead_nodes.iteritems():
4774 auxdb = portdb.auxdb[mytree]
4778 except (KeyError, CacheError):
4782 def action_config(settings, trees, myopts, myfiles):
4783 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
4784 print red("!!! config can only take a single package atom at this time\n")
4786 if not is_valid_package_atom(myfiles[0]):
4787 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
4789 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
4790 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
4794 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
4795 except ValueError, e:
4796 # Multiple matches thrown from cpv_expand
4799 print "No packages found.\n"
4802 if "--ask" in myopts:
4804 print "Please select a package to configure:"
4808 options.append(str(idx))
4809 print options[-1]+") "+pkg
4812 idx = userquery("Selection?", options)
4815 pkg = pkgs[int(idx)-1]
4817 print "The following packages available:"
4820 print "\nPlease use a specific atom or the --ask option."
4826 if "--ask" in myopts:
4827 if userquery("Ready to configure "+pkg+"?") == "No":
4830 print "Configuring pkg..."
4832 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
4833 mysettings = portage.config(clone=settings)
4834 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
4835 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
4836 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
4839 def action_info(settings, trees, myopts, myfiles):
4840 unameout=commands.getstatusoutput("uname -mrp")[1]
4841 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4842 settings.profile_path, settings["CHOST"],
4843 trees[settings["ROOT"]]["vartree"].dbapi)
4845 header_title = "System Settings"
4847 print header_width * "="
4848 print header_title.rjust(int(header_width/2 + len(header_title)/2))
4849 print header_width * "="
4850 print "System uname: "+unameout
4851 gentoo_release = portage.grabfile(os.path.join(
4852 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
4854 print gentoo_release[0]
4856 print "Unknown Host Operating System"
4857 lastSync = portage.grabfile(os.path.join(
4858 settings["PORTDIR"], "metadata", "timestamp.chk"))
4859 print "Timestamp of tree:",
4865 output=commands.getstatusoutput("distcc --version")
4867 print str(output[1].split("\n",1)[0]),
4868 if "distcc" in settings.features:
4873 output=commands.getstatusoutput("ccache -V")
4875 print str(output[1].split("\n",1)[0]),
4876 if "ccache" in settings.features:
4881 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
4882 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
4883 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
4884 myvars = portage.util.unique_array(myvars)
4888 if portage.isvalidatom(x):
4889 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
4890 pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
4891 pkg_matches.sort(portage.pkgcmp)
4893 for pn, ver, rev in pkg_matches:
4895 pkgs.append(ver + "-" + rev)
4899 pkgs = ", ".join(pkgs)
4900 print "%-20s %s" % (x+":", pkgs)
4902 print "%-20s %s" % (x+":", "[NOT VALID]")
4904 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
4906 if "--verbose" in myopts:
4907 myvars=settings.keys()
4909 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
4910 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
4911 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
4912 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
4914 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
4916 myvars = portage.util.unique_array(myvars)
4922 print '%s="%s"' % (x, settings[x])
4924 use = set(settings["USE"].split())
4925 use_expand = settings["USE_EXPAND"].split()
4927 for varname in use_expand:
4928 flag_prefix = varname.lower() + "_"
4930 if f.startswith(flag_prefix):
4934 print 'USE="%s"' % " ".join(use),
4935 for varname in use_expand:
4936 myval = settings.get(varname)
4938 print '%s="%s"' % (varname, myval),
4941 unset_vars.append(x)
4943 print "Unset: "+", ".join(unset_vars)
4946 if "--debug" in myopts:
4947 for x in dir(portage):
4948 module = getattr(portage, x)
4949 if "cvs_id_string" in dir(module):
4950 print "%s: %s" % (str(x), str(module.cvs_id_string))
4952 # See if we can find any packages installed matching the strings
4953 # passed on the command line
4955 vardb = trees[settings["ROOT"]]["vartree"].dbapi
4956 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4958 mypkgs.extend(vardb.match(x))
4960 # If some packages were found...
4962 # Get our global settings (we only print stuff if it varies from
4963 # the current config)
4964 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
4965 auxkeys = mydesiredvars + [ "USE", "IUSE"]
4967 pkgsettings = portage.config(clone=settings)
4969 for myvar in mydesiredvars:
4970 global_vals[myvar] = set(settings.get(myvar, "").split())
4972 # Loop through each package
4973 # Only print settings if they differ from global settings
4974 header_printed = False
4976 # Get all package specific variables
4977 auxvalues = vardb.aux_get(pkg, auxkeys)
4979 for i in xrange(len(auxkeys)):
4980 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
4982 for myvar in mydesiredvars:
4983 # If the package variable doesn't match the
4984 # current global variable, something has changed
4985 # so set diff_found so we know to print
4986 if valuesmap[myvar] != global_vals[myvar]:
4987 diff_values[myvar] = valuesmap[myvar]
4988 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
4989 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
4991 # If a matching ebuild is no longer available in the tree, maybe it
4992 # would make sense to compare against the flags for the best
4993 # available version with the same slot?
4995 if portdb.cpv_exists(pkg):
4997 pkgsettings.setcpv(pkg, mydb=mydb)
4998 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
5000 diff_values["USE"] = valuesmap["USE"]
5001 # If a difference was found, print the info for
5005 # If we have not yet printed the header,
5007 if not header_printed:
5008 header_title = "Package Settings"
5009 print header_width * "="
5010 print header_title.rjust(int(header_width/2 + len(header_title)/2))
5011 print header_width * "="
5012 header_printed = True
5014 # Print package info
5015 print "%s was built with the following:" % pkg
5016 for myvar in mydesiredvars + ["USE"]:
5017 if myvar in diff_values:
5018 mylist = list(diff_values[myvar])
5020 print "%s=\"%s\"" % (myvar, " ".join(mylist))
5023 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
5025 print "emerge: no search terms provided."
5027 searchinstance = search(settings, portdb,
5028 vartree, spinner, "--searchdesc" in myopts,
5029 "--quiet" not in myopts)
5030 for mysearch in myfiles:
5032 searchinstance.execute(mysearch)
5033 except re.error, comment:
5034 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
5036 searchinstance.output()
5038 def action_depclean(settings, trees, ldpath_mtimes,
5040 # Kill packages that aren't explicitly merged or are required as a
5041 # dependency of another package. World file is explicit.
5043 warn_prefix = colorize("BAD", "*** WARNING *** ")
5045 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
5046 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
5047 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
5049 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
5050 print warn_prefix + "mistakes. Packages that are part of the world set will always"
5051 print warn_prefix + "be kept. They can be manually added to this set with"
5052 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
5053 print warn_prefix + "package.provided (see portage(5)) will be removed by"
5054 print warn_prefix + "depclean, even if they are part of the world set."
5056 print warn_prefix + "As a safety measure, depclean will not remove any packages"
5057 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
5058 print warn_prefix + "consequence, it is often necessary to run "
5059 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
5061 xterm_titles = "notitles" not in settings.features
5062 myroot = settings["ROOT"]
5063 dep_check_trees = {}
5064 dep_check_trees[myroot] = {}
5065 dep_check_trees[myroot]["vartree"] = \
5066 FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
5067 vardb = dep_check_trees[myroot]["vartree"].dbapi
5068 # Constrain dependency selection to the installed packages.
5069 dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
5070 syslist = getlist(settings, "system")
5071 worldlist = getlist(settings, "world")
5072 system_world_dict = genericdict(worldlist)
5073 system_world_dict.update(genericdict(syslist))
5074 fakedb = portage.fakedbapi(settings=settings)
5075 myvarlist = vardb.cpv_all()
5078 print "\n!!! You have no system list.",
5080 print "\n!!! You have no world file.",
5082 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
5084 if not (syslist and worldlist and myvarlist):
5085 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
5086 print " break your installation.\n"
5087 if "--pretend" not in myopts:
5088 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
5090 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
5091 emergelog(xterm_titles, " >>> depclean")
5093 if "--quiet" not in myopts:
5094 print "\nCalculating dependencies ",
5098 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
5099 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
5101 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
5103 while remaining_atoms:
5104 atom, parent, priority = remaining_atoms.pop()
5105 pkgs = vardb.match(atom)
5107 if not atom.startswith("!") and priority == hard:
5108 unresolveable.setdefault(atom, []).append(parent)
5110 if portage.dep_getkey(atom) not in system_world_dict:
5111 # Prune all but the best matching slot, since that's all that a
5112 # deep world update would pull in. Don't prune if the cpv is in
5113 # system or world though, since those sets trigger greedy update
5115 pkgs = [portage.best(pkgs)]
5117 if fakedb.cpv_exists(pkg):
5120 fakedb.cpv_inject(pkg)
5121 myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
5123 if myopts.get("--with-bdeps", "y") == "y":
5124 mydeps.append((myaux["DEPEND"], soft))
5126 mydeps.append((" ".join(myaux.values()), hard))
5127 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
5128 for depstr, priority in mydeps:
5133 if "--debug" in myopts:
5135 print "Parent: ", pkg
5136 print "Depstring:", depstr
5138 if priority == soft:
5144 portage.dep._dep_check_strict = False
5145 success, atoms = portage.dep_check(depstr, None, settings,
5146 myuse=usedef, trees=dep_check_trees, myroot=myroot)
5148 portage.dep._dep_check_strict = True
5150 show_invalid_depstring_notice(
5151 ("installed", myroot, pkg, "nomerge"),
5155 if "--debug" in myopts:
5156 print "Candidates:", atoms
5159 remaining_atoms.append((atom, pkg, priority))
5161 if "--quiet" not in myopts:
5162 print "\b\b... done!\n"
5165 print "Dependencies could not be completely resolved due to"
5166 print "the following required packages not being installed:"
5168 for atom in unresolveable:
5169 print atom, "required by", " ".join(unresolveable[atom])
5171 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
5172 print "depclean? It may be necessary to manually uninstall packages that no longer"
5173 print "exist in the portage tree since it may not be possible to satisfy their"
5174 print "dependencies. Also, be aware of the --with-bdeps option that is documented"
5175 print "in " + good("`man emerge`") + "."
5179 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
5182 unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
5183 "unmerge", cleanlist, ldpath_mtimes)
5185 print "Packages installed: "+str(len(myvarlist))
5186 print "Packages in world: "+str(len(worldlist))
5187 print "Packages in system: "+str(len(syslist))
5188 print "Unique package names: "+str(len(myvarlist))
5189 print "Required packages: "+str(len(fakedb.cpv_all()))
5190 if "--pretend" in myopts:
5191 print "Number to remove: "+str(len(cleanlist))
5193 print "Number removed: "+str(len(cleanlist))
5195 def action_build(settings, trees, mtimedb,
5196 myopts, myaction, myfiles, spinner):
5197 ldpath_mtimes = mtimedb["ldpath"]
5199 if "--quiet" not in myopts and \
5200 ("--pretend" in myopts or "--ask" in myopts or \
5201 "--tree" in myopts or "--verbose" in myopts):
5203 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5207 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
5209 print darkgreen("These are the packages that would be %s, in reverse order:") % action
5213 print darkgreen("These are the packages that would be %s, in order:") % action
5216 # validate the state of the resume data
5217 # so that we can make assumptions later.
5218 for k in ("resume", "resume_backup"):
5220 if "mergelist" in mtimedb[k]:
5221 if not mtimedb[k]["mergelist"]:
5226 if "--resume" in myopts and \
5227 ("resume" in mtimedb or
5228 "resume_backup" in mtimedb):
5229 if "resume" not in mtimedb:
5230 mtimedb["resume"] = mtimedb["resume_backup"]
5231 del mtimedb["resume_backup"]
5233 # XXX: "myopts" is a list for backward compatibility.
5234 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
5236 for opt in ("--skipfirst", "--ask", "--tree"):
5237 myresumeopts.pop(opt, None)
5239 for myopt, myarg in myopts.iteritems():
5240 if myopt not in myresumeopts:
5241 myresumeopts[myopt] = myarg
5244 # Adjust config according to options of the command being resumed.
5245 for myroot in trees:
5246 mysettings = trees[myroot]["vartree"].settings
5248 adjust_config(myopts, mysettings)
5250 del myroot, mysettings
5252 myparams = create_depgraph_params(myopts, myaction)
5253 if "--quiet" not in myopts and "--nodeps" not in myopts:
5254 print "Calculating dependencies ",
5255 mydepgraph = depgraph(settings, trees,
5256 myopts, myparams, spinner)
5257 if "--quiet" not in myopts and "--nodeps" not in myopts:
5258 print "\b\b... done!"
5260 if ("--resume" in myopts):
5261 print darkgreen("emerge: It seems we have nothing to resume...")
5264 myparams = create_depgraph_params(myopts, myaction)
5265 if myaction in ["system","world"]:
5266 if "--quiet" not in myopts and "--nodeps" not in myopts:
5267 print "Calculating",myaction,"dependencies ",
5269 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
5270 if not mydepgraph.xcreate(myaction):
5271 print "!!! Depgraph creation failed."
5273 if "--quiet" not in myopts and "--nodeps" not in myopts:
5274 print "\b\b... done!"
5276 if "--quiet" not in myopts and "--nodeps" not in myopts:
5277 print "Calculating dependencies ",
5279 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
5281 retval, favorites = mydepgraph.select_files(myfiles)
5282 except portage.exception.PackageNotFound, e:
5283 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
5287 if "--quiet" not in myopts and "--nodeps" not in myopts:
5288 print "\b\b... done!"
5290 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
5291 sys.stderr.write(red("The following binaries are not available for merging...\n"))
5293 if mydepgraph.missingbins:
5294 for x in mydepgraph.missingbins:
5295 sys.stderr.write(" "+str(x)+"\n")
5296 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
5299 if "--pretend" not in myopts and \
5300 ("--ask" in myopts or "--tree" in myopts or \
5301 "--verbose" in myopts) and \
5302 not ("--quiet" in myopts and "--ask" not in myopts):
5303 if "--resume" in myopts:
5304 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5305 mymergelist = mtimedb["resume"]["mergelist"]
5306 if "--skipfirst" in myopts:
5307 mymergelist = mymergelist[1:]
5308 if len(mymergelist) == 0:
5309 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5311 mydepgraph.display(mymergelist)
5312 prompt="Would you like to resume merging these packages?"
5315 mydepgraph.altlist(reversed=("--tree" in myopts)))
5317 for x in mydepgraph.altlist():
5318 if x[0] != "blocks" and x[3] != "nomerge":
5320 #check for blocking dependencies
5321 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
5322 print "\n!!! Error: The above package list contains packages which cannot be installed"
5323 print "!!! at the same time on the same system."
5324 if "--quiet" not in myopts:
5325 show_blocker_docs_link()
5328 if "--noreplace" in myopts and favorites:
5331 print " %s %s" % (good("*"), x)
5332 prompt="Would you like to add these packages to your world favorites?"
5333 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5334 prompt="Nothing to merge; would you like to auto-clean packages?"
5337 print "Nothing to merge; quitting."
5340 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5341 prompt="Would you like to fetch the source files for these packages?"
5343 prompt="Would you like to merge these packages?"
5345 if "--ask" in myopts and userquery(prompt) == "No":
5350 # Don't ask again (e.g. when auto-cleaning packages after merge)
5351 myopts.pop("--ask", None)
5353 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5354 if ("--resume" in myopts):
5355 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
5356 mymergelist = mtimedb["resume"]["mergelist"]
5357 if "--skipfirst" in myopts:
5358 mymergelist = mymergelist[1:]
5359 if len(mymergelist) == 0:
5360 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5362 mydepgraph.display(mymergelist)
5365 mydepgraph.altlist(reversed=("--tree" in myopts)))
5366 if "--buildpkgonly" in myopts and \
5367 not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5368 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5369 print "!!! You have to merge the dependencies before you can build this package.\n"
5372 if ("--buildpkgonly" in myopts):
5373 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5374 print "\n!!! --buildpkgonly requires all dependencies to be merged."
5375 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
5378 if ("--resume" in myopts):
5379 favorites=mtimedb["resume"]["favorites"]
5380 mergetask = MergeTask(settings, trees, myopts)
5381 if "--fetchonly" in myopts:
5382 """ parallel-fetch uses --resume --fetchonly and we don't want
5383 it to write the mtimedb"""
5384 mtimedb.filename = None
5385 time.sleep(3) # allow the parent to have first fetch
5387 retval = mergetask.merge(
5388 mtimedb["resume"]["mergelist"], favorites, mtimedb)
5389 if retval != os.EX_OK:
5392 if "resume" in mtimedb and \
5393 "mergelist" in mtimedb["resume"] and \
5394 len(mtimedb["resume"]["mergelist"]) > 1:
5395 mtimedb["resume_backup"] = mtimedb["resume"]
5396 del mtimedb["resume"]
5398 mtimedb["resume"]={}
5399 # XXX: Stored as a list for backward compatibility.
5400 mtimedb["resume"]["myopts"] = \
5401 [k for k in myopts if myopts[k] is True]
5402 mtimedb["resume"]["favorites"]=favorites
5403 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5404 for pkgline in mydepgraph.altlist():
5405 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5406 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
5407 tmpsettings = portage.config(clone=settings)
5409 if settings.get("PORTAGE_DEBUG", "") == "1":
5411 retval = portage.doebuild(
5412 y, "digest", settings["ROOT"], tmpsettings, edebug,
5413 ("--pretend" in myopts),
5414 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
5416 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5418 for pkg in mydepgraph.altlist():
5419 if pkg[0] != "blocks":
5422 pkglist = mydepgraph.altlist()
5424 mergetask = MergeTask(settings, trees, myopts)
5425 retval = mergetask.merge(pkglist, favorites, mtimedb)
5426 if retval != os.EX_OK:
5429 if mtimedb.has_key("resume"):
5430 del mtimedb["resume"]
5431 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5432 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5433 vartree = trees[settings["ROOT"]]["vartree"]
5434 unmerge(settings, myopts, vartree, "clean", ["world"],
5435 ldpath_mtimes, autoclean=1)
5437 portage.writemsg_stdout(colorize("WARN", "WARNING:")
5438 + " AUTOCLEAN is disabled. This can cause serious"
5439 + " problems due to overlapping packages.\n")
5441 def multiple_actions(action1, action2):
5442 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
5443 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
5446 def parse_opts(tmpcmdline, silent=False):
5451 global actions, options, shortmapping
5453 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
5454 argument_options = {
5456 "help":"specify the location for portage configuration files",
5460 "help":"enable or disable color output",
5462 "choices":("y", "n")
5465 "help":"include unnecessary build time dependencies",
5467 "choices":("y", "n")
5470 "help":"specify conditions to trigger package reinstallation",
5472 "choices":["changed-use"]
5476 from optparse import OptionParser
5477 parser = OptionParser()
5478 if parser.has_option("--help"):
5479 parser.remove_option("--help")
5481 for action_opt in actions:
5482 parser.add_option("--" + action_opt, action="store_true",
5483 dest=action_opt.replace("-", "_"), default=False)
5484 for myopt in options:
5485 parser.add_option(myopt, action="store_true",
5486 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5487 for shortopt, longopt in shortmapping.iteritems():
5488 parser.add_option("-" + shortopt, action="store_true",
5489 dest=longopt.lstrip("--").replace("-", "_"), default=False)
5490 for myalias, myopt in longopt_aliases.iteritems():
5491 parser.add_option(myalias, action="store_true",
5492 dest=myopt.lstrip("--").replace("-", "_"), default=False)
5494 for myopt, kwargs in argument_options.iteritems():
5495 parser.add_option(myopt,
5496 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
5498 myoptions, myargs = parser.parse_args(args=tmpcmdline)
5500 for myopt in options:
5501 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
5503 myopts[myopt] = True
5505 for myopt in argument_options:
5506 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
5510 for action_opt in actions:
5511 v = getattr(myoptions, action_opt.replace("-", "_"))
5514 multiple_actions(myaction, action_opt)
5516 myaction = action_opt
5519 if x in actions and myaction != "search":
5520 if not silent and x not in ["system", "world"]:
5521 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
5522 # special case "search" so people can search for action terms, e.g. emerge -s sync
5524 multiple_actions(myaction, x)
5530 if "--nocolor" in myopts:
5532 sys.stderr.write("*** Deprecated use of '--nocolor', " + \
5533 "use '--color=n' instead.\n")
5534 del myopts["--nocolor"]
5535 myopts["--color"] = "n"
5537 return myaction, myopts, myfiles
5539 def validate_ebuild_environment(trees):
5540 for myroot in trees:
5541 mysettings = trees[myroot]["vartree"].settings
5542 for var in "ARCH", "USERLAND":
5543 if mysettings.get(var):
5545 print >> sys.stderr, bad(("\a!!! %s is not set... " % var) + \
5546 "Are you missing the '%setc/make.profile' symlink?" % \
5547 mysettings["PORTAGE_CONFIGROOT"])
5548 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
5549 "Is your portage tree complete?\n")
5551 del myroot, mysettings
5553 def load_emerge_config(trees=None):
5555 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
5556 kwargs[k] = os.environ.get(envvar, None)
5557 trees = portage.create_trees(trees=trees, **kwargs)
5559 settings = trees["/"]["vartree"].settings
5561 for myroot in trees:
5563 settings = trees[myroot]["vartree"].settings
5566 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
5567 mtimedb = portage.MtimeDB(mtimedbfile)
5568 return settings, trees, mtimedb
5570 def adjust_config(myopts, settings):
5571 """Make emerge specific adjustments to the config."""
5573 # To enhance usability, make some vars case insensitive by forcing them to
5575 for myvar in ("AUTOCLEAN", "NOCOLOR"):
5576 if myvar in settings:
5577 settings[myvar] = settings[myvar].lower()
5578 settings.backup_changes(myvar)
5581 # Kill noauto as it will break merges otherwise.
5582 if "noauto" in settings.features:
5583 while "noauto" in settings.features:
5584 settings.features.remove("noauto")
5585 settings["FEATURES"] = " ".join(settings.features)
5586 settings.backup_changes("FEATURES")
5590 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
5591 except ValueError, e:
5592 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5593 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
5594 settings["CLEAN_DELAY"], noiselevel=-1)
5595 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
5596 settings.backup_changes("CLEAN_DELAY")
5598 EMERGE_WARNING_DELAY = 10
5600 EMERGE_WARNING_DELAY = int(settings.get(
5601 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
5602 except ValueError, e:
5603 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5604 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
5605 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
5606 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
5607 settings.backup_changes("EMERGE_WARNING_DELAY")
5609 if "--quiet" in myopts:
5610 settings["PORTAGE_QUIET"]="1"
5611 settings.backup_changes("PORTAGE_QUIET")
5613 # Set so that configs will be merged regardless of remembered status
5614 if ("--noconfmem" in myopts):
5615 settings["NOCONFMEM"]="1"
5616 settings.backup_changes("NOCONFMEM")
5618 # Set various debug markers... They should be merged somehow.
5621 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
5622 if PORTAGE_DEBUG not in (0, 1):
5623 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
5624 PORTAGE_DEBUG, noiselevel=-1)
5625 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
5628 except ValueError, e:
5629 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
5630 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
5631 settings["PORTAGE_DEBUG"], noiselevel=-1)
5633 if "--debug" in myopts:
5635 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
5636 settings.backup_changes("PORTAGE_DEBUG")
5638 if settings.get("NOCOLOR") not in ("yes","true"):
5639 portage.output.havecolor = 1
5641 """The explicit --color < y | n > option overrides the NOCOLOR environment
5642 variable and stdout auto-detection."""
5643 if "--color" in myopts:
5644 if "y" == myopts["--color"]:
5645 portage.output.havecolor = 1
5646 settings["NOCOLOR"] = "false"
5648 portage.output.havecolor = 0
5649 settings["NOCOLOR"] = "true"
5650 settings.backup_changes("NOCOLOR")
5651 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
5652 portage.output.havecolor = 0
5653 settings["NOCOLOR"] = "true"
5654 settings.backup_changes("NOCOLOR")
5657 global portage # NFC why this is necessary now - genone
5658 # Disable color until we're sure that it should be enabled (after
5659 # EMERGE_DEFAULT_OPTS has been parsed).
5660 portage.output.havecolor = 0
5661 # This first pass is just for options that need to be known as early as
5662 # possible, such as --config-root. They will be parsed again later,
5663 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
5664 # the value of --config-root).
5665 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
5666 if "--debug" in myopts:
5667 os.environ["PORTAGE_DEBUG"] = "1"
5668 if "--config-root" in myopts:
5669 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
5671 # Portage needs to ensure a sane umask for the files it creates.
5673 settings, trees, mtimedb = load_emerge_config()
5674 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5677 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
5678 except (OSError, ValueError), e:
5679 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
5680 settings["PORTAGE_NICENESS"])
5681 portage.writemsg("!!! %s\n" % str(e))
5684 if portage._global_updates(trees, mtimedb["updates"]):
5686 # Reload the whole config from scratch.
5687 settings, trees, mtimedb = load_emerge_config(trees=trees)
5688 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5690 xterm_titles = "notitles" not in settings.features
5693 if "--ignore-default-opts" not in myopts:
5694 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
5695 tmpcmdline.extend(sys.argv[1:])
5696 myaction, myopts, myfiles = parse_opts(tmpcmdline)
5698 if "--digest" in myopts:
5699 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
5700 # Reload the whole config from scratch so that the portdbapi internal
5701 # config is updated with new FEATURES.
5702 settings, trees, mtimedb = load_emerge_config(trees=trees)
5703 portdb = trees[settings["ROOT"]]["porttree"].dbapi
5705 for myroot in trees:
5706 mysettings = trees[myroot]["vartree"].settings
5708 adjust_config(myopts, mysettings)
5710 del myroot, mysettings
5712 spinner = stdout_spinner()
5713 if "candy" in settings.features:
5714 spinner.update = spinner.update_scroll
5716 if "--quiet" not in myopts:
5717 portage.deprecated_profile_check()
5719 #Freeze the portdbapi for enhanced performance:
5720 for myroot in trees:
5721 trees[myroot]["porttree"].dbapi.freeze()
5724 if "moo" in myfiles:
5727 Larry loves Gentoo (""" + os.uname()[0] + """)
5729 _______________________
5730 < Have you mooed today? >
5731 -----------------------
5740 if (myaction in ["world", "system"]) and myfiles:
5741 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
5745 ext = os.path.splitext(x)[1]
5746 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
5747 print "emerging by path implies --oneshot... adding --oneshot to options."
5748 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
5751 if ("--tree" in myopts) and ("--columns" in myopts):
5752 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
5755 if ("--quiet" in myopts):
5756 spinner.update = spinner.update_quiet
5757 portage.util.noiselimit = -1
5759 # Always create packages if FEATURES=buildpkg
5760 # Imply --buildpkg if --buildpkgonly
5761 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
5762 if "--buildpkg" not in myopts:
5763 myopts["--buildpkg"] = True
5765 # Also allow -S to invoke search action (-sS)
5766 if ("--searchdesc" in myopts):
5767 if myaction and myaction != "search":
5768 myfiles.append(myaction)
5769 if "--search" not in myopts:
5770 myopts["--search"] = True
5773 # Always try and fetch binary packages if FEATURES=getbinpkg
5774 if ("getbinpkg" in settings.features):
5775 myopts["--getbinpkg"] = True
5777 if "--skipfirst" in myopts and "--resume" not in myopts:
5778 myopts["--resume"] = True
5780 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
5781 myopts["--usepkgonly"] = True
5783 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
5784 myopts["--getbinpkg"] = True
5786 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
5787 myopts["--usepkg"] = True
5789 # Also allow -K to apply --usepkg/-k
5790 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
5791 myopts["--usepkg"] = True
5793 # Allow -p to remove --ask
5794 if ("--pretend" in myopts) and ("--ask" in myopts):
5795 print ">>> --pretend disables --ask... removing --ask from options."
5798 # forbid --ask when not in a terminal
5799 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
5800 if ("--ask" in myopts) and (not sys.stdin.isatty()):
5801 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
5805 if settings.get("PORTAGE_DEBUG", "") == "1":
5806 spinner.update = spinner.update_quiet
5808 if "python-trace" in settings.features:
5809 import portage.debug
5810 portage.debug.set_trace(True)
5812 if ("--resume" in myopts):
5813 if "--tree" in myopts:
5814 print "* --tree is currently broken with --resume. Disabling..."
5815 del myopts["--tree"]
5817 if not ("--quiet" in myopts):
5818 if not sys.stdout.isatty() or ("--nospinner" in myopts):
5819 spinner.update = spinner.update_basic
5821 if "--version" in myopts:
5822 print getportageversion(settings["PORTDIR"], settings["ROOT"],
5823 settings.profile_path, settings["CHOST"],
5824 trees[settings["ROOT"]]["vartree"].dbapi)
5826 elif "--help" in myopts:
5827 emerge.help.help(myaction, myopts, portage.output.havecolor)
5830 if "--debug" in myopts:
5831 print "myaction", myaction
5832 print "myopts", myopts
5834 if not myaction and not myfiles and "--resume" not in myopts:
5835 emerge.help.help(myaction, myopts, portage.output.havecolor)
5838 # check if root user is the current user for the actions where emerge needs this
5839 if portage.secpass < 2:
5840 # We've already allowed "--version" and "--help" above.
5841 if "--pretend" not in myopts and myaction not in ("search","info"):
5842 need_superuser = not \
5843 ("--fetchonly" in myopts or \
5844 "--fetch-all-uri" in myopts or \
5845 myaction in ("metadata", "regen") or \
5846 (myaction == "sync" and os.access(settings["PORTDIR"], os.W_OK)))
5847 if portage.secpass < 1 or \
5850 access_desc = "superuser"
5852 access_desc = "portage group"
5853 # Always show portage_group_warning() when only portage group
5854 # access is required but the user is not in the portage group.
5855 from portage.data import portage_group_warning
5856 if "--ask" in myopts:
5857 myopts["--pretend"] = True
5859 print ("%s access is required... " + \
5860 "adding --pretend to options.\n") % access_desc
5861 if portage.secpass < 1 and not need_superuser:
5862 portage_group_warning()
5864 sys.stderr.write(("emerge: %s access is " + \
5865 "required.\n\n") % access_desc)
5866 if portage.secpass < 1 and not need_superuser:
5867 portage_group_warning()
5870 disable_emergelog = False
5871 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
5873 disable_emergelog = True
5875 if myaction in ("search", "info"):
5876 disable_emergelog = True
5877 if disable_emergelog:
5878 """ Disable emergelog for everything except build or unmerge
5879 operations. This helps minimize parallel emerge.log entries that can
5880 confuse log parsers. We especially want it disabled during
5881 parallel-fetch, which uses --resume --fetchonly."""
5883 def emergelog(*pargs, **kargs):
5886 if not "--pretend" in myopts:
5887 emergelog(xterm_titles, "Started emerge on: "+\
5888 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
5891 myelogstr=" ".join(myopts)
5893 myelogstr+=" "+myaction
5895 myelogstr+=" "+" ".join(myfiles)
5896 emergelog(xterm_titles, " *** emerge " + myelogstr)
5898 def emergeexitsig(signum, frame):
5899 signal.signal(signal.SIGINT, signal.SIG_IGN)
5900 signal.signal(signal.SIGTERM, signal.SIG_IGN)
5901 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
5902 sys.exit(100+signum)
5903 signal.signal(signal.SIGINT, emergeexitsig)
5904 signal.signal(signal.SIGTERM, emergeexitsig)
5907 """This gets out final log message in before we quit."""
5908 if "--pretend" not in myopts:
5909 emergelog(xterm_titles, " *** terminating.")
5910 if "notitles" not in settings.features:
5912 portage.atexit_register(emergeexit)
5914 if myaction in ("config", "metadata", "regen", "sync"):
5915 if "--pretend" in myopts:
5916 sys.stderr.write(("emerge: The '%s' action does " + \
5917 "not support '--pretend'.\n") % myaction)
5919 if "sync" == myaction:
5920 action_sync(settings, trees, mtimedb, myopts, myaction)
5921 elif "metadata" == myaction:
5922 action_metadata(settings, portdb, myopts)
5923 elif myaction=="regen":
5924 validate_ebuild_environment(trees)
5925 action_regen(settings, portdb)
5927 elif "config"==myaction:
5928 validate_ebuild_environment(trees)
5929 action_config(settings, trees, myopts, myfiles)
5932 elif "info"==myaction:
5933 action_info(settings, trees, myopts, myfiles)
5936 elif "search"==myaction:
5937 validate_ebuild_environment(trees)
5938 action_search(settings, portdb, trees["/"]["vartree"],
5939 myopts, myfiles, spinner)
5940 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
5941 validate_ebuild_environment(trees)
5942 vartree = trees[settings["ROOT"]]["vartree"]
5943 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
5945 if "--pretend" not in myopts:
5946 post_emerge(trees, mtimedb, os.EX_OK)
5948 elif "depclean"==myaction:
5949 validate_ebuild_environment(trees)
5950 action_depclean(settings, trees, mtimedb["ldpath"],
5952 if "--pretend" not in myopts:
5953 post_emerge(trees, mtimedb, os.EX_OK)
5954 # "update", "system", or just process files:
5956 validate_ebuild_environment(trees)
5957 if "--pretend" not in myopts:
5958 display_news_notification(trees)
5959 action_build(settings, trees, mtimedb,
5960 myopts, myaction, myfiles, spinner)
5961 if "--pretend" not in myopts:
5962 post_emerge(trees, mtimedb, os.EX_OK)
5964 display_news_notification(trees)
5966 if __name__ == "__main__":
5967 retval = emerge_main()