348
353
set(f.get_ancestry('rM', topo_sorted=False)))
350
355
def test_mutate_after_finish(self):
356
self._transaction = 'before'
351
357
f = self.get_file()
352
f.transaction_finished()
358
self._transaction = 'after'
353
359
self.assertRaises(errors.OutSideTransaction, f.add_lines, '', [], [])
354
360
self.assertRaises(errors.OutSideTransaction, f.add_lines_with_ghosts, '', [], [])
355
361
self.assertRaises(errors.OutSideTransaction, f.join, '')
356
self.assertRaises(errors.OutSideTransaction, f.clone_text, 'base', 'bar', ['foo'])
358
def test_clear_cache(self):
360
# on a new file it should not error
362
# and after adding content, doing a clear_cache and a get should work.
363
f.add_lines('0', [], ['a'])
365
self.assertEqual(['a'], f.get_lines('0'))
367
363
def test_clone_text(self):
368
364
f = self.get_file()
369
365
f.add_lines('r0', [], ['a\n', 'b\n'])
370
f.clone_text('r1', 'r0', ['r0'])
366
self.applyDeprecated(one_four, f.clone_text, 'r1', 'r0', ['r0'])
371
367
def verify_file(f):
372
368
self.assertEquals(f.get_lines('r1'), f.get_lines('r0'))
373
369
self.assertEquals(f.get_lines('r1'), ['a\n', 'b\n'])
374
370
self.assertEqual({'r1':('r0',)}, f.get_parent_map(['r1']))
375
371
self.assertRaises(RevisionNotPresent,
376
f.clone_text, 'r2', 'rX', [])
372
self.applyDeprecated, one_four, f.clone_text, 'r2', 'rX', [])
377
373
self.assertRaises(RevisionAlreadyPresent,
378
f.clone_text, 'r1', 'r0', [])
374
self.applyDeprecated, one_four, f.clone_text, 'r1', 'r0', [])
380
376
verify_file(self.reopen_file())
382
def test_create_empty(self):
384
f.add_lines('0', [], ['a\n'])
385
new_f = f.create_empty('t', MemoryTransport())
386
# smoke test, specific types should check it is honoured correctly for
387
# non type attributes
388
self.assertEqual([], new_f.versions())
389
self.assertTrue(isinstance(new_f, f.__class__))
391
378
def test_copy_to(self):
392
379
f = self.get_file()
393
380
f.add_lines('0', [], ['a\n'])
394
381
t = MemoryTransport()
395
382
f.copy_to('foo', t)
396
for suffix in f.__class__.get_suffixes():
383
for suffix in self.get_factory().get_suffixes():
397
384
self.assertTrue(t.has('foo' + suffix))
399
386
def test_get_suffixes(self):
400
387
f = self.get_file()
402
self.assertEqual(f.__class__.get_suffixes(), f.__class__.get_suffixes())
403
388
# and should be a list
404
self.assertTrue(isinstance(f.__class__.get_suffixes(), list))
389
self.assertTrue(isinstance(self.get_factory().get_suffixes(), list))
406
391
def build_graph(self, file, graph):
407
392
for node in topo_sort(graph.items()):
441
426
simple_b_gam.update(simple_gam)
442
427
simple_b_gam.update(simple_b)
443
428
self.build_graph(f, complex_graph)
444
self.assertEqual(simple_a, f.get_graph(['a']))
445
self.assertEqual(simple_b, f.get_graph(['b']))
446
self.assertEqual(simple_gam, f.get_graph(['gam']))
447
self.assertEqual(simple_b_gam, f.get_graph(['b', 'gam']))
429
self.assertEqual(simple_a, self.applyDeprecated(one_four, f.get_graph,
431
self.assertEqual(simple_b, self.applyDeprecated(one_four, f.get_graph,
433
self.assertEqual(simple_gam, self.applyDeprecated(one_four,
434
f.get_graph, ['gam']))
435
self.assertEqual(simple_b_gam, self.applyDeprecated(one_four,
436
f.get_graph, ['b', 'gam']))
449
438
def test_get_parents(self):
450
439
f = self.get_file()
534
523
# XXX TODO a ghost
535
524
# cases: each sample data individually:
536
525
self.assertEqual(set([('r0', ())]),
537
set(f.iter_parents(['r0'])))
526
set(self.applyDeprecated(one_four, f.iter_parents, ['r0'])))
538
527
self.assertEqual(set([('r1', ('r0', ))]),
539
set(f.iter_parents(['r1'])))
528
set(self.applyDeprecated(one_four, f.iter_parents, ['r1'])))
540
529
self.assertEqual(set([('r2', ('r1', 'r0'))]),
541
set(f.iter_parents(['r2'])))
530
set(self.applyDeprecated(one_four, f.iter_parents, ['r2'])))
542
531
# no nodes returned for a missing node
543
532
self.assertEqual(set(),
544
set(f.iter_parents(['missing'])))
533
set(self.applyDeprecated(one_four, f.iter_parents, ['missing'])))
545
534
# 1 node returned with missing nodes skipped
546
535
self.assertEqual(set([('r1', ('r0', ))]),
547
set(f.iter_parents(['ghost1', 'r1', 'ghost'])))
536
set(self.applyDeprecated(one_four, f.iter_parents, ['ghost1', 'r1',
548
538
# 2 nodes returned
549
539
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),
550
set(f.iter_parents(['r0', 'r1'])))
540
set(self.applyDeprecated(one_four, f.iter_parents, ['r0', 'r1'])))
551
541
# 2 nodes returned, missing skipped
552
542
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),
553
set(f.iter_parents(['a', 'r0', 'b', 'r1', 'c'])))
543
set(self.applyDeprecated(one_four, f.iter_parents,
544
['a', 'r0', 'b', 'r1', 'c'])))
555
546
def test_iter_lines_added_or_present_in_versions(self):
556
547
# test that we get at least an equalset of the lines added by
630
621
vf.add_lines_with_ghosts('notbxbfse', [parent_id_utf8], [])
631
622
except NotImplementedError:
632
623
# check the other ghost apis are also not implemented
633
self.assertRaises(NotImplementedError, vf.has_ghost, 'foo')
634
624
self.assertRaises(NotImplementedError, vf.get_ancestry_with_ghosts, ['foo'])
635
625
self.assertRaises(NotImplementedError, vf.get_parents_with_ghosts, 'foo')
636
self.assertRaises(NotImplementedError, vf.get_graph_with_ghosts)
638
627
vf = self.reopen_file()
639
628
# test key graph related apis: getncestry, _graph, get_parents
642
631
self.assertEqual(['notbxbfse'], vf.get_ancestry('notbxbfse'))
643
632
self.assertEqual([],
644
633
self.applyDeprecated(one_four, vf.get_parents, 'notbxbfse'))
645
self.assertEqual({'notbxbfse':()}, vf.get_graph())
634
self.assertEqual({'notbxbfse':()}, self.applyDeprecated(one_four,
646
636
self.assertFalse(vf.has_version(parent_id_utf8))
647
637
# we have _with_ghost apis to give us ghost information.
648
638
self.assertEqual([parent_id_utf8, 'notbxbfse'], vf.get_ancestry_with_ghosts(['notbxbfse']))
649
639
self.assertEqual([parent_id_utf8], vf.get_parents_with_ghosts('notbxbfse'))
650
self.assertEqual({'notbxbfse':(parent_id_utf8,)}, vf.get_graph_with_ghosts())
651
self.assertTrue(vf.has_ghost(parent_id_utf8))
640
self.assertEqual({'notbxbfse':(parent_id_utf8,)},
641
self.applyDeprecated(one_four, vf.get_graph_with_ghosts))
642
self.assertTrue(self.applyDeprecated(one_four, vf.has_ghost,
652
644
# if we add something that is a ghost of another, it should correct the
653
645
# results of the prior apis
654
646
vf.add_lines(parent_id_utf8, [], [])
713
704
vf.add_lines('b', ['a'], ['a\n'])
714
705
# a file differing only in last newline.
715
706
vf.add_lines('c', [], ['a'])
717
'3f786850e387550fdab836ed7e6dc881de23001b', vf.get_sha1('a'))
719
'3f786850e387550fdab836ed7e6dc881de23001b', vf.get_sha1('b'))
721
'86f7e437faa5a7fce15d1ddcb9eaeaea377667b8', vf.get_sha1('c'))
707
# Deprecasted single-version API.
709
'3f786850e387550fdab836ed7e6dc881de23001b',
710
self.applyDeprecated(one_four, vf.get_sha1, 'a'))
712
'3f786850e387550fdab836ed7e6dc881de23001b',
713
self.applyDeprecated(one_four, vf.get_sha1, 'b'))
715
'86f7e437faa5a7fce15d1ddcb9eaeaea377667b8',
716
self.applyDeprecated(one_four, vf.get_sha1, 'c'))
723
717
self.assertEqual(['3f786850e387550fdab836ed7e6dc881de23001b',
724
718
'86f7e437faa5a7fce15d1ddcb9eaeaea377667b8',
725
719
'3f786850e387550fdab836ed7e6dc881de23001b'],
729
723
class TestWeave(TestCaseWithMemoryTransport, VersionedFileTestMixIn):
731
725
def get_file(self, name='foo'):
732
return WeaveFile(name, get_transport(self.get_url('.')), create=True)
726
return WeaveFile(name, get_transport(self.get_url('.')), create=True,
727
get_scope=self.get_transaction)
734
729
def get_file_corrupted_text(self):
735
w = WeaveFile('foo', get_transport(self.get_url('.')), create=True)
730
w = WeaveFile('foo', get_transport(self.get_url('.')), create=True,
731
get_scope=self.get_transaction)
736
732
w.add_lines('v1', [], ['hello\n'])
737
733
w.add_lines('v2', ['v1'], ['hello\n', 'there\n'])
768
764
def reopen_file(self, name='foo', create=False):
769
return WeaveFile(name, get_transport(self.get_url('.')), create=create)
765
return WeaveFile(name, get_transport(self.get_url('.')), create=create,
766
get_scope=self.get_transaction)
771
768
def test_no_implicit_create(self):
772
769
self.assertRaises(errors.NoSuchFile,
775
get_transport(self.get_url('.')))
772
get_transport(self.get_url('.')),
773
get_scope=self.get_transaction)
777
775
def get_factory(self):
805
803
def test_no_implicit_create(self):
806
self.assertRaises(errors.NoSuchFile,
809
get_transport(self.get_url('.')))
804
self.assertRaises(errors.NoSuchFile, self.get_factory(), 'foo',
805
get_transport(self.get_url('.')))
812
808
class TestPlaintextKnit(TestKnit):
813
809
"""Test a knit with no cached annotations"""
815
def _factory(self, name, transport, file_mode=None, access_mode=None,
816
delta=True, create=False):
817
return KnitVersionedFile(name, transport, file_mode, access_mode,
818
KnitPlainFactory(), delta=delta,
821
811
def get_factory(self):
812
return make_file_knit
825
815
class TestPlanMergeVersionedFile(TestCaseWithMemoryTransport):
828
818
TestCaseWithMemoryTransport.setUp(self)
829
self.vf1 = KnitVersionedFile('root', self.get_transport(), create=True)
830
self.vf2 = KnitVersionedFile('root', self.get_transport(), create=True)
819
self.vf1 = make_file_knit('root', self.get_transport(), create=True)
820
self.vf2 = make_file_knit('root', self.get_transport(), create=True)
831
821
self.plan_merge_vf = versionedfile._PlanMergeVersionedFile('root',
832
822
[self.vf1, self.vf2])
1250
1244
overlappedInsertExpected = ['aaa', '<<<<<<< ', 'xxx', 'yyy', '=======',
1251
1245
'xxx', '>>>>>>> ', 'bbb']
1254
class TestFormatSignatures(TestCaseWithMemoryTransport):
1256
def get_knit_file(self, name, annotated):
1258
factory = KnitAnnotateFactory()
1260
factory = KnitPlainFactory()
1261
return KnitVersionedFile(
1262
name, get_transport(self.get_url('.')), create=True,
1265
def test_knit_format_signatures(self):
1266
"""Different formats of knit have different signature strings."""
1267
knit = self.get_knit_file('a', True)
1268
self.assertEqual('knit-annotated', knit.get_format_signature())
1269
knit = self.get_knit_file('p', False)
1270
self.assertEqual('knit-plain', knit.get_format_signature())