Skip to content

Commit 6ba50aa

Browse files
committed
parser: Handle binary git patches
'git-format-patch' is able to generate binary patches. Fortunately, these are quite easy to spot since they're explicitly labelled as such. Add support for parsing these to the parser. Signed-off-by: Stephen Finucane <[email protected]> Closes: #463
1 parent 5b53f46 commit 6ba50aa

File tree

5 files changed

+142
-2
lines changed

5 files changed

+142
-2
lines changed

patchwork/parser.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ def parse_patch(content):
873873
format, and splits it into the component comments and diff.
874874
875875
Args:
876-
patch: The patch to be split
876+
content: The mail to be split
877877
878878
Returns:
879879
A tuple containing the diff and comment. Either one or both of
@@ -895,6 +895,7 @@ def parse_patch(content):
895895
# 4: patch hunk header line (@@ line)
896896
# 5: patch hunk content
897897
# 6: patch meta header (rename from/rename to/new file/index)
898+
# 7: binary patch hunk
898899
#
899900
# valid transitions:
900901
# 0 -> 1 (diff, Index:)
@@ -903,10 +904,12 @@ def parse_patch(content):
903904
# 2 -> 3 (+++)
904905
# 3 -> 4 (@@ line)
905906
# 4 -> 5 (patch content)
906-
# 5 -> 1 (run out of lines from @@-specifed count)
907+
# 5 -> 1 (ran out of lines from @@-specified count)
907908
# 1 -> 6 (extended header lines)
908909
# 6 -> 2 (---)
910+
# 6 -> 7 (GIT binary patch)
909911
# 6 -> 1 (other text)
912+
# 7 -> 1 (diff)
910913
#
911914
# Suspected patch header is stored into buf, and appended to
912915
# patchbuf if we find a following hunk. Otherwise, append to
@@ -1001,9 +1004,20 @@ def fn(x):
10011004
patchbuf += buf + line
10021005
buf = ''
10031006
state = 2
1007+
elif line.startswith('GIT binary patch'):
1008+
patchbuf += buf + line
1009+
buf = ''
1010+
state = 7
10041011
else:
10051012
buf += line
10061013
state = 1
1014+
elif state == 7:
1015+
if line.startswith('diff'):
1016+
buf += line
1017+
state = 0
1018+
else:
1019+
patchbuf += buf + line
1020+
buf = ''
10071021
else:
10081022
raise Exception("Unknown state %d! (line '%s')" % (state, line))
10091023

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
From 3029b9604cf2b2eaa5f38167f59246e2fa026eb5 Mon Sep 17 00:00:00 2001
2+
From: Stephen Finucane <[email protected]>
3+
Date: Wed, 11 May 2022 10:59:59 +0100
4+
Subject: [PATCH] Add a single pixel bitmap image
5+
6+
7+
Demonstrate how Git generates a patch for a binary file.
8+
9+
Signed-off-by: Stephen Finucane <[email protected]>
10+
---
11+
pixel.bmp | Bin 0 -> 142 bytes
12+
1 file changed, 0 insertions(+), 0 deletions(-)
13+
create mode 100644 pixel.bmp
14+
15+
diff --git pixel.bmp pixel.bmp
16+
new file mode 100644
17+
index 0000000000000000000000000000000000000000..9710347a13c4336e7dbaafa69af0e44a40c21172
18+
GIT binary patch
19+
literal 142
20+
zcmZ?r?PGv|E+AC{#Eft(0hV9^lFE7z3>E+r{}~t{2+VVG4=P5;5yxUeQzj#`nE?RC
21+
Ceh3`^
22+
23+
literal 0
24+
HcmV?d00001
25+
26+
--
27+
2.35.3
28+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
From 499d36d946a6f1f654eebad500742eb5c3057569 Mon Sep 17 00:00:00 2001
2+
From: Stephen Finucane <[email protected]>
3+
Date: Wed, 11 May 2022 10:33:58 +0100
4+
Subject: [PATCH] Add a single pixel bitmap image, minimal script
5+
6+
7+
Demonstrate how Git generates a patch for a binary file when mixed with
8+
other file types.
9+
10+
Signed-off-by: Stephen Finucane <[email protected]>
11+
---
12+
pixel.bmp | Bin 0 -> 142 bytes
13+
quit.sh | 3 +++
14+
2 files changed, 3 insertions(+)
15+
create mode 100644 pixel.bmp
16+
create mode 100644 quit.sh
17+
18+
diff --git pixel.bmp pixel.bmp
19+
new file mode 100644
20+
index 0000000000000000000000000000000000000000..9710347a13c4336e7dbaafa69af0e44a40c21172
21+
GIT binary patch
22+
literal 142
23+
zcmZ?r?PGv|E+AC{#Eft(0hV9^lFE7z3>E+r{}~t{2+VVG4=P5;5yxUeQzj#`nE?RC
24+
Ceh3`^
25+
26+
literal 0
27+
HcmV?d00001
28+
29+
diff --git quit.sh quit.sh
30+
new file mode 100644
31+
index 0000000..f5f929a
32+
--- /dev/null
33+
+++ quit.sh
34+
@@ -0,0 +1,3 @@
35+
+#/usr/bin/env bash
36+
+echo "Wuh wuh"
37+
+exit 1
38+
--
39+
2.35.3
40+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
From 434fe33a7ed28cc8cd0b344e55f0be2c74f1a58c Mon Sep 17 00:00:00 2001
2+
From: Stephen Finucane <[email protected]>
3+
Date: Wed, 11 May 2022 11:46:10 +0100
4+
Subject: [PATCH] Make changes to an existing binary file
5+
6+
7+
Signed-off-by: Stephen Finucane <[email protected]>
8+
---
9+
pixel.bmp | Bin 142 -> 0 bytes
10+
1 file changed, 0 insertions(+), 0 deletions(-)
11+
12+
diff --git pixel.bmp pixel.bmp
13+
index 9710347a13c4336e7dbaafa69af0e44a40c21172..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
14+
GIT binary patch
15+
literal 0
16+
HcmV?d00001
17+
18+
literal 142
19+
zcmZ?r?PGv|E+AC{#Eft(0hV9^lFE7z3>E+r{}~t{2+VVG4=P5;5yxUeQzj#`nE?RC
20+
Ceh3`^
21+
22+
--
23+
2.35.3
24+

patchwork/tests/test_parser.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,40 @@ def test_git_pull_trailing_space(self):
730730
pull_url,
731731
)
732732

733+
def test_git_add_binary_file(self):
734+
diff, message = self._find_content('0025-git-add-binary-file.mbox')
735+
self.assertTrue(diff is not None)
736+
self.assertTrue(message is not None)
737+
self.assertTrue(
738+
diff.startswith('diff --git pixel.bmp pixel.bmp'), diff
739+
)
740+
self.assertIn('GIT binary patch\n', diff)
741+
self.assertIn('literal 142\n', diff)
742+
self.assertIn('literal 0\n', diff)
743+
744+
def test_git_add_mixed_binary_text_files(self):
745+
diff, message = self._find_content(
746+
'0026-git-add-mixed-binary-text-files.mbox'
747+
)
748+
self.assertTrue(diff is not None)
749+
self.assertTrue(message is not None)
750+
self.assertTrue(
751+
diff.startswith('diff --git pixel.bmp pixel.bmp'), diff
752+
)
753+
self.assertIn('GIT binary patch\n', diff)
754+
self.assertIn('diff --git quit.sh quit.sh\n', diff)
755+
756+
def test_git_modify_binary_file(self):
757+
diff, message = self._find_content('0027-git-modify-binary-file.mbox')
758+
self.assertTrue(diff is not None)
759+
self.assertTrue(message is not None)
760+
self.assertTrue(
761+
diff.startswith('diff --git pixel.bmp pixel.bmp'), diff
762+
)
763+
self.assertIn('GIT binary patch\n', diff)
764+
self.assertIn('literal 0\n', diff)
765+
self.assertIn('literal 142\n', diff)
766+
733767
def test_git_rename(self):
734768
diff, _ = self._find_content('0008-git-rename.mbox')
735769
self.assertTrue(diff is not None)

0 commit comments

Comments
 (0)