#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

from __future__ import unicode_literals
from __future__ import absolute_import
import os
import logging
import difflib
from datetime import datetime
from six.moves.urllib.parse import quote, unquote
from collections import defaultdict, OrderedDict


from ming.utils import LazyProperty
from paste.deploy.converters import asbool, asint
from tg import tmpl_context as c, app_globals as g
from tg import request, response
from webob import exc
import tg
from tg import redirect, expose, flash, validate
from tg.decorators import with_trailing_slash, without_trailing_slash
from tg import session as web_session
import formencode
from formencode import validators
from bson import ObjectId
from ming.base import Object
from ming.orm import ThreadLocalORMSession, session

import allura.tasks
from allura import model as M
from allura.lib import utils
from allura.lib import helpers as h
from allura.lib import widgets as w
from allura.lib.decorators import require_post, memorable_forget
from allura.lib.diff import HtmlSideBySideDiff
from allura.lib.security import require_access, require_authenticated, has_access
from allura.lib.widgets import form_fields as ffw
from allura.lib.widgets.repo import SCMLogWidget, SCMRevisionWidget, SCMTreeWidget
from allura.lib.widgets.repo import SCMMergeRequestWidget
from allura.lib.widgets.repo import SCMMergeRequestDisposeWidget, SCMCommitBrowserWidget
from allura.lib.widgets.subscriptions import SubscribeForm
from allura.controllers import AppDiscussionController
from allura.controllers.base import DispatchIndex
from allura.controllers.rest import AppRestControllerMixin
from allura.controllers.feed import FeedController, FeedArgs
from .base import BaseController
import six

log = logging.getLogger(__name__)


def on_import():
    BranchBrowser.CommitBrowserClass = CommitBrowser
    CommitBrowser.TreeBrowserClass = TreeBrowser
    TreeBrowser.FileBrowserClass = FileBrowser


class RepoRootController(BaseController, FeedController):
    _discuss = AppDiscussionController()
    commit_browser_widget = SCMCommitBrowserWidget()

    def get_feed(self, project, app, user):
        query = dict(project_id=project._id, app_config_id=app.config._id)
        pname, repo = (project.shortname, app.config.options.mount_label)
        title = '%s %s changes' % (pname, repo)
        description = 'Recent changes to %s repository in %s project' % (
            repo, pname)
        return FeedArgs(query, title, app.url, description=description)

    def _check_security(self):
        require_access(c.app, 'read')

    @expose('jinja:allura:templates/markdown_syntax_dialog.html')
    def markdown_syntax_dialog(self, **kw):
        """Static page explaining markdown."""
        return dict()

    @with_trailing_slash
    @expose()
    def index(self, offset=0, branch=None, **kw):
        if branch is None:
            branch = c.app.default_branch_name
        redirect(c.app.repo.url_for_commit(branch, url_type='ref'))

    @with_trailing_slash
    @expose('jinja:allura:templates/repo/forks.html')
    def forks(self, **kw):

        links = []
        if c.app.repo.forks:
            for f in c.app.repo.forks:
                repo_path_parts = f.url().strip('/').split('/')
                links.append(dict(
                    repo_url=f.url(),
                    repo='%s / %s' % (repo_path_parts[1],
                                      repo_path_parts[-1]),
                ))
        return dict(links=links)

    @expose()
    def refresh(self, **kw):
        allura.tasks.repo_tasks.refresh.post()
        if request.referer:
            flash('Repository is being refreshed')
            redirect(six.ensure_text(request.referer or '/'))
        else:
            return '%r refresh queued.\n' % c.app.repo

    @with_trailing_slash
    @expose('jinja:allura:templates/repo/fork.html')
    def fork(self, project_id=None, mount_point=None, mount_label=None, **kw):
        # this shows the form and handles the submission
        require_authenticated()
        if not c.app.forkable:
            raise exc.HTTPNotFound
        from_repo = c.app.repo
        ThreadLocalORMSession.flush_all()
        ThreadLocalORMSession.close_all()
        from_project = c.project
        to_project = M.Project.query.get(_id=ObjectId(project_id))
        mount_label = mount_label or '%s - %s' % (c.project.name,
                                                  c.app.config.options.mount_label)
        mount_point = (mount_point or from_project.shortname)
        if request.method != 'POST' or not mount_point:
            return dict(from_repo=from_repo,
                        user_project=c.user.private_project(),
                        mount_point=mount_point,
                        mount_label=mount_label)
        else:
            with h.push_config(c, project=to_project):
                if not to_project.database_configured:
                    to_project.configure_project(is_user_project=True)
                require_access(to_project, 'admin')
                try:
                    to_project.install_app(
                        ep_name=from_repo.tool_name,
                        mount_point=mount_point,
                        mount_label=mount_label,
                        cloned_from_project_id=from_project._id,
                        cloned_from_repo_id=from_repo._id)
                    redirect(to_project.url() + mount_point + '/')
                except exc.HTTPRedirection:
                    raise
                except Exception as ex:
                    flash(str(ex), 'error')
                    redirect(six.ensure_text(request.referer or '/'))

    @property
    def mr_widget(self):
        source_branches = [
            b.name
            for b in c.app.repo.get_branches() + c.app.repo.get_tags(for_merge_request=True)]
        with c.app.repo.push_upstream_context():
            target_branches = [b.name for b in c.app.repo.get_branches()]
            subscribed_to_upstream = M.Mailbox.subscribed()
        return SCMMergeRequestWidget(
            source_branches=source_branches,
            target_branches=target_branches,
            show_subscribe_checkbox=not subscribed_to_upstream,
        )

    @without_trailing_slash
    @expose('jinja:allura:templates/repo/request_merge.html')
    def request_merge(self, branch=None, **kw):
        require_access(c.app.repo, 'admin')
        c.form = self.mr_widget
        if branch in c.form.source_branches:
            source_branch = branch
        else:
            source_branch = c.app.default_branch_name
        with c.app.repo.push_upstream_context():
            target_branch = c.app.default_branch_name
        return {
            'source_branch': source_branch,
            'target_branch': target_branch,
        }

    @memorable_forget()
    @expose('jinja:allura:templates/repo/request_merge.html')  # needed when we "return self.request_merge(...)"
    @require_post()
    def do_request_merge(self, **kw):
        try:
            kw = self.mr_widget.to_python(kw)
        except formencode.Invalid:
            # trigger error_handler directly
            return self.request_merge(**kw)
        downstream = dict(
            project_id=c.project._id,
            mount_point=c.app.config.options.mount_point,
            commit_id=c.app.repo.commit(kw['source_branch'])._id)
        with c.app.repo.push_upstream_context():
            mr = M.MergeRequest.upsert(
                downstream=downstream,
                target_branch=kw['target_branch'],
                source_branch=kw['source_branch'],
                summary=kw['summary'],
                description=kw['description'])
            if kw.get('subscribe'):
                mr.subscribe(user=c.user)
            M.Notification.post(
                mr, 'merge_request',
                subject=mr.email_subject,
                message_id=mr.message_id(),
            )
            t = M.Thread.new(
                discussion_id=c.app.config.discussion_id,
                ref_id=mr.index_id(),
            )
            session(t).flush()
            allura.tasks.notification_tasks.send_usermentions_notification.post(mr.index_id(), kw['description'])
            g.director.create_activity(c.user, 'created', mr,
                                       related_nodes=[c.project], tags=['merge-request'])
            redirect(mr.url())

    @without_trailing_slash
    @expose('jinja:allura:templates/repo/commit_browser.html')
    def commit_browser(self, **kw):
        if not c.app.repo or c.app.repo.status != 'ready':
            return dict(status='not_ready')
        # if c.app.repo.count() > 2000:
        #     return dict(status='too_many_commits')
        if c.app.repo.is_empty():
            return dict(status='no_commits')
        c.commit_browser_widget = self.commit_browser_widget
        return dict(status='ready')

    @without_trailing_slash
    @expose('json:')
    def commit_browser_data(self, start=None, limit=None, **kw):
        log.debug('Start commit_browser_data')
        if limit is None:
            limit = int(tg.config.get('scm.view.commit_browser.limit', 500))

        if start:
            head_ids = start.split(',')
        else:
            # master, and any other branches
            head_ids = [head.object_id for head in c.app.repo.get_heads()]
        log.debug('Got %s heads', len(head_ids))

        # recent commits from any head
        heads_log = list(c.app.repo.log(head_ids, id_only=True, limit=int(limit)))
        log.debug('Did log lookup')
        commit_ids = [c.app.repo.rev_to_commit_id(r) for r in heads_log]

        # any we didn't get to will be attempted in next page of commits
        next_page_commits = list(set(head_ids) - set(commit_ids))
        # and remove any heads that didn't come through from further processing
        head_ids = set(head_ids).intersection(set(commit_ids))

        log.info('Grab %d commit objects by ID', len(commit_ids))
        commits_by_id = {
            c_obj._id: c_obj
            for c_obj in M.repository.CommitDoc.m.find(dict(_id={'$in': commit_ids}))}

        log.info('... build graph')
        parents = {}
        children = defaultdict(list)
        dates = {}
        for row, (oid, ci) in enumerate(six.iteritems(commits_by_id)):
            parents[oid] = list(ci.parent_ids)
            dates[oid] = ci.committed.date
            for p_oid in ci.parent_ids:
                children[p_oid].append(oid)
        result = []
        row = 0
        for oid in topo_sort(children, parents, dates, head_ids):
            if oid not in commits_by_id:
                next_page_commits.append(oid)
                continue
            ci = commits_by_id[oid]
            url = c.app.repo.url_for_commit(Object(_id=oid))
            msg_split = ci.message.splitlines()
            if msg_split:
                msg = h.hide_private_info(msg_split[0])
            else:
                msg = "No commit message."
            result.append(dict(
                oid=oid,
                short_id=c.app.repo.shorthand_for_commit(oid),
                row=row,
                parents=ci.parent_ids,
                message=msg,
                url=url))
            row += 1

        built_tree = OrderedDict((ci_json['oid'], ci_json) for ci_json in result)
        log.info('...done')
        return dict(
            built_tree=built_tree,
            next_commit=','.join(next_page_commits),
        )

    @expose('json:')
    def status(self, **kw):
        return dict(status=c.app.repo.status)


class RepoRestController(RepoRootController, AppRestControllerMixin):

    @expose('json:')
    def index(self, **kw):
        all_commits = c.app.repo._impl.new_commits(all_commits=True)
        return dict(commit_count=len(all_commits))

    @expose('json:')
    def commits(self, rev=None, limit=25, **kw):
        '''
        Return 25 latest commits   : /rest/p/code/logs/
        Return 25 commits since sha: /rest/p/code/logs/e1a2ad
        Return 04 commits since sha: /rest/p/code/logs/e1a2ad/4
        Return 120 latest commits  : /rest/p/code/logs/?limit=120
        '''

        revisions = c.app.repo.log(rev, id_only=False, limit=int(limit))

        return {
            'commits': [
                {
                    'parents': [{'id': p} for p in commit['parents']],
                    'url': c.app.repo.url_for_commit(commit['id']),
                    'id': commit['id'],
                    'message': commit['message'],
                    'tree': commit.get('tree'),
                    'committed_date': commit['committed']['date'],
                    'authored_date': commit['authored']['date'],
                    'author': {
                        'name': commit['authored']['name'],
                        'email': commit['authored']['email'],
                    },
                    'committer': {
                        'name': commit['committed']['name'],
                        'email': commit['committed']['email'],
                    },
                }
                for commit in revisions
            ]}


class MergeRequestsController(object):

    @with_trailing_slash
    @expose('jinja:allura:templates/repo/merge_requests.html')
    def index(self, status=None, **kw):
        status = status or 'open'
        status = [status]
        if status == ['all']:
            requests = c.app.repo.all_merge_requests()
        else:
            requests = c.app.repo.merge_requests_by_statuses(*status)

        return dict(
            status=status,
            requests=requests)

    @expose()
    def _lookup(self, num, *remainder):
        return MergeRequestController(num), remainder


class MergeRequestController(object):
    log_widget = SCMLogWidget(show_paging=False)
    thread_widget = w.Thread(
        page=None, limit=None, page_size=None, count=None,
        style='linear')
    mr_dispose_form = SCMMergeRequestDisposeWidget()
    subscribe_form = SubscribeForm(thing='merge request')

    def __init__(self, num):
        self.req = M.MergeRequest.query.get(
            app_config_id=c.app.config._id,
            request_number=int(num))
        if self.req is None:
            raise exc.HTTPNotFound

    @with_trailing_slash
    @expose('jinja:allura:templates/repo/merge_request.html')
    def index(self, page=0, limit=250, **kw):
        c.thread = self.thread_widget
        c.log_widget = self.log_widget
        c.mr_dispose_form = self.mr_dispose_form
        c.subscribe_form = self.subscribe_form

        limit, page = h.paging_sanitizer(limit, page)
        with self.req.push_downstream_context():
            downstream_app = c.app

        tool_subscribed = M.Mailbox.subscribed()
        if tool_subscribed:
            subscribed = False
        else:
            subscribed = M.Mailbox.subscribed(artifact=self.req)

        result = dict(
            downstream_app=downstream_app,
            req=self.req,
            can_merge=self.req.can_merge(),
            can_merge_status=self.req.can_merge_task_status(),
            merge_status=self.req.merge_task_status(),
            page=page,
            limit=limit,
            count=self.req.discussion_thread.post_count,
            subscribed=subscribed,
            commits_task_started=False,
        )
        if self.req.new_commits is not None:
            try:
                result['commits'] = self.req.commits
            except Exception:
                log.info(
                    "Can't get commits for merge request %s",
                    self.req.url(),
                    exc_info=True)
                result['commits'] = []
                result['error'] = True
        else:
            if self.req.commits_task_status() not in ('busy', 'ready'):
                allura.tasks.repo_tasks.determine_mr_commits.post(self.req._id)
            result['commits'] = []
            result['commits_task_started'] = True
        return result

    @property
    def mr_widget_edit(self):
        target_branches = [
            b.name
            for b in c.app.repo.get_branches() + c.app.repo.get_tags(for_merge_request=True)]
        with self.req.push_downstream_context():
            source_branches = [b.name for b in c.app.repo.get_branches()]
        return SCMMergeRequestWidget(
            source_branches=source_branches,
            target_branches=target_branches)

    @expose('jinja:allura:templates/repo/merge_request_edit.html')
    def edit(self, **kw):
        require_access(self.req, 'write')
        c.form = self.mr_widget_edit
        if self.req['source_branch'] in c.form.source_branches:
            source_branch = self.req['source_branch']
        else:
            source_branch = c.app.default_branch_name
        if self.req['target_branch'] in c.form.target_branches:
            target_branch = self.req['target_branch']
        else:
            target_branch = c.app.default_branch_name
        return {
            'source_branch': source_branch,
            'target_branch': target_branch,
            'description': self.req['description'],
            'summary': self.req['summary']
        }

    @memorable_forget()
    @expose('jinja:allura:templates/repo/merge_request_edit.html')   # needed when we "return self.edit(...)"
    @require_post()
    def do_request_merge_edit(self, **kw):
        require_access(self.req, 'write')
        try:
            kw = self.mr_widget_edit.to_python(kw)
        except formencode.Invalid:
            # trigger error_handler directly
            return self.edit(**kw)
        changes = OrderedDict()
        old_text = self.req.description
        if self.req.summary != kw['summary']:
            changes['Summary'] = [self.req.summary, kw['summary']]
            self.req.summary = kw['summary']

        if self.req.target_branch != kw['target_branch']:
            changes['Target branch'] = [self.req.target_branch, kw['target_branch']]
            self.req.target_branch = kw['target_branch']

        if self.req.source_branch != kw['source_branch']:
            changes['Source branch'] = [self.req.source_branch, kw['source_branch']]
            self.req.source_branch = kw['source_branch']

        if self.req.description != kw['description']:
            changes['Description'] = h.unidiff(self.req.description, kw['description'])
            self.req.description = kw['description']

        if changes:
            self.req.add_meta_post(changes=changes)
            allura.tasks.notification_tasks.send_usermentions_notification.post(self.req.index_id(), kw['description'], old_text)
            g.director.create_activity(c.user, 'updated', self.req,
                                       related_nodes=[c.project], tags=['merge-request'])
        self.refresh()

    @without_trailing_slash
    @expose('json:')
    @require_post()
    def update_markdown(self, text=None, **kw):
        if has_access(self.req, 'write'):
            self.req.description = text
            self.req.commit()
            g.director.create_activity(c.user, 'updated', self.req,
                                       related_nodes=[c.project], tags=['merge-request'])
            return {
                'status' : 'success'
            }
        else:
            return {
                'status' : 'no_permission'
            }

    @expose()
    @without_trailing_slash
    def get_markdown(self):
        return self.req.description

    @expose()
    @require_post()
    @validate(mr_dispose_form)
    def save(self, status=None, **kw):
        if status and self.req.status != status and \
           (has_access(self.req, 'write') or (self.req.creator == c.user and status == 'rejected')):
            self.req.add_meta_post(changes={'Status': [self.req.status, status]})
            g.director.create_activity(c.user, 'updated', self.req,
                                       related_nodes=[c.project], tags=['merge-request'])
            self.req.status = status
        redirect('.')

    @expose()
    @require_post()
    def refresh(self, **kw):
        require_access(self.req, 'read')
        with self.req.push_downstream_context():
            self.req.new_commits = None  # invalidate this cache
            self.req.downstream['commit_id'] = c.app.repo.commit(self.req.source_branch)._id
        redirect(self.req.url())

    @expose()
    @require_post()
    def merge(self):
        if not self.req.merge_allowed(c.user) or not self.req.can_merge():
            raise exc.HTTPNotFound
        self.req.merge()
        redirect(self.req.url())

    @expose('json:')
    def merge_task_status(self, **kw):
        return {'status': self.req.merge_task_status()}

    @expose('json:')
    def can_merge_task_status(self, **kw):
        return {'status': self.req.can_merge_task_status()}

    @expose('json:')
    def can_merge_result(self, **kw):
        """Return result from the cache. Used by js, after task was completed."""
        return {'can_merge': self.req.can_merge()}

    @expose()
    def commits_html(self, **kw):
        if self.req.new_commits is not None:
            with self.req.push_downstream_context():
                downstream_app = c.app
            return SCMLogWidget().display(value=self.req.commits, app=downstream_app)

        task_status = self.req.commits_task_status()
        if task_status is None:
            raise exc.HTTPNotFound
        elif task_status == 'error':
            raise exc.HTTPInternalServerError
        elif task_status in ('busy', 'ready'):
            raise exc.HTTPAccepted

    @expose('json:')
    @require_post()
    @validate(subscribe_form)
    def subscribe(self, subscribe=None, unsubscribe=None, **kw):
        if subscribe:
            self.req.subscribe()
        elif unsubscribe:
            self.req.unsubscribe()
        return {
            'status': 'ok',
            'subscribed': M.Mailbox.subscribed(artifact=self.req),
            'subscribed_to_tool': M.Mailbox.subscribed(),
            'subscribed_to_entire_name': 'code repository',
        }


class RefsController(object):

    def __init__(self, BranchBrowserClass):
        self.BranchBrowserClass = BranchBrowserClass

    @expose()
    def _lookup(self, ref, *remainder):
        EOR = c.app.END_OF_REF_ESCAPE
        if EOR in remainder:
            i = remainder.index(EOR)
            ref = '/'.join((ref,) + remainder[:i])
            remainder = remainder[i + 1:]
        return self.BranchBrowserClass(ref), remainder


class CommitsController(object):

    @expose()
    def _lookup(self, ci, *remainder):
        ci = unquote(ci)
        EOR = c.app.END_OF_REF_ESCAPE
        if EOR in remainder:
            i = remainder.index(EOR)
            ci = '/'.join((ci,) + remainder[:i])
            remainder = remainder[i + 1:]
        return CommitBrowser(ci), remainder


class BranchBrowser(BaseController):
    CommitBrowserClass = None

    def __init__(self, branch):
        self._branch = branch

    def _check_security(self):
        require_access(c.app.repo, 'read')

    @expose('jinja:allura:templates/repo/tags.html')
    @with_trailing_slash
    def tags(self, **kw):
        return dict(tags=c.app.repo.get_tags())

    @expose('jinja:allura:templates/repo/tags.html')
    @with_trailing_slash
    def branches(self, **kw):
        return dict(title='Branches', tags=c.app.repo.get_branches())

    @expose()
    @with_trailing_slash
    def log(self, **kw):
        ci = c.app.repo.commit(self._branch)
        redirect(ci.url() + 'log/')


class CommitBrowser(BaseController):
    TreeBrowserClass = None
    revision_widget = SCMRevisionWidget()
    log_widget = SCMLogWidget()
    page_list = ffw.PageList()
    DEFAULT_PAGE_LIMIT = 25

    def __init__(self, revision):
        self._revision = revision
        self._commit = c.app.repo.commit(revision)
        c.revision = revision
        if self._commit is None:
            raise exc.HTTPNotFound

    @LazyProperty
    def tree(self):
        return self.TreeBrowserClass(self._commit, tree=self._commit.tree)

    @expose('jinja:allura:templates/repo/commit.html')
    @validate(dict(page=validators.Int(if_empty=0, if_invalid=0),
                   limit=validators.Int(if_empty=DEFAULT_PAGE_LIMIT, if_invalid=DEFAULT_PAGE_LIMIT)))
    def index(self, page=0, limit=DEFAULT_PAGE_LIMIT, **kw):
        c.revision_widget = self.revision_widget
        c.page_list = self.page_list
        result = dict(commit=self._commit)
        if self._commit:
            result.update(self._commit.context())
        tree = self._commit.tree
        limit, page, start = g.handle_paging(limit, page,
                                             default=self.DEFAULT_PAGE_LIMIT)
        diffs = self._commit.paged_diffs(start=start, end=start + limit, onlyChangedFiles=True)
        result['artifacts'] = []
        for t in ('added', 'removed', 'changed', 'copied', 'renamed'):
            for f in diffs[t]:
                if t in ('copied', 'renamed'):
                    filepath = f['new']
                else:
                    filepath = f
                is_text = filepath and tree.get_blob_by_path(filepath) and tree.get_blob_by_path(filepath).has_html_view
                result['artifacts'].append(
                    (t, f, 'blob' if tree.get_blob_by_path(f) else 'tree', is_text)
                )
        count = diffs['total']
        result.update(dict(page=page, limit=limit, count=count))
        # Sort the result['artifacts'] which is in format as below -
        # [('added', u'aaa.txt', 'blob', True),
        # ('added', u'eee.txt', 'blob', True),
        # ('added', u'ggg.txt', 'blob', True),
        # ('removed', u'bbb.txt', 'tree', None),
        # ('removed', u'ddd.txt', 'tree', None),
        # ('changed', u'ccc.txt', 'blob', True)]
        result['artifacts'].sort(key=lambda x: x[1]['old'] if(isinstance(x[1], dict)) else x[1])
        return result

    @expose('jinja:allura:templates/repo/commit_basic.html')
    def basic(self, **kw):
        c.revision_widget = self.revision_widget
        result = dict(commit=self._commit)
        if self._commit:
            result.update(self._commit.context())
        return result

    @expose('jinja:allura:templates/repo/tarball.html')
    def tarball(self, **kw):
        path = request.params.get('path')
        if not asbool(tg.config.get('scm.repos.tarball.enable', False)):
            raise exc.HTTPNotFound()
        rev = self._commit.url().split('/')[-2]
        status = c.app.repo.get_tarball_status(rev, path)
        if not status and request.method == 'POST':
            allura.tasks.repo_tasks.tarball.post(rev, path)
            redirect('tarball?path={0}'.format(h.urlquote(path) if path else ''))
        return dict(commit=self._commit, revision=rev, status=status)

    @expose('json:')
    def tarball_status(self, path=None, **kw):
        if not asbool(tg.config.get('scm.repos.tarball.enable', False)):
            raise exc.HTTPNotFound()
        rev = self._commit.url().split('/')[-2]
        return dict(status=c.app.repo.get_tarball_status(rev, path))

    @expose('jinja:allura:templates/repo/log.html')
    @with_trailing_slash
    @validate(dict(page=validators.Int(if_empty=0, if_invalid=0),
                   limit=validators.Int(if_empty=0, if_invalid=0)))
    def log(self, limit=0, path=None, **kw):
        if not limit:
            limit = int(tg.config.get('scm.view.log.limit', 25))
        is_file = False
        if path:
            is_file = c.app.repo.is_file(path, self._commit._id)
        limit, _ = h.paging_sanitizer(limit, 0)
        commits = list(c.app.repo.log(
            revs=self._commit._id,
            path=path,
            id_only=False,
            limit=limit + 1))  # get an extra one to check for a next commit
        next_commit = None
        if len(commits) > limit:
            next_commit = commits.pop()
        c.log_widget = self.log_widget
        return dict(
            username=c.user._id and c.user.username,
            branch=None,
            log=commits,
            next_commit=next_commit,
            limit=limit,
            path=path,
            is_file=is_file,
            **kw)


class TreeBrowser(BaseController, DispatchIndex):
    tree_widget = SCMTreeWidget()
    FileBrowserClass = None
    subscribe_form = SubscribeForm()

    def __init__(self, commit, tree, path='', parent=None):
        self._commit = commit
        self._tree = tree
        self._path = path
        self._parent = parent

    @expose('jinja:allura:templates/repo/tree.html')
    @with_trailing_slash
    def index(self, **kw):
        c.tree_widget = self.tree_widget
        c.subscribe_form = self.subscribe_form
        tool_subscribed = M.Mailbox.subscribed()
        tarball_url = None
        if asbool(tg.config.get('scm.repos.tarball.enable', False)):
            cutout = len(b'tree' + self._path.encode('utf8'))
            if request.path.endswith('/') and not self._path.endswith('/'):
                cutout += 1
            tarball_url = h.urlquote('%starball' % unquote(request.path)[:-cutout])
        return dict(
            repo=c.app.repo,
            commit=self._commit,
            tree=self._tree,
            path=self._path,
            parent=self._parent,
            tool_subscribed=tool_subscribed,
            tarball_url=tarball_url)

    @expose()
    def _lookup(self, next, *rest):
        next = h.really_unicode(unquote(next))
        if not rest:
            # Might be a file rather than a dir
            filename = h.really_unicode(request.environ['PATH_INFO'].rsplit(str('/'))[-1])
            if filename:
                try:
                    obj = self._tree[filename]
                except KeyError:
                    raise exc.HTTPNotFound()
                if isinstance(obj, M.repository.Blob):
                    return self.FileBrowserClass(
                        self._commit,
                        self._tree,
                        filename), rest
        elif rest == ('index', ):
            rest = (request.environ['PATH_INFO'].rsplit(str('/'))[-1],)
        try:
            tree = self._tree[next]
        except KeyError:
            raise exc.HTTPNotFound
        return self.__class__(
            self._commit,
            tree,
            self._path + '/' + next,
            self), rest

    @expose('json:')
    @require_post()
    @validate(subscribe_form)
    def subscribe(self, subscribe=None, unsubscribe=None, **kw):
        if subscribe:
            M.Mailbox.subscribe()
        elif unsubscribe:
            M.Mailbox.unsubscribe()
        return {
            'status': 'ok',
            'subscribed': M.Mailbox.subscribed(),
        }


class FileBrowser(BaseController):

    def __init__(self, commit, tree, filename):
        self._commit = commit
        self._tree = tree
        self._filename = filename
        self._blob = self._tree.get_blob(filename)

    @expose('jinja:allura:templates/repo/file.html')
    def index(self, **kw):
        if kw.pop('format', 'html') == 'raw':
            return self.raw()
        elif 'diff' in kw:
            tg.decorators.override_template(
                self.index, 'jinja:allura:templates/repo/diff.html')
            return self.diff(kw['diff'], kw.pop('diformat', None), kw.pop('prev_file', None))
        elif 'barediff' in kw:
            tg.decorators.override_template(
                self.index, 'jinja:allura:templates/repo/barediff.html')
            return self.diff(kw['barediff'], kw.pop('diformat', None), kw.pop('prev_file', None))
        else:
            force_display = 'force' in kw
            stats = utils.generate_code_stats(self._blob)
            return dict(
                blob=self._blob,
                stats=stats,
                force_display=force_display
            )

    def raw(self, **kw):
        content_type = self._blob.content_type
        filename = self._blob.name
        response.headers['Content-Type'] = str('')
        response.content_type = str(content_type)
        if self._blob.content_encoding is not None:
            content_encoding = self._blob.content_encoding
            response.headers['Content-Encoding'] = str('')
            response.content_encoding = str(content_encoding)
        response.headers.add(
            str('Content-Disposition'),
            str('attachment;filename="%s"') % h.urlquote(filename))
        return iter(self._blob)

    def diff(self, prev_commit, fmt=None, prev_file=None, **kw):
        '''
        :param prev_commit: previous commit to compare against
        :param fmt: "sidebyside", or anything else for "unified"
        :param prev_file: previous filename, if different
        :return:
        '''
        try:
            path, filename = os.path.split(self._blob.path())
            a_ci = c.app.repo.commit(prev_commit)
            a = a_ci.get_path(prev_file or self._blob.path())
            apath = a.path()
        except Exception:
            # prev commit doesn't have the file
            a = M.repository.EmptyBlob()
            apath = ''
        b = self._blob

        if not self._blob.has_html_view:
            diff = "Cannot display: file marked as a binary type."
            return dict(a=a, b=b, diff=diff)

        la = list(a)
        lb = list(b)
        adesc = ('a' + h.really_unicode(apath)).encode('utf-8')
        bdesc = ('b' + h.really_unicode(b.path())).encode('utf-8')

        if not fmt:
            fmt = web_session.get('diformat', '')
        else:
            web_session['diformat'] = fmt
            web_session.save()
        if fmt == 'sidebyside':
            if max(a.size, b.size) > asint(tg.config.get('scm.view.max_syntax_highlight_bytes', 500000)):
                # have to check the original file size, not diff size, because difflib._mdiff inside HtmlSideBySideDiff
                # can take an extremely long time on large files (and its even a generator)
                diff = '<em>File too large for side-by-side view</em>'
            else:
                hd = HtmlSideBySideDiff()
                diff = hd.make_table(la, lb, adesc, bdesc)
        else:
            diff = str('').join(difflib.unified_diff(la, lb, adesc, bdesc))
        return dict(a=a, b=b, diff=diff)


def topo_sort(children, parents, dates, head_ids):
    to_visit = sorted(list(set(head_ids)), key=lambda x: dates[x])
    visited = set()
    while to_visit:
        next = to_visit.pop()
        if next in visited:
            continue
        visited.add(next)
        yield next
        for p in parents.get(next, []):
            for child in children[p]:
                if child not in visited:
                    break
            else:
                to_visit.append(p)

on_import()
