/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')
2255.2.186 by Martin Pool
Fix up root id for some more comparison tests
665
        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.
666
        self.build_tree(['tree1/file'])
667
        tree1.add(['file'], ['file-id'])
668
        self.build_tree(['tree2/directory/'])
669
        tree2.add(['directory'], ['file-id'])
670
        os.rmdir('tree2/directory')
671
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
672
        tree1.lock_read()
673
        self.addCleanup(tree1.unlock)
674
        tree2.lock_read()
675
        self.addCleanup(tree2.unlock)
676
        root_id = tree1.path2id('')
677
        expected = sorted([
678
            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.
679
            ])
680
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
681
2012.1.1 by Aaron Bentley
Implement change iterator
682
    def test_unchanged_with_renames_and_modifications(self):
683
        """want_unchanged should generate a list of unchanged entries."""
684
        tree1 = self.make_branch_and_tree('1')
685
        tree2 = self.make_to_branch_and_tree('2')
686
        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.
687
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
688
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
689
        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.
690
        tree1.lock_read()
691
        self.addCleanup(tree1.unlock)
692
        tree2.lock_read()
693
        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.
694
        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.
695
            self.unchanged(tree1, 'b-id'),
696
            ('a-id', ('a', 'd'), True, (True, True),
697
             (root_id, root_id), ('a', 'd'), ('file', 'file'),
2255.7.4 by Robert Collins
Test InterTree._iter_changes with missing (absent but versioned) files.
698
            (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.
699
            self.do_iter_changes(tree1, tree2, include_unchanged=True))
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
700
701
    def test_compare_subtrees(self):
702
        """want_unchanged should generate a list of unchanged entries."""
703
        tree1 = self.make_branch_and_tree('1')
2255.9.2 by Martin Pool
test_compare_subtrees runs against all trees that claim to support
704
        if not tree1.supports_tree_reference():
705
            raise tests.TestSkipped('Tree %s does not support references'
706
                % (tree1,))
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
707
        tree1.set_root_id('root-id')
708
        subtree1 = self.make_branch_and_tree('1/sub')
709
        subtree1.set_root_id('subtree-id')
2255.9.2 by Martin Pool
test_compare_subtrees runs against all trees that claim to support
710
        tree1.add_reference(subtree1)
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
711
712
        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
713
        if not tree2.supports_tree_reference():
714
            raise tests.TestSkipped('Tree %s does not support references'
715
                % (tree2,))
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
716
        tree2.set_root_id('root-id')
717
        subtree2 = self.make_to_branch_and_tree('2/sub')
718
        subtree2.set_root_id('subtree-id')
719
        tree2.add_reference(subtree2)
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
720
        tree1.lock_read()
721
        tree2.lock_read()
722
        try:
723
            self.assertEqual([], list(tree2._iter_changes(tree1)))
724
            subtree1.commit('commit', rev_id='commit-a')
725
            self.assertEqual([('subtree-id',
726
                               'sub',
727
                               True,
728
                               (True, True),
729
                               ('root-id', 'root-id'),
730
                               ('sub', 'sub'),
731
                               ('tree-reference', 'tree-reference'),
732
                               (False, False))],
733
                             list(tree2._iter_changes(tree1)))
734
        finally:
735
            tree1.unlock()
736
            tree2.unlock()
2255.2.160 by Martin Pool
(merge) updates from dirstate branch
737
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
738
    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.
739
        tree1 = self.make_branch_and_tree('tree1')
740
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.186 by Martin Pool
Fix up root id for some more comparison tests
741
        tree2.set_root_id(tree1.get_root_id())
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
742
        self.build_tree(['tree1/a', 'tree1/c',
743
                         'tree2/a', 'tree2/b', 'tree2/c'])
744
        tree1.add(['a', 'c'], ['a-id', 'c-id'])
745
        tree2.add(['a', 'c'], ['a-id', 'c-id'])
746
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
747
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
748
        tree1.lock_read()
749
        self.addCleanup(tree1.unlock)
750
        tree2.lock_read()
751
        self.addCleanup(tree2.unlock)
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
752
753
        # We should ignore the fact that 'b' exists in tree-2
754
        # because the want_unversioned parameter was not given.
755
        expected = sorted([
756
            self.content_changed(tree2, 'a-id'),
757
            self.content_changed(tree2, 'c-id'),
758
            ])
2255.7.2 by Robert Collins
Add a (currently) disabled test for unversioned paths in the target tree with _iter_changes.
759
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
760
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
761
    def test_unversioned_paths_in_tree(self):
762
        tree1 = self.make_branch_and_tree('tree1')
763
        tree2 = self.make_to_branch_and_tree('tree2')
2255.2.184 by Martin Pool
Fixes for some comparison tests; repr of DirStateRevisionTree
764
        tree2.set_root_id(tree1.get_root_id())
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
765
        self.build_tree(['tree2/file', 'tree2/dir/'])
766
        # try:
767
        os.symlink('target', 'tree2/link')
768
        links_supported = True
769
        # except ???:
770
        #   links_supported = False
771
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
772
        tree1.lock_read()
773
        self.addCleanup(tree1.unlock)
774
        tree2.lock_read()
775
        self.addCleanup(tree2.unlock)
776
        expected = [
777
            self.unversioned(tree2, 'file'),
778
            self.unversioned(tree2, 'dir'),
779
            ]
780
        if links_supported:
781
            expected.append(self.unversioned(tree2, 'link'))
782
        expected = sorted(expected)
783
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
784
            want_unversioned=True))
785
786
    def test_unversioned_paths_in_tree_specific_files(self):
787
        tree1 = self.make_branch_and_tree('tree1')
788
        tree2 = self.make_to_branch_and_tree('tree2')
789
        self.build_tree(['tree2/file', 'tree2/dir/'])
790
        # try:
791
        os.symlink('target', 'tree2/link')
792
        links_supported = True
793
        # except ???:
794
        #   links_supported = False
795
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
796
        tree1.lock_read()
797
        self.addCleanup(tree1.unlock)
798
        tree2.lock_read()
799
        self.addCleanup(tree2.unlock)
800
        expected = [
801
            self.unversioned(tree2, 'file'),
802
            self.unversioned(tree2, 'dir'),
803
            ]
804
        specific_files=['file', 'dir']
805
        if links_supported:
806
            expected.append(self.unversioned(tree2, 'link'))
807
            specific_files.append('link')
808
        expected = sorted(expected)
809
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
810
            specific_files=specific_files, require_versioned=False,
811
            want_unversioned=True))
812
813
    def test_unversioned_paths_in_target_matching_source_old_names(self):
814
        # its likely that naive implementations of unversioned file support
815
        # will fail if the path was versioned, but is not any more, 
816
        # due to a rename, not due to unversioning it.
817
        # That is, if the old tree has a versioned file 'foo', and
818
        # the new tree has the same file but versioned as 'bar', and also
819
        # has an unknown file 'foo', we should get back output for
820
        # both foo and bar.
821
        tree1 = self.make_branch_and_tree('tree1')
822
        tree2 = self.make_to_branch_and_tree('tree2')
823
        self.build_tree(['tree2/file', 'tree2/dir/',
824
            'tree1/file', 'tree2/movedfile',
825
            'tree1/dir/', 'tree2/moveddir/'])
826
        # try:
827
        os.symlink('target', 'tree1/link')
828
        os.symlink('target', 'tree2/link')
829
        os.symlink('target', 'tree2/movedlink')
830
        links_supported = True
831
        # except ???:
832
        #   links_supported = False
833
        tree1.add(['file', 'dir', 'link'], ['file-id', 'dir-id', 'link-id'])
834
        tree2.add(['movedfile', 'moveddir', 'movedlink'],
835
            ['file-id', 'dir-id', 'link-id'])
836
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
837
        root_id = tree1.path2id('')
838
        tree1.lock_read()
839
        self.addCleanup(tree1.unlock)
840
        tree2.lock_read()
841
        self.addCleanup(tree2.unlock)
842
        expected = [
843
            self.renamed(tree1, tree2, 'dir-id', False),
844
            self.renamed(tree1, tree2, 'file-id', True),
845
            self.unversioned(tree2, 'file'),
846
            self.unversioned(tree2, 'dir'),
847
            ]
848
        specific_files=['file', 'dir']
849
        if links_supported:
850
            expected.append(self.renamed(tree1, tree2, 'link-id', False))
851
            expected.append(self.unversioned(tree2, 'link'))
852
            specific_files.append('link')
853
        expected = sorted(expected)
854
        # run once with, and once without specific files, to catch
855
        # potentially different code paths.
856
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
857
            require_versioned=False,
858
            want_unversioned=True))
859
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
860
            specific_files=specific_files, require_versioned=False,
861
            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.
862
2255.7.87 by Robert Collins
Dont walk unversioned directories in _iter_changes.
863
    def test_unversioned_subtree_only_emits_root(self):
864
        tree1 = self.make_branch_and_tree('tree1')
865
        tree2 = self.make_to_branch_and_tree('tree2')
866
        self.build_tree(['tree2/dir/', 'tree2/dir/file'])
867
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
868
        expected = [
869
            self.unversioned(tree2, 'dir'),
870
            ]
871
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
872
            want_unversioned=True))
873
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.
874
    def make_trees_with_symlinks(self):
875
        tree1 = self.make_branch_and_tree('tree1')
876
        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
877
        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.
878
        self.build_tree(['tree1/fromfile', 'tree1/fromdir/'])
879
        self.build_tree(['tree2/tofile', 'tree2/todir/', 'tree2/unknown'])
880
        # try:
881
        os.symlink('original', 'tree1/changed')
882
        os.symlink('original', 'tree1/removed')
883
        os.symlink('original', 'tree1/tofile')
884
        os.symlink('original', 'tree1/todir')
885
        # we make the unchanged link point at unknown to catch incorrect
886
        # symlink-following code in the specified_files test.
887
        os.symlink('unknown', 'tree1/unchanged')
888
        os.symlink('new',      'tree2/added')
889
        os.symlink('new',      'tree2/changed')
890
        os.symlink('new',      'tree2/fromfile')
891
        os.symlink('new',      'tree2/fromdir')
892
        os.symlink('unknown', 'tree2/unchanged')
893
        from_paths_and_ids = [
894
            'fromdir',
895
            'fromfile',
896
            'changed',
897
            'removed',
898
            'todir',
899
            'tofile',
900
            'unchanged',
901
            ]
902
        to_paths_and_ids = [
903
            'added',
904
            'fromdir',
905
            'fromfile',
906
            'changed',
907
            'todir',
908
            'tofile',
909
            'unchanged',
910
            ]
911
        tree1.add(from_paths_and_ids, from_paths_and_ids)
912
        tree2.add(to_paths_and_ids, to_paths_and_ids)
913
        # except ???:
914
        #   raise TestSkipped('OS does not support symlinks')
915
        #   links_supported = False
916
        return self.mutable_trees_to_test_trees(tree1, tree2)
917
2255.2.182 by Martin Pool
merge dirstate and trunk
918
    def make_trees_with_subtrees(self):
919
        # trees containing tree references
920
        # TODO: might have to skip if the format can't do tree references
921
        tree1 = self.make_branch_and_tree('tree1')
922
        tree2 = self.make_to_branch_and_tree('tree2')
923
        self.build_tree(['tree1/fromdir/', 'tree1/common/',
924
            'tree2/todir/', 'tree2/common/'])
925
        # TODO: actually add the references
926
        return self.mutable_trees_to_test_trees(tree1, tree2)
927
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
928
    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.
929
        tree1, tree2 = self.make_trees_with_symlinks()
930
        root_id = tree1.path2id('')
931
        tree1.lock_read()
932
        self.addCleanup(tree1.unlock)
933
        tree2.lock_read()
934
        self.addCleanup(tree2.unlock)
935
        expected = [
936
            self.unchanged(tree1, tree1.path2id('')),
937
            self.added(tree2, 'added'),
938
            self.content_changed(tree2, 'changed'),
939
            self.kind_changed(tree1, tree2, 'fromdir'),
940
            self.kind_changed(tree1, tree2, 'fromfile'),
941
            self.deleted(tree1, 'removed'),
942
            self.unchanged(tree2, 'unchanged'),
943
            self.unversioned(tree2, 'unknown'),
944
            self.kind_changed(tree1, tree2, 'todir'),
945
            self.kind_changed(tree1, tree2, 'tofile'),
946
            ]
947
        expected = sorted(expected)
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
948
        self.assertEqual(expected,
949
            self.do_iter_changes(tree1, tree2, include_unchanged=True,
950
                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.
951
2255.7.88 by Robert Collins
Enable InterTree._iter_changes symlink tests.
952
    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.
953
        tree1, tree2 = self.make_trees_with_symlinks()
954
        root_id = tree1.path2id('')
955
        tree1.lock_read()
956
        self.addCleanup(tree1.unlock)
957
        tree2.lock_read()
958
        self.addCleanup(tree2.unlock)
959
        expected = [
960
            self.added(tree2, 'added'),
961
            self.content_changed(tree2, 'changed'),
962
            self.kind_changed(tree1, tree2, 'fromdir'),
963
            self.kind_changed(tree1, tree2, 'fromfile'),
964
            self.deleted(tree1, 'removed'),
965
            self.kind_changed(tree1, tree2, 'todir'),
966
            self.kind_changed(tree1, tree2, 'tofile'),
967
            ]
968
        expected = sorted(expected)
969
        # we should get back just the changed links. We pass in 'unchanged' to
970
        # make sure that it is correctly not returned - and neither is the
971
        # unknown path 'unknown' which it points at.
972
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
973
            specific_files=['added', 'changed', 'fromdir', 'fromfile',
974
            '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.
975
2255.7.21 by John Arbash Meinel
Get iter_changes working again, by fixing set_parent_trees to
976
    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.
977
        tree1, tree2, paths, path_ids = self.make_tree_with_special_names()
978
        tree1.lock_read()
979
        self.addCleanup(tree1.unlock)
980
        tree2.lock_read()
981
        self.addCleanup(tree2.unlock)
982
        expected = sorted(self.added(tree2, f_id) for f_id in path_ids)
983
        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.
984
985
    def test_trees_with_special_names(self):
986
        tree1, tree2, paths, path_ids = self.make_trees_with_special_names()
987
        tree1.lock_read()
988
        self.addCleanup(tree1.unlock)
989
        tree2.lock_read()
990
        self.addCleanup(tree2.unlock)
991
        expected = sorted(self.content_changed(tree2, f_id) for f_id in path_ids
992
                          if f_id.endswith('_f-id'))
993
        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
994
2255.2.182 by Martin Pool
merge dirstate and trunk
995
    def test_trees_with_subtrees(self):
996
        tree1, tree2 = self.make_trees_with_subtrees()
997
        self.do_iter_changes(tree1, tree2)
998
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
999
    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.
1000
        tree1 = self.make_branch_and_tree('tree1')
1001
        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
1002
        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.
1003
        self.build_tree(['tree1/a', 'tree1/b/', 'tree1/b/c',
1004
                         'tree1/b/d/', 'tree1/b/d/e', 'tree1/f/', 'tree1/f/g',
1005
                         'tree2/a', 'tree2/f/', 'tree2/f/g'])
1006
        tree1.add(['a', 'b', 'b/c', 'b/d/', 'b/d/e', 'f', 'f/g'],
1007
                  ['a-id', 'b-id', 'c-id', 'd-id', 'e-id', 'f-id', 'g-id'])
1008
        tree2.add(['a', 'f', 'f/g'], ['a-id', 'f-id', 'g-id'])
1009
1010
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1011
        tree1.lock_read()
1012
        self.addCleanup(tree1.unlock)
1013
        tree2.lock_read()
1014
        self.addCleanup(tree2.unlock)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1015
        # 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.
1016
        expected = sorted([
1017
            self.content_changed(tree2, 'a-id'),
1018
            self.content_changed(tree2, 'g-id'),
1019
            self.deleted(tree1, 'b-id'),
1020
            self.deleted(tree1, 'c-id'),
1021
            self.deleted(tree1, 'd-id'),
1022
            self.deleted(tree1, 'e-id'),
1023
            ])
1024
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))