~bzr-pqm/bzr/bzr.dev

4634.123.9 by John Arbash Meinel
Fix a bug in the dirstate logic for 'set_path_id'.
1
# Copyright (C) 2006-2010 Canonical Ltd
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
16
17
"""Tests of the dirstate functionality being built for WorkingTreeFormat4."""
18
2255.8.2 by John Arbash Meinel
Add a helper function, which allows us to store keys as plain paths,
19
import bisect
1852.13.20 by Robert Collins
Steps toward an object model.
20
import os
21
2255.2.125 by John Arbash Meinel
Initial effort at adding a basic _bisect function to DirState.
22
from bzrlib import (
23
    dirstate,
24
    errors,
3477.2.1 by John Arbash Meinel
Assert that we properly encode inv_entry.symlink_target, (bug #135320)
25
    inventory,
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
26
    memorytree,
2255.2.125 by John Arbash Meinel
Initial effort at adding a basic _bisect function to DirState.
27
    osutils,
3668.5.1 by Jelmer Vernooij
Use NULL_REVISION rather than None for Repository.revision_tree().
28
    revision as _mod_revision,
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
29
    tests,
2255.2.125 by John Arbash Meinel
Initial effort at adding a basic _bisect function to DirState.
30
    )
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
31
from bzrlib.tests import test_osutils
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
32
33
34
# TODO:
2255.2.4 by Robert Collins
Snapshot dirstate development
35
# TESTS to write:
2255.2.15 by Robert Collins
Dirstate - truncate state file fixing bug in saving a smaller file, get more tree_implementation tests passing.
36
# general checks for NOT_IN_MEMORY error conditions.
37
# set_path_id on a NOT_IN_MEMORY dirstate
2255.2.4 by Robert Collins
Snapshot dirstate development
38
# set_path_id  unicode support
39
# set_path_id  setting id of a path not root
40
# set_path_id  setting id when there are parents without the id in the parents
41
# set_path_id  setting id when there are parents with the id in the parents
42
# set_path_id  setting id when state is not in memory
43
# set_path_id  setting id when state is in memory unmodified
44
# set_path_id  setting id when state is in memory modified
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
45
2255.2.236 by Martin Pool
Review cleanups: mostly updating or removing todo comments.
46
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
47
def load_tests(basic_tests, module, loader):
48
    suite = loader.suiteClass()
49
    dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
50
        basic_tests, tests.condition_isinstance(TestCaseWithDirState))
51
    tests.multiply_tests(dir_reader_tests,
52
                         test_osutils.dir_reader_scenarios(), suite)
53
    suite.addTest(remaining_tests)
54
    return suite
55
56
57
class TestCaseWithDirState(tests.TestCaseWithTransport):
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
58
    """Helper functions for creating DirState objects with various content."""
59
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
60
    # Set by load_tests
61
    _dir_reader_class = None
62
    _native_to_unicode = None # Not used yet
63
64
    def setUp(self):
65
        tests.TestCaseWithTransport.setUp(self)
66
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
67
        self.overrideAttr(osutils,
68
                          '_selected_dir_reader', self._dir_reader_class())
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
69
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
70
    def create_empty_dirstate(self):
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
71
        """Return a locked but empty dirstate"""
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
72
        state = dirstate.DirState.initialize('dirstate')
73
        return state
74
75
    def create_dirstate_with_root(self):
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
76
        """Return a write-locked state with a single root entry."""
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
77
        packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
78
        root_entry_direntry = ('', '', 'a-root-value'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
79
            ('d', '', 0, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
80
            ]
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
81
        dirblocks = []
82
        dirblocks.append(('', [root_entry_direntry]))
83
        dirblocks.append(('', []))
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
84
        state = self.create_empty_dirstate()
85
        try:
86
            state._set_data([], dirblocks)
2255.7.78 by Martin Pool
Add DirState._validate and call from the tests
87
            state._validate()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
88
        except:
89
            state.unlock()
90
            raise
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
91
        return state
92
93
    def create_dirstate_with_root_and_subdir(self):
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
94
        """Return a locked DirState with a root and a subdir"""
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
95
        packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
96
        subdir_entry = ('', 'subdir', 'subdir-id'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
97
            ('d', '', 0, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
98
            ]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
99
        state = self.create_dirstate_with_root()
100
        try:
101
            dirblocks = list(state._dirblocks)
102
            dirblocks[1][1].append(subdir_entry)
103
            state._set_data([], dirblocks)
104
        except:
105
            state.unlock()
106
            raise
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
107
        return state
108
109
    def create_complex_dirstate(self):
110
        """This dirstate contains multiple files and directories.
111
112
         /        a-root-value
113
         a/       a-dir
114
         b/       b-dir
115
         c        c-file
116
         d        d-file
117
         a/e/     e-dir
118
         a/f      f-file
119
         b/g      g-file
120
         b/h\xc3\xa5  h-\xc3\xa5-file  #This is u'\xe5' encoded into utf-8
121
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
122
        Notice that a/e is an empty directory.
123
124
        :return: The dirstate, still write-locked.
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
125
        """
126
        packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
127
        null_sha = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
128
        root_entry = ('', '', 'a-root-value'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
129
            ('d', '', 0, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
130
            ]
131
        a_entry = ('', 'a', 'a-dir'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
132
            ('d', '', 0, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
133
            ]
134
        b_entry = ('', 'b', 'b-dir'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
135
            ('d', '', 0, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
136
            ]
137
        c_entry = ('', 'c', 'c-file'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
138
            ('f', null_sha, 10, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
139
            ]
140
        d_entry = ('', 'd', 'd-file'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
141
            ('f', null_sha, 20, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
142
            ]
143
        e_entry = ('a', 'e', 'e-dir'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
144
            ('d', '', 0, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
145
            ]
146
        f_entry = ('a', 'f', 'f-file'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
147
            ('f', null_sha, 30, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
148
            ]
149
        g_entry = ('b', 'g', 'g-file'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
150
            ('f', null_sha, 30, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
151
            ]
152
        h_entry = ('b', 'h\xc3\xa5', 'h-\xc3\xa5-file'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
153
            ('f', null_sha, 40, False, packed_stat),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
154
            ]
155
        dirblocks = []
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
156
        dirblocks.append(('', [root_entry]))
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
157
        dirblocks.append(('', [a_entry, b_entry, c_entry, d_entry]))
158
        dirblocks.append(('a', [e_entry, f_entry]))
159
        dirblocks.append(('b', [g_entry, h_entry]))
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
160
        state = dirstate.DirState.initialize('dirstate')
2255.7.78 by Martin Pool
Add DirState._validate and call from the tests
161
        state._validate()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
162
        try:
163
            state._set_data([], dirblocks)
164
        except:
165
            state.unlock()
166
            raise
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
167
        return state
168
169
    def check_state_with_reopen(self, expected_result, state):
170
        """Check that state has current state expected_result.
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
171
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
172
        This will check the current state, open the file anew and check it
173
        again.
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
174
        This function expects the current state to be locked for writing, and
175
        will unlock it before re-opening.
176
        This is required because we can't open a lock_read() while something
177
        else has a lock_write().
178
            write => mutually exclusive lock
179
            read => shared lock
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
180
        """
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
181
        # The state should already be write locked, since we just had to do
182
        # some operation to get here.
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
183
        self.assertTrue(state._lock_token is not None)
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
184
        try:
185
            self.assertEqual(expected_result[0],  state.get_parent_ids())
186
            # there should be no ghosts in this tree.
187
            self.assertEqual([], state.get_ghosts())
188
            # there should be one fileid in this tree - the root of the tree.
189
            self.assertEqual(expected_result[1], list(state._iter_entries()))
190
            state.save()
191
        finally:
192
            state.unlock()
2425.3.1 by John Arbash Meinel
Change the DirState.test_initialize test so that we don't try to read a locked file.
193
        del state
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
194
        state = dirstate.DirState.on_file('dirstate')
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
195
        state.lock_read()
196
        try:
197
            self.assertEqual(expected_result[1], list(state._iter_entries()))
198
        finally:
199
            state.unlock()
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
200
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
201
    def create_basic_dirstate(self):
202
        """Create a dirstate with a few files and directories.
203
204
            a
205
            b/
206
              c
207
              d/
208
                e
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
209
            b-c
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
210
            f
211
        """
212
        tree = self.make_branch_and_tree('tree')
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
213
        paths = ['a', 'b/', 'b/c', 'b/d/', 'b/d/e', 'b-c', 'f']
214
        file_ids = ['a-id', 'b-id', 'c-id', 'd-id', 'e-id', 'b-c-id', 'f-id']
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
215
        self.build_tree(['tree/' + p for p in paths])
216
        tree.set_root_id('TREE_ROOT')
217
        tree.add([p.rstrip('/') for p in paths], file_ids)
218
        tree.commit('initial', rev_id='rev-1')
219
        revision_id = 'rev-1'
220
        # a_packed_stat = dirstate.pack_stat(os.stat('tree/a'))
2520.3.1 by Vincent Ladeuil
Fix 110448 by adding a relpath parameter to get_transport.
221
        t = self.get_transport('tree')
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
222
        a_text = t.get_bytes('a')
223
        a_sha = osutils.sha_string(a_text)
224
        a_len = len(a_text)
225
        # b_packed_stat = dirstate.pack_stat(os.stat('tree/b'))
226
        # c_packed_stat = dirstate.pack_stat(os.stat('tree/b/c'))
227
        c_text = t.get_bytes('b/c')
228
        c_sha = osutils.sha_string(c_text)
229
        c_len = len(c_text)
230
        # d_packed_stat = dirstate.pack_stat(os.stat('tree/b/d'))
231
        # e_packed_stat = dirstate.pack_stat(os.stat('tree/b/d/e'))
232
        e_text = t.get_bytes('b/d/e')
233
        e_sha = osutils.sha_string(e_text)
234
        e_len = len(e_text)
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
235
        b_c_text = t.get_bytes('b-c')
236
        b_c_sha = osutils.sha_string(b_c_text)
237
        b_c_len = len(b_c_text)
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
238
        # f_packed_stat = dirstate.pack_stat(os.stat('tree/f'))
239
        f_text = t.get_bytes('f')
240
        f_sha = osutils.sha_string(f_text)
241
        f_len = len(f_text)
242
        null_stat = dirstate.DirState.NULLSTAT
243
        expected = {
244
            '':(('', '', 'TREE_ROOT'), [
245
                  ('d', '', 0, False, null_stat),
246
                  ('d', '', 0, False, revision_id),
247
                ]),
248
            'a':(('', 'a', 'a-id'), [
249
                   ('f', '', 0, False, null_stat),
250
                   ('f', a_sha, a_len, False, revision_id),
251
                 ]),
252
            'b':(('', 'b', 'b-id'), [
253
                  ('d', '', 0, False, null_stat),
254
                  ('d', '', 0, False, revision_id),
255
                 ]),
256
            'b/c':(('b', 'c', 'c-id'), [
257
                    ('f', '', 0, False, null_stat),
258
                    ('f', c_sha, c_len, False, revision_id),
259
                   ]),
260
            'b/d':(('b', 'd', 'd-id'), [
261
                    ('d', '', 0, False, null_stat),
262
                    ('d', '', 0, False, revision_id),
263
                   ]),
264
            'b/d/e':(('b/d', 'e', 'e-id'), [
265
                      ('f', '', 0, False, null_stat),
266
                      ('f', e_sha, e_len, False, revision_id),
267
                     ]),
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
268
            'b-c':(('', 'b-c', 'b-c-id'), [
269
                      ('f', '', 0, False, null_stat),
270
                      ('f', b_c_sha, b_c_len, False, revision_id),
271
                     ]),
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
272
            'f':(('', 'f', 'f-id'), [
273
                  ('f', '', 0, False, null_stat),
274
                  ('f', f_sha, f_len, False, revision_id),
275
                 ]),
276
        }
277
        state = dirstate.DirState.from_tree(tree, 'dirstate')
278
        try:
279
            state.save()
280
        finally:
281
            state.unlock()
282
        # Use a different object, to make sure nothing is pre-cached in memory.
283
        state = dirstate.DirState.on_file('dirstate')
284
        state.lock_read()
285
        self.addCleanup(state.unlock)
286
        self.assertEqual(dirstate.DirState.NOT_IN_MEMORY,
287
                         state._dirblock_state)
288
        # This is code is only really tested if we actually have to make more
289
        # than one read, so set the page size to something smaller.
290
        # We want it to contain about 2.2 records, so that we have a couple
291
        # records that we can read per attempt
292
        state._bisect_page_size = 200
293
        return tree, state, expected
294
295
    def create_duplicated_dirstate(self):
296
        """Create a dirstate with a deleted and added entries.
297
298
        This grabs a basic_dirstate, and then removes and re adds every entry
299
        with a new file id.
300
        """
301
        tree, state, expected = self.create_basic_dirstate()
302
        # Now we will just remove and add every file so we get an extra entry
303
        # per entry. Unversion in reverse order so we handle subdirs
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
304
        tree.unversion(['f-id', 'b-c-id', 'e-id', 'd-id', 'c-id', 'b-id', 'a-id'])
305
        tree.add(['a', 'b', 'b/c', 'b/d', 'b/d/e', 'b-c', 'f'],
306
                 ['a-id2', 'b-id2', 'c-id2', 'd-id2', 'e-id2', 'b-c-id2', 'f-id2'])
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
307
308
        # Update the expected dictionary.
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
309
        for path in ['a', 'b', 'b/c', 'b/d', 'b/d/e', 'b-c', 'f']:
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
310
            orig = expected[path]
311
            path2 = path + '2'
312
            # This record was deleted in the current tree
313
            expected[path] = (orig[0], [dirstate.DirState.NULL_PARENT_DETAILS,
314
                                        orig[1][1]])
315
            new_key = (orig[0][0], orig[0][1], orig[0][2]+'2')
316
            # And didn't exist in the basis tree
317
            expected[path2] = (new_key, [orig[1][0],
318
                                         dirstate.DirState.NULL_PARENT_DETAILS])
319
320
        # We will replace the 'dirstate' file underneath 'state', but that is
321
        # okay as lock as we unlock 'state' first.
322
        state.unlock()
323
        try:
324
            new_state = dirstate.DirState.from_tree(tree, 'dirstate')
325
            try:
326
                new_state.save()
327
            finally:
328
                new_state.unlock()
329
        finally:
330
            # But we need to leave state in a read-lock because we already have
331
            # a cleanup scheduled
332
            state.lock_read()
333
        return tree, state, expected
334
335
    def create_renamed_dirstate(self):
336
        """Create a dirstate with a few internal renames.
337
338
        This takes the basic dirstate, and moves the paths around.
339
        """
340
        tree, state, expected = self.create_basic_dirstate()
341
        # Rename a file
342
        tree.rename_one('a', 'b/g')
343
        # And a directory
344
        tree.rename_one('b/d', 'h')
345
346
        old_a = expected['a']
347
        expected['a'] = (old_a[0], [('r', 'b/g', 0, False, ''), old_a[1][1]])
348
        expected['b/g'] = (('b', 'g', 'a-id'), [old_a[1][0],
349
                                                ('r', 'a', 0, False, '')])
350
        old_d = expected['b/d']
351
        expected['b/d'] = (old_d[0], [('r', 'h', 0, False, ''), old_d[1][1]])
352
        expected['h'] = (('', 'h', 'd-id'), [old_d[1][0],
353
                                             ('r', 'b/d', 0, False, '')])
354
355
        old_e = expected['b/d/e']
356
        expected['b/d/e'] = (old_e[0], [('r', 'h/e', 0, False, ''),
357
                             old_e[1][1]])
358
        expected['h/e'] = (('h', 'e', 'e-id'), [old_e[1][0],
359
                                                ('r', 'b/d/e', 0, False, '')])
360
361
        state.unlock()
362
        try:
363
            new_state = dirstate.DirState.from_tree(tree, 'dirstate')
364
            try:
365
                new_state.save()
366
            finally:
367
                new_state.unlock()
368
        finally:
369
            state.lock_read()
370
        return tree, state, expected
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
371
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
372
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
373
class TestTreeToDirState(TestCaseWithDirState):
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
374
375
    def test_empty_to_dirstate(self):
376
        """We should be able to create a dirstate for an empty tree."""
377
        # There are no files on disk and no parents
378
        tree = self.make_branch_and_tree('tree')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
379
        expected_result = ([], [
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
380
            (('', '', tree.get_root_id()), # common details
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
381
             [('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
382
             ])])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
383
        state = dirstate.DirState.from_tree(tree, 'dirstate')
2255.7.78 by Martin Pool
Add DirState._validate and call from the tests
384
        state._validate()
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
385
        self.check_state_with_reopen(expected_result, state)
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
386
387
    def test_1_parents_empty_to_dirstate(self):
388
        # create a parent by doing a commit
389
        tree = self.make_branch_and_tree('tree')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
390
        rev_id = tree.commit('first post').encode('utf8')
391
        root_stat_pack = dirstate.pack_stat(os.stat(tree.basedir))
392
        expected_result = ([rev_id], [
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
393
            (('', '', tree.get_root_id()), # common details
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
394
             [('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
395
              ('d', '', 0, False, rev_id), # first parent details
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
396
             ])])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
397
        state = dirstate.DirState.from_tree(tree, 'dirstate')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
398
        self.check_state_with_reopen(expected_result, state)
2323.6.13 by Martin Pool
Fix some tests that need to lock dirstate before validating
399
        state.lock_read()
400
        try:
401
            state._validate()
402
        finally:
403
            state.unlock()
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
404
405
    def test_2_parents_empty_to_dirstate(self):
406
        # create a parent by doing a commit
407
        tree = self.make_branch_and_tree('tree')
408
        rev_id = tree.commit('first post')
409
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
1852.13.24 by Robert Collins
Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.
410
        rev_id2 = tree2.commit('second post', allow_pointless=True)
1852.13.19 by Robert Collins
Get DirState objects roundtripping an add of a ghost tree.
411
        tree.merge_from_branch(tree2.branch)
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
412
        expected_result = ([rev_id, rev_id2], [
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
413
            (('', '', tree.get_root_id()), # common details
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
414
             [('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
415
              ('d', '', 0, False, rev_id), # first parent details
4599.4.24 by Robert Collins
Prepare dirstate tests for 2a as default.
416
              ('d', '', 0, False, rev_id), # second parent details
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
417
             ])])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
418
        state = dirstate.DirState.from_tree(tree, 'dirstate')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
419
        self.check_state_with_reopen(expected_result, state)
2323.6.13 by Martin Pool
Fix some tests that need to lock dirstate before validating
420
        state.lock_read()
421
        try:
422
            state._validate()
423
        finally:
424
            state.unlock()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
425
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
426
    def test_empty_unknowns_are_ignored_to_dirstate(self):
427
        """We should be able to create a dirstate for an empty tree."""
428
        # There are no files on disk and no parents
429
        tree = self.make_branch_and_tree('tree')
1852.13.10 by Robert Collins
Use just the tree api to generate dirstate information.
430
        self.build_tree(['tree/unknown'])
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
431
        expected_result = ([], [
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
432
            (('', '', tree.get_root_id()), # common details
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
433
             [('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
434
             ])])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
435
        state = dirstate.DirState.from_tree(tree, 'dirstate')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
436
        self.check_state_with_reopen(expected_result, state)
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
437
1852.13.12 by Robert Collins
get actual parent info for the first parent.
438
    def get_tree_with_a_file(self):
439
        tree = self.make_branch_and_tree('tree')
440
        self.build_tree(['tree/a file'])
3010.1.2 by Robert Collins
Use valid file-ids for dirstate tests.
441
        tree.add('a file', 'a-file-id')
1852.13.12 by Robert Collins
get actual parent info for the first parent.
442
        return tree
443
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
444
    def test_non_empty_no_parents_to_dirstate(self):
445
        """We should be able to create a dirstate for an empty tree."""
1852.13.11 by Robert Collins
Get one content containing test passing.
446
        # There are files on disk and no parents
1852.13.12 by Robert Collins
get actual parent info for the first parent.
447
        tree = self.get_tree_with_a_file()
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
448
        expected_result = ([], [
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
449
            (('', '', tree.get_root_id()), # common details
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
450
             [('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
451
             ]),
3010.1.2 by Robert Collins
Use valid file-ids for dirstate tests.
452
            (('', 'a file', 'a-file-id'), # common
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
453
             [('f', '', 0, False, dirstate.DirState.NULLSTAT), # current
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
454
             ]),
455
            ])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
456
        state = dirstate.DirState.from_tree(tree, 'dirstate')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
457
        self.check_state_with_reopen(expected_result, state)
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
458
459
    def test_1_parents_not_empty_to_dirstate(self):
460
        # create a parent by doing a commit
1852.13.12 by Robert Collins
get actual parent info for the first parent.
461
        tree = self.get_tree_with_a_file()
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
462
        rev_id = tree.commit('first post').encode('utf8')
1852.13.12 by Robert Collins
get actual parent info for the first parent.
463
        # change the current content to be different this will alter stat, sha
464
        # and length:
465
        self.build_tree_contents([('tree/a file', 'new content\n')])
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
466
        expected_result = ([rev_id], [
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
467
            (('', '', tree.get_root_id()), # common details
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
468
             [('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
469
              ('d', '', 0, False, rev_id), # first parent details
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
470
             ]),
3010.1.2 by Robert Collins
Use valid file-ids for dirstate tests.
471
            (('', 'a file', 'a-file-id'), # common
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
472
             [('f', '', 0, False, dirstate.DirState.NULLSTAT), # current
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
473
              ('f', 'c3ed76e4bfd45ff1763ca206055bca8e9fc28aa8', 24, False,
474
               rev_id), # first parent
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
475
             ]),
476
            ])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
477
        state = dirstate.DirState.from_tree(tree, 'dirstate')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
478
        self.check_state_with_reopen(expected_result, state)
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
479
480
    def test_2_parents_not_empty_to_dirstate(self):
481
        # create a parent by doing a commit
1852.13.13 by Robert Collins
2-parent case working.
482
        tree = self.get_tree_with_a_file()
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
483
        rev_id = tree.commit('first post').encode('utf8')
1852.13.6 by Robert Collins
start hooking in the prototype dirstate serialiser.
484
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
1852.13.13 by Robert Collins
2-parent case working.
485
        # change the current content to be different this will alter stat, sha
486
        # and length:
487
        self.build_tree_contents([('tree2/a file', 'merge content\n')])
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
488
        rev_id2 = tree2.commit('second post').encode('utf8')
1852.13.19 by Robert Collins
Get DirState objects roundtripping an add of a ghost tree.
489
        tree.merge_from_branch(tree2.branch)
1852.13.13 by Robert Collins
2-parent case working.
490
        # change the current content to be different this will alter stat, sha
491
        # and length again, giving us three distinct values:
492
        self.build_tree_contents([('tree/a file', 'new content\n')])
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
493
        expected_result = ([rev_id, rev_id2], [
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
494
            (('', '', tree.get_root_id()), # common details
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
495
             [('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
496
              ('d', '', 0, False, rev_id), # first parent details
4599.4.24 by Robert Collins
Prepare dirstate tests for 2a as default.
497
              ('d', '', 0, False, rev_id), # second parent details
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
498
             ]),
3010.1.2 by Robert Collins
Use valid file-ids for dirstate tests.
499
            (('', 'a file', 'a-file-id'), # common
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
500
             [('f', '', 0, False, dirstate.DirState.NULLSTAT), # current
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
501
              ('f', 'c3ed76e4bfd45ff1763ca206055bca8e9fc28aa8', 24, False,
502
               rev_id), # first parent
503
              ('f', '314d796174c9412647c3ce07dfb5d36a94e72958', 14, False,
504
               rev_id2), # second parent
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
505
             ]),
506
            ])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
507
        state = dirstate.DirState.from_tree(tree, 'dirstate')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
508
        self.check_state_with_reopen(expected_result, state)
509
2255.7.94 by Martin Pool
Fix dirstate sorting bug and refine the _validate() assertions:
510
    def test_colliding_fileids(self):
511
        # test insertion of parents creating several entries at the same path.
512
        # we used to have a bug where they could cause the dirstate to break
513
        # its ordering invariants.
514
        # create some trees to test from
515
        parents = []
516
        for i in range(7):
517
            tree = self.make_branch_and_tree('tree%d' % i)
518
            self.build_tree(['tree%d/name' % i,])
519
            tree.add(['name'], ['file-id%d' % i])
520
            revision_id = 'revid-%d' % i
521
            tree.commit('message', rev_id=revision_id)
522
            parents.append((revision_id,
523
                tree.branch.repository.revision_tree(revision_id)))
524
        # now fold these trees into a dirstate
525
        state = dirstate.DirState.initialize('dirstate')
526
        try:
527
            state.set_parent_trees(parents, [])
528
            state._validate()
529
        finally:
530
            state.unlock()
531
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
532
533
class TestDirStateOnFile(TestCaseWithDirState):
1852.13.15 by Robert Collins
Ensure Format4 working trees start with a dirstate.
534
535
    def test_construct_with_path(self):
536
        tree = self.make_branch_and_tree('tree')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
537
        state = dirstate.DirState.from_tree(tree, 'dirstate.from_tree')
1852.13.15 by Robert Collins
Ensure Format4 working trees start with a dirstate.
538
        # we want to be able to get the lines of the dirstate that we will
539
        # write to disk.
540
        lines = state.get_lines()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
541
        state.unlock()
1852.13.15 by Robert Collins
Ensure Format4 working trees start with a dirstate.
542
        self.build_tree_contents([('dirstate', ''.join(lines))])
543
        # get a state object
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
544
        # no parents, default tree content
545
        expected_result = ([], [
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
546
            (('', '', tree.get_root_id()), # common details
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
547
             # current tree details, but new from_tree skips statting, it
548
             # uses set_state_from_inventory, and thus depends on the
549
             # inventory state.
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
550
             [('d', '', 0, False, dirstate.DirState.NULLSTAT),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
551
             ])
552
            ])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
553
        state = dirstate.DirState.on_file('dirstate')
554
        state.lock_write() # check_state_with_reopen will save() and unlock it
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
555
        self.check_state_with_reopen(expected_result, state)
556
557
    def test_can_save_clean_on_file(self):
558
        tree = self.make_branch_and_tree('tree')
559
        state = dirstate.DirState.from_tree(tree, 'dirstate')
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
560
        try:
561
            # doing a save should work here as there have been no changes.
562
            state.save()
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
563
            # TODO: stat it and check it hasn't changed; may require waiting
564
            # for the state accuracy window.
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
565
        finally:
566
            state.unlock()
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
567
2353.4.5 by John Arbash Meinel
Update DirState to use the new 'temporary_write_lock', and add tests that it works.
568
    def test_can_save_in_read_lock(self):
569
        self.build_tree(['a-file'])
570
        state = dirstate.DirState.initialize('dirstate')
571
        try:
572
            # No stat and no sha1 sum.
573
            state.add('a-file', 'a-file-id', 'file', None, '')
574
            state.save()
575
        finally:
576
            state.unlock()
577
578
        # Now open in readonly mode
579
        state = dirstate.DirState.on_file('dirstate')
580
        state.lock_read()
581
        try:
582
            entry = state._get_entry(0, path_utf8='a-file')
3709.4.1 by Robert Collins
Sha files for the stat cache more lazily rather than on first-examination, allowing less overall sha calculations to occur.
583
            # The current size should be 0 (default)
584
            self.assertEqual(0, entry[1][0][2])
2353.4.5 by John Arbash Meinel
Update DirState to use the new 'temporary_write_lock', and add tests that it works.
585
            # We should have a real entry.
586
            self.assertNotEqual((None, None), entry)
2485.3.14 by John Arbash Meinel
Update the code so that symlinks aren't cached at incorrect times
587
            # Make sure everything is old enough
588
            state._sha_cutoff_time()
589
            state._cutoff_time += 10
3709.4.1 by Robert Collins
Sha files for the stat cache more lazily rather than on first-examination, allowing less overall sha calculations to occur.
590
            # Change the file length
591
            self.build_tree_contents([('a-file', 'shorter')])
3696.5.2 by Robert Collins
Integrate less aggressive sha logic with C iter-changes.
592
            sha1sum = dirstate.update_entry(state, entry, 'a-file',
593
                os.lstat('a-file'))
3709.4.1 by Robert Collins
Sha files for the stat cache more lazily rather than on first-examination, allowing less overall sha calculations to occur.
594
            # new file, no cached sha:
595
            self.assertEqual(None, sha1sum)
2353.4.5 by John Arbash Meinel
Update DirState to use the new 'temporary_write_lock', and add tests that it works.
596
597
            # The dirblock has been updated
3709.4.1 by Robert Collins
Sha files for the stat cache more lazily rather than on first-examination, allowing less overall sha calculations to occur.
598
            self.assertEqual(7, entry[1][0][2])
2353.4.5 by John Arbash Meinel
Update DirState to use the new 'temporary_write_lock', and add tests that it works.
599
            self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
600
                             state._dirblock_state)
601
602
            del entry
603
            # Now, since we are the only one holding a lock, we should be able
604
            # to save and have it written to disk
605
            state.save()
606
        finally:
607
            state.unlock()
608
609
        # Re-open the file, and ensure that the state has been updated.
610
        state = dirstate.DirState.on_file('dirstate')
611
        state.lock_read()
612
        try:
613
            entry = state._get_entry(0, path_utf8='a-file')
3709.4.1 by Robert Collins
Sha files for the stat cache more lazily rather than on first-examination, allowing less overall sha calculations to occur.
614
            self.assertEqual(7, entry[1][0][2])
2353.4.5 by John Arbash Meinel
Update DirState to use the new 'temporary_write_lock', and add tests that it works.
615
        finally:
616
            state.unlock()
617
618
    def test_save_fails_quietly_if_locked(self):
619
        """If dirstate is locked, save will fail without complaining."""
620
        self.build_tree(['a-file'])
621
        state = dirstate.DirState.initialize('dirstate')
622
        try:
623
            # No stat and no sha1 sum.
624
            state.add('a-file', 'a-file-id', 'file', None, '')
625
            state.save()
626
        finally:
627
            state.unlock()
628
629
        state = dirstate.DirState.on_file('dirstate')
630
        state.lock_read()
631
        try:
632
            entry = state._get_entry(0, path_utf8='a-file')
3696.5.2 by Robert Collins
Integrate less aggressive sha logic with C iter-changes.
633
            sha1sum = dirstate.update_entry(state, entry, 'a-file',
634
                os.lstat('a-file'))
3709.4.1 by Robert Collins
Sha files for the stat cache more lazily rather than on first-examination, allowing less overall sha calculations to occur.
635
            # No sha - too new
636
            self.assertEqual(None, sha1sum)
2353.4.5 by John Arbash Meinel
Update DirState to use the new 'temporary_write_lock', and add tests that it works.
637
            self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
638
                             state._dirblock_state)
639
640
            # Now, before we try to save, grab another dirstate, and take out a
641
            # read lock.
642
            # TODO: jam 20070315 Ideally this would be locked by another
643
            #       process. To make sure the file is really OS locked.
644
            state2 = dirstate.DirState.on_file('dirstate')
645
            state2.lock_read()
646
            try:
647
                # This won't actually write anything, because it couldn't grab
648
                # a write lock. But it shouldn't raise an error, either.
649
                # TODO: jam 20070315 We should probably distinguish between
650
                #       being dirty because of 'update_entry'. And dirty
651
                #       because of real modification. So that save() *does*
652
                #       raise a real error if it fails when we have real
653
                #       modifications.
654
                state.save()
655
            finally:
656
                state2.unlock()
657
        finally:
658
            state.unlock()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
659
2353.4.5 by John Arbash Meinel
Update DirState to use the new 'temporary_write_lock', and add tests that it works.
660
        # The file on disk should not be modified.
661
        state = dirstate.DirState.on_file('dirstate')
662
        state.lock_read()
663
        try:
664
            entry = state._get_entry(0, path_utf8='a-file')
665
            self.assertEqual('', entry[1][0][1])
666
        finally:
667
            state.unlock()
668
3221.1.7 by Martin Pool
Update and rename test for Dirstate._changes_aborted
669
    def test_save_refuses_if_changes_aborted(self):
3207.2.2 by John Arbash Meinel
Fix bug #187169, when an invalid delta is supplied to update_basis_by_delta
670
        self.build_tree(['a-file', 'a-dir/'])
671
        state = dirstate.DirState.initialize('dirstate')
672
        try:
673
            # No stat and no sha1 sum.
674
            state.add('a-file', 'a-file-id', 'file', None, '')
675
            state.save()
676
        finally:
677
            state.unlock()
678
679
        # The dirstate should include TREE_ROOT and 'a-file' and nothing else
680
        expected_blocks = [
681
            ('', [(('', '', 'TREE_ROOT'),
682
                   [('d', '', 0, False, dirstate.DirState.NULLSTAT)])]),
683
            ('', [(('', 'a-file', 'a-file-id'),
684
                   [('f', '', 0, False, dirstate.DirState.NULLSTAT)])]),
685
        ]
686
687
        state = dirstate.DirState.on_file('dirstate')
688
        state.lock_write()
689
        try:
690
            state._read_dirblocks_if_needed()
691
            self.assertEqual(expected_blocks, state._dirblocks)
692
693
            # Now modify the state, but mark it as inconsistent
694
            state.add('a-dir', 'a-dir-id', 'directory', None, '')
3221.1.7 by Martin Pool
Update and rename test for Dirstate._changes_aborted
695
            state._changes_aborted = True
3207.2.2 by John Arbash Meinel
Fix bug #187169, when an invalid delta is supplied to update_basis_by_delta
696
            state.save()
697
        finally:
698
            state.unlock()
699
700
        state = dirstate.DirState.on_file('dirstate')
701
        state.lock_read()
702
        try:
703
            state._read_dirblocks_if_needed()
704
            self.assertEqual(expected_blocks, state._dirblocks)
705
        finally:
706
            state.unlock()
707
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
708
709
class TestDirStateInitialize(TestCaseWithDirState):
1852.13.15 by Robert Collins
Ensure Format4 working trees start with a dirstate.
710
711
    def test_initialize(self):
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
712
        expected_result = ([], [
713
            (('', '', 'TREE_ROOT'), # common details
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
714
             [('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
715
             ])
716
            ])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
717
        state = dirstate.DirState.initialize('dirstate')
718
        try:
719
            self.assertIsInstance(state, dirstate.DirState)
720
            lines = state.get_lines()
2425.3.1 by John Arbash Meinel
Change the DirState.test_initialize test so that we don't try to read a locked file.
721
        finally:
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
722
            state.unlock()
2425.3.1 by John Arbash Meinel
Change the DirState.test_initialize test so that we don't try to read a locked file.
723
        # On win32 you can't read from a locked file, even within the same
724
        # process. So we have to unlock and release before we check the file
725
        # contents.
726
        self.assertFileEqual(''.join(lines), 'dirstate')
727
        state.lock_read() # check_state_with_reopen will unlock
728
        self.check_state_with_reopen(expected_result, state)
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
729
730
731
class TestDirStateManipulations(TestCaseWithDirState):
1852.13.19 by Robert Collins
Get DirState objects roundtripping an add of a ghost tree.
732
2255.2.16 by Robert Collins
Implement WorkingTreeFormat4._write_inventory for better compatability with existing code, letting more test_test_trees pass, now up to test_tree_with_subdirs_and_all_content_types.
733
    def test_set_state_from_inventory_no_content_no_parents(self):
734
        # setting the current inventory is a slow but important api to support.
735
        tree1 = self.make_branch_and_memory_tree('tree1')
736
        tree1.lock_write()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
737
        try:
738
            tree1.add('')
739
            revid1 = tree1.commit('foo').encode('utf8')
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
740
            root_id = tree1.get_root_id()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
741
            inv = tree1.inventory
742
        finally:
743
            tree1.unlock()
2255.2.87 by Robert Collins
core dirstate tests passing with new structure.
744
        expected_result = [], [
745
            (('', '', root_id), [
2255.2.124 by John Arbash Meinel
Remove direct access to Dirstate prefering dirstate.Dirstate
746
             ('d', '', 0, False, dirstate.DirState.NULLSTAT)])]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
747
        state = dirstate.DirState.initialize('dirstate')
748
        try:
749
            state.set_state_from_inventory(inv)
2255.2.124 by John Arbash Meinel
Remove direct access to Dirstate prefering dirstate.Dirstate
750
            self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
751
                             state._header_state)
2255.2.124 by John Arbash Meinel
Remove direct access to Dirstate prefering dirstate.Dirstate
752
            self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
753
                             state._dirblock_state)
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
754
        except:
755
            state.unlock()
756
            raise
757
        else:
758
            # This will unlock it
759
            self.check_state_with_reopen(expected_result, state)
2255.2.16 by Robert Collins
Implement WorkingTreeFormat4._write_inventory for better compatability with existing code, letting more test_test_trees pass, now up to test_tree_with_subdirs_and_all_content_types.
760
2872.4.3 by Martin Pool
Fix comparison for merge sort in Dirstate.set_state_from_inventory
761
    def test_set_state_from_inventory_preserves_hashcache(self):
2872.4.11 by Martin Pool
Review documentation cleanups
762
        # https://bugs.launchpad.net/bzr/+bug/146176
2872.4.1 by Martin Pool
Add xfail test for #146176
763
        # set_state_from_inventory should preserve the stat and hash value for
764
        # workingtree files that are not changed by the inventory.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
765
2872.4.1 by Martin Pool
Add xfail test for #146176
766
        tree = self.make_branch_and_tree('.')
767
        # depends on the default format using dirstate...
768
        tree.lock_write()
769
        try:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
770
            # make a dirstate with some valid hashcache data
2872.4.1 by Martin Pool
Add xfail test for #146176
771
            # file on disk, but that's not needed for this test
772
            foo_contents = 'contents of foo'
773
            self.build_tree_contents([('foo', foo_contents)])
774
            tree.add('foo', 'foo-id')
775
776
            foo_stat = os.stat('foo')
777
            foo_packed = dirstate.pack_stat(foo_stat)
778
            foo_sha = osutils.sha_string(foo_contents)
779
            foo_size = len(foo_contents)
780
781
            # should not be cached yet, because the file's too fresh
2872.4.8 by Martin Pool
Clear up test code
782
            self.assertEqual(
783
                (('', 'foo', 'foo-id',),
784
                 [('f', '', 0, False, dirstate.DirState.NULLSTAT)]),
785
                tree._dirstate._get_entry(0, 'foo-id'))
2872.4.1 by Martin Pool
Add xfail test for #146176
786
            # poke in some hashcache information - it wouldn't normally be
787
            # stored because it's too fresh
788
            tree._dirstate.update_minimal(
789
                ('', 'foo', 'foo-id'),
790
                'f', False, foo_sha, foo_packed, foo_size, 'foo')
791
            # now should be cached
2872.4.8 by Martin Pool
Clear up test code
792
            self.assertEqual(
793
                (('', 'foo', 'foo-id',),
794
                 [('f', foo_sha, foo_size, False, foo_packed)]),
795
                tree._dirstate._get_entry(0, 'foo-id'))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
796
2872.4.1 by Martin Pool
Add xfail test for #146176
797
            # extract the inventory, and add something to it
798
            inv = tree._get_inventory()
2872.4.3 by Martin Pool
Fix comparison for merge sort in Dirstate.set_state_from_inventory
799
            # should see the file we poked in...
800
            self.assertTrue(inv.has_id('foo-id'))
801
            self.assertTrue(inv.has_filename('foo'))
2872.4.1 by Martin Pool
Add xfail test for #146176
802
            inv.add_path('bar', 'file', 'bar-id')
2872.4.13 by Martin Pool
Validate dirstate during tests
803
            tree._dirstate._validate()
2872.4.11 by Martin Pool
Review documentation cleanups
804
            # this used to cause it to lose its hashcache
2872.4.1 by Martin Pool
Add xfail test for #146176
805
            tree._dirstate.set_state_from_inventory(inv)
2872.4.13 by Martin Pool
Validate dirstate during tests
806
            tree._dirstate._validate()
2872.4.1 by Martin Pool
Add xfail test for #146176
807
        finally:
808
            tree.unlock()
809
810
        tree.lock_read()
811
        try:
812
            # now check that the state still has the original hashcache value
813
            state = tree._dirstate
2872.4.13 by Martin Pool
Validate dirstate during tests
814
            state._validate()
2872.4.1 by Martin Pool
Add xfail test for #146176
815
            foo_tuple = state._get_entry(0, path_utf8='foo')
2872.4.3 by Martin Pool
Fix comparison for merge sort in Dirstate.set_state_from_inventory
816
            self.assertEqual(
2872.4.1 by Martin Pool
Add xfail test for #146176
817
                (('', 'foo', 'foo-id',),
818
                 [('f', foo_sha, len(foo_contents), False,
819
                   dirstate.pack_stat(foo_stat))]),
820
                foo_tuple)
821
        finally:
822
            tree.unlock()
823
2487.1.1 by John Arbash Meinel
Adding a (broken) test that set_state_from_inventory works
824
    def test_set_state_from_inventory_mixed_paths(self):
825
        tree1 = self.make_branch_and_tree('tree1')
826
        self.build_tree(['tree1/a/', 'tree1/a/b/', 'tree1/a-b/',
827
                         'tree1/a/b/foo', 'tree1/a-b/bar'])
828
        tree1.lock_write()
829
        try:
830
            tree1.add(['a', 'a/b', 'a-b', 'a/b/foo', 'a-b/bar'],
831
                      ['a-id', 'b-id', 'a-b-id', 'foo-id', 'bar-id'])
832
            tree1.commit('rev1', rev_id='rev1')
833
            root_id = tree1.get_root_id()
834
            inv = tree1.inventory
835
        finally:
836
            tree1.unlock()
837
        expected_result1 = [('', '', root_id, 'd'),
838
                            ('', 'a', 'a-id', 'd'),
839
                            ('', 'a-b', 'a-b-id', 'd'),
840
                            ('a', 'b', 'b-id', 'd'),
841
                            ('a/b', 'foo', 'foo-id', 'f'),
842
                            ('a-b', 'bar', 'bar-id', 'f'),
843
                           ]
844
        expected_result2 = [('', '', root_id, 'd'),
845
                            ('', 'a', 'a-id', 'd'),
846
                            ('', 'a-b', 'a-b-id', 'd'),
847
                            ('a-b', 'bar', 'bar-id', 'f'),
848
                           ]
849
        state = dirstate.DirState.initialize('dirstate')
850
        try:
851
            state.set_state_from_inventory(inv)
852
            values = []
853
            for entry in state._iter_entries():
854
                values.append(entry[0] + entry[1][0][:1])
855
            self.assertEqual(expected_result1, values)
856
            del inv['b-id']
857
            state.set_state_from_inventory(inv)
858
            values = []
859
            for entry in state._iter_entries():
860
                values.append(entry[0] + entry[1][0][:1])
861
            self.assertEqual(expected_result2, values)
862
        finally:
863
            state.unlock()
864
2255.2.4 by Robert Collins
Snapshot dirstate development
865
    def test_set_path_id_no_parents(self):
866
        """The id of a path can be changed trivally with no parents."""
867
        state = dirstate.DirState.initialize('dirstate')
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
868
        try:
869
            # check precondition to be sure the state does change appropriately.
4634.123.4 by John Arbash Meinel
Start working on some direct dirstate tests.
870
            root_entry = (('', '', 'TREE_ROOT'), [('d', '', 0, False, 'x'*32)])
871
            self.assertEqual([root_entry], list(state._iter_entries()))
872
            self.assertEqual(root_entry, state._get_entry(0, path_utf8=''))
873
            self.assertEqual(root_entry,
874
                             state._get_entry(0, fileid_utf8='TREE_ROOT'))
875
            self.assertEqual((None, None),
4634.123.9 by John Arbash Meinel
Fix a bug in the dirstate logic for 'set_path_id'.
876
                             state._get_entry(0, fileid_utf8='second-root-id'))
877
            state.set_path_id('', 'second-root-id')
878
            new_root_entry = (('', '', 'second-root-id'),
4634.123.4 by John Arbash Meinel
Start working on some direct dirstate tests.
879
                              [('d', '', 0, False, 'x'*32)])
880
            expected_rows = [new_root_entry]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
881
            self.assertEqual(expected_rows, list(state._iter_entries()))
4634.123.4 by John Arbash Meinel
Start working on some direct dirstate tests.
882
            self.assertEqual(new_root_entry, state._get_entry(0, path_utf8=''))
883
            self.assertEqual(new_root_entry, 
4634.123.9 by John Arbash Meinel
Fix a bug in the dirstate logic for 'set_path_id'.
884
                             state._get_entry(0, fileid_utf8='second-root-id'))
4634.123.4 by John Arbash Meinel
Start working on some direct dirstate tests.
885
            self.assertEqual((None, None),
886
                             state._get_entry(0, fileid_utf8='TREE_ROOT'))
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
887
            # should work across save too
888
            state.save()
889
        finally:
890
            state.unlock()
2255.2.15 by Robert Collins
Dirstate - truncate state file fixing bug in saving a smaller file, get more tree_implementation tests passing.
891
        state = dirstate.DirState.on_file('dirstate')
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
892
        state.lock_read()
893
        try:
2323.6.13 by Martin Pool
Fix some tests that need to lock dirstate before validating
894
            state._validate()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
895
            self.assertEqual(expected_rows, list(state._iter_entries()))
896
        finally:
897
            state.unlock()
2255.2.4 by Robert Collins
Snapshot dirstate development
898
2255.7.68 by Martin Pool
Add a test for setting the root id in a dirstate with parent trees
899
    def test_set_path_id_with_parents(self):
900
        """Set the root file id in a dirstate with parents"""
901
        mt = self.make_branch_and_tree('mt')
2255.2.178 by Martin Pool
test_set_path_id_with_parents shouldn't depend on tree default root id
902
        # in case the default tree format uses a different root id
903
        mt.set_root_id('TREE_ROOT')
2255.7.68 by Martin Pool
Add a test for setting the root id in a dirstate with parent trees
904
        mt.commit('foo', rev_id='parent-revid')
905
        rt = mt.branch.repository.revision_tree('parent-revid')
906
        state = dirstate.DirState.initialize('dirstate')
2255.7.78 by Martin Pool
Add DirState._validate and call from the tests
907
        state._validate()
2255.7.68 by Martin Pool
Add a test for setting the root id in a dirstate with parent trees
908
        try:
909
            state.set_parent_trees([('parent-revid', rt)], ghosts=[])
4634.123.9 by John Arbash Meinel
Fix a bug in the dirstate logic for 'set_path_id'.
910
            root_entry = (('', '', 'TREE_ROOT'),
911
                          [('d', '', 0, False, 'x'*32),
912
                           ('d', '', 0, False, 'parent-revid')])
913
            self.assertEqual(root_entry, state._get_entry(0, path_utf8=''))
914
            self.assertEqual(root_entry,
915
                             state._get_entry(0, fileid_utf8='TREE_ROOT'))
916
            self.assertEqual((None, None),
917
                             state._get_entry(0, fileid_utf8='Asecond-root-id'))
918
            state.set_path_id('', 'Asecond-root-id')
2255.2.177 by Martin Pool
merge dirstate sorting fix, add more validation tests
919
            state._validate()
2255.7.68 by Martin Pool
Add a test for setting the root id in a dirstate with parent trees
920
            # now see that it is what we expected
4634.123.9 by John Arbash Meinel
Fix a bug in the dirstate logic for 'set_path_id'.
921
            old_root_entry = (('', '', 'TREE_ROOT'),
922
                              [('a', '', 0, False, ''),
923
                               ('d', '', 0, False, 'parent-revid')])
924
            new_root_entry = (('', '', 'Asecond-root-id'),
925
                              [('d', '', 0, False, ''),
926
                               ('a', '', 0, False, '')])
927
            expected_rows = [new_root_entry, old_root_entry]
2255.11.2 by Martin Pool
Add more dirstate root-id-changing tests
928
            state._validate()
2255.7.68 by Martin Pool
Add a test for setting the root id in a dirstate with parent trees
929
            self.assertEqual(expected_rows, list(state._iter_entries()))
4634.123.9 by John Arbash Meinel
Fix a bug in the dirstate logic for 'set_path_id'.
930
            self.assertEqual(new_root_entry, state._get_entry(0, path_utf8=''))
931
            self.assertEqual(old_root_entry, state._get_entry(1, path_utf8=''))
932
            self.assertEqual((None, None),
933
                             state._get_entry(0, fileid_utf8='TREE_ROOT'))
934
            self.assertEqual(old_root_entry,
935
                             state._get_entry(1, fileid_utf8='TREE_ROOT'))
936
            self.assertEqual(new_root_entry,
937
                             state._get_entry(0, fileid_utf8='Asecond-root-id'))
938
            self.assertEqual((None, None),
939
                             state._get_entry(1, fileid_utf8='Asecond-root-id'))
2255.7.68 by Martin Pool
Add a test for setting the root id in a dirstate with parent trees
940
            # should work across save too
941
            state.save()
942
        finally:
943
            state.unlock()
944
        # now flush & check we get the same
945
        state = dirstate.DirState.on_file('dirstate')
946
        state.lock_read()
947
        try:
2255.11.2 by Martin Pool
Add more dirstate root-id-changing tests
948
            state._validate()
2255.7.68 by Martin Pool
Add a test for setting the root id in a dirstate with parent trees
949
            self.assertEqual(expected_rows, list(state._iter_entries()))
950
        finally:
951
            state.unlock()
2255.11.2 by Martin Pool
Add more dirstate root-id-changing tests
952
        # now change within an existing file-backed state
953
        state.lock_write()
954
        try:
955
            state._validate()
956
            state.set_path_id('', 'tree-root-2')
957
            state._validate()
958
        finally:
959
            state.unlock()
960
1852.13.24 by Robert Collins
Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.
961
    def test_set_parent_trees_no_content(self):
962
        # set_parent_trees is a slow but important api to support.
963
        tree1 = self.make_branch_and_memory_tree('tree1')
2255.2.2 by Robert Collins
Partial updates for API changes in trunk.
964
        tree1.lock_write()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
965
        try:
966
            tree1.add('')
967
            revid1 = tree1.commit('foo')
968
        finally:
969
            tree1.unlock()
2255.2.4 by Robert Collins
Snapshot dirstate development
970
        branch2 = tree1.branch.bzrdir.clone('tree2').open_branch()
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
971
        tree2 = memorytree.MemoryTree.create_on_branch(branch2)
2255.2.2 by Robert Collins
Partial updates for API changes in trunk.
972
        tree2.lock_write()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
973
        try:
974
            revid2 = tree2.commit('foo')
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
975
            root_id = tree2.get_root_id()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
976
        finally:
977
            tree2.unlock()
978
        state = dirstate.DirState.initialize('dirstate')
979
        try:
980
            state.set_path_id('', root_id)
981
            state.set_parent_trees(
982
                ((revid1, tree1.branch.repository.revision_tree(revid1)),
983
                 (revid2, tree2.branch.repository.revision_tree(revid2)),
984
                 ('ghost-rev', None)),
985
                ['ghost-rev'])
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
986
            # check we can reopen and use the dirstate after setting parent
987
            # trees.
2255.7.78 by Martin Pool
Add DirState._validate and call from the tests
988
            state._validate()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
989
            state.save()
2255.7.78 by Martin Pool
Add DirState._validate and call from the tests
990
            state._validate()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
991
        finally:
992
            state.unlock()
2255.2.3 by Robert Collins
Split out working tree format 4 to its own file, create stub dirstate revision object, start working on dirstate.set_parent_trees - a key failure point.
993
        state = dirstate.DirState.on_file('dirstate')
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
994
        state.lock_write()
995
        try:
996
            self.assertEqual([revid1, revid2, 'ghost-rev'],
997
                             state.get_parent_ids())
998
            # iterating the entire state ensures that the state is parsable.
999
            list(state._iter_entries())
1000
            # be sure that it sets not appends - change it
1001
            state.set_parent_trees(
1002
                ((revid1, tree1.branch.repository.revision_tree(revid1)),
1003
                 ('ghost-rev', None)),
1004
                ['ghost-rev'])
1005
            # and now put it back.
1006
            state.set_parent_trees(
1007
                ((revid1, tree1.branch.repository.revision_tree(revid1)),
1008
                 (revid2, tree2.branch.repository.revision_tree(revid2)),
3668.5.1 by Jelmer Vernooij
Use NULL_REVISION rather than None for Repository.revision_tree().
1009
                 ('ghost-rev', tree2.branch.repository.revision_tree(
1010
                                   _mod_revision.NULL_REVISION))),
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1011
                ['ghost-rev'])
1012
            self.assertEqual([revid1, revid2, 'ghost-rev'],
1013
                             state.get_parent_ids())
1014
            # the ghost should be recorded as such by set_parent_trees.
1015
            self.assertEqual(['ghost-rev'], state.get_ghosts())
1016
            self.assertEqual(
1017
                [(('', '', root_id), [
2255.2.124 by John Arbash Meinel
Remove direct access to Dirstate prefering dirstate.Dirstate
1018
                  ('d', '', 0, False, dirstate.DirState.NULLSTAT),
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1019
                  ('d', '', 0, False, revid1),
4599.4.24 by Robert Collins
Prepare dirstate tests for 2a as default.
1020
                  ('d', '', 0, False, revid1)
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1021
                  ])],
1022
                list(state._iter_entries()))
1023
        finally:
1024
            state.unlock()
1852.13.19 by Robert Collins
Get DirState objects roundtripping an add of a ghost tree.
1025
2255.2.9 by Robert Collins
Dirstate: Fix setting of parent trees to record data about entries not in
1026
    def test_set_parent_trees_file_missing_from_tree(self):
1027
        # Adding a parent tree may reference files not in the current state.
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1028
        # they should get listed just once by id, even if they are in two
2255.2.9 by Robert Collins
Dirstate: Fix setting of parent trees to record data about entries not in
1029
        # separate trees.
1030
        # set_parent_trees is a slow but important api to support.
1031
        tree1 = self.make_branch_and_memory_tree('tree1')
1032
        tree1.lock_write()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1033
        try:
1034
            tree1.add('')
1035
            tree1.add(['a file'], ['file-id'], ['file'])
1036
            tree1.put_file_bytes_non_atomic('file-id', 'file-content')
1037
            revid1 = tree1.commit('foo')
1038
        finally:
1039
            tree1.unlock()
2255.2.9 by Robert Collins
Dirstate: Fix setting of parent trees to record data about entries not in
1040
        branch2 = tree1.branch.bzrdir.clone('tree2').open_branch()
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1041
        tree2 = memorytree.MemoryTree.create_on_branch(branch2)
2255.2.9 by Robert Collins
Dirstate: Fix setting of parent trees to record data about entries not in
1042
        tree2.lock_write()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1043
        try:
1044
            tree2.put_file_bytes_non_atomic('file-id', 'new file-content')
1045
            revid2 = tree2.commit('foo')
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
1046
            root_id = tree2.get_root_id()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1047
        finally:
1048
            tree2.unlock()
2255.2.9 by Robert Collins
Dirstate: Fix setting of parent trees to record data about entries not in
1049
        # check the layout in memory
2255.2.87 by Robert Collins
core dirstate tests passing with new structure.
1050
        expected_result = [revid1.encode('utf8'), revid2.encode('utf8')], [
1051
            (('', '', root_id), [
2255.2.124 by John Arbash Meinel
Remove direct access to Dirstate prefering dirstate.Dirstate
1052
             ('d', '', 0, False, dirstate.DirState.NULLSTAT),
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
1053
             ('d', '', 0, False, revid1.encode('utf8')),
4599.4.24 by Robert Collins
Prepare dirstate tests for 2a as default.
1054
             ('d', '', 0, False, revid1.encode('utf8'))
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1055
             ]),
2255.2.87 by Robert Collins
core dirstate tests passing with new structure.
1056
            (('', 'a file', 'file-id'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
1057
             ('a', '', 0, False, ''),
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1058
             ('f', '2439573625385400f2a669657a7db6ae7515d371', 12, False,
1059
              revid1.encode('utf8')),
1060
             ('f', '542e57dc1cda4af37cb8e55ec07ce60364bb3c7d', 16, False,
1061
              revid2.encode('utf8'))
1062
             ])
2255.2.9 by Robert Collins
Dirstate: Fix setting of parent trees to record data about entries not in
1063
            ]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1064
        state = dirstate.DirState.initialize('dirstate')
1065
        try:
1066
            state.set_path_id('', root_id)
1067
            state.set_parent_trees(
1068
                ((revid1, tree1.branch.repository.revision_tree(revid1)),
1069
                 (revid2, tree2.branch.repository.revision_tree(revid2)),
1070
                 ), [])
1071
        except:
1072
            state.unlock()
1073
            raise
1074
        else:
1075
            # check_state_with_reopen will unlock
1076
            self.check_state_with_reopen(expected_result, state)
2255.2.9 by Robert Collins
Dirstate: Fix setting of parent trees to record data about entries not in
1077
1852.13.20 by Robert Collins
Steps toward an object model.
1078
    ### add a path via _set_data - so we dont need delta work, just
1079
    # raw data in, and ensure that it comes out via get_lines happily.
1852.13.19 by Robert Collins
Get DirState objects roundtripping an add of a ghost tree.
1080
1852.13.25 by Robert Collins
Snapshot state
1081
    def test_add_path_to_root_no_parents_all_data(self):
1082
        # The most trivial addition of a path is when there are no parents and
1083
        # its in the root and all data about the file is supplied
1084
        self.build_tree(['a file'])
1085
        stat = os.lstat('a file')
1086
        # the 1*20 is the sha1 pretend value.
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1087
        state = dirstate.DirState.initialize('dirstate')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1088
        expected_entries = [
1089
            (('', '', 'TREE_ROOT'), [
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1090
             ('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1091
             ]),
3010.1.2 by Robert Collins
Use valid file-ids for dirstate tests.
1092
            (('', 'a file', 'a-file-id'), [
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1093
             ('f', '1'*20, 19, False, dirstate.pack_stat(stat)), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1094
             ]),
2255.2.13 by Robert Collins
Test adding of directories to the root of a dirstate.
1095
            ]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1096
        try:
3010.1.2 by Robert Collins
Use valid file-ids for dirstate tests.
1097
            state.add('a file', 'a-file-id', 'file', stat, '1'*20)
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1098
            # having added it, it should be in the output of iter_entries.
1099
            self.assertEqual(expected_entries, list(state._iter_entries()))
1100
            # saving and reloading should not affect this.
1101
            state.save()
1102
        finally:
1103
            state.unlock()
2255.2.13 by Robert Collins
Test adding of directories to the root of a dirstate.
1104
        state = dirstate.DirState.on_file('dirstate')
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1105
        state.lock_read()
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1106
        self.addCleanup(state.unlock)
1107
        self.assertEqual(expected_entries, list(state._iter_entries()))
2255.2.13 by Robert Collins
Test adding of directories to the root of a dirstate.
1108
1109
    def test_add_path_to_unversioned_directory(self):
2255.2.29 by Robert Collins
Change the error raised from Dirstate.add for an unversioned parent path to match the WorkingTree interface.
1110
        """Adding a path to an unversioned directory should error.
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1111
1112
        This is a duplicate of TestWorkingTree.test_add_in_unversioned,
2255.2.29 by Robert Collins
Change the error raised from Dirstate.add for an unversioned parent path to match the WorkingTree interface.
1113
        once dirstate is stable and if it is merged with WorkingTree3, consider
1114
        removing this copy of the test.
1115
        """
2255.2.13 by Robert Collins
Test adding of directories to the root of a dirstate.
1116
        self.build_tree(['unversioned/', 'unversioned/a file'])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1117
        state = dirstate.DirState.initialize('dirstate')
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1118
        self.addCleanup(state.unlock)
1119
        self.assertRaises(errors.NotVersionedError, state.add,
1120
                          'unversioned/a file', 'a-file-id', 'file', None, None)
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1121
2255.2.13 by Robert Collins
Test adding of directories to the root of a dirstate.
1122
    def test_add_directory_to_root_no_parents_all_data(self):
1123
        # The most trivial addition of a dir is when there are no parents and
1124
        # its in the root and all data about the file is supplied
1125
        self.build_tree(['a dir/'])
1126
        stat = os.lstat('a dir')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1127
        expected_entries = [
1128
            (('', '', 'TREE_ROOT'), [
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1129
             ('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1130
             ]),
1131
            (('', 'a dir', 'a dir id'), [
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1132
             ('d', '', 0, False, dirstate.pack_stat(stat)), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1133
             ]),
2255.2.13 by Robert Collins
Test adding of directories to the root of a dirstate.
1134
            ]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1135
        state = dirstate.DirState.initialize('dirstate')
1136
        try:
1137
            state.add('a dir', 'a dir id', 'directory', stat, None)
1138
            # having added it, it should be in the output of iter_entries.
1139
            self.assertEqual(expected_entries, list(state._iter_entries()))
1140
            # saving and reloading should not affect this.
1141
            state.save()
1142
        finally:
1143
            state.unlock()
2255.2.13 by Robert Collins
Test adding of directories to the root of a dirstate.
1144
        state = dirstate.DirState.on_file('dirstate')
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1145
        state.lock_read()
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1146
        self.addCleanup(state.unlock)
2255.7.78 by Martin Pool
Add DirState._validate and call from the tests
1147
        state._validate()
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1148
        self.assertEqual(expected_entries, list(state._iter_entries()))
1852.13.25 by Robert Collins
Snapshot state
1149
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1150
    def _test_add_symlink_to_root_no_parents_all_data(self, link_name, target):
2255.2.14 by Robert Collins
Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.
1151
        # The most trivial addition of a symlink when there are no parents and
1152
        # its in the root and all data about the file is supplied
2321.3.8 by Alexander Belchenko
Cleanup patch after John's review
1153
        # bzr doesn't support fake symlinks on windows, yet.
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1154
        self.requireFeature(tests.SymlinkFeature)
1155
        os.symlink(target, link_name)
1156
        stat = os.lstat(link_name)
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1157
        expected_entries = [
1158
            (('', '', 'TREE_ROOT'), [
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1159
             ('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1160
             ]),
4241.14.11 by Vincent Ladeuil
Fix wrong encoding.
1161
            (('', link_name.encode('UTF-8'), 'a link id'), [
1162
             ('l', target.encode('UTF-8'), stat[6],
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1163
              False, dirstate.pack_stat(stat)), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1164
             ]),
2255.2.14 by Robert Collins
Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.
1165
            ]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1166
        state = dirstate.DirState.initialize('dirstate')
1167
        try:
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1168
            state.add(link_name, 'a link id', 'symlink', stat,
4241.14.11 by Vincent Ladeuil
Fix wrong encoding.
1169
                      target.encode('UTF-8'))
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1170
            # having added it, it should be in the output of iter_entries.
1171
            self.assertEqual(expected_entries, list(state._iter_entries()))
1172
            # saving and reloading should not affect this.
1173
            state.save()
1174
        finally:
1175
            state.unlock()
2255.2.14 by Robert Collins
Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.
1176
        state = dirstate.DirState.on_file('dirstate')
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1177
        state.lock_read()
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1178
        self.addCleanup(state.unlock)
1179
        self.assertEqual(expected_entries, list(state._iter_entries()))
1180
1181
    def test_add_symlink_to_root_no_parents_all_data(self):
1182
        self._test_add_symlink_to_root_no_parents_all_data('a link', 'target')
1183
1184
    def test_add_symlink_unicode_to_root_no_parents_all_data(self):
1185
        self.requireFeature(tests.UnicodeFilenameFeature)
1186
        self._test_add_symlink_to_root_no_parents_all_data(
1187
            u'\N{Euro Sign}link', u'targ\N{Euro Sign}et')
2255.2.14 by Robert Collins
Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.
1188
1189
    def test_add_directory_and_child_no_parents_all_data(self):
1190
        # after adding a directory, we should be able to add children to it.
1191
        self.build_tree(['a dir/', 'a dir/a file'])
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1192
        dirstat = os.lstat('a dir')
2255.2.14 by Robert Collins
Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.
1193
        filestat = os.lstat('a dir/a file')
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1194
        expected_entries = [
1195
            (('', '', 'TREE_ROOT'), [
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1196
             ('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1197
             ]),
1198
            (('', 'a dir', 'a dir id'), [
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1199
             ('d', '', 0, False, dirstate.pack_stat(dirstat)), # current tree
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1200
             ]),
3010.1.2 by Robert Collins
Use valid file-ids for dirstate tests.
1201
            (('a dir', 'a file', 'a-file-id'), [
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1202
             ('f', '1'*20, 25, False,
1203
              dirstate.pack_stat(filestat)), # current tree details
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1204
             ]),
2255.2.14 by Robert Collins
Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.
1205
            ]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1206
        state = dirstate.DirState.initialize('dirstate')
1207
        try:
1208
            state.add('a dir', 'a dir id', 'directory', dirstat, None)
3010.1.2 by Robert Collins
Use valid file-ids for dirstate tests.
1209
            state.add('a dir/a file', 'a-file-id', 'file', filestat, '1'*20)
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1210
            # added it, it should be in the output of iter_entries.
1211
            self.assertEqual(expected_entries, list(state._iter_entries()))
1212
            # saving and reloading should not affect this.
1213
            state.save()
1214
        finally:
1215
            state.unlock()
2255.2.14 by Robert Collins
Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.
1216
        state = dirstate.DirState.on_file('dirstate')
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1217
        state.lock_read()
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1218
        self.addCleanup(state.unlock)
1219
        self.assertEqual(expected_entries, list(state._iter_entries()))
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1220
2255.7.93 by Martin Pool
Add support for tree-references in dirstate
1221
    def test_add_tree_reference(self):
1222
        # make a dirstate and add a tree reference
1223
        state = dirstate.DirState.initialize('dirstate')
1224
        expected_entry = (
1225
            ('', 'subdir', 'subdir-id'),
1226
            [('t', 'subtree-123123', 0, False,
1227
              'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')],
1228
            )
1229
        try:
1230
            state.add('subdir', 'subdir-id', 'tree-reference', None, 'subtree-123123')
1231
            entry = state._get_entry(0, 'subdir-id', 'subdir')
1232
            self.assertEqual(entry, expected_entry)
1233
            state._validate()
1234
            state.save()
1235
        finally:
1236
            state.unlock()
1237
        # now check we can read it back
1238
        state.lock_read()
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1239
        self.addCleanup(state.unlock)
2255.7.93 by Martin Pool
Add support for tree-references in dirstate
1240
        state._validate()
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1241
        entry2 = state._get_entry(0, 'subdir-id', 'subdir')
1242
        self.assertEqual(entry, entry2)
1243
        self.assertEqual(entry, expected_entry)
1244
        # and lookup by id should work too
1245
        entry2 = state._get_entry(0, fileid_utf8='subdir-id')
1246
        self.assertEqual(entry, expected_entry)
2255.7.93 by Martin Pool
Add support for tree-references in dirstate
1247
2255.2.225 by Martin Pool
Prohibit dirstate from getting entries called ..
1248
    def test_add_forbidden_names(self):
1249
        state = dirstate.DirState.initialize('dirstate')
2255.2.233 by John Arbash Meinel
DirState.initialize returns a locked state, unlock as part of cleanup.
1250
        self.addCleanup(state.unlock)
2255.2.225 by Martin Pool
Prohibit dirstate from getting entries called ..
1251
        self.assertRaises(errors.BzrError,
1252
            state.add, '.', 'ass-id', 'directory', None, None)
1253
        self.assertRaises(errors.BzrError,
1254
            state.add, '..', 'ass-id', 'directory', None, None)
1255
4536.4.1 by Robert Collins
Fix dirstate.set_state_from_inventory to have a more stable old_iterator, fixing rename problems in new trees. (Robert Collins, bug 395556)
1256
    def test_set_state_with_rename_b_a_bug_395556(self):
1257
        # bug 395556 uncovered a bug where the dirstate ends up with a false
1258
        # relocation record - in a tree with no parents there should be no
1259
        # absent or relocated records. This then leads to further corruption
1260
        # when a commit occurs, as the incorrect relocation gathers an
1261
        # incorrect absent in tree 1, and future changes go to pot.
1262
        tree1 = self.make_branch_and_tree('tree1')
1263
        self.build_tree(['tree1/b'])
1264
        tree1.lock_write()
1265
        try:
1266
            tree1.add(['b'], ['b-id'])
1267
            root_id = tree1.get_root_id()
1268
            inv = tree1.inventory
1269
            state = dirstate.DirState.initialize('dirstate')
1270
            try:
1271
                # Set the initial state with 'b'
1272
                state.set_state_from_inventory(inv)
1273
                inv.rename('b-id', root_id, 'a')
1274
                # Set the new state with 'a', which currently corrupts.
1275
                state.set_state_from_inventory(inv)
1276
                expected_result1 = [('', '', root_id, 'd'),
1277
                                    ('', 'a', 'b-id', 'f'),
1278
                                   ]
1279
                values = []
1280
                for entry in state._iter_entries():
1281
                    values.append(entry[0] + entry[1][0][:1])
1282
                self.assertEqual(expected_result1, values)
1283
            finally:
1284
                state.unlock()
1285
        finally:
1286
            tree1.unlock()
1287
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1288
1289
class TestGetLines(TestCaseWithDirState):
1852.13.19 by Robert Collins
Get DirState objects roundtripping an add of a ghost tree.
1290
1852.13.24 by Robert Collins
Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.
1291
    def test_get_line_with_2_rows(self):
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1292
        state = self.create_dirstate_with_root_and_subdir()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1293
        try:
2255.7.20 by John Arbash Meinel
update test for format 3, and enable caching of path split while lock is held.
1294
            self.assertEqual(['#bazaar dirstate flat format 3\n',
2255.2.239 by Robert Collins
Change from adler to crc checksums, as adler32 in python is not stable from 32 to 64 bit systems.
1295
                'crc32: 41262208\n',
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1296
                'num_entries: 2\n',
1297
                '0\x00\n\x00'
1298
                '0\x00\n\x00'
1299
                '\x00\x00a-root-value\x00'
1300
                'd\x00\x000\x00n\x00AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk\x00\n\x00'
1301
                '\x00subdir\x00subdir-id\x00'
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1302
                'd\x00\x000\x00n\x00AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk\x00\n\x00'
1303
                ], state.get_lines())
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1304
        finally:
1305
            state.unlock()
1852.13.24 by Robert Collins
Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.
1306
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1307
    def test_entry_to_line(self):
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1308
        state = self.create_dirstate_with_root()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1309
        try:
1310
            self.assertEqual(
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1311
                '\x00\x00a-root-value\x00d\x00\x000\x00n'
1312
                '\x00AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk',
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1313
                state._entry_to_line(state._dirblocks[0][1][0]))
1314
        finally:
1315
            state.unlock()
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1316
1317
    def test_entry_to_line_with_parent(self):
1318
        packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
1319
        root_entry = ('', '', 'a-root-value'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
1320
            ('d', '', 0, False, packed_stat), # current tree details
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1321
             # first: a pointer to the current location
1322
            ('a', 'dirname/basename', 0, False, ''),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1323
            ]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1324
        state = dirstate.DirState.initialize('dirstate')
1325
        try:
1326
            self.assertEqual(
1327
                '\x00\x00a-root-value\x00'
1328
                'd\x00\x000\x00n\x00AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk\x00'
1329
                'a\x00dirname/basename\x000\x00n\x00',
1330
                state._entry_to_line(root_entry))
1331
        finally:
1332
            state.unlock()
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1333
1334
    def test_entry_to_line_with_two_parents_at_different_paths(self):
1335
        # / in the tree, at / in one parent and /dirname/basename in the other.
1336
        packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
1337
        root_entry = ('', '', 'a-root-value'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
1338
            ('d', '', 0, False, packed_stat), # current tree details
1339
            ('d', '', 0, False, 'rev_id'), # first parent details
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1340
             # second: a pointer to the current location
1341
            ('a', 'dirname/basename', 0, False, ''),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1342
            ]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1343
        state = dirstate.DirState.initialize('dirstate')
1344
        try:
1345
            self.assertEqual(
1346
                '\x00\x00a-root-value\x00'
1347
                'd\x00\x000\x00n\x00AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk\x00'
1348
                'd\x00\x000\x00n\x00rev_id\x00'
1349
                'a\x00dirname/basename\x000\x00n\x00',
1350
                state._entry_to_line(root_entry))
1351
        finally:
1352
            state.unlock()
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1353
1354
    def test_iter_entries(self):
1355
        # we should be able to iterate the dirstate entries from end to end
1852.13.24 by Robert Collins
Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.
1356
        # this is for get_lines to be easy to read.
1357
        packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
1358
        dirblocks = []
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1359
        root_entries = [(('', '', 'a-root-value'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
1360
            ('d', '', 0, False, packed_stat), # current tree details
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1361
            ])]
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
1362
        dirblocks.append(('', root_entries))
1852.13.24 by Robert Collins
Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.
1363
        # add two files in the root
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1364
        subdir_entry = ('', 'subdir', 'subdir-id'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
1365
            ('d', '', 0, False, packed_stat), # current tree details
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1366
            ]
1367
        afile_entry = ('', 'afile', 'afile-id'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
1368
            ('f', 'sha1value', 34, False, packed_stat), # current tree details
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1369
            ]
1370
        dirblocks.append(('', [subdir_entry, afile_entry]))
1852.13.24 by Robert Collins
Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.
1371
        # and one in subdir
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1372
        file_entry2 = ('subdir', '2file', '2file-id'), [
2255.2.113 by John Arbash Meinel
545ms, 600ms: Switch memory model from storing kind to using minikind
1373
            ('f', 'sha1value', 23, False, packed_stat), # current tree details
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1374
            ]
1375
        dirblocks.append(('subdir', [file_entry2]))
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1376
        state = dirstate.DirState.initialize('dirstate')
1377
        try:
1378
            state._set_data([], dirblocks)
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1379
            expected_entries = [root_entries[0], subdir_entry, afile_entry,
1380
                                file_entry2]
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1381
            self.assertEqual(expected_entries, list(state._iter_entries()))
1382
        finally:
1383
            state.unlock()
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1384
1385
1386
class TestGetBlockRowIndex(TestCaseWithDirState):
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1387
1388
    def assertBlockRowIndexEqual(self, block_index, row_index, dir_present,
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1389
        file_present, state, dirname, basename, tree_index):
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1390
        self.assertEqual((block_index, row_index, dir_present, file_present),
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1391
            state._get_block_entry_index(dirname, basename, tree_index))
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1392
        if dir_present:
1393
            block = state._dirblocks[block_index]
1394
            self.assertEqual(dirname, block[0])
1395
        if dir_present and file_present:
1396
            row = state._dirblocks[block_index][1][row_index]
1397
            self.assertEqual(dirname, row[0][0])
1398
            self.assertEqual(basename, row[0][1])
1399
1400
    def test_simple_structure(self):
1401
        state = self.create_dirstate_with_root_and_subdir()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1402
        self.addCleanup(state.unlock)
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
1403
        self.assertBlockRowIndexEqual(1, 0, True, True, state, '', 'subdir', 0)
1404
        self.assertBlockRowIndexEqual(1, 0, True, False, state, '', 'bdir', 0)
1405
        self.assertBlockRowIndexEqual(1, 1, True, False, state, '', 'zdir', 0)
1406
        self.assertBlockRowIndexEqual(2, 0, False, False, state, 'a', 'foo', 0)
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1407
        self.assertBlockRowIndexEqual(2, 0, False, False, state,
1408
                                      'subdir', 'foo', 0)
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1409
1410
    def test_complex_structure_exists(self):
1411
        state = self.create_complex_dirstate()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1412
        self.addCleanup(state.unlock)
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1413
        # Make sure we can find everything that exists
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
1414
        self.assertBlockRowIndexEqual(0, 0, True, True, state, '', '', 0)
1415
        self.assertBlockRowIndexEqual(1, 0, True, True, state, '', 'a', 0)
1416
        self.assertBlockRowIndexEqual(1, 1, True, True, state, '', 'b', 0)
1417
        self.assertBlockRowIndexEqual(1, 2, True, True, state, '', 'c', 0)
1418
        self.assertBlockRowIndexEqual(1, 3, True, True, state, '', 'd', 0)
1419
        self.assertBlockRowIndexEqual(2, 0, True, True, state, 'a', 'e', 0)
1420
        self.assertBlockRowIndexEqual(2, 1, True, True, state, 'a', 'f', 0)
1421
        self.assertBlockRowIndexEqual(3, 0, True, True, state, 'b', 'g', 0)
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1422
        self.assertBlockRowIndexEqual(3, 1, True, True, state,
1423
                                      'b', 'h\xc3\xa5', 0)
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1424
1425
    def test_complex_structure_missing(self):
1426
        state = self.create_complex_dirstate()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1427
        self.addCleanup(state.unlock)
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1428
        # Make sure things would be inserted in the right locations
1429
        # '_' comes before 'a'
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
1430
        self.assertBlockRowIndexEqual(0, 0, True, True, state, '', '', 0)
1431
        self.assertBlockRowIndexEqual(1, 0, True, False, state, '', '_', 0)
1432
        self.assertBlockRowIndexEqual(1, 1, True, False, state, '', 'aa', 0)
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1433
        self.assertBlockRowIndexEqual(1, 4, True, False, state,
1434
                                      '', 'h\xc3\xa5', 0)
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
1435
        self.assertBlockRowIndexEqual(2, 0, False, False, state, '_', 'a', 0)
1436
        self.assertBlockRowIndexEqual(3, 0, False, False, state, 'aa', 'a', 0)
1437
        self.assertBlockRowIndexEqual(4, 0, False, False, state, 'bb', 'a', 0)
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1438
        # This would be inserted between a/ and b/
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
1439
        self.assertBlockRowIndexEqual(3, 0, False, False, state, 'a/e', 'a', 0)
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1440
        # Put at the end
2255.2.96 by Robert Collins
Restore dirstate to all tests passing condition.
1441
        self.assertBlockRowIndexEqual(4, 0, False, False, state, 'e', 'a', 0)
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1442
1443
1444
class TestGetEntry(TestCaseWithDirState):
1445
1446
    def assertEntryEqual(self, dirname, basename, file_id, state, path, index):
1447
        """Check that the right entry is returned for a request to getEntry."""
2255.2.87 by Robert Collins
core dirstate tests passing with new structure.
1448
        entry = state._get_entry(index, path_utf8=path)
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1449
        if file_id is None:
1450
            self.assertEqual((None, None), entry)
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1451
        else:
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1452
            cur = entry[0]
1453
            self.assertEqual((dirname, basename, file_id), cur[:3])
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1454
1455
    def test_simple_structure(self):
1456
        state = self.create_dirstate_with_root_and_subdir()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1457
        self.addCleanup(state.unlock)
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1458
        self.assertEntryEqual('', '', 'a-root-value', state, '', 0)
1459
        self.assertEntryEqual('', 'subdir', 'subdir-id', state, 'subdir', 0)
1460
        self.assertEntryEqual(None, None, None, state, 'missing', 0)
1461
        self.assertEntryEqual(None, None, None, state, 'missing/foo', 0)
1462
        self.assertEntryEqual(None, None, None, state, 'subdir/foo', 0)
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1463
1464
    def test_complex_structure_exists(self):
1465
        state = self.create_complex_dirstate()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1466
        self.addCleanup(state.unlock)
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1467
        self.assertEntryEqual('', '', 'a-root-value', state, '', 0)
1468
        self.assertEntryEqual('', 'a', 'a-dir', state, 'a', 0)
1469
        self.assertEntryEqual('', 'b', 'b-dir', state, 'b', 0)
1470
        self.assertEntryEqual('', 'c', 'c-file', state, 'c', 0)
1471
        self.assertEntryEqual('', 'd', 'd-file', state, 'd', 0)
1472
        self.assertEntryEqual('a', 'e', 'e-dir', state, 'a/e', 0)
1473
        self.assertEntryEqual('a', 'f', 'f-file', state, 'a/f', 0)
1474
        self.assertEntryEqual('b', 'g', 'g-file', state, 'b/g', 0)
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1475
        self.assertEntryEqual('b', 'h\xc3\xa5', 'h-\xc3\xa5-file', state,
1476
                              'b/h\xc3\xa5', 0)
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1477
1478
    def test_complex_structure_missing(self):
1479
        state = self.create_complex_dirstate()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1480
        self.addCleanup(state.unlock)
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1481
        self.assertEntryEqual(None, None, None, state, '_', 0)
1482
        self.assertEntryEqual(None, None, None, state, '_\xc3\xa5', 0)
1483
        self.assertEntryEqual(None, None, None, state, 'a/b', 0)
1484
        self.assertEntryEqual(None, None, None, state, 'c/d', 0)
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1485
2255.2.85 by Robert Collins
[BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.
1486
    def test_get_entry_uninitialized(self):
1487
        """Calling get_entry will load data if it needs to"""
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1488
        state = self.create_dirstate_with_root()
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1489
        try:
1490
            state.save()
1491
        finally:
1492
            state.unlock()
2255.2.66 by John Arbash Meinel
Move _get_row and _get_block_row_index into Dirstate itself.
1493
        del state
1494
        state = dirstate.DirState.on_file('dirstate')
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1495
        state.lock_read()
1496
        try:
2255.2.123 by John Arbash Meinel
Simple line wrapping cleanup in test_dirstate.py
1497
            self.assertEqual(dirstate.DirState.NOT_IN_MEMORY,
1498
                             state._header_state)
1499
            self.assertEqual(dirstate.DirState.NOT_IN_MEMORY,
1500
                             state._dirblock_state)
2255.5.1 by John Arbash Meinel
Update the dirstate tests to lock and unlock properly.
1501
            self.assertEntryEqual('', '', 'a-root-value', state, '', 0)
1502
        finally:
1503
            state.unlock()
2255.3.2 by John Arbash Meinel
(broken) some basic work on adding bisect functionality to dirstate.
1504
1505
2929.2.1 by Robert Collins
* Commit updates the state of the working tree via a delta rather than
1506
class TestIterChildEntries(TestCaseWithDirState):
1507
1508
    def create_dirstate_with_two_trees(self):
1509
        """This dirstate contains multiple files and directories.
1510
1511
         /        a-root-value
1512
         a/       a-dir
1513
         b/       b-dir
1514
         c        c-file
1515
         d        d-file
1516
         a/e/     e-dir
1517
         a/f      f-file
1518
         b/g      g-file
1519
         b/h\xc3\xa5  h-\xc3\xa5-file  #This is u'\xe5' encoded into utf-8
1520
1521
        Notice that a/e is an empty directory.
1522
1523
        There is one parent tree, which has the same shape with the following variations:
1524
        b/g in the parent is gone.
1525
        b/h in the parent has a different id
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1526
        b/i is new in the parent
2929.2.1 by Robert Collins
* Commit updates the state of the working tree via a delta rather than
1527
        c is renamed to b/j in the parent
1528
1529
        :return: The dirstate, still write-locked.
1530
        """
1531
        packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
1532
        null_sha = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
1533
        NULL_PARENT_DETAILS = dirstate.DirState.NULL_PARENT_DETAILS
1534
        root_entry = ('', '', 'a-root-value'), [
1535
            ('d', '', 0, False, packed_stat),
1536
            ('d', '', 0, False, 'parent-revid'),
1537
            ]
1538
        a_entry = ('', 'a', 'a-dir'), [
1539
            ('d', '', 0, False, packed_stat),
1540
            ('d', '', 0, False, 'parent-revid'),
1541
            ]
1542
        b_entry = ('', 'b', 'b-dir'), [
1543
            ('d', '', 0, False, packed_stat),
1544
            ('d', '', 0, False, 'parent-revid'),
1545
            ]
1546
        c_entry = ('', 'c', 'c-file'), [
1547
            ('f', null_sha, 10, False, packed_stat),
1548
            ('r', 'b/j', 0, False, ''),
1549
            ]
1550
        d_entry = ('', 'd', 'd-file'), [
1551
            ('f', null_sha, 20, False, packed_stat),
1552
            ('f', 'd', 20, False, 'parent-revid'),
1553
            ]
1554
        e_entry = ('a', 'e', 'e-dir'), [
1555
            ('d', '', 0, False, packed_stat),
1556
            ('d', '', 0, False, 'parent-revid'),
1557
            ]
1558
        f_entry = ('a', 'f', 'f-file'), [
1559
            ('f', null_sha, 30, False, packed_stat),
1560
            ('f', 'f', 20, False, 'parent-revid'),
1561
            ]
1562
        g_entry = ('b', 'g', 'g-file'), [
1563
            ('f', null_sha, 30, False, packed_stat),
1564
            NULL_PARENT_DETAILS,
1565
            ]
1566
        h_entry1 = ('b', 'h\xc3\xa5', 'h-\xc3\xa5-file1'), [
1567
            ('f', null_sha, 40, False, packed_stat),
1568
            NULL_PARENT_DETAILS,
1569
            ]
1570
        h_entry2 = ('b', 'h\xc3\xa5', 'h-\xc3\xa5-file2'), [
1571
            NULL_PARENT_DETAILS,
1572
            ('f', 'h', 20, False, 'parent-revid'),
1573
            ]
1574
        i_entry = ('b', 'i', 'i-file'), [
1575
            NULL_PARENT_DETAILS,
1576
            ('f', 'h', 20, False, 'parent-revid'),
1577
            ]
1578
        j_entry = ('b', 'j', 'c-file'), [
1579
            ('r', 'c', 0, False, ''),
1580
            ('f', 'j', 20, False, 'parent-revid'),
1581
            ]
1582
        dirblocks = []
1583
        dirblocks.append(('', [root_entry]))
1584
        dirblocks.append(('', [a_entry, b_entry, c_entry, d_entry]))
1585
        dirblocks.append(('a', [e_entry, f_entry]))
1586
        dirblocks.append(('b', [g_entry, h_entry1, h_entry2, i_entry, j_entry]))
1587
        state = dirstate.DirState.initialize('dirstate')
1588
        state._validate()
1589
        try:
1590
            state._set_data(['parent'], dirblocks)
1591
        except:
1592
            state.unlock()
1593
            raise
1594
        return state, dirblocks
1595
1596
    def test_iter_children_b(self):
1597
        state, dirblocks = self.create_dirstate_with_two_trees()
1598
        self.addCleanup(state.unlock)
1599
        expected_result = []
1600
        expected_result.append(dirblocks[3][1][2]) # h2
1601
        expected_result.append(dirblocks[3][1][3]) # i
1602
        expected_result.append(dirblocks[3][1][4]) # j
1603
        self.assertEqual(expected_result,
1604
            list(state._iter_child_entries(1, 'b')))
1605
2929.2.2 by Robert Collins
Review feedback on dirstate update_basis_via_delta logic.
1606
    def test_iter_child_root(self):
1607
        state, dirblocks = self.create_dirstate_with_two_trees()
1608
        self.addCleanup(state.unlock)
1609
        expected_result = []
1610
        expected_result.append(dirblocks[1][1][0]) # a
1611
        expected_result.append(dirblocks[1][1][1]) # b
1612
        expected_result.append(dirblocks[1][1][3]) # d
1613
        expected_result.append(dirblocks[2][1][0]) # e
1614
        expected_result.append(dirblocks[2][1][1]) # f
1615
        expected_result.append(dirblocks[3][1][2]) # h2
1616
        expected_result.append(dirblocks[3][1][3]) # i
1617
        expected_result.append(dirblocks[3][1][4]) # j
1618
        self.assertEqual(expected_result,
1619
            list(state._iter_child_entries(1, '')))
1620
2929.2.1 by Robert Collins
* Commit updates the state of the working tree via a delta rather than
1621
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1622
class TestDirstateSortOrder(tests.TestCaseWithTransport):
2255.8.5 by John Arbash Meinel
Add a test that dirstate adds records in the right order.
1623
    """Test that DirState adds entries in the right order."""
1624
1625
    def test_add_sorting(self):
2255.7.21 by John Arbash Meinel
Get iter_changes working again, by fixing set_parent_trees to
1626
        """Add entries in lexicographical order, we get path sorted order.
1627
1628
        This tests it to a depth of 4, to make sure we don't just get it right
1629
        at a single depth. 'a/a' should come before 'a-a', even though it
1630
        doesn't lexicographically.
1631
        """
1632
        dirs = ['a', 'a/a', 'a/a/a', 'a/a/a/a',
1633
                'a-a', 'a/a-a', 'a/a/a-a', 'a/a/a/a-a',
2255.8.5 by John Arbash Meinel
Add a test that dirstate adds records in the right order.
1634
               ]
1635
        null_sha = ''
1636
        state = dirstate.DirState.initialize('dirstate')
1637
        self.addCleanup(state.unlock)
1638
1639
        fake_stat = os.stat('dirstate')
1640
        for d in dirs:
1641
            d_id = d.replace('/', '_')+'-id'
1642
            file_path = d + '/f'
1643
            file_id = file_path.replace('/', '_')+'-id'
1644
            state.add(d, d_id, 'directory', fake_stat, null_sha)
1645
            state.add(file_path, file_id, 'file', fake_stat, null_sha)
1646
1647
        expected = ['', '', 'a',
2255.7.21 by John Arbash Meinel
Get iter_changes working again, by fixing set_parent_trees to
1648
                'a/a', 'a/a/a', 'a/a/a/a',
1649
                'a/a/a/a-a', 'a/a/a-a', 'a/a-a', 'a-a',
2255.8.5 by John Arbash Meinel
Add a test that dirstate adds records in the right order.
1650
               ]
2255.7.21 by John Arbash Meinel
Get iter_changes working again, by fixing set_parent_trees to
1651
        split = lambda p:p.split('/')
1652
        self.assertEqual(sorted(expected, key=split), expected)
1653
        dirblock_names = [d[0] for d in state._dirblocks]
1654
        self.assertEqual(expected, dirblock_names)
1655
1656
    def test_set_parent_trees_correct_order(self):
1657
        """After calling set_parent_trees() we should maintain the order."""
1658
        dirs = ['a', 'a-a', 'a/a']
1659
        null_sha = ''
1660
        state = dirstate.DirState.initialize('dirstate')
1661
        self.addCleanup(state.unlock)
1662
1663
        fake_stat = os.stat('dirstate')
1664
        for d in dirs:
1665
            d_id = d.replace('/', '_')+'-id'
1666
            file_path = d + '/f'
1667
            file_id = file_path.replace('/', '_')+'-id'
1668
            state.add(d, d_id, 'directory', fake_stat, null_sha)
1669
            state.add(file_path, file_id, 'file', fake_stat, null_sha)
1670
1671
        expected = ['', '', 'a', 'a/a', 'a-a']
1672
        dirblock_names = [d[0] for d in state._dirblocks]
1673
        self.assertEqual(expected, dirblock_names)
1674
1675
        # *really* cheesy way to just get an empty tree
1676
        repo = self.make_repository('repo')
3668.5.1 by Jelmer Vernooij
Use NULL_REVISION rather than None for Repository.revision_tree().
1677
        empty_tree = repo.revision_tree(_mod_revision.NULL_REVISION)
2255.7.21 by John Arbash Meinel
Get iter_changes working again, by fixing set_parent_trees to
1678
        state.set_parent_trees([('null:', empty_tree)], [])
1679
2255.8.5 by John Arbash Meinel
Add a test that dirstate adds records in the right order.
1680
        dirblock_names = [d[0] for d in state._dirblocks]
1681
        self.assertEqual(expected, dirblock_names)
1682
1683
2255.10.3 by John Arbash Meinel
(broken) Change get_sha1_for_entry into update_entry
1684
class InstrumentedDirState(dirstate.DirState):
2255.10.1 by John Arbash Meinel
Update WorkingTree4 so that it doesn't use a HashCache,
1685
    """An DirState with instrumented sha1 functionality."""
1686
4132.2.2 by Ian Clatworthy
make sha1_provider a mandatory param for DirState.__init__()
1687
    def __init__(self, path, sha1_provider):
1688
        super(InstrumentedDirState, self).__init__(path, sha1_provider)
2255.10.1 by John Arbash Meinel
Update WorkingTree4 so that it doesn't use a HashCache,
1689
        self._time_offset = 0
2255.10.3 by John Arbash Meinel
(broken) Change get_sha1_for_entry into update_entry
1690
        self._log = []
2872.3.3 by Martin Pool
Fix up test_update_entry to work with -Dhashcache
1691
        # member is dynamically set in DirState.__init__ to turn on trace
4132.2.2 by Ian Clatworthy
make sha1_provider a mandatory param for DirState.__init__()
1692
        self._sha1_provider = sha1_provider
2872.3.3 by Martin Pool
Fix up test_update_entry to work with -Dhashcache
1693
        self._sha1_file = self._sha1_file_and_log
2255.10.1 by John Arbash Meinel
Update WorkingTree4 so that it doesn't use a HashCache,
1694
1695
    def _sha_cutoff_time(self):
2255.10.3 by John Arbash Meinel
(broken) Change get_sha1_for_entry into update_entry
1696
        timestamp = super(InstrumentedDirState, self)._sha_cutoff_time()
2255.10.6 by John Arbash Meinel
Save approx 30-60ms (5-10%) on a LP tree by not calling time.time() for every entry.
1697
        self._cutoff_time = timestamp + self._time_offset
2255.10.1 by John Arbash Meinel
Update WorkingTree4 so that it doesn't use a HashCache,
1698
2872.3.3 by Martin Pool
Fix up test_update_entry to work with -Dhashcache
1699
    def _sha1_file_and_log(self, abspath):
2255.10.3 by John Arbash Meinel
(broken) Change get_sha1_for_entry into update_entry
1700
        self._log.append(('sha1', abspath))
4132.2.2 by Ian Clatworthy
make sha1_provider a mandatory param for DirState.__init__()
1701
        return self._sha1_provider.sha1(abspath)
2255.10.3 by John Arbash Meinel
(broken) Change get_sha1_for_entry into update_entry
1702
1703
    def _read_link(self, abspath, old_link):
1704
        self._log.append(('read_link', abspath, old_link))
1705
        return super(InstrumentedDirState, self)._read_link(abspath, old_link)
1706
1707
    def _lstat(self, abspath, entry):
1708
        self._log.append(('lstat', abspath))
1709
        return super(InstrumentedDirState, self)._lstat(abspath, entry)
1710
1711
    def _is_executable(self, mode, old_executable):
1712
        self._log.append(('is_exec', mode, old_executable))
1713
        return super(InstrumentedDirState, self)._is_executable(mode,
1714
                                                                old_executable)
2255.10.1 by John Arbash Meinel
Update WorkingTree4 so that it doesn't use a HashCache,
1715
1716
    def adjust_time(self, secs):
1717
        """Move the clock forward or back.
1718
1719
        :param secs: The amount to adjust the clock by. Positive values make it
1720
        seem as if we are in the future, negative values make it seem like we
1721
        are in the past.
1722
        """
1723
        self._time_offset += secs
2255.10.6 by John Arbash Meinel
Save approx 30-60ms (5-10%) on a LP tree by not calling time.time() for every entry.
1724
        self._cutoff_time = None
2255.10.1 by John Arbash Meinel
Update WorkingTree4 so that it doesn't use a HashCache,
1725
1726
1727
class _FakeStat(object):
1728
    """A class with the same attributes as a real stat result."""
1729
1730
    def __init__(self, size, mtime, ctime, dev, ino, mode):
1731
        self.st_size = size
1732
        self.st_mtime = mtime
1733
        self.st_ctime = ctime
1734
        self.st_dev = dev
1735
        self.st_ino = ino
1736
        self.st_mode = mode
1737
4132.2.3 by Ian Clatworthy
add test as suggested by poolie's review
1738
    @staticmethod
1739
    def from_stat(st):
1740
        return _FakeStat(st.st_size, st.st_mtime, st.st_ctime, st.st_dev,
1741
            st.st_ino, st.st_mode)
1742
2255.10.1 by John Arbash Meinel
Update WorkingTree4 so that it doesn't use a HashCache,
1743
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
1744
class TestPackStat(tests.TestCaseWithTransport):
2255.10.1 by John Arbash Meinel
Update WorkingTree4 so that it doesn't use a HashCache,
1745
1746
    def assertPackStat(self, expected, stat_value):
1747
        """Check the packed and serialized form of a stat value."""
1748
        self.assertEqual(expected, dirstate.pack_stat(stat_value))
1749
1750
    def test_pack_stat_int(self):
1751
        st = _FakeStat(6859L, 1172758614, 1172758617, 777L, 6499538L, 0100644)
1752
        # Make sure that all parameters have an impact on the packed stat.
1753
        self.assertPackStat('AAAay0Xm4FZF5uBZAAADCQBjLNIAAIGk', st)
1754
        st.st_size = 7000L
1755
        #                ay0 => bWE
1756
        self.assertPackStat('AAAbWEXm4FZF5uBZAAADCQBjLNIAAIGk', st)
1757
        st.st_mtime = 1172758620
1758
        #                     4FZ => 4Fx
1759
        self.assertPackStat('AAAbWEXm4FxF5uBZAAADCQBjLNIAAIGk', st)
1760
        st.st_ctime = 1172758630
1761
        #                          uBZ => uBm
1762
        self.assertPackStat('AAAbWEXm4FxF5uBmAAADCQBjLNIAAIGk', st)
1763
        st.st_dev = 888L
1764
        #                                DCQ => DeA
1765
        self.assertPackStat('AAAbWEXm4FxF5uBmAAADeABjLNIAAIGk', st)
1766
        st.st_ino = 6499540L
1767
        #                                     LNI => LNQ
1768
        self.assertPackStat('AAAbWEXm4FxF5uBmAAADeABjLNQAAIGk', st)
1769
        st.st_mode = 0100744
1770
        #                                          IGk => IHk
1771
        self.assertPackStat('AAAbWEXm4FxF5uBmAAADeABjLNQAAIHk', st)
1772
1773
    def test_pack_stat_float(self):
1774
        """On some platforms mtime and ctime are floats.
1775
1776
        Make sure we don't get warnings or errors, and that we ignore changes <
1777
        1s
1778
        """
1779
        st = _FakeStat(7000L, 1172758614.0, 1172758617.0,
1780
                       777L, 6499538L, 0100644)
1781
        # These should all be the same as the integer counterparts
1782
        self.assertPackStat('AAAbWEXm4FZF5uBZAAADCQBjLNIAAIGk', st)
1783
        st.st_mtime = 1172758620.0
1784
        #                     FZF5 => FxF5
1785
        self.assertPackStat('AAAbWEXm4FxF5uBZAAADCQBjLNIAAIGk', st)
1786
        st.st_ctime = 1172758630.0
1787
        #                          uBZ => uBm
1788
        self.assertPackStat('AAAbWEXm4FxF5uBmAAADCQBjLNIAAIGk', st)
1789
        # fractional seconds are discarded, so no change from above
1790
        st.st_mtime = 1172758620.453
1791
        self.assertPackStat('AAAbWEXm4FxF5uBmAAADCQBjLNIAAIGk', st)
1792
        st.st_ctime = 1172758630.228
1793
        self.assertPackStat('AAAbWEXm4FxF5uBmAAADCQBjLNIAAIGk', st)
1794
1795
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
1796
class TestBisect(TestCaseWithDirState):
2255.3.2 by John Arbash Meinel
(broken) some basic work on adding bisect functionality to dirstate.
1797
    """Test the ability to bisect into the disk format."""
1798
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1799
    def assertBisect(self, expected_map, map_keys, state, paths):
2255.2.125 by John Arbash Meinel
Initial effort at adding a basic _bisect function to DirState.
1800
        """Assert that bisecting for paths returns the right result.
1801
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1802
        :param expected_map: A map from key => entry value
1803
        :param map_keys: The keys to expect for each path
2255.2.125 by John Arbash Meinel
Initial effort at adding a basic _bisect function to DirState.
1804
        :param state: The DirState object.
1805
        :param paths: A list of paths, these will automatically be split into
1806
                      (dir, name) tuples, and sorted according to how _bisect
1807
                      requires.
1808
        """
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1809
        result = state._bisect(paths)
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1810
        # For now, results are just returned in whatever order we read them.
1811
        # We could sort by (dir, name, file_id) or something like that, but in
1812
        # the end it would still be fairly arbitrary, and we don't want the
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1813
        # extra overhead if we can avoid it. So sort everything to make sure
1814
        # equality is true
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
1815
        self.assertEqual(len(map_keys), len(paths))
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1816
        expected = {}
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1817
        for path, keys in zip(paths, map_keys):
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1818
            if keys is None:
1819
                # This should not be present in the output
1820
                continue
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1821
            expected[path] = sorted(expected_map[k] for k in keys)
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1822
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1823
        # The returned values are just arranged randomly based on when they
1824
        # were read, for testing, make sure it is properly sorted.
1825
        for path in result:
1826
            result[path].sort()
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1827
1828
        self.assertEqual(expected, result)
1829
1830
    def assertBisectDirBlocks(self, expected_map, map_keys, state, paths):
2255.2.130 by John Arbash Meinel
Add a very similar function which grabs everything for a particular directory block.
1831
        """Assert that bisecting for dirbblocks returns the right result.
1832
2255.2.132 by John Arbash Meinel
Implement _bisect_recursive, which uses multiple bisect calls to
1833
        :param expected_map: A map from key => expected values
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1834
        :param map_keys: A nested list of paths we expect to be returned.
2255.2.130 by John Arbash Meinel
Add a very similar function which grabs everything for a particular directory block.
1835
            Something like [['a', 'b', 'f'], ['b/c', 'b/d']]
1836
        :param state: The DirState object.
1837
        :param paths: A list of directories
1838
        """
1839
        result = state._bisect_dirblocks(paths)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
1840
        self.assertEqual(len(map_keys), len(paths))
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1841
        expected = {}
1842
        for path, keys in zip(paths, map_keys):
1843
            if keys is None:
1844
                # This should not be present in the output
1845
                continue
1846
            expected[path] = sorted(expected_map[k] for k in keys)
1847
        for path in result:
1848
            result[path].sort()
1849
1850
        self.assertEqual(expected, result)
2255.2.130 by John Arbash Meinel
Add a very similar function which grabs everything for a particular directory block.
1851
2255.2.132 by John Arbash Meinel
Implement _bisect_recursive, which uses multiple bisect calls to
1852
    def assertBisectRecursive(self, expected_map, map_keys, state, paths):
1853
        """Assert the return value of a recursive bisection.
1854
1855
        :param expected_map: A map from key => entry value
1856
        :param map_keys: A list of paths we expect to be returned.
1857
            Something like ['a', 'b', 'f', 'b/d', 'b/d2']
1858
        :param state: The DirState object.
1859
        :param paths: A list of files and directories. It will be broken up
1860
            into (dir, name) pairs and sorted before calling _bisect_recursive.
1861
        """
1862
        expected = {}
1863
        for key in map_keys:
1864
            entry = expected_map[key]
1865
            dir_name_id, trees_info = entry
1866
            expected[dir_name_id] = trees_info
1867
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1868
        result = state._bisect_recursive(paths)
2255.2.132 by John Arbash Meinel
Implement _bisect_recursive, which uses multiple bisect calls to
1869
1870
        self.assertEqual(expected, result)
1871
2255.3.2 by John Arbash Meinel
(broken) some basic work on adding bisect functionality to dirstate.
1872
    def test_bisect_each(self):
1873
        """Find a single record using bisect."""
2255.2.125 by John Arbash Meinel
Initial effort at adding a basic _bisect function to DirState.
1874
        tree, state, expected = self.create_basic_dirstate()
2255.3.2 by John Arbash Meinel
(broken) some basic work on adding bisect functionality to dirstate.
1875
1876
        # Bisect should return the rows for the specified files.
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1877
        self.assertBisect(expected, [['']], state, [''])
1878
        self.assertBisect(expected, [['a']], state, ['a'])
1879
        self.assertBisect(expected, [['b']], state, ['b'])
1880
        self.assertBisect(expected, [['b/c']], state, ['b/c'])
1881
        self.assertBisect(expected, [['b/d']], state, ['b/d'])
1882
        self.assertBisect(expected, [['b/d/e']], state, ['b/d/e'])
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1883
        self.assertBisect(expected, [['b-c']], state, ['b-c'])
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1884
        self.assertBisect(expected, [['f']], state, ['f'])
2255.2.125 by John Arbash Meinel
Initial effort at adding a basic _bisect function to DirState.
1885
1886
    def test_bisect_multi(self):
1887
        """Bisect can be used to find multiple records at the same time."""
1888
        tree, state, expected = self.create_basic_dirstate()
1889
        # Bisect should be capable of finding multiple entries at the same time
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1890
        self.assertBisect(expected, [['a'], ['b'], ['f']],
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1891
                          state, ['a', 'b', 'f'])
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1892
        self.assertBisect(expected, [['f'], ['b/d'], ['b/d/e']],
2474.1.61 by John Arbash Meinel
Finish fixing DirState._bisect and the bisect tests
1893
                          state, ['f', 'b/d', 'b/d/e'])
1894
        self.assertBisect(expected, [['b'], ['b-c'], ['b/c']],
1895
                          state, ['b', 'b-c', 'b/c'])
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1896
1897
    def test_bisect_one_page(self):
1898
        """Test bisect when there is only 1 page to read"""
1899
        tree, state, expected = self.create_basic_dirstate()
1900
        state._bisect_page_size = 5000
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1901
        self.assertBisect(expected,[['']], state, [''])
1902
        self.assertBisect(expected,[['a']], state, ['a'])
1903
        self.assertBisect(expected,[['b']], state, ['b'])
1904
        self.assertBisect(expected,[['b/c']], state, ['b/c'])
1905
        self.assertBisect(expected,[['b/d']], state, ['b/d'])
1906
        self.assertBisect(expected,[['b/d/e']], state, ['b/d/e'])
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1907
        self.assertBisect(expected,[['b-c']], state, ['b-c'])
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1908
        self.assertBisect(expected,[['f']], state, ['f'])
1909
        self.assertBisect(expected,[['a'], ['b'], ['f']],
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1910
                          state, ['a', 'b', 'f'])
2474.1.61 by John Arbash Meinel
Finish fixing DirState._bisect and the bisect tests
1911
        self.assertBisect(expected, [['b/d'], ['b/d/e'], ['f']],
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1912
                          state, ['b/d', 'b/d/e', 'f'])
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1913
        self.assertBisect(expected, [['b'], ['b/c'], ['b-c']],
1914
                          state, ['b', 'b/c', 'b-c'])
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1915
1916
    def test_bisect_duplicate_paths(self):
1917
        """When bisecting for a path, handle multiple entries."""
1918
        tree, state, expected = self.create_duplicated_dirstate()
1919
1920
        # Now make sure that both records are properly returned.
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1921
        self.assertBisect(expected, [['']], state, [''])
1922
        self.assertBisect(expected, [['a', 'a2']], state, ['a'])
1923
        self.assertBisect(expected, [['b', 'b2']], state, ['b'])
1924
        self.assertBisect(expected, [['b/c', 'b/c2']], state, ['b/c'])
1925
        self.assertBisect(expected, [['b/d', 'b/d2']], state, ['b/d'])
1926
        self.assertBisect(expected, [['b/d/e', 'b/d/e2']],
2255.2.129 by John Arbash Meinel
Start cleaning up the code, and fix one more edge case
1927
                          state, ['b/d/e'])
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1928
        self.assertBisect(expected, [['b-c', 'b-c2']], state, ['b-c'])
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1929
        self.assertBisect(expected, [['f', 'f2']], state, ['f'])
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1930
1931
    def test_bisect_page_size_too_small(self):
2255.2.128 by John Arbash Meinel
Rather than falling over when the page size is to small, just increase it and try again.
1932
        """If the page size is too small, we will auto increase it."""
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1933
        tree, state, expected = self.create_basic_dirstate()
1934
        state._bisect_page_size = 50
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1935
        self.assertBisect(expected, [None], state, ['b/e'])
1936
        self.assertBisect(expected, [['a']], state, ['a'])
1937
        self.assertBisect(expected, [['b']], state, ['b'])
1938
        self.assertBisect(expected, [['b/c']], state, ['b/c'])
1939
        self.assertBisect(expected, [['b/d']], state, ['b/d'])
1940
        self.assertBisect(expected, [['b/d/e']], state, ['b/d/e'])
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1941
        self.assertBisect(expected, [['b-c']], state, ['b-c'])
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1942
        self.assertBisect(expected, [['f']], state, ['f'])
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1943
1944
    def test_bisect_missing(self):
1945
        """Test that bisect return None if it cannot find a path."""
1946
        tree, state, expected = self.create_basic_dirstate()
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1947
        self.assertBisect(expected, [None], state, ['foo'])
1948
        self.assertBisect(expected, [None], state, ['b/foo'])
1949
        self.assertBisect(expected, [None], state, ['bar/foo'])
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1950
        self.assertBisect(expected, [None], state, ['b-c/foo'])
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1951
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1952
        self.assertBisect(expected, [['a'], None, ['b/d']],
2255.2.126 by John Arbash Meinel
Switch the bisect code to support the fact that we can have
1953
                          state, ['a', 'foo', 'b/d'])
2255.2.127 by John Arbash Meinel
Expand the test suite to cover more cases.
1954
1955
    def test_bisect_rename(self):
1956
        """Check that we find a renamed row."""
1957
        tree, state, expected = self.create_renamed_dirstate()
1958
1959
        # Search for the pre and post renamed entries
2255.2.131 by John Arbash Meinel
Change the return values for bisect functions so they just return
1960
        self.assertBisect(expected, [['a']], state, ['a'])
1961
        self.assertBisect(expected, [['b/g']], state, ['b/g'])
2255.2.132 by John Arbash Meinel
Implement _bisect_recursive, which uses multiple bisect calls to
1962
        self.assertBisect(expected, [['b/d']], state, ['b/d'])
1963
        self.assertBisect(expected, [['h']], state, ['h'])
1964
1965
        # What about b/d/e? shouldn't that also get 2 directory entries?
1966
        self.assertBisect(expected, [['b/d/e']], state, ['b/d/e'])
1967
        self.assertBisect(expected, [['h/e']], state, ['h/e'])
2255.2.130 by John Arbash Meinel
Add a very similar function which grabs everything for a particular directory block.
1968
1969
    def test_bisect_dirblocks(self):
1970
        tree, state, expected = self.create_duplicated_dirstate()
1971
        self.assertBisectDirBlocks(expected,
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1972
            [['', 'a', 'a2', 'b', 'b2', 'b-c', 'b-c2', 'f', 'f2']],
1973
            state, [''])
2255.2.130 by John Arbash Meinel
Add a very similar function which grabs everything for a particular directory block.
1974
        self.assertBisectDirBlocks(expected,
1975
            [['b/c', 'b/c2', 'b/d', 'b/d2']], state, ['b'])
1976
        self.assertBisectDirBlocks(expected,
1977
            [['b/d/e', 'b/d/e2']], state, ['b/d'])
1978
        self.assertBisectDirBlocks(expected,
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
1979
            [['', 'a', 'a2', 'b', 'b2', 'b-c', 'b-c2', 'f', 'f2'],
2255.2.130 by John Arbash Meinel
Add a very similar function which grabs everything for a particular directory block.
1980
             ['b/c', 'b/c2', 'b/d', 'b/d2'],
1981
             ['b/d/e', 'b/d/e2'],
1982
            ], state, ['', 'b', 'b/d'])
1983
1984
    def test_bisect_dirblocks_missing(self):
1985
        tree, state, expected = self.create_basic_dirstate()
1986
        self.assertBisectDirBlocks(expected, [['b/d/e'], None],
1987
            state, ['b/d', 'b/e'])
1988
        # Files don't show up in this search
1989
        self.assertBisectDirBlocks(expected, [None], state, ['a'])
1990
        self.assertBisectDirBlocks(expected, [None], state, ['b/c'])
1991
        self.assertBisectDirBlocks(expected, [None], state, ['c'])
1992
        self.assertBisectDirBlocks(expected, [None], state, ['b/d/e'])
1993
        self.assertBisectDirBlocks(expected, [None], state, ['f'])
2255.2.132 by John Arbash Meinel
Implement _bisect_recursive, which uses multiple bisect calls to
1994
1995
    def test_bisect_recursive_each(self):
1996
        tree, state, expected = self.create_basic_dirstate()
1997
        self.assertBisectRecursive(expected, ['a'], state, ['a'])
1998
        self.assertBisectRecursive(expected, ['b/c'], state, ['b/c'])
1999
        self.assertBisectRecursive(expected, ['b/d/e'], state, ['b/d/e'])
2474.1.58 by John Arbash Meinel
(broken) Try to properly implement DirState._bisect*
2000
        self.assertBisectRecursive(expected, ['b-c'], state, ['b-c'])
2255.2.132 by John Arbash Meinel
Implement _bisect_recursive, which uses multiple bisect calls to
2001
        self.assertBisectRecursive(expected, ['b/d', 'b/d/e'],
2002
                                   state, ['b/d'])
2003
        self.assertBisectRecursive(expected, ['b', 'b/c', 'b/d', 'b/d/e'],
2004
                                   state, ['b'])
2474.1.61 by John Arbash Meinel
Finish fixing DirState._bisect and the bisect tests
2005
        self.assertBisectRecursive(expected, ['', 'a', 'b', 'b-c', 'f', 'b/c',
2255.2.132 by John Arbash Meinel
Implement _bisect_recursive, which uses multiple bisect calls to
2006
                                              'b/d', 'b/d/e'],
2007
                                   state, [''])
2008
2009
    def test_bisect_recursive_multiple(self):
2010
        tree, state, expected = self.create_basic_dirstate()
2011
        self.assertBisectRecursive(expected, ['a', 'b/c'], state, ['a', 'b/c'])
2012
        self.assertBisectRecursive(expected, ['b/d', 'b/d/e'],
2013
                                   state, ['b/d', 'b/d/e'])
2014
2015
    def test_bisect_recursive_missing(self):
2016
        tree, state, expected = self.create_basic_dirstate()
2017
        self.assertBisectRecursive(expected, [], state, ['d'])
2018
        self.assertBisectRecursive(expected, [], state, ['b/e'])
2019
        self.assertBisectRecursive(expected, [], state, ['g'])
2020
        self.assertBisectRecursive(expected, ['a'], state, ['a', 'g'])
2021
2022
    def test_bisect_recursive_renamed(self):
2023
        tree, state, expected = self.create_renamed_dirstate()
2024
2025
        # Looking for either renamed item should find the other
2026
        self.assertBisectRecursive(expected, ['a', 'b/g'], state, ['a'])
2027
        self.assertBisectRecursive(expected, ['a', 'b/g'], state, ['b/g'])
2028
        # Looking in the containing directory should find the rename target,
2029
        # and anything in a subdir of the renamed target.
2030
        self.assertBisectRecursive(expected, ['a', 'b', 'b/c', 'b/d',
2031
                                              'b/d/e', 'b/g', 'h', 'h/e'],
2032
                                   state, ['b'])
2033
2255.8.2 by John Arbash Meinel
Add a helper function, which allows us to store keys as plain paths,
2034
2323.5.4 by Martin Pool
Move some dirstate test setup methods into the base class
2035
class TestDirstateValidation(TestCaseWithDirState):
2036
2037
    def test_validate_correct_dirstate(self):
2038
        state = self.create_complex_dirstate()
2039
        state._validate()
2040
        state.unlock()
2041
        # and make sure we can also validate with a read lock
2042
        state.lock_read()
2043
        try:
2044
            state._validate()
2045
        finally:
2046
            state.unlock()
2323.5.6 by Martin Pool
Add some tests and better messages for DirState._validate
2047
2048
    def test_dirblock_not_sorted(self):
2049
        tree, state, expected = self.create_renamed_dirstate()
2050
        state._read_dirblocks_if_needed()
2051
        last_dirblock = state._dirblocks[-1]
2052
        # we're appending to the dirblock, but this name comes before some of
2053
        # the existing names; that's wrong
2054
        last_dirblock[1].append(
2055
            (('h', 'aaaa', 'a-id'),
2056
             [('a', '', 0, False, ''),
2057
              ('a', '', 0, False, '')]))
2058
        e = self.assertRaises(AssertionError,
2059
            state._validate)
2060
        self.assertContainsRe(str(e), 'not sorted')
2061
2062
    def test_dirblock_name_mismatch(self):
2063
        tree, state, expected = self.create_renamed_dirstate()
2064
        state._read_dirblocks_if_needed()
2065
        last_dirblock = state._dirblocks[-1]
2066
        # add an entry with the wrong directory name
2067
        last_dirblock[1].append(
2068
            (('', 'z', 'a-id'),
2069
             [('a', '', 0, False, ''),
2070
              ('a', '', 0, False, '')]))
2071
        e = self.assertRaises(AssertionError,
2072
            state._validate)
2073
        self.assertContainsRe(str(e),
2074
            "doesn't match directory name")
2075
2323.5.7 by Martin Pool
Better DirState._validate and tests for it.
2076
    def test_dirblock_missing_rename(self):
2077
        tree, state, expected = self.create_renamed_dirstate()
2078
        state._read_dirblocks_if_needed()
2079
        last_dirblock = state._dirblocks[-1]
2323.5.6 by Martin Pool
Add some tests and better messages for DirState._validate
2080
        # make another entry for a-id, without a correct 'r' pointer to
2081
        # the real occurrence in the working tree
2323.5.7 by Martin Pool
Better DirState._validate and tests for it.
2082
        last_dirblock[1].append(
2083
            (('h', 'z', 'a-id'),
2084
             [('a', '', 0, False, ''),
2085
              ('a', '', 0, False, '')]))
2086
        e = self.assertRaises(AssertionError,
2087
            state._validate)
2088
        self.assertContainsRe(str(e),
2089
            'file a-id is absent in row')
2474.1.41 by John Arbash Meinel
Change the name of cmp_dirblock_strings to cmp_by_dirs
2090
2645.2.1 by Wouter van Heyst
The DirState fingerprint for tree-references should be an empty string instead of None
2091
2092
class TestDirstateTreeReference(TestCaseWithDirState):
2093
2094
    def test_reference_revision_is_none(self):
2095
        tree = self.make_branch_and_tree('tree', format='dirstate-with-subtree')
2096
        subtree = self.make_branch_and_tree('tree/subtree',
2097
                            format='dirstate-with-subtree')
2098
        subtree.set_root_id('subtree')
2099
        tree.add_reference(subtree)
2100
        tree.add('subtree')
2101
        state = dirstate.DirState.from_tree(tree, 'dirstate')
2102
        key = ('', 'subtree', 'subtree')
2103
        expected = ('', [(key,
2104
            [('t', '', 0, False, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')])])
2105
2106
        try:
2107
            self.assertEqual(expected, state._find_block(key))
2108
        finally:
2109
            state.unlock()
2984.1.1 by John Arbash Meinel
Fix bug #161131: Correct DirState._discard_merge_parents logic.
2110
2111
2112
class TestDiscardMergeParents(TestCaseWithDirState):
2113
2114
    def test_discard_no_parents(self):
2115
        # This should be a no-op
2116
        state = self.create_empty_dirstate()
2117
        self.addCleanup(state.unlock)
2118
        state._discard_merge_parents()
2119
        state._validate()
2120
2121
    def test_discard_one_parent(self):
2122
        # No-op
2123
        packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
2124
        root_entry_direntry = ('', '', 'a-root-value'), [
2125
            ('d', '', 0, False, packed_stat),
2126
            ('d', '', 0, False, packed_stat),
2127
            ]
2128
        dirblocks = []
2129
        dirblocks.append(('', [root_entry_direntry]))
2130
        dirblocks.append(('', []))
2131
2132
        state = self.create_empty_dirstate()
2133
        self.addCleanup(state.unlock)
2134
        state._set_data(['parent-id'], dirblocks[:])
2135
        state._validate()
2136
2137
        state._discard_merge_parents()
2138
        state._validate()
2139
        self.assertEqual(dirblocks, state._dirblocks)
2140
2141
    def test_discard_simple(self):
2142
        # No-op
2143
        packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
2144
        root_entry_direntry = ('', '', 'a-root-value'), [
2145
            ('d', '', 0, False, packed_stat),
2146
            ('d', '', 0, False, packed_stat),
2147
            ('d', '', 0, False, packed_stat),
2148
            ]
2149
        expected_root_entry_direntry = ('', '', 'a-root-value'), [
2150
            ('d', '', 0, False, packed_stat),
2151
            ('d', '', 0, False, packed_stat),
2152
            ]
2153
        dirblocks = []
2154
        dirblocks.append(('', [root_entry_direntry]))
2155
        dirblocks.append(('', []))
2156
2157
        state = self.create_empty_dirstate()
2158
        self.addCleanup(state.unlock)
2159
        state._set_data(['parent-id', 'merged-id'], dirblocks[:])
2160
        state._validate()
2161
2162
        # This should strip of the extra column
2163
        state._discard_merge_parents()
2164
        state._validate()
2165
        expected_dirblocks = [('', [expected_root_entry_direntry]), ('', [])]
2166
        self.assertEqual(expected_dirblocks, state._dirblocks)
2167
2168
    def test_discard_absent(self):
2169
        """If entries are only in a merge, discard should remove the entries"""
2170
        null_stat = dirstate.DirState.NULLSTAT
2171
        present_dir = ('d', '', 0, False, null_stat)
2172
        present_file = ('f', '', 0, False, null_stat)
2173
        absent = dirstate.DirState.NULL_PARENT_DETAILS
2174
        root_key = ('', '', 'a-root-value')
2175
        file_in_root_key = ('', 'file-in-root', 'a-file-id')
2176
        file_in_merged_key = ('', 'file-in-merged', 'b-file-id')
2177
        dirblocks = [('', [(root_key, [present_dir, present_dir, present_dir])]),
2178
                     ('', [(file_in_merged_key,
2179
                            [absent, absent, present_file]),
2180
                           (file_in_root_key,
2181
                            [present_file, present_file, present_file]),
2182
                          ]),
2183
                    ]
2184
2185
        state = self.create_empty_dirstate()
2186
        self.addCleanup(state.unlock)
2187
        state._set_data(['parent-id', 'merged-id'], dirblocks[:])
2188
        state._validate()
2189
2190
        exp_dirblocks = [('', [(root_key, [present_dir, present_dir])]),
2191
                         ('', [(file_in_root_key,
2192
                                [present_file, present_file]),
2193
                              ]),
2194
                        ]
2195
        state._discard_merge_parents()
2196
        state._validate()
2197
        self.assertEqual(exp_dirblocks, state._dirblocks)
2198
2199
    def test_discard_renamed(self):
2200
        null_stat = dirstate.DirState.NULLSTAT
2201
        present_dir = ('d', '', 0, False, null_stat)
2202
        present_file = ('f', '', 0, False, null_stat)
2203
        absent = dirstate.DirState.NULL_PARENT_DETAILS
2204
        root_key = ('', '', 'a-root-value')
2205
        file_in_root_key = ('', 'file-in-root', 'a-file-id')
2206
        # Renamed relative to parent
2207
        file_rename_s_key = ('', 'file-s', 'b-file-id')
2208
        file_rename_t_key = ('', 'file-t', 'b-file-id')
2209
        # And one that is renamed between the parents, but absent in this
2210
        key_in_1 = ('', 'file-in-1', 'c-file-id')
2211
        key_in_2 = ('', 'file-in-2', 'c-file-id')
2212
2213
        dirblocks = [
2214
            ('', [(root_key, [present_dir, present_dir, present_dir])]),
2215
            ('', [(key_in_1,
2216
                   [absent, present_file, ('r', 'file-in-2', 'c-file-id')]),
2217
                  (key_in_2,
2218
                   [absent, ('r', 'file-in-1', 'c-file-id'), present_file]),
2219
                  (file_in_root_key,
2220
                   [present_file, present_file, present_file]),
2221
                  (file_rename_s_key,
2222
                   [('r', 'file-t', 'b-file-id'), absent, present_file]),
2223
                  (file_rename_t_key,
2224
                   [present_file, absent, ('r', 'file-s', 'b-file-id')]),
2225
                 ]),
2226
        ]
2227
        exp_dirblocks = [
2228
            ('', [(root_key, [present_dir, present_dir])]),
2229
            ('', [(key_in_1, [absent, present_file]),
2230
                  (file_in_root_key, [present_file, present_file]),
2231
                  (file_rename_t_key, [present_file, absent]),
2232
                 ]),
2233
        ]
2234
        state = self.create_empty_dirstate()
2235
        self.addCleanup(state.unlock)
2236
        state._set_data(['parent-id', 'merged-id'], dirblocks[:])
2237
        state._validate()
2238
2239
        state._discard_merge_parents()
2240
        state._validate()
2241
        self.assertEqual(exp_dirblocks, state._dirblocks)
2242
2243
    def test_discard_all_subdir(self):
2244
        null_stat = dirstate.DirState.NULLSTAT
2245
        present_dir = ('d', '', 0, False, null_stat)
2246
        present_file = ('f', '', 0, False, null_stat)
2247
        absent = dirstate.DirState.NULL_PARENT_DETAILS
2248
        root_key = ('', '', 'a-root-value')
2249
        subdir_key = ('', 'sub', 'dir-id')
2250
        child1_key = ('sub', 'child1', 'child1-id')
2251
        child2_key = ('sub', 'child2', 'child2-id')
2252
        child3_key = ('sub', 'child3', 'child3-id')
2253
2254
        dirblocks = [
2255
            ('', [(root_key, [present_dir, present_dir, present_dir])]),
2256
            ('', [(subdir_key, [present_dir, present_dir, present_dir])]),
2257
            ('sub', [(child1_key, [absent, absent, present_file]),
2258
                     (child2_key, [absent, absent, present_file]),
2259
                     (child3_key, [absent, absent, present_file]),
2260
                    ]),
2261
        ]
2262
        exp_dirblocks = [
2263
            ('', [(root_key, [present_dir, present_dir])]),
2264
            ('', [(subdir_key, [present_dir, present_dir])]),
2265
            ('sub', []),
2266
        ]
2267
        state = self.create_empty_dirstate()
2268
        self.addCleanup(state.unlock)
2269
        state._set_data(['parent-id', 'merged-id'], dirblocks[:])
2270
        state._validate()
2271
2272
        state._discard_merge_parents()
2273
        state._validate()
2274
        self.assertEqual(exp_dirblocks, state._dirblocks)
3477.2.1 by John Arbash Meinel
Assert that we properly encode inv_entry.symlink_target, (bug #135320)
2275
2276
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
2277
class Test_InvEntryToDetails(tests.TestCase):
3477.2.1 by John Arbash Meinel
Assert that we properly encode inv_entry.symlink_target, (bug #135320)
2278
2279
    def assertDetails(self, expected, inv_entry):
2280
        details = dirstate.DirState._inv_entry_to_details(inv_entry)
2281
        self.assertEqual(expected, details)
3477.2.2 by John Arbash Meinel
Change how we handle unicode targets, and add a NEWS entry.
2282
        # details should always allow join() and always be a plain str when
2283
        # finished
2284
        (minikind, fingerprint, size, executable, tree_data) = details
2285
        self.assertIsInstance(minikind, str)
2286
        self.assertIsInstance(fingerprint, str)
2287
        self.assertIsInstance(tree_data, str)
3477.2.1 by John Arbash Meinel
Assert that we properly encode inv_entry.symlink_target, (bug #135320)
2288
2289
    def test_unicode_symlink(self):
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
2290
        inv_entry = inventory.InventoryLink('link-file-id',
2291
                                            u'nam\N{Euro Sign}e',
3477.2.1 by John Arbash Meinel
Assert that we properly encode inv_entry.symlink_target, (bug #135320)
2292
                                            'link-parent-id')
2293
        inv_entry.revision = 'link-revision-id'
4241.14.10 by Vincent Ladeuil
Add DirReader parametrized tests.
2294
        target = u'link-targ\N{Euro Sign}t'
2295
        inv_entry.symlink_target = target
2296
        self.assertDetails(('l', target.encode('UTF-8'), 0, False,
2297
                            'link-revision-id'), inv_entry)
2298
2299
2300
class TestSHA1Provider(tests.TestCaseInTempDir):
4132.2.1 by Ian Clatworthy
make sha1_provider a parameter to DirState()
2301
2302
    def test_sha1provider_is_an_interface(self):
4132.2.5 by Ian Clatworthy
feedback from poolie - use SHA, not Sha, in class names
2303
        p = dirstate.SHA1Provider()
4132.2.1 by Ian Clatworthy
make sha1_provider a parameter to DirState()
2304
        self.assertRaises(NotImplementedError, p.sha1, "foo")
2305
        self.assertRaises(NotImplementedError, p.stat_and_sha1, "foo")
2306
2307
    def test_defaultsha1provider_sha1(self):
2308
        text = 'test\r\nwith\nall\rpossible line endings\r\n'
2309
        self.build_tree_contents([('foo', text)])
2310
        expected_sha = osutils.sha_string(text)
4132.2.5 by Ian Clatworthy
feedback from poolie - use SHA, not Sha, in class names
2311
        p = dirstate.DefaultSHA1Provider()
4132.2.1 by Ian Clatworthy
make sha1_provider a parameter to DirState()
2312
        self.assertEqual(expected_sha, p.sha1('foo'))
2313
2314
    def test_defaultsha1provider_stat_and_sha1(self):
2315
        text = 'test\r\nwith\nall\rpossible line endings\r\n'
2316
        self.build_tree_contents([('foo', text)])
2317
        expected_sha = osutils.sha_string(text)
4132.2.5 by Ian Clatworthy
feedback from poolie - use SHA, not Sha, in class names
2318
        p = dirstate.DefaultSHA1Provider()
4132.2.1 by Ian Clatworthy
make sha1_provider a parameter to DirState()
2319
        statvalue, sha1 = p.stat_and_sha1('foo')
2320
        self.assertTrue(len(statvalue) >= 10)
2321
        self.assertEqual(len(text), statvalue.st_size)
2322
        self.assertEqual(expected_sha, sha1)