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