/brz/remove-bazaar

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