Merged from trunk -r15470:15477
authorFabian Groffen <grobian@gentoo.org>
Sat, 27 Feb 2010 20:11:56 +0000 (20:11 -0000)
committerFabian Groffen <grobian@gentoo.org>
Sat, 27 Feb 2010 20:11:56 +0000 (20:11 -0000)
   | 15471   | Bug #307021 - Show "Please fix" message in red instead of    |
   | zmedico | turquoise when repoman fails.                                |

   | 15472   | Another turquoise -> red.                                    |
   | zmedico |                                                              |

   | 15473   | Move missing encodings module workarounds (<python-2.6.4 +   |
   | zmedico | USE=build) to a _ensure_encodings module that's only         |
   |         | imported on demand.                                          |

   | 15474   | Remove unused 'dircache' variable that's moved to            |
   | zmedico | portage.util.listdir.                                        |

   | 15475   | Move portage._global_updates to a submodule.                 |
   | zmedico |                                                              |

   | 15476   | Remove deprecated flushmtimedb function.                     |
   | zmedico |                                                              |

   | 15477   | Fix reference to portage.util.listdir.dircache.              |
   | zmedico |                                                              |

svn path=/main/branches/prefix/; revision=15485

bin/fixpackages
bin/repoman
pym/_emerge/actions.py
pym/_emerge/clear_caches.py
pym/_emerge/main.py
pym/portage/__init__.py
pym/portage/_ensure_encodings.py [new file with mode: 0644]
pym/portage/_global_updates.py [new file with mode: 0644]

index 140eda4bb4a9f4be5200e90efd7bc536349291b5..fed30ac754b29dc3dae191b9ad1f820db0ca0b9e 100755 (executable)
@@ -9,6 +9,7 @@ import os,sys
 os.environ["PORTAGE_CALLER"]="fixpackages"
 
 from portage import os
+from portage._global_updates import _global_updates
 mysettings = portage.settings
 mytrees = portage.db
 mtimedb = portage.mtimedb
@@ -21,7 +22,7 @@ except (OSError, ValueError) as e:
        portage.writemsg("!!! %s\n" % str(e))
        del e
 
-portage._global_updates(mytrees, mtimedb["updates"])
+_global_updates(mytrees, mtimedb["updates"])
 
 print()
 print("Done.")
index 5a924f5f1e6e9180f3f4e5946c1d96a57bf2252b..4cdeae5de7e1894115b136b86a573f6643fa2e4f 100755 (executable)
@@ -1956,7 +1956,7 @@ if options.mode != 'commit':
        elif not dofail:
                print(green("RepoMan sez:"),"\"If everyone were like you, I'd be out of business!\"")
        elif dofail:
-               print(turquoise("Please fix these important QA issues first."))
+               print(bad("Please fix these important QA issues first."))
                print(green("RepoMan sez:"),"\"Make your QA payment on time and you'll never see the likes of me.\"\n")
                sys.exit(1)
 else:
@@ -1967,7 +1967,7 @@ else:
        elif dofail:
                if options.force and not can_force:
                        print(bad("The --force option has been disabled due to extraordinary issues."))
-               print(turquoise("Please fix these important QA issues first."))
+               print(bad("Please fix these important QA issues first."))
                print(green("RepoMan sez:"),"\"Make your QA payment on time and you'll never see the likes of me.\"\n")
                sys.exit(1)
 
index 05839b8bed43b69b5660c8a5993852d0844f1ed8..aff3ce7b13e6a130dc95581a1d258bad15e3752f 100644 (file)
@@ -35,6 +35,7 @@ bad = create_color_func("BAD")
 from portage.sets import load_default_config, SETPREFIX
 from portage.sets.base import InternalPackageSet
 from portage.util import cmp_sort_key, writemsg, writemsg_level
+from portage._global_updates import _global_updates
 
 from _emerge.clear_caches import clear_caches
 from _emerge.countdown import countdown
@@ -2207,7 +2208,7 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
                # the only one that's been synced here.
                action_metadata(settings, portdb, myopts, porttrees=[myportdir])
 
-       if portage._global_updates(trees, mtimedb["updates"]):
+       if _global_updates(trees, mtimedb["updates"]):
                mtimedb.commit()
                # Reload the whole config from scratch.
                settings, trees, mtimedb = load_emerge_config(trees=trees)
index 83ab77eb42aacd4bf28041cedd07eb0a53560dad..a6b004f5d9299853518fd5e8f44adc651b4ed4a0 100644 (file)
@@ -4,6 +4,7 @@
 
 import gc
 import portage
+from portage.util.listdir import dircache
 
 def clear_caches(trees):
        for d in trees.values():
@@ -12,5 +13,5 @@ def clear_caches(trees):
                d["bintree"].dbapi._aux_cache.clear()
                d["bintree"].dbapi._clear_cache()
                d["vartree"].dbapi.linkmap._clear_cache()
-       portage.dircache.clear()
+       dircache.clear()
        gc.collect()
index acae2b545162785400858df7a75ad2fa01d08965..48a799423260be00ccd34412ad44766d42bbac22 100644 (file)
@@ -37,6 +37,7 @@ from portage.dbapi.dep_expand import dep_expand
 from portage.util import normalize_path as normpath
 from portage.util import writemsg, writemsg_level, writemsg_stdout
 from portage.sets import SETPREFIX
+from portage._global_updates import _global_updates
 
 from _emerge.actions import action_config, action_sync, action_metadata, \
        action_regen, action_search, action_uninstall, action_info, action_build, \
@@ -1185,7 +1186,7 @@ def emerge_main():
                return rval
 
        if myaction not in ('help', 'info', 'version') and \
-               portage._global_updates(trees, mtimedb["updates"]):
+               _global_updates(trees, mtimedb["updates"]):
                mtimedb.commit()
                # Reload the whole config from scratch.
                settings, trees, mtimedb = load_emerge_config(trees=trees)
index d894fbdc6eb25d674e43e5b953d109c797e5de94..670ef204dbdc3ee86bfaf62cdbfca5603e9cb381 100644 (file)
@@ -331,89 +331,8 @@ except (ImportError, OSError) as e:
 # END OF IMPORTS -- END OF IMPORTS -- END OF IMPORTS -- END OF IMPORTS -- END
 # ===========================================================================
 
-def _gen_missing_encodings(missing_encodings):
-
-       encodings = {}
-
-       if 'ascii' in missing_encodings:
-
-               class AsciiIncrementalEncoder(codecs.IncrementalEncoder):
-                       def encode(self, input, final=False):
-                               return codecs.ascii_encode(input, self.errors)[0]
-
-               class AsciiIncrementalDecoder(codecs.IncrementalDecoder):
-                       def decode(self, input, final=False):
-                               return codecs.ascii_decode(input, self.errors)[0]
-
-               class AsciiStreamWriter(codecs.StreamWriter):
-                       encode = codecs.ascii_encode
-
-               class AsciiStreamReader(codecs.StreamReader):
-                       decode = codecs.ascii_decode
-
-               codec_info =  codecs.CodecInfo(
-                       name='ascii',
-                       encode=codecs.ascii_encode,
-                       decode=codecs.ascii_decode,
-                       incrementalencoder=AsciiIncrementalEncoder,
-                       incrementaldecoder=AsciiIncrementalDecoder,
-                       streamwriter=AsciiStreamWriter,
-                       streamreader=AsciiStreamReader,
-               )
-
-               for alias in ('ascii', '646', 'ansi_x3.4_1968', 'ansi_x3_4_1968',
-                       'ansi_x3.4_1986', 'cp367', 'csascii', 'ibm367', 'iso646_us',
-                       'iso_646.irv_1991', 'iso_ir_6', 'us', 'us_ascii'):
-                       encodings[alias] = codec_info
-
-       if 'utf_8' in missing_encodings:
-
-               def utf8decode(input, errors='strict'):
-                       return codecs.utf_8_decode(input, errors, True)
-
-               class Utf8IncrementalEncoder(codecs.IncrementalEncoder):
-                       def encode(self, input, final=False):
-                               return codecs.utf_8_encode(input, self.errors)[0]
-
-               class Utf8IncrementalDecoder(codecs.BufferedIncrementalDecoder):
-                       _buffer_decode = codecs.utf_8_decode
-
-               class Utf8StreamWriter(codecs.StreamWriter):
-                       encode = codecs.utf_8_encode
-
-               class Utf8StreamReader(codecs.StreamReader):
-                       decode = codecs.utf_8_decode
-
-               codec_info = codecs.CodecInfo(
-                       name='utf-8',
-                       encode=codecs.utf_8_encode,
-                       decode=utf8decode,
-                       incrementalencoder=Utf8IncrementalEncoder,
-                       incrementaldecoder=Utf8IncrementalDecoder,
-                       streamreader=Utf8StreamReader,
-                       streamwriter=Utf8StreamWriter,
-               )
-
-               for alias in ('utf_8', 'u8', 'utf', 'utf8', 'utf8_ucs2', 'utf8_ucs4'):
-                       encodings[alias] = codec_info
-
-       return encodings
-
 def _ensure_default_encoding():
-       """
-       The python that's inside stage 1 or 2 is built with a minimal
-       configuration which does not include the /usr/lib/pythonX.Y/encodings
-       directory. This results in error like the following:
-
-         LookupError: no codec search functions registered: can't find encoding
 
-       In order to solve this problem, detect it early and manually register
-       a search function for the ascii and utf_8 codecs. Starting with python-3.0
-       this problem is more noticeable because of stricter handling of encoding
-       and decoding between strings of characters and bytes.
-       """
-
-       default_fallback = 'utf_8'
        default_encoding = sys.getdefaultencoding().lower().replace('-', '_')
        filesystem_encoding = _encodings['merge'].lower().replace('-', '_')
        required_encodings = set(['ascii', 'utf_8'])
@@ -429,49 +348,9 @@ def _ensure_default_encoding():
        if not missing_encodings:
                return
 
-       encodings = _gen_missing_encodings(missing_encodings)
-
-       if default_encoding in missing_encodings and \
-               default_encoding not in encodings:
-               # Make the fallback codec correspond to whatever name happens
-               # to be returned by sys.getfilesystemencoding().
-
-               try:
-                       encodings[default_encoding] = codecs.lookup(default_fallback)
-               except LookupError:
-                       encodings[default_encoding] = encodings[default_fallback]
-
-       if filesystem_encoding in missing_encodings and \
-               filesystem_encoding not in encodings:
-               # Make the fallback codec correspond to whatever name happens
-               # to be returned by sys.getdefaultencoding().
-
-               try:
-                       encodings[filesystem_encoding] = codecs.lookup(default_fallback)
-               except LookupError:
-                       encodings[filesystem_encoding] = encodings[default_fallback]
-
-       def search_function(name):
-               name = name.lower()
-               name = name.replace('-', '_')
-               codec_info = encodings.get(name)
-               if codec_info is not None:
-                       return codecs.CodecInfo(
-                               name=codec_info.name,
-                               encode=codec_info.encode,
-                               decode=codec_info.decode,
-                               incrementalencoder=codec_info.incrementalencoder,
-                               incrementaldecoder=codec_info.incrementaldecoder,
-                               streamreader=codec_info.streamreader,
-                               streamwriter=codec_info.streamwriter,
-                       )
-               return None
-
-       codecs.register(search_function)
-
-       del codec_name, default_encoding, default_fallback, \
-               filesystem_encoding, missing_encodings, \
-               required_encodings, search_function
+       from portage import _ensure_encodings
+       _ensure_encodings._setup_encodings(default_encoding,
+               filesystem_encoding, missing_encodings)
 
 # Do this ASAP since writemsg() might not work without it.
 _ensure_default_encoding()
@@ -685,146 +564,6 @@ def portageexit():
 
 atexit_register(portageexit)
 
-def _global_updates(trees, prev_mtimes):
-       """
-       Perform new global updates if they exist in $PORTDIR/profiles/updates/.
-
-       @param trees: A dictionary containing portage trees.
-       @type trees: dict
-       @param prev_mtimes: A dictionary containing mtimes of files located in
-               $PORTDIR/profiles/updates/.
-       @type prev_mtimes: dict
-       @rtype: None or List
-       @return: None if no were no updates, otherwise a list of update commands
-               that have been performed.
-       """
-       # only do this if we're root and not running repoman/ebuild digest
-       global secpass
-       if secpass < 2 or "SANDBOX_ACTIVE" in os.environ:
-               return
-       root = "/"
-       mysettings = trees["/"]["vartree"].settings
-       updpath = os.path.join(mysettings["PORTDIR"], "profiles", "updates")
-
-       try:
-               if mysettings["PORTAGE_CALLER"] == "fixpackages":
-                       update_data = grab_updates(updpath)
-               else:
-                       update_data = grab_updates(updpath, prev_mtimes)
-       except portage.exception.DirectoryNotFound:
-               writemsg(_("--- 'profiles/updates' is empty or "
-                       "not available. Empty portage tree?\n"), noiselevel=1)
-               return
-       myupd = None
-       if len(update_data) > 0:
-               do_upgrade_packagesmessage = 0
-               myupd = []
-               timestamps = {}
-               for mykey, mystat, mycontent in update_data:
-                       writemsg_stdout("\n\n")
-                       writemsg_stdout(colorize("GOOD",
-                               _("Performing Global Updates: "))+bold(mykey)+"\n")
-                       writemsg_stdout(_("(Could take a couple of minutes if you have a lot of binary packages.)\n"))
-                       writemsg_stdout(_("  %s='update pass'  %s='binary update'  "
-                               "%s='/var/db update'  %s='/var/db move'\n"
-                               "  %s='/var/db SLOT move'  %s='binary move'  "
-                               "%s='binary SLOT move'\n  %s='update /etc/portage/package.*'\n") % \
-                               (bold("."), bold("*"), bold("#"), bold("@"), bold("s"), bold("%"), bold("S"), bold("p")))
-                       valid_updates, errors = parse_updates(mycontent)
-                       myupd.extend(valid_updates)
-                       writemsg_stdout(len(valid_updates) * "." + "\n")
-                       if len(errors) == 0:
-                               # Update our internal mtime since we
-                               # processed all of our directives.
-                               timestamps[mykey] = mystat[stat.ST_MTIME]
-                       else:
-                               for msg in errors:
-                                       writemsg("%s\n" % msg, noiselevel=-1)
-
-               world_file = os.path.join(root, EPREFIX_LSTRIP, WORLD_FILE)
-               world_list = grabfile(world_file)
-               world_modified = False
-               for update_cmd in myupd:
-                       for pos, atom in enumerate(world_list):
-                               new_atom = update_dbentry(update_cmd, atom)
-                               if atom != new_atom:
-                                       world_list[pos] = new_atom
-                                       world_modified = True
-               if world_modified:
-                       world_list.sort()
-                       write_atomic(world_file,
-                               "".join("%s\n" % (x,) for x in world_list))
-
-               update_config_files("/",
-                       mysettings.get("CONFIG_PROTECT","").split(),
-                       mysettings.get("CONFIG_PROTECT_MASK","").split(),
-                       myupd)
-
-               trees["/"]["bintree"] = binarytree("/", mysettings["PKGDIR"],
-                       settings=mysettings)
-               vardb = trees["/"]["vartree"].dbapi
-               bindb = trees["/"]["bintree"].dbapi
-               if not os.access(bindb.bintree.pkgdir, os.W_OK):
-                       bindb = None
-               for update_cmd in myupd:
-                       if update_cmd[0] == "move":
-                               moves = vardb.move_ent(update_cmd)
-                               if moves:
-                                       writemsg_stdout(moves * "@")
-                               if bindb:
-                                       moves = bindb.move_ent(update_cmd)
-                                       if moves:
-                                               writemsg_stdout(moves * "%")
-                       elif update_cmd[0] == "slotmove":
-                               moves = vardb.move_slot_ent(update_cmd)
-                               if moves:
-                                       writemsg_stdout(moves * "s")
-                               if bindb:
-                                       moves = bindb.move_slot_ent(update_cmd)
-                                       if moves:
-                                               writemsg_stdout(moves * "S")
-
-               # The above global updates proceed quickly, so they
-               # are considered a single mtimedb transaction.
-               if len(timestamps) > 0:
-                       # We do not update the mtime in the mtimedb
-                       # until after _all_ of the above updates have
-                       # been processed because the mtimedb will
-                       # automatically commit when killed by ctrl C.
-                       for mykey, mtime in timestamps.items():
-                               prev_mtimes[mykey] = mtime
-
-               # We gotta do the brute force updates for these now.
-               if mysettings["PORTAGE_CALLER"] == "fixpackages" or \
-               "fixpackages" in mysettings.features:
-                       def onUpdate(maxval, curval):
-                               if curval > 0:
-                                       writemsg_stdout("#")
-                       vardb.update_ents(myupd, onUpdate=onUpdate)
-                       if bindb:
-                               def onUpdate(maxval, curval):
-                                       if curval > 0:
-                                               writemsg_stdout("*")
-                               bindb.update_ents(myupd, onUpdate=onUpdate)
-               else:
-                       do_upgrade_packagesmessage = 1
-
-               # Update progress above is indicated by characters written to stdout so
-               # we print a couple new lines here to separate the progress output from
-               # what follows.
-               print()
-               print()
-
-               if do_upgrade_packagesmessage and bindb and \
-                       bindb.cpv_all():
-                       writemsg_stdout(_(" ** Skipping packages. Run 'fixpackages' or set it in FEATURES to fix the tbz2's in the packages directory.\n"))
-                       writemsg_stdout(bold(_("Note: This can take a very long time.")))
-                       writemsg_stdout("\n")
-       if myupd:
-               return myupd
-
-#continue setting up other trees
-
 class MtimeDB(dict):
        def __init__(self, filename):
                dict.__init__(self)
@@ -1010,7 +749,7 @@ def init_legacy_globals():
 
        global db, settings, root, portdb, selinux_enabled, mtimedbfile, mtimedb, \
        archlist, features, groups, pkglines, thirdpartymirrors, usedefaults, \
-       profiledir, flushmtimedb
+       profiledir
 
        # Portage needs to ensure a sane umask for the files it creates.
        os.umask(0o22)
@@ -1049,8 +788,6 @@ def init_legacy_globals():
        profiledir  = os.path.join(settings["PORTAGE_CONFIGROOT"], PROFILE_PATH)
        if not os.path.isdir(profiledir):
                profiledir = None
-       def flushmtimedb(record):
-               writemsg("portage.flushmtimedb() is DEPRECATED\n")
        # ========================================================================
        # COMPATIBILITY
        # These attributes should not be used
@@ -1070,13 +807,5 @@ if True:
 
        for k in ("db", "settings", "root", "selinux_enabled",
                "archlist", "features", "groups",
-               "pkglines", "thirdpartymirrors", "usedefaults", "profiledir",
-               "flushmtimedb"):
+               "pkglines", "thirdpartymirrors", "usedefaults", "profiledir"):
                globals()[k] = _LegacyGlobalProxy(k)
-
-# Clear the cache
-dircache={}
-
-# ============================================================================
-# ============================================================================
-
diff --git a/pym/portage/_ensure_encodings.py b/pym/portage/_ensure_encodings.py
new file mode 100644 (file)
index 0000000..7daf52e
--- /dev/null
@@ -0,0 +1,133 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+import codecs
+
+_codec_map = None
+
+def _setup_encodings(default_encoding, filesystem_encoding, missing_encodings):
+       """
+       The <python-2.6.4 that's inside stage 1 or 2 is built with a minimal
+       configuration which does not include the /usr/lib/pythonX.Y/encodings
+       directory. This results in error like the following:
+
+         LookupError: no codec search functions registered: can't find encoding
+
+       In order to solve this problem, detect it early and manually register
+       a search function for the ascii and utf_8 codecs. Starting with python-3.0
+       this problem is more noticeable because of stricter handling of encoding
+       and decoding between strings of characters and bytes.
+       """
+
+       global _codec_map
+       _codec_map = _gen_missing_encodings(missing_encodings)
+
+       default_fallback = 'utf_8'
+
+       if default_encoding in missing_encodings and \
+               default_encoding not in _codec_map:
+               # Make the fallback codec correspond to whatever name happens
+               # to be returned by sys.getfilesystemencoding().
+
+               try:
+                       _codec_map[default_encoding] = codecs.lookup(default_fallback)
+               except LookupError:
+                       _codec_map[default_encoding] = _codec_map[default_fallback]
+
+       if filesystem_encoding in missing_encodings and \
+               filesystem_encoding not in _codec_map:
+               # Make the fallback codec correspond to whatever name happens
+               # to be returned by sys.getdefaultencoding().
+
+               try:
+                       _codec_map[filesystem_encoding] = codecs.lookup(default_fallback)
+               except LookupError:
+                       _codec_map[filesystem_encoding] = _codec_map[default_fallback]
+
+       codecs.register(_search_function)
+
+def _gen_missing_encodings(missing_encodings):
+
+       codec_map = {}
+
+       if 'ascii' in missing_encodings:
+
+               class AsciiIncrementalEncoder(codecs.IncrementalEncoder):
+                       def encode(self, input, final=False):
+                               return codecs.ascii_encode(input, self.errors)[0]
+
+               class AsciiIncrementalDecoder(codecs.IncrementalDecoder):
+                       def decode(self, input, final=False):
+                               return codecs.ascii_decode(input, self.errors)[0]
+
+               class AsciiStreamWriter(codecs.StreamWriter):
+                       encode = codecs.ascii_encode
+
+               class AsciiStreamReader(codecs.StreamReader):
+                       decode = codecs.ascii_decode
+
+               codec_info =  codecs.CodecInfo(
+                       name='ascii',
+                       encode=codecs.ascii_encode,
+                       decode=codecs.ascii_decode,
+                       incrementalencoder=AsciiIncrementalEncoder,
+                       incrementaldecoder=AsciiIncrementalDecoder,
+                       streamwriter=AsciiStreamWriter,
+                       streamreader=AsciiStreamReader,
+               )
+
+               for alias in ('ascii', '646', 'ansi_x3.4_1968', 'ansi_x3_4_1968',
+                       'ansi_x3.4_1986', 'cp367', 'csascii', 'ibm367', 'iso646_us',
+                       'iso_646.irv_1991', 'iso_ir_6', 'us', 'us_ascii'):
+                       codec_map[alias] = codec_info
+
+       if 'utf_8' in missing_encodings:
+
+               def utf8decode(input, errors='strict'):
+                       return codecs.utf_8_decode(input, errors, True)
+
+               class Utf8IncrementalEncoder(codecs.IncrementalEncoder):
+                       def encode(self, input, final=False):
+                               return codecs.utf_8_encode(input, self.errors)[0]
+
+               class Utf8IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+                       _buffer_decode = codecs.utf_8_decode
+
+               class Utf8StreamWriter(codecs.StreamWriter):
+                       encode = codecs.utf_8_encode
+
+               class Utf8StreamReader(codecs.StreamReader):
+                       decode = codecs.utf_8_decode
+
+               codec_info = codecs.CodecInfo(
+                       name='utf-8',
+                       encode=codecs.utf_8_encode,
+                       decode=utf8decode,
+                       incrementalencoder=Utf8IncrementalEncoder,
+                       incrementaldecoder=Utf8IncrementalDecoder,
+                       streamreader=Utf8StreamReader,
+                       streamwriter=Utf8StreamWriter,
+               )
+
+               for alias in ('utf_8', 'u8', 'utf', 'utf8', 'utf8_ucs2', 'utf8_ucs4'):
+                       codec_map[alias] = codec_info
+
+       return codec_map
+
+def _search_function(name):
+       global _codec_map
+       name = name.lower()
+       name = name.replace('-', '_')
+       codec_info = _codec_map.get(name)
+       if codec_info is not None:
+               return codecs.CodecInfo(
+                       name=codec_info.name,
+                       encode=codec_info.encode,
+                       decode=codec_info.decode,
+                       incrementalencoder=codec_info.incrementalencoder,
+                       incrementaldecoder=codec_info.incrementaldecoder,
+                       streamreader=codec_info.streamreader,
+                       streamwriter=codec_info.streamwriter,
+               )
+       return None
diff --git a/pym/portage/_global_updates.py b/pym/portage/_global_updates.py
new file mode 100644 (file)
index 0000000..acb548b
--- /dev/null
@@ -0,0 +1,152 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+from __future__ import print_function
+
+import stat
+
+from portage import os
+from portage.const import WORLD_FILE
+from portage.data import secpass
+from portage.exception import DirectoryNotFound
+from portage.localization import _
+from portage.output import bold, colorize
+from portage.update import grab_updates, parse_updates, update_config_files, update_dbentry
+from portage.util import grabfile, writemsg, writemsg_stdout, write_atomic
+
+def _global_updates(trees, prev_mtimes):
+       """
+       Perform new global updates if they exist in $PORTDIR/profiles/updates/.
+
+       @param trees: A dictionary containing portage trees.
+       @type trees: dict
+       @param prev_mtimes: A dictionary containing mtimes of files located in
+               $PORTDIR/profiles/updates/.
+       @type prev_mtimes: dict
+       @rtype: None or List
+       @return: None if no were no updates, otherwise a list of update commands
+               that have been performed.
+       """
+       # only do this if we're root and not running repoman/ebuild digest
+
+       if secpass < 2 or "SANDBOX_ACTIVE" in os.environ:
+               return
+       root = "/"
+       mysettings = trees["/"]["vartree"].settings
+       updpath = os.path.join(mysettings["PORTDIR"], "profiles", "updates")
+
+       try:
+               if mysettings["PORTAGE_CALLER"] == "fixpackages":
+                       update_data = grab_updates(updpath)
+               else:
+                       update_data = grab_updates(updpath, prev_mtimes)
+       except DirectoryNotFound:
+               writemsg(_("--- 'profiles/updates' is empty or "
+                       "not available. Empty portage tree?\n"), noiselevel=1)
+               return
+       myupd = None
+       if len(update_data) > 0:
+               do_upgrade_packagesmessage = 0
+               myupd = []
+               timestamps = {}
+               for mykey, mystat, mycontent in update_data:
+                       writemsg_stdout("\n\n")
+                       writemsg_stdout(colorize("GOOD",
+                               _("Performing Global Updates: "))+bold(mykey)+"\n")
+                       writemsg_stdout(_("(Could take a couple of minutes if you have a lot of binary packages.)\n"))
+                       writemsg_stdout(_("  %s='update pass'  %s='binary update'  "
+                               "%s='/var/db update'  %s='/var/db move'\n"
+                               "  %s='/var/db SLOT move'  %s='binary move'  "
+                               "%s='binary SLOT move'\n  %s='update /etc/portage/package.*'\n") % \
+                               (bold("."), bold("*"), bold("#"), bold("@"), bold("s"), bold("%"), bold("S"), bold("p")))
+                       valid_updates, errors = parse_updates(mycontent)
+                       myupd.extend(valid_updates)
+                       writemsg_stdout(len(valid_updates) * "." + "\n")
+                       if len(errors) == 0:
+                               # Update our internal mtime since we
+                               # processed all of our directives.
+                               timestamps[mykey] = mystat[stat.ST_MTIME]
+                       else:
+                               for msg in errors:
+                                       writemsg("%s\n" % msg, noiselevel=-1)
+
+               world_file = os.path.join(root, EPREFIX_LSTRIP, WORLD_FILE)
+               world_list = grabfile(world_file)
+               world_modified = False
+               for update_cmd in myupd:
+                       for pos, atom in enumerate(world_list):
+                               new_atom = update_dbentry(update_cmd, atom)
+                               if atom != new_atom:
+                                       world_list[pos] = new_atom
+                                       world_modified = True
+               if world_modified:
+                       world_list.sort()
+                       write_atomic(world_file,
+                               "".join("%s\n" % (x,) for x in world_list))
+
+               update_config_files("/",
+                       mysettings.get("CONFIG_PROTECT","").split(),
+                       mysettings.get("CONFIG_PROTECT_MASK","").split(),
+                       myupd)
+
+               vardb = trees["/"]["vartree"].dbapi
+               bindb = trees["/"]["bintree"].dbapi
+               if not os.access(bindb.bintree.pkgdir, os.W_OK):
+                       bindb = None
+               for update_cmd in myupd:
+                       if update_cmd[0] == "move":
+                               moves = vardb.move_ent(update_cmd)
+                               if moves:
+                                       writemsg_stdout(moves * "@")
+                               if bindb:
+                                       moves = bindb.move_ent(update_cmd)
+                                       if moves:
+                                               writemsg_stdout(moves * "%")
+                       elif update_cmd[0] == "slotmove":
+                               moves = vardb.move_slot_ent(update_cmd)
+                               if moves:
+                                       writemsg_stdout(moves * "s")
+                               if bindb:
+                                       moves = bindb.move_slot_ent(update_cmd)
+                                       if moves:
+                                               writemsg_stdout(moves * "S")
+
+               # The above global updates proceed quickly, so they
+               # are considered a single mtimedb transaction.
+               if len(timestamps) > 0:
+                       # We do not update the mtime in the mtimedb
+                       # until after _all_ of the above updates have
+                       # been processed because the mtimedb will
+                       # automatically commit when killed by ctrl C.
+                       for mykey, mtime in timestamps.items():
+                               prev_mtimes[mykey] = mtime
+
+               # We gotta do the brute force updates for these now.
+               if mysettings["PORTAGE_CALLER"] == "fixpackages" or \
+               "fixpackages" in mysettings.features:
+                       def onUpdate(maxval, curval):
+                               if curval > 0:
+                                       writemsg_stdout("#")
+                       vardb.update_ents(myupd, onUpdate=onUpdate)
+                       if bindb:
+                               def onUpdate(maxval, curval):
+                                       if curval > 0:
+                                               writemsg_stdout("*")
+                               bindb.update_ents(myupd, onUpdate=onUpdate)
+               else:
+                       do_upgrade_packagesmessage = 1
+
+               # Update progress above is indicated by characters written to stdout so
+               # we print a couple new lines here to separate the progress output from
+               # what follows.
+               print()
+               print()
+
+               if do_upgrade_packagesmessage and bindb and \
+                       bindb.cpv_all():
+                       writemsg_stdout(_(" ** Skipping packages. Run 'fixpackages' or set it in FEATURES to fix the tbz2's in the packages directory.\n"))
+                       writemsg_stdout(bold(_("Note: This can take a very long time.")))
+                       writemsg_stdout("\n")
+       if myupd:
+               return myupd