Old "Change USE" message: Don't screw up if the highest version is masked and parent...
[portage.git] / bin / emaint
index 7aac5d49ab06cd8846c9657b1f718c0c08d6946f..5ff60422c7e5ad188237dd70383cce26f90792f7 100755 (executable)
@@ -32,7 +32,7 @@ class WorldHandler(object):
                self.not_installed = []
                self.invalid_category = []
                self.okay = []
-               from portage.sets import load_default_config
+               from portage._sets import load_default_config
                setconfig = load_default_config(portage.settings,
                        portage.db[portage.settings["ROOT"]])
                self._sets = setconfig.getSets()
@@ -44,14 +44,14 @@ class WorldHandler(object):
                self.found = os.access(self.world_file, os.R_OK)
                vardb = portage.db[myroot]["vartree"].dbapi
 
-               from portage.sets import SETPREFIX
+               from portage._sets import SETPREFIX
                sets = self._sets
-               world_atoms = list(sets["world"])
+               world_atoms = list(sets["selected"])
                maxval = len(world_atoms)
                if onProgress:
                        onProgress(maxval, 0)
                for i, atom in enumerate(world_atoms):
-                       if not portage.isvalidatom(atom):
+                       if not isinstance(atom, portage.dep.Atom):
                                if atom.startswith(SETPREFIX):
                                        s = atom[len(SETPREFIX):]
                                        if s in sets:
@@ -63,12 +63,11 @@ class WorldHandler(object):
                                if onProgress:
                                        onProgress(maxval, i+1)
                                continue
-                       cp = portage.dep_getkey(atom)
                        okay = True
                        if not vardb.match(atom):
                                self.not_installed.append(atom)
                                okay = False
-                       if portage.catsplit(cp)[0] not in categories:
+                       if portage.catsplit(atom.cp)[0] not in categories:
                                self.invalid_category.append(atom)
                                okay = False
                        if okay:
@@ -80,15 +79,15 @@ class WorldHandler(object):
                self._check_world(onProgress)
                errors = []
                if self.found:
-                       errors += map(lambda x: "'%s' is not a valid atom" % x, self.invalid)
-                       errors += map(lambda x: "'%s' is not installed" % x, self.not_installed)
-                       errors += map(lambda x: "'%s' has a category that is not listed in /etc/portage/categories" % x, self.invalid_category)
+                       errors += ["'%s' is not a valid atom" % x for x in self.invalid]
+                       errors += ["'%s' is not installed" % x for x in self.not_installed]
+                       errors += ["'%s' has a category that is not listed in /etc/portage/categories" % x for x in self.invalid_category]
                else:
                        errors.append(self.world_file + " could not be opened for reading")
                return errors
 
        def fix(self, onProgress=None):
-               world_set = self._sets["world"]
+               world_set = self._sets["selected"]
                world_set.lock()
                try:
                        world_set.load() # maybe it's changed on disk
@@ -227,48 +226,74 @@ class BinhostHandler(object):
 
 class MoveHandler(object):
 
-       def __init__(self, tree):
+       def __init__(self, tree, porttree):
                self._tree = tree
-               self._portdir = tree.settings["PORTDIR"]
+               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, portdir):
+       def _grab_global_updates(self):
                from portage.update import grab_updates, parse_updates
-               updpath = os.path.join(portdir, "profiles", "updates")
-               try:
-                       rawupdates = grab_updates(updpath)
-               except portage.exception.DirectoryNotFound:
-                       rawupdates = []
-               upd_commands = []
+               retupdates = {}
                errors = []
-               for mykey, mystat, mycontent in rawupdates:
-                       commands, errors = parse_updates(mycontent)
-                       upd_commands.extend(commands)
-                       errors.extend(errors)
-               return upd_commands, errors
+
+               for repo_name in self._portdb.getRepositories():
+                       repo = self._portdb.getRepositoryPath(repo_name)
+                       updpath = os.path.join(repo, "profiles", "updates")
+                       if not os.path.isdir(updpath):
+                               continue
+
+                       try:
+                               rawupdates = grab_updates(updpath)
+                       except portage.exception.DirectoryNotFound:
+                               rawupdates = []
+                       upd_commands = []
+                       for mykey, mystat, mycontent in rawupdates:
+                               commands, errors = parse_updates(mycontent)
+                               upd_commands.extend(commands)
+                               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):
-               updates, errors = self._grab_global_updates(self._portdir)
+               allupdates, errors = self._grab_global_updates()
                # Matching packages and moving them is relatively fast, so the
                # progress bar is updated in indeterminate mode.
                match = self._tree.dbapi.match
                aux_get = self._tree.dbapi.aux_get
                if onProgress:
                        onProgress(0, 0)
-               for i, update_cmd in enumerate(updates):
-                       if update_cmd[0] == "move":
-                               origcp, newcp = update_cmd[1:]
-                               for cpv in match(origcp):
-                                       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 = aux_get(cpv, ["SLOT"])[0]
-                                       if slot == origslot:
-                                               errors.append("'%s' slot moved from '%s' to '%s'" % \
-                                                       (cpv, origslot, newslot))
-                       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 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 repo_match(prepo):
+                                                       errors.append("'%s' slot moved from '%s' to '%s'" % \
+                                                               (cpv, origslot, newslot))
+                               if onProgress:
+                                       onProgress(0, 0)
 
                # Searching for updates in all the metadata is relatively slow, so this
                # is where the progress bar comes out of indeterminate mode.
@@ -276,12 +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(update_keys, aux_get(cpv, update_keys)))
+                       metadata = dict(zip(meta_keys, aux_get(cpv, meta_keys)))
+                       repository = metadata.pop('repository')
+                       try:
+                               updates = allupdates[repository]
+                       except KeyError:
+                               try:
+                                       updates = allupdates['DEFAULT']
+                               except KeyError:
+                                       continue
+                       if not updates:
+                               continue
                        metadata_updates = update_dbentries(updates, metadata)
                        if metadata_updates:
                                errors.append("'%s' has outdated metadata" % cpv)
@@ -290,24 +325,35 @@ class MoveHandler(object):
                return errors
 
        def fix(self, onProgress=None):
-               updates, errors = self._grab_global_updates(self._portdir)
+               allupdates, errors = self._grab_global_updates()
                # Matching packages and moving them is relatively fast, so the
                # progress bar is updated in indeterminate mode.
                move = self._tree.dbapi.move_ent
                slotmove = self._tree.dbapi.move_slot_ent
                if onProgress:
                        onProgress(0, 0)
-               for i, update_cmd in enumerate(updates):
-                       if update_cmd[0] == "move":
-                               move(update_cmd)
-                       elif update_cmd[0] == "slotmove":
-                               slotmove(update_cmd)
-                       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_match=repo_match)
+                               elif update_cmd[0] == "slotmove":
+                                       slotmove(update_cmd, repo_match=repo_match)
+                               if onProgress:
+                                       onProgress(0, 0)
 
                # Searching for updates in all the metadata is relatively slow, so this
                # is where the progress bar comes out of indeterminate mode.
-               self._tree.dbapi.update_ents(updates, onProgress=onProgress)
+               self._tree.dbapi.update_ents(allupdates, onProgress=onProgress)
                return errors
 
 class MoveInstalled(MoveHandler):
@@ -319,7 +365,7 @@ class MoveInstalled(MoveHandler):
        name = staticmethod(name)
        def __init__(self):
                myroot = portage.settings["ROOT"]
-               MoveHandler.__init__(self, portage.db[myroot]["vartree"])
+               MoveHandler.__init__(self, portage.db[myroot]["vartree"], portage.db[myroot]["porttree"])
 
 class MoveBinary(MoveHandler):
 
@@ -330,7 +376,7 @@ class MoveBinary(MoveHandler):
        name = staticmethod(name)
        def __init__(self):
                myroot = portage.settings["ROOT"]
-               MoveHandler.__init__(self, portage.db[myroot]["bintree"])
+               MoveHandler.__init__(self, portage.db[myroot]["bintree"], portage.db[myroot]["porttree"])
 
 class VdbKeyHandler(object):
        def name():
@@ -536,7 +582,7 @@ def emaint_main(myargv):
                status = "Attempting to fix %s"
                func = "fix"
 
-       isatty = sys.stdout.isatty()
+       isatty = os.environ.get('TERM') != 'dumb' and sys.stdout.isatty()
        for task in tasks:
                print(status % task.name())
                inst = task()