Switch to side-by-side view

--- a/ForgeSCM/forgescm/main.py
+++ b/ForgeSCM/forgescm/main.py
@@ -1,24 +1,16 @@
 #-*- python -*-
 import os
-import shutil
 import logging
-from cStringIO import StringIO
-from pprint import pformat
 
 # Non-stdlib imports
 import pkg_resources
-from tg import expose, validate, redirect, flash
-from pylons import g, c, request
-from formencode import validators
-from pymongo.bson import ObjectId
+from pylons import g, c
 from ming import schema
 
 
 # Pyforge-specific imports
 from pyforge.app import Application, ConfigOption, SitemapEntry
-from pyforge.lib.helpers import push_config
-from pyforge.lib.search import search
-from pyforge.lib.decorators import audit, react
+from pyforge.lib.helpers import push_config, mixin_reactors
 from pyforge.lib.security import require, has_artifact_access
 from pyforge.model import ProjectRole
 
@@ -26,7 +18,8 @@
 from . import model
 from . import version
 from .wsgi import WSGIHook
-from .lib import hg
+from .reactors import hg_react
+from .controllers import root
 
 log = logging.getLogger(__name__)
 
@@ -40,102 +33,11 @@
 
     def __init__(self, project, config):
         Application.__init__(self, project, config)
-        self.root = RootController()
+        self.root = root.RootController()
 
     @property
     def repo(self):
         return model.Repository.m.get(app_config_id=self.config._id)
-
-    @audit('scm.hg.init')
-    def scm_hg_init(self, routing_key, data):
-        repo = self.repo
-        cmd = hg.init()
-        cmd.clean_dir()
-        repo.clear_commits()
-        repo.parent = None
-        cmd.run()
-        if cmd.sp.returncode:
-            g.publish('react', 'error', dict(
-                    message=cmd.output))
-        else:
-            log.info('Setting repo status for %s', repo)
-            repo.status = 'Ready'
-            repo.m.save()
-                    
-    @audit('scm.hg.clone')
-    def scm_hg_clone(self, routing_key, data):
-        repo = self.repo
-        log.info('Begin cloning %s', data['url'])
-        # Perform the clone
-        cmd = hg.clone(data['url'], '.')
-        cmd.clean_dir()
-        cmd.run()
-        log.info('Clone complete for %s', data['url'])
-        if cmd.sp.returncode:
-            errmsg = cmd.output
-            g.publish('react', 'error', dict(
-                    message=errmsg))
-            repo.status = 'Error: %s' % errmsg
-            repo.m.save()
-            return
-        # Update the repo status
-        repo.status = 'Ready'
-        repo.m.save()
-        # Load the log & create refresh commit messages
-        cmd = hg.scm_log('-q')
-        cmd.run()
-        for line in cmd.output.split('\n'):
-            rev, hash = line.split(':')
-            g.publish('audit', 'scm.hg.refresh_commit', dict(
-                    hash=hash))
-            
-        # log.info('Begin log %s', data['url'])
-        # cmd = hg.scm_log('-g', '-p')
-        # cmd.run()
-        # log.info('Log complete %s', data['url'])
-        # # Clear the old set of commits
-        # repo.clear_commits()
-        # repo.parent = data['url']
-        # parser = hg.LogParser(repo._id)
-        # log.info('Begin parsing log')
-        # parser.feed(StringIO(cmd.output))
-
-    @audit('scm.hg.refresh_commit')
-    def scm_hg_refresh_commit(self, routing_key, data):
-        repo = self.repo
-        hash = data['hash']
-        log.info('Refresh commit %s', hash)
-        # Load the log
-        cmd = hg.scm_log('-g', '-p', '-r', hash)
-        cmd.run()
-        parser = hg.LogParser(repo._id)
-        parser.feed(StringIO(cmd.output))
-
-    @audit('scm.hg.fork')
-    def scm_hg_fork(self, routing_key, data):
-        assert False
-
-    @audit('scm.hg.reclone')
-    def scm_hg_reclone(self, routing_key, data):
-        repo = self.repo
-        # Perform the clone
-        cmd = hg.clone(repo.parent, '.')
-        cmd.clean_dir()
-        cmd.run()
-        if cmd.sp.returncode:
-            g.publish('react', 'error', dict(
-                    message=cmd.sp.stdout.read()))
-            return
-        # Load the log
-        cmd = hg.log('-g', '-p')
-        cmd.run()
-        # Clear the old set of commits
-        repo.clear_commits()
-        parser = hg.LogParser(repo._id)
-        parser.feed(StringIO(cmd.output))
-        # Update the repo status
-        repo.status = 'Ready'
-        repo.m.save()
 
     @property
     def sitemap(self):
@@ -145,10 +47,16 @@
                 SitemapEntry(menu_id, '.')[self.sidebar_menu()] ]
 
     def sidebar_menu(self):
-        return [
+        result = [
             SitemapEntry('Home', '.'),      
-            SitemapEntry('Search', 'search'),      
+            SitemapEntry('Search', 'search'),
             ]
+        if self.config.options.type == 'hg':
+            repo = self.repo
+            result += [
+                SitemapEntry('HgWeb', repo.native_url()),
+                SitemapEntry('Files', repo.native_url() + '/file') ]
+        return result
 
     @property
     def templates(self):
@@ -174,99 +82,13 @@
         # Create a repository
         repo = model.Repository.make(dict(
                 description='This is the repository object',
-                status='Pending'))
+                status='Pending',
+                type=self.config.options['type']))
         repo.m.insert()
-        rk = 'scm.%s.init' % self.config.options.type
-        g.publish('audit', rk, {})
 
     def uninstall(self, project):
         "Remove all the plugin's artifacts from the database"
         model.Repository.m.remove(dict(app_config_id=self.config._id))
 
-class RootController(object):
+mixin_reactors(ForgeSCMApp, hg_react)
 
-    def __init__(self):
-        self.repo = CommitsController()
-
-    @expose('forgescm.templates.index')
-    def index(self):
-        return dict(repo=c.app.repo)
-
-    @expose('forgescm.templates.fork')
-    def fork(self, project, mount_point):
-        new_repo = c.app.repo.fork(project, mount_point)
-        # Find projects where we can mount things
-        flash('Project %s forked' % c.app.repo.url())
-        redirect(new_repo.url())
-                    
-                  
-    @expose('forgescm.templates.search')
-    @validate(dict(q=validators.UnicodeString(if_empty=None),
-                   history=validators.StringBool(if_empty=False)))
-    def search(self, q=None, history=None):
-        'local plugin search'
-        results = []
-        count=0
-        if not q:
-            q = ''
-        else:
-            search_query = '''%s
-            AND is_history_b:%s
-            AND mount_point_s:%s''' % (
-                q, history, c.app.config.options.mount_point)
-            results = search(search_query)
-            if results: count=results.hits
-        return dict(q=q, history=history, results=results or [], count=count)
-
-    @expose()
-    def reinit(self):
-        repo = c.app.repo
-        repo.status = 'Pending Reinit'
-        repo.m.save()
-        g.publish('audit', 'scm.%s.init' % c.app.config.options.type, {})
-        redirect('.')
-        
-    @expose()
-    def reclone(self):
-        repo = c.app.repo
-        repo.status = 'Pending Reclone'
-        repo.m.save()
-        g.publish('audit', 'scm.%s.reclone' % c.app.config.options.type, {})
-        redirect('.')
-        
-    @expose()
-    def clone_from(self, url=None):
-        repo = c.app.repo
-        repo.status = 'Pending Clone'
-        repo.m.save()
-        g.publish('audit', 'scm.%s.clone' % c.app.config.options.type, dict(
-                url=url))
-        redirect('.')
-
-class CommitsController(object):
-
-    def _lookup(self, id, *remainder):
-        if ':' in id: id = id.split(':')[-1]
-        if '%3A' in id: id = id.split('%3A')[-1]
-        return CommitController(id), remainder
-
-class CommitController(object):
-
-    def __init__(self, id):
-        self.commit = model.Commit.m.get(hash=id)
-
-    @expose('forgescm.templates.commit_index')
-    def index(self):
-        return dict(value=self.commit)
-
-    def _lookup(self, id, *remainder):
-        return PatchController(id), remainder
-
-class PatchController(object):
-
-    def __init__(self, id):
-        self.patch = model.Patch.m.get(_id=ObjectId.url_decode(id))
-
-    @expose('forgescm.templates.patch_index')
-    def index(self):
-        return dict(value=self.patch)