147
142
self.assertEqual(imaginary_id, imaginary_id2)
148
143
self.assertEqual(root, transform.get_tree_parent(imaginary_id))
149
144
self.assertEqual('directory', transform.final_kind(root))
150
self.assertEqual(self.wt.path2id(''), transform.final_file_id(root))
145
self.assertEqual(self.wt.get_root_id(), transform.final_file_id(root))
151
146
trans_id = transform.create_path('name', root)
152
147
self.assertIs(transform.final_file_id(trans_id), None)
153
148
self.assertIs(None, transform.final_kind(trans_id))
262
256
fo, st2 = self.wt.get_file_with_stat('two', filtered=False)
264
258
# We only guarantee 2s resolution
266
abs(creation_mtime - st1.st_mtime) < 2.0,
259
self.assertTrue(abs(creation_mtime - st1.st_mtime) < 2.0,
267
260
"%s != %s within 2 seconds" % (creation_mtime, st1.st_mtime))
268
261
# But if we have more than that, all files should get the same result
269
262
self.assertEqual(st1.st_mtime, st2.st_mtime)
271
264
def test_change_root_id(self):
272
265
transform, root = self.get_transform()
273
self.assertNotEqual(b'new-root-id', self.wt.path2id(''))
266
self.assertNotEqual(b'new-root-id', self.wt.get_root_id())
274
267
transform.new_directory('', ROOT_PARENT, b'new-root-id')
275
268
transform.delete_contents(root)
276
269
transform.unversion_file(root)
277
270
transform.fixup_new_roots()
278
271
transform.apply()
279
self.assertEqual(b'new-root-id', self.wt.path2id(''))
272
self.assertEqual(b'new-root-id', self.wt.get_root_id())
281
274
def test_change_root_id_add_files(self):
282
275
transform, root = self.get_transform()
283
self.assertNotEqual(b'new-root-id', self.wt.path2id(''))
276
self.assertNotEqual(b'new-root-id', self.wt.get_root_id())
284
277
new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
285
278
transform.new_file('file', new_trans_id, [b'new-contents\n'],
288
281
transform.unversion_file(root)
289
282
transform.fixup_new_roots()
290
283
transform.apply()
291
self.assertEqual(b'new-root-id', self.wt.path2id(''))
284
self.assertEqual(b'new-root-id', self.wt.get_root_id())
292
285
self.assertEqual(b'new-file-id', self.wt.path2id('file'))
293
286
self.assertFileEqual(b'new-contents\n', self.wt.abspath('file'))
295
288
def test_add_two_roots(self):
296
289
transform, root = self.get_transform()
297
transform.new_directory('', ROOT_PARENT, b'new-root-id')
298
transform.new_directory('', ROOT_PARENT, b'alt-root-id')
290
new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
291
new_trans_id = transform.new_directory('', ROOT_PARENT, b'alt-root-id')
299
292
self.assertRaises(ValueError, transform.fixup_new_roots)
301
294
def test_retain_existing_root(self):
315
308
def test_add_unversioned_root(self):
316
309
transform, root = self.get_transform()
317
transform.new_directory('', ROOT_PARENT, None)
310
new_trans_id = transform.new_directory('', ROOT_PARENT, None)
318
311
transform.delete_contents(transform.root)
319
312
transform.fixup_new_roots()
320
313
self.assertNotIn(transform.root, transform._new_id)
322
315
def test_remove_root_fixup(self):
323
316
transform, root = self.get_transform()
324
old_root_id = self.wt.path2id('')
317
old_root_id = self.wt.get_root_id()
325
318
self.assertNotEqual(b'new-root-id', old_root_id)
326
319
transform.delete_contents(root)
327
320
transform.unversion_file(root)
328
321
transform.fixup_new_roots()
329
322
transform.apply()
330
self.assertEqual(old_root_id, self.wt.path2id(''))
323
self.assertEqual(old_root_id, self.wt.get_root_id())
332
325
transform, root = self.get_transform()
333
transform.new_directory('', ROOT_PARENT, b'new-root-id')
334
transform.new_directory('', ROOT_PARENT, b'alt-root-id')
326
new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
327
new_trans_id = transform.new_directory('', ROOT_PARENT, b'alt-root-id')
335
328
self.assertRaises(ValueError, transform.fixup_new_roots)
337
330
def test_fixup_new_roots_permits_empty_tree(self):
379
372
transform, root = self.get_transform()
380
373
self.wt.lock_tree_write()
381
374
self.addCleanup(self.wt.unlock)
382
transform.new_file('name', root, [b'contents'], b'my_pretties', True)
383
oz = transform.new_directory('oz', root, b'oz-id')
375
trans_id = transform.new_file('name', root, [b'contents'],
376
b'my_pretties', True)
377
oz = transform.new_directory('oz', root, 'oz-id')
384
378
dorothy = transform.new_directory('dorothy', oz, b'dorothy-id')
385
transform.new_file('toto', dorothy, [b'toto-contents'], b'toto-id',
379
toto = transform.new_file('toto', dorothy, [b'toto-contents'],
388
382
self.assertEqual(len(transform.find_conflicts()), 0)
389
383
transform.apply()
390
384
self.assertRaises(ReusingTransform, transform.find_conflicts)
391
385
with open(self.wt.abspath('name'), 'r') as f:
392
386
self.assertEqual('contents', f.read())
393
self.assertEqual(self.wt.path2id('name'), b'my_pretties')
387
self.assertEqual(self.wt.path2id('name'), 'my_pretties')
394
388
self.assertIs(self.wt.is_executable('name'), True)
395
389
self.assertEqual(self.wt.path2id('oz'), b'oz-id')
396
390
self.assertEqual(self.wt.path2id('oz/dorothy'), b'dorothy-id')
403
397
def test_tree_reference(self):
404
398
transform, root = self.get_transform()
405
399
tree = transform._tree
406
trans_id = transform.new_directory('reference', root, b'subtree-id')
407
transform.set_tree_reference(b'subtree-revision', trans_id)
400
trans_id = transform.new_directory('reference', root, 'subtree-id')
401
transform.set_tree_reference('subtree-revision', trans_id)
408
402
transform.apply()
410
404
self.addCleanup(tree.unlock)
413
tree.root_inventory.get_entry(b'subtree-id').reference_revision)
405
self.assertEqual('subtree-revision',
406
tree.root_inventory.get_entry('subtree-id').reference_revision)
415
408
def test_conflicts(self):
416
409
transform, root = self.get_transform()
437
430
self.assertEqual(transform.find_conflicts(),
438
431
[('unversioned parent', lion_id),
439
432
('missing parent', lion_id)])
440
transform.version_file(b"Courage", lion_id)
433
transform.version_file("Courage", lion_id)
441
434
self.assertEqual(transform.find_conflicts(),
442
435
[('missing parent', lion_id),
443
436
('versioning no contents', lion_id)])
461
454
tip_id = transform.new_file('tip', oz_id, [b'ozma'], b'tip-id')
462
455
transform.apply()
463
456
self.assertEqual(self.wt.path2id('name'), b'my_pretties')
464
with open(self.wt.abspath('name'), 'rb') as f:
457
with open(self.wt.abspath('name'), 'r') as f:
465
458
self.assertEqual(b'contents', f.read())
466
459
transform2, root = self.get_transform()
467
460
oz_id = transform2.trans_id_tree_path('oz')
610
603
def test_add_del(self):
611
604
start, root = self.get_transform()
612
start.new_directory('a', root, b'a')
605
start.new_directory('a', root, 'a')
614
607
transform, root = self.get_transform()
615
608
transform.delete_versioned(transform.trans_id_tree_path('a'))
616
transform.new_directory('a', root, b'a')
609
transform.new_directory('a', root, 'a')
617
610
transform.apply()
619
612
def test_unversioning(self):
646
639
mangle_tree, root = self.get_transform()
647
640
root = mangle_tree.root
649
642
name1 = mangle_tree.trans_id_tree_path('name1')
650
643
name2 = mangle_tree.trans_id_tree_path('name2')
651
644
mangle_tree.adjust_path('name2', root, name1)
652
645
mangle_tree.adjust_path('name1', root, name2)
654
# tests for deleting parent directories
647
#tests for deleting parent directories
655
648
ddir = mangle_tree.trans_id_tree_path('dying_directory')
656
649
mangle_tree.delete_contents(ddir)
657
650
dfile = mangle_tree.trans_id_tree_path('dying_directory/dying_file')
660
653
mfile = mangle_tree.trans_id_tree_path('dying_directory/moving_file')
661
654
mangle_tree.adjust_path('mfile', root, mfile)
663
# tests for adding parent directories
664
newdir = mangle_tree.new_directory('new_directory', root, b'newdir')
656
#tests for adding parent directories
657
newdir = mangle_tree.new_directory('new_directory', root, 'newdir')
665
658
mfile2 = mangle_tree.trans_id_tree_path('moving_file2')
666
659
mangle_tree.adjust_path('mfile2', newdir, mfile2)
667
660
mangle_tree.new_file('newfile', newdir, [b'hello3'], b'dfile')
689
682
def test_both_rename(self):
690
683
create_tree, root = self.get_transform()
691
684
newdir = create_tree.new_directory('selftest', root, b'selftest-id')
692
create_tree.new_file('blackbox.py', newdir, [
693
b'hello1'], b'blackbox-id')
685
create_tree.new_file('blackbox.py', newdir, [b'hello1'], b'blackbox-id')
694
686
create_tree.apply()
695
687
mangle_tree, root = self.get_transform()
696
688
selftest = mangle_tree.trans_id_tree_path('selftest')
703
695
def test_both_rename2(self):
704
696
create_tree, root = self.get_transform()
705
breezy = create_tree.new_directory('breezy', root, b'breezy-id')
706
tests = create_tree.new_directory('tests', breezy, b'tests-id')
707
blackbox = create_tree.new_directory('blackbox', tests, b'blackbox-id')
697
breezy = create_tree.new_directory('breezy', root, 'breezy-id')
698
tests = create_tree.new_directory('tests', breezy, 'tests-id')
699
blackbox = create_tree.new_directory('blackbox', tests, 'blackbox-id')
708
700
create_tree.new_file('test_too_much.py', blackbox, [b'hello1'],
709
701
b'test_too_much-id')
710
702
create_tree.apply()
711
703
mangle_tree, root = self.get_transform()
712
704
breezy = mangle_tree.trans_id_tree_path('breezy')
713
705
tests = mangle_tree.trans_id_tree_path('breezy/tests')
714
test_too_much = mangle_tree.trans_id_tree_path(
715
'breezy/tests/blackbox/test_too_much.py')
706
test_too_much = mangle_tree.trans_id_tree_path('breezy/tests/blackbox/test_too_much.py')
716
707
mangle_tree.adjust_path('selftest', breezy, tests)
717
708
mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
718
709
mangle_tree.set_executability(True, test_too_much)
726
717
create_tree.apply()
727
718
mangle_tree, root = self.get_transform()
728
719
tests = mangle_tree.trans_id_tree_path('tests')
729
test_too_much = mangle_tree.trans_id_tree_path(
730
'tests/test_too_much.py')
720
test_too_much = mangle_tree.trans_id_tree_path('tests/test_too_much.py')
731
721
mangle_tree.adjust_path('selftest', root, tests)
732
722
mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
733
723
mangle_tree.set_executability(True, test_too_much)
740
730
create_tree.new_file('name1', root, [b'hello1'], b'name1')
741
731
create_tree.apply()
742
732
delete_contents, root = self.get_transform()
743
file = delete_contents.trans_id_tree_path('name1')
733
file = delete_contents.trans_id_tree_path(b'name1')
744
734
delete_contents.delete_contents(file)
745
735
delete_contents.apply()
746
736
move_id, root = self.get_transform()
747
737
name1 = move_id.trans_id_tree_path('name1')
748
newdir = move_id.new_directory('dir', root, b'newdir')
738
newdir = move_id.new_directory('dir', root, 'newdir')
749
739
move_id.adjust_path('name2', newdir, name1)
763
753
delete_contents.finalize()
764
754
replace = TreeTransform(self.wt)
765
755
self.addCleanup(replace.finalize)
766
name2 = replace.new_file('name2', root, [b'hello2'], b'name1')
756
name2 = replace.new_file('name2', root, [b'hello2'], 'name1')
767
757
conflicts = replace.find_conflicts()
768
758
name1 = replace.trans_id_tree_path('name1')
769
759
self.assertEqual(conflicts, [('duplicate id', name1, name2)])
773
763
def _test_symlinks(self, link_name1, link_target1,
774
764
link_name2, link_target2):
766
def ozpath(p): return 'oz/' + p
779
768
self.requireFeature(SymlinkFeature)
780
769
transform, root = self.get_transform()
781
770
oz_id = transform.new_directory('oz', root, b'oz-id')
782
transform.new_symlink(link_name1, oz_id, link_target1, b'wizard-id')
771
wizard = transform.new_symlink(link_name1, oz_id, link_target1,
783
773
wiz_id = transform.create_path(link_name2, oz_id)
784
774
transform.create_symlink(link_target2, wiz_id)
785
775
transform.version_file(b'wiz-id2', wiz_id)
807
797
u'\N{Euro Sign}wizard2',
808
798
u'b\N{Euro Sign}hind_curtain')
810
def test_unsupported_symlink_no_conflict(self):
800
def test_unable_create_symlink(self):
812
802
wt = self.make_branch_and_tree('.')
813
tt = TreeTransform(wt)
814
self.addCleanup(tt.finalize)
815
tt.new_symlink('foo', tt.root, 'bar')
816
result = tt.find_conflicts()
817
self.assertEqual([], result)
803
tt = TreeTransform(wt) # TreeTransform obtains write lock
805
tt.new_symlink('foo', tt.root, 'bar')
818
809
os_symlink = getattr(os, 'symlink', None)
819
810
os.symlink = None
812
err = self.assertRaises(errors.UnableCreateSymlink, tt_helper)
814
"Unable to create symlink 'foo' on this platform",
824
818
os.symlink = os_symlink
877
871
b'munchkincity-id')
878
872
unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
880
874
self.assertEqual(cooked_conflicts[3], unversioned_parent)
881
parent_loop = ParentLoop(
882
'Cancelled move', 'oz/emeraldcity',
883
'oz/emeraldcity', b'emerald-id', b'emerald-id')
875
parent_loop = ParentLoop('Cancelled move', 'oz/emeraldcity',
876
'oz/emeraldcity', b'emerald-id', b'emerald-id')
884
877
self.assertEqual(cooked_conflicts[4], deleted_parent)
885
878
self.assertEqual(cooked_conflicts[5], unversioned_parent2)
886
879
self.assertEqual(cooked_conflicts[6], parent_loop)
905
898
self.assertEqual(conflicts_s[3], 'Conflict because munchkincity is not'
906
899
' versioned, but has versioned'
907
900
' children. Versioned directory.')
908
self.assertEqualDiff(
909
conflicts_s[4], "Conflict: can't delete oz because it"
910
" is not empty. Not deleting.")
901
self.assertEqualDiff(conflicts_s[4], "Conflict: can't delete oz because it"
902
" is not empty. Not deleting.")
911
903
self.assertEqual(conflicts_s[5], 'Conflict because oz is not'
912
904
' versioned, but has versioned'
913
905
' children. Versioned directory.')
931
923
tt = self.prepare_wrong_parent_kind()
932
924
raw_conflicts = resolve_conflicts(tt)
933
925
self.assertEqual({('non-directory parent', 'Created directory',
934
'new-3')}, raw_conflicts)
926
'new-3')}, raw_conflicts)
935
927
cooked_conflicts = cook_conflicts(raw_conflicts, tt)
936
928
self.assertEqual([NonDirectoryParent('Created directory', 'parent.new',
937
b'parent-id')], cooked_conflicts)
929
b'parent-id')], cooked_conflicts)
939
931
self.assertFalse(self.wt.is_versioned('parent'))
940
self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
932
self.assertEqual('parent-id', self.wt.path2id('parent.new'))
942
934
def test_resolve_conflicts_wrong_new_parent_kind(self):
943
935
tt, root = self.get_transform()
987
979
def test_moving_versioned_directories(self):
988
980
create, root = self.get_transform()
989
kansas = create.new_directory('kansas', root, b'kansas-id')
990
create.new_directory('house', kansas, b'house-id')
991
create.new_directory('oz', root, b'oz-id')
981
kansas = create.new_directory('kansas', root, 'kansas-id')
982
create.new_directory('house', kansas, 'house-id')
983
create.new_directory('oz', root, 'oz-id')
993
985
cyclone, root = self.get_transform()
994
986
oz = cyclone.trans_id_tree_path('oz')
1026
1018
self.requireFeature(features.not_running_as_root)
1027
1019
# see https://bugs.launchpad.net/bzr/+bug/491763
1028
1020
create, root_id = self.get_transform()
1029
create.new_directory('first-dir', root_id, b'first-id')
1030
create.new_file('myfile', root_id, [b'myfile-text'], b'myfile-id')
1021
first_dir = create.new_directory('first-dir', root_id, b'first-id')
1022
myfile = create.new_file('myfile', root_id, [b'myfile-text'],
1032
1025
if os.name == "posix" and sys.platform != "cygwin":
1033
1026
# posix filesystems fail on renaming if the readonly bit is set
1043
1036
dir_id = rename_transform.trans_id_file_id(b'first-id')
1044
1037
rename_transform.adjust_path('newname', dir_id, file_trans_id)
1045
1038
e = self.assertRaises(errors.TransformRenameFailed,
1046
rename_transform.apply)
1047
# On nix looks like:
1039
rename_transform.apply)
1040
# On nix looks like:
1048
1041
# "Failed to rename .../work/.bzr/checkout/limbo/new-1
1049
1042
# to .../first-dir/newname: [Errno 13] Permission denied"
1050
1043
# On windows looks like:
1051
# "Failed to rename .../work/myfile to
1044
# "Failed to rename .../work/myfile to
1052
1045
# .../work/.bzr/checkout/limbo/new-1: [Errno 13] Permission denied"
1053
1046
# This test isn't concerned with exactly what the error looks like,
1054
1047
# and the strerror will vary across OS and locales, but the assert
1073
1065
wt = transform._tree
1075
1067
self.addCleanup(wt.unlock)
1076
transform.new_file('set_on_creation', root, [b'Set on creation'],
1068
transform.new_file('set_on_creation', root, [b'Set on creation'], 'soc',
1078
1070
sac = transform.new_file('set_after_creation', root,
1079
[b'Set after creation'], b'sac')
1071
[b'Set after creation'], 'sac')
1080
1072
transform.set_executability(True, sac)
1081
1073
uws = transform.new_file('unset_without_set', root, [b'Unset badly'],
1083
1075
self.assertRaises(KeyError, transform.set_executability, None, uws)
1084
1076
transform.apply()
1085
1077
self.assertTrue(wt.is_executable('set_on_creation'))
1145
1135
old = transform.trans_id_tree_path('old')
1146
1136
transform.unversion_file(old)
1147
1137
self.assertEqual([(b'id-1', ('old', None), False, (True, False),
1148
(b'eert_toor', b'eert_toor'),
1149
('old', 'old'), ('file', 'file'),
1150
(True, True), False)],
1151
list(transform.iter_changes()))
1138
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1139
(True, True))], list(transform.iter_changes()))
1152
1140
transform.new_directory('new', root, b'id-1')
1153
1141
self.assertEqual([(b'id-1', ('old', 'new'), True, (True, True),
1154
(b'eert_toor', b'eert_toor'), ('old', 'new'),
1155
('file', 'directory'),
1156
(True, False), False)],
1157
list(transform.iter_changes()))
1142
(b'eert_toor', b'eert_toor'), ('old', 'new'),
1143
('file', 'directory'),
1144
(True, False))], list(transform.iter_changes()))
1159
1146
transform.finalize()
1168
1155
old = transform.trans_id_tree_path('old')
1169
1156
transform.version_file(b'id-1', old)
1170
1157
self.assertEqual([(b'id-1', (None, 'old'), False, (False, True),
1171
(b'eert_toor', b'eert_toor'),
1172
('old', 'old'), ('file', 'file'),
1173
(False, False), False)],
1174
list(transform.iter_changes()))
1158
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1159
(False, False))], list(transform.iter_changes()))
1176
1161
transform.finalize()
1178
1163
def test_iter_changes_modifications(self):
1179
1164
self.wt.set_root_id(b'eert_toor')
1180
1165
transform, root = self.get_transform()
1181
transform.new_file('old', root, [b'blah'], b'id-1')
1166
transform.new_file('old', root, [b'blah'], 'id-1')
1182
1167
transform.new_file('new', root, [b'blah'])
1183
transform.new_directory('subdir', root, b'subdir-id')
1168
transform.new_directory('subdir', root, 'subdir-id')
1184
1169
transform.apply()
1185
1170
transform, root = self.get_transform()
1189
1174
new = transform.trans_id_tree_path('new')
1190
1175
self.assertEqual([], list(transform.iter_changes()))
1193
1178
transform.delete_contents(old)
1194
1179
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1195
(b'eert_toor', b'eert_toor'),
1196
('old', 'old'), ('file', None),
1197
(False, False), False)],
1198
list(transform.iter_changes()))
1180
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', None),
1181
(False, False))], list(transform.iter_changes()))
1201
1184
transform.create_file([b'blah'], old)
1202
1185
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1203
(b'eert_toor', b'eert_toor'),
1204
('old', 'old'), ('file', 'file'),
1205
(False, False), False)],
1206
list(transform.iter_changes()))
1186
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1187
(False, False))], list(transform.iter_changes()))
1207
1188
transform.cancel_deletion(old)
1208
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1209
(b'eert_toor', b'eert_toor'),
1210
('old', 'old'), ('file', 'file'),
1211
(False, False), False)],
1212
list(transform.iter_changes()))
1189
self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
1190
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1191
(False, False))], list(transform.iter_changes()))
1213
1192
transform.cancel_creation(old)
1215
1194
# move file_id to a different file
1218
1197
transform.version_file(b'id-1', new)
1219
1198
transform.adjust_path('old', root, new)
1220
1199
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1221
(b'eert_toor', b'eert_toor'),
1222
('old', 'old'), ('file', 'file'),
1223
(False, False), False)],
1224
list(transform.iter_changes()))
1200
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
1201
(False, False))], list(transform.iter_changes()))
1225
1202
transform.cancel_versioning(new)
1226
1203
transform._removed_id = set()
1229
1206
self.assertEqual([], list(transform.iter_changes()))
1230
1207
transform.set_executability(True, old)
1231
1208
self.assertEqual([(b'id-1', ('old', 'old'), False, (True, True),
1232
(b'eert_toor', b'eert_toor'),
1233
('old', 'old'), ('file', 'file'),
1234
(False, True), False)],
1235
list(transform.iter_changes()))
1209
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1210
(False, True))], list(transform.iter_changes()))
1236
1211
transform.set_executability(None, old)
1240
1215
transform.adjust_path('new', root, old)
1241
1216
transform._new_parent = {}
1242
1217
self.assertEqual([(b'id-1', ('old', 'new'), False, (True, True),
1243
(b'eert_toor', b'eert_toor'),
1244
('old', 'new'), ('file', 'file'),
1245
(False, False), False)],
1246
list(transform.iter_changes()))
1218
(b'eert_toor', b'eert_toor'), ('old', 'new'), ('file', 'file'),
1219
(False, False))], list(transform.iter_changes()))
1247
1220
transform._new_name = {}
1249
1222
# parent directory
1251
1224
transform.adjust_path('new', subdir, old)
1252
1225
transform._new_name = {}
1253
1226
self.assertEqual([(b'id-1', ('old', 'subdir/old'), False,
1254
(True, True), (b'eert_toor',
1255
b'subdir-id'), ('old', 'old'),
1256
('file', 'file'), (False, False), False)],
1257
list(transform.iter_changes()))
1227
(True, True), (b'eert_toor', b'subdir-id'), ('old', 'old'),
1228
('file', 'file'), (False, False))],
1229
list(transform.iter_changes()))
1258
1230
transform._new_path = {}
1276
1248
transform.delete_contents(transform.trans_id_file_id(b'id-1'))
1277
1249
transform.set_executability(True,
1278
transform.trans_id_file_id(b'id-2'))
1280
[(b'id-1', (u'file1', u'file1'), True, (True, True),
1281
(b'eert_toor', b'eert_toor'), ('file1', u'file1'),
1282
('file', None), (False, False), False),
1283
(b'id-2', (u'file2', u'file2'), False, (True, True),
1284
(b'eert_toor', b'eert_toor'), ('file2', u'file2'),
1285
('file', 'file'), (False, True), False)],
1250
transform.trans_id_file_id(b'id-2'))
1251
self.assertEqual([(b'id-1', (u'file1', u'file1'), True, (True, True),
1252
(b'eert_toor', b'eert_toor'), ('file1', u'file1'),
1253
('file', None), (False, False)),
1254
(b'id-2', (u'file2', u'file2'), False, (True, True),
1255
(b'eert_toor', b'eert_toor'), ('file2', u'file2'),
1256
('file', 'file'), (False, True))],
1286
1257
list(transform.iter_changes()))
1288
1259
transform.finalize()
1303
1274
transform.adjust_path('flitter', root, floater)
1304
1275
self.assertEqual([(b'floater-id', ('floater', 'flitter'), False,
1306
(b'toor_eert', b'toor_eert'),
1307
('floater', 'flitter'),
1308
(None, None), (False, False), False)],
1309
list(transform.iter_changes()))
1276
(True, True), ('toor_eert', 'toor_eert'), ('floater', 'flitter'),
1277
(None, None), (False, False))], list(transform.iter_changes()))
1311
1279
transform.finalize()
1597
1565
self.addCleanup(wt.unlock)
1598
1566
self.assertEqual(wt.kind("foo"), "symlink")
1600
def test_file_to_symlink_unsupported(self):
1601
wt = self.make_branch_and_tree('.')
1602
self.build_tree(['foo'])
1605
self.overrideAttr(osutils, 'supports_symlinks', lambda p: False)
1606
tt = TreeTransform(wt)
1607
self.addCleanup(tt.finalize)
1608
foo_trans_id = tt.trans_id_tree_path("foo")
1609
tt.delete_contents(foo_trans_id)
1611
trace.push_log_file(log)
1612
tt.create_symlink("bar", foo_trans_id)
1614
self.assertContainsRe(
1616
b'Unable to create symlink "foo" on this filesystem')
1618
1568
def test_dir_to_file(self):
1619
1569
wt = self.make_branch_and_tree('.')
1620
1570
self.build_tree(['foo/', 'foo/bar'])
1668
1618
tree2 = self.make_branch_and_tree('tree2')
1669
1619
tt = TreeTransform(tree2)
1670
1620
foo_trans_id = tt.create_path('foo', tt.root)
1671
create_from_tree(tt, foo_trans_id, tree1, 'foo')
1621
create_from_tree(tt, foo_trans_id, tree1, 'foo', file_id=b'foo-id')
1672
1622
bar_trans_id = tt.create_path('bar', tt.root)
1673
create_from_tree(tt, bar_trans_id, tree1, 'bar')
1623
create_from_tree(tt, bar_trans_id, tree1, 'bar', file_id=b'bar-id')
1675
1625
self.assertEqual('directory', osutils.file_kind('tree2/foo'))
1676
1626
self.assertFileEqual(b'baz', 'tree2/bar')
1678
1628
def test_create_from_tree_bytes(self):
1679
1629
"""Provided lines are used instead of tree content."""
1680
1630
tree1 = self.make_branch_and_tree('tree1')
1681
self.build_tree_contents([('tree1/foo', b'bar'), ])
1631
self.build_tree_contents([('tree1/foo', b'bar'),])
1682
1632
tree1.add('foo', b'foo-id')
1683
1633
tree2 = self.make_branch_and_tree('tree2')
1684
1634
tt = TreeTransform(tree2)
1685
1635
foo_trans_id = tt.create_path('foo', tt.root)
1686
create_from_tree(tt, foo_trans_id, tree1, 'foo', chunks=[b'qux'])
1636
create_from_tree(tt, foo_trans_id, tree1, 'foo', file_id=b'foo-id',
1688
1639
self.assertFileEqual(b'qux', 'tree2/foo')
1694
1645
tree1.add('foo', b'foo-id')
1695
1646
tt = TreeTransform(self.make_branch_and_tree('tree2'))
1696
1647
foo_trans_id = tt.create_path('foo', tt.root)
1697
create_from_tree(tt, foo_trans_id, tree1, 'foo')
1648
create_from_tree(tt, foo_trans_id, tree1, 'foo', file_id=b'foo-id')
1699
1650
self.assertEqual('bar', os.readlink('tree2/foo'))
1848
1798
for link, target in (('e', e_target), ('f', f_target),
1849
1799
('g', g_target), ('h', h_target)):
1850
1800
if target is not None:
1851
tg.tt.new_symlink(link, tg.root, target,
1852
link.encode('ascii'))
1801
tg.tt.new_symlink(link, tg.root, target, link)
1854
1803
for tg in this, base, other:
1858
1807
self.assertIs(os.path.islink(this.wt.abspath('b')), True)
1859
1808
self.assertIs(os.path.isfile(this.wt.abspath('c')), True)
1860
1809
for suffix in ('THIS', 'BASE', 'OTHER'):
1861
self.assertEqual(os.readlink(
1862
this.wt.abspath('d.' + suffix)), suffix)
1810
self.assertEqual(os.readlink(this.wt.abspath('d.'+suffix)), suffix)
1863
1811
self.assertIs(os.path.lexists(this.wt.abspath('d')), False)
1864
1812
self.assertEqual(this.wt.id2path(b'd'), 'd.OTHER')
1865
1813
self.assertEqual(this.wt.id2path(b'f'), 'f.THIS')
1879
1827
base = TransformGroup("BASE", root_id)
1880
1828
this = TransformGroup("THIS", root_id)
1881
1829
other = TransformGroup("OTHER", root_id)
1882
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, b'a')
1883
for t in [base, this, other]]
1884
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, b'b')
1885
for t in [base, this, other]]
1886
base.tt.new_directory('c', base_a, b'c')
1887
this.tt.new_directory('c1', this_a, b'c')
1888
other.tt.new_directory('c', other_b, b'c')
1890
base.tt.new_directory('d', base_a, b'd')
1891
this.tt.new_directory('d1', this_b, b'd')
1892
other.tt.new_directory('d', other_a, b'd')
1894
base.tt.new_directory('e', base_a, b'e')
1895
this.tt.new_directory('e', this_a, b'e')
1896
other.tt.new_directory('e1', other_b, b'e')
1898
base.tt.new_directory('f', base_a, b'f')
1899
this.tt.new_directory('f1', this_b, b'f')
1900
other.tt.new_directory('f1', other_b, b'f')
1830
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a')
1831
for t in [base, this, other]]
1832
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b')
1833
for t in [base, this, other]]
1834
base.tt.new_directory('c', base_a, 'c')
1835
this.tt.new_directory('c1', this_a, 'c')
1836
other.tt.new_directory('c', other_b, 'c')
1838
base.tt.new_directory('d', base_a, 'd')
1839
this.tt.new_directory('d1', this_b, 'd')
1840
other.tt.new_directory('d', other_a, 'd')
1842
base.tt.new_directory('e', base_a, 'e')
1843
this.tt.new_directory('e', this_a, 'e')
1844
other.tt.new_directory('e1', other_b, 'e')
1846
base.tt.new_directory('f', base_a, 'f')
1847
this.tt.new_directory('f1', this_b, 'f')
1848
other.tt.new_directory('f1', other_b, 'f')
1902
1850
for tg in [this, base, other]:
1912
1860
base = TransformGroup("BASE", root_id)
1913
1861
this = TransformGroup("THIS", root_id)
1914
1862
other = TransformGroup("OTHER", root_id)
1915
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, b'a')
1863
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a')
1916
1864
for t in [base, this, other]]
1917
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, b'b')
1865
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b')
1918
1866
for t in [base, this, other]]
1920
1868
base.tt.new_file('g', base_a, [b'g'], b'g')
1958
1905
build_tree(basis, b)
1959
1906
self.assertIs(os.path.isdir('b/foo'), True)
1960
1907
with open('b/foo/bar', 'rb') as f:
1961
self.assertEqual(f.read(), b"contents")
1908
self.assertEqual(f.read(), "contents")
1962
1909
self.assertEqual(os.readlink('b/foo/baz'), 'a/foo/bar')
1964
1911
def test_build_with_references(self):
1965
1912
tree = self.make_branch_and_tree('source',
1966
format='development-subtree')
1913
format='development-subtree')
1967
1914
subtree = self.make_branch_and_tree('source/subtree',
1968
format='development-subtree')
1915
format='development-subtree')
1969
1916
tree.add_reference(subtree)
1970
1917
tree.commit('a revision')
1971
1918
tree.branch.create_checkout('target')
1980
1927
source.add('file', b'new-file')
1981
1928
source.commit('added file')
1982
1929
build_tree(source.basis_tree(), target)
1984
[DuplicateEntry('Moved existing file to', 'file.moved',
1985
'file', None, 'new-file')],
1930
self.assertEqual([DuplicateEntry('Moved existing file to',
1931
'file.moved', 'file', None, 'new-file')],
1987
1933
target2 = self.make_branch_and_tree('target2')
1988
1934
with open('target2/file', 'wb') as target_file, \
1989
1935
open('source/file', 'rb') as source_file:
2001
1947
target = self.make_branch_and_tree('target')
2002
1948
os.symlink('bar', 'target/symlink')
2003
1949
build_tree(source.basis_tree(), target)
2005
[DuplicateEntry('Moved existing file to', 'symlink.moved',
2006
'symlink', None, 'new-symlink')],
1950
self.assertEqual([DuplicateEntry('Moved existing file to',
1951
'symlink.moved', 'symlink', None, 'new-symlink')],
2007
1952
target.conflicts())
2008
1953
target = self.make_branch_and_tree('target2')
2009
1954
os.symlink('foo', 'target2/symlink')
2037
1982
self.assertPathDoesNotExist('target3/dir1/file')
2038
1983
self.assertPathExists('target3/dir1/file2')
2039
1984
self.assertPathExists('target3/dir1.diverted/file')
2041
[DuplicateEntry('Diverted to', 'dir1.diverted',
2042
'dir1', 'new-dir1', None)],
1985
self.assertEqual([DuplicateEntry('Diverted to',
1986
'dir1.diverted', 'dir1', 'new-dir1', None)],
2043
1987
target.conflicts())
2045
1989
target = self.make_branch_and_tree('target4')
2049
1993
self.assertPathExists('target4/dir1/file')
2050
1994
self.assertEqual('directory', file_kind('target4/dir1/file'))
2051
1995
self.assertPathExists('target4/dir1/file.diverted')
2053
[DuplicateEntry('Diverted to', 'dir1/file.diverted',
2054
'dir1/file', 'new-file', None)],
1996
self.assertEqual([DuplicateEntry('Diverted to',
1997
'dir1/file.diverted', 'dir1/file', 'new-file', None)],
2055
1998
target.conflicts())
2057
2000
def test_mixed_conflict_handling(self):
2062
2005
source.add('name', b'new-name')
2063
2006
source.commit('added file')
2064
2007
build_tree(source.basis_tree(), target)
2066
[DuplicateEntry('Moved existing file to',
2067
'name.moved', 'name', None, 'new-name')],
2008
self.assertEqual([DuplicateEntry('Moved existing file to',
2009
'name.moved', 'name', None, 'new-name')], target.conflicts())
2070
2011
def test_raises_in_populated(self):
2071
2012
source = self.make_branch_and_tree('source')
2111
2052
self.build_tree_contents([('source/file2', b'C')])
2113
2054
real_source_get_file = source.get_file
2117
return real_source_get_file(path)
2055
def get_file(path, file_id=None):
2056
calls.append(file_id)
2057
return real_source_get_file(path, file_id)
2118
2058
source.get_file = get_file
2119
2059
target = self.make_branch_and_tree('target')
2120
2060
revision_tree = source.basis_tree()
2121
2061
revision_tree.lock_read()
2122
2062
self.addCleanup(revision_tree.unlock)
2123
2063
build_tree(revision_tree, target, source)
2124
self.assertEqual(['file1'], calls)
2064
self.assertEqual([b'file1-id'], calls)
2125
2065
target.lock_read()
2126
2066
self.addCleanup(target.unlock)
2127
2067
self.assertEqual([], list(target.iter_changes(revision_tree)))
2245
2184
# below, but that looks a bit... hard to read even if it's exactly
2246
2185
# the same thing.
2247
2186
original_registry = filters._reset_registry()
2249
2187
def restore_registry():
2250
2188
filters._reset_registry(original_registry)
2251
2189
self.addCleanup(restore_registry)
2253
2190
def rot13(chunks, context=None):
2255
codecs.encode(chunk.decode('ascii'), 'rot13').encode('ascii')
2256
for chunk in chunks]
2191
return [b''.join(chunks).encode('rot13')]
2257
2192
rot13filter = filters.ContentFilter(rot13, rot13)
2258
2193
filters.filter_stacks_registry.register(
2259
2194
'rot13', {'yes': [rot13filter]}.get)
2326
2260
# entry[1] is the state information, entry[1][0] is the state of the
2327
2261
# working tree, entry[1][0][1] is the sha value for the current working
2329
entry1 = state._get_entry(0, path_utf8=b'file1')
2263
entry1 = state._get_entry(0, path_utf8='file1')
2330
2264
self.assertEqual(entry1_sha, entry1[1][0][1])
2331
2265
# The 'size' field must also be set.
2332
2266
self.assertEqual(25, entry1[1][0][2])
2333
2267
entry1_state = entry1[1][0]
2334
entry2 = state._get_entry(0, path_utf8=b'dir/file2')
2268
entry2 = state._get_entry(0, path_utf8='dir/file2')
2335
2269
self.assertEqual(entry2_sha, entry2[1][0][1])
2336
2270
self.assertEqual(29, entry2[1][0][2])
2337
2271
entry2_state = entry2[1][0]
2338
2272
# Now, make sure that we don't have to re-read the content. The
2339
2273
# packed_stat should match exactly.
2340
self.assertEqual(entry1_sha, target.get_file_sha1('file1'))
2341
self.assertEqual(entry2_sha, target.get_file_sha1('dir/file2'))
2274
self.assertEqual(entry1_sha, target.get_file_sha1('file1', b'file1-id'))
2275
self.assertEqual(entry2_sha,
2276
target.get_file_sha1('dir/file2', b'file2-id'))
2342
2277
self.assertEqual(entry1_state, entry1[1][0])
2343
2278
self.assertEqual(entry2_state, entry2[1][0])
2378
2313
def test_merge_parents(self):
2379
2314
branch, tt = self.get_branch_and_transform()
2380
tt.commit(branch, 'my message', [b'rev1b', b'rev1c'])
2381
self.assertEqual([b'rev1b', b'rev1c'],
2315
rev = tt.commit(branch, 'my message', ['rev1b', 'rev1c'])
2316
self.assertEqual(['rev1b', 'rev1c'],
2382
2317
branch.basis_tree().get_parent_ids()[1:])
2384
2319
def test_first_commit(self):
2387
2322
self.addCleanup(branch.unlock)
2388
2323
tt = TransformPreview(branch.basis_tree())
2389
2324
self.addCleanup(tt.finalize)
2390
tt.new_directory('', ROOT_PARENT, b'TREE_ROOT')
2391
tt.commit(branch, 'my message')
2325
tt.new_directory('', ROOT_PARENT, 'TREE_ROOT')
2326
rev = tt.commit(branch, 'my message')
2392
2327
self.assertEqual([], branch.basis_tree().get_parent_ids())
2393
2328
self.assertNotEqual(_mod_revision.NULL_REVISION,
2394
2329
branch.last_revision())
2411
2346
trans_id = tt.new_directory('dir', tt.root, b'dir-id')
2412
2347
if SymlinkFeature.available():
2413
2348
tt.new_symlink('symlink', trans_id, 'target', b'symlink-id')
2414
tt.commit(branch, 'message')
2349
rev = tt.commit(branch, 'message')
2415
2350
tree = branch.basis_tree()
2416
2351
self.assertEqual('file', tree.id2path(b'file-id'))
2417
self.assertEqual(b'contents', tree.get_file_text('file'))
2352
self.assertEqual(b'contents', tree.get_file_text('file', b'file-id'))
2418
2353
self.assertEqual('dir', tree.id2path(b'dir-id'))
2419
2354
if SymlinkFeature.available():
2420
2355
self.assertEqual('dir/symlink', tree.id2path(b'symlink-id'))
2454
2389
committer='me <me@example.com>',
2455
2390
revprops={u'foo': 'bar'}, revision_id=b'revid-1',
2456
2391
authors=['Author1 <author1@example.com>',
2457
'Author2 <author2@example.com>',
2392
'Author2 <author2@example.com>',
2459
2394
self.assertEqual(b'revid-1', rev_id)
2460
2395
revision = branch.repository.get_revision(rev_id)
2461
2396
self.assertEqual(1, revision.timestamp)
2610
2545
new_globals = dict(func.__globals__)
2611
2546
new_globals.update(globals)
2612
2547
new_func = types.FunctionType(func.__code__, new_globals,
2613
func.__name__, func.__defaults__)
2615
setattr(instance, method_name,
2616
types.MethodType(new_func, instance))
2618
setattr(instance, method_name,
2619
types.MethodType(new_func, instance, instance.__class__))
2548
func.__name__, func.__defaults__)
2549
setattr(instance, method_name,
2550
types.MethodType(new_func, instance, instance.__class__))
2620
2551
self.addCleanup(delattr, instance, method_name)
2649
2580
def test_root_create_file_open_raises_before_creation(self):
2650
2581
tt, trans_id = self.create_transform_and_root_trans_id()
2651
self._override_globals_in_method(
2652
tt, "create_file", {"open": self._fake_open_raises_before})
2653
self.assertRaises(RuntimeError, tt.create_file,
2654
[b"contents"], trans_id)
2582
self._override_globals_in_method(tt, "create_file",
2583
{"open": self._fake_open_raises_before})
2584
self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
2655
2585
path = tt._limbo_name(trans_id)
2656
2586
self.assertPathDoesNotExist(path)
2660
2590
def test_root_create_file_open_raises_after_creation(self):
2661
2591
tt, trans_id = self.create_transform_and_root_trans_id()
2662
self._override_globals_in_method(
2663
tt, "create_file", {"open": self._fake_open_raises_after})
2664
self.assertRaises(RuntimeError, tt.create_file,
2665
[b"contents"], trans_id)
2592
self._override_globals_in_method(tt, "create_file",
2593
{"open": self._fake_open_raises_after})
2594
self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
2666
2595
path = tt._limbo_name(trans_id)
2667
2596
self.assertPathExists(path)
2672
2601
def test_subdir_create_file_open_raises_before_creation(self):
2673
2602
tt, trans_id = self.create_transform_and_subdir_trans_id()
2674
self._override_globals_in_method(
2675
tt, "create_file", {"open": self._fake_open_raises_before})
2676
self.assertRaises(RuntimeError, tt.create_file,
2677
[b"contents"], trans_id)
2603
self._override_globals_in_method(tt, "create_file",
2604
{"open": self._fake_open_raises_before})
2605
self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
2678
2606
path = tt._limbo_name(trans_id)
2679
2607
self.assertPathDoesNotExist(path)
2683
2611
def test_subdir_create_file_open_raises_after_creation(self):
2684
2612
tt, trans_id = self.create_transform_and_subdir_trans_id()
2685
self._override_globals_in_method(
2686
tt, "create_file", {"open": self._fake_open_raises_after})
2687
self.assertRaises(RuntimeError, tt.create_file,
2688
[b"contents"], trans_id)
2613
self._override_globals_in_method(tt, "create_file",
2614
{"open": self._fake_open_raises_after})
2615
self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
2689
2616
path = tt._limbo_name(trans_id)
2690
2617
self.assertPathExists(path)
2746
2673
def test_resolve_create_parent_for_versioned_file(self):
2747
2674
wt, tt = self.make_tt_with_versioned_dir()
2748
2675
dir_tid = tt.trans_id_tree_path('dir')
2749
tt.new_file('file', dir_tid, [b'Contents'], file_id=b'file-id')
2676
file_tid = tt.new_file('file', dir_tid, [b'Contents'], file_id=b'file-id')
2750
2677
tt.delete_contents(dir_tid)
2751
2678
tt.unversion_file(dir_tid)
2752
2679
conflicts = resolve_conflicts(tt)
2770
2697
A_ENTRY = (b'a-id', ('a', 'a'), True, (True, True),
2771
(b'TREE_ROOT', b'TREE_ROOT'), ('a', 'a'), ('file', 'file'),
2772
(False, False), False)
2698
(b'TREE_ROOT', b'TREE_ROOT'), ('a', 'a'), ('file', 'file'),
2773
2700
ROOT_ENTRY = (b'TREE_ROOT', ('', ''), False, (True, True), (None, None),
2774
('', ''), ('directory', 'directory'), (False, False), False)
2701
('', ''), ('directory', 'directory'), (False, False))
2777
2704
class TestTransformPreview(tests.TestCaseWithTransport):
2821
2748
out = BytesIO()
2822
2749
show_diff_trees(revision_tree, preview_tree, out)
2823
2750
lines = out.getvalue().splitlines()
2824
self.assertEqual(lines[0], b"=== added file 'file2'")
2751
self.assertEqual(lines[0], "=== added file 'file2'")
2825
2752
# 3 lines of diff administrivia
2826
self.assertEqual(lines[4], b"+content B")
2828
def test_unsupported_symlink_diff(self):
2829
self.requireFeature(SymlinkFeature)
2830
tree = self.make_branch_and_tree('.')
2831
self.build_tree_contents([('a', 'content 1')])
2832
tree.set_root_id(b'TREE_ROOT')
2833
tree.add('a', b'a-id')
2834
os.symlink('a', 'foo')
2835
tree.add('foo', b'foo-id')
2836
tree.commit('rev1', rev_id=b'rev1')
2837
revision_tree = tree.branch.repository.revision_tree(b'rev1')
2838
preview = TransformPreview(revision_tree)
2839
self.addCleanup(preview.finalize)
2840
preview.delete_versioned(preview.trans_id_tree_path('foo'))
2841
preview_tree = preview.get_preview_tree()
2844
trace.push_log_file(log)
2845
os_symlink = getattr(os, 'symlink', None)
2848
show_diff_trees(revision_tree, preview_tree, out)
2849
lines = out.getvalue().splitlines()
2851
os.symlink = os_symlink
2852
self.assertContainsRe(
2854
b'Ignoring "foo" as symlinks are not supported on this filesystem')
2753
self.assertEqual(lines[4], "+content B")
2856
2755
def test_transform_conflicts(self):
2857
2756
revision_tree = self.create_tree()
2875
2774
def test_iter_changes(self):
2876
2775
revision_tree, preview_tree = self.get_tree_and_preview_tree()
2877
root = revision_tree.path2id('')
2776
root = revision_tree.get_root_id()
2878
2777
self.assertEqual([(b'a-id', ('a', 'a'), True, (True, True),
2879
(root, root), ('a', 'a'), ('file', 'file'),
2880
(False, False), False)],
2881
list(preview_tree.iter_changes(revision_tree)))
2778
(root, root), ('a', 'a'), ('file', 'file'),
2780
list(preview_tree.iter_changes(revision_tree)))
2883
2782
def test_include_unchanged_succeeds(self):
2884
2783
revision_tree, preview_tree = self.get_tree_and_preview_tree()
2885
2784
changes = preview_tree.iter_changes(revision_tree,
2886
2785
include_unchanged=True)
2786
root = revision_tree.get_root_id()
2887
2788
self.assertEqual([ROOT_ENTRY, A_ENTRY], list(changes))
2889
2790
def test_specific_files(self):
2919
2820
preview = TransformPreview(revision_tree)
2920
2821
self.addCleanup(preview.finalize)
2921
2822
preview.new_file('file', preview.root, [b'contents'], b'file-id')
2922
preview.new_directory('directory', preview.root, b'dir-id')
2823
preview.new_directory('directory', preview.root, 'dir-id')
2923
2824
preview_tree = preview.get_preview_tree()
2924
2825
self.assertEqual('file', preview_tree.kind('file'))
2925
2826
self.assertEqual('directory', preview_tree.kind('directory'))
2942
2843
file_trans_id = preview.trans_id_tree_path('file')
2943
2844
preview.adjust_path('renamed', preview.root, file_trans_id)
2944
2845
preview_tree = preview.get_preview_tree()
2945
preview_mtime = preview_tree.get_file_mtime('renamed')
2946
work_mtime = work_tree.get_file_mtime('file')
2846
preview_mtime = preview_tree.get_file_mtime('renamed', b'file-id')
2847
work_mtime = work_tree.get_file_mtime('file', b'file-id')
2948
2849
def test_get_file_size(self):
2949
2850
work_tree = self.make_branch_and_tree('tree')
2951
2852
work_tree.add('old', b'old-id')
2952
2853
preview = TransformPreview(work_tree)
2953
2854
self.addCleanup(preview.finalize)
2954
preview.new_file('name', preview.root, [b'contents'], b'new-id',
2855
new_id = preview.new_file('name', preview.root, [b'contents'], b'new-id',
2956
2857
tree = preview.get_preview_tree()
2957
2858
self.assertEqual(len('old'), tree.get_file_size('old'))
2958
2859
self.assertEqual(len('contents'), tree.get_file_size('name'))
2967
2868
def test_get_symlink_target(self):
2968
2869
self.requireFeature(SymlinkFeature)
2969
2870
preview = self.get_empty_preview()
2970
preview.new_symlink('symlink', preview.root, 'target', b'symlink-id')
2871
preview.new_symlink('symlink', preview.root, 'target', 'symlink-id')
2971
2872
preview_tree = preview.get_preview_tree()
2972
2873
self.assertEqual('target',
2973
2874
preview_tree.get_symlink_target('symlink'))
3110
3011
def test_file_content_summary_executable(self):
3111
3012
preview = self.get_empty_preview()
3112
path_id = preview.new_file('path', preview.root, [
3113
b'contents'], b'path-id')
3013
path_id = preview.new_file('path', preview.root, [b'contents'], b'path-id')
3114
3014
preview.set_executability(True, path_id)
3115
3015
summary = preview.get_preview_tree().path_content_summary('path')
3116
3016
self.assertEqual(4, len(summary))
3155
3055
def test_tree_content_summary(self):
3156
3056
preview = self.get_empty_preview()
3157
3057
path = preview.new_directory('path', preview.root, b'path-id')
3158
preview.set_tree_reference(b'rev-1', path)
3058
preview.set_tree_reference('rev-1', path)
3159
3059
summary = preview.get_preview_tree().path_content_summary('path')
3160
3060
self.assertEqual(4, len(summary))
3161
3061
self.assertEqual('tree-reference', summary[0])
3283
3179
tree_a = preview.get_preview_tree()
3284
3180
tree_a.set_parent_ids([base_id])
3285
3181
self.assertEqual([
3286
('killed-a', b'a\n'),
3287
('killed-b', b'b\n'),
3288
('unchanged', b'c\n'),
3289
('unchanged', b'd\n'),
3292
], list(tree_a.plan_file_merge('file', tree_b)))
3182
('killed-a', 'a\n'),
3183
('killed-b', 'b\n'),
3184
('unchanged', 'c\n'),
3185
('unchanged', 'd\n'),
3188
], list(tree_a.plan_file_merge(b'file-id', tree_b)))
3294
3190
def test_walkdirs(self):
3295
3191
preview = self.get_empty_preview()
3296
preview.new_directory('', ROOT_PARENT, b'tree-root')
3192
root = preview.new_directory('', ROOT_PARENT, b'tree-root')
3297
3193
# FIXME: new_directory should mark root.
3298
3194
preview.fixup_new_roots()
3299
3195
preview_tree = preview.get_preview_tree()
3300
preview.new_file('a', preview.root, [b'contents'], b'a-id')
3196
file_trans_id = preview.new_file('a', preview.root, [b'contents'],
3301
3198
expected = [(('', b'tree-root'),
3302
[('a', 'a', 'file', None, b'a-id', 'file')])]
3199
[('a', 'a', 'file', None, b'a-id', 'file')])]
3303
3200
self.assertEqual(expected, list(preview_tree.walkdirs()))
3305
3202
def test_extras(self):
3486
3384
attribs[b'_new_parent'] = {b'new-1': b'new-0', b'new-2': b'new-0'}
3487
3385
attribs[b'_new_executability'] = {b'new-1': 1}
3489
(b'new-1', b'file', b'i 1\nbar\n'),
3490
(b'new-2', b'directory', b''),
3387
('new-1', 'file', b'i 1\nbar\n'),
3388
('new-2', 'directory', b''),
3492
3390
return self.make_records(attribs, contents)
3494
3392
def test_serialize_creation(self):
3495
3393
tt = self.get_preview()
3496
3394
tt.new_file(u'foo\u1234', tt.root, [b'bar'], b'baz', True)
3497
tt.new_directory('qux', tt.root, b'quxx')
3395
tt.new_directory('qux', tt.root, 'quxx')
3498
3396
self.assertSerializesTo(self.creation_records(), tt)
3500
3398
def test_deserialize_creation(self):
3503
3401
self.assertEqual(3, tt._id_number)
3504
3402
self.assertEqual({'new-1': u'foo\u1234',
3505
3403
'new-2': 'qux'}, tt._new_name)
3506
self.assertEqual({'new-1': b'baz', 'new-2': b'quxx'}, tt._new_id)
3404
self.assertEqual({'new-1': 'baz', 'new-2': 'quxx'}, tt._new_id)
3507
3405
self.assertEqual({'new-1': tt.root, 'new-2': tt.root}, tt._new_parent)
3508
self.assertEqual({b'baz': 'new-1', b'quxx': 'new-2'}, tt._r_new_id)
3406
self.assertEqual({'baz': 'new-1', 'quxx': 'new-2'}, tt._r_new_id)
3509
3407
self.assertEqual({'new-1': True}, tt._new_executability)
3510
3408
self.assertEqual({'new-1': 'file',
3511
3409
'new-2': 'directory'}, tt._new_contents)
3514
3412
foo_content = foo_limbo.read()
3516
3414
foo_limbo.close()
3517
self.assertEqual(b'bar', foo_content)
3415
self.assertEqual('bar', foo_content)
3519
3417
def symlink_creation_records(self):
3520
3418
attribs = self.default_attribs()
3521
attribs[b'_id_number'] = 2
3522
attribs[b'_new_name'] = {b'new-1': u'foo\u1234'.encode('utf-8')}
3523
attribs[b'_new_parent'] = {b'new-1': b'new-0'}
3524
contents = [(b'new-1', b'symlink', u'bar\u1234'.encode('utf-8'))]
3419
attribs['_id_number'] = 2
3420
attribs['_new_name'] = {'new-1': u'foo\u1234'.encode('utf-8')}
3421
attribs['_new_parent'] = {'new-1': 'new-0'}
3422
contents = [('new-1', 'symlink', u'bar\u1234'.encode('utf-8'))]
3525
3423
return self.make_records(attribs, contents)
3527
3425
def test_serialize_symlink_creation(self):
3547
3445
def destruction_records(self):
3548
3446
attribs = self.default_attribs()
3549
attribs[b'_id_number'] = 3
3550
attribs[b'_removed_id'] = [b'new-1']
3551
attribs[b'_removed_contents'] = [b'new-2']
3552
attribs[b'_tree_path_ids'] = {
3554
u'foo\u1234'.encode('utf-8'): b'new-1',
3447
attribs['_id_number'] = 3
3448
attribs['_removed_id'] = ['new-1']
3449
attribs['_removed_contents'] = ['new-2']
3450
attribs['_tree_path_ids'] = {
3452
u'foo\u1234'.encode('utf-8'): 'new-1',
3557
3455
return self.make_records(attribs, [])
3580
3478
attribs = self.default_attribs()
3581
3479
attribs[b'_id_number'] = 2
3582
3480
attribs[b'_non_present_ids'] = {
3584
3482
return self.make_records(attribs, [])
3586
3484
def test_serialize_missing(self):
3587
3485
tt = self.get_preview()
3588
tt.trans_id_file_id(b'boo')
3486
boo_trans_id = tt.trans_id_file_id(b'boo')
3589
3487
self.assertSerializesTo(self.missing_records(), tt)
3591
3489
def test_deserialize_missing(self):
3592
3490
tt = self.get_preview()
3593
3491
tt.deserialize(iter(self.missing_records()))
3594
self.assertEqual({b'boo': 'new-1'}, tt._non_present_ids)
3492
self.assertEqual({b'boo': b'new-1'}, tt._non_present_ids)
3596
3494
def make_modification_preview(self):
3597
3495
LINES_ONE = b'aa\nbb\ncc\ndd\n'
3599
3497
tree = self.make_branch_and_tree('tree')
3600
3498
self.build_tree_contents([('tree/file', LINES_ONE)])
3601
3499
tree.add('file', b'file-id')
3602
return self.get_preview(tree), [LINES_TWO]
3500
return self.get_preview(tree), LINES_TWO
3604
3502
def modification_records(self):
3605
3503
attribs = self.default_attribs()
3606
attribs[b'_id_number'] = 2
3607
attribs[b'_tree_path_ids'] = {
3610
attribs[b'_removed_contents'] = [b'new-1']
3611
contents = [(b'new-1', b'file',
3612
b'i 1\nz\n\nc 0 1 1 1\ni 1\nx\n\nc 0 3 3 1\n')]
3504
attribs['_id_number'] = 2
3505
attribs['_tree_path_ids'] = {
3508
attribs['_removed_contents'] = ['new-1']
3509
contents = [('new-1', 'file',
3510
'i 1\nz\n\nc 0 1 1 1\ni 1\nx\n\nc 0 3 3 1\n')]
3613
3511
return self.make_records(attribs, contents)
3615
3513
def test_serialize_modification(self):
3622
3520
def test_deserialize_modification(self):
3623
3521
tt, LINES = self.make_modification_preview()
3624
3522
tt.deserialize(iter(self.modification_records()))
3625
self.assertFileEqual(b''.join(LINES), tt._limbo_name('new-1'))
3523
self.assertFileEqual(LINES, tt._limbo_name('new-1'))
3627
3525
def make_kind_change_preview(self):
3628
3526
LINES = b'a\nb\nc\nd\n'
3629
3527
tree = self.make_branch_and_tree('tree')
3630
3528
self.build_tree(['tree/foo/'])
3631
3529
tree.add('foo', b'foo-id')
3632
return self.get_preview(tree), [LINES]
3530
return self.get_preview(tree), LINES
3634
3532
def kind_change_records(self):
3635
3533
attribs = self.default_attribs()
3636
3534
attribs[b'_id_number'] = 2
3637
3535
attribs[b'_tree_path_ids'] = {
3638
3536
b'foo': b'new-1',
3640
3538
attribs[b'_removed_contents'] = [b'new-1']
3641
contents = [(b'new-1', b'file',
3539
contents = [('new-1', 'file',
3642
3540
b'i 4\na\nb\nc\nd\n\n')]
3643
3541
return self.make_records(attribs, contents)
3686
3584
def test_get_parents_lines(self):
3687
3585
LINES_ONE = b'aa\nbb\ncc\ndd\n'
3586
LINES_TWO = b'z\nbb\nx\ndd\n'
3688
3587
tree = self.make_branch_and_tree('tree')
3689
3588
self.build_tree_contents([('tree/file', LINES_ONE)])
3690
3589
tree.add('file', b'file-id')
3691
3590
tt = self.get_preview(tree)
3692
3591
trans_id = tt.trans_id_tree_path('file')
3693
3592
self.assertEqual(([b'aa\n', b'bb\n', b'cc\n', b'dd\n'],),
3694
tt._get_parents_lines(trans_id))
3593
tt._get_parents_lines(trans_id))
3696
3595
def test_get_parents_texts(self):
3697
3596
LINES_ONE = b'aa\nbb\ncc\ndd\n'
3597
LINES_TWO = b'z\nbb\nx\ndd\n'
3698
3598
tree = self.make_branch_and_tree('tree')
3699
3599
self.build_tree_contents([('tree/file', LINES_ONE)])
3700
3600
tree.add('file', b'file-id')
3701
3601
tt = self.get_preview(tree)
3702
3602
trans_id = tt.trans_id_tree_path('file')
3703
3603
self.assertEqual((LINES_ONE,),
3704
tt._get_parents_texts(trans_id))
3604
tt._get_parents_texts(trans_id))
3707
3607
class TestOrphan(tests.TestCaseWithTransport):
3741
3641
self._set_orphan_policy(wt, 'move')
3742
3642
tt, orphan_tid = self._prepare_orphan(wt)
3745
3644
def warning(*args):
3746
3645
warnings.append(args[0] % args[1:])
3747
3646
self.overrideAttr(trace, 'warning', warning)
3748
3647
remaining_conflicts = resolve_conflicts(tt)
3749
3648
self.assertEqual(['dir/foo has been orphaned in brz-orphans'],
3751
3650
# Yeah for resolved conflicts !
3752
3651
self.assertLength(0, remaining_conflicts)
3753
3652
# We have a new orphan
3754
3653
self.assertEqual('foo.~1~', tt.final_name(orphan_tid))
3755
3654
self.assertEqual('brz-orphans',
3756
tt.final_name(tt.final_parent(orphan_tid)))
3655
tt.final_name(tt.final_parent(orphan_tid)))
3758
3657
def test_never_orphan(self):
3759
3658
wt = self.make_branch_and_tree('.')
3812
3710
def test_pre_commit_hooks(self):
3815
3712
def record_pre_transform(tree, tt):
3816
3713
calls.append((tree, tt))
3817
MutableTree.hooks.install_named_hook(
3818
'pre_transform', record_pre_transform, "Pre transform")
3714
MutableTree.hooks.install_named_hook('pre_transform',
3715
record_pre_transform, "Pre transform")
3819
3716
transform, root = self.get_transform()
3820
3717
old_root_id = transform.tree_file_id(root)
3821
3718
transform.apply()
3822
self.assertEqual(old_root_id, self.wt.path2id(''))
3719
self.assertEqual(old_root_id, self.wt.get_root_id())
3823
3720
self.assertEqual([(self.wt, transform)], calls)
3825
3722
def test_post_commit_hooks(self):
3828
3724
def record_post_transform(tree, tt):
3829
3725
calls.append((tree, tt))
3830
MutableTree.hooks.install_named_hook(
3831
'post_transform', record_post_transform, "Post transform")
3726
MutableTree.hooks.install_named_hook('post_transform',
3727
record_post_transform, "Post transform")
3832
3728
transform, root = self.get_transform()
3833
3729
old_root_id = transform.tree_file_id(root)
3834
3730
transform.apply()
3835
self.assertEqual(old_root_id, self.wt.path2id(''))
3731
self.assertEqual(old_root_id, self.wt.get_root_id())
3836
3732
self.assertEqual([(self.wt, transform)], calls)