/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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for the InterTree.compare() function."""
18
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
19
import os
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
20
import shutil
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
21
2255.6.4 by Aaron Bentley
merge from dirstate
22
from bzrlib import errors, tests, workingtree_4
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
23
from bzrlib.osutils import file_kind
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
24
from bzrlib.tests.intertree_implementations import TestCaseWithTwoTrees
25
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
26
# TODO: test diff unversioned dir that exists
27
# TODO: test the include_root option.
28
# TODO: test that renaming a directory x->y does not emit a rename for the
29
#       child x/a->y/a.
30
# TODO: test that renaming a directory x-> does not emit a rename for the child
31
#        x/a -> y/a when a supplied_files argument gives either 'x/' or 'y/a'
32
#        -> that is, when the renamed parent is not processed by the function.
33
# TODO: include dangling in the diff output.
34
# TODO: test items are only emitted once when a specific_files list names a dir
35
#       whose parent is now a child.
36
# TODO: test require_versioned
2255.2.151 by Robert Collins
Handle specific_files natively for WorkingTreeFormat4._iter_changes.
37
# TODO: explicitly test specific_files listing a non-dir, and listing a symlink
38
#       (it should not follow the link)
39
# TODO: test specific_files when the target tree has a file and the source a
40
#       dir with children, same id and same path. 
2255.2.161 by Martin Pool
merge some of dirstate, update comparison tests to keep tree roots the same unless they're meant to differ
41
# TODO: test comparisons between trees with different root ids. mbp 20070301
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
42
43
class TestCompare(TestCaseWithTwoTrees):
44
45
    def test_compare_empty_trees(self):
46
        tree1 = self.make_branch_and_tree('1')
47
        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
48
        tree2.set_root_id(tree1.get_root_id())
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
49
        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.
50
        tree2 = self.get_tree_no_parents_no_content(tree2)
51
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
52
        d = self.intertree_class(tree1, tree2).compare()
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
53
        self.assertEqual([], d.added)
54
        self.assertEqual([], d.modified)
55
        self.assertEqual([], d.removed)
56
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
57
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
58
59
    def test_empty_to_abc_content(self):
60
        tree1 = self.make_branch_and_tree('1')
61
        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
62
        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.
63
        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.
64
        tree2 = self.get_tree_no_parents_abc_content(tree2)
65
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
66
        d = self.intertree_class(tree1, tree2).compare()
67
        self.assertEqual([('a', 'a-id', 'file'),
68
                          ('b', 'b-id', 'directory'),
69
                          ('b/c', 'c-id', 'file'),
70
                         ], d.added)
71
        self.assertEqual([], d.modified)
72
        self.assertEqual([], d.removed)
73
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
74
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
75
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
76
    def test_dangling(self):
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
77
        # This test depends on the ability for some trees to have a difference
78
        # between a 'versioned present' and 'versioned not present' (aka
79
        # dangling) file. In this test there are two trees each with a separate
80
        # dangling file, and the dangling files should be considered absent for
81
        # the test.
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
82
        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.
83
        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
84
        tree2.set_root_id(tree1.get_root_id())
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
85
        self.build_tree(['2/a'])
86
        tree2.add('a')
87
        os.unlink('2/a')
88
        self.build_tree(['1/b'])
89
        tree1.add('b')
90
        os.unlink('1/b')
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
91
        # the conversion to test trees here will leave the trees intact for the
92
        # default intertree, but may perform a commit for other tree types,
93
        # which may reduce the validity of the test. XXX: Think about how to
94
        # address this.
95
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
96
        d = self.intertree_class(tree1, tree2).compare()
97
        self.assertEqual([], d.added)
98
        self.assertEqual([], d.modified)
99
        self.assertEqual([], d.removed)
100
        self.assertEqual([], d.renamed)
101
        self.assertEqual([], d.unchanged)
102
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
103
    def test_abc_content_to_empty(self):
104
        tree1 = self.make_branch_and_tree('1')
105
        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
106
        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.
107
        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.
108
        tree2 = self.get_tree_no_parents_no_content(tree2)
109
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
110
        d = self.intertree_class(tree1, tree2).compare()
111
        self.assertEqual([], d.added)
112
        self.assertEqual([], d.modified)
113
        self.assertEqual([('a', 'a-id', 'file'),
114
                          ('b', 'b-id', 'directory'),
115
                          ('b/c', 'c-id', 'file'),
116
                         ], d.removed)
117
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
118
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
119
120
    def test_content_modification(self):
121
        tree1 = self.make_branch_and_tree('1')
122
        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
123
        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.
124
        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.
125
        tree2 = self.get_tree_no_parents_abc_content_2(tree2)
126
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
127
        d = self.intertree_class(tree1, tree2).compare()
128
        self.assertEqual([], d.added)
129
        self.assertEqual([('a', 'a-id', 'file', True, False)], d.modified)
130
        self.assertEqual([], d.removed)
131
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
132
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
133
        
134
    def test_meta_modification(self):
135
        tree1 = self.make_branch_and_tree('1')
136
        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
137
        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.
138
        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.
139
        tree2 = self.get_tree_no_parents_abc_content_3(tree2)
140
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
141
        d = self.intertree_class(tree1, tree2).compare()
142
        self.assertEqual([], d.added)
143
        self.assertEqual([('b/c', 'c-id', 'file', False, True)], d.modified)
144
        self.assertEqual([], d.removed)
145
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
146
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
147
148
    def test_file_rename(self):
149
        tree1 = self.make_branch_and_tree('1')
150
        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
151
        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.
152
        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.
153
        tree2 = self.get_tree_no_parents_abc_content_4(tree2)
154
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
155
        d = self.intertree_class(tree1, tree2).compare()
156
        self.assertEqual([], d.added)
157
        self.assertEqual([], d.modified)
158
        self.assertEqual([], d.removed)
159
        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=...).
160
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
161
162
    def test_file_rename_and_modification(self):
163
        tree1 = self.make_branch_and_tree('1')
164
        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
165
        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.
166
        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.
167
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
168
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
169
        d = self.intertree_class(tree1, tree2).compare()
170
        self.assertEqual([], d.added)
171
        self.assertEqual([], d.modified)
172
        self.assertEqual([], d.removed)
173
        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=...).
174
        self.assertEqual([], d.unchanged)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
175
176
    def test_file_rename_and_meta_modification(self):
177
        tree1 = self.make_branch_and_tree('1')
178
        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
179
        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.
180
        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.
181
        tree2 = self.get_tree_no_parents_abc_content_6(tree2)
182
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.2 by Robert Collins
Convert stock delta tests to intertree_implementation tests of InterTree.compare.
183
        d = self.intertree_class(tree1, tree2).compare()
184
        self.assertEqual([], d.added)
185
        self.assertEqual([], d.modified)
186
        self.assertEqual([], d.removed)
187
        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=...).
188
        self.assertEqual([], d.unchanged)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
189
190
    def test_empty_to_abc_content_a_only(self):
191
        tree1 = self.make_branch_and_tree('1')
192
        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
193
        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.
194
        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.
195
        tree2 = self.get_tree_no_parents_abc_content(tree2)
196
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
197
        d = self.intertree_class(tree1, tree2).compare(specific_files=['a'])
198
        self.assertEqual([('a', 'a-id', 'file')], d.added)
199
        self.assertEqual([], d.modified)
200
        self.assertEqual([], d.removed)
201
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
202
        self.assertEqual([], d.unchanged)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
203
204
    def test_empty_to_abc_content_a_and_c_only(self):
205
        tree1 = self.make_branch_and_tree('1')
206
        tree2 = self.make_to_branch_and_tree('2')
207
        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.
208
        tree2 = self.get_tree_no_parents_abc_content(tree2)
209
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
210
        d = self.intertree_class(tree1, tree2).compare(
211
            specific_files=['a', 'b/c'])
212
        self.assertEqual(
213
            [('a', 'a-id', 'file'), ('b/c', 'c-id', 'file')],
214
            d.added)
215
        self.assertEqual([], d.modified)
216
        self.assertEqual([], d.removed)
217
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
218
        self.assertEqual([], d.unchanged)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
219
220
    def test_empty_to_abc_content_b_only(self):
221
        """Restricting to a dir matches the children of the dir."""
222
        tree1 = self.make_branch_and_tree('1')
223
        tree2 = self.make_to_branch_and_tree('2')
224
        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.
225
        tree2 = self.get_tree_no_parents_abc_content(tree2)
226
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
227
        d = self.intertree_class(tree1, tree2).compare(specific_files=['b'])
228
        self.assertEqual(
229
            [('b', 'b-id', 'directory'),('b/c', 'c-id', 'file')],
230
            d.added)
231
        self.assertEqual([], d.modified)
232
        self.assertEqual([], d.removed)
233
        self.assertEqual([], d.renamed)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
234
        self.assertEqual([], d.unchanged)
235
236
    def test_unchanged_with_renames_and_modifications(self):
237
        """want_unchanged should generate a list of unchanged entries."""
238
        tree1 = self.make_branch_and_tree('1')
239
        tree2 = self.make_to_branch_and_tree('2')
240
        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.
241
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
242
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
243
        d = self.intertree_class(tree1, tree2).compare(want_unchanged=True)
244
        self.assertEqual([], d.added)
245
        self.assertEqual([], d.modified)
246
        self.assertEqual([], d.removed)
247
        self.assertEqual([('a', 'd', 'a-id', 'file', True, False)], d.renamed)
248
        self.assertEqual(
249
            [(u'b', 'b-id', 'directory'), (u'b/c', 'c-id', 'file')],
250
            d.unchanged)
251
252
    def test_extra_trees_finds_ids(self):
253
        """Ask for a delta between two trees with a path present in a third."""
254
        tree1 = self.make_branch_and_tree('1')
255
        tree2 = self.make_to_branch_and_tree('2')
256
        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.
257
        tree2 = self.get_tree_no_parents_abc_content_3(tree2)
258
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
259
        d = self.intertree_class(tree1, tree2).compare(specific_files=['b'])
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
260
        # 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.
261
        # a dispatch. XXX: For dirstate it does speak to the optimisability of
262
        # the lookup, in merged trees it can be fast-pathed. We probably want
263
        # 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=...).
264
        tree3 = self.make_branch_and_tree('3')
265
        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.
266
        tree3.lock_read()
267
        self.addCleanup(tree3.unlock)
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
268
        # tree 3 has 'e' which is 'c-id'. Tree 1 has c-id at b/c, and Tree 2
269
        # has c-id at b/c with its exec flag toggled.
270
        # without extra_trees, we should get no modifications from this
271
        # so do one, to be sure the test is valid.
272
        d = self.intertree_class(tree1, tree2).compare(
273
            specific_files=['e'])
274
        self.assertEqual([], d.modified)
275
        # now give it an additional lookup:
276
        d = self.intertree_class(tree1, tree2).compare(
277
            specific_files=['e'], extra_trees=[tree3])
278
        self.assertEqual([], d.added)
279
        self.assertEqual([('b/c', 'c-id', 'file', False, True)], d.modified)
280
        self.assertEqual([], d.removed)
281
        self.assertEqual([], d.renamed)
282
        self.assertEqual([], d.unchanged)
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
283
284
    def test_require_versioned(self):
285
        # this does not quite robustly test, as it is passing in missing paths
286
        # rather than present-but-not-versioned paths. At the moment there is
287
        # no mechanism for managing the test trees (which are readonly) to 
288
        # get present-but-not-versioned files for trees that can do that.
289
        tree1 = self.make_branch_and_tree('1')
290
        tree2 = self.make_to_branch_and_tree('2')
291
        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.
292
        tree2 = self.get_tree_no_parents_abc_content(tree2)
293
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
294
        self.assertRaises(errors.PathsNotVersionedError, 
295
            self.intertree_class(tree1, tree2).compare,
296
            specific_files=['d'],
297
            require_versioned=True)
2012.1.1 by Aaron Bentley
Implement change iterator
298
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
299
    def test_default_ignores_unversioned_files(self):
300
        tree1 = self.make_branch_and_tree('tree1')
301
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
302
        tree2.set_root_id(tree1.get_root_id())
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
303
        self.build_tree(['tree1/a', 'tree1/c',
304
                         'tree2/a', 'tree2/b', 'tree2/c'])
305
        tree1.add(['a', 'c'], ['a-id', 'c-id'])
306
        tree2.add(['a', 'c'], ['a-id', 'c-id'])
307
308
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
2255.7.91 by Robert Collins
Move unknown detection in long status into the delta creation, saving a tree-scan.
309
        d = self.intertree_class(tree1, tree2).compare()
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
310
        self.assertEqual([], d.added)
311
        self.assertEqual([(u'a', 'a-id', 'file', True, False),
312
            (u'c', 'c-id', 'file', True, False)], d.modified)
313
        self.assertEqual([], d.removed)
314
        self.assertEqual([], d.renamed)
315
        self.assertEqual([], d.unchanged)
316
        self.assertEqual([], d.unversioned)
317
318
    def test_unversioned_paths_in_tree(self):
319
        tree1 = self.make_branch_and_tree('tree1')
320
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
321
        tree2.set_root_id(tree1.get_root_id())
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
322
        self.build_tree(['tree2/file', 'tree2/dir/'])
323
        # try:
324
        os.symlink('target', 'tree2/link')
325
        links_supported = True
326
        # except ???:
327
        #   links_supported = False
328
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
329
        d = self.intertree_class(tree1, tree2).compare(want_unversioned=True)
330
        self.assertEqual([], d.added)
331
        self.assertEqual([], d.modified)
332
        self.assertEqual([], d.removed)
333
        self.assertEqual([], d.renamed)
334
        self.assertEqual([], d.unchanged)
2255.7.91 by Robert Collins
Move unknown detection in long status into the delta creation, saving a tree-scan.
335
        self.assertEqual([(u'dir', None, 'directory'), (u'file', None, 'file'),
336
            (u'link', None, 'symlink')], d.unversioned)
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
337
2012.1.1 by Aaron Bentley
Implement change iterator
338
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
339
class TestIterChanges(TestCaseWithTwoTrees):
2012.1.1 by Aaron Bentley
Implement change iterator
340
    """Test the comparison iterator"""
341
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
342
    def do_iter_changes(self, tree1, tree2, **extra_args):
343
        """Helper to run _iter_changes from tree1 to tree2.
344
        
345
        :param tree1, tree2:  The source and target trees. These will be locked
346
            automatically.
347
        :param **extra_args: Extra args to pass to _iter_changes. This is not
348
            inspected by this test helper.
349
        """
350
        tree1.lock_read()
351
        tree2.lock_read()
352
        try:
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
353
            # sort order of output is not strictly defined
354
            return sorted(self.intertree_class(tree1, tree2)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
355
                ._iter_changes(**extra_args))
356
        finally:
357
            tree1.unlock()
358
            tree2.unlock()
359
2255.7.15 by John Arbash Meinel
Try to create an intertree test that exposes the walkdir vs dirstate mismatch. No luck yet.
360
    def make_tree_with_special_names(self):
361
        """Create a tree with filenames chosen to exercise the walk order."""
362
        tree1 = self.make_branch_and_tree('tree1')
363
        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
364
        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.
365
        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.
366
        tree2.commit('initial', rev_id='rev-1')
367
        tree1, tree2 = self.mutable_trees_to_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.
368
        return (tree1, tree2, paths, path_ids)
369
370
    def make_trees_with_special_names(self):
371
        """Both trees will use the special names.
372
373
        But the contents will differ for each file.
374
        """
375
        tree1 = self.make_branch_and_tree('tree1')
376
        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
377
        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.
378
        paths, path_ids = self._create_special_names(tree1, 'tree1')
379
        paths, path_ids = self._create_special_names(tree2, 'tree2')
380
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
381
        return (tree1, tree2, paths, path_ids)
382
383
    def _create_special_names(self, tree, base_path):
384
        """Create a tree with paths that expose differences in sort orders."""
385
        # Each directory will have a single file named 'f' inside
386
        dirs = ['a',
387
                'a-a',
388
                'a/a',
389
                'a/a-a',
390
                'a/a/a',
391
                'a/a/a-a',
392
                'a/a/a/a',
393
                'a/a/a/a-a',
394
                'a/a/a/a/a',
395
               ]
396
        with_slashes = []
397
        paths = []
398
        path_ids = []
399
        for d in dirs:
400
            with_slashes.append(base_path + '/' + d + '/')
401
            with_slashes.append(base_path + '/' + d + '/f')
402
            paths.append(d)
403
            paths.append(d+'/f')
404
            path_ids.append(d.replace('/', '_') + '-id')
405
            path_ids.append(d.replace('/', '_') + '_f-id')
406
        self.build_tree(with_slashes)
407
        tree.add(paths, path_ids)
408
        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.
409
2012.1.1 by Aaron Bentley
Implement change iterator
410
    def test_compare_empty_trees(self):
411
        tree1 = self.make_branch_and_tree('1')
412
        tree2 = self.make_to_branch_and_tree('2')
413
        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.
414
        tree2 = self.get_tree_no_parents_no_content(tree2)
415
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
416
        self.assertEqual([], self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
417
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
418
    def added(self, tree, file_id):
419
        entry = tree.inventory[file_id]
420
        path = tree.id2path(file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
421
        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.
422
                (None, entry.name), (None, entry.kind),
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
423
                (None, entry.executable))
424
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.
425
    def content_changed(self, tree, file_id):
426
        entry = tree.inventory[file_id]
427
        path = tree.id2path(file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
428
        return (file_id, (path, path), True, (True, True), (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.
429
                (entry.name, entry.name), (entry.kind, entry.kind),
430
                (entry.executable, entry.executable))
431
432
    def kind_changed(self, from_tree, to_tree, file_id):
433
        old_entry = from_tree.inventory[file_id]
434
        new_entry = to_tree.inventory[file_id]
435
        path = to_tree.id2path(file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
436
        from_path = from_tree.id2path(file_id)
437
        return (file_id, (from_path, path), True, (True, True), (old_entry.parent_id, new_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.
438
                (old_entry.name, new_entry.name), (old_entry.kind, new_entry.kind),
439
                (old_entry.executable, new_entry.executable))
440
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
441
    def missing(self, file_id, from_path, to_path, parent_id, kind):
442
        _, from_basename = os.path.split(from_path)
443
        _, to_basename = os.path.split(to_path)
444
        # missing files have both paths, but no kind.
445
        return (file_id, (from_path, to_path), True, (True, True),
446
            (parent_id, parent_id),
447
            (from_basename, to_basename), (kind, None), (False, False))
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
448
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
449
    def deleted(self, tree, file_id):
450
        entry = tree.inventory[file_id]
451
        path = tree.id2path(file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
452
        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.
453
                (entry.name, None), (entry.kind, None),
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
454
                (entry.executable, None))
455
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
456
    def renamed(self, from_tree, to_tree, file_id, content_changed):
457
        from_entry = from_tree.inventory[file_id]
458
        to_entry = to_tree.inventory[file_id]
459
        from_path = from_tree.id2path(file_id)
460
        to_path = to_tree.id2path(file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
461
        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.
462
            (from_entry.parent_id, to_entry.parent_id),
463
            (from_entry.name, to_entry.name),
464
            (from_entry.kind, to_entry.kind),
465
            (from_entry.executable, to_entry.executable))
466
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.
467
    def unchanged(self, tree, file_id):
468
        entry = tree.inventory[file_id]
469
        parent = entry.parent_id
470
        name = entry.name
471
        kind = entry.kind
472
        executable = entry.executable
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
473
        path = tree.id2path(file_id)
474
        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.
475
               (parent, parent), (name, name), (kind, kind),
476
               (executable, executable))
477
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
478
    def unversioned(self, tree, path):
479
        """Create an unversioned result."""
480
        _, basename = os.path.split(path)
481
        kind = file_kind(tree.abspath(path))
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
482
        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.
483
                (None, basename), (None, kind),
484
                (None, False))
485
2012.1.1 by Aaron Bentley
Implement change iterator
486
    def test_empty_to_abc_content(self):
487
        tree1 = self.make_branch_and_tree('1')
488
        tree2 = self.make_to_branch_and_tree('2')
489
        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.
490
        tree2 = self.get_tree_no_parents_abc_content(tree2)
491
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
2255.2.118 by Robert Collins
Change _iter_changes tests to lock the tested trees - its an iterator interface so implicit locks dont ensure the tree is locked - callers need to lock and thus so do our tests.
492
        tree1.lock_read()
493
        tree2.lock_read()
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
494
        expected_results = sorted([
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
495
            self.added(tree2, 'root-id'),
496
            self.added(tree2, 'a-id'),
497
            self.added(tree2, 'b-id'),
498
            self.added(tree2, 'c-id'),
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
499
            self.deleted(tree1, 'empty-root-id')])
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
500
        tree1.unlock()
501
        tree2.unlock()
502
        self.assertEqual(expected_results, self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
503
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
504
    def test_empty_to_abc_content_a_only(self):
505
        tree1 = self.make_branch_and_tree('1')
506
        tree2 = self.make_to_branch_and_tree('2')
507
        tree1 = self.get_tree_no_parents_no_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
508
        tree2 = self.get_tree_no_parents_abc_content(tree2)
509
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
510
        tree1.lock_read()
511
        tree2.lock_read()
512
        self.assertEqual(
513
            [self.added(tree2, 'a-id')],
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
514
            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.
515
        tree1.unlock()
516
        tree2.unlock()
517
518
    def test_abc_content_to_empty_to_abc_content_a_only(self):
519
        tree1 = self.make_branch_and_tree('1')
520
        tree2 = self.make_to_branch_and_tree('2')
521
        tree1 = self.get_tree_no_parents_abc_content(tree1)
522
        tree2 = self.get_tree_no_parents_no_content(tree2)
523
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
524
        tree1.lock_read()
525
        tree2.lock_read()
526
        self.assertEqual(
527
            [self.deleted(tree1, 'a-id')],
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
528
            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.
529
        tree1.unlock()
530
        tree2.unlock()
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
531
532
    def test_empty_to_abc_content_a_and_c_only(self):
533
        tree1 = self.make_branch_and_tree('1')
534
        tree2 = self.make_to_branch_and_tree('2')
535
        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.
536
        tree2 = self.get_tree_no_parents_abc_content(tree2)
537
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
2255.2.118 by Robert Collins
Change _iter_changes tests to lock the tested trees - its an iterator interface so implicit locks dont ensure the tree is locked - callers need to lock and thus so do our tests.
538
        tree1.lock_read()
539
        tree2.lock_read()
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
540
        expected_result = [self.added(tree2, 'a-id'), self.added(tree2, 'c-id')]
541
        tree1.unlock()
542
        tree2.unlock()
543
        self.assertEqual(expected_result,
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
544
            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
545
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
546
    def test_abc_content_to_empty(self):
2012.1.1 by Aaron Bentley
Implement change iterator
547
        tree1 = self.make_branch_and_tree('1')
548
        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.
549
        tree1 = self.get_tree_no_parents_abc_content(tree1)
550
        tree2 = self.get_tree_no_parents_no_content(tree2)
551
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
552
        tree1.lock_read()
553
        tree2.lock_read()
2012.1.1 by Aaron Bentley
Implement change iterator
554
        def deleted(file_id):
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
555
            entry = tree1.inventory[file_id]
556
            path = tree1.id2path(file_id)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
557
            return (file_id, (path, None), True, (True, False),
2012.1.1 by Aaron Bentley
Implement change iterator
558
                    (entry.parent_id, None),
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
559
                    (entry.name, None), (entry.kind, None),
2012.1.1 by Aaron Bentley
Implement change iterator
560
                    (entry.executable, None))
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
561
        expected_results = sorted([
562
            self.added(tree2, 'empty-root-id'),
563
            deleted('root-id'), deleted('a-id'),
564
            deleted('b-id'), deleted('c-id')])
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
565
        tree1.unlock()
566
        tree2.unlock()
567
        self.assertEqual(
568
            expected_results,
569
            self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
570
571
    def test_content_modification(self):
572
        tree1 = self.make_branch_and_tree('1')
573
        tree2 = self.make_to_branch_and_tree('2')
574
        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.
575
        tree2 = self.get_tree_no_parents_abc_content_2(tree2)
576
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
577
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
578
        self.assertEqual([('a-id', ('a', 'a'), True, (True, True),
579
                           (root_id, root_id), ('a', 'a'),
580
                           ('file', 'file'), (False, False))],
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
581
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
582
583
    def test_meta_modification(self):
584
        tree1 = self.make_branch_and_tree('1')
585
        tree2 = self.make_to_branch_and_tree('2')
586
        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.
587
        tree2 = self.get_tree_no_parents_abc_content_3(tree2)
588
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
589
        self.assertEqual([('c-id', ('b/c', 'b/c'), False, (True, True),
590
                           ('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.
591
                          (False, True))],
592
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
593
2255.7.6 by Robert Collins
Test for iterating changes past empty directories.
594
    def test_empty_dir(self):
595
        """an empty dir should not cause glitches to surrounding files."""
596
        tree1 = self.make_branch_and_tree('1')
597
        tree2 = self.make_to_branch_and_tree('2')
598
        tree1 = self.get_tree_no_parents_abc_content(tree1)
599
        tree2 = self.get_tree_no_parents_abc_content(tree2)
600
        # the pathname is chosen to fall between 'a' and 'b'.
601
        self.build_tree(['1/a-empty/', '2/a-empty/'])
602
        tree1.add(['a-empty'], ['a-empty'])
603
        tree2.add(['a-empty'], ['a-empty'])
604
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
605
        expected = []
606
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
607
2012.1.1 by Aaron Bentley
Implement change iterator
608
    def test_file_rename(self):
609
        tree1 = self.make_branch_and_tree('1')
610
        tree2 = self.make_to_branch_and_tree('2')
611
        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.
612
        tree2 = self.get_tree_no_parents_abc_content_4(tree2)
613
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
614
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
615
        self.assertEqual([('a-id', ('a', 'd'), False, (True, True),
616
                           (root_id, root_id), ('a', 'd'), ('file', 'file'),
617
                           (False, False))],
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
618
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
619
620
    def test_file_rename_and_modification(self):
621
        tree1 = self.make_branch_and_tree('1')
622
        tree2 = self.make_to_branch_and_tree('2')
623
        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.
624
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
625
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
626
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
627
        self.assertEqual([('a-id', ('a', 'd'), True, (True, True),
628
                           (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.
629
                           (False, False))],
630
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
631
632
    def test_file_rename_and_meta_modification(self):
633
        tree1 = self.make_branch_and_tree('1')
634
        tree2 = self.make_to_branch_and_tree('2')
635
        tree1 = self.get_tree_no_parents_abc_content(tree1)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
636
        tree2 = self.get_tree_no_parents_abc_content_6(tree2)
637
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
638
        root_id = tree1.path2id('')
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
639
        self.assertEqual([('c-id', ('b/c', 'e'), False, (True, True),
640
                           ('b-id', root_id), ('c', 'e'), ('file', 'file'),
641
                           (False, True))],
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
642
                         self.do_iter_changes(tree1, tree2))
2012.1.1 by Aaron Bentley
Implement change iterator
643
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
644
    def test_missing_in_target(self):
645
        """Test with the target files versioned but absent from disk."""
646
        tree1 = self.make_branch_and_tree('1')
647
        tree2 = self.make_to_branch_and_tree('2')
648
        tree1 = self.get_tree_no_parents_abc_content(tree1)
649
        tree2 = self.get_tree_no_parents_abc_content(tree2)
650
        os.unlink('2/a')
651
        shutil.rmtree('2/b')
652
        # TODO ? have a symlink here?
653
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
654
        root_id = tree1.path2id('')
655
        expected = sorted([
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
656
            self.missing('a-id', 'a', 'a', root_id, 'file'),
657
            self.missing('b-id', 'b', 'b', root_id, 'directory'),
658
            self.missing('c-id', 'b/c', 'b/c', 'b-id', 'file'),
659
            ])
660
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
661
662
    def test_missing_and_renamed(self):
663
        tree1 = self.make_branch_and_tree('tree1')
664
        tree2 = self.make_to_branch_and_tree('tree2')
665
        self.build_tree(['tree1/file'])
666
        tree1.add(['file'], ['file-id'])
667
        self.build_tree(['tree2/directory/'])
668
        tree2.add(['directory'], ['file-id'])
669
        os.rmdir('tree2/directory')
670
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
671
        tree1.lock_read()
672
        self.addCleanup(tree1.unlock)
673
        tree2.lock_read()
674
        self.addCleanup(tree2.unlock)
675
        root_id = tree1.path2id('')
676
        expected = sorted([
677
            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.
678
            ])
679
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
680
2012.1.1 by Aaron Bentley
Implement change iterator
681
    def test_unchanged_with_renames_and_modifications(self):
682
        """want_unchanged should generate a list of unchanged entries."""
683
        tree1 = self.make_branch_and_tree('1')
684
        tree2 = self.make_to_branch_and_tree('2')
685
        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.
686
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
687
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
688
        root_id = tree1.path2id('')
2255.2.118 by Robert Collins
Change _iter_changes tests to lock the tested trees - its an iterator interface so implicit locks dont ensure the tree is locked - callers need to lock and thus so do our tests.
689
        tree1.lock_read()
690
        self.addCleanup(tree1.unlock)
691
        tree2.lock_read()
692
        self.addCleanup(tree2.unlock)
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.
693
        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.
694
            self.unchanged(tree1, 'b-id'),
695
            ('a-id', ('a', 'd'), True, (True, True),
696
             (root_id, root_id), ('a', 'd'), ('file', 'file'),
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
697
            (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.
698
            self.do_iter_changes(tree1, tree2, include_unchanged=True))
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
699
700
    def test_compare_subtrees(self):
701
        """want_unchanged should generate a list of unchanged entries."""
702
        tree1 = self.make_branch_and_tree('1')
2255.9.2 by Martin Pool
test_compare_subtrees runs against all trees that claim to support
703
        if not tree1.supports_tree_reference():
704
            raise tests.TestSkipped('Tree %s does not support references'
705
                % (tree1,))
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
706
        tree1.set_root_id('root-id')
707
        subtree1 = self.make_branch_and_tree('1/sub')
708
        subtree1.set_root_id('subtree-id')
2255.9.2 by Martin Pool
test_compare_subtrees runs against all trees that claim to support
709
        tree1.add_reference(subtree1)
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
710
711
        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
712
        if not tree2.supports_tree_reference():
713
            raise tests.TestSkipped('Tree %s does not support references'
714
                % (tree2,))
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
715
        tree2.set_root_id('root-id')
716
        subtree2 = self.make_to_branch_and_tree('2/sub')
717
        subtree2.set_root_id('subtree-id')
718
        tree2.add_reference(subtree2)
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
719
        tree1.lock_read()
720
        tree2.lock_read()
721
        try:
722
            self.assertEqual([], list(tree2._iter_changes(tree1)))
723
            subtree1.commit('commit', rev_id='commit-a')
724
            self.assertEqual([('subtree-id',
725
                               'sub',
726
                               True,
727
                               (True, True),
728
                               ('root-id', 'root-id'),
729
                               ('sub', 'sub'),
730
                               ('tree-reference', 'tree-reference'),
731
                               (False, False))],
732
                             list(tree2._iter_changes(tree1)))
733
        finally:
734
            tree1.unlock()
735
            tree2.unlock()
2255.2.160 by Martin Pool
(merge) updates from dirstate branch
736
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
737
    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.
738
        tree1 = self.make_branch_and_tree('tree1')
739
        tree2 = self.make_to_branch_and_tree('tree2')
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
740
        self.build_tree(['tree1/a', 'tree1/c',
741
                         'tree2/a', 'tree2/b', 'tree2/c'])
742
        tree1.add(['a', 'c'], ['a-id', 'c-id'])
743
        tree2.add(['a', 'c'], ['a-id', 'c-id'])
744
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
745
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
746
        tree1.lock_read()
747
        self.addCleanup(tree1.unlock)
748
        tree2.lock_read()
749
        self.addCleanup(tree2.unlock)
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
750
751
        # We should ignore the fact that 'b' exists in tree-2
752
        # because the want_unversioned parameter was not given.
753
        expected = sorted([
754
            self.content_changed(tree2, 'a-id'),
755
            self.content_changed(tree2, 'c-id'),
756
            ])
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
757
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
758
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
759
    def test_unversioned_paths_in_tree(self):
760
        tree1 = self.make_branch_and_tree('tree1')
761
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
762
        tree2.set_root_id(tree1.get_root_id())
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
763
        self.build_tree(['tree2/file', 'tree2/dir/'])
764
        # try:
765
        os.symlink('target', 'tree2/link')
766
        links_supported = True
767
        # except ???:
768
        #   links_supported = False
769
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
770
        tree1.lock_read()
771
        self.addCleanup(tree1.unlock)
772
        tree2.lock_read()
773
        self.addCleanup(tree2.unlock)
774
        expected = [
775
            self.unversioned(tree2, 'file'),
776
            self.unversioned(tree2, 'dir'),
777
            ]
778
        if links_supported:
779
            expected.append(self.unversioned(tree2, 'link'))
780
        expected = sorted(expected)
781
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
782
            want_unversioned=True))
783
784
    def test_unversioned_paths_in_tree_specific_files(self):
785
        tree1 = self.make_branch_and_tree('tree1')
786
        tree2 = self.make_to_branch_and_tree('tree2')
787
        self.build_tree(['tree2/file', 'tree2/dir/'])
788
        # try:
789
        os.symlink('target', 'tree2/link')
790
        links_supported = True
791
        # except ???:
792
        #   links_supported = False
793
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
794
        tree1.lock_read()
795
        self.addCleanup(tree1.unlock)
796
        tree2.lock_read()
797
        self.addCleanup(tree2.unlock)
798
        expected = [
799
            self.unversioned(tree2, 'file'),
800
            self.unversioned(tree2, 'dir'),
801
            ]
802
        specific_files=['file', 'dir']
803
        if links_supported:
804
            expected.append(self.unversioned(tree2, 'link'))
805
            specific_files.append('link')
806
        expected = sorted(expected)
807
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
808
            specific_files=specific_files, require_versioned=False,
809
            want_unversioned=True))
810
811
    def test_unversioned_paths_in_target_matching_source_old_names(self):
812
        # its likely that naive implementations of unversioned file support
813
        # will fail if the path was versioned, but is not any more, 
814
        # due to a rename, not due to unversioning it.
815
        # That is, if the old tree has a versioned file 'foo', and
816
        # the new tree has the same file but versioned as 'bar', and also
817
        # has an unknown file 'foo', we should get back output for
818
        # both foo and bar.
819
        tree1 = self.make_branch_and_tree('tree1')
820
        tree2 = self.make_to_branch_and_tree('tree2')
821
        self.build_tree(['tree2/file', 'tree2/dir/',
822
            'tree1/file', 'tree2/movedfile',
823
            'tree1/dir/', 'tree2/moveddir/'])
824
        # try:
825
        os.symlink('target', 'tree1/link')
826
        os.symlink('target', 'tree2/link')
827
        os.symlink('target', 'tree2/movedlink')
828
        links_supported = True
829
        # except ???:
830
        #   links_supported = False
831
        tree1.add(['file', 'dir', 'link'], ['file-id', 'dir-id', 'link-id'])
832
        tree2.add(['movedfile', 'moveddir', 'movedlink'],
833
            ['file-id', 'dir-id', 'link-id'])
834
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
835
        root_id = tree1.path2id('')
836
        tree1.lock_read()
837
        self.addCleanup(tree1.unlock)
838
        tree2.lock_read()
839
        self.addCleanup(tree2.unlock)
840
        expected = [
841
            self.renamed(tree1, tree2, 'dir-id', False),
842
            self.renamed(tree1, tree2, 'file-id', True),
843
            self.unversioned(tree2, 'file'),
844
            self.unversioned(tree2, 'dir'),
845
            ]
846
        specific_files=['file', 'dir']
847
        if links_supported:
848
            expected.append(self.renamed(tree1, tree2, 'link-id', False))
849
            expected.append(self.unversioned(tree2, 'link'))
850
            specific_files.append('link')
851
        expected = sorted(expected)
852
        # run once with, and once without specific files, to catch
853
        # potentially different code paths.
854
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
855
            require_versioned=False,
856
            want_unversioned=True))
857
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
858
            specific_files=specific_files, require_versioned=False,
859
            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.
860
2255.7.87 by Robert Collins
Dont walk unversioned directories in _iter_changes.
861
    def test_unversioned_subtree_only_emits_root(self):
862
        tree1 = self.make_branch_and_tree('tree1')
863
        tree2 = self.make_to_branch_and_tree('tree2')
864
        self.build_tree(['tree2/dir/', 'tree2/dir/file'])
865
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
866
        expected = [
867
            self.unversioned(tree2, 'dir'),
868
            ]
869
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
870
            want_unversioned=True))
871
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.
872
    def make_trees_with_symlinks(self):
873
        tree1 = self.make_branch_and_tree('tree1')
874
        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
875
        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.
876
        self.build_tree(['tree1/fromfile', 'tree1/fromdir/'])
877
        self.build_tree(['tree2/tofile', 'tree2/todir/', 'tree2/unknown'])
878
        # try:
879
        os.symlink('original', 'tree1/changed')
880
        os.symlink('original', 'tree1/removed')
881
        os.symlink('original', 'tree1/tofile')
882
        os.symlink('original', 'tree1/todir')
883
        # we make the unchanged link point at unknown to catch incorrect
884
        # symlink-following code in the specified_files test.
885
        os.symlink('unknown', 'tree1/unchanged')
886
        os.symlink('new',      'tree2/added')
887
        os.symlink('new',      'tree2/changed')
888
        os.symlink('new',      'tree2/fromfile')
889
        os.symlink('new',      'tree2/fromdir')
890
        os.symlink('unknown', 'tree2/unchanged')
891
        from_paths_and_ids = [
892
            'fromdir',
893
            'fromfile',
894
            'changed',
895
            'removed',
896
            'todir',
897
            'tofile',
898
            'unchanged',
899
            ]
900
        to_paths_and_ids = [
901
            'added',
902
            'fromdir',
903
            'fromfile',
904
            'changed',
905
            'todir',
906
            'tofile',
907
            'unchanged',
908
            ]
909
        tree1.add(from_paths_and_ids, from_paths_and_ids)
910
        tree2.add(to_paths_and_ids, to_paths_and_ids)
911
        # except ???:
912
        #   raise TestSkipped('OS does not support symlinks')
913
        #   links_supported = False
914
        return self.mutable_trees_to_test_trees(tree1, tree2)
915
2255.2.182 by Martin Pool
merge dirstate and trunk
916
    def make_trees_with_subtrees(self):
917
        # trees containing tree references
918
        # TODO: might have to skip if the format can't do tree references
919
        tree1 = self.make_branch_and_tree('tree1')
920
        tree2 = self.make_to_branch_and_tree('tree2')
921
        self.build_tree(['tree1/fromdir/', 'tree1/common/',
922
            'tree2/todir/', 'tree2/common/'])
923
        # TODO: actually add the references
924
        return self.mutable_trees_to_test_trees(tree1, tree2)
925
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
926
    def test_versioned_symlinks(self):
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.
927
        tree1, tree2 = self.make_trees_with_symlinks()
928
        root_id = tree1.path2id('')
929
        tree1.lock_read()
930
        self.addCleanup(tree1.unlock)
931
        tree2.lock_read()
932
        self.addCleanup(tree2.unlock)
933
        expected = [
934
            self.unchanged(tree1, tree1.path2id('')),
935
            self.added(tree2, 'added'),
936
            self.content_changed(tree2, 'changed'),
937
            self.kind_changed(tree1, tree2, 'fromdir'),
938
            self.kind_changed(tree1, tree2, 'fromfile'),
939
            self.deleted(tree1, 'removed'),
940
            self.unchanged(tree2, 'unchanged'),
941
            self.unversioned(tree2, 'unknown'),
942
            self.kind_changed(tree1, tree2, 'todir'),
943
            self.kind_changed(tree1, tree2, 'tofile'),
944
            ]
945
        expected = sorted(expected)
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
946
        self.assertEqual(expected,
947
            self.do_iter_changes(tree1, tree2, include_unchanged=True,
948
                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.
949
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
950
    def test_versioned_symlinks_specific_files(self):
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.
951
        tree1, tree2 = self.make_trees_with_symlinks()
952
        root_id = tree1.path2id('')
953
        tree1.lock_read()
954
        self.addCleanup(tree1.unlock)
955
        tree2.lock_read()
956
        self.addCleanup(tree2.unlock)
957
        expected = [
958
            self.added(tree2, 'added'),
959
            self.content_changed(tree2, 'changed'),
960
            self.kind_changed(tree1, tree2, 'fromdir'),
961
            self.kind_changed(tree1, tree2, 'fromfile'),
962
            self.deleted(tree1, 'removed'),
963
            self.kind_changed(tree1, tree2, 'todir'),
964
            self.kind_changed(tree1, tree2, 'tofile'),
965
            ]
966
        expected = sorted(expected)
967
        # we should get back just the changed links. We pass in 'unchanged' to
968
        # make sure that it is correctly not returned - and neither is the
969
        # unknown path 'unknown' which it points at.
970
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
971
            specific_files=['added', 'changed', 'fromdir', 'fromfile',
972
            'removed', 'unchanged', 'todir', 'tofile']))
2255.7.15 by John Arbash Meinel
Try to create an intertree test that exposes the walkdir vs dirstate mismatch. No luck yet.
973
2255.7.21 by John Arbash Meinel
Get iter_changes working again, by fixing set_parent_trees to
974
    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.
975
        tree1, tree2, paths, path_ids = self.make_tree_with_special_names()
976
        tree1.lock_read()
977
        self.addCleanup(tree1.unlock)
978
        tree2.lock_read()
979
        self.addCleanup(tree2.unlock)
980
        expected = sorted(self.added(tree2, f_id) for f_id in path_ids)
981
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
2255.7.22 by John Arbash Meinel
add a test that shows _iter_changes works when only contents have changed, and nothing is considered newly added.
982
983
    def test_trees_with_special_names(self):
984
        tree1, tree2, paths, path_ids = self.make_trees_with_special_names()
985
        tree1.lock_read()
986
        self.addCleanup(tree1.unlock)
987
        tree2.lock_read()
988
        self.addCleanup(tree2.unlock)
989
        expected = sorted(self.content_changed(tree2, f_id) for f_id in path_ids
990
                          if f_id.endswith('_f-id'))
991
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
2255.7.34 by John Arbash Meinel
Clean up test_bad_files, and fix a bug in _iter_changes when
992
2255.2.182 by Martin Pool
merge dirstate and trunk
993
    def test_trees_with_subtrees(self):
994
        tree1, tree2 = self.make_trees_with_subtrees()
995
        self.do_iter_changes(tree1, tree2)
996
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
997
    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.
998
        tree1 = self.make_branch_and_tree('tree1')
999
        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
1000
        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.
1001
        self.build_tree(['tree1/a', 'tree1/b/', 'tree1/b/c',
1002
                         'tree1/b/d/', 'tree1/b/d/e', 'tree1/f/', 'tree1/f/g',
1003
                         'tree2/a', 'tree2/f/', 'tree2/f/g'])
1004
        tree1.add(['a', 'b', 'b/c', 'b/d/', 'b/d/e', 'f', 'f/g'],
1005
                  ['a-id', 'b-id', 'c-id', 'd-id', 'e-id', 'f-id', 'g-id'])
1006
        tree2.add(['a', 'f', 'f/g'], ['a-id', 'f-id', 'g-id'])
1007
1008
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1009
        tree1.lock_read()
1010
        self.addCleanup(tree1.unlock)
1011
        tree2.lock_read()
1012
        self.addCleanup(tree2.unlock)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1013
        # We should notice that 'b' and all its children are deleted
2255.7.35 by John Arbash Meinel
Handle the case when a directory has been removed, and isn't the last entry.
1014
        expected = sorted([
1015
            self.content_changed(tree2, 'a-id'),
1016
            self.content_changed(tree2, 'g-id'),
1017
            self.deleted(tree1, 'b-id'),
1018
            self.deleted(tree1, 'c-id'),
1019
            self.deleted(tree1, 'd-id'),
1020
            self.deleted(tree1, 'e-id'),
1021
            ])
1022
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))