diff --git a/rhodecode/lib/codeblocks.py b/rhodecode/lib/codeblocks.py --- a/rhodecode/lib/codeblocks.py +++ b/rhodecode/lib/codeblocks.py @@ -20,12 +20,12 @@ import logging import difflib -import string from itertools import groupby from pygments import lex from pygments.formatters.html import _get_ttype_class as pygment_token_class from pygments.lexers.special import TextLexer, Token +from pygments.lexers import get_lexer_by_name from rhodecode.lib.helpers import ( get_lexer_for_filenode, html_escape, get_custom_lexer) @@ -34,7 +34,7 @@ from rhodecode.lib.vcs.nodes import File from rhodecode.lib.vcs.exceptions import VCSError, NodeDoesNotExistError from rhodecode.lib.diff_match_patch import diff_match_patch 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( 'text', stripall=False, stripnl=False, ensurenl=False) @@ -307,7 +307,7 @@ def tokens_diff(old_tokens, new_tokens, if use_diff_match_patch: dmp = diff_match_patch() - dmp.Diff_EditCost = 11 # TODO: dan: extract this to a setting + dmp.Diff_EditCost = 11 # TODO: dan: extract this to a setting reps = dmp.diff_main(old_string, new_string) dmp.diff_cleanupEfficiency(reps) @@ -449,7 +449,10 @@ class DiffSet(object): target_lexer = plain_text_lexer if not patch['stats']['binary']: - if self.highlight_mode == self.HL_REAL: + node_hl_mode = self.HL_NONE if patch['chunks'] == [] else None + hl_mode = node_hl_mode or self.highlight_mode + + if hl_mode == self.HL_REAL: if (source_filename and patch['operation'] in ('D', 'M') and source_filename not in self.source_nodes): self.source_nodes[source_filename] = ( @@ -460,7 +463,7 @@ class DiffSet(object): self.target_nodes[target_filename] = ( self.target_node_getter(target_filename)) - elif self.highlight_mode == self.HL_FAST: + elif hl_mode == self.HL_FAST: source_lexer = self._get_lexer_for_filename(source_filename) target_lexer = self._get_lexer_for_filename(target_filename) @@ -510,8 +513,8 @@ class DiffSet(object): 'hunk_ops': None, 'diffset': self, }) - - for hunk in patch['chunks'][1:]: + file_chunks = patch['chunks'][1:] + for hunk in file_chunks: hunkbit = self.parse_hunk(hunk, source_file, target_file) hunkbit.source_file_path = source_file_path hunkbit.target_file_path = target_file_path @@ -519,28 +522,29 @@ class DiffSet(object): # 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' + if not file_chunks: + 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'NO CONTENT: ' + \ + u', '.join(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} + hunk_ops = {'source_length': 0, 'source_start': 0, + 'lines': [ + {'new_lineno': 0, 'old_lineno': 1, + 'action': 'unmod-no-hl', '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 + 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): @@ -555,10 +559,10 @@ class DiffSet(object): before, after = [], [] for line in hunk['lines']: - - if line['action'] == 'unmod': + if line['action'] in ['unmod', 'unmod-no-hl']: + no_hl = line['action'] == 'unmod-no-hl' result.lines.extend( - self.parse_lines(before, after, source_file, target_file)) + self.parse_lines(before, after, source_file, target_file, no_hl=no_hl)) after.append(line) before.append(line) elif line['action'] == 'add': @@ -570,14 +574,18 @@ class DiffSet(object): elif line['action'] == 'new-no-nl': after.append(line) + all_actions = [x['action'] for x in after] + [x['action'] for x in before] + no_hl = {x for x in all_actions} == {'unmod-no-hl'} result.lines.extend( - self.parse_lines(before, after, source_file, target_file)) + self.parse_lines(before, after, source_file, target_file, no_hl=no_hl)) + # NOTE(marcink): we must keep list() call here so we can cache the result... result.unified = list(self.as_unified(result.lines)) result.sideside = result.lines return result - def parse_lines(self, before_lines, after_lines, source_file, target_file): + def parse_lines(self, before_lines, after_lines, source_file, target_file, + no_hl=False): # TODO: dan: investigate doing the diff comparison and fast highlighting # on the entire before and after buffered block lines rather than by # line, this means we can get better 'fast' highlighting if the context @@ -621,9 +629,8 @@ class DiffSet(object): before_tokens = [('nonl', before['line'])] else: before_tokens = self.get_line_tokens( - line_text=before['line'], - line_number=before['old_lineno'], - file=source_file) + line_text=before['line'], line_number=before['old_lineno'], + input_file=source_file, no_hl=no_hl) original.lineno = before['old_lineno'] original.content = before['line'] original.action = self.action_to_op(before['action']) @@ -637,13 +644,12 @@ class DiffSet(object): else: after_tokens = self.get_line_tokens( line_text=after['line'], line_number=after['new_lineno'], - file=target_file) + input_file=target_file, no_hl=no_hl) modified.lineno = after['new_lineno'] modified.content = after['line'] modified.action = self.action_to_op(after['action']) - modified.get_comment_args = ( - target_file, 'n', after['new_lineno']) + modified.get_comment_args = (target_file, 'n', after['new_lineno']) # diff the lines if before_tokens and after_tokens: @@ -672,24 +678,25 @@ class DiffSet(object): return lines - def get_line_tokens(self, line_text, line_number, file=None): + def get_line_tokens(self, line_text, line_number, input_file=None, no_hl=False): filenode = None filename = None - if isinstance(file, basestring): - filename = file - elif isinstance(file, FileNode): - filenode = file - filename = file.unicode_path + if isinstance(input_file, basestring): + filename = input_file + elif isinstance(input_file, FileNode): + filenode = input_file + filename = input_file.unicode_path - if self.highlight_mode == self.HL_REAL and filenode: + hl_mode = self.HL_NONE if no_hl else self.highlight_mode + if hl_mode == self.HL_REAL and filenode: lexer = self._get_lexer_for_filename(filename) - file_size_allowed = file.size < self.max_file_size_limit + file_size_allowed = input_file.size < self.max_file_size_limit if line_number and file_size_allowed: return self.get_tokenized_filenode_line( - file, line_number, lexer) + input_file, line_number, lexer) - if self.highlight_mode in (self.HL_REAL, self.HL_FAST) and filename: + if hl_mode in (self.HL_REAL, self.HL_FAST) and filename: lexer = self._get_lexer_for_filename(filename) return list(tokenize_string(line_text, lexer)) @@ -707,6 +714,7 @@ class DiffSet(object): 'add': '+', 'del': '-', 'unmod': ' ', + 'unmod-no-hl': ' ', 'old-no-nl': ' ', 'new-no-nl': ' ', }.get(action, action) diff --git a/rhodecode/lib/diffs.py b/rhodecode/lib/diffs.py --- a/rhodecode/lib/diffs.py +++ b/rhodecode/lib/diffs.py @@ -1136,7 +1136,7 @@ class DiffLimitExceeded(Exception): # NOTE(marcink): if diffs.mako change, probably this # needs a bump to next version -CURRENT_DIFF_VERSION = 'v1' +CURRENT_DIFF_VERSION = 'v2' def _cleanup_cache_file(cached_diff_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 @@ -653,7 +653,7 @@ def get_comments_for(diff_type, comments %if comments_args: <% comments = get_comments_for('unified', inline_comments, *comments_args) %> %else: - <% comments = None%> + <% comments = None %> %endif % if comments: