544
548
('new-b', 'z\n')],
545
549
list(my_plan.plan_merge()))
551
def test_plan_merge_tail_ancestors(self):
552
# The graph looks like this:
553
# A # Common to all ancestors
555
# B C # Ancestors of E, only common to one side
557
# D E F # D, F are unique to G, H respectively
558
# |/ \| # E is the LCA for G & H, and the unique LCA for
563
# I J # criss-cross merge of G, H
565
# In this situation, a simple pruning of ancestors of E will leave D &
566
# F "dangling", which looks like they introduce lines different from
567
# the ones in E, but in actuality C&B introduced the lines, and they
568
# are already present in E
570
# Introduce the base text
571
self.add_rev('root', 'A', [], 'abc')
572
# Introduces a new line B
573
self.add_rev('root', 'B', ['A'], 'aBbc')
574
# Introduces a new line C
575
self.add_rev('root', 'C', ['A'], 'abCc')
576
# Introduce new line D
577
self.add_rev('root', 'D', ['B'], 'DaBbc')
578
# Merges B and C by just incorporating both
579
self.add_rev('root', 'E', ['B', 'C'], 'aBbCc')
580
# Introduce new line F
581
self.add_rev('root', 'F', ['C'], 'abCcF')
582
# Merge D & E by just combining the texts
583
self.add_rev('root', 'G', ['D', 'E'], 'DaBbCc')
584
# Merge F & E by just combining the texts
585
self.add_rev('root', 'H', ['F', 'E'], 'aBbCcF')
586
# Merge G & H by just combining texts
587
self.add_rev('root', 'I', ['G', 'H'], 'DaBbCcF')
588
# Merge G & H but supersede an old line in B
589
self.add_rev('root', 'J', ['H', 'G'], 'DaJbCcF')
590
plan = self.plan_merge_vf.plan_merge('I', 'J')
592
('unchanged', 'D\n'),
593
('unchanged', 'a\n'),
596
('unchanged', 'b\n'),
597
('unchanged', 'C\n'),
598
('unchanged', 'c\n'),
599
('unchanged', 'F\n')],
602
def test_plan_merge_tail_triple_ancestors(self):
603
# The graph looks like this:
604
# A # Common to all ancestors
606
# B C # Ancestors of E, only common to one side
608
# D E F # D, F are unique to G, H respectively
609
# |/|\| # E is the LCA for G & H, and the unique LCA for
611
# |\ /| # Q is just an extra node which is merged into both
614
# I J # criss-cross merge of G, H
616
# This is the same as the test_plan_merge_tail_ancestors, except we add
617
# a third LCA that doesn't add new lines, but will trigger our more
618
# involved ancestry logic
620
self.add_rev('root', 'A', [], 'abc')
621
self.add_rev('root', 'B', ['A'], 'aBbc')
622
self.add_rev('root', 'C', ['A'], 'abCc')
623
self.add_rev('root', 'D', ['B'], 'DaBbc')
624
self.add_rev('root', 'E', ['B', 'C'], 'aBbCc')
625
self.add_rev('root', 'F', ['C'], 'abCcF')
626
self.add_rev('root', 'G', ['D', 'E'], 'DaBbCc')
627
self.add_rev('root', 'H', ['F', 'E'], 'aBbCcF')
628
self.add_rev('root', 'Q', ['E'], 'aBbCc')
629
self.add_rev('root', 'I', ['G', 'Q', 'H'], 'DaBbCcF')
630
# Merge G & H but supersede an old line in B
631
self.add_rev('root', 'J', ['H', 'Q', 'G'], 'DaJbCcF')
632
plan = self.plan_merge_vf.plan_merge('I', 'J')
633
# This has a slight incorrect value, as it considers the lines in A to
634
# be 'killed-base', because they show up as new in both B and C, and
635
# then E has to resolve which ones are the 'real' ones.
636
# However, I believe this is okay as the important lines will all
639
('unchanged', 'D\n'),
640
('unchanged', 'a\n'),
643
('unchanged', 'b\n'),
644
('killed-base', 'c\n'), # Not technically correct
645
('killed-base', 'a\n'), # as they came from A
646
('killed-base', 'b\n'), # but the final text is right
647
('unchanged', 'C\n'),
648
('unchanged', 'c\n'),
649
('unchanged', 'F\n')],
547
652
def test_plan_merge_uncommitted_files(self):
548
653
self.setup_plan_merge_uncommitted()
549
654
plan = self.plan_merge_vf.plan_merge('B:', 'C:')