/brz/remove-bazaar

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