From 21400e2ea6b5be55ec5a54b15d63df558d815e67 Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Sat, 18 Jul 2026 20:37:28 -0300 Subject: [PATCH] Fix trailing newline error on hunkless files (#73, #74) --- tests/test_parser.py | 30 ++++++++++++++++++++++++++++++ unidiff/patch.py | 7 +++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/tests/test_parser.py b/tests/test_parser.py index b4cf3e8..d8096bd 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -586,6 +586,36 @@ def test_index_line_mode(self): # the index line is preserved so the diff still round-trips self.assertEqual(str(res), diff) + def test_parse_format_patch_hunkless_rename(self): + # regression test for issues #73 / #74: git format-patch output where a + # hunkless file (a pure rename) is followed by the "-- " email + # signature and a trailing blank line must not raise. + lines = [ + 'From 82dd164 Mon Sep 17 00:00:00 2001\n', + 'From: Someone \n', + 'Subject: [PATCH] Rename JSONHelper to JSONHelper.java\n', + '\n', + '---\n', + ' JSONHelper => JSONHelper.java | 0\n', + ' 1 file changed, 0 insertions(+), 0 deletions(-)\n', + ' rename JSONHelper => JSONHelper.java (100%)\n', + '\n', + 'diff --git a/JSONHelper b/JSONHelper.java\n', + 'similarity index 100%\n', + 'rename from JSONHelper\n', + 'rename to JSONHelper.java\n', + '-- \n', + '2.17.1\n', + '\n', + ] + + res = PatchSet(lines) + + self.assertEqual(len(res), 1) + self.assertTrue(res[0].is_rename) + self.assertEqual(res[0].path, 'JSONHelper.java') + self.assertEqual(len(res[0]), 0) + def test_diff_lines_linenos(self): with open(self.sample_file, 'rb') as diff_file: res = PatchSet(diff_file, encoding='utf-8') diff --git a/unidiff/patch.py b/unidiff/patch.py index 68489cb..ede7699 100644 --- a/unidiff/patch.py +++ b/unidiff/patch.py @@ -575,8 +575,11 @@ def _parse(self, diff: Iterable, encoding: Optional[str], current_file._add_no_newline_marker_to_last_hunk() continue - # sometimes hunks can be followed by empty lines - if line == '\n' and current_file is not None: + # sometimes hunks can be followed by empty lines; only attach the + # empty line to the current file when it actually has hunks, + # otherwise (e.g. a hunkless rename in git format-patch output) it + # is just a separator and belongs to the surrounding patch info + if line == '\n' and current_file: current_file._append_trailing_empty_line() continue