2
0

test_patch.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. # test_patch.py -- tests for patch.py
  2. # Copyright (C) 2010 Jelmer Vernooij <jelmer@jelmer.uk>
  3. #
  4. # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  5. # Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
  6. # General Public License as public by the Free Software Foundation; version 2.0
  7. # or (at your option) any later version. You can redistribute it and/or
  8. # modify it under the terms of either of these two licenses.
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. #
  16. # You should have received a copy of the licenses; if not, see
  17. # <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
  18. # and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
  19. # License, Version 2.0.
  20. #
  21. """Tests for patch.py."""
  22. from io import BytesIO, StringIO
  23. from typing import NoReturn
  24. from dulwich.object_store import MemoryObjectStore
  25. from dulwich.objects import S_IFGITLINK, Blob, Commit, Tree
  26. from dulwich.patch import (
  27. get_summary,
  28. git_am_patch_split,
  29. write_blob_diff,
  30. write_commit_patch,
  31. write_object_diff,
  32. write_tree_diff,
  33. )
  34. from . import SkipTest, TestCase
  35. class WriteCommitPatchTests(TestCase):
  36. def test_simple_bytesio(self) -> None:
  37. f = BytesIO()
  38. c = Commit()
  39. c.committer = c.author = b"Jelmer <jelmer@samba.org>"
  40. c.commit_time = c.author_time = 1271350201
  41. c.commit_timezone = c.author_timezone = 0
  42. c.message = b"This is the first line\nAnd this is the second line.\n"
  43. c.tree = Tree().id
  44. write_commit_patch(f, c, b"CONTENTS", (1, 1), version="custom")
  45. f.seek(0)
  46. lines = f.readlines()
  47. self.assertTrue(
  48. lines[0].startswith(b"From 0b0d34d1b5b596c928adc9a727a4b9e03d025298")
  49. )
  50. self.assertEqual(lines[1], b"From: Jelmer <jelmer@samba.org>\n")
  51. self.assertTrue(lines[2].startswith(b"Date: "))
  52. self.assertEqual(
  53. [
  54. b"Subject: [PATCH 1/1] This is the first line\n",
  55. b"And this is the second line.\n",
  56. b"\n",
  57. b"\n",
  58. b"---\n",
  59. ],
  60. lines[3:8],
  61. )
  62. self.assertEqual([b"CONTENTS-- \n", b"custom\n"], lines[-2:])
  63. if len(lines) >= 12:
  64. # diffstat may not be present
  65. self.assertEqual(lines[8], b" 0 files changed\n")
  66. class ReadGitAmPatch(TestCase):
  67. def test_extract_string(self) -> None:
  68. text = b"""\
  69. From ff643aae102d8870cac88e8f007e70f58f3a7363 Mon Sep 17 00:00:00 2001
  70. From: Jelmer Vernooij <jelmer@samba.org>
  71. Date: Thu, 15 Apr 2010 15:40:28 +0200
  72. Subject: [PATCH 1/2] Remove executable bit from prey.ico (triggers a warning).
  73. ---
  74. pixmaps/prey.ico | Bin 9662 -> 9662 bytes
  75. 1 files changed, 0 insertions(+), 0 deletions(-)
  76. mode change 100755 => 100644 pixmaps/prey.ico
  77. --
  78. 1.7.0.4
  79. """
  80. c, diff, version = git_am_patch_split(StringIO(text.decode("utf-8")), "utf-8")
  81. self.assertEqual(b"Jelmer Vernooij <jelmer@samba.org>", c.committer)
  82. self.assertEqual(b"Jelmer Vernooij <jelmer@samba.org>", c.author)
  83. self.assertEqual(
  84. b"Remove executable bit from prey.ico " b"(triggers a warning).\n",
  85. c.message,
  86. )
  87. self.assertEqual(
  88. b""" pixmaps/prey.ico | Bin 9662 -> 9662 bytes
  89. 1 files changed, 0 insertions(+), 0 deletions(-)
  90. mode change 100755 => 100644 pixmaps/prey.ico
  91. """,
  92. diff,
  93. )
  94. self.assertEqual(b"1.7.0.4", version)
  95. def test_extract_bytes(self) -> None:
  96. text = b"""\
  97. From ff643aae102d8870cac88e8f007e70f58f3a7363 Mon Sep 17 00:00:00 2001
  98. From: Jelmer Vernooij <jelmer@samba.org>
  99. Date: Thu, 15 Apr 2010 15:40:28 +0200
  100. Subject: [PATCH 1/2] Remove executable bit from prey.ico (triggers a warning).
  101. ---
  102. pixmaps/prey.ico | Bin 9662 -> 9662 bytes
  103. 1 files changed, 0 insertions(+), 0 deletions(-)
  104. mode change 100755 => 100644 pixmaps/prey.ico
  105. --
  106. 1.7.0.4
  107. """
  108. c, diff, version = git_am_patch_split(BytesIO(text))
  109. self.assertEqual(b"Jelmer Vernooij <jelmer@samba.org>", c.committer)
  110. self.assertEqual(b"Jelmer Vernooij <jelmer@samba.org>", c.author)
  111. self.assertEqual(
  112. b"Remove executable bit from prey.ico " b"(triggers a warning).\n",
  113. c.message,
  114. )
  115. self.assertEqual(
  116. b""" pixmaps/prey.ico | Bin 9662 -> 9662 bytes
  117. 1 files changed, 0 insertions(+), 0 deletions(-)
  118. mode change 100755 => 100644 pixmaps/prey.ico
  119. """,
  120. diff,
  121. )
  122. self.assertEqual(b"1.7.0.4", version)
  123. def test_extract_spaces(self) -> None:
  124. text = b"""From ff643aae102d8870cac88e8f007e70f58f3a7363 Mon Sep 17 00:00:00 2001
  125. From: Jelmer Vernooij <jelmer@samba.org>
  126. Date: Thu, 15 Apr 2010 15:40:28 +0200
  127. Subject: [Dulwich-users] [PATCH] Added unit tests for
  128. dulwich.object_store.tree_lookup_path.
  129. * dulwich/tests/test_object_store.py
  130. (TreeLookupPathTests): This test case contains a few tests that ensure the
  131. tree_lookup_path function works as expected.
  132. ---
  133. pixmaps/prey.ico | Bin 9662 -> 9662 bytes
  134. 1 files changed, 0 insertions(+), 0 deletions(-)
  135. mode change 100755 => 100644 pixmaps/prey.ico
  136. --
  137. 1.7.0.4
  138. """
  139. c, diff, version = git_am_patch_split(BytesIO(text), "utf-8")
  140. self.assertEqual(
  141. b"""\
  142. Added unit tests for dulwich.object_store.tree_lookup_path.
  143. * dulwich/tests/test_object_store.py
  144. (TreeLookupPathTests): This test case contains a few tests that ensure the
  145. tree_lookup_path function works as expected.
  146. """,
  147. c.message,
  148. )
  149. def test_extract_pseudo_from_header(self) -> None:
  150. text = b"""From ff643aae102d8870cac88e8f007e70f58f3a7363 Mon Sep 17 00:00:00 2001
  151. From: Jelmer Vernooij <jelmer@samba.org>
  152. Date: Thu, 15 Apr 2010 15:40:28 +0200
  153. Subject: [Dulwich-users] [PATCH] Added unit tests for
  154. dulwich.object_store.tree_lookup_path.
  155. From: Jelmer Vernooij <jelmer@debian.org>
  156. * dulwich/tests/test_object_store.py
  157. (TreeLookupPathTests): This test case contains a few tests that ensure the
  158. tree_lookup_path function works as expected.
  159. ---
  160. pixmaps/prey.ico | Bin 9662 -> 9662 bytes
  161. 1 files changed, 0 insertions(+), 0 deletions(-)
  162. mode change 100755 => 100644 pixmaps/prey.ico
  163. --
  164. 1.7.0.4
  165. """
  166. c, diff, version = git_am_patch_split(BytesIO(text), "utf-8")
  167. self.assertEqual(b"Jelmer Vernooij <jelmer@debian.org>", c.author)
  168. self.assertEqual(
  169. b"""\
  170. Added unit tests for dulwich.object_store.tree_lookup_path.
  171. * dulwich/tests/test_object_store.py
  172. (TreeLookupPathTests): This test case contains a few tests that ensure the
  173. tree_lookup_path function works as expected.
  174. """,
  175. c.message,
  176. )
  177. def test_extract_no_version_tail(self) -> None:
  178. text = b"""\
  179. From ff643aae102d8870cac88e8f007e70f58f3a7363 Mon Sep 17 00:00:00 2001
  180. From: Jelmer Vernooij <jelmer@samba.org>
  181. Date: Thu, 15 Apr 2010 15:40:28 +0200
  182. Subject: [Dulwich-users] [PATCH] Added unit tests for
  183. dulwich.object_store.tree_lookup_path.
  184. From: Jelmer Vernooij <jelmer@debian.org>
  185. ---
  186. pixmaps/prey.ico | Bin 9662 -> 9662 bytes
  187. 1 files changed, 0 insertions(+), 0 deletions(-)
  188. mode change 100755 => 100644 pixmaps/prey.ico
  189. """
  190. c, diff, version = git_am_patch_split(BytesIO(text), "utf-8")
  191. self.assertEqual(None, version)
  192. def test_extract_mercurial(self) -> NoReturn:
  193. raise SkipTest(
  194. "git_am_patch_split doesn't handle Mercurial patches " "properly yet"
  195. )
  196. expected_diff = """\
  197. diff --git a/dulwich/tests/test_patch.py b/dulwich/tests/test_patch.py
  198. --- a/dulwich/tests/test_patch.py
  199. +++ b/dulwich/tests/test_patch.py
  200. @@ -158,7 +158,7 @@
  201. '''
  202. c, diff, version = git_am_patch_split(BytesIO(text))
  203. - self.assertIs(None, version)
  204. + self.assertEqual(None, version)
  205. class DiffTests(TestCase):
  206. """
  207. text = f"""\
  208. From dulwich-users-bounces+jelmer=samba.org@lists.launchpad.net \
  209. Mon Nov 29 00:58:18 2010
  210. Date: Sun, 28 Nov 2010 17:57:27 -0600
  211. From: Augie Fackler <durin42@gmail.com>
  212. To: dulwich-users <dulwich-users@lists.launchpad.net>
  213. Subject: [Dulwich-users] [PATCH] test_patch: fix tests on Python 2.6
  214. Content-Transfer-Encoding: 8bit
  215. Change-Id: I5e51313d4ae3a65c3f00c665002a7489121bb0d6
  216. {expected_diff}
  217. _______________________________________________
  218. Mailing list: https://launchpad.net/~dulwich-users
  219. Post to : dulwich-users@lists.launchpad.net
  220. Unsubscribe : https://launchpad.net/~dulwich-users
  221. More help : https://help.launchpad.net/ListHelp
  222. """
  223. c, diff, version = git_am_patch_split(BytesIO(text))
  224. self.assertEqual(expected_diff, diff)
  225. self.assertEqual(None, version)
  226. class DiffTests(TestCase):
  227. """Tests for write_blob_diff and write_tree_diff."""
  228. def test_blob_diff(self) -> None:
  229. f = BytesIO()
  230. write_blob_diff(
  231. f,
  232. (b"foo.txt", 0o644, Blob.from_string(b"old\nsame\n")),
  233. (b"bar.txt", 0o644, Blob.from_string(b"new\nsame\n")),
  234. )
  235. self.assertEqual(
  236. [
  237. b"diff --git a/foo.txt b/bar.txt",
  238. b"index 3b0f961..a116b51 644",
  239. b"--- a/foo.txt",
  240. b"+++ b/bar.txt",
  241. b"@@ -1,2 +1,2 @@",
  242. b"-old",
  243. b"+new",
  244. b" same",
  245. ],
  246. f.getvalue().splitlines(),
  247. )
  248. def test_blob_add(self) -> None:
  249. f = BytesIO()
  250. write_blob_diff(
  251. f,
  252. (None, None, None),
  253. (b"bar.txt", 0o644, Blob.from_string(b"new\nsame\n")),
  254. )
  255. self.assertEqual(
  256. [
  257. b"diff --git a/bar.txt b/bar.txt",
  258. b"new file mode 644",
  259. b"index 0000000..a116b51",
  260. b"--- /dev/null",
  261. b"+++ b/bar.txt",
  262. b"@@ -0,0 +1,2 @@",
  263. b"+new",
  264. b"+same",
  265. ],
  266. f.getvalue().splitlines(),
  267. )
  268. def test_blob_remove(self) -> None:
  269. f = BytesIO()
  270. write_blob_diff(
  271. f,
  272. (b"bar.txt", 0o644, Blob.from_string(b"new\nsame\n")),
  273. (None, None, None),
  274. )
  275. self.assertEqual(
  276. [
  277. b"diff --git a/bar.txt b/bar.txt",
  278. b"deleted file mode 644",
  279. b"index a116b51..0000000",
  280. b"--- a/bar.txt",
  281. b"+++ /dev/null",
  282. b"@@ -1,2 +0,0 @@",
  283. b"-new",
  284. b"-same",
  285. ],
  286. f.getvalue().splitlines(),
  287. )
  288. def test_tree_diff(self) -> None:
  289. f = BytesIO()
  290. store = MemoryObjectStore()
  291. added = Blob.from_string(b"add\n")
  292. removed = Blob.from_string(b"removed\n")
  293. changed1 = Blob.from_string(b"unchanged\nremoved\n")
  294. changed2 = Blob.from_string(b"unchanged\nadded\n")
  295. unchanged = Blob.from_string(b"unchanged\n")
  296. tree1 = Tree()
  297. tree1.add(b"removed.txt", 0o644, removed.id)
  298. tree1.add(b"changed.txt", 0o644, changed1.id)
  299. tree1.add(b"unchanged.txt", 0o644, changed1.id)
  300. tree2 = Tree()
  301. tree2.add(b"added.txt", 0o644, added.id)
  302. tree2.add(b"changed.txt", 0o644, changed2.id)
  303. tree2.add(b"unchanged.txt", 0o644, changed1.id)
  304. store.add_objects(
  305. [
  306. (o, None)
  307. for o in [
  308. tree1,
  309. tree2,
  310. added,
  311. removed,
  312. changed1,
  313. changed2,
  314. unchanged,
  315. ]
  316. ]
  317. )
  318. write_tree_diff(f, store, tree1.id, tree2.id)
  319. self.assertEqual(
  320. [
  321. b"diff --git a/added.txt b/added.txt",
  322. b"new file mode 644",
  323. b"index 0000000..76d4bb8",
  324. b"--- /dev/null",
  325. b"+++ b/added.txt",
  326. b"@@ -0,0 +1 @@",
  327. b"+add",
  328. b"diff --git a/changed.txt b/changed.txt",
  329. b"index bf84e48..1be2436 644",
  330. b"--- a/changed.txt",
  331. b"+++ b/changed.txt",
  332. b"@@ -1,2 +1,2 @@",
  333. b" unchanged",
  334. b"-removed",
  335. b"+added",
  336. b"diff --git a/removed.txt b/removed.txt",
  337. b"deleted file mode 644",
  338. b"index 2c3f0b3..0000000",
  339. b"--- a/removed.txt",
  340. b"+++ /dev/null",
  341. b"@@ -1 +0,0 @@",
  342. b"-removed",
  343. ],
  344. f.getvalue().splitlines(),
  345. )
  346. def test_tree_diff_submodule(self) -> None:
  347. f = BytesIO()
  348. store = MemoryObjectStore()
  349. tree1 = Tree()
  350. tree1.add(
  351. b"asubmodule",
  352. S_IFGITLINK,
  353. b"06d0bdd9e2e20377b3180e4986b14c8549b393e4",
  354. )
  355. tree2 = Tree()
  356. tree2.add(
  357. b"asubmodule",
  358. S_IFGITLINK,
  359. b"cc975646af69f279396d4d5e1379ac6af80ee637",
  360. )
  361. store.add_objects([(o, None) for o in [tree1, tree2]])
  362. write_tree_diff(f, store, tree1.id, tree2.id)
  363. self.assertEqual(
  364. [
  365. b"diff --git a/asubmodule b/asubmodule",
  366. b"index 06d0bdd..cc97564 160000",
  367. b"--- a/asubmodule",
  368. b"+++ b/asubmodule",
  369. b"@@ -1 +1 @@",
  370. b"-Subproject commit 06d0bdd9e2e20377b3180e4986b14c8549b393e4",
  371. b"+Subproject commit cc975646af69f279396d4d5e1379ac6af80ee637",
  372. ],
  373. f.getvalue().splitlines(),
  374. )
  375. def test_object_diff_blob(self) -> None:
  376. f = BytesIO()
  377. b1 = Blob.from_string(b"old\nsame\n")
  378. b2 = Blob.from_string(b"new\nsame\n")
  379. store = MemoryObjectStore()
  380. store.add_objects([(b1, None), (b2, None)])
  381. write_object_diff(
  382. f, store, (b"foo.txt", 0o644, b1.id), (b"bar.txt", 0o644, b2.id)
  383. )
  384. self.assertEqual(
  385. [
  386. b"diff --git a/foo.txt b/bar.txt",
  387. b"index 3b0f961..a116b51 644",
  388. b"--- a/foo.txt",
  389. b"+++ b/bar.txt",
  390. b"@@ -1,2 +1,2 @@",
  391. b"-old",
  392. b"+new",
  393. b" same",
  394. ],
  395. f.getvalue().splitlines(),
  396. )
  397. def test_object_diff_add_blob(self) -> None:
  398. f = BytesIO()
  399. store = MemoryObjectStore()
  400. b2 = Blob.from_string(b"new\nsame\n")
  401. store.add_object(b2)
  402. write_object_diff(f, store, (None, None, None), (b"bar.txt", 0o644, b2.id))
  403. self.assertEqual(
  404. [
  405. b"diff --git a/bar.txt b/bar.txt",
  406. b"new file mode 644",
  407. b"index 0000000..a116b51",
  408. b"--- /dev/null",
  409. b"+++ b/bar.txt",
  410. b"@@ -0,0 +1,2 @@",
  411. b"+new",
  412. b"+same",
  413. ],
  414. f.getvalue().splitlines(),
  415. )
  416. def test_object_diff_remove_blob(self) -> None:
  417. f = BytesIO()
  418. b1 = Blob.from_string(b"new\nsame\n")
  419. store = MemoryObjectStore()
  420. store.add_object(b1)
  421. write_object_diff(f, store, (b"bar.txt", 0o644, b1.id), (None, None, None))
  422. self.assertEqual(
  423. [
  424. b"diff --git a/bar.txt b/bar.txt",
  425. b"deleted file mode 644",
  426. b"index a116b51..0000000",
  427. b"--- a/bar.txt",
  428. b"+++ /dev/null",
  429. b"@@ -1,2 +0,0 @@",
  430. b"-new",
  431. b"-same",
  432. ],
  433. f.getvalue().splitlines(),
  434. )
  435. def test_object_diff_bin_blob_force(self) -> None:
  436. f = BytesIO()
  437. # Prepare two slightly different PNG headers
  438. b1 = Blob.from_string(
  439. b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"
  440. b"\x00\x00\x00\x0d\x49\x48\x44\x52"
  441. b"\x00\x00\x01\xd5\x00\x00\x00\x9f"
  442. b"\x08\x04\x00\x00\x00\x05\x04\x8b"
  443. )
  444. b2 = Blob.from_string(
  445. b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"
  446. b"\x00\x00\x00\x0d\x49\x48\x44\x52"
  447. b"\x00\x00\x01\xd5\x00\x00\x00\x9f"
  448. b"\x08\x03\x00\x00\x00\x98\xd3\xb3"
  449. )
  450. store = MemoryObjectStore()
  451. store.add_objects([(b1, None), (b2, None)])
  452. write_object_diff(
  453. f,
  454. store,
  455. (b"foo.png", 0o644, b1.id),
  456. (b"bar.png", 0o644, b2.id),
  457. diff_binary=True,
  458. )
  459. self.assertEqual(
  460. [
  461. b"diff --git a/foo.png b/bar.png",
  462. b"index f73e47d..06364b7 644",
  463. b"--- a/foo.png",
  464. b"+++ b/bar.png",
  465. b"@@ -1,4 +1,4 @@",
  466. b" \x89PNG",
  467. b" \x1a",
  468. b" \x00\x00\x00",
  469. b"-IHDR\x00\x00\x01\xd5\x00\x00\x00"
  470. b"\x9f\x08\x04\x00\x00\x00\x05\x04\x8b",
  471. b"\\ No newline at end of file",
  472. b"+IHDR\x00\x00\x01\xd5\x00\x00\x00\x9f"
  473. b"\x08\x03\x00\x00\x00\x98\xd3\xb3",
  474. b"\\ No newline at end of file",
  475. ],
  476. f.getvalue().splitlines(),
  477. )
  478. def test_object_diff_bin_blob(self) -> None:
  479. f = BytesIO()
  480. # Prepare two slightly different PNG headers
  481. b1 = Blob.from_string(
  482. b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"
  483. b"\x00\x00\x00\x0d\x49\x48\x44\x52"
  484. b"\x00\x00\x01\xd5\x00\x00\x00\x9f"
  485. b"\x08\x04\x00\x00\x00\x05\x04\x8b"
  486. )
  487. b2 = Blob.from_string(
  488. b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"
  489. b"\x00\x00\x00\x0d\x49\x48\x44\x52"
  490. b"\x00\x00\x01\xd5\x00\x00\x00\x9f"
  491. b"\x08\x03\x00\x00\x00\x98\xd3\xb3"
  492. )
  493. store = MemoryObjectStore()
  494. store.add_objects([(b1, None), (b2, None)])
  495. write_object_diff(
  496. f, store, (b"foo.png", 0o644, b1.id), (b"bar.png", 0o644, b2.id)
  497. )
  498. self.assertEqual(
  499. [
  500. b"diff --git a/foo.png b/bar.png",
  501. b"index f73e47d..06364b7 644",
  502. b"Binary files a/foo.png and b/bar.png differ",
  503. ],
  504. f.getvalue().splitlines(),
  505. )
  506. def test_object_diff_add_bin_blob(self) -> None:
  507. f = BytesIO()
  508. b2 = Blob.from_string(
  509. b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"
  510. b"\x00\x00\x00\x0d\x49\x48\x44\x52"
  511. b"\x00\x00\x01\xd5\x00\x00\x00\x9f"
  512. b"\x08\x03\x00\x00\x00\x98\xd3\xb3"
  513. )
  514. store = MemoryObjectStore()
  515. store.add_object(b2)
  516. write_object_diff(f, store, (None, None, None), (b"bar.png", 0o644, b2.id))
  517. self.assertEqual(
  518. [
  519. b"diff --git a/bar.png b/bar.png",
  520. b"new file mode 644",
  521. b"index 0000000..06364b7",
  522. b"Binary files /dev/null and b/bar.png differ",
  523. ],
  524. f.getvalue().splitlines(),
  525. )
  526. def test_object_diff_remove_bin_blob(self) -> None:
  527. f = BytesIO()
  528. b1 = Blob.from_string(
  529. b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"
  530. b"\x00\x00\x00\x0d\x49\x48\x44\x52"
  531. b"\x00\x00\x01\xd5\x00\x00\x00\x9f"
  532. b"\x08\x04\x00\x00\x00\x05\x04\x8b"
  533. )
  534. store = MemoryObjectStore()
  535. store.add_object(b1)
  536. write_object_diff(f, store, (b"foo.png", 0o644, b1.id), (None, None, None))
  537. self.assertEqual(
  538. [
  539. b"diff --git a/foo.png b/foo.png",
  540. b"deleted file mode 644",
  541. b"index f73e47d..0000000",
  542. b"Binary files a/foo.png and /dev/null differ",
  543. ],
  544. f.getvalue().splitlines(),
  545. )
  546. def test_object_diff_kind_change(self) -> None:
  547. f = BytesIO()
  548. b1 = Blob.from_string(b"new\nsame\n")
  549. store = MemoryObjectStore()
  550. store.add_object(b1)
  551. write_object_diff(
  552. f,
  553. store,
  554. (b"bar.txt", 0o644, b1.id),
  555. (
  556. b"bar.txt",
  557. 0o160000,
  558. b"06d0bdd9e2e20377b3180e4986b14c8549b393e4",
  559. ),
  560. )
  561. self.assertEqual(
  562. [
  563. b"diff --git a/bar.txt b/bar.txt",
  564. b"old file mode 644",
  565. b"new file mode 160000",
  566. b"index a116b51..06d0bdd 160000",
  567. b"--- a/bar.txt",
  568. b"+++ b/bar.txt",
  569. b"@@ -1,2 +1 @@",
  570. b"-new",
  571. b"-same",
  572. b"+Subproject commit 06d0bdd9e2e20377b3180e4986b14c8549b393e4",
  573. ],
  574. f.getvalue().splitlines(),
  575. )
  576. class GetSummaryTests(TestCase):
  577. def test_simple(self) -> None:
  578. c = Commit()
  579. c.committer = c.author = b"Jelmer <jelmer@samba.org>"
  580. c.commit_time = c.author_time = 1271350201
  581. c.commit_timezone = c.author_timezone = 0
  582. c.message = b"This is the first line\nAnd this is the second line.\n"
  583. c.tree = Tree().id
  584. self.assertEqual("This-is-the-first-line", get_summary(c))