def test_tree_changes_complex(self): blob_a_1 = make_object(Blob, data=b"a1_1") blob_bx1_1 = make_object(Blob, data=b"bx1_1") blob_bx2_1 = make_object(Blob, data=b"bx2_1") blob_by1_1 = make_object(Blob, data=b"by1_1") blob_by2_1 = make_object(Blob, data=b"by2_1") tree1 = self.commit_tree( [ ("a", blob_a_1), ("b/x/1", blob_bx1_1), ("b/x/2", blob_bx2_1), ("b/y/1", blob_by1_1), ("b/y/2", blob_by2_1), ] ) blob_a_2 = make_object(Blob, data=b"a1_2") blob_bx1_2 = blob_bx1_1 blob_by_2 = make_object(Blob, data=b"by_2") blob_c_2 = make_object(Blob, data=b"c_2") tree2 = self.commit_tree([("a", blob_a_2), ("b/x/1", blob_bx1_2), ("b/y", blob_by_2), ("c", blob_c_2)]) self.assertChangesEqual( [ TreeChange(CHANGE_MODIFY, (b"a", F, blob_a_1.id), (b"a", F, blob_a_2.id)), TreeChange.delete((b"b/x/2", F, blob_bx2_1.id)), TreeChange.add((b"b/y", F, blob_by_2.id)), TreeChange.delete((b"b/y/1", F, blob_by1_1.id)), TreeChange.delete((b"b/y/2", F, blob_by2_1.id)), TreeChange.add((b"c", F, blob_c_2.id)), ], tree1, tree2, )
def test_tree_changes_rename_detector(self): blob_a1 = make_object(Blob, data='a\nb\nc\nd\n') blob_a2 = make_object(Blob, data='a\nb\nc\ne\n') blob_b = make_object(Blob, data='b') tree1 = self.commit_tree([('a', blob_a1), ('b', blob_b)]) tree2 = self.commit_tree([('c', blob_a2), ('b', blob_b)]) detector = RenameDetector(self.store) self.assertChangesEqual( [TreeChange.delete(('a', F, blob_a1.id)), TreeChange.add(('c', F, blob_a2.id))], tree1, tree2) self.assertChangesEqual( [TreeChange.delete(('a', F, blob_a1.id)), TreeChange(CHANGE_UNCHANGED, ('b', F, blob_b.id), ('b', F, blob_b.id)), TreeChange.add(('c', F, blob_a2.id))], tree1, tree2, want_unchanged=True) self.assertChangesEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob_a1.id), ('c', F, blob_a2.id))], tree1, tree2, rename_detector=detector) self.assertChangesEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob_a1.id), ('c', F, blob_a2.id)), TreeChange(CHANGE_UNCHANGED, ('b', F, blob_b.id), ('b', F, blob_b.id))], tree1, tree2, rename_detector=detector, want_unchanged=True)
def test_tree_changes_complex(self): blob_a_1 = make_object(Blob, data='a1_1') blob_bx1_1 = make_object(Blob, data='bx1_1') blob_bx2_1 = make_object(Blob, data='bx2_1') blob_by1_1 = make_object(Blob, data='by1_1') blob_by2_1 = make_object(Blob, data='by2_1') tree1 = self.commit_tree([ ('a', blob_a_1), ('b/x/1', blob_bx1_1), ('b/x/2', blob_bx2_1), ('b/y/1', blob_by1_1), ('b/y/2', blob_by2_1), ]) blob_a_2 = make_object(Blob, data='a1_2') blob_bx1_2 = blob_bx1_1 blob_by_2 = make_object(Blob, data='by_2') blob_c_2 = make_object(Blob, data='c_2') tree2 = self.commit_tree([ ('a', blob_a_2), ('b/x/1', blob_bx1_2), ('b/y', blob_by_2), ('c', blob_c_2), ]) self.assertChangesEqual( [TreeChange(CHANGE_MODIFY, ('a', F, blob_a_1.id), ('a', F, blob_a_2.id)), TreeChange.delete(('b/x/2', F, blob_bx2_1.id)), TreeChange.add(('b/y', F, blob_by_2.id)), TreeChange.delete(('b/y/1', F, blob_by1_1.id)), TreeChange.delete(('b/y/2', F, blob_by2_1.id)), TreeChange.add(('c', F, blob_c_2.id))], tree1, tree2)
def test_all_with_merge(self): blob_a = make_object(Blob, data=b'a') blob_a2 = make_object(Blob, data=b'a2') blob_b = make_object(Blob, data=b'b') blob_b2 = make_object(Blob, data=b'b2') x1, y2, m3 = self.make_commits( [[1], [2], [3, 1, 2]], trees={1: [(b'x/a', blob_a)], 2: [(b'y/b', blob_b)], 3: [(b'x/a', blob_a2), (b'y/b', blob_b2)]}) # Get the WalkEntry for the merge commit. walker = Walker(self.store, m3.id) entries = list(walker) walker_entry = entries[0] self.assertEqual(walker_entry.commit.id, m3.id) changes = walker_entry.changes() self.assertEqual(2, len(changes)) entry_a = (b'x/a', F, blob_a.id) entry_a2 = (b'x/a', F, blob_a2.id) entry_b = (b'y/b', F, blob_b.id) entry_b2 = (b'y/b', F, blob_b2.id) self.assertEqual( [[TreeChange(CHANGE_MODIFY, entry_a, entry_a2), TreeChange.add(entry_a2)], [TreeChange.add(entry_b2), TreeChange(CHANGE_MODIFY, entry_b, entry_b2)]], changes, )
def test_tree_changes_to_tree(self): blob_a = make_object(Blob, data=b"a") blob_x = make_object(Blob, data=b"x") tree1 = self.commit_tree([("a", blob_a)]) tree2 = self.commit_tree([("a/x", blob_x)]) self.assertChangesEqual( [TreeChange.delete((b"a", F, blob_a.id)), TreeChange.add((b"a/x", F, blob_x.id))], tree1, tree2 )
def test_exact_rename_split_different_type(self): blob = make_object(Blob, data=b"/foo") tree1 = self.commit_tree([("a", blob, 0o100644)]) tree2 = self.commit_tree([("a", blob, 0o120000)]) self.assertEqual( [TreeChange.add((b"a", 0o120000, blob.id)), TreeChange.delete((b"a", 0o100644, blob.id))], self.detect_renames(tree1, tree2), )
def test_tree_changes_change_type(self): blob_a1 = make_object(Blob, data='a') blob_a2 = make_object(Blob, data='/foo/bar') tree1 = self.commit_tree([('a', blob_a1, 0o100644)]) tree2 = self.commit_tree([('a', blob_a2, 0o120000)]) self.assertChangesEqual( [TreeChange.delete(('a', 0o100644, blob_a1.id)), TreeChange.add(('a', 0o120000, blob_a2.id))], tree1, tree2)
def test_tree_changes_to_tree(self): blob_a = make_object(Blob, data='a') blob_x = make_object(Blob, data='x') tree1 = self.commit_tree([('a', blob_a)]) tree2 = self.commit_tree([('a/x', blob_x)]) self.assertChangesEqual( [TreeChange.delete(('a', F, blob_a.id)), TreeChange.add(('a/x', F, blob_x.id))], tree1, tree2)
def test_content_rename_one_to_many(self): blob1 = make_object(Blob, data='aa\nb\nc\nd\ne\n') blob2 = make_object(Blob, data='ab\nb\nc\nd\ne\n') # 8/11 match blob3 = make_object(Blob, data='aa\nb\nc\nd\nf\n') # 9/11 match tree1 = self.commit_tree([('a', blob1)]) tree2 = self.commit_tree([('b', blob2), ('c', blob3)]) self.assertEqual([ TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('b', F, blob2.id)), TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('c', F, blob3.id)) ], self.detect_renames(tree1, tree2))
def test_tree_changes_for_merge_delete_delete_conflict(self): blob1 = make_object(Blob, data='1') blob2 = make_object(Blob, data='2') parent1 = self.commit_tree([('a', blob1)]) parent2 = self.commit_tree([('a', blob2)]) merge = self.commit_tree([]) self.assertChangesForMergeEqual([[ TreeChange.delete(('a', F, blob1.id)), TreeChange.delete(('a', F, blob2.id)) ]], [parent1, parent2], merge)
def test_find_copies_harder_content(self): blob1 = make_object(Blob, data='a\nb\nc\nd\n') blob2 = make_object(Blob, data='a\nb\nc\ne\n') tree1 = self.commit_tree([('a', blob1)]) tree2 = self.commit_tree([('a', blob1), ('b', blob2)]) self.assertEqual([TreeChange.add(('b', F, blob2.id))], self.detect_renames(tree1, tree2)) self.assertEqual( [TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('b', F, blob2.id))], self.detect_renames(tree1, tree2, find_copies_harder=True))
def test_content_rename_many_to_one(self): blob1 = make_object(Blob, data='a\nb\nc\nd\n') blob2 = make_object(Blob, data='a\nb\nc\ne\n') blob3 = make_object(Blob, data='a\nb\nc\nf\n') tree1 = self.commit_tree([('a', blob1), ('b', blob2)]) tree2 = self.commit_tree([('c', blob3)]) self.assertEqual([ TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('c', F, blob3.id)), TreeChange.delete(('b', F, blob2.id)) ], self.detect_renames(tree1, tree2))
def test_exact_rename_and_different_type(self): blob1 = make_object(Blob, data=b'1') blob2 = make_object(Blob, data=b'2') tree1 = self.commit_tree([(b'a', blob1)]) tree2 = self.commit_tree([(b'a', blob2, 0o120000), (b'b', blob1)]) self.assertEqual( [TreeChange.add((b'a', 0o120000, blob2.id)), TreeChange(CHANGE_RENAME, (b'a', F, blob1.id), (b'b', F, blob1.id))], self.detect_renames(tree1, tree2))
def test_tree_changes_for_merge_add_exact_rename_conflict(self): blob = make_object(Blob, data=b'a\nb\nc\nd\n') parent1 = self.commit_tree([(b'a', blob)]) parent2 = self.commit_tree([]) merge = self.commit_tree([(b'b', blob)]) self.assertChangesForMergeEqual( [[TreeChange(CHANGE_RENAME, (b'a', F, blob.id), (b'b', F, blob.id)), TreeChange.add((b'b', F, blob.id))]], [parent1, parent2], merge, rename_detector=self.detector)
def test_tree_changes_for_merge_modify_rename_conflict(self): blob1 = make_object(Blob, data=b'a\nb\nc\nd\n') blob2 = make_object(Blob, data=b'a\nb\nc\ne\n') parent1 = self.commit_tree([(b'a', blob1)]) parent2 = self.commit_tree([(b'b', blob1)]) merge = self.commit_tree([(b'b', blob2)]) self.assertChangesForMergeEqual( [[TreeChange(CHANGE_RENAME, (b'a', F, blob1.id), (b'b', F, blob2.id)), TreeChange(CHANGE_MODIFY, (b'b', F, blob1.id), (b'b', F, blob2.id))]], [parent1, parent2], merge, rename_detector=self.detector)
def test_tree_changes_no_changes(self): blob = make_object(Blob, data=b'blob') tree = self.commit_tree([(b'a', blob), (b'b/c', blob)]) self.assertChangesEqual([], self.empty_tree, self.empty_tree) self.assertChangesEqual([], tree, tree) self.assertChangesEqual( [TreeChange(CHANGE_UNCHANGED, (b'a', F, blob.id), (b'a', F, blob.id)), TreeChange(CHANGE_UNCHANGED, (b'b/c', F, blob.id), (b'b/c', F, blob.id))], tree, tree, want_unchanged=True)
def test_tree_changes_for_merge_add_modify_conflict(self): blob1 = make_object(Blob, data='1') blob2 = make_object(Blob, data='2') parent1 = self.commit_tree([]) parent2 = self.commit_tree([('a', blob1)]) merge = self.commit_tree([('a', blob2)]) self.assertChangesForMergeEqual([[ TreeChange.add(('a', F, blob2.id)), TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob2.id)) ]], [parent1, parent2], merge)
def test_tree_changes_for_merge_delete_delete_conflict(self): blob1 = make_object(Blob, data='1') blob2 = make_object(Blob, data='2') parent1 = self.commit_tree([('a', blob1)]) parent2 = self.commit_tree([('a', blob2)]) merge = self.commit_tree([]) self.assertChangesForMergeEqual( [[TreeChange.delete(('a', F, blob1.id)), TreeChange.delete(('a', F, blob2.id))]], [parent1, parent2], merge)
def test_exact_copy_modify(self): blob1 = make_object(Blob, data=b'a\nb\nc\nd\n') blob2 = make_object(Blob, data=b'a\nb\nc\ne\n') tree1 = self.commit_tree([(b'a', blob1)]) tree2 = self.commit_tree([(b'a', blob2), (b'b', blob1)]) self.assertEqual([ TreeChange(CHANGE_MODIFY, (b'a', F, blob1.id), (b'a', F, blob2.id)), TreeChange(CHANGE_COPY, (b'a', F, blob1.id), (b'b', F, blob1.id)) ], self.detect_renames(tree1, tree2))
def test_exact_rename_one_to_one(self): blob1 = make_object(Blob, data=b'1') blob2 = make_object(Blob, data=b'2') tree1 = self.commit_tree([(b'a', blob1), (b'b', blob2)]) tree2 = self.commit_tree([(b'c', blob1), (b'd', blob2)]) self.assertEqual([ TreeChange(CHANGE_RENAME, (b'a', F, blob1.id), (b'c', F, blob1.id)), TreeChange(CHANGE_RENAME, (b'b', F, blob2.id), (b'd', F, blob2.id)) ], self.detect_renames(tree1, tree2))
def test_content_rename_one_to_one(self): b11 = make_object(Blob, data='a\nb\nc\nd\n') b12 = make_object(Blob, data='a\nb\nc\ne\n') b21 = make_object(Blob, data='e\nf\ng\n\h') b22 = make_object(Blob, data='e\nf\ng\n\i') tree1 = self.commit_tree([('a', b11), ('b', b21)]) tree2 = self.commit_tree([('c', b12), ('d', b22)]) self.assertEqual( [TreeChange(CHANGE_RENAME, ('a', F, b11.id), ('c', F, b12.id)), TreeChange(CHANGE_RENAME, ('b', F, b21.id), ('d', F, b22.id))], self.detect_renames(tree1, tree2))
def test_content_rename_with_more_deletions(self): blob1 = make_object(Blob, data='') tree1 = self.commit_tree([('a', blob1), ('b', blob1), ('c', blob1), ('d', blob1)]) tree2 = self.commit_tree([('e', blob1), ('f', blob1), ('g', blob1)]) self.maxDiff = None self.assertEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('e', F, blob1.id)), TreeChange(CHANGE_RENAME, ('b', F, blob1.id), ('f', F, blob1.id)), TreeChange(CHANGE_RENAME, ('c', F, blob1.id), ('g', F, blob1.id)), TreeChange.delete(('d', F, blob1.id))], self.detect_renames(tree1, tree2))
def test_exact_rename_split_different_type(self): blob = make_object(Blob, data=b"/foo") tree1 = self.commit_tree([(b"a", blob, 0o100644)]) tree2 = self.commit_tree([(b"a", blob, 0o120000)]) self.assertEqual( [ TreeChange.add((b"a", 0o120000, blob.id)), TreeChange.delete((b"a", 0o100644, blob.id)), ], self.detect_renames(tree1, tree2), )
def test_content_rename_swap(self): blob1 = make_object(Blob, data='a\nb\nc\nd\n') blob2 = make_object(Blob, data='e\nf\ng\nh\n') blob3 = make_object(Blob, data='a\nb\nc\ne\n') blob4 = make_object(Blob, data='e\nf\ng\ni\n') tree1 = self.commit_tree([('a', blob1), ('b', blob2)]) tree2 = self.commit_tree([('a', blob4), ('b', blob3)]) self.assertEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob3.id)), TreeChange(CHANGE_RENAME, ('b', F, blob2.id), ('a', F, blob4.id))], self.detect_renames(tree1, tree2, rewrite_threshold=60))
def test_find_copies_harder_exact(self): blob = make_object(Blob, data=b"blob") tree1 = self.commit_tree([(b"a", blob)]) tree2 = self.commit_tree([(b"a", blob), (b"b", blob)]) self.assertEqual( [TreeChange.add((b"b", F, blob.id))], self.detect_renames(tree1, tree2), ) self.assertEqual( [TreeChange(CHANGE_COPY, (b"a", F, blob.id), (b"b", F, blob.id))], self.detect_renames(tree1, tree2, find_copies_harder=True), )
def test_changes_with_renames(self): blob = make_object(Blob, data="blob") c1, c2 = self.make_linear_commits(2, trees={1: [("a", blob)], 2: [("b", blob)]}) entry_a = ("a", F, blob.id) entry_b = ("b", F, blob.id) changes_without_renames = [TreeChange.delete(entry_a), TreeChange.add(entry_b)] changes_with_renames = [TreeChange(CHANGE_RENAME, entry_a, entry_b)] self.assertWalkYields([TestWalkEntry(c2, changes_without_renames)], [c2.id], max_entries=1) detector = RenameDetector(self.store) self.assertWalkYields( [TestWalkEntry(c2, changes_with_renames)], [c2.id], max_entries=1, rename_detector=detector )
def test_tree_entry_sort(self): sha = Sha1Sum("abcd" * 10) expected_entries = [ TreeChange.add(TreeEntry(b"aaa", F, sha)), TreeChange(CHANGE_COPY, TreeEntry(b"bbb", F, sha), TreeEntry(b"aab", F, sha)), TreeChange(CHANGE_MODIFY, TreeEntry(b"bbb", F, sha), TreeEntry(b"bbb", F, Sha1Sum("dabc" * 10))), TreeChange(CHANGE_RENAME, TreeEntry(b"bbc", F, sha), TreeEntry(b"ddd", F, sha)), TreeChange.delete(TreeEntry(b"ccc", F, sha)), ] for perm in permutations(expected_entries): self.assertEqual(expected_entries, sorted(perm, key=_tree_change_key))
def test_changes_one_parent(self): blob_a1 = make_object(Blob, data='a1') blob_a2 = make_object(Blob, data='a2') blob_b2 = make_object(Blob, data='b2') c1, c2 = self.make_linear_commits( 2, trees={1: [('a', blob_a1)], 2: [('a', blob_a2), ('b', blob_b2)]}) e1 = TestWalkEntry(c1, [TreeChange.add(('a', F, blob_a1.id))]) e2 = TestWalkEntry(c2, [TreeChange(CHANGE_MODIFY, ('a', F, blob_a1.id), ('a', F, blob_a2.id)), TreeChange.add(('b', F, blob_b2.id))]) self.assertWalkYields([e2, e1], [c2.id])
def test_exact_rename_many_to_one(self): blob = make_object(Blob, data=b"1") tree1 = self.commit_tree([(b"a", blob), (b"b", blob)]) tree2 = self.commit_tree([(b"c", blob)]) self.assertEqual( [ TreeChange(CHANGE_RENAME, (b"a", F, blob.id), (b"c", F, blob.id)), TreeChange.delete((b"b", F, blob.id)), ], self.detect_renames(tree1, tree2), )
def test_rename_threshold(self): blob1 = make_object(Blob, data='a\nb\nc\n') blob2 = make_object(Blob, data='a\nb\nd\n') tree1 = self.commit_tree([('a', blob1)]) tree2 = self.commit_tree([('b', blob2)]) self.assertEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob2.id))], self.detect_renames(tree1, tree2, rename_threshold=50)) self.assertEqual( [TreeChange.delete(('a', F, blob1.id)), TreeChange.add(('b', F, blob2.id))], self.detect_renames(tree1, tree2, rename_threshold=75))
def test_exact_rename_many_to_many(self): blob = make_object(Blob, data=b'1') tree1 = self.commit_tree([(b'a', blob), (b'b', blob)]) tree2 = self.commit_tree([(b'c', blob), (b'd', blob), (b'e', blob)]) self.assertEqual( [TreeChange(CHANGE_RENAME, (b'a', F, blob.id), (b'c', F, blob.id)), TreeChange(CHANGE_COPY, (b'a', F, blob.id), (b'e', F, blob.id)), TreeChange(CHANGE_RENAME, (b'b', F, blob.id), (b'd', F, blob.id))], self.detect_renames(tree1, tree2))
def test_tree_changes_name_order(self): blob = make_object(Blob, data='a') tree1 = self.commit_tree([('a', blob), ('a.', blob), ('a..', blob)]) # Tree order is the reverse of this, so if we used tree order, 'a..' # would not be merged. tree2 = self.commit_tree([('a/x', blob), ('a./x', blob), ('a..', blob)]) self.assertChangesEqual( [TreeChange.delete(('a', F, blob.id)), TreeChange.add(('a/x', F, blob.id)), TreeChange.delete(('a.', F, blob.id)), TreeChange.add(('a./x', F, blob.id))], tree1, tree2)
def test_tree_changes_add_delete(self): blob_a = make_object(Blob, data='a') blob_b = make_object(Blob, data='b') tree = self.commit_tree([('a', blob_a, 0o100644), ('x/b', blob_b, 0o100755)]) self.assertChangesEqual( [TreeChange.add(('a', 0o100644, blob_a.id)), TreeChange.add(('x/b', 0o100755, blob_b.id))], self.empty_tree, tree) self.assertChangesEqual( [TreeChange.delete(('a', 0o100644, blob_a.id)), TreeChange.delete(('x/b', 0o100755, blob_b.id))], tree, self.empty_tree)
def test_tree_changes_change_type(self): blob_a1 = make_object(Blob, data=b"a") blob_a2 = make_object(Blob, data=b"/foo/bar") tree1 = self.commit_tree([(b"a", blob_a1, 0o100644)]) tree2 = self.commit_tree([(b"a", blob_a2, 0o120000)]) self.assertChangesEqual( [ TreeChange.delete((b"a", 0o100644, blob_a1.id)), TreeChange.add((b"a", 0o120000, blob_a2.id)), ], tree1, tree2, )
def test_tree_changes_to_tree(self): blob_a = make_object(Blob, data=b"a") blob_x = make_object(Blob, data=b"x") tree1 = self.commit_tree([(b"a", blob_a)]) tree2 = self.commit_tree([(b"a/x", blob_x)]) self.assertChangesEqual( [ TreeChange.delete((b"a", F, blob_a.id)), TreeChange.add((b"a/x", F, blob_x.id)), ], tree1, tree2, )
def test_content_rename_gitlink(self): blob1 = make_object(Blob, data='blob1') blob2 = make_object(Blob, data='blob2') link1 = '1' * 40 link2 = '2' * 40 tree1 = self.commit_tree([('a', blob1), ('b', link1, 0o160000)]) tree2 = self.commit_tree([('c', blob2), ('d', link2, 0o160000)]) self.assertEqual( [TreeChange.delete(('a', 0o100644, blob1.id)), TreeChange.delete(('b', 0o160000, link1)), TreeChange.add(('c', 0o100644, blob2.id)), TreeChange.add(('d', 0o160000, link2))], self.detect_renames(tree1, tree2))
def test_tree_changes_for_merge_octopus_delete(self): blob1 = make_object(Blob, data='1') blob2 = make_object(Blob, data='3') parent1 = self.commit_tree([('a', blob1)]) parent2 = self.commit_tree([('a', blob2)]) parent3 = merge = self.commit_tree([]) self.assertChangesForMergeEqual([], [parent1, parent1, parent1], merge) self.assertChangesForMergeEqual([], [parent1, parent1, parent3], merge) self.assertChangesForMergeEqual([], [parent1, parent3, parent3], merge) self.assertChangesForMergeEqual([[ TreeChange.delete(('a', F, blob1.id)), TreeChange.delete(('a', F, blob2.id)), None ]], [parent1, parent2, parent3], merge)
def test_exact_rename_swap(self): blob1 = make_object(Blob, data='1') blob2 = make_object(Blob, data='2') tree1 = self.commit_tree([('a', blob1), ('b', blob2)]) tree2 = self.commit_tree([('a', blob2), ('b', blob1)]) self.assertEqual( [TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob2.id)), TreeChange(CHANGE_MODIFY, ('b', F, blob2.id), ('b', F, blob1.id))], self.detect_renames(tree1, tree2)) self.assertEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob1.id)), TreeChange(CHANGE_RENAME, ('b', F, blob2.id), ('a', F, blob2.id))], self.detect_renames(tree1, tree2, rewrite_threshold=50))
def test_follow_rename(self): blob = make_object(Blob, data='blob') names = ['a', 'a', 'b', 'b', 'c', 'c'] trees = dict((i + 1, [(n, blob, F)]) for i, n in enumerate(names)) c1, c2, c3, c4, c5, c6 = self.make_linear_commits(6, trees=trees) self.assertWalkYields([c5], [c6.id], paths=['c']) e = lambda n: (n, F, blob.id) self.assertWalkYields( [TestWalkEntry(c5, [TreeChange(CHANGE_RENAME, e('b'), e('c'))]), TestWalkEntry(c3, [TreeChange(CHANGE_RENAME, e('a'), e('b'))]), TestWalkEntry(c1, [TreeChange.add(e('a'))])], [c6.id], paths=['c'], follow=True)
def test_content_rename_many_to_many(self): blob1 = make_object(Blob, data='a\nb\nc\nd\n') blob2 = make_object(Blob, data='a\nb\nc\ne\n') blob3 = make_object(Blob, data='a\nb\nc\nf\n') blob4 = make_object(Blob, data='a\nb\nc\ng\n') tree1 = self.commit_tree([('a', blob1), ('b', blob2)]) tree2 = self.commit_tree([('c', blob3), ('d', blob4)]) # TODO(dborowitz): Distribute renames rather than greedily choosing # copies. self.assertEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('c', F, blob3.id)), TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('d', F, blob4.id)), TreeChange.delete(('b', F, blob2.id))], self.detect_renames(tree1, tree2))
def test_tree_changes_add_delete(self): blob_a = make_object(Blob, data=b"a") blob_b = make_object(Blob, data=b"b") tree = self.commit_tree([("a", blob_a, 0o100644), ("x/b", blob_b, 0o100755)]) self.assertChangesEqual( [TreeChange.add((b"a", 0o100644, blob_a.id)), TreeChange.add((b"x/b", 0o100755, blob_b.id))], self.empty_tree, tree, ) self.assertChangesEqual( [TreeChange.delete((b"a", 0o100644, blob_a.id)), TreeChange.delete((b"x/b", 0o100755, blob_b.id))], tree, self.empty_tree, )
def test_tree_changes_for_merge_octopus_delete(self): blob1 = make_object(Blob, data='1') blob2 = make_object(Blob, data='3') parent1 = self.commit_tree([('a', blob1)]) parent2 = self.commit_tree([('a', blob2)]) parent3 = merge = self.commit_tree([]) self.assertChangesForMergeEqual([], [parent1, parent1, parent1], merge) self.assertChangesForMergeEqual([], [parent1, parent1, parent3], merge) self.assertChangesForMergeEqual([], [parent1, parent3, parent3], merge) self.assertChangesForMergeEqual( [[TreeChange.delete(('a', F, blob1.id)), TreeChange.delete(('a', F, blob2.id)), None]], [parent1, parent2, parent3], merge)
def test_tree_entry_sort(self): sha = 'abcd' * 10 expected_entries = [ TreeChange.add(TreeEntry('aaa', F, sha)), TreeChange(CHANGE_COPY, TreeEntry('bbb', F, sha), TreeEntry('aab', F, sha)), TreeChange(CHANGE_MODIFY, TreeEntry('bbb', F, sha), TreeEntry('bbb', F, 'dabc' * 10)), TreeChange(CHANGE_RENAME, TreeEntry('bbc', F, sha), TreeEntry('ddd', F, sha)), TreeChange.delete(TreeEntry('ccc', F, sha)), ] for perm in permutations(expected_entries): self.assertEqual(expected_entries, sorted(perm, key=_tree_change_key))
def test_tree_changes_for_merge_add_add_same_conflict(self): blob = make_object(Blob, data='a\nb\nc\nd\n') parent1 = self.commit_tree([('a', blob)]) parent2 = self.commit_tree([]) merge = self.commit_tree([('b', blob)]) add = TreeChange.add(('b', F, blob.id)) self.assertChangesForMergeEqual([[add, add]], [parent1, parent2], merge)
def test_content_rename_gitlink(self): blob1 = make_object(Blob, data=b"blob1") blob2 = make_object(Blob, data=b"blob2") link1 = Sha1Sum("1" * 40) link2 = Sha1Sum("2" * 40) tree1 = self.commit_tree([("a", blob1), ("b", link1, 0o160000)]) tree2 = self.commit_tree([("c", blob2), ("d", link2, 0o160000)]) self.assertEqual( [ TreeChange.delete((b"a", 0o100644, blob1.id)), TreeChange.delete((b"b", 0o160000, link1)), TreeChange.add((b"c", 0o100644, blob2.id)), TreeChange.add((b"d", 0o160000, link2)), ], self.detect_renames(tree1, tree2), )
def test_exact_rename_many_to_one(self): blob = make_object(Blob, data='1') tree1 = self.commit_tree([('a', blob), ('b', blob)]) tree2 = self.commit_tree([('c', blob)]) self.assertEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob.id), ('c', F, blob.id)), TreeChange.delete(('b', F, blob.id))], self.detect_renames(tree1, tree2))
def test_exact_rename_many_to_one(self): blob = make_object(Blob, data=b"1") tree1 = self.commit_tree([("a", blob), ("b", blob)]) tree2 = self.commit_tree([("c", blob)]) self.assertEqual( [TreeChange(CHANGE_RENAME, (b"a", F, blob.id), (b"c", F, blob.id)), TreeChange.delete((b"b", F, blob.id))], self.detect_renames(tree1, tree2), )
def test_content_rename_max_files(self): blob1 = make_object(Blob, data='a\nb\nc\nd') blob4 = make_object(Blob, data='a\nb\nc\ne\n') blob2 = make_object(Blob, data='e\nf\ng\nh\n') blob3 = make_object(Blob, data='e\nf\ng\ni\n') tree1 = self.commit_tree([('a', blob1), ('b', blob2)]) tree2 = self.commit_tree([('c', blob3), ('d', blob4)]) self.assertEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('d', F, blob4.id)), TreeChange(CHANGE_RENAME, ('b', F, blob2.id), ('c', F, blob3.id))], self.detect_renames(tree1, tree2)) self.assertEqual( [TreeChange.delete(('a', F, blob1.id)), TreeChange.delete(('b', F, blob2.id)), TreeChange.add(('c', F, blob3.id)), TreeChange.add(('d', F, blob4.id))], self.detect_renames(tree1, tree2, max_files=1))
def test_exact_rename_and_different_type(self): blob1 = make_object(Blob, data='1') blob2 = make_object(Blob, data='2') tree1 = self.commit_tree([('a', blob1)]) tree2 = self.commit_tree([('a', blob2, 0o120000), ('b', blob1)]) self.assertEqual( [TreeChange.add(('a', 0o120000, blob2.id)), TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob1.id))], self.detect_renames(tree1, tree2))
def test_find_copies_harder_exact(self): blob = make_object(Blob, data='blob') tree1 = self.commit_tree([('a', blob)]) tree2 = self.commit_tree([('a', blob), ('b', blob)]) self.assertEqual([TreeChange.add(('b', F, blob.id))], self.detect_renames(tree1, tree2)) self.assertEqual( [TreeChange(CHANGE_COPY, ('a', F, blob.id), ('b', F, blob.id))], self.detect_renames(tree1, tree2, find_copies_harder=True))
def test_content_rename_one_to_one_ordering(self): blob1 = make_object(Blob, data='a\nb\nc\nd\ne\nf\n') blob2 = make_object(Blob, data='a\nb\nc\nd\ng\nh\n') # 6/10 match to blob1, 8/10 match to blob2 blob3 = make_object(Blob, data='a\nb\nc\nd\ng\ni\n') tree1 = self.commit_tree([('a', blob1), ('b', blob2)]) tree2 = self.commit_tree([('c', blob3)]) self.assertEqual( [TreeChange.delete(('a', F, blob1.id)), TreeChange(CHANGE_RENAME, ('b', F, blob2.id), ('c', F, blob3.id))], self.detect_renames(tree1, tree2)) tree3 = self.commit_tree([('a', blob2), ('b', blob1)]) tree4 = self.commit_tree([('c', blob3)]) self.assertEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob2.id), ('c', F, blob3.id)), TreeChange.delete(('b', F, blob1.id))], self.detect_renames(tree3, tree4))
def test_tree_changes_for_merge_add_exact_rename_conflict(self): blob = make_object(Blob, data='a\nb\nc\nd\n') parent1 = self.commit_tree([('a', blob)]) parent2 = self.commit_tree([]) merge = self.commit_tree([('b', blob)]) self.assertChangesForMergeEqual( [[TreeChange(CHANGE_RENAME, ('a', F, blob.id), ('b', F, blob.id)), TreeChange.add(('b', F, blob.id))]], [parent1, parent2], merge, rename_detector=self.detector)
def test_content_rename_many_to_one(self): blob1 = make_object(Blob, data='a\nb\nc\nd\n') blob2 = make_object(Blob, data='a\nb\nc\ne\n') blob3 = make_object(Blob, data='a\nb\nc\nf\n') tree1 = self.commit_tree([('a', blob1), ('b', blob2)]) tree2 = self.commit_tree([('c', blob3)]) self.assertEqual( [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('c', F, blob3.id)), TreeChange.delete(('b', F, blob2.id))], self.detect_renames(tree1, tree2))