/brz/remove-bazaar

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