repo-commits: ported changeset code into pyramid views.

- refactored part of naming to use commit_id instead of revision
- renamed some parts to repo_commits instead of changeset without breaking backward compat
- small improvements and fixes for tests
This commit is contained in:
Marcin Kuzminski 2017-07-24 17:04:14 +02:00
parent 5b3187fdf9
commit 8efc4d92c5
41 changed files with 553 additions and 456 deletions

View file

@ -210,11 +210,12 @@ gist_alias_url =
## The list should be "," separated and on a single line.
##
## Most common views to enable:
# ChangesetController:changeset_patch
# ChangesetController:changeset_raw
# RepoFilesView.repo_files_diff
# RepoFilesView.repo_archivefile
# RepoFilesView.repo_file_raw
# RepoCommitsView:repo_commit_download
# RepoCommitsView:repo_commit_patch
# RepoCommitsView:repo_commit_raw
# RepoFilesView:repo_files_diff
# RepoFilesView:repo_archivefile
# RepoFilesView:repo_file_raw
# GistView:*
api_access_controllers_whitelist =

View file

@ -184,11 +184,12 @@ gist_alias_url =
## The list should be "," separated and on a single line.
##
## Most common views to enable:
# ChangesetController:changeset_patch
# ChangesetController:changeset_raw
# RepoFilesView.repo_files_diff
# RepoFilesView.repo_archivefile
# RepoFilesView.repo_file_raw
# RepoCommitsView:repo_commit_download
# RepoCommitsView:repo_commit_patch
# RepoCommitsView:repo_commit_raw
# RepoFilesView:repo_files_diff
# RepoFilesView:repo_archivefile
# RepoFilesView:repo_file_raw
# GistView:*
api_access_controllers_whitelist =

View file

@ -42,7 +42,7 @@ archive.
## Syntax is <ControllerClass>:<function_pattern>.
## The list should be "," separated and on a single line.
##
api_access_controllers_whitelist = ChangesetController:changeset_patch,ChangesetController:changeset_raw,ilesController:raw,FilesController:archivefile,
api_access_controllers_whitelist = RepoCommitsView:repo_commit_raw,RepoCommitsView:repo_commit_patch,RepoCommitsView:repo_commit_download
After this change, a |RCE| view can be accessed without login by adding a
GET parameter ``?auth_token=<auth_token>`` to a url. For example to

View file

@ -172,9 +172,9 @@ class HomeView(BaseAppView):
'text': entry['commit_id'],
'type': 'commit',
'obj': {'repo': entry['repository']},
'url': h.url('changeset_home',
'url': h.route_path('repo_commit',
repo_name=entry['repository'],
revision=entry['commit_id'])
commit_id=entry['commit_id'])
}
for entry in result['results']]

View file

@ -36,6 +36,8 @@ from rhodecode.model.meta import Session
fixture = Fixture()
whitelist_view = ['RepoCommitsView:repo_commit_raw']
def route_path(name, params=None, **kwargs):
import urllib
@ -474,11 +476,10 @@ class TestLoginController(object):
def test_access_whitelisted_page_via_auth_token(
self, test_name, auth_token, code, user_admin):
whitelist_entry = ['ChangesetController:changeset_raw']
whitelist = self._get_api_whitelist(whitelist_entry)
whitelist = self._get_api_whitelist(whitelist_view)
with mock.patch.dict('rhodecode.CONFIG', whitelist):
assert whitelist_entry == whitelist['api_access_controllers_whitelist']
assert whitelist_view == whitelist['api_access_controllers_whitelist']
if test_name == 'proper_auth_token':
auth_token = user_admin.api_key
@ -492,10 +493,9 @@ class TestLoginController(object):
status=code)
def test_access_page_via_extra_auth_token(self):
whitelist = self._get_api_whitelist(
['ChangesetController:changeset_raw'])
whitelist = self._get_api_whitelist(whitelist_view)
with mock.patch.dict('rhodecode.CONFIG', whitelist):
assert ['ChangesetController:changeset_raw'] == \
assert whitelist_view == \
whitelist['api_access_controllers_whitelist']
new_auth_token = AuthTokenModel().create(
@ -509,10 +509,9 @@ class TestLoginController(object):
status=200)
def test_access_page_via_expired_auth_token(self):
whitelist = self._get_api_whitelist(
['ChangesetController:changeset_raw'])
whitelist = self._get_api_whitelist(whitelist_view)
with mock.patch.dict('rhodecode.CONFIG', whitelist):
assert ['ChangesetController:changeset_raw'] == \
assert whitelist_view == \
whitelist['api_access_controllers_whitelist']
new_auth_token = AuthTokenModel().create(

View file

@ -33,10 +33,52 @@ def includeme(config):
pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True)
# repo commits
config.add_route(
name='repo_commit',
pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}', repo_route=True)
config.add_route(
name='repo_commit_children',
pattern='/{repo_name:.*?[^/]}/changeset_children/{commit_id}', repo_route=True)
config.add_route(
name='repo_commit_parents',
pattern='/{repo_name:.*?[^/]}/changeset_parents/{commit_id}', repo_route=True)
# still working url for backward compat.
config.add_route(
name='repo_commit_raw_deprecated',
pattern='/{repo_name:.*?[^/]}/raw-changeset/{commit_id}', repo_route=True)
config.add_route(
name='repo_commit_raw',
pattern='/{repo_name:.*?[^/]}/changeset-diff/{commit_id}', repo_route=True)
config.add_route(
name='repo_commit_patch',
pattern='/{repo_name:.*?[^/]}/changeset-patch/{commit_id}', repo_route=True)
config.add_route(
name='repo_commit_download',
pattern='/{repo_name:.*?[^/]}/changeset-download/{commit_id}', repo_route=True)
config.add_route(
name='repo_commit_data',
pattern='/{repo_name:.*?[^/]}/changeset-data/{commit_id}', repo_route=True)
config.add_route(
name='repo_commit_comment_create',
pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/create', repo_route=True)
config.add_route(
name='repo_commit_comment_preview',
pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/preview', repo_route=True)
config.add_route(
name='repo_commit_comment_delete',
pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/{comment_id}/delete', repo_route=True)
# repo files
config.add_route(
name='repo_archivefile',
@ -180,21 +222,6 @@ def includeme(config):
pattern='/{repo_name:.*?[^/]}/pull-request-data',
repo_route=True, repo_accepted_types=['hg', 'git'])
# commits aka changesets
# TODO(dan): handle default landing revision ?
config.add_route(
name='changeset_home',
pattern='/{repo_name:.*?[^/]}/changeset/{revision}',
repo_route=True)
config.add_route(
name='changeset_children',
pattern='/{repo_name:.*?[^/]}/changeset_children/{revision}',
repo_route=True)
config.add_route(
name='changeset_parents',
pattern='/{repo_name:.*?[^/]}/changeset_parents/{revision}',
repo_route=True)
# Settings
config.add_route(
name='edit_repo',

View file

@ -18,18 +18,33 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
from pylons.i18n import ungettext
import pytest
from rhodecode.tests import *
from rhodecode.tests import TestController
from rhodecode.model.db import (
ChangesetComment, Notification, UserNotification)
from rhodecode.model.meta import Session
from rhodecode.lib import helpers as h
def route_path(name, params=None, **kwargs):
import urllib
base_url = {
'repo_commit': '/{repo_name}/changeset/{commit_id}',
'repo_commit_comment_create': '/{repo_name}/changeset/{commit_id}/comment/create',
'repo_commit_comment_preview': '/{repo_name}/changeset/{commit_id}/comment/preview',
'repo_commit_comment_delete': '/{repo_name}/changeset/{commit_id}/comment/{comment_id}/delete',
}[name].format(**kwargs)
if params:
base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
return base_url
@pytest.mark.backends("git", "hg", "svn")
class TestCommitCommentsController(TestController):
class TestRepoCommitCommentsView(TestController):
@pytest.fixture(autouse=True)
def prepare(self, request, pylonsapp):
@ -62,12 +77,13 @@ class TestCommitCommentsController(TestController):
params = {'text': text, 'csrf_token': self.csrf_token,
'comment_type': comment_type}
self.app.post(
url(controller='changeset', action='comment',
repo_name=backend.repo_name, revision=commit_id), params=params)
route_path('repo_commit_comment_create',
repo_name=backend.repo_name, commit_id=commit_id),
params=params)
response = self.app.get(
url(controller='changeset', action='index',
repo_name=backend.repo_name, revision=commit_id))
route_path('repo_commit',
repo_name=backend.repo_name, commit_id=commit_id))
# test DB
assert ChangesetComment.query().count() == 1
@ -103,12 +119,13 @@ class TestCommitCommentsController(TestController):
'csrf_token': self.csrf_token}
self.app.post(
url(controller='changeset', action='comment',
repo_name=backend.repo_name, revision=commit_id), params=params)
route_path('repo_commit_comment_create',
repo_name=backend.repo_name, commit_id=commit_id),
params=params)
response = self.app.get(
url(controller='changeset', action='index',
repo_name=backend.repo_name, revision=commit_id))
route_path('repo_commit',
repo_name=backend.repo_name, commit_id=commit_id))
# test DB
assert ChangesetComment.query().count() == 1
@ -153,12 +170,13 @@ class TestCommitCommentsController(TestController):
params = {'text': text, 'csrf_token': self.csrf_token}
self.app.post(
url(controller='changeset', action='comment',
repo_name=backend.repo_name, revision=commit_id), params=params)
route_path('repo_commit_comment_create',
repo_name=backend.repo_name, commit_id=commit_id),
params=params)
response = self.app.get(
url(controller='changeset', action='index',
repo_name=backend.repo_name, revision=commit_id))
route_path('repo_commit',
repo_name=backend.repo_name, commit_id=commit_id))
# test DB
assert ChangesetComment.query().count() == 1
assert_comment_links(response, ChangesetComment.query().count(), 0)
@ -183,12 +201,14 @@ class TestCommitCommentsController(TestController):
'csrf_token': self.csrf_token}
self.app.post(
url(controller='changeset', action='comment',
repo_name=backend.repo_name, revision=commit_id), params=params)
route_path(
'repo_commit_comment_create',
repo_name=backend.repo_name, commit_id=commit_id),
params=params)
response = self.app.get(
url(controller='changeset', action='index',
repo_name=backend.repo_name, revision=commit_id))
route_path('repo_commit',
repo_name=backend.repo_name, commit_id=commit_id))
# test DB
assert ChangesetComment.query().count() == 1
@ -218,9 +238,9 @@ class TestCommitCommentsController(TestController):
params = {'text': text, 'csrf_token': self.csrf_token}
self.app.post(
url(
controller='changeset', action='comment',
repo_name=backend.repo_name, revision=commit_id),
route_path(
'repo_commit_comment_create',
repo_name=backend.repo_name, commit_id=commit_id),
params=params)
comments = ChangesetComment.query().all()
@ -228,16 +248,18 @@ class TestCommitCommentsController(TestController):
comment_id = comments[0].comment_id
self.app.post(
url(controller='changeset', action='delete_comment',
repo_name=backend.repo_name, comment_id=comment_id),
params={'_method': 'delete', 'csrf_token': self.csrf_token})
route_path('repo_commit_comment_delete',
repo_name=backend.repo_name,
commit_id=commit_id,
comment_id=comment_id),
params={'csrf_token': self.csrf_token})
comments = ChangesetComment.query().all()
assert len(comments) == 0
response = self.app.get(
url(controller='changeset', action='index',
repo_name=backend.repo_name, revision=commit_id))
route_path('repo_commit',
repo_name=backend.repo_name, commit_id=commit_id))
assert_comment_links(response, 0, 0)
@pytest.mark.parametrize('renderer, input, output', [
@ -251,36 +273,39 @@ class TestCommitCommentsController(TestController):
('markdown', '**bold**', '<strong>bold</strong>'),
], ids=['rst-plain', 'rst-header', 'rst-italics', 'rst-bold', 'md-plain',
'md-header', 'md-italics', 'md-bold', ])
def test_preview(self, renderer, input, output, backend):
def test_preview(self, renderer, input, output, backend, xhr_header):
self.log_user()
params = {
'renderer': renderer,
'text': input,
'csrf_token': self.csrf_token
}
environ = {
'HTTP_X_PARTIAL_XHR': 'true'
}
commit_id = '0' * 16 # fake this for tests
response = self.app.post(
url(controller='changeset',
action='preview_comment',
repo_name=backend.repo_name),
route_path('repo_commit_comment_preview',
repo_name=backend.repo_name, commit_id=commit_id,),
params=params,
extra_environ=environ)
extra_environ=xhr_header)
response.mustcontain(output)
def assert_comment_links(response, comments, inline_comments):
comments_text = ungettext("%d Commit comment",
"%d Commit comments", comments) % comments
if comments == 1:
comments_text = "%d Commit comment" % comments
else:
comments_text = "%d Commit comments" % comments
if inline_comments == 1:
inline_comments_text = "%d Inline Comment" % inline_comments
else:
inline_comments_text = "%d Inline Comments" % inline_comments
if comments:
response.mustcontain('<a href="#comments">%s</a>,' % comments_text)
else:
response.mustcontain(comments_text)
inline_comments_text = ungettext("%d Inline Comment", "%d Inline Comments",
inline_comments) % inline_comments
if inline_comments:
response.mustcontain(
'id="inline-comments-counter">%s</' % inline_comments_text)

View file

@ -21,40 +21,56 @@
import pytest
from rhodecode.lib.helpers import _shorten_commit_id
from rhodecode.tests import url
def route_path(name, params=None, **kwargs):
import urllib
base_url = {
'repo_commit': '/{repo_name}/changeset/{commit_id}',
'repo_commit_children': '/{repo_name}/changeset_children/{commit_id}',
'repo_commit_parents': '/{repo_name}/changeset_parents/{commit_id}',
'repo_commit_raw': '/{repo_name}/changeset-diff/{commit_id}',
'repo_commit_patch': '/{repo_name}/changeset-patch/{commit_id}',
'repo_commit_download': '/{repo_name}/changeset-download/{commit_id}',
'repo_commit_data': '/{repo_name}/changeset-data/{commit_id}',
'repo_compare': '/{repo_name}/compare/{source_ref_type}@{source_ref}...{target_ref_type}@{target_ref}',
}[name].format(**kwargs)
if params:
base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
return base_url
@pytest.mark.usefixtures("app")
class TestChangesetController(object):
class TestRepoCommitView(object):
def test_index(self, backend):
def test_show_commit(self, backend):
commit_id = self.commit_id[backend.alias]
response = self.app.get(url(
controller='changeset', action='index',
repo_name=backend.repo_name, revision=commit_id))
response = self.app.get(route_path(
'repo_commit', repo_name=backend.repo_name, commit_id=commit_id))
response.mustcontain('Added a symlink')
response.mustcontain(commit_id)
response.mustcontain('No newline at end of file')
def test_index_raw(self, backend):
def test_show_raw(self, backend):
commit_id = self.commit_id[backend.alias]
response = self.app.get(url(
controller='changeset', action='changeset_raw',
repo_name=backend.repo_name, revision=commit_id))
response = self.app.get(route_path(
'repo_commit_raw',
repo_name=backend.repo_name, commit_id=commit_id))
assert response.body == self.diffs[backend.alias]
def test_index_raw_patch(self, backend):
response = self.app.get(url(
controller='changeset', action='changeset_patch',
repo_name=backend.repo_name,
revision=self.commit_id[backend.alias]))
def test_show_raw_patch(self, backend):
response = self.app.get(route_path(
'repo_commit_patch', repo_name=backend.repo_name,
commit_id=self.commit_id[backend.alias]))
assert response.body == self.patches[backend.alias]
def test_index_changeset_download(self, backend):
response = self.app.get(url(
controller='changeset', action='changeset_download',
def test_commit_download(self, backend):
response = self.app.get(route_path(
'repo_commit_download',
repo_name=backend.repo_name,
revision=self.commit_id[backend.alias]))
commit_id=self.commit_id[backend.alias]))
assert response.body == self.diffs[backend.alias]
def test_single_commit_page_different_ops(self, backend):
@ -64,9 +80,9 @@ class TestChangesetController(object):
'svn': '337',
}
commit_id = commit_id[backend.alias]
response = self.app.get(url(
controller='changeset', action='index',
repo_name=backend.repo_name, revision=commit_id))
response = self.app.get(route_path(
'repo_commit',
repo_name=backend.repo_name, commit_id=commit_id))
response.mustcontain(_shorten_commit_id(commit_id))
response.mustcontain('21 files changed: 943 inserted, 288 deleted')
@ -98,9 +114,9 @@ class TestChangesetController(object):
}
commit_ids = commit_id_range[backend.alias]
commit_id = '%s...%s' % (commit_ids[0], commit_ids[1])
response = self.app.get(url(
controller='changeset', action='index',
repo_name=backend.repo_name, revision=commit_id))
response = self.app.get(route_path(
'repo_commit',
repo_name=backend.repo_name, commit_id=commit_id))
response.mustcontain(_shorten_commit_id(commit_ids[0]))
response.mustcontain(_shorten_commit_id(commit_ids[1]))
@ -137,8 +153,8 @@ class TestChangesetController(object):
'337'),
}
commit_ids = commit_id_range[backend.alias]
response = self.app.get(url(
controller='compare', action='compare',
response = self.app.get(route_path(
'repo_compare',
repo_name=backend.repo_name,
source_ref_type='rev', source_ref=commit_ids[0],
target_ref_type='rev', target_ref=commit_ids[1], ))
@ -188,9 +204,10 @@ class TestChangesetController(object):
def _check_changeset_range(
self, backend, commit_id_ranges, commit_id_range_result):
response = self.app.get(
url(controller='changeset', action='index',
repo_name=backend.repo_name,
revision=commit_id_ranges[backend.alias]))
route_path('repo_commit',
repo_name=backend.repo_name,
commit_id=commit_id_ranges[backend.alias]))
expected_result = commit_id_range_result[backend.alias]
response.mustcontain('{} commits'.format(len(expected_result)))
for commit_id in expected_result:

View file

@ -18,28 +18,24 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
"""
commit controller for RhodeCode showing changes between commits
"""
import logging
import collections
from collections import defaultdict
from webob.exc import HTTPForbidden, HTTPBadRequest, HTTPNotFound
from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound
from pyramid.view import view_config
from pyramid.renderers import render
from pyramid.response import Response
from pylons import tmpl_context as c, request, response
from pylons.i18n.translation import _
from pylons.controllers.util import redirect
from rhodecode.apps._base import RepoAppView
from rhodecode.lib import auth
from rhodecode.lib import diffs, codeblocks
from rhodecode.lib.auth import (
LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous)
from rhodecode.lib.base import BaseRepoController, render
LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, CSRFRequired)
from rhodecode.lib.compat import OrderedDict
from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
import rhodecode.lib.helpers as h
from rhodecode.lib.utils import jsonify
from rhodecode.lib.utils2 import safe_unicode, safe_int
from rhodecode.lib.vcs.backends.base import EmptyCommit
from rhodecode.lib.vcs.exceptions import (
@ -53,14 +49,14 @@ from rhodecode.model.meta import Session
log = logging.getLogger(__name__)
def _update_with_GET(params, GET):
def _update_with_GET(params, request):
for k in ['diff1', 'diff2', 'diff']:
params[k] += GET.getall(k)
params[k] += request.GET.getall(k)
def get_ignore_ws(fid, GET):
ig_ws_global = GET.get('ignorews')
ig_ws = filter(lambda k: k.startswith('WS'), GET.getall(fid))
def get_ignore_ws(fid, request):
ig_ws_global = request.GET.get('ignorews')
ig_ws = filter(lambda k: k.startswith('WS'), request.GET.getall(fid))
if ig_ws:
try:
return int(ig_ws[0].split(':')[-1])
@ -69,14 +65,15 @@ def get_ignore_ws(fid, GET):
return ig_ws_global
def _ignorews_url(GET, fileid=None):
def _ignorews_url(request, fileid=None):
_ = request.translate
fileid = str(fileid) if fileid else None
params = defaultdict(list)
_update_with_GET(params, GET)
params = collections.defaultdict(list)
_update_with_GET(params, request)
label = _('Show whitespace')
tooltiplbl = _('Show whitespace for all diffs')
ig_ws = get_ignore_ws(fileid, GET)
ln_ctx = get_line_ctx(fileid, GET)
ig_ws = get_ignore_ws(fileid, request)
ln_ctx = get_line_ctx(fileid, request)
if ig_ws is None:
params['ignorews'] += [1]
@ -91,16 +88,17 @@ def _ignorews_url(GET, fileid=None):
if fileid:
params['anchor'] = 'a_' + fileid
return h.link_to(label, h.url.current(**params), title=tooltiplbl, class_='tooltip')
return h.link_to(label, request.current_route_path(_query=params),
title=tooltiplbl, class_='tooltip')
def get_line_ctx(fid, GET):
ln_ctx_global = GET.get('context')
def get_line_ctx(fid, request):
ln_ctx_global = request.GET.get('context')
if fid:
ln_ctx = filter(lambda k: k.startswith('C'), GET.getall(fid))
ln_ctx = filter(lambda k: k.startswith('C'), request.GET.getall(fid))
else:
_ln_ctx = filter(lambda k: k.startswith('C'), GET)
ln_ctx = GET.get(_ln_ctx[0]) if _ln_ctx else ln_ctx_global
_ln_ctx = filter(lambda k: k.startswith('C'), request.GET)
ln_ctx = request.GET.get(_ln_ctx[0]) if _ln_ctx else ln_ctx_global
if ln_ctx:
ln_ctx = [ln_ctx]
@ -115,19 +113,20 @@ def get_line_ctx(fid, GET):
return 3
def _context_url(GET, fileid=None):
def _context_url(request, fileid=None):
"""
Generates a url for context lines.
:param fileid:
"""
_ = request.translate
fileid = str(fileid) if fileid else None
ig_ws = get_ignore_ws(fileid, GET)
ln_ctx = (get_line_ctx(fileid, GET) or 3) * 2
ig_ws = get_ignore_ws(fileid, request)
ln_ctx = (get_line_ctx(fileid, request) or 3) * 2
params = defaultdict(list)
_update_with_GET(params, GET)
params = collections.defaultdict(list)
_update_with_GET(params, request)
if ln_ctx > 0:
params['context'] += [ln_ctx]
@ -142,27 +141,36 @@ def _context_url(GET, fileid=None):
if fileid:
params['anchor'] = 'a_' + fileid
return h.link_to(lbl, h.url.current(**params), title=tooltiplbl, class_='tooltip')
return h.link_to(lbl, request.current_route_path(_query=params),
title=tooltiplbl, class_='tooltip')
class ChangesetController(BaseRepoController):
class RepoCommitsView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context(include_app_defaults=True)
def __before__(self):
super(ChangesetController, self).__before__()
# TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
c.repo_info = self.db_repo
c.rhodecode_repo = self.rhodecode_vcs_repo
def _index(self, commit_id_range, method):
self._register_global_c(c)
return c
def _commit(self, commit_id_range, method):
_ = self.request.translate
c = self.load_default_context()
c.ignorews_url = _ignorews_url
c.context_url = _context_url
c.fulldiff = fulldiff = request.GET.get('fulldiff')
c.fulldiff = self.request.GET.get('fulldiff')
# fetch global flags of ignore ws or context lines
context_lcl = get_line_ctx('', request.GET)
ign_whitespace_lcl = get_ignore_ws('', request.GET)
context_lcl = get_line_ctx('', self.request)
ign_whitespace_lcl = get_ignore_ws('', self.request)
# diff_limit will cut off the whole diff if the limit is applied
# otherwise it will just hide the big files from the front-end
diff_limit = self.cut_off_limit_diff
file_limit = self.cut_off_limit_file
diff_limit = c.visual.cut_off_limit_diff
file_limit = c.visual.cut_off_limit_file
# get ranges of commit ids if preset
commit_range = commit_id_range.split('...')[:2]
@ -172,12 +180,12 @@ class ChangesetController(BaseRepoController):
'message', 'parents']
if len(commit_range) == 2:
commits = c.rhodecode_repo.get_commits(
commits = self.rhodecode_vcs_repo.get_commits(
start_id=commit_range[0], end_id=commit_range[1],
pre_load=pre_load)
commits = list(commits)
else:
commits = [c.rhodecode_repo.get_commit(
commits = [self.rhodecode_vcs_repo.get_commit(
commit_id=commit_id_range, pre_load=pre_load)]
c.commit_ranges = commits
@ -210,13 +218,13 @@ class ChangesetController(BaseRepoController):
if len(c.commit_ranges) == 1:
commit = c.commit_ranges[0]
c.comments = CommentsModel().get_comments(
c.rhodecode_db_repo.repo_id,
self.db_repo.repo_id,
revision=commit.raw_id)
c.statuses.append(ChangesetStatusModel().get_status(
c.rhodecode_db_repo.repo_id, commit.raw_id))
self.db_repo.repo_id, commit.raw_id))
# comments from PR
statuses = ChangesetStatusModel().get_statuses(
c.rhodecode_db_repo.repo_id, commit.raw_id,
self.db_repo.repo_id, commit.raw_id,
with_revisions=True)
prs = set(st.pull_request for st in statuses
if st.pull_request is not None)
@ -228,6 +236,7 @@ class ChangesetController(BaseRepoController):
c.unresolved_comments = CommentsModel()\
.get_commit_unresolved_todos(commit.raw_id)
diff = None
# Iterate over ranges (default commit view is always one commit)
for commit in c.commit_ranges:
c.changes[commit.raw_id] = []
@ -235,12 +244,12 @@ class ChangesetController(BaseRepoController):
commit2 = commit
commit1 = commit.parents[0] if commit.parents else EmptyCommit()
_diff = c.rhodecode_repo.get_diff(
_diff = self.rhodecode_vcs_repo.get_diff(
commit1, commit2,
ignore_whitespace=ign_whitespace_lcl, context=context_lcl)
diff_processor = diffs.DiffProcessor(
_diff, format='newdiff', diff_limit=diff_limit,
file_limit=file_limit, show_full_diff=fulldiff)
file_limit=file_limit, show_full_diff=c.fulldiff)
commit_changes = OrderedDict()
if method == 'show':
@ -258,12 +267,12 @@ class ChangesetController(BaseRepoController):
return get_node
inline_comments = CommentsModel().get_inline_comments(
c.rhodecode_db_repo.repo_id, revision=commit.raw_id)
self.db_repo.repo_id, revision=commit.raw_id)
c.inline_cnt = CommentsModel().get_inline_comments_count(
inline_comments)
diffset = codeblocks.DiffSet(
repo_name=c.repo_name,
repo_name=self.db_repo_name,
source_node_getter=_node_getter(commit1),
target_node_getter=_node_getter(commit2),
comments=inline_comments)
@ -283,62 +292,101 @@ class ChangesetController(BaseRepoController):
c.commit = c.commit_ranges[0]
c.parent_tmpl = ''.join(
'# Parent %s\n' % x.raw_id for x in c.commit.parents)
if method == 'download':
response = Response(diff)
response.content_type = 'text/plain'
response.content_disposition = (
'attachment; filename=%s.diff' % commit_id_range[:12])
return diff
return response
elif method == 'patch':
response.content_type = 'text/plain'
c.diff = safe_unicode(diff)
return render('changeset/patch_changeset.mako')
elif method == 'raw':
patch = render(
'rhodecode:templates/changeset/patch_changeset.mako',
self._get_template_context(c), self.request)
response = Response(patch)
response.content_type = 'text/plain'
return diff
return response
elif method == 'raw':
response = Response(diff)
response.content_type = 'text/plain'
return response
elif method == 'show':
if len(c.commit_ranges) == 1:
return render('changeset/changeset.mako')
html = render(
'rhodecode:templates/changeset/changeset.mako',
self._get_template_context(c), self.request)
return Response(html)
else:
c.ancestor = None
c.target_repo = c.rhodecode_db_repo
return render('changeset/changeset_range.mako')
c.target_repo = self.db_repo
html = render(
'rhodecode:templates/changeset/changeset_range.mako',
self._get_template_context(c), self.request)
return Response(html)
raise HTTPBadRequest()
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
def index(self, revision, method='show'):
return self._index(revision, method=method)
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='repo_commit', request_method='GET',
renderer=None)
def repo_commit_show(self):
commit_id = self.request.matchdict['commit_id']
return self._commit(commit_id, method='show')
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
def changeset_raw(self, revision):
return self._index(revision, method='raw')
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='repo_commit_raw', request_method='GET',
renderer=None)
@view_config(
route_name='repo_commit_raw_deprecated', request_method='GET',
renderer=None)
def repo_commit_raw(self):
commit_id = self.request.matchdict['commit_id']
return self._commit(commit_id, method='raw')
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
def changeset_patch(self, revision):
return self._index(revision, method='patch')
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='repo_commit_patch', request_method='GET',
renderer=None)
def repo_commit_patch(self):
commit_id = self.request.matchdict['commit_id']
return self._commit(commit_id, method='patch')
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
def changeset_download(self, revision):
return self._index(revision, method='download')
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='repo_commit_download', request_method='GET',
renderer=None)
def repo_commit_download(self):
commit_id = self.request.matchdict['commit_id']
return self._commit(commit_id, method='download')
@LoginRequired()
@NotAnonymous()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
@auth.CSRFRequired()
@jsonify
def comment(self, repo_name, revision):
commit_id = revision
status = request.POST.get('changeset_status', None)
text = request.POST.get('text')
comment_type = request.POST.get('comment_type')
resolves_comment_id = request.POST.get('resolves_comment_id', None)
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@CSRFRequired()
@view_config(
route_name='repo_commit_comment_create', request_method='POST',
renderer='json_ext')
def repo_commit_comment_create(self):
_ = self.request.translate
commit_id = self.request.matchdict['commit_id']
c = self.load_default_context()
status = self.request.POST.get('changeset_status', None)
text = self.request.POST.get('text')
comment_type = self.request.POST.get('comment_type')
resolves_comment_id = self.request.POST.get('resolves_comment_id', None)
if status:
text = text or (_('Status change %(transition_icon)s %(status)s')
@ -346,7 +394,7 @@ class ChangesetController(BaseRepoController):
'status': ChangesetStatus.get_status_lbl(status)})
multi_commit_ids = []
for _commit_id in request.POST.get('commit_ids', '').split(','):
for _commit_id in self.request.POST.get('commit_ids', '').split(','):
if _commit_id not in ['', None, EmptyCommit.raw_id]:
if _commit_id not in multi_commit_ids:
multi_commit_ids.append(_commit_id)
@ -355,13 +403,13 @@ class ChangesetController(BaseRepoController):
comment = None
for current_id in filter(None, commit_ids):
c.co = comment = CommentsModel().create(
comment = CommentsModel().create(
text=text,
repo=c.rhodecode_db_repo.repo_id,
user=c.rhodecode_user.user_id,
repo=self.db_repo.repo_id,
user=self._rhodecode_db_user.user_id,
commit_id=current_id,
f_path=request.POST.get('f_path'),
line_no=request.POST.get('line'),
f_path=self.request.POST.get('f_path'),
line_no=self.request.POST.get('line'),
status_change=(ChangesetStatus.get_status_lbl(status)
if status else None),
status_change_type=status,
@ -377,9 +425,9 @@ class ChangesetController(BaseRepoController):
try:
ChangesetStatusModel().set_status(
c.rhodecode_db_repo.repo_id,
self.db_repo.repo_id,
status,
c.rhodecode_user.user_id,
self._rhodecode_db_user.user_id,
comment,
revision=current_id,
dont_allow_on_closed_pull_request=True
@ -389,103 +437,121 @@ class ChangesetController(BaseRepoController):
'a closed pull request is not allowed')
log.exception(msg)
h.flash(msg, category='warning')
return redirect(h.url(
'changeset_home', repo_name=repo_name,
revision=current_id))
raise HTTPFound(h.route_path(
'repo_commit', repo_name=self.db_repo_name,
commit_id=current_id))
# finalize, commit and redirect
Session().commit()
data = {
'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
'target_id': h.safeid(h.safe_unicode(
self.request.POST.get('f_path'))),
}
if comment:
c.co = comment
rendered_comment = render(
'rhodecode:templates/changeset/changeset_comment_block.mako',
self._get_template_context(c), self.request)
data.update(comment.get_dict())
data.update({'rendered_text':
render('changeset/changeset_comment_block.mako')})
data.update({'rendered_text': rendered_comment})
return data
@LoginRequired()
@NotAnonymous()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
@auth.CSRFRequired()
def preview_comment(self):
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@CSRFRequired()
@view_config(
route_name='repo_commit_comment_preview', request_method='POST',
renderer='string', xhr=True)
def repo_commit_comment_preview(self):
# Technically a CSRF token is not needed as no state changes with this
# call. However, as this is a POST is better to have it, so automated
# tools don't flag it as potential CSRF.
# Post is required because the payload could be bigger than the maximum
# allowed by GET.
if not request.environ.get('HTTP_X_PARTIAL_XHR'):
raise HTTPBadRequest()
text = request.POST.get('text')
renderer = request.POST.get('renderer') or 'rst'
text = self.request.POST.get('text')
renderer = self.request.POST.get('renderer') or 'rst'
if text:
return h.render(text, renderer=renderer, mentions=True)
return ''
@LoginRequired()
@NotAnonymous()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
@auth.CSRFRequired()
@jsonify
def delete_comment(self, repo_name, comment_id):
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@CSRFRequired()
@view_config(
route_name='repo_commit_comment_delete', request_method='POST',
renderer='json_ext')
def repo_commit_comment_delete(self):
commit_id = self.request.matchdict['commit_id']
comment_id = self.request.matchdict['comment_id']
comment = ChangesetComment.get_or_404(safe_int(comment_id))
if not comment:
log.debug('Comment with id:%s not found, skipping', comment_id)
# comment already deleted in another call probably
return True
is_repo_admin = h.HasRepoPermissionAny('repository.admin')(c.repo_name)
is_repo_admin = h.HasRepoPermissionAny('repository.admin')(self.db_repo_name)
super_admin = h.HasPermissionAny('hg.admin')()
comment_owner = (comment.author.user_id == c.rhodecode_user.user_id)
is_repo_comment = comment.repo.repo_name == c.repo_name
comment_owner = (comment.author.user_id == self._rhodecode_db_user.user_id)
is_repo_comment = comment.repo.repo_name == self.db_repo_name
comment_repo_admin = is_repo_admin and is_repo_comment
if super_admin or comment_owner or comment_repo_admin:
CommentsModel().delete(comment=comment, user=c.rhodecode_user)
CommentsModel().delete(comment=comment, user=self._rhodecode_db_user)
Session().commit()
return True
else:
log.warning('No permissions for user %s to delete comment_id: %s',
c.rhodecode_user, comment_id)
self._rhodecode_db_user, comment_id)
raise HTTPNotFound()
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
@jsonify
def changeset_info(self, repo_name, revision):
if request.is_xhr:
try:
return c.rhodecode_repo.get_commit(commit_id=revision)
except CommitDoesNotExistError as e:
return EmptyCommit(message=str(e))
else:
raise HTTPBadRequest()
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='repo_commit_data', request_method='GET',
renderer='json_ext', xhr=True)
def repo_commit_data(self):
commit_id = self.request.matchdict['commit_id']
self.load_default_context()
try:
return self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
except CommitDoesNotExistError as e:
return EmptyCommit(message=str(e))
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
@jsonify
def changeset_children(self, repo_name, revision):
if request.is_xhr:
commit = c.rhodecode_repo.get_commit(commit_id=revision)
result = {"results": commit.children}
return result
else:
raise HTTPBadRequest()
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='repo_commit_children', request_method='GET',
renderer='json_ext', xhr=True)
def repo_commit_children(self):
commit_id = self.request.matchdict['commit_id']
self.load_default_context()
commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
result = {"results": commit.children}
return result
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
@jsonify
def changeset_parents(self, repo_name, revision):
if request.is_xhr:
commit = c.rhodecode_repo.get_commit(commit_id=revision)
result = {"results": commit.parents}
return result
else:
raise HTTPBadRequest()
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='repo_commit_parents', request_method='GET',
renderer='json_ext')
def repo_commit_parents(self):
commit_id = self.request.matchdict['commit_id']
self.load_default_context()
commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
result = {"results": commit.parents}
return result

View file

@ -139,8 +139,8 @@ class RepoFeedView(RepoAppView):
author_name=commit.author,
description=self._get_description(commit),
link=h.route_url(
'changeset_home', repo_name=self.db_repo_name,
revision=commit.raw_id),
'repo_commit', repo_name=self.db_repo_name,
commit_id=commit.raw_id),
pubdate=date,)
return feed.mime_type, feed.writeString('utf-8')
@ -185,8 +185,8 @@ class RepoFeedView(RepoAppView):
author_name=commit.author,
description=self._get_description(commit),
link=h.route_url(
'changeset_home', repo_name=self.db_repo_name,
revision=commit.raw_id),
'repo_commit', repo_name=self.db_repo_name,
commit_id=commit.raw_id),
pubdate=date,)
return feed.mime_type, feed.writeString('utf-8')

View file

@ -1043,8 +1043,8 @@ class RepoFilesView(RepoAppView):
log.exception('Error during commit operation')
h.flash(_('Error occurred during commit'), category='error')
raise HTTPFound(
h.route_path('changeset_home', repo_name=self.db_repo_name,
revision='tip'))
h.route_path('repo_commit', repo_name=self.db_repo_name,
commit_id='tip'))
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
@ -1133,8 +1133,8 @@ class RepoFilesView(RepoAppView):
if content == old_content and filename == org_filename:
h.flash(_('No changes'), category='warning')
raise HTTPFound(
h.route_path('changeset_home', repo_name=self.db_repo_name,
revision='tip'))
h.route_path('repo_commit', repo_name=self.db_repo_name,
commit_id='tip'))
try:
mapping = {
org_f_path: {
@ -1161,8 +1161,8 @@ class RepoFilesView(RepoAppView):
log.exception('Error occurred during commit')
h.flash(_('Error occurred during commit'), category='error')
raise HTTPFound(
h.route_path('changeset_home', repo_name=self.db_repo_name,
revision='tip'))
h.route_path('repo_commit', repo_name=self.db_repo_name,
commit_id='tip'))
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
@ -1222,7 +1222,7 @@ class RepoFilesView(RepoAppView):
content = content.file
default_redirect_url = h.route_path(
'changeset_home', repo_name=self.db_repo_name, revision='tip')
'repo_commit', repo_name=self.db_repo_name, commit_id='tip')
# If there's no commit, redirect to repo summary
if type(c.commit) is EmptyCommit:

View file

@ -429,19 +429,6 @@ def make_map(config):
controller='admin/repos', action='repo_check',
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}',
controller='changeset', revision='tip',
conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}',
controller='changeset', revision='tip', action='changeset_children',
conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}',
controller='changeset', revision='tip', action='changeset_parents',
conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
# repo edit options
rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
controller='admin/repos', action='edit_fields',
@ -515,54 +502,6 @@ def make_map(config):
conditions={'method': ['GET', 'POST'], 'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
# still working url for backward compat.
rmap.connect('raw_changeset_home_depraced',
'/{repo_name}/raw-changeset/{revision}',
controller='changeset', action='changeset_raw',
revision='tip', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
# new URLs
rmap.connect('changeset_raw_home',
'/{repo_name}/changeset-diff/{revision}',
controller='changeset', action='changeset_raw',
revision='tip', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changeset_patch_home',
'/{repo_name}/changeset-patch/{revision}',
controller='changeset', action='changeset_patch',
revision='tip', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changeset_download_home',
'/{repo_name}/changeset-download/{revision}',
controller='changeset', action='changeset_download',
revision='tip', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changeset_comment',
'/{repo_name}/changeset/{revision}/comment', jsroute=True,
controller='changeset', revision='tip', action='comment',
conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changeset_comment_preview',
'/{repo_name}/changeset/comment/preview', jsroute=True,
controller='changeset', action='preview_comment',
conditions={'function': check_repo, 'method': ['POST']},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changeset_comment_delete',
'/{repo_name}/changeset/comment/{comment_id}/delete',
controller='changeset', action='delete_comment',
conditions={'function': check_repo, 'method': ['DELETE']},
requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('changeset_info', '/{repo_name}/changeset_info/{revision}',
controller='changeset', action='changeset_info',
requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('compare_home',
'/{repo_name}/compare',
controller='compare', action='index',

View file

@ -20,7 +20,6 @@
import logging
from pylons import url
from pylons.i18n.translation import _
from webhelpers.html.builder import literal
from webhelpers.html.tags import link_to
@ -201,6 +200,7 @@ class ActionParser(object):
return literal(tmpl % (ico, self.action))
def get_cs_links(self):
from rhodecode.lib import helpers as h
if self.is_deleted():
return self.action_params
@ -223,8 +223,9 @@ class ActionParser(object):
_('Show all combined commits %s->%s') % (
commit_ids[0][:12], commit_ids[-1][:12]
),
url('changeset_home', repo_name=repo_name,
revision=commit_id_range), _('compare view')
h.route_path(
'repo_commit', repo_name=repo_name,
commit_id=commit_id_range), _('compare view')
)
)
@ -275,6 +276,7 @@ class ActionParser(object):
def lnk(self, commit_or_id, repo_name):
from rhodecode.lib.helpers import tooltip
from rhodecode.lib import helpers as h
if isinstance(commit_or_id, (BaseCommit, AttributeDict)):
lazy_cs = True
@ -292,8 +294,8 @@ class ActionParser(object):
else:
lbl = '%s' % (commit_or_id.short_id[:8])
_url = url('changeset_home', repo_name=repo_name,
revision=commit_or_id.raw_id)
_url = h.route_path('repo_commit', repo_name=repo_name,
commit_id=commit_or_id.raw_id)
title = tooltip(commit_or_id.message)
else:
# commit cannot be found/striped/removed etc.

View file

@ -754,7 +754,7 @@ class PermissionCalculator(object):
}
def allowed_auth_token_access(controller_name, whitelist=None, auth_token=None):
def allowed_auth_token_access(view_name, whitelist=None, auth_token=None):
"""
Check if given controller_name is in whitelist of auth token access
"""
@ -767,16 +767,16 @@ def allowed_auth_token_access(controller_name, whitelist=None, auth_token=None):
auth_token_access_valid = False
for entry in whitelist:
if fnmatch.fnmatch(controller_name, entry):
if fnmatch.fnmatch(view_name, entry):
auth_token_access_valid = True
break
if auth_token_access_valid:
log.debug('controller:%s matches entry in whitelist'
% (controller_name,))
log.debug('view: `%s` matches entry in whitelist: %s'
% (view_name, whitelist))
else:
msg = ('controller: %s does *NOT* match any entry in whitelist'
% (controller_name,))
msg = ('view: `%s` does *NOT* match any entry in whitelist: %s'
% (view_name, whitelist))
if auth_token:
# if we use auth token key and don't have access it's a warning
log.warning(msg)

View file

@ -1575,7 +1575,7 @@ def urlify_commits(text_, repository):
:param text_:
:param repository: repo name to build the URL with
"""
from pylons import url # doh, we need to re-import url to mock it later
URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
def url_func(match_obj):
@ -1590,8 +1590,8 @@ def urlify_commits(text_, repository):
return tmpl % {
'pref': pref,
'cls': 'revision-link',
'url': url('changeset_home', repo_name=repository,
revision=commit_id, qualified=True),
'url': route_url('repo_commit', repo_name=repository,
commit_id=commit_id),
'commit_id': commit_id,
'suf': suf
}

View file

@ -15,11 +15,6 @@ function registerRCRoutes() {
pyroutes.register('new_repo', '/_admin/create_repository', []);
pyroutes.register('edit_user', '/_admin/users/%(user_id)s/edit', ['user_id']);
pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']);
pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']);
pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']);
pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
pyroutes.register('changeset_info', '/%(repo_name)s/changeset_info/%(revision)s', ['repo_name', 'revision']);
pyroutes.register('compare_url', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']);
pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']);
pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']);
@ -111,6 +106,16 @@ function registerRCRoutes() {
pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']);
pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']);
pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']);
pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']);
pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']);
pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']);
pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']);
pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']);
pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']);
pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']);
pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']);
pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']);
@ -146,9 +151,6 @@ function registerRCRoutes() {
pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
pyroutes.register('changeset_children', '/%(repo_name)s/changeset_children/%(revision)s', ['repo_name', 'revision']);
pyroutes.register('changeset_parents', '/%(repo_name)s/changeset_parents/%(revision)s', ['repo_name', 'revision']);
pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);

View file

@ -103,8 +103,9 @@ var bindToggleButtons = function() {
this.submitButton = $(this.submitForm).find('input[type="submit"]');
this.submitButtonText = this.submitButton.val();
this.previewUrl = pyroutes.url('changeset_comment_preview',
{'repo_name': templateContext.repo_name});
this.previewUrl = pyroutes.url('repo_commit_comment_preview',
{'repo_name': templateContext.repo_name,
'commit_id': templateContext.commit_data.commit_id});
if (resolvesCommentId){
this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
@ -129,12 +130,12 @@ var bindToggleButtons = function() {
// based on commitId, or pullRequestId decide where do we submit
// out data
if (this.commitId){
this.submitUrl = pyroutes.url('changeset_comment',
this.submitUrl = pyroutes.url('repo_commit_comment_create',
{'repo_name': templateContext.repo_name,
'revision': this.commitId});
this.selfUrl = pyroutes.url('changeset_home',
'commit_id': this.commitId});
this.selfUrl = pyroutes.url('repo_commit',
{'repo_name': templateContext.repo_name,
'revision': this.commitId});
'commit_id': this.commitId});
} else if (this.pullRequestId) {
this.submitUrl = pyroutes.url('pullrequest_comment',

View file

@ -5,7 +5,7 @@
(_('Owner'), lambda:base.gravatar_with_user(c.repo_info.user.email), '', ''),
(_('Created on'), h.format_date(c.repo_info.created_on), '', ''),
(_('Updated on'), h.format_date(c.repo_info.updated_on), '', ''),
(_('Cached Commit id'), lambda: h.link_to(c.repo_info.changeset_cache.get('short_id'), h.url('changeset_home',repo_name=c.repo_name,revision=c.repo_info.changeset_cache.get('raw_id'))), '', ''),
(_('Cached Commit id'), lambda: h.link_to(c.repo_info.changeset_cache.get('short_id'), h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.repo_info.changeset_cache.get('raw_id'))), '', ''),
]
%>

View file

@ -161,9 +161,9 @@
if (selectedCheckboxes.length>0){
var revEnd = selectedCheckboxes[0].name;
var revStart = selectedCheckboxes[selectedCheckboxes.length-1].name;
var url = pyroutes.url('changeset_home',
var url = pyroutes.url('repo_commit',
{'repo_name': '${c.repo_name}',
'revision': revStart+'...'+revEnd});
'commit_id': revStart+'...'+revEnd});
var link = (revStart == revEnd)
? _gettext('Show selected commit __S')

View file

@ -24,11 +24,11 @@
<div class="changeset-status-ico">
%if c.statuses.get(commit.raw_id)[2]:
<a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.route_path('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}">
<div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
<div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
</a>
%else:
<a class="tooltip" title="${_('Commit status: %s') % h.commit_status_lbl(c.statuses.get(commit.raw_id)[0])}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
<div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
<a class="tooltip" title="${_('Commit status: {}').format(h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]))}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id,_anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
<div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
</a>
%endif
</div>
@ -38,7 +38,7 @@
</td>
<td class="td-comments comments-col">
%if c.comments.get(commit.raw_id):
<a title="${_('Commit has comments')}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
<a title="${_('Commit has comments')}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id,_anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
<i class="icon-comment"></i> ${len(c.comments[commit.raw_id])}
</a>
%endif
@ -46,7 +46,7 @@
<td class="td-hash">
<code>
<a href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id)}">
<a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id)}">
<span class="${'commit_hash obsolete' if getattr(commit, 'obsolete', None) else 'commit_hash'}">${h.show_id(commit)}</span>
</a>
<i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${commit.raw_id}" title="${_('Copy the full commit id')}"></i>

View file

@ -15,7 +15,7 @@
<td class="td-message">
<div class="log-container">
<div class="message_history" title="${h.tooltip(cs.message)}">
<a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}">
<a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id)}">
${h.shorter(cs.message, 75)}
</a>
</div>
@ -23,7 +23,7 @@
</td>
<td class="td-hash">
<code>
<a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}">
<a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id)}">
<span>${h.show_id(cs)}</span>
</a>
</code>

View file

@ -21,7 +21,7 @@
<%def name="main()">
<script>
// TODO: marcink switch this to pyroutes
AJAX_COMMENT_DELETE_URL = "${h.url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
AJAX_COMMENT_DELETE_URL = "${h.route_path('repo_commit_comment_delete',repo_name=c.repo_name,commit_id=c.commit.raw_id,comment_id='__COMMENT_ID__')}";
templateContext.commit_data.commit_id = "${c.commit.raw_id}";
</script>
<div class="box">
@ -137,21 +137,21 @@
</div>
<div class="right-content">
<div class="diff-actions">
<a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision=c.commit.raw_id)}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
<a href="${h.route_path('repo_commit_raw',repo_name=c.repo_name,commit_id=c.commit.raw_id)}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
${_('Raw Diff')}
</a>
|
<a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision=c.commit.raw_id)}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
<a href="${h.route_path('repo_commit_patch',repo_name=c.repo_name,commit_id=c.commit.raw_id)}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
${_('Patch Diff')}
</a>
|
<a href="${h.url('changeset_download_home',repo_name=c.repo_name,revision=c.commit.raw_id,diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
<a href="${h.route_path('repo_commit_download',repo_name=c.repo_name,commit_id=c.commit.raw_id,_query=dict(diff='download'))}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
${_('Download Diff')}
</a>
|
${c.ignorews_url(request.GET)}
${c.ignorews_url(request)}
|
${c.context_url(request.GET)}
${c.context_url(request)}
</div>
</div>
</div>
@ -221,7 +221,7 @@
${comment.generate_comments(c.comments)}
## main comment form and it status
${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision=c.commit.raw_id),
${comment.comments(h.route_path('repo_commit_comment_create', repo_name=c.repo_name, commit_id=c.commit.raw_id),
h.commit_status(c.rhodecode_db_repo, c.commit.raw_id))}
</div>
@ -264,14 +264,14 @@
// >1 links show them to user to choose
if(!$('#child_link').hasClass('disabled')){
$.ajax({
url: '${h.url('changeset_children',repo_name=c.repo_name, revision=c.commit.raw_id)}',
url: '${h.route_path('repo_commit_children',repo_name=c.repo_name, commit_id=c.commit.raw_id)}',
success: function(data) {
if(data.results.length === 0){
$('#child_link').html("${_('No Child Commits')}").addClass('disabled');
}
if(data.results.length === 1){
var commit = data.results[0];
window.location = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': commit.raw_id});
window.location = pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': commit.raw_id});
}
else if(data.results.length === 2){
$('#child_link').addClass('disabled');
@ -280,12 +280,12 @@
_html +='<a title="__title__" href="__url__">__rev__</a> '
.replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
.replace('__title__', data.results[0].message)
.replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[0].raw_id}));
.replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[0].raw_id}));
_html +=' | ';
_html +='<a title="__title__" href="__url__">__rev__</a> '
.replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
.replace('__title__', data.results[1].message)
.replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[1].raw_id}));
.replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[1].raw_id}));
$('#child_link').html(_html);
}
}
@ -300,14 +300,14 @@
// >1 links show them to user to choose
if(!$('#parent_link').hasClass('disabled')){
$.ajax({
url: '${h.url("changeset_parents",repo_name=c.repo_name, revision=c.commit.raw_id)}',
url: '${h.route_path("repo_commit_parents",repo_name=c.repo_name, commit_id=c.commit.raw_id)}',
success: function(data) {
if(data.results.length === 0){
$('#parent_link').html('${_('No Parent Commits')}').addClass('disabled');
}
if(data.results.length === 1){
var commit = data.results[0];
window.location = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': commit.raw_id});
window.location = pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': commit.raw_id});
}
else if(data.results.length === 2){
$('#parent_link').addClass('disabled');
@ -316,12 +316,12 @@
_html +='<a title="__title__" href="__url__">Parent __rev__</a>'
.replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
.replace('__title__', data.results[0].message)
.replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[0].raw_id}));
.replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[0].raw_id}));
_html +=' | ';
_html +='<a title="__title__" href="__url__">Parent __rev__</a>'
.replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
.replace('__title__', data.results[1].message)
.replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[1].raw_id}));
.replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[1].raw_id}));
$('#parent_link').html(_html);
}
}

View file

@ -100,7 +100,7 @@
% endif
% if inline:
<div class="pr-version-inline">
<a href="${h.url.current(version=comment.pull_request_version_id, anchor='comment-{}'.format(comment.comment_id))}">
<a href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}">
% if outdated_at_ver:
<code class="pr-version-num" title="${_('Outdated comment from pull request version {0}').format(pr_index_ver)}">
outdated ${'v{}'.format(pr_index_ver)} |

View file

@ -70,15 +70,15 @@
</div>
<div class="right-content">
<div class="diff-actions">
<a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
<a href="${h.route_path('repo_commit_raw',repo_name=c.repo_name,commit_id='?')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
${_('Raw Diff')}
</a>
|
<a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
<a href="${h.route_path('repo_commit_patch',repo_name=c.repo_name,commit_id='?')}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
${_('Patch Diff')}
</a>
|
<a href="${h.url('changeset_download_home',repo_name=c.repo_name,revision='?',diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
<a href="${h.route_path('repo_commit_download',repo_name=c.repo_name,commit_id='?',_query=dict(diff='download'))}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
${_('Download Diff')}
</a>
</div>

View file

@ -121,7 +121,7 @@ collapse_all = len(diffset.files) > collapse_when_files_over
%endif
<h2 class="clearinner">
%if commit:
<a class="tooltip revision" title="${h.tooltip(commit.message)}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id)}">${'r%s:%s' % (commit.revision,h.short_id(commit.raw_id))}</a> -
<a class="tooltip revision" title="${h.tooltip(commit.message)}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id)}">${'r%s:%s' % (commit.revision,h.short_id(commit.raw_id))}</a> -
${h.age_component(commit.date)} -
%endif
%if diffset.limited_diff:
@ -459,10 +459,10 @@ from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
## TODO: dan: refactor ignorews_url and context_url into the diff renderer same as diffmode=unified/sideside. Also use ajax to load more context (by clicking hunks)
%if hasattr(c, 'ignorews_url'):
${c.ignorews_url(request.GET, h.FID('', filediff.patch['filename']))}
${c.ignorews_url(request, h.FID('', filediff.patch['filename']))}
%endif
%if hasattr(c, 'context_url'):
${c.context_url(request.GET, h.FID('', filediff.patch['filename']))}
${c.context_url(request, h.FID('', filediff.patch['filename']))}
%endif
%if use_comments:

View file

@ -31,7 +31,7 @@
data-revision="${annotation.revision}"
onclick="$('[data-revision=${annotation.revision}]').toggleClass('cb-line-fresh')"
style="background: ${bgcolor}">
<a class="cb-annotate" href="${h.url('changeset_home',repo_name=c.repo_name,revision=annotation.raw_id)}">
<a class="cb-annotate" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=annotation.raw_id)}">
r${annotation.revision}
</a>
</td>

View file

@ -3,7 +3,7 @@
%if c.ancestor:
<div class="ancestor">${_('Common Ancestor Commit')}:
<a href="${h.url('changeset_home', repo_name=c.repo_name, revision=c.ancestor)}">
<a href="${h.route_path('repo_commit', repo_name=c.repo_name, commit_id=c.ancestor)}">
${h.short_id(c.ancestor)}
</a>. ${_('Compare was calculated based on this shared commit.')}
<input id="common_ancestor" type="hidden" name="common_ancestor" value="${c.ancestor}">
@ -34,9 +34,7 @@
</td>
<td class="td-hash">
<code>
<a href="${h.url('changeset_home',
repo_name=c.target_repo.repo_name,
revision=commit.raw_id)}">
<a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
r${commit.revision}:${h.short_id(commit.raw_id)}
</a>
${h.hidden('revisions',commit.raw_id)}

View file

@ -137,15 +137,15 @@
</div>
<div class="right-content">
<div class="diff-actions">
<a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
<a href="${h.route_path('repo_commit_raw',repo_name=c.repo_name,commit_id='?')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
${_('Raw Diff')}
</a>
|
<a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
<a href="${h.route_path('repo_commit_patch',repo_name=c.repo_name,commit_id='?')}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
${_('Patch Diff')}
</a>
|
<a href="${h.url('changeset_download_home',repo_name=c.repo_name,revision='?',diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
<a href="${h.route_path('repo_commit_download',repo_name=c.repo_name,commit_id='?',_query=dict(diff='download'))}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
${_('Download Diff')}
</a>
</div>
@ -170,7 +170,7 @@
return form_inputs
%>
<div>
${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision='0'*16), None, is_compare=True, form_extras=revs(c.commit_ranges))}
${comment.comments(h.route_path('repo_commit_comment_create', repo_name=c.repo_name, commit_id='0'*16), None, is_compare=True, form_extras=revs(c.commit_ranges))}
</div>
</div>
</div>

View file

@ -83,7 +83,7 @@
<%def name="revision(name,rev,tip,author,last_msg)">
<div>
%if rev >= 0:
<code><a title="${h.tooltip('%s:\n\n%s' % (author,last_msg))}" class="tooltip" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a></code>
<code><a title="${h.tooltip('%s:\n\n%s' % (author,last_msg))}" class="tooltip" href="${h.route_path('repo_commit',repo_name=name,commit_id=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a></code>
%else:
${_('No commits yet')}
%endif

View file

@ -840,7 +840,8 @@ $(document).ready(function() {
$('#edit-container').hide();
$('#preview-container').show();
var url = pyroutes.url('changeset_comment_preview', {'repo_name': 'rhodecode-momentum'});
var url = pyroutes.url('repo_commit_comment_preview',
{'repo_name': 'rhodecode-momentum', 'commit_id': '000000'});
ajaxPOST(url, post_data, function(o) {
previewbox.html(o);

View file

@ -17,7 +17,7 @@ ${_('%(user)s commited on %(date)s UTC') % {
tag: ${tag} <br/>
% endfor
commit: <a href="${h.url('changeset_home', repo_name=c.rhodecode_db_repo.repo_name, revision=commit.raw_id, qualified=True)}">${h.show_id(commit)}</a>
commit: <a href="${h.route_url('repo_commit', repo_name=c.rhodecode_db_repo.repo_name, commit_id=commit.raw_id)}">${h.show_id(commit)}</a>
<pre>
${h.urlify_commit_message(commit.message)}

View file

@ -23,7 +23,7 @@
<div class="right-content">
<div class="tags">
<code>
<a href="${h.url('changeset_home',repo_name=c.repo_name,revision=c.commit.raw_id)}">${h.show_id(c.commit)}</a>
<a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">${h.show_id(c.commit)}</a>
</code>
${file_base.refs(c.commit)}

View file

@ -217,7 +217,9 @@
var _renderer = possible_renderer || DEFAULT_RENDERER;
var post_data = {'text': _text, 'renderer': _renderer, 'csrf_token': CSRF_TOKEN};
$('#editor_preview').html(_gettext('Loading ...'));
var url = pyroutes.url('changeset_comment_preview', {'repo_name': '${c.repo_name}'});
var url = pyroutes.url('repo_commit_comment_preview',
{'repo_name': '${c.repo_name}',
'commit_id': '${c.commit.raw_id}'});
ajaxPOST(url, post_data, function(o){
$('#editor_preview').html(o);

View file

@ -21,7 +21,7 @@
</div>
<div class="right-content">
<div class="tags tags-main">
<code><a href="${h.url('changeset_home',repo_name=c.repo_name,revision=c.commit.raw_id)}">${h.show_id(c.commit)}</a></code>
<code><a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">${h.show_id(c.commit)}</a></code>
${file_base.refs(c.commit)}
</div>
</div>
@ -33,7 +33,7 @@
</div>
<div class="right-content">
<div class="tags">
<code><a href="${h.url('changeset_home',repo_name=c.repo_name,revision=c.file_last_commit.raw_id)}">${h.show_id(c.file_last_commit)}</a></code>
<code><a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.file_last_commit.raw_id)}">${h.show_id(c.file_last_commit)}</a></code>
${file_base.refs(c.file_last_commit)}
</div>

View file

@ -47,7 +47,7 @@
<div class="code-header">
<div class="stats">
<i class="icon-file"></i>
<span class="item">${h.link_to("r%s:%s" % (c.file.commit.idx,h.short_id(c.file.commit.raw_id)),h.url('changeset_home',repo_name=c.repo_name,revision=c.file.commit.raw_id))}</span>
<span class="item">${h.link_to("r%s:%s" % (c.file.commit.idx,h.short_id(c.file.commit.raw_id)),h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.file.commit.raw_id))}</span>
<span class="item">${h.format_byte_size_binary(c.file.size)}</span>
<span class="item last">${c.file.mimetype}</span>
<div class="buttons">
@ -177,8 +177,9 @@ $(document).ready(function(){
var _renderer = possible_renderer || DEFAULT_RENDERER;
var post_data = {'text': _text, 'renderer': _renderer, 'csrf_token': CSRF_TOKEN};
$('#editor_preview').html(_gettext('Loading ...'));
var url = pyroutes.url('changeset_comment_preview', {'repo_name': '${c.repo_name}'});
var url = pyroutes.url('repo_commit_comment_preview',
{'repo_name': '${c.repo_name}',
'commit_id': '${c.commit.raw_id}'});
ajaxPOST(url, post_data, function(o){
$('#editor_preview').html(o);
})

View file

@ -86,7 +86,7 @@
<br/>
% if c.ancestor_commit:
${_('Common ancestor')}:
<code><a href="${h.url('changeset_home', repo_name=c.target_repo.repo_name, revision=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a></code>
<code><a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a></code>
% endif
</div>
<div class="pr-pullinfo">
@ -513,7 +513,7 @@
</td>
<td class="td-hash">
<code>
<a href="${h.url('changeset_home', repo_name=c.target_repo.repo_name, revision=commit.raw_id)}">
<a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
r${commit.revision}:${h.short_id(commit.raw_id)}
</a>
${h.hidden('revisions', commit.raw_id)}

View file

@ -31,7 +31,7 @@
</td>
<td class="td-commit">
${h.link_to(h._shorten_commit_id(entry['commit_id']),
h.url('changeset_home',repo_name=entry['repository'],revision=entry['commit_id']))}
h.route_path('repo_commit',repo_name=entry['repository'],commit_id=entry['commit_id']))}
</td>
<td class="td-message expand_commit search open" data-commit-id="${h.md5_safe(entry['repository'])+entry['commit_id']}" id="t-${h.md5_safe(entry['repository'])+entry['commit_id']}" title="${_('Expand commit message')}">
<div class="show_more_col">

View file

@ -19,11 +19,11 @@
<div class="changeset-status-ico shortlog">
%if c.statuses.get(cs.raw_id)[2]:
<a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (c.statuses.get(cs.raw_id)[0], c.statuses.get(cs.raw_id)[2])}" href="${h.route_path('pullrequest_show',repo_name=c.statuses.get(cs.raw_id)[3],pull_request_id=c.statuses.get(cs.raw_id)[2])}">
<div class="${'flag_status %s' % c.statuses.get(cs.raw_id)[0]}"></div>
<div class="${'flag_status {}'.format(c.statuses.get(cs.raw_id)[0])}"></div>
</a>
%else:
<a class="tooltip" title="${_('Commit status: %s') % h.commit_status_lbl(c.statuses.get(cs.raw_id)[0])}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
<div class="${'flag_status %s' % c.statuses.get(cs.raw_id)[0]}"></div>
<a class="tooltip" title="${_('Commit status: {}').format(h.commit_status_lbl(c.statuses.get(cs.raw_id)[0]))}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id,_anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
<div class="${'flag_status {}'.format(c.statuses.get(cs.raw_id)[0])}"></div>
</a>
%endif
</div>
@ -33,13 +33,13 @@
</td>
<td class="td-comments">
%if c.comments.get(cs.raw_id,[]):
<a title="${_('Commit has comments')}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
<a title="${_('Commit has comments')}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id,_anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
<i class="icon-comment"></i> ${len(c.comments[cs.raw_id])}
</a>
%endif
</td>
<td class="td-commit">
<pre><a href="${h.url('changeset_home', repo_name=c.repo_name, revision=cs.raw_id)}">${h.show_id(cs)}</a></pre>
<pre><a href="${h.route_path('repo_commit', repo_name=c.repo_name, commit_id=cs.raw_id)}">${h.show_id(cs)}</a></pre>
</td>
<td class="td-description mid">

View file

@ -471,7 +471,7 @@ class TestCompareController(object):
compare_page.contains_change_summary(1, 1, 0)
@pytest.mark.xfail_backends("svn")
def test_compare_commits(self, backend):
def test_compare_commits(self, backend, xhr_header):
commit0 = backend.repo.get_commit(commit_idx=0)
commit1 = backend.repo.get_commit(commit_idx=1)
@ -483,7 +483,7 @@ class TestCompareController(object):
target_ref_type="rev",
target_ref=commit1.raw_id,
merge='1',),
extra_environ={'HTTP_X_PARTIAL_XHR': '1'},)
extra_environ=xhr_header,)
# outgoing commits between those commits
compare_page = ComparePage(response)

View file

@ -397,7 +397,7 @@ def test_urlify_commits(sample, expected):
expected = _quick_url(expected)
with mock.patch('pylons.url', fake_url):
with mock.patch('rhodecode.lib.helpers.route_url', fake_url):
from rhodecode.lib.helpers import urlify_commits
assert urlify_commits(sample, 'repo_name') == expected

View file

@ -1,7 +1,7 @@
################################################################################
## RHODECODE ENTERPRISE CONFIGURATION ##
## RHODECODE COMMUNITY EDITION CONFIGURATION ##
# The %(here)s variable will be replaced with the parent directory of this file#
################################################################################
@ -64,7 +64,7 @@ asyncore_use_poll = true
##########################
## GUNICORN WSGI SERVER ##
##########################
## run with gunicorn --log-config <inifile.ini> --paste <inifile.ini>
## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
#use = egg:gunicorn#main
## Sets the number of process workers. You must set `instance_id = *`
@ -153,8 +153,10 @@ asyncore_use_poll = true
## prefix middleware for RhodeCode.
## recommended when using proxy setup.
## allows to set RhodeCode under a prefix in server.
## eg https://server.com/<prefix>. Enable `filter-with =` option below as well.
## optionally set prefix like: `prefix = /<your-prefix>`
## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well.
## And set your prefix like: `prefix = /custom_prefix`
## be sure to also set beaker.session.cookie_path = /custom_prefix if you need
## to make your cookies only work on prefix url
[filter:proxy-prefix]
use = egg:PasteDeploy#prefix
prefix = /
@ -238,27 +240,27 @@ rss_items_per_page = 10
rss_include_diff = false
## gist URL alias, used to create nicer urls for gist. This should be an
## url that does rewrites to _admin/gists/<gistid>.
## url that does rewrites to _admin/gists/{gistid}.
## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/<gistid>
## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid}
gist_alias_url =
## List of controllers (using glob pattern syntax) that AUTH TOKENS could be
## List of views (using glob pattern syntax) that AUTH TOKENS could be
## used for access.
## Adding ?auth_token = <token> to the url authenticates this request as if it
## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
## came from the the logged in user who own this authentication token.
##
## Syntax is <ControllerClass>:<function_pattern>.
## To enable access to raw_files put `FilesController:raw`.
## To enable access to patches add `ChangesetController:changeset_patch`.
## list of all views can be found under `_admin/permissions/auth_token_access`
## The list should be "," separated and on a single line.
##
## Recommended controllers to enable:
# ChangesetController:changeset_patch,
# ChangesetController:changeset_raw,
# FilesController:raw,
# FilesController:archivefile,
# GistsController:*,
## Most common views to enable:
# RepoCommitsView:repo_commit_download
# RepoCommitsView:repo_commit_patch
# RepoCommitsView:repo_commit_raw
# RepoFilesView:repo_files_diff
# RepoFilesView:repo_archivefile
# RepoFilesView:repo_file_raw
# GistView:*
api_access_controllers_whitelist =
## default encoding used to convert from and to unicode
@ -421,15 +423,15 @@ beaker.session.lock_dir = %(here)s/rc/data/sessions/lock
## Secure encrypted cookie. Requires AES and AES python libraries
## you must disable beaker.session.secret to use this
#beaker.session.encrypt_key = <key_for_encryption>
#beaker.session.validate_key = <validation_key>
#beaker.session.encrypt_key = key_for_encryption
#beaker.session.validate_key = validation_key
## sets session as invalid(also logging out user) if it haven not been
## accessed for given amount of time in seconds
beaker.session.timeout = 2592000
beaker.session.httponly = true
## Path to use for the cookie.
#beaker.session.cookie_path = /<your-prefix>
## Path to use for the cookie. Set to prefix if you use prefix middleware
#beaker.session.cookie_path = /custom_prefix
## uncomment for https secure cookie
beaker.session.secure = false
@ -447,8 +449,8 @@ beaker.session.auto = false
## Full text search indexer is available in rhodecode-tools under
## `rhodecode-tools index` command
# WHOOSH Backend, doesn't require additional services to run
# it works good with few dozen repos
## WHOOSH Backend, doesn't require additional services to run
## it works good with few dozen repos
search.module = rhodecode.lib.index.whoosh
search.location = %(here)s/data/index
@ -459,15 +461,21 @@ search.location = %(here)s/data/index
## in the system. It's also used by the chat system
channelstream.enabled = false
# location of channelstream server on the backend
## server address for channelstream server on the backend
channelstream.server = 127.0.0.1:9800
## location of the channelstream server from outside world
## most likely this would be an http server special backend URL, that handles
## websocket connections see nginx example for config
## use ws:// for http or wss:// for https. This address needs to be handled
## by external HTTP server such as Nginx or Apache
## see nginx/apache configuration examples in our docs
channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
channelstream.secret = secret
channelstream.history.location = %(here)s/channelstream_history
## Internal application path that Javascript uses to connect into.
## If you use proxy-prefix the prefix should be added before /_channelstream
channelstream.proxy_path = /_channelstream
###################################
## APPENLIGHT CONFIG ##
@ -541,19 +549,19 @@ set debug = false
##############
debug_style = false
#########################################################
### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
#########################################################
#sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db
###########################################
### MAIN RHODECODE DATABASE CONFIG ###
###########################################
#sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db?timeout=30
#sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode_test
#sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode_test
sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db
sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db?timeout=30
# see sqlalchemy docs for other advanced settings
## print the sql statements to output
sqlalchemy.db1.echo = false
## recycle the connections after this ammount of seconds
## recycle the connections after this amount of seconds
sqlalchemy.db1.pool_recycle = 3600
sqlalchemy.db1.convert_unicode = true
@ -575,7 +583,7 @@ vcs.server = localhost:9901
## Web server connectivity protocol, responsible for web based VCS operatations
## Available protocols are:
## `http` - using http-rpc backend
## `http` - use http-rpc backend (default)
vcs.server.protocol = http
## Push/Pull operations protocol, available options are:
@ -584,7 +592,7 @@ vcs.server.protocol = http
vcs.scm_app_implementation = http
## Push/Pull operations hooks protocol, available options are:
## `http` - using http-rpc backend
## `http` - use http-rpc backend (default)
vcs.hooks.protocol = http
vcs.server.log_level = debug
@ -613,12 +621,19 @@ svn.proxy.generate_config = false
svn.proxy.list_parent_path = true
## Set location and file name of generated config file.
svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
## File system path to the directory containing the repositories served by
## RhodeCode.
svn.proxy.parent_path_root = /path/to/repo_store
## Used as a prefix to the <Location> block in the generated config file. In
## most cases it should be set to `/`.
## Used as a prefix to the `Location` block in the generated config file.
## In most cases it should be set to `/`.
svn.proxy.location_root = /
## Command to reload the mod dav svn configuration on change.
## Example: `/etc/init.d/apache2 reload`
#svn.proxy.reload_cmd = /etc/init.d/apache2 reload
## If the timeout expires before the reload command finishes, the command will
## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
#svn.proxy.reload_timeout = 10
## Dummy marker to add new entries after.
## Add any custom entries below. Please don't remove.
custom.conf = 1
################################