488
519
self.assertEqual(find_interesting(wt, wt, ['vfile']),
489
520
set(['myfile-id']))
490
self.assertRaises(NotVersionedError, find_interesting, wt, wt,
521
self.assertRaises(PathsNotVersionedError, find_interesting, wt, wt,
524
def test_set_executability_order(self):
525
"""Ensure that executability behaves the same, no matter what order.
527
- create file and set executability simultaneously
528
- create file and set executability afterward
529
- unsetting the executability of a file whose executability has not been
530
declared should throw an exception (this may happen when a
531
merge attempts to create a file with a duplicate ID)
533
transform, root = self.get_transform()
535
transform.new_file('set_on_creation', root, 'Set on creation', 'soc',
537
sac = transform.new_file('set_after_creation', root, 'Set after creation', 'sac')
538
transform.set_executability(True, sac)
539
uws = transform.new_file('unset_without_set', root, 'Unset badly', 'uws')
540
self.assertRaises(KeyError, transform.set_executability, None, uws)
542
self.assertTrue(wt.is_executable('soc'))
543
self.assertTrue(wt.is_executable('sac'))
545
def test_preserve_mode(self):
546
"""File mode is preserved when replacing content"""
547
if sys.platform == 'win32':
548
raise TestSkipped('chmod has no effect on win32')
549
transform, root = self.get_transform()
550
transform.new_file('file1', root, 'contents', 'file1-id', True)
552
self.assertTrue(self.wt.is_executable('file1-id'))
553
transform, root = self.get_transform()
554
file1_id = transform.trans_id_tree_file_id('file1-id')
555
transform.delete_contents(file1_id)
556
transform.create_file('contents2', file1_id)
558
self.assertTrue(self.wt.is_executable('file1-id'))
560
def test__set_mode_stats_correctly(self):
561
"""_set_mode stats to determine file mode."""
562
if sys.platform == 'win32':
563
raise TestSkipped('chmod has no effect on win32')
567
def instrumented_stat(path):
568
stat_paths.append(path)
569
return real_stat(path)
571
transform, root = self.get_transform()
573
bar1_id = transform.new_file('bar', root, 'bar contents 1\n',
574
file_id='bar-id-1', executable=False)
577
transform, root = self.get_transform()
578
bar1_id = transform.trans_id_tree_path('bar')
579
bar2_id = transform.trans_id_tree_path('bar2')
581
os.stat = instrumented_stat
582
transform.create_file('bar2 contents\n', bar2_id, mode_id=bar1_id)
587
bar1_abspath = self.wt.abspath('bar')
588
self.assertEqual([bar1_abspath], stat_paths)
590
def test_iter_changes(self):
591
transform, root = self.get_transform()
592
transform.new_file('old', root, 'blah', 'id-1', True)
594
transform, root = self.get_transform()
596
self.assertEqual([], list(transform._iter_changes()))
597
old = transform.trans_id_tree_file_id('id-1')
598
transform.unversion_file(old)
599
self.assertEqual([('id-1', 'old', False, (True, False),
600
('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
601
(True, True))], list(transform._iter_changes()))
602
transform.new_directory('new', root, 'id-1')
603
self.assertEqual([('id-1', 'new', True, (True, True),
604
('TREE_ROOT', 'TREE_ROOT'), ('old', 'new'),
605
('file', 'directory'),
606
(True, False))], list(transform._iter_changes()))
610
def test_iter_changes_new(self):
611
transform, root = self.get_transform()
612
transform.new_file('old', root, 'blah')
614
transform, root = self.get_transform()
616
old = transform.trans_id_tree_path('old')
617
transform.version_file('id-1', old)
618
self.assertEqual([('id-1', 'old', False, (False, True),
619
('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
620
(False, False))], list(transform._iter_changes()))
624
def test_iter_changes_modifications(self):
625
transform, root = self.get_transform()
626
transform.new_file('old', root, 'blah', 'id-1')
627
transform.new_file('new', root, 'blah')
628
transform.new_directory('subdir', root, 'subdir-id')
630
transform, root = self.get_transform()
632
old = transform.trans_id_tree_path('old')
633
subdir = transform.trans_id_tree_file_id('subdir-id')
634
new = transform.trans_id_tree_path('new')
635
self.assertEqual([], list(transform._iter_changes()))
638
transform.delete_contents(old)
639
self.assertEqual([('id-1', 'old', True, (True, True),
640
('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', None),
641
(False, False))], list(transform._iter_changes()))
644
transform.create_file('blah', old)
645
self.assertEqual([('id-1', 'old', True, (True, True),
646
('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
647
(False, False))], list(transform._iter_changes()))
648
transform.cancel_deletion(old)
649
self.assertEqual([('id-1', 'old', True, (True, True),
650
('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
651
(False, False))], list(transform._iter_changes()))
652
transform.cancel_creation(old)
654
# move file_id to a different file
655
self.assertEqual([], list(transform._iter_changes()))
656
transform.unversion_file(old)
657
transform.version_file('id-1', new)
658
transform.adjust_path('old', root, new)
659
self.assertEqual([('id-1', 'old', True, (True, True),
660
('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
661
(False, False))], list(transform._iter_changes()))
662
transform.cancel_versioning(new)
663
transform._removed_id = set()
666
self.assertEqual([], list(transform._iter_changes()))
667
transform.set_executability(True, old)
668
self.assertEqual([('id-1', 'old', False, (True, True),
669
('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
670
(False, True))], list(transform._iter_changes()))
671
transform.set_executability(None, old)
674
self.assertEqual([], list(transform._iter_changes()))
675
transform.adjust_path('new', root, old)
676
transform._new_parent = {}
677
self.assertEqual([('id-1', 'new', False, (True, True),
678
('TREE_ROOT', 'TREE_ROOT'), ('old', 'new'), ('file', 'file'),
679
(False, False))], list(transform._iter_changes()))
680
transform._new_name = {}
683
self.assertEqual([], list(transform._iter_changes()))
684
transform.adjust_path('new', subdir, old)
685
transform._new_name = {}
686
self.assertEqual([('id-1', 'subdir/old', False, (True, True),
687
('TREE_ROOT', 'subdir-id'), ('old', 'old'), ('file', 'file'),
688
(False, False))], list(transform._iter_changes()))
689
transform._new_path = {}
694
def test_iter_changes_modified_bleed(self):
695
"""Modified flag should not bleed from one change to another"""
696
# unfortunately, we have no guarantee that file1 (which is modified)
697
# will be applied before file2. And if it's applied after file2, it
698
# obviously can't bleed into file2's change output. But for now, it
700
transform, root = self.get_transform()
701
transform.new_file('file1', root, 'blah', 'id-1')
702
transform.new_file('file2', root, 'blah', 'id-2')
704
transform, root = self.get_transform()
706
transform.delete_contents(transform.trans_id_file_id('id-1'))
707
transform.set_executability(True,
708
transform.trans_id_file_id('id-2'))
709
self.assertEqual([('id-1', u'file1', True, (True, True),
710
('TREE_ROOT', 'TREE_ROOT'), ('file1', u'file1'),
711
('file', None), (False, False)),
712
('id-2', u'file2', False, (True, True),
713
('TREE_ROOT', 'TREE_ROOT'), ('file2', u'file2'),
714
('file', 'file'), (False, True))],
715
list(transform._iter_changes()))
719
def test_iter_changes_pointless(self):
720
"""Ensure that no-ops are not treated as modifications"""
721
transform, root = self.get_transform()
722
transform.new_file('old', root, 'blah', 'id-1')
723
transform.new_directory('subdir', root, 'subdir-id')
725
transform, root = self.get_transform()
727
old = transform.trans_id_tree_path('old')
728
subdir = transform.trans_id_tree_file_id('subdir-id')
729
self.assertEqual([], list(transform._iter_changes()))
730
transform.delete_contents(subdir)
731
transform.create_directory(subdir)
732
transform.set_executability(False, old)
733
transform.unversion_file(old)
734
transform.version_file('id-1', old)
735
transform.adjust_path('old', root, old)
736
self.assertEqual([], list(transform._iter_changes()))
494
740
class TransformGroup(object):
495
def __init__(self, dirname):
741
def __init__(self, dirname, root_id):
496
742
self.name = dirname
497
743
os.mkdir(dirname)
498
744
self.wt = BzrDir.create_standalone_workingtree(dirname)
745
self.wt.set_root_id(root_id)
499
746
self.b = self.wt.branch
500
747
self.tt = TreeTransform(self.wt)
501
748
self.root = self.tt.trans_id_tree_file_id(self.wt.get_root_id())
503
751
def conflict_text(tree, merge):
504
752
template = '%s TREE\n%s%s\n%s%s MERGE-SOURCE\n'
505
753
return template % ('<' * 7, tree, '=' * 7, merge, '>' * 7)
702
956
self.assertIs(os.path.isdir('b/foo'), True)
703
957
self.assertEqual(file('b/foo/bar', 'rb').read(), "contents")
704
958
self.assertEqual(os.readlink('b/foo/baz'), 'a/foo/bar')
960
def test_file_conflict_handling(self):
961
"""Ensure that when building trees, conflict handling is done"""
962
source = self.make_branch_and_tree('source')
963
target = self.make_branch_and_tree('target')
964
self.build_tree(['source/file', 'target/file'])
965
source.add('file', 'new-file')
966
source.commit('added file')
967
build_tree(source.basis_tree(), target)
968
self.assertEqual([DuplicateEntry('Moved existing file to',
969
'file.moved', 'file', None, 'new-file')],
971
target2 = self.make_branch_and_tree('target2')
972
target_file = file('target2/file', 'wb')
974
source_file = file('source/file', 'rb')
976
target_file.write(source_file.read())
981
build_tree(source.basis_tree(), target2)
982
self.assertEqual([], target2.conflicts())
984
def test_symlink_conflict_handling(self):
985
"""Ensure that when building trees, conflict handling is done"""
986
if not has_symlinks():
987
raise TestSkipped('Test requires symlink support')
988
source = self.make_branch_and_tree('source')
989
os.symlink('foo', 'source/symlink')
990
source.add('symlink', 'new-symlink')
991
source.commit('added file')
992
target = self.make_branch_and_tree('target')
993
os.symlink('bar', 'target/symlink')
994
build_tree(source.basis_tree(), target)
995
self.assertEqual([DuplicateEntry('Moved existing file to',
996
'symlink.moved', 'symlink', None, 'new-symlink')],
998
target = self.make_branch_and_tree('target2')
999
os.symlink('foo', 'target2/symlink')
1000
build_tree(source.basis_tree(), target)
1001
self.assertEqual([], target.conflicts())
1003
def test_directory_conflict_handling(self):
1004
"""Ensure that when building trees, conflict handling is done"""
1005
source = self.make_branch_and_tree('source')
1006
target = self.make_branch_and_tree('target')
1007
self.build_tree(['source/dir1/', 'source/dir1/file', 'target/dir1/'])
1008
source.add(['dir1', 'dir1/file'], ['new-dir1', 'new-file'])
1009
source.commit('added file')
1010
build_tree(source.basis_tree(), target)
1011
self.assertEqual([], target.conflicts())
1012
self.failUnlessExists('target/dir1/file')
1014
# Ensure contents are merged
1015
target = self.make_branch_and_tree('target2')
1016
self.build_tree(['target2/dir1/', 'target2/dir1/file2'])
1017
build_tree(source.basis_tree(), target)
1018
self.assertEqual([], target.conflicts())
1019
self.failUnlessExists('target2/dir1/file2')
1020
self.failUnlessExists('target2/dir1/file')
1022
# Ensure new contents are suppressed for existing branches
1023
target = self.make_branch_and_tree('target3')
1024
self.make_branch('target3/dir1')
1025
self.build_tree(['target3/dir1/file2'])
1026
build_tree(source.basis_tree(), target)
1027
self.failIfExists('target3/dir1/file')
1028
self.failUnlessExists('target3/dir1/file2')
1029
self.failUnlessExists('target3/dir1.diverted/file')
1030
self.assertEqual([DuplicateEntry('Diverted to',
1031
'dir1.diverted', 'dir1', 'new-dir1', None)],
1034
target = self.make_branch_and_tree('target4')
1035
self.build_tree(['target4/dir1/'])
1036
self.make_branch('target4/dir1/file')
1037
build_tree(source.basis_tree(), target)
1038
self.failUnlessExists('target4/dir1/file')
1039
self.assertEqual('directory', file_kind('target4/dir1/file'))
1040
self.failUnlessExists('target4/dir1/file.diverted')
1041
self.assertEqual([DuplicateEntry('Diverted to',
1042
'dir1/file.diverted', 'dir1/file', 'new-file', None)],
1045
def test_mixed_conflict_handling(self):
1046
"""Ensure that when building trees, conflict handling is done"""
1047
source = self.make_branch_and_tree('source')
1048
target = self.make_branch_and_tree('target')
1049
self.build_tree(['source/name', 'target/name/'])
1050
source.add('name', 'new-name')
1051
source.commit('added file')
1052
build_tree(source.basis_tree(), target)
1053
self.assertEqual([DuplicateEntry('Moved existing file to',
1054
'name.moved', 'name', None, 'new-name')], target.conflicts())
1056
def test_raises_in_populated(self):
1057
source = self.make_branch_and_tree('source')
1058
self.build_tree(['source/name'])
1060
source.commit('added name')
1061
target = self.make_branch_and_tree('target')
1062
self.build_tree(['target/name'])
1064
self.assertRaises(errors.WorkingTreeAlreadyPopulated,
1065
build_tree, source.basis_tree(), target)
706
1068
class MockTransform(object):
708
1070
def has_named_child(self, by_parent, parent_id, name):