62
59
self.log(' %r' % k._parents)
63
60
self.log(' %r' % k2._parents)
65
64
self.fail('read/write check failed')
68
class WeaveContains(TestBase):
69
"""Weave __contains__ operator"""
72
k = Weave(get_scope=lambda: None)
73
self.assertFalse(b'foo' in k)
74
k.add_lines(b'foo', [], TEXT_1)
75
self.assertTrue(b'foo' in k)
78
69
class Easy(TestBase):
74
class StoreText(TestBase):
75
"""Store and retrieve a simple text."""
78
idx = k.add('text0', [], TEXT_0)
79
self.assertEqual(k.get(idx), TEXT_0)
80
self.assertEqual(idx, 0)
84
84
class AnnotateOne(TestBase):
88
k.add_lines(b'text0', [], TEXT_0)
89
self.assertEqual(k.annotate(b'text0'),
90
[(b'text0', TEXT_0[0])])
87
k.add('text0', [], TEXT_0)
88
self.assertEqual(k.annotate(0),
92
class StoreTwo(TestBase):
96
idx = k.add('text0', [], TEXT_0)
97
self.assertEqual(idx, 0)
99
idx = k.add('text1', [], TEXT_1)
100
self.assertEqual(idx, 1)
102
self.assertEqual(k.get(0), TEXT_0)
103
self.assertEqual(k.get(1), TEXT_1)
107
class AddWithGivenSha(TestBase):
109
"""Add with caller-supplied SHA-1"""
113
k.add('text0', [], [t], sha1=sha_string(t))
93
117
class InvalidAdd(TestBase):
94
118
"""Try to use invalid version number during add."""
96
119
def runTest(self):
99
self.assertRaises(errors.RevisionNotPresent,
122
self.assertRaises(IndexError,
106
129
class RepeatedAdd(TestBase):
107
130
"""Add the same version twice; harmless."""
109
def test_duplicate_add(self):
111
idx = k.add_lines(b'text0', [], TEXT_0)
112
idx2 = k.add_lines(b'text0', [], TEXT_0)
133
idx = k.add('text0', [], TEXT_0)
134
idx2 = k.add('text0', [], TEXT_0)
113
135
self.assertEqual(idx, idx2)
116
139
class InvalidRepeatedAdd(TestBase):
118
140
def runTest(self):
120
k.add_lines(b'basis', [], TEXT_0)
121
k.add_lines(b'text0', [], TEXT_0)
122
self.assertRaises(errors.RevisionAlreadyPresent,
142
idx = k.add('text0', [], TEXT_0)
143
self.assertRaises(WeaveError,
126
[b'not the same text'])
127
self.assertRaises(errors.RevisionAlreadyPresent,
130
[b'basis'], # not the right parents
147
['not the same text'])
148
self.assertRaises(WeaveError,
151
[12], # not the right parents
134
156
class InsertLines(TestBase):
137
159
Look at the annotations to make sure that the first line is matched
138
160
and not stored repeatedly."""
140
161
def runTest(self):
143
k.add_lines(b'text0', [], [b'line 1'])
144
k.add_lines(b'text1', [b'text0'], [b'line 1', b'line 2'])
146
self.assertEqual(k.annotate(b'text0'),
147
[(b'text0', b'line 1')])
149
self.assertEqual(k.get_lines(1),
153
self.assertEqual(k.annotate(b'text1'),
154
[(b'text0', b'line 1'),
155
(b'text1', b'line 2')])
157
k.add_lines(b'text2', [b'text0'], [b'line 1', b'diverged line'])
159
self.assertEqual(k.annotate(b'text2'),
160
[(b'text0', b'line 1'),
161
(b'text2', b'diverged line')])
163
text3 = [b'line 1', b'middle line', b'line 2']
164
k.add_lines(b'text3',
165
[b'text0', b'text1'],
168
# self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]),
164
k.add('text0', [], ['line 1'])
165
k.add('text1', [0], ['line 1', 'line 2'])
167
self.assertEqual(k.annotate(0),
170
self.assertEqual(k.get(1),
174
self.assertEqual(k.annotate(1),
178
k.add('text2', [0], ['line 1', 'diverged line'])
180
self.assertEqual(k.annotate(2),
182
(2, 'diverged line')])
184
text3 = ['line 1', 'middle line', 'line 2']
189
# self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
171
191
self.log("k._weave=" + pformat(k._weave))
173
self.assertEqual(k.annotate(b'text3'),
174
[(b'text0', b'line 1'),
175
(b'text3', b'middle line'),
176
(b'text1', b'line 2')])
193
self.assertEqual(k.annotate(3),
178
198
# now multiple insertions at different places
180
b'text4', [b'text0', b'text1', b'text3'],
181
[b'line 1', b'aaa', b'middle line', b'bbb', b'line 2', b'ccc'])
183
self.assertEqual(k.annotate(b'text4'),
184
[(b'text0', b'line 1'),
186
(b'text3', b'middle line'),
188
(b'text1', b'line 2'),
201
['line 1', 'aaa', 'middle line', 'bbb', 'line 2', 'ccc'])
203
self.assertEqual(k.annotate(4),
192
213
class DeleteLines(TestBase):
193
214
"""Deletion of lines from existing text.
195
216
Try various texts all based on a common ancestor."""
197
217
def runTest(self):
200
base_text = [b'one', b'two', b'three', b'four']
202
k.add_lines(b'text0', [], base_text)
204
texts = [[b'one', b'two', b'three'],
205
[b'two', b'three', b'four'],
207
[b'one', b'two', b'three', b'four'],
220
base_text = ['one', 'two', 'three', 'four']
222
k.add('text0', [], base_text)
224
texts = [['one', 'two', 'three'],
225
['two', 'three', 'four'],
227
['one', 'two', 'three', 'four'],
212
k.add_lines(b'text%d' % i, [b'text0'], t)
232
ver = k.add('text%d' % i,
215
236
self.log('final weave:')
216
237
self.log('k._weave=' + pformat(k._weave))
218
239
for i in range(len(texts)):
219
self.assertEqual(k.get_lines(i + 1),
240
self.assertEqual(k.get(i+1),
223
246
class SuicideDelete(TestBase):
224
247
"""Invalid weave which tries to add and delete simultaneously."""
226
248
def runTest(self):
229
251
k._parents = [(),
231
k._weave = [(b'{', 0),
253
k._weave = [('{', 0),
260
################################### SKIPPED
239
261
# Weave.get doesn't trap this anymore
242
264
self.assertRaises(WeaveFormatError,
247
270
class CannedDelete(TestBase):
248
271
"""Unpack canned weave with deleted lines."""
250
272
def runTest(self):
253
275
k._parents = [(),
256
k._weave = [(b'{', 0),
259
b'line to be deleted',
265
sha_string(b'first lineline to be deletedlast line'),
266
sha_string(b'first linelast line')]
268
self.assertEqual(k.get_lines(0),
270
b'line to be deleted',
274
self.assertEqual(k.get_lines(1),
278
k._weave = [('{', 0),
281
'line to be deleted',
287
self.assertEqual(k.get(0),
289
'line to be deleted',
293
self.assertEqual(k.get(1),
280
300
class CannedReplacement(TestBase):
281
301
"""Unpack canned weave with deleted lines."""
283
302
def runTest(self):
286
305
k._parents = [frozenset(),
289
k._weave = [(b'{', 0),
292
b'line to be deleted',
301
sha_string(b'first lineline to be deletedlast line'),
302
sha_string(b'first linereplacement linelast line')]
304
self.assertEqual(k.get_lines(0),
306
b'line to be deleted',
310
self.assertEqual(k.get_lines(1),
308
k._weave = [('{', 0),
311
'line to be deleted',
320
self.assertEqual(k.get(0),
322
'line to be deleted',
326
self.assertEqual(k.get(1),
317
334
class BadWeave(TestBase):
318
335
"""Test that we trap an insert which should not occur."""
320
336
def runTest(self):
323
339
k._parents = [frozenset(),
325
k._weave = [b'bad line',
329
b' added in version 1',
341
k._weave = ['bad line',
345
' added in version 1',
354
################################### SKIPPED
339
355
# Weave.get doesn't trap this anymore
342
359
self.assertRaises(WeaveFormatError,
475
484
k._parents = [frozenset(), frozenset([0])]
476
k._weave = [(b'{', 0),
483
k._sha1s = [sha_string(b'first line'), sha_string(
484
b'first linesecond line')]
486
self.assertEqual(k.get_lines(1),
490
self.assertEqual(k.get_lines(0),
485
k._weave = [('{', 0),
492
self.assertEqual(k.get(1),
496
self.assertEqual(k.get(0),
494
500
class DivergedIncludes(TestBase):
495
501
"""Weave with two diverged texts based on version 0.
498
503
def runTest(self):
499
# FIXME make the weave, dont poke at it.
502
k._names = [b'0', b'1', b'2']
503
k._name_map = {b'0': 0, b'1': 1, b'2': 2}
504
506
k._parents = [frozenset(),
508
k._weave = [(b'{', 0),
515
b"alternative second line",
520
sha_string(b'first line'),
521
sha_string(b'first linesecond line'),
522
sha_string(b'first linealternative second line')]
524
self.assertEqual(k.get_lines(0),
527
self.assertEqual(k.get_lines(1),
531
self.assertEqual(k.get_lines(b'2'),
533
b"alternative second line"])
535
self.assertEqual(list(k.get_ancestry([b'2'])),
510
k._weave = [('{', 0),
517
"alternative second line",
521
self.assertEqual(k.get(0),
524
self.assertEqual(k.get(1),
528
self.assertEqual(k.get(2),
530
"alternative second line"])
532
self.assertEqual(list(k.inclusions([2])),
539
537
class ReplaceLine(TestBase):
540
538
def runTest(self):
543
text0 = [b'cheddar', b'stilton', b'gruyere']
544
text1 = [b'cheddar', b'blue vein', b'neufchatel', b'chevre']
546
k.add_lines(b'text0', [], text0)
547
k.add_lines(b'text1', [b'text0'], text1)
541
text0 = ['cheddar', 'stilton', 'gruyere']
542
text1 = ['cheddar', 'blue vein', 'neufchatel', 'chevre']
544
k.add('text0', [], text0)
545
k.add('text1', [0], text1)
549
547
self.log('k._weave=' + pformat(k._weave))
551
self.assertEqual(k.get_lines(0), text0)
552
self.assertEqual(k.get_lines(1), text1)
549
self.assertEqual(k.get(0), text0)
550
self.assertEqual(k.get(1), text1)
555
554
class Merge(TestBase):
556
555
"""Storage of versions that merge diverged parents"""
558
556
def runTest(self):
563
[b'header', b'', b'line from 1'],
564
[b'header', b'', b'line from 2', b'more from 2'],
565
[b'header', b'', b'line from 1', b'fixup line', b'line from 2'],
560
['header', '', 'line from 1'],
561
['header', '', 'line from 2', 'more from 2'],
562
['header', '', 'line from 1', 'fixup line', 'line from 2'],
568
k.add_lines(b'text0', [], texts[0])
569
k.add_lines(b'text1', [b'text0'], texts[1])
570
k.add_lines(b'text2', [b'text0'], texts[2])
571
k.add_lines(b'merge', [b'text0', b'text1', b'text2'], texts[3])
565
k.add('text0', [], texts[0])
566
k.add('text1', [0], texts[1])
567
k.add('text2', [0], texts[2])
568
k.add('merge', [0, 1, 2], texts[3])
573
570
for i, t in enumerate(texts):
574
self.assertEqual(k.get_lines(i), t)
571
self.assertEqual(k.get(i), t)
576
self.assertEqual(k.annotate(b'merge'),
577
[(b'text0', b'header'),
579
(b'text1', b'line from 1'),
580
(b'merge', b'fixup line'),
581
(b'text2', b'line from 2'),
573
self.assertEqual(k.annotate(3),
584
self.assertEqual(list(k.get_ancestry([b'merge'])),
585
[b'text0', b'text1', b'text2', b'merge'])
581
self.assertEqual(list(k.inclusions([3])),
587
584
self.log('k._weave=' + pformat(k._weave))
595
592
A base version is inserted, then two descendents try to
596
593
insert different lines in the same place. These should be
597
594
reported as a possible conflict and forwarded to the user."""
599
595
def runTest(self):
603
k.add_lines([], [b'aaa', b'bbb'])
604
k.add_lines([0], [b'aaa', b'111', b'bbb'])
605
k.add_lines([1], [b'aaa', b'222', b'bbb'])
609
self.assertEqual([[[b'aaa']],
610
[[b'111'], [b'222']],
599
k.add([], ['aaa', 'bbb'])
600
k.add([0], ['aaa', '111', 'bbb'])
601
k.add([1], ['aaa', '222', 'bbb'])
603
merged = k.merge([1, 2])
605
self.assertEquals([[['aaa']],
614
611
class NonConflict(TestBase):
615
612
"""Two descendants insert compatible changes.
617
614
No conflict should be reported."""
619
615
def runTest(self):
623
k.add_lines([], [b'aaa', b'bbb'])
624
k.add_lines([0], [b'111', b'aaa', b'ccc', b'bbb'])
625
k.add_lines([1], [b'aaa', b'ccc', b'bbb', b'222'])
619
k.add([], ['aaa', 'bbb'])
620
k.add([0], ['111', 'aaa', 'ccc', 'bbb'])
621
k.add([1], ['aaa', 'ccc', 'bbb', '222'])
627
class AutoMerge(TestBase):
631
texts = [['header', 'aaa', 'bbb'],
632
['header', 'aaa', 'line from 1', 'bbb'],
633
['header', 'aaa', 'bbb', 'line from 2', 'more from 2'],
636
k.add('text0', [], texts[0])
637
k.add('text1', [0], texts[1])
638
k.add('text2', [0], texts[2])
640
self.log('k._weave=' + pformat(k._weave))
642
m = list(k.mash_iter([0, 1, 2]))
648
'line from 2', 'more from 2'])
628
652
class Khayyam(TestBase):
629
653
"""Test changes to multi-line texts, and read/write"""
631
def test_multi_line_merge(self):
633
b"""A Book of Verses underneath the Bough,
656
"""A Book of Verses underneath the Bough,
634
657
A Jug of Wine, a Loaf of Bread, -- and Thou
635
658
Beside me singing in the Wilderness --
636
659
Oh, Wilderness were Paradise enow!""",
638
b"""A Book of Verses underneath the Bough,
661
"""A Book of Verses underneath the Bough,
639
662
A Jug of Wine, a Loaf of Bread, -- and Thou
640
663
Beside me singing in the Wilderness --
641
664
Oh, Wilderness were Paradise now!""",
643
b"""A Book of poems underneath the tree,
666
"""A Book of poems underneath the tree,
644
667
A Jug of Wine, a Loaf of Bread,
646
669
Beside me singing in the Wilderness --
649
672
-- O. Khayyam""",
651
b"""A Book of Verses underneath the Bough,
674
"""A Book of Verses underneath the Bough,
652
675
A Jug of Wine, a Loaf of Bread,
654
677
Beside me singing in the Wilderness --
655
678
Oh, Wilderness were Paradise now!""",
657
texts = [[l.strip() for l in t.split(b'\n')] for t in rawtexts]
680
texts = [[l.strip() for l in t.split('\n')] for t in rawtexts]
663
k.add_lines(b'text%d' % i, list(parents), t)
664
parents.add(b'text%d' % i)
686
ver = k.add('text%d' % i,
667
691
self.log("k._weave=" + pformat(k._weave))
669
693
for i, t in enumerate(texts):
670
self.assertEqual(k.get_lines(i), t)
694
self.assertEqual(k.get(i), t)
672
696
self.check_read_write(k)
700
class MergeCases(TestBase):
701
def doMerge(self, base, a, b, mp):
702
from cStringIO import StringIO
703
from textwrap import dedent
709
w.add('text0', [], map(addcrlf, base))
710
w.add('text1', [0], map(addcrlf, a))
711
w.add('text2', [0], map(addcrlf, b))
713
self.log('weave is:')
716
self.log(tmpf.getvalue())
718
self.log('merge plan:')
719
p = list(w.plan_merge(1, 2))
720
for state, line in p:
722
self.log('%12s | %s' % (state, line[:-1]))
726
mt.writelines(w.weave_merge(p))
728
self.log(mt.getvalue())
730
mp = map(addcrlf, mp)
731
self.assertEqual(mt.readlines(), mp)
734
def testOneInsert(self):
740
def testSeparateInserts(self):
741
self.doMerge(['aaa', 'bbb', 'ccc'],
742
['aaa', 'xxx', 'bbb', 'ccc'],
743
['aaa', 'bbb', 'yyy', 'ccc'],
744
['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
746
def testSameInsert(self):
747
self.doMerge(['aaa', 'bbb', 'ccc'],
748
['aaa', 'xxx', 'bbb', 'ccc'],
749
['aaa', 'xxx', 'bbb', 'yyy', 'ccc'],
750
['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
752
def testOverlappedInsert(self):
753
self.doMerge(['aaa', 'bbb'],
754
['aaa', 'xxx', 'yyy', 'bbb'],
755
['aaa', 'xxx', 'bbb'],
756
['aaa', '<<<<', 'xxx', 'yyy', '====', 'xxx', '>>>>', 'bbb'])
758
# really it ought to reduce this to
759
# ['aaa', 'xxx', 'yyy', 'bbb']
762
def testClashReplace(self):
763
self.doMerge(['aaa'],
766
['<<<<', 'xxx', '====', 'yyy', 'zzz', '>>>>'])
768
def testNonClashInsert(self):
769
self.doMerge(['aaa'],
772
['<<<<', 'xxx', 'aaa', '====', 'yyy', 'zzz', '>>>>'])
774
self.doMerge(['aaa'],
780
def testDeleteAndModify(self):
781
"""Clashing delete and modification.
783
If one side modifies a region and the other deletes it then
784
there should be a conflict with one side blank.
787
#######################################
788
# skippd, not working yet
791
self.doMerge(['aaa', 'bbb', 'ccc'],
792
['aaa', 'ddd', 'ccc'],
794
['<<<<', 'aaa', '====', '>>>>', 'ccc'])
675
797
class JoinWeavesTests(TestBase):
678
799
super(JoinWeavesTests, self).setUp()
679
800
self.weave1 = Weave()
680
self.lines1 = [b'hello\n']
681
self.lines3 = [b'hello\n', b'cruel\n', b'world\n']
682
self.weave1.add_lines(b'v1', [], self.lines1)
683
self.weave1.add_lines(b'v2', [b'v1'], [b'hello\n', b'world\n'])
684
self.weave1.add_lines(b'v3', [b'v2'], self.lines3)
686
def test_written_detection(self):
687
# Test detection of weave file corruption.
689
# Make sure that we can detect if a weave file has
690
# been corrupted. This doesn't test all forms of corruption,
691
# but it at least helps verify the data you get, is what you want.
694
w.add_lines(b'v1', [], [b'hello\n'])
695
w.add_lines(b'v2', [b'v1'], [b'hello\n', b'there\n'])
700
# Because we are corrupting, we need to make sure we have the exact
703
b'# bzr weave file v5\n'
704
b'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
705
b'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
706
b'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n',
709
# Change a single letter
711
b'# bzr weave file v5\n'
712
b'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
713
b'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
714
b'w\n{ 0\n. hello\n}\n{ 1\n. There\n}\nW\n')
718
self.assertEqual(b'hello\n', w.get_text(b'v1'))
719
self.assertRaises(WeaveInvalidChecksum, w.get_text, b'v2')
720
self.assertRaises(WeaveInvalidChecksum, w.get_lines, b'v2')
721
self.assertRaises(WeaveInvalidChecksum, w.check)
723
# Change the sha checksum
725
b'# bzr weave file v5\n'
726
b'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
727
b'i 0\n1 f0f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
728
b'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n')
732
self.assertEqual(b'hello\n', w.get_text(b'v1'))
733
self.assertRaises(WeaveInvalidChecksum, w.get_text, b'v2')
734
self.assertRaises(WeaveInvalidChecksum, w.get_lines, b'v2')
735
self.assertRaises(WeaveInvalidChecksum, w.check)
738
class TestWeave(TestCase):
740
def test_allow_reserved_false(self):
741
w = Weave('name', allow_reserved=False)
742
# Add lines is checked at the WeaveFile level, not at the Weave level
743
w.add_lines(b'name:', [], TEXT_1)
744
# But get_lines is checked at this level
745
self.assertRaises(errors.ReservedId, w.get_lines, b'name:')
747
def test_allow_reserved_true(self):
748
w = Weave('name', allow_reserved=True)
749
w.add_lines(b'name:', [], TEXT_1)
750
self.assertEqual(TEXT_1, w.get_lines(b'name:'))
753
class InstrumentedWeave(Weave):
754
"""Keep track of how many times functions are called."""
756
def __init__(self, weave_name=None):
757
self._extract_count = 0
758
Weave.__init__(self, weave_name=weave_name)
760
def _extract(self, versions):
761
self._extract_count += 1
762
return Weave._extract(self, versions)
765
class TestNeedsReweave(TestCase):
766
"""Internal corner cases for when reweave is needed."""
768
def test_compatible_parents(self):
770
my_parents = {1, 2, 3}
772
self.assertTrue(w1._compatible_parents(my_parents, {3}))
774
self.assertTrue(w1._compatible_parents(my_parents, set(my_parents)))
775
# same empty corner case
776
self.assertTrue(w1._compatible_parents(set(), set()))
777
# other cannot contain stuff my_parents does not
778
self.assertFalse(w1._compatible_parents(set(), {1}))
779
self.assertFalse(w1._compatible_parents(my_parents, {1, 2, 3, 4}))
780
self.assertFalse(w1._compatible_parents(my_parents, {4}))
783
class TestWeaveFile(TestCaseInTempDir):
785
def test_empty_file(self):
786
with open('empty.weave', 'wb+') as f:
787
self.assertRaises(WeaveFormatError, read_weave, f)
801
self.lines1 = ['hello\n']
802
self.lines3 = ['hello\n', 'cruel\n', 'world\n']
803
self.weave1.add('v1', [], self.lines1)
804
self.weave1.add('v2', [0], ['hello\n', 'world\n'])
805
self.weave1.add('v3', [1], self.lines3)
807
def test_join_empty(self):
808
"""Join two empty weaves."""
809
eq = self.assertEqual
813
eq(w1.numversions(), 0)
815
def test_join_empty_to_nonempty(self):
816
"""Join empty weave onto nonempty."""
817
self.weave1.join(Weave())
818
self.assertEqual(len(self.weave1), 3)
820
def test_join_unrelated(self):
821
"""Join two weaves with no history in common."""
823
wb.add('b1', [], ['line from b\n'])
826
eq = self.assertEqual
828
eq(sorted(list(w1.iter_names())),
829
['b1', 'v1', 'v2', 'v3'])
831
def test_join_related(self):
832
wa = self.weave1.copy()
833
wb = self.weave1.copy()
834
wa.add('a1', ['v3'], ['hello\n', 'sweet\n', 'world\n'])
835
wb.add('b1', ['v3'], ['hello\n', 'pale blue\n', 'world\n'])
836
eq = self.assertEquals
841
eq(wa.get_lines('b1'),
842
['hello\n', 'pale blue\n', 'world\n'])
844
def test_join_parent_disagreement(self):
845
"""Cannot join weaves with different parents for a version."""
848
wa.add('v1', [], ['hello\n'])
850
wb.add('v1', ['v0'], ['hello\n'])
851
self.assertRaises(WeaveError,
854
def test_join_text_disagreement(self):
855
"""Cannot join weaves with different texts for a version."""
858
wa.add('v1', [], ['hello\n'])
859
wb.add('v1', [], ['not\n', 'hello\n'])
860
self.assertRaises(WeaveError,
863
def test_join_unordered(self):
864
"""Join weaves where indexes differ.
866
The source weave contains a different version at index 0."""
867
wa = self.weave1.copy()
869
wb.add('x1', [], ['line from x1\n'])
870
wb.add('v1', [], ['hello\n'])
871
wb.add('v2', ['v1'], ['hello\n', 'world\n'])
873
eq = self.assertEquals
874
eq(sorted(wa.iter_names()), ['v1', 'v2', 'v3', 'x1',])
875
eq(wa.get_text('x1'), 'line from x1\n')
877
def test_reweave_with_empty(self):
879
wr = reweave(self.weave1, wb)
880
eq = self.assertEquals
881
eq(sorted(wr.iter_names()), ['v1', 'v2', 'v3'])
882
eq(wr.get_lines('v3'), ['hello\n', 'cruel\n', 'world\n'])
883
self.weave1.reweave(wb)
884
self.assertEquals(wr, self.weave1)
886
def test_join_with_ghosts_raises_parent_mismatch(self):
887
wa = self.weave1.copy()
889
wb.add('x1', [], ['line from x1\n'])
890
wb.add('v1', [], ['hello\n'])
891
wb.add('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
892
self.assertRaises(errors.WeaveParentMismatch, wa.join, wb)
894
def test_reweave_with_ghosts(self):
895
"""Join that inserts parents of an existing revision.
897
This can happen when merging from another branch who
898
knows about revisions the destination does not. In
899
this test the second weave knows of an additional parent of
900
v2. Any revisions which are in common still have to have the
902
wa = self.weave1.copy()
904
wb.add('x1', [], ['line from x1\n'])
905
wb.add('v1', [], ['hello\n'])
906
wb.add('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
908
eq = self.assertEquals
909
eq(sorted(wc.iter_names()), ['v1', 'v2', 'v3', 'x1',])
910
eq(wc.get_text('x1'), 'line from x1\n')
911
eq(wc.get_lines('v2'), ['hello\n', 'world\n'])
912
eq(wc.parent_names('v2'), ['v1', 'x1'])
913
self.weave1.reweave(wb)
914
self.assertEquals(wc, self.weave1)
917
if __name__ == '__main__':
920
sys.exit(unittest.main())