2
0

test_repository.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. # test_repository.py -- tests for repository.py
  2. # Copyright (C) 2007 James Westby <jw+debian@jameswestby.net>
  3. #
  4. # This program is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU General Public License
  6. # as published by the Free Software Foundation; version 2
  7. # of the License or (at your option) any later version of
  8. # the License.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  18. # MA 02110-1301, USA.
  19. """Tests for the repository."""
  20. from cStringIO import StringIO
  21. import os
  22. import shutil
  23. import tempfile
  24. import unittest
  25. import warnings
  26. from dulwich import errors
  27. from dulwich import objects
  28. from dulwich.repo import (
  29. check_ref_format,
  30. DictRefsContainer,
  31. Repo,
  32. read_packed_refs,
  33. read_packed_refs_with_peeled,
  34. write_packed_refs,
  35. _split_ref_line,
  36. )
  37. from dulwich.tests.utils import (
  38. open_repo,
  39. tear_down_repo,
  40. )
  41. missing_sha = 'b91fa4d900e17e99b433218e988c4eb4a3e9a097'
  42. class CreateRepositoryTests(unittest.TestCase):
  43. def test_create(self):
  44. tmp_dir = tempfile.mkdtemp()
  45. try:
  46. repo = Repo.init_bare(tmp_dir)
  47. self.assertEquals(tmp_dir, repo._controldir)
  48. finally:
  49. shutil.rmtree(tmp_dir)
  50. class RepositoryTests(unittest.TestCase):
  51. def setUp(self):
  52. self._repo = None
  53. def tearDown(self):
  54. if self._repo is not None:
  55. tear_down_repo(self._repo)
  56. def test_simple_props(self):
  57. r = self._repo = open_repo('a.git')
  58. self.assertEqual(r.controldir(), r.path)
  59. def test_ref(self):
  60. r = self._repo = open_repo('a.git')
  61. self.assertEqual(r.ref('refs/heads/master'),
  62. 'a90fa2d900a17e99b433217e988c4eb4a2e9a097')
  63. def test_setitem(self):
  64. r = self._repo = open_repo('a.git')
  65. r["refs/tags/foo"] = 'a90fa2d900a17e99b433217e988c4eb4a2e9a097'
  66. self.assertEquals('a90fa2d900a17e99b433217e988c4eb4a2e9a097',
  67. r["refs/tags/foo"].id)
  68. def test_get_refs(self):
  69. r = self._repo = open_repo('a.git')
  70. self.assertEqual({
  71. 'HEAD': 'a90fa2d900a17e99b433217e988c4eb4a2e9a097',
  72. 'refs/heads/master': 'a90fa2d900a17e99b433217e988c4eb4a2e9a097',
  73. 'refs/tags/mytag': '28237f4dc30d0d462658d6b937b08a0f0b6ef55a',
  74. 'refs/tags/mytag-packed': 'b0931cadc54336e78a1d980420e3268903b57a50',
  75. }, r.get_refs())
  76. def test_head(self):
  77. r = self._repo = open_repo('a.git')
  78. self.assertEqual(r.head(), 'a90fa2d900a17e99b433217e988c4eb4a2e9a097')
  79. def test_get_object(self):
  80. r = self._repo = open_repo('a.git')
  81. obj = r.get_object(r.head())
  82. self.assertEqual(obj.type_name, 'commit')
  83. def test_get_object_non_existant(self):
  84. r = self._repo = open_repo('a.git')
  85. self.assertRaises(KeyError, r.get_object, missing_sha)
  86. def test_contains_object(self):
  87. r = self._repo = open_repo('a.git')
  88. self.assertTrue(r.head() in r)
  89. def test_contains_ref(self):
  90. r = self._repo = open_repo('a.git')
  91. self.assertTrue("HEAD" in r)
  92. def test_contains_missing(self):
  93. r = self._repo = open_repo('a.git')
  94. self.assertFalse("bar" in r)
  95. def test_commit(self):
  96. r = self._repo = open_repo('a.git')
  97. warnings.simplefilter("ignore", DeprecationWarning)
  98. try:
  99. obj = r.commit(r.head())
  100. finally:
  101. warnings.resetwarnings()
  102. self.assertEqual(obj.type_name, 'commit')
  103. def test_commit_not_commit(self):
  104. r = self._repo = open_repo('a.git')
  105. warnings.simplefilter("ignore", DeprecationWarning)
  106. try:
  107. self.assertRaises(errors.NotCommitError,
  108. r.commit, '4f2e6529203aa6d44b5af6e3292c837ceda003f9')
  109. finally:
  110. warnings.resetwarnings()
  111. def test_tree(self):
  112. r = self._repo = open_repo('a.git')
  113. commit = r[r.head()]
  114. warnings.simplefilter("ignore", DeprecationWarning)
  115. try:
  116. tree = r.tree(commit.tree)
  117. finally:
  118. warnings.resetwarnings()
  119. self.assertEqual(tree.type_name, 'tree')
  120. self.assertEqual(tree.sha().hexdigest(), commit.tree)
  121. def test_tree_not_tree(self):
  122. r = self._repo = open_repo('a.git')
  123. warnings.simplefilter("ignore", DeprecationWarning)
  124. try:
  125. self.assertRaises(errors.NotTreeError, r.tree, r.head())
  126. finally:
  127. warnings.resetwarnings()
  128. def test_tag(self):
  129. r = self._repo = open_repo('a.git')
  130. tag_sha = '28237f4dc30d0d462658d6b937b08a0f0b6ef55a'
  131. warnings.simplefilter("ignore", DeprecationWarning)
  132. try:
  133. tag = r.tag(tag_sha)
  134. finally:
  135. warnings.resetwarnings()
  136. self.assertEqual(tag.type_name, 'tag')
  137. self.assertEqual(tag.sha().hexdigest(), tag_sha)
  138. obj_class, obj_sha = tag.object
  139. self.assertEqual(obj_class, objects.Commit)
  140. self.assertEqual(obj_sha, r.head())
  141. def test_tag_not_tag(self):
  142. r = self._repo = open_repo('a.git')
  143. warnings.simplefilter("ignore", DeprecationWarning)
  144. try:
  145. self.assertRaises(errors.NotTagError, r.tag, r.head())
  146. finally:
  147. warnings.resetwarnings()
  148. def test_get_peeled(self):
  149. # unpacked ref
  150. r = self._repo = open_repo('a.git')
  151. tag_sha = '28237f4dc30d0d462658d6b937b08a0f0b6ef55a'
  152. self.assertNotEqual(r[tag_sha].sha().hexdigest(), r.head())
  153. self.assertEqual(r.get_peeled('refs/tags/mytag'), r.head())
  154. # packed ref with cached peeled value
  155. packed_tag_sha = 'b0931cadc54336e78a1d980420e3268903b57a50'
  156. parent_sha = r[r.head()].parents[0]
  157. self.assertNotEqual(r[packed_tag_sha].sha().hexdigest(), parent_sha)
  158. self.assertEqual(r.get_peeled('refs/tags/mytag-packed'), parent_sha)
  159. # TODO: add more corner cases to test repo
  160. def test_get_peeled_not_tag(self):
  161. r = self._repo = open_repo('a.git')
  162. self.assertEqual(r.get_peeled('HEAD'), r.head())
  163. def test_get_blob(self):
  164. r = self._repo = open_repo('a.git')
  165. commit = r[r.head()]
  166. tree = r[commit.tree]
  167. blob_sha = tree.entries()[0][2]
  168. warnings.simplefilter("ignore", DeprecationWarning)
  169. try:
  170. blob = r.get_blob(blob_sha)
  171. finally:
  172. warnings.resetwarnings()
  173. self.assertEqual(blob.type_name, 'blob')
  174. self.assertEqual(blob.sha().hexdigest(), blob_sha)
  175. def test_get_blob_notblob(self):
  176. r = self._repo = open_repo('a.git')
  177. warnings.simplefilter("ignore", DeprecationWarning)
  178. try:
  179. self.assertRaises(errors.NotBlobError, r.get_blob, r.head())
  180. finally:
  181. warnings.resetwarnings()
  182. def test_linear_history(self):
  183. r = self._repo = open_repo('a.git')
  184. history = r.revision_history(r.head())
  185. shas = [c.sha().hexdigest() for c in history]
  186. self.assertEqual(shas, [r.head(),
  187. '2a72d929692c41d8554c07f6301757ba18a65d91'])
  188. def test_merge_history(self):
  189. r = self._repo = open_repo('simple_merge.git')
  190. history = r.revision_history(r.head())
  191. shas = [c.sha().hexdigest() for c in history]
  192. self.assertEqual(shas, ['5dac377bdded4c9aeb8dff595f0faeebcc8498cc',
  193. 'ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd',
  194. '4cffe90e0a41ad3f5190079d7c8f036bde29cbe6',
  195. '60dacdc733de308bb77bb76ce0fb0f9b44c9769e',
  196. '0d89f20333fbb1d2f3a94da77f4981373d8f4310'])
  197. def test_revision_history_missing_commit(self):
  198. r = self._repo = open_repo('simple_merge.git')
  199. self.assertRaises(errors.MissingCommitError, r.revision_history,
  200. missing_sha)
  201. def test_out_of_order_merge(self):
  202. """Test that revision history is ordered by date, not parent order."""
  203. r = self._repo = open_repo('ooo_merge.git')
  204. history = r.revision_history(r.head())
  205. shas = [c.sha().hexdigest() for c in history]
  206. self.assertEqual(shas, ['7601d7f6231db6a57f7bbb79ee52e4d462fd44d1',
  207. 'f507291b64138b875c28e03469025b1ea20bc614',
  208. 'fb5b0425c7ce46959bec94d54b9a157645e114f5',
  209. 'f9e39b120c68182a4ba35349f832d0e4e61f485c'])
  210. def test_get_tags_empty(self):
  211. r = self._repo = open_repo('ooo_merge.git')
  212. self.assertEqual({}, r.refs.as_dict('refs/tags'))
  213. def test_get_config(self):
  214. r = self._repo = open_repo('ooo_merge.git')
  215. self.assertEquals({}, r.get_config())
  216. def test_common_revisions(self):
  217. """
  218. This test demonstrates that ``find_common_revisions()`` actually returns
  219. common heads, not revisions; dulwich already uses
  220. ``find_common_revisions()`` in such a manner (see
  221. ``Repo.fetch_objects()``).
  222. """
  223. expected_shas = set(['60dacdc733de308bb77bb76ce0fb0f9b44c9769e'])
  224. # Source for objects.
  225. r_base = open_repo('simple_merge.git')
  226. # Re-create each-side of the merge in simple_merge.git.
  227. #
  228. # Since the trees and blobs are missing, the repository created is
  229. # corrupted, but we're only checking for commits for the purpose of this
  230. # test, so it's immaterial.
  231. r1_dir = tempfile.mkdtemp()
  232. r1_commits = ['ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd', # HEAD
  233. '60dacdc733de308bb77bb76ce0fb0f9b44c9769e',
  234. '0d89f20333fbb1d2f3a94da77f4981373d8f4310']
  235. r2_dir = tempfile.mkdtemp()
  236. r2_commits = ['4cffe90e0a41ad3f5190079d7c8f036bde29cbe6', # HEAD
  237. '60dacdc733de308bb77bb76ce0fb0f9b44c9769e',
  238. '0d89f20333fbb1d2f3a94da77f4981373d8f4310']
  239. try:
  240. r1 = Repo.init_bare(r1_dir)
  241. map(lambda c: r1.object_store.add_object(r_base.get_object(c)), \
  242. r1_commits)
  243. r1.refs['HEAD'] = r1_commits[0]
  244. r2 = Repo.init_bare(r2_dir)
  245. map(lambda c: r2.object_store.add_object(r_base.get_object(c)), \
  246. r2_commits)
  247. r2.refs['HEAD'] = r2_commits[0]
  248. # Finally, the 'real' testing!
  249. shas = r2.object_store.find_common_revisions(r1.get_graph_walker())
  250. self.assertEqual(set(shas), expected_shas)
  251. shas = r1.object_store.find_common_revisions(r2.get_graph_walker())
  252. self.assertEqual(set(shas), expected_shas)
  253. finally:
  254. shutil.rmtree(r1_dir)
  255. shutil.rmtree(r2_dir)
  256. class CheckRefFormatTests(unittest.TestCase):
  257. """Tests for the check_ref_format function.
  258. These are the same tests as in the git test suite.
  259. """
  260. def test_valid(self):
  261. self.assertTrue(check_ref_format('heads/foo'))
  262. self.assertTrue(check_ref_format('foo/bar/baz'))
  263. self.assertTrue(check_ref_format('refs///heads/foo'))
  264. self.assertTrue(check_ref_format('foo./bar'))
  265. self.assertTrue(check_ref_format('heads/foo@bar'))
  266. self.assertTrue(check_ref_format('heads/fix.lock.error'))
  267. def test_invalid(self):
  268. self.assertFalse(check_ref_format('foo'))
  269. self.assertFalse(check_ref_format('heads/foo/'))
  270. self.assertFalse(check_ref_format('./foo'))
  271. self.assertFalse(check_ref_format('.refs/foo'))
  272. self.assertFalse(check_ref_format('heads/foo..bar'))
  273. self.assertFalse(check_ref_format('heads/foo?bar'))
  274. self.assertFalse(check_ref_format('heads/foo.lock'))
  275. self.assertFalse(check_ref_format('heads/v@{ation'))
  276. self.assertFalse(check_ref_format('heads/foo\bar'))
  277. ONES = "1" * 40
  278. TWOS = "2" * 40
  279. THREES = "3" * 40
  280. FOURS = "4" * 40
  281. class PackedRefsFileTests(unittest.TestCase):
  282. def test_split_ref_line_errors(self):
  283. self.assertRaises(errors.PackedRefsException, _split_ref_line,
  284. 'singlefield')
  285. self.assertRaises(errors.PackedRefsException, _split_ref_line,
  286. 'badsha name')
  287. self.assertRaises(errors.PackedRefsException, _split_ref_line,
  288. '%s bad/../refname' % ONES)
  289. def test_read_without_peeled(self):
  290. f = StringIO('# comment\n%s ref/1\n%s ref/2' % (ONES, TWOS))
  291. self.assertEqual([(ONES, 'ref/1'), (TWOS, 'ref/2')],
  292. list(read_packed_refs(f)))
  293. def test_read_without_peeled_errors(self):
  294. f = StringIO('%s ref/1\n^%s' % (ONES, TWOS))
  295. self.assertRaises(errors.PackedRefsException, list, read_packed_refs(f))
  296. def test_read_with_peeled(self):
  297. f = StringIO('%s ref/1\n%s ref/2\n^%s\n%s ref/4' % (
  298. ONES, TWOS, THREES, FOURS))
  299. self.assertEqual([
  300. (ONES, 'ref/1', None),
  301. (TWOS, 'ref/2', THREES),
  302. (FOURS, 'ref/4', None),
  303. ], list(read_packed_refs_with_peeled(f)))
  304. def test_read_with_peeled_errors(self):
  305. f = StringIO('^%s\n%s ref/1' % (TWOS, ONES))
  306. self.assertRaises(errors.PackedRefsException, list, read_packed_refs(f))
  307. f = StringIO('%s ref/1\n^%s\n^%s' % (ONES, TWOS, THREES))
  308. self.assertRaises(errors.PackedRefsException, list, read_packed_refs(f))
  309. def test_write_with_peeled(self):
  310. f = StringIO()
  311. write_packed_refs(f, {'ref/1': ONES, 'ref/2': TWOS},
  312. {'ref/1': THREES})
  313. self.assertEqual(
  314. "# pack-refs with: peeled\n%s ref/1\n^%s\n%s ref/2\n" % (
  315. ONES, THREES, TWOS), f.getvalue())
  316. def test_write_without_peeled(self):
  317. f = StringIO()
  318. write_packed_refs(f, {'ref/1': ONES, 'ref/2': TWOS})
  319. self.assertEqual("%s ref/1\n%s ref/2\n" % (ONES, TWOS), f.getvalue())
  320. # Dict of refs that we expect all RefsContainerTests subclasses to define.
  321. _TEST_REFS = {
  322. 'HEAD': '42d06bd4b77fed026b154d16493e5deab78f02ec',
  323. 'refs/heads/master': '42d06bd4b77fed026b154d16493e5deab78f02ec',
  324. 'refs/heads/packed': '42d06bd4b77fed026b154d16493e5deab78f02ec',
  325. 'refs/tags/refs-0.1': 'df6800012397fb85c56e7418dd4eb9405dee075c',
  326. 'refs/tags/refs-0.2': '3ec9c43c84ff242e3ef4a9fc5bc111fd780a76a8',
  327. }
  328. class RefsContainerTests(object):
  329. def test_keys(self):
  330. actual_keys = set(self._refs.keys())
  331. self.assertEqual(set(self._refs.allkeys()), actual_keys)
  332. # ignore the symref loop if it exists
  333. actual_keys.discard('refs/heads/loop')
  334. self.assertEqual(set(_TEST_REFS.iterkeys()), actual_keys)
  335. actual_keys = self._refs.keys('refs/heads')
  336. actual_keys.discard('loop')
  337. self.assertEqual(['master', 'packed'], sorted(actual_keys))
  338. self.assertEqual(['refs-0.1', 'refs-0.2'],
  339. sorted(self._refs.keys('refs/tags')))
  340. def test_as_dict(self):
  341. # refs/heads/loop does not show up even if it exists
  342. self.assertEqual(_TEST_REFS, self._refs.as_dict())
  343. def test_setitem(self):
  344. self._refs['refs/some/ref'] = '42d06bd4b77fed026b154d16493e5deab78f02ec'
  345. self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
  346. self._refs['refs/some/ref'])
  347. def test_set_if_equals(self):
  348. nines = '9' * 40
  349. self.assertFalse(self._refs.set_if_equals('HEAD', 'c0ffee', nines))
  350. self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
  351. self._refs['HEAD'])
  352. self.assertTrue(self._refs.set_if_equals(
  353. 'HEAD', '42d06bd4b77fed026b154d16493e5deab78f02ec', nines))
  354. self.assertEqual(nines, self._refs['HEAD'])
  355. self.assertTrue(self._refs.set_if_equals('refs/heads/master', None,
  356. nines))
  357. self.assertEqual(nines, self._refs['refs/heads/master'])
  358. def test_add_if_new(self):
  359. nines = '9' * 40
  360. self.assertFalse(self._refs.add_if_new('refs/heads/master', nines))
  361. self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
  362. self._refs['refs/heads/master'])
  363. self.assertTrue(self._refs.add_if_new('refs/some/ref', nines))
  364. self.assertEqual(nines, self._refs['refs/some/ref'])
  365. def test_check_refname(self):
  366. try:
  367. self._refs._check_refname('HEAD')
  368. except KeyError:
  369. self.fail()
  370. try:
  371. self._refs._check_refname('refs/heads/foo')
  372. except KeyError:
  373. self.fail()
  374. self.assertRaises(KeyError, self._refs._check_refname, 'refs')
  375. self.assertRaises(KeyError, self._refs._check_refname, 'notrefs/foo')
  376. def test_contains(self):
  377. self.assertTrue('refs/heads/master' in self._refs)
  378. self.assertFalse('refs/heads/bar' in self._refs)
  379. def test_delitem(self):
  380. self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
  381. self._refs['refs/heads/master'])
  382. del self._refs['refs/heads/master']
  383. self.assertRaises(KeyError, lambda: self._refs['refs/heads/master'])
  384. def test_remove_if_equals(self):
  385. self.assertFalse(self._refs.remove_if_equals('HEAD', 'c0ffee'))
  386. self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
  387. self._refs['HEAD'])
  388. self.assertTrue(self._refs.remove_if_equals(
  389. 'refs/tags/refs-0.2', '3ec9c43c84ff242e3ef4a9fc5bc111fd780a76a8'))
  390. self.assertFalse('refs/tags/refs-0.2' in self._refs)
  391. class DictRefsContainerTests(RefsContainerTests, unittest.TestCase):
  392. def setUp(self):
  393. self._refs = DictRefsContainer(dict(_TEST_REFS))
  394. class DiskRefsContainerTests(RefsContainerTests, unittest.TestCase):
  395. def setUp(self):
  396. self._repo = open_repo('refs.git')
  397. self._refs = self._repo.refs
  398. def tearDown(self):
  399. tear_down_repo(self._repo)
  400. def test_get_packed_refs(self):
  401. self.assertEqual({
  402. 'refs/heads/packed': '42d06bd4b77fed026b154d16493e5deab78f02ec',
  403. 'refs/tags/refs-0.1': 'df6800012397fb85c56e7418dd4eb9405dee075c',
  404. }, self._refs.get_packed_refs())
  405. def test_get_peeled_not_packed(self):
  406. # not packed
  407. self.assertEqual(None, self._refs.get_peeled('refs/tags/refs-0.2'))
  408. self.assertEqual('3ec9c43c84ff242e3ef4a9fc5bc111fd780a76a8',
  409. self._refs['refs/tags/refs-0.2'])
  410. # packed, known not peelable
  411. self.assertEqual(self._refs['refs/heads/packed'],
  412. self._refs.get_peeled('refs/heads/packed'))
  413. # packed, peeled
  414. self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
  415. self._refs.get_peeled('refs/tags/refs-0.1'))
  416. def test_setitem(self):
  417. RefsContainerTests.test_setitem(self)
  418. f = open(os.path.join(self._refs.path, 'refs', 'some', 'ref'), 'rb')
  419. self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
  420. f.read()[:40])
  421. f.close()
  422. def test_setitem_symbolic(self):
  423. ones = '1' * 40
  424. self._refs['HEAD'] = ones
  425. self.assertEqual(ones, self._refs['HEAD'])
  426. # ensure HEAD was not modified
  427. f = open(os.path.join(self._refs.path, 'HEAD'), 'rb')
  428. self.assertEqual('ref: refs/heads/master', iter(f).next().rstrip('\n'))
  429. f.close()
  430. # ensure the symbolic link was written through
  431. f = open(os.path.join(self._refs.path, 'refs', 'heads', 'master'), 'rb')
  432. self.assertEqual(ones, f.read()[:40])
  433. f.close()
  434. def test_set_if_equals(self):
  435. RefsContainerTests.test_set_if_equals(self)
  436. # ensure symref was followed
  437. self.assertEqual('9' * 40, self._refs['refs/heads/master'])
  438. # ensure lockfile was deleted
  439. self.assertFalse(os.path.exists(
  440. os.path.join(self._refs.path, 'refs', 'heads', 'master.lock')))
  441. self.assertFalse(os.path.exists(
  442. os.path.join(self._refs.path, 'HEAD.lock')))
  443. def test_add_if_new_packed(self):
  444. # don't overwrite packed ref
  445. self.assertFalse(self._refs.add_if_new('refs/tags/refs-0.1', '9' * 40))
  446. self.assertEqual('df6800012397fb85c56e7418dd4eb9405dee075c',
  447. self._refs['refs/tags/refs-0.1'])
  448. def test_add_if_new_symbolic(self):
  449. # Use an empty repo instead of the default.
  450. tear_down_repo(self._repo)
  451. repo_dir = os.path.join(tempfile.mkdtemp(), 'test')
  452. os.makedirs(repo_dir)
  453. self._repo = Repo.init(repo_dir)
  454. refs = self._repo.refs
  455. nines = '9' * 40
  456. self.assertEqual('ref: refs/heads/master', refs.read_ref('HEAD'))
  457. self.assertFalse('refs/heads/master' in refs)
  458. self.assertTrue(refs.add_if_new('HEAD', nines))
  459. self.assertEqual('ref: refs/heads/master', refs.read_ref('HEAD'))
  460. self.assertEqual(nines, refs['HEAD'])
  461. self.assertEqual(nines, refs['refs/heads/master'])
  462. self.assertFalse(refs.add_if_new('HEAD', '1' * 40))
  463. self.assertEqual(nines, refs['HEAD'])
  464. self.assertEqual(nines, refs['refs/heads/master'])
  465. def test_follow(self):
  466. self.assertEquals(
  467. ('refs/heads/master', '42d06bd4b77fed026b154d16493e5deab78f02ec'),
  468. self._refs._follow('HEAD'))
  469. self.assertEquals(
  470. ('refs/heads/master', '42d06bd4b77fed026b154d16493e5deab78f02ec'),
  471. self._refs._follow('refs/heads/master'))
  472. self.assertRaises(KeyError, self._refs._follow, 'notrefs/foo')
  473. self.assertRaises(KeyError, self._refs._follow, 'refs/heads/loop')
  474. def test_delitem(self):
  475. RefsContainerTests.test_delitem(self)
  476. ref_file = os.path.join(self._refs.path, 'refs', 'heads', 'master')
  477. self.assertFalse(os.path.exists(ref_file))
  478. self.assertFalse('refs/heads/master' in self._refs.get_packed_refs())
  479. def test_delitem_symbolic(self):
  480. self.assertEqual('ref: refs/heads/master',
  481. self._refs.read_loose_ref('HEAD'))
  482. del self._refs['HEAD']
  483. self.assertRaises(KeyError, lambda: self._refs['HEAD'])
  484. self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
  485. self._refs['refs/heads/master'])
  486. self.assertFalse(os.path.exists(os.path.join(self._refs.path, 'HEAD')))
  487. def test_remove_if_equals_symref(self):
  488. # HEAD is a symref, so shouldn't equal its dereferenced value
  489. self.assertFalse(self._refs.remove_if_equals(
  490. 'HEAD', '42d06bd4b77fed026b154d16493e5deab78f02ec'))
  491. self.assertTrue(self._refs.remove_if_equals(
  492. 'refs/heads/master', '42d06bd4b77fed026b154d16493e5deab78f02ec'))
  493. self.assertRaises(KeyError, lambda: self._refs['refs/heads/master'])
  494. # HEAD is now a broken symref
  495. self.assertRaises(KeyError, lambda: self._refs['HEAD'])
  496. self.assertEqual('ref: refs/heads/master',
  497. self._refs.read_loose_ref('HEAD'))
  498. self.assertFalse(os.path.exists(
  499. os.path.join(self._refs.path, 'refs', 'heads', 'master.lock')))
  500. self.assertFalse(os.path.exists(
  501. os.path.join(self._refs.path, 'HEAD.lock')))
  502. def test_remove_if_equals_packed(self):
  503. # test removing ref that is only packed
  504. self.assertEqual('df6800012397fb85c56e7418dd4eb9405dee075c',
  505. self._refs['refs/tags/refs-0.1'])
  506. self.assertTrue(
  507. self._refs.remove_if_equals('refs/tags/refs-0.1',
  508. 'df6800012397fb85c56e7418dd4eb9405dee075c'))
  509. self.assertRaises(KeyError, lambda: self._refs['refs/tags/refs-0.1'])
  510. def test_read_ref(self):
  511. self.assertEqual('ref: refs/heads/master', self._refs.read_ref("HEAD"))
  512. self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
  513. self._refs.read_ref("refs/heads/packed"))
  514. self.assertEqual(None,
  515. self._refs.read_ref("nonexistant"))