|
@@ -0,0 +1,194 @@
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+from dulwich.object_store import (
|
|
|
+ MemoryObjectStore,
|
|
|
+ )
|
|
|
+from dulwich.objects import (
|
|
|
+ Blob,
|
|
|
+ )
|
|
|
+from dulwich.tests import TestCase
|
|
|
+from utils import (
|
|
|
+ make_object,
|
|
|
+ build_commit_graph,
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+class MissingObjectFinderTest(TestCase):
|
|
|
+
|
|
|
+ def setUp(self):
|
|
|
+ super(MissingObjectFinderTest, self).setUp()
|
|
|
+ self.store = MemoryObjectStore()
|
|
|
+ self.commits = []
|
|
|
+
|
|
|
+ def cmt(self, n):
|
|
|
+ return self.commits[n-1]
|
|
|
+
|
|
|
+ def assertMissingMatch(self, haves, wants, expected):
|
|
|
+ for sha, path in self.store.find_missing_objects(haves, wants):
|
|
|
+ self.assertTrue(sha in expected,
|
|
|
+ "(%s,%s) erroneously reported as missing" % (sha, path))
|
|
|
+ expected.remove(sha)
|
|
|
+
|
|
|
+ self.assertEquals(len(expected), 0,
|
|
|
+ "some objects are not reported as missing: %s" % (expected, ))
|
|
|
+
|
|
|
+
|
|
|
+class MOFLinearRepoTest(MissingObjectFinderTest):
|
|
|
+
|
|
|
+ def setUp(self):
|
|
|
+ super(MOFLinearRepoTest, self).setUp()
|
|
|
+ f1_1 = make_object(Blob, data='f1')
|
|
|
+ f2_1 = make_object(Blob, data='f2')
|
|
|
+ f2_2 = make_object(Blob, data='f2-changed')
|
|
|
+ f2_3 = make_object(Blob, data='f2-changed-again')
|
|
|
+ f3_2 = make_object(Blob, data='f3')
|
|
|
+
|
|
|
+ commit_spec = [[1], [2, 1], [3, 2]]
|
|
|
+ trees = {1: [('f1', f1_1), ('f2', f2_1)],
|
|
|
+ 2: [('f1', f1_1), ('f2', f2_2), ('f3', f3_2)],
|
|
|
+ 3: [('f2', f2_3), ('f3', f3_2)] }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ self.commits = build_commit_graph(self.store, commit_spec, trees)
|
|
|
+ self.missing_1_2 = [self.cmt(2).id, self.cmt(2).tree, f2_2.id, f3_2.id]
|
|
|
+ self.missing_2_3 = [self.cmt(3).id, self.cmt(3).tree, f2_3.id]
|
|
|
+ self.missing_1_3 = [
|
|
|
+ self.cmt(2).id, self.cmt(3).id,
|
|
|
+ self.cmt(2).tree, self.cmt(3).tree,
|
|
|
+ f2_2.id, f3_2.id, f2_3.id]
|
|
|
+
|
|
|
+ def test_1_to_2(self):
|
|
|
+ self.assertMissingMatch([self.cmt(1).id], [self.cmt(2).id],
|
|
|
+ self.missing_1_2)
|
|
|
+
|
|
|
+ def test_2_to_3(self):
|
|
|
+ self.assertMissingMatch([self.cmt(2).id], [self.cmt(3).id],
|
|
|
+ self.missing_2_3)
|
|
|
+
|
|
|
+ def test_1_to_3(self):
|
|
|
+ self.assertMissingMatch([self.cmt(1).id], [self.cmt(3).id],
|
|
|
+ self.missing_1_3)
|
|
|
+
|
|
|
+ def test_bogus_haves_failure(self):
|
|
|
+ """Ensure non-existent SHA in haves are not tolerated"""
|
|
|
+ bogus_sha = self.cmt(2).id[::-1]
|
|
|
+ haves = [self.cmt(1).id, bogus_sha]
|
|
|
+ wants = [self.cmt(3).id]
|
|
|
+ self.assertRaises(KeyError, self.store.find_missing_objects,
|
|
|
+ self.store, haves, wants)
|
|
|
+
|
|
|
+ def test_bogus_wants_failure(self):
|
|
|
+ """Ensure non-existent SHA in wants are not tolerated"""
|
|
|
+ bogus_sha = self.cmt(2).id[::-1]
|
|
|
+ haves = [self.cmt(1).id]
|
|
|
+ wants = [self.cmt(3).id, bogus_sha]
|
|
|
+ self.assertRaises(KeyError, self.store.find_missing_objects,
|
|
|
+ self.store, haves, wants)
|
|
|
+
|
|
|
+ def test_no_changes(self):
|
|
|
+ self.assertMissingMatch([self.cmt(3).id], [self.cmt(3).id], [])
|
|
|
+
|
|
|
+
|
|
|
+class MOFMergeForkRepoTest(MissingObjectFinderTest):
|
|
|
+ """ 1 --- 2 --- 4 --- 6 --- 7
|
|
|
+ \ /
|
|
|
+ 3 ---
|
|
|
+ \
|
|
|
+ 5
|
|
|
+ """
|
|
|
+
|
|
|
+ def setUp(self):
|
|
|
+ super(MOFMergeForkRepoTest, self).setUp()
|
|
|
+ f1_1 = make_object(Blob, data='f1')
|
|
|
+ f1_2 = make_object(Blob, data='f1-2')
|
|
|
+ f1_4 = make_object(Blob, data='f1-4')
|
|
|
+ f1_7 = make_object(Blob, data='f1-2')
|
|
|
+ f2_1 = make_object(Blob, data='f2')
|
|
|
+ f2_3 = make_object(Blob, data='f2-3')
|
|
|
+ f3_3 = make_object(Blob, data='f3')
|
|
|
+ f3_5 = make_object(Blob, data='f3-5')
|
|
|
+ commit_spec = [[1], [2, 1], [3, 2], [4, 2], [5, 3], [6, 3, 4], [7, 6]]
|
|
|
+ trees = {1: [('f1', f1_1), ('f2', f2_1)],
|
|
|
+ 2: [('f1', f1_2), ('f2', f2_1)],
|
|
|
+
|
|
|
+ 3: [('f1', f1_2), ('f2', f2_3), ('f3', f3_3)],
|
|
|
+ 4: [('f1', f1_4), ('f2', f2_1)],
|
|
|
+ 5: [('f1', f1_2), ('f3', f3_5)],
|
|
|
+ 6: [('f1', f1_4), ('f2', f2_3), ('f3', f3_3)],
|
|
|
+
|
|
|
+ 7: [('f1', f1_7), ('f2', f2_3)]}
|
|
|
+ self.commits = build_commit_graph(self.store, commit_spec, trees)
|
|
|
+
|
|
|
+ self.f1_2_id = f1_2.id
|
|
|
+ self.f1_4_id = f1_4.id
|
|
|
+ self.f1_7_id = f1_7.id
|
|
|
+ self.f2_3_id = f2_3.id
|
|
|
+ self.f3_3_id = f3_3.id
|
|
|
+
|
|
|
+ self.assertEquals(f1_2.id, f1_7.id, "[sanity]")
|
|
|
+
|
|
|
+ def test_have6_want7(self):
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ self.assertMissingMatch([self.cmt(6).id], [self.cmt(7).id],
|
|
|
+ [self.cmt(7).id, self.cmt(7).tree, self.f1_7_id])
|
|
|
+
|
|
|
+ def test_have4_want7(self):
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ self.assertMissingMatch([self.cmt(4).id], [self.cmt(7).id], [
|
|
|
+ self.cmt(7).id, self.cmt(6).id, self.cmt(3).id,
|
|
|
+ self.cmt(7).tree, self.cmt(6).tree, self.cmt(3).tree,
|
|
|
+ self.f2_3_id, self.f3_3_id])
|
|
|
+
|
|
|
+ def test_have1_want6(self):
|
|
|
+
|
|
|
+ self.assertMissingMatch([self.cmt(1).id], [self.cmt(6).id], [
|
|
|
+ self.cmt(6).id, self.cmt(4).id, self.cmt(3).id, self.cmt(2).id,
|
|
|
+ self.cmt(6).tree, self.cmt(4).tree, self.cmt(3).tree,
|
|
|
+ self.cmt(2).tree, self.f1_2_id, self.f1_4_id, self.f2_3_id,
|
|
|
+ self.f3_3_id])
|
|
|
+
|
|
|
+ def test_have3_want6(self):
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ self.assertMissingMatch([self.cmt(3).id], [self.cmt(7).id], [
|
|
|
+ self.cmt(7).id, self.cmt(6).id, self.cmt(4).id,
|
|
|
+ self.cmt(7).tree, self.cmt(6).tree, self.cmt(4).tree,
|
|
|
+ self.f1_4_id])
|
|
|
+
|
|
|
+ def test_have5_want7(self):
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ self.assertMissingMatch([self.cmt(5).id], [self.cmt(7).id], [
|
|
|
+ self.cmt(7).id, self.cmt(6).id, self.cmt(4).id,
|
|
|
+ self.cmt(7).tree, self.cmt(6).tree, self.cmt(4).tree,
|
|
|
+ self.f1_4_id])
|