Edgewall Software

Ticket #7822: 7822-multirepos-repos-mgmt-r7888.patch

File 7822-multirepos-repos-mgmt-r7888.patch, 8.1 KB (added by rblank, 3 years ago)

Updated patch to current head of multirepos branch.

  • trac/admin/tests/console-tests.txt

    diff --git a/trac/admin/tests/console-tests.txt b/trac/admin/tests/console-tests.txt
    a b  
    3131priority list         Show possible ticket priorities 
    3232priority order        Move a priority value up or down in the list 
    3333priority remove       Remove a priority value 
     34repository add        Add a source repository 
     35repository alias      Create an alias for a repository 
    3436repository changeset  Notify trac about new changesets 
     37repository list       List source repositories 
     38repository remove     Remove a source repository 
     39repository rename     Rename a source repository 
    3540repository resync     Re-synchronize trac with repositories 
    3641resolution add        Add a resolution value option 
    3742resolution change     Change a resolution value 
  • trac/versioncontrol/admin.py

    diff --git a/trac/versioncontrol/admin.py b/trac/versioncontrol/admin.py
    a b  
    1313 
    1414import sys 
    1515 
    16 from trac.admin import IAdminCommandProvider 
     16from trac.admin import IAdminCommandProvider, get_dir_list 
    1717from trac.core import * 
    18 from trac.util.text import printerr, printout 
     18from trac.util.text import print_table, printerr, printout 
    1919from trac.util.translation import _, ngettext 
    2020from trac.versioncontrol import RepositoryManager 
    2121 
     
    2828    # IAdminCommandProvider methods 
    2929     
    3030    def get_admin_commands(self): 
     31        yield ('repository add', '<repos> <dir> [type]', 
     32               'Add a source repository', 
     33               self._complete_add, self._do_add) 
     34        yield ('repository alias', '<repos> <alias>', 
     35               'Create an alias for a repository', 
     36               self._complete_repos, self._do_alias) 
    3137        yield ('repository changeset', '<repos> <rev> [rev] [...]', 
    3238               'Notify trac about new changesets', 
    3339               self._complete_repos, self._do_changeset) 
     40        yield ('repository list', '', 
     41               'List source repositories', 
     42               None, self._do_list) 
     43        yield ('repository remove', '<repos>', 
     44               'Remove a source repository', 
     45               self._complete_repos, self._do_remove) 
     46        yield ('repository rename', '<repos> <newname>', 
     47               'Rename a source repository', 
     48               self._complete_repos, self._do_rename) 
    3449        yield ('repository resync', '<repos> [rev]', 
    3550               """Re-synchronize trac with repositories 
    3651                
     
    4257               """, 
    4358               self._complete_repos, self._do_resync) 
    4459     
     60    def get_supported_types(self): 
     61        rm = RepositoryManager(self.env) 
     62        return [type_ for connector in rm.connectors 
     63                for (type_, prio) in connector.get_supported_types() 
     64                if prio >= 0] 
     65     
     66    def _complete_add(self, args): 
     67        if len(args) == 2: 
     68            return get_dir_list(args[-1], True) 
     69        elif len(args) == 3: 
     70            return self.get_supported_types() 
     71     
    4572    def _complete_repos(self, args): 
    4673        if len(args) == 1: 
    4774            rm = RepositoryManager(self.env) 
    4875            return [reponame or '(default)' for reponame 
    4976                    in rm.get_all_repositories()] 
    5077     
     78    def _do_add(self, reponame, dir, type_=None): 
     79        if reponame == '(default)': 
     80            reponame = '' 
     81        if type_ is not None and type_ not in self.get_supported_types(): 
     82            raise TracError(_("The repository type '%(type)s' is not " 
     83                              "supported", type=type_)) 
     84        db = self.env.get_db_cnx() 
     85        cursor = db.cursor() 
     86        cursor.executemany("INSERT INTO repository (id, name, value) " 
     87                           "VALUES (%s, %s, %s)", 
     88                           [(reponame, 'dir', dir), (reponame, 'type', type_)]) 
     89        db.commit() 
     90        RepositoryManager(self.env).reload_repositories() 
     91     
     92    def _do_alias(self, reponame, alias): 
     93        if reponame == '(default)': 
     94            reponame = '' 
     95        if alias in ('', '(default)'): 
     96            raise TracError(_("Invalid alias name '%(alias)s'", alias=alias)) 
     97        db = self.env.get_db_cnx() 
     98        cursor = db.cursor() 
     99        cursor.executemany("INSERT INTO repository (id, name, value) " 
     100                           "VALUES (%s, %s, %s)", 
     101                           [(alias, 'dir', None), (alias, 'alias', reponame)]) 
     102        db.commit() 
     103        RepositoryManager(self.env).reload_repositories() 
     104     
    51105    def _do_changeset(self, reponame, *revs): 
    52106        rm = RepositoryManager(self.env) 
    53107        rm.notify_changesets_added(reponame, revs, None) 
    54108     
     109    def _do_list(self): 
     110        rm = RepositoryManager(self.env) 
     111        values = [] 
     112        for (reponame, info) in sorted(rm.get_all_repositories().iteritems()): 
     113            alias = '' 
     114            if 'alias' in info: 
     115                alias = info['alias'] or '(default)' 
     116            values.append((reponame or '(default)', info.get('type', ''), 
     117                           alias, info.get('dir', ''))) 
     118        print_table(values, [_('Name'), _('Type'), _('Alias'), _('Directory')]) 
     119     
     120    def _do_remove(self, reponame): 
     121        if reponame == '(default)': 
     122            reponame = '' 
     123        db = self.env.get_db_cnx() 
     124        cursor = db.cursor() 
     125        cursor.execute("DELETE FROM repository " 
     126                       "WHERE id=%s AND name IN ('dir', 'type', 'alias')", 
     127                       (reponame,)) 
     128        cursor.execute("DELETE FROM revision WHERE repos=%s", (reponame,)) 
     129        cursor.execute("DELETE FROM node_change WHERE repos=%s", (reponame,)) 
     130        db.commit() 
     131        RepositoryManager(self.env).reload_repositories() 
     132     
     133    def _do_rename(self, reponame, newname): 
     134        if reponame == '(default)': 
     135            reponame = '' 
     136        if newname == '(default)': 
     137            newname = '' 
     138        db = self.env.get_db_cnx() 
     139        cursor = db.cursor() 
     140        cursor.execute("UPDATE repository SET id=%s WHERE id=%s", 
     141                       (newname, reponame)) 
     142        cursor.execute("UPDATE revision SET repos=%s WHERE repos=%s", 
     143                       (newname, reponame)) 
     144        cursor.execute("UPDATE node_change SET repos=%s WHERE repos=%s", 
     145                       (newname, reponame)) 
     146        db.commit() 
     147        RepositoryManager(self.env).reload_repositories() 
     148     
    55149    def _do_resync(self, reponame, rev=None): 
    56150        rm = RepositoryManager(self.env) 
    57151        if reponame == '*': 
  • trac/versioncontrol/api.py

    diff --git a/trac/versioncontrol/api.py b/trac/versioncontrol/api.py
    a b  
    8181        """Called after a changeset has been added to a repository.""" 
    8282 
    8383 
     84class DbRepositoryProvider(Component): 
     85    """Component providing repositories registered in the DB.""" 
     86 
     87    implements(IRepositoryProvider) 
     88 
     89    # IRepositoryProvider methods 
     90 
     91    def get_repositories(self): 
     92        """Retrieve repositories specified in the repository DB table.""" 
     93        db = self.env.get_db_cnx() 
     94        cursor = db.cursor() 
     95        cursor.execute("SELECT id,name,value FROM repository " 
     96                       "WHERE name IN ('dir', 'alias', 'type')") 
     97        reponames = {} 
     98        for (id, name, value) in cursor: 
     99            if value is not None: 
     100                reponames.setdefault(id, {})[name] = value 
     101         
     102        for reponame, info in reponames.iteritems(): 
     103            yield (reponame, info) 
     104 
     105 
    84106class RepositoryManager(Component): 
    85107    """Component registering the supported version control systems. 
    86108 
     
    296318                "Skip invalid repositories" 
    297319        return repositories 
    298320 
     321    def reload_repositories(self): 
     322        """Reload the repositories from the providers.""" 
     323        self._lock.acquire() 
     324        try: 
     325            # FIXME: trac-admin doesn't reload the environment 
     326            self._cache = {} 
     327            self._all_repositories = None 
     328        finally: 
     329            self._lock.release() 
     330        self.config.touch()     # Force environment reload 
     331     
    299332    def notify_changesets_added(self, reponame, revs, authname): 
    300333        """Notify repositories and change listeners about added changesets.""" 
    301334        self.log.debug('Notification on %s for changesets %r'