/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2007-2012, 2016 Canonical Ltd
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
2
# Authors:  Robert Collins <robert.collins@canonical.com>
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
17
18
"""Tests for WorkingTreeFormat4"""
19
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
20
import os
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
21
import time
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
22
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
23
from .. import (
6670.4.1 by Jelmer Vernooij
Update imports.
24
    errors,
25
    osutils,
26
    )
27
from ..bzr import (
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
28
    bzrdir,
29
    dirstate,
1551.15.6 by Aaron Bentley
Use ROOT_ID when the repository supports old clients (Bug #107168)
30
    inventory,
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
31
    workingtree_4,
32
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
33
from ..lockdir import LockDir
34
from . import TestCaseWithTransport, TestSkipped, features
35
from ..tree import InterTree
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
36
37
38
class TestWorkingTreeFormat4(TestCaseWithTransport):
39
    """Tests specific to WorkingTreeFormat4."""
40
41
    def test_disk_layout(self):
42
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
43
        control.create_repository()
44
        control.create_branch()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
45
        workingtree_4.WorkingTreeFormat4().initialize(control)
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
46
        # we want:
47
        # format 'Bazaar Working Tree format 4'
48
        # stat-cache = ??
49
        t = control.get_workingtree_transport(None)
7045.1.1 by Jelmer Vernooij
Fix another 300 tests.
50
        self.assertEqualDiff(b'Bazaar Working Tree Format 4 (bzr 0.15)\n',
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
51
                             t.get('format').read())
52
        self.assertFalse(t.has('inventory.basis'))
53
        # no last-revision file means 'None' or 'NULLREVISION'
54
        self.assertFalse(t.has('last-revision'))
55
        state = dirstate.DirState.on_file(t.local_abspath('dirstate'))
56
        state.lock_read()
57
        try:
58
            self.assertEqual([], state.get_parent_ids())
59
        finally:
60
            state.unlock()
61
5900.1.1 by Jelmer Vernooij
Make sure only the last unlock resets the cached ignore glob.
62
    def test_resets_ignores_on_last_unlock(self):
63
        # Only the last unlock call will actually reset the
64
        # ignores. (bug #785671)
65
        tree = self.make_workingtree()
66
        tree.lock_read()
67
        try:
68
            tree.lock_read()
69
            try:
70
                tree.is_ignored("foo")
71
            finally:
72
                tree.unlock()
73
            self.assertIsNot(None, tree._ignoreglobster)
74
        finally:
75
            tree.unlock()
76
        self.assertIs(None, tree._ignoreglobster)
77
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
78
    def test_uses_lockdir(self):
79
        """WorkingTreeFormat4 uses its own LockDir:
2255.10.1 by John Arbash Meinel
Update WorkingTree4 so that it doesn't use a HashCache,
80
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
81
            - lock is a directory
82
            - when the WorkingTree is locked, LockDir can see that
83
        """
84
        # this test could be factored into a subclass of tests common to both
4285.2.1 by Vincent Ladeuil
Cleanup test imports and use features to better track skipped tests.
85
        # format 3 and 4, but for now its not much of an issue as there is only
86
        # one in common.
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
87
        t = self.get_transport()
88
        tree = self.make_workingtree()
89
        self.assertIsDirectory('.bzr', t)
90
        self.assertIsDirectory('.bzr/checkout', t)
91
        self.assertIsDirectory('.bzr/checkout/lock', t)
92
        our_lock = LockDir(t, '.bzr/checkout/lock')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
93
        self.assertEqual(our_lock.peek(), None)
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
94
        tree.lock_write()
95
        self.assertTrue(our_lock.peek())
96
        tree.unlock()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
97
        self.assertEqual(our_lock.peek(), None)
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
98
99
    def make_workingtree(self, relpath=''):
100
        url = self.get_url(relpath)
101
        if relpath:
102
            self.build_tree([relpath + '/'])
103
        dir = bzrdir.BzrDirMetaFormat1().initialize(url)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
104
        dir.create_repository()
105
        dir.create_branch()
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
106
        try:
107
            return workingtree_4.WorkingTreeFormat4().initialize(dir)
108
        except errors.NotLocalUrl:
109
            raise TestSkipped('Not a local URL')
110
111
    def test_dirstate_stores_all_parent_inventories(self):
112
        tree = self.make_workingtree()
113
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
114
        # We're going to build in tree a working tree
115
        # with three parent trees, with some files in common.
116
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
117
        # We really don't want to do commit or merge in the new dirstate-based
118
        # tree, because that might not work yet.  So instead we build
119
        # revisions elsewhere and pull them across, doing by hand part of the
120
        # work that merge would do.
121
122
        subtree = self.make_branch_and_tree('subdir')
123
        # writelock the tree so its repository doesn't get readlocked by
124
        # the revision tree locks. This works around the bug where we dont
125
        # permit lock upgrading.
126
        subtree.lock_write()
127
        self.addCleanup(subtree.unlock)
7143.15.2 by Jelmer Vernooij
Run autopep8.
128
        self.build_tree(['subdir/file-a', ])
7007.1.9 by Jelmer Vernooij
Fix more dirstate tests.
129
        subtree.add(['file-a'], [b'id-a'])
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
130
        rev1 = subtree.commit('commit in subdir')
131
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
132
        subtree2 = subtree.controldir.sprout('subdir2').open_workingtree()
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
133
        self.build_tree(['subdir2/file-b'])
7007.1.9 by Jelmer Vernooij
Fix more dirstate tests.
134
        subtree2.add(['file-b'], [b'id-b'])
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
135
        rev2 = subtree2.commit('commit in subdir2')
136
137
        subtree.flush()
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
138
        subtree3 = subtree.controldir.sprout('subdir3').open_workingtree()
3462.1.7 by John Arbash Meinel
fix a test that assumed WT4.set_parent_trees() wouldn't filter the list.
139
        rev3 = subtree3.commit('merge from subdir2')
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
140
141
        repo = tree.branch.repository
3462.1.7 by John Arbash Meinel
fix a test that assumed WT4.set_parent_trees() wouldn't filter the list.
142
        repo.fetch(subtree.branch.repository, rev1)
143
        repo.fetch(subtree2.branch.repository, rev2)
144
        repo.fetch(subtree3.branch.repository, rev3)
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
145
        # will also pull the others...
146
147
        # create repository based revision trees
3462.1.7 by John Arbash Meinel
fix a test that assumed WT4.set_parent_trees() wouldn't filter the list.
148
        rev1_revtree = repo.revision_tree(rev1)
149
        rev2_revtree = repo.revision_tree(rev2)
150
        rev3_revtree = repo.revision_tree(rev3)
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
151
        # tree doesn't contain a text merge yet but we'll just
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
152
        # set the parents as if a merge had taken place.
153
        # this should cause the tree data to be folded into the
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
154
        # dirstate.
155
        tree.set_parent_trees([
156
            (rev1, rev1_revtree),
157
            (rev2, rev2_revtree),
158
            (rev3, rev3_revtree), ])
159
160
        # create tree-sourced revision trees
161
        rev1_tree = tree.revision_tree(rev1)
162
        rev1_tree.lock_read()
163
        self.addCleanup(rev1_tree.unlock)
164
        rev2_tree = tree.revision_tree(rev2)
165
        rev2_tree.lock_read()
166
        self.addCleanup(rev2_tree.unlock)
167
        rev3_tree = tree.revision_tree(rev3)
168
        rev3_tree.lock_read()
169
        self.addCleanup(rev3_tree.unlock)
170
171
        # now we should be able to get them back out
172
        self.assertTreesEqual(rev1_revtree, rev1_tree)
173
        self.assertTreesEqual(rev2_revtree, rev2_tree)
174
        self.assertTreesEqual(rev3_revtree, rev3_tree)
175
176
    def test_dirstate_doesnt_read_parents_from_repo_when_setting(self):
177
        """Setting parent trees on a dirstate working tree takes
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
178
        the trees it's given and doesn't need to read them from the
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
179
        repository.
180
        """
181
        tree = self.make_workingtree()
182
183
        subtree = self.make_branch_and_tree('subdir')
184
        rev1 = subtree.commit('commit in subdir')
185
        rev1_tree = subtree.basis_tree()
186
        rev1_tree.lock_read()
187
        self.addCleanup(rev1_tree.unlock)
188
189
        tree.branch.pull(subtree.branch)
190
191
        # break the repository's legs to make sure it only uses the trees
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
192
        # it's given; any calls to forbidden methods will raise an
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
193
        # AssertionError
194
        repo = tree.branch.repository
5340.15.1 by John Arbash Meinel
supersede exc-info branch
195
        self.overrideAttr(repo, "get_revision", self.fail)
196
        self.overrideAttr(repo, "get_inventory", self.fail)
197
        self.overrideAttr(repo, "_get_inventory_xml", self.fail)
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
198
        # try to set the parent trees.
199
        tree.set_parent_trees([(rev1, rev1_tree)])
200
201
    def test_dirstate_doesnt_read_from_repo_when_returning_cache_tree(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
202
        """Getting parent trees from a dirstate tree does not read from the
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
203
        repos inventory store. This is an important part of the dirstate
204
        performance optimisation work.
205
        """
206
        tree = self.make_workingtree()
207
208
        subtree = self.make_branch_and_tree('subdir')
209
        # writelock the tree so its repository doesn't get readlocked by
210
        # the revision tree locks. This works around the bug where we dont
211
        # permit lock upgrading.
212
        subtree.lock_write()
213
        self.addCleanup(subtree.unlock)
214
        rev1 = subtree.commit('commit in subdir')
215
        rev1_tree = subtree.basis_tree()
216
        rev1_tree.lock_read()
7324.2.3 by Jelmer Vernooij
Fix caching test.
217
        # Trigger reading of inventory
6405.2.12 by Jelmer Vernooij
Fix tests.
218
        rev1_tree.root_inventory
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
219
        self.addCleanup(rev1_tree.unlock)
220
        rev2 = subtree.commit('second commit in subdir', allow_pointless=True)
221
        rev2_tree = subtree.basis_tree()
222
        rev2_tree.lock_read()
7324.2.3 by Jelmer Vernooij
Fix caching test.
223
        # Trigger reading of inventory
6405.2.12 by Jelmer Vernooij
Fix tests.
224
        rev2_tree.root_inventory
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
225
        self.addCleanup(rev2_tree.unlock)
226
227
        tree.branch.pull(subtree.branch)
228
229
        # break the repository's legs to make sure it only uses the trees
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
230
        # it's given; any calls to forbidden methods will raise an
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
231
        # AssertionError
232
        repo = tree.branch.repository
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
233
        # dont uncomment this: the revision object must be accessed to
234
        # answer 'get_parent_ids' for the revision tree- dirstate does not
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
235
        # cache the parents of a parent tree at this point.
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
236
        # repo.get_revision = self.fail
5340.15.1 by John Arbash Meinel
supersede exc-info branch
237
        self.overrideAttr(repo, "get_inventory", self.fail)
238
        self.overrideAttr(repo, "_get_inventory_xml", self.fail)
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
239
        # set the parent trees.
240
        tree.set_parent_trees([(rev1, rev1_tree), (rev2, rev2_tree)])
241
        # read the first tree
242
        result_rev1_tree = tree.revision_tree(rev1)
243
        # read the second
244
        result_rev2_tree = tree.revision_tree(rev2)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
245
        # compare - there should be no differences between the handed and
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
246
        # returned trees
247
        self.assertTreesEqual(rev2_tree, result_rev2_tree)
7324.2.3 by Jelmer Vernooij
Fix caching test.
248
        self.assertRaises(
249
            errors.NoSuchRevisionInTree, self.assertTreesEqual, rev1_tree,
250
            result_rev1_tree)
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
251
252
    def test_dirstate_doesnt_cache_non_parent_trees(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
253
        """Getting parent trees from a dirstate tree does not read from the
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
254
        repos inventory store. This is an important part of the dirstate
255
        performance optimisation work.
256
        """
257
        tree = self.make_workingtree()
258
259
        # make a tree that we can try for, which is able to be returned but
260
        # must not be
261
        subtree = self.make_branch_and_tree('subdir')
262
        rev1 = subtree.commit('commit in subdir')
263
        tree.branch.pull(subtree.branch)
264
        # check it fails
265
        self.assertRaises(errors.NoSuchRevision, tree.revision_tree, rev1)
266
267
    def test_no_dirstate_outside_lock(self):
268
        # temporary test until the code is mature enough to test from outside.
269
        """Getting a dirstate object fails if there is no lock."""
270
        def lock_and_call_current_dirstate(tree, lock_method):
271
            getattr(tree, lock_method)()
272
            tree.current_dirstate()
273
            tree.unlock()
274
        tree = self.make_workingtree()
275
        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
276
        lock_and_call_current_dirstate(tree, 'lock_read')
277
        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
278
        lock_and_call_current_dirstate(tree, 'lock_write')
279
        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
280
        lock_and_call_current_dirstate(tree, 'lock_tree_write')
281
        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
282
5847.4.1 by John Arbash Meinel
When WT4.set_parent_trees() is called, sometimes we can use
283
    def test_set_parent_trees_uses_update_basis_by_delta(self):
284
        builder = self.make_branch_builder('source')
285
        builder.start_series()
286
        self.addCleanup(builder.finish_series)
6816.2.3 by Jelmer Vernooij
Port over last uses of build_snapshot.
287
        builder.build_snapshot([], [
6973.6.2 by Jelmer Vernooij
Fix more tests.
288
            ('add', ('', b'root-id', 'directory', None)),
289
            ('add', ('a', b'a-id', 'file', b'content\n'))],
6973.5.2 by Jelmer Vernooij
Add more bees.
290
            revision_id=b'A')
6973.6.2 by Jelmer Vernooij
Fix more tests.
291
        builder.build_snapshot([b'A'], [
292
            ('modify', ('a', b'new content\nfor a\n')),
293
            ('add', ('b', b'b-id', 'file', b'b-content\n'))],
6973.5.2 by Jelmer Vernooij
Add more bees.
294
            revision_id=b'B')
5847.4.1 by John Arbash Meinel
When WT4.set_parent_trees() is called, sometimes we can use
295
        tree = self.make_workingtree('tree')
296
        source_branch = builder.get_branch()
6973.6.2 by Jelmer Vernooij
Fix more tests.
297
        tree.branch.repository.fetch(source_branch.repository, b'B')
298
        tree.pull(source_branch, stop_revision=b'A')
5847.4.1 by John Arbash Meinel
When WT4.set_parent_trees() is called, sometimes we can use
299
        tree.lock_write()
300
        self.addCleanup(tree.unlock)
301
        state = tree.current_dirstate()
302
        called = []
303
        orig_update = state.update_basis_by_delta
7143.15.2 by Jelmer Vernooij
Run autopep8.
304
5847.4.1 by John Arbash Meinel
When WT4.set_parent_trees() is called, sometimes we can use
305
        def log_update_basis_by_delta(delta, new_revid):
306
            called.append(new_revid)
307
            return orig_update(delta, new_revid)
308
        state.update_basis_by_delta = log_update_basis_by_delta
309
        basis = tree.basis_tree()
6973.6.2 by Jelmer Vernooij
Fix more tests.
310
        self.assertEqual(b'a-id', basis.path2id('a'))
6852.3.1 by Jelmer Vernooij
add Tree.is_versioned.
311
        self.assertFalse(basis.is_versioned('b'))
7143.15.2 by Jelmer Vernooij
Run autopep8.
312
5847.4.1 by John Arbash Meinel
When WT4.set_parent_trees() is called, sometimes we can use
313
        def fail_set_parent_trees(trees, ghosts):
314
            raise AssertionError('dirstate.set_parent_trees() was called')
315
        state.set_parent_trees = fail_set_parent_trees
6973.6.2 by Jelmer Vernooij
Fix more tests.
316
        tree.pull(source_branch, stop_revision=b'B')
317
        self.assertEqual([b'B'], called)
5847.4.1 by John Arbash Meinel
When WT4.set_parent_trees() is called, sometimes we can use
318
        basis = tree.basis_tree()
6973.6.2 by Jelmer Vernooij
Fix more tests.
319
        self.assertEqual(b'a-id', basis.path2id('a'))
320
        self.assertEqual(b'b-id', basis.path2id('b'))
5847.4.1 by John Arbash Meinel
When WT4.set_parent_trees() is called, sometimes we can use
321
5847.4.10 by John Arbash Meinel
A few more bug fixes.
322
    def test_set_parent_trees_handles_missing_basis(self):
323
        builder = self.make_branch_builder('source')
324
        builder.start_series()
325
        self.addCleanup(builder.finish_series)
6816.2.3 by Jelmer Vernooij
Port over last uses of build_snapshot.
326
        builder.build_snapshot([], [
6973.6.2 by Jelmer Vernooij
Fix more tests.
327
            ('add', ('', b'root-id', 'directory', None)),
328
            ('add', ('a', b'a-id', 'file', b'content\n'))],
6973.5.2 by Jelmer Vernooij
Add more bees.
329
            revision_id=b'A')
6973.6.2 by Jelmer Vernooij
Fix more tests.
330
        builder.build_snapshot([b'A'], [
331
            ('modify', ('a', b'new content\nfor a\n')),
332
            ('add', ('b', b'b-id', 'file', b'b-content\n'))],
6973.5.2 by Jelmer Vernooij
Add more bees.
333
            revision_id=b'B')
6973.6.2 by Jelmer Vernooij
Fix more tests.
334
        builder.build_snapshot([b'A'], [
335
            ('add', ('c', b'c-id', 'file', b'c-content\n'))],
6973.5.2 by Jelmer Vernooij
Add more bees.
336
            revision_id=b'C')
5847.4.10 by John Arbash Meinel
A few more bug fixes.
337
        b_c = self.make_branch('branch_with_c')
6973.6.2 by Jelmer Vernooij
Fix more tests.
338
        b_c.pull(builder.get_branch(), stop_revision=b'C')
5847.4.10 by John Arbash Meinel
A few more bug fixes.
339
        b_b = self.make_branch('branch_with_b')
6973.6.2 by Jelmer Vernooij
Fix more tests.
340
        b_b.pull(builder.get_branch(), stop_revision=b'B')
5847.4.10 by John Arbash Meinel
A few more bug fixes.
341
        # This is reproducing some of what 'switch' does, just to isolate the
342
        # set_parent_trees() step.
343
        wt = b_b.create_checkout('tree', lightweight=True)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
344
        fmt = wt.controldir.find_branch_format()
345
        fmt.set_reference(wt.controldir, None, b_c)
5847.4.10 by John Arbash Meinel
A few more bug fixes.
346
        # Re-open with the new reference
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
347
        wt = wt.controldir.open_workingtree()
6973.6.2 by Jelmer Vernooij
Fix more tests.
348
        wt.set_parent_trees([(b'C', b_c.repository.revision_tree(b'C'))])
6852.3.1 by Jelmer Vernooij
add Tree.is_versioned.
349
        self.assertFalse(wt.basis_tree().is_versioned('b'))
5847.4.10 by John Arbash Meinel
A few more bug fixes.
350
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
351
    def test_new_dirstate_on_new_lock(self):
352
        # until we have detection for when a dirstate can be reused, we
353
        # want to reparse dirstate on every new lock.
354
        known_dirstates = set()
7143.15.2 by Jelmer Vernooij
Run autopep8.
355
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
356
        def lock_and_compare_all_current_dirstate(tree, lock_method):
357
            getattr(tree, lock_method)()
358
            state = tree.current_dirstate()
359
            self.assertFalse(state in known_dirstates)
360
            known_dirstates.add(state)
361
            tree.unlock()
362
        tree = self.make_workingtree()
363
        # lock twice with each type to prevent silly per-lock-type bugs.
364
        # each lock and compare looks for a unique state object.
365
        lock_and_compare_all_current_dirstate(tree, 'lock_read')
366
        lock_and_compare_all_current_dirstate(tree, 'lock_read')
367
        lock_and_compare_all_current_dirstate(tree, 'lock_tree_write')
368
        lock_and_compare_all_current_dirstate(tree, 'lock_tree_write')
369
        lock_and_compare_all_current_dirstate(tree, 'lock_write')
370
        lock_and_compare_all_current_dirstate(tree, 'lock_write')
371
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
372
    def test_constructing_invalid_interdirstate_raises(self):
373
        tree = self.make_workingtree()
374
        rev_id = tree.commit('first post')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
375
        tree.commit('second post')
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
376
        rev_tree = tree.branch.repository.revision_tree(rev_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
377
        # Exception is not a great thing to raise, but this test is
378
        # very short, and code is used to sanity check other tests, so
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
379
        # a full error object is YAGNI.
380
        self.assertRaises(
381
            Exception, workingtree_4.InterDirStateTree, rev_tree, tree)
382
        self.assertRaises(
383
            Exception, workingtree_4.InterDirStateTree, tree, rev_tree)
384
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
385
    def test_revtree_to_revtree_not_interdirstate(self):
386
        # we should not get a dirstate optimiser for two repository sourced
387
        # revtrees. we can't prove a negative, so we dont do exhaustive tests
388
        # of all formats; though that could be written in the future it doesn't
389
        # seem well worth it.
390
        tree = self.make_workingtree()
391
        rev_id = tree.commit('first post')
392
        rev_id2 = tree.commit('second post')
393
        rev_tree = tree.branch.repository.revision_tree(rev_id)
394
        rev_tree2 = tree.branch.repository.revision_tree(rev_id2)
395
        optimiser = InterTree.get(rev_tree, rev_tree2)
396
        self.assertIsInstance(optimiser, InterTree)
7143.15.2 by Jelmer Vernooij
Run autopep8.
397
        self.assertFalse(isinstance(
398
            optimiser, workingtree_4.InterDirStateTree))
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
399
        optimiser = InterTree.get(rev_tree2, rev_tree)
400
        self.assertIsInstance(optimiser, InterTree)
7143.15.2 by Jelmer Vernooij
Run autopep8.
401
        self.assertFalse(isinstance(
402
            optimiser, workingtree_4.InterDirStateTree))
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
403
404
    def test_revtree_not_in_dirstate_to_dirstate_not_interdirstate(self):
405
        # we should not get a dirstate optimiser when the revision id for of
406
        # the source is not in the dirstate of the target.
407
        tree = self.make_workingtree()
408
        rev_id = tree.commit('first post')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
409
        tree.commit('second post')
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
410
        rev_tree = tree.branch.repository.revision_tree(rev_id)
411
        tree.lock_read()
412
        optimiser = InterTree.get(rev_tree, tree)
413
        self.assertIsInstance(optimiser, InterTree)
7143.15.2 by Jelmer Vernooij
Run autopep8.
414
        self.assertFalse(isinstance(
415
            optimiser, workingtree_4.InterDirStateTree))
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
416
        optimiser = InterTree.get(tree, rev_tree)
417
        self.assertIsInstance(optimiser, InterTree)
7143.15.2 by Jelmer Vernooij
Run autopep8.
418
        self.assertFalse(isinstance(
419
            optimiser, workingtree_4.InterDirStateTree))
2255.2.121 by John Arbash Meinel
split out the WorkingTreeFormat4 tests into a separate test file
420
        tree.unlock()
421
422
    def test_empty_basis_to_dirstate_tree(self):
423
        # we should get a InterDirStateTree for doing
424
        # 'changes_from' from the first basis dirstate revision tree to a
425
        # WorkingTree4.
426
        tree = self.make_workingtree()
427
        tree.lock_read()
428
        basis_tree = tree.basis_tree()
429
        basis_tree.lock_read()
430
        optimiser = InterTree.get(basis_tree, tree)
431
        tree.unlock()
432
        basis_tree.unlock()
433
        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
434
435
    def test_nonempty_basis_to_dirstate_tree(self):
436
        # we should get a InterDirStateTree for doing
437
        # 'changes_from' from a non-null basis dirstate revision tree to a
438
        # WorkingTree4.
439
        tree = self.make_workingtree()
440
        tree.commit('first post')
441
        tree.lock_read()
442
        basis_tree = tree.basis_tree()
443
        basis_tree.lock_read()
444
        optimiser = InterTree.get(basis_tree, tree)
445
        tree.unlock()
446
        basis_tree.unlock()
447
        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
448
449
    def test_empty_basis_revtree_to_dirstate_tree(self):
450
        # we should get a InterDirStateTree for doing
451
        # 'changes_from' from an empty repository based rev tree to a
452
        # WorkingTree4.
453
        tree = self.make_workingtree()
454
        tree.lock_read()
455
        basis_tree = tree.branch.repository.revision_tree(tree.last_revision())
456
        basis_tree.lock_read()
457
        optimiser = InterTree.get(basis_tree, tree)
458
        tree.unlock()
459
        basis_tree.unlock()
460
        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
461
462
    def test_nonempty_basis_revtree_to_dirstate_tree(self):
463
        # we should get a InterDirStateTree for doing
464
        # 'changes_from' from a non-null repository based rev tree to a
465
        # WorkingTree4.
466
        tree = self.make_workingtree()
467
        tree.commit('first post')
468
        tree.lock_read()
469
        basis_tree = tree.branch.repository.revision_tree(tree.last_revision())
470
        basis_tree.lock_read()
471
        optimiser = InterTree.get(basis_tree, tree)
472
        tree.unlock()
473
        basis_tree.unlock()
474
        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
475
476
    def test_tree_to_basis_in_other_tree(self):
477
        # we should get a InterDirStateTree when
478
        # the source revid is in the dirstate object of the target and
479
        # the dirstates are different. This is largely covered by testing
480
        # with repository revtrees, so is just for extra confidence.
481
        tree = self.make_workingtree('a')
482
        tree.commit('first post')
483
        tree2 = self.make_workingtree('b')
484
        tree2.pull(tree.branch)
485
        basis_tree = tree.basis_tree()
486
        tree2.lock_read()
487
        basis_tree.lock_read()
488
        optimiser = InterTree.get(basis_tree, tree2)
489
        tree2.unlock()
490
        basis_tree.unlock()
491
        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
492
493
    def test_merged_revtree_to_tree(self):
494
        # we should get a InterDirStateTree when
495
        # the source tree is a merged tree present in the dirstate of target.
496
        tree = self.make_workingtree('a')
497
        tree.commit('first post')
498
        tree.commit('tree 1 commit 2')
499
        tree2 = self.make_workingtree('b')
500
        tree2.pull(tree.branch)
501
        tree2.commit('tree 2 commit 2')
502
        tree.merge_from_branch(tree2.branch)
503
        second_parent_tree = tree.revision_tree(tree.get_parent_ids()[1])
504
        second_parent_tree.lock_read()
505
        tree.lock_read()
506
        optimiser = InterTree.get(second_parent_tree, tree)
507
        tree.unlock()
508
        second_parent_tree.unlock()
509
        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
2255.2.144 by John Arbash Meinel
Simplify update_minimal a bit more, by making id_index a
510
511
    def test_id2path(self):
512
        tree = self.make_workingtree('tree')
2255.2.147 by John Arbash Meinel
Move fast id => path lookups down into DirState
513
        self.build_tree(['tree/a', 'tree/b'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
514
        tree.add(['a'], [b'a-id'])
515
        self.assertEqual(u'a', tree.id2path(b'a-id'))
2255.11.5 by Martin Pool
Tree.id2path should raise NoSuchId, not return None.
516
        self.assertRaises(errors.NoSuchId, tree.id2path, 'a')
2255.2.144 by John Arbash Meinel
Simplify update_minimal a bit more, by making id_index a
517
        tree.commit('a')
6855.4.1 by Jelmer Vernooij
Yet more bees.
518
        tree.add(['b'], [b'b-id'])
2255.2.144 by John Arbash Meinel
Simplify update_minimal a bit more, by making id_index a
519
2321.1.2 by Robert Collins
Skip new tests that depend on unicode file paths.
520
        try:
2825.6.1 by Robert Collins
* ``WorkingTree.rename_one`` will now raise an error if normalisation of the
521
            new_path = u'b\u03bcrry'
522
            tree.rename_one('a', new_path)
2321.1.2 by Robert Collins
Skip new tests that depend on unicode file paths.
523
        except UnicodeEncodeError:
524
            # support running the test on non-unicode platforms
525
            new_path = 'c'
2825.6.1 by Robert Collins
* ``WorkingTree.rename_one`` will now raise an error if normalisation of the
526
            tree.rename_one('a', new_path)
6855.4.1 by Jelmer Vernooij
Yet more bees.
527
        self.assertEqual(new_path, tree.id2path(b'a-id'))
2255.2.144 by John Arbash Meinel
Simplify update_minimal a bit more, by making id_index a
528
        tree.commit(u'b\xb5rry')
6809.4.25 by Jelmer Vernooij
Add paths argument to .unversion.
529
        tree.unversion([new_path])
6855.4.1 by Jelmer Vernooij
Yet more bees.
530
        self.assertRaises(errors.NoSuchId, tree.id2path, b'a-id')
531
        self.assertEqual('b', tree.id2path(b'b-id'))
532
        self.assertRaises(errors.NoSuchId, tree.id2path, b'c-id')
2255.2.166 by Martin Pool
(broken) Add Tree.get_root_id() & test
533
534
    def test_unique_root_id_per_tree(self):
535
        # each time you initialize a new tree, it gets a different root id
6437.14.2 by Jelmer Vernooij
Run subtree tests with development-subtree rather than deprecated dirstate-with-subtree.
536
        format_name = 'development-subtree'
2255.2.166 by Martin Pool
(broken) Add Tree.get_root_id() & test
537
        tree1 = self.make_branch_and_tree('tree1',
7143.15.2 by Jelmer Vernooij
Run autopep8.
538
                                          format=format_name)
2255.2.166 by Martin Pool
(broken) Add Tree.get_root_id() & test
539
        tree2 = self.make_branch_and_tree('tree2',
7143.15.2 by Jelmer Vernooij
Run autopep8.
540
                                          format=format_name)
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
541
        self.assertNotEqual(tree1.path2id(''), tree2.path2id(''))
2255.2.166 by Martin Pool
(broken) Add Tree.get_root_id() & test
542
        # when you branch, it inherits the same root id
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
543
        tree1.commit('first post')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
544
        tree3 = tree1.controldir.sprout('tree3').open_workingtree()
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
545
        self.assertEqual(tree3.path2id(''), tree1.path2id(''))
2255.2.166 by Martin Pool
(broken) Add Tree.get_root_id() & test
546
2255.11.2 by Martin Pool
Add more dirstate root-id-changing tests
547
    def test_set_root_id(self):
548
        # similar to some code that fails in the dirstate-plus-subtree branch
549
        # -- setting the root id while adding a parent seems to scramble the
550
        # dirstate invariants. -- mbp 20070303
551
        def validate():
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
552
            with wt.lock_read():
2255.11.2 by Martin Pool
Add more dirstate root-id-changing tests
553
                wt.current_dirstate()._validate()
554
        wt = self.make_workingtree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
555
        wt.set_root_id(b'TREE-ROOTID')
2255.11.2 by Martin Pool
Add more dirstate root-id-changing tests
556
        validate()
557
        wt.commit('somenthing')
558
        validate()
559
        # now switch and commit again
6855.4.1 by Jelmer Vernooij
Yet more bees.
560
        wt.set_root_id(b'tree-rootid')
2255.11.2 by Martin Pool
Add more dirstate root-id-changing tests
561
        validate()
562
        wt.commit('again')
563
        validate()
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
564
1551.15.6 by Aaron Bentley
Use ROOT_ID when the repository supports old clients (Bug #107168)
565
    def test_default_root_id(self):
566
        tree = self.make_branch_and_tree('tag', format='dirstate-tags')
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
567
        self.assertEqual(inventory.ROOT_ID, tree.path2id(''))
1551.15.6 by Aaron Bentley
Use ROOT_ID when the repository supports old clients (Bug #107168)
568
        tree = self.make_branch_and_tree('subtree',
6437.14.2 by Jelmer Vernooij
Run subtree tests with development-subtree rather than deprecated dirstate-with-subtree.
569
                                         format='development-subtree')
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
570
        self.assertNotEqual(inventory.ROOT_ID, tree.path2id(''))
1551.15.6 by Aaron Bentley
Use ROOT_ID when the repository supports old clients (Bug #107168)
571
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
572
    def test_non_subtree_with_nested_trees(self):
573
        # prior to dirstate, st/diff/commit ignored nested trees.
6437.14.2 by Jelmer Vernooij
Run subtree tests with development-subtree rather than deprecated dirstate-with-subtree.
574
        # dirstate, as opposed to development-subtree, should
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
575
        # behave the same way.
576
        tree = self.make_branch_and_tree('.', format='dirstate')
577
        self.assertFalse(tree.supports_tree_reference())
578
        self.build_tree(['dir/'])
579
        # for testing easily.
6855.4.1 by Jelmer Vernooij
Yet more bees.
580
        tree.set_root_id(b'root')
581
        tree.add(['dir'], [b'dir-id'])
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
582
        self.make_branch_and_tree('dir')
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
583
        # the most primitive operation: kind
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
584
        self.assertEqual('directory', tree.kind('dir'))
4570.2.8 by Robert Collins
Adjust WorkingTree4 specific test to deal with iter_changes reporting required directories.
585
        # a diff against the basis should give us a directory and the root (as
586
        # the root is new too).
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
587
        tree.lock_read()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
588
        expected = [(b'dir-id',
7143.15.2 by Jelmer Vernooij
Run autopep8.
589
                     (None, u'dir'),
590
                     True,
591
                     (False, True),
592
                     (None, b'root'),
593
                     (None, u'dir'),
594
                     (None, 'directory'),
7358.17.5 by Jelmer Vernooij
Fix more tests.
595
                     (None, False), False),
7143.15.2 by Jelmer Vernooij
Run autopep8.
596
                    (b'root', (None, u''), True, (False, True), (None, None),
7358.17.5 by Jelmer Vernooij
Fix more tests.
597
                     (None, u''), (None, 'directory'), (None, False), False)]
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
598
        self.assertEqual(
599
            expected,
600
            list(tree.iter_changes(tree.basis_tree(), specific_files=['dir'])))
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
601
        tree.unlock()
602
        # do a commit, we want to trigger the dirstate fast-path too
603
        tree.commit('first post')
604
        # change the path for the subdir, which will trigger getting all
605
        # its data:
606
        os.rename('dir', 'also-dir')
607
        # now the diff will use the fast path
608
        tree.lock_read()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
609
        expected = [(b'dir-id',
7143.15.2 by Jelmer Vernooij
Run autopep8.
610
                     (u'dir', u'dir'),
611
                     True,
612
                     (True, True),
613
                     (b'root', b'root'),
614
                     ('dir', 'dir'),
615
                     ('directory', None),
7358.17.5 by Jelmer Vernooij
Fix more tests.
616
                     (False, False), False)]
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
617
        self.assertEqual(expected, list(tree.iter_changes(tree.basis_tree())))
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
618
        tree.unlock()
619
620
    def test_with_subtree_supports_tree_references(self):
6437.14.2 by Jelmer Vernooij
Run subtree tests with development-subtree rather than deprecated dirstate-with-subtree.
621
        # development-subtree should support tree-references.
622
        tree = self.make_branch_and_tree('.', format='development-subtree')
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
623
        self.assertTrue(tree.supports_tree_reference())
624
        # having checked this is on, the tree interface, and intertree
625
        # interface tests, will proceed to test the subtree support of
626
        # workingtree_4.
2466.4.1 by John Arbash Meinel
Add a (failing) test that exposes how _iter_changes is accidentally walking into unversioned directories.
627
628
    def test_iter_changes_ignores_unversioned_dirs(self):
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
629
        """iter_changes should not descend into unversioned directories."""
2466.4.1 by John Arbash Meinel
Add a (failing) test that exposes how _iter_changes is accidentally walking into unversioned directories.
630
        tree = self.make_branch_and_tree('.', format='dirstate')
631
        # We have an unversioned directory at the root, a versioned one with
632
        # other versioned files and an unversioned directory, and another
633
        # versioned dir with nothing but an unversioned directory.
634
        self.build_tree(['unversioned/',
635
                         'unversioned/a',
636
                         'unversioned/b/',
637
                         'versioned/',
638
                         'versioned/unversioned/',
639
                         'versioned/unversioned/a',
640
                         'versioned/unversioned/b/',
641
                         'versioned2/',
642
                         'versioned2/a',
643
                         'versioned2/unversioned/',
644
                         'versioned2/unversioned/a',
645
                         'versioned2/unversioned/b/',
7143.15.2 by Jelmer Vernooij
Run autopep8.
646
                         ])
2466.4.1 by John Arbash Meinel
Add a (failing) test that exposes how _iter_changes is accidentally walking into unversioned directories.
647
        tree.add(['versioned', 'versioned2', 'versioned2/a'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
648
        tree.commit('one', rev_id=b'rev-1')
2466.4.1 by John Arbash Meinel
Add a (failing) test that exposes how _iter_changes is accidentally walking into unversioned directories.
649
        # Trap osutils._walkdirs_utf8 to spy on what dirs have been accessed.
650
        returned = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
651
2466.4.1 by John Arbash Meinel
Add a (failing) test that exposes how _iter_changes is accidentally walking into unversioned directories.
652
        def walkdirs_spy(*args, **kwargs):
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
653
            for val in orig(*args, **kwargs):
2466.4.1 by John Arbash Meinel
Add a (failing) test that exposes how _iter_changes is accidentally walking into unversioned directories.
654
                returned.append(val[0][0])
655
                yield val
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
656
        orig = self.overrideAttr(osutils, '_walkdirs_utf8', walkdirs_spy)
2466.4.1 by John Arbash Meinel
Add a (failing) test that exposes how _iter_changes is accidentally walking into unversioned directories.
657
658
        basis = tree.basis_tree()
659
        tree.lock_read()
660
        self.addCleanup(tree.unlock)
661
        basis.lock_read()
662
        self.addCleanup(basis.unlock)
7358.16.1 by Jelmer Vernooij
Don't make TreeChange tuple-like objects anymore, so we can add and remove attributes as necessary.
663
        changes = [c.path for c in
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
664
                   tree.iter_changes(basis, want_unversioned=True)]
2466.4.2 by John Arbash Meinel
Clean up the (failing) test so that the last thing
665
        self.assertEqual([(None, 'unversioned'),
666
                          (None, 'versioned/unversioned'),
667
                          (None, 'versioned2/unversioned'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
668
                          ], changes)
7045.2.13 by Jelmer Vernooij
Fix some workingtree_4 tests.
669
        self.assertEqual([b'', b'versioned', b'versioned2'], returned)
7143.15.2 by Jelmer Vernooij
Run autopep8.
670
        del returned[:]  # reset
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
671
        changes = [c[1] for c in tree.iter_changes(basis)]
2466.4.2 by John Arbash Meinel
Clean up the (failing) test so that the last thing
672
        self.assertEqual([], changes)
7045.2.13 by Jelmer Vernooij
Fix some workingtree_4 tests.
673
        self.assertEqual([b'', b'versioned', b'versioned2'], returned)
3207.2.1 by jameinel
Add a test that _iter_changes raises a clearer error when we encounter an invalid rename.
674
4496.2.1 by Ian Clatworthy
(igc) Improve paths are not versioned reporting (Benoît PIERRE)
675
    def test_iter_changes_unversioned_error(self):
676
        """ Check if a PathsNotVersionedError is correctly raised and the
677
            paths list contains all unversioned entries only.
678
        """
679
        tree = self.make_branch_and_tree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
680
        self.build_tree_contents([('tree/bar', b'')])
681
        tree.add(['bar'], [b'bar-id'])
4496.2.1 by Ian Clatworthy
(igc) Improve paths are not versioned reporting (Benoît PIERRE)
682
        tree.lock_read()
683
        self.addCleanup(tree.unlock)
7143.15.2 by Jelmer Vernooij
Run autopep8.
684
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
685
        def tree_iter_changes(files):
686
            return [
687
                c for c in tree.iter_changes(
688
                    tree.basis_tree(), specific_files=files,
689
                    require_versioned=True)]
4496.2.1 by Ian Clatworthy
(igc) Improve paths are not versioned reporting (Benoît PIERRE)
690
        e = self.assertRaises(errors.PathsNotVersionedError,
691
                              tree_iter_changes, ['bar', 'foo'])
692
        self.assertEqual(e.paths, ['foo'])
693
6345.1.2 by Martin Packman
Add targetted working tree tests for places that raise PathsNotVersionedError
694
    def test_iter_changes_unversioned_non_ascii(self):
695
        """Unversioned non-ascii paths should be reported as unicode"""
696
        self.requireFeature(features.UnicodeFilenameFeature)
697
        tree = self.make_branch_and_tree('.')
6855.4.1 by Jelmer Vernooij
Yet more bees.
698
        self.build_tree_contents([('f', b'')])
699
        tree.add(['f'], [b'f-id'])
7143.15.2 by Jelmer Vernooij
Run autopep8.
700
6345.1.2 by Martin Packman
Add targetted working tree tests for places that raise PathsNotVersionedError
701
        def tree_iter_changes(tree, files):
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
702
            return list(tree.iter_changes(
703
                tree.basis_tree(), specific_files=files,
704
                require_versioned=True))
6345.1.2 by Martin Packman
Add targetted working tree tests for places that raise PathsNotVersionedError
705
        tree.lock_read()
706
        self.addCleanup(tree.unlock)
707
        e = self.assertRaises(errors.PathsNotVersionedError,
7143.15.2 by Jelmer Vernooij
Run autopep8.
708
                              tree_iter_changes, tree, [u'\xa7', u'\u03c0'])
6973.10.6 by Jelmer Vernooij
Fix tests.
709
        self.assertEqual(set(e.paths), set([u'\xa7', u'\u03c0']))
6345.1.2 by Martin Packman
Add targetted working tree tests for places that raise PathsNotVersionedError
710
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
711
    def get_tree_with_cachable_file_foo(self):
712
        tree = self.make_branch_and_tree('.')
5755.1.1 by John Arbash Meinel
Change WT._observed_sha1 to also update st.st_size.
713
        tree.lock_write()
714
        self.addCleanup(tree.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
715
        self.build_tree_contents([('foo', b'a bit of content for foo\n')])
716
        tree.add(['foo'], [b'foo-id'])
5755.1.1 by John Arbash Meinel
Change WT._observed_sha1 to also update st.st_size.
717
        tree.current_dirstate()._cutoff_time = time.time() + 60
3207.2.1 by jameinel
Add a test that _iter_changes raises a clearer error when we encounter an invalid rename.
718
        return tree
719
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
720
    def test_commit_updates_hash_cache(self):
721
        tree = self.get_tree_with_cachable_file_foo()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
722
        tree.commit('a commit')
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
723
        # tree's dirstate should now have a valid stat entry for foo.
724
        entry = tree._get_entry(path='foo')
725
        expected_sha1 = osutils.sha_file_by_name('foo')
726
        self.assertEqual(expected_sha1, entry[1][0][1])
5755.1.2 by John Arbash Meinel
use soft constants rather than '25'
727
        self.assertEqual(len('a bit of content for foo\n'), entry[1][0][2])
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
728
729
    def test_observed_sha1_cachable(self):
730
        tree = self.get_tree_with_cachable_file_foo()
731
        expected_sha1 = osutils.sha_file_by_name('foo')
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
732
        statvalue = os.lstat("foo")
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
733
        tree._observed_sha1("foo", (expected_sha1, statvalue))
5755.1.1 by John Arbash Meinel
Change WT._observed_sha1 to also update st.st_size.
734
        entry = tree._get_entry(path="foo")
735
        entry_state = entry[1][0]
736
        self.assertEqual(expected_sha1, entry_state[1])
5755.1.2 by John Arbash Meinel
use soft constants rather than '25'
737
        self.assertEqual(statvalue.st_size, entry_state[2])
5755.1.1 by John Arbash Meinel
Change WT._observed_sha1 to also update st.st_size.
738
        tree.unlock()
739
        tree.lock_read()
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
740
        tree = tree.controldir.open_workingtree()
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
741
        tree.lock_read()
3207.2.1 by jameinel
Add a test that _iter_changes raises a clearer error when we encounter an invalid rename.
742
        self.addCleanup(tree.unlock)
5755.1.1 by John Arbash Meinel
Change WT._observed_sha1 to also update st.st_size.
743
        entry = tree._get_entry(path="foo")
744
        entry_state = entry[1][0]
745
        self.assertEqual(expected_sha1, entry_state[1])
5755.1.2 by John Arbash Meinel
use soft constants rather than '25'
746
        self.assertEqual(statvalue.st_size, entry_state[2])
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
747
748
    def test_observed_sha1_new_file(self):
749
        tree = self.make_branch_and_tree('.')
750
        self.build_tree(['foo'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
751
        tree.add(['foo'], [b'foo-id'])
6969.3.2 by Jelmer Vernooij
Use context managers for locking.
752
        with tree.lock_read():
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
753
            current_sha1 = tree._get_entry(path="foo")[1][0][1]
6969.3.2 by Jelmer Vernooij
Use context managers for locking.
754
        with tree.lock_write():
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
755
            tree._observed_sha1(
7143.15.15 by Jelmer Vernooij
Merge trunk.
756
                "foo", (osutils.sha_file_by_name('foo'), os.lstat("foo")))
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
757
            # Must not have changed
758
            self.assertEqual(current_sha1,
7143.15.2 by Jelmer Vernooij
Run autopep8.
759
                             tree._get_entry(path="foo")[1][0][1])
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
760
761
    def test_get_file_with_stat_id_only(self):
762
        # Explicit test to ensure we get a lstat value from WT4 trees.
763
        tree = self.make_branch_and_tree('.')
764
        self.build_tree(['foo'])
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
765
        tree.add(['foo'])
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
766
        tree.lock_read()
767
        self.addCleanup(tree.unlock)
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
768
        file_obj, statvalue = tree.get_file_with_stat('foo')
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
769
        expected = os.lstat('foo')
4807.2.2 by John Arbash Meinel
Move all the stat comparison and platform checkning code to assertEqualStat.
770
        self.assertEqualStat(expected, statvalue)
7045.1.1 by Jelmer Vernooij
Fix another 300 tests.
771
        self.assertEqual([b"contents of foo\n"], file_obj.readlines())
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
772
773
774
class TestCorruptDirstate(TestCaseWithTransport):
775
    """Tests for how we handle when the dirstate has been corrupted."""
776
777
    def create_wt4(self):
778
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
779
        control.create_repository()
780
        control.create_branch()
781
        tree = workingtree_4.WorkingTreeFormat4().initialize(control)
782
        return tree
783
784
    def test_invalid_rename(self):
785
        tree = self.create_wt4()
786
        # Create a corrupted dirstate
6969.3.2 by Jelmer Vernooij
Use context managers for locking.
787
        with tree.lock_write():
4285.2.1 by Vincent Ladeuil
Cleanup test imports and use features to better track skipped tests.
788
            # We need a parent, or we always compare with NULL
789
            tree.commit('init')
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
790
            state = tree.current_dirstate()
791
            state._read_dirblocks_if_needed()
792
            # Now add in an invalid entry, a rename with a dangling pointer
7045.2.13 by Jelmer Vernooij
Fix some workingtree_4 tests.
793
            state._dirblocks[1][1].append(((b'', b'foo', b'foo-id'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
794
                                           [(b'f', b'', 0, False, b''),
795
                                            (b'r', b'bar', 0, False, b'')]))
6744 by Jelmer Vernooij
Merge lp:~jelmer/brz/move-errors-knit.
796
            self.assertListRaises(dirstate.DirstateCorrupt,
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
797
                                  tree.iter_changes, tree.basis_tree())
798
799
    def get_simple_dirblocks(self, state):
800
        """Extract the simple information from the DirState.
801
802
        This returns the dirblocks, only with the sha1sum and stat details
803
        filtered out.
804
        """
805
        simple_blocks = []
806
        for block in state._dirblocks:
807
            simple_block = (block[0], [])
808
            for entry in block[1]:
809
                # Include the key for each entry, and for each parent include
810
                # just the minikind, so we know if it was
811
                # present/absent/renamed/etc
812
                simple_block[1].append((entry[0], [i[0] for i in entry[1]]))
813
            simple_blocks.append(simple_block)
814
        return simple_blocks
815
816
    def test_update_basis_with_invalid_delta(self):
817
        """When given an invalid delta, it should abort, and not be saved."""
818
        self.build_tree(['dir/', 'dir/file'])
819
        tree = self.create_wt4()
820
        tree.lock_write()
821
        self.addCleanup(tree.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
822
        tree.add(['dir', 'dir/file'], [b'dir-id', b'file-id'])
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
823
        first_revision_id = tree.commit('init')
824
825
        root_id = tree.path2id('')
826
        state = tree.current_dirstate()
827
        state._read_dirblocks_if_needed()
828
        self.assertEqual([
7045.1.13 by Jelmer Vernooij
Fix a few more tests.
829
            (b'', [((b'', b'', root_id), [b'd', b'd'])]),
830
            (b'', [((b'', b'dir', b'dir-id'), [b'd', b'd'])]),
831
            (b'dir', [((b'dir', b'file', b'file-id'), [b'f', b'f'])]),
7143.15.2 by Jelmer Vernooij
Run autopep8.
832
        ], self.get_simple_dirblocks(state))
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
833
834
        tree.remove(['dir/file'])
835
        self.assertEqual([
7045.1.13 by Jelmer Vernooij
Fix a few more tests.
836
            (b'', [((b'', b'', root_id), [b'd', b'd'])]),
837
            (b'', [((b'', b'dir', b'dir-id'), [b'd', b'd'])]),
838
            (b'dir', [((b'dir', b'file', b'file-id'), [b'a', b'f'])]),
7143.15.2 by Jelmer Vernooij
Run autopep8.
839
        ], self.get_simple_dirblocks(state))
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
840
        # Make sure the removal is written to disk
841
        tree.flush()
842
843
        # self.assertRaises(Exception, tree.update_basis_by_delta,
6855.4.1 by Jelmer Vernooij
Yet more bees.
844
        new_dir = inventory.InventoryDirectory(b'dir-id', 'new-dir', root_id)
845
        new_dir.revision = b'new-revision-id'
846
        new_file = inventory.InventoryFile(b'file-id', 'new-file', root_id)
847
        new_file.revision = b'new-revision-id'
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
848
        self.assertRaises(
849
            errors.InconsistentDelta,
850
            tree.update_basis_by_delta, b'new-revision-id',
851
            [('dir', 'new-dir', b'dir-id', new_dir),
852
             ('dir/file', 'new-dir/new-file', b'file-id', new_file),
7143.16.6 by Jelmer Vernooij
Fix E124.
853
             ])
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
854
        del state
855
856
        # Now when we re-read the file it should not have been modified
857
        tree.unlock()
858
        tree.lock_read()
859
        self.assertEqual(first_revision_id, tree.last_revision())
860
        state = tree.current_dirstate()
861
        state._read_dirblocks_if_needed()
862
        self.assertEqual([
7045.2.13 by Jelmer Vernooij
Fix some workingtree_4 tests.
863
            (b'', [((b'', b'', root_id), [b'd', b'd'])]),
864
            (b'', [((b'', b'dir', b'dir-id'), [b'd', b'd'])]),
865
            (b'dir', [((b'dir', b'file', b'file-id'), [b'a', b'f'])]),
7143.15.2 by Jelmer Vernooij
Run autopep8.
866
        ], self.get_simple_dirblocks(state))
4634.156.1 by Vincent Ladeuil
Don't traceback when unversioning a directory.
867
868
869
class TestInventoryCoherency(TestCaseWithTransport):
870
871
    def test_inventory_is_synced_when_unversioning_a_dir(self):
872
        """Unversioning the root of a subtree unversions the entire subtree."""
873
        tree = self.make_branch_and_tree('.')
874
        self.build_tree(['a/', 'a/b', 'c/'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
875
        tree.add(['a', 'a/b', 'c'], [b'a-id', b'b-id', b'c-id'])
4634.156.1 by Vincent Ladeuil
Don't traceback when unversioning a directory.
876
        # within a lock unversion should take effect
877
        tree.lock_write()
878
        self.addCleanup(tree.unlock)
879
        # Force access to the in memory inventory to trigger bug #494221: try
880
        # maintaining the in-memory inventory
6405.2.10 by Jelmer Vernooij
Fix more tests.
881
        inv = tree.root_inventory
6973.7.5 by Jelmer Vernooij
s/file/open.
882
        self.assertTrue(inv.has_id(b'a-id'))
883
        self.assertTrue(inv.has_id(b'b-id'))
6809.4.25 by Jelmer Vernooij
Add paths argument to .unversion.
884
        tree.unversion(['a', 'a/b'])
6973.7.5 by Jelmer Vernooij
s/file/open.
885
        self.assertFalse(inv.has_id(b'a-id'))
886
        self.assertFalse(inv.has_id(b'b-id'))