147
141
self.assertEqual(imaginary_id, imaginary_id2)
148
142
self.assertEqual(root, transform.get_tree_parent(imaginary_id))
149
143
self.assertEqual('directory', transform.final_kind(root))
150
self.assertEqual(self.wt.path2id(''), transform.final_file_id(root))
144
self.assertEqual(self.wt.get_root_id(), transform.final_file_id(root))
151
145
trans_id = transform.create_path('name', root)
152
146
self.assertIs(transform.final_file_id(trans_id), None)
153
147
self.assertIs(None, transform.final_kind(trans_id))
154
transform.create_file([b'contents'], trans_id)
148
transform.create_file('contents', trans_id)
155
149
transform.set_executability(True, trans_id)
156
transform.version_file(b'my_pretties', trans_id)
150
transform.version_file('my_pretties', trans_id)
157
151
self.assertRaises(DuplicateKey, transform.version_file,
158
b'my_pretties', trans_id)
159
self.assertEqual(transform.final_file_id(trans_id), b'my_pretties')
152
'my_pretties', trans_id)
153
self.assertEqual(transform.final_file_id(trans_id), 'my_pretties')
160
154
self.assertEqual(transform.final_parent(trans_id), root)
161
155
self.assertIs(transform.final_parent(root), ROOT_PARENT)
162
156
self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
163
157
oz_id = transform.create_path('oz', root)
164
158
transform.create_directory(oz_id)
165
transform.version_file(b'ozzie', oz_id)
159
transform.version_file('ozzie', oz_id)
166
160
trans_id2 = transform.create_path('name2', root)
167
transform.create_file([b'contents'], trans_id2)
161
transform.create_file('contents', trans_id2)
168
162
transform.set_executability(False, trans_id2)
169
transform.version_file(b'my_pretties2', trans_id2)
163
transform.version_file('my_pretties2', trans_id2)
170
164
modified_paths = transform.apply().modified_paths
171
with self.wt.get_file('name') as f:
172
self.assertEqual(b'contents', f.read())
173
self.assertEqual(self.wt.path2id('name'), b'my_pretties')
165
self.assertEqual('contents', self.wt.get_file('name').read())
166
self.assertEqual(self.wt.path2id('name'), 'my_pretties')
174
167
self.assertIs(self.wt.is_executable('name'), True)
175
168
self.assertIs(self.wt.is_executable('name2'), False)
176
169
self.assertEqual('directory', file_kind(self.wt.abspath('oz')))
177
170
self.assertEqual(len(modified_paths), 3)
178
171
tree_mod_paths = [self.wt.abspath(self.wt.id2path(f)) for f in
179
(b'ozzie', b'my_pretties', b'my_pretties2')]
172
('ozzie', 'my_pretties', 'my_pretties2')]
180
173
self.assertSubset(tree_mod_paths, modified_paths)
181
174
# is it safe to finalize repeatedly?
182
175
transform.finalize()
262
254
fo, st2 = self.wt.get_file_with_stat('two', filtered=False)
264
256
# We only guarantee 2s resolution
266
abs(creation_mtime - st1.st_mtime) < 2.0,
257
self.assertTrue(abs(creation_mtime - st1.st_mtime) < 2.0,
267
258
"%s != %s within 2 seconds" % (creation_mtime, st1.st_mtime))
268
259
# But if we have more than that, all files should get the same result
269
260
self.assertEqual(st1.st_mtime, st2.st_mtime)
271
262
def test_change_root_id(self):
272
263
transform, root = self.get_transform()
273
self.assertNotEqual(b'new-root-id', self.wt.path2id(''))
264
self.assertNotEqual(b'new-root-id', self.wt.get_root_id())
274
265
transform.new_directory('', ROOT_PARENT, b'new-root-id')
275
266
transform.delete_contents(root)
276
267
transform.unversion_file(root)
277
268
transform.fixup_new_roots()
278
269
transform.apply()
279
self.assertEqual(b'new-root-id', self.wt.path2id(''))
270
self.assertEqual(b'new-root-id', self.wt.get_root_id())
281
272
def test_change_root_id_add_files(self):
282
273
transform, root = self.get_transform()
283
self.assertNotEqual(b'new-root-id', self.wt.path2id(''))
274
self.assertNotEqual(b'new-root-id', self.wt.get_root_id())
284
275
new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
285
transform.new_file('file', new_trans_id, [b'new-contents\n'],
276
transform.new_file('file', new_trans_id, ['new-contents\n'],
287
278
transform.delete_contents(root)
288
279
transform.unversion_file(root)
289
280
transform.fixup_new_roots()
290
281
transform.apply()
291
self.assertEqual(b'new-root-id', self.wt.path2id(''))
282
self.assertEqual(b'new-root-id', self.wt.get_root_id())
292
283
self.assertEqual(b'new-file-id', self.wt.path2id('file'))
293
self.assertFileEqual(b'new-contents\n', self.wt.abspath('file'))
284
self.assertFileEqual('new-contents\n', self.wt.abspath('file'))
295
286
def test_add_two_roots(self):
296
287
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')
288
new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
289
new_trans_id = transform.new_directory('', ROOT_PARENT, b'alt-root-id')
299
290
self.assertRaises(ValueError, transform.fixup_new_roots)
301
292
def test_retain_existing_root(self):
379
370
transform, root = self.get_transform()
380
371
self.wt.lock_tree_write()
381
372
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')
384
dorothy = transform.new_directory('dorothy', oz, b'dorothy-id')
385
transform.new_file('toto', dorothy, [b'toto-contents'], b'toto-id',
373
trans_id = transform.new_file('name', root, 'contents',
375
oz = transform.new_directory('oz', root, 'oz-id')
376
dorothy = transform.new_directory('dorothy', oz, 'dorothy-id')
377
toto = transform.new_file('toto', dorothy, 'toto-contents',
388
380
self.assertEqual(len(transform.find_conflicts()), 0)
389
381
transform.apply()
390
382
self.assertRaises(ReusingTransform, transform.find_conflicts)
391
with open(self.wt.abspath('name'), 'r') as f:
392
self.assertEqual('contents', f.read())
393
self.assertEqual(self.wt.path2id('name'), b'my_pretties')
383
self.assertEqual('contents', file(self.wt.abspath('name')).read())
384
self.assertEqual(self.wt.path2id('name'), 'my_pretties')
394
385
self.assertIs(self.wt.is_executable('name'), True)
395
self.assertEqual(self.wt.path2id('oz'), b'oz-id')
396
self.assertEqual(self.wt.path2id('oz/dorothy'), b'dorothy-id')
397
self.assertEqual(self.wt.path2id('oz/dorothy/toto'), b'toto-id')
386
self.assertEqual(self.wt.path2id('oz'), 'oz-id')
387
self.assertEqual(self.wt.path2id('oz/dorothy'), 'dorothy-id')
388
self.assertEqual(self.wt.path2id('oz/dorothy/toto'), 'toto-id')
399
self.assertEqual(b'toto-contents',
390
self.assertEqual('toto-contents',
400
391
self.wt.get_file('oz/dorothy/toto').read())
401
392
self.assertIs(self.wt.is_executable('oz/dorothy/toto'), False)
403
394
def test_tree_reference(self):
404
395
transform, root = self.get_transform()
405
396
tree = transform._tree
406
trans_id = transform.new_directory('reference', root, b'subtree-id')
407
transform.set_tree_reference(b'subtree-revision', trans_id)
397
trans_id = transform.new_directory('reference', root, 'subtree-id')
398
transform.set_tree_reference('subtree-revision', trans_id)
408
399
transform.apply()
410
401
self.addCleanup(tree.unlock)
413
tree.root_inventory.get_entry(b'subtree-id').reference_revision)
402
self.assertEqual('subtree-revision',
403
tree.root_inventory.get_entry('subtree-id').reference_revision)
415
405
def test_conflicts(self):
416
406
transform, root = self.get_transform()
417
trans_id = transform.new_file('name', root, [b'contents'],
407
trans_id = transform.new_file('name', root, 'contents',
419
409
self.assertEqual(len(transform.find_conflicts()), 0)
420
trans_id2 = transform.new_file('name', root, [b'Crontents'], b'toto')
410
trans_id2 = transform.new_file('name', root, 'Crontents', 'toto')
421
411
self.assertEqual(transform.find_conflicts(),
422
412
[('duplicate', trans_id, trans_id2, 'name')])
423
413
self.assertRaises(MalformedTransform, transform.apply)
454
444
transform.set_executability(True, oz_id)
455
445
self.assertEqual(transform.find_conflicts(),
456
446
[('unversioned executability', oz_id)])
457
transform.version_file(b'oz-id', oz_id)
447
transform.version_file('oz-id', oz_id)
458
448
self.assertEqual(transform.find_conflicts(),
459
449
[('non-file executability', oz_id)])
460
450
transform.set_executability(None, oz_id)
461
tip_id = transform.new_file('tip', oz_id, [b'ozma'], b'tip-id')
451
tip_id = transform.new_file('tip', oz_id, 'ozma', 'tip-id')
462
452
transform.apply()
463
self.assertEqual(self.wt.path2id('name'), b'my_pretties')
464
with open(self.wt.abspath('name'), 'rb') as f:
465
self.assertEqual(b'contents', f.read())
453
self.assertEqual(self.wt.path2id('name'), 'my_pretties')
454
self.assertEqual('contents', file(self.wt.abspath('name')).read())
466
455
transform2, root = self.get_transform()
467
456
oz_id = transform2.trans_id_tree_path('oz')
468
newtip = transform2.new_file('tip', oz_id, [b'other'], b'tip-id')
457
newtip = transform2.new_file('tip', oz_id, 'other', 'tip-id')
469
458
result = transform2.find_conflicts()
470
459
fp = FinalPaths(transform2)
471
460
self.assertTrue('oz/tip' in transform2._tree_path_ids)
635
624
create_tree, root = self.get_transform()
637
626
root = create_tree.root
638
create_tree.new_file('name1', root, [b'hello1'], b'name1')
639
create_tree.new_file('name2', root, [b'hello2'], b'name2')
640
ddir = create_tree.new_directory('dying_directory', root, b'ddir')
641
create_tree.new_file('dying_file', ddir, [b'goodbye1'], b'dfile')
642
create_tree.new_file('moving_file', ddir, [b'later1'], b'mfile')
643
create_tree.new_file('moving_file2', root, [b'later2'], b'mfile2')
627
create_tree.new_file('name1', root, 'hello1', 'name1')
628
create_tree.new_file('name2', root, 'hello2', 'name2')
629
ddir = create_tree.new_directory('dying_directory', root, 'ddir')
630
create_tree.new_file('dying_file', ddir, 'goodbye1', 'dfile')
631
create_tree.new_file('moving_file', ddir, 'later1', 'mfile')
632
create_tree.new_file('moving_file2', root, 'later2', 'mfile2')
644
633
create_tree.apply()
646
635
mangle_tree, root = self.get_transform()
647
636
root = mangle_tree.root
649
638
name1 = mangle_tree.trans_id_tree_path('name1')
650
639
name2 = mangle_tree.trans_id_tree_path('name2')
651
640
mangle_tree.adjust_path('name2', root, name1)
652
641
mangle_tree.adjust_path('name1', root, name2)
654
# tests for deleting parent directories
643
#tests for deleting parent directories
655
644
ddir = mangle_tree.trans_id_tree_path('dying_directory')
656
645
mangle_tree.delete_contents(ddir)
657
646
dfile = mangle_tree.trans_id_tree_path('dying_directory/dying_file')
660
649
mfile = mangle_tree.trans_id_tree_path('dying_directory/moving_file')
661
650
mangle_tree.adjust_path('mfile', root, mfile)
663
# tests for adding parent directories
664
newdir = mangle_tree.new_directory('new_directory', root, b'newdir')
652
#tests for adding parent directories
653
newdir = mangle_tree.new_directory('new_directory', root, 'newdir')
665
654
mfile2 = mangle_tree.trans_id_tree_path('moving_file2')
666
655
mangle_tree.adjust_path('mfile2', newdir, mfile2)
667
mangle_tree.new_file('newfile', newdir, [b'hello3'], b'dfile')
668
self.assertEqual(mangle_tree.final_file_id(mfile2), b'mfile2')
656
mangle_tree.new_file('newfile', newdir, 'hello3', 'dfile')
657
self.assertEqual(mangle_tree.final_file_id(mfile2), 'mfile2')
669
658
self.assertEqual(mangle_tree.final_parent(mfile2), newdir)
670
self.assertEqual(mangle_tree.final_file_id(mfile2), b'mfile2')
659
self.assertEqual(mangle_tree.final_file_id(mfile2), 'mfile2')
671
660
mangle_tree.apply()
672
with open(self.wt.abspath('name1'), 'r') as f:
673
self.assertEqual(f.read(), 'hello2')
674
with open(self.wt.abspath('name2'), 'r') as f:
675
self.assertEqual(f.read(), 'hello1')
661
self.assertEqual(file(self.wt.abspath('name1')).read(), 'hello2')
662
self.assertEqual(file(self.wt.abspath('name2')).read(), 'hello1')
676
663
mfile2_path = self.wt.abspath(pathjoin('new_directory', 'mfile2'))
677
664
self.assertEqual(mangle_tree.final_parent(mfile2), newdir)
678
with open(mfile2_path, 'r') as f:
679
self.assertEqual(f.read(), 'later2')
665
self.assertEqual(file(mfile2_path).read(), 'later2')
680
666
self.assertEqual(self.wt.id2path(b'mfile2'), 'new_directory/mfile2')
681
667
self.assertEqual(self.wt.path2id('new_directory/mfile2'), b'mfile2')
682
668
newfile_path = self.wt.abspath(pathjoin('new_directory', 'newfile'))
683
with open(newfile_path, 'r') as f:
684
self.assertEqual(f.read(), 'hello3')
669
self.assertEqual(file(newfile_path).read(), 'hello3')
685
670
self.assertEqual(self.wt.path2id('dying_directory'), b'ddir')
686
671
self.assertIs(self.wt.path2id('dying_directory/dying_file'), None)
687
672
mfile2_path = self.wt.abspath(pathjoin('new_directory', 'mfile2'))
689
674
def test_both_rename(self):
690
675
create_tree, root = self.get_transform()
691
newdir = create_tree.new_directory('selftest', root, b'selftest-id')
692
create_tree.new_file('blackbox.py', newdir, [
693
b'hello1'], b'blackbox-id')
676
newdir = create_tree.new_directory('selftest', root, 'selftest-id')
677
create_tree.new_file('blackbox.py', newdir, 'hello1', 'blackbox-id')
694
678
create_tree.apply()
695
679
mangle_tree, root = self.get_transform()
696
680
selftest = mangle_tree.trans_id_tree_path('selftest')
773
755
def _test_symlinks(self, link_name1, link_target1,
774
756
link_name2, link_target2):
758
def ozpath(p): return 'oz/' + p
779
760
self.requireFeature(SymlinkFeature)
780
761
transform, root = self.get_transform()
781
oz_id = transform.new_directory('oz', root, b'oz-id')
782
transform.new_symlink(link_name1, oz_id, link_target1, b'wizard-id')
762
oz_id = transform.new_directory('oz', root, 'oz-id')
763
wizard = transform.new_symlink(link_name1, oz_id, link_target1,
783
765
wiz_id = transform.create_path(link_name2, oz_id)
784
766
transform.create_symlink(link_target2, wiz_id)
785
transform.version_file(b'wiz-id2', wiz_id)
767
transform.version_file('wiz-id2', wiz_id)
786
768
transform.set_executability(True, wiz_id)
787
769
self.assertEqual(transform.find_conflicts(),
788
770
[('non-file executability', wiz_id)])
789
771
transform.set_executability(None, wiz_id)
790
772
transform.apply()
791
self.assertEqual(self.wt.path2id(ozpath(link_name1)), b'wizard-id')
773
self.assertEqual(self.wt.path2id(ozpath(link_name1)), 'wizard-id')
792
774
self.assertEqual('symlink',
793
775
file_kind(self.wt.abspath(ozpath(link_name1))))
794
776
self.assertEqual(link_target2,
807
789
u'\N{Euro Sign}wizard2',
808
790
u'b\N{Euro Sign}hind_curtain')
810
def test_unsupported_symlink_no_conflict(self):
792
def test_unable_create_symlink(self):
812
794
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)
795
tt = TreeTransform(wt) # TreeTransform obtains write lock
797
tt.new_symlink('foo', tt.root, 'bar')
818
801
os_symlink = getattr(os, 'symlink', None)
819
802
os.symlink = None
804
err = self.assertRaises(errors.UnableCreateSymlink, tt_helper)
806
"Unable to create symlink 'foo' on this platform",
824
810
os.symlink = os_symlink
826
812
def get_conflicted(self):
827
813
create, root = self.get_transform()
828
create.new_file('dorothy', root, [b'dorothy'], b'dorothy-id')
829
oz = create.new_directory('oz', root, b'oz-id')
830
create.new_directory('emeraldcity', oz, b'emerald-id')
814
create.new_file('dorothy', root, 'dorothy', 'dorothy-id')
815
oz = create.new_directory('oz', root, 'oz-id')
816
create.new_directory('emeraldcity', oz, 'emerald-id')
832
818
conflicts, root = self.get_transform()
833
819
# set up duplicate entry, duplicate id
834
new_dorothy = conflicts.new_file('dorothy', root, [b'dorothy'],
820
new_dorothy = conflicts.new_file('dorothy', root, 'dorothy',
836
822
old_dorothy = conflicts.trans_id_tree_path('dorothy')
837
823
oz = conflicts.trans_id_tree_path('oz')
838
824
# set up DeletedParent parent conflict
839
825
conflicts.delete_versioned(oz)
840
826
emerald = conflicts.trans_id_tree_path('oz/emeraldcity')
841
827
# set up MissingParent conflict
842
munchkincity = conflicts.trans_id_file_id(b'munchkincity-id')
828
munchkincity = conflicts.trans_id_file_id('munchkincity-id')
843
829
conflicts.adjust_path('munchkincity', root, munchkincity)
844
conflicts.new_directory('auntem', munchkincity, b'auntem-id')
830
conflicts.new_directory('auntem', munchkincity, 'auntem-id')
845
831
# set up parent loop
846
832
conflicts.adjust_path('emeraldcity', emerald, emerald)
847
833
return conflicts, emerald, oz, old_dorothy, new_dorothy
862
848
raw_conflicts = resolve_conflicts(tt)
863
849
cooked_conflicts = cook_conflicts(raw_conflicts, tt)
864
850
duplicate = DuplicateEntry('Moved existing file to', 'dorothy.moved',
865
'dorothy', None, b'dorothy-id')
851
'dorothy', None, 'dorothy-id')
866
852
self.assertEqual(cooked_conflicts[0], duplicate)
867
853
duplicate_id = DuplicateID('Unversioned existing file',
868
854
'dorothy.moved', 'dorothy', None,
870
856
self.assertEqual(cooked_conflicts[1], duplicate_id)
871
857
missing_parent = MissingParent('Created directory', 'munchkincity',
873
deleted_parent = DeletingParent('Not deleting', 'oz', b'oz-id')
859
deleted_parent = DeletingParent('Not deleting', 'oz', 'oz-id')
874
860
self.assertEqual(cooked_conflicts[2], missing_parent)
875
861
unversioned_parent = UnversionedParent('Versioned directory',
878
864
unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
880
866
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')
867
parent_loop = ParentLoop('Cancelled move', 'oz/emeraldcity',
868
'oz/emeraldcity', 'emerald-id', 'emerald-id')
884
869
self.assertEqual(cooked_conflicts[4], deleted_parent)
885
870
self.assertEqual(cooked_conflicts[5], unversioned_parent2)
886
871
self.assertEqual(cooked_conflicts[6], parent_loop)
931
915
tt = self.prepare_wrong_parent_kind()
932
916
raw_conflicts = resolve_conflicts(tt)
933
917
self.assertEqual({('non-directory parent', 'Created directory',
934
'new-3')}, raw_conflicts)
918
'new-3')}, raw_conflicts)
935
919
cooked_conflicts = cook_conflicts(raw_conflicts, tt)
936
920
self.assertEqual([NonDirectoryParent('Created directory', 'parent.new',
937
b'parent-id')], cooked_conflicts)
921
b'parent-id')], cooked_conflicts)
939
923
self.assertFalse(self.wt.is_versioned('parent'))
940
self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
924
self.assertEqual('parent-id', self.wt.path2id('parent.new'))
942
926
def test_resolve_conflicts_wrong_new_parent_kind(self):
943
927
tt, root = self.get_transform()
944
928
parent_id = tt.new_directory('parent', root, b'parent-id')
945
tt.new_file('child,', parent_id, [b'contents2'], b'file-id')
929
tt.new_file('child,', parent_id, 'contents2', b'file-id')
947
931
tt, root = self.get_transform()
948
parent_id = tt.trans_id_file_id(b'parent-id')
932
parent_id = tt.trans_id_file_id('parent-id')
949
933
tt.delete_contents(parent_id)
950
tt.create_file([b'contents'], parent_id)
934
tt.create_file('contents', parent_id)
951
935
raw_conflicts = resolve_conflicts(tt)
952
936
self.assertEqual({('non-directory parent', 'Created directory',
953
'new-3')}, raw_conflicts)
937
'new-3')}, raw_conflicts)
955
939
self.assertFalse(self.wt.is_versioned('parent'))
956
self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
940
self.assertEqual('parent-id', self.wt.path2id('parent.new'))
958
942
def test_resolve_conflicts_wrong_parent_kind_unversioned(self):
959
943
tt, root = self.get_transform()
960
944
parent_id = tt.new_directory('parent', root)
961
tt.new_file('child,', parent_id, [b'contents2'])
945
tt.new_file('child,', parent_id, 'contents2')
963
947
tt, root = self.get_transform()
964
948
parent_id = tt.trans_id_tree_path('parent')
965
949
tt.delete_contents(parent_id)
966
tt.create_file([b'contents'], parent_id)
950
tt.create_file('contents', parent_id)
967
951
resolve_conflicts(tt)
969
953
self.assertFalse(self.wt.is_versioned('parent'))
999
983
def test_moving_root(self):
1000
984
create, root = self.get_transform()
1001
fun = create.new_directory('fun', root, b'fun-id')
1002
create.new_directory('sun', root, b'sun-id')
1003
create.new_directory('moon', root, b'moon')
985
fun = create.new_directory('fun', root, 'fun-id')
986
create.new_directory('sun', root, 'sun-id')
987
create.new_directory('moon', root, 'moon')
1005
989
transform, root = self.get_transform()
1006
990
transform.adjust_root_path('oldroot', fun)
1007
991
new_root = transform.trans_id_tree_path('')
1008
transform.version_file(b'new-root', new_root)
992
transform.version_file('new-root', new_root)
1009
993
transform.apply()
1011
995
def test_renames(self):
1012
996
create, root = self.get_transform()
1013
old = create.new_directory('old-parent', root, b'old-id')
1014
intermediate = create.new_directory('intermediate', old, b'im-id')
1015
myfile = create.new_file('myfile', intermediate, [b'myfile-text'],
997
old = create.new_directory('old-parent', root, 'old-id')
998
intermediate = create.new_directory('intermediate', old, 'im-id')
999
myfile = create.new_file('myfile', intermediate, 'myfile-text',
1018
1002
rename, root = self.get_transform()
1019
old = rename.trans_id_file_id(b'old-id')
1003
old = rename.trans_id_file_id('old-id')
1020
1004
rename.adjust_path('new', root, old)
1021
myfile = rename.trans_id_file_id(b'myfile-id')
1005
myfile = rename.trans_id_file_id('myfile-id')
1022
1006
rename.set_executability(True, myfile)
1026
1010
self.requireFeature(features.not_running_as_root)
1027
1011
# see https://bugs.launchpad.net/bzr/+bug/491763
1028
1012
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')
1013
first_dir = create.new_directory('first-dir', root_id, 'first-id')
1014
myfile = create.new_file('myfile', root_id, 'myfile-text',
1032
1017
if os.name == "posix" and sys.platform != "cygwin":
1033
1018
# posix filesystems fail on renaming if the readonly bit is set
1034
1019
osutils.make_readonly(self.wt.abspath('first-dir'))
1035
1020
elif os.name == "nt":
1036
1021
# windows filesystems fail on renaming open files
1037
self.addCleanup(open(self.wt.abspath('myfile')).close)
1022
self.addCleanup(file(self.wt.abspath('myfile')).close)
1039
1024
self.skipTest("Can't force a permissions error on rename")
1040
1025
# now transform to rename
1041
1026
rename_transform, root_id = self.get_transform()
1042
file_trans_id = rename_transform.trans_id_file_id(b'myfile-id')
1043
dir_id = rename_transform.trans_id_file_id(b'first-id')
1027
file_trans_id = rename_transform.trans_id_file_id('myfile-id')
1028
dir_id = rename_transform.trans_id_file_id('first-id')
1044
1029
rename_transform.adjust_path('newname', dir_id, file_trans_id)
1045
1030
e = self.assertRaises(errors.TransformRenameFailed,
1046
rename_transform.apply)
1047
# On nix looks like:
1031
rename_transform.apply)
1032
# On nix looks like:
1048
1033
# "Failed to rename .../work/.bzr/checkout/limbo/new-1
1049
1034
# to .../first-dir/newname: [Errno 13] Permission denied"
1050
1035
# On windows looks like:
1051
# "Failed to rename .../work/myfile to
1036
# "Failed to rename .../work/myfile to
1052
1037
# .../work/.bzr/checkout/limbo/new-1: [Errno 13] Permission denied"
1053
1038
# This test isn't concerned with exactly what the error looks like,
1054
1039
# and the strerror will vary across OS and locales, but the assert
1137
1119
def test_iter_changes(self):
1138
1120
self.wt.set_root_id(b'eert_toor')
1139
1121
transform, root = self.get_transform()
1140
transform.new_file('old', root, [b'blah'], b'id-1', True)
1122
transform.new_file('old', root, 'blah', 'id-1', True)
1141
1123
transform.apply()
1142
1124
transform, root = self.get_transform()
1144
1126
self.assertEqual([], list(transform.iter_changes()))
1145
1127
old = transform.trans_id_tree_path('old')
1146
1128
transform.unversion_file(old)
1147
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()))
1152
transform.new_directory('new', root, b'id-1')
1153
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()))
1129
self.assertEqual([('id-1', ('old', None), False, (True, False),
1130
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
1131
(True, True))], list(transform.iter_changes()))
1132
transform.new_directory('new', root, 'id-1')
1133
self.assertEqual([('id-1', ('old', 'new'), True, (True, True),
1134
('eert_toor', 'eert_toor'), ('old', 'new'),
1135
('file', 'directory'),
1136
(True, False))], list(transform.iter_changes()))
1159
1138
transform.finalize()
1161
1140
def test_iter_changes_new(self):
1162
1141
self.wt.set_root_id(b'eert_toor')
1163
1142
transform, root = self.get_transform()
1164
transform.new_file('old', root, [b'blah'])
1143
transform.new_file('old', root, 'blah')
1165
1144
transform.apply()
1166
1145
transform, root = self.get_transform()
1168
1147
old = transform.trans_id_tree_path('old')
1169
transform.version_file(b'id-1', old)
1170
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()))
1148
transform.version_file('id-1', old)
1149
self.assertEqual([('id-1', (None, 'old'), False, (False, True),
1150
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
1151
(False, False))], list(transform.iter_changes()))
1176
1153
transform.finalize()
1178
1155
def test_iter_changes_modifications(self):
1179
1156
self.wt.set_root_id(b'eert_toor')
1180
1157
transform, root = self.get_transform()
1181
transform.new_file('old', root, [b'blah'], b'id-1')
1182
transform.new_file('new', root, [b'blah'])
1183
transform.new_directory('subdir', root, b'subdir-id')
1158
transform.new_file('old', root, 'blah', 'id-1')
1159
transform.new_file('new', root, 'blah')
1160
transform.new_directory('subdir', root, 'subdir-id')
1184
1161
transform.apply()
1185
1162
transform, root = self.get_transform()
1189
1166
new = transform.trans_id_tree_path('new')
1190
1167
self.assertEqual([], list(transform.iter_changes()))
1193
1170
transform.delete_contents(old)
1194
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()))
1171
self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
1172
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', None),
1173
(False, False))], list(transform.iter_changes()))
1201
transform.create_file([b'blah'], old)
1202
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()))
1176
transform.create_file('blah', old)
1177
self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
1178
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
1179
(False, False))], list(transform.iter_changes()))
1207
1180
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()))
1181
self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
1182
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
1183
(False, False))], list(transform.iter_changes()))
1213
1184
transform.cancel_creation(old)
1215
1186
# move file_id to a different file
1216
1187
self.assertEqual([], list(transform.iter_changes()))
1217
1188
transform.unversion_file(old)
1218
transform.version_file(b'id-1', new)
1189
transform.version_file('id-1', new)
1219
1190
transform.adjust_path('old', root, new)
1220
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()))
1191
self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
1192
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
1193
(False, False))], list(transform.iter_changes()))
1225
1194
transform.cancel_versioning(new)
1226
1195
transform._removed_id = set()
1229
1198
self.assertEqual([], list(transform.iter_changes()))
1230
1199
transform.set_executability(True, old)
1231
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()))
1200
self.assertEqual([('id-1', ('old', 'old'), False, (True, True),
1201
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
1202
(False, True))], list(transform.iter_changes()))
1236
1203
transform.set_executability(None, old)
1239
1206
self.assertEqual([], list(transform.iter_changes()))
1240
1207
transform.adjust_path('new', root, old)
1241
1208
transform._new_parent = {}
1242
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()))
1209
self.assertEqual([('id-1', ('old', 'new'), False, (True, True),
1210
('eert_toor', 'eert_toor'), ('old', 'new'), ('file', 'file'),
1211
(False, False))], list(transform.iter_changes()))
1247
1212
transform._new_name = {}
1249
1214
# parent directory
1250
1215
self.assertEqual([], list(transform.iter_changes()))
1251
1216
transform.adjust_path('new', subdir, old)
1252
1217
transform._new_name = {}
1253
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()))
1218
self.assertEqual([('id-1', ('old', 'subdir/old'), False,
1219
(True, True), ('eert_toor', 'subdir-id'), ('old', 'old'),
1220
('file', 'file'), (False, False))],
1221
list(transform.iter_changes()))
1258
1222
transform._new_path = {}
1268
1232
# obviously can't bleed into file2's change output. But for now, it
1270
1234
transform, root = self.get_transform()
1271
transform.new_file('file1', root, [b'blah'], b'id-1')
1272
transform.new_file('file2', root, [b'blah'], b'id-2')
1235
transform.new_file('file1', root, 'blah', 'id-1')
1236
transform.new_file('file2', root, 'blah', 'id-2')
1273
1237
transform.apply()
1274
1238
transform, root = self.get_transform()
1276
transform.delete_contents(transform.trans_id_file_id(b'id-1'))
1240
transform.delete_contents(transform.trans_id_file_id('id-1'))
1277
1241
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)],
1242
transform.trans_id_file_id('id-2'))
1243
self.assertEqual([('id-1', (u'file1', u'file1'), True, (True, True),
1244
('eert_toor', 'eert_toor'), ('file1', u'file1'),
1245
('file', None), (False, False)),
1246
('id-2', (u'file2', u'file2'), False, (True, True),
1247
('eert_toor', 'eert_toor'), ('file2', u'file2'),
1248
('file', 'file'), (False, True))],
1286
1249
list(transform.iter_changes()))
1288
1251
transform.finalize()
1668
1610
tree2 = self.make_branch_and_tree('tree2')
1669
1611
tt = TreeTransform(tree2)
1670
1612
foo_trans_id = tt.create_path('foo', tt.root)
1671
create_from_tree(tt, foo_trans_id, tree1, 'foo')
1613
create_from_tree(tt, foo_trans_id, tree1, 'foo', file_id=b'foo-id')
1672
1614
bar_trans_id = tt.create_path('bar', tt.root)
1673
create_from_tree(tt, bar_trans_id, tree1, 'bar')
1615
create_from_tree(tt, bar_trans_id, tree1, 'bar', file_id='bbar-id')
1675
1617
self.assertEqual('directory', osutils.file_kind('tree2/foo'))
1676
self.assertFileEqual(b'baz', 'tree2/bar')
1618
self.assertFileEqual('baz', 'tree2/bar')
1678
1620
def test_create_from_tree_bytes(self):
1679
1621
"""Provided lines are used instead of tree content."""
1680
1622
tree1 = self.make_branch_and_tree('tree1')
1681
self.build_tree_contents([('tree1/foo', b'bar'), ])
1623
self.build_tree_contents([('tree1/foo', 'bar'),])
1682
1624
tree1.add('foo', b'foo-id')
1683
1625
tree2 = self.make_branch_and_tree('tree2')
1684
1626
tt = TreeTransform(tree2)
1685
1627
foo_trans_id = tt.create_path('foo', tt.root)
1686
create_from_tree(tt, foo_trans_id, tree1, 'foo', chunks=[b'qux'])
1628
create_from_tree(tt, foo_trans_id, tree1, 'foo', file_id=b'foo-id',
1688
self.assertFileEqual(b'qux', 'tree2/foo')
1631
self.assertFileEqual('qux', 'tree2/foo')
1690
1633
def test_create_from_tree_symlink(self):
1691
1634
self.requireFeature(SymlinkFeature)
1753
1696
def test_text_merge(self):
1754
1697
root_id = generate_ids.gen_root_id()
1755
1698
base = TransformGroup("base", root_id)
1756
base.tt.new_file('a', base.root, [b'a\nb\nc\nd\be\n'], b'a')
1757
base.tt.new_file('b', base.root, [b'b1'], b'b')
1758
base.tt.new_file('c', base.root, [b'c'], b'c')
1759
base.tt.new_file('d', base.root, [b'd'], b'd')
1760
base.tt.new_file('e', base.root, [b'e'], b'e')
1761
base.tt.new_file('f', base.root, [b'f'], b'f')
1762
base.tt.new_directory('g', base.root, b'g')
1763
base.tt.new_directory('h', base.root, b'h')
1699
base.tt.new_file('a', base.root, 'a\nb\nc\nd\be\n', 'a')
1700
base.tt.new_file('b', base.root, 'b1', 'b')
1701
base.tt.new_file('c', base.root, 'c', 'c')
1702
base.tt.new_file('d', base.root, 'd', 'd')
1703
base.tt.new_file('e', base.root, 'e', 'e')
1704
base.tt.new_file('f', base.root, 'f', 'f')
1705
base.tt.new_directory('g', base.root, 'g')
1706
base.tt.new_directory('h', base.root, 'h')
1764
1707
base.tt.apply()
1765
1708
other = TransformGroup("other", root_id)
1766
other.tt.new_file('a', other.root, [b'y\nb\nc\nd\be\n'], b'a')
1767
other.tt.new_file('b', other.root, [b'b2'], b'b')
1768
other.tt.new_file('c', other.root, [b'c2'], b'c')
1769
other.tt.new_file('d', other.root, [b'd'], b'd')
1770
other.tt.new_file('e', other.root, [b'e2'], b'e')
1771
other.tt.new_file('f', other.root, [b'f'], b'f')
1772
other.tt.new_file('g', other.root, [b'g'], b'g')
1773
other.tt.new_file('h', other.root, [b'h\ni\nj\nk\n'], b'h')
1774
other.tt.new_file('i', other.root, [b'h\ni\nj\nk\n'], b'i')
1709
other.tt.new_file('a', other.root, 'y\nb\nc\nd\be\n', 'a')
1710
other.tt.new_file('b', other.root, 'b2', 'b')
1711
other.tt.new_file('c', other.root, 'c2', 'c')
1712
other.tt.new_file('d', other.root, 'd', 'd')
1713
other.tt.new_file('e', other.root, 'e2', 'e')
1714
other.tt.new_file('f', other.root, 'f', 'f')
1715
other.tt.new_file('g', other.root, 'g', 'g')
1716
other.tt.new_file('h', other.root, 'h\ni\nj\nk\n', 'h')
1717
other.tt.new_file('i', other.root, 'h\ni\nj\nk\n', 'i')
1775
1718
other.tt.apply()
1776
1719
this = TransformGroup("this", root_id)
1777
this.tt.new_file('a', this.root, [b'a\nb\nc\nd\bz\n'], b'a')
1778
this.tt.new_file('b', this.root, [b'b'], b'b')
1779
this.tt.new_file('c', this.root, [b'c'], b'c')
1780
this.tt.new_file('d', this.root, [b'd2'], b'd')
1781
this.tt.new_file('e', this.root, [b'e2'], b'e')
1782
this.tt.new_file('f', this.root, [b'f'], b'f')
1783
this.tt.new_file('g', this.root, [b'g'], b'g')
1784
this.tt.new_file('h', this.root, [b'1\n2\n3\n4\n'], b'h')
1785
this.tt.new_file('i', this.root, [b'1\n2\n3\n4\n'], b'i')
1720
this.tt.new_file('a', this.root, 'a\nb\nc\nd\bz\n', 'a')
1721
this.tt.new_file('b', this.root, 'b', 'b')
1722
this.tt.new_file('c', this.root, 'c', 'c')
1723
this.tt.new_file('d', this.root, 'd2', 'd')
1724
this.tt.new_file('e', this.root, 'e2', 'e')
1725
this.tt.new_file('f', this.root, 'f', 'f')
1726
this.tt.new_file('g', this.root, 'g', 'g')
1727
this.tt.new_file('h', this.root, '1\n2\n3\n4\n', 'h')
1728
this.tt.new_file('i', this.root, '1\n2\n3\n4\n', 'i')
1786
1729
this.tt.apply()
1787
1730
Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1789
1732
# textual merge
1790
with this.wt.get_file(this.wt.id2path(b'a')) as f:
1791
self.assertEqual(f.read(), b'y\nb\nc\nd\bz\n')
1733
self.assertEqual(this.wt.get_file(this.wt.id2path(b'a')).read(), 'y\nb\nc\nd\bz\n')
1792
1734
# three-way text conflict
1793
with this.wt.get_file(this.wt.id2path(b'b')) as f:
1794
self.assertEqual(f.read(), conflict_text(b'b', b'b2'))
1735
self.assertEqual(this.wt.get_file(this.wt.id2path(b'b')).read(),
1736
conflict_text('b', 'b2'))
1796
self.assertEqual(this.wt.get_file(this.wt.id2path(b'c')).read(), b'c2')
1738
self.assertEqual(this.wt.get_file(this.wt.id2path(b'c')).read(), 'c2')
1798
self.assertEqual(this.wt.get_file(this.wt.id2path(b'd')).read(), b'd2')
1740
self.assertEqual(this.wt.get_file(this.wt.id2path(b'd')).read(), 'd2')
1799
1741
# Ambigious clean merge
1800
self.assertEqual(this.wt.get_file(this.wt.id2path(b'e')).read(), b'e2')
1742
self.assertEqual(this.wt.get_file(this.wt.id2path(b'e')).read(), 'e2')
1802
self.assertEqual(this.wt.get_file(this.wt.id2path(b'f')).read(), b'f')
1744
self.assertEqual(this.wt.get_file(this.wt.id2path(b'f')).read(), 'f')
1803
1745
# Correct correct results when THIS == OTHER
1804
self.assertEqual(this.wt.get_file(this.wt.id2path(b'g')).read(), b'g')
1746
self.assertEqual(this.wt.get_file(this.wt.id2path(b'g')).read(), 'g')
1805
1747
# Text conflict when THIS & OTHER are text and BASE is dir
1806
1748
self.assertEqual(this.wt.get_file(this.wt.id2path(b'h')).read(),
1807
conflict_text(b'1\n2\n3\n4\n', b'h\ni\nj\nk\n'))
1749
conflict_text('1\n2\n3\n4\n', 'h\ni\nj\nk\n'))
1808
1750
self.assertEqual(this.wt.get_file('h.THIS').read(),
1810
1752
self.assertEqual(this.wt.get_file('h.OTHER').read(),
1812
1754
self.assertEqual(file_kind(this.wt.abspath('h.BASE')), 'directory')
1813
1755
self.assertEqual(this.wt.get_file(this.wt.id2path(b'i')).read(),
1814
conflict_text(b'1\n2\n3\n4\n', b'h\ni\nj\nk\n'))
1756
conflict_text('1\n2\n3\n4\n', 'h\ni\nj\nk\n'))
1815
1757
self.assertEqual(this.wt.get_file('i.THIS').read(),
1817
1759
self.assertEqual(this.wt.get_file('i.OTHER').read(),
1819
1761
self.assertEqual(os.path.exists(this.wt.abspath('i.BASE')), False)
1820
1762
modified = ['a', 'b', 'c', 'h', 'i']
1821
1763
merge_modified = this.wt.merge_modified()
1822
1764
self.assertSubset(merge_modified, modified)
1823
1765
self.assertEqual(len(merge_modified), len(modified))
1824
with open(this.wt.abspath(this.wt.id2path(b'a')), 'wb') as f:
1766
with file(this.wt.abspath(this.wt.id2path('a')), 'wb') as f: f.write('booga')
1826
1767
modified.pop(0)
1827
1768
merge_modified = this.wt.merge_modified()
1828
1769
self.assertSubset(merge_modified, modified)
1879
1818
base = TransformGroup("BASE", root_id)
1880
1819
this = TransformGroup("THIS", root_id)
1881
1820
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')
1821
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a')
1822
for t in [base, this, other]]
1823
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b')
1824
for t in [base, this, other]]
1825
base.tt.new_directory('c', base_a, 'c')
1826
this.tt.new_directory('c1', this_a, 'c')
1827
other.tt.new_directory('c', other_b, 'c')
1829
base.tt.new_directory('d', base_a, 'd')
1830
this.tt.new_directory('d1', this_b, 'd')
1831
other.tt.new_directory('d', other_a, 'd')
1833
base.tt.new_directory('e', base_a, 'e')
1834
this.tt.new_directory('e', this_a, 'e')
1835
other.tt.new_directory('e1', other_b, 'e')
1837
base.tt.new_directory('f', base_a, 'f')
1838
this.tt.new_directory('f1', this_b, 'f')
1839
other.tt.new_directory('f1', other_b, 'f')
1902
1841
for tg in [this, base, other]:
1912
1851
base = TransformGroup("BASE", root_id)
1913
1852
this = TransformGroup("THIS", root_id)
1914
1853
other = TransformGroup("OTHER", root_id)
1915
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, b'a')
1916
for t in [base, this, other]]
1917
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, b'b')
1918
for t in [base, this, other]]
1920
base.tt.new_file('g', base_a, [b'g'], b'g')
1921
other.tt.new_file('g1', other_b, [b'g1'], b'g')
1923
base.tt.new_file('h', base_a, [b'h'], b'h')
1924
this.tt.new_file('h1', this_b, [b'h1'], b'h')
1926
base.tt.new_file('i', base.root, [b'i'], b'i')
1927
other.tt.new_directory('i1', this_b, b'i')
1854
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a')
1855
for t in [base, this, other]]
1856
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b')
1857
for t in [base, this, other]]
1859
base.tt.new_file('g', base_a, 'g', 'g')
1860
other.tt.new_file('g1', other_b, 'g1', 'g')
1862
base.tt.new_file('h', base_a, 'h', 'h')
1863
this.tt.new_file('h1', this_b, 'h1', 'h')
1865
base.tt.new_file('i', base.root, 'i', 'i')
1866
other.tt.new_directory('i1', this_b, 'i')
1929
1868
for tg in [this, base, other]:
2400
2332
tt = TransformPreview(branch.basis_tree())
2401
2333
self.addCleanup(tt.finalize)
2402
2334
e = self.assertRaises(ValueError, tt.commit, branch,
2403
'my message', [b'rev1b-id'])
2335
'my message', ['rev1b-id'])
2404
2336
self.assertEqual('Cannot supply merge parents for first commit.',
2406
2338
self.assertEqual(_mod_revision.NULL_REVISION, branch.last_revision())
2408
2340
def test_add_files(self):
2409
2341
branch, tt = self.get_branch_and_transform()
2410
tt.new_file('file', tt.root, [b'contents'], b'file-id')
2411
trans_id = tt.new_directory('dir', tt.root, b'dir-id')
2342
tt.new_file('file', tt.root, 'contents', b'file-id')
2343
trans_id = tt.new_directory('dir', tt.root, 'dir-id')
2412
2344
if SymlinkFeature.available():
2413
tt.new_symlink('symlink', trans_id, 'target', b'symlink-id')
2414
tt.commit(branch, 'message')
2345
tt.new_symlink('symlink', trans_id, 'target', 'symlink-id')
2346
rev = tt.commit(branch, 'message')
2415
2347
tree = branch.basis_tree()
2416
2348
self.assertEqual('file', tree.id2path(b'file-id'))
2417
self.assertEqual(b'contents', tree.get_file_text('file'))
2349
self.assertEqual('contents', tree.get_file_text('file', b'file-id'))
2418
2350
self.assertEqual('dir', tree.id2path(b'dir-id'))
2419
2351
if SymlinkFeature.available():
2420
2352
self.assertEqual('dir/symlink', tree.id2path(b'symlink-id'))
2806
2730
revision_tree = self.create_tree()
2807
2731
preview = TransformPreview(revision_tree)
2808
2732
self.addCleanup(preview.finalize)
2809
preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id')
2733
preview.new_file('file2', preview.root, 'content B\n', 'file2-id')
2810
2734
preview_tree = preview.get_preview_tree()
2811
2735
self.assertEqual(preview_tree.kind('file2'), 'file')
2812
with preview_tree.get_file('file2') as f:
2813
self.assertEqual(f.read(), b'content B\n')
2737
preview_tree.get_file('file2', 'file2-id').read(), 'content B\n')
2815
2739
def test_diff_preview_tree(self):
2816
2740
revision_tree = self.create_tree()
2817
2741
preview = TransformPreview(revision_tree)
2818
2742
self.addCleanup(preview.finalize)
2819
preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id')
2743
preview.new_file('file2', preview.root, 'content B\n', 'file2-id')
2820
2744
preview_tree = preview.get_preview_tree()
2821
2745
out = BytesIO()
2822
2746
show_diff_trees(revision_tree, preview_tree, out)
2823
2747
lines = out.getvalue().splitlines()
2824
self.assertEqual(lines[0], b"=== added file 'file2'")
2748
self.assertEqual(lines[0], "=== added file 'file2'")
2825
2749
# 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')
2750
self.assertEqual(lines[4], "+content B")
2856
2752
def test_transform_conflicts(self):
2857
2753
revision_tree = self.create_tree()
2858
2754
preview = TransformPreview(revision_tree)
2859
2755
self.addCleanup(preview.finalize)
2860
preview.new_file('a', preview.root, [b'content 2'])
2756
preview.new_file('a', preview.root, 'content 2')
2861
2757
resolve_conflicts(preview)
2862
trans_id = preview.trans_id_file_id(b'a-id')
2758
trans_id = preview.trans_id_file_id('a-id')
2863
2759
self.assertEqual('a.moved', preview.final_name(trans_id))
2865
2761
def get_tree_and_preview_tree(self):
2866
2762
revision_tree = self.create_tree()
2867
2763
preview = TransformPreview(revision_tree)
2868
2764
self.addCleanup(preview.finalize)
2869
a_trans_id = preview.trans_id_file_id(b'a-id')
2765
a_trans_id = preview.trans_id_file_id('a-id')
2870
2766
preview.delete_contents(a_trans_id)
2871
preview.create_file([b'b content'], a_trans_id)
2767
preview.create_file('b content', a_trans_id)
2872
2768
preview_tree = preview.get_preview_tree()
2873
2769
return revision_tree, preview_tree
2875
2771
def test_iter_changes(self):
2876
2772
revision_tree, preview_tree = self.get_tree_and_preview_tree()
2877
root = revision_tree.path2id('')
2878
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)))
2773
root = revision_tree.get_root_id()
2774
self.assertEqual([('a-id', ('a', 'a'), True, (True, True),
2775
(root, root), ('a', 'a'), ('file', 'file'),
2777
list(preview_tree.iter_changes(revision_tree)))
2883
2779
def test_include_unchanged_succeeds(self):
2884
2780
revision_tree, preview_tree = self.get_tree_and_preview_tree()
2885
2781
changes = preview_tree.iter_changes(revision_tree,
2886
2782
include_unchanged=True)
2783
root = revision_tree.get_root_id()
2887
2785
self.assertEqual([ROOT_ENTRY, A_ENTRY], list(changes))
2889
2787
def test_specific_files(self):
2951
2849
work_tree.add('old', b'old-id')
2952
2850
preview = TransformPreview(work_tree)
2953
2851
self.addCleanup(preview.finalize)
2954
preview.new_file('name', preview.root, [b'contents'], b'new-id',
2852
new_id = preview.new_file('name', preview.root, 'contents', b'new-id',
2956
2854
tree = preview.get_preview_tree()
2957
2855
self.assertEqual(len('old'), tree.get_file_size('old'))
2958
2856
self.assertEqual(len('contents'), tree.get_file_size('name'))
2960
2858
def test_get_file(self):
2961
2859
preview = self.get_empty_preview()
2962
preview.new_file('file', preview.root, [b'contents'], b'file-id')
2860
preview.new_file('file', preview.root, 'contents', b'file-id')
2963
2861
preview_tree = preview.get_preview_tree()
2964
with preview_tree.get_file('file') as tree_file:
2965
self.assertEqual(b'contents', tree_file.read())
2862
tree_file = preview_tree.get_file('file')
2864
self.assertEqual('contents', tree_file.read())
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'))
3278
3174
self.addCleanup(preview.finalize)
3279
3175
trans_id = preview.trans_id_file_id(b'file-id')
3280
3176
preview.delete_contents(trans_id)
3281
preview.create_file([b'b\nc\nd\ne\n'], trans_id)
3177
preview.create_file('b\nc\nd\ne\n', trans_id)
3282
3178
self.build_tree_contents([('wtb/file', b'a\nc\nd\nf\n')])
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, '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, '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):
3461
3359
def default_attribs():
3466
b'_new_executability': {},
3468
b'_tree_path_ids': {b'': b'new-0'},
3470
b'_removed_contents': [],
3471
b'_non_present_ids': {},
3364
'_new_executability': {},
3366
'_tree_path_ids': {'': 'new-0'},
3368
'_removed_contents': [],
3369
'_non_present_ids': {},
3474
3372
def make_records(self, attribs, contents):
3476
((((b'attribs'),),), bencode.bencode(attribs))]
3374
(((('attribs'),),), bencode.bencode(attribs))]
3477
3375
records.extend([(((n, k),), c) for n, k, c in contents])
3480
3378
def creation_records(self):
3481
3379
attribs = self.default_attribs()
3482
attribs[b'_id_number'] = 3
3483
attribs[b'_new_name'] = {
3484
b'new-1': u'foo\u1234'.encode('utf-8'), b'new-2': b'qux'}
3485
attribs[b'_new_id'] = {b'new-1': b'baz', b'new-2': b'quxx'}
3486
attribs[b'_new_parent'] = {b'new-1': b'new-0', b'new-2': b'new-0'}
3487
attribs[b'_new_executability'] = {b'new-1': 1}
3380
attribs['_id_number'] = 3
3381
attribs['_new_name'] = {
3382
'new-1': u'foo\u1234'.encode('utf-8'), 'new-2': 'qux'}
3383
attribs['_new_id'] = {'new-1': 'baz', 'new-2': 'quxx'}
3384
attribs['_new_parent'] = {'new-1': 'new-0', 'new-2': 'new-0'}
3385
attribs['_new_executability'] = {'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', 'i 1\nbar\n'),
3388
('new-2', 'directory', ''),
3492
3390
return self.make_records(attribs, contents)
3494
3392
def test_serialize_creation(self):
3495
3393
tt = self.get_preview()
3496
tt.new_file(u'foo\u1234', tt.root, [b'bar'], b'baz', True)
3497
tt.new_directory('qux', tt.root, b'quxx')
3394
tt.new_file(u'foo\u1234', tt.root, 'bar', 'baz', True)
3395
tt.new_directory('qux', tt.root, 'quxx')
3498
3396
self.assertSerializesTo(self.creation_records(), tt)
3500
3398
def test_deserialize_creation(self):