##// END OF EJS Templates
repo-commits: ported changeset code into pyramid views....
marcink -
r1951:965019b0 default
parent child Browse files
Show More
This diff has been collapsed as it changes many lines, (557 lines changed) Show them Hide them
@@ -0,0 +1,557 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 import collections
24
25 from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound
26 from pyramid.view import view_config
27 from pyramid.renderers import render
28 from pyramid.response import Response
29
30 from rhodecode.apps._base import RepoAppView
31
32 from rhodecode.lib import diffs, codeblocks
33 from rhodecode.lib.auth import (
34 LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, CSRFRequired)
35
36 from rhodecode.lib.compat import OrderedDict
37 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
38 import rhodecode.lib.helpers as h
39 from rhodecode.lib.utils2 import safe_unicode, safe_int
40 from rhodecode.lib.vcs.backends.base import EmptyCommit
41 from rhodecode.lib.vcs.exceptions import (
42 RepositoryError, CommitDoesNotExistError, NodeDoesNotExistError)
43 from rhodecode.model.db import ChangesetComment, ChangesetStatus
44 from rhodecode.model.changeset_status import ChangesetStatusModel
45 from rhodecode.model.comment import CommentsModel
46 from rhodecode.model.meta import Session
47
48
49 log = logging.getLogger(__name__)
50
51
52 def _update_with_GET(params, request):
53 for k in ['diff1', 'diff2', 'diff']:
54 params[k] += request.GET.getall(k)
55
56
57 def get_ignore_ws(fid, request):
58 ig_ws_global = request.GET.get('ignorews')
59 ig_ws = filter(lambda k: k.startswith('WS'), request.GET.getall(fid))
60 if ig_ws:
61 try:
62 return int(ig_ws[0].split(':')[-1])
63 except Exception:
64 pass
65 return ig_ws_global
66
67
68 def _ignorews_url(request, fileid=None):
69 _ = request.translate
70 fileid = str(fileid) if fileid else None
71 params = collections.defaultdict(list)
72 _update_with_GET(params, request)
73 label = _('Show whitespace')
74 tooltiplbl = _('Show whitespace for all diffs')
75 ig_ws = get_ignore_ws(fileid, request)
76 ln_ctx = get_line_ctx(fileid, request)
77
78 if ig_ws is None:
79 params['ignorews'] += [1]
80 label = _('Ignore whitespace')
81 tooltiplbl = _('Ignore whitespace for all diffs')
82 ctx_key = 'context'
83 ctx_val = ln_ctx
84
85 # if we have passed in ln_ctx pass it along to our params
86 if ln_ctx:
87 params[ctx_key] += [ctx_val]
88
89 if fileid:
90 params['anchor'] = 'a_' + fileid
91 return h.link_to(label, request.current_route_path(_query=params),
92 title=tooltiplbl, class_='tooltip')
93
94
95 def get_line_ctx(fid, request):
96 ln_ctx_global = request.GET.get('context')
97 if fid:
98 ln_ctx = filter(lambda k: k.startswith('C'), request.GET.getall(fid))
99 else:
100 _ln_ctx = filter(lambda k: k.startswith('C'), request.GET)
101 ln_ctx = request.GET.get(_ln_ctx[0]) if _ln_ctx else ln_ctx_global
102 if ln_ctx:
103 ln_ctx = [ln_ctx]
104
105 if ln_ctx:
106 retval = ln_ctx[0].split(':')[-1]
107 else:
108 retval = ln_ctx_global
109
110 try:
111 return int(retval)
112 except Exception:
113 return 3
114
115
116 def _context_url(request, fileid=None):
117 """
118 Generates a url for context lines.
119
120 :param fileid:
121 """
122
123 _ = request.translate
124 fileid = str(fileid) if fileid else None
125 ig_ws = get_ignore_ws(fileid, request)
126 ln_ctx = (get_line_ctx(fileid, request) or 3) * 2
127
128 params = collections.defaultdict(list)
129 _update_with_GET(params, request)
130
131 if ln_ctx > 0:
132 params['context'] += [ln_ctx]
133
134 if ig_ws:
135 ig_ws_key = 'ignorews'
136 ig_ws_val = 1
137 params[ig_ws_key] += [ig_ws_val]
138
139 lbl = _('Increase context')
140 tooltiplbl = _('Increase context for all diffs')
141
142 if fileid:
143 params['anchor'] = 'a_' + fileid
144 return h.link_to(lbl, request.current_route_path(_query=params),
145 title=tooltiplbl, class_='tooltip')
146
147
148 class RepoCommitsView(RepoAppView):
149 def load_default_context(self):
150 c = self._get_local_tmpl_context(include_app_defaults=True)
151
152 # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
153 c.repo_info = self.db_repo
154 c.rhodecode_repo = self.rhodecode_vcs_repo
155
156 self._register_global_c(c)
157 return c
158
159 def _commit(self, commit_id_range, method):
160 _ = self.request.translate
161 c = self.load_default_context()
162 c.ignorews_url = _ignorews_url
163 c.context_url = _context_url
164 c.fulldiff = self.request.GET.get('fulldiff')
165
166 # fetch global flags of ignore ws or context lines
167 context_lcl = get_line_ctx('', self.request)
168 ign_whitespace_lcl = get_ignore_ws('', self.request)
169
170 # diff_limit will cut off the whole diff if the limit is applied
171 # otherwise it will just hide the big files from the front-end
172 diff_limit = c.visual.cut_off_limit_diff
173 file_limit = c.visual.cut_off_limit_file
174
175 # get ranges of commit ids if preset
176 commit_range = commit_id_range.split('...')[:2]
177
178 try:
179 pre_load = ['affected_files', 'author', 'branch', 'date',
180 'message', 'parents']
181
182 if len(commit_range) == 2:
183 commits = self.rhodecode_vcs_repo.get_commits(
184 start_id=commit_range[0], end_id=commit_range[1],
185 pre_load=pre_load)
186 commits = list(commits)
187 else:
188 commits = [self.rhodecode_vcs_repo.get_commit(
189 commit_id=commit_id_range, pre_load=pre_load)]
190
191 c.commit_ranges = commits
192 if not c.commit_ranges:
193 raise RepositoryError(
194 'The commit range returned an empty result')
195 except CommitDoesNotExistError:
196 msg = _('No such commit exists for this repository')
197 h.flash(msg, category='error')
198 raise HTTPNotFound()
199 except Exception:
200 log.exception("General failure")
201 raise HTTPNotFound()
202
203 c.changes = OrderedDict()
204 c.lines_added = 0
205 c.lines_deleted = 0
206
207 # auto collapse if we have more than limit
208 collapse_limit = diffs.DiffProcessor._collapse_commits_over
209 c.collapse_all_commits = len(c.commit_ranges) > collapse_limit
210
211 c.commit_statuses = ChangesetStatus.STATUSES
212 c.inline_comments = []
213 c.files = []
214
215 c.statuses = []
216 c.comments = []
217 c.unresolved_comments = []
218 if len(c.commit_ranges) == 1:
219 commit = c.commit_ranges[0]
220 c.comments = CommentsModel().get_comments(
221 self.db_repo.repo_id,
222 revision=commit.raw_id)
223 c.statuses.append(ChangesetStatusModel().get_status(
224 self.db_repo.repo_id, commit.raw_id))
225 # comments from PR
226 statuses = ChangesetStatusModel().get_statuses(
227 self.db_repo.repo_id, commit.raw_id,
228 with_revisions=True)
229 prs = set(st.pull_request for st in statuses
230 if st.pull_request is not None)
231 # from associated statuses, check the pull requests, and
232 # show comments from them
233 for pr in prs:
234 c.comments.extend(pr.comments)
235
236 c.unresolved_comments = CommentsModel()\
237 .get_commit_unresolved_todos(commit.raw_id)
238
239 diff = None
240 # Iterate over ranges (default commit view is always one commit)
241 for commit in c.commit_ranges:
242 c.changes[commit.raw_id] = []
243
244 commit2 = commit
245 commit1 = commit.parents[0] if commit.parents else EmptyCommit()
246
247 _diff = self.rhodecode_vcs_repo.get_diff(
248 commit1, commit2,
249 ignore_whitespace=ign_whitespace_lcl, context=context_lcl)
250 diff_processor = diffs.DiffProcessor(
251 _diff, format='newdiff', diff_limit=diff_limit,
252 file_limit=file_limit, show_full_diff=c.fulldiff)
253
254 commit_changes = OrderedDict()
255 if method == 'show':
256 _parsed = diff_processor.prepare()
257 c.limited_diff = isinstance(_parsed, diffs.LimitedDiffContainer)
258
259 _parsed = diff_processor.prepare()
260
261 def _node_getter(commit):
262 def get_node(fname):
263 try:
264 return commit.get_node(fname)
265 except NodeDoesNotExistError:
266 return None
267 return get_node
268
269 inline_comments = CommentsModel().get_inline_comments(
270 self.db_repo.repo_id, revision=commit.raw_id)
271 c.inline_cnt = CommentsModel().get_inline_comments_count(
272 inline_comments)
273
274 diffset = codeblocks.DiffSet(
275 repo_name=self.db_repo_name,
276 source_node_getter=_node_getter(commit1),
277 target_node_getter=_node_getter(commit2),
278 comments=inline_comments)
279 diffset = diffset.render_patchset(
280 _parsed, commit1.raw_id, commit2.raw_id)
281
282 c.changes[commit.raw_id] = diffset
283 else:
284 # downloads/raw we only need RAW diff nothing else
285 diff = diff_processor.as_raw()
286 c.changes[commit.raw_id] = [None, None, None, None, diff, None, None]
287
288 # sort comments by how they were generated
289 c.comments = sorted(c.comments, key=lambda x: x.comment_id)
290
291 if len(c.commit_ranges) == 1:
292 c.commit = c.commit_ranges[0]
293 c.parent_tmpl = ''.join(
294 '# Parent %s\n' % x.raw_id for x in c.commit.parents)
295
296 if method == 'download':
297 response = Response(diff)
298 response.content_type = 'text/plain'
299 response.content_disposition = (
300 'attachment; filename=%s.diff' % commit_id_range[:12])
301 return response
302 elif method == 'patch':
303 c.diff = safe_unicode(diff)
304 patch = render(
305 'rhodecode:templates/changeset/patch_changeset.mako',
306 self._get_template_context(c), self.request)
307 response = Response(patch)
308 response.content_type = 'text/plain'
309 return response
310 elif method == 'raw':
311 response = Response(diff)
312 response.content_type = 'text/plain'
313 return response
314 elif method == 'show':
315 if len(c.commit_ranges) == 1:
316 html = render(
317 'rhodecode:templates/changeset/changeset.mako',
318 self._get_template_context(c), self.request)
319 return Response(html)
320 else:
321 c.ancestor = None
322 c.target_repo = self.db_repo
323 html = render(
324 'rhodecode:templates/changeset/changeset_range.mako',
325 self._get_template_context(c), self.request)
326 return Response(html)
327
328 raise HTTPBadRequest()
329
330 @LoginRequired()
331 @HasRepoPermissionAnyDecorator(
332 'repository.read', 'repository.write', 'repository.admin')
333 @view_config(
334 route_name='repo_commit', request_method='GET',
335 renderer=None)
336 def repo_commit_show(self):
337 commit_id = self.request.matchdict['commit_id']
338 return self._commit(commit_id, method='show')
339
340 @LoginRequired()
341 @HasRepoPermissionAnyDecorator(
342 'repository.read', 'repository.write', 'repository.admin')
343 @view_config(
344 route_name='repo_commit_raw', request_method='GET',
345 renderer=None)
346 @view_config(
347 route_name='repo_commit_raw_deprecated', request_method='GET',
348 renderer=None)
349 def repo_commit_raw(self):
350 commit_id = self.request.matchdict['commit_id']
351 return self._commit(commit_id, method='raw')
352
353 @LoginRequired()
354 @HasRepoPermissionAnyDecorator(
355 'repository.read', 'repository.write', 'repository.admin')
356 @view_config(
357 route_name='repo_commit_patch', request_method='GET',
358 renderer=None)
359 def repo_commit_patch(self):
360 commit_id = self.request.matchdict['commit_id']
361 return self._commit(commit_id, method='patch')
362
363 @LoginRequired()
364 @HasRepoPermissionAnyDecorator(
365 'repository.read', 'repository.write', 'repository.admin')
366 @view_config(
367 route_name='repo_commit_download', request_method='GET',
368 renderer=None)
369 def repo_commit_download(self):
370 commit_id = self.request.matchdict['commit_id']
371 return self._commit(commit_id, method='download')
372
373 @LoginRequired()
374 @NotAnonymous()
375 @HasRepoPermissionAnyDecorator(
376 'repository.read', 'repository.write', 'repository.admin')
377 @CSRFRequired()
378 @view_config(
379 route_name='repo_commit_comment_create', request_method='POST',
380 renderer='json_ext')
381 def repo_commit_comment_create(self):
382 _ = self.request.translate
383 commit_id = self.request.matchdict['commit_id']
384
385 c = self.load_default_context()
386 status = self.request.POST.get('changeset_status', None)
387 text = self.request.POST.get('text')
388 comment_type = self.request.POST.get('comment_type')
389 resolves_comment_id = self.request.POST.get('resolves_comment_id', None)
390
391 if status:
392 text = text or (_('Status change %(transition_icon)s %(status)s')
393 % {'transition_icon': '>',
394 'status': ChangesetStatus.get_status_lbl(status)})
395
396 multi_commit_ids = []
397 for _commit_id in self.request.POST.get('commit_ids', '').split(','):
398 if _commit_id not in ['', None, EmptyCommit.raw_id]:
399 if _commit_id not in multi_commit_ids:
400 multi_commit_ids.append(_commit_id)
401
402 commit_ids = multi_commit_ids or [commit_id]
403
404 comment = None
405 for current_id in filter(None, commit_ids):
406 comment = CommentsModel().create(
407 text=text,
408 repo=self.db_repo.repo_id,
409 user=self._rhodecode_db_user.user_id,
410 commit_id=current_id,
411 f_path=self.request.POST.get('f_path'),
412 line_no=self.request.POST.get('line'),
413 status_change=(ChangesetStatus.get_status_lbl(status)
414 if status else None),
415 status_change_type=status,
416 comment_type=comment_type,
417 resolves_comment_id=resolves_comment_id
418 )
419
420 # get status if set !
421 if status:
422 # if latest status was from pull request and it's closed
423 # disallow changing status !
424 # dont_allow_on_closed_pull_request = True !
425
426 try:
427 ChangesetStatusModel().set_status(
428 self.db_repo.repo_id,
429 status,
430 self._rhodecode_db_user.user_id,
431 comment,
432 revision=current_id,
433 dont_allow_on_closed_pull_request=True
434 )
435 except StatusChangeOnClosedPullRequestError:
436 msg = _('Changing the status of a commit associated with '
437 'a closed pull request is not allowed')
438 log.exception(msg)
439 h.flash(msg, category='warning')
440 raise HTTPFound(h.route_path(
441 'repo_commit', repo_name=self.db_repo_name,
442 commit_id=current_id))
443
444 # finalize, commit and redirect
445 Session().commit()
446
447 data = {
448 'target_id': h.safeid(h.safe_unicode(
449 self.request.POST.get('f_path'))),
450 }
451 if comment:
452 c.co = comment
453 rendered_comment = render(
454 'rhodecode:templates/changeset/changeset_comment_block.mako',
455 self._get_template_context(c), self.request)
456
457 data.update(comment.get_dict())
458 data.update({'rendered_text': rendered_comment})
459
460 return data
461
462 @LoginRequired()
463 @NotAnonymous()
464 @HasRepoPermissionAnyDecorator(
465 'repository.read', 'repository.write', 'repository.admin')
466 @CSRFRequired()
467 @view_config(
468 route_name='repo_commit_comment_preview', request_method='POST',
469 renderer='string', xhr=True)
470 def repo_commit_comment_preview(self):
471 # Technically a CSRF token is not needed as no state changes with this
472 # call. However, as this is a POST is better to have it, so automated
473 # tools don't flag it as potential CSRF.
474 # Post is required because the payload could be bigger than the maximum
475 # allowed by GET.
476
477 text = self.request.POST.get('text')
478 renderer = self.request.POST.get('renderer') or 'rst'
479 if text:
480 return h.render(text, renderer=renderer, mentions=True)
481 return ''
482
483 @LoginRequired()
484 @NotAnonymous()
485 @HasRepoPermissionAnyDecorator(
486 'repository.read', 'repository.write', 'repository.admin')
487 @CSRFRequired()
488 @view_config(
489 route_name='repo_commit_comment_delete', request_method='POST',
490 renderer='json_ext')
491 def repo_commit_comment_delete(self):
492 commit_id = self.request.matchdict['commit_id']
493 comment_id = self.request.matchdict['comment_id']
494
495 comment = ChangesetComment.get_or_404(safe_int(comment_id))
496 if not comment:
497 log.debug('Comment with id:%s not found, skipping', comment_id)
498 # comment already deleted in another call probably
499 return True
500
501 is_repo_admin = h.HasRepoPermissionAny('repository.admin')(self.db_repo_name)
502 super_admin = h.HasPermissionAny('hg.admin')()
503 comment_owner = (comment.author.user_id == self._rhodecode_db_user.user_id)
504 is_repo_comment = comment.repo.repo_name == self.db_repo_name
505 comment_repo_admin = is_repo_admin and is_repo_comment
506
507 if super_admin or comment_owner or comment_repo_admin:
508 CommentsModel().delete(comment=comment, user=self._rhodecode_db_user)
509 Session().commit()
510 return True
511 else:
512 log.warning('No permissions for user %s to delete comment_id: %s',
513 self._rhodecode_db_user, comment_id)
514 raise HTTPNotFound()
515
516 @LoginRequired()
517 @HasRepoPermissionAnyDecorator(
518 'repository.read', 'repository.write', 'repository.admin')
519 @view_config(
520 route_name='repo_commit_data', request_method='GET',
521 renderer='json_ext', xhr=True)
522 def repo_commit_data(self):
523 commit_id = self.request.matchdict['commit_id']
524 self.load_default_context()
525
526 try:
527 return self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
528 except CommitDoesNotExistError as e:
529 return EmptyCommit(message=str(e))
530
531 @LoginRequired()
532 @HasRepoPermissionAnyDecorator(
533 'repository.read', 'repository.write', 'repository.admin')
534 @view_config(
535 route_name='repo_commit_children', request_method='GET',
536 renderer='json_ext', xhr=True)
537 def repo_commit_children(self):
538 commit_id = self.request.matchdict['commit_id']
539 self.load_default_context()
540
541 commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
542 result = {"results": commit.children}
543 return result
544
545 @LoginRequired()
546 @HasRepoPermissionAnyDecorator(
547 'repository.read', 'repository.write', 'repository.admin')
548 @view_config(
549 route_name='repo_commit_parents', request_method='GET',
550 renderer='json_ext')
551 def repo_commit_parents(self):
552 commit_id = self.request.matchdict['commit_id']
553 self.load_default_context()
554
555 commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
556 result = {"results": commit.parents}
557 return result
@@ -210,11 +210,12 b' gist_alias_url ='
210 210 ## The list should be "," separated and on a single line.
211 211 ##
212 212 ## Most common views to enable:
213 # ChangesetController:changeset_patch
214 # ChangesetController:changeset_raw
215 # RepoFilesView.repo_files_diff
216 # RepoFilesView.repo_archivefile
217 # RepoFilesView.repo_file_raw
213 # RepoCommitsView:repo_commit_download
214 # RepoCommitsView:repo_commit_patch
215 # RepoCommitsView:repo_commit_raw
216 # RepoFilesView:repo_files_diff
217 # RepoFilesView:repo_archivefile
218 # RepoFilesView:repo_file_raw
218 219 # GistView:*
219 220 api_access_controllers_whitelist =
220 221
@@ -184,11 +184,12 b' gist_alias_url ='
184 184 ## The list should be "," separated and on a single line.
185 185 ##
186 186 ## Most common views to enable:
187 # ChangesetController:changeset_patch
188 # ChangesetController:changeset_raw
189 # RepoFilesView.repo_files_diff
190 # RepoFilesView.repo_archivefile
191 # RepoFilesView.repo_file_raw
187 # RepoCommitsView:repo_commit_download
188 # RepoCommitsView:repo_commit_patch
189 # RepoCommitsView:repo_commit_raw
190 # RepoFilesView:repo_files_diff
191 # RepoFilesView:repo_archivefile
192 # RepoFilesView:repo_file_raw
192 193 # GistView:*
193 194 api_access_controllers_whitelist =
194 195
@@ -42,7 +42,7 b' archive.'
42 42 ## Syntax is <ControllerClass>:<function_pattern>.
43 43 ## The list should be "," separated and on a single line.
44 44 ##
45 api_access_controllers_whitelist = ChangesetController:changeset_patch,ChangesetController:changeset_raw,ilesController:raw,FilesController:archivefile,
45 api_access_controllers_whitelist = RepoCommitsView:repo_commit_raw,RepoCommitsView:repo_commit_patch,RepoCommitsView:repo_commit_download
46 46
47 47 After this change, a |RCE| view can be accessed without login by adding a
48 48 GET parameter ``?auth_token=<auth_token>`` to a url. For example to
@@ -172,9 +172,9 b' class HomeView(BaseAppView):'
172 172 'text': entry['commit_id'],
173 173 'type': 'commit',
174 174 'obj': {'repo': entry['repository']},
175 'url': h.url('changeset_home',
175 'url': h.route_path('repo_commit',
176 176 repo_name=entry['repository'],
177 revision=entry['commit_id'])
177 commit_id=entry['commit_id'])
178 178 }
179 179 for entry in result['results']]
180 180
@@ -36,6 +36,8 b' from rhodecode.model.meta import Session'
36 36
37 37 fixture = Fixture()
38 38
39 whitelist_view = ['RepoCommitsView:repo_commit_raw']
40
39 41
40 42 def route_path(name, params=None, **kwargs):
41 43 import urllib
@@ -474,11 +476,10 b' class TestLoginController(object):'
474 476 def test_access_whitelisted_page_via_auth_token(
475 477 self, test_name, auth_token, code, user_admin):
476 478
477 whitelist_entry = ['ChangesetController:changeset_raw']
478 whitelist = self._get_api_whitelist(whitelist_entry)
479 whitelist = self._get_api_whitelist(whitelist_view)
479 480
480 481 with mock.patch.dict('rhodecode.CONFIG', whitelist):
481 assert whitelist_entry == whitelist['api_access_controllers_whitelist']
482 assert whitelist_view == whitelist['api_access_controllers_whitelist']
482 483
483 484 if test_name == 'proper_auth_token':
484 485 auth_token = user_admin.api_key
@@ -492,10 +493,9 b' class TestLoginController(object):'
492 493 status=code)
493 494
494 495 def test_access_page_via_extra_auth_token(self):
495 whitelist = self._get_api_whitelist(
496 ['ChangesetController:changeset_raw'])
496 whitelist = self._get_api_whitelist(whitelist_view)
497 497 with mock.patch.dict('rhodecode.CONFIG', whitelist):
498 assert ['ChangesetController:changeset_raw'] == \
498 assert whitelist_view == \
499 499 whitelist['api_access_controllers_whitelist']
500 500
501 501 new_auth_token = AuthTokenModel().create(
@@ -509,10 +509,9 b' class TestLoginController(object):'
509 509 status=200)
510 510
511 511 def test_access_page_via_expired_auth_token(self):
512 whitelist = self._get_api_whitelist(
513 ['ChangesetController:changeset_raw'])
512 whitelist = self._get_api_whitelist(whitelist_view)
514 513 with mock.patch.dict('rhodecode.CONFIG', whitelist):
515 assert ['ChangesetController:changeset_raw'] == \
514 assert whitelist_view == \
516 515 whitelist['api_access_controllers_whitelist']
517 516
518 517 new_auth_token = AuthTokenModel().create(
@@ -33,10 +33,52 b' def includeme(config):'
33 33 pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True)
34 34
35 35 # repo commits
36
36 37 config.add_route(
37 38 name='repo_commit',
38 39 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}', repo_route=True)
39 40
41 config.add_route(
42 name='repo_commit_children',
43 pattern='/{repo_name:.*?[^/]}/changeset_children/{commit_id}', repo_route=True)
44
45 config.add_route(
46 name='repo_commit_parents',
47 pattern='/{repo_name:.*?[^/]}/changeset_parents/{commit_id}', repo_route=True)
48
49 # still working url for backward compat.
50 config.add_route(
51 name='repo_commit_raw_deprecated',
52 pattern='/{repo_name:.*?[^/]}/raw-changeset/{commit_id}', repo_route=True)
53
54 config.add_route(
55 name='repo_commit_raw',
56 pattern='/{repo_name:.*?[^/]}/changeset-diff/{commit_id}', repo_route=True)
57
58 config.add_route(
59 name='repo_commit_patch',
60 pattern='/{repo_name:.*?[^/]}/changeset-patch/{commit_id}', repo_route=True)
61
62 config.add_route(
63 name='repo_commit_download',
64 pattern='/{repo_name:.*?[^/]}/changeset-download/{commit_id}', repo_route=True)
65
66 config.add_route(
67 name='repo_commit_data',
68 pattern='/{repo_name:.*?[^/]}/changeset-data/{commit_id}', repo_route=True)
69
70 config.add_route(
71 name='repo_commit_comment_create',
72 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/create', repo_route=True)
73
74 config.add_route(
75 name='repo_commit_comment_preview',
76 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/preview', repo_route=True)
77
78 config.add_route(
79 name='repo_commit_comment_delete',
80 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/{comment_id}/delete', repo_route=True)
81
40 82 # repo files
41 83 config.add_route(
42 84 name='repo_archivefile',
@@ -180,21 +222,6 b' def includeme(config):'
180 222 pattern='/{repo_name:.*?[^/]}/pull-request-data',
181 223 repo_route=True, repo_accepted_types=['hg', 'git'])
182 224
183 # commits aka changesets
184 # TODO(dan): handle default landing revision ?
185 config.add_route(
186 name='changeset_home',
187 pattern='/{repo_name:.*?[^/]}/changeset/{revision}',
188 repo_route=True)
189 config.add_route(
190 name='changeset_children',
191 pattern='/{repo_name:.*?[^/]}/changeset_children/{revision}',
192 repo_route=True)
193 config.add_route(
194 name='changeset_parents',
195 pattern='/{repo_name:.*?[^/]}/changeset_parents/{revision}',
196 repo_route=True)
197
198 225 # Settings
199 226 config.add_route(
200 227 name='edit_repo',
@@ -18,18 +18,33 b''
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 from pylons.i18n import ungettext
22 21 import pytest
23 22
24 from rhodecode.tests import *
23 from rhodecode.tests import TestController
24
25 25 from rhodecode.model.db import (
26 26 ChangesetComment, Notification, UserNotification)
27 27 from rhodecode.model.meta import Session
28 28 from rhodecode.lib import helpers as h
29 29
30 30
31 def route_path(name, params=None, **kwargs):
32 import urllib
33
34 base_url = {
35 'repo_commit': '/{repo_name}/changeset/{commit_id}',
36 'repo_commit_comment_create': '/{repo_name}/changeset/{commit_id}/comment/create',
37 'repo_commit_comment_preview': '/{repo_name}/changeset/{commit_id}/comment/preview',
38 'repo_commit_comment_delete': '/{repo_name}/changeset/{commit_id}/comment/{comment_id}/delete',
39 }[name].format(**kwargs)
40
41 if params:
42 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
43 return base_url
44
45
31 46 @pytest.mark.backends("git", "hg", "svn")
32 class TestCommitCommentsController(TestController):
47 class TestRepoCommitCommentsView(TestController):
33 48
34 49 @pytest.fixture(autouse=True)
35 50 def prepare(self, request, pylonsapp):
@@ -62,12 +77,13 b' class TestCommitCommentsController(TestC'
62 77 params = {'text': text, 'csrf_token': self.csrf_token,
63 78 'comment_type': comment_type}
64 79 self.app.post(
65 url(controller='changeset', action='comment',
66 repo_name=backend.repo_name, revision=commit_id), params=params)
80 route_path('repo_commit_comment_create',
81 repo_name=backend.repo_name, commit_id=commit_id),
82 params=params)
67 83
68 84 response = self.app.get(
69 url(controller='changeset', action='index',
70 repo_name=backend.repo_name, revision=commit_id))
85 route_path('repo_commit',
86 repo_name=backend.repo_name, commit_id=commit_id))
71 87
72 88 # test DB
73 89 assert ChangesetComment.query().count() == 1
@@ -103,12 +119,13 b' class TestCommitCommentsController(TestC'
103 119 'csrf_token': self.csrf_token}
104 120
105 121 self.app.post(
106 url(controller='changeset', action='comment',
107 repo_name=backend.repo_name, revision=commit_id), params=params)
122 route_path('repo_commit_comment_create',
123 repo_name=backend.repo_name, commit_id=commit_id),
124 params=params)
108 125
109 126 response = self.app.get(
110 url(controller='changeset', action='index',
111 repo_name=backend.repo_name, revision=commit_id))
127 route_path('repo_commit',
128 repo_name=backend.repo_name, commit_id=commit_id))
112 129
113 130 # test DB
114 131 assert ChangesetComment.query().count() == 1
@@ -153,12 +170,13 b' class TestCommitCommentsController(TestC'
153 170
154 171 params = {'text': text, 'csrf_token': self.csrf_token}
155 172 self.app.post(
156 url(controller='changeset', action='comment',
157 repo_name=backend.repo_name, revision=commit_id), params=params)
173 route_path('repo_commit_comment_create',
174 repo_name=backend.repo_name, commit_id=commit_id),
175 params=params)
158 176
159 177 response = self.app.get(
160 url(controller='changeset', action='index',
161 repo_name=backend.repo_name, revision=commit_id))
178 route_path('repo_commit',
179 repo_name=backend.repo_name, commit_id=commit_id))
162 180 # test DB
163 181 assert ChangesetComment.query().count() == 1
164 182 assert_comment_links(response, ChangesetComment.query().count(), 0)
@@ -183,12 +201,14 b' class TestCommitCommentsController(TestC'
183 201 'csrf_token': self.csrf_token}
184 202
185 203 self.app.post(
186 url(controller='changeset', action='comment',
187 repo_name=backend.repo_name, revision=commit_id), params=params)
204 route_path(
205 'repo_commit_comment_create',
206 repo_name=backend.repo_name, commit_id=commit_id),
207 params=params)
188 208
189 209 response = self.app.get(
190 url(controller='changeset', action='index',
191 repo_name=backend.repo_name, revision=commit_id))
210 route_path('repo_commit',
211 repo_name=backend.repo_name, commit_id=commit_id))
192 212
193 213 # test DB
194 214 assert ChangesetComment.query().count() == 1
@@ -218,9 +238,9 b' class TestCommitCommentsController(TestC'
218 238
219 239 params = {'text': text, 'csrf_token': self.csrf_token}
220 240 self.app.post(
221 url(
222 controller='changeset', action='comment',
223 repo_name=backend.repo_name, revision=commit_id),
241 route_path(
242 'repo_commit_comment_create',
243 repo_name=backend.repo_name, commit_id=commit_id),
224 244 params=params)
225 245
226 246 comments = ChangesetComment.query().all()
@@ -228,16 +248,18 b' class TestCommitCommentsController(TestC'
228 248 comment_id = comments[0].comment_id
229 249
230 250 self.app.post(
231 url(controller='changeset', action='delete_comment',
232 repo_name=backend.repo_name, comment_id=comment_id),
233 params={'_method': 'delete', 'csrf_token': self.csrf_token})
251 route_path('repo_commit_comment_delete',
252 repo_name=backend.repo_name,
253 commit_id=commit_id,
254 comment_id=comment_id),
255 params={'csrf_token': self.csrf_token})
234 256
235 257 comments = ChangesetComment.query().all()
236 258 assert len(comments) == 0
237 259
238 260 response = self.app.get(
239 url(controller='changeset', action='index',
240 repo_name=backend.repo_name, revision=commit_id))
261 route_path('repo_commit',
262 repo_name=backend.repo_name, commit_id=commit_id))
241 263 assert_comment_links(response, 0, 0)
242 264
243 265 @pytest.mark.parametrize('renderer, input, output', [
@@ -251,36 +273,39 b' class TestCommitCommentsController(TestC'
251 273 ('markdown', '**bold**', '<strong>bold</strong>'),
252 274 ], ids=['rst-plain', 'rst-header', 'rst-italics', 'rst-bold', 'md-plain',
253 275 'md-header', 'md-italics', 'md-bold', ])
254 def test_preview(self, renderer, input, output, backend):
276 def test_preview(self, renderer, input, output, backend, xhr_header):
255 277 self.log_user()
256 278 params = {
257 279 'renderer': renderer,
258 280 'text': input,
259 281 'csrf_token': self.csrf_token
260 282 }
261 environ = {
262 'HTTP_X_PARTIAL_XHR': 'true'
263 }
283 commit_id = '0' * 16 # fake this for tests
264 284 response = self.app.post(
265 url(controller='changeset',
266 action='preview_comment',
267 repo_name=backend.repo_name),
285 route_path('repo_commit_comment_preview',
286 repo_name=backend.repo_name, commit_id=commit_id,),
268 287 params=params,
269 extra_environ=environ)
288 extra_environ=xhr_header)
270 289
271 290 response.mustcontain(output)
272 291
273 292
274 293 def assert_comment_links(response, comments, inline_comments):
275 comments_text = ungettext("%d Commit comment",
276 "%d Commit comments", comments) % comments
294 if comments == 1:
295 comments_text = "%d Commit comment" % comments
296 else:
297 comments_text = "%d Commit comments" % comments
298
299 if inline_comments == 1:
300 inline_comments_text = "%d Inline Comment" % inline_comments
301 else:
302 inline_comments_text = "%d Inline Comments" % inline_comments
303
277 304 if comments:
278 305 response.mustcontain('<a href="#comments">%s</a>,' % comments_text)
279 306 else:
280 307 response.mustcontain(comments_text)
281 308
282 inline_comments_text = ungettext("%d Inline Comment", "%d Inline Comments",
283 inline_comments) % inline_comments
284 309 if inline_comments:
285 310 response.mustcontain(
286 311 'id="inline-comments-counter">%s</' % inline_comments_text)
@@ -21,40 +21,56 b''
21 21 import pytest
22 22
23 23 from rhodecode.lib.helpers import _shorten_commit_id
24 from rhodecode.tests import url
24
25
26 def route_path(name, params=None, **kwargs):
27 import urllib
28
29 base_url = {
30 'repo_commit': '/{repo_name}/changeset/{commit_id}',
31 'repo_commit_children': '/{repo_name}/changeset_children/{commit_id}',
32 'repo_commit_parents': '/{repo_name}/changeset_parents/{commit_id}',
33 'repo_commit_raw': '/{repo_name}/changeset-diff/{commit_id}',
34 'repo_commit_patch': '/{repo_name}/changeset-patch/{commit_id}',
35 'repo_commit_download': '/{repo_name}/changeset-download/{commit_id}',
36 'repo_commit_data': '/{repo_name}/changeset-data/{commit_id}',
37 'repo_compare': '/{repo_name}/compare/{source_ref_type}@{source_ref}...{target_ref_type}@{target_ref}',
38 }[name].format(**kwargs)
39
40 if params:
41 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
42 return base_url
25 43
26 44
27 45 @pytest.mark.usefixtures("app")
28 class TestChangesetController(object):
46 class TestRepoCommitView(object):
29 47
30 def test_index(self, backend):
48 def test_show_commit(self, backend):
31 49 commit_id = self.commit_id[backend.alias]
32 response = self.app.get(url(
33 controller='changeset', action='index',
34 repo_name=backend.repo_name, revision=commit_id))
50 response = self.app.get(route_path(
51 'repo_commit', repo_name=backend.repo_name, commit_id=commit_id))
35 52 response.mustcontain('Added a symlink')
36 53 response.mustcontain(commit_id)
37 54 response.mustcontain('No newline at end of file')
38 55
39 def test_index_raw(self, backend):
56 def test_show_raw(self, backend):
40 57 commit_id = self.commit_id[backend.alias]
41 response = self.app.get(url(
42 controller='changeset', action='changeset_raw',
43 repo_name=backend.repo_name, revision=commit_id))
58 response = self.app.get(route_path(
59 'repo_commit_raw',
60 repo_name=backend.repo_name, commit_id=commit_id))
44 61 assert response.body == self.diffs[backend.alias]
45 62
46 def test_index_raw_patch(self, backend):
47 response = self.app.get(url(
48 controller='changeset', action='changeset_patch',
49 repo_name=backend.repo_name,
50 revision=self.commit_id[backend.alias]))
63 def test_show_raw_patch(self, backend):
64 response = self.app.get(route_path(
65 'repo_commit_patch', repo_name=backend.repo_name,
66 commit_id=self.commit_id[backend.alias]))
51 67 assert response.body == self.patches[backend.alias]
52 68
53 def test_index_changeset_download(self, backend):
54 response = self.app.get(url(
55 controller='changeset', action='changeset_download',
69 def test_commit_download(self, backend):
70 response = self.app.get(route_path(
71 'repo_commit_download',
56 72 repo_name=backend.repo_name,
57 revision=self.commit_id[backend.alias]))
73 commit_id=self.commit_id[backend.alias]))
58 74 assert response.body == self.diffs[backend.alias]
59 75
60 76 def test_single_commit_page_different_ops(self, backend):
@@ -64,9 +80,9 b' class TestChangesetController(object):'
64 80 'svn': '337',
65 81 }
66 82 commit_id = commit_id[backend.alias]
67 response = self.app.get(url(
68 controller='changeset', action='index',
69 repo_name=backend.repo_name, revision=commit_id))
83 response = self.app.get(route_path(
84 'repo_commit',
85 repo_name=backend.repo_name, commit_id=commit_id))
70 86
71 87 response.mustcontain(_shorten_commit_id(commit_id))
72 88 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
@@ -98,9 +114,9 b' class TestChangesetController(object):'
98 114 }
99 115 commit_ids = commit_id_range[backend.alias]
100 116 commit_id = '%s...%s' % (commit_ids[0], commit_ids[1])
101 response = self.app.get(url(
102 controller='changeset', action='index',
103 repo_name=backend.repo_name, revision=commit_id))
117 response = self.app.get(route_path(
118 'repo_commit',
119 repo_name=backend.repo_name, commit_id=commit_id))
104 120
105 121 response.mustcontain(_shorten_commit_id(commit_ids[0]))
106 122 response.mustcontain(_shorten_commit_id(commit_ids[1]))
@@ -137,8 +153,8 b' class TestChangesetController(object):'
137 153 '337'),
138 154 }
139 155 commit_ids = commit_id_range[backend.alias]
140 response = self.app.get(url(
141 controller='compare', action='compare',
156 response = self.app.get(route_path(
157 'repo_compare',
142 158 repo_name=backend.repo_name,
143 159 source_ref_type='rev', source_ref=commit_ids[0],
144 160 target_ref_type='rev', target_ref=commit_ids[1], ))
@@ -188,9 +204,10 b' class TestChangesetController(object):'
188 204 def _check_changeset_range(
189 205 self, backend, commit_id_ranges, commit_id_range_result):
190 206 response = self.app.get(
191 url(controller='changeset', action='index',
192 repo_name=backend.repo_name,
193 revision=commit_id_ranges[backend.alias]))
207 route_path('repo_commit',
208 repo_name=backend.repo_name,
209 commit_id=commit_id_ranges[backend.alias]))
210
194 211 expected_result = commit_id_range_result[backend.alias]
195 212 response.mustcontain('{} commits'.format(len(expected_result)))
196 213 for commit_id in expected_result:
@@ -139,8 +139,8 b' class RepoFeedView(RepoAppView):'
139 139 author_name=commit.author,
140 140 description=self._get_description(commit),
141 141 link=h.route_url(
142 'changeset_home', repo_name=self.db_repo_name,
143 revision=commit.raw_id),
142 'repo_commit', repo_name=self.db_repo_name,
143 commit_id=commit.raw_id),
144 144 pubdate=date,)
145 145
146 146 return feed.mime_type, feed.writeString('utf-8')
@@ -185,8 +185,8 b' class RepoFeedView(RepoAppView):'
185 185 author_name=commit.author,
186 186 description=self._get_description(commit),
187 187 link=h.route_url(
188 'changeset_home', repo_name=self.db_repo_name,
189 revision=commit.raw_id),
188 'repo_commit', repo_name=self.db_repo_name,
189 commit_id=commit.raw_id),
190 190 pubdate=date,)
191 191
192 192 return feed.mime_type, feed.writeString('utf-8')
@@ -1043,8 +1043,8 b' class RepoFilesView(RepoAppView):'
1043 1043 log.exception('Error during commit operation')
1044 1044 h.flash(_('Error occurred during commit'), category='error')
1045 1045 raise HTTPFound(
1046 h.route_path('changeset_home', repo_name=self.db_repo_name,
1047 revision='tip'))
1046 h.route_path('repo_commit', repo_name=self.db_repo_name,
1047 commit_id='tip'))
1048 1048
1049 1049 @LoginRequired()
1050 1050 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
@@ -1133,8 +1133,8 b' class RepoFilesView(RepoAppView):'
1133 1133 if content == old_content and filename == org_filename:
1134 1134 h.flash(_('No changes'), category='warning')
1135 1135 raise HTTPFound(
1136 h.route_path('changeset_home', repo_name=self.db_repo_name,
1137 revision='tip'))
1136 h.route_path('repo_commit', repo_name=self.db_repo_name,
1137 commit_id='tip'))
1138 1138 try:
1139 1139 mapping = {
1140 1140 org_f_path: {
@@ -1161,8 +1161,8 b' class RepoFilesView(RepoAppView):'
1161 1161 log.exception('Error occurred during commit')
1162 1162 h.flash(_('Error occurred during commit'), category='error')
1163 1163 raise HTTPFound(
1164 h.route_path('changeset_home', repo_name=self.db_repo_name,
1165 revision='tip'))
1164 h.route_path('repo_commit', repo_name=self.db_repo_name,
1165 commit_id='tip'))
1166 1166
1167 1167 @LoginRequired()
1168 1168 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
@@ -1222,7 +1222,7 b' class RepoFilesView(RepoAppView):'
1222 1222 content = content.file
1223 1223
1224 1224 default_redirect_url = h.route_path(
1225 'changeset_home', repo_name=self.db_repo_name, revision='tip')
1225 'repo_commit', repo_name=self.db_repo_name, commit_id='tip')
1226 1226
1227 1227 # If there's no commit, redirect to repo summary
1228 1228 if type(c.commit) is EmptyCommit:
@@ -429,19 +429,6 b' def make_map(config):'
429 429 controller='admin/repos', action='repo_check',
430 430 requirements=URL_NAME_REQUIREMENTS)
431 431
432 rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}',
433 controller='changeset', revision='tip',
434 conditions={'function': check_repo},
435 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
436 rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}',
437 controller='changeset', revision='tip', action='changeset_children',
438 conditions={'function': check_repo},
439 requirements=URL_NAME_REQUIREMENTS)
440 rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}',
441 controller='changeset', revision='tip', action='changeset_parents',
442 conditions={'function': check_repo},
443 requirements=URL_NAME_REQUIREMENTS)
444
445 432 # repo edit options
446 433 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
447 434 controller='admin/repos', action='edit_fields',
@@ -515,54 +502,6 b' def make_map(config):'
515 502 conditions={'method': ['GET', 'POST'], 'function': check_repo},
516 503 requirements=URL_NAME_REQUIREMENTS)
517 504
518 # still working url for backward compat.
519 rmap.connect('raw_changeset_home_depraced',
520 '/{repo_name}/raw-changeset/{revision}',
521 controller='changeset', action='changeset_raw',
522 revision='tip', conditions={'function': check_repo},
523 requirements=URL_NAME_REQUIREMENTS)
524
525 # new URLs
526 rmap.connect('changeset_raw_home',
527 '/{repo_name}/changeset-diff/{revision}',
528 controller='changeset', action='changeset_raw',
529 revision='tip', conditions={'function': check_repo},
530 requirements=URL_NAME_REQUIREMENTS)
531
532 rmap.connect('changeset_patch_home',
533 '/{repo_name}/changeset-patch/{revision}',
534 controller='changeset', action='changeset_patch',
535 revision='tip', conditions={'function': check_repo},
536 requirements=URL_NAME_REQUIREMENTS)
537
538 rmap.connect('changeset_download_home',
539 '/{repo_name}/changeset-download/{revision}',
540 controller='changeset', action='changeset_download',
541 revision='tip', conditions={'function': check_repo},
542 requirements=URL_NAME_REQUIREMENTS)
543
544 rmap.connect('changeset_comment',
545 '/{repo_name}/changeset/{revision}/comment', jsroute=True,
546 controller='changeset', revision='tip', action='comment',
547 conditions={'function': check_repo},
548 requirements=URL_NAME_REQUIREMENTS)
549
550 rmap.connect('changeset_comment_preview',
551 '/{repo_name}/changeset/comment/preview', jsroute=True,
552 controller='changeset', action='preview_comment',
553 conditions={'function': check_repo, 'method': ['POST']},
554 requirements=URL_NAME_REQUIREMENTS)
555
556 rmap.connect('changeset_comment_delete',
557 '/{repo_name}/changeset/comment/{comment_id}/delete',
558 controller='changeset', action='delete_comment',
559 conditions={'function': check_repo, 'method': ['DELETE']},
560 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
561
562 rmap.connect('changeset_info', '/{repo_name}/changeset_info/{revision}',
563 controller='changeset', action='changeset_info',
564 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
565
566 505 rmap.connect('compare_home',
567 506 '/{repo_name}/compare',
568 507 controller='compare', action='index',
@@ -20,7 +20,6 b''
20 20
21 21 import logging
22 22
23 from pylons import url
24 23 from pylons.i18n.translation import _
25 24 from webhelpers.html.builder import literal
26 25 from webhelpers.html.tags import link_to
@@ -201,6 +200,7 b' class ActionParser(object):'
201 200 return literal(tmpl % (ico, self.action))
202 201
203 202 def get_cs_links(self):
203 from rhodecode.lib import helpers as h
204 204 if self.is_deleted():
205 205 return self.action_params
206 206
@@ -223,8 +223,9 b' class ActionParser(object):'
223 223 _('Show all combined commits %s->%s') % (
224 224 commit_ids[0][:12], commit_ids[-1][:12]
225 225 ),
226 url('changeset_home', repo_name=repo_name,
227 revision=commit_id_range), _('compare view')
226 h.route_path(
227 'repo_commit', repo_name=repo_name,
228 commit_id=commit_id_range), _('compare view')
228 229 )
229 230 )
230 231
@@ -275,6 +276,7 b' class ActionParser(object):'
275 276
276 277 def lnk(self, commit_or_id, repo_name):
277 278 from rhodecode.lib.helpers import tooltip
279 from rhodecode.lib import helpers as h
278 280
279 281 if isinstance(commit_or_id, (BaseCommit, AttributeDict)):
280 282 lazy_cs = True
@@ -292,8 +294,8 b' class ActionParser(object):'
292 294
293 295 else:
294 296 lbl = '%s' % (commit_or_id.short_id[:8])
295 _url = url('changeset_home', repo_name=repo_name,
296 revision=commit_or_id.raw_id)
297 _url = h.route_path('repo_commit', repo_name=repo_name,
298 commit_id=commit_or_id.raw_id)
297 299 title = tooltip(commit_or_id.message)
298 300 else:
299 301 # commit cannot be found/striped/removed etc.
@@ -754,7 +754,7 b' class PermissionCalculator(object):'
754 754 }
755 755
756 756
757 def allowed_auth_token_access(controller_name, whitelist=None, auth_token=None):
757 def allowed_auth_token_access(view_name, whitelist=None, auth_token=None):
758 758 """
759 759 Check if given controller_name is in whitelist of auth token access
760 760 """
@@ -767,16 +767,16 b' def allowed_auth_token_access(controller'
767 767
768 768 auth_token_access_valid = False
769 769 for entry in whitelist:
770 if fnmatch.fnmatch(controller_name, entry):
770 if fnmatch.fnmatch(view_name, entry):
771 771 auth_token_access_valid = True
772 772 break
773 773
774 774 if auth_token_access_valid:
775 log.debug('controller:%s matches entry in whitelist'
776 % (controller_name,))
775 log.debug('view: `%s` matches entry in whitelist: %s'
776 % (view_name, whitelist))
777 777 else:
778 msg = ('controller: %s does *NOT* match any entry in whitelist'
779 % (controller_name,))
778 msg = ('view: `%s` does *NOT* match any entry in whitelist: %s'
779 % (view_name, whitelist))
780 780 if auth_token:
781 781 # if we use auth token key and don't have access it's a warning
782 782 log.warning(msg)
@@ -1575,7 +1575,7 b' def urlify_commits(text_, repository):'
1575 1575 :param text_:
1576 1576 :param repository: repo name to build the URL with
1577 1577 """
1578 from pylons import url # doh, we need to re-import url to mock it later
1578
1579 1579 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1580 1580
1581 1581 def url_func(match_obj):
@@ -1590,8 +1590,8 b' def urlify_commits(text_, repository):'
1590 1590 return tmpl % {
1591 1591 'pref': pref,
1592 1592 'cls': 'revision-link',
1593 'url': url('changeset_home', repo_name=repository,
1594 revision=commit_id, qualified=True),
1593 'url': route_url('repo_commit', repo_name=repository,
1594 commit_id=commit_id),
1595 1595 'commit_id': commit_id,
1596 1596 'suf': suf
1597 1597 }
@@ -15,11 +15,6 b' function registerRCRoutes() {'
15 15 pyroutes.register('new_repo', '/_admin/create_repository', []);
16 16 pyroutes.register('edit_user', '/_admin/users/%(user_id)s/edit', ['user_id']);
17 17 pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']);
18 pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
19 pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']);
20 pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']);
21 pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
22 pyroutes.register('changeset_info', '/%(repo_name)s/changeset_info/%(revision)s', ['repo_name', 'revision']);
23 18 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']);
24 19 pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']);
25 20 pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']);
@@ -111,6 +106,16 b' function registerRCRoutes() {'
111 106 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
112 107 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
113 108 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
109 pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']);
110 pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']);
111 pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']);
112 pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']);
113 pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']);
114 pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']);
115 pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']);
116 pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']);
117 pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']);
118 pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']);
114 119 pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
115 120 pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']);
116 121 pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']);
@@ -146,9 +151,6 b' function registerRCRoutes() {'
146 151 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
147 152 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
148 153 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
149 pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
150 pyroutes.register('changeset_children', '/%(repo_name)s/changeset_children/%(revision)s', ['repo_name', 'revision']);
151 pyroutes.register('changeset_parents', '/%(repo_name)s/changeset_parents/%(revision)s', ['repo_name', 'revision']);
152 154 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
153 155 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
154 156 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
@@ -103,8 +103,9 b' var bindToggleButtons = function() {'
103 103 this.submitButton = $(this.submitForm).find('input[type="submit"]');
104 104 this.submitButtonText = this.submitButton.val();
105 105
106 this.previewUrl = pyroutes.url('changeset_comment_preview',
107 {'repo_name': templateContext.repo_name});
106 this.previewUrl = pyroutes.url('repo_commit_comment_preview',
107 {'repo_name': templateContext.repo_name,
108 'commit_id': templateContext.commit_data.commit_id});
108 109
109 110 if (resolvesCommentId){
110 111 this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
@@ -129,12 +130,12 b' var bindToggleButtons = function() {'
129 130 // based on commitId, or pullRequestId decide where do we submit
130 131 // out data
131 132 if (this.commitId){
132 this.submitUrl = pyroutes.url('changeset_comment',
133 this.submitUrl = pyroutes.url('repo_commit_comment_create',
133 134 {'repo_name': templateContext.repo_name,
134 'revision': this.commitId});
135 this.selfUrl = pyroutes.url('changeset_home',
135 'commit_id': this.commitId});
136 this.selfUrl = pyroutes.url('repo_commit',
136 137 {'repo_name': templateContext.repo_name,
137 'revision': this.commitId});
138 'commit_id': this.commitId});
138 139
139 140 } else if (this.pullRequestId) {
140 141 this.submitUrl = pyroutes.url('pullrequest_comment',
@@ -5,7 +5,7 b''
5 5 (_('Owner'), lambda:base.gravatar_with_user(c.repo_info.user.email), '', ''),
6 6 (_('Created on'), h.format_date(c.repo_info.created_on), '', ''),
7 7 (_('Updated on'), h.format_date(c.repo_info.updated_on), '', ''),
8 (_('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'))), '', ''),
8 (_('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'))), '', ''),
9 9 ]
10 10 %>
11 11
@@ -161,9 +161,9 b''
161 161 if (selectedCheckboxes.length>0){
162 162 var revEnd = selectedCheckboxes[0].name;
163 163 var revStart = selectedCheckboxes[selectedCheckboxes.length-1].name;
164 var url = pyroutes.url('changeset_home',
164 var url = pyroutes.url('repo_commit',
165 165 {'repo_name': '${c.repo_name}',
166 'revision': revStart+'...'+revEnd});
166 'commit_id': revStart+'...'+revEnd});
167 167
168 168 var link = (revStart == revEnd)
169 169 ? _gettext('Show selected commit __S')
@@ -24,11 +24,11 b''
24 24 <div class="changeset-status-ico">
25 25 %if c.statuses.get(commit.raw_id)[2]:
26 26 <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])}">
27 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
27 <div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
28 28 </a>
29 29 %else:
30 <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)}">
31 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
30 <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)}">
31 <div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
32 32 </a>
33 33 %endif
34 34 </div>
@@ -38,7 +38,7 b''
38 38 </td>
39 39 <td class="td-comments comments-col">
40 40 %if c.comments.get(commit.raw_id):
41 <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)}">
41 <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)}">
42 42 <i class="icon-comment"></i> ${len(c.comments[commit.raw_id])}
43 43 </a>
44 44 %endif
@@ -46,7 +46,7 b''
46 46 <td class="td-hash">
47 47 <code>
48 48
49 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id)}">
49 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id)}">
50 50 <span class="${'commit_hash obsolete' if getattr(commit, 'obsolete', None) else 'commit_hash'}">${h.show_id(commit)}</span>
51 51 </a>
52 52 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${commit.raw_id}" title="${_('Copy the full commit id')}"></i>
@@ -15,7 +15,7 b''
15 15 <td class="td-message">
16 16 <div class="log-container">
17 17 <div class="message_history" title="${h.tooltip(cs.message)}">
18 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}">
18 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id)}">
19 19 ${h.shorter(cs.message, 75)}
20 20 </a>
21 21 </div>
@@ -23,7 +23,7 b''
23 23 </td>
24 24 <td class="td-hash">
25 25 <code>
26 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}">
26 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id)}">
27 27 <span>${h.show_id(cs)}</span>
28 28 </a>
29 29 </code>
@@ -21,7 +21,7 b''
21 21 <%def name="main()">
22 22 <script>
23 23 // TODO: marcink switch this to pyroutes
24 AJAX_COMMENT_DELETE_URL = "${h.url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
24 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__')}";
25 25 templateContext.commit_data.commit_id = "${c.commit.raw_id}";
26 26 </script>
27 27 <div class="box">
@@ -137,21 +137,21 b''
137 137 </div>
138 138 <div class="right-content">
139 139 <div class="diff-actions">
140 <a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision=c.commit.raw_id)}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
140 <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'))}">
141 141 ${_('Raw Diff')}
142 142 </a>
143 143 |
144 <a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision=c.commit.raw_id)}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
144 <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'))}">
145 145 ${_('Patch Diff')}
146 146 </a>
147 147 |
148 <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'))}">
148 <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'))}">
149 149 ${_('Download Diff')}
150 150 </a>
151 151 |
152 ${c.ignorews_url(request.GET)}
152 ${c.ignorews_url(request)}
153 153 |
154 ${c.context_url(request.GET)}
154 ${c.context_url(request)}
155 155 </div>
156 156 </div>
157 157 </div>
@@ -221,7 +221,7 b''
221 221 ${comment.generate_comments(c.comments)}
222 222
223 223 ## main comment form and it status
224 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision=c.commit.raw_id),
224 ${comment.comments(h.route_path('repo_commit_comment_create', repo_name=c.repo_name, commit_id=c.commit.raw_id),
225 225 h.commit_status(c.rhodecode_db_repo, c.commit.raw_id))}
226 226 </div>
227 227
@@ -264,14 +264,14 b''
264 264 // >1 links show them to user to choose
265 265 if(!$('#child_link').hasClass('disabled')){
266 266 $.ajax({
267 url: '${h.url('changeset_children',repo_name=c.repo_name, revision=c.commit.raw_id)}',
267 url: '${h.route_path('repo_commit_children',repo_name=c.repo_name, commit_id=c.commit.raw_id)}',
268 268 success: function(data) {
269 269 if(data.results.length === 0){
270 270 $('#child_link').html("${_('No Child Commits')}").addClass('disabled');
271 271 }
272 272 if(data.results.length === 1){
273 273 var commit = data.results[0];
274 window.location = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': commit.raw_id});
274 window.location = pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': commit.raw_id});
275 275 }
276 276 else if(data.results.length === 2){
277 277 $('#child_link').addClass('disabled');
@@ -280,12 +280,12 b''
280 280 _html +='<a title="__title__" href="__url__">__rev__</a> '
281 281 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
282 282 .replace('__title__', data.results[0].message)
283 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[0].raw_id}));
283 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[0].raw_id}));
284 284 _html +=' | ';
285 285 _html +='<a title="__title__" href="__url__">__rev__</a> '
286 286 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
287 287 .replace('__title__', data.results[1].message)
288 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[1].raw_id}));
288 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[1].raw_id}));
289 289 $('#child_link').html(_html);
290 290 }
291 291 }
@@ -300,14 +300,14 b''
300 300 // >1 links show them to user to choose
301 301 if(!$('#parent_link').hasClass('disabled')){
302 302 $.ajax({
303 url: '${h.url("changeset_parents",repo_name=c.repo_name, revision=c.commit.raw_id)}',
303 url: '${h.route_path("repo_commit_parents",repo_name=c.repo_name, commit_id=c.commit.raw_id)}',
304 304 success: function(data) {
305 305 if(data.results.length === 0){
306 306 $('#parent_link').html('${_('No Parent Commits')}').addClass('disabled');
307 307 }
308 308 if(data.results.length === 1){
309 309 var commit = data.results[0];
310 window.location = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': commit.raw_id});
310 window.location = pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': commit.raw_id});
311 311 }
312 312 else if(data.results.length === 2){
313 313 $('#parent_link').addClass('disabled');
@@ -316,12 +316,12 b''
316 316 _html +='<a title="__title__" href="__url__">Parent __rev__</a>'
317 317 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
318 318 .replace('__title__', data.results[0].message)
319 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[0].raw_id}));
319 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[0].raw_id}));
320 320 _html +=' | ';
321 321 _html +='<a title="__title__" href="__url__">Parent __rev__</a>'
322 322 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
323 323 .replace('__title__', data.results[1].message)
324 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[1].raw_id}));
324 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[1].raw_id}));
325 325 $('#parent_link').html(_html);
326 326 }
327 327 }
@@ -100,7 +100,7 b''
100 100 % endif
101 101 % if inline:
102 102 <div class="pr-version-inline">
103 <a href="${h.url.current(version=comment.pull_request_version_id, anchor='comment-{}'.format(comment.comment_id))}">
103 <a href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}">
104 104 % if outdated_at_ver:
105 105 <code class="pr-version-num" title="${_('Outdated comment from pull request version {0}').format(pr_index_ver)}">
106 106 outdated ${'v{}'.format(pr_index_ver)} |
@@ -70,15 +70,15 b''
70 70 </div>
71 71 <div class="right-content">
72 72 <div class="diff-actions">
73 <a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
73 <a href="${h.route_path('repo_commit_raw',repo_name=c.repo_name,commit_id='?')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
74 74 ${_('Raw Diff')}
75 75 </a>
76 76 |
77 <a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
77 <a href="${h.route_path('repo_commit_patch',repo_name=c.repo_name,commit_id='?')}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
78 78 ${_('Patch Diff')}
79 79 </a>
80 80 |
81 <a href="${h.url('changeset_download_home',repo_name=c.repo_name,revision='?',diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
81 <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'))}">
82 82 ${_('Download Diff')}
83 83 </a>
84 84 </div>
@@ -121,7 +121,7 b' collapse_all = len(diffset.files) > coll'
121 121 %endif
122 122 <h2 class="clearinner">
123 123 %if commit:
124 <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> -
124 <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> -
125 125 ${h.age_component(commit.date)} -
126 126 %endif
127 127 %if diffset.limited_diff:
@@ -459,10 +459,10 b' from rhodecode.lib.diffs import NEW_FILE'
459 459
460 460 ## 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)
461 461 %if hasattr(c, 'ignorews_url'):
462 ${c.ignorews_url(request.GET, h.FID('', filediff.patch['filename']))}
462 ${c.ignorews_url(request, h.FID('', filediff.patch['filename']))}
463 463 %endif
464 464 %if hasattr(c, 'context_url'):
465 ${c.context_url(request.GET, h.FID('', filediff.patch['filename']))}
465 ${c.context_url(request, h.FID('', filediff.patch['filename']))}
466 466 %endif
467 467
468 468 %if use_comments:
@@ -31,7 +31,7 b''
31 31 data-revision="${annotation.revision}"
32 32 onclick="$('[data-revision=${annotation.revision}]').toggleClass('cb-line-fresh')"
33 33 style="background: ${bgcolor}">
34 <a class="cb-annotate" href="${h.url('changeset_home',repo_name=c.repo_name,revision=annotation.raw_id)}">
34 <a class="cb-annotate" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=annotation.raw_id)}">
35 35 r${annotation.revision}
36 36 </a>
37 37 </td>
@@ -3,7 +3,7 b''
3 3
4 4 %if c.ancestor:
5 5 <div class="ancestor">${_('Common Ancestor Commit')}:
6 <a href="${h.url('changeset_home', repo_name=c.repo_name, revision=c.ancestor)}">
6 <a href="${h.route_path('repo_commit', repo_name=c.repo_name, commit_id=c.ancestor)}">
7 7 ${h.short_id(c.ancestor)}
8 8 </a>. ${_('Compare was calculated based on this shared commit.')}
9 9 <input id="common_ancestor" type="hidden" name="common_ancestor" value="${c.ancestor}">
@@ -34,9 +34,7 b''
34 34 </td>
35 35 <td class="td-hash">
36 36 <code>
37 <a href="${h.url('changeset_home',
38 repo_name=c.target_repo.repo_name,
39 revision=commit.raw_id)}">
37 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
40 38 r${commit.revision}:${h.short_id(commit.raw_id)}
41 39 </a>
42 40 ${h.hidden('revisions',commit.raw_id)}
@@ -137,15 +137,15 b''
137 137 </div>
138 138 <div class="right-content">
139 139 <div class="diff-actions">
140 <a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
140 <a href="${h.route_path('repo_commit_raw',repo_name=c.repo_name,commit_id='?')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
141 141 ${_('Raw Diff')}
142 142 </a>
143 143 |
144 <a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
144 <a href="${h.route_path('repo_commit_patch',repo_name=c.repo_name,commit_id='?')}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
145 145 ${_('Patch Diff')}
146 146 </a>
147 147 |
148 <a href="${h.url('changeset_download_home',repo_name=c.repo_name,revision='?',diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
148 <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'))}">
149 149 ${_('Download Diff')}
150 150 </a>
151 151 </div>
@@ -170,7 +170,7 b''
170 170 return form_inputs
171 171 %>
172 172 <div>
173 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision='0'*16), None, is_compare=True, form_extras=revs(c.commit_ranges))}
173 ${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))}
174 174 </div>
175 175 </div>
176 176 </div>
@@ -83,7 +83,7 b''
83 83 <%def name="revision(name,rev,tip,author,last_msg)">
84 84 <div>
85 85 %if rev >= 0:
86 <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>
86 <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>
87 87 %else:
88 88 ${_('No commits yet')}
89 89 %endif
@@ -840,7 +840,8 b''
840 840 $('#edit-container').hide();
841 841 $('#preview-container').show();
842 842
843 var url = pyroutes.url('changeset_comment_preview', {'repo_name': 'rhodecode-momentum'});
843 var url = pyroutes.url('repo_commit_comment_preview',
844 {'repo_name': 'rhodecode-momentum', 'commit_id': '000000'});
844 845
845 846 ajaxPOST(url, post_data, function(o) {
846 847 previewbox.html(o);
@@ -17,7 +17,7 b''
17 17 tag: ${tag} <br/>
18 18 % endfor
19 19
20 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>
20 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>
21 21 <pre>
22 22 ${h.urlify_commit_message(commit.message)}
23 23
@@ -23,7 +23,7 b''
23 23 <div class="right-content">
24 24 <div class="tags">
25 25 <code>
26 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=c.commit.raw_id)}">${h.show_id(c.commit)}</a>
26 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">${h.show_id(c.commit)}</a>
27 27 </code>
28 28
29 29 ${file_base.refs(c.commit)}
@@ -217,7 +217,9 b''
217 217 var _renderer = possible_renderer || DEFAULT_RENDERER;
218 218 var post_data = {'text': _text, 'renderer': _renderer, 'csrf_token': CSRF_TOKEN};
219 219 $('#editor_preview').html(_gettext('Loading ...'));
220 var url = pyroutes.url('changeset_comment_preview', {'repo_name': '${c.repo_name}'});
220 var url = pyroutes.url('repo_commit_comment_preview',
221 {'repo_name': '${c.repo_name}',
222 'commit_id': '${c.commit.raw_id}'});
221 223
222 224 ajaxPOST(url, post_data, function(o){
223 225 $('#editor_preview').html(o);
@@ -21,7 +21,7 b''
21 21 </div>
22 22 <div class="right-content">
23 23 <div class="tags tags-main">
24 <code><a href="${h.url('changeset_home',repo_name=c.repo_name,revision=c.commit.raw_id)}">${h.show_id(c.commit)}</a></code>
24 <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>
25 25 ${file_base.refs(c.commit)}
26 26 </div>
27 27 </div>
@@ -33,7 +33,7 b''
33 33 </div>
34 34 <div class="right-content">
35 35 <div class="tags">
36 <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>
36 <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>
37 37
38 38 ${file_base.refs(c.file_last_commit)}
39 39 </div>
@@ -47,7 +47,7 b''
47 47 <div class="code-header">
48 48 <div class="stats">
49 49 <i class="icon-file"></i>
50 <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>
50 <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>
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">
@@ -177,8 +177,9 b''
177 177 var _renderer = possible_renderer || DEFAULT_RENDERER;
178 178 var post_data = {'text': _text, 'renderer': _renderer, 'csrf_token': CSRF_TOKEN};
179 179 $('#editor_preview').html(_gettext('Loading ...'));
180 var url = pyroutes.url('changeset_comment_preview', {'repo_name': '${c.repo_name}'});
181
180 var url = pyroutes.url('repo_commit_comment_preview',
181 {'repo_name': '${c.repo_name}',
182 'commit_id': '${c.commit.raw_id}'});
182 183 ajaxPOST(url, post_data, function(o){
183 184 $('#editor_preview').html(o);
184 185 })
@@ -86,7 +86,7 b''
86 86 <br/>
87 87 % if c.ancestor_commit:
88 88 ${_('Common ancestor')}:
89 <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>
89 <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>
90 90 % endif
91 91 </div>
92 92 <div class="pr-pullinfo">
@@ -513,7 +513,7 b''
513 513 </td>
514 514 <td class="td-hash">
515 515 <code>
516 <a href="${h.url('changeset_home', repo_name=c.target_repo.repo_name, revision=commit.raw_id)}">
516 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
517 517 r${commit.revision}:${h.short_id(commit.raw_id)}
518 518 </a>
519 519 ${h.hidden('revisions', commit.raw_id)}
@@ -31,7 +31,7 b''
31 31 </td>
32 32 <td class="td-commit">
33 33 ${h.link_to(h._shorten_commit_id(entry['commit_id']),
34 h.url('changeset_home',repo_name=entry['repository'],revision=entry['commit_id']))}
34 h.route_path('repo_commit',repo_name=entry['repository'],commit_id=entry['commit_id']))}
35 35 </td>
36 36 <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')}">
37 37 <div class="show_more_col">
@@ -19,11 +19,11 b''
19 19 <div class="changeset-status-ico shortlog">
20 20 %if c.statuses.get(cs.raw_id)[2]:
21 21 <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])}">
22 <div class="${'flag_status %s' % c.statuses.get(cs.raw_id)[0]}"></div>
22 <div class="${'flag_status {}'.format(c.statuses.get(cs.raw_id)[0])}"></div>
23 23 </a>
24 24 %else:
25 <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)}">
26 <div class="${'flag_status %s' % c.statuses.get(cs.raw_id)[0]}"></div>
25 <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)}">
26 <div class="${'flag_status {}'.format(c.statuses.get(cs.raw_id)[0])}"></div>
27 27 </a>
28 28 %endif
29 29 </div>
@@ -33,13 +33,13 b''
33 33 </td>
34 34 <td class="td-comments">
35 35 %if c.comments.get(cs.raw_id,[]):
36 <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)}">
36 <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)}">
37 37 <i class="icon-comment"></i> ${len(c.comments[cs.raw_id])}
38 38 </a>
39 39 %endif
40 40 </td>
41 41 <td class="td-commit">
42 <pre><a href="${h.url('changeset_home', repo_name=c.repo_name, revision=cs.raw_id)}">${h.show_id(cs)}</a></pre>
42 <pre><a href="${h.route_path('repo_commit', repo_name=c.repo_name, commit_id=cs.raw_id)}">${h.show_id(cs)}</a></pre>
43 43 </td>
44 44
45 45 <td class="td-description mid">
@@ -471,7 +471,7 b' class TestCompareController(object):'
471 471 compare_page.contains_change_summary(1, 1, 0)
472 472
473 473 @pytest.mark.xfail_backends("svn")
474 def test_compare_commits(self, backend):
474 def test_compare_commits(self, backend, xhr_header):
475 475 commit0 = backend.repo.get_commit(commit_idx=0)
476 476 commit1 = backend.repo.get_commit(commit_idx=1)
477 477
@@ -483,7 +483,7 b' class TestCompareController(object):'
483 483 target_ref_type="rev",
484 484 target_ref=commit1.raw_id,
485 485 merge='1',),
486 extra_environ={'HTTP_X_PARTIAL_XHR': '1'},)
486 extra_environ=xhr_header,)
487 487
488 488 # outgoing commits between those commits
489 489 compare_page = ComparePage(response)
@@ -397,7 +397,7 b' def test_urlify_commits(sample, expected'
397 397
398 398 expected = _quick_url(expected)
399 399
400 with mock.patch('pylons.url', fake_url):
400 with mock.patch('rhodecode.lib.helpers.route_url', fake_url):
401 401 from rhodecode.lib.helpers import urlify_commits
402 402 assert urlify_commits(sample, 'repo_name') == expected
403 403
@@ -1,7 +1,7 b''
1 1
2 2
3 3 ################################################################################
4 ## RHODECODE ENTERPRISE CONFIGURATION ##
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
5 5 # The %(here)s variable will be replaced with the parent directory of this file#
6 6 ################################################################################
7 7
@@ -64,7 +64,7 b' asyncore_use_poll = true'
64 64 ##########################
65 65 ## GUNICORN WSGI SERVER ##
66 66 ##########################
67 ## run with gunicorn --log-config <inifile.ini> --paste <inifile.ini>
67 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
68 68
69 69 #use = egg:gunicorn#main
70 70 ## Sets the number of process workers. You must set `instance_id = *`
@@ -153,8 +153,10 b' asyncore_use_poll = true'
153 153 ## prefix middleware for RhodeCode.
154 154 ## recommended when using proxy setup.
155 155 ## allows to set RhodeCode under a prefix in server.
156 ## eg https://server.com/<prefix>. Enable `filter-with =` option below as well.
157 ## optionally set prefix like: `prefix = /<your-prefix>`
156 ## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well.
157 ## And set your prefix like: `prefix = /custom_prefix`
158 ## be sure to also set beaker.session.cookie_path = /custom_prefix if you need
159 ## to make your cookies only work on prefix url
158 160 [filter:proxy-prefix]
159 161 use = egg:PasteDeploy#prefix
160 162 prefix = /
@@ -238,27 +240,27 b' rss_items_per_page = 10'
238 240 rss_include_diff = false
239 241
240 242 ## gist URL alias, used to create nicer urls for gist. This should be an
241 ## url that does rewrites to _admin/gists/<gistid>.
243 ## url that does rewrites to _admin/gists/{gistid}.
242 244 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
243 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/<gistid>
245 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid}
244 246 gist_alias_url =
245 247
246 ## List of controllers (using glob pattern syntax) that AUTH TOKENS could be
248 ## List of views (using glob pattern syntax) that AUTH TOKENS could be
247 249 ## used for access.
248 ## Adding ?auth_token = <token> to the url authenticates this request as if it
250 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
249 251 ## came from the the logged in user who own this authentication token.
250 252 ##
251 ## Syntax is <ControllerClass>:<function_pattern>.
252 ## To enable access to raw_files put `FilesController:raw`.
253 ## To enable access to patches add `ChangesetController:changeset_patch`.
253 ## list of all views can be found under `_admin/permissions/auth_token_access`
254 254 ## The list should be "," separated and on a single line.
255 255 ##
256 ## Recommended controllers to enable:
257 # ChangesetController:changeset_patch,
258 # ChangesetController:changeset_raw,
259 # FilesController:raw,
260 # FilesController:archivefile,
261 # GistsController:*,
256 ## Most common views to enable:
257 # RepoCommitsView:repo_commit_download
258 # RepoCommitsView:repo_commit_patch
259 # RepoCommitsView:repo_commit_raw
260 # RepoFilesView:repo_files_diff
261 # RepoFilesView:repo_archivefile
262 # RepoFilesView:repo_file_raw
263 # GistView:*
262 264 api_access_controllers_whitelist =
263 265
264 266 ## default encoding used to convert from and to unicode
@@ -421,15 +423,15 b' beaker.session.lock_dir = %(here)s/rc/da'
421 423
422 424 ## Secure encrypted cookie. Requires AES and AES python libraries
423 425 ## you must disable beaker.session.secret to use this
424 #beaker.session.encrypt_key = <key_for_encryption>
425 #beaker.session.validate_key = <validation_key>
426 #beaker.session.encrypt_key = key_for_encryption
427 #beaker.session.validate_key = validation_key
426 428
427 429 ## sets session as invalid(also logging out user) if it haven not been
428 430 ## accessed for given amount of time in seconds
429 431 beaker.session.timeout = 2592000
430 432 beaker.session.httponly = true
431 ## Path to use for the cookie.
432 #beaker.session.cookie_path = /<your-prefix>
433 ## Path to use for the cookie. Set to prefix if you use prefix middleware
434 #beaker.session.cookie_path = /custom_prefix
433 435
434 436 ## uncomment for https secure cookie
435 437 beaker.session.secure = false
@@ -447,8 +449,8 b' beaker.session.auto = false'
447 449 ## Full text search indexer is available in rhodecode-tools under
448 450 ## `rhodecode-tools index` command
449 451
450 # WHOOSH Backend, doesn't require additional services to run
451 # it works good with few dozen repos
452 ## WHOOSH Backend, doesn't require additional services to run
453 ## it works good with few dozen repos
452 454 search.module = rhodecode.lib.index.whoosh
453 455 search.location = %(here)s/data/index
454 456
@@ -459,15 +461,21 b' search.location = %(here)s/data/index'
459 461 ## in the system. It's also used by the chat system
460 462
461 463 channelstream.enabled = false
462 # location of channelstream server on the backend
464
465 ## server address for channelstream server on the backend
463 466 channelstream.server = 127.0.0.1:9800
464 467 ## location of the channelstream server from outside world
465 ## most likely this would be an http server special backend URL, that handles
466 ## websocket connections see nginx example for config
468 ## use ws:// for http or wss:// for https. This address needs to be handled
469 ## by external HTTP server such as Nginx or Apache
470 ## see nginx/apache configuration examples in our docs
467 471 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
468 472 channelstream.secret = secret
469 473 channelstream.history.location = %(here)s/channelstream_history
470 474
475 ## Internal application path that Javascript uses to connect into.
476 ## If you use proxy-prefix the prefix should be added before /_channelstream
477 channelstream.proxy_path = /_channelstream
478
471 479
472 480 ###################################
473 481 ## APPENLIGHT CONFIG ##
@@ -541,19 +549,19 b' set debug = false'
541 549 ##############
542 550 debug_style = false
543 551
544 #########################################################
545 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
546 #########################################################
547 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db
552 ###########################################
553 ### MAIN RHODECODE DATABASE CONFIG ###
554 ###########################################
555 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db?timeout=30
548 556 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode_test
549 557 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode_test
550 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db
558 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db?timeout=30
551 559
552 560 # see sqlalchemy docs for other advanced settings
553 561
554 562 ## print the sql statements to output
555 563 sqlalchemy.db1.echo = false
556 ## recycle the connections after this ammount of seconds
564 ## recycle the connections after this amount of seconds
557 565 sqlalchemy.db1.pool_recycle = 3600
558 566 sqlalchemy.db1.convert_unicode = true
559 567
@@ -575,7 +583,7 b' vcs.server = localhost:9901'
575 583
576 584 ## Web server connectivity protocol, responsible for web based VCS operatations
577 585 ## Available protocols are:
578 ## `http` - using http-rpc backend
586 ## `http` - use http-rpc backend (default)
579 587 vcs.server.protocol = http
580 588
581 589 ## Push/Pull operations protocol, available options are:
@@ -584,7 +592,7 b' vcs.server.protocol = http'
584 592 vcs.scm_app_implementation = http
585 593
586 594 ## Push/Pull operations hooks protocol, available options are:
587 ## `http` - using http-rpc backend
595 ## `http` - use http-rpc backend (default)
588 596 vcs.hooks.protocol = http
589 597
590 598 vcs.server.log_level = debug
@@ -613,12 +621,19 b' svn.proxy.generate_config = false'
613 621 svn.proxy.list_parent_path = true
614 622 ## Set location and file name of generated config file.
615 623 svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
616 ## File system path to the directory containing the repositories served by
617 ## RhodeCode.
618 svn.proxy.parent_path_root = /path/to/repo_store
619 ## Used as a prefix to the <Location> block in the generated config file. In
620 ## most cases it should be set to `/`.
624 ## Used as a prefix to the `Location` block in the generated config file.
625 ## In most cases it should be set to `/`.
621 626 svn.proxy.location_root = /
627 ## Command to reload the mod dav svn configuration on change.
628 ## Example: `/etc/init.d/apache2 reload`
629 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
630 ## If the timeout expires before the reload command finishes, the command will
631 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
632 #svn.proxy.reload_timeout = 10
633
634 ## Dummy marker to add new entries after.
635 ## Add any custom entries below. Please don't remove.
636 custom.conf = 1
622 637
623 638
624 639 ################################
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now