~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_merge.py

  • Committer: John Arbash Meinel
  • Date: 2008-07-10 22:41:46 UTC
  • mto: This revision was merged to the branch mainline in revision 3543.
  • Revision ID: john@arbash-meinel.com-20080710224146-pmkkzgc4vbxhgrsr
The insertion ordering into the weave has an impact on conflicts.

Basically, when A has ancestors B and C which have overlapping changes,
inserting B before C will implicitly sort its lines earlier in the weave.
If A resolves the conflict by preserving this ordering, then switching that
ordering later will make those lines look like they originated in A, rather
than in B and C. (Because diff can't track moved lines yet.)

So bring in some explicit ordering constraints which are likely to fit the
real world workflow. Specifically, prefer to add the left-hand parents before
the right-hand parents. Since that is how the merge was done.

Show diffs side-by-side

added added

removed removed

Lines of Context:
508
508
                          ('unchanged', 'a\n'),
509
509
                          ('killed-a', 'b\n'),
510
510
                          ('killed-b', 'c\n'),
511
 
                          ('new-b', 'g\n'),
512
511
                          ('new-a', 'e\n'),
513
512
                          ('new-a', 'h\n'),
514
 
                          ('new-a', 'g\n')],
 
513
                          ('new-a', 'g\n'),
 
514
                          ('new-b', 'g\n')],
515
515
                         list(plan))
516
516
 
517
517
    def test_plan_merge_cherrypick(self):
536
536
        self.add_version(('root', 'B'), [], 'xyz')
537
537
        my_plan = _PlanMerge('A', 'B', self.plan_merge_vf, ('root',))
538
538
        self.assertEqual([
 
539
                          ('new-a', 'a\n'),
 
540
                          ('new-a', 'b\n'),
 
541
                          ('new-a', 'c\n'),
539
542
                          ('new-b', 'x\n'),
540
543
                          ('new-b', 'y\n'),
541
 
                          ('new-b', 'z\n'),
542
 
                          ('new-a', 'a\n'),
543
 
                          ('new-a', 'b\n'),
544
 
                          ('new-a', 'c\n')],
 
544
                          ('new-b', 'z\n')],
545
545
                          list(my_plan.plan_merge()))
546
546
 
547
547
    def test_plan_merge_uncommitted_files(self):
552
552
                          ('unchanged', 'a\n'),
553
553
                          ('killed-a', 'b\n'),
554
554
                          ('killed-b', 'c\n'),
555
 
                          ('new-b', 'g\n'),
556
555
                          ('new-a', 'e\n'),
557
556
                          ('new-a', 'h\n'),
558
 
                          ('new-a', 'g\n')],
 
557
                          ('new-a', 'g\n'),
 
558
                          ('new-b', 'g\n')],
 
559
                         list(plan))
 
560
 
 
561
    def test_plan_merge_insert_order(self):
 
562
        """Weave merges are sensitive to the order of insertion.
 
563
        
 
564
        Specifically for overlapping regions, it effects which region gets put
 
565
        'first'. And when a user resolves an overlapping merge, if they use the
 
566
        same ordering, then the lines match the parents, if they don't only
 
567
        *some* of the lines match.
 
568
        """
 
569
        self.add_version(('root', 'A'), [], 'abcdef')
 
570
        self.add_version(('root', 'B'), [('root', 'A')], 'abwxcdef')
 
571
        self.add_version(('root', 'C'), [('root', 'A')], 'abyzcdef')
 
572
        # Merge, and resolve the conflict by adding *both* sets of lines
 
573
        # If we get the ordering wrong, these will look like new lines in D,
 
574
        # rather than carried over from B, C
 
575
        self.add_version(('root', 'D'), [('root', 'B'), ('root', 'C')],
 
576
                         'abwxyzcdef')
 
577
        # Supersede the lines in B and delete the lines in C, which will
 
578
        # conflict if they are treated as being in D
 
579
        self.add_version(('root', 'E'), [('root', 'C'), ('root', 'B')],
 
580
                         'abnocdef')
 
581
        # Same thing for the lines in C
 
582
        self.add_version(('root', 'F'), [('root', 'C')], 'abpqcdef')
 
583
        plan = self.plan_merge_vf.plan_merge('D', 'E')
 
584
        self.assertEqual([
 
585
                          ('unchanged', 'a\n'),
 
586
                          ('unchanged', 'b\n'),
 
587
                          ('killed-b', 'w\n'),
 
588
                          ('killed-b', 'x\n'),
 
589
                          ('killed-b', 'y\n'),
 
590
                          ('killed-b', 'z\n'),
 
591
                          ('new-b', 'n\n'),
 
592
                          ('new-b', 'o\n'),
 
593
                          ('unchanged', 'c\n'),
 
594
                          ('unchanged', 'd\n'),
 
595
                          ('unchanged', 'e\n'),
 
596
                          ('unchanged', 'f\n')],
 
597
                         list(plan))
 
598
        plan = self.plan_merge_vf.plan_merge('E', 'D')
 
599
        # Going in the opposite direction shows the effect of the opposite plan
 
600
        self.assertEqual([
 
601
                          ('unchanged', 'a\n'),
 
602
                          ('unchanged', 'b\n'),
 
603
                          ('new-b', 'w\n'),
 
604
                          ('new-b', 'x\n'),
 
605
                          ('killed-a', 'y\n'),
 
606
                          ('killed-a', 'z\n'),
 
607
                          ('killed-both', 'w\n'),
 
608
                          ('killed-both', 'x\n'),
 
609
                          ('new-a', 'n\n'),
 
610
                          ('new-a', 'o\n'),
 
611
                          ('unchanged', 'c\n'),
 
612
                          ('unchanged', 'd\n'),
 
613
                          ('unchanged', 'e\n'),
 
614
                          ('unchanged', 'f\n')],
559
615
                         list(plan))
560
616
 
561
617
    def test_plan_merge_criss_cross(self):
562
618
        # This is specificly trying to trigger problems when using limited
563
619
        # ancestry and weaves. The ancestry graph looks like:
 
620
        #       XX      unused ancestor, should not show up in the weave
 
621
        #       |
564
622
        #       A       Unique LCA
565
623
        #       |\
566
624
        #       B \     Introduces a line 'foo'
581
639
        #   'foo', it should appear as superseding the value in F (since it
582
640
        #   came from B), rather than conflict because of the resolution during
583
641
        #   C & D.
584
 
        self.add_version(('root', 'A'), [], 'abcdef')
 
642
        self.add_version(('root', 'XX'), [], 'qrs')
 
643
        self.add_version(('root', 'A'), [('root', 'XX')], 'abcdef')
585
644
        self.add_version(('root', 'B'), [('root', 'A')], 'axcdef')
586
645
        self.add_version(('root', 'C'), [('root', 'B')], 'axcdefg')
587
646
        self.add_version(('root', 'D'), [('root', 'B')], 'haxcdef')