##// END OF EJS Templates
changelog: ported to pyramid views.
marcink -
r1931:f3f88cc8 default
parent child Browse files
Show More
@@ -0,0 +1,302 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import logging
23
24 from pyramid.httpexceptions import HTTPNotFound, HTTPFound
25 from pyramid.view import view_config
26 from pyramid.renderers import render
27 from pyramid.response import Response
28
29 from rhodecode.apps._base import RepoAppView
30 import rhodecode.lib.helpers as h
31 from rhodecode.lib.auth import (
32 LoginRequired, HasRepoPermissionAnyDecorator)
33
34 from rhodecode.lib.ext_json import json
35 from rhodecode.lib.graphmod import _colored, _dagwalker
36 from rhodecode.lib.helpers import RepoPage
37 from rhodecode.lib.utils2 import safe_int, safe_str
38 from rhodecode.lib.vcs.exceptions import (
39 RepositoryError, CommitDoesNotExistError,
40 CommitError, NodeDoesNotExistError, EmptyRepositoryError)
41
42 log = logging.getLogger(__name__)
43
44 DEFAULT_CHANGELOG_SIZE = 20
45
46
47 class RepoChangelogView(RepoAppView):
48
49 def _get_commit_or_redirect(self, commit_id, redirect_after=True):
50 """
51 This is a safe way to get commit. If an error occurs it redirects to
52 tip with proper message
53
54 :param commit_id: id of commit to fetch
55 :param redirect_after: toggle redirection
56 """
57 _ = self.request.translate
58
59 try:
60 return self.rhodecode_vcs_repo.get_commit(commit_id)
61 except EmptyRepositoryError:
62 if not redirect_after:
63 return None
64
65 h.flash(h.literal(
66 _('There are no commits yet')), category='warning')
67 raise HTTPFound(
68 h.route_path('repo_summary', repo_name=self.db_repo_name))
69
70 except (CommitDoesNotExistError, LookupError):
71 msg = _('No such commit exists for this repository')
72 h.flash(msg, category='error')
73 raise HTTPNotFound()
74 except RepositoryError as e:
75 h.flash(safe_str(h.escape(e)), category='error')
76 raise HTTPNotFound()
77
78 def _graph(self, repo, commits, prev_data=None, next_data=None):
79 """
80 Generates a DAG graph for repo
81
82 :param repo: repo instance
83 :param commits: list of commits
84 """
85 if not commits:
86 return json.dumps([])
87
88 def serialize(commit, parents=True):
89 data = dict(
90 raw_id=commit.raw_id,
91 idx=commit.idx,
92 branch=commit.branch,
93 )
94 if parents:
95 data['parents'] = [
96 serialize(x, parents=False) for x in commit.parents]
97 return data
98
99 prev_data = prev_data or []
100 next_data = next_data or []
101
102 current = [serialize(x) for x in commits]
103 commits = prev_data + current + next_data
104
105 dag = _dagwalker(repo, commits)
106
107 data = [[commit_id, vtx, edges, branch]
108 for commit_id, vtx, edges, branch in _colored(dag)]
109 return json.dumps(data), json.dumps(current)
110
111 def _check_if_valid_branch(self, branch_name, repo_name, f_path):
112 if branch_name not in self.rhodecode_vcs_repo.branches_all:
113 h.flash('Branch {} is not found.'.format(h.escape(branch_name)),
114 category='warning')
115 redirect_url = h.route_path(
116 'repo_changelog_file', repo_name=repo_name,
117 commit_id=branch_name, f_path=f_path or '')
118 raise HTTPFound(redirect_url)
119
120 def _load_changelog_data(
121 self, c, collection, page, chunk_size, branch_name=None,
122 dynamic=False):
123
124 def url_generator(**kw):
125 query_params = {}
126 query_params.update(kw)
127 return h.route_path(
128 'repo_changelog',
129 repo_name=c.rhodecode_db_repo.repo_name, _query=query_params)
130
131 c.total_cs = len(collection)
132 c.showing_commits = min(chunk_size, c.total_cs)
133 c.pagination = RepoPage(collection, page=page, item_count=c.total_cs,
134 items_per_page=chunk_size, branch=branch_name,
135 url=url_generator)
136
137 c.next_page = c.pagination.next_page
138 c.prev_page = c.pagination.previous_page
139
140 if dynamic:
141 if self.request.GET.get('chunk') != 'next':
142 c.next_page = None
143 if self.request.GET.get('chunk') != 'prev':
144 c.prev_page = None
145
146 page_commit_ids = [x.raw_id for x in c.pagination]
147 c.comments = c.rhodecode_db_repo.get_comments(page_commit_ids)
148 c.statuses = c.rhodecode_db_repo.statuses(page_commit_ids)
149
150 def load_default_context(self):
151 c = self._get_local_tmpl_context(include_app_defaults=True)
152
153 # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
154 c.repo_info = self.db_repo
155 c.rhodecode_repo = self.rhodecode_vcs_repo
156
157 self._register_global_c(c)
158 return c
159
160 @LoginRequired()
161 @HasRepoPermissionAnyDecorator(
162 'repository.read', 'repository.write', 'repository.admin')
163 @view_config(
164 route_name='repo_changelog', request_method='GET',
165 renderer='rhodecode:templates/changelog/changelog.mako')
166 @view_config(
167 route_name='repo_changelog_file', request_method='GET',
168 renderer='rhodecode:templates/changelog/changelog.mako')
169 def repo_changelog(self):
170 c = self.load_default_context()
171
172 commit_id = self.request.matchdict.get('commit_id')
173 f_path = self._get_f_path(self.request.matchdict)
174
175 chunk_size = 20
176
177 c.branch_name = branch_name = self.request.GET.get('branch') or ''
178 c.book_name = book_name = self.request.GET.get('bookmark') or ''
179 hist_limit = safe_int(self.request.GET.get('limit')) or None
180
181 p = safe_int(self.request.GET.get('page', 1), 1)
182
183 c.selected_name = branch_name or book_name
184 if not commit_id and branch_name:
185 self._check_if_valid_branch(branch_name, self.db_repo_name, f_path)
186
187 c.changelog_for_path = f_path
188 pre_load = ['author', 'branch', 'date', 'message', 'parents']
189 commit_ids = []
190
191 partial_xhr = self.request.environ.get('HTTP_X_PARTIAL_XHR')
192
193 try:
194 if f_path:
195 log.debug('generating changelog for path %s', f_path)
196 # get the history for the file !
197 base_commit = self.rhodecode_vcs_repo.get_commit(commit_id)
198 try:
199 collection = base_commit.get_file_history(
200 f_path, limit=hist_limit, pre_load=pre_load)
201 if collection and partial_xhr:
202 # for ajax call we remove first one since we're looking
203 # at it right now in the context of a file commit
204 collection.pop(0)
205 except (NodeDoesNotExistError, CommitError):
206 # this node is not present at tip!
207 try:
208 commit = self._get_commit_or_redirect(commit_id)
209 collection = commit.get_file_history(f_path)
210 except RepositoryError as e:
211 h.flash(safe_str(e), category='warning')
212 redirect_url = h.route_path(
213 'repo_changelog', repo_name=self.db_repo_name)
214 raise HTTPFound(redirect_url)
215 collection = list(reversed(collection))
216 else:
217 collection = self.rhodecode_vcs_repo.get_commits(
218 branch_name=branch_name, pre_load=pre_load)
219
220 self._load_changelog_data(
221 c, collection, p, chunk_size, c.branch_name, dynamic=f_path)
222
223 except EmptyRepositoryError as e:
224 h.flash(safe_str(h.escape(e)), category='warning')
225 raise HTTPFound(
226 h.route_path('repo_summary', repo_name=self.db_repo_name))
227 except (RepositoryError, CommitDoesNotExistError, Exception) as e:
228 log.exception(safe_str(e))
229 h.flash(safe_str(h.escape(e)), category='error')
230 raise HTTPFound(
231 h.route_path('repo_changelog', repo_name=self.db_repo_name))
232
233 if partial_xhr or self.request.environ.get('HTTP_X_PJAX'):
234 # loading from ajax, we don't want the first result, it's popped
235 # in the code above
236 html = render(
237 'rhodecode:templates/changelog/changelog_file_history.mako',
238 self._get_template_context(c), self.request)
239 return Response(html)
240
241 if not f_path:
242 commit_ids = c.pagination
243
244 c.graph_data, c.graph_commits = self._graph(
245 self.rhodecode_vcs_repo, commit_ids)
246
247 return self._get_template_context(c)
248
249 @LoginRequired()
250 @HasRepoPermissionAnyDecorator(
251 'repository.read', 'repository.write', 'repository.admin')
252 @view_config(
253 route_name='repo_changelog_elements', request_method=('GET', 'POST'),
254 renderer='rhodecode:templates/changelog/changelog_elements.mako',
255 xhr=True)
256 def repo_changelog_elements(self):
257 c = self.load_default_context()
258 chunk_size = 20
259
260 def wrap_for_error(err):
261 html = '<tr>' \
262 '<td colspan="9" class="alert alert-error">ERROR: {}</td>' \
263 '</tr>'.format(err)
264 return Response(html)
265
266 c.branch_name = branch_name = self.request.GET.get('branch') or ''
267 c.book_name = book_name = self.request.GET.get('bookmark') or ''
268
269 c.selected_name = branch_name or book_name
270 if branch_name and branch_name not in self.rhodecode_vcs_repo.branches_all:
271 return wrap_for_error(
272 safe_str('Branch: {} is not valid'.format(branch_name)))
273
274 pre_load = ['author', 'branch', 'date', 'message', 'parents']
275 collection = self.rhodecode_vcs_repo.get_commits(
276 branch_name=branch_name, pre_load=pre_load)
277
278 p = safe_int(self.request.GET.get('page', 1), 1)
279 try:
280 self._load_changelog_data(
281 c, collection, p, chunk_size, dynamic=True)
282 except EmptyRepositoryError as e:
283 return wrap_for_error(safe_str(e))
284 except (RepositoryError, CommitDoesNotExistError, Exception) as e:
285 log.exception('Failed to fetch commits')
286 return wrap_for_error(safe_str(e))
287
288 prev_data = None
289 next_data = None
290
291 prev_graph = json.loads(self.request.POST.get('graph', ''))
292
293 if self.request.GET.get('chunk') == 'prev':
294 next_data = prev_graph
295 elif self.request.GET.get('chunk') == 'next':
296 prev_data = prev_graph
297
298 c.graph_data, c.graph_commits = self._graph(
299 self.rhodecode_vcs_repo, c.pagination,
300 prev_data=prev_data, next_data=next_data)
301
302 return self._get_template_context(c)
@@ -139,6 +139,17 b' def includeme(config):'
139 139 name='repo_stats',
140 140 pattern='/{repo_name:.*?[^/]}/repo_stats/{commit_id}', repo_route=True)
141 141
142 # Changelog
143 config.add_route(
144 name='repo_changelog',
145 pattern='/{repo_name:.*?[^/]}/changelog', repo_route=True)
146 config.add_route(
147 name='repo_changelog_file',
148 pattern='/{repo_name:.*?[^/]}/changelog/{commit_id}/{f_path:.*}', repo_route=True)
149 config.add_route(
150 name='repo_changelog_elements',
151 pattern='/{repo_name:.*?[^/]}/changelog_elements', repo_route=True)
152
142 153 # Tags
143 154 config.add_route(
144 155 name='tags_home',
@@ -22,20 +22,32 b' import re'
22 22
23 23 import pytest
24 24
25 from rhodecode.controllers.changelog import DEFAULT_CHANGELOG_SIZE
26 from rhodecode.tests import url, TestController
27 from rhodecode.tests.utils import AssertResponse
28
25 from rhodecode.apps.repository.views.repo_changelog import DEFAULT_CHANGELOG_SIZE
26 from rhodecode.tests import TestController
29 27
30 28 MATCH_HASH = re.compile(r'<span class="commit_hash">r(\d+):[\da-f]+</span>')
31 29
32 30
31 def route_path(name, params=None, **kwargs):
32 import urllib
33
34 base_url = {
35 'repo_changelog':'/{repo_name}/changelog',
36 'repo_changelog_file':'/{repo_name}/changelog/{commit_id}/{f_path}',
37 'repo_changelog_elements':'/{repo_name}/changelog_elements',
38 }[name].format(**kwargs)
39
40 if params:
41 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
42 return base_url
43
44
33 45 class TestChangelogController(TestController):
34 46
35 def test_index(self, backend):
47 def test_changelog(self, backend):
36 48 self.log_user()
37 response = self.app.get(url(controller='changelog', action='index',
38 repo_name=backend.repo_name))
49 response = self.app.get(
50 route_path('repo_changelog', repo_name=backend.repo_name))
39 51
40 52 first_idx = -1
41 53 last_idx = -DEFAULT_CHANGELOG_SIZE
@@ -43,39 +55,30 b' class TestChangelogController(TestContro'
43 55 response, first_idx, last_idx, backend)
44 56
45 57 @pytest.mark.backends("hg", "git")
46 def test_index_filtered_by_branch(self, backend):
58 def test_changelog_filtered_by_branch(self, backend):
47 59 self.log_user()
48 60 self.app.get(
49 url(
50 controller='changelog',
51 action='index',
52 repo_name=backend.repo_name,
53 branch=backend.default_branch_name),
61 route_path('repo_changelog', repo_name=backend.repo_name,
62 params=dict(branch=backend.default_branch_name)),
54 63 status=200)
55 64
56 65 @pytest.mark.backends("svn")
57 def test_index_filtered_by_branch_svn(self, autologin_user, backend):
66 def test_changelog_filtered_by_branch_svn(self, autologin_user, backend):
58 67 repo = backend['svn-simple-layout']
59 68 response = self.app.get(
60 url(
61 controller='changelog',
62 action='index',
63 repo_name=repo.repo_name,
64 branch='trunk'),
69 route_path('repo_changelog', repo_name=repo.repo_name,
70 params=dict(branch='trunk')),
65 71 status=200)
66 72
67 73 self.assert_commits_on_page(
68 74 response, indexes=[15, 12, 7, 3, 2, 1])
69 75
70 def test_index_filtered_by_wrong_branch(self, backend):
76 def test_changelog_filtered_by_wrong_branch(self, backend):
71 77 self.log_user()
72 78 branch = 'wrong-branch-name'
73 79 response = self.app.get(
74 url(
75 controller='changelog',
76 action='index',
77 repo_name=backend.repo_name,
78 branch=branch),
80 route_path('repo_changelog', repo_name=backend.repo_name,
81 params=dict(branch=branch)),
79 82 status=302)
80 83 expected_url = '/{repo}/changelog/{branch}'.format(
81 84 repo=backend.repo_name, branch=branch)
@@ -89,7 +92,7 b' class TestChangelogController(TestContro'
89 92 assert found_indexes == indexes
90 93
91 94 @pytest.mark.xfail_backends("svn", reason="Depends on branch support")
92 def test_index_filtered_by_branch_with_merges(
95 def test_changelog_filtered_by_branch_with_merges(
93 96 self, autologin_user, backend):
94 97
95 98 # Note: The changelog of branch "b" does not contain the commit "a1"
@@ -104,33 +107,27 b' class TestChangelogController(TestContro'
104 107 backend.create_repo(commits)
105 108
106 109 self.app.get(
107 url('changelog_home',
108 controller='changelog',
109 action='index',
110 repo_name=backend.repo_name,
111 branch='b'),
110 route_path('repo_changelog', repo_name=backend.repo_name,
111 params=dict(branch='b')),
112 112 status=200)
113 113
114 114 @pytest.mark.backends("hg")
115 def test_index_closed_branches(self, autologin_user, backend):
115 def test_changelog_closed_branches(self, autologin_user, backend):
116 116 repo = backend['closed_branch']
117 117 response = self.app.get(
118 url(
119 controller='changelog',
120 action='index',
121 repo_name=repo.repo_name,
122 branch='experimental'),
118 route_path('repo_changelog', repo_name=repo.repo_name,
119 params=dict(branch='experimental')),
123 120 status=200)
124 121
125 122 self.assert_commits_on_page(
126 123 response, indexes=[3, 1])
127 124
128 def test_index_pagination(self, backend):
125 def test_changelog_pagination(self, backend):
129 126 self.log_user()
130 127 # pagination, walk up to page 6
131 changelog_url = url(
132 controller='changelog', action='index',
133 repo_name=backend.repo_name)
128 changelog_url = route_path(
129 'repo_changelog', repo_name=backend.repo_name)
130
134 131 for page in range(1, 7):
135 132 response = self.app.get(changelog_url, {'page': page})
136 133
@@ -166,27 +163,33 b' class TestChangelogController(TestContro'
166 163 first_commit_of_next_page.idx, first_commit_of_next_page.short_id)
167 164 assert first_span_of_next_page not in response
168 165
169 def test_index_with_filenode(self, backend):
166 @pytest.mark.parametrize('test_path', [
167 'vcs/exceptions.py',
168 '/vcs/exceptions.py',
169 '//vcs/exceptions.py'
170 ])
171 def test_changelog_with_filenode(self, backend, test_path):
170 172 self.log_user()
171 response = self.app.get(url(
172 controller='changelog', action='index', revision='tip',
173 f_path='/vcs/exceptions.py', repo_name=backend.repo_name))
173 response = self.app.get(
174 route_path('repo_changelog_file', repo_name=backend.repo_name,
175 commit_id='tip', f_path=test_path),
176 )
174 177
175 178 # history commits messages
176 179 response.mustcontain('Added exceptions module, this time for real')
177 180 response.mustcontain('Added not implemented hg backend test case')
178 181 response.mustcontain('Added BaseChangeset class')
179 182
180 def test_index_with_filenode_that_is_dirnode(self, backend):
183 def test_changelog_with_filenode_that_is_dirnode(self, backend):
181 184 self.log_user()
182 response = self.app.get(url(controller='changelog', action='index',
183 revision='tip', f_path='/tests',
184 repo_name=backend.repo_name))
185 assert response.status == '302 Found'
185 self.app.get(
186 route_path('repo_changelog_file', repo_name=backend.repo_name,
187 commit_id='tip', f_path='/tests'),
188 status=302)
186 189
187 def test_index_with_filenode_not_existing(self, backend):
190 def test_changelog_with_filenode_not_existing(self, backend):
188 191 self.log_user()
189 response = self.app.get(url(controller='changelog', action='index',
190 revision='tip', f_path='/wrong_path',
191 repo_name=backend.repo_name))
192 assert response.status == '302 Found'
192 self.app.get(
193 route_path('repo_changelog_file', repo_name=backend.repo_name,
194 commit_id='tip', f_path='wrong_path'),
195 status=302)
@@ -274,7 +274,6 b' def make_map(config):'
274 274 m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary',
275 275 action='edit_perms_summary', conditions={'method': ['GET']})
276 276
277
278 277 # ADMIN USER GROUPS REST ROUTES
279 278 with rmap.submapper(path_prefix=ADMIN_PREFIX,
280 279 controller='admin/user_groups') as m:
@@ -698,21 +697,6 b' def make_map(config):'
698 697 conditions={'function': check_repo, 'method': ['DELETE']},
699 698 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
700 699
701 rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True,
702 controller='changelog', conditions={'function': check_repo},
703 requirements=URL_NAME_REQUIREMENTS)
704
705 rmap.connect('changelog_file_home',
706 '/{repo_name}/changelog/{revision}/{f_path}',
707 controller='changelog', f_path=None,
708 conditions={'function': check_repo},
709 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
710
711 rmap.connect('changelog_elements', '/{repo_name}/changelog_details',
712 controller='changelog', action='changelog_elements',
713 conditions={'function': check_repo},
714 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
715
716 700 rmap.connect('repo_fork_create_home', '/{repo_name}/fork',
717 701 controller='forks', action='fork_create',
718 702 conditions={'function': check_repo, 'method': ['POST']},
@@ -149,7 +149,6 b' class ChangesetController(BaseRepoContro'
149 149
150 150 def __before__(self):
151 151 super(ChangesetController, self).__before__()
152 c.affected_files_cut_off = 60
153 152
154 153 def _index(self, commit_id_range, method):
155 154 c.ignorews_url = _ignorews_url
@@ -129,9 +129,8 b' class JournalController(BaseController):'
129 129 desc = action_extra()
130 130 _url = None
131 131 if entry.repository is not None:
132 _url = url('changelog_home',
133 repo_name=entry.repository.repo_name,
134 qualified=True)
132 _url = h.route_url('repo_changelog',
133 repo_name=entry.repository.repo_name)
135 134
136 135 feed.add_item(title=title,
137 136 pubdate=entry.action_date,
@@ -172,9 +171,8 b' class JournalController(BaseController):'
172 171 desc = action_extra()
173 172 _url = None
174 173 if entry.repository is not None:
175 _url = url('changelog_home',
176 repo_name=entry.repository.repo_name,
177 qualified=True)
174 _url = h.route_url('repo_changelog',
175 repo_name=entry.repository.repo_name)
178 176
179 177 feed.add_item(title=title,
180 178 pubdate=entry.action_date,
@@ -324,6 +324,8 b' def attach_context_attributes(context, r'
324 324 context.visual.rhodecode_support_url = \
325 325 rc_config.get('rhodecode_support_url') or h.route_url('rhodecode_support')
326 326
327 context.visual.affected_files_cut_off = 60
328
327 329 context.pre_code = rc_config.get('rhodecode_pre_code')
328 330 context.post_code = rc_config.get('rhodecode_post_code')
329 331 context.rhodecode_name = rc_config.get('rhodecode_title')
@@ -66,7 +66,7 b' function setRCMouseBindings(repoName, re'
66 66 });
67 67 Mousetrap.bind(['g c'], function(e) {
68 68 window.location = pyroutes.url(
69 'changelog_home', {'repo_name': repoName});
69 'repo_changelog', {'repo_name': repoName});
70 70 });
71 71 Mousetrap.bind(['g F'], function(e) {
72 72 window.location = pyroutes.url(
@@ -30,9 +30,6 b' function registerRCRoutes() {'
30 30 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
31 31 pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
32 32 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request-comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
33 pyroutes.register('changelog_home', '/%(repo_name)s/changelog', ['repo_name']);
34 pyroutes.register('changelog_file_home', '/%(repo_name)s/changelog/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
35 pyroutes.register('changelog_elements', '/%(repo_name)s/changelog_details', ['repo_name']);
36 33 pyroutes.register('favicon', '/favicon.ico', []);
37 34 pyroutes.register('robots', '/robots.txt', []);
38 35 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
@@ -124,6 +121,9 b' function registerRCRoutes() {'
124 121 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
125 122 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
126 123 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
124 pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']);
125 pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
126 pyroutes.register('repo_changelog_elements', '/%(repo_name)s/changelog_elements', ['repo_name']);
127 127 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
128 128 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
129 129 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
@@ -105,7 +105,7 b' var CommitsController = function () {'
105 105 urlData['branch'] = branch;
106 106 }
107 107
108 return pyroutes.url('changelog_elements', urlData);
108 return pyroutes.url('repo_changelog_elements', urlData);
109 109 };
110 110
111 111 this.loadNext = function (node, page, branch) {
@@ -226,7 +226,7 b''
226 226 <div class="wrapper">
227 227 <ul id="context-pages" class="horizontal-list navigation">
228 228 <li class="${is_active('summary')}"><a class="menulink" href="${h.route_path('repo_summary', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
229 <li class="${is_active('changelog')}"><a class="menulink" href="${h.url('changelog_home', repo_name=c.repo_name)}"><div class="menulabel">${_('Changelog')}</div></a></li>
229 <li class="${is_active('changelog')}"><a class="menulink" href="${h.route_path('repo_changelog', repo_name=c.repo_name)}"><div class="menulabel">${_('Changelog')}</div></a></li>
230 230 <li class="${is_active('files')}"><a class="menulink" href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.rhodecode_db_repo.landing_rev[1], f_path='')}"><div class="menulabel">${_('Files')}</div></a></li>
231 231 <li class="${is_active('compare')}">
232 232 <a class="menulink" href="${h.url('compare_home',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a>
@@ -86,7 +86,7 b''
86 86 </div>
87 87 ${self.breadcrumbs('breadcrumbs_light')}
88 88 <div id="commit-counter" data-total=${c.total_cs} class="pull-right">
89 ${ungettext('showing %d out of %d commit', 'showing %d out of %d commits', c.showing_commits) % (c.showing_commits, c.total_cs)}
89 ${_ungettext('showing %d out of %d commit', 'showing %d out of %d commits', c.showing_commits) % (c.showing_commits, c.total_cs)}
90 90 </div>
91 91 </div>
92 92
@@ -230,7 +230,7 b''
230 230
231 231 $("#clear_filter").on("click", function() {
232 232 var filter = {'repo_name': '${c.repo_name}'};
233 window.location = pyroutes.url('changelog_home', filter);
233 window.location = pyroutes.url('repo_changelog', filter);
234 234 });
235 235
236 236 $("#branch_filter").select2({
@@ -280,7 +280,7 b''
280 280 else if (data.type == 'book'){
281 281 filter["bookmark"] = selected;
282 282 }
283 window.location = pyroutes.url('changelog_home', filter);
283 window.location = pyroutes.url('repo_changelog', filter);
284 284 });
285 285
286 286 commitsController = new CommitsController();
@@ -101,7 +101,7 b''
101 101 ## branch
102 102 %if commit.branch:
103 103 <span class="tag branchtag" title="${h.tooltip(_('Branch %s') % commit.branch)}">
104 <a href="${h.url('changelog_home',repo_name=c.repo_name,branch=commit.branch)}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
104 <a href="${h.route_path('repo_changelog',repo_name=c.repo_name,_query=dict(branch=commit.branch))}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
105 105 </span>
106 106 %endif
107 107
@@ -14,7 +14,7 b''
14 14 </a>
15 15 </li>
16 16 <li>
17 <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=repo_name)}">
17 <a title="${_('Changelog')}" href="${h.route_path('repo_changelog',repo_name=repo_name)}">
18 18 <span>${_('Changelog')}</span>
19 19 </a>
20 20 </li>
@@ -219,9 +219,9 b''
219 219 if (path.indexOf("#") >= 0) {
220 220 path = path.slice(0, path.indexOf("#"));
221 221 }
222 var url = pyroutes.url('changelog_file_home',
222 var url = pyroutes.url('repo_changelog_file',
223 223 {'repo_name': templateContext.repo_name,
224 'revision': state.rev, 'f_path': path, 'limit': 6});
224 'commit_id': state.rev, 'f_path': path, 'limit': 6});
225 225 $('#file_history_container').show();
226 226 $('#file_history_container').html('<div class="file-history-inner">{0}</div>'.format(_gettext('Loading ...')));
227 227
@@ -51,7 +51,7 b''
51 51 <span class="item">${h.format_byte_size_binary(c.file.size)}</span>
52 52 <span class="item last">${c.file.mimetype}</span>
53 53 <div class="buttons">
54 <a class="btn btn-mini" href="${h.url('changelog_file_home',repo_name=c.repo_name, revision=c.commit.raw_id, f_path=c.f_path)}">
54 <a class="btn btn-mini" href="${h.route_path('repo_changelog_file',repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path)}">
55 55 <i class="icon-time"></i> ${_('history')}
56 56 </a>
57 57
@@ -16,7 +16,7 b''
16 16 <a id="file_history_overview" href="#">
17 17 ${_('History')}
18 18 </a>
19 <a id="file_history_overview_full" style="display: none" href="${h.url('changelog_file_home',repo_name=c.repo_name, revision=c.commit.raw_id, f_path=c.f_path)}">
19 <a id="file_history_overview_full" style="display: none" href="${h.route_path('repo_changelog_file',repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path)}">
20 20 ${_('Show Full History')}
21 21 </a> |
22 22 %if c.annotate:
@@ -75,7 +75,7 b''
75 75 ## branch link is only valid if it is a branch
76 76 <span class="tag">
77 77 %if c.pull_request.source_ref_parts.type == 'branch':
78 <a href="${h.url('changelog_home', repo_name=c.pull_request.source_repo.repo_name, branch=c.pull_request.source_ref_parts.name)}">${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}</a>
78 <a href="${h.route_path('repo_changelog', repo_name=c.pull_request.source_repo.repo_name, _query=dict(branch=c.pull_request.source_ref_parts.name))}">${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}</a>
79 79 %else:
80 80 ${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}
81 81 %endif
@@ -107,7 +107,7 b''
107 107 ## branch link is only valid if it is a branch
108 108 <span class="tag">
109 109 %if c.pull_request.target_ref_parts.type == 'branch':
110 <a href="${h.url('changelog_home', repo_name=c.pull_request.target_repo.repo_name, branch=c.pull_request.target_ref_parts.name)}">${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}</a>
110 <a href="${h.route_path('repo_changelog', repo_name=c.pull_request.target_repo.repo_name, _query=dict(branch=c.pull_request.target_ref_parts.name))}">${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}</a>
111 111 %else:
112 112 ${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}
113 113 %endif
@@ -65,7 +65,7 b' for line_number in matching_lines:'
65 65 %endif
66 66 </div>
67 67 <div class="buttons">
68 <a id="file_history_overview_full" href="${h.url('changelog_file_home',repo_name=entry.get('repository',''),revision=entry.get('commit_id', 'tip'),f_path=entry.get('f_path',''))}">
68 <a id="file_history_overview_full" href="${h.route_path('repo_changelog_file',repo_name=entry.get('repository',''),commit_id=entry.get('commit_id', 'tip'),f_path=entry.get('f_path',''))}">
69 69 ${_('Show Full History')}
70 70 </a>
71 71 | ${h.link_to(_('Annotation'), h.route_path('repo_files:annotated', repo_name=entry.get('repository',''),commit_id=entry.get('commit_id', 'tip'),f_path=entry.get('f_path','')))}
@@ -94,7 +94,7 b''
94 94 % if commit_rev == -1:
95 95 ${_ungettext('%(num)s Commit', '%(num)s Commits', 0) % {'num': 0}},
96 96 % else:
97 <a href="${h.url('changelog_home', repo_name=c.repo_name)}">
97 <a href="${h.route_path('repo_changelog', repo_name=c.repo_name)}">
98 98 ${_ungettext('%(num)s Commit', '%(num)s Commits', commit_rev) % {'num': commit_rev}}</a>,
99 99 % endif
100 100
@@ -74,7 +74,7 b''
74 74 ## branch
75 75 %if cs.branch:
76 76 <span class="branchtag tag" title="${h.tooltip(_('Branch %s') % cs.branch)}">
77 <a href="${h.url('changelog_home',repo_name=c.repo_name,branch=cs.branch)}"><i class="icon-code-fork"></i>${h.shorter(cs.branch)}</a>
77 <a href="${h.route_path('repo_changelog',repo_name=c.repo_name,_query=dict(branch=cs.branch))}"><i class="icon-code-fork"></i>${h.shorter(cs.branch)}</a>
78 78 </span>
79 79 %endif
80 80 </div>
@@ -36,6 +36,19 b' from rhodecode.tests import ('
36 36 from rhodecode.tests.utils import AssertResponse
37 37
38 38
39 def route_path(name, params=None, **kwargs):
40 import urllib
41
42 base_url = {
43 'repo_changelog':'/{repo_name}/changelog',
44 'repo_changelog_file':'/{repo_name}/changelog/{commit_id}/{f_path}',
45 }[name].format(**kwargs)
46
47 if params:
48 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
49 return base_url
50
51
39 52 @pytest.mark.usefixtures('app', 'autologin_user')
40 53 @pytest.mark.backends("git", "hg")
41 54 class TestPullrequestsController(object):
@@ -912,14 +925,14 b' class TestPullrequestsController(object)'
912 925 target_children = target.getchildren()
913 926 assert len(target_children) == 1
914 927
915 expected_origin_link = url(
916 'changelog_home',
928 expected_origin_link = route_path(
929 'repo_changelog',
917 930 repo_name=pull_request.source_repo.scm_instance().name,
918 branch='origin')
919 expected_target_link = url(
920 'changelog_home',
931 params=dict(branch='origin'))
932 expected_target_link = route_path(
933 'repo_changelog',
921 934 repo_name=pull_request.target_repo.scm_instance().name,
922 branch='target')
935 params=dict(branch='target'))
923 936 assert origin_children[0].attrib['href'] == expected_origin_link
924 937 assert origin_children[0].text == 'branch: origin'
925 938 assert target_children[0].attrib['href'] == expected_target_link
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now