99
99
self.wt = self.make_branch_and_tree('.', format='development-subtree')
102
def get_transform(self):
103
103
transform = TreeTransform(self.wt)
104
104
self.addCleanup(transform.finalize)
105
105
return transform, transform.root
107
def get_transform_for_sha1_test(self):
108
trans, root = self.get_transform()
107
def transform_for_sha1_test(self):
108
trans, root = self.transform()
109
109
self.wt.lock_tree_write()
110
110
self.addCleanup(self.wt.unlock)
111
111
contents = [b'just some content\n']
115
115
return trans, root, contents, sha1
117
117
def test_existing_limbo(self):
118
transform, root = self.get_transform()
118
transform, root = self.transform()
119
119
limbo_name = transform._limbodir
120
120
deletion_path = transform._deletiondir
121
121
os.mkdir(pathjoin(limbo_name, 'hehe'))
122
122
self.assertRaises(ImmortalLimbo, transform.apply)
123
123
self.assertRaises(LockError, self.wt.unlock)
124
self.assertRaises(ExistingLimbo, self.get_transform)
124
self.assertRaises(ExistingLimbo, self.transform)
125
125
self.assertRaises(LockError, self.wt.unlock)
126
126
os.rmdir(pathjoin(limbo_name, 'hehe'))
127
127
os.rmdir(limbo_name)
128
128
os.rmdir(deletion_path)
129
transform, root = self.get_transform()
129
transform, root = self.transform()
130
130
transform.apply()
132
132
def test_existing_pending_deletion(self):
133
transform, root = self.get_transform()
133
transform, root = self.transform()
134
134
deletion_path = self._limbodir = urlutils.local_path_from_url(
135
135
transform._tree._transport.abspath('pending-deletion'))
136
136
os.mkdir(pathjoin(deletion_path, 'blocking-directory'))
137
137
self.assertRaises(ImmortalPendingDeletion, transform.apply)
138
138
self.assertRaises(LockError, self.wt.unlock)
139
self.assertRaises(ExistingPendingDeletion, self.get_transform)
139
self.assertRaises(ExistingPendingDeletion, self.transform)
141
141
def test_build(self):
142
transform, root = self.get_transform()
142
transform, root = self.transform()
143
143
self.wt.lock_tree_write()
144
144
self.addCleanup(self.wt.unlock)
145
145
self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
184
184
transform.finalize()
186
186
def test_apply_informs_tree_of_observed_sha1(self):
187
trans, root, contents, sha1 = self.get_transform_for_sha1_test()
187
trans, root, contents, sha1 = self.transform_for_sha1_test()
188
188
trans_id = trans.new_file('file1', root, contents, file_id=b'file1-id',
201
201
def test_create_file_caches_sha1(self):
202
trans, root, contents, sha1 = self.get_transform_for_sha1_test()
202
trans, root, contents, sha1 = self.transform_for_sha1_test()
203
203
trans_id = trans.create_path('file1', root)
204
204
trans.create_file(contents, trans_id, sha1=sha1)
205
205
st_val = osutils.lstat(trans._limbo_name(trans_id))
208
208
self.assertEqualStat(o_st_val, st_val)
210
210
def test__apply_insertions_updates_sha1(self):
211
trans, root, contents, sha1 = self.get_transform_for_sha1_test()
211
trans, root, contents, sha1 = self.transform_for_sha1_test()
212
212
trans_id = trans.create_path('file1', root)
213
213
trans.create_file(contents, trans_id, sha1=sha1)
214
214
st_val = osutils.lstat(trans._limbo_name(trans_id))
229
229
self.assertNotEqual(st_val.st_mtime, new_st_val.st_mtime)
231
231
def test_new_file_caches_sha1(self):
232
trans, root, contents, sha1 = self.get_transform_for_sha1_test()
232
trans, root, contents, sha1 = self.transform_for_sha1_test()
233
233
trans_id = trans.new_file('file1', root, contents, file_id=b'file1-id',
235
235
st_val = osutils.lstat(trans._limbo_name(trans_id))
238
238
self.assertEqualStat(o_st_val, st_val)
240
240
def test_cancel_creation_removes_observed_sha1(self):
241
trans, root, contents, sha1 = self.get_transform_for_sha1_test()
241
trans, root, contents, sha1 = self.transform_for_sha1_test()
242
242
trans_id = trans.new_file('file1', root, contents, file_id=b'file1-id',
244
244
self.assertTrue(trans_id in trans._observed_sha1s)
246
246
self.assertFalse(trans_id in trans._observed_sha1s)
248
248
def test_create_files_same_timestamp(self):
249
transform, root = self.get_transform()
249
transform, root = self.transform()
250
250
self.wt.lock_tree_write()
251
251
self.addCleanup(self.wt.unlock)
252
252
# Roll back the clock, so that we know everything is being set to the
270
270
self.assertEqual(st1.st_mtime, st2.st_mtime)
272
272
def test_change_root_id(self):
273
transform, root = self.get_transform()
273
transform, root = self.transform()
274
274
self.assertNotEqual(b'new-root-id', self.wt.path2id(''))
275
275
transform.new_directory('', ROOT_PARENT, b'new-root-id')
276
276
transform.delete_contents(root)
280
280
self.assertEqual(b'new-root-id', self.wt.path2id(''))
282
282
def test_change_root_id_add_files(self):
283
transform, root = self.get_transform()
283
transform, root = self.transform()
284
284
self.assertNotEqual(b'new-root-id', self.wt.path2id(''))
285
285
new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
286
286
transform.new_file('file', new_trans_id, [b'new-contents\n'],
294
294
self.assertFileEqual(b'new-contents\n', self.wt.abspath('file'))
296
296
def test_add_two_roots(self):
297
transform, root = self.get_transform()
297
transform, root = self.transform()
298
298
transform.new_directory('', ROOT_PARENT, b'new-root-id')
299
299
transform.new_directory('', ROOT_PARENT, b'alt-root-id')
300
300
self.assertRaises(ValueError, transform.fixup_new_roots)
302
302
def test_retain_existing_root(self):
303
tt, root = self.get_transform()
303
tt, root = self.transform()
305
305
tt.new_directory('', ROOT_PARENT, b'new-root-id')
306
306
tt.fixup_new_roots()
307
307
self.assertNotEqual(b'new-root-id', tt.final_file_id(tt.root))
309
309
def test_retain_existing_root_added_file(self):
310
tt, root = self.get_transform()
310
tt, root = self.transform()
311
311
new_trans_id = tt.new_directory('', ROOT_PARENT, b'new-root-id')
312
312
child = tt.new_directory('child', new_trans_id, b'child-id')
313
313
tt.fixup_new_roots()
314
314
self.assertEqual(tt.root, tt.final_parent(child))
316
316
def test_add_unversioned_root(self):
317
transform, root = self.get_transform()
317
transform, root = self.transform()
318
318
transform.new_directory('', ROOT_PARENT, None)
319
319
transform.delete_contents(transform.root)
320
320
transform.fixup_new_roots()
321
321
self.assertNotIn(transform.root, transform._new_id)
323
323
def test_remove_root_fixup(self):
324
transform, root = self.get_transform()
324
transform, root = self.transform()
325
325
old_root_id = self.wt.path2id('')
326
326
self.assertNotEqual(b'new-root-id', old_root_id)
327
327
transform.delete_contents(root)
330
330
transform.apply()
331
331
self.assertEqual(old_root_id, self.wt.path2id(''))
333
transform, root = self.get_transform()
333
transform, root = self.transform()
334
334
transform.new_directory('', ROOT_PARENT, b'new-root-id')
335
335
transform.new_directory('', ROOT_PARENT, b'alt-root-id')
336
336
self.assertRaises(ValueError, transform.fixup_new_roots)
338
338
def test_fixup_new_roots_permits_empty_tree(self):
339
transform, root = self.get_transform()
339
transform, root = self.transform()
340
340
transform.delete_contents(root)
341
341
transform.unversion_file(root)
342
342
transform.fixup_new_roots()
346
346
def test_apply_retains_root_directory(self):
347
347
# Do not attempt to delete the physical root directory, because that
349
transform, root = self.get_transform()
349
transform, root = self.transform()
351
351
transform.delete_contents(root)
352
352
e = self.assertRaises(AssertionError, self.assertRaises,
355
355
self.assertContainsRe('TransformRenameFailed not raised', str(e))
357
357
def test_apply_retains_file_id(self):
358
transform, root = self.get_transform()
358
transform, root = self.transform()
359
359
old_root_id = transform.tree_file_id(root)
360
360
transform.unversion_file(root)
361
361
transform.apply()
364
364
def test_hardlink(self):
365
365
self.requireFeature(HardlinkFeature)
366
transform, root = self.get_transform()
366
transform, root = self.transform()
367
367
transform.new_file('file1', root, [b'contents'])
368
368
transform.apply()
369
369
target = self.make_branch_and_tree('target')
377
377
self.assertEqual(source_stat, target_stat)
379
379
def test_convenience(self):
380
transform, root = self.get_transform()
380
transform, root = self.transform()
381
381
self.wt.lock_tree_write()
382
382
self.addCleanup(self.wt.unlock)
383
383
transform.new_file('name', root, [b'contents'], b'my_pretties', True)
402
402
self.assertIs(self.wt.is_executable('oz/dorothy/toto'), False)
404
404
def test_tree_reference(self):
405
transform, root = self.get_transform()
405
transform, root = self.transform()
406
406
tree = transform._tree
407
407
trans_id = transform.new_directory('reference', root, b'subtree-id')
408
408
transform.set_tree_reference(b'subtree-revision', trans_id)
414
414
tree.root_inventory.get_entry(b'subtree-id').reference_revision)
416
416
def test_conflicts(self):
417
transform, root = self.get_transform()
417
transform, root = self.transform()
418
418
trans_id = transform.new_file('name', root, [b'contents'],
420
420
self.assertEqual(len(transform.find_conflicts()), 0)
464
464
self.assertEqual(self.wt.path2id('name'), b'my_pretties')
465
465
with open(self.wt.abspath('name'), 'rb') as f:
466
466
self.assertEqual(b'contents', f.read())
467
transform2, root = self.get_transform()
467
transform2, root = self.transform()
468
468
oz_id = transform2.trans_id_tree_path('oz')
469
469
newtip = transform2.new_file('tip', oz_id, [b'other'], b'tip-id')
470
470
result = transform2.find_conflicts()
609
609
transform._limbo_name(bar_id))
611
611
def test_add_del(self):
612
start, root = self.get_transform()
612
start, root = self.transform()
613
613
start.new_directory('a', root, b'a')
615
transform, root = self.get_transform()
615
transform, root = self.transform()
616
616
transform.delete_versioned(transform.trans_id_tree_path('a'))
617
617
transform.new_directory('a', root, b'a')
618
618
transform.apply()
620
620
def test_unversioning(self):
621
create_tree, root = self.get_transform()
621
create_tree, root = self.transform()
622
622
parent_id = create_tree.new_directory('parent', root, b'parent-id')
623
623
create_tree.new_file('child', parent_id, [b'child'], b'child-id')
624
624
create_tree.apply()
688
688
mfile2_path = self.wt.abspath(pathjoin('new_directory', 'mfile2'))
690
690
def test_both_rename(self):
691
create_tree, root = self.get_transform()
691
create_tree, root = self.transform()
692
692
newdir = create_tree.new_directory('selftest', root, b'selftest-id')
693
693
create_tree.new_file('blackbox.py', newdir, [
694
694
b'hello1'], b'blackbox-id')
695
695
create_tree.apply()
696
mangle_tree, root = self.get_transform()
696
mangle_tree, root = self.transform()
697
697
selftest = mangle_tree.trans_id_tree_path('selftest')
698
698
blackbox = mangle_tree.trans_id_tree_path('selftest/blackbox.py')
699
699
mangle_tree.adjust_path('test', root, selftest)
702
702
mangle_tree.apply()
704
704
def test_both_rename2(self):
705
create_tree, root = self.get_transform()
705
create_tree, root = self.transform()
706
706
breezy = create_tree.new_directory('breezy', root, b'breezy-id')
707
707
tests = create_tree.new_directory('tests', breezy, b'tests-id')
708
708
blackbox = create_tree.new_directory('blackbox', tests, b'blackbox-id')
709
709
create_tree.new_file('test_too_much.py', blackbox, [b'hello1'],
710
710
b'test_too_much-id')
711
711
create_tree.apply()
712
mangle_tree, root = self.get_transform()
712
mangle_tree, root = self.transform()
713
713
breezy = mangle_tree.trans_id_tree_path('breezy')
714
714
tests = mangle_tree.trans_id_tree_path('breezy/tests')
715
715
test_too_much = mangle_tree.trans_id_tree_path(
720
720
mangle_tree.apply()
722
722
def test_both_rename3(self):
723
create_tree, root = self.get_transform()
723
create_tree, root = self.transform()
724
724
tests = create_tree.new_directory('tests', root, b'tests-id')
725
725
create_tree.new_file('test_too_much.py', tests, [b'hello1'],
726
726
b'test_too_much-id')
727
727
create_tree.apply()
728
mangle_tree, root = self.get_transform()
728
mangle_tree, root = self.transform()
729
729
tests = mangle_tree.trans_id_tree_path('tests')
730
730
test_too_much = mangle_tree.trans_id_tree_path(
731
731
'tests/test_too_much.py')
735
735
mangle_tree.apply()
737
737
def test_move_dangling_ie(self):
738
create_tree, root = self.get_transform()
738
create_tree, root = self.transform()
740
740
root = create_tree.root
741
741
create_tree.new_file('name1', root, [b'hello1'], b'name1')
742
742
create_tree.apply()
743
delete_contents, root = self.get_transform()
743
delete_contents, root = self.transform()
744
744
file = delete_contents.trans_id_tree_path('name1')
745
745
delete_contents.delete_contents(file)
746
746
delete_contents.apply()
747
move_id, root = self.get_transform()
747
move_id, root = self.transform()
748
748
name1 = move_id.trans_id_tree_path('name1')
749
749
newdir = move_id.new_directory('dir', root, b'newdir')
750
750
move_id.adjust_path('name2', newdir, name1)
753
753
def test_replace_dangling_ie(self):
754
create_tree, root = self.get_transform()
754
create_tree, root = self.transform()
756
756
root = create_tree.root
757
757
create_tree.new_file('name1', root, [b'hello1'], b'name1')
780
780
self.requireFeature(SymlinkFeature)
781
transform, root = self.get_transform()
781
transform, root = self.transform()
782
782
oz_id = transform.new_directory('oz', root, b'oz-id')
783
783
transform.new_symlink(link_name1, oz_id, link_target1, b'wizard-id')
784
784
wiz_id = transform.create_path(link_name2, oz_id)
825
825
os.symlink = os_symlink
827
827
def get_conflicted(self):
828
create, root = self.get_transform()
828
create, root = self.transform()
829
829
create.new_file('dorothy', root, [b'dorothy'], b'dorothy-id')
830
830
oz = create.new_directory('oz', root, b'oz-id')
831
831
create.new_directory('emeraldcity', oz, b'emerald-id')
833
conflicts, root = self.get_transform()
833
conflicts, root = self.transform()
834
834
# set up duplicate entry, duplicate id
835
835
new_dorothy = conflicts.new_file('dorothy', root, [b'dorothy'],
916
916
' oz/emeraldcity. Cancelled move.')
918
918
def prepare_wrong_parent_kind(self):
919
tt, root = self.get_transform()
919
tt, root = self.transform()
920
920
tt.new_file('parent', root, [b'contents'], b'parent-id')
922
tt, root = self.get_transform()
922
tt, root = self.transform()
923
923
parent_id = tt.trans_id_file_id(b'parent-id')
924
924
tt.new_file('child,', parent_id, [b'contents2'], b'file-id')
941
941
self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
943
943
def test_resolve_conflicts_wrong_new_parent_kind(self):
944
tt, root = self.get_transform()
944
tt, root = self.transform()
945
945
parent_id = tt.new_directory('parent', root, b'parent-id')
946
946
tt.new_file('child,', parent_id, [b'contents2'], b'file-id')
948
tt, root = self.get_transform()
948
tt, root = self.transform()
949
949
parent_id = tt.trans_id_file_id(b'parent-id')
950
950
tt.delete_contents(parent_id)
951
951
tt.create_file([b'contents'], parent_id)
957
957
self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
959
959
def test_resolve_conflicts_wrong_parent_kind_unversioned(self):
960
tt, root = self.get_transform()
960
tt, root = self.transform()
961
961
parent_id = tt.new_directory('parent', root)
962
962
tt.new_file('child,', parent_id, [b'contents2'])
964
tt, root = self.get_transform()
964
tt, root = self.transform()
965
965
parent_id = tt.trans_id_tree_path('parent')
966
966
tt.delete_contents(parent_id)
967
967
tt.create_file([b'contents'], parent_id)
986
986
self.assertRaises(NoFinalPath, tt.apply)
988
988
def test_moving_versioned_directories(self):
989
create, root = self.get_transform()
989
create, root = self.transform()
990
990
kansas = create.new_directory('kansas', root, b'kansas-id')
991
991
create.new_directory('house', kansas, b'house-id')
992
992
create.new_directory('oz', root, b'oz-id')
994
cyclone, root = self.get_transform()
994
cyclone, root = self.transform()
995
995
oz = cyclone.trans_id_tree_path('oz')
996
996
house = cyclone.trans_id_tree_path('house')
997
997
cyclone.adjust_path('house', oz, house)
1000
1000
def test_moving_root(self):
1001
create, root = self.get_transform()
1001
create, root = self.transform()
1002
1002
fun = create.new_directory('fun', root, b'fun-id')
1003
1003
create.new_directory('sun', root, b'sun-id')
1004
1004
create.new_directory('moon', root, b'moon')
1006
transform, root = self.get_transform()
1006
transform, root = self.transform()
1007
1007
transform.adjust_root_path('oldroot', fun)
1008
1008
new_root = transform.trans_id_tree_path('')
1009
1009
transform.version_file(b'new-root', new_root)
1010
1010
transform.apply()
1012
1012
def test_renames(self):
1013
create, root = self.get_transform()
1013
create, root = self.transform()
1014
1014
old = create.new_directory('old-parent', root, b'old-id')
1015
1015
intermediate = create.new_directory('intermediate', old, b'im-id')
1016
1016
myfile = create.new_file('myfile', intermediate, [b'myfile-text'],
1019
rename, root = self.get_transform()
1019
rename, root = self.transform()
1020
1020
old = rename.trans_id_file_id(b'old-id')
1021
1021
rename.adjust_path('new', root, old)
1022
1022
myfile = rename.trans_id_file_id(b'myfile-id')
1026
1026
def test_rename_fails(self):
1027
1027
self.requireFeature(features.not_running_as_root)
1028
1028
# see https://bugs.launchpad.net/bzr/+bug/491763
1029
create, root_id = self.get_transform()
1029
create, root_id = self.transform()
1030
1030
create.new_directory('first-dir', root_id, b'first-id')
1031
1031
create.new_file('myfile', root_id, [b'myfile-text'], b'myfile-id')
1040
1040
self.skipTest("Can't force a permissions error on rename")
1041
1041
# now transform to rename
1042
rename_transform, root_id = self.get_transform()
1042
rename_transform, root_id = self.transform()
1043
1043
file_trans_id = rename_transform.trans_id_file_id(b'myfile-id')
1044
1044
dir_id = rename_transform.trans_id_file_id(b'first-id')
1045
1045
rename_transform.adjust_path('newname', dir_id, file_trans_id)
1090
1090
"""File mode is preserved when replacing content"""
1091
1091
if sys.platform == 'win32':
1092
1092
raise TestSkipped('chmod has no effect on win32')
1093
transform, root = self.get_transform()
1093
transform, root = self.transform()
1094
1094
transform.new_file('file1', root, [b'contents'], b'file1-id', True)
1095
1095
transform.apply()
1096
1096
self.wt.lock_write()
1097
1097
self.addCleanup(self.wt.unlock)
1098
1098
self.assertTrue(self.wt.is_executable('file1'))
1099
transform, root = self.get_transform()
1099
transform, root = self.transform()
1100
1100
file1_id = transform.trans_id_tree_path('file1')
1101
1101
transform.delete_contents(file1_id)
1102
1102
transform.create_file([b'contents2'], file1_id)
1115
1115
stat_paths.append(path)
1116
1116
return real_stat(path)
1118
transform, root = self.get_transform()
1118
transform, root = self.transform()
1120
1120
bar1_id = transform.new_file('bar', root, [b'bar contents 1\n'],
1121
1121
file_id=b'bar-id-1', executable=False)
1122
1122
transform.apply()
1124
transform, root = self.get_transform()
1124
transform, root = self.transform()
1125
1125
bar1_id = transform.trans_id_tree_path('bar')
1126
1126
bar2_id = transform.trans_id_tree_path('bar2')
1138
1138
def test_iter_changes(self):
1139
1139
self.wt.set_root_id(b'eert_toor')
1140
transform, root = self.get_transform()
1140
transform, root = self.transform()
1141
1141
transform.new_file('old', root, [b'blah'], b'id-1', True)
1142
1142
transform.apply()
1143
transform, root = self.get_transform()
1143
transform, root = self.transform()
1145
1145
self.assertEqual([], list(transform.iter_changes()))
1146
1146
old = transform.trans_id_tree_path('old')
1162
1162
def test_iter_changes_new(self):
1163
1163
self.wt.set_root_id(b'eert_toor')
1164
transform, root = self.get_transform()
1164
transform, root = self.transform()
1165
1165
transform.new_file('old', root, [b'blah'])
1166
1166
transform.apply()
1167
transform, root = self.get_transform()
1167
transform, root = self.transform()
1169
1169
old = transform.trans_id_tree_path('old')
1170
1170
transform.version_file(b'id-1', old)
1179
1179
def test_iter_changes_modifications(self):
1180
1180
self.wt.set_root_id(b'eert_toor')
1181
transform, root = self.get_transform()
1181
transform, root = self.transform()
1182
1182
transform.new_file('old', root, [b'blah'], b'id-1')
1183
1183
transform.new_file('new', root, [b'blah'])
1184
1184
transform.new_directory('subdir', root, b'subdir-id')
1185
1185
transform.apply()
1186
transform, root = self.get_transform()
1186
transform, root = self.transform()
1188
1188
old = transform.trans_id_tree_path('old')
1189
1189
subdir = transform.trans_id_tree_path('subdir')
1268
1268
# will be applied before file2. And if it's applied after file2, it
1269
1269
# obviously can't bleed into file2's change output. But for now, it
1271
transform, root = self.get_transform()
1271
transform, root = self.transform()
1272
1272
transform.new_file('file1', root, [b'blah'], b'id-1')
1273
1273
transform.new_file('file2', root, [b'blah'], b'id-2')
1274
1274
transform.apply()
1275
transform, root = self.get_transform()
1275
transform, root = self.transform()
1277
1277
transform.delete_contents(transform.trans_id_file_id(b'id-1'))
1278
1278
transform.set_executability(True,
1292
1292
"""Test moving ids with no files around"""
1293
1293
self.wt.set_root_id(b'toor_eert')
1294
1294
# Need two steps because versioning a non-existant file is a conflict.
1295
transform, root = self.get_transform()
1295
transform, root = self.transform()
1296
1296
transform.new_directory('floater', root, b'floater-id')
1297
1297
transform.apply()
1298
transform, root = self.get_transform()
1298
transform, root = self.transform()
1299
1299
transform.delete_contents(transform.trans_id_tree_path('floater'))
1300
1300
transform.apply()
1301
transform, root = self.get_transform()
1301
transform, root = self.transform()
1302
1302
floater = transform.trans_id_tree_path('floater')
1304
1304
transform.adjust_path('flitter', root, floater)
1314
1314
def test_iter_changes_pointless(self):
1315
1315
"""Ensure that no-ops are not treated as modifications"""
1316
1316
self.wt.set_root_id(b'eert_toor')
1317
transform, root = self.get_transform()
1317
transform, root = self.transform()
1318
1318
transform.new_file('old', root, [b'blah'], b'id-1')
1319
1319
transform.new_directory('subdir', root, b'subdir-id')
1320
1320
transform.apply()
1321
transform, root = self.get_transform()
1321
transform, root = self.transform()
1323
1323
old = transform.trans_id_tree_path('old')
1324
1324
subdir = transform.trans_id_tree_path('subdir')
1334
1334
transform.finalize()
1336
1336
def test_rename_count(self):
1337
transform, root = self.get_transform()
1337
transform, root = self.transform()
1338
1338
transform.new_file('name1', root, [b'contents'])
1339
1339
self.assertEqual(transform.rename_count, 0)
1340
1340
transform.apply()
1341
1341
self.assertEqual(transform.rename_count, 1)
1342
transform2, root = self.get_transform()
1342
transform2, root = self.transform()
1343
1343
transform2.adjust_path('name2', root,
1344
1344
transform2.trans_id_tree_path('name1'))
1345
1345
self.assertEqual(transform2.rename_count, 0)
1356
1356
This test ensures they work correctly with the rename-avoidance
1359
transform, root = self.get_transform()
1359
transform, root = self.transform()
1360
1360
parent1 = transform.new_directory('parent1', root)
1361
1361
child1 = transform.new_file('child1', parent1, [b'contents'])
1362
1362
parent2 = transform.new_directory('parent2', root)
1375
1375
before adjusting the path. The transform must detect that the
1376
1376
directory is non-empty, and move children to safe locations.
1378
transform, root = self.get_transform()
1378
transform, root = self.transform()
1379
1379
parent1 = transform.new_directory('parent1', root)
1380
1380
child1 = transform.new_file('child1', parent1, [b'contents'])
1381
1381
child2 = transform.new_file('child2', parent1, [b'contents'])
1403
1403
def test_adjust_and_cancel(self):
1404
1404
"""Make sure adjust_path keeps track of limbo children properly"""
1405
transform, root = self.get_transform()
1405
transform, root = self.transform()
1406
1406
parent1 = transform.new_directory('parent1', root)
1407
1407
child1 = transform.new_file('child1', parent1, [b'contents'])
1408
1408
parent2 = transform.new_directory('parent2', root)
1419
1419
def test_noname_contents(self):
1420
1420
"""TreeTransform should permit deferring naming files."""
1421
transform, root = self.get_transform()
1421
transform, root = self.transform()
1422
1422
parent = transform.trans_id_file_id(b'parent-id')
1424
1424
transform.create_directory(parent)
1429
1429
def test_noname_contents_nested(self):
1430
1430
"""TreeTransform should permit deferring naming files."""
1431
transform, root = self.get_transform()
1431
transform, root = self.transform()
1432
1432
parent = transform.trans_id_file_id(b'parent-id')
1434
1434
transform.create_directory(parent)
1443
1443
def test_reuse_name(self):
1444
1444
"""Avoid reusing the same limbo name for different files"""
1445
transform, root = self.get_transform()
1445
transform, root = self.transform()
1446
1446
parent = transform.new_directory('parent', root)
1447
1447
transform.new_directory('child', parent)
1461
1461
def test_reuse_when_first_moved(self):
1462
1462
"""Don't avoid direct paths when it is safe to use them"""
1463
transform, root = self.get_transform()
1463
transform, root = self.transform()
1464
1464
parent = transform.new_directory('parent', root)
1465
1465
child1 = transform.new_directory('child', parent)
1466
1466
transform.adjust_path('child1', parent, child1)
1472
1472
def test_reuse_after_cancel(self):
1473
1473
"""Don't avoid direct paths when it is safe to use them"""
1474
transform, root = self.get_transform()
1474
transform, root = self.transform()
1475
1475
parent2 = transform.new_directory('parent2', root)
1476
1476
child1 = transform.new_directory('child1', parent2)
1477
1477
transform.cancel_creation(parent2)
1485
1485
def test_finalize_order(self):
1486
1486
"""Finalize must be done in child-to-parent order"""
1487
transform, root = self.get_transform()
1487
transform, root = self.transform()
1488
1488
parent = transform.new_directory('parent', root)
1489
1489
transform.new_directory('child', parent)
1493
1493
self.fail('Tried to remove parent before child1')
1495
1495
def test_cancel_with_cancelled_child_should_succeed(self):
1496
transform, root = self.get_transform()
1496
transform, root = self.transform()
1497
1497
parent = transform.new_directory('parent', root)
1498
1498
child = transform.new_directory('child', parent)
1499
1499
transform.cancel_creation(child)
1656
1656
self.assertEqual(wt.kind("foo"), "file")
1658
1658
def test_no_final_path(self):
1659
transform, root = self.get_transform()
1659
transform, root = self.transform()
1660
1660
trans_id = transform.trans_id_file_id(b'foo')
1661
1661
transform.create_file([b'bar'], trans_id)
1662
1662
transform.cancel_creation(trans_id)
1723
1723
tree = self.make_branch_and_tree('tree')
1724
1724
self.build_tree(['tree/foo'])
1725
1725
tree.add('foo', b'foo-id')
1726
with TransformPreview(tree) as tt:
1726
with tree.preview_transform() as tt:
1727
1727
self.assertEqual([], tt._inventory_altered())
1729
1729
def test_inventory_altered_changed_parent_id(self):
1730
1730
tree = self.make_branch_and_tree('tree')
1731
1731
self.build_tree(['tree/foo'])
1732
1732
tree.add('foo', b'foo-id')
1733
with TransformPreview(tree) as tt:
1733
with tree.preview_transform() as tt:
1734
1734
tt.unversion_file(tt.root)
1735
1735
tt.version_file(b'new-id', tt.root)
1736
1736
foo_trans_id = tt.trans_id_tree_path('foo')
1742
1742
tree = self.make_branch_and_tree('tree')
1743
1743
self.build_tree(['tree/foo'])
1744
1744
tree.add('foo', b'foo-id')
1745
with TransformPreview(tree) as tt:
1745
with tree.preview_transform() as tt:
1746
1746
tt.unversion_file(tt.root)
1747
1747
tt.version_file(tree.path2id(''), tt.root)
1748
1748
tt.trans_id_tree_path('foo')
2363
2363
branch = self.get_branch()
2364
2364
basis = branch.repository.revision_tree(
2365
2365
_mod_revision.NULL_REVISION)
2366
tt = TransformPreview(basis)
2366
tt = basis.preview_transform()
2367
2367
self.addCleanup(tt.finalize)
2368
2368
e = self.assertRaises(ValueError, tt.commit, branch, '')
2369
2369
self.assertEqual('TreeTransform not based on branch basis: null:',
2386
2386
branch = self.make_branch('branch')
2387
2387
branch.lock_write()
2388
2388
self.addCleanup(branch.unlock)
2389
tt = TransformPreview(branch.basis_tree())
2389
tt = branch.basis_tree().preview_transform()
2390
2390
self.addCleanup(tt.finalize)
2391
2391
tt.new_directory('', ROOT_PARENT, b'TREE_ROOT')
2392
2392
tt.commit(branch, 'my message')
2398
2398
branch = self.make_branch('branch')
2399
2399
branch.lock_write()
2400
2400
self.addCleanup(branch.unlock)
2401
tt = TransformPreview(branch.basis_tree())
2401
tt = branch.basis_tree().preview_transform()
2402
2402
self.addCleanup(tt.finalize)
2403
2403
e = self.assertRaises(ValueError, tt.commit, branch,
2404
2404
'my message', [b'rev1b-id'])
2431
2431
branch, tt = self.get_branch_and_transform()
2432
2432
tt.new_file('file', tt.root, [b'contents'], b'file-id')
2433
2433
tt.commit(branch, 'message', strict=True)
2434
tt = TransformPreview(branch.basis_tree())
2434
tt = branch.basis_tree().preview_transform()
2435
2435
self.addCleanup(tt.finalize)
2436
2436
trans_id = tt.trans_id_file_id(b'file-id')
2437
2437
tt.delete_contents(trans_id)
2788
2788
def get_empty_preview(self):
2789
2789
repository = self.make_repository('repo')
2790
2790
tree = repository.revision_tree(_mod_revision.NULL_REVISION)
2791
preview = TransformPreview(tree)
2791
preview = tree.preview_transform()
2792
2792
self.addCleanup(preview.finalize)
2795
2795
def test_transform_preview(self):
2796
2796
revision_tree = self.create_tree()
2797
preview = TransformPreview(revision_tree)
2797
preview = revision_tree.preview_transform()
2798
2798
self.addCleanup(preview.finalize)
2800
2800
def test_transform_preview_tree(self):
2801
2801
revision_tree = self.create_tree()
2802
preview = TransformPreview(revision_tree)
2802
preview = revision_tree.preview_transform()
2803
2803
self.addCleanup(preview.finalize)
2804
2804
preview.get_preview_tree()
2806
2806
def test_transform_new_file(self):
2807
2807
revision_tree = self.create_tree()
2808
preview = TransformPreview(revision_tree)
2808
preview = revision_tree.preview_transform()
2809
2809
self.addCleanup(preview.finalize)
2810
2810
preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id')
2811
2811
preview_tree = preview.get_preview_tree()
2816
2816
def test_diff_preview_tree(self):
2817
2817
revision_tree = self.create_tree()
2818
preview = TransformPreview(revision_tree)
2818
preview = revision_tree.preview_transform()
2819
2819
self.addCleanup(preview.finalize)
2820
2820
preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id')
2821
2821
preview_tree = preview.get_preview_tree()
2836
2836
tree.add('foo', b'foo-id')
2837
2837
tree.commit('rev1', rev_id=b'rev1')
2838
2838
revision_tree = tree.branch.repository.revision_tree(b'rev1')
2839
preview = TransformPreview(revision_tree)
2839
preview = revision_tree.preview_transform()
2840
2840
self.addCleanup(preview.finalize)
2841
2841
preview.delete_versioned(preview.trans_id_tree_path('foo'))
2842
2842
preview_tree = preview.get_preview_tree()
2857
2857
def test_transform_conflicts(self):
2858
2858
revision_tree = self.create_tree()
2859
preview = TransformPreview(revision_tree)
2859
preview = revision_tree.preview_transform()
2860
2860
self.addCleanup(preview.finalize)
2861
2861
preview.new_file('a', preview.root, [b'content 2'])
2862
2862
resolve_conflicts(preview)
2866
2866
def get_tree_and_preview_tree(self):
2867
2867
revision_tree = self.create_tree()
2868
preview = TransformPreview(revision_tree)
2868
preview = revision_tree.preview_transform()
2869
2869
self.addCleanup(preview.finalize)
2870
2870
a_trans_id = preview.trans_id_file_id(b'a-id')
2871
2871
preview.delete_contents(a_trans_id)
2918
2918
def test_kind(self):
2919
2919
revision_tree = self.create_tree()
2920
preview = TransformPreview(revision_tree)
2920
preview = revision_tree.preview_transform()
2921
2921
self.addCleanup(preview.finalize)
2922
2922
preview.new_file('file', preview.root, [b'contents'], b'file-id')
2923
2923
preview.new_directory('directory', preview.root, b'dir-id')
2938
2938
work_tree = self.make_branch_and_tree('tree')
2939
2939
self.build_tree(['tree/file'])
2940
2940
work_tree.add('file', b'file-id')
2941
preview = TransformPreview(work_tree)
2941
preview = work_tree.preview_transform()
2942
2942
self.addCleanup(preview.finalize)
2943
2943
file_trans_id = preview.trans_id_tree_path('file')
2944
2944
preview.adjust_path('renamed', preview.root, file_trans_id)
2950
2950
work_tree = self.make_branch_and_tree('tree')
2951
2951
self.build_tree_contents([('tree/old', b'old')])
2952
2952
work_tree.add('old', b'old-id')
2953
preview = TransformPreview(work_tree)
2953
preview = work_tree.preview_transform()
2954
2954
self.addCleanup(preview.finalize)
2955
2955
preview.new_file('name', preview.root, [b'contents'], b'new-id',
2977
2977
tree = self.make_branch_and_tree('tree')
2978
2978
self.build_tree(['tree/a', 'tree/b', 'tree/c'])
2979
2979
tree.add(['a', 'b', 'c'], [b'a-id', b'b-id', b'c-id'])
2980
preview = TransformPreview(tree)
2980
preview = tree.preview_transform()
2981
2981
self.addCleanup(preview.finalize)
2982
2982
preview.unversion_file(preview.trans_id_file_id(b'b-id'))
2983
2983
c_trans_id = preview.trans_id_file_id(b'c-id')
2991
2991
tree = self.make_branch_and_tree('tree')
2992
2992
self.build_tree(['tree/unchanged', 'tree/deleted'])
2993
2993
tree.add(['unchanged', 'deleted'], [b'unchanged-id', b'deleted-id'])
2994
preview = TransformPreview(tree)
2994
preview = tree.preview_transform()
2995
2995
self.addCleanup(preview.finalize)
2996
2996
preview.unversion_file(preview.trans_id_file_id(b'deleted-id'))
2997
2997
preview_tree = preview.get_preview_tree()
3002
3002
tree = self.make_branch_and_tree('tree')
3003
3003
self.build_tree(['tree/unchanged'])
3004
3004
tree.add(['unchanged'], [b'unchanged-id'])
3005
preview = TransformPreview(tree)
3005
preview = tree.preview_transform()
3006
3006
self.addCleanup(preview.finalize)
3007
3007
preview.new_file('new', preview.trans_id_file_id(b'unchanged-id'),
3008
3008
[b'contents'], b'new-id')
3014
3014
self.build_tree(['tree/old_parent/', 'tree/old_parent/child'])
3015
3015
tree.add(['old_parent', 'old_parent/child'],
3016
3016
[b'old_parent-id', b'child-id'])
3017
preview = TransformPreview(tree)
3017
preview = tree.preview_transform()
3018
3018
self.addCleanup(preview.finalize)
3019
3019
new_parent = preview.new_directory('new_parent', preview.root,
3020
3020
b'new_parent-id')
3029
3029
self.build_tree(['tree/old_name/', 'tree/old_name/child'])
3030
3030
tree.add(['old_name', 'old_name/child'],
3031
3031
[b'parent-id', b'child-id'])
3032
preview = TransformPreview(tree)
3032
preview = tree.preview_transform()
3033
3033
self.addCleanup(preview.finalize)
3034
3034
preview.adjust_path('new_name', preview.root,
3035
3035
preview.trans_id_file_id(b'parent-id'))
3102
3102
tree = self.make_branch_and_tree('tree')
3103
3103
self.build_tree(['tree/path/'])
3104
3104
tree.add('path')
3105
preview = TransformPreview(tree)
3105
preview = tree.preview_transform()
3106
3106
self.addCleanup(preview.finalize)
3107
3107
preview.delete_contents(preview.trans_id_tree_path('path'))
3108
3108
summary = preview.get_preview_tree().path_content_summary('path')
3127
3127
tree = self.make_branch_and_tree('tree')
3128
3128
self.build_tree(['tree/path'])
3129
3129
tree.add('path')
3130
preview = TransformPreview(tree)
3130
preview = tree.preview_transform()
3131
3131
self.addCleanup(preview.finalize)
3132
3132
path_id = preview.trans_id_tree_path('path')
3133
3133
preview.set_executability(True, path_id)
3167
3167
tree.add('file', b'file-id')
3168
3168
tree.commit('a', rev_id=b'one')
3169
3169
self.build_tree_contents([('tree/file', b'a\nb\n')])
3170
preview = TransformPreview(tree)
3170
preview = tree.preview_transform()
3171
3171
self.addCleanup(preview.finalize)
3172
3172
file_trans_id = preview.trans_id_file_id(b'file-id')
3173
3173
preview.delete_contents(file_trans_id)
3200
3200
self.build_tree_contents([('tree/file', b'a\n')])
3201
3201
tree.add('file', b'file-id')
3202
3202
tree.commit('a', rev_id=b'one')
3203
preview = TransformPreview(tree)
3203
preview = tree.preview_transform()
3204
3204
self.addCleanup(preview.finalize)
3205
3205
file_trans_id = preview.trans_id_file_id(b'file-id')
3206
3206
preview.adjust_path('newname', preview.root, file_trans_id)
3218
3218
tree.add('file', b'file-id')
3219
3219
tree.commit('a', rev_id=b'one')
3220
3220
self.build_tree_contents([('tree/file', b'a\nb\n')])
3221
preview = TransformPreview(tree)
3221
preview = tree.preview_transform()
3222
3222
self.addCleanup(preview.finalize)
3223
3223
file_trans_id = preview.trans_id_file_id(b'file-id')
3224
3224
preview.delete_contents(file_trans_id)
3252
3252
work_a.add('file', b'file-id')
3253
3253
base_id = work_a.commit('base version')
3254
3254
tree_b = work_a.controldir.sprout('wtb').open_workingtree()
3255
preview = TransformPreview(work_a)
3255
preview = work_a.preview_transform()
3256
3256
self.addCleanup(preview.finalize)
3257
3257
trans_id = preview.trans_id_file_id(b'file-id')
3258
3258
preview.delete_contents(trans_id)
3275
3275
work_a.add('file', b'file-id')
3276
3276
base_id = work_a.commit('base version')
3277
3277
tree_b = work_a.controldir.sprout('wtb').open_workingtree()
3278
preview = TransformPreview(work_a.basis_tree())
3278
preview = work_a.basis_tree().preview_transform()
3279
3279
self.addCleanup(preview.finalize)
3280
3280
trans_id = preview.trans_id_file_id(b'file-id')
3281
3281
preview.delete_contents(trans_id)
3308
3308
self.build_tree(['tree/removed-file', 'tree/existing-file',
3309
3309
'tree/not-removed-file'])
3310
3310
work_tree.add(['removed-file', 'not-removed-file'])
3311
preview = TransformPreview(work_tree)
3311
preview = work_tree.preview_transform()
3312
3312
self.addCleanup(preview.finalize)
3313
3313
preview.new_file('new-file', preview.root, [b'contents'])
3314
3314
preview.new_file('new-versioned-file', preview.root, [b'contents'],
3330
3330
self.addCleanup(child_tree.unlock)
3331
3331
work_tree.lock_write()
3332
3332
self.addCleanup(work_tree.unlock)
3333
preview = TransformPreview(work_tree)
3333
preview = work_tree.preview_transform()
3334
3334
self.addCleanup(preview.finalize)
3335
3335
file_trans_id = preview.trans_id_file_id(b'file-id')
3336
3336
preview.delete_contents(file_trans_id)
3351
3351
def test_merge_preview_into_workingtree(self):
3352
3352
tree = self.make_branch_and_tree('tree')
3353
3353
tree.set_root_id(b'TREE_ROOT')
3354
tt = TransformPreview(tree)
3354
tt = tree.preview_transform()
3355
3355
self.addCleanup(tt.finalize)
3356
3356
tt.new_file('name', tt.root, [b'content'], b'file-id')
3357
3357
tree2 = self.make_branch_and_tree('tree2')
3366
3366
self.build_tree_contents([('tree/foo', b'bar')])
3367
3367
tree.add('foo', b'foo-id')
3368
3368
tree.commit('foo')
3369
tt = TransformPreview(tree)
3369
tt = tree.preview_transform()
3370
3370
self.addCleanup(tt.finalize)
3371
3371
trans_id = tt.trans_id_file_id(b'foo-id')
3372
3372
tt.delete_contents(trans_id)
3381
3381
def test_has_filename(self):
3382
3382
wt = self.make_branch_and_tree('tree')
3383
3383
self.build_tree(['tree/unmodified', 'tree/removed', 'tree/modified'])
3384
tt = TransformPreview(wt)
3384
tt = wt.preview_transform()
3385
3385
removed_id = tt.trans_id_tree_path('removed')
3386
3386
tt.delete_contents(removed_id)
3387
3387
tt.new_file('new', tt.root, [b'contents'])
3399
3399
def test_is_executable(self):
3400
3400
tree = self.make_branch_and_tree('tree')
3401
preview = TransformPreview(tree)
3401
preview = tree.preview_transform()
3402
3402
self.addCleanup(preview.finalize)
3403
3403
preview.new_file('foo', preview.root, [b'bar'], b'baz-id')
3404
3404
preview_tree = preview.get_preview_tree()
3409
3409
rev_id = tree.commit('rev1')
3410
3410
tree.branch.lock_write()
3411
3411
self.addCleanup(tree.branch.unlock)
3412
tt = TransformPreview(tree)
3412
tt = tree.preview_transform()
3413
3413
tt.new_file('file', tt.root, [b'contents'], b'file_id')
3414
3414
self.addCleanup(tt.finalize)
3415
3415
preview = tt.get_preview_tree()
3425
3425
self.requireFeature(features.UnicodeFilenameFeature)
3426
3426
branch = self.make_branch('any')
3427
3427
tree = branch.repository.revision_tree(_mod_revision.NULL_REVISION)
3428
tt = TransformPreview(tree)
3428
tt = tree.preview_transform()
3429
3429
self.addCleanup(tt.finalize)
3430
3430
foo_id = tt.new_directory('', ROOT_PARENT)
3431
3431
bar_id = tt.new_file(u'\u1234bar', foo_id, [b'contents'])
3710
3710
def test_no_orphan_for_transform_preview(self):
3711
3711
tree = self.make_branch_and_tree('tree')
3712
tt = transform.TransformPreview(tree)
3712
tt = tree.preview_transform()
3713
3713
self.addCleanup(tt.finalize)
3714
3714
self.assertRaises(NotImplementedError, tt.new_orphan, 'foo', 'bar')
3817
3817
calls.append((tree, tt))
3818
3818
MutableTree.hooks.install_named_hook(
3819
3819
'pre_transform', record_pre_transform, "Pre transform")
3820
transform, root = self.get_transform()
3820
transform, root = self.transform()
3821
3821
old_root_id = transform.tree_file_id(root)
3822
3822
transform.apply()
3823
3823
self.assertEqual(old_root_id, self.wt.path2id(''))
3830
3830
calls.append((tree, tt))
3831
3831
MutableTree.hooks.install_named_hook(
3832
3832
'post_transform', record_post_transform, "Post transform")
3833
transform, root = self.get_transform()
3833
transform, root = self.transform()
3834
3834
old_root_id = transform.tree_file_id(root)
3835
3835
transform.apply()
3836
3836
self.assertEqual(old_root_id, self.wt.path2id(''))