/brz/remove-bazaar

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