~ubuntu-branches/ubuntu/precise/dulwich/precise-security

« back to all changes in this revision

Viewing changes to dulwich/tests/test_diff_tree.py

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij
  • Date: 2011-08-07 15:03:44 UTC
  • mto: This revision was merged to the branch mainline in revision 25.
  • Revision ID: james.westby@ubuntu.com-20110807150344-94xw3o3hnh47y1m8
Tags: upstream-0.8.0
ImportĀ upstreamĀ versionĀ 0.8.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
    _merge_entries,
28
28
    _merge_entries_py,
29
29
    tree_changes,
 
30
    tree_changes_for_merge,
30
31
    _count_blocks,
31
32
    _count_blocks_py,
32
33
    _similarity_score,
54
55
    TestCase,
55
56
    )
56
57
from dulwich.tests.utils import (
 
58
    F,
57
59
    make_object,
58
60
    functest_builder,
59
61
    ext_functest_builder,
60
62
    )
61
63
 
62
 
# Shorthand mode for Files.
63
 
F = 0100644
64
 
 
65
64
 
66
65
class DiffTestCase(TestCase):
67
66
 
89
88
 
90
89
class TreeChangesTest(DiffTestCase):
91
90
 
 
91
    def setUp(self):
 
92
        super(TreeChangesTest, self).setUp()
 
93
        self.detector = RenameDetector(self.store)
 
94
 
92
95
    def assertMergeFails(self, merge_entries, name, mode, sha):
93
96
        t = Tree()
94
97
        t[name] = (mode, sha)
290
293
                      ('a', F, blob_a2.id))],
291
294
          tree1, tree2)
292
295
 
 
296
    def test_tree_changes_rename_detector(self):
 
297
        blob_a1 = make_object(Blob, data='a\nb\nc\nd\n')
 
298
        blob_a2 = make_object(Blob, data='a\nb\nc\ne\n')
 
299
        blob_b = make_object(Blob, data='b')
 
300
        tree1 = self.commit_tree([('a', blob_a1), ('b', blob_b)])
 
301
        tree2 = self.commit_tree([('c', blob_a2), ('b', blob_b)])
 
302
        detector = RenameDetector(self.store)
 
303
 
 
304
        self.assertChangesEqual(
 
305
          [TreeChange.delete(('a', F, blob_a1.id)),
 
306
           TreeChange.add(('c', F, blob_a2.id))],
 
307
          tree1, tree2)
 
308
        self.assertChangesEqual(
 
309
          [TreeChange.delete(('a', F, blob_a1.id)),
 
310
           TreeChange(CHANGE_UNCHANGED, ('b', F, blob_b.id),
 
311
                      ('b', F, blob_b.id)),
 
312
           TreeChange.add(('c', F, blob_a2.id))],
 
313
          tree1, tree2, want_unchanged=True)
 
314
        self.assertChangesEqual(
 
315
          [TreeChange(CHANGE_RENAME, ('a', F, blob_a1.id),
 
316
                      ('c', F, blob_a2.id))],
 
317
          tree1, tree2, rename_detector=detector)
 
318
        self.assertChangesEqual(
 
319
          [TreeChange(CHANGE_RENAME, ('a', F, blob_a1.id),
 
320
                      ('c', F, blob_a2.id)),
 
321
           TreeChange(CHANGE_UNCHANGED, ('b', F, blob_b.id),
 
322
                      ('b', F, blob_b.id))],
 
323
          tree1, tree2, rename_detector=detector, want_unchanged=True)
 
324
 
 
325
    def assertChangesForMergeEqual(self, expected, parent_trees, merge_tree,
 
326
                                   **kwargs):
 
327
        parent_tree_ids = [t.id for t in parent_trees]
 
328
        actual = list(tree_changes_for_merge(
 
329
          self.store, parent_tree_ids, merge_tree.id, **kwargs))
 
330
        self.assertEqual(expected, actual)
 
331
 
 
332
        parent_tree_ids.reverse()
 
333
        expected = [list(reversed(cs)) for cs in expected]
 
334
        actual = list(tree_changes_for_merge(
 
335
          self.store, parent_tree_ids, merge_tree.id, **kwargs))
 
336
        self.assertEqual(expected, actual)
 
337
 
 
338
    def test_tree_changes_for_merge_add_no_conflict(self):
 
339
        blob = make_object(Blob, data='blob')
 
340
        parent1 = self.commit_tree([])
 
341
        parent2 = merge = self.commit_tree([('a', blob)])
 
342
        self.assertChangesForMergeEqual([], [parent1, parent2], merge)
 
343
        self.assertChangesForMergeEqual([], [parent2, parent2], merge)
 
344
 
 
345
    def test_tree_changes_for_merge_add_modify_conflict(self):
 
346
        blob1 = make_object(Blob, data='1')
 
347
        blob2 = make_object(Blob, data='2')
 
348
        parent1 = self.commit_tree([])
 
349
        parent2 = self.commit_tree([('a', blob1)])
 
350
        merge = self.commit_tree([('a', blob2)])
 
351
        self.assertChangesForMergeEqual(
 
352
          [[TreeChange.add(('a', F, blob2.id)),
 
353
            TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob2.id))]],
 
354
          [parent1, parent2], merge)
 
355
 
 
356
    def test_tree_changes_for_merge_modify_modify_conflict(self):
 
357
        blob1 = make_object(Blob, data='1')
 
358
        blob2 = make_object(Blob, data='2')
 
359
        blob3 = make_object(Blob, data='3')
 
360
        parent1 = self.commit_tree([('a', blob1)])
 
361
        parent2 = self.commit_tree([('a', blob2)])
 
362
        merge = self.commit_tree([('a', blob3)])
 
363
        self.assertChangesForMergeEqual(
 
364
          [[TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob3.id)),
 
365
            TreeChange(CHANGE_MODIFY, ('a', F, blob2.id), ('a', F, blob3.id))]],
 
366
          [parent1, parent2], merge)
 
367
 
 
368
    def test_tree_changes_for_merge_modify_no_conflict(self):
 
369
        blob1 = make_object(Blob, data='1')
 
370
        blob2 = make_object(Blob, data='2')
 
371
        parent1 = self.commit_tree([('a', blob1)])
 
372
        parent2 = merge = self.commit_tree([('a', blob2)])
 
373
        self.assertChangesForMergeEqual([], [parent1, parent2], merge)
 
374
 
 
375
    def test_tree_changes_for_merge_delete_delete_conflict(self):
 
376
        blob1 = make_object(Blob, data='1')
 
377
        blob2 = make_object(Blob, data='2')
 
378
        parent1 = self.commit_tree([('a', blob1)])
 
379
        parent2 = self.commit_tree([('a', blob2)])
 
380
        merge = self.commit_tree([])
 
381
        self.assertChangesForMergeEqual(
 
382
          [[TreeChange.delete(('a', F, blob1.id)),
 
383
            TreeChange.delete(('a', F, blob2.id))]],
 
384
          [parent1, parent2], merge)
 
385
 
 
386
    def test_tree_changes_for_merge_delete_no_conflict(self):
 
387
        blob = make_object(Blob, data='blob')
 
388
        has = self.commit_tree([('a', blob)])
 
389
        doesnt_have = self.commit_tree([])
 
390
        self.assertChangesForMergeEqual([], [has, has], doesnt_have)
 
391
        self.assertChangesForMergeEqual([], [has, doesnt_have], doesnt_have)
 
392
 
 
393
    def test_tree_changes_for_merge_octopus_no_conflict(self):
 
394
        r = range(5)
 
395
        blobs = [make_object(Blob, data=str(i)) for i in r]
 
396
        parents = [self.commit_tree([('a', blobs[i])]) for i in r]
 
397
        for i in r:
 
398
            # Take the SHA from each of the parents.
 
399
            self.assertChangesForMergeEqual([], parents, parents[i])
 
400
 
 
401
    def test_tree_changes_for_merge_octopus_modify_conflict(self):
 
402
        # Because the octopus merge strategy is limited, I doubt it's possible
 
403
        # to create this with the git command line. But the output is well-
 
404
        # defined, so test it anyway.
 
405
        r = range(5)
 
406
        parent_blobs = [make_object(Blob, data=str(i)) for i in r]
 
407
        merge_blob = make_object(Blob, data='merge')
 
408
        parents = [self.commit_tree([('a', parent_blobs[i])]) for i in r]
 
409
        merge = self.commit_tree([('a', merge_blob)])
 
410
        expected = [[TreeChange(CHANGE_MODIFY, ('a', F, parent_blobs[i].id),
 
411
                                ('a', F, merge_blob.id)) for i in r]]
 
412
        self.assertChangesForMergeEqual(expected, parents, merge)
 
413
 
 
414
    def test_tree_changes_for_merge_octopus_delete(self):
 
415
        blob1 = make_object(Blob, data='1')
 
416
        blob2 = make_object(Blob, data='3')
 
417
        parent1 = self.commit_tree([('a', blob1)])
 
418
        parent2 = self.commit_tree([('a', blob2)])
 
419
        parent3 = merge = self.commit_tree([])
 
420
        self.assertChangesForMergeEqual([], [parent1, parent1, parent1], merge)
 
421
        self.assertChangesForMergeEqual([], [parent1, parent1, parent3], merge)
 
422
        self.assertChangesForMergeEqual([], [parent1, parent3, parent3], merge)
 
423
        self.assertChangesForMergeEqual(
 
424
          [[TreeChange.delete(('a', F, blob1.id)),
 
425
            TreeChange.delete(('a', F, blob2.id)),
 
426
            None]],
 
427
          [parent1, parent2, parent3], merge)
 
428
 
 
429
    def test_tree_changes_for_merge_add_add_same_conflict(self):
 
430
        blob = make_object(Blob, data='a\nb\nc\nd\n')
 
431
        parent1 = self.commit_tree([('a', blob)])
 
432
        parent2 = self.commit_tree([])
 
433
        merge = self.commit_tree([('b', blob)])
 
434
        add = TreeChange.add(('b', F, blob.id))
 
435
        self.assertChangesForMergeEqual([[add, add]], [parent1, parent2], merge)
 
436
 
 
437
    def test_tree_changes_for_merge_add_exact_rename_conflict(self):
 
438
        blob = make_object(Blob, data='a\nb\nc\nd\n')
 
439
        parent1 = self.commit_tree([('a', blob)])
 
440
        parent2 = self.commit_tree([])
 
441
        merge = self.commit_tree([('b', blob)])
 
442
        self.assertChangesForMergeEqual(
 
443
          [[TreeChange(CHANGE_RENAME, ('a', F, blob.id), ('b', F, blob.id)),
 
444
            TreeChange.add(('b', F, blob.id))]],
 
445
          [parent1, parent2], merge, rename_detector=self.detector)
 
446
 
 
447
    def test_tree_changes_for_merge_add_content_rename_conflict(self):
 
448
        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
 
449
        blob2 = make_object(Blob, data='a\nb\nc\ne\n')
 
450
        parent1 = self.commit_tree([('a', blob1)])
 
451
        parent2 = self.commit_tree([])
 
452
        merge = self.commit_tree([('b', blob2)])
 
453
        self.assertChangesForMergeEqual(
 
454
          [[TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob2.id)),
 
455
            TreeChange.add(('b', F, blob2.id))]],
 
456
          [parent1, parent2], merge, rename_detector=self.detector)
 
457
 
 
458
    def test_tree_changes_for_merge_modify_rename_conflict(self):
 
459
        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
 
460
        blob2 = make_object(Blob, data='a\nb\nc\ne\n')
 
461
        parent1 = self.commit_tree([('a', blob1)])
 
462
        parent2 = self.commit_tree([('b', blob1)])
 
463
        merge = self.commit_tree([('b', blob2)])
 
464
        self.assertChangesForMergeEqual(
 
465
          [[TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob2.id)),
 
466
            TreeChange(CHANGE_MODIFY, ('b', F, blob1.id), ('b', F, blob2.id))]],
 
467
          [parent1, parent2], merge, rename_detector=self.detector)
 
468
 
293
469
 
294
470
class RenameDetectionTest(DiffTestCase):
295
471
 
387
563
            self.assertEqual(expected_entries,
388
564
                             sorted(perm, key=_tree_change_key))
389
565
 
390
 
    def detect_renames(self, tree1, tree2, **kwargs):
391
 
        detector = RenameDetector(self.store, tree1.id, tree2.id, **kwargs)
392
 
        return detector.changes_with_renames()
 
566
    def detect_renames(self, tree1, tree2, want_unchanged=False, **kwargs):
 
567
        detector = RenameDetector(self.store, **kwargs)
 
568
        return detector.changes_with_renames(tree1.id, tree2.id,
 
569
                                             want_unchanged=want_unchanged)
393
570
 
394
571
    def test_no_renames(self):
395
572
        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
458
635
           TreeChange(CHANGE_RENAME, ('b', F, blob.id), ('d', F, blob.id))],
459
636
          self.detect_renames(tree1, tree2))
460
637
 
 
638
    def test_exact_copy_modify(self):
 
639
        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
 
640
        blob2 = make_object(Blob, data='a\nb\nc\ne\n')
 
641
        tree1 = self.commit_tree([('a', blob1)])
 
642
        tree2 = self.commit_tree([('a', blob2), ('b', blob1)])
 
643
        self.assertEqual(
 
644
          [TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob2.id)),
 
645
           TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('b', F, blob1.id))],
 
646
          self.detect_renames(tree1, tree2))
 
647
 
 
648
    def test_exact_copy_change_mode(self):
 
649
        blob = make_object(Blob, data='a\nb\nc\nd\n')
 
650
        tree1 = self.commit_tree([('a', blob)])
 
651
        tree2 = self.commit_tree([('a', blob, 0100755), ('b', blob)])
 
652
        self.assertEqual(
 
653
          [TreeChange(CHANGE_MODIFY, ('a', F, blob.id),
 
654
                      ('a', 0100755, blob.id)),
 
655
           TreeChange(CHANGE_COPY, ('a', F, blob.id), ('b', F, blob.id))],
 
656
          self.detect_renames(tree1, tree2))
 
657
 
461
658
    def test_rename_threshold(self):
462
659
        blob1 = make_object(Blob, data='a\nb\nc\n')
463
660
        blob2 = make_object(Blob, data='a\nb\nd\n')
607
804
 
608
805
        no_renames = [
609
806
          TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob3.id)),
610
 
          TreeChange.add(('b', F, blob2.id))]
 
807
          TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('b', F, blob2.id))]
611
808
        self.assertEqual(
612
809
          no_renames, self.detect_renames(tree1, tree2))
613
810
        self.assertEqual(
638
835
          [TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('b', F, blob2.id))],
639
836
          self.detect_renames(tree1, tree2, find_copies_harder=True))
640
837
 
641
 
    def test_find_copies_harder_modify(self):
642
 
        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
643
 
        blob2 = make_object(Blob, data='a\nb\nc\ne\n')
644
 
        tree1 = self.commit_tree([('a', blob1)])
645
 
        tree2 = self.commit_tree([('a', blob2), ('b', blob2)])
646
 
        self.assertEqual(
647
 
          [TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob2.id)),
648
 
           TreeChange.add(('b', F, blob2.id))],
649
 
          self.detect_renames(tree1, tree2))
650
 
        self.assertEqual(
651
 
          [TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob2.id)),
652
 
           TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('b', F, blob2.id))],
653
 
          self.detect_renames(tree1, tree2, find_copies_harder=True))
654
 
 
655
838
    def test_find_copies_harder_with_rewrites(self):
656
839
        blob_a1 = make_object(Blob, data='a\nb\nc\nd\n')
657
840
        blob_a2 = make_object(Blob, data='f\ng\nh\ni\n')
669
852
                      ('b', F, blob_b2.id))],
670
853
          self.detect_renames(tree1, tree2, rewrite_threshold=50,
671
854
                              find_copies_harder=True))
 
855
 
 
856
    def test_reuse_detector(self):
 
857
        blob = make_object(Blob, data='blob')
 
858
        tree1 = self.commit_tree([('a', blob)])
 
859
        tree2 = self.commit_tree([('b', blob)])
 
860
        detector = RenameDetector(self.store)
 
861
        changes = [TreeChange(CHANGE_RENAME, ('a', F, blob.id),
 
862
                              ('b', F, blob.id))]
 
863
        self.assertEqual(changes,
 
864
                         detector.changes_with_renames(tree1.id, tree2.id))
 
865
        self.assertEqual(changes,
 
866
                         detector.changes_with_renames(tree1.id, tree2.id))
 
867
 
 
868
    def test_want_unchanged(self):
 
869
        blob_a1 = make_object(Blob, data='a\nb\nc\nd\n')
 
870
        blob_b = make_object(Blob, data='b')
 
871
        blob_c2 = make_object(Blob, data='a\nb\nc\ne\n')
 
872
        tree1 = self.commit_tree([('a', blob_a1), ('b', blob_b)])
 
873
        tree2 = self.commit_tree([('c', blob_c2), ('b', blob_b)])
 
874
        detector = RenameDetector(self.store)
 
875
        self.assertEqual(
 
876
          [TreeChange(CHANGE_RENAME, ('a', F, blob_a1.id),
 
877
                      ('c', F, blob_c2.id))],
 
878
          self.detect_renames(tree1, tree2))
 
879
        self.assertEqual(
 
880
          [TreeChange(CHANGE_RENAME, ('a', F, blob_a1.id),
 
881
                      ('c', F, blob_c2.id)),
 
882
           TreeChange(CHANGE_UNCHANGED, ('b', F, blob_b.id),
 
883
                      ('b', F, blob_b.id))],
 
884
          self.detect_renames(tree1, tree2, want_unchanged=True))