Tweak global updates handling so that updates from $PORTDIR are applied
authorZac Medico <zmedico@gentoo.org>
Wed, 28 Jul 2010 04:30:45 +0000 (21:30 -0700)
committerZac Medico <zmedico@gentoo.org>
Wed, 28 Jul 2010 04:30:45 +0000 (21:30 -0700)
for all of the following cases:
* package is missing repository metadata
* package has repository metadata, but the source repository does not
  have a profiles/updates/ directory
* package has repository metadata, but the source repository is not
  currently accessible via PORTDIR_OVERLAY

bin/emaint
pym/_emerge/FakeVartree.py
pym/portage/_global_updates.py
pym/portage/dbapi/__init__.py
pym/portage/dbapi/bintree.py
pym/portage/dbapi/vartree.py

index 52990f7dfd4d27e146123ecf25877d36837abd60..6a73c6fe20372ba2244e53b9408d51501a1089c6 100755 (executable)
@@ -230,6 +230,8 @@ class MoveHandler(object):
                self._tree = tree
                self._portdb = porttree.dbapi
                self._update_keys = ["DEPEND", "RDEPEND", "PDEPEND", "PROVIDE"]
+               self._master_repo = \
+                       self._portdb.getRepositoryName(self._portdb.porttree_root)
 
        def _grab_global_updates(self):
                from portage.update import grab_updates, parse_updates
@@ -240,8 +242,8 @@ class MoveHandler(object):
                        repo = self._portdb.getRepositoryPath(repo_name)
                        updpath = os.path.join(repo, "profiles", "updates")
                        if not os.path.isdir(updpath):
-                               # as a backwards-compatibility measure, fallback to PORTDIR
-                               updpath = os.path.join(self._portdb.porttree_root, "profiles", "updates")
+                               continue
+
                        try:
                                rawupdates = grab_updates(updpath)
                        except portage.exception.DirectoryNotFound:
@@ -253,6 +255,9 @@ class MoveHandler(object):
                                errors.extend(errors)
                        retupdates[repo_name] = upd_commands
 
+               if self._master_repo in retupdates:
+                       retupdates['DEFAULT'] = retupdates[self._master_repo]
+
                return retupdates, errors
 
        def check(self, onProgress=None):
@@ -264,17 +269,27 @@ class MoveHandler(object):
                if onProgress:
                        onProgress(0, 0)
                for repo, updates in allupdates.items():
+                       if repo == 'DEFAULT':
+                               continue
+                       if not updates:
+                               continue
+
+                       def repo_match(repository):
+                               return repository == repo or \
+                                       (repo == self._master_repo and \
+                                       repository not in allupdates)
+
                        for i, update_cmd in enumerate(updates):
                                if update_cmd[0] == "move":
                                        origcp, newcp = update_cmd[1:]
                                        for cpv in match(origcp):
-                                               if aux_get(cpv, ["repository"])[0] == repo:
+                                               if repo_match(aux_get(cpv, ["repository"])[0]):
                                                        errors.append("'%s' moved to '%s'" % (cpv, newcp))
                                elif update_cmd[0] == "slotmove":
                                        pkg, origslot, newslot = update_cmd[1:]
                                        for cpv in match(pkg):
                                                slot, prepo = aux_get(cpv, ["SLOT", "repository"])
-                                               if slot == origslot and prepo == repo:
+                                               if slot == origslot and repo_match(prepo):
                                                        errors.append("'%s' slot moved from '%s' to '%s'" % \
                                                                (cpv, origslot, newslot))
                                if onProgress:
@@ -286,17 +301,22 @@ class MoveHandler(object):
                cpv_all.sort()
                maxval = len(cpv_all)
                aux_update = self._tree.dbapi.aux_update
-               update_keys = self._update_keys
+               meta_keys = self._update_keys + ['repository']
                from portage.update import update_dbentries
                if onProgress:
                        onProgress(maxval, 0)
                for i, cpv in enumerate(cpv_all):
+                       metadata = dict(zip(meta_keys, aux_get(cpv, meta_keys)))
+                       repository = metadata.pop('repository')
                        try:
-                               updates = allupdates[aux_get(cpv, ['repository'])[0]]
+                               updates = allupdates[repository]
                        except KeyError:
+                               try:
+                                       updates = allupdates['DEFAULT']
+                               except KeyError:
+                                       continue
+                       if not updates:
                                continue
-
-                       metadata = dict(zip(update_keys, aux_get(cpv, update_keys)))
                        metadata_updates = update_dbentries(updates, metadata)
                        if metadata_updates:
                                errors.append("'%s' has outdated metadata" % cpv)
@@ -313,11 +333,21 @@ class MoveHandler(object):
                if onProgress:
                        onProgress(0, 0)
                for repo, updates in allupdates.items():
+                       if repo == 'DEFAULT':
+                               continue
+                       if not updates:
+                               continue
+
+                       def repo_match(repository):
+                               return repository == repo or \
+                                       (repo == self._master_repo and \
+                                       repository not in allupdates)
+
                        for i, update_cmd in enumerate(updates):
                                if update_cmd[0] == "move":
-                                       move(update_cmd, repo_name=repo)
+                                       move(update_cmd, repo_match=repo_match)
                                elif update_cmd[0] == "slotmove":
-                                       slotmove(update_cmd, repo_name=repo)
+                                       slotmove(update_cmd, repo_match=repo_match)
                                if onProgress:
                                        onProgress(0, 0)
 
index 22f9f3739c6efc5d22bd34fe58f28f0a6df09611..c74092d55055045c837b3c4e198a800ef665407f 100644 (file)
@@ -186,8 +186,8 @@ def grab_global_updates(portdb):
                repo = portdb.getRepositoryPath(repo_name)
                updpath = os.path.join(repo, "profiles", "updates")
                if not os.path.isdir(updpath):
-                       # as a backwards-compatibility measure, fallback to PORTDIR
-                       updpath = os.path.join(portdb.porttree_root, "profiles", "updates")
+                       continue
+
                try:
                        rawupdates = grab_updates(updpath)
                except portage.exception.DirectoryNotFound:
@@ -198,16 +198,27 @@ def grab_global_updates(portdb):
                        upd_commands.extend(commands)
                retupdates[repo_name] = upd_commands
 
+       master_repo = portdb.getRepositoryName(portdb.porttree_root)
+       if master_repo in retupdates:
+               retupdates['DEFAULT'] = retupdates[master_repo]
+
        return retupdates
 
 def perform_global_updates(mycpv, mydb, myupdates):
+       aux_keys = ["DEPEND", "RDEPEND", "PDEPEND", 'repository']
+       aux_dict = dict(zip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
+       repository = aux_dict.pop('repository')
        try:
-               mycommands = myupdates[mydb.aux_get(mycpv, ['repository'])[0]]
+               mycommands = myupdates[repository]
        except KeyError:
+               try:
+                       mycommands = myupdates['DEFAULT']
+               except KeyError:
+                       return
+
+       if not mycommands:
                return
 
-       aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
-       aux_dict = dict(zip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
        updates = update_dbentries(mycommands, aux_dict)
        if updates:
                mydb.aux_update(mycpv, updates)
index cded5c45adc65cb256bbce0a96485d4247270a17..d3f55902d5c78b450f3f3a1544f91a1a5517cb58 100644 (file)
@@ -55,6 +55,10 @@ def _global_updates(trees, prev_mtimes):
        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 = {}
 
@@ -62,8 +66,7 @@ def _global_updates(trees, prev_mtimes):
                repo = portdb.getRepositoryPath(repo_name)
                updpath = os.path.join(repo, "profiles", "updates")
                if not os.path.isdir(updpath):
-                       # as a backwards-compatibility measure, fallback to PORTDIR
-                       updpath = os.path.join(portdb.porttree_root, "profiles", "updates")
+                       continue
 
                if updpath in updpath_map:
                        repo_map[repo_name] = updpath_map[updpath]
@@ -102,7 +105,20 @@ def _global_updates(trees, prev_mtimes):
                                                writemsg("%s\n" % msg, noiselevel=-1)
                        retupd.extend(myupd)
 
+       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.
@@ -111,7 +127,8 @@ def _global_updates(trees, prev_mtimes):
                                can find a match for old atom name, warn about that.
                                """
                                matches = vardb.match(atoma)
-                               if matches and vardb.aux_get(best(matches), ['repository'])[0] == repo_name:
+                               if matches and \
+                                       repo_match(vardb.aux_get(best(matches), ['repository'])[0]):
                                        if portdb.match(atoma):
                                                world_warnings.add((atoma, atomb))
                                        return True
@@ -132,19 +149,19 @@ def _global_updates(trees, prev_mtimes):
 
                        for update_cmd in myupd:
                                if update_cmd[0] == "move":
-                                       moves = vardb.move_ent(update_cmd, repo_name=repo_name)
+                                       moves = vardb.move_ent(update_cmd, repo_match=repo_match)
                                        if moves:
                                                writemsg_stdout(moves * "@")
                                        if bindb:
-                                               moves = bindb.move_ent(update_cmd, repo_name=repo_name)
+                                               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_name=repo_name)
+                                       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_name=repo_name)
+                                               moves = bindb.move_slot_ent(update_cmd, repo_match=repo_match)
                                                if moves:
                                                        writemsg_stdout(moves * "S")
 
@@ -158,7 +175,7 @@ def _global_updates(trees, prev_mtimes):
                                for mykey, mtime in timestamps.items():
                                        prev_mtimes[mykey] = mtime
 
-       if repo_map:
+       if retupd:
                        do_upgrade_packagesmessage = False
                        # We gotta do the brute force updates for these now.
                        if mysettings.get("PORTAGE_CALLER") == "fixpackages" or \
index b6b9175c6a06876febb3772c2e570e55573357a5..4799b25825088fba3b540c80da1a7bc0d60b1d34 100644 (file)
@@ -229,9 +229,16 @@ class dbapi(object):
                        if repo_dict is None:
                                updates_list = updates
                        else:
-                               updates_list = repo_dict.get(repo)
-                               if updates_list is None:
-                                       continue
+                               try:
+                                       updates_list = repo_dict[repo]
+                               except KeyError:
+                                       try:
+                                               updates_list = repo_dict['DEFAULT']
+                                       except KeyError:
+                                               continue
+
+                       if not updates_list:
+                               continue
 
                        metadata_updates = update_dbentries(updates_list, metadata)
                        if metadata_updates:
@@ -241,11 +248,12 @@ class dbapi(object):
                        if onProgress:
                                onProgress(maxval, i+1)
 
-       def move_slot_ent(self, mylist, repo_name = None):
+       def move_slot_ent(self, mylist, repo_match=None):
                """This function takes a sequence:
                Args:
                        mylist: a sequence of (package, originalslot, newslot)
-                       repo_name: repository from which update is originated
+                       repo_match: callable that takes single repo_name argument
+                               and returns True if the update should be applied
                Returns:
                        The number of slotmoves this function did
                """
@@ -260,7 +268,8 @@ class dbapi(object):
                        slot = self.aux_get(mycpv, ["SLOT"])[0]
                        if slot != origslot:
                                continue
-                       if repo_name and self.aux_get(mycpv, ['repository'])[0] != repo_name:
+                       if repo_match is not None \
+                               and not repo_match(self.aux_get(mycpv, ['repository'])[0]):
                                continue
                        moves += 1
                        mydata = {"SLOT": newslot+"\n"}
index 84c51a977e10d4ef5825b07966f4b59cfacd0bbd..f3f7aff98d295d688b6b4482c55c16ad7c2ed9ae 100644 (file)
@@ -288,7 +288,7 @@ class binarytree(object):
        remotepkgs = property(_get_remotepkgs, _set_remotepkgs, _del_remotepkgs,
                "Deprecated self.remotepkgs, only for backward compatibility")
 
-       def move_ent(self, mylist, repo_name = None):
+       def move_ent(self, mylist, repo_match=None):
                if not self.populated:
                        self.populate()
                origcp = mylist[1]
@@ -307,7 +307,8 @@ class binarytree(object):
                        if mycpv_cp != origcp:
                                # Ignore PROVIDE virtual match.
                                continue
-                       if repo_name and self.aux_get(mycpv, ['repository'])[0] != repo_name:
+                       if repo_match is not None \
+                               and not repo_match(self.aux_get(mycpv, ['repository'])[0]):
                                continue
                        mynewcpv = mycpv.replace(mycpv_cp, str(newcp), 1)
                        myoldpkg = catsplit(mycpv)[1]
index 6dbb51379ed06b4d94da9b8f923b3148480e730d..dbdb7d0b59056d781e7d6f67a99fe7c66a2c527f 100644 (file)
@@ -923,7 +923,7 @@ class vardbapi(dbapi):
                                return True
                return False
 
-       def move_ent(self, mylist, repo_name = None):
+       def move_ent(self, mylist, repo_match=None):
                origcp = mylist[1]
                newcp = mylist[2]
 
@@ -940,7 +940,8 @@ class vardbapi(dbapi):
                        if mycpv_cp != origcp:
                                # Ignore PROVIDE virtual match.
                                continue
-                       if repo_name and self.aux_get(mycpv, ['repository'])[0] != repo_name:
+                       if repo_match is not None \
+                               and not repo_match(self.aux_get(mycpv, ['repository'])[0]):
                                continue
                        mynewcpv = mycpv.replace(mycpv_cp, str(newcp), 1)
                        mynewcat = catsplit(newcp)[0]