test_patch.py 21 KB

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