/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)
2255.2.166 by Martin Pool
(broken) Add Tree.get_root_id() & test
541
        self.assertNotEqual(tree1.get_root_id(), tree2.get_root_id())
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()
2255.2.166 by Martin Pool
(broken) Add Tree.get_root_id() & test
545
        self.assertEqual(tree3.get_root_id(), tree1.get_root_id())
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():
552
            wt.lock_read()
553
            try:
554
                wt.current_dirstate()._validate()
555
            finally:
556
                wt.unlock()
557
        wt = self.make_workingtree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
558
        wt.set_root_id(b'TREE-ROOTID')
2255.11.2 by Martin Pool
Add more dirstate root-id-changing tests
559
        validate()
560
        wt.commit('somenthing')
561
        validate()
562
        # now switch and commit again
6855.4.1 by Jelmer Vernooij
Yet more bees.
563
        wt.set_root_id(b'tree-rootid')
2255.11.2 by Martin Pool
Add more dirstate root-id-changing tests
564
        validate()
565
        wt.commit('again')
566
        validate()
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
567
1551.15.6 by Aaron Bentley
Use ROOT_ID when the repository supports old clients (Bug #107168)
568
    def test_default_root_id(self):
569
        tree = self.make_branch_and_tree('tag', format='dirstate-tags')
570
        self.assertEqual(inventory.ROOT_ID, tree.get_root_id())
571
        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.
572
                                         format='development-subtree')
1551.15.6 by Aaron Bentley
Use ROOT_ID when the repository supports old clients (Bug #107168)
573
        self.assertNotEqual(inventory.ROOT_ID, tree.get_root_id())
574
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
575
    def test_non_subtree_with_nested_trees(self):
576
        # 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.
577
        # dirstate, as opposed to development-subtree, should
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
578
        # behave the same way.
579
        tree = self.make_branch_and_tree('.', format='dirstate')
580
        self.assertFalse(tree.supports_tree_reference())
581
        self.build_tree(['dir/'])
582
        # for testing easily.
6855.4.1 by Jelmer Vernooij
Yet more bees.
583
        tree.set_root_id(b'root')
584
        tree.add(['dir'], [b'dir-id'])
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
585
        self.make_branch_and_tree('dir')
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
586
        # the most primitive operation: kind
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
587
        self.assertEqual('directory', tree.kind('dir'))
4570.2.8 by Robert Collins
Adjust WorkingTree4 specific test to deal with iter_changes reporting required directories.
588
        # a diff against the basis should give us a directory and the root (as
589
        # the root is new too).
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
590
        tree.lock_read()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
591
        expected = [(b'dir-id',
7143.15.2 by Jelmer Vernooij
Run autopep8.
592
                     (None, u'dir'),
593
                     True,
594
                     (False, True),
595
                     (None, b'root'),
596
                     (None, u'dir'),
597
                     (None, 'directory'),
598
                     (None, False)),
599
                    (b'root', (None, u''), True, (False, True), (None, None),
600
                     (None, u''), (None, 'directory'), (None, 0))]
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
601
        self.assertEqual(
602
            expected,
603
            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.
604
        tree.unlock()
605
        # do a commit, we want to trigger the dirstate fast-path too
606
        tree.commit('first post')
607
        # change the path for the subdir, which will trigger getting all
608
        # its data:
609
        os.rename('dir', 'also-dir')
610
        # now the diff will use the fast path
611
        tree.lock_read()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
612
        expected = [(b'dir-id',
7143.15.2 by Jelmer Vernooij
Run autopep8.
613
                     (u'dir', u'dir'),
614
                     True,
615
                     (True, True),
616
                     (b'root', b'root'),
617
                     ('dir', 'dir'),
618
                     ('directory', None),
619
                     (False, False))]
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
620
        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.
621
        tree.unlock()
622
623
    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.
624
        # development-subtree should support tree-references.
625
        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.
626
        self.assertTrue(tree.supports_tree_reference())
627
        # having checked this is on, the tree interface, and intertree
628
        # interface tests, will proceed to test the subtree support of
629
        # workingtree_4.
2466.4.1 by John Arbash Meinel
Add a (failing) test that exposes how _iter_changes is accidentally walking into unversioned directories.
630
631
    def test_iter_changes_ignores_unversioned_dirs(self):
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
632
        """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.
633
        tree = self.make_branch_and_tree('.', format='dirstate')
634
        # We have an unversioned directory at the root, a versioned one with
635
        # other versioned files and an unversioned directory, and another
636
        # versioned dir with nothing but an unversioned directory.
637
        self.build_tree(['unversioned/',
638
                         'unversioned/a',
639
                         'unversioned/b/',
640
                         'versioned/',
641
                         'versioned/unversioned/',
642
                         'versioned/unversioned/a',
643
                         'versioned/unversioned/b/',
644
                         'versioned2/',
645
                         'versioned2/a',
646
                         'versioned2/unversioned/',
647
                         'versioned2/unversioned/a',
648
                         'versioned2/unversioned/b/',
7143.15.2 by Jelmer Vernooij
Run autopep8.
649
                         ])
2466.4.1 by John Arbash Meinel
Add a (failing) test that exposes how _iter_changes is accidentally walking into unversioned directories.
650
        tree.add(['versioned', 'versioned2', 'versioned2/a'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
651
        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.
652
        # Trap osutils._walkdirs_utf8 to spy on what dirs have been accessed.
653
        returned = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
654
2466.4.1 by John Arbash Meinel
Add a (failing) test that exposes how _iter_changes is accidentally walking into unversioned directories.
655
        def walkdirs_spy(*args, **kwargs):
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
656
            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.
657
                returned.append(val[0][0])
658
                yield val
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
659
        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.
660
661
        basis = tree.basis_tree()
662
        tree.lock_read()
663
        self.addCleanup(tree.unlock)
664
        basis.lock_read()
665
        self.addCleanup(basis.unlock)
2466.4.2 by John Arbash Meinel
Clean up the (failing) test so that the last thing
666
        changes = [c[1] for c in
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
667
                   tree.iter_changes(basis, want_unversioned=True)]
2466.4.2 by John Arbash Meinel
Clean up the (failing) test so that the last thing
668
        self.assertEqual([(None, 'unversioned'),
669
                          (None, 'versioned/unversioned'),
670
                          (None, 'versioned2/unversioned'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
671
                          ], changes)
7045.2.13 by Jelmer Vernooij
Fix some workingtree_4 tests.
672
        self.assertEqual([b'', b'versioned', b'versioned2'], returned)
7143.15.2 by Jelmer Vernooij
Run autopep8.
673
        del returned[:]  # reset
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
674
        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
675
        self.assertEqual([], changes)
7045.2.13 by Jelmer Vernooij
Fix some workingtree_4 tests.
676
        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.
677
4496.2.1 by Ian Clatworthy
(igc) Improve paths are not versioned reporting (Benoît PIERRE)
678
    def test_iter_changes_unversioned_error(self):
679
        """ Check if a PathsNotVersionedError is correctly raised and the
680
            paths list contains all unversioned entries only.
681
        """
682
        tree = self.make_branch_and_tree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
683
        self.build_tree_contents([('tree/bar', b'')])
684
        tree.add(['bar'], [b'bar-id'])
4496.2.1 by Ian Clatworthy
(igc) Improve paths are not versioned reporting (Benoît PIERRE)
685
        tree.lock_read()
686
        self.addCleanup(tree.unlock)
7143.15.2 by Jelmer Vernooij
Run autopep8.
687
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
688
        def tree_iter_changes(files):
689
            return [
690
                c for c in tree.iter_changes(
691
                    tree.basis_tree(), specific_files=files,
692
                    require_versioned=True)]
4496.2.1 by Ian Clatworthy
(igc) Improve paths are not versioned reporting (Benoît PIERRE)
693
        e = self.assertRaises(errors.PathsNotVersionedError,
694
                              tree_iter_changes, ['bar', 'foo'])
695
        self.assertEqual(e.paths, ['foo'])
696
6345.1.2 by Martin Packman
Add targetted working tree tests for places that raise PathsNotVersionedError
697
    def test_iter_changes_unversioned_non_ascii(self):
698
        """Unversioned non-ascii paths should be reported as unicode"""
699
        self.requireFeature(features.UnicodeFilenameFeature)
700
        tree = self.make_branch_and_tree('.')
6855.4.1 by Jelmer Vernooij
Yet more bees.
701
        self.build_tree_contents([('f', b'')])
702
        tree.add(['f'], [b'f-id'])
7143.15.2 by Jelmer Vernooij
Run autopep8.
703
6345.1.2 by Martin Packman
Add targetted working tree tests for places that raise PathsNotVersionedError
704
        def tree_iter_changes(tree, files):
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
705
            return list(tree.iter_changes(
706
                tree.basis_tree(), specific_files=files,
707
                require_versioned=True))
6345.1.2 by Martin Packman
Add targetted working tree tests for places that raise PathsNotVersionedError
708
        tree.lock_read()
709
        self.addCleanup(tree.unlock)
710
        e = self.assertRaises(errors.PathsNotVersionedError,
7143.15.2 by Jelmer Vernooij
Run autopep8.
711
                              tree_iter_changes, tree, [u'\xa7', u'\u03c0'])
6973.10.6 by Jelmer Vernooij
Fix tests.
712
        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
713
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
714
    def get_tree_with_cachable_file_foo(self):
715
        tree = self.make_branch_and_tree('.')
5755.1.1 by John Arbash Meinel
Change WT._observed_sha1 to also update st.st_size.
716
        tree.lock_write()
717
        self.addCleanup(tree.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
718
        self.build_tree_contents([('foo', b'a bit of content for foo\n')])
719
        tree.add(['foo'], [b'foo-id'])
5755.1.1 by John Arbash Meinel
Change WT._observed_sha1 to also update st.st_size.
720
        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.
721
        return tree
722
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
723
    def test_commit_updates_hash_cache(self):
724
        tree = self.get_tree_with_cachable_file_foo()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
725
        tree.commit('a commit')
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
726
        # tree's dirstate should now have a valid stat entry for foo.
727
        entry = tree._get_entry(path='foo')
728
        expected_sha1 = osutils.sha_file_by_name('foo')
729
        self.assertEqual(expected_sha1, entry[1][0][1])
5755.1.2 by John Arbash Meinel
use soft constants rather than '25'
730
        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.
731
732
    def test_observed_sha1_cachable(self):
733
        tree = self.get_tree_with_cachable_file_foo()
734
        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.
735
        statvalue = os.lstat("foo")
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
736
        tree._observed_sha1("foo", (expected_sha1, statvalue))
5755.1.1 by John Arbash Meinel
Change WT._observed_sha1 to also update st.st_size.
737
        entry = tree._get_entry(path="foo")
738
        entry_state = entry[1][0]
739
        self.assertEqual(expected_sha1, entry_state[1])
5755.1.2 by John Arbash Meinel
use soft constants rather than '25'
740
        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.
741
        tree.unlock()
742
        tree.lock_read()
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
743
        tree = tree.controldir.open_workingtree()
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
744
        tree.lock_read()
3207.2.1 by jameinel
Add a test that _iter_changes raises a clearer error when we encounter an invalid rename.
745
        self.addCleanup(tree.unlock)
5755.1.1 by John Arbash Meinel
Change WT._observed_sha1 to also update st.st_size.
746
        entry = tree._get_entry(path="foo")
747
        entry_state = entry[1][0]
748
        self.assertEqual(expected_sha1, entry_state[1])
5755.1.2 by John Arbash Meinel
use soft constants rather than '25'
749
        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.
750
751
    def test_observed_sha1_new_file(self):
752
        tree = self.make_branch_and_tree('.')
753
        self.build_tree(['foo'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
754
        tree.add(['foo'], [b'foo-id'])
6969.3.2 by Jelmer Vernooij
Use context managers for locking.
755
        with tree.lock_read():
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
756
            current_sha1 = tree._get_entry(path="foo")[1][0][1]
6969.3.2 by Jelmer Vernooij
Use context managers for locking.
757
        with tree.lock_write():
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
758
            tree._observed_sha1(
7143.15.15 by Jelmer Vernooij
Merge trunk.
759
                "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.
760
            # Must not have changed
761
            self.assertEqual(current_sha1,
7143.15.2 by Jelmer Vernooij
Run autopep8.
762
                             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.
763
764
    def test_get_file_with_stat_id_only(self):
765
        # Explicit test to ensure we get a lstat value from WT4 trees.
766
        tree = self.make_branch_and_tree('.')
767
        self.build_tree(['foo'])
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
768
        tree.add(['foo'])
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
769
        tree.lock_read()
770
        self.addCleanup(tree.unlock)
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
771
        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.
772
        expected = os.lstat('foo')
4807.2.2 by John Arbash Meinel
Move all the stat comparison and platform checkning code to assertEqualStat.
773
        self.assertEqualStat(expected, statvalue)
7045.1.1 by Jelmer Vernooij
Fix another 300 tests.
774
        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.
775
776
777
class TestCorruptDirstate(TestCaseWithTransport):
778
    """Tests for how we handle when the dirstate has been corrupted."""
779
780
    def create_wt4(self):
781
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
782
        control.create_repository()
783
        control.create_branch()
784
        tree = workingtree_4.WorkingTreeFormat4().initialize(control)
785
        return tree
786
787
    def test_invalid_rename(self):
788
        tree = self.create_wt4()
789
        # Create a corrupted dirstate
6969.3.2 by Jelmer Vernooij
Use context managers for locking.
790
        with tree.lock_write():
4285.2.1 by Vincent Ladeuil
Cleanup test imports and use features to better track skipped tests.
791
            # We need a parent, or we always compare with NULL
792
            tree.commit('init')
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
793
            state = tree.current_dirstate()
794
            state._read_dirblocks_if_needed()
795
            # Now add in an invalid entry, a rename with a dangling pointer
7045.2.13 by Jelmer Vernooij
Fix some workingtree_4 tests.
796
            state._dirblocks[1][1].append(((b'', b'foo', b'foo-id'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
797
                                           [(b'f', b'', 0, False, b''),
798
                                            (b'r', b'bar', 0, False, b'')]))
6744 by Jelmer Vernooij
Merge lp:~jelmer/brz/move-errors-knit.
799
            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.
800
                                  tree.iter_changes, tree.basis_tree())
801
802
    def get_simple_dirblocks(self, state):
803
        """Extract the simple information from the DirState.
804
805
        This returns the dirblocks, only with the sha1sum and stat details
806
        filtered out.
807
        """
808
        simple_blocks = []
809
        for block in state._dirblocks:
810
            simple_block = (block[0], [])
811
            for entry in block[1]:
812
                # Include the key for each entry, and for each parent include
813
                # just the minikind, so we know if it was
814
                # present/absent/renamed/etc
815
                simple_block[1].append((entry[0], [i[0] for i in entry[1]]))
816
            simple_blocks.append(simple_block)
817
        return simple_blocks
818
819
    def test_update_basis_with_invalid_delta(self):
820
        """When given an invalid delta, it should abort, and not be saved."""
821
        self.build_tree(['dir/', 'dir/file'])
822
        tree = self.create_wt4()
823
        tree.lock_write()
824
        self.addCleanup(tree.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
825
        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.
826
        first_revision_id = tree.commit('init')
827
828
        root_id = tree.path2id('')
829
        state = tree.current_dirstate()
830
        state._read_dirblocks_if_needed()
831
        self.assertEqual([
7045.1.13 by Jelmer Vernooij
Fix a few more tests.
832
            (b'', [((b'', b'', root_id), [b'd', b'd'])]),
833
            (b'', [((b'', b'dir', b'dir-id'), [b'd', b'd'])]),
834
            (b'dir', [((b'dir', b'file', b'file-id'), [b'f', b'f'])]),
7143.15.2 by Jelmer Vernooij
Run autopep8.
835
        ], 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.
836
837
        tree.remove(['dir/file'])
838
        self.assertEqual([
7045.1.13 by Jelmer Vernooij
Fix a few more tests.
839
            (b'', [((b'', b'', root_id), [b'd', b'd'])]),
840
            (b'', [((b'', b'dir', b'dir-id'), [b'd', b'd'])]),
841
            (b'dir', [((b'dir', b'file', b'file-id'), [b'a', b'f'])]),
7143.15.2 by Jelmer Vernooij
Run autopep8.
842
        ], 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.
843
        # Make sure the removal is written to disk
844
        tree.flush()
845
846
        # self.assertRaises(Exception, tree.update_basis_by_delta,
6855.4.1 by Jelmer Vernooij
Yet more bees.
847
        new_dir = inventory.InventoryDirectory(b'dir-id', 'new-dir', root_id)
848
        new_dir.revision = b'new-revision-id'
849
        new_file = inventory.InventoryFile(b'file-id', 'new-file', root_id)
850
        new_file.revision = b'new-revision-id'
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
851
        self.assertRaises(
852
            errors.InconsistentDelta,
853
            tree.update_basis_by_delta, b'new-revision-id',
854
            [('dir', 'new-dir', b'dir-id', new_dir),
855
             ('dir/file', 'new-dir/new-file', b'file-id', new_file),
7143.16.6 by Jelmer Vernooij
Fix E124.
856
             ])
3709.3.2 by Robert Collins
Race-free stat-fingerprint updating during commit via a new method get_file_with_stat.
857
        del state
858
859
        # Now when we re-read the file it should not have been modified
860
        tree.unlock()
861
        tree.lock_read()
862
        self.assertEqual(first_revision_id, tree.last_revision())
863
        state = tree.current_dirstate()
864
        state._read_dirblocks_if_needed()
865
        self.assertEqual([
7045.2.13 by Jelmer Vernooij
Fix some workingtree_4 tests.
866
            (b'', [((b'', b'', root_id), [b'd', b'd'])]),
867
            (b'', [((b'', b'dir', b'dir-id'), [b'd', b'd'])]),
868
            (b'dir', [((b'dir', b'file', b'file-id'), [b'a', b'f'])]),
7143.15.2 by Jelmer Vernooij
Run autopep8.
869
        ], self.get_simple_dirblocks(state))
4634.156.1 by Vincent Ladeuil
Don't traceback when unversioning a directory.
870
871
872
class TestInventoryCoherency(TestCaseWithTransport):
873
874
    def test_inventory_is_synced_when_unversioning_a_dir(self):
875
        """Unversioning the root of a subtree unversions the entire subtree."""
876
        tree = self.make_branch_and_tree('.')
877
        self.build_tree(['a/', 'a/b', 'c/'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
878
        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.
879
        # within a lock unversion should take effect
880
        tree.lock_write()
881
        self.addCleanup(tree.unlock)
882
        # Force access to the in memory inventory to trigger bug #494221: try
883
        # maintaining the in-memory inventory
6405.2.10 by Jelmer Vernooij
Fix more tests.
884
        inv = tree.root_inventory
6973.7.5 by Jelmer Vernooij
s/file/open.
885
        self.assertTrue(inv.has_id(b'a-id'))
886
        self.assertTrue(inv.has_id(b'b-id'))
6809.4.25 by Jelmer Vernooij
Add paths argument to .unversion.
887
        tree.unversion(['a', 'a/b'])
6973.7.5 by Jelmer Vernooij
s/file/open.
888
        self.assertFalse(inv.has_id(b'a-id'))
889
        self.assertFalse(inv.has_id(b'b-id'))