2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
7 # This block ensures that ^C interrupts are handled quietly.
11 def exithandler(signum,frame):
12 signal.signal(signal.SIGINT, signal.SIG_IGN)
13 signal.signal(signal.SIGTERM, signal.SIG_IGN)
16 signal.signal(signal.SIGINT, exithandler)
17 signal.signal(signal.SIGTERM, exithandler)
18 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
20 except KeyboardInterrupt:
25 os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
29 sys.path.insert(0, "/usr/lib/portage/pym")
31 del os.environ["PORTAGE_LEGACY_GLOBALS"]
32 from portage import digraph
34 import emergehelp, xpak, commands, errno, re, socket, string, time, types
36 from output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
37 havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
38 xtermTitleReset, yellow
39 from output import create_color_func
40 good = create_color_func("GOOD")
41 bad = create_color_func("BAD")
45 import portage_exception
46 from portage_data import secpass
48 if not hasattr(__builtins__, "set"):
49 from sets import Set as set
51 class stdout_spinner(object):
53 "Gentoo Rocks ("+os.uname()[0]+")",
54 "Thank you for using Gentoo. :)",
55 "Are you actually trying to read this?",
56 "How many times have you stared at this?",
57 "We are generating the cache right now",
58 "You are paying too much attention.",
59 "A theory is better than its explanation.",
60 "Phasers locked on target, Captain.",
61 "Thrashing is just virtual crashing.",
62 "To be is to program.",
63 "Real Users hate Real Programmers.",
64 "When all else fails, read the instructions.",
65 "Functionality breeds Contempt.",
66 "The future lies ahead.",
67 "3.1415926535897932384626433832795028841971694",
68 "Sometimes insanity is the only alternative.",
69 "Inaccuracy saves a world of explanation.",
72 twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
76 self.update = self.update_twirl
77 self.scroll_sequence = self.scroll_msgs[
78 int(time.time() * 100) % len(self.scroll_msgs)]
80 def update_basic(self):
81 self.spinpos = (self.spinpos + 1) % 500
82 if (self.spinpos % 100) == 0:
84 sys.stdout.write(". ")
89 def update_scroll(self):
90 if(self.spinpos >= len(self.scroll_sequence)):
91 sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
92 len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
94 sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
96 self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
98 def update_twirl(self):
99 self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
100 sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
103 def update_quiet(self):
110 os.path.normpath("//foo") returns "//foo" instead of "/foo"
111 We dislike this behavior so we create our own normpath func
114 if mystr and (mystr[0]=='/'):
115 return os.path.normpath("///"+mystr)
117 return os.path.normpath(mystr)
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("["+string.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):
155 def sorted_versions(verlist):
158 verparts = ver.split("-")
159 if len(verparts) == 2:
160 verrev = int(verparts[1][1:])
165 retparts = ret[x].split("-")
166 verdiff = portage.vercmp(retparts[0], verparts[0])
170 if len(retparts) == 2:
171 retrev = int(retparts[1][1:])
182 "clean", "config", "depclean",
184 "prune", "regen", "search",
185 "sync", "system", "unmerge", "world",
188 "--ask", "--alphabetical",
189 "--buildpkg", "--buildpkgonly",
190 "--changelog", "--columns",
194 "--fetchonly", "--fetch-all-uri",
195 "--getbinpkg", "--getbinpkgonly",
196 "--help", "--ignore-default-opts",
198 "--newuse", "--nocolor",
199 "--nodeps", "--noreplace",
200 "--nospinner", "--oneshot",
201 "--onlydeps", "--pretend",
202 "--quiet", "--resume",
203 "--searchdesc", "--selective",
207 "--usepkg", "--usepkgonly",
208 "--verbose", "--version"
214 "b":"--buildpkg", "B":"--buildpkgonly",
215 "c":"--clean", "C":"--unmerge",
216 "d":"--debug", "D":"--deep",
218 "f":"--fetchonly", "F":"--fetch-all-uri",
219 "g":"--getbinpkg", "G":"--getbinpkgonly",
221 "k":"--usepkg", "K":"--usepkgonly",
223 "n":"--noreplace", "N":"--newuse",
224 "o":"--onlydeps", "O":"--nodeps",
225 "p":"--pretend", "P":"--prune",
227 "s":"--search", "S":"--searchdesc",
230 "v":"--verbose", "V":"--version"
233 def emergelog(xterm_titles, mystr, short_msg=None):
236 xtermTitle(short_msg)
240 file_path = "/var/log/emerge.log"
241 mylogfile = open(file_path, "a")
242 portage_util.apply_secpass_permissions(file_path,
243 uid=portage.portage_uid, gid=portage.portage_gid,
247 mylock = portage_locks.lockfile(mylogfile)
248 # seek because we may have gotten held up by the lock.
249 # if so, we may not be positioned at the end of the file.
251 mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
255 portage_locks.unlockfile(mylock)
257 except (IOError,OSError,portage_exception.PortageException), e:
259 print >> sys.stderr, "emergelog():",e
261 def countdown(secs=5, doing="Starting"):
263 print ">>> Waiting",secs,"seconds before starting..."
264 print ">>> (Control-C to abort)...\n"+doing+" in: ",
268 sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
273 # formats a size given in bytes nicely
274 def format_size(mysize):
275 if type(mysize) not in [types.IntType,types.LongType]:
277 mystr=str(mysize/1024)
281 mystr=mystr[:mycount]+","+mystr[mycount:]
285 def getgccversion(chost):
288 return: the current in-use gcc version
291 gcc_ver_command = 'gcc -dumpversion'
292 gcc_ver_prefix = 'gcc-'
294 gcc_not_found_error = red(
295 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
296 "!!! to update the environment of this terminal and possibly\n" +
297 "!!! other terminals also.\n"
300 mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
301 if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
302 part1, part2 = myoutput.split("/")
303 if part1.startswith(chost + "-"):
304 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
306 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
307 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
308 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
310 mystatus, myoutput = commands.getstatusoutput(
311 chost + "-" + gcc_ver_command)
312 if mystatus == os.EX_OK:
313 return gcc_ver_prefix + myoutput
315 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
316 if mystatus == os.EX_OK:
317 return gcc_ver_prefix + myoutput
319 portage.writemsg(gcc_not_found_error, noiselevel=-1)
320 return "[unavailable]"
322 def getportageversion(portdir, target_root, profile, chost, vardb):
323 profilever = "unavailable"
325 realpath = os.path.realpath(profile)
326 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
327 if realpath.startswith(basepath):
328 profilever = realpath[1 + len(basepath):]
331 profilever = "!" + os.readlink(profile)
334 del realpath, basepath
337 libclist = vardb.match("virtual/libc")
338 libclist += vardb.match("virtual/glibc")
339 libclist = portage_util.unique_array(libclist)
341 xs=portage.catpkgsplit(x)
343 libcver+=","+string.join(xs[1:], "-")
345 libcver=string.join(xs[1:], "-")
347 libcver="unavailable"
349 gccver = getgccversion(chost)
350 unameout=os.uname()[2]+" "+os.uname()[4]
352 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
354 def create_depgraph_params(myopts, myaction):
355 #configure emerge engine parameters
357 # self: include _this_ package regardless of if it is merged.
358 # selective: exclude the package if it is merged
359 # recurse: go into the dependencies
360 # deep: go into the dependencies of already merged packages
361 # empty: pretend nothing is merged
362 myparams = ["recurse"]
365 if "--update" in myopts or \
366 "--newuse" in myopts or \
367 "--noreplace" in myopts or \
368 myaction in ("system", "world"):
369 add.extend(["selective"])
370 if "--emptytree" in myopts:
371 add.extend(["empty"])
372 sub.extend(["selective"])
373 if "--nodeps" in myopts:
374 sub.extend(["recurse"])
375 if "--deep" in myopts:
378 if (x not in myparams) and (x not in sub):
385 # search functionality
397 def __init__(self, settings, portdb, vartree, spinner, searchdesc,
399 """Searches the available and installed packages for the supplied search key.
400 The list of available and installed packages is created at object instantiation.
401 This makes successive searches faster."""
402 self.settings = settings
404 self.vartree = vartree
405 self.spinner = spinner
406 self.verbose = verbose
407 self.searchdesc = searchdesc
409 def execute(self,searchkey):
410 """Performs the search for the supplied search key"""
412 self.searchkey=searchkey
413 self.packagematches = []
416 self.matches = {"pkg":[], "desc":[]}
419 self.matches = {"pkg":[]}
420 print "Searching... ",
423 if self.searchkey[0] == '%':
425 self.searchkey = self.searchkey[1:]
426 if self.searchkey[0] == '@':
428 self.searchkey = self.searchkey[1:]
430 self.searchre=re.compile(self.searchkey,re.I)
432 self.searchre=re.compile(re.escape(self.searchkey), re.I)
433 for package in self.portdb.cp_all():
434 self.spinner.update()
437 match_string = package[:]
439 match_string = package.split("/")[-1]
442 if self.searchre.search(match_string):
443 if not self.portdb.xmatch("match-visible", package):
445 self.matches["pkg"].append([package,masked])
446 elif self.searchdesc: # DESCRIPTION searching
447 full_package = self.portdb.xmatch("bestmatch-visible", package)
449 #no match found; we don't want to query description
450 full_package = portage.best(
451 self.portdb.xmatch("match-all", package))
457 full_desc = self.portdb.aux_get(
458 full_package, ["DESCRIPTION"])[0]
460 print "emerge: search: aux_get() failed, skipping"
462 if self.searchre.search(full_desc):
463 self.matches["desc"].append([full_package,masked])
465 for mtype in self.matches.keys():
466 self.matches[mtype].sort()
467 self.mlen += len(self.matches[mtype])
470 """Outputs the results of the search."""
471 print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
472 print "[ Applications found : "+white(str(self.mlen))+" ]"
474 for mtype in self.matches.keys():
475 for match,masked in self.matches[mtype]:
478 full_package = self.portdb.xmatch(
479 "bestmatch-visible", match)
481 #no match found; we don't want to query description
483 full_package = portage.best(
484 self.portdb.xmatch("match-all",match))
487 match = portage.pkgsplit(match)[0]
491 desc, homepage, license = self.portdb.aux_get(
492 full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
494 print "emerge: search: aux_get() failed, skipping"
497 print green("*")+" "+white(match)+" "+red("[ Masked ]")
499 print green("*")+" "+white(match)
500 myversion = self.getVersion(full_package, search.VERSION_RELEASE)
503 mycat = match.split("/")[0]
504 mypkg = match.split("/")[1]
505 mycpv = match + "-" + myversion
506 myebuild = self.portdb.findname(mycpv)
507 pkgdir = os.path.dirname(myebuild)
508 import portage_manifest
509 mf = portage_manifest.Manifest(
510 pkgdir, self.settings["DISTDIR"])
511 fetchlist = self.portdb.getfetchlist(mycpv,
512 mysettings=self.settings, all=True)[1]
514 mysum[0] = mf.getDistfilesSize(fetchlist)
515 mystr = str(mysum[0]/1024)
519 mystr=mystr[:mycount]+","+mystr[mycount:]
522 mysum[0] = "Unknown (missing digest for %s)" % str(e)
525 print " ", darkgreen("Latest version available:"),myversion
526 print " ", self.getInstallationStatus(mycat+'/'+mypkg)
527 print " ", darkgreen("Size of files:"),mysum[0]
528 print " ", darkgreen("Homepage:")+" ",homepage
529 print " ", darkgreen("Description:")+" ",desc
530 print " ", darkgreen("License:")+" ",license
536 def getInstallationStatus(self,package):
537 installed_package = self.vartree.dep_bestmatch(package)
539 version = self.getVersion(installed_package,search.VERSION_RELEASE)
541 result = darkgreen("Latest version installed:")+" "+version
543 result = darkgreen("Latest version installed:")+" [ Not Installed ]"
546 def getVersion(self,full_package,detail):
547 if len(full_package) > 1:
548 package_parts = portage.catpkgsplit(full_package)
549 if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
550 result = package_parts[2]+ "-" + package_parts[3]
552 result = package_parts[2]
558 #build our package digraph
559 def getlist(settings, mode):
561 mylines = settings.packages
564 file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
565 myfile = open(file_path, "r")
566 mylines = myfile.readlines()
568 except (OSError, IOError), e:
569 if e.errno == errno.ENOENT:
570 portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
576 myline=string.join(string.split(x))
585 mynewlines.append(myline.strip())
587 # Remove everything that is package.provided from our list
588 for atom in mynewlines[:]:
589 for expanded_atom in portage.flatten(
590 portage.dep_virtual([atom], settings)):
591 mykey = portage.dep_getkey(expanded_atom)
592 if mykey in settings.pprovideddict and \
593 portage.match_from_list(
594 expanded_atom, settings.pprovideddict[mykey]):
595 mynewlines.remove(atom)
600 def clean_world(vardb, cpv):
601 """Remove a package from the world file when unmerged."""
602 world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
603 worldlist = portage_util.grabfile(world_filename)
604 mykey = portage.cpv_getkey(cpv)
607 if portage.dep_getkey(x) == mykey:
608 matches = vardb.match(x, use_cache=0)
612 elif len(matches) == 1 and matches[0] == cpv:
616 #others are around; keep it.
617 newworldlist.append(x)
619 #this doesn't match the package we're unmerging; keep it.
620 newworldlist.append(x)
622 portage_util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
623 gid=portage.portage_gid, mode=02770)
624 portage_util.write_atomic(world_filename, "\n".join(newworldlist))
626 def genericdict(mylist):
629 mynewdict[portage.dep_getkey(x)]=x
632 def filter_iuse_defaults(iuse):
634 if flag.startswith("+"):
639 class DepPriority(object):
641 This class generates an integer priority level based of various
642 attributes of the dependency relationship. Attributes can be assigned
643 at any time and the new integer value will be generated on calls to the
644 __int__() method. Rich comparison operators are supported.
646 The boolean attributes that affect the integer value are "satisfied",
647 "buildtime", "runtime", and "system". Various combinations of
648 attributes lead to the following priority levels:
650 Combination of properties Priority level
652 not satisfied and buildtime 0
653 not satisfied and runtime -1
654 satisfied and buildtime -2
655 satisfied and runtime -3
656 (none of the above) -4
658 Several integer constants are defined for categorization of priority
661 MEDIUM The upper boundary for medium dependencies.
662 SOFT The upper boundary for soft dependencies.
663 MIN The lower boundary for soft dependencies.
665 __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
669 def __init__(self, **kwargs):
670 for myattr in self.__slots__:
671 if myattr == "__weakref__":
673 myvalue = kwargs.get(myattr, False)
674 setattr(self, myattr, myvalue)
676 if not self.satisfied:
686 def __lt__(self, other):
687 return int(self) < other
688 def __le__(self, other):
689 return int(self) <= other
690 def __eq__(self, other):
691 return int(self) == other
692 def __ne__(self, other):
693 return int(self) != other
694 def __gt__(self, other):
695 return int(self) > other
696 def __ge__(self, other):
697 return int(self) >= other
700 return copy.copy(self)
703 if myvalue > self.MEDIUM:
705 if myvalue > self.SOFT:
714 "installed":"vartree"}
716 def __init__(self, settings, trees, myopts, myparams, spinner):
717 self.settings = settings
718 self.target_root = settings["ROOT"]
721 self.myparams = myparams
723 if settings.get("PORTAGE_DEBUG", "") == "1":
725 self.spinner = spinner
726 self.pkgsettings = {}
727 self.pkg_node_map = {}
728 for myroot in self.trees:
729 self.pkgsettings[myroot] = portage.config(
730 clone=trees[myroot]["vartree"].settings)
731 self.pkg_node_map[myroot] = {}
733 self.useFlags[self.target_root] = {}
734 if self.target_root != "/":
735 self.useFlags["/"] = {}
738 self.digraph=portage.digraph()
740 self.outdatedpackages=[]
742 self.mydbapi["/"] = portage.fakedbapi(settings=settings)
743 vardb = self.trees["/"]["vartree"].dbapi
744 fakedb = self.mydbapi["/"]
745 if "empty" not in self.myparams or self.target_root != "/":
746 for pkg in vardb.cpv_all():
747 myslot = vardb.aux_get(pkg, ["SLOT"])[0]
748 fakedb.cpv_inject(pkg, metadata={"SLOT":myslot})
749 if self.target_root != "/":
750 self.mydbapi[self.target_root] = \
751 portage.fakedbapi(settings=settings)
752 vardb = self.trees[self.target_root]["vartree"].dbapi
753 fakedb = self.mydbapi[self.target_root]
754 if "empty" not in self.myparams:
755 for pkg in vardb.cpv_all():
756 myslot = vardb.aux_get(pkg, ["SLOT"])[0]
757 fakedb.cpv_inject(pkg, metadata={"SLOT":myslot})
758 if "--usepkg" in self.myopts:
759 trees["/"]["bintree"].populate(
760 "--getbinpkg" in self.myopts, "--getbinpkgonly" in self.myopts)
761 if self.target_root != "/":
762 trees[self.target_root]["bintree"].populate(
763 "--getbinpkg" in self.myopts,
764 "--getbinpkgonly" in self.myopts)
766 self.global_updates = {}
767 self.blocker_digraph = digraph()
768 self.blocker_parents = {}
769 self._altlist_cache = {}
771 def create(self, mybigkey, myparent=None, addme=1, myuse=None,
772 priority=DepPriority(), rev_dep=False, arg=None):
774 Fills the digraph with nodes comprised of packages to merge.
775 mybigkey is the package spec of the package to merge.
776 myparent is the package depending on mybigkey ( or None )
777 addme = Should we add this package to the digraph or are we just looking at it's deps?
778 Think --onlydeps, we need to ignore packages in that case.
781 #IUSE-aware emerge -> USE DEP aware depgraph
782 #"no downgrade" emerge
784 jbigkey = " ".join(mybigkey) + " merge"
785 mytype, myroot, mykey = mybigkey
786 if self.digraph.hasnode(jbigkey):
787 if addme and jbigkey != myparent:
788 # Refuse to make a node depend on itself so that the we don't
789 # don't create a bogus circular dependency in self.altlist().
790 self.pkg_node_map[myroot][mykey] = jbigkey
791 if rev_dep and myparent:
792 ptype, proot, pkey, pstatus = myparent.split()
793 self.pkg_node_map[proot][pkey] = myparent
794 self.digraph.addnode(myparent, jbigkey, priority=priority)
796 self.digraph.addnode(jbigkey, myparent, priority=priority)
798 jbigkey = " ".join(mybigkey) + " nomerge"
799 if self.digraph.hasnode(jbigkey):
800 self.pkg_node_map[myroot][mykey] = jbigkey
801 if rev_dep and myparent:
802 ptype, proot, pkey, pstatus = myparent.split()
803 self.pkg_node_map[proot][pkey] = myparent
804 self.digraph.addnode(myparent, jbigkey, priority=priority)
806 self.digraph.addnode(jbigkey, myparent, priority=priority)
809 self.spinner.update()
810 if mytype == "blocks":
811 if addme and "--buildpkgonly" not in self.myopts and myparent:
812 mybigkey[1] = myparent.split()[1]
813 self.blocker_parents.setdefault(
814 " ".join(mybigkey), set()).add(myparent)
817 arg = portage.best_match_to_list(mykey, self.args_keys)
818 # select the correct /var database that we'll be checking against
819 vardbapi = self.trees[myroot]["vartree"].dbapi
820 portdb = self.trees[myroot]["porttree"].dbapi
821 bindb = self.trees[myroot]["bintree"].dbapi
822 pkgsettings = self.pkgsettings[myroot]
824 # if the package is already on the system, we add a "nomerge"
825 # directive, otherwise we add a "merge" directive.
827 mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
830 self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
831 myuse = self.pkgsettings[myroot]["USE"].split()
832 self.useFlags[myroot][mykey] = myuse
835 if mytype == "installed":
837 if addme and mytype != "installed":
838 # this is where we add the node to the list of packages to merge
839 if "selective" in self.myparams or not arg:
840 if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
843 """ If we aren't merging, perform the --newuse check.
844 If the package has new iuse flags or different use flags then if
845 --newuse is specified, we need to merge the package. """
846 if merging==0 and "--newuse" in self.myopts and \
847 mytype == "ebuild" and \
848 vardbapi.cpv_exists(mykey):
849 pkgsettings.setcpv(mykey, mydb=portdb)
851 forced_flags.update(pkgsettings.useforce)
852 forced_flags.update(pkgsettings.usemask)
853 old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
854 iuses = set(filter_iuse_defaults(
855 mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
856 old_iuse = set(filter_iuse_defaults(
857 vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
858 if iuses.symmetric_difference(
859 old_iuse).difference(forced_flags):
861 elif old_iuse.intersection(old_use) != \
862 iuses.intersection(myuse):
865 if addme and merging == 1:
866 mybigkey.append("merge")
868 mybigkey.append("nomerge")
870 if merging == 0 and vardbapi.cpv_exists(mykey):
871 myuse = vardbapi.aux_get(mykey, ["USE"])[0].split()
872 self.useFlags[myroot][mykey] = myuse
874 """ At this point, we have either hit a blocker and returned, found the package in the
875 depgraph already and returned, or we are here. Whether we are merging or not; we must
876 add the package to the depgraph; so we do that here. """
877 jbigkey = " ".join(mybigkey)
878 self.pkg_node_map[myroot][mykey] = jbigkey
879 if rev_dep and myparent:
880 ptype, proot, pkey, pstatus = myparent.split()
881 self.pkg_node_map[proot][pkey] = myparent
882 self.digraph.addnode(myparent, jbigkey,
885 self.digraph.addnode(jbigkey, myparent,
889 myslot = mydbapi.aux_get(mykey, ["SLOT"])[0]
890 self.mydbapi[myroot].cpv_inject(mykey, metadata={"SLOT":myslot})
892 """ This section determines whether we go deeper into dependencies or not.
893 We want to go deeper on a few occasions:
894 Installing package A, we need to make sure package A's deps are met.
895 emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
896 If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
898 if "deep" not in self.myparams and not merging and \
899 not ("--update" in self.myopts and arg and merging):
901 elif "recurse" not in self.myparams:
904 """ Check DEPEND/RDEPEND/PDEPEND/SLOT
905 Pull from bintree if it's binary package, porttree if it's ebuild.
906 Binpkg's can be either remote or local. """
909 depkeys = ["DEPEND","RDEPEND","PDEPEND"]
910 depvalues = mydbapi.aux_get(mykey, depkeys)
911 for i in xrange(len(depkeys)):
912 edepend[depkeys[i]] = depvalues[i]
914 if mytype == "ebuild":
915 if "--buildpkgonly" in self.myopts:
916 edepend["RDEPEND"] = ""
917 edepend["PDEPEND"] = ""
918 if not (arg and "--onlydeps" in self.myopts and \
919 mytype == "ebuild") and \
920 self.myopts.get("--with-bdeps", "n") == "n" and \
921 (mytype == "binary" or mybigkey[3] == "nomerge"):
922 edepend["DEPEND"] = ""
924 """ We have retrieve the dependency information, now we need to recursively
925 process them. DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
927 mp=string.join(mybigkey)
930 if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
931 myuse=myuse, priority=DepPriority(buildtime=True),
934 """RDEPEND is soft by definition. However, in order to ensure
935 correct merge order, we make it a hard dependency. Otherwise, a
936 build time dependency might not be usable due to it's run time
937 dependencies not being installed yet.
939 if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
940 myuse=myuse, priority=DepPriority(runtime=True),
943 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
944 # Post Depend -- Add to the list without a parent, as it depends
945 # on a package being present AND must be built after that package.
946 if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
947 myuse=myuse, priority=DepPriority(), rev_deps=True,
950 except ValueError, e:
952 portage.writemsg("\n\n!!! An atom in the dependencies " + \
953 "is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
955 portage.writemsg(" %s\n" % cpv, noiselevel=-1)
956 portage.writemsg("\n", noiselevel=-1)
957 if mytype == "binary":
959 "!!! This binary package cannot be installed: '%s'\n" % \
960 mykey, noiselevel=-1)
961 elif mytype == "ebuild":
962 myebuild, mylocation = portdb.findname2(mykey)
963 portage.writemsg("!!! This ebuild cannot be installed: " + \
964 "'%s'\n" % myebuild, noiselevel=-1)
965 portage.writemsg("!!! Please notify the package maintainer " + \
966 "that atoms must be fully-qualified.\n", noiselevel=-1)
970 def select_files(self,myfiles):
971 "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
973 myroot = self.target_root
974 portdb = self.trees[myroot]["porttree"].dbapi
975 bindb = self.trees[myroot]["bintree"].dbapi
976 pkgsettings = self.pkgsettings[myroot]
979 matches = portdb.gvisible(portdb.visible(mylist))
980 return [x for x in mylist \
981 if x in matches or not portdb.cpv_exists(x)]
983 ext = os.path.splitext(x)[1]
985 if not os.path.exists(x):
987 os.path.join(pkgsettings["PKGDIR"], "All", x)):
988 x = os.path.join(pkgsettings["PKGDIR"], "All", x)
990 os.path.join(pkgsettings["PKGDIR"], x)):
991 x = os.path.join(pkgsettings["PKGDIR"], x)
993 print "\n\n!!! Binary package '"+str(x)+"' does not exist."
994 print "!!! Please ensure the tbz2 exists as specified.\n"
997 mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
998 if os.path.realpath(x) != \
999 os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
1000 print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
1002 if not self.create(["binary", myroot, mykey],
1003 None, "--onlydeps" not in self.myopts):
1004 return (0,myfavorites)
1005 elif not "--oneshot" in self.myopts:
1006 myfavorites.append(mykey)
1007 elif ext==".ebuild":
1008 x = os.path.realpath(x)
1009 mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
1010 ebuild_path = portdb.findname(mykey)
1012 if os.path.realpath(ebuild_path) != x:
1013 print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
1015 if mykey not in portdb.xmatch(
1016 "match-visible", portage.dep_getkey(mykey)):
1017 print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
1018 print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
1019 print colorize("BAD", "*** page for details.")
1020 countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
1023 raise portage_exception.PackageNotFound(
1024 "%s is not in a valid portage tree hierarchy or does not exist" % x)
1025 if not self.create(["ebuild", myroot, mykey],
1026 None, "--onlydeps" not in self.myopts):
1027 return (0,myfavorites)
1028 elif not "--oneshot" in self.myopts:
1029 myfavorites.append(mykey)
1031 if not is_valid_package_atom(x):
1032 portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
1034 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1035 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1039 if "--usepkg" in self.myopts:
1040 mykey = portage.dep_expand(x, mydb=bindb,
1041 settings=pkgsettings)
1042 if (mykey and not mykey.startswith("null/")) or \
1043 "--usepkgonly" in self.myopts:
1044 arg_atoms.append((x, mykey))
1047 mykey = portage.dep_expand(x,
1048 mydb=portdb, settings=pkgsettings)
1049 arg_atoms.append((x, mykey))
1050 except ValueError, errpkgs:
1051 print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
1052 print "!!! one of the following fully-qualified ebuild names instead:\n"
1053 for i in errpkgs[0]:
1054 print " " + green(i)
1058 if "--update" in self.myopts:
1059 """Make sure all installed slots are updated when possible. Do this
1060 with --emptytree also, to ensure that all slots are remerged."""
1061 vardb = self.trees[self.target_root]["vartree"].dbapi
1063 for myarg, myatom in arg_atoms:
1064 greedy_atoms.append((myarg, myatom))
1066 for cpv in vardb.match(myatom):
1067 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1070 if "--usepkg" in self.myopts:
1071 mymatches = bindb.match(myatom)
1072 if "--usepkgonly" not in self.myopts:
1073 mymatches = visible(mymatches)
1074 best_pkg = portage.best(mymatches)
1076 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1077 best_pkgs.append(("binary", best_pkg, best_slot))
1078 if "--usepkgonly" not in self.myopts:
1079 best_pkg = portage.best(portdb.match(myatom))
1081 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1082 best_pkgs.append(("ebuild", best_pkg, best_slot))
1084 best_pkg = portage.best([x[1] for x in best_pkgs])
1085 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1086 best_slot = best_pkgs[0][2]
1087 myslots.add(best_slot)
1088 if len(myslots) > 1:
1089 for myslot in myslots:
1090 myslot_atom = "%s:%s" % \
1091 (portage.dep_getkey(myatom), myslot)
1093 if "--usepkgonly" not in self.myopts and \
1094 self.trees[self.target_root][
1095 "porttree"].dbapi.match(myslot_atom):
1097 elif "--usepkg" in self.myopts:
1098 mymatches = bindb.match(myslot_atom)
1099 if "--usepkgonly" not in self.myopts:
1100 mymatches = visible(mymatches)
1104 greedy_atoms.append((myarg, myslot_atom))
1105 arg_atoms = greedy_atoms
1107 """ These are used inside self.create() in order to ensure packages
1108 that happen to match arguments are not incorrectly marked as nomerge."""
1109 self.args_keys = [x[1] for x in arg_atoms]
1110 for myarg, myatom in arg_atoms:
1112 self.mysd = self.select_dep(myroot, myatom, arg=myarg)
1113 except portage_exception.MissingSignature, e:
1114 portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
1115 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1116 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1117 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1118 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1120 except portage_exception.InvalidSignature, e:
1121 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
1122 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
1123 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
1124 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
1125 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
1127 except SystemExit, e:
1128 raise # Needed else can't exit
1129 except Exception, e:
1130 print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
1131 print >> sys.stderr, "!!!", str(e), e.__module__
1135 return (0,myfavorites)
1136 elif not "--oneshot" in self.myopts:
1137 mykey = portage.dep_getkey(myatom)
1138 if mykey not in myfavorites:
1139 myfavorites.append(mykey)
1142 if "--usepkgonly" in self.myopts:
1143 for x in self.digraph.all_nodes():
1145 if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
1149 print "Missing binary for:",xs[2]
1151 self.validate_blockers()
1153 # We're true here unless we are missing binaries.
1154 return (not missing,myfavorites)
1156 def is_newer_ver_installed(self,myroot,pkg,pkgver):
1157 "if there is a version of pkg installed newer than pkgver, return it"
1158 vardbapi = self.trees[myroot]["vartree"].dbapi
1160 matches = self.trees[myroot]["vartree"].dbapi.match(pkg)
1162 myslot = self.trees[myroot]["porttree"].getslot(pkgver)
1163 for match in matches:
1164 if portage.pkgcmp(portage.catpkgsplit(pkgver)[1:], portage.catpkgsplit(match)[1:]) < 0:
1165 curslot = self.trees[myroot]["vartree"].getslot(match)
1166 if curslot == myslot:
1169 def select_dep(self, myroot, depstring, myparent=None, arg=None,
1170 myuse=None, raise_on_missing=False, priority=DepPriority(),
1171 rev_deps=False, parent_arg=None):
1172 """ Given a depstring, create the depgraph such that all dependencies are satisfied.
1173 myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
1174 myparent = the node whose depstring is being passed in
1175 arg = package was specified on the command line, merge even if it's already installed
1176 myuse = USE flags at present
1177 raise_on_missing = Given that the depgraph is not proper, raise an exception if true
1178 else continue trying.
1179 return 1 on success, 0 for failure
1182 portdb = self.trees[myroot]["porttree"].dbapi
1183 bindb = self.trees[myroot]["bintree"].dbapi
1184 vardb = self.trees[myroot]["vartree"].dbapi
1185 pkgsettings = self.pkgsettings[myroot]
1187 if "--debug" in self.myopts:
1189 print "Parent: ",myparent
1190 print "Depstring:",depstring
1192 print "Reverse:", rev_deps
1193 print "Priority:", priority
1195 #processing dependencies
1196 """ Call portage.dep_check to evaluate the use? conditionals and make sure all
1197 dependencies are satisfiable. """
1198 mycheck = portage.dep_check(depstring, self.mydbapi[myroot],
1199 pkgsettings, myuse=myuse,
1200 use_binaries=("--usepkgonly" in self.myopts),
1201 myroot=myroot, trees=self.trees, return_all_deps=True)
1204 sys.stderr.write("\n\n%s\n\n" % mycheck[1])
1205 sys.stderr.write("%s\n\n" % depstring)
1207 mymerge = mycheck[1]
1210 # The parent is added after it's own dep_check call so that it
1211 # isn't allowed to satisfy a direct bootstrap dependency on itself
1212 # via an old-style virtual. This isn't a problem with new-style
1213 # virtuals, which are preferenced in dep_zapdeps by looking only at
1214 # the depstring, vdb, and available packages.
1216 p_type, p_root, p_key, p_status = myparent.split()
1217 if p_status == "merge":
1218 # Update old-style virtuals if this package provides any.
1219 # These are needed for dep_virtual calls inside dep_check.
1220 self.pkgsettings[p_root].setinst(p_key,
1221 self.trees[p_root][self.pkg_tree_map[p_type]].dbapi)
1223 if "--debug" in self.myopts:
1224 print "Candidates:",mymerge
1228 selected_pkg = ["blocks", myroot, x[1:], None]
1230 #We are not processing a blocker but a normal dependency
1232 """In some cases, dep_check will return deps that shouldn't
1233 be proccessed any further, so they are identified and
1235 if "empty" not in self.myparams and \
1236 "deep" not in self.myparams and \
1237 not ("--update" in self.myopts and parent_arg) and \
1241 pkg_key = portage.dep_getkey(x)
1242 if pkg_key in pkgsettings.pprovideddict and \
1243 portage.match_from_list(
1244 x, pkgsettings.pprovideddict[pkg_key]):
1247 # List of acceptable packages, ordered by type preference.
1248 matched_packages = []
1249 myeb_matches = portdb.xmatch("match-visible", x)
1251 if "--usepkgonly" not in self.myopts:
1252 myeb = portage.best(myeb_matches)
1255 if "--usepkg" in self.myopts:
1256 # The next line assumes the binarytree has been populated.
1257 # XXX: Need to work out how we use the binary tree with roots.
1258 myeb_pkg_matches = bindb.match(x)
1259 if "--usepkgonly" not in self.myopts:
1260 # Remove any binary package entries that are masked in the portage tree (#55871)
1261 myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
1262 if pkg in myeb_matches or \
1263 not portdb.cpv_exists(pkg)]
1264 if myeb_pkg_matches:
1265 myeb_pkg = portage.best(myeb_pkg_matches)
1267 if myeb_pkg and "--newuse" in self.myopts:
1268 iuses = set(filter_iuse_defaults(
1269 bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
1270 old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
1272 if "--usepkgonly" not in self.myopts and myeb:
1275 pkgsettings.setcpv(myeb, mydb=mydb)
1277 pkgsettings.setcpv(myeb_pkg, mydb=mydb)
1278 now_use = pkgsettings["USE"].split()
1279 forced_flags = set()
1280 forced_flags.update(pkgsettings.useforce)
1281 forced_flags.update(pkgsettings.usemask)
1283 if "--usepkgonly" not in self.myopts and myeb:
1284 cur_iuse = set(filter_iuse_defaults(
1285 portdb.aux_get(myeb, ["IUSE"])[0].split()))
1286 if iuses.symmetric_difference(
1287 cur_iuse).difference(forced_flags):
1289 elif iuses.intersection(old_use) != \
1290 cur_iuse.intersection(now_use):
1294 self.trees[myroot]["bintree"].dbapi.aux_get(
1295 myeb_pkg, ["USE"])[0].split()
1296 matched_packages.append(
1297 ["binary", myroot, myeb_pkg, binpkguseflags])
1299 if "--usepkgonly" not in self.myopts and myeb_matches:
1300 matched_packages.append(
1301 ["ebuild", myroot, myeb, None])
1303 if not matched_packages and \
1304 not (arg and "selective" not in self.myparams):
1305 """Fall back to the installed package database. This is a
1306 last resort because the metadata tends to diverge from that
1307 of the ebuild in the tree."""
1308 myeb_inst_matches = vardb.match(x)
1309 if "--usepkgonly" not in self.myopts:
1310 """ TODO: Improve masking check for installed and
1311 binary packages. bug #149816"""
1312 myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
1313 if not portdb.cpv_exists(pkg)]
1315 if myeb_inst_matches:
1316 myeb_inst = portage.best(myeb_inst_matches)
1318 binpkguseflags = vardb.aux_get(
1319 myeb_inst, ["USE"])[0].split()
1320 matched_packages.append(
1321 ["installed", myroot, myeb_inst, binpkguseflags])
1322 """Now make sure that *DEPEND atoms are up to date.
1323 This is done on the fly for single packages only when
1324 necessary, since it can be time consuming to run this
1325 on all installed packages."""
1326 from portage_update import grab_updates, \
1327 parse_updates, update_dbentries
1328 if myroot not in self.global_updates:
1329 updpath = os.path.join(
1330 pkgsettings["PORTDIR"], "profiles", "updates")
1332 rawupdates = grab_updates(updpath)
1333 except portage_exception.DirectoryNotFound:
1336 for mykey, mystat, mycontent in rawupdates:
1337 commands, errors = parse_updates(mycontent)
1338 upd_commands.extend(commands)
1339 del updpath, rawupdates
1340 self.global_updates[myroot] = upd_commands
1341 upd_commands = self.global_updates[myroot]
1342 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
1343 aux_vals = vardb.aux_get(myeb_inst, aux_keys)
1344 aux_dict = dict(zip(aux_keys, aux_vals))
1345 updates = update_dbentries(upd_commands, aux_dict)
1347 vardb.aux_update(myeb_inst, updates)
1348 del binpkguseflags, myeb_inst, upd_commands, \
1349 aux_keys, aux_vals, aux_dict, updates
1351 if not matched_packages:
1352 if raise_on_missing:
1359 xfrom = '(dependency required by '+green('"'+myparent.split()[2]+'"')+red(' ['+myparent.split()[0]+"]")+')'
1360 alleb = portdb.xmatch("match-all", x)
1362 if "--usepkgonly" not in self.myopts:
1363 print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
1364 print "!!! One of the following masked packages is required to complete your request:"
1368 mreasons = portage.getmaskingstatus(p,
1369 settings=pkgsettings, portdb=portdb)
1370 print "- "+p+" (masked by: "+string.join(mreasons, ", ")+")"
1371 if "package.mask" in mreasons:
1372 comment = portage.getpmaskcomment(p,
1373 settings=pkgsettings, portdb=portdb)
1374 if comment and comment != oldcomment:
1376 oldcomment = comment
1377 licdict = portage.getlicensetexts(p, settings=pkgsettings, portdb=portdb, onlymasked=True)
1378 for lic in licdict.keys():
1379 if lic+" license" in mreasons and not lic in shown_licenses:
1380 if len(licdict[lic][1]) > 2000:
1381 print "Please read the text of license %s in %s" % (lic, licdict[lic][0])
1384 print "License text for license %s:" % lic
1386 print licdict[lic][1]
1388 shown_licenses.append(lic)
1391 print "For more information, see MASKED PACKAGES section in the emerge man page or "
1392 print "refer to the Gentoo Handbook."
1394 print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
1395 print "!!! Either add a suitable binary package or compile from an ebuild."
1397 print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
1403 if "--debug" in self.myopts:
1404 for pkg in matched_packages:
1405 print (pkg[0] + ":").rjust(10), pkg[2]
1407 if len(matched_packages) > 1:
1408 bestmatch = portage.best(
1409 [pkg[2] for pkg in matched_packages])
1410 matched_packages = [pkg for pkg in matched_packages \
1411 if pkg[2] == bestmatch]
1413 # ordered by type preference ("ebuild" type is the last resort)
1414 selected_pkg = matched_packages[0]
1417 #we are a dependency, so we want to be unconditionally added
1418 mypriority = priority.copy()
1420 mypriority.satisfied = True
1421 if not self.create(selected_pkg[0:3], myparent,
1422 myuse=selected_pkg[-1], priority=mypriority,
1423 rev_dep=rev_deps, arg=arg):
1426 #if mysource is not set, then we are a command-line dependency and should not be added
1427 #if --onlydeps is specified.
1428 if not self.create(selected_pkg[0:3], myparent,
1429 addme=("--onlydeps" not in self.myopts),
1430 myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
1433 if "--debug" in self.myopts:
1434 print "Exiting...",myparent
1437 def validate_blockers(self):
1438 """Remove any blockers from the digraph that do not match any of the
1439 packages within the graph. If necessary, create hard deps to ensure
1440 correct merge order such that mutually blocking packages are never
1441 installed simultaneously."""
1443 for blocker in self.blocker_parents.keys():
1444 mytype, myroot, mydep = blocker.split()
1445 vardb = self.trees[myroot]["vartree"].dbapi
1446 blocked_pkgs = vardb.match(mydep)
1447 blocked_after_update = self.mydbapi[myroot].match(mydep)
1448 if not blocked_pkgs and not blocked_after_update:
1449 del self.blocker_parents[blocker]
1451 """It may be possible to circumvent this block via correct
1452 ordering of upgrades. If necessary, create hard deps to
1453 enforce correct merge order."""
1454 fakedb = self.mydbapi[myroot]
1456 unresolvable = False
1457 for cpv in blocked_pkgs:
1458 myslot = vardb.aux_get(cpv, ["SLOT"])[0]
1459 myslot_atom = "%s:%s" % (portage.dep_getkey(cpv), myslot)
1460 mymatches = fakedb.match(myslot_atom)
1462 new_pkgs.append((myslot_atom, mymatches[0]))
1464 """There's an installed package that's blocked and
1465 there's no upgrade found to invalidate it, so leave
1466 this blocker in the digraph."""
1470 # Keep trying to invalidate as many blockers as possible.
1473 for parent in list(self.blocker_parents[blocker]):
1474 ptype, proot, pcpv, pstatus = parent.split()
1475 pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
1476 pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
1477 pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
1478 depends_on_merge_order = False
1479 for myslot_atom, pkg in new_pkgs:
1480 if pslot_atom == myslot_atom:
1481 """A merge within a slot invalidates the block,
1482 so the order does not need to be enforced."""
1484 if pkg in blocked_after_update:
1485 """This isn't a case of a package blocking itself,
1486 and the block is still valid in the final state, so
1487 this one is unresolvable."""
1490 # Enforce correct merge order with a hard dep.
1491 node = self.pkg_node_map[proot][pkg]
1492 self.digraph.addnode(node, parent,
1493 priority=DepPriority(buildtime=True))
1494 """Count references to this blocker so that it can be
1495 invalidated after nodes referencing it have been merged."""
1496 self.blocker_digraph.addnode(node, blocker)
1497 depends_on_merge_order = True
1500 elif not depends_on_merge_order:
1501 self.blocker_parents[blocker].remove(parent)
1503 """This blocker can not be solved, so make sure that it is
1504 removed from the digraph if it has already been added."""
1505 if self.blocker_digraph.contains(blocker):
1506 self.blocker_digraph.remove(blocker)
1507 # Keep trying to invalidate as many blockers as possible.
1509 if not self.blocker_parents[blocker]:
1510 del self.blocker_parents[blocker]
1511 # Validate blockers that depend on merge order.
1512 if not self.blocker_digraph.empty():
1515 def altlist(self, reversed=False):
1516 if reversed in self._altlist_cache:
1517 return self._altlist_cache[reversed][:]
1518 mygraph=self.digraph.copy()
1519 myblockers = self.blocker_digraph.copy()
1521 circular_blocks = False
1525 get_nodes = mygraph.root_nodes
1527 get_nodes = mygraph.leaf_nodes
1528 for cpv, node in self.pkg_node_map["/"].iteritems():
1529 if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
1530 asap_nodes.append(node)
1532 ignore_priority_range = [None]
1533 ignore_priority_range.extend(
1534 xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
1535 while not mygraph.empty():
1536 ignore_priority = None
1539 """ASAP nodes are merged before their soft deps."""
1540 for node in asap_nodes:
1541 if not mygraph.contains(node):
1542 asap_nodes.remove(node)
1544 if not mygraph.child_nodes(node,
1545 ignore_priority=DepPriority.SOFT):
1547 asap_nodes.remove(node)
1550 for ignore_priority in ignore_priority_range:
1551 nodes = get_nodes(ignore_priority=ignore_priority)
1554 selected_nodes = None
1556 if ignore_priority <= DepPriority.SOFT:
1557 selected_nodes = [nodes[0]]
1559 """Recursively gather a group of nodes that RDEPEND on
1560 eachother. This ensures that they are merged as a group
1561 and get their RDEPENDs satisfied as soon as possible."""
1562 def gather_deps(mergeable_nodes, selected_nodes, node):
1563 if node in selected_nodes:
1565 if node not in mergeable_nodes:
1567 selected_nodes.add(node)
1568 for child in mygraph.child_nodes(node,
1569 ignore_priority=DepPriority.SOFT):
1571 mergeable_nodes, selected_nodes, child):
1574 mergeable_nodes = set(nodes)
1576 selected_nodes = set()
1578 mergeable_nodes, selected_nodes, node):
1581 selected_nodes = None
1583 if not selected_nodes:
1584 if not myblockers.is_empty():
1585 """A blocker couldn't be circumnavigated while keeping all
1586 dependencies satisfied. The user will have to resolve this
1587 manually. This is a panic condition and thus the order
1588 doesn't really matter, so just pop a random node in order
1589 to avoid a circular dependency panic if possible."""
1590 if not circular_blocks:
1591 circular_blocks = True
1592 blocker_deps = myblockers.leaf_nodes()
1594 selected_nodes = [blocker_deps.pop()]
1596 if not selected_nodes:
1598 """The circular deps ouput should have less noise when
1599 altlist is not in reversed mode."""
1601 print "!!! Error: circular dependencies:"
1603 mygraph.debug_print()
1606 for node in selected_nodes:
1607 retlist.append(node.split())
1608 mygraph.remove(node)
1609 if not reversed and not circular_blocks and myblockers.contains(node):
1610 """This node may have invalidated one or more blockers."""
1611 myblockers.remove(node)
1612 for blocker in myblockers.root_nodes():
1613 if not myblockers.child_nodes(blocker):
1614 myblockers.remove(blocker)
1615 del self.blocker_parents[blocker]
1618 """Blocker validation does not work with reverse mode,
1619 so self.altlist() should first be called with reverse disabled
1620 so that blockers are properly validated."""
1621 self.blocker_digraph = myblockers
1623 """ Add any unresolved blocks so that they can be displayed."""
1624 for blocker in self.blocker_parents:
1625 retlist.append(blocker.split())
1626 self._altlist_cache[reversed] = retlist[:]
1629 def xcreate(self,mode="system"):
1630 vardb = self.trees[self.target_root]["vartree"].dbapi
1631 portdb = self.trees[self.target_root]["porttree"].dbapi
1632 bindb = self.trees[self.target_root]["bintree"].dbapi
1633 def visible(mylist):
1634 matches = portdb.gvisible(portdb.visible(mylist))
1635 return [x for x in mylist \
1636 if x in matches or not portdb.cpv_exists(x)]
1637 world_problems = False
1639 mylist = getlist(self.settings, "system")
1642 worldlist = getlist(self.settings, "world")
1643 sysdict = genericdict(getlist(self.settings, "system"))
1644 worlddict=genericdict(worldlist)
1646 for x in worlddict.keys():
1647 if not portage.isvalidatom(x):
1648 world_problems = True
1649 elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
1650 world_problems = True
1652 sysdict[x]=worlddict[x]
1654 mylist = sysdict.keys()
1658 mykey = portage.dep_getkey(atom)
1660 newlist.append(atom)
1661 """Make sure all installed slots are updated when possible.
1662 Do this with --emptytree also, to ensure that all slots are
1665 for cpv in vardb.match(mykey):
1666 myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
1669 if "--usepkg" in self.myopts:
1670 mymatches = bindb.match(atom)
1671 if "--usepkgonly" not in self.myopts:
1672 mymatches = visible(mymatches)
1673 best_pkg = portage.best(mymatches)
1675 best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
1676 best_pkgs.append(("binary", best_pkg, best_slot))
1677 if "--usepkgonly" not in self.myopts:
1678 best_pkg = portage.best(portdb.match(atom))
1680 best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
1681 best_pkgs.append(("ebuild", best_pkg, best_slot))
1683 best_pkg = portage.best([x[1] for x in best_pkgs])
1684 best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
1685 best_slot = best_pkgs[0][2]
1686 myslots.add(best_slot)
1687 if len(myslots) > 1:
1688 for myslot in myslots:
1689 myslot_atom = "%s:%s" % (mykey, myslot)
1691 if "--usepkgonly" not in self.myopts and \
1692 self.trees[self.target_root][
1693 "porttree"].dbapi.match(myslot_atom):
1695 elif "--usepkg" in self.myopts:
1696 mymatches = bindb.match(myslot_atom)
1697 if "--usepkgonly" not in self.myopts:
1698 mymatches = visible(mymatches)
1702 newlist.append(myslot_atom)
1706 for mydep in mylist:
1708 if not self.select_dep(
1709 self.target_root, mydep, raise_on_missing=True, arg=mydep):
1710 print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
1713 missing_atoms.append(mydep)
1715 self.validate_blockers()
1718 print >> sys.stderr, "\n!!! Problems have been detected with your world file"
1719 print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
1722 print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
1723 " Ebuilds for the following packages are either all"
1724 print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
1725 print >> sys.stderr, " ".join(missing_atoms) + "\n"
1729 def match(self, mydep, myroot=None, mykey=None):
1730 # support mutual exclusive deps
1732 myroot = self.target_root
1738 #add our blocker; it will be ignored later if necessary (if we are remerging the same pkg, for example)
1739 myk="blocks "+myroot+" "+mydep2
1741 myeb = self.trees[myroot]["porttree"].dep_bestmatch(mydep2)
1744 print "\n!!! Error: couldn't find match for",mydep
1746 print "\n!!! Error: couldn't find match for",mydep,"in",mykey
1750 if "--usepkg" in self.myopts:
1751 mypk = self.trees[myroot]["bintree"].dep_bestmatch(mydep)
1753 myk = " ".join(("binary", myroot, mypk))
1755 myk = " ".join(("ebuild", myroot, myeb))
1757 myk="ebuild "+myroot+" "+myeb
1761 def display(self,mylist,verbosity=None):
1762 if verbosity is None:
1763 verbosity = ("--quiet" in self.myopts and 1 or \
1764 "--verbose" in self.myopts and 3 or 2)
1768 counters = PackageCounters()
1770 if verbosity == 1 and "--verbose" not in self.myopts:
1771 def create_use_string(*args):
1774 def create_use_string(name, cur_iuse, iuse_forced, cur_use,
1776 is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
1777 alphabetical=("--alphabetical" in self.myopts)):
1785 cur_iuse = set(cur_iuse)
1786 enabled_flags = cur_iuse.intersection(cur_use)
1787 removed_iuse = set(old_iuse).difference(cur_iuse)
1788 any_iuse = cur_iuse.union(old_iuse)
1789 any_iuse = list(any_iuse)
1791 for flag in any_iuse:
1794 if flag in enabled_flags:
1796 if is_new or flag in old_use and all_flags:
1797 flag_str = red(flag)
1798 elif flag not in old_iuse:
1799 flag_str = yellow(flag) + "%*"
1800 elif flag not in old_use:
1801 flag_str = green(flag) + "*"
1802 elif flag in removed_iuse:
1804 flag_str = yellow("-" + flag) + "%"
1807 flag_str = "(" + flag_str + ")"
1808 removed.append(flag_str)
1811 if is_new or flag in old_iuse and flag not in old_use and all_flags:
1812 flag_str = blue("-" + flag)
1813 elif flag not in old_iuse:
1814 flag_str = yellow("-" + flag)
1815 if flag not in iuse_forced:
1817 elif flag in old_use:
1818 flag_str = green("-" + flag) + "*"
1820 if flag in iuse_forced:
1821 flag_str = "(" + flag_str + ")"
1823 enabled.append(flag_str)
1825 disabled.append(flag_str)
1828 ret = " ".join(enabled)
1830 ret = " ".join(enabled + disabled + removed)
1832 ret = '%s="%s" ' % (name, ret)
1836 # FIXME: account for the possibility of different overlays in
1837 # /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
1838 overlays = self.settings["PORTDIR_OVERLAY"].split()
1839 overlays_real = [os.path.realpath(t) \
1840 for t in self.settings["PORTDIR_OVERLAY"].split()]
1847 if "blocks" == x[0]:
1849 graph_key = " ".join(x)
1850 if "--tree" in self.myopts:
1851 depth = len(tree_nodes)
1852 while depth and graph_key not in \
1853 self.digraph.child_nodes(tree_nodes[depth-1]):
1855 tree_nodes = tree_nodes[:depth]
1856 tree_nodes.append(graph_key)
1857 node_depth[graph_key] = depth
1859 last_merge_depth = 0
1860 for i in xrange(len(mylist)-1,-1,-1):
1861 if "blocks" == mylist[i][0]:
1863 graph_key = " ".join(mylist[i])
1864 if mylist[i][-1] != "nomerge":
1865 last_merge_depth = node_depth[graph_key]
1867 if node_depth[graph_key] >= last_merge_depth or \
1868 i < len(mylist) - 1 and \
1869 node_depth[graph_key] >= node_depth[" ".join(mylist[i+1])]:
1871 del node_depth[graph_key]
1874 display_overlays=False
1875 # files to fetch list - avoids counting a same file twice
1876 # in size display (verbose mode)
1882 portdb = self.trees[myroot]["porttree"].dbapi
1883 bindb = self.trees[myroot]["bintree"].dbapi
1884 vartree = self.trees[myroot]["vartree"]
1885 pkgsettings = self.pkgsettings[myroot]
1890 addl=""+red("B")+" "+fetch+" "
1891 counters.blocks += 1
1892 resolved = self.trees[x[1]]["vartree"].resolve_key(x[2])
1893 print "["+x[0]+" "+addl+"]",red(resolved),
1894 block_parents = self.blocker_parents[" ".join(x)]
1895 block_parents = [pnode.split()[2] for pnode in block_parents]
1896 block_parents = ", ".join(block_parents)
1898 print bad("(\"%s\" is blocking %s)") % \
1899 (pkg_key, block_parents)
1901 print bad("(is blocking %s)") % block_parents
1903 mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
1904 binary_package = True
1905 if "ebuild" == pkg_type:
1906 if "merge" == x[3] or \
1907 not vartree.dbapi.cpv_exists(pkg_key):
1908 """An ebuild "merge" node or a --onlydeps "nomerge"
1910 binary_package = False
1911 pkgsettings.setcpv(pkg_key, mydb=portdb)
1912 if pkg_key not in self.useFlags[myroot]:
1913 self.useFlags[myroot][pkg_key] = \
1914 pkgsettings["USE"].split()
1916 # An ebuild "nomerge" node, so USE come from the vardb.
1917 mydbapi = vartree.dbapi
1918 if pkg_key not in self.useFlags[myroot]:
1919 """If this is a --resume then the USE flags need to be
1920 fetched from the appropriate locations here."""
1921 self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
1922 pkg_key, ["USE"])[0].split()
1924 if "ebuild" == pkg_type and x[3] != "nomerge" and \
1925 "fetch" in portdb.aux_get(
1926 x[2], ["RESTRICT"])[0].split():
1928 counters.restrict_fetch += 1
1929 if portdb.fetch_check(
1930 pkg_key, self.useFlags[myroot][pkg_key]):
1932 counters.restrict_fetch_satisfied += 1
1934 #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
1935 #param is used for -u, where you still *do* want to see when something is being upgraded.
1937 if self.trees[x[1]]["vartree"].exists_specific(pkg_key):
1938 addl=" "+yellow("R")+fetch+" "
1939 if x[3] != "nomerge":
1940 counters.reinst += 1
1941 elif self.trees[x[1]]["vartree"].exists_specific_cat(pkg_key):
1942 mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
1943 myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
1944 portage.pkgsplit(x[2])[0])
1945 myinslotlist = [inst_pkg for inst_pkg in myoldlist
1946 if mynewslot == vartree.getslot(inst_pkg)]
1948 myoldbest=portage.best(myinslotlist)
1950 if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
1952 addl+=turquoise("U")+blue("D")
1953 counters.downgrades += 1
1956 addl+=turquoise("U")+" "
1957 counters.upgrades += 1
1959 # New slot, mark it new.
1960 addl=" "+green("NS")+fetch+" "
1961 counters.newslot += 1
1963 if "--changelog" in self.myopts:
1964 changelogs.extend(self.calc_changelog(
1965 portdb.findname(pkg_key),
1966 self.trees[x[1]]["vartree"].dep_bestmatch(
1967 '/'.join(portage.catpkgsplit(x[2])[:2])), x[2]))
1969 addl=" "+green("N")+" "+fetch+" "
1974 if pkg_key in self.useFlags[myroot]:
1976 cur_iuse = list(filter_iuse_defaults(
1977 mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
1979 forced_flags = set()
1980 if not binary_package:
1981 forced_flags.update(pkgsettings.useforce)
1982 forced_flags.update(pkgsettings.usemask)
1984 cur_iuse = portage.unique_array(cur_iuse)
1986 cur_use = self.useFlags[myroot][pkg_key]
1987 cur_use = [flag for flag in cur_use if flag in cur_iuse]
1993 if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
1994 old_iuse, old_use = \
1995 self.trees[x[1]]["vartree"].dbapi.aux_get(
1996 pkg, ["IUSE", "USE"])
1997 old_iuse = list(set(
1998 filter_iuse_defaults(old_iuse.split())))
2000 old_use = old_use.split()
2007 old_use = [flag for flag in old_use if flag in old_iuse]
2009 use_expand = pkgsettings["USE_EXPAND"].lower().split()
2011 use_expand.reverse()
2012 use_expand_hidden = \
2013 pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
2015 def map_to_use_expand(myvals, forcedFlags=False):
2018 for exp in use_expand:
2021 for val in myvals[:]:
2022 if val.startswith(exp.lower()+"_"):
2023 if val in forced_flags:
2024 forced[exp].add(val[len(exp)+1:])
2025 ret[exp].append(val[len(exp)+1:])
2028 forced["USE"] = [val for val in myvals \
2029 if val in forced_flags]
2030 for exp in use_expand_hidden:
2037 cur_iuse_map, iuse_forced = \
2038 map_to_use_expand(cur_iuse, forcedFlags=True)
2039 cur_use_map = map_to_use_expand(cur_use)
2040 old_iuse_map = map_to_use_expand(old_iuse)
2041 old_use_map = map_to_use_expand(old_use)
2044 use_expand.insert(0, "USE")
2046 for key in use_expand:
2047 if key in use_expand_hidden:
2049 verboseadd += create_use_string(key.upper(),
2050 cur_iuse_map[key], iuse_forced[key],
2051 cur_use_map[key], old_iuse_map[key],
2052 old_use_map[key], is_new)
2057 if x[0] == "ebuild" and x[-1]!="nomerge":
2058 myfilesdict = portdb.getfetchsizes(
2059 pkg_key, useflags=self.useFlags[myroot][pkg_key],
2061 if myfilesdict is None:
2062 myfilesdict="[empty/missing/bad digest]"
2064 for myfetchfile in myfilesdict.keys():
2065 if myfetchfile not in myfetchlist:
2066 mysize+=myfilesdict[myfetchfile]
2067 myfetchlist.append(myfetchfile)
2068 counters.totalsize += mysize
2069 verboseadd+=format_size(mysize)+" "
2072 # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
2073 # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
2074 file_name = portdb.findname(pkg_key)
2075 if file_name: # It might not exist in the tree
2076 dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
2077 if (overlays_real.count(dir_name)>0):
2078 verboseadd+=teal("["+str(overlays_real.index(
2079 os.path.normpath(dir_name))+1)+"]")+" "
2080 display_overlays=True
2082 verboseadd += "[No ebuild?]"
2084 xs=portage.pkgsplit(x[2])
2091 if "COLUMNWIDTH" in self.settings:
2093 mywidth = int(self.settings["COLUMNWIDTH"])
2094 except ValueError, e:
2095 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
2097 "!!! Unable to parse COLUMNWIDTH='%s'\n" % \
2098 self.settings["COLUMNWIDTH"], noiselevel=-1)
2103 indent = " " * node_depth[" ".join(x)]
2106 myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2107 if myoldbest[-3:]=="-r0":
2108 myoldbest=myoldbest[:-3]
2109 myoldbest=blue("["+myoldbest+"]")
2114 if "--columns" in self.myopts:
2115 if "--quiet" in self.myopts:
2116 myprint=addl+" "+indent+darkgreen(xs[0])
2117 myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
2118 myprint=myprint+myoldbest
2119 myprint=myprint+darkgreen("to "+x[1])
2121 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2122 if (newlp-nc_len(myprint)) > 0:
2123 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2124 myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
2125 if (oldlp-nc_len(myprint)) > 0:
2126 myprint=myprint+" "*(oldlp-nc_len(myprint))
2127 myprint=myprint+myoldbest
2128 myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2130 if x[3] == "nomerge":
2131 myprint = darkblue("[nomerge ] ")
2133 myprint = "[" + pkg_type + " " + addl + "] "
2134 myprint += indent + darkgreen(pkg_key) + " " + \
2135 myoldbest + darkgreen("to " + myroot) + " " + \
2138 if "--columns" in self.myopts:
2139 if "--quiet" in self.myopts:
2140 myprint=addl+" "+indent+darkgreen(xs[0])
2141 myprint=myprint+" "+green(xs[1]+xs[2])+" "
2142 myprint=myprint+myoldbest
2144 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
2145 if (newlp-nc_len(myprint)) > 0:
2146 myprint=myprint+(" "*(newlp-nc_len(myprint)))
2147 myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
2148 if (oldlp-nc_len(myprint)) > 0:
2149 myprint=myprint+(" "*(oldlp-nc_len(myprint)))
2150 myprint=myprint+myoldbest+" "+verboseadd
2153 myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
2155 myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
2158 mysplit = portage.pkgsplit(x[2])
2159 if "--tree" not in self.myopts and mysplit and \
2160 len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
2163 if mysplit[2] == "r0":
2164 myversion = mysplit[1]
2166 myversion = "%s-%s" % (mysplit[1], mysplit[2])
2168 if myversion != portage.VERSION and "--quiet" not in self.myopts:
2169 if mylist.index(x) < len(mylist) - 1 and \
2170 "livecvsportage" not in self.settings.features:
2171 p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
2172 p.append(colorize("WARN", " then resume the merge."))
2182 if overlays and display_overlays:
2183 print "Portage overlays:"
2187 print " "+teal("["+str(y)+"]"),x
2189 if "--changelog" in self.myopts:
2191 for revision,text in changelogs:
2192 print bold('*'+revision)
2193 sys.stdout.write(text)
2195 def calc_changelog(self,ebuildpath,current,next):
2196 current = '-'.join(portage.catpkgsplit(current)[1:])
2197 if current.endswith('-r0'): current = current[:-3]
2198 next = '-'.join(portage.catpkgsplit(next)[1:])
2199 if next.endswith('-r0'): next = next[:-3]
2200 changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
2202 changelog = open(changelogpath).read()
2203 except SystemExit, e:
2204 raise # Needed else can't exit
2207 divisions = self.find_changelog_tags(changelog)
2208 #print 'XX from',current,'to',next
2209 #for div,text in divisions: print 'XX',div
2210 # skip entries for all revisions above the one we are about to emerge
2211 for i in range(len(divisions)):
2212 if divisions[i][0]==next:
2213 divisions = divisions[i:]
2215 # find out how many entries we are going to display
2216 for i in range(len(divisions)):
2217 if divisions[i][0]==current:
2218 divisions = divisions[:i]
2221 # couldnt find the current revision in the list. display nothing
2225 def find_changelog_tags(self,changelog):
2229 match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
2231 if release is not None:
2232 divs.append((release,changelog))
2234 if release is not None:
2235 divs.append((release,changelog[:match.start()]))
2236 changelog = changelog[match.end():]
2237 release = match.group(1)
2238 if release.endswith('.ebuild'):
2239 release = release[:-7]
2240 if release.endswith('-r0'):
2241 release = release[:-3]
2244 return self.outdatedpackages
2246 class PackageCounters(object):
2256 self.restrict_fetch = 0
2257 self.restrict_fetch_satisfied = 0
2260 total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
2263 myoutput.append("Total: %s package" % total_installs)
2264 if total_installs != 1:
2265 myoutput.append("s")
2266 if total_installs != 0:
2267 myoutput.append(" (")
2268 if self.upgrades > 0:
2269 details.append("%s upgrade" % self.upgrades)
2270 if self.upgrades > 1:
2272 if self.downgrades > 0:
2273 details.append("%s downgrade" % self.downgrades)
2274 if self.downgrades > 1:
2277 details.append("%s new" % self.new)
2278 if self.newslot > 0:
2279 details.append("%s in new slot" % self.newslot)
2280 if self.newslot > 1:
2283 details.append("%s reinstall" % self.reinst)
2287 details.append("%s block" % self.blocks)
2290 myoutput.append(", ".join(details))
2291 if total_installs != 0:
2292 myoutput.append(")")
2293 myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
2294 if self.restrict_fetch:
2295 myoutput.append("\nFetch Restriction: %s package" % \
2296 self.restrict_fetch)
2297 if self.restrict_fetch > 1:
2298 myoutput.append("s")
2299 if self.restrict_fetch_satisfied < self.restrict_fetch:
2300 myoutput.append(bad(" (%s unsatisfied)") % \
2301 (self.restrict_fetch - self.restrict_fetch_satisfied))
2302 return "".join(myoutput)
2304 class MergeTask(object):
2306 def __init__(self, settings, trees, myopts):
2307 self.settings = settings
2308 self.target_root = settings["ROOT"]
2310 self.myopts = myopts
2312 if settings.get("PORTAGE_DEBUG", "") == "1":
2314 self.pkgsettings = {}
2315 self.pkgsettings[self.target_root] = portage.config(clone=settings)
2316 if self.target_root != "/":
2317 self.pkgsettings["/"] = \
2318 portage.config(clone=trees["/"]["vartree"].settings)
2320 def merge(self, mylist, favorites, mtimedb):
2323 ldpath_mtimes = mtimedb["ldpath"]
2324 xterm_titles = "notitles" not in self.settings.features
2326 #check for blocking dependencies
2327 if "--fetchonly" not in self.myopts and \
2328 "--buildpkgonly" not in self.myopts:
2331 print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
2332 print "!!! the two packages cannot be installed on the same system together."
2333 print "!!! Please use 'emerge --pretend' to determine blockers."
2334 if "--quiet" not in self.myopts:
2335 show_blocker_docs_link()
2336 if "--pretend" not in self.myopts:
2338 del mtimedb["resume"]
2343 #buildsyspkg: I need mysysdict also on resume (moved from the else block)
2344 mysysdict = genericdict(getlist(self.settings, "system"))
2345 if "--resume" in self.myopts:
2347 print colorize("GOOD", "*** Resuming merge...")
2348 emergelog(xterm_titles, " *** Resuming merge...")
2349 mymergelist=mtimedb["resume"]["mergelist"][:]
2350 if "--skipfirst" in self.myopts and mymergelist:
2351 del mtimedb["resume"]["mergelist"][0]
2354 validate_merge_list(self.trees, mymergelist)
2356 myfavs = portage.grabfile(
2357 os.path.join(self.target_root, portage.WORLD_FILE))
2358 myfavdict=genericdict(myfavs)
2359 for x in range(len(mylist)):
2360 if mylist[x][3]!="nomerge":
2361 # Add to the mergelist
2362 mymergelist.append(mylist[x])
2364 myfavkey=portage.cpv_getkey(mylist[x][2])
2365 if "--onlydeps" in self.myopts:
2367 # Add to the world file. Since we won't be able to later.
2368 if "--fetchonly" not in self.myopts and \
2369 myfavkey in favorites:
2370 #don't record if already in system profile or already recorded
2371 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
2372 #we don't have a favorites entry for this package yet; add one
2373 myfavdict[myfavkey]=myfavkey
2374 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
2375 if not ("--fetchonly" in self.myopts or \
2376 "--fetch-all-uri" in self.myopts or \
2377 "--pretend" in self.myopts):
2378 portage.write_atomic(
2379 os.path.join(self.target_root, portage.WORLD_FILE),
2380 "\n".join(myfavdict.values()))
2382 mtimedb["resume"]["mergelist"]=mymergelist[:]
2385 myfeat = self.settings.features[:]
2386 bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
2388 if "parallel-fetch" in myfeat and \
2389 not ("--pretend" in self.myopts or \
2390 "--fetch-all-uri" in self.myopts or \
2391 "--fetchonly" in self.myopts):
2392 if "distlocks" not in myfeat:
2394 print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
2395 print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
2397 elif len(mymergelist) > 1:
2398 print ">>> starting parallel fetching"
2399 fetch_log = "/var/log/emerge-fetch.log"
2400 logfile = open(fetch_log, "w")
2401 fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
2402 portage_util.apply_secpass_permissions(fetch_log,
2403 uid=portage.portage_uid, gid=portage.portage_gid,
2405 fetch_env = os.environ.copy()
2406 fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
2407 fetch_env["PORTAGE_NICENESS"] = "0"
2408 fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
2409 for myopt, myarg in self.myopts.iteritems():
2410 if myopt not in bad_resume_opts:
2412 fetch_args.append(myopt)
2414 fetch_args.append(myopt +"="+ myarg)
2415 portage.portage_exec.spawn(fetch_args, env=fetch_env,
2416 fd_pipes=fd_pipes, returnpid=True)
2417 logfile.close() # belongs to the spawned process
2420 for x in mymergelist:
2425 portdb = self.trees[myroot]["porttree"].dbapi
2426 bindb = self.trees[myroot]["bintree"].dbapi
2427 vartree = self.trees[myroot]["vartree"]
2428 pkgsettings = self.pkgsettings[myroot]
2431 y = portdb.findname(pkg_key)
2432 if "--pretend" not in self.myopts:
2433 print "\n>>> Emerging (" + \
2434 colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2435 colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
2436 colorize("GOOD", x[pkgindex]) + " to " + x[1]
2437 emergelog(xterm_titles, " >>> emerge ("+\
2438 str(mergecount)+" of "+str(len(mymergelist))+\
2439 ") "+x[pkgindex]+" to "+x[1])
2441 pkgsettings["EMERGE_FROM"] = x[0]
2442 pkgsettings.backup_changes("EMERGE_FROM")
2445 #buildsyspkg: Check if we need to _force_ binary package creation
2446 issyspkg = ("buildsyspkg" in myfeat) \
2447 and x[0] != "blocks" \
2448 and mysysdict.has_key(portage.cpv_getkey(x[2])) \
2449 and "--buildpkg" not in self.myopts
2450 if x[0] in ["ebuild","blocks"]:
2451 if x[0] == "blocks" and "--fetchonly" not in self.myopts:
2452 raise Exception, "Merging a blocker"
2453 elif "--fetchonly" in self.myopts or \
2454 "--fetch-all-uri" in self.myopts:
2455 if "--fetch-all-uri" in self.myopts:
2456 retval = portage.doebuild(y, "fetch", myroot,
2457 pkgsettings, self.edebug,
2458 "--pretend" in self.myopts, fetchonly=1,
2459 fetchall=1, mydbapi=portdb, tree="porttree")
2461 retval = portage.doebuild(y, "fetch", myroot,
2462 pkgsettings, self.edebug,
2463 "--pretend" in self.myopts, fetchonly=1,
2464 mydbapi=portdb, tree="porttree")
2465 if (retval is None) or retval:
2467 print "!!! Fetch for",y,"failed, continuing..."
2472 portage.doebuild_environment(y, "setup", myroot,
2473 pkgsettings, self.edebug, 1, portdb)
2474 catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
2475 portage_util.ensure_dirs(os.path.dirname(catdir),
2476 uid=portage.portage_uid, gid=portage.portage_gid,
2478 builddir_lock = None
2481 catdir_lock = portage_locks.lockdir(catdir)
2482 portage_util.ensure_dirs(catdir,
2483 uid=portage.portage_uid, gid=portage.portage_gid,
2485 builddir_lock = portage_locks.lockdir(
2486 pkgsettings["PORTAGE_BUILDDIR"])
2488 portage_locks.unlockdir(catdir_lock)
2491 msg = " === (%s of %s) Cleaning (%s::%s)" % \
2492 (mergecount, len(mymergelist), pkg_key, y)
2493 short_msg = "emerge: (%s of %s) %s Clean" % \
2494 (mergecount, len(mymergelist), pkg_key)
2495 emergelog(xterm_titles, msg, short_msg=short_msg)
2496 retval = portage.doebuild(y, "clean", myroot,
2497 pkgsettings, self.edebug, cleanup=1,
2498 mydbapi=portdb, tree="porttree")
2499 if retval != os.EX_OK:
2501 if "--buildpkg" in self.myopts or issyspkg:
2503 print ">>> This is a system package, " + \
2504 "let's pack a rescue tarball."
2505 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
2506 (mergecount, len(mymergelist), pkg_key, y)
2507 short_msg = "emerge: (%s of %s) %s Compile" % \
2508 (mergecount, len(mymergelist), pkg_key)
2509 emergelog(xterm_titles, msg, short_msg=short_msg)
2510 self.trees[myroot]["bintree"].prevent_collision(pkg_key)
2511 retval = portage.doebuild(y, "package", myroot,
2512 pkgsettings, self.edebug, mydbapi=portdb,
2514 if retval != os.EX_OK:
2516 if "--buildpkgonly" not in self.myopts:
2517 bintree = self.trees[myroot]["bintree"]
2518 bintree.inject(pkg_key)
2519 mytbz2 = bintree.getname(pkg_key)
2520 msg = " === (%s of %s) Merging (%s::%s)" % \
2521 (mergecount, len(mymergelist), pkg_key, y)
2522 short_msg = "emerge: (%s of %s) %s Merge" % \
2523 (mergecount, len(mymergelist), pkg_key)
2524 emergelog(xterm_titles, msg, short_msg=short_msg)
2525 retval = portage.merge(pkgsettings["CATEGORY"],
2526 pkgsettings["PF"], pkgsettings["D"],
2527 os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
2528 "build-info"), myroot, pkgsettings,
2529 myebuild=pkgsettings["EBUILD"],
2530 mytree="porttree", mydbapi=portdb,
2531 vartree=vartree, prev_mtimes=ldpath_mtimes)
2532 if retval != os.EX_OK:
2534 elif "noclean" not in pkgsettings.features:
2535 portage.doebuild(y, "clean", myroot,
2536 pkgsettings, self.edebug, mydbapi=portdb,
2539 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
2540 (mergecount, len(mymergelist), pkg_key, y)
2541 short_msg = "emerge: (%s of %s) %s Compile" % \
2542 (mergecount, len(mymergelist), pkg_key)
2543 emergelog(xterm_titles, msg, short_msg=short_msg)
2544 retval = portage.doebuild(y, "merge", myroot,
2545 pkgsettings, self.edebug, vartree=vartree,
2546 mydbapi=portdb, tree="porttree",
2547 prev_mtimes=ldpath_mtimes)
2548 if retval != os.EX_OK:
2552 portage_locks.unlockdir(builddir_lock)
2555 # Lock catdir for removal if empty.
2556 catdir_lock = portage_locks.lockdir(catdir)
2562 if e.errno != errno.ENOTEMPTY:
2565 portage_locks.unlockdir(catdir_lock)
2567 elif x[0]=="binary":
2569 mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
2570 if self.trees[myroot]["bintree"].isremote(pkg_key):
2571 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Fetch"
2572 emergelog(xterm_titles, " --- ("+str(mergecount)+\
2573 " of "+str(len(mymergelist))+\
2574 ") Fetching Binary ("+x[pkgindex]+\
2575 "::"+mytbz2+")", short_msg=short_msg)
2576 if not self.trees[myroot]["bintree"].gettbz2(pkg_key):
2579 if "--fetchonly" in self.myopts or \
2580 "--fetch-all-uri" in self.myopts:
2583 short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
2584 emergelog(xterm_titles, " === ("+str(mergecount)+\
2585 " of "+str(len(mymergelist))+") Merging Binary ("+\
2586 x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
2587 retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
2589 vartree=self.trees[myroot]["vartree"],
2590 prev_mtimes=ldpath_mtimes)
2593 #need to check for errors
2594 if "--buildpkgonly" not in self.myopts:
2595 self.trees[x[1]]["vartree"].inject(x[2])
2596 myfavkey=portage.cpv_getkey(x[2])
2597 if "--fetchonly" not in self.myopts and \
2598 "--fetch-all-uri" not in self.myopts and \
2599 myfavkey in favorites:
2600 myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
2601 myfavdict=genericdict(myfavs)
2602 #don't record if already in system profile or already recorded
2603 if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
2604 #we don't have a favorites entry for this package yet; add one
2605 myfavdict[myfavkey]=myfavkey
2606 print ">>> Recording",myfavkey,"in \"world\" favorites file..."
2607 emergelog(xterm_titles, " === ("+\
2608 str(mergecount)+" of "+\
2609 str(len(mymergelist))+\
2610 ") Updating world file ("+x[pkgindex]+")")
2611 portage.write_atomic(
2612 os.path.join(myroot, portage.WORLD_FILE),
2613 "\n".join(myfavdict.values()))
2615 if "--pretend" not in self.myopts and \
2616 "--fetchonly" not in self.myopts and \
2617 "--fetch-all-uri" not in self.myopts:
2618 # Clean the old package that we have merged over top of it.
2619 if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
2620 xsplit=portage.pkgsplit(x[2])
2621 emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
2622 retval = unmerge(pkgsettings, self.myopts, vartree,
2623 "clean", [xsplit[0]], ldpath_mtimes)
2625 emergelog(xterm_titles,
2626 " --- AUTOCLEAN: Nothing unmerged.")
2628 portage.writemsg_stdout(colorize("WARN", "WARNING:")
2629 + " AUTOCLEAN is disabled. This can cause serious"
2630 + " problems due to overlapping packages.\n")
2632 # Figure out if we need a restart.
2633 mysplit=portage.pkgsplit(x[2])
2634 if mysplit[0] == "sys-apps/portage" and x[1] == "/":
2635 myver=mysplit[1]+"-"+mysplit[2]
2636 if myver[-3:]=='-r0':
2638 if (myver != portage.VERSION) and \
2639 "livecvsportage" not in self.settings.features:
2640 if len(mymergelist) > mergecount:
2641 emergelog(xterm_titles,
2642 " ::: completed emerge ("+ \
2643 str(mergecount)+" of "+ \
2644 str(len(mymergelist))+") "+ \
2646 emergelog(xterm_titles, " *** RESTARTING " + \
2647 "emerge via exec() after change of " + \
2649 del mtimedb["resume"]["mergelist"][0]
2651 portage.run_exitfuncs()
2652 mynewargv=[sys.argv[0],"--resume"]
2653 for myopt, myarg in self.myopts.iteritems():
2654 if myopt not in bad_resume_opts:
2656 mynewargv.append(myopt)
2658 mynewargv.append(myopt +"="+ myarg)
2659 # priority only needs to be adjusted on the first run
2660 os.environ["PORTAGE_NICENESS"] = "0"
2661 os.execv(mynewargv[0], mynewargv)
2663 if "--pretend" not in self.myopts and \
2664 "--fetchonly" not in self.myopts and \
2665 "--fetch-all-uri" not in self.myopts:
2666 if "noclean" not in self.settings.features:
2667 short_msg = "emerge: (%s of %s) %s Clean Post" % \
2668 (mergecount, len(mymergelist), x[pkgindex])
2669 emergelog(xterm_titles, (" === (%s of %s) " + \
2670 "Post-Build Cleaning (%s::%s)") % \
2671 (mergecount, len(mymergelist), x[pkgindex], y),
2672 short_msg=short_msg)
2673 emergelog(xterm_titles, " ::: completed emerge ("+\
2674 str(mergecount)+" of "+str(len(mymergelist))+") "+\
2677 # Unsafe for parallel merges
2678 del mtimedb["resume"]["mergelist"][0]
2679 # Commit after each merge so that --resume may still work in
2680 # in the event that portage is not allowed to exit normally
2681 # due to power failure, SIGKILL, etc...
2684 if "--pretend" not in self.myopts:
2685 emergelog(xterm_titles, " *** Finished. Cleaning up...")
2687 # We're out of the loop... We're done. Delete the resume data.
2688 if mtimedb.has_key("resume"):
2689 del mtimedb["resume"]
2692 #by doing an exit this way, --fetchonly can continue to try to
2693 #fetch everything even if a particular download fails.
2694 if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
2696 print "\n\n!!! Some fetch errors were encountered. Please see above for details.\n\n"
2702 def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
2703 ldpath_mtimes, raise_on_missing=True):
2704 candidate_catpkgs=[]
2706 xterm_titles = "notitles" not in settings.features
2708 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
2711 if os.access(vdb_path, os.W_OK):
2712 vdb_lock = portage_locks.lockdir(vdb_path)
2713 realsyslist = getlist(settings, "system")
2715 for x in realsyslist:
2716 mycp = portage.dep_getkey(x)
2717 if mycp in settings.getvirtuals():
2719 for provider in settings.getvirtuals()[mycp]:
2720 if vartree.dbapi.match(provider):
2721 providers.append(provider)
2722 if len(providers) == 1:
2723 syslist.extend(providers)
2725 syslist.append(mycp)
2727 mysettings = portage.config(clone=settings)
2729 if not unmerge_files or "world" in unmerge_files or \
2730 "system" in unmerge_files:
2731 if "unmerge"==unmerge_action:
2733 print bold("emerge unmerge") + " can only be used with " + \
2734 "specific package names, not with "+bold("world")+" or"
2735 print bold("system")+" targets."
2742 # process all arguments and add all
2743 # valid db entries to candidate_catpkgs
2745 if not unmerge_files or "world" in unmerge_files:
2746 candidate_catpkgs.extend(vartree.dbapi.cp_all())
2747 elif "system" in unmerge_files:
2748 candidate_catpkgs.extend(getlist(settings, "system"))
2750 #we've got command-line arguments
2751 if not unmerge_files:
2752 print "\nNo packages to unmerge have been provided.\n"
2754 for x in unmerge_files:
2755 arg_parts = x.split('/')
2756 if x[0] not in [".","/"] and \
2757 arg_parts[-1][-7:] != ".ebuild":
2758 #possible cat/pkg or dep; treat as such
2759 candidate_catpkgs.append(x)
2760 elif unmerge_action in ["prune","clean"]:
2761 print "\n!!! Prune and clean do not accept individual" + \
2762 " ebuilds as arguments;\n skipping.\n"
2765 # it appears that the user is specifying an installed
2766 # ebuild and we're in "unmerge" mode, so it's ok.
2767 if not os.path.exists(x):
2768 print "\n!!! The path '"+x+"' doesn't exist.\n"
2771 absx = os.path.abspath(x)
2772 sp_absx = absx.split("/")
2773 if sp_absx[-1][-7:] == ".ebuild":
2775 absx = "/".join(sp_absx)
2777 sp_absx_len = len(sp_absx)
2779 vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
2780 vdb_len = len(vdb_path)
2782 sp_vdb = vdb_path.split("/")
2783 sp_vdb_len = len(sp_vdb)
2785 if not os.path.exists(absx+"/CONTENTS"):
2786 print "!!! Not a valid db dir: "+str(absx)
2789 if sp_absx_len <= sp_vdb_len:
2790 # The Path is shorter... so it can't be inside the vdb.
2793 print "\n!!!",x,"cannot be inside "+ \
2794 vdb_path+"; aborting.\n"
2797 for idx in range(0,sp_vdb_len):
2798 if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
2801 print "\n!!!", x, "is not inside "+\
2802 vdb_path+"; aborting.\n"
2805 print "="+"/".join(sp_absx[sp_vdb_len:])
2806 candidate_catpkgs.append(
2807 "="+"/".join(sp_absx[sp_vdb_len:]))
2810 if (not "--quiet" in myopts):
2812 if settings["ROOT"] != "/":
2813 print darkgreen(newline+ \
2814 ">>> Using system located in ROOT tree "+settings["ROOT"])
2815 if (("--pretend" in myopts) or ("--ask" in myopts)) and \
2816 not ("--quiet" in myopts):
2817 print darkgreen(newline+\
2818 ">>> These are the packages that would be unmerged:")
2822 for x in candidate_catpkgs:
2823 # cycle through all our candidate deps and determine
2824 # what will and will not get unmerged
2826 mymatch=localtree.dep_match(x)
2829 except ValueError, errpkgs:
2830 print "\n\n!!! The short ebuild name \"" + \
2831 x + "\" is ambiguous. Please specify"
2832 print "!!! one of the following fully-qualified " + \
2833 "ebuild names instead:\n"
2834 for i in errpkgs[0]:
2835 print " " + green(i)
2839 if not mymatch and x[0] not in "<>=~":
2840 #add a "=" if missing
2841 mymatch=localtree.dep_match("="+x)
2843 if raise_on_missing:
2844 raise portage_exception.PackageNotFound(x)
2846 portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
2847 (x, unmerge_action), noiselevel=-1)
2849 mykey = portage.key_expand(
2851 mymatch[0]), mydb=vartree.dbapi, settings=settings)
2852 if not pkgmap.has_key(mykey):
2853 pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
2854 if unmerge_action=="unmerge":
2856 if y not in pkgmap[mykey]["selected"]:
2857 pkgmap[mykey]["selected"].append(y)
2858 numselected=numselected+len(mymatch)
2861 #unmerge_action in ["prune", clean"]
2863 for mypkg in mymatch:
2864 if unmerge_action=="clean":
2865 myslot=localtree.getslot(mypkg)
2867 # since we're pruning, we don't care about slots
2868 # and put all the pkgs in together
2870 if not slotmap.has_key(myslot):
2872 slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
2873 for myslot in slotmap.keys():
2874 counterkeys=slotmap[myslot].keys()
2879 pkgmap[mykey]["protected"].append(
2880 slotmap[myslot][counterkeys[-1]])
2882 #be pretty and get them in order of merge:
2883 for ckey in counterkeys:
2884 pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
2885 numselected=numselected+1
2886 # ok, now the last-merged package
2887 # is protected, and the rest are selected
2888 if global_unmerge and not numselected:
2889 print "\n>>> No outdated packages were found on your system.\n"
2893 print "\n>>> No packages selected for removal by", \
2894 unmerge_action+".\n"
2898 portage_locks.unlockdir(vdb_lock)
2899 for x in pkgmap.keys():
2900 for y in localtree.dep_match(x):
2901 if y not in pkgmap[x]["omitted"] and \
2902 y not in pkgmap[x]["selected"] and \
2903 y not in pkgmap[x]["protected"]:
2904 pkgmap[x]["omitted"].append(y)
2905 if global_unmerge and not pkgmap[x]["selected"]:
2906 #avoid cluttering the preview printout with stuff that isn't getting unmerged
2908 if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
2909 print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
2910 print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
2911 if "--pretend" not in myopts and "--ask" not in myopts:
2912 countdown(int(settings["EMERGE_WARNING_DELAY"]),
2913 colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
2914 print "\n "+white(x)
2915 for mytype in ["selected","protected","omitted"]:
2916 portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
2917 if pkgmap[x][mytype]:
2918 for mypkg in pkgmap[x][mytype]:
2919 mysplit=portage.catpkgsplit(mypkg)
2920 if mysplit[3]=="r0":
2921 myversion=mysplit[2]
2923 myversion=mysplit[2]+"-"+mysplit[3]
2924 if mytype=="selected":
2925 portage.writemsg_stdout(
2926 colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
2928 portage.writemsg_stdout(
2929 colorize("GOOD", myversion + " "), noiselevel=-1)
2931 portage.writemsg_stdout("none", noiselevel=-1)
2932 portage.writemsg_stdout("\n", noiselevel=-1)
2934 portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
2935 " packages are slated for removal.\n")
2936 portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
2937 " and " + colorize("GOOD", "'omitted'") + \
2938 " packages will not be removed.\n\n")
2940 if "--pretend" in myopts:
2941 #we're done... return
2943 if "--ask" in myopts:
2944 if userquery("Would you like to unmerge these packages?")=="No":
2945 # enter pretend mode for correct formatting of results
2946 myopts["--pretend"] = True
2951 #the real unmerging begins, after a short delay....
2952 countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
2954 for x in pkgmap.keys():
2955 for y in pkgmap[x]["selected"]:
2956 print ">>> Unmerging "+y+"..."
2957 emergelog(xterm_titles, "=== Unmerging... ("+y+")")
2958 mysplit=string.split(y,"/")
2960 retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
2961 mysettings, unmerge_action not in ["clean","prune"],
2962 vartree=vartree, ldpath_mtimes=ldpath_mtimes)
2963 if retval != os.EX_OK:
2964 emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
2966 clean_world(vartree.dbapi, y)
2967 emergelog(xterm_titles, " >>> unmerge success: "+y)
2970 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
2973 if os.path.exists("/usr/bin/install-info"):
2978 inforoot=normpath(root+z)
2979 if os.path.isdir(inforoot):
2980 infomtime = long(os.stat(inforoot).st_mtime)
2981 if inforoot not in prev_mtimes or \
2982 prev_mtimes[inforoot] != infomtime:
2983 regen_infodirs.append(inforoot)
2985 if not regen_infodirs:
2986 print " "+green("*")+" GNU info directory index is up-to-date."
2988 print " "+green("*")+" Regenerating GNU info directory index..."
2992 for inforoot in regen_infodirs:
2996 os.rename(inforoot+"/dir",inforoot+"/dir.old")
2997 except SystemExit, e:
2998 raise # Needed else can't exit
3002 if not os.path.isdir(inforoot):
3005 file_list = os.listdir(inforoot)
3008 if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
3010 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
3011 existsstr="already exists, for file `"
3013 if re.search(existsstr,myso):
3014 # Already exists... Don't increment the count for this.
3016 elif myso[:44]=="install-info: warning: no info dir entry in ":
3017 # This info file doesn't contain a DIR-header: install-info produces this
3018 # (harmless) warning (the --quiet switch doesn't seem to work).
3019 # Don't increment the count for this.
3023 errmsg += myso + "\n"
3026 #update mtime so we can potentially avoid regenerating.
3027 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
3030 print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
3033 print " "+green("*")+" Processed",icount,"info files."
3036 def post_emerge(settings, mtimedb, retval):
3037 target_root = settings["ROOT"]
3038 info_mtimes = mtimedb["info"]
3039 config_protect = settings.get("CONFIG_PROTECT","").split()
3040 infodirs = settings.get("INFOPATH","").split(":") + \
3041 settings.get("INFODIR","").split(":")
3045 emergelog("notitles" not in settings.features,
3046 " *** exiting successfully.")
3048 if "noinfo" not in settings.features:
3049 chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
3051 chk_updated_cfg_files(target_root, config_protect)
3056 def chk_updated_cfg_files(target_root, config_protect):
3058 #number of directories with some protect files in them
3060 for x in config_protect:
3061 x = os.path.join(target_root, x.lstrip(os.path.sep))
3063 mymode = os.lstat(x).st_mode
3066 if stat.S_ISDIR(mymode):
3067 mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
3069 mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
3070 os.path.split(x.rstrip(os.path.sep))
3071 a = commands.getstatusoutput(mycommand)
3073 print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
3075 files = a[1].split()
3078 print colorize("WARN", " * IMPORTANT:"),
3079 if stat.S_ISDIR(mymode):
3080 print "%d config files in '%s' need updating." % \
3083 print "config file '%s' needs updating." % x
3086 #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3087 print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
3090 def is_valid_package_atom(x):
3091 testkey = portage.dep_getkey(x)
3092 if testkey.startswith("null/"):
3093 testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
3098 return portage.isvalidatom(testatom)
3100 def validate_merge_list(trees, mergelist):
3101 """Validate the list to make sure all the packages are still available.
3102 This is needed for --resume."""
3103 for (pkg_type, myroot, pkg_key, action) in mergelist:
3104 if pkg_type == "binary" and \
3105 not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3106 pkg_type == "ebuild" and \
3107 not trees[myroot]["porttree"].dbapi.xmatch(
3108 "match-all", "="+pkg_key):
3109 print red("!!! Error: The resume list contains packages that are no longer")
3110 print red("!!! available to be emerged. Please restart/continue")
3111 print red("!!! the merge operation manually.")
3114 def show_blocker_docs_link():
3116 print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
3117 print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
3119 print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
3122 def action_sync(settings, trees, mtimedb, myopts, myaction):
3123 xterm_titles = "notitles" not in settings.features
3124 emergelog(xterm_titles, " === sync")
3125 myportdir = settings.get("PORTDIR", None)
3127 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
3129 if myportdir[-1]=="/":
3130 myportdir=myportdir[:-1]
3131 if not os.path.exists(myportdir):
3132 print ">>>",myportdir,"not found, creating it."
3133 os.makedirs(myportdir,0755)
3134 syncuri=string.rstrip(settings["SYNC"])
3136 updatecache_flg = False
3137 if myaction == "metadata":
3138 print "skipping sync"
3139 updatecache_flg = True
3140 tmpservertimestampfile = None
3141 elif syncuri[:8]=="rsync://":
3142 if not os.path.exists("/usr/bin/rsync"):
3143 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
3144 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
3150 if settings["PORTAGE_RSYNC_OPTS"] == "":
3151 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
3153 "--recursive", # Recurse directories
3154 "--links", # Consider symlinks
3155 "--safe-links", # Ignore links outside of tree
3156 "--perms", # Preserve permissions
3157 "--times", # Preserive mod times
3158 "--compress", # Compress the data transmitted
3159 "--force", # Force deletion on non-empty dirs
3160 "--whole-file", # Don't do block transfers, only entire files
3161 "--delete", # Delete files that aren't in the master tree
3162 "--delete-after", # Delete only after everything else is done
3163 "--stats", # Show final statistics about what was transfered
3164 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
3165 "--exclude='/distfiles'", # Exclude distfiles from consideration
3166 "--exclude='/local'", # Exclude local from consideration
3167 "--exclude='/packages'", # Exclude packages from consideration
3171 # The below validation is not needed when using the above hardcoded
3174 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
3175 rsync_opts.extend(settings["PORTAGE_RSYNC_OPTS"].split())
3177 for opt in ("--recursive", "--times"):
3178 if opt not in rsync_opts:
3179 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3180 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3181 rsync_opts.append(opt)
3183 for exclude in ("distfiles", "local", "packages"):
3184 opt = "--exclude=/%s" % exclude
3185 if opt not in rsync_opts:
3186 portage.writemsg(yellow("WARNING:") + \
3187 " adding required option %s not included in " % opt + \
3188 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
3189 rsync_opts.append(opt)
3191 if settings["RSYNC_TIMEOUT"] != "":
3192 portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
3193 "use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3195 mytimeout = int(settings["RSYNC_TIMEOUT"])
3196 rsync_opts.append("--timeout=%d" % mytimeout)
3197 except ValueError, e:
3198 portage.writemsg("!!! %s\n" % str(e))
3200 # TODO: determine options required for official servers
3201 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
3203 def rsync_opt_startswith(opt_prefix):
3204 for x in rsync_opts:
3205 if x.startswith(opt_prefix):
3209 if not rsync_opt_startswith("--timeout="):
3210 rsync_opts.append("--timeout=%d" % mytimeout)
3212 for opt in ("--compress", "--whole-file"):
3213 if opt not in rsync_opts:
3214 portage.writemsg(yellow("WARNING:") + " adding required option " + \
3215 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
3216 rsync_opts.append(opt)
3218 if "--quiet" in myopts:
3219 rsync_opts.append("--quiet") # Shut up a lot
3221 rsync_opts.append("--verbose") # Print filelist
3223 if "--verbose" in myopts:
3224 rsync_opts.append("--progress") # Progress meter for each file
3226 if "--debug" in myopts:
3227 rsync_opts.append("--checksum") # Force checksum on all files
3229 if settings["RSYNC_EXCLUDEFROM"] != "":
3230 portage.writemsg(yellow("WARNING:") + \
3231 " usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
3232 "PORTAGE_RSYNC_EXTRA_OPTS instead\n")
3233 if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
3234 rsync_opts.append("--exclude-from=%s" % \
3235 settings["RSYNC_EXCLUDEFROM"])
3237 portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
3238 " but file does not exist.\n")
3240 if settings["RSYNC_RATELIMIT"] != "":
3241 portage.writemsg(yellow("WARNING:") + \
3242 " usage of RSYNC_RATELIMIT is deprecated, use " + \
3243 "PORTAGE_RSYNC_EXTRA_OPTS instead")
3244 rsync_opts.append("--bwlimit=%s" % \
3245 settings["RSYNC_RATELIMIT"])
3247 servertimestampdir = settings.depcachedir+"/"
3248 servertimestampfile = settings.depcachedir+"/timestamp.chk"
3249 tmpservertimestampdir = settings["PORTAGE_TMPDIR"]+"/"
3250 tmpservertimestampfile = settings["PORTAGE_TMPDIR"]+"/timestamp.chk"
3252 # We only use the backup if a timestamp exists in the portdir.
3254 if os.path.exists(myportdir+"/metadata/timestamp.chk"):
3255 content=portage.grabfile(servertimestampfile)
3257 content=portage.grabfile(myportdir+"/metadata/timestamp.chk")
3261 mytimestamp=time.mktime(time.strptime(content[0], "%a, %d %b %Y %H:%M:%S +0000"))
3267 if not os.path.exists(servertimestampdir):
3268 os.mkdir(servertimestampdir)
3269 os.chown(servertimestampdir, os.getuid(), portage.portage_gid)
3270 os.chmod(servertimestampdir, 02775)
3274 if settings.has_key("RSYNC_RETRIES"):
3275 print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
3276 maxretries=int(settings["RSYNC_RETRIES"])
3278 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
3279 except SystemExit, e:
3280 raise # Needed else can't exit
3282 maxretries=3 #default number of retries
3285 user_name, hostname, port = re.split(
3286 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
3289 if user_name is None:
3291 updatecache_flg=True
3292 all_rsync_opts = set(rsync_opts)
3293 all_rsync_opts.update(
3294 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","").split())
3295 family = socket.AF_UNSPEC
3296 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
3297 family = socket.AF_INET
3298 elif socket.has_ipv6 and \
3299 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
3300 family = socket.AF_INET6
3307 for addrinfo in socket.getaddrinfo(
3308 hostname, None, family, socket.SOCK_STREAM):
3309 if addrinfo[0] == socket.AF_INET6:
3310 # IPv6 addresses need to be enclosed in square brackets
3311 ips.append("[%s]" % addrinfo[4][0])
3313 ips.append(addrinfo[4][0])
3314 except SystemExit, e:
3315 raise # Needed else can't exit
3316 except Exception, e:
3317 print "Notice:",str(e)
3322 dosyncuri = syncuri.replace(
3323 "//" + user_name + hostname + port + "/",
3324 "//" + user_name + ips[0] + port + "/", 1)
3325 except SystemExit, e:
3326 raise # Needed else can't exit
3327 except Exception, e:
3328 print "Notice:",str(e)
3332 if "--ask" in myopts:
3333 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
3338 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
3339 if "--quiet" not in myopts:
3340 print ">>> Starting rsync with "+dosyncuri+"..."
3342 emergelog(xterm_titles,
3343 ">>> Starting retry %d of %d with %s" % \
3344 (retries,maxretries,dosyncuri))
3345 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
3347 if "--quiet" not in myopts:
3348 print ">>> Checking server timestamp ..."
3350 rsynccommand = " ".join(["/usr/bin/rsync", " ".join(rsync_opts),
3351 settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")])
3353 if "--debug" in myopts:
3356 mycommand = " ".join([rsynccommand,
3357 dosyncuri + "/metadata/timestamp.chk",
3358 tmpservertimestampdir])
3359 exitcode=portage.spawn(mycommand,settings,free=1)
3362 servertimestamp = time.mktime(time.strptime(portage.grabfile(tmpservertimestampfile)[0], "%a, %d %b %Y %H:%M:%S +0000"))
3363 except SystemExit, e:
3364 raise # Needed else can't exit
3368 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
3369 emergelog(xterm_titles,
3370 ">>> Cancelling sync -- Already current.")
3373 print ">>> Timestamps on the server and in the local repository are the same."
3374 print ">>> Cancelling all further sync action. You are already up to date."
3378 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
3379 emergelog(xterm_titles,
3380 ">>> Server out of date: %s" % dosyncuri)
3383 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
3386 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
3388 mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
3389 exitcode=portage.spawn(mycommand,settings,free=1)
3390 if exitcode in [0,1,2,3,4,11,14,20,21]:
3392 elif exitcode in [0,1,2,3,4,11,14,20,21]:
3397 if retries<=maxretries:
3398 print ">>> Retrying..."
3403 updatecache_flg=False
3407 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
3408 # save timestamp.chk for next timestamp check.
3410 if tmpservertimestampfile is not None:
3411 portage.movefile(tmpservertimestampfile,
3412 servertimestampfile, mysettings=settings)
3413 except SystemExit, e:
3415 except Exception, e:
3416 portage.writemsg("!!! Failed to save current timestamp.\n",
3418 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
3423 print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
3424 print darkred("!!!")+green(" that your SYNC statement is proper.")
3425 print darkred("!!!")+green(" SYNC="+settings["SYNC"])
3427 print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
3428 print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
3429 print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
3430 print darkred("!!!")+green(" and try again after the problem has been fixed.")
3431 print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
3433 print darkred("!!!")+green(" Rsync was killed before it finished.")
3435 print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
3436 print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
3437 print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
3438 print darkred("!!!")+green(" temporary problem unless complications exist with your network")
3439 print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
3442 elif syncuri[:6]=="cvs://":
3443 if not os.path.exists("/usr/bin/cvs"):
3444 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
3445 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
3448 cvsdir=os.path.dirname(myportdir)
3449 if not os.path.exists(myportdir+"/CVS"):
3451 print ">>> Starting initial cvs checkout with "+syncuri+"..."
3452 if os.path.exists(cvsdir+"/gentoo-x86"):
3453 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
3458 if e.errno != errno.ENOENT:
3460 "!!! existing '%s' directory; exiting.\n" % myportdir)
3463 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
3464 print "!!! cvs checkout error; exiting."
3466 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
3469 print ">>> Starting cvs update with "+syncuri+"..."
3470 retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
3471 myportdir, settings, free=1)
3472 if retval != os.EX_OK:
3476 print "!!! rsync setting: ",syncuri,"not recognized; exiting."
3479 if updatecache_flg and \
3480 myaction != "metadata" and \
3481 "metadata-transfer" not in settings.features:
3482 updatecache_flg = False
3484 # Reload the whole config from scratch.
3485 settings, trees, mtimedb = load_emerge_config(trees=trees)
3486 portdb = trees[settings["ROOT"]]["porttree"].dbapi
3488 if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
3489 action_metadata(settings, portdb, myopts)
3491 if portage.global_updates(settings, trees, mtimedb["updates"]):
3493 # Reload the whole config from scratch.
3494 settings, trees, mtimedb = load_emerge_config(trees=trees)
3495 portdb = trees[settings["ROOT"]]["porttree"].dbapi
3497 mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
3498 mypvs = portage.best(
3499 trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
3501 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
3503 if myaction != "metadata":
3504 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
3505 retval = portage.portage_exec.spawn(
3506 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
3507 dosyncuri], env=settings.environ())
3508 if retval != os.EX_OK:
3509 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
3511 if(mybestpv != mypvs) and not "--quiet" in myopts:
3513 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
3514 print red(" * ")+"that you update portage now, before any other packages are updated."
3515 print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
3516 print red(" * ")+"configuration files."
3517 print red(" * ")+"To update portage, run 'emerge portage'."
3520 def action_metadata(settings, portdb, myopts):
3521 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
3522 old_umask = os.umask(0002)
3523 cachedir = os.path.normpath(settings.depcachedir)
3524 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
3525 "/lib", "/opt", "/proc", "/root", "/sbin",
3526 "/sys", "/tmp", "/usr", "/var"]:
3527 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
3528 "ROOT DIRECTORY ON YOUR SYSTEM."
3529 print >> sys.stderr, \
3530 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
3532 if not os.path.exists(cachedir):
3535 ec = portage.eclass_cache.cache(portdb.porttree_root)
3536 myportdir = os.path.realpath(settings["PORTDIR"])
3537 cm = settings.load_best_module("portdbapi.metadbmodule")(
3538 myportdir, "metadata/cache", portage.auxdbkeys[:])
3542 class percentage_noise_maker(cache.util.quiet_mirroring):
3543 def __init__(self, dbapi):
3545 self.cp_all = dbapi.cp_all()
3546 l = len(self.cp_all)
3547 self.call_update_min = 100000000
3548 self.min_cp_all = l/100.0
3553 for x in self.cp_all:
3555 if self.count > self.min_cp_all:
3556 self.call_update_min = 0
3558 for y in self.dbapi.cp_list(x):
3560 self.call_update_mine = 0
3562 def update(self, *arg):
3563 try: self.pstr = int(self.pstr) + 1
3564 except ValueError: self.pstr = 1
3565 sys.stdout.write("%s%i%%" % \
3566 ("\b" * (len(str(self.pstr))+1), self.pstr))
3568 self.call_update_min = 10000000
3570 def finish(self, *arg):
3571 sys.stdout.write("\b\b\b\b100%\n")
3574 if "--quiet" in myopts:
3575 def quicky_cpv_generator(cp_all_list):
3576 for x in cp_all_list:
3577 for y in portdb.cp_list(x):
3579 source = quicky_cpv_generator(portdb.cp_all())
3580 noise_maker = cache.util.quiet_mirroring()
3582 noise_maker = source = percentage_noise_maker(portdb)
3583 cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
3584 eclass_cache=ec, verbose_instance=noise_maker)
3589 def action_regen(settings, portdb):
3590 xterm_titles = "notitles" not in settings.features
3591 emergelog(xterm_titles, " === regen")
3592 #regenerate cache entries
3593 print "Regenerating cache entries... "
3595 os.close(sys.stdin.fileno())
3596 except SystemExit, e:
3597 raise # Needed else can't exit
3601 mynodes = portdb.cp_all()
3603 mymatches = portdb.xmatch("match-all",x)
3604 portage.writemsg_stdout("processing %s\n" % x)
3607 foo = portdb.aux_get(y,["DEPEND"])
3608 except SystemExit, e:
3609 # sys.exit is an exception... And consequently, we can't catch it.
3611 except Exception, e:
3612 print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
3615 def action_config(settings, trees, myopts, myfiles):
3616 if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
3617 print red("!!! config can only take a single package atom at this time\n")
3619 if not is_valid_package_atom(myfiles[0]):
3620 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
3622 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
3623 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
3627 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
3628 except ValueError, e:
3629 # Multiple matches thrown from cpv_expand
3632 print "No packages found.\n"
3635 if "--ask" in myopts:
3637 print "Please select a package to configure:"
3641 options.append(str(idx))
3642 print options[-1]+") "+pkg
3645 idx = userquery("Selection?", options)
3648 pkg = pkgs[int(idx)-1]
3650 print "The following packages available:"
3653 print "\nPlease use a specific atom or the --ask option."
3659 if "--ask" in myopts:
3660 if userquery("Ready to configure "+pkg+"?") == "No":
3663 print "Configuring pkg..."
3665 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
3666 mysettings = portage.config(clone=settings)
3667 portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
3668 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
3669 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
3672 def action_info(settings, trees, myopts, myfiles):
3673 unameout=commands.getstatusoutput("uname -mrp")[1]
3674 print getportageversion(settings["PORTDIR"], settings["ROOT"],
3675 settings.profile_path, settings["CHOST"],
3676 trees[settings["ROOT"]]["vartree"].dbapi)
3678 header_title = "System Settings"
3680 print header_width * "="
3681 print header_title.rjust(int(header_width/2 + len(header_title)/2))
3682 print header_width * "="
3683 print "System uname: "+unameout
3684 gentoo_release = portage.grabfile(os.path.join(
3685 settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
3687 print gentoo_release[0]
3689 print "Unknown Host Operating System"
3690 lastSync = portage.grabfile(os.path.join(
3691 settings["PORTDIR"], "metadata", "timestamp.chk"))
3698 output=commands.getstatusoutput("distcc --version")
3700 print str(string.split(output[1],"\n",1)[0]),
3701 if "distcc" in settings.features:
3706 output=commands.getstatusoutput("ccache -V")
3708 print str(string.split(output[1],"\n",1)[0]),
3709 if "ccache" in settings.features:
3714 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
3715 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
3716 myvars += portage_util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
3717 myvars = portage_util.unique_array(myvars)
3721 if portage.isvalidatom(x):
3722 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
3724 for y in pkg_matches:
3725 mycpv = portage.catpkgsplit(y)
3726 if(mycpv[3] != "r0"):
3727 pkgs += [mycpv[2] + "-" + mycpv[3]]
3731 pkgs = ", ".join(sorted_versions(pkgs))
3732 print "%-20s %s" % (x+":", pkgs)
3734 print "%-20s %s" % (x+":", "[NOT VALID]")
3736 libtool_vers = string.join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"), ",")
3738 if "--verbose" in myopts:
3739 myvars=settings.keys()
3741 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
3742 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
3743 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
3744 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
3746 myvars.extend(portage_util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
3748 myvars = portage_util.unique_array(myvars)
3752 if settings.has_key(x):
3753 print x+'="'+settings[x]+'"'
3755 unset_vars.append(x)
3757 print "Unset: "+", ".join(unset_vars)
3760 if "--debug" in myopts:
3761 for x in dir(portage):
3762 module = getattr(portage, x)
3763 if "cvs_id_string" in dir(module):
3764 print "%s: %s" % (str(x), str(module.cvs_id_string))
3766 # See if we can find any packages installed matching the strings
3767 # passed on the command line
3769 vardb = trees[settings["ROOT"]]["vartree"].dbapi
3770 portdb = trees[settings["ROOT"]]["porttree"].dbapi
3772 mypkgs.extend(vardb.match(x))
3774 # If some packages were found...
3776 # Get our global settings (we only print stuff if it varies from
3777 # the current config)
3778 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
3779 auxkeys = mydesiredvars + [ "USE", "IUSE"]
3781 pkgsettings = portage.config(clone=settings)
3783 for myvar in mydesiredvars:
3784 global_vals[myvar] = set(settings.get(myvar, "").split())
3786 # Loop through each package
3787 # Only print settings if they differ from global settings
3788 header_printed = False
3790 # Get all package specific variables
3791 auxvalues = vardb.aux_get(pkg, auxkeys)
3793 for i in xrange(len(auxkeys)):
3794 valuesmap[auxkeys[i]] = set(auxvalues[i].split())
3796 for myvar in mydesiredvars:
3797 # If the package variable doesn't match the
3798 # current global variable, something has changed
3799 # so set diff_found so we know to print
3800 if valuesmap[myvar] != global_vals[myvar]:
3801 diff_values[myvar] = valuesmap[myvar]
3802 valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
3803 valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
3805 pkgsettings.setcpv(pkg, mydb=portdb)
3806 if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
3808 diff_values["USE"] = valuesmap["USE"]
3809 # If a difference was found, print the info for
3813 # If we have not yet printed the header,
3815 if not header_printed:
3816 header_title = "Package Settings"
3817 print header_width * "="
3818 print header_title.rjust(int(header_width/2 + len(header_title)/2))
3819 print header_width * "="
3820 header_printed = True
3822 # Print package info
3823 print "%s was built with the following:" % pkg
3824 for myvar in mydesiredvars + ["USE"]:
3825 if myvar in diff_values:
3826 mylist = list(diff_values[myvar])
3828 print "%s=\"%s\"" % (myvar, " ".join(mylist))
3831 def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
3833 print "emerge: no search terms provided."
3835 searchinstance = search(settings, portdb,
3836 vartree, spinner, "--searchdesc" in myopts,
3837 "--quiet" not in myopts)
3838 for mysearch in myfiles:
3840 searchinstance.execute(mysearch)
3841 except re.error, comment:
3842 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
3844 searchinstance.output()
3846 def action_depclean(settings, trees, ldpath_mtimes,
3848 # Kill packages that aren't explicitly merged or are required as a
3849 # dependency of another package. World file is explicit.
3851 warn_prefix = colorize("BAD", "*** WARNING *** ")
3853 print warn_prefix + "Depclean may break link level dependencies. Thus, it is"
3854 print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
3855 print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
3857 print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
3858 print warn_prefix + "mistakes. Packages that are part of the world set will always"
3859 print warn_prefix + "be kept. They can be manually added to this set with"
3860 print warn_prefix + good("`emerge --noreplace <atom>`") + ". Packages that are listed in"
3861 print warn_prefix + "package.provided (see portage(5)) will be removed by"
3862 print warn_prefix + "depclean, even if they are part of the world set."
3864 print warn_prefix + "As a safety measure, depclean will not remove any packages"
3865 print warn_prefix + "unless *all* required dependencies have been resolved. As a"
3866 print warn_prefix + "consequence, it is often necessary to run "
3867 print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
3869 xterm_titles = "notitles" not in settings.features
3870 portdb = trees[settings["ROOT"]]["porttree"].dbapi
3871 vartree = trees[settings["ROOT"]]["vartree"]
3872 vardb = vartree.dbapi
3873 syslist = getlist(settings, "system")
3874 worldlist = getlist(settings, "world")
3875 fakedb = portage.fakedbapi(settings=settings)
3876 emptydb = portage.fakedbapi(settings=settings)
3877 myvarlist = vardb.cpv_all()
3880 print "\n!!! You have no system list.",
3882 print "\n!!! You have no world file.",
3884 print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
3886 if not (syslist and worldlist and myvarlist):
3887 print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
3888 print " break your installation.\n"
3889 if "--pretend" not in myopts:
3890 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
3892 if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
3893 emergelog(xterm_titles, " >>> depclean")
3895 if "--quiet" not in myopts:
3896 print "\nCalculating dependencies ",
3900 remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
3901 remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
3903 aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
3905 while remaining_atoms:
3906 atom, parent, priority = remaining_atoms.pop()
3907 pkgs = vardb.match(atom)
3909 if not atom.startswith("!") and priority == hard:
3910 unresolveable.setdefault(atom, []).append(parent)
3912 # Could put slot checking here to ensure that there aren't two
3913 # packages with the same slot...
3915 if fakedb.cpv_exists(pkg):
3918 fakedb.cpv_inject(pkg)
3919 mydb = portdb.xmatch("match-visible", "="+pkg) and portdb or vardb
3920 myaux = dict(zip(aux_keys, mydb.aux_get(pkg, aux_keys)))
3922 if myopts.get("--with-bdeps", "y") == "y":
3923 mydeps.append((myaux["DEPEND"], soft))
3925 mydeps.append((" ".join(myaux.values()), hard))
3926 usedef = vardb.aux_get(pkg, ["USE"])[0].split()
3927 for depstr, priority in mydeps:
3928 success, atoms = portage.dep_check(depstr, emptydb, settings,
3929 myuse=usedef, trees=trees, myroot=settings["ROOT"])
3932 print "Error occurred while processing",pkg
3936 remaining_atoms.append((atom, pkg, priority))
3938 if "--quiet" not in myopts:
3939 print "\b\b... done!\n"
3942 print "Dependencies could not be completely resolved due to"
3943 print "the following required packages not being installed:"
3945 for atom in unresolveable:
3946 print atom, "required by", " ".join(unresolveable[atom])
3948 print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
3949 print "depclean? It may also be necessary to manually uninstalled packages that no"
3950 print "longer exist in the portage tree since it may not be possible to satisfy their"
3951 print "dependencies."
3955 cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
3958 unmerge(settings, myopts, vartree, "unmerge", cleanlist, ldpath_mtimes)
3960 print "Packages installed: "+str(len(myvarlist))
3961 print "Packages in world: "+str(len(worldlist))
3962 print "Packages in system: "+str(len(syslist))
3963 print "Unique package names: "+str(len(myvarlist))
3964 print "Required packages: "+str(len(fakedb.cpv_all()))
3965 if "--pretend" in myopts:
3966 print "Number to remove: "+str(len(cleanlist))
3968 print "Number removed: "+str(len(cleanlist))
3970 def action_build(settings, trees, mtimedb,
3971 myopts, myaction, myfiles, spinner):
3972 ldpath_mtimes = mtimedb["ldpath"]
3974 if ("--ask" in myopts or "--pretend" in myopts) and not "--quiet" in myopts:
3976 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
3980 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
3982 print darkgreen("These are the packages that would be %s, in reverse order:") % action
3986 print darkgreen("These are the packages that would be %s, in order:") % action
3989 # validate the state of the resume data
3990 # so that we can make assumptions later.
3991 for k in ("resume", "resume_backup"):
3993 if "mergelist" in mtimedb[k]:
3994 if not mtimedb[k]["mergelist"]:
3999 if "--resume" in myopts and \
4000 ("resume" in mtimedb or
4001 "resume_backup" in mtimedb):
4002 if "resume" not in mtimedb:
4003 mtimedb["resume"] = mtimedb["resume_backup"]
4004 del mtimedb["resume_backup"]
4006 # XXX: "myopts" is a list for backward compatibility.
4007 myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
4009 for opt in ("--skipfirst", "--ask", "--tree"):
4010 myresumeopts.pop(opt, None)
4012 for myopt, myarg in myopts.iteritems():
4013 if myopt not in myresumeopts:
4014 myresumeopts[myopt] = myarg
4016 myparams = create_depgraph_params(myopts, myaction)
4017 mydepgraph = depgraph(settings, trees,
4018 myopts, myparams, spinner)
4020 if ("--resume" in myopts):
4021 print darkgreen("emerge: It seems we have nothing to resume...")
4024 myparams = create_depgraph_params(myopts, myaction)
4025 mydepgraph = depgraph(settings, trees,
4026 myopts, myparams, spinner)
4027 if myaction in ["system","world"]:
4028 if not ("--quiet" in myopts):
4029 print "Calculating",myaction,"dependencies ",
4031 if not mydepgraph.xcreate(myaction):
4032 print "!!! Depgraph creation failed."
4034 if not ("--quiet" in myopts):
4035 print "\b\b... done!"
4037 if not ("--quiet" in myopts):
4038 print "Calculating dependencies ",
4041 retval, favorites = mydepgraph.select_files(myfiles)
4042 except portage_exception.PackageNotFound, e:
4043 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4047 if not ("--quiet" in myopts):
4048 print "\b\b... done!"
4050 if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
4051 sys.stderr.write(red("The following binaries are not available for merging...\n"))
4053 if mydepgraph.missingbins:
4054 for x in mydepgraph.missingbins:
4055 sys.stderr.write(" "+str(x)+"\n")
4056 sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
4059 if "--ask" in myopts:
4060 if "--resume" in myopts:
4061 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4062 mymergelist = mtimedb["resume"]["mergelist"]
4063 if "--skipfirst" in myopts:
4064 mymergelist = mymergelist[1:]
4065 if len(mymergelist) == 0:
4066 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4068 mydepgraph.display(mymergelist)
4069 prompt="Would you like to resume merging these packages?"
4072 mydepgraph.altlist(reversed=("--tree" in myopts)))
4074 for x in mydepgraph.altlist():
4075 if x[0] != "blocks" and x[3] != "nomerge":
4077 #check for blocking dependencies
4078 if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
4079 print "\n!!! Error: The above package list contains packages which cannot be installed"
4080 print "!!! at the same time on the same system."
4081 if "--quiet" not in myopts:
4082 show_blocker_docs_link()
4085 if "--noreplace" in myopts and favorites:
4088 print " %s %s" % (good("*"), x)
4089 prompt="Would you like to add these packages to your world favorites?"
4090 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4091 prompt="Nothing to merge; would you like to auto-clean packages?"
4094 print "Nothing to merge; quitting."
4097 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4098 prompt="Would you like to fetch the source files for these packages?"
4100 prompt="Would you like to merge these packages?"
4102 if userquery(prompt)=="No":
4107 # Don't ask again (e.g. when auto-cleaning packages after merge)
4110 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4111 if ("--resume" in myopts):
4112 validate_merge_list(trees, mtimedb["resume"]["mergelist"])
4113 mymergelist = mtimedb["resume"]["mergelist"]
4114 if "--skipfirst" in myopts:
4115 mymergelist = mymergelist[1:]
4116 if len(mymergelist) == 0:
4117 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4119 mydepgraph.display(mymergelist)
4122 mydepgraph.altlist(reversed=("--tree" in myopts)))
4124 if ("--buildpkgonly" in myopts):
4125 if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
4126 print "\n!!! --buildpkgonly requires all dependencies to be merged."
4127 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
4130 if ("--resume" in myopts):
4131 favorites=mtimedb["resume"]["favorites"]
4132 mergetask = MergeTask(settings, trees, myopts)
4133 if "--fetchonly" in myopts:
4134 """ parallel-fetch uses --resume --fetchonly and we don't want
4135 it to write the mtimedb"""
4136 mtimedb.filename = None
4137 time.sleep(3) # allow the parent to have first fetch
4138 retval = mergetask.merge(
4139 mtimedb["resume"]["mergelist"], favorites, mtimedb)
4140 if retval != os.EX_OK:
4143 if "resume" in mtimedb and \
4144 "mergelist" in mtimedb["resume"] and \
4145 len(mtimedb["resume"]["mergelist"]) > 1:
4146 mtimedb["resume_backup"] = mtimedb["resume"]
4147 del mtimedb["resume"]
4149 mtimedb["resume"]={}
4150 # XXX: Stored as a list for backward compatibility.
4151 mtimedb["resume"]["myopts"] = \
4152 [k for k in myopts if myopts[k] is True]
4153 mtimedb["resume"]["favorites"]=favorites
4154 if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4155 for pkgline in mydepgraph.altlist():
4156 if pkgline[0]=="ebuild" and pkgline[3]=="merge":
4157 y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
4158 tmpsettings = portage.config(clone=settings)
4160 if settings.get("PORTAGE_DEBUG", "") == "1":
4162 retval = portage.doebuild(
4163 y, "digest", settings["ROOT"], tmpsettings, edebug,
4164 ("--pretend" in myopts),
4165 mydbapi=trees[pkgline[1]]["porttree"].dbapi,
4167 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4169 for pkg in mydepgraph.altlist():
4170 if pkg[0] != "blocks":
4173 pkglist = mydepgraph.altlist()
4174 mergetask = MergeTask(settings, trees, myopts)
4175 retval = mergetask.merge(pkglist, favorites, mtimedb)
4176 if retval != os.EX_OK:
4179 if mtimedb.has_key("resume"):
4180 del mtimedb["resume"]
4181 if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4182 print ">>> Auto-cleaning packages..."
4183 vartree = trees[settings["ROOT"]]["vartree"]
4184 unmerge(settings, myopts, vartree, "clean", ["world"],
4187 portage.writemsg_stdout(colorize("WARN", "WARNING:")
4188 + " AUTOCLEAN is disabled. This can cause serious"
4189 + " problems due to overlapping packages.\n")
4191 def multiple_actions(action1, action2):
4192 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
4193 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
4196 def parse_opts(tmpcmdline):
4201 global actions, options, shortmapping
4203 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
4204 argument_options = {
4206 "help":"enable or disable color output",
4208 "choices":("y", "n")
4211 "help":"include unnecessary build time dependencies",
4213 "choices":("y", "n")
4217 from optparse import OptionParser
4218 parser = OptionParser()
4219 if parser.has_option("--help"):
4220 parser.remove_option("--help")
4222 for action_opt in actions:
4223 parser.add_option("--" + action_opt, action="store_true",
4224 dest=action_opt.replace("-", "_"), default=False)
4225 for myopt in options:
4226 parser.add_option(myopt, action="store_true",
4227 dest=myopt.lstrip("--").replace("-", "_"), default=False)
4228 for shortopt, longopt in shortmapping.iteritems():
4229 parser.add_option("-" + shortopt, action="store_true",
4230 dest=longopt.lstrip("--").replace("-", "_"), default=False)
4231 for myalias, myopt in longopt_aliases.iteritems():
4232 parser.add_option(myalias, action="store_true",
4233 dest=myopt.lstrip("--").replace("-", "_"), default=False)
4235 for myopt, kwargs in argument_options.iteritems():
4236 parser.add_option(myopt,
4237 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
4239 myoptions, myargs = parser.parse_args(args=tmpcmdline)
4241 for myopt in options:
4242 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
4244 myopts[myopt] = True
4246 for myopt in argument_options:
4247 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
4251 for action_opt in actions:
4252 v = getattr(myoptions, action_opt.replace("-", "_"))
4255 multiple_actions(myaction, action_opt)
4257 myaction = action_opt
4261 if x not in ["system", "world"]:
4262 print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
4264 multiple_actions(myaction, x)
4270 if "--nocolor" in myopts:
4271 print "*** Deprecated use of '--nocolor', use '--color=n' instead."
4272 del myopts["--nocolor"]
4273 myopts["--color"] = "n"
4275 return myaction, myopts, myfiles
4277 def validate_ebuild_environment(trees):
4278 for myroot in trees:
4279 mysettings = trees[myroot]["vartree"].settings
4280 if not mysettings.get("ARCH", None):
4281 print >> sys.stderr, bad("\a!!! ARCH is not set... " + \
4282 "Are you missing the '%setc/make.profile' symlink?" % \
4283 mysettings["PORTAGE_CONFIGROOT"])
4284 print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
4285 "Is your portage tree complete?\n")
4287 del myroot, mysettings
4289 def load_emerge_config(trees=None):
4291 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
4292 kwargs[k] = os.environ.get(envvar, "/")
4293 trees = portage.create_trees(trees=trees, **kwargs)
4295 settings = trees["/"]["vartree"].settings
4297 for myroot in trees:
4299 settings = trees[myroot]["vartree"].settings
4302 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
4303 mtimedb = portage.MtimeDB(mtimedbfile)
4304 return settings, trees, mtimedb
4306 def adjust_config(myopts, settings):
4307 """Make emerge specific adjustments to the config."""
4309 # To enhance usability, make some vars case insensitive by forcing them to
4311 for myvar in ("AUTOCLEAN", "NOCOLOR"):
4312 if myvar in settings:
4313 settings[myvar] = settings[myvar].lower()
4314 settings.backup_changes(myvar)
4317 # Kill noauto as it will break merges otherwise.
4318 if "noauto" in settings.features:
4319 while "noauto" in settings.features:
4320 settings.features.remove("noauto")
4321 settings["FEATURES"] = " ".join(settings.features)
4322 settings.backup_changes("FEATURES")
4326 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
4327 except ValueError, e:
4328 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4329 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
4330 settings["CLEAN_DELAY"], noiselevel=-1)
4331 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
4332 settings.backup_changes("CLEAN_DELAY")
4334 EMERGE_WARNING_DELAY = 10
4336 EMERGE_WARNING_DELAY = int(settings.get(
4337 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
4338 except ValueError, e:
4339 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4340 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
4341 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
4342 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
4343 settings.backup_changes("EMERGE_WARNING_DELAY")
4345 if "--quiet" in myopts:
4346 settings["PORTAGE_QUIET"]="1"
4347 settings.backup_changes("PORTAGE_QUIET")
4349 # Set so that configs will be merged regardless of remembered status
4350 if ("--noconfmem" in myopts):
4351 settings["NOCONFMEM"]="1"
4352 settings.backup_changes("NOCONFMEM")
4354 # Set various debug markers... They should be merged somehow.
4357 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
4358 if PORTAGE_DEBUG not in (0, 1):
4359 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
4360 PORTAGE_DEBUG, noiselevel=-1)
4361 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
4364 except ValueError, e:
4365 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
4366 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
4367 settings["PORTAGE_DEBUG"], noiselevel=-1)
4369 if "--debug" in myopts:
4371 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
4372 settings.backup_changes("PORTAGE_DEBUG")
4374 """The explicit --color < y | n > option overrides the NOCOLOR environment
4375 variable and stdout auto-detection."""
4376 if "--color" in myopts:
4377 if "y" == myopts["--color"]:
4378 output.havecolor = 1
4379 settings["NOCOLOR"] = "false"
4381 output.havecolor = 0
4382 settings["NOCOLOR"] = "true"
4383 settings.backup_changes("NOCOLOR")
4384 elif not sys.stdout.isatty():
4385 output.havecolor = 0
4386 settings["NOCOLOR"] = "true"
4387 settings.backup_changes("NOCOLOR")
4390 # Portage needs to ensure a sane umask for the files it creates.
4392 settings, trees, mtimedb = load_emerge_config()
4393 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4396 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
4397 except (OSError, ValueError), e:
4398 portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
4399 settings["PORTAGE_NICENESS"])
4400 portage.writemsg("!!! %s\n" % str(e))
4403 if portage.global_updates(settings, trees, mtimedb["updates"]):
4405 # Reload the whole config from scratch.
4406 settings, trees, mtimedb = load_emerge_config(trees=trees)
4407 portdb = trees[settings["ROOT"]]["porttree"].dbapi
4409 ldpath_mtimes = mtimedb["ldpath"]
4410 xterm_titles = "notitles" not in settings.features
4412 """Disable color as early as possible via NOCOLOR and stdout
4413 auto-detection. This initial setting may later be overridden via the
4414 --color < yes | no > option."""
4415 if settings.get("NOCOLOR","").lower() in ("yes","true"):
4417 elif (not sys.stdout.isatty()) and \
4418 settings.get("NOCOLOR","").lower() != "no":
4419 # revdep-rebuild exports NOCOLOR=false, so for now, don't allow
4420 # NOCOLOR=false to override the isatty() check. This can be fixed
4421 # in revdep-rebuild by using the --nocolor option when appropriate
4422 # instead of exporting NOCOLOR.
4426 if "--ignore-default-opts" not in sys.argv:
4427 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
4428 tmpcmdline.extend(sys.argv[1:])
4429 myaction, myopts, myfiles = parse_opts(tmpcmdline)
4431 for myroot in trees:
4432 mysettings = trees[myroot]["vartree"].settings
4434 adjust_config(myopts, mysettings)
4436 del myroot, mysettings
4438 spinner = stdout_spinner()
4439 if "candy" in settings.features:
4440 spinner.update = spinner.update_scroll
4442 portage.deprecated_profile_check()
4444 #Freeze the portdbapi for enhanced performance:
4445 for myroot in trees:
4446 trees[myroot]["porttree"].dbapi.freeze()
4449 if "moo" in myfiles:
4452 Larry loves Gentoo (""" + os.uname()[0] + """)
4454 _______________________
4455 < Have you mooed today? >
4456 -----------------------
4465 if (myaction in ["world", "system"]) and myfiles:
4466 print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
4470 ext = os.path.splitext(x)[1]
4471 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
4472 print "emerging by path implies --oneshot... adding --oneshot to options."
4473 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
4476 if ("--tree" in myopts) and ("--columns" in myopts):
4477 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
4480 if ("--quiet" in myopts):
4481 spinner.update = spinner.update_quiet
4482 portage_util.noiselimit = -1
4484 # Always create packages if FEATURES=buildpkg
4485 # Imply --buildpkg if --buildpkgonly
4486 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
4487 if "--buildpkg" not in myopts:
4488 myopts["--buildpkg"] = True
4490 # Also allow -S to invoke search action (-sS)
4491 if ("--searchdesc" in myopts):
4492 if myaction and myaction != "search":
4493 myfiles.append(myaction)
4494 if "--search" not in myopts:
4495 myopts["--search"] = True
4498 # Always try and fetch binary packages if FEATURES=getbinpkg
4499 if ("getbinpkg" in settings.features):
4500 myopts["--getbinpkg"] = True
4502 if "--skipfirst" in myopts and "--resume" not in myopts:
4503 myopts["--resume"] = True
4505 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
4506 myopts["--usepkgonly"] = True
4508 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
4509 myopts["--getbinpkg"] = True
4511 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
4512 myopts["--usepkg"] = True
4514 # Also allow -K to apply --usepkg/-k
4515 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
4516 myopts["--usepkg"] = True
4518 # Also allow -l to apply --pretend/-p, but if already in --ask mode
4519 if ("--changelog" in myopts) and not (("--pretend" in myopts) or ("--ask" in myopts)):
4520 print ">>> --changelog implies --pretend... adding --pretend to options."
4521 myopts["--pretend"] = True
4523 # Allow -p to remove --ask
4524 if ("--pretend" in myopts) and ("--ask" in myopts):
4525 print ">>> --pretend disables --ask... removing --ask from options."
4528 # forbid --ask when not in a terminal
4529 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
4530 if ("--ask" in myopts) and (not sys.stdin.isatty()):
4531 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
4535 if settings.get("PORTAGE_DEBUG", "") == "1":
4537 if "python-trace" in settings.features:
4538 import portage_debug
4539 portage_debug.set_trace(True)
4541 if ("--resume" in myopts):
4542 if "--tree" in myopts:
4543 print "* --tree is currently broken with --resume. Disabling..."
4544 del myopts["--tree"]
4546 if not ("--quiet" in myopts):
4547 if not sys.stdout.isatty() or ("--nospinner" in myopts):
4548 spinner.update = spinner.update_basic
4550 if "--version" in myopts:
4551 print getportageversion(settings["PORTDIR"], settings["ROOT"],
4552 settings.profile_path, settings["CHOST"],
4553 trees[settings["ROOT"]]["vartree"].dbapi)
4555 elif "--help" in myopts:
4556 emergehelp.help(myaction, myopts, output.havecolor)
4559 if portage.wheelgid == portage.portage_gid:
4560 print "emerge: wheel group use is being deprecated. Please update group and passwd to"
4561 print " include the portage user as noted above, and then use group portage."
4563 if "--debug" in myopts:
4564 print "myaction", myaction
4565 print "myopts", myopts
4567 if not myaction and not myfiles and "--resume" not in myopts:
4568 emergehelp.help(myaction, myopts, output.havecolor)
4571 # check if root user is the current user for the actions where emerge needs this
4572 if portage.secpass < 2:
4573 # We've already allowed "--version" and "--help" above.
4574 if "--pretend" not in myopts and \
4575 myaction not in ("search","info"):
4576 if portage.secpass < 1 or \
4577 not ("--fetchonly" in myopts or \
4578 "--fetch-all-uri" in myopts or \
4579 myaction in ("metadata", "regen")):
4580 if "--ask" in myopts:
4581 myopts["--pretend"] = True
4583 print "root access would be required..." + \
4584 " adding --pretend to options."
4586 print "emerge: root access required."
4589 disable_emergelog = False
4590 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
4592 disable_emergelog = True
4594 if myaction in ("search", "info"):
4595 disable_emergelog = True
4596 if disable_emergelog:
4597 """ Disable emergelog for everything except build or unmerge
4598 operations. This helps minimize parallel emerge.log entries that can
4599 confuse log parsers. We especially want it disabled during
4600 parallel-fetch, which uses --resume --fetchonly."""
4602 def emergelog(*pargs, **kargs):
4605 if not "--pretend" in myopts:
4606 emergelog(xterm_titles, "Started emerge on: "+\
4607 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
4610 myelogstr=string.join(myopts, " ")
4612 myelogstr+=" "+myaction
4614 myelogstr+=" "+string.join(myfiles, " ")
4615 emergelog(xterm_titles, " *** emerge " + myelogstr)
4617 def emergeexitsig(signum, frame):
4618 signal.signal(signal.SIGINT, signal.SIG_IGN)
4619 signal.signal(signal.SIGTERM, signal.SIG_IGN)
4620 portage_util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
4621 sys.exit(100+signum)
4622 signal.signal(signal.SIGINT, emergeexitsig)
4623 signal.signal(signal.SIGTERM, emergeexitsig)
4626 """This gets out final log message in before we quit."""
4627 if "--pretend" not in myopts:
4628 emergelog(xterm_titles, " *** terminating.")
4629 if "notitles" not in settings.features:
4631 portage.atexit_register(emergeexit)
4633 if myaction in ["sync","metadata"] and "--help" not in myopts:
4634 if "--pretend" in myopts:
4635 print "emerge: \"sync\" actions do not support \"--pretend.\""
4637 if "sync" == myaction:
4638 action_sync(settings, trees, mtimedb, myopts, myaction)
4640 action_metadata(settings, portdb, myopts)
4641 elif myaction=="regen":
4642 validate_ebuild_environment(trees)
4643 action_regen(settings, portdb)
4645 elif "config"==myaction:
4646 if "--pretend" in myopts:
4647 sys.stderr.write("emerge: The --config action " + \
4648 "does not support --pretend.\n")
4650 validate_ebuild_environment(trees)
4651 action_config(settings, trees, myopts, myfiles)
4654 elif "info"==myaction:
4655 action_info(settings, trees, myopts, myfiles)
4658 elif "search"==myaction:
4659 validate_ebuild_environment(trees)
4660 action_search(settings, portdb, trees["/"]["vartree"],
4661 myopts, myfiles, spinner)
4662 elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
4663 validate_ebuild_environment(trees)
4664 vartree = trees[settings["ROOT"]]["vartree"]
4665 if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
4666 ldpath_mtimes, raise_on_missing=False):
4667 if "--pretend" not in myopts:
4668 post_emerge(settings, mtimedb, 0)
4670 elif "depclean"==myaction:
4671 validate_ebuild_environment(trees)
4672 action_depclean(settings, trees, ldpath_mtimes,
4674 if "--pretend" not in myopts:
4675 post_emerge(settings, mtimedb, 0)
4676 # "update", "system", or just process files:
4678 validate_ebuild_environment(trees)
4679 action_build(settings, trees, mtimedb,
4680 myopts, myaction, myfiles, spinner)
4681 if "--pretend" not in myopts:
4682 post_emerge(settings, mtimedb, 0)
4684 if __name__ == "__main__":
4685 retval = emerge_main()