~bzr-pqm/bzr/bzr.dev

2255.2.152 by Martin Pool
(broken) merge aaron's workingtree format changes
1
# Copyright (C) 2006, 2007 Canonical Ltd
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
16
17
"""Tests for the InterTree.compare() function."""
18
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
19
import os
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
20
import shutil
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
21
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
22
from bzrlib import (
23
    errors,
4503.1.3 by Vincent Ladeuil
Take review comments into account.
24
    mutabletree,
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
25
    tests,
26
    workingtree_4,
27
    )
2321.3.4 by Alexander Belchenko
test intertree_implementations: skip tests with symlinks on platforms that don't have symlinks support
28
from bzrlib.osutils import file_kind, has_symlinks
3619.4.4 by Robert Collins
Review feedback.
29
from bzrlib.tests import TestNotApplicable
4523.1.4 by Martin Pool
Rename remaining *_implementations tests
30
from bzrlib.tests.per_intertree import TestCaseWithTwoTrees
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
31
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
32
# TODO: test the include_root option.
33
# TODO: test that renaming a directory x->y does not emit a rename for the
34
#       child x/a->y/a.
35
# TODO: test that renaming a directory x-> does not emit a rename for the child
36
#        x/a -> y/a when a supplied_files argument gives either 'x/' or 'y/a'
37
#        -> that is, when the renamed parent is not processed by the function.
38
# TODO: test items are only emitted once when a specific_files list names a dir
39
#       whose parent is now a child.
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
40
# TODO: test comparisons between trees with different root ids. mbp 20070301
2255.2.189 by Martin Pool
Add and fix up basic comparison of subtrees.
41
#
42
# TODO: More comparisons between trees with subtrees in different states.
2255.2.236 by Martin Pool
Review cleanups: mostly updating or removing todo comments.
43
#
44
# TODO: Many tests start out by setting the tree roots ids the same, maybe
45
#       that should just be the default for these tests, by changing
46
#       make_branch_and_tree.  mbp 20070307
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
47
48
class TestCompare(TestCaseWithTwoTrees):
49
50
    def test_compare_empty_trees(self):
51
        tree1 = self.make_branch_and_tree('1')
52
        tree2 = self.make_to_branch_and_tree('2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
53
        tree2.set_root_id(tree1.get_root_id())
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
54
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
55
        tree2 = self.get_tree_no_parents_no_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
56
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
57
        d = self.intertree_class(tree1, tree2).compare()
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
58
        self.assertEqual([], d.added)
59
        self.assertEqual([], d.modified)
60
        self.assertEqual([], d.removed)
61
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
62
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
63
64
    def test_empty_to_abc_content(self):
65
        tree1 = self.make_branch_and_tree('1')
66
        tree2 = self.make_to_branch_and_tree('2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
67
        tree2.set_root_id(tree1.get_root_id())
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
68
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
69
        tree2 = self.get_tree_no_parents_abc_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
70
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
71
        d = self.intertree_class(tree1, tree2).compare()
72
        self.assertEqual([('a', 'a-id', 'file'),
73
                          ('b', 'b-id', 'directory'),
74
                          ('b/c', 'c-id', 'file'),
75
                         ], d.added)
76
        self.assertEqual([], d.modified)
77
        self.assertEqual([], d.removed)
78
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
79
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
80
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
81
    def test_dangling(self):
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
82
        # This test depends on the ability for some trees to have a difference
83
        # between a 'versioned present' and 'versioned not present' (aka
84
        # dangling) file. In this test there are two trees each with a separate
85
        # dangling file, and the dangling files should be considered absent for
86
        # the test.
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
87
        tree1 = self.make_branch_and_tree('1')
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
88
        tree2 = self.make_to_branch_and_tree('2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
89
        tree2.set_root_id(tree1.get_root_id())
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
90
        self.build_tree(['2/a'])
91
        tree2.add('a')
92
        os.unlink('2/a')
93
        self.build_tree(['1/b'])
94
        tree1.add('b')
95
        os.unlink('1/b')
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
96
        # the conversion to test trees here will leave the trees intact for the
97
        # default intertree, but may perform a commit for other tree types,
98
        # which may reduce the validity of the test. XXX: Think about how to
99
        # address this.
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
100
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
101
        d = self.intertree_class(tree1, tree2).compare()
102
        self.assertEqual([], d.added)
103
        self.assertEqual([], d.modified)
104
        self.assertEqual([], d.removed)
105
        self.assertEqual([], d.renamed)
106
        self.assertEqual([], d.unchanged)
107
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
108
    def test_abc_content_to_empty(self):
109
        tree1 = self.make_branch_and_tree('1')
110
        tree2 = self.make_to_branch_and_tree('2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
111
        tree2.set_root_id(tree1.get_root_id())
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
112
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
113
        tree2 = self.get_tree_no_parents_no_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
114
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
115
        d = self.intertree_class(tree1, tree2).compare()
116
        self.assertEqual([], d.added)
117
        self.assertEqual([], d.modified)
118
        self.assertEqual([('a', 'a-id', 'file'),
119
                          ('b', 'b-id', 'directory'),
120
                          ('b/c', 'c-id', 'file'),
121
                         ], d.removed)
122
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
123
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
124
125
    def test_content_modification(self):
126
        tree1 = self.make_branch_and_tree('1')
127
        tree2 = self.make_to_branch_and_tree('2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
128
        tree2.set_root_id(tree1.get_root_id())
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
129
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
130
        tree2 = self.get_tree_no_parents_abc_content_2(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
131
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
132
        d = self.intertree_class(tree1, tree2).compare()
133
        self.assertEqual([], d.added)
134
        self.assertEqual([('a', 'a-id', 'file', True, False)], d.modified)
135
        self.assertEqual([], d.removed)
136
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
137
        self.assertEqual([], d.unchanged)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
138
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
139
    def test_meta_modification(self):
140
        tree1 = self.make_branch_and_tree('1')
141
        tree2 = self.make_to_branch_and_tree('2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
142
        tree2.set_root_id(tree1.get_root_id())
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
143
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
144
        tree2 = self.get_tree_no_parents_abc_content_3(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
145
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
146
        d = self.intertree_class(tree1, tree2).compare()
147
        self.assertEqual([], d.added)
148
        self.assertEqual([('b/c', 'c-id', 'file', False, True)], d.modified)
149
        self.assertEqual([], d.removed)
150
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
151
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
152
153
    def test_file_rename(self):
154
        tree1 = self.make_branch_and_tree('1')
155
        tree2 = self.make_to_branch_and_tree('2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
156
        tree2.set_root_id(tree1.get_root_id())
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
157
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
158
        tree2 = self.get_tree_no_parents_abc_content_4(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
159
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
160
        d = self.intertree_class(tree1, tree2).compare()
161
        self.assertEqual([], d.added)
162
        self.assertEqual([], d.modified)
163
        self.assertEqual([], d.removed)
164
        self.assertEqual([('a', 'd', 'a-id', 'file', False, False)], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
165
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
166
167
    def test_file_rename_and_modification(self):
168
        tree1 = self.make_branch_and_tree('1')
169
        tree2 = self.make_to_branch_and_tree('2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
170
        tree2.set_root_id(tree1.get_root_id())
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
171
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
172
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
173
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
174
        d = self.intertree_class(tree1, tree2).compare()
175
        self.assertEqual([], d.added)
176
        self.assertEqual([], d.modified)
177
        self.assertEqual([], d.removed)
178
        self.assertEqual([('a', 'd', 'a-id', 'file', True, False)], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
179
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
180
181
    def test_file_rename_and_meta_modification(self):
182
        tree1 = self.make_branch_and_tree('1')
183
        tree2 = self.make_to_branch_and_tree('2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
184
        tree2.set_root_id(tree1.get_root_id())
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
185
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
186
        tree2 = self.get_tree_no_parents_abc_content_6(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
187
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
188
        d = self.intertree_class(tree1, tree2).compare()
189
        self.assertEqual([], d.added)
190
        self.assertEqual([], d.modified)
191
        self.assertEqual([], d.removed)
192
        self.assertEqual([('b/c', 'e', 'c-id', 'file', False, True)], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
193
        self.assertEqual([], d.unchanged)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
194
195
    def test_empty_to_abc_content_a_only(self):
196
        tree1 = self.make_branch_and_tree('1')
197
        tree2 = self.make_to_branch_and_tree('2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
198
        tree2.set_root_id(tree1.get_root_id())
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
199
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
200
        tree2 = self.get_tree_no_parents_abc_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
201
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
202
        d = self.intertree_class(tree1, tree2).compare(specific_files=['a'])
203
        self.assertEqual([('a', 'a-id', 'file')], d.added)
204
        self.assertEqual([], d.modified)
205
        self.assertEqual([], d.removed)
206
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
207
        self.assertEqual([], d.unchanged)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
208
209
    def test_empty_to_abc_content_a_and_c_only(self):
210
        tree1 = self.make_branch_and_tree('1')
211
        tree2 = self.make_to_branch_and_tree('2')
212
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
213
        tree2 = self.get_tree_no_parents_abc_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
214
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
215
        d = self.intertree_class(tree1, tree2).compare(
216
            specific_files=['a', 'b/c'])
217
        self.assertEqual(
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
218
            [('a', 'a-id', 'file'),  (u'b', 'b-id', 'directory'),
219
             ('b/c', 'c-id', 'file')],
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
220
            d.added)
221
        self.assertEqual([], d.modified)
222
        self.assertEqual([], d.removed)
223
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
224
        self.assertEqual([], d.unchanged)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
225
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
226
    def test_empty_to_abc_content_c_only(self):
227
        tree1 = self.make_branch_and_tree('1')
228
        tree2 = self.make_to_branch_and_tree('2')
229
        tree1 = self.get_tree_no_parents_no_content(tree1)
230
        tree2 = self.get_tree_no_parents_abc_content(tree2)
231
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
232
        d = self.intertree_class(tree1, tree2).compare(
233
            specific_files=['b/c'])
234
        self.assertEqual(
235
            [(u'b', 'b-id', 'directory'), ('b/c', 'c-id', 'file')], d.added)
236
        self.assertEqual([], d.modified)
237
        self.assertEqual([], d.removed)
238
        self.assertEqual([], d.renamed)
239
        self.assertEqual([], d.unchanged)
240
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
241
    def test_empty_to_abc_content_b_only(self):
242
        """Restricting to a dir matches the children of the dir."""
243
        tree1 = self.make_branch_and_tree('1')
244
        tree2 = self.make_to_branch_and_tree('2')
245
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
246
        tree2 = self.get_tree_no_parents_abc_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
247
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
248
        d = self.intertree_class(tree1, tree2).compare(specific_files=['b'])
249
        self.assertEqual(
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
250
            [('b', 'b-id', 'directory'), ('b/c', 'c-id', 'file')],
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
251
            d.added)
252
        self.assertEqual([], d.modified)
253
        self.assertEqual([], d.removed)
254
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
255
        self.assertEqual([], d.unchanged)
256
257
    def test_unchanged_with_renames_and_modifications(self):
258
        """want_unchanged should generate a list of unchanged entries."""
259
        tree1 = self.make_branch_and_tree('1')
260
        tree2 = self.make_to_branch_and_tree('2')
261
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
262
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
263
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
264
        d = self.intertree_class(tree1, tree2).compare(want_unchanged=True)
265
        self.assertEqual([], d.added)
266
        self.assertEqual([], d.modified)
267
        self.assertEqual([], d.removed)
268
        self.assertEqual([('a', 'd', 'a-id', 'file', True, False)], d.renamed)
269
        self.assertEqual(
270
            [(u'b', 'b-id', 'directory'), (u'b/c', 'c-id', 'file')],
271
            d.unchanged)
272
273
    def test_extra_trees_finds_ids(self):
274
        """Ask for a delta between two trees with a path present in a third."""
275
        tree1 = self.make_branch_and_tree('1')
276
        tree2 = self.make_to_branch_and_tree('2')
277
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
278
        tree2 = self.get_tree_no_parents_abc_content_3(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
279
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
280
        d = self.intertree_class(tree1, tree2).compare(specific_files=['b'])
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
281
        # the type of tree-3 does not matter - it is used as a lookup, not
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
282
        # a dispatch. XXX: For dirstate it does speak to the optimisability of
283
        # the lookup, in merged trees it can be fast-pathed. We probably want
284
        # two tests: one as is, and one with it as a pending merge.
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
285
        tree3 = self.make_branch_and_tree('3')
286
        tree3 = self.get_tree_no_parents_abc_content_6(tree3)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
287
        tree3.lock_read()
288
        self.addCleanup(tree3.unlock)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
289
        # tree 3 has 'e' which is 'c-id'. Tree 1 has c-id at b/c, and Tree 2
290
        # has c-id at b/c with its exec flag toggled.
291
        # without extra_trees, we should get no modifications from this
292
        # so do one, to be sure the test is valid.
293
        d = self.intertree_class(tree1, tree2).compare(
294
            specific_files=['e'])
295
        self.assertEqual([], d.modified)
296
        # now give it an additional lookup:
297
        d = self.intertree_class(tree1, tree2).compare(
298
            specific_files=['e'], extra_trees=[tree3])
299
        self.assertEqual([], d.added)
300
        self.assertEqual([('b/c', 'c-id', 'file', False, True)], d.modified)
301
        self.assertEqual([], d.removed)
302
        self.assertEqual([], d.renamed)
303
        self.assertEqual([], d.unchanged)
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
304
305
    def test_require_versioned(self):
306
        # this does not quite robustly test, as it is passing in missing paths
307
        # rather than present-but-not-versioned paths. At the moment there is
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
308
        # no mechanism for managing the test trees (which are readonly) to
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
309
        # get present-but-not-versioned files for trees that can do that.
310
        tree1 = self.make_branch_and_tree('1')
311
        tree2 = self.make_to_branch_and_tree('2')
312
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
313
        tree2 = self.get_tree_no_parents_abc_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
314
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
315
        self.assertRaises(errors.PathsNotVersionedError,
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
316
            self.intertree_class(tree1, tree2).compare,
317
            specific_files=['d'],
318
            require_versioned=True)
2012.1.1 by Aaron Bentley
Implement change iterator
319
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
320
    def test_default_ignores_unversioned_files(self):
321
        tree1 = self.make_branch_and_tree('tree1')
322
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
323
        tree2.set_root_id(tree1.get_root_id())
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
324
        self.build_tree(['tree1/a', 'tree1/c',
325
                         'tree2/a', 'tree2/b', 'tree2/c'])
326
        tree1.add(['a', 'c'], ['a-id', 'c-id'])
327
        tree2.add(['a', 'c'], ['a-id', 'c-id'])
328
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
329
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.7.91 by Robert Collins
Move unknown detection in long status into the delta creation, saving a tree-scan.
330
        d = self.intertree_class(tree1, tree2).compare()
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
331
        self.assertEqual([], d.added)
332
        self.assertEqual([(u'a', 'a-id', 'file', True, False),
333
            (u'c', 'c-id', 'file', True, False)], d.modified)
334
        self.assertEqual([], d.removed)
335
        self.assertEqual([], d.renamed)
336
        self.assertEqual([], d.unchanged)
337
        self.assertEqual([], d.unversioned)
338
339
    def test_unversioned_paths_in_tree(self):
340
        tree1 = self.make_branch_and_tree('tree1')
341
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
342
        tree2.set_root_id(tree1.get_root_id())
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
343
        self.build_tree(['tree2/file', 'tree2/dir/'])
2408.1.2 by Alexander Belchenko
intertree_implementations: make usage of symlinks optional
344
        if has_symlinks():
345
            os.symlink('target', 'tree2/link')
346
            links_supported = True
347
        else:
348
            links_supported = False
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
349
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
350
        self.not_applicable_if_cannot_represent_unversioned(tree2)
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
351
        d = self.intertree_class(tree1, tree2).compare(want_unversioned=True)
352
        self.assertEqual([], d.added)
353
        self.assertEqual([], d.modified)
354
        self.assertEqual([], d.removed)
355
        self.assertEqual([], d.renamed)
356
        self.assertEqual([], d.unchanged)
2408.1.2 by Alexander Belchenko
intertree_implementations: make usage of symlinks optional
357
        expected_unversioned = [(u'dir', None, 'directory'),
358
                                (u'file', None, 'file')]
359
        if links_supported:
360
            expected_unversioned.append((u'link', None, 'symlink'))
361
        self.assertEqual(expected_unversioned, d.unversioned)
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
362
2012.1.1 by Aaron Bentley
Implement change iterator
363
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
364
class TestIterChanges(TestCaseWithTwoTrees):
2012.1.1 by Aaron Bentley
Implement change iterator
365
    """Test the comparison iterator"""
366
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
367
    def assertEqualIterChanges(self, left_changes, right_changes):
368
        """Assert that left_changes == right_changes.
369
370
        :param left_changes: A list of the output from iter_changes.
371
        :param right_changes: A list of the output from iter_changes.
372
        """
373
        left_changes = sorted(left_changes)
374
        right_changes = sorted(right_changes)
375
        if left_changes == right_changes:
376
            return
377
        # setify to get item by item differences, but we can only do this
378
        # when all the ids are unique on both sides.
379
        left_dict = dict((item[0], item) for item in left_changes)
380
        right_dict = dict((item[0], item) for item in right_changes)
381
        if (len(left_dict) != len(left_changes) or
382
            len(right_dict) != len(right_changes)):
383
            # Can't do a direct comparison. We could do a sequence diff, but
384
            # for now just do a regular assertEqual for now.
385
            self.assertEqual(left_changes, right_changes)
386
        keys = set(left_dict).union(set(right_dict))
387
        different = []
388
        same = []
389
        for key in keys:
390
            left_item = left_dict.get(key)
391
            right_item = right_dict.get(key)
392
            if left_item == right_item:
393
                same.append(str(left_item))
394
            else:
395
                different.append(" %s\n %s" % (left_item, right_item))
396
        self.fail("iter_changes output different. Unchanged items:\n" +
397
            "\n".join(same) + "\nChanged items:\n" + "\n".join(different))
398
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
399
    def do_iter_changes(self, tree1, tree2, **extra_args):
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
400
        """Helper to run iter_changes from tree1 to tree2.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
401
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
402
        :param tree1, tree2:  The source and target trees. These will be locked
403
            automatically.
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
404
        :param **extra_args: Extra args to pass to iter_changes. This is not
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
405
            inspected by this test helper.
406
        """
407
        tree1.lock_read()
408
        tree2.lock_read()
409
        try:
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
410
            # sort order of output is not strictly defined
411
            return sorted(self.intertree_class(tree1, tree2)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
412
                .iter_changes(**extra_args))
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
413
        finally:
414
            tree1.unlock()
415
            tree2.unlock()
416
4503.1.3 by Vincent Ladeuil
Take review comments into account.
417
    def check_has_changes(self, expected, tree1, tree2):
418
        # has_changes is defined for mutable trees only
419
        if not isinstance(tree2, mutabletree.MutableTree):
420
            if isinstance(tree1, mutabletree.MutableTree):
421
                # Let's switch the trees since has_changes() is commutative
422
                # (where we can apply it)
423
                tree2, tree1 = tree1, tree2
424
            else:
425
                # Neither tree can be used
426
                return
4503.1.1 by Vincent Ladeuil
Add tree.has_changes() to quickly check iter_changes().
427
        tree1.lock_read()
428
        try:
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
429
            tree2.lock_read()
430
            try:
431
                return tree2.has_changes(tree1)
432
            finally:
433
                tree2.unlock()
4503.1.1 by Vincent Ladeuil
Add tree.has_changes() to quickly check iter_changes().
434
        finally:
435
            tree1.unlock()
436
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
437
    def mutable_trees_to_locked_test_trees(self, tree1, tree2):
438
        """Convert the working trees into test trees.
439
440
        Read lock them, and add the unlock to the cleanup.
441
        """
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
442
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
443
        tree1.lock_read()
444
        self.addCleanup(tree1.unlock)
445
        tree2.lock_read()
446
        self.addCleanup(tree2.unlock)
447
        return tree1, tree2
448
2255.7.15 by John Arbash Meinel
Try to create an intertree test that exposes the walkdir vs dirstate mismatch. No luck yet.
449
    def make_tree_with_special_names(self):
450
        """Create a tree with filenames chosen to exercise the walk order."""
451
        tree1 = self.make_branch_and_tree('tree1')
452
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
453
        tree2.set_root_id(tree1.get_root_id())
2255.7.22 by John Arbash Meinel
add a test that shows _iter_changes works when only contents have changed, and nothing is considered newly added.
454
        paths, path_ids = self._create_special_names(tree2, 'tree2')
2255.7.15 by John Arbash Meinel
Try to create an intertree test that exposes the walkdir vs dirstate mismatch. No luck yet.
455
        tree2.commit('initial', rev_id='rev-1')
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
456
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2255.7.22 by John Arbash Meinel
add a test that shows _iter_changes works when only contents have changed, and nothing is considered newly added.
457
        return (tree1, tree2, paths, path_ids)
458
459
    def make_trees_with_special_names(self):
460
        """Both trees will use the special names.
461
462
        But the contents will differ for each file.
463
        """
464
        tree1 = self.make_branch_and_tree('tree1')
465
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
466
        tree2.set_root_id(tree1.get_root_id())
2255.7.22 by John Arbash Meinel
add a test that shows _iter_changes works when only contents have changed, and nothing is considered newly added.
467
        paths, path_ids = self._create_special_names(tree1, 'tree1')
468
        paths, path_ids = self._create_special_names(tree2, 'tree2')
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
469
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2255.7.22 by John Arbash Meinel
add a test that shows _iter_changes works when only contents have changed, and nothing is considered newly added.
470
        return (tree1, tree2, paths, path_ids)
471
472
    def _create_special_names(self, tree, base_path):
473
        """Create a tree with paths that expose differences in sort orders."""
474
        # Each directory will have a single file named 'f' inside
475
        dirs = ['a',
476
                'a-a',
477
                'a/a',
478
                'a/a-a',
479
                'a/a/a',
480
                'a/a/a-a',
481
                'a/a/a/a',
482
                'a/a/a/a-a',
483
                'a/a/a/a/a',
484
               ]
485
        with_slashes = []
486
        paths = []
487
        path_ids = []
488
        for d in dirs:
489
            with_slashes.append(base_path + '/' + d + '/')
490
            with_slashes.append(base_path + '/' + d + '/f')
491
            paths.append(d)
492
            paths.append(d+'/f')
493
            path_ids.append(d.replace('/', '_') + '-id')
494
            path_ids.append(d.replace('/', '_') + '_f-id')
495
        self.build_tree(with_slashes)
496
        tree.add(paths, path_ids)
497
        return paths, path_ids
2255.7.15 by John Arbash Meinel
Try to create an intertree test that exposes the walkdir vs dirstate mismatch. No luck yet.
498
2012.1.1 by Aaron Bentley
Implement change iterator
499
    def test_compare_empty_trees(self):
500
        tree1 = self.make_branch_and_tree('1')
501
        tree2 = self.make_to_branch_and_tree('2')
502
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
503
        tree2 = self.get_tree_no_parents_no_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
504
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
3254.1.2 by Aaron Bentley
Fix doiter_changes
505
        self.assertEqual([], self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
506
        self.check_has_changes(False, tree1, tree2)
2012.1.1 by Aaron Bentley
Implement change iterator
507
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
508
    def added(self, tree, file_id):
3363.14.7 by Aaron Bentley
Get more tests passing
509
        path, entry = self.get_path_entry(tree, file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
510
        return (file_id, (None, path), True, (False, True), (None, entry.parent_id),
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
511
                (None, entry.name), (None, entry.kind),
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
512
                (None, entry.executable))
513
3363.14.7 by Aaron Bentley
Get more tests passing
514
    @staticmethod
515
    def get_path_entry(tree, file_id):
516
        iterator = tree.iter_entries_by_dir(specific_file_ids=[file_id])
517
        return iterator.next()
518
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
519
    def content_changed(self, tree, file_id):
3363.14.7 by Aaron Bentley
Get more tests passing
520
        path, entry = self.get_path_entry(tree, file_id)
521
        return (file_id, (path, path), True, (True, True),
522
                (entry.parent_id, entry.parent_id),
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
523
                (entry.name, entry.name), (entry.kind, entry.kind),
524
                (entry.executable, entry.executable))
525
526
    def kind_changed(self, from_tree, to_tree, file_id):
3363.14.7 by Aaron Bentley
Get more tests passing
527
        from_path, old_entry = self.get_path_entry(from_tree, file_id)
528
        path, new_entry = self.get_path_entry(to_tree, file_id)
529
        return (file_id, (from_path, path), True, (True, True),
530
                (old_entry.parent_id, new_entry.parent_id),
531
                (old_entry.name, new_entry.name),
532
                (old_entry.kind, new_entry.kind),
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
533
                (old_entry.executable, new_entry.executable))
534
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
535
    def missing(self, file_id, from_path, to_path, parent_id, kind):
536
        _, from_basename = os.path.split(from_path)
537
        _, to_basename = os.path.split(to_path)
538
        # missing files have both paths, but no kind.
539
        return (file_id, (from_path, to_path), True, (True, True),
540
            (parent_id, parent_id),
541
            (from_basename, to_basename), (kind, None), (False, False))
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
542
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
543
    def deleted(self, tree, file_id):
544
        entry = tree.inventory[file_id]
545
        path = tree.id2path(file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
546
        return (file_id, (path, None), True, (True, False), (entry.parent_id, None),
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
547
                (entry.name, None), (entry.kind, None),
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
548
                (entry.executable, None))
549
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
550
    def renamed(self, from_tree, to_tree, file_id, content_changed):
3363.14.8 by Aaron Bentley
Fix more tests
551
        from_path, from_entry = self.get_path_entry(from_tree, file_id)
552
        to_path, to_entry = self.get_path_entry(to_tree, file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
553
        return (file_id, (from_path, to_path), content_changed, (True, True),
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
554
            (from_entry.parent_id, to_entry.parent_id),
555
            (from_entry.name, to_entry.name),
556
            (from_entry.kind, to_entry.kind),
557
            (from_entry.executable, to_entry.executable))
558
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
559
    def unchanged(self, tree, file_id):
3363.14.8 by Aaron Bentley
Fix more tests
560
        path, entry = self.get_path_entry(tree, file_id)
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
561
        parent = entry.parent_id
562
        name = entry.name
563
        kind = entry.kind
564
        executable = entry.executable
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
565
        return (file_id, (path, path), False, (True, True),
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
566
               (parent, parent), (name, name), (kind, kind),
567
               (executable, executable))
568
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
569
    def unversioned(self, tree, path):
570
        """Create an unversioned result."""
571
        _, basename = os.path.split(path)
3363.14.7 by Aaron Bentley
Get more tests passing
572
        kind = tree._comparison_data(None, path)[0]
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
573
        return (None, (None, path), True, (False, False), (None, None),
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
574
                (None, basename), (None, kind),
575
                (None, False))
576
2012.1.1 by Aaron Bentley
Implement change iterator
577
    def test_empty_to_abc_content(self):
578
        tree1 = self.make_branch_and_tree('1')
579
        tree2 = self.make_to_branch_and_tree('2')
580
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
581
        tree2 = self.get_tree_no_parents_abc_content(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
582
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
583
        expected_results = sorted([
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
584
            self.added(tree2, 'root-id'),
585
            self.added(tree2, 'a-id'),
586
            self.added(tree2, 'b-id'),
587
            self.added(tree2, 'c-id'),
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
588
            self.deleted(tree1, 'empty-root-id')])
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
589
        self.assertEqual(expected_results, self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
590
        self.check_has_changes(True, tree1, tree2)
2012.1.1 by Aaron Bentley
Implement change iterator
591
2748.3.1 by Aaron Bentley
Start supporting [] for empty list
592
    def test_empty_specific_files(self):
593
        tree1 = self.make_branch_and_tree('1')
594
        tree2 = self.make_to_branch_and_tree('2')
595
        tree1 = self.get_tree_no_parents_no_content(tree1)
596
        tree2 = self.get_tree_no_parents_abc_content(tree2)
597
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
598
        self.assertEqual([],
599
            self.do_iter_changes(tree1, tree2, specific_files=[]))
600
601
    def test_no_specific_files(self):
602
        tree1 = self.make_branch_and_tree('1')
603
        tree2 = self.make_to_branch_and_tree('2')
604
        tree1 = self.get_tree_no_parents_no_content(tree1)
605
        tree2 = self.get_tree_no_parents_abc_content(tree2)
606
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2796.1.2 by Aaron Bentley
Harmonize test_no_specific_files with test_empty_to_abc_content
607
        expected_results = sorted([
608
            self.added(tree2, 'root-id'),
609
            self.added(tree2, 'a-id'),
610
            self.added(tree2, 'b-id'),
611
            self.added(tree2, 'c-id'),
612
            self.deleted(tree1, 'empty-root-id')])
613
        self.assertEqual(expected_results, self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
614
        self.check_has_changes(True, tree1, tree2)
2748.3.1 by Aaron Bentley
Start supporting [] for empty list
615
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
616
    def test_empty_to_abc_content_a_only(self):
617
        tree1 = self.make_branch_and_tree('1')
618
        tree2 = self.make_to_branch_and_tree('2')
619
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
620
        tree2 = self.get_tree_no_parents_abc_content(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
621
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
622
        self.assertEqual(
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
623
            sorted([self.added(tree2, 'root-id'),
624
             self.added(tree2, 'a-id'),
625
             self.deleted(tree1, 'empty-root-id')]),
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
626
            self.do_iter_changes(tree1, tree2, specific_files=['a']))
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
627
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
628
    def test_abc_content_to_empty_a_only(self):
629
        # For deletes we don't need to pickup parents.
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
630
        tree1 = self.make_branch_and_tree('1')
631
        tree2 = self.make_to_branch_and_tree('2')
632
        tree1 = self.get_tree_no_parents_abc_content(tree1)
633
        tree2 = self.get_tree_no_parents_no_content(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
634
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
635
        self.assertEqual(
636
            [self.deleted(tree1, 'a-id')],
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
637
            self.do_iter_changes(tree1, tree2, specific_files=['a']))
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
638
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
639
    def test_abc_content_to_empty_b_only(self):
640
        # When b stops being a directory we have to pick up b/c as well.
641
        tree1 = self.make_branch_and_tree('1')
642
        tree2 = self.make_to_branch_and_tree('2')
643
        tree1 = self.get_tree_no_parents_abc_content(tree1)
644
        tree2 = self.get_tree_no_parents_no_content(tree2)
645
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
646
        self.assertEqual(
647
            [self.deleted(tree1, 'b-id'), self.deleted(tree1, 'c-id')],
648
            self.do_iter_changes(tree1, tree2, specific_files=['b']))
649
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
650
    def test_empty_to_abc_content_a_and_c_only(self):
651
        tree1 = self.make_branch_and_tree('1')
652
        tree2 = self.make_to_branch_and_tree('2')
653
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
654
        tree2 = self.get_tree_no_parents_abc_content(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
655
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
656
        expected_result = sorted([self.added(tree2, 'root-id'),
657
            self.added(tree2, 'a-id'), self.added(tree2, 'b-id'),
658
            self.added(tree2, 'c-id'), self.deleted(tree1, 'empty-root-id')])
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
659
        self.assertEqual(expected_result,
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
660
            self.do_iter_changes(tree1, tree2, specific_files=['a', 'b/c']))
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
661
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
662
    def test_abc_content_to_empty(self):
2012.1.1 by Aaron Bentley
Implement change iterator
663
        tree1 = self.make_branch_and_tree('1')
664
        tree2 = self.make_to_branch_and_tree('2')
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
665
        tree1 = self.get_tree_no_parents_abc_content(tree1)
666
        tree2 = self.get_tree_no_parents_no_content(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
667
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
668
        expected_results = sorted([
669
            self.added(tree2, 'empty-root-id'),
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
670
            self.deleted(tree1, 'root-id'), self.deleted(tree1, 'a-id'),
671
            self.deleted(tree1, 'b-id'), self.deleted(tree1, 'c-id')])
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
672
        self.assertEqual(
673
            expected_results,
674
            self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
675
        self.check_has_changes(True, tree1, tree2)
2012.1.1 by Aaron Bentley
Implement change iterator
676
677
    def test_content_modification(self):
678
        tree1 = self.make_branch_and_tree('1')
679
        tree2 = self.make_to_branch_and_tree('2')
680
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
681
        tree2 = self.get_tree_no_parents_abc_content_2(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
682
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
683
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
684
        self.assertEqual([('a-id', ('a', 'a'), True, (True, True),
685
                           (root_id, root_id), ('a', 'a'),
686
                           ('file', 'file'), (False, False))],
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
687
                         self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
688
        self.check_has_changes(True, tree1, tree2)
2012.1.1 by Aaron Bentley
Implement change iterator
689
690
    def test_meta_modification(self):
691
        tree1 = self.make_branch_and_tree('1')
692
        tree2 = self.make_to_branch_and_tree('2')
693
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
694
        tree2 = self.get_tree_no_parents_abc_content_3(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
695
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
696
        self.assertEqual([('c-id', ('b/c', 'b/c'), False, (True, True),
697
                           ('b-id', 'b-id'), ('c', 'c'), ('file', 'file'),
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
698
                          (False, True))],
699
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
700
2255.7.6 by Robert Collins
Test for iterating changes past empty directories.
701
    def test_empty_dir(self):
702
        """an empty dir should not cause glitches to surrounding files."""
703
        tree1 = self.make_branch_and_tree('1')
704
        tree2 = self.make_to_branch_and_tree('2')
705
        tree1 = self.get_tree_no_parents_abc_content(tree1)
706
        tree2 = self.get_tree_no_parents_abc_content(tree2)
707
        # the pathname is chosen to fall between 'a' and 'b'.
708
        self.build_tree(['1/a-empty/', '2/a-empty/'])
709
        tree1.add(['a-empty'], ['a-empty'])
710
        tree2.add(['a-empty'], ['a-empty'])
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
711
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.7.6 by Robert Collins
Test for iterating changes past empty directories.
712
        expected = []
713
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
714
2012.1.1 by Aaron Bentley
Implement change iterator
715
    def test_file_rename(self):
716
        tree1 = self.make_branch_and_tree('1')
717
        tree2 = self.make_to_branch_and_tree('2')
718
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
719
        tree2 = self.get_tree_no_parents_abc_content_4(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
720
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
721
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
722
        self.assertEqual([('a-id', ('a', 'd'), False, (True, True),
723
                           (root_id, root_id), ('a', 'd'), ('file', 'file'),
724
                           (False, False))],
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
725
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
726
727
    def test_file_rename_and_modification(self):
728
        tree1 = self.make_branch_and_tree('1')
729
        tree2 = self.make_to_branch_and_tree('2')
730
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
731
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
732
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
733
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
734
        self.assertEqual([('a-id', ('a', 'd'), True, (True, True),
735
                           (root_id, root_id), ('a', 'd'), ('file', 'file'),
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
736
                           (False, False))],
737
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
738
4570.2.5 by Robert Collins
Review feedback, including finding a bug with changes at the root.
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']))
761
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
780
        # file-id(content)
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']))
789
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
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']))
802
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']))
817
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']))
836
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,
852
        # deleted-id is gone
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']))
860
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,
874
        # deleted-id is gone
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']))
882
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']))
908
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']))
938
2012.1.1 by Aaron Bentley
Implement change iterator
939
    def test_file_rename_and_meta_modification(self):
940
        tree1 = self.make_branch_and_tree('1')
941
        tree2 = self.make_to_branch_and_tree('2')
942
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
943
        tree2 = self.get_tree_no_parents_abc_content_6(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
944
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
945
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
946
        self.assertEqual([('c-id', ('b/c', 'e'), False, (True, True),
947
                           ('b-id', root_id), ('c', 'e'), ('file', 'file'),
948
                           (False, True))],
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
949
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
950
4634.58.1 by Robert Collins
Show a sensible error when a previously versionable path becomes a FIFO or other unversionable file.
951
    def test_file_becomes_unversionable_bug_438569(self):
952
        # This isn't strictly a intertree problem, but its the intertree code
953
        # path that triggers all stat cache updates on both xml and dirstate
954
        # trees.
955
        # In bug 438569, a file becoming a fifo causes an assert. Fifo's are
956
        # not versionable or diffable. For now, we simply stop cold when they
957
        # are detected (because we don't know how far through the code the 
958
        # assumption 'fifo's do not exist' goes). In future we could report 
959
        # the kind change and have commit refuse to go futher, or something
960
        # similar. One particular reason for choosing this approach is that
961
        # there is no minikind for 'fifo' in dirstate today, so we can't 
962
        # actually update records that way.
963
        # To add confusion, the totally generic code path works - but it
964
        # doesn't update persistent metadata. So this test permits InterTrees
965
        # to either work, or fail with BadFileKindError.
966
        self.requireFeature(tests.OsFifoFeature)
967
        tree1 = self.make_branch_and_tree('1')
968
        self.build_tree(['1/a'])
969
        tree1.set_root_id('root-id')
970
        tree1.add(['a'], ['a-id'])
971
        tree2 = self.make_branch_and_tree('2')
972
        os.mkfifo('2/a')
973
        tree2.add(['a'], ['a-id'], ['file'])
974
        try:
975
            tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
976
        except (KeyError,):
977
            raise tests.TestNotApplicable(
978
                "Cannot represent a FIFO in this case %s" % self.id())
979
        try:
980
            self.do_iter_changes(tree1, tree2)
4634.58.2 by Robert Collins
Review feedback.
981
        except errors.BadFileKindError:
982
            pass
4634.58.1 by Robert Collins
Show a sensible error when a previously versionable path becomes a FIFO or other unversionable file.
983
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
984
    def test_missing_in_target(self):
985
        """Test with the target files versioned but absent from disk."""
986
        tree1 = self.make_branch_and_tree('1')
987
        tree2 = self.make_to_branch_and_tree('2')
988
        tree1 = self.get_tree_no_parents_abc_content(tree1)
989
        tree2 = self.get_tree_no_parents_abc_content(tree2)
990
        os.unlink('2/a')
991
        shutil.rmtree('2/b')
992
        # TODO ? have a symlink here?
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
993
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
994
        self.not_applicable_if_missing_in('a', tree2)
995
        self.not_applicable_if_missing_in('b', tree2)
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
996
        root_id = tree1.path2id('')
997
        expected = sorted([
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
998
            self.missing('a-id', 'a', 'a', root_id, 'file'),
999
            self.missing('b-id', 'b', 'b', root_id, 'directory'),
1000
            self.missing('c-id', 'b/c', 'b/c', 'b-id', 'file'),
1001
            ])
1002
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1003
1004
    def test_missing_and_renamed(self):
1005
        tree1 = self.make_branch_and_tree('tree1')
1006
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.186 by Martin Pool
Fix up root id for some more comparison tests
1007
        tree2.set_root_id(tree1.get_root_id())
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1008
        self.build_tree(['tree1/file'])
1009
        tree1.add(['file'], ['file-id'])
1010
        self.build_tree(['tree2/directory/'])
1011
        tree2.add(['directory'], ['file-id'])
1012
        os.rmdir('tree2/directory')
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1013
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1014
        self.not_applicable_if_missing_in('directory', tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1015
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1016
        root_id = tree1.path2id('')
1017
        expected = sorted([
1018
            self.missing('file-id', 'file', 'directory', root_id, 'file'),
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
1019
            ])
1020
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1021
3619.4.1 by Robert Collins
Improve tests for the behaviour of Tree.iter_changes for missing paths that are only present in one tree, and fix found bugs. (Robert Collins)
1022
    def test_only_in_source_and_missing(self):
1023
        tree1 = self.make_branch_and_tree('tree1')
1024
        tree2 = self.make_to_branch_and_tree('tree2')
1025
        tree2.set_root_id(tree1.get_root_id())
1026
        self.build_tree(['tree1/file'])
1027
        tree1.add(['file'], ['file-id'])
1028
        os.unlink('tree1/file')
1029
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1030
        self.not_applicable_if_missing_in('file', tree1)
3619.4.1 by Robert Collins
Improve tests for the behaviour of Tree.iter_changes for missing paths that are only present in one tree, and fix found bugs. (Robert Collins)
1031
        root_id = tree1.path2id('')
1032
        expected = [('file-id', ('file', None), False, (True, False),
1033
            (root_id, None), ('file', None), (None, None), (False, None))]
1034
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1035
1036
    def test_only_in_target_and_missing(self):
1037
        tree1 = self.make_branch_and_tree('tree1')
1038
        tree2 = self.make_to_branch_and_tree('tree2')
1039
        tree2.set_root_id(tree1.get_root_id())
1040
        self.build_tree(['tree2/file'])
1041
        tree2.add(['file'], ['file-id'])
1042
        os.unlink('tree2/file')
1043
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1044
        self.not_applicable_if_missing_in('file', tree2)
3619.4.1 by Robert Collins
Improve tests for the behaviour of Tree.iter_changes for missing paths that are only present in one tree, and fix found bugs. (Robert Collins)
1045
        root_id = tree1.path2id('')
1046
        expected = [('file-id', (None, 'file'), False, (False, True),
1047
            (None, root_id), (None, 'file'), (None, None), (None, False))]
1048
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1049
4544.2.1 by Robert Collins
Add interface enforcement for the behaviour of iter_changes with missing subtrees with explicit paths - the whole subtree is returned.
1050
    def test_only_in_target_missing_subtree_specific_bug_367632(self):
1051
        tree1 = self.make_branch_and_tree('tree1')
1052
        tree2 = self.make_to_branch_and_tree('tree2')
1053
        tree2.set_root_id(tree1.get_root_id())
1054
        self.build_tree(['tree2/a-dir/', 'tree2/a-dir/a-file'])
1055
        tree2.add(['a-dir', 'a-dir/a-file'], ['dir-id', 'file-id'])
1056
        os.unlink('tree2/a-dir/a-file')
1057
        os.rmdir('tree2/a-dir')
1058
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1059
        self.not_applicable_if_missing_in('a-dir', tree2)
1060
        root_id = tree1.path2id('')
1061
        expected = [
1062
            ('dir-id', (None, 'a-dir'), False, (False, True),
1063
            (None, root_id), (None, 'a-dir'), (None, None), (None, False)),
1064
            ('file-id', (None, 'a-dir/a-file'), False, (False, True),
1065
            (None, 'dir-id'), (None, 'a-file'), (None, None), (None, False))
1066
            ]
1067
        # bug 367632 showed that specifying the root broke some code paths,
1068
        # so we check this contract with and without it.
1069
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1070
        self.assertEqual(expected,
1071
            self.do_iter_changes(tree1, tree2, specific_files=['']))
1072
2012.1.1 by Aaron Bentley
Implement change iterator
1073
    def test_unchanged_with_renames_and_modifications(self):
1074
        """want_unchanged should generate a list of unchanged entries."""
1075
        tree1 = self.make_branch_and_tree('1')
1076
        tree2 = self.make_to_branch_and_tree('2')
1077
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
1078
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1079
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
1080
        root_id = tree1.path2id('')
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1081
        self.assertEqual(sorted([self.unchanged(tree1, root_id),
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1082
            self.unchanged(tree1, 'b-id'),
1083
            ('a-id', ('a', 'd'), True, (True, True),
1084
             (root_id, root_id), ('a', 'd'), ('file', 'file'),
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
1085
            (False, False)), self.unchanged(tree1, 'c-id')]),
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1086
            self.do_iter_changes(tree1, tree2, include_unchanged=True))
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
1087
1088
    def test_compare_subtrees(self):
1089
        tree1 = self.make_branch_and_tree('1')
2255.9.2 by Martin Pool
test_compare_subtrees runs against all trees that claim to support
1090
        if not tree1.supports_tree_reference():
2323.4.2 by Robert Collins
Fix the behaviour of dirstate optimised iter_changes recursing its disk iterator into subtrees inappropriately.
1091
            return
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
1092
        tree1.set_root_id('root-id')
1093
        subtree1 = self.make_branch_and_tree('1/sub')
1094
        subtree1.set_root_id('subtree-id')
2255.9.2 by Martin Pool
test_compare_subtrees runs against all trees that claim to support
1095
        tree1.add_reference(subtree1)
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
1096
1097
        tree2 = self.make_to_branch_and_tree('2')
2255.9.2 by Martin Pool
test_compare_subtrees runs against all trees that claim to support
1098
        if not tree2.supports_tree_reference():
2323.4.2 by Robert Collins
Fix the behaviour of dirstate optimised iter_changes recursing its disk iterator into subtrees inappropriately.
1099
            return
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
1100
        tree2.set_root_id('root-id')
1101
        subtree2 = self.make_to_branch_and_tree('2/sub')
1102
        subtree2.set_root_id('subtree-id')
1103
        tree2.add_reference(subtree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1104
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1105
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1106
        self.assertEqual([], list(tree2.iter_changes(tree1)))
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
1107
        subtree1.commit('commit', rev_id='commit-a')
1108
        self.assertEqual([
1109
            ('root-id',
1110
             (u'', u''),
1111
             False,
1112
             (True, True),
1113
             (None, None),
1114
             (u'', u''),
1115
             ('directory', 'directory'),
1116
             (False, False)),
1117
            ('subtree-id',
1118
             ('sub', 'sub',),
1119
             False,
1120
             (True, True),
1121
             ('root-id', 'root-id'),
1122
             ('sub', 'sub'),
1123
             ('tree-reference', 'tree-reference'),
1124
             (False, False))],
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1125
                         list(tree2.iter_changes(tree1,
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
1126
                             include_unchanged=True)))
2255.2.160 by Martin Pool
(merge) updates from dirstate branch
1127
2323.4.2 by Robert Collins
Fix the behaviour of dirstate optimised iter_changes recursing its disk iterator into subtrees inappropriately.
1128
    def test_disk_in_subtrees_skipped(self):
1129
        """subtrees are considered not-in-the-current-tree.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1130
2323.4.2 by Robert Collins
Fix the behaviour of dirstate optimised iter_changes recursing its disk iterator into subtrees inappropriately.
1131
        This test tests the trivial case, where the basis has no paths in the
1132
        current trees subtree.
1133
        """
1134
        tree1 = self.make_branch_and_tree('1')
1135
        tree1.set_root_id('root-id')
1136
        tree2 = self.make_to_branch_and_tree('2')
1137
        if not tree2.supports_tree_reference():
1138
            return
1139
        tree2.set_root_id('root-id')
1140
        subtree2 = self.make_to_branch_and_tree('2/sub')
1141
        subtree2.set_root_id('subtree-id')
4100.2.4 by Aaron Bentley
More support for not autodetecting tree refs
1142
        tree2.add_reference(subtree2)
2323.4.2 by Robert Collins
Fix the behaviour of dirstate optimised iter_changes recursing its disk iterator into subtrees inappropriately.
1143
        self.build_tree(['2/sub/file'])
1144
        subtree2.add(['file'])
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1145
1146
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2323.4.2 by Robert Collins
Fix the behaviour of dirstate optimised iter_changes recursing its disk iterator into subtrees inappropriately.
1147
        # this should filter correctly from above
1148
        self.assertEqual([self.added(tree2, 'subtree-id')],
1149
            self.do_iter_changes(tree1, tree2, want_unversioned=True))
1150
        # and when the path is named
1151
        self.assertEqual([self.added(tree2, 'subtree-id')],
1152
            self.do_iter_changes(tree1, tree2, specific_files=['sub'],
1153
                want_unversioned=True))
1154
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
1155
    def test_default_ignores_unversioned_files(self):
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
1156
        tree1 = self.make_branch_and_tree('tree1')
1157
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.186 by Martin Pool
Fix up root id for some more comparison tests
1158
        tree2.set_root_id(tree1.get_root_id())
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
1159
        self.build_tree(['tree1/a', 'tree1/c',
1160
                         'tree2/a', 'tree2/b', 'tree2/c'])
1161
        tree1.add(['a', 'c'], ['a-id', 'c-id'])
1162
        tree2.add(['a', 'c'], ['a-id', 'c-id'])
1163
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1164
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
1165
1166
        # We should ignore the fact that 'b' exists in tree-2
1167
        # because the want_unversioned parameter was not given.
1168
        expected = sorted([
1169
            self.content_changed(tree2, 'a-id'),
1170
            self.content_changed(tree2, 'c-id'),
1171
            ])
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
1172
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1173
        self.check_has_changes(True, tree1, tree2)
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
1174
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
1175
    def test_unversioned_paths_in_tree(self):
1176
        tree1 = self.make_branch_and_tree('tree1')
1177
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
1178
        tree2.set_root_id(tree1.get_root_id())
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
1179
        self.build_tree(['tree2/file', 'tree2/dir/'])
2408.1.2 by Alexander Belchenko
intertree_implementations: make usage of symlinks optional
1180
        if has_symlinks():
1181
            os.symlink('target', 'tree2/link')
1182
            links_supported = True
1183
        else:
1184
            links_supported = False
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1185
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1186
        self.not_applicable_if_cannot_represent_unversioned(tree2)
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
1187
        expected = [
1188
            self.unversioned(tree2, 'file'),
1189
            self.unversioned(tree2, 'dir'),
1190
            ]
1191
        if links_supported:
1192
            expected.append(self.unversioned(tree2, 'link'))
1193
        expected = sorted(expected)
1194
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
1195
            want_unversioned=True))
1196
1197
    def test_unversioned_paths_in_tree_specific_files(self):
1198
        tree1 = self.make_branch_and_tree('tree1')
1199
        tree2 = self.make_to_branch_and_tree('tree2')
1200
        self.build_tree(['tree2/file', 'tree2/dir/'])
2408.1.2 by Alexander Belchenko
intertree_implementations: make usage of symlinks optional
1201
        if has_symlinks():
1202
            os.symlink('target', 'tree2/link')
1203
            links_supported = True
1204
        else:
1205
            links_supported = False
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1206
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1207
        self.not_applicable_if_cannot_represent_unversioned(tree2)
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
1208
        expected = [
1209
            self.unversioned(tree2, 'file'),
1210
            self.unversioned(tree2, 'dir'),
1211
            ]
1212
        specific_files=['file', 'dir']
1213
        if links_supported:
1214
            expected.append(self.unversioned(tree2, 'link'))
1215
            specific_files.append('link')
1216
        expected = sorted(expected)
1217
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
1218
            specific_files=specific_files, require_versioned=False,
1219
            want_unversioned=True))
1220
1221
    def test_unversioned_paths_in_target_matching_source_old_names(self):
1222
        # its likely that naive implementations of unversioned file support
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1223
        # will fail if the path was versioned, but is not any more,
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
1224
        # due to a rename, not due to unversioning it.
1225
        # That is, if the old tree has a versioned file 'foo', and
1226
        # the new tree has the same file but versioned as 'bar', and also
1227
        # has an unknown file 'foo', we should get back output for
1228
        # both foo and bar.
1229
        tree1 = self.make_branch_and_tree('tree1')
1230
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.187 by Martin Pool
set common root ids in more tests
1231
        tree2.set_root_id(tree1.get_root_id())
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
1232
        self.build_tree(['tree2/file', 'tree2/dir/',
1233
            'tree1/file', 'tree2/movedfile',
1234
            'tree1/dir/', 'tree2/moveddir/'])
2408.1.2 by Alexander Belchenko
intertree_implementations: make usage of symlinks optional
1235
        if has_symlinks():
1236
            os.symlink('target', 'tree1/link')
1237
            os.symlink('target', 'tree2/link')
1238
            os.symlink('target', 'tree2/movedlink')
1239
            links_supported = True
1240
        else:
1241
            links_supported = False
1242
        tree1.add(['file', 'dir'], ['file-id', 'dir-id'])
1243
        tree2.add(['movedfile', 'moveddir'], ['file-id', 'dir-id'])
1244
        if links_supported:
1245
            tree1.add(['link'], ['link-id'])
1246
            tree2.add(['movedlink'], ['link-id'])
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1247
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1248
        self.not_applicable_if_cannot_represent_unversioned(tree2)
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
1249
        root_id = tree1.path2id('')
1250
        expected = [
1251
            self.renamed(tree1, tree2, 'dir-id', False),
1252
            self.renamed(tree1, tree2, 'file-id', True),
1253
            self.unversioned(tree2, 'file'),
1254
            self.unversioned(tree2, 'dir'),
1255
            ]
1256
        specific_files=['file', 'dir']
1257
        if links_supported:
1258
            expected.append(self.renamed(tree1, tree2, 'link-id', False))
1259
            expected.append(self.unversioned(tree2, 'link'))
1260
            specific_files.append('link')
1261
        expected = sorted(expected)
1262
        # run once with, and once without specific files, to catch
1263
        # potentially different code paths.
1264
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
1265
            require_versioned=False,
1266
            want_unversioned=True))
1267
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
1268
            specific_files=specific_files, require_versioned=False,
1269
            want_unversioned=True))
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1270
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
1271
    def test_similar_filenames(self):
1272
        """Test when we have a few files with similar names."""
1273
        tree1 = self.make_branch_and_tree('tree1')
1274
        tree2 = self.make_branch_and_tree('tree2')
1275
        tree2.set_root_id(tree1.get_root_id())
1276
1277
        # The trees are actually identical, but they happen to contain
1278
        # similarly named files.
1279
        self.build_tree(['tree1/a/',
1280
                         'tree1/a/b/',
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
1281
                         'tree1/a/b/c/',
1282
                         'tree1/a/b/c/d/',
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
1283
                         'tree1/a-c/',
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
1284
                         'tree1/a-c/e/',
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
1285
                         'tree2/a/',
1286
                         'tree2/a/b/',
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
1287
                         'tree2/a/b/c/',
1288
                         'tree2/a/b/c/d/',
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
1289
                         'tree2/a-c/',
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
1290
                         'tree2/a-c/e/',
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
1291
                        ])
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
1292
        tree1.add(['a', 'a/b', 'a/b/c', 'a/b/c/d', 'a-c', 'a-c/e'],
1293
                  ['a-id', 'b-id', 'c-id', 'd-id', 'a-c-id', 'e-id'])
1294
        tree2.add(['a', 'a/b', 'a/b/c', 'a/b/c/d', 'a-c', 'a-c/e'],
1295
                  ['a-id', 'b-id', 'c-id', 'd-id', 'a-c-id', 'e-id'])
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
1296
1297
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1298
        self.not_applicable_if_cannot_represent_unversioned(tree2)
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
1299
1300
        self.assertEqual([], self.do_iter_changes(tree1, tree2,
1301
                                                  want_unversioned=True))
2466.5.2 by John Arbash Meinel
Extend the test a bit to make sure the include_unchanged value is correct.
1302
        expected = sorted([
1303
            self.unchanged(tree2, tree2.get_root_id()),
1304
            self.unchanged(tree2, 'a-id'),
1305
            self.unchanged(tree2, 'b-id'),
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
1306
            self.unchanged(tree2, 'c-id'),
1307
            self.unchanged(tree2, 'd-id'),
2466.5.2 by John Arbash Meinel
Extend the test a bit to make sure the include_unchanged value is correct.
1308
            self.unchanged(tree2, 'a-c-id'),
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
1309
            self.unchanged(tree2, 'e-id'),
2466.5.2 by John Arbash Meinel
Extend the test a bit to make sure the include_unchanged value is correct.
1310
            ])
1311
        self.assertEqual(expected,
1312
                         self.do_iter_changes(tree1, tree2,
1313
                                              want_unversioned=True,
1314
                                              include_unchanged=True))
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
1315
1316
2255.7.87 by Robert Collins
Dont walk unversioned directories in _iter_changes.
1317
    def test_unversioned_subtree_only_emits_root(self):
1318
        tree1 = self.make_branch_and_tree('tree1')
1319
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.188 by Martin Pool
Set common root id in comparison tests
1320
        tree2.set_root_id(tree1.get_root_id())
2255.7.87 by Robert Collins
Dont walk unversioned directories in _iter_changes.
1321
        self.build_tree(['tree2/dir/', 'tree2/dir/file'])
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
1322
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1323
        self.not_applicable_if_cannot_represent_unversioned(tree2)
2255.7.87 by Robert Collins
Dont walk unversioned directories in _iter_changes.
1324
        expected = [
1325
            self.unversioned(tree2, 'dir'),
1326
            ]
1327
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
1328
            want_unversioned=True))
1329
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1330
    def make_trees_with_symlinks(self):
1331
        tree1 = self.make_branch_and_tree('tree1')
1332
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
1333
        tree2.set_root_id(tree1.get_root_id())
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1334
        self.build_tree(['tree1/fromfile', 'tree1/fromdir/'])
1335
        self.build_tree(['tree2/tofile', 'tree2/todir/', 'tree2/unknown'])
1336
        os.symlink('original', 'tree1/changed')
1337
        os.symlink('original', 'tree1/removed')
1338
        os.symlink('original', 'tree1/tofile')
1339
        os.symlink('original', 'tree1/todir')
1340
        # we make the unchanged link point at unknown to catch incorrect
1341
        # symlink-following code in the specified_files test.
1342
        os.symlink('unknown', 'tree1/unchanged')
1343
        os.symlink('new',      'tree2/added')
1344
        os.symlink('new',      'tree2/changed')
1345
        os.symlink('new',      'tree2/fromfile')
1346
        os.symlink('new',      'tree2/fromdir')
1347
        os.symlink('unknown', 'tree2/unchanged')
1348
        from_paths_and_ids = [
1349
            'fromdir',
1350
            'fromfile',
1351
            'changed',
1352
            'removed',
1353
            'todir',
1354
            'tofile',
1355
            'unchanged',
1356
            ]
1357
        to_paths_and_ids = [
1358
            'added',
1359
            'fromdir',
1360
            'fromfile',
1361
            'changed',
1362
            'todir',
1363
            'tofile',
1364
            'unchanged',
1365
            ]
1366
        tree1.add(from_paths_and_ids, from_paths_and_ids)
1367
        tree2.add(to_paths_and_ids, to_paths_and_ids)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1368
        return self.mutable_trees_to_locked_test_trees(tree1, tree2)
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1369
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
1370
    def test_versioned_symlinks(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
1371
        self.requireFeature(tests.SymlinkFeature)
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1372
        tree1, tree2 = self.make_trees_with_symlinks()
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1373
        self.not_applicable_if_cannot_represent_unversioned(tree2)
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1374
        root_id = tree1.path2id('')
1375
        expected = [
1376
            self.unchanged(tree1, tree1.path2id('')),
1377
            self.added(tree2, 'added'),
1378
            self.content_changed(tree2, 'changed'),
1379
            self.kind_changed(tree1, tree2, 'fromdir'),
1380
            self.kind_changed(tree1, tree2, 'fromfile'),
1381
            self.deleted(tree1, 'removed'),
1382
            self.unchanged(tree2, 'unchanged'),
1383
            self.unversioned(tree2, 'unknown'),
1384
            self.kind_changed(tree1, tree2, 'todir'),
1385
            self.kind_changed(tree1, tree2, 'tofile'),
1386
            ]
1387
        expected = sorted(expected)
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
1388
        self.assertEqual(expected,
1389
            self.do_iter_changes(tree1, tree2, include_unchanged=True,
1390
                want_unversioned=True))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1391
        self.check_has_changes(True, tree1, tree2)
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1392
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
1393
    def test_versioned_symlinks_specific_files(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
1394
        self.requireFeature(tests.SymlinkFeature)
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1395
        tree1, tree2 = self.make_trees_with_symlinks()
1396
        root_id = tree1.path2id('')
1397
        expected = [
1398
            self.added(tree2, 'added'),
1399
            self.content_changed(tree2, 'changed'),
1400
            self.kind_changed(tree1, tree2, 'fromdir'),
1401
            self.kind_changed(tree1, tree2, 'fromfile'),
1402
            self.deleted(tree1, 'removed'),
1403
            self.kind_changed(tree1, tree2, 'todir'),
1404
            self.kind_changed(tree1, tree2, 'tofile'),
1405
            ]
1406
        expected = sorted(expected)
1407
        # we should get back just the changed links. We pass in 'unchanged' to
1408
        # make sure that it is correctly not returned - and neither is the
1409
        # unknown path 'unknown' which it points at.
1410
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
1411
            specific_files=['added', 'changed', 'fromdir', 'fromfile',
1412
            'removed', 'unchanged', 'todir', 'tofile']))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1413
        self.check_has_changes(True, tree1, tree2)
2255.7.15 by John Arbash Meinel
Try to create an intertree test that exposes the walkdir vs dirstate mismatch. No luck yet.
1414
2255.7.21 by John Arbash Meinel
Get iter_changes working again, by fixing set_parent_trees to
1415
    def test_tree_with_special_names(self):
2255.7.15 by John Arbash Meinel
Try to create an intertree test that exposes the walkdir vs dirstate mismatch. No luck yet.
1416
        tree1, tree2, paths, path_ids = self.make_tree_with_special_names()
1417
        expected = sorted(self.added(tree2, f_id) for f_id in path_ids)
1418
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1419
        self.check_has_changes(True, tree1, tree2)
2255.7.22 by John Arbash Meinel
add a test that shows _iter_changes works when only contents have changed, and nothing is considered newly added.
1420
1421
    def test_trees_with_special_names(self):
1422
        tree1, tree2, paths, path_ids = self.make_trees_with_special_names()
1423
        expected = sorted(self.content_changed(tree2, f_id) for f_id in path_ids
1424
                          if f_id.endswith('_f-id'))
1425
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1426
        self.check_has_changes(True, tree1, tree2)
2255.7.34 by John Arbash Meinel
Clean up test_bad_files, and fix a bug in _iter_changes when
1427
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1428
    def test_trees_with_deleted_dir(self):
2255.7.35 by John Arbash Meinel
Handle the case when a directory has been removed, and isn't the last entry.
1429
        tree1 = self.make_branch_and_tree('tree1')
1430
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
1431
        tree2.set_root_id(tree1.get_root_id())
2255.7.35 by John Arbash Meinel
Handle the case when a directory has been removed, and isn't the last entry.
1432
        self.build_tree(['tree1/a', 'tree1/b/', 'tree1/b/c',
1433
                         'tree1/b/d/', 'tree1/b/d/e', 'tree1/f/', 'tree1/f/g',
1434
                         'tree2/a', 'tree2/f/', 'tree2/f/g'])
1435
        tree1.add(['a', 'b', 'b/c', 'b/d/', 'b/d/e', 'f', 'f/g'],
1436
                  ['a-id', 'b-id', 'c-id', 'd-id', 'e-id', 'f-id', 'g-id'])
1437
        tree2.add(['a', 'f', 'f/g'], ['a-id', 'f-id', 'g-id'])
1438
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1439
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1440
        # We should notice that 'b' and all its children are deleted
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1441
        expected = [
2255.7.35 by John Arbash Meinel
Handle the case when a directory has been removed, and isn't the last entry.
1442
            self.content_changed(tree2, 'a-id'),
1443
            self.content_changed(tree2, 'g-id'),
1444
            self.deleted(tree1, 'b-id'),
1445
            self.deleted(tree1, 'c-id'),
1446
            self.deleted(tree1, 'd-id'),
1447
            self.deleted(tree1, 'e-id'),
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1448
            ]
1449
        self.assertEqualIterChanges(expected,
1450
            self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1451
        self.check_has_changes(True, tree1, tree2)
2360.1.1 by John Arbash Meinel
Basic implementation test that makes sure _iter_changes handles unknown files.
1452
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1453
    def test_added_unicode(self):
1454
        tree1 = self.make_branch_and_tree('tree1')
1455
        tree2 = self.make_to_branch_and_tree('tree2')
1456
        root_id = tree1.get_root_id()
1457
        tree2.set_root_id(root_id)
1458
1459
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1460
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1461
        a_id = u'\u03b1-id'.encode('utf8')
1462
        added_id = u'\u03c9_added_id'.encode('utf8')
2360.1.8 by John Arbash Meinel
Update the tests to handle when fs is non-unicode.
1463
        try:
1464
            self.build_tree([u'tree1/\u03b1/',
1465
                             u'tree2/\u03b1/',
1466
                             u'tree2/\u03b1/\u03c9-added',
1467
                            ])
1468
        except UnicodeError:
1469
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1470
        tree1.add([u'\u03b1'], [a_id])
1471
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-added'], [a_id, added_id])
1472
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1473
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1474
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1475
        self.assertEqual([self.added(tree2, added_id)],
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1476
                         self.do_iter_changes(tree1, tree2))
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1477
        self.assertEqual([self.added(tree2, added_id)],
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1478
                         self.do_iter_changes(tree1, tree2,
1479
                                              specific_files=[u'\u03b1']))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1480
        self.check_has_changes(True, tree1, tree2)
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1481
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1482
    def test_deleted_unicode(self):
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1483
        tree1 = self.make_branch_and_tree('tree1')
1484
        tree2 = self.make_to_branch_and_tree('tree2')
1485
        root_id = tree1.get_root_id()
1486
        tree2.set_root_id(root_id)
1487
1488
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1489
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1490
        a_id = u'\u03b1-id'.encode('utf8')
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1491
        deleted_id = u'\u03c9_deleted_id'.encode('utf8')
2360.1.8 by John Arbash Meinel
Update the tests to handle when fs is non-unicode.
1492
        try:
1493
            self.build_tree([u'tree1/\u03b1/',
1494
                             u'tree1/\u03b1/\u03c9-deleted',
1495
                             u'tree2/\u03b1/',
1496
                            ])
1497
        except UnicodeError:
1498
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1499
        tree1.add([u'\u03b1', u'\u03b1/\u03c9-deleted'], [a_id, deleted_id])
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1500
        tree2.add([u'\u03b1'], [a_id])
1501
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1502
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1503
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1504
        self.assertEqual([self.deleted(tree1, deleted_id)],
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1505
                         self.do_iter_changes(tree1, tree2))
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1506
        self.assertEqual([self.deleted(tree1, deleted_id)],
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1507
                         self.do_iter_changes(tree1, tree2,
1508
                                              specific_files=[u'\u03b1']))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1509
        self.check_has_changes(True, tree1, tree2)
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1510
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1511
    def test_modified_unicode(self):
2360.1.1 by John Arbash Meinel
Basic implementation test that makes sure _iter_changes handles unknown files.
1512
        tree1 = self.make_branch_and_tree('tree1')
1513
        tree2 = self.make_to_branch_and_tree('tree2')
1514
        root_id = tree1.get_root_id()
1515
        tree2.set_root_id(root_id)
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1516
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1517
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1518
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1519
        a_id = u'\u03b1-id'.encode('utf8')
1520
        mod_id = u'\u03c9_mod_id'.encode('utf8')
2360.1.8 by John Arbash Meinel
Update the tests to handle when fs is non-unicode.
1521
        try:
1522
            self.build_tree([u'tree1/\u03b1/',
1523
                             u'tree1/\u03b1/\u03c9-modified',
1524
                             u'tree2/\u03b1/',
1525
                             u'tree2/\u03b1/\u03c9-modified',
1526
                            ])
1527
        except UnicodeError:
1528
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1529
        tree1.add([u'\u03b1', u'\u03b1/\u03c9-modified'], [a_id, mod_id])
1530
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-modified'], [a_id, mod_id])
1531
1532
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1533
1534
        self.assertEqual([self.content_changed(tree1, mod_id)],
1535
                         self.do_iter_changes(tree1, tree2))
1536
        self.assertEqual([self.content_changed(tree1, mod_id)],
1537
                         self.do_iter_changes(tree1, tree2,
1538
                                              specific_files=[u'\u03b1']))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1539
        self.check_has_changes(True, tree1, tree2)
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1540
1541
    def test_renamed_unicode(self):
1542
        tree1 = self.make_branch_and_tree('tree1')
1543
        tree2 = self.make_to_branch_and_tree('tree2')
1544
        root_id = tree1.get_root_id()
1545
        tree2.set_root_id(root_id)
1546
1547
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1548
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1549
        a_id = u'\u03b1-id'.encode('utf8')
1550
        rename_id = u'\u03c9_rename_id'.encode('utf8')
2360.1.8 by John Arbash Meinel
Update the tests to handle when fs is non-unicode.
1551
        try:
1552
            self.build_tree([u'tree1/\u03b1/',
1553
                             u'tree2/\u03b1/',
1554
                            ])
1555
        except UnicodeError:
1556
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1557
        self.build_tree_contents([(u'tree1/\u03c9-source', 'contents\n'),
1558
                                  (u'tree2/\u03b1/\u03c9-target', 'contents\n'),
1559
                                 ])
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1560
        tree1.add([u'\u03b1', u'\u03c9-source'], [a_id, rename_id])
1561
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-target'], [a_id, rename_id])
1562
1563
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1564
1565
        self.assertEqual([self.renamed(tree1, tree2, rename_id, False)],
1566
                         self.do_iter_changes(tree1, tree2))
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1567
        self.assertEqualIterChanges(
1568
            [self.renamed(tree1, tree2, rename_id, False)],
1569
            self.do_iter_changes(tree1, tree2, specific_files=[u'\u03b1']))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1570
        self.check_has_changes(True, tree1, tree2)
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1571
1572
    def test_unchanged_unicode(self):
1573
        tree1 = self.make_branch_and_tree('tree1')
1574
        tree2 = self.make_to_branch_and_tree('tree2')
1575
        root_id = tree1.get_root_id()
1576
        tree2.set_root_id(root_id)
1577
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1578
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1579
        a_id = u'\u03b1-id'.encode('utf8')
1580
        subfile_id = u'\u03c9-subfile-id'.encode('utf8')
1581
        rootfile_id = u'\u03c9-root-id'.encode('utf8')
2360.1.8 by John Arbash Meinel
Update the tests to handle when fs is non-unicode.
1582
        try:
1583
            self.build_tree([u'tree1/\u03b1/',
1584
                             u'tree2/\u03b1/',
1585
                            ])
1586
        except UnicodeError:
1587
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1588
        self.build_tree_contents([
1589
            (u'tree1/\u03b1/\u03c9-subfile', 'sub contents\n'),
1590
            (u'tree2/\u03b1/\u03c9-subfile', 'sub contents\n'),
1591
            (u'tree1/\u03c9-rootfile', 'root contents\n'),
1592
            (u'tree2/\u03c9-rootfile', 'root contents\n'),
1593
            ])
1594
        tree1.add([u'\u03b1', u'\u03b1/\u03c9-subfile', u'\u03c9-rootfile'],
1595
                  [a_id, subfile_id, rootfile_id])
1596
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-subfile', u'\u03c9-rootfile'],
1597
                  [a_id, subfile_id, rootfile_id])
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1598
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1599
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1600
2360.1.1 by John Arbash Meinel
Basic implementation test that makes sure _iter_changes handles unknown files.
1601
        expected = sorted([
1602
            self.unchanged(tree1, root_id),
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1603
            self.unchanged(tree1, a_id),
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1604
            self.unchanged(tree1, subfile_id),
1605
            self.unchanged(tree1, rootfile_id),
1606
            ])
1607
        self.assertEqual(expected,
1608
                         self.do_iter_changes(tree1, tree2,
1609
                                              include_unchanged=True))
1610
1611
        # We should also be able to select just a subset
1612
        expected = sorted([
1613
            self.unchanged(tree1, a_id),
1614
            self.unchanged(tree1, subfile_id),
1615
            ])
1616
        self.assertEqual(expected,
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1617
            self.do_iter_changes(tree1, tree2, specific_files=[u'\u03b1'],
1618
                include_unchanged=True))
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1619
1620
    def test_unknown_unicode(self):
1621
        tree1 = self.make_branch_and_tree('tree1')
1622
        tree2 = self.make_to_branch_and_tree('tree2')
1623
        root_id = tree1.get_root_id()
1624
        tree2.set_root_id(root_id)
1625
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1626
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1627
        a_id = u'\u03b1-id'.encode('utf8')
2360.1.8 by John Arbash Meinel
Update the tests to handle when fs is non-unicode.
1628
        try:
1629
            self.build_tree([u'tree1/\u03b1/',
1630
                             u'tree2/\u03b1/',
1631
                             u'tree2/\u03b1/unknown_dir/',
1632
                             u'tree2/\u03b1/unknown_file',
1633
                             u'tree2/\u03b1/unknown_dir/file',
1634
                             u'tree2/\u03c9-unknown_root_file',
1635
                            ])
1636
        except UnicodeError:
1637
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1638
        tree1.add([u'\u03b1'], [a_id])
1639
        tree2.add([u'\u03b1'], [a_id])
1640
1641
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1642
        self.not_applicable_if_cannot_represent_unversioned(tree2)
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1643
1644
        expected = sorted([
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1645
            self.unversioned(tree2, u'\u03b1/unknown_dir'),
1646
            self.unversioned(tree2, u'\u03b1/unknown_file'),
1647
            self.unversioned(tree2, u'\u03c9-unknown_root_file'),
2360.1.1 by John Arbash Meinel
Basic implementation test that makes sure _iter_changes handles unknown files.
1648
            # a/unknown_dir/file should not be included because we should not
1649
            # recurse into unknown_dir
1650
            # self.unversioned(tree2, 'a/unknown_dir/file'),
1651
            ])
1652
        self.assertEqual(expected,
1653
                         self.do_iter_changes(tree1, tree2,
1654
                                              require_versioned=False,
1655
                                              want_unversioned=True))
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1656
        self.assertEqual([], # Without want_unversioned we should get nothing
1657
                         self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1658
        self.check_has_changes(False, tree1, tree2)
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1659
1660
        # We should also be able to select just a subset
1661
        expected = sorted([
1662
            self.unversioned(tree2, u'\u03b1/unknown_dir'),
1663
            self.unversioned(tree2, u'\u03b1/unknown_file'),
1664
            ])
1665
        self.assertEqual(expected,
1666
                         self.do_iter_changes(tree1, tree2,
1667
                                              specific_files=[u'\u03b1'],
1668
                                              require_versioned=False,
1669
                                              want_unversioned=True))
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1670
        self.assertEqual([], # Without want_unversioned we should get nothing
1671
                         self.do_iter_changes(tree1, tree2,
1672
                                              specific_files=[u'\u03b1']))
2402.2.1 by John Arbash Meinel
Add a test which exposes the bug in WT4._iter_changes()
1673
1674
    def test_unknown_empty_dir(self):
1675
        tree1 = self.make_branch_and_tree('tree1')
1676
        tree2 = self.make_to_branch_and_tree('tree2')
1677
        root_id = tree1.get_root_id()
1678
        tree2.set_root_id(root_id)
1679
2402.2.4 by John Arbash Meinel
Clean up the setup for clarity (suggested by Robert)
1680
        # Start with 2 identical trees
1681
        self.build_tree(['tree1/a/', 'tree1/b/',
1682
                         'tree2/a/', 'tree2/b/'])
1683
        self.build_tree_contents([('tree1/b/file', 'contents\n'),
1684
                                  ('tree2/b/file', 'contents\n')])
2402.2.1 by John Arbash Meinel
Add a test which exposes the bug in WT4._iter_changes()
1685
        tree1.add(['a', 'b', 'b/file'], ['a-id', 'b-id', 'b-file-id'])
1686
        tree2.add(['a', 'b', 'b/file'], ['a-id', 'b-id', 'b-file-id'])
1687
2402.2.2 by John Arbash Meinel
Fix _iter_changes to properly handle versioned (but empty) directories
1688
        # Now create some unknowns in tree2
1689
        # We should find both a/file and a/dir as unknown, but we shouldn't
1690
        # recurse into a/dir to find that a/dir/subfile is also unknown.
1691
        self.build_tree(['tree2/a/file', 'tree2/a/dir/', 'tree2/a/dir/subfile'])
1692
2402.2.1 by John Arbash Meinel
Add a test which exposes the bug in WT4._iter_changes()
1693
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1694
        self.not_applicable_if_cannot_represent_unversioned(tree2)
2402.2.1 by John Arbash Meinel
Add a test which exposes the bug in WT4._iter_changes()
1695
1696
        expected = sorted([
1697
            self.unversioned(tree2, u'a/file'),
2402.2.2 by John Arbash Meinel
Fix _iter_changes to properly handle versioned (but empty) directories
1698
            self.unversioned(tree2, u'a/dir'),
2402.2.1 by John Arbash Meinel
Add a test which exposes the bug in WT4._iter_changes()
1699
            ])
1700
        self.assertEqual(expected,
1701
                         self.do_iter_changes(tree1, tree2,
1702
                                              require_versioned=False,
1703
                                              want_unversioned=True))
2456.2.1 by John Arbash Meinel
(broken) Add a (failing) test that _iter_changes works correctly
1704
1705
    def test_rename_over_deleted(self):
1706
        tree1 = self.make_branch_and_tree('tree1')
1707
        tree2 = self.make_to_branch_and_tree('tree2')
1708
        root_id = tree1.get_root_id()
1709
        tree2.set_root_id(root_id)
1710
1711
        # The final changes should be:
1712
        #   touch a b c d
1713
        #   add a b c d
1714
        #   commit
1715
        #   rm a d
1716
        #   mv b a
1717
        #   mv c d
1718
        self.build_tree_contents([
1719
            ('tree1/a', 'a contents\n'),
1720
            ('tree1/b', 'b contents\n'),
1721
            ('tree1/c', 'c contents\n'),
1722
            ('tree1/d', 'd contents\n'),
1723
            ('tree2/a', 'b contents\n'),
1724
            ('tree2/d', 'c contents\n'),
1725
            ])
1726
        tree1.add(['a', 'b', 'c', 'd'], ['a-id', 'b-id', 'c-id', 'd-id'])
1727
        tree2.add(['a', 'd'], ['b-id', 'c-id'])
1728
1729
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1730
1731
        expected = sorted([
1732
            self.deleted(tree1, 'a-id'),
1733
            self.deleted(tree1, 'd-id'),
1734
            self.renamed(tree1, tree2, 'b-id', False),
1735
            self.renamed(tree1, tree2, 'c-id', False),
1736
            ])
1737
        self.assertEqual(expected,
1738
                         self.do_iter_changes(tree1, tree2))
4503.1.3 by Vincent Ladeuil
Take review comments into account.
1739
        self.check_has_changes(True, tree1, tree2)
2456.2.2 by John Arbash Meinel
Add another (failing) test case.
1740
1741
    def test_deleted_and_unknown(self):
1742
        """Test a file marked removed, but still present on disk."""
1743
        tree1 = self.make_branch_and_tree('tree1')
1744
        tree2 = self.make_to_branch_and_tree('tree2')
1745
        root_id = tree1.get_root_id()
1746
        tree2.set_root_id(root_id)
1747
1748
        # The final changes should be:
1749
        # bzr add a b c
1750
        # bzr rm --keep b
1751
        self.build_tree_contents([
1752
            ('tree1/a', 'a contents\n'),
1753
            ('tree1/b', 'b contents\n'),
1754
            ('tree1/c', 'c contents\n'),
1755
            ('tree2/a', 'a contents\n'),
1756
            ('tree2/b', 'b contents\n'),
1757
            ('tree2/c', 'c contents\n'),
1758
            ])
1759
        tree1.add(['a', 'b', 'c'], ['a-id', 'b-id', 'c-id'])
1760
        tree2.add(['a', 'c'], ['a-id', 'c-id'])
1761
1762
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1763
        self.not_applicable_if_cannot_represent_unversioned(tree2)
2456.2.2 by John Arbash Meinel
Add another (failing) test case.
1764
1765
        expected = sorted([
1766
            self.deleted(tree1, 'b-id'),
1767
            self.unversioned(tree2, 'b'),
1768
            ])
1769
        self.assertEqual(expected,
1770
                         self.do_iter_changes(tree1, tree2,
1771
                                              want_unversioned=True))
2456.2.5 by John Arbash Meinel
Make sure the output with want_unversioned=False is reasonable.
1772
        expected = sorted([
1773
            self.deleted(tree1, 'b-id'),
1774
            ])
1775
        self.assertEqual(expected,
1776
                         self.do_iter_changes(tree1, tree2,
1777
                                              want_unversioned=False))
2465.1.1 by John Arbash Meinel
Add a (failing) test exposing the bug in _iter_changes
1778
1779
    def test_renamed_and_added(self):
1780
        """Test when we have renamed a file, and put another in its place."""
1781
        tree1 = self.make_branch_and_tree('tree1')
1782
        tree2 = self.make_to_branch_and_tree('tree2')
1783
        root_id = tree1.get_root_id()
1784
        tree2.set_root_id(root_id)
1785
1786
        # The final changes are:
1787
        # bzr add b c
1788
        # bzr mv b a
1789
        # bzr mv c d
1790
        # bzr add b c
1791
1792
        self.build_tree_contents([
1793
            ('tree1/b', 'b contents\n'),
1794
            ('tree1/c', 'c contents\n'),
1795
            ('tree2/a', 'b contents\n'),
1796
            ('tree2/b', 'new b contents\n'),
1797
            ('tree2/c', 'new c contents\n'),
1798
            ('tree2/d', 'c contents\n'),
1799
            ])
1800
        tree1.add(['b', 'c'], ['b1-id', 'c1-id'])
1801
        tree2.add(['a', 'b', 'c', 'd'], ['b1-id', 'b2-id', 'c2-id', 'c1-id'])
1802
1803
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1804
1805
        expected = sorted([
1806
            self.renamed(tree1, tree2, 'b1-id', False),
1807
            self.renamed(tree1, tree2, 'c1-id', False),
1808
            self.added(tree2, 'b2-id'),
1809
            self.added(tree2, 'c2-id'),
1810
            ])
1811
        self.assertEqual(expected,
1812
                         self.do_iter_changes(tree1, tree2,
1813
                                              want_unversioned=True))
2472.3.1 by John Arbash Meinel
Fix bug #111288. When we don't have a match
1814
1815
    def test_renamed_and_unknown(self):
1816
        """A file was moved on the filesystem, but not in bzr."""
1817
        tree1 = self.make_branch_and_tree('tree1')
1818
        tree2 = self.make_to_branch_and_tree('tree2')
1819
        root_id = tree1.get_root_id()
1820
        tree2.set_root_id(root_id)
1821
1822
        # The final changes are:
1823
        # bzr add a b
1824
        # mv a a2
1825
1826
        self.build_tree_contents([
1827
            ('tree1/a', 'a contents\n'),
1828
            ('tree1/b', 'b contents\n'),
1829
            ('tree2/a', 'a contents\n'),
1830
            ('tree2/b', 'b contents\n'),
1831
            ])
1832
        tree1.add(['a', 'b'], ['a-id', 'b-id'])
1833
        tree2.add(['a', 'b'], ['a-id', 'b-id'])
1834
        os.rename('tree2/a', 'tree2/a2')
1835
1836
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
4241.6.7 by Vincent Ladeuil
Add InterCHKRevisionTree
1837
        self.not_applicable_if_missing_in('a', tree2)
2472.3.1 by John Arbash Meinel
Fix bug #111288. When we don't have a match
1838
1839
        expected = sorted([
1840
            self.missing('a-id', 'a', 'a', tree2.get_root_id(), 'file'),
1841
            self.unversioned(tree2, 'a2'),
1842
            ])
1843
        self.assertEqual(expected,
1844
                         self.do_iter_changes(tree1, tree2,
1845
                                              want_unversioned=True))