~bzr-pqm/bzr/bzr.dev

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