##// END OF EJS Templates
implements #308 rewrote diffs to enable displaying full diff on each file...
marcink -
r1789:17caf4ef beta
parent child Browse files
Show More
@@ -46,6 +46,7 b' from rhodecode.lib import diffs'
46 from rhodecode.model.db import ChangesetComment
46 from rhodecode.model.db import ChangesetComment
47 from rhodecode.model.comment import ChangesetCommentsModel
47 from rhodecode.model.comment import ChangesetCommentsModel
48 from rhodecode.model.meta import Session
48 from rhodecode.model.meta import Session
49 from rhodecode.lib.diffs import wrapped_diff
49
50
50 log = logging.getLogger(__name__)
51 log = logging.getLogger(__name__)
51
52
@@ -145,15 +146,6 b' def _context_url(fileid=None):'
145 return h.link_to(lbl, h.url.current(**params))
146 return h.link_to(lbl, h.url.current(**params))
146
147
147
148
148 def wrap_to_table(str_):
149 return '''<table class="code-difftable">
150 <tr class="line no-comment">
151 <td class="lineno new"></td>
152 <td class="code no-comment"><pre>%s</pre></td>
153 </tr>
154 </table>''' % str_
155
156
157 class ChangesetController(BaseRepoController):
149 class ChangesetController(BaseRepoController):
158
150
159 @LoginRequired()
151 @LoginRequired()
@@ -192,10 +184,11 b' class ChangesetController(BaseRepoContro'
192 return redirect(url('home'))
184 return redirect(url('home'))
193
185
194 c.changes = OrderedDict()
186 c.changes = OrderedDict()
195 c.sum_added = 0
187
196 c.sum_removed = 0
188 c.lines_added = 0 # count of lines added
197 c.lines_added = 0
189 c.lines_deleted = 0 # count of lines removes
198 c.lines_deleted = 0
190
191 cumulative_diff = 0
199 c.cut_off = False # defines if cut off limit is reached
192 c.cut_off = False # defines if cut off limit is reached
200
193
201 c.comments = []
194 c.comments = []
@@ -220,37 +213,19 b' class ChangesetController(BaseRepoContro'
220 # ADDED FILES
213 # ADDED FILES
221 #==================================================================
214 #==================================================================
222 for node in changeset.added:
215 for node in changeset.added:
223
216 fid = h.FID(revision, node.path)
224 filenode_old = FileNode(node.path, '', EmptyChangeset())
217 line_context_lcl = get_line_ctx(fid, request.GET)
225 if filenode_old.is_binary or node.is_binary:
218 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
226 diff = wrap_to_table(_('binary file'))
219 lim = self.cut_off_limit
227 st = (0, 0)
220 if cumulative_diff > self.cut_off_limit:
228 else:
221 lim = -1
229 # in this case node.size is good parameter since those are
222 size, cs1, cs2, diff, st = wrapped_diff(filenode_old=None,
230 # added nodes and their size defines how many changes were
223 filenode_new=node,
231 # made
224 cut_off_limit=lim,
232 c.sum_added += node.size
225 ignore_whitespace=ign_whitespace_lcl,
233 fid = h.FID(revision, node.path)
226 line_context=line_context_lcl,
234 line_context_lcl = get_line_ctx(fid, request.GET)
227 enable_comments=enable_comments)
235 ignore_whitespace_lcl = get_ignore_ws(fid, request.GET)
228 cumulative_diff += size
236 if c.sum_added < self.cut_off_limit:
237 f_gitdiff = diffs.get_gitdiff(filenode_old, node,
238 ignore_whitespace=ignore_whitespace_lcl,
239 context=line_context_lcl)
240 d = diffs.DiffProcessor(f_gitdiff, format='gitdiff')
241
242 st = d.stat()
243 diff = d.as_html(enable_comments=enable_comments)
244
245 else:
246 diff = wrap_to_table(_('Changeset is to big and '
247 'was cut off, see raw '
248 'changeset instead'))
249 c.cut_off = True
250 break
251
252 cs1 = None
253 cs2 = node.last_changeset.raw_id
254 c.lines_added += st[0]
229 c.lines_added += st[0]
255 c.lines_deleted += st[1]
230 c.lines_deleted += st[1]
256 c.changes[changeset.raw_id].append(('added', node, diff,
231 c.changes[changeset.raw_id].append(('added', node, diff,
@@ -259,60 +234,37 b' class ChangesetController(BaseRepoContro'
259 #==================================================================
234 #==================================================================
260 # CHANGED FILES
235 # CHANGED FILES
261 #==================================================================
236 #==================================================================
262 if not c.cut_off:
237 for node in changeset.changed:
263 for node in changeset.changed:
238 try:
264 try:
239 filenode_old = changeset_parent.get_node(node.path)
265 filenode_old = changeset_parent.get_node(node.path)
240 except ChangesetError:
266 except ChangesetError:
241 log.warning('Unable to fetch parent node for diff')
267 log.warning('Unable to fetch parent node for diff')
242 filenode_old = FileNode(node.path, '', EmptyChangeset())
268 filenode_old = FileNode(node.path, '',
269 EmptyChangeset())
270
271 if filenode_old.is_binary or node.is_binary:
272 diff = wrap_to_table(_('binary file'))
273 st = (0, 0)
274 else:
275
243
276 if c.sum_removed < self.cut_off_limit:
244 fid = h.FID(revision, node.path)
277 fid = h.FID(revision, node.path)
245 line_context_lcl = get_line_ctx(fid, request.GET)
278 line_context_lcl = get_line_ctx(fid, request.GET)
246 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
279 ignore_whitespace_lcl = get_ignore_ws(fid, request.GET,)
247 lim = self.cut_off_limit
280 f_gitdiff = diffs.get_gitdiff(filenode_old, node,
248 if cumulative_diff > self.cut_off_limit:
281 ignore_whitespace=ignore_whitespace_lcl,
249 lim = -1
282 context=line_context_lcl)
250 size, cs1, cs2, diff, st = wrapped_diff(filenode_old=filenode_old,
283 d = diffs.DiffProcessor(f_gitdiff,
251 filenode_new=node,
284 format='gitdiff')
252 cut_off_limit=lim,
285 st = d.stat()
253 ignore_whitespace=ign_whitespace_lcl,
286 if (st[0] + st[1]) * 256 > self.cut_off_limit:
254 line_context=line_context_lcl,
287 diff = wrap_to_table(_('Diff is to big '
255 enable_comments=enable_comments)
288 'and was cut off, see '
256 cumulative_diff += size
289 'raw diff instead'))
257 c.lines_added += st[0]
290 else:
258 c.lines_deleted += st[1]
291 diff = d.as_html(enable_comments=enable_comments)
259 c.changes[changeset.raw_id].append(('changed', node, diff,
292
260 cs1, cs2, st))
293 if diff:
294 c.sum_removed += len(diff)
295 else:
296 diff = wrap_to_table(_('Changeset is to big and '
297 'was cut off, see raw '
298 'changeset instead'))
299 c.cut_off = True
300 break
301
302 cs1 = filenode_old.last_changeset.raw_id
303 cs2 = node.last_changeset.raw_id
304 c.lines_added += st[0]
305 c.lines_deleted += st[1]
306 c.changes[changeset.raw_id].append(('changed', node, diff,
307 cs1, cs2, st))
308
261
309 #==================================================================
262 #==================================================================
310 # REMOVED FILES
263 # REMOVED FILES
311 #==================================================================
264 #==================================================================
312 if not c.cut_off:
265 for node in changeset.removed:
313 for node in changeset.removed:
266 c.changes[changeset.raw_id].append(('removed', node, None,
314 c.changes[changeset.raw_id].append(('removed', node, None,
267 None, None, (0, 0)))
315 None, None, (0, 0)))
316
268
317 # count inline comments
269 # count inline comments
318 for path, lines in c.inline_comments:
270 for path, lines in c.inline_comments:
@@ -27,19 +27,18 b' import os'
27 import logging
27 import logging
28 import traceback
28 import traceback
29
29
30 from os.path import join as jn
30 from pylons import request, response, tmpl_context as c, url
31
32 from pylons import request, response, session, tmpl_context as c, url
33 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
34 from pylons.controllers.util import redirect
32 from pylons.controllers.util import redirect
35 from pylons.decorators import jsonify
33 from pylons.decorators import jsonify
36
34
37 from vcs.conf import settings
35 from vcs.conf import settings
38 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
36 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
39 EmptyRepositoryError, ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError
37 EmptyRepositoryError, ImproperArchiveTypeError, VCSError, \
40 from vcs.nodes import FileNode, NodeKind
38 NodeAlreadyExistsError
39 from vcs.nodes import FileNode
41
40
42
41 from rhodecode.lib.compat import OrderedDict
43 from rhodecode.lib import convert_line_endings, detect_mode, safe_str
42 from rhodecode.lib import convert_line_endings, detect_mode, safe_str
44 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
43 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
45 from rhodecode.lib.base import BaseRepoController, render
44 from rhodecode.lib.base import BaseRepoController, render
@@ -47,6 +46,9 b' from rhodecode.lib.utils import EmptyCha'
47 from rhodecode.lib import diffs
46 from rhodecode.lib import diffs
48 import rhodecode.lib.helpers as h
47 import rhodecode.lib.helpers as h
49 from rhodecode.model.repo import RepoModel
48 from rhodecode.model.repo import RepoModel
49 from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\
50 _context_url, get_line_ctx, get_ignore_ws
51 from rhodecode.lib.diffs import wrapped_diff
50
52
51 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
52
54
@@ -105,7 +107,6 b' class FilesController(BaseRepoController'
105
107
106 return file_node
108 return file_node
107
109
108
109 def __get_paths(self, changeset, starting_path):
110 def __get_paths(self, changeset, starting_path):
110 """recursive walk in root dir and return a set of all path in that dir
111 """recursive walk in root dir and return a set of all path in that dir
111 based on repository walk function
112 based on repository walk function
@@ -128,7 +129,7 b' class FilesController(BaseRepoController'
128 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
129 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
129 'repository.admin')
130 'repository.admin')
130 def index(self, repo_name, revision, f_path):
131 def index(self, repo_name, revision, f_path):
131 #reditect to given revision from form if given
132 # redirect to given revision from form if given
132 post_revision = request.POST.get('at_rev', None)
133 post_revision = request.POST.get('at_rev', None)
133 if post_revision:
134 if post_revision:
134 cs = self.__get_cs_or_redirect(post_revision, repo_name)
135 cs = self.__get_cs_or_redirect(post_revision, repo_name)
@@ -141,7 +142,7 b' class FilesController(BaseRepoController'
141
142
142 cur_rev = c.changeset.revision
143 cur_rev = c.changeset.revision
143
144
144 #prev link
145 # prev link
145 try:
146 try:
146 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
147 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
147 c.url_prev = url('files_home', repo_name=c.repo_name,
148 c.url_prev = url('files_home', repo_name=c.repo_name,
@@ -151,7 +152,7 b' class FilesController(BaseRepoController'
151 except (ChangesetDoesNotExistError, VCSError):
152 except (ChangesetDoesNotExistError, VCSError):
152 c.url_prev = '#'
153 c.url_prev = '#'
153
154
154 #next link
155 # next link
155 try:
156 try:
156 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
157 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
157 c.url_next = url('files_home', repo_name=c.repo_name,
158 c.url_next = url('files_home', repo_name=c.repo_name,
@@ -161,7 +162,7 b' class FilesController(BaseRepoController'
161 except (ChangesetDoesNotExistError, VCSError):
162 except (ChangesetDoesNotExistError, VCSError):
162 c.url_next = '#'
163 c.url_next = '#'
163
164
164 #files or dirs
165 # files or dirs
165 try:
166 try:
166 c.file = c.changeset.get_node(f_path)
167 c.file = c.changeset.get_node(f_path)
167
168
@@ -407,13 +408,17 b' class FilesController(BaseRepoController'
407 def diff(self, repo_name, f_path):
408 def diff(self, repo_name, f_path):
408 ignore_whitespace = request.GET.get('ignorews') == '1'
409 ignore_whitespace = request.GET.get('ignorews') == '1'
409 line_context = request.GET.get('context', 3)
410 line_context = request.GET.get('context', 3)
410 diff1 = request.GET.get('diff1')
411 diff1 = request.GET.get('diff1', '')
411 diff2 = request.GET.get('diff2')
412 diff2 = request.GET.get('diff2', '')
412 c.action = request.GET.get('diff')
413 c.action = request.GET.get('diff')
413 c.no_changes = diff1 == diff2
414 c.no_changes = diff1 == diff2
414 c.f_path = f_path
415 c.f_path = f_path
415 c.big_diff = False
416 c.big_diff = False
416
417 c.anchor_url = anchor_url
418 c.ignorews_url = _ignorews_url
419 c.context_url = _context_url
420 c.changes = OrderedDict()
421 c.changes[diff2] = []
417 try:
422 try:
418 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
423 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
419 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
424 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
@@ -429,14 +434,14 b' class FilesController(BaseRepoController'
429 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
434 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
430 node2 = FileNode('.', '', changeset=c.changeset_2)
435 node2 = FileNode('.', '', changeset=c.changeset_2)
431 except RepositoryError:
436 except RepositoryError:
432 return redirect(url('files_home',
437 return redirect(url('files_home', repo_name=c.repo_name,
433 repo_name=c.repo_name, f_path=f_path))
438 f_path=f_path))
434
439
435 if c.action == 'download':
440 if c.action == 'download':
436 _diff = diffs.get_gitdiff(node1, node2,
441 _diff = diffs.get_gitdiff(node1, node2,
437 ignore_whitespace=ignore_whitespace,
442 ignore_whitespace=ignore_whitespace,
438 context=line_context)
443 context=line_context)
439 diff = diffs.DiffProcessor(_diff,format='gitdiff')
444 diff = diffs.DiffProcessor(_diff, format='gitdiff')
440
445
441 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
446 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
442 response.content_type = 'text/plain'
447 response.content_type = 'text/plain'
@@ -448,42 +453,25 b' class FilesController(BaseRepoController'
448 _diff = diffs.get_gitdiff(node1, node2,
453 _diff = diffs.get_gitdiff(node1, node2,
449 ignore_whitespace=ignore_whitespace,
454 ignore_whitespace=ignore_whitespace,
450 context=line_context)
455 context=line_context)
451 diff = diffs.DiffProcessor(_diff,format='gitdiff')
456 diff = diffs.DiffProcessor(_diff, format='gitdiff')
452 response.content_type = 'text/plain'
457 response.content_type = 'text/plain'
453 return diff.raw_diff()
458 return diff.raw_diff()
454
459
455 elif c.action == 'diff':
456 if node1.is_binary or node2.is_binary:
457 c.cur_diff = _('Binary file')
458 elif node1.size > self.cut_off_limit or \
459 node2.size > self.cut_off_limit:
460 c.cur_diff = ''
461 c.big_diff = True
462 else:
463 _diff = diffs.get_gitdiff(node1, node2,
464 ignore_whitespace=ignore_whitespace,
465 context=line_context)
466 diff = diffs.DiffProcessor(_diff,format='gitdiff')
467 c.cur_diff = diff.as_html()
468 else:
460 else:
461 fid = h.FID(diff2, node2.path)
462 line_context_lcl = get_line_ctx(fid, request.GET)
463 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
469
464
470 #default option
465 lim = request.GET.get('fulldiff') or self.cut_off_limit
471 if node1.is_binary or node2.is_binary:
466 _, cs1, cs2, diff, st = wrapped_diff(filenode_old=node1,
472 c.cur_diff = _('Binary file')
467 filenode_new=node2,
473 elif node1.size > self.cut_off_limit or \
468 cut_off_limit=lim,
474 node2.size > self.cut_off_limit:
469 ignore_whitespace=ign_whitespace_lcl,
475 c.cur_diff = ''
470 line_context=line_context_lcl,
476 c.big_diff = True
471 enable_comments=False)
477
472
478 else:
473 c.changes = [('', node2, diff, cs1, cs2, st,)]
479 _diff = diffs.get_gitdiff(node1, node2,
480 ignore_whitespace=ignore_whitespace,
481 context=line_context)
482 diff = diffs.DiffProcessor(_diff,format='gitdiff')
483 c.cur_diff = diff.as_html()
484
474
485 if not c.cur_diff and not c.big_diff:
486 c.no_changes = True
487 return render('files/file_diff.html')
475 return render('files/file_diff.html')
488
476
489 def _get_node_history(self, cs, f_path):
477 def _get_node_history(self, cs, f_path):
@@ -501,12 +489,10 b' class FilesController(BaseRepoController'
501 hist_l.append(changesets_group)
489 hist_l.append(changesets_group)
502
490
503 for name, chs in c.rhodecode_repo.branches.items():
491 for name, chs in c.rhodecode_repo.branches.items():
504 #chs = chs.split(':')[-1]
505 branches_group[0].append((chs, name),)
492 branches_group[0].append((chs, name),)
506 hist_l.append(branches_group)
493 hist_l.append(branches_group)
507
494
508 for name, chs in c.rhodecode_repo.tags.items():
495 for name, chs in c.rhodecode_repo.tags.items():
509 #chs = chs.split(':')[-1]
510 tags_group[0].append((chs, name),)
496 tags_group[0].append((chs, name),)
511 hist_l.append(tags_group)
497 hist_l.append(tags_group)
512
498
@@ -27,12 +27,66 b''
27
27
28 import re
28 import re
29 import difflib
29 import difflib
30 import markupsafe
31 from itertools import tee, imap
30
32
31 from itertools import tee, imap
33 from pylons.i18n.translation import _
32
34
33 from vcs.exceptions import VCSError
35 from vcs.exceptions import VCSError
34 from vcs.nodes import FileNode
36 from vcs.nodes import FileNode
35 import markupsafe
37
38 from rhodecode.lib.utils import EmptyChangeset
39
40
41 def wrap_to_table(str_):
42 return '''<table class="code-difftable">
43 <tr class="line no-comment">
44 <td class="lineno new"></td>
45 <td class="code no-comment"><pre>%s</pre></td>
46 </tr>
47 </table>''' % str_
48
49
50 def wrapped_diff(filenode_old, filenode_new, cut_off_limit=None,
51 ignore_whitespace=True, line_context=3,
52 enable_comments=False):
53 """
54 returns a wrapped diff into a table, checks for cut_off_limit and presents
55 proper message
56 """
57
58 if filenode_old is None:
59 filenode_old = FileNode(filenode_new.path, '', EmptyChangeset())
60
61 if filenode_old.is_binary or filenode_new.is_binary:
62 diff = wrap_to_table(_('binary file'))
63 stats = (0, 0)
64 size = 0
65
66 elif cut_off_limit != -1 and (cut_off_limit is None or
67 (filenode_old.size < cut_off_limit and filenode_new.size < cut_off_limit)):
68
69 f_gitdiff = get_gitdiff(filenode_old, filenode_new,
70 ignore_whitespace=ignore_whitespace,
71 context=line_context)
72 diff_processor = DiffProcessor(f_gitdiff, format='gitdiff')
73
74 diff = diff_processor.as_html(enable_comments=enable_comments)
75 stats = diff_processor.stat()
76 size = len(diff or '')
77 else:
78 diff = wrap_to_table(_('Changeset was to big and was cut off, use '
79 'diff menu to display this diff'))
80 stats = (0, 0)
81 size = 0
82
83 if not diff:
84 diff = wrap_to_table(_('No changes detected'))
85
86 cs1 = filenode_old.last_changeset.raw_id
87 cs2 = filenode_new.last_changeset.raw_id
88
89 return size, cs1, cs2, diff, stats
36
90
37
91
38 def get_gitdiff(filenode_old, filenode_new, ignore_whitespace=True, context=3):
92 def get_gitdiff(filenode_old, filenode_new, ignore_whitespace=True, context=3):
@@ -263,8 +317,8 b' class DiffProcessor(object):'
263 lines.append({
317 lines.append({
264 'old_lineno': '...',
318 'old_lineno': '...',
265 'new_lineno': '...',
319 'new_lineno': '...',
266 'action': 'context',
320 'action': 'context',
267 'line': line,
321 'line': line,
268 })
322 })
269 else:
323 else:
270 skipfirst = False
324 skipfirst = False
@@ -371,34 +425,40 b' class DiffProcessor(object):'
371 """
425 """
372
426
373 if condition:
427 if condition:
374 return '''<a href="%(url)s">%(label)s</a>''' % {'url': url,
428 return '''<a href="%(url)s">%(label)s</a>''' % {
375 'label': label}
429 'url': url,
430 'label': label
431 }
376 else:
432 else:
377 return label
433 return label
378 diff_lines = self.prepare()
434 diff_lines = self.prepare()
379 _html_empty = True
435 _html_empty = True
380 _html = []
436 _html = []
381 _html.append('''<table class="%(table_class)s">\n''' \
437 _html.append('''<table class="%(table_class)s">\n''' % {
382 % {'table_class': table_class})
438 'table_class': table_class
439 })
383 for diff in diff_lines:
440 for diff in diff_lines:
384 for line in diff['chunks']:
441 for line in diff['chunks']:
385 _html_empty = False
442 _html_empty = False
386 for change in line:
443 for change in line:
387 _html.append('''<tr class="%(line_class)s %(action)s">\n''' \
444 _html.append('''<tr class="%(lc)s %(action)s">\n''' % {
388 % {'line_class': line_class,
445 'lc': line_class,
389 'action': change['action']})
446 'action': change['action']
447 })
390 anchor_old_id = ''
448 anchor_old_id = ''
391 anchor_new_id = ''
449 anchor_new_id = ''
392 anchor_old = "%(filename)s_o%(oldline_no)s" % \
450 anchor_old = "%(filename)s_o%(oldline_no)s" % {
393 {'filename': self._safe_id(diff['filename']),
451 'filename': self._safe_id(diff['filename']),
394 'oldline_no': change['old_lineno']}
452 'oldline_no': change['old_lineno']
395 anchor_new = "%(filename)s_n%(oldline_no)s" % \
453 }
396 {'filename': self._safe_id(diff['filename']),
454 anchor_new = "%(filename)s_n%(oldline_no)s" % {
397 'oldline_no': change['new_lineno']}
455 'filename': self._safe_id(diff['filename']),
398 cond_old = change['old_lineno'] != '...' and \
456 'oldline_no': change['new_lineno']
399 change['old_lineno']
457 }
400 cond_new = change['new_lineno'] != '...' and \
458 cond_old = (change['old_lineno'] != '...' and
401 change['new_lineno']
459 change['old_lineno'])
460 cond_new = (change['new_lineno'] != '...' and
461 change['new_lineno'])
402 if cond_old:
462 if cond_old:
403 anchor_old_id = 'id="%s"' % anchor_old
463 anchor_old_id = 'id="%s"' % anchor_old
404 if cond_new:
464 if cond_new:
@@ -406,37 +466,41 b' class DiffProcessor(object):'
406 ###########################################################
466 ###########################################################
407 # OLD LINE NUMBER
467 # OLD LINE NUMBER
408 ###########################################################
468 ###########################################################
409 _html.append('''\t<td %(a_id)s class="%(old_lineno_cls)s">''' \
469 _html.append('''\t<td %(a_id)s class="%(olc)s">''' % {
410 % {'a_id': anchor_old_id,
470 'a_id': anchor_old_id,
411 'old_lineno_cls': old_lineno_class})
471 'olc': old_lineno_class
472 })
412
473
413 _html.append('''%(link)s''' \
474 _html.append('''%(link)s''' % {
414 % {'link':
475 'link': _link_to_if(True, change['old_lineno'],
415 _link_to_if(cond_old, change['old_lineno'], '#%s' \
476 '#%s' % anchor_old)
416 % anchor_old)})
477 })
417 _html.append('''</td>\n''')
478 _html.append('''</td>\n''')
418 ###########################################################
479 ###########################################################
419 # NEW LINE NUMBER
480 # NEW LINE NUMBER
420 ###########################################################
481 ###########################################################
421
482
422 _html.append('''\t<td %(a_id)s class="%(new_lineno_cls)s">''' \
483 _html.append('''\t<td %(a_id)s class="%(nlc)s">''' % {
423 % {'a_id': anchor_new_id,
484 'a_id': anchor_new_id,
424 'new_lineno_cls': new_lineno_class})
485 'nlc': new_lineno_class
486 })
425
487
426 _html.append('''%(link)s''' \
488 _html.append('''%(link)s''' % {
427 % {'link':
489 'link': _link_to_if(True, change['new_lineno'],
428 _link_to_if(cond_new, change['new_lineno'], '#%s' \
490 '#%s' % anchor_new)
429 % anchor_new)})
491 })
430 _html.append('''</td>\n''')
492 _html.append('''</td>\n''')
431 ###########################################################
493 ###########################################################
432 # CODE
494 # CODE
433 ###########################################################
495 ###########################################################
434 comments = '' if enable_comments else 'no-comment'
496 comments = '' if enable_comments else 'no-comment'
435 _html.append('''\t<td class="%(code_class)s %(in-comments)s">''' \
497 _html.append('''\t<td class="%(cc)s %(inc)s">''' % {
436 % {'code_class': code_class,
498 'cc': code_class,
437 'in-comments': comments})
499 'inc': comments
438 _html.append('''\n\t\t<pre>%(code)s</pre>\n''' \
500 })
439 % {'code': change['line']})
501 _html.append('''\n\t\t<pre>%(code)s</pre>\n''' % {
502 'code': change['line']
503 })
440 _html.append('''\t</td>''')
504 _html.append('''\t</td>''')
441 _html.append('''\n</tr>\n''')
505 _html.append('''\n</tr>\n''')
442 _html.append('''</table>''')
506 _html.append('''</table>''')
@@ -40,6 +40,7 b' from rhodecode.lib.utils import repo_nam'
40 from rhodecode.lib import str2bool, safe_unicode, safe_str, get_changeset_safe
40 from rhodecode.lib import str2bool, safe_unicode, safe_str, get_changeset_safe
41 from rhodecode.lib.markup_renderer import MarkupRenderer
41 from rhodecode.lib.markup_renderer import MarkupRenderer
42
42
43
43 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
44 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
44 """
45 """
45 Reset button
46 Reset button
@@ -52,11 +53,11 b' def _reset(name, value=None, id=NotGiven'
52 reset = _reset
53 reset = _reset
53 safeid = _make_safe_id_component
54 safeid = _make_safe_id_component
54
55
55
56
56 def FID(raw_id,path):
57 def FID(raw_id, path):
57 """
58 """
58 Creates a uniqe ID for filenode based on it's path and revision
59 Creates a uniqe ID for filenode based on it's path and revision
59
60
60 :param raw_id:
61 :param raw_id:
61 :param path:
62 :param path:
62 """
63 """
@@ -116,7 +117,7 b' class _FilesBreadCrumbs(object):'
116 paths_l = paths.split('/')
117 paths_l = paths.split('/')
117 for cnt, p in enumerate(paths_l):
118 for cnt, p in enumerate(paths_l):
118 if p != '':
119 if p != '':
119 url_l.append(link_to(p,
120 url_l.append(link_to(p,
120 url('files_home',
121 url('files_home',
121 repo_name=repo_name,
122 repo_name=repo_name,
122 revision=rev,
123 revision=rev,
@@ -738,14 +739,14 b' def urlify_text(text):'
738
739
739
740
740 def rst(source):
741 def rst(source):
741 return literal('<div class="rst-block">%s</div>' %
742 return literal('<div class="rst-block">%s</div>' %
742 MarkupRenderer.rst(source))
743 MarkupRenderer.rst(source))
743
744
744 def rst_w_mentions(source):
745 def rst_w_mentions(source):
745 """
746 """
746 Wrapped rst renderer with @mention highlighting
747 Wrapped rst renderer with @mention highlighting
747
748
748 :param source:
749 :param source:
749 """
750 """
750 return literal('<div class="rst-block">%s</div>' %
751 return literal('<div class="rst-block">%s</div>' %
751 MarkupRenderer.rst_with_mentions(source))
752 MarkupRenderer.rst_with_mentions(source))
@@ -4,7 +4,7 b''
4 ~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 comments model for RhodeCode
6 comments model for RhodeCode
7
7
8 :created_on: Nov 11, 2011
8 :created_on: Nov 11, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
@@ -55,7 +55,7 b' class ChangesetCommentsModel(BaseModel):'
55 line_no=None):
55 line_no=None):
56 """
56 """
57 Creates new comment for changeset
57 Creates new comment for changeset
58
58
59 :param text:
59 :param text:
60 :param repo_id:
60 :param repo_id:
61 :param user_id:
61 :param user_id:
@@ -84,7 +84,7 b' class ChangesetCommentsModel(BaseModel):'
84 if line_no:
84 if line_no:
85 line = _('on line %s') % line_no
85 line = _('on line %s') % line_no
86 subj = h.link_to('Re commit: %(commit_desc)s %(line)s' % \
86 subj = h.link_to('Re commit: %(commit_desc)s %(line)s' % \
87 {'commit_desc':desc, 'line':line},
87 {'commit_desc': desc, 'line': line},
88 h.url('changeset_home', repo_name=repo.repo_name,
88 h.url('changeset_home', repo_name=repo.repo_name,
89 revision=revision,
89 revision=revision,
90 anchor='comment-%s' % comment.comment_id,
90 anchor='comment-%s' % comment.comment_id,
@@ -114,7 +114,7 b' class ChangesetCommentsModel(BaseModel):'
114 def delete(self, comment):
114 def delete(self, comment):
115 """
115 """
116 Deletes given comment
116 Deletes given comment
117
117
118 :param comment_id:
118 :param comment_id:
119 """
119 """
120 comment = self.__get_changeset_comment(comment)
120 comment = self.__get_changeset_comment(comment)
@@ -122,7 +122,6 b' class ChangesetCommentsModel(BaseModel):'
122
122
123 return comment
123 return comment
124
124
125
126 def get_comments(self, repo_id, revision):
125 def get_comments(self, repo_id, revision):
127 return ChangesetComment.query()\
126 return ChangesetComment.query()\
128 .filter(ChangesetComment.repo_id == repo_id)\
127 .filter(ChangesetComment.repo_id == repo_id)\
@@ -137,7 +136,7 b' class ChangesetCommentsModel(BaseModel):'
137 .filter(ChangesetComment.line_no != None)\
136 .filter(ChangesetComment.line_no != None)\
138 .filter(ChangesetComment.f_path != None).all()
137 .filter(ChangesetComment.f_path != None).all()
139
138
140 paths = defaultdict(lambda:defaultdict(list))
139 paths = defaultdict(lambda: defaultdict(list))
141
140
142 for co in comments:
141 for co in comments:
143 paths[co.f_path][co.line_no].append(co)
142 paths[co.f_path][co.line_no].append(co)
@@ -19,7 +19,7 b''
19 <img class="diff-menu-activate" style="margin-bottom:-6px;cursor: pointer" alt="diff-menu" src="${h.url('/images/icons/script_gear.png')}" />
19 <img class="diff-menu-activate" style="margin-bottom:-6px;cursor: pointer" alt="diff-menu" src="${h.url('/images/icons/script_gear.png')}" />
20 <div class="diff-menu" style="display:none">
20 <div class="diff-menu" style="display:none">
21 <ul>
21 <ul>
22 <li>${h.link_to(_('diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='diff'))}</li>
22 <li>${h.link_to(_('diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='diff',fulldiff=1))}</li>
23 <li>${h.link_to(_('raw diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='raw'))}</li>
23 <li>${h.link_to(_('raw diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='raw'))}</li>
24 <li>${h.link_to(_('download diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='download'))}</li>
24 <li>${h.link_to(_('download diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='download'))}</li>
25 <li>${c.ignorews_url(h.FID(filenode.changeset.raw_id,filenode.path))}</li>
25 <li>${c.ignorews_url(h.FID(filenode.changeset.raw_id,filenode.path))}</li>
@@ -37,11 +37,7 b''
37 </div>
37 </div>
38 <div class="code-body">
38 <div class="code-body">
39 <div class="full_f_path" path="${h.safe_unicode(filenode.path)}"></div>
39 <div class="full_f_path" path="${h.safe_unicode(filenode.path)}"></div>
40 %if diff:
40 ${diff|n}
41 ${diff|n}
42 %else:
43 ${_('No changes in this file')}
44 %endif
45 </div>
41 </div>
46 </div>
42 </div>
47 %endif
43 %endif
@@ -21,33 +21,29 b''
21 <div class="title">
21 <div class="title">
22 ${self.breadcrumbs()}
22 ${self.breadcrumbs()}
23 </div>
23 </div>
24 <div class="table">
24 <div>
25 <div id="body" class="diffblock">
25 ## diff block
26 <div class="code-header">
26 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
27 <div class="changeset_header">
27 ${diff_block.diff_block(c.changes)}
28 <span class="changeset_file">${h.link_to(c.f_path,h.url('files_home',repo_name=c.repo_name,
29 revision=c.changeset_2.raw_id,f_path=c.f_path))}</span>
30 &raquo; <span>${h.link_to(_('diff'),
31 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='diff'))}</span>
32 &raquo; <span>${h.link_to(_('raw diff'),
33 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='raw'))}</span>
34 &raquo; <span>${h.link_to(_('download diff'),
35 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='download'))}</span>
36 </div>
37 </div>
38 <div class="code-body">
39 %if c.no_changes:
40 ${_('No changes')}
41 %elif c.big_diff:
42 ${_('Diff is to big to display')} ${h.link_to(_('raw diff'),
43 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='raw'))}
44 %else:
45 ${c.cur_diff|n}
46 %endif
47 </div>
48 </div>
49 </div>
28 </div>
50 </div>
29 </div>
30 <script>
31 YUE.onDOMReady(function(){
32
33 YUE.on(YUQ('.diff-menu-activate'),'click',function(e){
34 var act = e.currentTarget.nextElementSibling;
35
36 if(YUD.hasClass(act,'active')){
37 YUD.removeClass(act,'active');
38 YUD.setStyle(act,'display','none');
39 }else{
40 YUD.addClass(act,'active');
41 YUD.setStyle(act,'display','');
42 }
43 });
44
45 })
46 </script>
51 </%def>
47 </%def>
52
48
53 No newline at end of file
49
@@ -59,7 +59,7 b''
59 <div class="commit">${_('Editing file')}: ${c.file.path}</div>
59 <div class="commit">${_('Editing file')}: ${c.file.path}</div>
60 </div>
60 </div>
61 <pre id="editor_pre"></pre>
61 <pre id="editor_pre"></pre>
62 <textarea id="editor" name="content" style="display:none">${c.file.content|n}</textarea>
62 <textarea id="editor" name="content" style="display:none">${h.escape(c.file.content)|n}</textarea>
63 <div style="padding: 10px;color:#666666">${_('commit message')}</div>
63 <div style="padding: 10px;color:#666666">${_('commit message')}</div>
64 <textarea id="commit" name="message" style="height: 60px;width: 99%;margin-left:4px"></textarea>
64 <textarea id="commit" name="message" style="height: 60px;width: 99%;margin-left:4px"></textarea>
65 </div>
65 </div>
@@ -11,7 +11,6 b''
11 </div>
11 </div>
12 </dd>
12 </dd>
13 </dl>
13 </dl>
14
15
14
16 <div id="body" class="codeblock">
15 <div id="body" class="codeblock">
17 <div class="code-header">
16 <div class="code-header">
General Comments 0
You need to be logged in to leave comments. Login now