# HG changeset patch # User Mads Kiilerich # Date 1603890508 -3600 # Node ID 161cf7e3566f9aa2f41878ff496a14ad6fac5cde # Parent c6964daffe57dc3855115c6ce88a2b6eb96a9443 diff: refactor to avoid complexity of passing unnecessary trailing newline around _escaper tried to handle these optional newlines ... but did not always preserve them. Keep it simple. In normal operations, all diff lines end with \n . We only saw un-terminated lines in a couple of old test cases. diff -r c6964daffe57 -r 161cf7e3566f kallithea/lib/diffs.py --- a/kallithea/lib/diffs.py Thu Oct 22 11:29:32 2020 +0200 +++ b/kallithea/lib/diffs.py Wed Oct 28 14:08:28 2020 +0100 @@ -445,7 +445,7 @@ return self.adds, self.removes -_escape_re = re.compile(r'(&)|(<)|(>)|(\t)|(\r)|(?<=.)( \n| $)|(\t\n|\t$)') +_escape_re = re.compile(r'(&)|(<)|(>)|(\t)|(\r)|(?<=.)( $)|(\t$)') def _escaper(diff_line): @@ -571,9 +571,13 @@ raise Exception('diff not recognized as valid %s diff' % vcs) meta_info = {k: None if v is None else safe_str(v) for k, v in match.groupdict().items()} rest = diff_chunk[match.end():] - if rest and _header_next_check.match(rest): - raise Exception('cannot parse %s diff header: %r followed by %r' % (vcs, safe_str(bytes(diff_chunk[:match.end()])), safe_str(bytes(rest[:1000])))) - diff_lines = (_escaper(safe_str(m.group(0))) for m in re.finditer(br'.*\n|.+$', rest)) # don't split on \r as str.splitlines do + if rest: + if _header_next_check.match(rest): + raise Exception('cannot parse %s diff header: %r followed by %r' % (vcs, safe_str(bytes(diff_chunk[:match.end()])), safe_str(bytes(rest[:1000])))) + if rest[-1:] != b'\n': + # The diff will generally already have trailing \n (and be a memoryview). It might also be huge so we don't want to allocate it twice. But in this very rare case, we don't care. + rest = bytes(rest) + b'\n' + diff_lines = (_escaper(safe_str(m.group(1))) for m in re.finditer(br'(.*)\n', rest)) return meta_info, diff_lines diff -r c6964daffe57 -r 161cf7e3566f kallithea/tests/models/test_diff_parsers.py --- a/kallithea/tests/models/test_diff_parsers.py Thu Oct 22 11:29:32 2020 +0200 +++ b/kallithea/tests/models/test_diff_parsers.py Wed Oct 28 14:08:28 2020 +0100 @@ -295,20 +295,20 @@ l.append('%(action)-7s %(new_lineno)3s %(old_lineno)3s %(line)r\n' % d) s = ''.join(l) assert s == r''' -context '@@ -51,6 +51,13 @@\n' -unmod 51 51 '\tbegin();\n' -unmod 52 52 '\t\n' -add 53 '\tint foo;\n' -add 54 '\tint bar; \n' -add 55 '\tint baz;\t\n' +context '@@ -51,6 +51,13 @@' +unmod 51 51 '\tbegin();' +unmod 52 52 '\t' +add 53 '\tint foo;' +add 54 '\tint bar; ' +add 55 '\tint baz;\t' add 56 '\tint space; ' -add 57 '\tint tab;\t\n' -add 58 '\t\n' +add 57 '\tint tab;\t' +add 58 '\t' unmod 59 53 ' ' -del 54 '\t#define MAX_STEPS (48)\n' -add 60 '\t\n' -add 61 '\t#define MAX_STEPS (64)\n' -unmod 62 55 '\n' -del 56 '\t#define MIN_STEPS (48)\n' -add 63 '\t#define MIN_STEPS (42)\n' +del 54 '\t#define MAX_STEPS (48)' +add 60 '\t' +add 61 '\t#define MAX_STEPS (64)' +unmod 62 55 '' +del 56 '\t#define MIN_STEPS (48)' +add 63 '\t#define MIN_STEPS (42)' '''