/brz/remove-bazaar

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