diff --git a/rhodecode/lib/codeblocks.py b/rhodecode/lib/codeblocks.py
--- a/rhodecode/lib/codeblocks.py
+++ b/rhodecode/lib/codeblocks.py
@@ -20,6 +20,7 @@
import logging
import difflib
+import string
from itertools import groupby
from pygments import lex
@@ -28,11 +29,11 @@ from pygments.lexers.special import Text
from rhodecode.lib.helpers import (
get_lexer_for_filenode, html_escape, get_custom_lexer)
-from rhodecode.lib.utils2 import AttributeDict, StrictAttributeDict
+from rhodecode.lib.utils2 import AttributeDict, StrictAttributeDict, safe_unicode
from rhodecode.lib.vcs.nodes import FileNode
from rhodecode.lib.vcs.exceptions import VCSError, NodeDoesNotExistError
from rhodecode.lib.diff_match_patch import diff_match_patch
-from rhodecode.lib.diffs import LimitedDiffContainer
+from rhodecode.lib.diffs import LimitedDiffContainer, DEL_FILENODE, BIN_FILENODE
from pygments.lexers import get_lexer_by_name
plain_text_lexer = get_lexer_by_name(
@@ -506,6 +507,7 @@ class DiffSet(object):
'target_mode': patch['stats']['new_mode'],
'limited_diff': isinstance(patch, LimitedDiffContainer),
'hunks': [],
+ 'hunk_ops': None,
'diffset': self,
})
@@ -515,6 +517,30 @@ class DiffSet(object):
hunkbit.target_file_path = target_file_path
filediff.hunks.append(hunkbit)
+ # Simulate hunk on OPS type line which doesn't really contain any diff
+ # this allows commenting on those
+ actions = []
+ for op_id, op_text in filediff.patch['stats']['ops'].items():
+ if op_id == DEL_FILENODE:
+ actions.append(u'file was deleted')
+ elif op_id == BIN_FILENODE:
+ actions.append(u'binary diff hidden')
+ else:
+ actions.append(safe_unicode(op_text))
+ action_line = u'FILE WITHOUT CONTENT: ' + \
+ u', '.join(map(string.upper, actions)) or u'UNDEFINED_ACTION'
+
+ hunk_ops = {'source_length': 0, 'source_start': 0,
+ 'lines': [
+ {'new_lineno': 0, 'old_lineno': 1,
+ 'action': 'unmod', 'line': action_line}
+ ],
+ 'section_header': u'', 'target_start': 1, 'target_length': 1}
+
+ hunkbit = self.parse_hunk(hunk_ops, source_file, target_file)
+ hunkbit.source_file_path = source_file_path
+ hunkbit.target_file_path = target_file_path
+ filediff.hunk_ops = hunkbit
return filediff
def parse_hunk(self, hunk, source_file, target_file):
diff --git a/rhodecode/templates/codeblocks/diffs.mako b/rhodecode/templates/codeblocks/diffs.mako
--- a/rhodecode/templates/codeblocks/diffs.mako
+++ b/rhodecode/templates/codeblocks/diffs.mako
@@ -149,42 +149,37 @@ collapse_all = len(diffset.files) > coll
lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted']
over_lines_changed_limit = lines_changed > lines_changed_limit
%>
-
+
+
-
-
- ${diff_ops(filediff)}
-
- ${diff_menu(filediff, use_comments=use_comments)}
-
- %if not filediff.hunks:
- %for op_id, op_text in filediff.patch['stats']['ops'].items():
-
-
- %if op_id == DEL_FILENODE:
- ${_('File was deleted')}
- %elif op_id == BIN_FILENODE:
- ${_('Binary file hidden')}
- %else:
- ${op_text}
- %endif
-
-
- %endfor
- %endif
+ id="a_${h.FID('', filediff.patch['filename'])}"
+ >
+
+
+
+ ${diff_ops(filediff)}
+
+ ${diff_menu(filediff, use_comments=use_comments)}
+
+
+ ## new/deleted/empty content case
+ % if not filediff.hunks:
+ ## Comment container, on "fakes" hunk that contains all data to render comments
+ ${render_hunk_lines(c.diffmode, filediff.hunk_ops, use_comments=use_comments, inline_comments=inline_comments)}
+ % endif
+
%if filediff.limited_diff:
-
+
${_('The requested commit is too big and content was truncated.')} ${_('Show full diff')}
%else:
%if over_lines_changed_limit:
-
+
${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)}
${_('Show them')}
@@ -197,31 +192,23 @@ collapse_all = len(diffset.files) > coll
%endif
%endif
- %for hunk in filediff.hunks:
-
-
- ## TODO: dan: add ajax loading of more context here
- ##
-
- ##
-
-
- @@
- -${hunk.source_start},${hunk.source_length}
- +${hunk.target_start},${hunk.target_length}
- ${hunk.section_header}
-
-
- %if c.diffmode == 'unified':
- ${render_hunk_lines_unified(hunk, use_comments=use_comments, inline_comments=inline_comments)}
- %elif c.diffmode == 'sideside':
- ${render_hunk_lines_sideside(hunk, use_comments=use_comments, inline_comments=inline_comments)}
- %else:
-
- unknown diff mode
-
- %endif
- %endfor
+ % for hunk in filediff.hunks:
+
+
+ ## TODO: dan: add ajax loading of more context here
+ ##
+
+ ##
+
+
+ @@
+ -${hunk.source_start},${hunk.source_length}
+ +${hunk.target_start},${hunk.target_length}
+ ${hunk.section_header}
+
+
+ ${render_hunk_lines(c.diffmode, hunk, use_comments=use_comments, inline_comments=inline_comments)}
+ % endfor
<% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %>
@@ -292,7 +279,7 @@ collapse_all = len(diffset.files) > coll
display_state = ''
%>
-
+
@@ -714,6 +701,20 @@ def get_comments_for(diff_type, comments
%endfor
%def>
+
+<%def name="render_hunk_lines(diff_mode, hunk, use_comments, inline_comments)">
+ % if diff_mode == 'unified':
+ ${render_hunk_lines_unified(hunk, use_comments=use_comments, inline_comments=inline_comments)}
+ % elif diff_mode == 'sideside':
+ ${render_hunk_lines_sideside(hunk, use_comments=use_comments, inline_comments=inline_comments)}
+ % else:
+
+ unknown diff mode
+
+ % endif
+%def>
+
+
<%def name="render_add_comment_button()">