def testUpdateDbentryTestCase(self):
     cases = (
         (("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "1",
          "  dev-libs/A:0  ", "  dev-libs/B:0  "),
         (("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "1",
          "  >=dev-libs/A-1:0  ", "  >=dev-libs/B-1:0  "),
         (("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "2",
          "  dev-libs/A[foo]  ", "  dev-libs/B[foo]  "),
         (("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "5",
          "  dev-libs/A:0/1=[foo]  ", "  dev-libs/B:0/1=[foo]  "),
         (("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "5",
          "  dev-libs/A:0/1[foo]  ", "  dev-libs/B:0/1[foo]  "),
         (("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "5",
          "  dev-libs/A:0/0[foo]  ", "  dev-libs/B:0/0[foo]  "),
         (("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "5",
          "  dev-libs/A:0=[foo]  ", "  dev-libs/B:0=[foo]  "),
         (("slotmove", Atom("dev-libs/A"), "0", "1"), "1",
          "  dev-libs/A:0  ", "  dev-libs/A:1  "),
         (("slotmove", Atom("dev-libs/A"), "0", "1"), "1",
          "  >=dev-libs/A-1:0  ", "  >=dev-libs/A-1:1  "),
         (("slotmove", Atom("dev-libs/A"), "0", "1"), "5",
          "  dev-libs/A:0/1=[foo]  ", "  dev-libs/A:1/1=[foo]  "),
         (("slotmove", Atom("dev-libs/A"), "0", "1"), "5",
          "  dev-libs/A:0/1[foo]  ", "  dev-libs/A:1/1[foo]  "),
         (("slotmove", Atom("dev-libs/A"), "0", "1"), "5",
          "  dev-libs/A:0/0[foo]  ", "  dev-libs/A:1/1[foo]  "),
         (("slotmove", Atom("dev-libs/A"), "0", "1"), "5",
          "  dev-libs/A:0=[foo]  ", "  dev-libs/A:1=[foo]  "),
     )
     for update_cmd, eapi, input_str, output_str in cases:
         result = update_dbentry(update_cmd, input_str, eapi=eapi)
         self.assertEqual(result, output_str)
Exemple #2
0
    def testUpdateDbentryBlockerTestCase(self):
        """
		Avoid creating self-blockers for bug #367215.
		"""
        cases = (
            (("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
             _pkg_str("dev-libs/B-1", eapi="1",
                      slot="0"), "  !dev-libs/A  ", "  !dev-libs/A  "),
            (("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
             _pkg_str("dev-libs/C-1", eapi="1",
                      slot="0"), "  !dev-libs/A  ", "  !dev-libs/B  "),
            (("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
             _pkg_str("dev-libs/B-1", eapi="1",
                      slot="0"), "  !dev-libs/A:0  ", "  !dev-libs/A:0  "),
            (("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
             _pkg_str("dev-libs/C-1", eapi="1",
                      slot="0"), "  !dev-libs/A:0  ", "  !dev-libs/B:0  "),
            (("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
             _pkg_str("dev-libs/C-1", eapi="1", slot="0"),
             "  !>=dev-libs/A-1:0  ", "  !>=dev-libs/B-1:0  "),
            (("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
             _pkg_str("dev-libs/B-1", eapi="1", slot="0"),
             "  !>=dev-libs/A-1:0  ", "  !>=dev-libs/A-1:0  "),
            (("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
             _pkg_str("dev-libs/C-1", eapi="1",
                      slot="0"), "  !>=dev-libs/A-1  ", "  !>=dev-libs/B-1  "),
            (("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
             _pkg_str("dev-libs/B-1", eapi="1",
                      slot="0"), "  !>=dev-libs/A-1  ", "  !>=dev-libs/A-1  "),
        )
        for update_cmd, parent, input_str, output_str in cases:
            result = update_dbentry(update_cmd, input_str, parent=parent)
            self.assertEqual(result, output_str)
	def testUpdateDbentryTestCase(self):
		cases = (

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "1",
				"  dev-libs/A:0  ", "  dev-libs/B:0  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "1",
				"  >=dev-libs/A-1:0  ", "  >=dev-libs/B-1:0  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "2",
				"  dev-libs/A[foo]  ", "  dev-libs/B[foo]  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "5",
				"  dev-libs/A:0/1=[foo]  ", "  dev-libs/B:0/1=[foo]  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "5",
				"  dev-libs/A:0/1[foo]  ", "  dev-libs/B:0/1[foo]  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "5",
				"  dev-libs/A:0/0[foo]  ", "  dev-libs/B:0/0[foo]  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")), "5",
				"  dev-libs/A:0=[foo]  ", "  dev-libs/B:0=[foo]  "),

			(("slotmove", Atom("dev-libs/A"), "0", "1"), "1",
				"  dev-libs/A:0  ", "  dev-libs/A:1  "),

			(("slotmove", Atom("dev-libs/A"), "0", "1"), "1",
				"  >=dev-libs/A-1:0  ", "  >=dev-libs/A-1:1  "),

			(("slotmove", Atom("dev-libs/A"), "0", "1"), "5",
				"  dev-libs/A:0/1=[foo]  ", "  dev-libs/A:1/1=[foo]  "),

			(("slotmove", Atom("dev-libs/A"), "0", "1"), "5",
				"  dev-libs/A:0/1[foo]  ", "  dev-libs/A:1/1[foo]  "),

			(("slotmove", Atom("dev-libs/A"), "0", "1"), "5",
				"  dev-libs/A:0/0[foo]  ", "  dev-libs/A:1/1[foo]  "),

			(("slotmove", Atom("dev-libs/A"), "0", "1"), "5",
				"  dev-libs/A:0=[foo]  ", "  dev-libs/A:1=[foo]  "),
		)
		for update_cmd, eapi, input_str, output_str in cases:
			result = update_dbentry(update_cmd, input_str, eapi=eapi)
			self.assertEqual(result, output_str)
	def testUpdateDbentryBlockerTestCase(self):
		"""
		Avoid creating self-blockers for bug #367215.
		"""
		cases = (

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
				_pkg_str("dev-libs/B-1", eapi="1", slot="0"),
				"  !dev-libs/A  ", "  !dev-libs/A  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
				_pkg_str("dev-libs/C-1", eapi="1", slot="0"),
				"  !dev-libs/A  ", "  !dev-libs/B  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
				_pkg_str("dev-libs/B-1", eapi="1", slot="0"),
				"  !dev-libs/A:0  ", "  !dev-libs/A:0  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
				_pkg_str("dev-libs/C-1", eapi="1", slot="0"),
				"  !dev-libs/A:0  ", "  !dev-libs/B:0  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
				_pkg_str("dev-libs/C-1", eapi="1", slot="0"),
				"  !>=dev-libs/A-1:0  ", "  !>=dev-libs/B-1:0  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
				_pkg_str("dev-libs/B-1", eapi="1", slot="0"),
				"  !>=dev-libs/A-1:0  ", "  !>=dev-libs/A-1:0  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
				_pkg_str("dev-libs/C-1", eapi="1", slot="0"),
				"  !>=dev-libs/A-1  ", "  !>=dev-libs/B-1  "),

			(("move", Atom("dev-libs/A"), Atom("dev-libs/B")),
				_pkg_str("dev-libs/B-1", eapi="1", slot="0"),
				"  !>=dev-libs/A-1  ", "  !>=dev-libs/A-1  "),

		)
		for update_cmd, parent, input_str, output_str in cases:
			result = update_dbentry(update_cmd, input_str, parent=parent)
			self.assertEqual(result, output_str)
Exemple #5
0
def _do_global_updates(trees, prev_mtimes, quiet=False, if_mtime_changed=True):
    root = trees._running_eroot
    mysettings = trees[root]["vartree"].settings
    portdb = trees[root]["porttree"].dbapi
    vardb = trees[root]["vartree"].dbapi
    bindb = trees[root]["bintree"].dbapi

    world_file = os.path.join(mysettings['EROOT'], WORLD_FILE)
    world_list = grabfile(world_file)
    world_modified = False
    world_warnings = set()
    updpath_map = {}
    # Maps repo_name to list of updates. If a given repo has no updates
    # directory, it will be omitted. If a repo has an updates directory
    # but none need to be applied (according to timestamp logic), the
    # value in the dict will be an empty list.
    repo_map = {}
    timestamps = {}

    retupd = False
    update_notice_printed = False
    for repo_name in portdb.getRepositories():
        repo = portdb.getRepositoryPath(repo_name)
        updpath = os.path.join(repo, "profiles", "updates")
        if not os.path.isdir(updpath):
            continue

        if updpath in updpath_map:
            repo_map[repo_name] = updpath_map[updpath]
            continue

        try:
            if if_mtime_changed:
                update_data = grab_updates(updpath, prev_mtimes=prev_mtimes)
            else:
                update_data = grab_updates(updpath)
        except DirectoryNotFound:
            continue
        myupd = []
        updpath_map[updpath] = myupd
        repo_map[repo_name] = myupd
        if len(update_data) > 0:
            for mykey, mystat, mycontent in update_data:
                if not update_notice_printed:
                    update_notice_printed = True
                    writemsg_stdout("\n")
                    writemsg_stdout(
                        colorize("GOOD", _("Performing Global Updates\n")))
                    writemsg_stdout(
                        _("(Could take a couple of minutes if you have a lot of binary packages.)\n"
                          ))
                    if not quiet:
                        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)
                if not quiet:
                    writemsg_stdout(bold(mykey))
                    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)
            if myupd:
                retupd = True

    if retupd:
        if os.access(bindb.bintree.pkgdir, os.W_OK):
            # Call binarytree.populate(), since we want to make sure it's
            # only populated with local packages here (getbinpkgs=0).
            bindb.bintree.populate()
        else:
            bindb = None

    master_repo = portdb.repositories.mainRepo()
    if master_repo is not None:
        master_repo = master_repo.name
    if master_repo in repo_map:
        repo_map['DEFAULT'] = repo_map[master_repo]

    for repo_name, myupd in repo_map.items():
        if repo_name == 'DEFAULT':
            continue
        if not myupd:
            continue

        def repo_match(repository):
            return repository == repo_name or \
             (repo_name == master_repo and repository not in repo_map)

        def _world_repo_match(atoma, atomb):
            """
			Check whether to perform a world change from atoma to atomb.
			If best vardb match for atoma comes from the same repository
			as the update file, allow that. Additionally, if portdb still
			can find a match for old atom name, warn about that.
			"""
            matches = vardb.match(atoma)
            if not matches:
                matches = vardb.match(atomb)
            if matches and \
             repo_match(vardb.aux_get(best(matches), ['repository'])[0]):
                if portdb.match(atoma):
                    world_warnings.add((atoma, atomb))
                return True
            else:
                return False

        for update_cmd in myupd:
            for pos, atom in enumerate(world_list):
                new_atom = update_dbentry(update_cmd, atom)
                if atom != new_atom:
                    if _world_repo_match(atom, new_atom):
                        world_list[pos] = new_atom
                        world_modified = True

        for update_cmd in myupd:
            if update_cmd[0] == "move":
                moves = vardb.move_ent(update_cmd, repo_match=repo_match)
                if moves:
                    writemsg_stdout(moves * "@")
                if bindb:
                    moves = bindb.move_ent(update_cmd, repo_match=repo_match)
                    if moves:
                        writemsg_stdout(moves * "%")
            elif update_cmd[0] == "slotmove":
                moves = vardb.move_slot_ent(update_cmd, repo_match=repo_match)
                if moves:
                    writemsg_stdout(moves * "s")
                if bindb:
                    moves = bindb.move_slot_ent(update_cmd,
                                                repo_match=repo_match)
                    if moves:
                        writemsg_stdout(moves * "S")

    if world_modified:
        world_list.sort()
        write_atomic(world_file, "".join("%s\n" % (x, ) for x in world_list))
        if world_warnings:
            # XXX: print warning that we've updated world entries
            # and the old name still matches something (from an overlay)?
            pass

    if retupd:

        def _config_repo_match(repo_name, atoma, atomb):
            """
			Check whether to perform a world change from atoma to atomb.
			If best vardb match for atoma comes from the same repository
			as the update file, allow that. Additionally, if portdb still
			can find a match for old atom name, warn about that.
			"""
            matches = vardb.match(atoma)
            if not matches:
                matches = vardb.match(atomb)
                if not matches:
                    return False
            repository = vardb.aux_get(best(matches), ['repository'])[0]
            return repository == repo_name or \
             (repo_name == master_repo and repository not in repo_map)

        update_config_files(root,
                            shlex_split(mysettings.get("CONFIG_PROTECT", "")),
                            shlex_split(
                                mysettings.get("CONFIG_PROTECT_MASK", "")),
                            repo_map,
                            match_callback=_config_repo_match,
                            case_insensitive="case-insensitive-fs"
                            in mysettings.features)

        # The above global updates proceed quickly, so they
        # are considered a single mtimedb transaction.
        if timestamps:
            # 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

        do_upgrade_packagesmessage = False
        # We gotta do the brute force updates for these now.
        if True:

            def onUpdate(_maxval, curval):
                if curval > 0:
                    writemsg_stdout("#")

            if quiet:
                onUpdate = None
            vardb.update_ents(repo_map, onUpdate=onUpdate)
            if bindb:

                def onUpdate(_maxval, curval):
                    if curval > 0:
                        writemsg_stdout("*")

                if quiet:
                    onUpdate = None
                bindb.update_ents(repo_map, 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.
        writemsg_stdout("\n\n")

        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")

    return retupd
def _do_global_updates(trees, prev_mtimes, quiet=False, if_mtime_changed=True):
	root = trees._running_eroot
	mysettings = trees[root]["vartree"].settings
	portdb = trees[root]["porttree"].dbapi
	vardb = trees[root]["vartree"].dbapi
	bindb = trees[root]["bintree"].dbapi

	world_file = os.path.join(mysettings['EROOT'], WORLD_FILE)
	world_list = grabfile(world_file)
	world_modified = False
	world_warnings = set()
	updpath_map = {}
	# Maps repo_name to list of updates. If a given repo has no updates
	# directory, it will be omitted. If a repo has an updates directory
	# but none need to be applied (according to timestamp logic), the
	# value in the dict will be an empty list.
	repo_map = {}
	timestamps = {}

	retupd = False
	update_notice_printed = False
	for repo_name in portdb.getRepositories():
		repo = portdb.getRepositoryPath(repo_name)
		updpath = os.path.join(repo, "profiles", "updates")
		if not os.path.isdir(updpath):
			continue

		if updpath in updpath_map:
			repo_map[repo_name] = updpath_map[updpath]
			continue

		try:
			if if_mtime_changed:
				update_data = grab_updates(updpath, prev_mtimes=prev_mtimes)
			else:
				update_data = grab_updates(updpath)
		except DirectoryNotFound:
			continue
		myupd = []
		updpath_map[updpath] = myupd
		repo_map[repo_name] = myupd
		if len(update_data) > 0:
			for mykey, mystat, mycontent in update_data:
				if not update_notice_printed:
					update_notice_printed = True
					writemsg_stdout("\n")
					if quiet:
						writemsg_stdout(colorize("GOOD",
							_("Performing Global Updates\n")))
						writemsg_stdout(_("(Could take a couple of minutes if you have a lot of binary packages.)\n"))
					else:
						writemsg_stdout(colorize("GOOD",
							_("Performing Global Updates:\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)
				if not quiet:
					writemsg_stdout(bold(mykey))
					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)
			if myupd:
				retupd = True

	if retupd:
		if os.access(bindb.bintree.pkgdir, os.W_OK):
			# Call binarytree.populate(), since we want to make sure it's
			# only populated with local packages here (getbinpkgs=0).
			bindb.bintree.populate()
		else:
			bindb = None

	master_repo = portdb.getRepositoryName(portdb.porttree_root)
	if master_repo in repo_map:
		repo_map['DEFAULT'] = repo_map[master_repo]

	for repo_name, myupd in repo_map.items():
			if repo_name == 'DEFAULT':
				continue
			if not myupd:
				continue

			def repo_match(repository):
				return repository == repo_name or \
					(repo_name == master_repo and repository not in repo_map)

			def _world_repo_match(atoma, atomb):
				"""
				Check whether to perform a world change from atoma to atomb.
				If best vardb match for atoma comes from the same repository
				as the update file, allow that. Additionally, if portdb still
				can find a match for old atom name, warn about that.
				"""
				matches = vardb.match(atoma)
				if not matches:
					matches = vardb.match(atomb)
				if matches and \
					repo_match(vardb.aux_get(best(matches), ['repository'])[0]):
					if portdb.match(atoma):
						world_warnings.add((atoma, atomb))
					return True
				else:
					return False

			for update_cmd in myupd:
				for pos, atom in enumerate(world_list):
					new_atom = update_dbentry(update_cmd, atom)
					if atom != new_atom:
						if _world_repo_match(atom, new_atom):
							world_list[pos] = new_atom
							world_modified = True

			for update_cmd in myupd:
				if update_cmd[0] == "move":
					moves = vardb.move_ent(update_cmd, repo_match=repo_match)
					if moves:
						writemsg_stdout(moves * "@")
					if bindb:
						moves = bindb.move_ent(update_cmd, repo_match=repo_match)
						if moves:
							writemsg_stdout(moves * "%")
				elif update_cmd[0] == "slotmove":
					moves = vardb.move_slot_ent(update_cmd, repo_match=repo_match)
					if moves:
						writemsg_stdout(moves * "s")
					if bindb:
						moves = bindb.move_slot_ent(update_cmd, repo_match=repo_match)
						if moves:
							writemsg_stdout(moves * "S")

	if world_modified:
		world_list.sort()
		write_atomic(world_file,
			"".join("%s\n" % (x,) for x in world_list))
		if world_warnings:
			# XXX: print warning that we've updated world entries
			# and the old name still matches something (from an overlay)?
			pass

	if retupd:

			def _config_repo_match(repo_name, atoma, atomb):
				"""
				Check whether to perform a world change from atoma to atomb.
				If best vardb match for atoma comes from the same repository
				as the update file, allow that. Additionally, if portdb still
				can find a match for old atom name, warn about that.
				"""
				matches = vardb.match(atoma)
				if not matches:
					matches = vardb.match(atomb)
					if not matches:
						return False
				repository = vardb.aux_get(best(matches), ['repository'])[0]
				return repository == repo_name or \
					(repo_name == master_repo and repository not in repo_map)

			update_config_files(root,
				shlex_split(mysettings.get("CONFIG_PROTECT", "")),
				shlex_split(mysettings.get("CONFIG_PROTECT_MASK", "")),
				repo_map, match_callback=_config_repo_match)

			# The above global updates proceed quickly, so they
			# are considered a single mtimedb transaction.
			if timestamps:
				# 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

			do_upgrade_packagesmessage = False
			# We gotta do the brute force updates for these now.
			if True:
				def onUpdate(maxval, curval):
					if curval > 0:
						writemsg_stdout("#")
				if quiet:
					onUpdate = None
				vardb.update_ents(repo_map, onUpdate=onUpdate)
				if bindb:
					def onUpdate(maxval, curval):
						if curval > 0:
							writemsg_stdout("*")
					if quiet:
						onUpdate = None
					bindb.update_ents(repo_map, 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.
			writemsg_stdout("\n\n")

			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")

	return retupd
def _global_updates(trees, prev_mtimes):
	"""
	Perform new global updates if they exist in $PORTDIR/profiles/updates/.
	This simply returns if ROOT != "/" (when len(trees) != 1). If ROOT != "/"
	then the user should instead use emaint --fix movebin and/or moveinst.

	@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 or \
		len(trees) != 1:
		return 0
	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 0
	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, 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
		else:
			# Call binarytree.populate(), since we want to make sure it's
			# only populated with local packages here (getbinpkgs=0).
			bindb.bintree.populate()
		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