# Copyright 2005-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import portage from portage import os from portage.exception import InvalidData from _emerge.Package import Package from portage.versions import _pkg_str class MoveHandler(object): def __init__(self, tree, porttree): self._tree = tree self._portdb = porttree.dbapi self._update_keys = Package._dep_keys + ("PROVIDE",) self._master_repo = \ self._portdb.getRepositoryName(self._portdb.porttree_root) def _grab_global_updates(self): from portage.update import grab_updates, parse_updates retupdates = {} 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, **kwargs): onProgress = kwargs.get('onProgress', None) 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 pkg_str = self._tree.dbapi._pkg_str settings = self._tree.dbapi.settings 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): try: cpv = pkg_str(cpv, origcp.repo) except (KeyError, InvalidData): continue if repo_match(cpv.repo): errors.append("'%s' moved to '%s'" % (cpv, newcp)) elif update_cmd[0] == "slotmove": pkg, origslot, newslot = update_cmd[1:] atom = pkg.with_slot(origslot) for cpv in match(atom): try: cpv = pkg_str(cpv, atom.repo) except (KeyError, InvalidData): continue if repo_match(cpv.repo): 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. cpv_all = self._tree.dbapi.cpv_all() cpv_all.sort() maxval = len(cpv_all) meta_keys = self._update_keys + self._portdb._pkg_str_aux_keys if onProgress: onProgress(maxval, 0) for i, cpv in enumerate(cpv_all): try: metadata = dict(zip(meta_keys, aux_get(cpv, meta_keys))) except KeyError: continue try: pkg = _pkg_str(cpv, metadata=metadata, settings=settings) except InvalidData: continue metadata = dict((k, metadata[k]) for k in self._update_keys) try: updates = allupdates[pkg.repo] except KeyError: try: updates = allupdates['DEFAULT'] except KeyError: continue if not updates: continue metadata_updates = \ portage.update_dbentries(updates, metadata, parent=pkg) if metadata_updates: errors.append("'%s' has outdated metadata" % cpv) if onProgress: onProgress(maxval, i+1) return errors def fix(self, **kwargs): onProgress = kwargs.get('onProgress', None) 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 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(allupdates, onProgress=onProgress) return errors class MoveInstalled(MoveHandler): short_desc = "Perform package move updates for installed packages" def name(): return "moveinst" name = staticmethod(name) def __init__(self): eroot = portage.settings['EROOT'] MoveHandler.__init__(self, portage.db[eroot]["vartree"], portage.db[eroot]["porttree"]) class MoveBinary(MoveHandler): short_desc = "Perform package move updates for binary packages" def name(): return "movebin" name = staticmethod(name) def __init__(self): eroot = portage.settings['EROOT'] MoveHandler.__init__(self, portage.db[eroot]["bintree"], portage.db[eroot]['porttree'])