~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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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
2255.6.4 by Aaron Bentley
merge from dirstate
22
from bzrlib import errors, tests, workingtree_4
2321.3.4 by Alexander Belchenko
test intertree_implementations: skip tests with symlinks on platforms that don't have symlinks support
23
from bzrlib.osutils import file_kind, has_symlinks
3619.4.4 by Robert Collins
Review feedback.
24
from bzrlib.tests import TestNotApplicable
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
25
from bzrlib.tests.intertree_implementations import TestCaseWithTwoTrees
26
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
27
# TODO: test the include_root option.
28
# TODO: test that renaming a directory x->y does not emit a rename for the
29
#       child x/a->y/a.
30
# TODO: test that renaming a directory x-> does not emit a rename for the child
31
#        x/a -> y/a when a supplied_files argument gives either 'x/' or 'y/a'
32
#        -> that is, when the renamed parent is not processed by the function.
33
# TODO: test items are only emitted once when a specific_files list names a dir
34
#       whose parent is now a child.
2255.2.151 by Robert Collins
Handle specific_files natively for WorkingTreeFormat4._iter_changes.
35
# TODO: test specific_files when the target tree has a file and the source a
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
36
#       dir with children, same id and same path.
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
37
# 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.
38
#
39
# TODO: More comparisons between trees with subtrees in different states.
2255.2.236 by Martin Pool
Review cleanups: mostly updating or removing todo comments.
40
#
41
# TODO: Many tests start out by setting the tree roots ids the same, maybe
42
#       that should just be the default for these tests, by changing
43
#       make_branch_and_tree.  mbp 20070307
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
44
45
class TestCompare(TestCaseWithTwoTrees):
46
47
    def test_compare_empty_trees(self):
48
        tree1 = self.make_branch_and_tree('1')
49
        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
50
        tree2.set_root_id(tree1.get_root_id())
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
51
        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.
52
        tree2 = self.get_tree_no_parents_no_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
53
        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.
54
        d = self.intertree_class(tree1, tree2).compare()
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
55
        self.assertEqual([], d.added)
56
        self.assertEqual([], d.modified)
57
        self.assertEqual([], d.removed)
58
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
59
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
60
61
    def test_empty_to_abc_content(self):
62
        tree1 = self.make_branch_and_tree('1')
63
        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
64
        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.
65
        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.
66
        tree2 = self.get_tree_no_parents_abc_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
67
        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.
68
        d = self.intertree_class(tree1, tree2).compare()
69
        self.assertEqual([('a', 'a-id', 'file'),
70
                          ('b', 'b-id', 'directory'),
71
                          ('b/c', 'c-id', 'file'),
72
                         ], d.added)
73
        self.assertEqual([], d.modified)
74
        self.assertEqual([], d.removed)
75
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
76
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
77
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
78
    def test_dangling(self):
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
79
        # This test depends on the ability for some trees to have a difference
80
        # between a 'versioned present' and 'versioned not present' (aka
81
        # dangling) file. In this test there are two trees each with a separate
82
        # dangling file, and the dangling files should be considered absent for
83
        # the test.
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
84
        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.
85
        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
86
        tree2.set_root_id(tree1.get_root_id())
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
87
        self.build_tree(['2/a'])
88
        tree2.add('a')
89
        os.unlink('2/a')
90
        self.build_tree(['1/b'])
91
        tree1.add('b')
92
        os.unlink('1/b')
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
93
        # the conversion to test trees here will leave the trees intact for the
94
        # default intertree, but may perform a commit for other tree types,
95
        # which may reduce the validity of the test. XXX: Think about how to
96
        # address this.
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
97
        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
98
        d = self.intertree_class(tree1, tree2).compare()
99
        self.assertEqual([], d.added)
100
        self.assertEqual([], d.modified)
101
        self.assertEqual([], d.removed)
102
        self.assertEqual([], d.renamed)
103
        self.assertEqual([], d.unchanged)
104
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
105
    def test_abc_content_to_empty(self):
106
        tree1 = self.make_branch_and_tree('1')
107
        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
108
        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.
109
        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.
110
        tree2 = self.get_tree_no_parents_no_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
111
        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.
112
        d = self.intertree_class(tree1, tree2).compare()
113
        self.assertEqual([], d.added)
114
        self.assertEqual([], d.modified)
115
        self.assertEqual([('a', 'a-id', 'file'),
116
                          ('b', 'b-id', 'directory'),
117
                          ('b/c', 'c-id', 'file'),
118
                         ], d.removed)
119
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
120
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
121
122
    def test_content_modification(self):
123
        tree1 = self.make_branch_and_tree('1')
124
        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
125
        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.
126
        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.
127
        tree2 = self.get_tree_no_parents_abc_content_2(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
128
        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.
129
        d = self.intertree_class(tree1, tree2).compare()
130
        self.assertEqual([], d.added)
131
        self.assertEqual([('a', 'a-id', 'file', True, False)], d.modified)
132
        self.assertEqual([], d.removed)
133
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
134
        self.assertEqual([], d.unchanged)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
135
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
136
    def test_meta_modification(self):
137
        tree1 = self.make_branch_and_tree('1')
138
        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
139
        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.
140
        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.
141
        tree2 = self.get_tree_no_parents_abc_content_3(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
142
        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.
143
        d = self.intertree_class(tree1, tree2).compare()
144
        self.assertEqual([], d.added)
145
        self.assertEqual([('b/c', 'c-id', 'file', False, True)], d.modified)
146
        self.assertEqual([], d.removed)
147
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
148
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
149
150
    def test_file_rename(self):
151
        tree1 = self.make_branch_and_tree('1')
152
        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
153
        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.
154
        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.
155
        tree2 = self.get_tree_no_parents_abc_content_4(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
156
        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.
157
        d = self.intertree_class(tree1, tree2).compare()
158
        self.assertEqual([], d.added)
159
        self.assertEqual([], d.modified)
160
        self.assertEqual([], d.removed)
161
        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=...).
162
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
163
164
    def test_file_rename_and_modification(self):
165
        tree1 = self.make_branch_and_tree('1')
166
        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
167
        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.
168
        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.
169
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
170
        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.
171
        d = self.intertree_class(tree1, tree2).compare()
172
        self.assertEqual([], d.added)
173
        self.assertEqual([], d.modified)
174
        self.assertEqual([], d.removed)
175
        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=...).
176
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
177
178
    def test_file_rename_and_meta_modification(self):
179
        tree1 = self.make_branch_and_tree('1')
180
        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
181
        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.
182
        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.
183
        tree2 = self.get_tree_no_parents_abc_content_6(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
184
        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.
185
        d = self.intertree_class(tree1, tree2).compare()
186
        self.assertEqual([], d.added)
187
        self.assertEqual([], d.modified)
188
        self.assertEqual([], d.removed)
189
        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=...).
190
        self.assertEqual([], d.unchanged)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
191
192
    def test_empty_to_abc_content_a_only(self):
193
        tree1 = self.make_branch_and_tree('1')
194
        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
195
        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.
196
        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.
197
        tree2 = self.get_tree_no_parents_abc_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
198
        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.
199
        d = self.intertree_class(tree1, tree2).compare(specific_files=['a'])
200
        self.assertEqual([('a', 'a-id', 'file')], d.added)
201
        self.assertEqual([], d.modified)
202
        self.assertEqual([], d.removed)
203
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
204
        self.assertEqual([], d.unchanged)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
205
206
    def test_empty_to_abc_content_a_and_c_only(self):
207
        tree1 = self.make_branch_and_tree('1')
208
        tree2 = self.make_to_branch_and_tree('2')
209
        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.
210
        tree2 = self.get_tree_no_parents_abc_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
211
        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.
212
        d = self.intertree_class(tree1, tree2).compare(
213
            specific_files=['a', 'b/c'])
214
        self.assertEqual(
215
            [('a', 'a-id', 'file'), ('b/c', 'c-id', 'file')],
216
            d.added)
217
        self.assertEqual([], d.modified)
218
        self.assertEqual([], d.removed)
219
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
220
        self.assertEqual([], d.unchanged)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
221
222
    def test_empty_to_abc_content_b_only(self):
223
        """Restricting to a dir matches the children of the dir."""
224
        tree1 = self.make_branch_and_tree('1')
225
        tree2 = self.make_to_branch_and_tree('2')
226
        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.
227
        tree2 = self.get_tree_no_parents_abc_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
228
        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.
229
        d = self.intertree_class(tree1, tree2).compare(specific_files=['b'])
230
        self.assertEqual(
231
            [('b', 'b-id', 'directory'),('b/c', 'c-id', 'file')],
232
            d.added)
233
        self.assertEqual([], d.modified)
234
        self.assertEqual([], d.removed)
235
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
236
        self.assertEqual([], d.unchanged)
237
238
    def test_unchanged_with_renames_and_modifications(self):
239
        """want_unchanged should generate a list of unchanged entries."""
240
        tree1 = self.make_branch_and_tree('1')
241
        tree2 = self.make_to_branch_and_tree('2')
242
        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.
243
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
244
        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=...).
245
        d = self.intertree_class(tree1, tree2).compare(want_unchanged=True)
246
        self.assertEqual([], d.added)
247
        self.assertEqual([], d.modified)
248
        self.assertEqual([], d.removed)
249
        self.assertEqual([('a', 'd', 'a-id', 'file', True, False)], d.renamed)
250
        self.assertEqual(
251
            [(u'b', 'b-id', 'directory'), (u'b/c', 'c-id', 'file')],
252
            d.unchanged)
253
254
    def test_extra_trees_finds_ids(self):
255
        """Ask for a delta between two trees with a path present in a third."""
256
        tree1 = self.make_branch_and_tree('1')
257
        tree2 = self.make_to_branch_and_tree('2')
258
        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.
259
        tree2 = self.get_tree_no_parents_abc_content_3(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
260
        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.
261
        d = self.intertree_class(tree1, tree2).compare(specific_files=['b'])
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
262
        # 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.
263
        # a dispatch. XXX: For dirstate it does speak to the optimisability of
264
        # the lookup, in merged trees it can be fast-pathed. We probably want
265
        # 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=...).
266
        tree3 = self.make_branch_and_tree('3')
267
        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.
268
        tree3.lock_read()
269
        self.addCleanup(tree3.unlock)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
270
        # tree 3 has 'e' which is 'c-id'. Tree 1 has c-id at b/c, and Tree 2
271
        # has c-id at b/c with its exec flag toggled.
272
        # without extra_trees, we should get no modifications from this
273
        # so do one, to be sure the test is valid.
274
        d = self.intertree_class(tree1, tree2).compare(
275
            specific_files=['e'])
276
        self.assertEqual([], d.modified)
277
        # now give it an additional lookup:
278
        d = self.intertree_class(tree1, tree2).compare(
279
            specific_files=['e'], extra_trees=[tree3])
280
        self.assertEqual([], d.added)
281
        self.assertEqual([('b/c', 'c-id', 'file', False, True)], d.modified)
282
        self.assertEqual([], d.removed)
283
        self.assertEqual([], d.renamed)
284
        self.assertEqual([], d.unchanged)
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
285
286
    def test_require_versioned(self):
287
        # this does not quite robustly test, as it is passing in missing paths
288
        # 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
289
        # 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.
290
        # get present-but-not-versioned files for trees that can do that.
291
        tree1 = self.make_branch_and_tree('1')
292
        tree2 = self.make_to_branch_and_tree('2')
293
        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.
294
        tree2 = self.get_tree_no_parents_abc_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
295
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
296
        self.assertRaises(errors.PathsNotVersionedError,
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
297
            self.intertree_class(tree1, tree2).compare,
298
            specific_files=['d'],
299
            require_versioned=True)
2012.1.1 by Aaron Bentley
Implement change iterator
300
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
301
    def test_default_ignores_unversioned_files(self):
302
        tree1 = self.make_branch_and_tree('tree1')
303
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
304
        tree2.set_root_id(tree1.get_root_id())
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
305
        self.build_tree(['tree1/a', 'tree1/c',
306
                         'tree2/a', 'tree2/b', 'tree2/c'])
307
        tree1.add(['a', 'c'], ['a-id', 'c-id'])
308
        tree2.add(['a', 'c'], ['a-id', 'c-id'])
309
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
310
        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.
311
        d = self.intertree_class(tree1, tree2).compare()
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
312
        self.assertEqual([], d.added)
313
        self.assertEqual([(u'a', 'a-id', 'file', True, False),
314
            (u'c', 'c-id', 'file', True, False)], d.modified)
315
        self.assertEqual([], d.removed)
316
        self.assertEqual([], d.renamed)
317
        self.assertEqual([], d.unchanged)
318
        self.assertEqual([], d.unversioned)
319
320
    def test_unversioned_paths_in_tree(self):
321
        tree1 = self.make_branch_and_tree('tree1')
322
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
323
        tree2.set_root_id(tree1.get_root_id())
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
324
        self.build_tree(['tree2/file', 'tree2/dir/'])
2408.1.2 by Alexander Belchenko
intertree_implementations: make usage of symlinks optional
325
        if has_symlinks():
326
            os.symlink('target', 'tree2/link')
327
            links_supported = True
328
        else:
329
            links_supported = False
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
330
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
331
        d = self.intertree_class(tree1, tree2).compare(want_unversioned=True)
332
        self.assertEqual([], d.added)
333
        self.assertEqual([], d.modified)
334
        self.assertEqual([], d.removed)
335
        self.assertEqual([], d.renamed)
336
        self.assertEqual([], d.unchanged)
2408.1.2 by Alexander Belchenko
intertree_implementations: make usage of symlinks optional
337
        expected_unversioned = [(u'dir', None, 'directory'),
338
                                (u'file', None, 'file')]
339
        if links_supported:
340
            expected_unversioned.append((u'link', None, 'symlink'))
341
        self.assertEqual(expected_unversioned, d.unversioned)
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
342
2012.1.1 by Aaron Bentley
Implement change iterator
343
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
344
class TestIterChanges(TestCaseWithTwoTrees):
2012.1.1 by Aaron Bentley
Implement change iterator
345
    """Test the comparison iterator"""
346
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
347
    def do_iter_changes(self, tree1, tree2, **extra_args):
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
348
        """Helper to run iter_changes from tree1 to tree2.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
349
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
350
        :param tree1, tree2:  The source and target trees. These will be locked
351
            automatically.
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
352
        :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.
353
            inspected by this test helper.
354
        """
355
        tree1.lock_read()
356
        tree2.lock_read()
357
        try:
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
358
            # sort order of output is not strictly defined
359
            return sorted(self.intertree_class(tree1, tree2)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
360
                .iter_changes(**extra_args))
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
361
        finally:
362
            tree1.unlock()
363
            tree2.unlock()
364
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
365
    def mutable_trees_to_locked_test_trees(self, tree1, tree2):
366
        """Convert the working trees into test trees.
367
368
        Read lock them, and add the unlock to the cleanup.
369
        """
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
370
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
371
        tree1.lock_read()
372
        self.addCleanup(tree1.unlock)
373
        tree2.lock_read()
374
        self.addCleanup(tree2.unlock)
375
        return tree1, tree2
376
2255.7.15 by John Arbash Meinel
Try to create an intertree test that exposes the walkdir vs dirstate mismatch. No luck yet.
377
    def make_tree_with_special_names(self):
378
        """Create a tree with filenames chosen to exercise the walk order."""
379
        tree1 = self.make_branch_and_tree('tree1')
380
        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
381
        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.
382
        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.
383
        tree2.commit('initial', rev_id='rev-1')
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
384
        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.
385
        return (tree1, tree2, paths, path_ids)
386
387
    def make_trees_with_special_names(self):
388
        """Both trees will use the special names.
389
390
        But the contents will differ for each file.
391
        """
392
        tree1 = self.make_branch_and_tree('tree1')
393
        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
394
        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.
395
        paths, path_ids = self._create_special_names(tree1, 'tree1')
396
        paths, path_ids = self._create_special_names(tree2, 'tree2')
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
397
        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.
398
        return (tree1, tree2, paths, path_ids)
399
400
    def _create_special_names(self, tree, base_path):
401
        """Create a tree with paths that expose differences in sort orders."""
402
        # Each directory will have a single file named 'f' inside
403
        dirs = ['a',
404
                'a-a',
405
                'a/a',
406
                'a/a-a',
407
                'a/a/a',
408
                'a/a/a-a',
409
                'a/a/a/a',
410
                'a/a/a/a-a',
411
                'a/a/a/a/a',
412
               ]
413
        with_slashes = []
414
        paths = []
415
        path_ids = []
416
        for d in dirs:
417
            with_slashes.append(base_path + '/' + d + '/')
418
            with_slashes.append(base_path + '/' + d + '/f')
419
            paths.append(d)
420
            paths.append(d+'/f')
421
            path_ids.append(d.replace('/', '_') + '-id')
422
            path_ids.append(d.replace('/', '_') + '_f-id')
423
        self.build_tree(with_slashes)
424
        tree.add(paths, path_ids)
425
        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.
426
2012.1.1 by Aaron Bentley
Implement change iterator
427
    def test_compare_empty_trees(self):
428
        tree1 = self.make_branch_and_tree('1')
429
        tree2 = self.make_to_branch_and_tree('2')
430
        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.
431
        tree2 = self.get_tree_no_parents_no_content(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
432
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
3254.1.2 by Aaron Bentley
Fix doiter_changes
433
        self.assertEqual([], self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
434
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
435
    def added(self, tree, file_id):
3363.14.7 by Aaron Bentley
Get more tests passing
436
        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.
437
        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.
438
                (None, entry.name), (None, entry.kind),
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
439
                (None, entry.executable))
440
3363.14.7 by Aaron Bentley
Get more tests passing
441
    @staticmethod
442
    def get_path_entry(tree, file_id):
443
        iterator = tree.iter_entries_by_dir(specific_file_ids=[file_id])
444
        return iterator.next()
445
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.
446
    def content_changed(self, tree, file_id):
3363.14.7 by Aaron Bentley
Get more tests passing
447
        path, entry = self.get_path_entry(tree, file_id)
448
        return (file_id, (path, path), True, (True, True),
449
                (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.
450
                (entry.name, entry.name), (entry.kind, entry.kind),
451
                (entry.executable, entry.executable))
452
453
    def kind_changed(self, from_tree, to_tree, file_id):
3363.14.7 by Aaron Bentley
Get more tests passing
454
        from_path, old_entry = self.get_path_entry(from_tree, file_id)
455
        path, new_entry = self.get_path_entry(to_tree, file_id)
456
        return (file_id, (from_path, path), True, (True, True),
457
                (old_entry.parent_id, new_entry.parent_id),
458
                (old_entry.name, new_entry.name),
459
                (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.
460
                (old_entry.executable, new_entry.executable))
461
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
462
    def missing(self, file_id, from_path, to_path, parent_id, kind):
463
        _, from_basename = os.path.split(from_path)
464
        _, to_basename = os.path.split(to_path)
465
        # missing files have both paths, but no kind.
466
        return (file_id, (from_path, to_path), True, (True, True),
467
            (parent_id, parent_id),
468
            (from_basename, to_basename), (kind, None), (False, False))
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
469
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
470
    def deleted(self, tree, file_id):
471
        entry = tree.inventory[file_id]
472
        path = tree.id2path(file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
473
        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.
474
                (entry.name, None), (entry.kind, None),
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
475
                (entry.executable, None))
476
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
477
    def renamed(self, from_tree, to_tree, file_id, content_changed):
3363.14.8 by Aaron Bentley
Fix more tests
478
        from_path, from_entry = self.get_path_entry(from_tree, file_id)
479
        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.
480
        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.
481
            (from_entry.parent_id, to_entry.parent_id),
482
            (from_entry.name, to_entry.name),
483
            (from_entry.kind, to_entry.kind),
484
            (from_entry.executable, to_entry.executable))
485
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.
486
    def unchanged(self, tree, file_id):
3363.14.8 by Aaron Bentley
Fix more tests
487
        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.
488
        parent = entry.parent_id
489
        name = entry.name
490
        kind = entry.kind
491
        executable = entry.executable
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
492
        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.
493
               (parent, parent), (name, name), (kind, kind),
494
               (executable, executable))
495
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
496
    def unversioned(self, tree, path):
497
        """Create an unversioned result."""
498
        _, basename = os.path.split(path)
3363.14.7 by Aaron Bentley
Get more tests passing
499
        kind = tree._comparison_data(None, path)[0]
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
500
        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.
501
                (None, basename), (None, kind),
502
                (None, False))
503
2012.1.1 by Aaron Bentley
Implement change iterator
504
    def test_empty_to_abc_content(self):
505
        tree1 = self.make_branch_and_tree('1')
506
        tree2 = self.make_to_branch_and_tree('2')
507
        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.
508
        tree2 = self.get_tree_no_parents_abc_content(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
509
        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.
510
        expected_results = sorted([
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
511
            self.added(tree2, 'root-id'),
512
            self.added(tree2, 'a-id'),
513
            self.added(tree2, 'b-id'),
514
            self.added(tree2, 'c-id'),
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
515
            self.deleted(tree1, 'empty-root-id')])
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
516
        self.assertEqual(expected_results, self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
517
2748.3.1 by Aaron Bentley
Start supporting [] for empty list
518
    def test_empty_specific_files(self):
519
        tree1 = self.make_branch_and_tree('1')
520
        tree2 = self.make_to_branch_and_tree('2')
521
        tree1 = self.get_tree_no_parents_no_content(tree1)
522
        tree2 = self.get_tree_no_parents_abc_content(tree2)
523
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
524
        self.assertEqual([],
525
            self.do_iter_changes(tree1, tree2, specific_files=[]))
526
527
    def test_no_specific_files(self):
528
        tree1 = self.make_branch_and_tree('1')
529
        tree2 = self.make_to_branch_and_tree('2')
530
        tree1 = self.get_tree_no_parents_no_content(tree1)
531
        tree2 = self.get_tree_no_parents_abc_content(tree2)
532
        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
533
        expected_results = sorted([
534
            self.added(tree2, 'root-id'),
535
            self.added(tree2, 'a-id'),
536
            self.added(tree2, 'b-id'),
537
            self.added(tree2, 'c-id'),
538
            self.deleted(tree1, 'empty-root-id')])
539
        self.assertEqual(expected_results, self.do_iter_changes(tree1, tree2))
2748.3.1 by Aaron Bentley
Start supporting [] for empty list
540
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
541
    def test_empty_to_abc_content_a_only(self):
542
        tree1 = self.make_branch_and_tree('1')
543
        tree2 = self.make_to_branch_and_tree('2')
544
        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.
545
        tree2 = self.get_tree_no_parents_abc_content(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
546
        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.
547
        self.assertEqual(
548
            [self.added(tree2, 'a-id')],
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
549
            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.
550
551
    def test_abc_content_to_empty_to_abc_content_a_only(self):
552
        tree1 = self.make_branch_and_tree('1')
553
        tree2 = self.make_to_branch_and_tree('2')
554
        tree1 = self.get_tree_no_parents_abc_content(tree1)
555
        tree2 = self.get_tree_no_parents_no_content(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
556
        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.
557
        self.assertEqual(
558
            [self.deleted(tree1, 'a-id')],
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
559
            self.do_iter_changes(tree1, tree2, specific_files=['a']))
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
560
561
    def test_empty_to_abc_content_a_and_c_only(self):
562
        tree1 = self.make_branch_and_tree('1')
563
        tree2 = self.make_to_branch_and_tree('2')
564
        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.
565
        tree2 = self.get_tree_no_parents_abc_content(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
566
        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.
567
        expected_result = [self.added(tree2, 'a-id'), self.added(tree2, 'c-id')]
568
        self.assertEqual(expected_result,
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
569
            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
570
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
571
    def test_abc_content_to_empty(self):
2012.1.1 by Aaron Bentley
Implement change iterator
572
        tree1 = self.make_branch_and_tree('1')
573
        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.
574
        tree1 = self.get_tree_no_parents_abc_content(tree1)
575
        tree2 = self.get_tree_no_parents_no_content(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
576
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
2012.1.1 by Aaron Bentley
Implement change iterator
577
        def deleted(file_id):
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
578
            entry = tree1.inventory[file_id]
579
            path = tree1.id2path(file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
580
            return (file_id, (path, None), True, (True, False),
2012.1.1 by Aaron Bentley
Implement change iterator
581
                    (entry.parent_id, None),
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
582
                    (entry.name, None), (entry.kind, None),
2012.1.1 by Aaron Bentley
Implement change iterator
583
                    (entry.executable, None))
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
584
        expected_results = sorted([
585
            self.added(tree2, 'empty-root-id'),
586
            deleted('root-id'), deleted('a-id'),
587
            deleted('b-id'), deleted('c-id')])
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
588
        self.assertEqual(
589
            expected_results,
590
            self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
591
592
    def test_content_modification(self):
593
        tree1 = self.make_branch_and_tree('1')
594
        tree2 = self.make_to_branch_and_tree('2')
595
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
596
        tree2 = self.get_tree_no_parents_abc_content_2(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
597
        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.
598
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
599
        self.assertEqual([('a-id', ('a', 'a'), True, (True, True),
600
                           (root_id, root_id), ('a', 'a'),
601
                           ('file', 'file'), (False, False))],
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
602
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
603
604
    def test_meta_modification(self):
605
        tree1 = self.make_branch_and_tree('1')
606
        tree2 = self.make_to_branch_and_tree('2')
607
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
608
        tree2 = self.get_tree_no_parents_abc_content_3(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
609
        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.
610
        self.assertEqual([('c-id', ('b/c', 'b/c'), False, (True, True),
611
                           ('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.
612
                          (False, True))],
613
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
614
2255.7.6 by Robert Collins
Test for iterating changes past empty directories.
615
    def test_empty_dir(self):
616
        """an empty dir should not cause glitches to surrounding files."""
617
        tree1 = self.make_branch_and_tree('1')
618
        tree2 = self.make_to_branch_and_tree('2')
619
        tree1 = self.get_tree_no_parents_abc_content(tree1)
620
        tree2 = self.get_tree_no_parents_abc_content(tree2)
621
        # the pathname is chosen to fall between 'a' and 'b'.
622
        self.build_tree(['1/a-empty/', '2/a-empty/'])
623
        tree1.add(['a-empty'], ['a-empty'])
624
        tree2.add(['a-empty'], ['a-empty'])
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
625
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.7.6 by Robert Collins
Test for iterating changes past empty directories.
626
        expected = []
627
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
628
2012.1.1 by Aaron Bentley
Implement change iterator
629
    def test_file_rename(self):
630
        tree1 = self.make_branch_and_tree('1')
631
        tree2 = self.make_to_branch_and_tree('2')
632
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
633
        tree2 = self.get_tree_no_parents_abc_content_4(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
634
        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.
635
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
636
        self.assertEqual([('a-id', ('a', 'd'), False, (True, True),
637
                           (root_id, root_id), ('a', 'd'), ('file', 'file'),
638
                           (False, False))],
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
639
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
640
641
    def test_file_rename_and_modification(self):
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)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
645
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
646
        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.
647
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
648
        self.assertEqual([('a-id', ('a', 'd'), True, (True, True),
649
                           (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.
650
                           (False, False))],
651
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
652
653
    def test_file_rename_and_meta_modification(self):
654
        tree1 = self.make_branch_and_tree('1')
655
        tree2 = self.make_to_branch_and_tree('2')
656
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
657
        tree2 = self.get_tree_no_parents_abc_content_6(tree2)
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
658
        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.
659
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
660
        self.assertEqual([('c-id', ('b/c', 'e'), False, (True, True),
661
                           ('b-id', root_id), ('c', 'e'), ('file', 'file'),
662
                           (False, True))],
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
663
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
664
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
665
    def test_missing_in_target(self):
666
        """Test with the target files versioned but absent from disk."""
667
        tree1 = self.make_branch_and_tree('1')
668
        tree2 = self.make_to_branch_and_tree('2')
669
        tree1 = self.get_tree_no_parents_abc_content(tree1)
670
        tree2 = self.get_tree_no_parents_abc_content(tree2)
671
        os.unlink('2/a')
672
        shutil.rmtree('2/b')
673
        # TODO ? have a symlink here?
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
674
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
675
        root_id = tree1.path2id('')
676
        expected = sorted([
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
677
            self.missing('a-id', 'a', 'a', root_id, 'file'),
678
            self.missing('b-id', 'b', 'b', root_id, 'directory'),
679
            self.missing('c-id', 'b/c', 'b/c', 'b-id', 'file'),
680
            ])
681
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
682
683
    def test_missing_and_renamed(self):
684
        tree1 = self.make_branch_and_tree('tree1')
685
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.186 by Martin Pool
Fix up root id for some more comparison tests
686
        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.
687
        self.build_tree(['tree1/file'])
688
        tree1.add(['file'], ['file-id'])
689
        self.build_tree(['tree2/directory/'])
690
        tree2.add(['directory'], ['file-id'])
691
        os.rmdir('tree2/directory')
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
692
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
693
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
694
        root_id = tree1.path2id('')
695
        expected = sorted([
696
            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.
697
            ])
698
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
699
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)
700
    def test_only_in_source_and_missing(self):
701
        tree1 = self.make_branch_and_tree('tree1')
702
        tree2 = self.make_to_branch_and_tree('tree2')
703
        tree2.set_root_id(tree1.get_root_id())
704
        self.build_tree(['tree1/file'])
705
        tree1.add(['file'], ['file-id'])
706
        os.unlink('tree1/file')
707
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
708
        root_id = tree1.path2id('')
709
        if not tree1.path2id('file'):
710
            # The locked test trees conversion could not preserve the missing
711
            # file status. This is normal (e.g. InterDirstateTree falls back
712
            # to InterTree if the basis is not a DirstateRevisionTree, and
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
713
            # revision trees cannot have missing files.
3619.4.4 by Robert Collins
Review feedback.
714
            raise TestNotApplicable()
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)
715
        expected = [('file-id', ('file', None), False, (True, False),
716
            (root_id, None), ('file', None), (None, None), (False, None))]
717
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
718
719
    def test_only_in_target_and_missing(self):
720
        tree1 = self.make_branch_and_tree('tree1')
721
        tree2 = self.make_to_branch_and_tree('tree2')
722
        tree2.set_root_id(tree1.get_root_id())
723
        self.build_tree(['tree2/file'])
724
        tree2.add(['file'], ['file-id'])
725
        os.unlink('tree2/file')
726
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
727
        root_id = tree1.path2id('')
728
        expected = [('file-id', (None, 'file'), False, (False, True),
729
            (None, root_id), (None, 'file'), (None, None), (None, False))]
730
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
731
2012.1.1 by Aaron Bentley
Implement change iterator
732
    def test_unchanged_with_renames_and_modifications(self):
733
        """want_unchanged should generate a list of unchanged entries."""
734
        tree1 = self.make_branch_and_tree('1')
735
        tree2 = self.make_to_branch_and_tree('2')
736
        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.
737
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
738
        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.
739
        root_id = tree1.path2id('')
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
740
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.
741
        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.
742
            self.unchanged(tree1, 'b-id'),
743
            ('a-id', ('a', 'd'), True, (True, True),
744
             (root_id, root_id), ('a', 'd'), ('file', 'file'),
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
745
            (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.
746
            self.do_iter_changes(tree1, tree2, include_unchanged=True))
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
747
748
    def test_compare_subtrees(self):
749
        tree1 = self.make_branch_and_tree('1')
2255.9.2 by Martin Pool
test_compare_subtrees runs against all trees that claim to support
750
        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.
751
            return
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
752
        tree1.set_root_id('root-id')
753
        subtree1 = self.make_branch_and_tree('1/sub')
754
        subtree1.set_root_id('subtree-id')
2255.9.2 by Martin Pool
test_compare_subtrees runs against all trees that claim to support
755
        tree1.add_reference(subtree1)
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
756
757
        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
758
        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.
759
            return
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
760
        tree2.set_root_id('root-id')
761
        subtree2 = self.make_to_branch_and_tree('2/sub')
762
        subtree2.set_root_id('subtree-id')
763
        tree2.add_reference(subtree2)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
764
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
765
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
766
        self.assertEqual([], list(tree2.iter_changes(tree1)))
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
767
        subtree1.commit('commit', rev_id='commit-a')
768
        self.assertEqual([
769
            ('root-id',
770
             (u'', u''),
771
             False,
772
             (True, True),
773
             (None, None),
774
             (u'', u''),
775
             ('directory', 'directory'),
776
             (False, False)),
777
            ('subtree-id',
778
             ('sub', 'sub',),
779
             False,
780
             (True, True),
781
             ('root-id', 'root-id'),
782
             ('sub', 'sub'),
783
             ('tree-reference', 'tree-reference'),
784
             (False, False))],
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
785
                         list(tree2.iter_changes(tree1,
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
786
                             include_unchanged=True)))
2255.2.160 by Martin Pool
(merge) updates from dirstate branch
787
2323.4.2 by Robert Collins
Fix the behaviour of dirstate optimised iter_changes recursing its disk iterator into subtrees inappropriately.
788
    def test_disk_in_subtrees_skipped(self):
789
        """subtrees are considered not-in-the-current-tree.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
790
2323.4.2 by Robert Collins
Fix the behaviour of dirstate optimised iter_changes recursing its disk iterator into subtrees inappropriately.
791
        This test tests the trivial case, where the basis has no paths in the
792
        current trees subtree.
793
        """
794
        tree1 = self.make_branch_and_tree('1')
795
        tree1.set_root_id('root-id')
796
        tree2 = self.make_to_branch_and_tree('2')
797
        if not tree2.supports_tree_reference():
798
            return
799
        tree2.set_root_id('root-id')
800
        subtree2 = self.make_to_branch_and_tree('2/sub')
801
        subtree2.set_root_id('subtree-id')
4100.2.4 by Aaron Bentley
More support for not autodetecting tree refs
802
        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.
803
        self.build_tree(['2/sub/file'])
804
        subtree2.add(['file'])
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
805
806
        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.
807
        # this should filter correctly from above
808
        self.assertEqual([self.added(tree2, 'subtree-id')],
809
            self.do_iter_changes(tree1, tree2, want_unversioned=True))
810
        # and when the path is named
811
        self.assertEqual([self.added(tree2, 'subtree-id')],
812
            self.do_iter_changes(tree1, tree2, specific_files=['sub'],
813
                want_unversioned=True))
814
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
815
    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.
816
        tree1 = self.make_branch_and_tree('tree1')
817
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.186 by Martin Pool
Fix up root id for some more comparison tests
818
        tree2.set_root_id(tree1.get_root_id())
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
819
        self.build_tree(['tree1/a', 'tree1/c',
820
                         'tree2/a', 'tree2/b', 'tree2/c'])
821
        tree1.add(['a', 'c'], ['a-id', 'c-id'])
822
        tree2.add(['a', 'c'], ['a-id', 'c-id'])
823
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
824
        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.
825
826
        # We should ignore the fact that 'b' exists in tree-2
827
        # because the want_unversioned parameter was not given.
828
        expected = sorted([
829
            self.content_changed(tree2, 'a-id'),
830
            self.content_changed(tree2, 'c-id'),
831
            ])
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
832
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
833
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
834
    def test_unversioned_paths_in_tree(self):
835
        tree1 = self.make_branch_and_tree('tree1')
836
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
837
        tree2.set_root_id(tree1.get_root_id())
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
838
        self.build_tree(['tree2/file', 'tree2/dir/'])
2408.1.2 by Alexander Belchenko
intertree_implementations: make usage of symlinks optional
839
        if has_symlinks():
840
            os.symlink('target', 'tree2/link')
841
            links_supported = True
842
        else:
843
            links_supported = False
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
844
        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.
845
        expected = [
846
            self.unversioned(tree2, 'file'),
847
            self.unversioned(tree2, 'dir'),
848
            ]
849
        if links_supported:
850
            expected.append(self.unversioned(tree2, 'link'))
851
        expected = sorted(expected)
852
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
853
            want_unversioned=True))
854
855
    def test_unversioned_paths_in_tree_specific_files(self):
856
        tree1 = self.make_branch_and_tree('tree1')
857
        tree2 = self.make_to_branch_and_tree('tree2')
858
        self.build_tree(['tree2/file', 'tree2/dir/'])
2408.1.2 by Alexander Belchenko
intertree_implementations: make usage of symlinks optional
859
        if has_symlinks():
860
            os.symlink('target', 'tree2/link')
861
            links_supported = True
862
        else:
863
            links_supported = False
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
864
        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.
865
        expected = [
866
            self.unversioned(tree2, 'file'),
867
            self.unversioned(tree2, 'dir'),
868
            ]
869
        specific_files=['file', 'dir']
870
        if links_supported:
871
            expected.append(self.unversioned(tree2, 'link'))
872
            specific_files.append('link')
873
        expected = sorted(expected)
874
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
875
            specific_files=specific_files, require_versioned=False,
876
            want_unversioned=True))
877
878
    def test_unversioned_paths_in_target_matching_source_old_names(self):
879
        # its likely that naive implementations of unversioned file support
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
880
        # 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.
881
        # due to a rename, not due to unversioning it.
882
        # That is, if the old tree has a versioned file 'foo', and
883
        # the new tree has the same file but versioned as 'bar', and also
884
        # has an unknown file 'foo', we should get back output for
885
        # both foo and bar.
886
        tree1 = self.make_branch_and_tree('tree1')
887
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.187 by Martin Pool
set common root ids in more tests
888
        tree2.set_root_id(tree1.get_root_id())
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
889
        self.build_tree(['tree2/file', 'tree2/dir/',
890
            'tree1/file', 'tree2/movedfile',
891
            'tree1/dir/', 'tree2/moveddir/'])
2408.1.2 by Alexander Belchenko
intertree_implementations: make usage of symlinks optional
892
        if has_symlinks():
893
            os.symlink('target', 'tree1/link')
894
            os.symlink('target', 'tree2/link')
895
            os.symlink('target', 'tree2/movedlink')
896
            links_supported = True
897
        else:
898
            links_supported = False
899
        tree1.add(['file', 'dir'], ['file-id', 'dir-id'])
900
        tree2.add(['movedfile', 'moveddir'], ['file-id', 'dir-id'])
901
        if links_supported:
902
            tree1.add(['link'], ['link-id'])
903
            tree2.add(['movedlink'], ['link-id'])
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
904
        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.
905
        root_id = tree1.path2id('')
906
        expected = [
907
            self.renamed(tree1, tree2, 'dir-id', False),
908
            self.renamed(tree1, tree2, 'file-id', True),
909
            self.unversioned(tree2, 'file'),
910
            self.unversioned(tree2, 'dir'),
911
            ]
912
        specific_files=['file', 'dir']
913
        if links_supported:
914
            expected.append(self.renamed(tree1, tree2, 'link-id', False))
915
            expected.append(self.unversioned(tree2, 'link'))
916
            specific_files.append('link')
917
        expected = sorted(expected)
918
        # run once with, and once without specific files, to catch
919
        # potentially different code paths.
920
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
921
            require_versioned=False,
922
            want_unversioned=True))
923
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
924
            specific_files=specific_files, require_versioned=False,
925
            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.
926
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
927
    def test_similar_filenames(self):
928
        """Test when we have a few files with similar names."""
929
        tree1 = self.make_branch_and_tree('tree1')
930
        tree2 = self.make_branch_and_tree('tree2')
931
        tree2.set_root_id(tree1.get_root_id())
932
933
        # The trees are actually identical, but they happen to contain
934
        # similarly named files.
935
        self.build_tree(['tree1/a/',
936
                         'tree1/a/b/',
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
937
                         'tree1/a/b/c/',
938
                         'tree1/a/b/c/d/',
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
939
                         'tree1/a-c/',
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
940
                         'tree1/a-c/e/',
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
941
                         'tree2/a/',
942
                         'tree2/a/b/',
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
943
                         'tree2/a/b/c/',
944
                         'tree2/a/b/c/d/',
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
945
                         'tree2/a-c/',
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
946
                         'tree2/a-c/e/',
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
947
                        ])
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
948
        tree1.add(['a', 'a/b', 'a/b/c', 'a/b/c/d', 'a-c', 'a-c/e'],
949
                  ['a-id', 'b-id', 'c-id', 'd-id', 'a-c-id', 'e-id'])
950
        tree2.add(['a', 'a/b', 'a/b/c', 'a/b/c/d', 'a-c', 'a-c/e'],
951
                  ['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
952
953
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
954
955
        self.assertEqual([], self.do_iter_changes(tree1, tree2,
956
                                                  want_unversioned=True))
2466.5.2 by John Arbash Meinel
Extend the test a bit to make sure the include_unchanged value is correct.
957
        expected = sorted([
958
            self.unchanged(tree2, tree2.get_root_id()),
959
            self.unchanged(tree2, 'a-id'),
960
            self.unchanged(tree2, 'b-id'),
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
961
            self.unchanged(tree2, 'c-id'),
962
            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.
963
            self.unchanged(tree2, 'a-c-id'),
2466.5.4 by John Arbash Meinel
Fix bug #11127 by splitting paths on '/'.
964
            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.
965
            ])
966
        self.assertEqual(expected,
967
                         self.do_iter_changes(tree1, tree2,
968
                                              want_unversioned=True,
969
                                              include_unchanged=True))
2466.5.1 by John Arbash Meinel
Add a (failing) test for bug 111127
970
971
2255.7.87 by Robert Collins
Dont walk unversioned directories in _iter_changes.
972
    def test_unversioned_subtree_only_emits_root(self):
973
        tree1 = self.make_branch_and_tree('tree1')
974
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.188 by Martin Pool
Set common root id in comparison tests
975
        tree2.set_root_id(tree1.get_root_id())
2255.7.87 by Robert Collins
Dont walk unversioned directories in _iter_changes.
976
        self.build_tree(['tree2/dir/', 'tree2/dir/file'])
3363.14.9 by Aaron Bentley
Ensure TransformPreview is finalized
977
        tree1, tree2 = self.mutable_trees_to_test_trees(self, tree1, tree2)
2255.7.87 by Robert Collins
Dont walk unversioned directories in _iter_changes.
978
        expected = [
979
            self.unversioned(tree2, 'dir'),
980
            ]
981
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
982
            want_unversioned=True))
983
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.
984
    def make_trees_with_symlinks(self):
985
        tree1 = self.make_branch_and_tree('tree1')
986
        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
987
        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.
988
        self.build_tree(['tree1/fromfile', 'tree1/fromdir/'])
989
        self.build_tree(['tree2/tofile', 'tree2/todir/', 'tree2/unknown'])
990
        os.symlink('original', 'tree1/changed')
991
        os.symlink('original', 'tree1/removed')
992
        os.symlink('original', 'tree1/tofile')
993
        os.symlink('original', 'tree1/todir')
994
        # we make the unchanged link point at unknown to catch incorrect
995
        # symlink-following code in the specified_files test.
996
        os.symlink('unknown', 'tree1/unchanged')
997
        os.symlink('new',      'tree2/added')
998
        os.symlink('new',      'tree2/changed')
999
        os.symlink('new',      'tree2/fromfile')
1000
        os.symlink('new',      'tree2/fromdir')
1001
        os.symlink('unknown', 'tree2/unchanged')
1002
        from_paths_and_ids = [
1003
            'fromdir',
1004
            'fromfile',
1005
            'changed',
1006
            'removed',
1007
            'todir',
1008
            'tofile',
1009
            'unchanged',
1010
            ]
1011
        to_paths_and_ids = [
1012
            'added',
1013
            'fromdir',
1014
            'fromfile',
1015
            'changed',
1016
            'todir',
1017
            'tofile',
1018
            'unchanged',
1019
            ]
1020
        tree1.add(from_paths_and_ids, from_paths_and_ids)
1021
        tree2.add(to_paths_and_ids, to_paths_and_ids)
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1022
        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.
1023
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
1024
    def test_versioned_symlinks(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
1025
        self.requireFeature(tests.SymlinkFeature)
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1026
        tree1, tree2 = self.make_trees_with_symlinks()
1027
        root_id = tree1.path2id('')
1028
        expected = [
1029
            self.unchanged(tree1, tree1.path2id('')),
1030
            self.added(tree2, 'added'),
1031
            self.content_changed(tree2, 'changed'),
1032
            self.kind_changed(tree1, tree2, 'fromdir'),
1033
            self.kind_changed(tree1, tree2, 'fromfile'),
1034
            self.deleted(tree1, 'removed'),
1035
            self.unchanged(tree2, 'unchanged'),
1036
            self.unversioned(tree2, 'unknown'),
1037
            self.kind_changed(tree1, tree2, 'todir'),
1038
            self.kind_changed(tree1, tree2, 'tofile'),
1039
            ]
1040
        expected = sorted(expected)
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
1041
        self.assertEqual(expected,
1042
            self.do_iter_changes(tree1, tree2, include_unchanged=True,
1043
                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.
1044
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
1045
    def test_versioned_symlinks_specific_files(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
1046
        self.requireFeature(tests.SymlinkFeature)
2255.7.3 by Robert Collins
Add tests for _iter_changes with symlinks, disabled until unversioned file support is added, as that affects the test expected value.
1047
        tree1, tree2 = self.make_trees_with_symlinks()
1048
        root_id = tree1.path2id('')
1049
        expected = [
1050
            self.added(tree2, 'added'),
1051
            self.content_changed(tree2, 'changed'),
1052
            self.kind_changed(tree1, tree2, 'fromdir'),
1053
            self.kind_changed(tree1, tree2, 'fromfile'),
1054
            self.deleted(tree1, 'removed'),
1055
            self.kind_changed(tree1, tree2, 'todir'),
1056
            self.kind_changed(tree1, tree2, 'tofile'),
1057
            ]
1058
        expected = sorted(expected)
1059
        # we should get back just the changed links. We pass in 'unchanged' to
1060
        # make sure that it is correctly not returned - and neither is the
1061
        # unknown path 'unknown' which it points at.
1062
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
1063
            specific_files=['added', 'changed', 'fromdir', 'fromfile',
1064
            'removed', 'unchanged', 'todir', 'tofile']))
2255.7.15 by John Arbash Meinel
Try to create an intertree test that exposes the walkdir vs dirstate mismatch. No luck yet.
1065
2255.7.21 by John Arbash Meinel
Get iter_changes working again, by fixing set_parent_trees to
1066
    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.
1067
        tree1, tree2, paths, path_ids = self.make_tree_with_special_names()
1068
        expected = sorted(self.added(tree2, f_id) for f_id in path_ids)
1069
        self.assertEqual(expected, self.do_iter_changes(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.
1070
1071
    def test_trees_with_special_names(self):
1072
        tree1, tree2, paths, path_ids = self.make_trees_with_special_names()
1073
        expected = sorted(self.content_changed(tree2, f_id) for f_id in path_ids
1074
                          if f_id.endswith('_f-id'))
1075
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
2255.7.34 by John Arbash Meinel
Clean up test_bad_files, and fix a bug in _iter_changes when
1076
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1077
    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.
1078
        tree1 = self.make_branch_and_tree('tree1')
1079
        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
1080
        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.
1081
        self.build_tree(['tree1/a', 'tree1/b/', 'tree1/b/c',
1082
                         'tree1/b/d/', 'tree1/b/d/e', 'tree1/f/', 'tree1/f/g',
1083
                         'tree2/a', 'tree2/f/', 'tree2/f/g'])
1084
        tree1.add(['a', 'b', 'b/c', 'b/d/', 'b/d/e', 'f', 'f/g'],
1085
                  ['a-id', 'b-id', 'c-id', 'd-id', 'e-id', 'f-id', 'g-id'])
1086
        tree2.add(['a', 'f', 'f/g'], ['a-id', 'f-id', 'g-id'])
1087
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1088
        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.
1089
        # We should notice that 'b' and all its children are deleted
2255.7.35 by John Arbash Meinel
Handle the case when a directory has been removed, and isn't the last entry.
1090
        expected = sorted([
1091
            self.content_changed(tree2, 'a-id'),
1092
            self.content_changed(tree2, 'g-id'),
1093
            self.deleted(tree1, 'b-id'),
1094
            self.deleted(tree1, 'c-id'),
1095
            self.deleted(tree1, 'd-id'),
1096
            self.deleted(tree1, 'e-id'),
1097
            ])
1098
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
2360.1.1 by John Arbash Meinel
Basic implementation test that makes sure _iter_changes handles unknown files.
1099
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1100
    def test_added_unicode(self):
1101
        tree1 = self.make_branch_and_tree('tree1')
1102
        tree2 = self.make_to_branch_and_tree('tree2')
1103
        root_id = tree1.get_root_id()
1104
        tree2.set_root_id(root_id)
1105
1106
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1107
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1108
        a_id = u'\u03b1-id'.encode('utf8')
1109
        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.
1110
        try:
1111
            self.build_tree([u'tree1/\u03b1/',
1112
                             u'tree2/\u03b1/',
1113
                             u'tree2/\u03b1/\u03c9-added',
1114
                            ])
1115
        except UnicodeError:
1116
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1117
        tree1.add([u'\u03b1'], [a_id])
1118
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-added'], [a_id, added_id])
1119
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1120
        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.
1121
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1122
        self.assertEqual([self.added(tree2, added_id)],
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1123
                         self.do_iter_changes(tree1, tree2))
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1124
        self.assertEqual([self.added(tree2, added_id)],
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1125
                         self.do_iter_changes(tree1, tree2,
1126
                                              specific_files=[u'\u03b1']))
1127
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1128
    def test_deleted_unicode(self):
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1129
        tree1 = self.make_branch_and_tree('tree1')
1130
        tree2 = self.make_to_branch_and_tree('tree2')
1131
        root_id = tree1.get_root_id()
1132
        tree2.set_root_id(root_id)
1133
1134
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1135
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1136
        a_id = u'\u03b1-id'.encode('utf8')
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1137
        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.
1138
        try:
1139
            self.build_tree([u'tree1/\u03b1/',
1140
                             u'tree1/\u03b1/\u03c9-deleted',
1141
                             u'tree2/\u03b1/',
1142
                            ])
1143
        except UnicodeError:
1144
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1145
        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.
1146
        tree2.add([u'\u03b1'], [a_id])
1147
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1148
        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.
1149
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1150
        self.assertEqual([self.deleted(tree1, deleted_id)],
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1151
                         self.do_iter_changes(tree1, tree2))
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1152
        self.assertEqual([self.deleted(tree1, deleted_id)],
2360.1.3 by John Arbash Meinel
Start splitting up the overzealous test into focused tests.
1153
                         self.do_iter_changes(tree1, tree2,
1154
                                              specific_files=[u'\u03b1']))
1155
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1156
    def test_modified_unicode(self):
2360.1.1 by John Arbash Meinel
Basic implementation test that makes sure _iter_changes handles unknown files.
1157
        tree1 = self.make_branch_and_tree('tree1')
1158
        tree2 = self.make_to_branch_and_tree('tree2')
1159
        root_id = tree1.get_root_id()
1160
        tree2.set_root_id(root_id)
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1161
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1162
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1163
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1164
        a_id = u'\u03b1-id'.encode('utf8')
1165
        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.
1166
        try:
1167
            self.build_tree([u'tree1/\u03b1/',
1168
                             u'tree1/\u03b1/\u03c9-modified',
1169
                             u'tree2/\u03b1/',
1170
                             u'tree2/\u03b1/\u03c9-modified',
1171
                            ])
1172
        except UnicodeError:
1173
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1174
        tree1.add([u'\u03b1', u'\u03b1/\u03c9-modified'], [a_id, mod_id])
1175
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-modified'], [a_id, mod_id])
1176
1177
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1178
1179
        self.assertEqual([self.content_changed(tree1, mod_id)],
1180
                         self.do_iter_changes(tree1, tree2))
1181
        self.assertEqual([self.content_changed(tree1, mod_id)],
1182
                         self.do_iter_changes(tree1, tree2,
1183
                                              specific_files=[u'\u03b1']))
1184
1185
    def test_renamed_unicode(self):
1186
        tree1 = self.make_branch_and_tree('tree1')
1187
        tree2 = self.make_to_branch_and_tree('tree2')
1188
        root_id = tree1.get_root_id()
1189
        tree2.set_root_id(root_id)
1190
1191
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1192
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1193
        a_id = u'\u03b1-id'.encode('utf8')
1194
        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.
1195
        try:
1196
            self.build_tree([u'tree1/\u03b1/',
1197
                             u'tree2/\u03b1/',
1198
                            ])
1199
        except UnicodeError:
1200
            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.
1201
        self.build_tree_contents([(u'tree1/\u03c9-source', 'contents\n'),
1202
                                  (u'tree2/\u03b1/\u03c9-target', 'contents\n'),
1203
                                 ])
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1204
        tree1.add([u'\u03b1', u'\u03c9-source'], [a_id, rename_id])
1205
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-target'], [a_id, rename_id])
1206
1207
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1208
1209
        self.assertEqual([self.renamed(tree1, tree2, rename_id, False)],
1210
                         self.do_iter_changes(tree1, tree2))
1211
        self.assertEqual([self.renamed(tree1, tree2, rename_id, False)],
1212
                         self.do_iter_changes(tree1, tree2,
1213
                                              specific_files=[u'\u03b1']))
1214
1215
    def test_unchanged_unicode(self):
1216
        tree1 = self.make_branch_and_tree('tree1')
1217
        tree2 = self.make_to_branch_and_tree('tree2')
1218
        root_id = tree1.get_root_id()
1219
        tree2.set_root_id(root_id)
1220
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1221
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1222
        a_id = u'\u03b1-id'.encode('utf8')
1223
        subfile_id = u'\u03c9-subfile-id'.encode('utf8')
1224
        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.
1225
        try:
1226
            self.build_tree([u'tree1/\u03b1/',
1227
                             u'tree2/\u03b1/',
1228
                            ])
1229
        except UnicodeError:
1230
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1231
        self.build_tree_contents([
1232
            (u'tree1/\u03b1/\u03c9-subfile', 'sub contents\n'),
1233
            (u'tree2/\u03b1/\u03c9-subfile', 'sub contents\n'),
1234
            (u'tree1/\u03c9-rootfile', 'root contents\n'),
1235
            (u'tree2/\u03c9-rootfile', 'root contents\n'),
1236
            ])
1237
        tree1.add([u'\u03b1', u'\u03b1/\u03c9-subfile', u'\u03c9-rootfile'],
1238
                  [a_id, subfile_id, rootfile_id])
1239
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-subfile', u'\u03c9-rootfile'],
1240
                  [a_id, subfile_id, rootfile_id])
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1241
2360.1.4 by John Arbash Meinel
Clean up of test_compare code.
1242
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1243
2360.1.1 by John Arbash Meinel
Basic implementation test that makes sure _iter_changes handles unknown files.
1244
        expected = sorted([
1245
            self.unchanged(tree1, root_id),
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1246
            self.unchanged(tree1, a_id),
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1247
            self.unchanged(tree1, subfile_id),
1248
            self.unchanged(tree1, rootfile_id),
1249
            ])
1250
        self.assertEqual(expected,
1251
                         self.do_iter_changes(tree1, tree2,
1252
                                              include_unchanged=True))
1253
1254
        # We should also be able to select just a subset
1255
        expected = sorted([
1256
            self.unchanged(tree1, a_id),
1257
            self.unchanged(tree1, subfile_id),
1258
            ])
1259
        self.assertEqual(expected,
1260
                         self.do_iter_changes(tree1, tree2,
1261
                                              specific_files=[u'\u03b1'],
1262
                                              include_unchanged=True))
1263
1264
    def test_unknown_unicode(self):
1265
        tree1 = self.make_branch_and_tree('tree1')
1266
        tree2 = self.make_to_branch_and_tree('tree2')
1267
        root_id = tree1.get_root_id()
1268
        tree2.set_root_id(root_id)
1269
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
1270
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
1271
        a_id = u'\u03b1-id'.encode('utf8')
2360.1.8 by John Arbash Meinel
Update the tests to handle when fs is non-unicode.
1272
        try:
1273
            self.build_tree([u'tree1/\u03b1/',
1274
                             u'tree2/\u03b1/',
1275
                             u'tree2/\u03b1/unknown_dir/',
1276
                             u'tree2/\u03b1/unknown_file',
1277
                             u'tree2/\u03b1/unknown_dir/file',
1278
                             u'tree2/\u03c9-unknown_root_file',
1279
                            ])
1280
        except UnicodeError:
1281
            raise tests.TestSkipped("Could not create Unicode files.")
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1282
        tree1.add([u'\u03b1'], [a_id])
1283
        tree2.add([u'\u03b1'], [a_id])
1284
1285
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1286
1287
        expected = sorted([
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1288
            self.unversioned(tree2, u'\u03b1/unknown_dir'),
1289
            self.unversioned(tree2, u'\u03b1/unknown_file'),
1290
            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.
1291
            # a/unknown_dir/file should not be included because we should not
1292
            # recurse into unknown_dir
1293
            # self.unversioned(tree2, 'a/unknown_dir/file'),
1294
            ])
1295
        self.assertEqual(expected,
1296
                         self.do_iter_changes(tree1, tree2,
1297
                                              require_versioned=False,
1298
                                              want_unversioned=True))
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1299
        self.assertEqual([], # Without want_unversioned we should get nothing
1300
                         self.do_iter_changes(tree1, tree2))
2360.1.2 by John Arbash Meinel
Add an overzealous test, for Unicode support of _iter_changes.
1301
1302
        # We should also be able to select just a subset
1303
        expected = sorted([
1304
            self.unversioned(tree2, u'\u03b1/unknown_dir'),
1305
            self.unversioned(tree2, u'\u03b1/unknown_file'),
1306
            ])
1307
        self.assertEqual(expected,
1308
                         self.do_iter_changes(tree1, tree2,
1309
                                              specific_files=[u'\u03b1'],
1310
                                              require_versioned=False,
1311
                                              want_unversioned=True))
2360.1.5 by John Arbash Meinel
Split out the unicode tests properly.
1312
        self.assertEqual([], # Without want_unversioned we should get nothing
1313
                         self.do_iter_changes(tree1, tree2,
1314
                                              specific_files=[u'\u03b1']))
2402.2.1 by John Arbash Meinel
Add a test which exposes the bug in WT4._iter_changes()
1315
1316
    def test_unknown_empty_dir(self):
1317
        tree1 = self.make_branch_and_tree('tree1')
1318
        tree2 = self.make_to_branch_and_tree('tree2')
1319
        root_id = tree1.get_root_id()
1320
        tree2.set_root_id(root_id)
1321
2402.2.4 by John Arbash Meinel
Clean up the setup for clarity (suggested by Robert)
1322
        # Start with 2 identical trees
1323
        self.build_tree(['tree1/a/', 'tree1/b/',
1324
                         'tree2/a/', 'tree2/b/'])
1325
        self.build_tree_contents([('tree1/b/file', 'contents\n'),
1326
                                  ('tree2/b/file', 'contents\n')])
2402.2.1 by John Arbash Meinel
Add a test which exposes the bug in WT4._iter_changes()
1327
        tree1.add(['a', 'b', 'b/file'], ['a-id', 'b-id', 'b-file-id'])
1328
        tree2.add(['a', 'b', 'b/file'], ['a-id', 'b-id', 'b-file-id'])
1329
2402.2.2 by John Arbash Meinel
Fix _iter_changes to properly handle versioned (but empty) directories
1330
        # Now create some unknowns in tree2
1331
        # We should find both a/file and a/dir as unknown, but we shouldn't
1332
        # recurse into a/dir to find that a/dir/subfile is also unknown.
1333
        self.build_tree(['tree2/a/file', 'tree2/a/dir/', 'tree2/a/dir/subfile'])
1334
2402.2.1 by John Arbash Meinel
Add a test which exposes the bug in WT4._iter_changes()
1335
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1336
1337
        expected = sorted([
1338
            self.unversioned(tree2, u'a/file'),
2402.2.2 by John Arbash Meinel
Fix _iter_changes to properly handle versioned (but empty) directories
1339
            self.unversioned(tree2, u'a/dir'),
2402.2.1 by John Arbash Meinel
Add a test which exposes the bug in WT4._iter_changes()
1340
            ])
1341
        self.assertEqual(expected,
1342
                         self.do_iter_changes(tree1, tree2,
1343
                                              require_versioned=False,
1344
                                              want_unversioned=True))
2456.2.1 by John Arbash Meinel
(broken) Add a (failing) test that _iter_changes works correctly
1345
1346
    def test_rename_over_deleted(self):
1347
        tree1 = self.make_branch_and_tree('tree1')
1348
        tree2 = self.make_to_branch_and_tree('tree2')
1349
        root_id = tree1.get_root_id()
1350
        tree2.set_root_id(root_id)
1351
1352
        # The final changes should be:
1353
        #   touch a b c d
1354
        #   add a b c d
1355
        #   commit
1356
        #   rm a d
1357
        #   mv b a
1358
        #   mv c d
1359
        self.build_tree_contents([
1360
            ('tree1/a', 'a contents\n'),
1361
            ('tree1/b', 'b contents\n'),
1362
            ('tree1/c', 'c contents\n'),
1363
            ('tree1/d', 'd contents\n'),
1364
            ('tree2/a', 'b contents\n'),
1365
            ('tree2/d', 'c contents\n'),
1366
            ])
1367
        tree1.add(['a', 'b', 'c', 'd'], ['a-id', 'b-id', 'c-id', 'd-id'])
1368
        tree2.add(['a', 'd'], ['b-id', 'c-id'])
1369
1370
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1371
1372
        expected = sorted([
1373
            self.deleted(tree1, 'a-id'),
1374
            self.deleted(tree1, 'd-id'),
1375
            self.renamed(tree1, tree2, 'b-id', False),
1376
            self.renamed(tree1, tree2, 'c-id', False),
1377
            ])
1378
        self.assertEqual(expected,
1379
                         self.do_iter_changes(tree1, tree2))
2456.2.2 by John Arbash Meinel
Add another (failing) test case.
1380
1381
    def test_deleted_and_unknown(self):
1382
        """Test a file marked removed, but still present on disk."""
1383
        tree1 = self.make_branch_and_tree('tree1')
1384
        tree2 = self.make_to_branch_and_tree('tree2')
1385
        root_id = tree1.get_root_id()
1386
        tree2.set_root_id(root_id)
1387
1388
        # The final changes should be:
1389
        # bzr add a b c
1390
        # bzr rm --keep b
1391
        self.build_tree_contents([
1392
            ('tree1/a', 'a contents\n'),
1393
            ('tree1/b', 'b contents\n'),
1394
            ('tree1/c', 'c contents\n'),
1395
            ('tree2/a', 'a contents\n'),
1396
            ('tree2/b', 'b contents\n'),
1397
            ('tree2/c', 'c contents\n'),
1398
            ])
1399
        tree1.add(['a', 'b', 'c'], ['a-id', 'b-id', 'c-id'])
1400
        tree2.add(['a', 'c'], ['a-id', 'c-id'])
1401
1402
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1403
1404
        expected = sorted([
1405
            self.deleted(tree1, 'b-id'),
1406
            self.unversioned(tree2, 'b'),
1407
            ])
1408
        self.assertEqual(expected,
1409
                         self.do_iter_changes(tree1, tree2,
1410
                                              want_unversioned=True))
2456.2.5 by John Arbash Meinel
Make sure the output with want_unversioned=False is reasonable.
1411
        expected = sorted([
1412
            self.deleted(tree1, 'b-id'),
1413
            ])
1414
        self.assertEqual(expected,
1415
                         self.do_iter_changes(tree1, tree2,
1416
                                              want_unversioned=False))
2465.1.1 by John Arbash Meinel
Add a (failing) test exposing the bug in _iter_changes
1417
1418
    def test_renamed_and_added(self):
1419
        """Test when we have renamed a file, and put another in its place."""
1420
        tree1 = self.make_branch_and_tree('tree1')
1421
        tree2 = self.make_to_branch_and_tree('tree2')
1422
        root_id = tree1.get_root_id()
1423
        tree2.set_root_id(root_id)
1424
1425
        # The final changes are:
1426
        # bzr add b c
1427
        # bzr mv b a
1428
        # bzr mv c d
1429
        # bzr add b c
1430
1431
        self.build_tree_contents([
1432
            ('tree1/b', 'b contents\n'),
1433
            ('tree1/c', 'c contents\n'),
1434
            ('tree2/a', 'b contents\n'),
1435
            ('tree2/b', 'new b contents\n'),
1436
            ('tree2/c', 'new c contents\n'),
1437
            ('tree2/d', 'c contents\n'),
1438
            ])
1439
        tree1.add(['b', 'c'], ['b1-id', 'c1-id'])
1440
        tree2.add(['a', 'b', 'c', 'd'], ['b1-id', 'b2-id', 'c2-id', 'c1-id'])
1441
1442
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1443
1444
        expected = sorted([
1445
            self.renamed(tree1, tree2, 'b1-id', False),
1446
            self.renamed(tree1, tree2, 'c1-id', False),
1447
            self.added(tree2, 'b2-id'),
1448
            self.added(tree2, 'c2-id'),
1449
            ])
1450
        self.assertEqual(expected,
1451
                         self.do_iter_changes(tree1, tree2,
1452
                                              want_unversioned=True))
2472.3.1 by John Arbash Meinel
Fix bug #111288. When we don't have a match
1453
1454
    def test_renamed_and_unknown(self):
1455
        """A file was moved on the filesystem, but not in bzr."""
1456
        tree1 = self.make_branch_and_tree('tree1')
1457
        tree2 = self.make_to_branch_and_tree('tree2')
1458
        root_id = tree1.get_root_id()
1459
        tree2.set_root_id(root_id)
1460
1461
        # The final changes are:
1462
        # bzr add a b
1463
        # mv a a2
1464
1465
        self.build_tree_contents([
1466
            ('tree1/a', 'a contents\n'),
1467
            ('tree1/b', 'b contents\n'),
1468
            ('tree2/a', 'a contents\n'),
1469
            ('tree2/b', 'b contents\n'),
1470
            ])
1471
        tree1.add(['a', 'b'], ['a-id', 'b-id'])
1472
        tree2.add(['a', 'b'], ['a-id', 'b-id'])
1473
        os.rename('tree2/a', 'tree2/a2')
1474
1475
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1476
1477
        expected = sorted([
1478
            self.missing('a-id', 'a', 'a', tree2.get_root_id(), 'file'),
1479
            self.unversioned(tree2, 'a2'),
1480
            ])
1481
        self.assertEqual(expected,
1482
                         self.do_iter_changes(tree1, tree2,
1483
                                              want_unversioned=True))