--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -1,59 +1,143 @@
import os
-from urllib import unquote
+import logging
+from urllib import quote, unquote
from pylons import c, g, request, response
-import tg
-from tg import redirect, expose, url, override_template
+from webob import exc
+from tg import redirect, expose, override_template, flash, url
+from tg.decorators import with_trailing_slash
+
+from ming.orm import ThreadLocalORMSession
from allura.lib import patience
-from allura.lib.widgets.file_browser import TreeWidget
-from allura import model
+from allura.lib import security
+from allura.lib import helpers as h
+from allura.lib.widgets.repo import SCMLogWidget, SCMRevisionWidget, SCMTreeWidget
+from allura import model as M
+
from .base import BaseController
+
+log = logging.getLogger(__name__)
def on_import():
BranchBrowser.CommitBrowserClass = CommitBrowser
CommitBrowser.TreeBrowserClass = TreeBrowser
TreeBrowser.FileBrowserClass = FileBrowser
+class RepoRootController(BaseController):
+
+ def _check_security(self):
+ security.require(security.has_artifact_access('read'))
+
+ @expose()
+ def index(self, offset=0, branch=None, **kw):
+ if branch is None:
+ branch=c.app.default_branch_name
+ redirect(url(quote('%s%s/' % (
+ branch, c.app.END_OF_REF_ESCAPE))))
+
+ @expose()
+ def refresh(self):
+ g.publish('audit', 'repo.refresh')
+ return '%r refresh queued.\n' % c.app.repo
+
+ @with_trailing_slash
+ @expose('jinja:repo/fork.html')
+ def fork(self, to_name=None):
+ security.require_authenticated()
+ if not c.app.forkable: raise exc.HTTPNotFound
+ from_repo = c.app.repo
+ to_project_name = 'u/' + c.user.username
+ ThreadLocalORMSession.flush_all()
+ ThreadLocalORMSession.close_all()
+ from_project = c.project
+ to_project = M.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)
+ security.require(security.has_project_access('tool', to_project))
+ try:
+ to_project.install_app(
+ from_repo.tool_name, 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 RefsController(object):
+
+ def __init__(self, BranchBrowserClass):
+ self.BranchBrowserClass = BranchBrowserClass
+
+ @expose()
+ def _lookup(self, *parts):
+ parts = map(unquote, parts)
+ ref = []
+ while parts:
+ part = parts.pop(0)
+ ref.append(part)
+ if part.endswith(c.app.END_OF_REF_ESCAPE):
+ break
+ ref = '/'.join(ref)[:-1]
+ return self.BranchBrowserClass(ref), parts
+
+class CommitsController(object):
+
+ @expose()
+ def _lookup(self, ci, *remainder):
+ return CommitBrowser(ci), remainder
+
class BranchBrowser(BaseController):
+ log_widget=SCMLogWidget()
CommitBrowserClass=None
def __init__(self, branch):
self._branch = branch
- def index(self, limit=None, page=0, count=0, **kw):
+ def _check_security(self):
+ security.require(security.has_artifact_access('read', c.app.repo))
+
+ @expose('jinja:repo/log.html')
+ @with_trailing_slash
+ def log(self, limit=None, page=0, count=0, **kw):
limit, page, start = g.handle_paging(limit, page)
- count = c.app.repo.count(branch=self._branch)
revisions = c.app.repo.log(
branch=self._branch,
offset=start,
limit=limit)
- revisions = [ dict(value=r) for r in revisions ]
- for r in revisions:
- r.update(r['value'].context())
+ c.log_widget = self.log_widget
return dict(
username=c.user._id and c.user.username,
branch=self._branch,
log=revisions,
page=page,
limit=limit,
- count=count,
+ count=self._branch.count,
**kw)
-
- @expose()
- def _lookup(self, commit, *rest):
- commit=unquote(commit)
- return self.CommitBrowserClass(commit), rest
class CommitBrowser(BaseController):
TreeBrowserClass=None
- revision_widget = None
+ revision_widget = SCMRevisionWidget()
def __init__(self, revision):
self._revision = revision
self._commit = c.app.repo.commit(revision)
- self.tree = self.TreeBrowserClass(self._commit)
-
+ self.tree = self.TreeBrowserClass(self._commit, tree=self._commit.tree)
+
+ @expose('jinja:repo/commit.html')
def index(self):
c.revision_widget = self.revision_widget
result = dict(commit=self._commit)
@@ -62,38 +146,24 @@
return result
class TreeBrowser(BaseController):
+ tree_widget = SCMTreeWidget()
FileBrowserClass=None
- tree_widget=TreeWidget()
-
- def __init__(self, commit, parent=None, name=None):
+
+ def __init__(self, commit, tree, path='', parent=None):
self._commit = commit
+ self._tree = tree
+ self._path = path
self._parent = parent
- self._name = name
- if parent:
- self._tree = parent.get_tree(name)
- elif self._commit:
- self._tree = self._commit.tree()
- else:
- self._tree = None
@expose('jinja:repo/tree.html')
+ @with_trailing_slash
def index(self, **kw):
- if not request.path.endswith('/'):
- filename = request.environ['PATH_INFO'].rsplit('/')[-1]
- if filename and self._tree.is_blob(filename):
- controller = self.FileBrowserClass(
- self._commit,
- self._tree,
- filename)
- if 'diff' in kw:
- override_template(self.index, 'jinja:repo/diff.html')
- else:
- override_template(self.index, 'jinja:repo/file.html')
- return controller.index(**kw)
c.tree_widget = self.tree_widget
return dict(
+ repo=c.app.repo,
commit=self._commit,
tree=self._tree,
+ path=self._path,
parent=self._parent)
@expose()
@@ -107,10 +177,16 @@
self._commit,
self._tree,
filename), rest
+ elif rest == ('index', ):
+ rest = (request.environ['PATH_INFO'].rsplit('/')[-1],)
+ tree = self._tree.get_tree(next)
+ if tree is None:
+ raise exc.HTTPNotFound
return self.__class__(
self._commit,
- self._tree,
- next), rest
+ tree,
+ self._path + '/' + next,
+ self), rest
class FileBrowser(BaseController):
@@ -122,7 +198,6 @@
@expose('jinja:repo/file.html')
def index(self, **kw):
- self._blob.context()
if kw.pop('format', 'html') == 'raw':
return self.raw()
elif 'diff' in kw:
@@ -141,7 +216,7 @@
@expose()
def raw(self):
content_type = self._blob.content_type.encode('utf-8')
- filename = self._blob.filename.encode('utf-8')
+ filename = self._blob.name.encode('utf-8')
response.headers['Content-Type'] = ''
response.content_type = content_type
if self._blob.content_encoding is not None:
@@ -156,8 +231,7 @@
try:
path, filename = os.path.split(self._blob.path())
a_ci = c.app.repo.commit(commit)
- a_tree = a_ci.tree()
- a = a_tree.get_blob(filename, path[1:].split('/'))
+ a = a_ci.get_path(self._blob.path())
apath = a.path()
except:
a = []