52
52
def delta_application_scenarios():
54
('Inventory', {'apply_delta':apply_inventory_Inventory}),
54
('Inventory', {'apply_delta': apply_inventory_Inventory}),
56
56
# Working tree basis delta application
57
57
# Repository add_inv_by_delta.
62
62
for _, format in repository.format_registry.iteritems():
63
63
if format.supports_full_versioned_files:
64
64
scenarios.append((str(format.__name__), {
65
'apply_delta':apply_inventory_Repository_add_inventory_by_delta,
65
'apply_delta': apply_inventory_Repository_add_inventory_by_delta,
67
67
for getter in workingtree.format_registry._get_all_lazy():
78
78
(str(format.__class__.__name__) + ".update_basis_by_delta", {
79
'apply_delta':apply_inventory_WT_basis,
79
'apply_delta': apply_inventory_WT_basis,
82
82
(str(format.__class__.__name__) + ".apply_inventory_delta", {
83
'apply_delta':apply_inventory_WT,
83
'apply_delta': apply_inventory_WT,
114
114
:param delta: The inventory delta to apply:
115
115
:return: An inventory resulting from the application.
117
control = self.make_controldir('tree', format=self.format._matchingcontroldir)
117
control = self.make_controldir(
118
'tree', format=self.format._matchingcontroldir)
118
119
control.create_repository()
119
120
control.create_branch()
120
121
tree = self.format.initialize(control)
143
144
repo.start_write_group()
145
146
rev = revision.Revision(b'basis', timestamp=0, timezone=None,
146
message="", committer="foo@example.com")
147
message="", committer="foo@example.com")
147
148
basis.revision_id = b'basis'
148
149
create_texts_for_inv(repo, basis)
149
150
repo.add_revision(b'basis', rev, basis)
158
159
create_texts_for_inv(repo, result_inv)
159
160
target_entries = list(result_inv.iter_entries_by_dir())
160
161
rev = revision.Revision(b'result', timestamp=0, timezone=None,
161
message="", committer="foo@example.com")
162
message="", committer="foo@example.com")
162
163
repo.add_revision(b'result', rev, result_inv)
163
164
repo.commit_write_group()
205
206
:param delta: The inventory delta to apply:
206
207
:return: An inventory resulting from the application.
208
control = test.make_controldir('tree', format=test.format._matchingcontroldir)
209
control = test.make_controldir(
210
'tree', format=test.format._matchingcontroldir)
209
211
control.create_repository()
210
212
control.create_branch()
211
213
tree = test.format.initialize(control)
240
242
def apply_inventory_Repository_add_inventory_by_delta(self, basis, delta,
241
243
invalid_delta=True):
242
244
"""Apply delta to basis and return the result.
244
246
This inserts basis as a whole inventory and then uses
245
247
add_inventory_by_delta to add delta.
255
257
repo.start_write_group()
257
259
rev = revision.Revision(b'basis', timestamp=0, timezone=None,
258
message="", committer="foo@example.com")
260
message="", committer="foo@example.com")
259
261
basis.revision_id = b'basis'
260
262
create_texts_for_inv(repo, basis)
261
263
repo.add_revision(b'basis', rev, basis)
338
340
inv = inventory.Inventory(b'tree-root')
339
341
inv.add(InventoryFile(b'a-id', u'\u1234', b'tree-root'))
340
342
e = self.assertRaises(errors.InconsistentDelta, inv.add,
341
InventoryFile(b'b-id', u'\u1234', b'tree-root'))
343
InventoryFile(b'b-id', u'\u1234', b'tree-root'))
342
344
self.assertContainsRe(str(e), '\\u1234')
344
346
def test_add_recursive(self):
395
396
dir1.revision = b'result'
396
397
delta = [(None, u'dir1', None, dir1)]
397
398
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
400
401
def test_unicode_file_id(self):
401
402
inv = self.get_empty_inventory()
404
405
dir1.revision = b'result'
405
406
delta = [(None, u'dir1', dir1.file_id, dir1)]
406
407
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
409
410
def test_repeated_file_id(self):
410
411
inv = self.get_empty_inventory()
414
415
file1.text_sha1 = b""
415
416
file2 = file1.copy()
416
417
file2.name = 'path2'
417
delta = [(None, u'path1', b'id', file1), (None, u'path2', b'id', file2)]
418
delta = [(None, u'path1', b'id', file1),
419
(None, u'path2', b'id', file2)]
418
420
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
421
423
def test_repeated_new_path(self):
422
424
inv = self.get_empty_inventory()
426
428
file1.text_sha1 = b""
427
429
file2 = file1.copy()
428
430
file2.file_id = b'id2'
429
delta = [(None, u'path', b'id1', file1), (None, u'path', b'id2', file2)]
431
delta = [(None, u'path', b'id1', file1),
432
(None, u'path', b'id2', file2)]
430
433
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
433
436
def test_repeated_old_path(self):
434
437
inv = self.get_empty_inventory()
451
454
delta = [(u'path', None, b'id1', None), (u'path', None, b'id2', None)]
452
455
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
455
458
def test_mismatched_id_entry_id(self):
456
459
inv = self.get_empty_inventory()
460
463
file1.text_sha1 = b""
461
464
delta = [(None, u'path', b'id', file1)]
462
465
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
465
468
def test_mismatched_new_path_entry_None(self):
466
469
inv = self.get_empty_inventory()
467
470
delta = [(None, u'path', b'id', None)]
468
471
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
471
474
def test_mismatched_new_path_None_entry(self):
472
475
inv = self.get_empty_inventory()
476
479
file1.text_sha1 = b""
477
480
delta = [(u"path", None, b'id1', file1)]
478
481
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
481
484
def test_parent_is_not_directory(self):
482
485
inv = self.get_empty_inventory()
492
495
delta = [(None, u'path/path2', b'id2', file2)]
493
496
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
496
499
def test_parent_is_missing(self):
497
500
inv = self.get_empty_inventory()
501
504
file2.text_sha1 = b""
502
505
delta = [(None, u'path/path2', b'id2', file2)]
503
506
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
506
509
def test_new_parent_path_has_wrong_id(self):
507
510
inv = self.get_empty_inventory()
508
511
parent1 = inventory.InventoryDirectory(b'p-1', 'dir', inv.root.file_id)
509
512
parent1.revision = b'result'
510
parent2 = inventory.InventoryDirectory(b'p-2', 'dir2', inv.root.file_id)
513
parent2 = inventory.InventoryDirectory(
514
b'p-2', 'dir2', inv.root.file_id)
511
515
parent2.revision = b'result'
512
516
file1 = inventory.InventoryFile(b'id', 'path', b'p-2')
513
517
file1.revision = b'result'
519
523
# dir2/path if you follow the inventory parent structure.
520
524
delta = [(None, u'dir/path', b'id', file1)]
521
525
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
524
528
def test_old_parent_path_is_wrong(self):
525
529
inv = self.get_empty_inventory()
526
530
parent1 = inventory.InventoryDirectory(b'p-1', 'dir', inv.root.file_id)
527
531
parent1.revision = b'result'
528
parent2 = inventory.InventoryDirectory(b'p-2', 'dir2', inv.root.file_id)
532
parent2 = inventory.InventoryDirectory(
533
b'p-2', 'dir2', inv.root.file_id)
529
534
parent2.revision = b'result'
530
535
file1 = inventory.InventoryFile(b'id', 'path', b'p-2')
531
536
file1.revision = b'result'
538
543
# dir2/path if you follow the inventory parent structure.
539
544
delta = [(u'dir/path', None, b'id', None)]
540
545
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
543
548
def test_old_parent_path_is_for_other_id(self):
544
549
inv = self.get_empty_inventory()
545
550
parent1 = inventory.InventoryDirectory(b'p-1', 'dir', inv.root.file_id)
546
551
parent1.revision = b'result'
547
parent2 = inventory.InventoryDirectory(b'p-2', 'dir2', inv.root.file_id)
552
parent2 = inventory.InventoryDirectory(
553
b'p-2', 'dir2', inv.root.file_id)
548
554
parent2.revision = b'result'
549
555
file1 = inventory.InventoryFile(b'id', 'path', b'p-2')
550
556
file1.revision = b'result'
563
569
# is another entry we should not delete.
564
570
delta = [(u'dir/path', None, b'id', None)]
565
571
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
568
574
def test_add_existing_id_new_path(self):
569
575
inv = self.get_empty_inventory()
570
parent1 = inventory.InventoryDirectory(b'p-1', 'dir1', inv.root.file_id)
576
parent1 = inventory.InventoryDirectory(
577
b'p-1', 'dir1', inv.root.file_id)
571
578
parent1.revision = b'result'
572
parent2 = inventory.InventoryDirectory(b'p-1', 'dir2', inv.root.file_id)
579
parent2 = inventory.InventoryDirectory(
580
b'p-1', 'dir2', inv.root.file_id)
573
581
parent2.revision = b'result'
575
583
delta = [(None, u'dir2', b'p-1', parent2)]
576
584
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
579
587
def test_add_new_id_existing_path(self):
580
588
inv = self.get_empty_inventory()
581
parent1 = inventory.InventoryDirectory(b'p-1', 'dir1', inv.root.file_id)
589
parent1 = inventory.InventoryDirectory(
590
b'p-1', 'dir1', inv.root.file_id)
582
591
parent1.revision = b'result'
583
parent2 = inventory.InventoryDirectory(b'p-2', 'dir1', inv.root.file_id)
592
parent2 = inventory.InventoryDirectory(
593
b'p-2', 'dir1', inv.root.file_id)
584
594
parent2.revision = b'result'
586
596
delta = [(None, u'dir1', b'p-2', parent2)]
587
597
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
590
600
def test_remove_dir_leaving_dangling_child(self):
591
601
inv = self.get_empty_inventory()
601
611
delta = [(u'dir1', None, b'p-1', None),
602
(u'dir1/child2', None, b'p-3', None)]
612
(u'dir1/child2', None, b'p-3', None)]
603
613
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
606
616
def test_add_file(self):
607
617
inv = self.get_empty_inventory()
648
658
def test_rename_dir(self):
649
659
inv = self.get_empty_inventory()
650
dir1 = inventory.InventoryDirectory(b'dir-id', 'dir1', inv.root.file_id)
660
dir1 = inventory.InventoryDirectory(
661
b'dir-id', 'dir1', inv.root.file_id)
651
662
dir1.revision = b'basis'
652
663
file1 = self.make_file_ie(parent_id=b'dir-id')
655
dir2 = inventory.InventoryDirectory(b'dir-id', 'dir2', inv.root.file_id)
666
dir2 = inventory.InventoryDirectory(
667
b'dir-id', 'dir2', inv.root.file_id)
656
668
dir2.revision = b'result'
657
669
delta = [('dir1', 'dir2', b'dir-id', dir2)]
658
670
res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
662
674
def test_renamed_dir_with_renamed_child(self):
663
675
inv = self.get_empty_inventory()
664
dir1 = inventory.InventoryDirectory(b'dir-id', 'dir1', inv.root.file_id)
676
dir1 = inventory.InventoryDirectory(
677
b'dir-id', 'dir1', inv.root.file_id)
665
678
dir1.revision = b'basis'
666
679
file1 = self.make_file_ie(b'file-id-1', 'name1', parent_id=b'dir-id')
667
680
file2 = self.make_file_ie(b'file-id-2', 'name2', parent_id=b'dir-id')
671
dir2 = inventory.InventoryDirectory(b'dir-id', 'dir2', inv.root.file_id)
684
dir2 = inventory.InventoryDirectory(
685
b'dir-id', 'dir2', inv.root.file_id)
672
686
dir2.revision = b'result'
673
687
file2b = self.make_file_ie(b'file-id-2', 'name2', inv.root.file_id)
674
688
delta = [('dir1', 'dir2', b'dir-id', dir2),
703
717
def test_file_invalid_entry_name(self):
704
718
self.assertRaises(errors.InvalidEntryName, inventory.InventoryFile,
705
b'123', 'a/hello.c', ROOT_ID)
719
b'123', 'a/hello.c', ROOT_ID)
707
721
def test_file_backslash(self):
708
722
file = inventory.InventoryFile(b'123', 'h\\ello.c', ROOT_ID)
747
761
def test_symlink_detect_changes(self):
748
762
left = inventory.InventoryLink(b'123', 'hello.c', ROOT_ID)
749
left.symlink_target='foo'
763
left.symlink_target = 'foo'
750
764
right = inventory.InventoryLink(b'123', 'hello.c', ROOT_ID)
751
right.symlink_target='foo'
765
right.symlink_target = 'foo'
752
766
self.assertEqual((False, False), left.detect_changes(right))
753
767
self.assertEqual((False, False), right.detect_changes(left))
754
768
left.symlink_target = 'different'
770
784
def test_make_entry(self):
771
785
self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
772
inventory.InventoryFile)
786
inventory.InventoryFile)
773
787
self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
774
inventory.InventoryLink)
788
inventory.InventoryLink)
775
789
self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
776
inventory.InventoryDirectory)
790
inventory.InventoryDirectory)
778
792
def test_make_entry_non_normalized(self):
779
793
orig_normalized_filename = osutils.normalized_filename
787
801
osutils.normalized_filename = osutils._inaccessible_normalized_filename
788
802
self.assertRaises(errors.InvalidNormalization,
789
inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
803
inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
791
805
osutils.normalized_filename = orig_normalized_filename
884
898
chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
885
899
bytes = b''.join(chk_inv.to_lines())
886
900
self.assertRaises(ValueError, CHKInventory.deserialise, chk_bytes,
889
903
def test_captures_rev_root_byid(self):
890
904
inv = Inventory()
900
914
b'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
901
915
b'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
903
chk_inv = CHKInventory.deserialise(chk_bytes, b''.join(lines), (b'foo',))
917
chk_inv = CHKInventory.deserialise(
918
chk_bytes, b''.join(lines), (b'foo',))
904
919
self.assertEqual(b'plain', chk_inv._search_key_name)
906
921
def test_captures_parent_id_basename_index(self):
917
932
b'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
918
933
b'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
920
chk_inv = CHKInventory.deserialise(chk_bytes, b''.join(lines), (b'foo',))
935
chk_inv = CHKInventory.deserialise(
936
chk_bytes, b''.join(lines), (b'foo',))
921
937
self.assertEqual(b'plain', chk_inv._search_key_name)
923
939
def test_captures_search_key_name(self):
936
952
b'revision_id: foo\n',
937
953
b'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
939
chk_inv = CHKInventory.deserialise(chk_bytes, b''.join(lines), (b'foo',))
955
chk_inv = CHKInventory.deserialise(
956
chk_bytes, b''.join(lines), (b'foo',))
940
957
self.assertEqual(b'hash-16-way', chk_inv._search_key_name)
942
959
def test_directory_children_on_demand(self):
1115
1132
inv.root.revision = b"myrootrev"
1116
1133
reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
1117
1134
delta = [("", None, base_inv.root.file_id, None),
1118
(None, "", b"myrootid", inv.root)]
1135
(None, "", b"myrootid", inv.root)]
1119
1136
new_inv = base_inv.create_by_apply_delta(delta, b"expectedid")
1120
1137
self.assertEqual(reference_inv.root, new_inv.root)
1133
1150
inv.add(a_entry)
1134
1151
inv.revision_id = b"expectedid"
1135
1152
reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
1136
delta = [(None, "A", b"A-id", a_entry)]
1153
delta = [(None, "A", b"A-id", a_entry)]
1137
1154
new_inv = base_inv.create_by_apply_delta(delta, b"expectedid")
1138
1155
# new_inv should be the same as reference_inv.
1139
1156
self.assertEqual(reference_inv.revision_id, new_inv.revision_id)
1141
1158
reference_inv.id_to_entry._ensure_root()
1142
1159
new_inv.id_to_entry._ensure_root()
1143
1160
self.assertEqual(reference_inv.id_to_entry._root_node._key,
1144
new_inv.id_to_entry._root_node._key)
1161
new_inv.id_to_entry._root_node._key)
1146
1163
def test_create_by_apply_delta_empty_add_child_updates_parent_id(self):
1147
1164
inv = Inventory()
1167
1184
self.assertEqual(reference_inv.revision_id, new_inv.revision_id)
1168
1185
self.assertEqual(reference_inv.root_id, new_inv.root_id)
1169
1186
self.assertEqual(reference_inv.id_to_entry._root_node._key,
1170
new_inv.id_to_entry._root_node._key)
1187
new_inv.id_to_entry._root_node._key)
1171
1188
self.assertEqual(reference_inv.parent_id_basename_to_file_id._root_node._key,
1172
new_inv.parent_id_basename_to_file_id._root_node._key)
1189
new_inv.parent_id_basename_to_file_id._root_node._key)
1174
1191
def test_iter_changes(self):
1175
1192
# Low level bootstrapping smoke test; comprehensive generic tests via
1199
1216
bytes = b''.join(chk_inv2.to_lines())
1200
1217
inv_2 = CHKInventory.deserialise(chk_bytes, bytes, (b"revid2",))
1201
1218
self.assertEqual([(b'fileid', (u'file', u'file'), True, (True, True),
1202
(b'TREE_ROOT', b'TREE_ROOT'), (u'file', u'file'), ('file', 'file'),
1204
list(inv_1.iter_changes(inv_2)))
1219
(b'TREE_ROOT', b'TREE_ROOT'), (u'file',
1220
u'file'), ('file', 'file'),
1222
list(inv_1.iter_changes(inv_2)))
1206
1224
def test_parent_id_basename_to_file_id_index_enabled(self):
1207
1225
inv = Inventory()
1217
1235
tmp_inv = CHKInventory.from_inventory(chk_bytes, inv)
1218
1236
bytes = b''.join(tmp_inv.to_lines())
1219
1237
chk_inv = CHKInventory.deserialise(chk_bytes, bytes, (b"revid",))
1220
self.assertIsInstance(chk_inv.parent_id_basename_to_file_id, chk_map.CHKMap)
1238
self.assertIsInstance(
1239
chk_inv.parent_id_basename_to_file_id, chk_map.CHKMap)
1221
1240
self.assertEqual(
1222
1241
{(b'', b''): b'TREE_ROOT', (b'TREE_ROOT', b'file'): b'fileid'},
1223
1242
dict(chk_inv.parent_id_basename_to_file_id.iteritems()))
1300
1319
def test_symlink2_entry_to_bytes(self):
1301
1320
inv = CHKInventory(None)
1302
ie = inventory.InventoryLink(b'link-id', u'link\u03a9name', b'parent-id')
1321
ie = inventory.InventoryLink(
1322
b'link-id', u'link\u03a9name', b'parent-id')
1303
1323
ie.revision = b'link-rev-id'
1304
1324
ie.symlink_target = u'target/\u03a9path'
1305
1325
bytes = inv._entry_to_bytes(ie)
1444
1465
return factory(trans)
1446
1467
def make_dir(self, inv, name, parent_id, revision):
1447
ie = inv.make_entry('directory', name, parent_id, name.encode('utf-8') + b'-id')
1468
ie = inv.make_entry('directory', name, parent_id,
1469
name.encode('utf-8') + b'-id')
1448
1470
ie.revision = revision
1451
1473
def make_file(self, inv, name, parent_id, revision, content=b'content\n'):
1452
ie = inv.make_entry('file', name, parent_id, name.encode('utf-8') + b'-id')
1474
ie = inv.make_entry('file', name, parent_id,
1475
name.encode('utf-8') + b'-id')
1453
1476
ie.text_sha1 = osutils.sha_string(content)
1454
1477
ie.text_size = len(content)
1455
1478
ie.revision = revision
1479
1502
chk_bytes = self.get_chk_bytes()
1480
1503
# use a small maximum_size to force internal paging structures
1481
1504
chk_inv = CHKInventory.from_inventory(chk_bytes, inv,
1483
search_key_name=b'hash-255-way')
1506
search_key_name=b'hash-255-way')
1484
1507
bytes = b''.join(chk_inv.to_lines())
1485
1508
return CHKInventory.deserialise(chk_bytes, bytes, (b"revid",))
1542
1565
inv = self.make_simple_inventory()
1543
1566
self.assertExpand([b'TREE_ROOT', b'dir1-id', b'sub-dir1-id',
1544
1567
b'subsub-file1-id',
1545
], inv, [b'subsub-file1-id'])
1568
], inv, [b'subsub-file1-id'])
1547
1570
def test_get_children(self):
1548
1571
inv = self.make_simple_inventory()
1549
1572
self.assertExpand([b'TREE_ROOT', b'dir1-id', b'sub-dir1-id',
1550
1573
b'sub-file1-id', b'sub-file2-id', b'subsub-file1-id',
1551
], inv, [b'dir1-id'])
1574
], inv, [b'dir1-id'])
1553
1576
def test_from_root(self):
1554
1577
inv = self.make_simple_inventory()
1592
1615
self.assertEqual("a", inv.get_entry(b'thefileid').name)
1593
1616
# The inventory should be mutable and independent of
1594
1617
# the original tree
1595
self.assertFalse(tree.root_inventory.get_entry(b'thefileid').executable)
1618
self.assertFalse(tree.root_inventory.get_entry(
1619
b'thefileid').executable)
1596
1620
inv.get_entry(b'thefileid').executable = True
1597
self.assertFalse(tree.root_inventory.get_entry(b'thefileid').executable)
1621
self.assertFalse(tree.root_inventory.get_entry(
1622
b'thefileid').executable)