Switch to side-by-side view

--- 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 = []