--- a/ForgeHg/forgehg/hg_main.py
+++ b/ForgeHg/forgehg/hg_main.py
@@ -1,132 +1,50 @@
#-*- python -*-
import logging
-import re
-import os
-import sys
-import shutil
-import email
-from subprocess import Popen
-from datetime import datetime
-from itertools import islice, chain
-from urllib import urlencode, quote, unquote
# Non-stdlib imports
import pkg_resources
-from tg import expose, validate, redirect, response, flash, url
-from tg.decorators import with_trailing_slash, without_trailing_slash
-import pylons
-from pylons import g, c, request
-from formencode import validators
-from pymongo import bson
-from webob import exc
-from mercurial import ui, hg
+from pylons import c, g
+from ming.utils import LazyProperty
from ming.orm.ormsession import ThreadLocalORMSession
-from ming.orm.base import mapper
-from pymongo.bson import ObjectId
# Pyforge-specific imports
-from allura.app import Application, ConfigOption, SitemapEntry, DefaultAdminController
from allura.lib import helpers as h
-from allura.lib.search import search
-from allura.lib.decorators import audit, react
-from allura.lib.security import require, has_artifact_access, has_project_access, require_authenticated
-from allura.model import Project, ProjectRole, User, ArtifactReference, Feed
-from allura.controllers import BaseController
+from allura import model as M
+from allura.controllers.repository import RepoRootController, RefsController, CommitsController
+from allura.lib.repository import RepositoryApp
# Local imports
-from forgehg import model
-from forgehg import version
-from .widgets import HgRevisionWidget
-from .reactors import reactors
-from .controllers import BranchBrowser, CommitBrowser
+from . import model as HM
+from . import version
+from .controllers import BranchBrowser
log = logging.getLogger(__name__)
-class W(object):
- revision_widget = HgRevisionWidget()
-
-class ForgeHgApp(Application):
- '''This is the Hg app for PyForge'''
+class ForgeHgApp(RepositoryApp):
+ '''This is the Git app for PyForge'''
__version__ = version.__version__
- # installable=False
- permissions = [ 'read', 'write', 'create', 'admin', 'configure' ]
- config_options = Application.config_options + [
- ConfigOption('cloned_from_project_id', ObjectId, None),
- ConfigOption('cloned_from_repo_id', ObjectId, None)
- ]
tool_label='Mercurial'
default_mount_label='Mercurial'
default_mount_point='mercurial'
ordinal=3
+ forkable=True
+ default_branch_name='ref/default'
def __init__(self, project, config):
- Application.__init__(self, project, config)
- self.root = RootController()
- self.admin = HgAdminController(self)
+ super(ForgeHgApp, self).__init__(project, config)
+ self.root = RepoRootController()
+ self.root.ref = RefsController(BranchBrowser)
+ self.root.ci = CommitsController()
- @property
- @h.exceptionless([], log)
- def sitemap(self):
- menu_id = self.config.options.mount_label.title()
- with h.push_config(c, app=self):
- return [
- SitemapEntry(menu_id, '.')[self.sidebar_menu()] ]
-
- def admin_menu(self):
- admin_url = c.project.url()+'admin/'+self.config.options.mount_point+'/'
- links = [SitemapEntry('Viewable Files', admin_url + 'extensions', className='nav_child')]
- # if self.permissions and has_artifact_access('configure', app=self)():
- # links.append(SitemapEntry('Permissions', admin_url + 'permissions', className='nav_child'))
- return links
-
- @h.exceptionless([], log)
- def sidebar_menu(self):
- links = [ SitemapEntry('Browse',c.app.url + url(quote('ref/default:/')), ui_icon='folder-collapsed'),
- SitemapEntry('History', c.app.url + url(quote('ref/default:/')) + 'log', ui_icon='document-b', small=c.app.repo.count())]
- if has_artifact_access('admin', app=c.app)():
- links.append(SitemapEntry('Admin', c.project.url()+'admin/'+self.config.options.mount_point, ui_icon='wrench'))
- repo = c.app.repo
- if repo and repo.status == 'ready':
- branches= repo.branchmap().keys()
- tags = repo.repo_tags().keys()
- if branches:
- links.append(SitemapEntry('Branches'))
- for b in branches:
- links.append(SitemapEntry(
- b, c.app.url + '?' + urlencode(dict(branch=b)),
- className='nav_child',
- small=c.app.repo.count(branch=b)))
- if tags:
- links.append(SitemapEntry('Tags'))
- for b in tags:
- links.append(SitemapEntry(
- b, c.app.url + '?' + urlencode(dict(tag=b)),
- className='nav_child'))
- return links
-
- @property
+ @LazyProperty
def repo(self):
- return model.HgRepository.query.get(app_config_id=self.config._id)
-
- @property
- def templates(self):
- return pkg_resources.resource_filename('forgehg', 'templates')
+ return HM.Repository.query.get(app_config_id=self.config._id)
def install(self, project):
- 'Set up any default permissions and roles here'
- self.config.options['project_name'] = project.name
+ '''Create repo object for this tool'''
super(ForgeHgApp, self).install(project)
- # Setup permissions
- role_developer = ProjectRole.query.get(name='Developer')._id
- role_auth = ProjectRole.query.get(name='*authenticated')._id
- self.config.acl.update(
- configure=c.project.acl['tool'],
- read=c.project.acl['read'],
- write=[role_developer],
- create=[role_developer],
- admin=c.project.acl['tool'])
- repo = model.HgRepository(
+ repo = HM.Repository(
name=self.config.options.mount_point,
tool='hg',
status='initing')
@@ -134,118 +52,14 @@
cloned_from_project_id = self.config.options.get('cloned_from_project_id')
cloned_from_repo_id = self.config.options.get('cloned_from_repo_id')
if cloned_from_project_id is not None:
- with h.push_config(c, project=Project.query.get(_id=cloned_from_project_id)):
- cloned_from = model.HgRepository.query.get(_id=cloned_from_repo_id)
- g.publish('audit', 'scm.hg.clone',
- dict(repo_name=repo.name, repo_path=repo.fs_path, cloned_from=cloned_from.full_fs_path))
+ with h.push_config(c, project=M.Project.query.get(_id=cloned_from_project_id)):
+ cloned_from = HM.Repository.query.get(_id=cloned_from_repo_id)
+ msg = dict(
+ cloned_from_path=cloned_from.full_fs_path,
+ cloned_from_name=cloned_from.app.config.script_name(),
+ cloned_from_url=cloned_from.app.url)
+ g.publish('audit', 'repo.clone', msg)
else:
- g.publish('audit', 'scm.hg.init',
+ g.publish('audit', 'repo.init',
dict(repo_name=repo.name, repo_path=repo.fs_path))
-
- def uninstall(self, project):
- g.publish('audit', 'scm.hg.uninstall', dict(project_id=project._id))
-
- @audit('scm.hg.uninstall')
- def _uninstall(self, routing_key, data):
- "Remove all the tool's artifacts and the physical repository"
- repo = self.repo
- if repo is not None:
- shutil.rmtree(repo.full_fs_path, ignore_errors=True)
- model.HgRepository.query.remove(dict(app_config_id=self.config._id))
- super(ForgeHgApp, self).uninstall(project_id=data['project_id'])
-
-
-class HgAdminController(DefaultAdminController):
-
- def __init__(self, app):
- self.app = app
- self.repo = app.repo
-
- @with_trailing_slash
- def index(self, **kw):
- redirect('permissions')
-
- @without_trailing_slash
- @expose('jinja:hg/admin_extensions.html')
- def extensions(self, **kw):
- return dict(app=self.app,
- allow_config=has_artifact_access('configure', app=self.app)(),
- additional_viewable_extensions=getattr(self.repo, 'additional_viewable_extensions', ''))
-
- @without_trailing_slash
- @expose()
- def set_extensions(self, **post_data):
- self.repo.additional_viewable_extensions = post_data['additional_viewable_extensions']
-
-
-class RootController(BaseController):
-
- def _check_security(self):
- require(has_artifact_access('read'))
-
- def __init__(self):
- self.ref = Refs()
- self.ci = Commits()
-
- @expose('jinja:hg/index.html')
- def index(self, offset=0, branch='default', **kw):
- # Add the colon so we know where the branch part ends
- redirect(url(quote('ref/%s:/' % branch)))
-
- @with_trailing_slash
- @expose('jinja:hg/fork.html')
- def fork(self, to_name=None):
- require_authenticated()
- from_repo = c.app.repo
- to_project_name = 'u/' + c.user.username
- ThreadLocalORMSession.flush_all()
- ThreadLocalORMSession.close_all()
- from_project = c.project
- to_project = Project.query.get(shortname=to_project_name)
- with h.push_config(c, project=to_project):
- if request.method!='POST' or to_name is None:
- prefix_len = len(to_project_name+'/')
- in_use = [sp.shortname[prefix_len:] for sp in to_project.direct_subprojects]
- in_use += [ac.options['mount_point'] for ac in to_project.app_configs]
- return dict(from_repo=from_repo,
- to_project_name=to_project_name,
- in_use=in_use,
- to_name=to_name or '')
- else:
- if not to_project.database_configured:
- to_project.configure_project_database(is_user_project=True)
- require(has_project_access('tool', to_project))
- try:
- to_project.install_app(
- 'Hg', to_name,
- cloned_from_project_id=from_project._id,
- cloned_from_repo_id=from_repo._id)
- redirect('/'+to_project_name+'/'+to_name+'/')
- except exc.HTTPRedirection:
- raise
- except Exception, ex:
- flash(str(ex), 'error')
- redirect(request.referer)
-
-
-class Refs(object):
-
- @expose()
- def _lookup(self, *parts):
- parts = map(unquote, parts)
- ref = []
- while parts:
- part = parts.pop(0)
- ref.append(part)
- if part.endswith(':'): break
- ref = '/'.join(ref)[:-1]
- return BranchBrowser(ref), parts
-
-class Commits(object):
-
- @expose()
- def _lookup(self, ci, *remainder):
- return CommitBrowser(ci), remainder
-
-h.mixin_reactors(ForgeHgApp, reactors)