485
528
create.new_file('vfile', root, 'myfile-text', 'myfile-id')
486
529
create.new_file('uvfile', root, 'othertext')
488
self.assertEqual(find_interesting(wt, wt, ['vfile']),
490
self.assertRaises(NotVersionedError, find_interesting, wt, wt,
531
result = self.applyDeprecated(symbol_versioning.zero_fifteen,
532
find_interesting, wt, wt, ['vfile'])
533
self.assertEqual(result, set(['myfile-id']))
535
def test_set_executability_order(self):
536
"""Ensure that executability behaves the same, no matter what order.
538
- create file and set executability simultaneously
539
- create file and set executability afterward
540
- unsetting the executability of a file whose executability has not been
541
declared should throw an exception (this may happen when a
542
merge attempts to create a file with a duplicate ID)
544
transform, root = self.get_transform()
546
transform.new_file('set_on_creation', root, 'Set on creation', 'soc',
548
sac = transform.new_file('set_after_creation', root, 'Set after creation', 'sac')
549
transform.set_executability(True, sac)
550
uws = transform.new_file('unset_without_set', root, 'Unset badly', 'uws')
551
self.assertRaises(KeyError, transform.set_executability, None, uws)
553
self.assertTrue(wt.is_executable('soc'))
554
self.assertTrue(wt.is_executable('sac'))
556
def test_preserve_mode(self):
557
"""File mode is preserved when replacing content"""
558
if sys.platform == 'win32':
559
raise TestSkipped('chmod has no effect on win32')
560
transform, root = self.get_transform()
561
transform.new_file('file1', root, 'contents', 'file1-id', True)
563
self.assertTrue(self.wt.is_executable('file1-id'))
564
transform, root = self.get_transform()
565
file1_id = transform.trans_id_tree_file_id('file1-id')
566
transform.delete_contents(file1_id)
567
transform.create_file('contents2', file1_id)
569
self.assertTrue(self.wt.is_executable('file1-id'))
571
def test__set_mode_stats_correctly(self):
572
"""_set_mode stats to determine file mode."""
573
if sys.platform == 'win32':
574
raise TestSkipped('chmod has no effect on win32')
578
def instrumented_stat(path):
579
stat_paths.append(path)
580
return real_stat(path)
582
transform, root = self.get_transform()
584
bar1_id = transform.new_file('bar', root, 'bar contents 1\n',
585
file_id='bar-id-1', executable=False)
588
transform, root = self.get_transform()
589
bar1_id = transform.trans_id_tree_path('bar')
590
bar2_id = transform.trans_id_tree_path('bar2')
592
os.stat = instrumented_stat
593
transform.create_file('bar2 contents\n', bar2_id, mode_id=bar1_id)
598
bar1_abspath = self.wt.abspath('bar')
599
self.assertEqual([bar1_abspath], stat_paths)
601
def test_iter_changes(self):
602
self.wt.set_root_id('eert_toor')
603
transform, root = self.get_transform()
604
transform.new_file('old', root, 'blah', 'id-1', True)
606
transform, root = self.get_transform()
608
self.assertEqual([], list(transform._iter_changes()))
609
old = transform.trans_id_tree_file_id('id-1')
610
transform.unversion_file(old)
611
self.assertEqual([('id-1', ('old', None), False, (True, False),
612
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
613
(True, True))], list(transform._iter_changes()))
614
transform.new_directory('new', root, 'id-1')
615
self.assertEqual([('id-1', ('old', 'new'), True, (True, True),
616
('eert_toor', 'eert_toor'), ('old', 'new'),
617
('file', 'directory'),
618
(True, False))], list(transform._iter_changes()))
622
def test_iter_changes_new(self):
623
self.wt.set_root_id('eert_toor')
624
transform, root = self.get_transform()
625
transform.new_file('old', root, 'blah')
627
transform, root = self.get_transform()
629
old = transform.trans_id_tree_path('old')
630
transform.version_file('id-1', old)
631
self.assertEqual([('id-1', (None, 'old'), False, (False, True),
632
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
633
(False, False))], list(transform._iter_changes()))
637
def test_iter_changes_modifications(self):
638
self.wt.set_root_id('eert_toor')
639
transform, root = self.get_transform()
640
transform.new_file('old', root, 'blah', 'id-1')
641
transform.new_file('new', root, 'blah')
642
transform.new_directory('subdir', root, 'subdir-id')
644
transform, root = self.get_transform()
646
old = transform.trans_id_tree_path('old')
647
subdir = transform.trans_id_tree_file_id('subdir-id')
648
new = transform.trans_id_tree_path('new')
649
self.assertEqual([], list(transform._iter_changes()))
652
transform.delete_contents(old)
653
self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
654
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', None),
655
(False, False))], list(transform._iter_changes()))
658
transform.create_file('blah', old)
659
self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
660
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
661
(False, False))], list(transform._iter_changes()))
662
transform.cancel_deletion(old)
663
self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
664
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
665
(False, False))], list(transform._iter_changes()))
666
transform.cancel_creation(old)
668
# move file_id to a different file
669
self.assertEqual([], list(transform._iter_changes()))
670
transform.unversion_file(old)
671
transform.version_file('id-1', new)
672
transform.adjust_path('old', root, new)
673
self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
674
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
675
(False, False))], list(transform._iter_changes()))
676
transform.cancel_versioning(new)
677
transform._removed_id = set()
680
self.assertEqual([], list(transform._iter_changes()))
681
transform.set_executability(True, old)
682
self.assertEqual([('id-1', ('old', 'old'), False, (True, True),
683
('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
684
(False, True))], list(transform._iter_changes()))
685
transform.set_executability(None, old)
688
self.assertEqual([], list(transform._iter_changes()))
689
transform.adjust_path('new', root, old)
690
transform._new_parent = {}
691
self.assertEqual([('id-1', ('old', 'new'), False, (True, True),
692
('eert_toor', 'eert_toor'), ('old', 'new'), ('file', 'file'),
693
(False, False))], list(transform._iter_changes()))
694
transform._new_name = {}
697
self.assertEqual([], list(transform._iter_changes()))
698
transform.adjust_path('new', subdir, old)
699
transform._new_name = {}
700
self.assertEqual([('id-1', ('old', 'subdir/old'), False,
701
(True, True), ('eert_toor', 'subdir-id'), ('old', 'old'),
702
('file', 'file'), (False, False))],
703
list(transform._iter_changes()))
704
transform._new_path = {}
709
def test_iter_changes_modified_bleed(self):
710
self.wt.set_root_id('eert_toor')
711
"""Modified flag should not bleed from one change to another"""
712
# unfortunately, we have no guarantee that file1 (which is modified)
713
# will be applied before file2. And if it's applied after file2, it
714
# obviously can't bleed into file2's change output. But for now, it
716
transform, root = self.get_transform()
717
transform.new_file('file1', root, 'blah', 'id-1')
718
transform.new_file('file2', root, 'blah', 'id-2')
720
transform, root = self.get_transform()
722
transform.delete_contents(transform.trans_id_file_id('id-1'))
723
transform.set_executability(True,
724
transform.trans_id_file_id('id-2'))
725
self.assertEqual([('id-1', (u'file1', u'file1'), True, (True, True),
726
('eert_toor', 'eert_toor'), ('file1', u'file1'),
727
('file', None), (False, False)),
728
('id-2', (u'file2', u'file2'), False, (True, True),
729
('eert_toor', 'eert_toor'), ('file2', u'file2'),
730
('file', 'file'), (False, True))],
731
list(transform._iter_changes()))
735
def test_iter_changes_move_missing(self):
736
"""Test moving ids with no files around"""
737
self.wt.set_root_id('toor_eert')
738
# Need two steps because versioning a non-existant file is a conflict.
739
transform, root = self.get_transform()
740
transform.new_directory('floater', root, 'floater-id')
742
transform, root = self.get_transform()
743
transform.delete_contents(transform.trans_id_tree_path('floater'))
745
transform, root = self.get_transform()
746
floater = transform.trans_id_tree_path('floater')
748
transform.adjust_path('flitter', root, floater)
749
self.assertEqual([('floater-id', ('floater', 'flitter'), False,
750
(True, True), ('toor_eert', 'toor_eert'), ('floater', 'flitter'),
751
(None, None), (False, False))], list(transform._iter_changes()))
755
def test_iter_changes_pointless(self):
756
"""Ensure that no-ops are not treated as modifications"""
757
self.wt.set_root_id('eert_toor')
758
transform, root = self.get_transform()
759
transform.new_file('old', root, 'blah', 'id-1')
760
transform.new_directory('subdir', root, 'subdir-id')
762
transform, root = self.get_transform()
764
old = transform.trans_id_tree_path('old')
765
subdir = transform.trans_id_tree_file_id('subdir-id')
766
self.assertEqual([], list(transform._iter_changes()))
767
transform.delete_contents(subdir)
768
transform.create_directory(subdir)
769
transform.set_executability(False, old)
770
transform.unversion_file(old)
771
transform.version_file('id-1', old)
772
transform.adjust_path('old', root, old)
773
self.assertEqual([], list(transform._iter_changes()))
494
777
class TransformGroup(object):
495
def __init__(self, dirname):
778
def __init__(self, dirname, root_id):
496
779
self.name = dirname
497
780
os.mkdir(dirname)
498
781
self.wt = BzrDir.create_standalone_workingtree(dirname)
782
self.wt.set_root_id(root_id)
499
783
self.b = self.wt.branch
500
784
self.tt = TreeTransform(self.wt)
501
785
self.root = self.tt.trans_id_tree_file_id(self.wt.get_root_id())
503
788
def conflict_text(tree, merge):
504
789
template = '%s TREE\n%s%s\n%s%s MERGE-SOURCE\n'
505
790
return template % ('<' * 7, tree, '=' * 7, merge, '>' * 7)
698
989
a.add(['foo', 'foo/bar', 'foo/baz'])
699
990
a.commit('initial commit')
700
991
b = BzrDir.create_standalone_workingtree('b')
701
build_tree(a.basis_tree(), b)
992
basis = a.basis_tree()
994
self.addCleanup(basis.unlock)
702
996
self.assertIs(os.path.isdir('b/foo'), True)
703
997
self.assertEqual(file('b/foo/bar', 'rb').read(), "contents")
704
998
self.assertEqual(os.readlink('b/foo/baz'), 'a/foo/bar')
1000
def test_build_with_references(self):
1001
tree = self.make_branch_and_tree('source',
1002
format='dirstate-with-subtree')
1003
subtree = self.make_branch_and_tree('source/subtree',
1004
format='dirstate-with-subtree')
1005
tree.add_reference(subtree)
1006
tree.commit('a revision')
1007
tree.branch.create_checkout('target')
1008
self.failUnlessExists('target')
1009
self.failUnlessExists('target/subtree')
1011
def test_file_conflict_handling(self):
1012
"""Ensure that when building trees, conflict handling is done"""
1013
source = self.make_branch_and_tree('source')
1014
target = self.make_branch_and_tree('target')
1015
self.build_tree(['source/file', 'target/file'])
1016
source.add('file', 'new-file')
1017
source.commit('added file')
1018
build_tree(source.basis_tree(), target)
1019
self.assertEqual([DuplicateEntry('Moved existing file to',
1020
'file.moved', 'file', None, 'new-file')],
1022
target2 = self.make_branch_and_tree('target2')
1023
target_file = file('target2/file', 'wb')
1025
source_file = file('source/file', 'rb')
1027
target_file.write(source_file.read())
1032
build_tree(source.basis_tree(), target2)
1033
self.assertEqual([], target2.conflicts())
1035
def test_symlink_conflict_handling(self):
1036
"""Ensure that when building trees, conflict handling is done"""
1037
if not has_symlinks():
1038
raise TestSkipped('Test requires symlink support')
1039
source = self.make_branch_and_tree('source')
1040
os.symlink('foo', 'source/symlink')
1041
source.add('symlink', 'new-symlink')
1042
source.commit('added file')
1043
target = self.make_branch_and_tree('target')
1044
os.symlink('bar', 'target/symlink')
1045
build_tree(source.basis_tree(), target)
1046
self.assertEqual([DuplicateEntry('Moved existing file to',
1047
'symlink.moved', 'symlink', None, 'new-symlink')],
1049
target = self.make_branch_and_tree('target2')
1050
os.symlink('foo', 'target2/symlink')
1051
build_tree(source.basis_tree(), target)
1052
self.assertEqual([], target.conflicts())
1054
def test_directory_conflict_handling(self):
1055
"""Ensure that when building trees, conflict handling is done"""
1056
source = self.make_branch_and_tree('source')
1057
target = self.make_branch_and_tree('target')
1058
self.build_tree(['source/dir1/', 'source/dir1/file', 'target/dir1/'])
1059
source.add(['dir1', 'dir1/file'], ['new-dir1', 'new-file'])
1060
source.commit('added file')
1061
build_tree(source.basis_tree(), target)
1062
self.assertEqual([], target.conflicts())
1063
self.failUnlessExists('target/dir1/file')
1065
# Ensure contents are merged
1066
target = self.make_branch_and_tree('target2')
1067
self.build_tree(['target2/dir1/', 'target2/dir1/file2'])
1068
build_tree(source.basis_tree(), target)
1069
self.assertEqual([], target.conflicts())
1070
self.failUnlessExists('target2/dir1/file2')
1071
self.failUnlessExists('target2/dir1/file')
1073
# Ensure new contents are suppressed for existing branches
1074
target = self.make_branch_and_tree('target3')
1075
self.make_branch('target3/dir1')
1076
self.build_tree(['target3/dir1/file2'])
1077
build_tree(source.basis_tree(), target)
1078
self.failIfExists('target3/dir1/file')
1079
self.failUnlessExists('target3/dir1/file2')
1080
self.failUnlessExists('target3/dir1.diverted/file')
1081
self.assertEqual([DuplicateEntry('Diverted to',
1082
'dir1.diverted', 'dir1', 'new-dir1', None)],
1085
target = self.make_branch_and_tree('target4')
1086
self.build_tree(['target4/dir1/'])
1087
self.make_branch('target4/dir1/file')
1088
build_tree(source.basis_tree(), target)
1089
self.failUnlessExists('target4/dir1/file')
1090
self.assertEqual('directory', file_kind('target4/dir1/file'))
1091
self.failUnlessExists('target4/dir1/file.diverted')
1092
self.assertEqual([DuplicateEntry('Diverted to',
1093
'dir1/file.diverted', 'dir1/file', 'new-file', None)],
1096
def test_mixed_conflict_handling(self):
1097
"""Ensure that when building trees, conflict handling is done"""
1098
source = self.make_branch_and_tree('source')
1099
target = self.make_branch_and_tree('target')
1100
self.build_tree(['source/name', 'target/name/'])
1101
source.add('name', 'new-name')
1102
source.commit('added file')
1103
build_tree(source.basis_tree(), target)
1104
self.assertEqual([DuplicateEntry('Moved existing file to',
1105
'name.moved', 'name', None, 'new-name')], target.conflicts())
1107
def test_raises_in_populated(self):
1108
source = self.make_branch_and_tree('source')
1109
self.build_tree(['source/name'])
1111
source.commit('added name')
1112
target = self.make_branch_and_tree('target')
1113
self.build_tree(['target/name'])
1115
self.assertRaises(errors.WorkingTreeAlreadyPopulated,
1116
build_tree, source.basis_tree(), target)
706
1119
class MockTransform(object):
708
1121
def has_named_child(self, by_parent, parent_id, name):