655
736
(False, False))],
656
737
self.do_iter_changes(tree1, tree2))
739
def test_specific_content_modification_grabs_parents(self):
740
# WHen the only direct change to a specified file is a content change,
741
# and its in a reparented subtree, the parents are grabbed.
742
tree1 = self.make_branch_and_tree('1')
743
tree1.mkdir('changing', 'parent-id')
744
tree1.mkdir('changing/unchanging', 'mid-id')
745
tree1.add(['changing/unchanging/file'], ['file-id'], ['file'])
746
tree1.put_file_bytes_non_atomic('file-id', 'a file')
747
tree2 = self.make_to_branch_and_tree('2')
748
tree2.set_root_id(tree1.get_root_id())
749
tree2.mkdir('changed', 'parent-id')
750
tree2.mkdir('changed/unchanging', 'mid-id')
751
tree2.add(['changed/unchanging/file'], ['file-id'], ['file'])
752
tree2.put_file_bytes_non_atomic('file-id', 'changed content')
753
tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
754
# parent-id has changed, as has file-id
755
root_id = tree1.path2id('')
756
self.assertEqualIterChanges(
757
[self.renamed(tree1, tree2, 'parent-id', False),
758
self.renamed(tree1, tree2, 'file-id', True)],
759
self.do_iter_changes(tree1, tree2,
760
specific_files=['changed/unchanging/file']))
762
def test_specific_content_modification_grabs_parents_root_changes(self):
763
# WHen the only direct change to a specified file is a content change,
764
# and its in a reparented subtree, the parents are grabbed, even if
765
# that includes the root.
766
tree1 = self.make_branch_and_tree('1')
767
tree1.set_root_id('old')
768
tree1.mkdir('changed', 'parent-id')
769
tree1.mkdir('changed/unchanging', 'mid-id')
770
tree1.add(['changed/unchanging/file'], ['file-id'], ['file'])
771
tree1.put_file_bytes_non_atomic('file-id', 'a file')
772
tree2 = self.make_to_branch_and_tree('2')
773
tree2.set_root_id('new')
774
tree2.mkdir('changed', 'parent-id')
775
tree2.mkdir('changed/unchanging', 'mid-id')
776
tree2.add(['changed/unchanging/file'], ['file-id'], ['file'])
777
tree2.put_file_bytes_non_atomic('file-id', 'changed content')
778
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
779
# old is gone, new is added, parent-id has changed(reparented), as has
781
root_id = tree1.path2id('')
782
self.assertEqualIterChanges(
783
[self.renamed(tree1, tree2, 'parent-id', False),
784
self.added(tree2, 'new'),
785
self.deleted(tree1, 'old'),
786
self.renamed(tree1, tree2, 'file-id', True)],
787
self.do_iter_changes(tree1, tree2,
788
specific_files=['changed/unchanging/file']))
790
def test_specific_with_rename_under_new_dir_reports_new_dir(self):
791
tree1 = self.make_branch_and_tree('1')
792
tree2 = self.make_to_branch_and_tree('2')
793
tree1 = self.get_tree_no_parents_abc_content(tree1)
794
tree2 = self.get_tree_no_parents_abc_content_7(tree2)
795
tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
796
# d(d-id) is new, e is b-id renamed.
797
root_id = tree1.path2id('')
798
self.assertEqualIterChanges(
799
[self.renamed(tree1, tree2, 'b-id', False),
800
self.added(tree2, 'd-id')],
801
self.do_iter_changes(tree1, tree2, specific_files=['d/e']))
803
def test_specific_with_rename_under_dir_under_new_dir_reports_new_dir(self):
804
tree1 = self.make_branch_and_tree('1')
805
tree2 = self.make_to_branch_and_tree('2')
806
tree1 = self.get_tree_no_parents_abc_content(tree1)
807
tree2 = self.get_tree_no_parents_abc_content_7(tree2)
808
tree2.rename_one('a', 'd/e/a')
809
tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
810
# d is new, d/e is b-id renamed, d/e/a is a-id renamed
811
root_id = tree1.path2id('')
812
self.assertEqualIterChanges(
813
[self.renamed(tree1, tree2, 'b-id', False),
814
self.added(tree2, 'd-id'),
815
self.renamed(tree1, tree2, 'a-id', False)],
816
self.do_iter_changes(tree1, tree2, specific_files=['d/e/a']))
818
def test_specific_old_parent_same_path_new_parent(self):
819
# when a parent is new at its path, if the path was used in the source
820
# it must be emitted as a change.
821
tree1 = self.make_branch_and_tree('1')
822
tree1.add(['a'], ['a-id'], ['file'])
823
tree1.put_file_bytes_non_atomic('a-id', 'a file')
824
tree2 = self.make_to_branch_and_tree('2')
825
tree2.set_root_id(tree1.get_root_id())
826
tree2.mkdir('a', 'b-id')
827
tree2.add(['a/c'], ['c-id'], ['file'])
828
tree2.put_file_bytes_non_atomic('c-id', 'another file')
829
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
830
# a-id is gone, b-id and c-id are added.
831
self.assertEqualIterChanges(
832
[self.deleted(tree1, 'a-id'),
833
self.added(tree2, 'b-id'),
834
self.added(tree2, 'c-id')],
835
self.do_iter_changes(tree1, tree2, specific_files=['a/c']))
837
def test_specific_old_parent_becomes_file(self):
838
# When an old parent included because of a path conflict becomes a
839
# non-directory, its children have to be all included in the delta.
840
tree1 = self.make_branch_and_tree('1')
841
tree1.mkdir('a', 'a-old-id')
842
tree1.mkdir('a/reparented', 'reparented-id')
843
tree1.mkdir('a/deleted', 'deleted-id')
844
tree2 = self.make_to_branch_and_tree('2')
845
tree2.set_root_id(tree1.get_root_id())
846
tree2.mkdir('a', 'a-new-id')
847
tree2.mkdir('a/reparented', 'reparented-id')
848
tree2.add(['b'], ['a-old-id'], ['file'])
849
tree2.put_file_bytes_non_atomic('a-old-id', '')
850
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
851
# a-old-id is kind-changed, a-new-id is added, reparented-id is renamed,
853
self.assertEqualIterChanges(
854
[self.kind_changed(tree1, tree2, 'a-old-id'),
855
self.added(tree2, 'a-new-id'),
856
self.renamed(tree1, tree2, 'reparented-id', False),
857
self.deleted(tree1, 'deleted-id')],
858
self.do_iter_changes(tree1, tree2,
859
specific_files=['a/reparented']))
861
def test_specific_old_parent_is_deleted(self):
862
# When an old parent included because of a path conflict is removed,
863
# its children have to be all included in the delta.
864
tree1 = self.make_branch_and_tree('1')
865
tree1.mkdir('a', 'a-old-id')
866
tree1.mkdir('a/reparented', 'reparented-id')
867
tree1.mkdir('a/deleted', 'deleted-id')
868
tree2 = self.make_to_branch_and_tree('2')
869
tree2.set_root_id(tree1.get_root_id())
870
tree2.mkdir('a', 'a-new-id')
871
tree2.mkdir('a/reparented', 'reparented-id')
872
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
873
# a-old-id is gone, a-new-id is added, reparented-id is renamed,
875
self.assertEqualIterChanges(
876
[self.deleted(tree1, 'a-old-id'),
877
self.added(tree2, 'a-new-id'),
878
self.renamed(tree1, tree2, 'reparented-id', False),
879
self.deleted(tree1, 'deleted-id')],
880
self.do_iter_changes(tree1, tree2,
881
specific_files=['a/reparented']))
883
def test_specific_old_parent_child_collides_with_unselected_new(self):
884
# When the child of an old parent because of a path conflict becomes a
885
# path conflict with some unselected item in the source, that item also
886
# needs to be included (because otherwise the output of applying the
887
# delta to the source would have two items at that path).
888
tree1 = self.make_branch_and_tree('1')
889
tree1.mkdir('a', 'a-old-id')
890
tree1.mkdir('a/reparented', 'reparented-id')
891
tree1.mkdir('collides', 'collides-id')
892
tree2 = self.make_to_branch_and_tree('2')
893
tree2.set_root_id(tree1.get_root_id())
894
tree2.mkdir('a', 'a-new-id')
895
tree2.mkdir('a/selected', 'selected-id')
896
tree2.mkdir('collides', 'reparented-id')
897
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
898
# a-old-id is one, a-new-id is added, reparented-id is renamed,
899
# collides-id is gone, selected-id is new.
900
self.assertEqualIterChanges(
901
[self.deleted(tree1, 'a-old-id'),
902
self.added(tree2, 'a-new-id'),
903
self.renamed(tree1, tree2, 'reparented-id', False),
904
self.deleted(tree1, 'collides-id'),
905
self.added(tree2, 'selected-id')],
906
self.do_iter_changes(tree1, tree2,
907
specific_files=['a/selected']))
909
def test_specific_old_parent_child_dir_stops_being_dir(self):
910
# When the child of an old parent also stops being a directory, its
911
# children must also be included. This test checks that downward
912
# recursion is done appropriately by starting at a child of the root of
913
# a deleted subtree (a/reparented), and checking that a sibling
914
# directory (a/deleted) has its children included in the delta.
915
tree1 = self.make_branch_and_tree('1')
916
tree1.mkdir('a', 'a-old-id')
917
tree1.mkdir('a/reparented', 'reparented-id-1')
918
tree1.mkdir('a/deleted', 'deleted-id-1')
919
tree1.mkdir('a/deleted/reparented', 'reparented-id-2')
920
tree1.mkdir('a/deleted/deleted', 'deleted-id-2')
921
tree2 = self.make_to_branch_and_tree('2')
922
tree2.set_root_id(tree1.get_root_id())
923
tree2.mkdir('a', 'a-new-id')
924
tree2.mkdir('a/reparented', 'reparented-id-1')
925
tree2.mkdir('reparented', 'reparented-id-2')
926
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
927
# a-old-id is gone, a-new-id is added, reparented-id-1, -2 are renamed,
928
# deleted-id-1 and -2 are gone.
929
self.assertEqualIterChanges(
930
[self.deleted(tree1, 'a-old-id'),
931
self.added(tree2, 'a-new-id'),
932
self.renamed(tree1, tree2, 'reparented-id-1', False),
933
self.renamed(tree1, tree2, 'reparented-id-2', False),
934
self.deleted(tree1, 'deleted-id-1'),
935
self.deleted(tree1, 'deleted-id-2')],
936
self.do_iter_changes(tree1, tree2,
937
specific_files=['a/reparented']))
658
939
def test_file_rename_and_meta_modification(self):
659
940
tree1 = self.make_branch_and_tree('1')
660
941
tree2 = self.make_to_branch_and_tree('2')