1
# Copyright (C) 2006 by Canonical Ltd
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.
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.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Tests of the dirstate functionality being built for WorkingTreeFormat4."""
21
from bzrlib import dirstate, errors
22
from bzrlib.dirstate import DirState
23
from bzrlib.memorytree import MemoryTree
24
from bzrlib.tests import TestCaseWithTransport
28
# test DirStateRevisionTree : test filtering out of deleted files does not
29
# filter out files called RECYCLED.BIN ;)
30
# test 0 parents, 1 parent, 4 parents.
31
# test unicode parents, non unicode parents
32
# test all change permutations in one and two parents.
33
# i.e. file in parent 1, dir in parent 2, symlink in tree.
34
# test that renames in the tree result in correct parent paths
35
# Test get state from a file, then asking for lines.
36
# write a smaller state, and check the file has been truncated.
37
# add a entry when its in state deleted
38
# revision attribute for root entries.
39
# test that utf8 strings are preserved in _row_to_line
40
# test parent manipulation
41
# test parents that are null in save : i.e. no record in the parent tree for this.
42
# todo: _set_data records ghost parents.
44
# general checks for NOT_IN_MEMORY error conditions.
45
# set_path_id on a NOT_IN_MEMORY dirstate
46
# set_path_id unicode support
47
# set_path_id setting id of a path not root
48
# set_path_id setting id when there are parents without the id in the parents
49
# set_path_id setting id when there are parents with the id in the parents
50
# set_path_id setting id when state is not in memory
51
# set_path_id setting id when state is in memory unmodified
52
# set_path_id setting id when state is in memory modified
54
class TestTreeToDirstate(TestCaseWithTransport):
56
def test_empty_to_dirstate(self):
57
"""We should be able to create a dirstate for an empty tree."""
58
# There are no files on disk and no parents
59
tree = self.make_branch_and_tree('tree')
60
state = dirstate.DirState.from_tree(tree, 'dirstate')
62
# an inner function because there is no parameterisation at this point
63
# if we make it reusable that would be a good thing.
64
self.assertEqual([], state.get_parent_ids())
65
# there should be no ghosts in this tree.
66
self.assertEqual([], state.get_ghosts())
67
# there should be one fileid in this tree - the root of the tree.
68
root_stat_pack = dirstate.pack_stat(os.stat(tree.basedir))
70
[(('', '', 'directory', tree.inventory.root.file_id, 0, root_stat_pack, ''), [])],
71
list(state._iter_rows()))
73
state = dirstate.DirState.on_file('dirstate')
76
def test_1_parents_empty_to_dirstate(self):
77
# create a parent by doing a commit
78
tree = self.make_branch_and_tree('tree')
79
rev_id = tree.commit('first post')
80
state = dirstate.DirState.from_tree(tree, 'dirstate')
81
# we want to be able to get the lines of the dirstate that we will
83
lines = state.get_lines()
84
# we now have parent revisions, and all the files in the tree were
85
# last modified in the parent.
87
'#bazaar dirstate flat format 1\n'
88
'adler32: [0-9-][0-9]*\n'
92
'\x00\x00d\x00TREE_ROOT\x00[0-9]+\x00[0-9a-zA-Z+/]{32}\x00\x00%s\x00d\x00\x00\x00\x00n\x00\x00\n'
93
'\x00$') % rev_id.encode('utf8')
94
self.assertContainsRe(''.join(lines), expected_lines_re)
96
def test_2_parents_empty_to_dirstate(self):
97
# create a parent by doing a commit
98
tree = self.make_branch_and_tree('tree')
99
rev_id = tree.commit('first post')
100
tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
101
rev_id2 = tree2.commit('second post', allow_pointless=True)
102
tree.merge_from_branch(tree2.branch)
103
state = dirstate.DirState.from_tree(tree, 'dirstate')
104
# we want to be able to get the lines of the dirstate that we will
106
lines = state.get_lines()
107
# we now have parent revisions, and all the files in the tree were
108
# last modified in the parent.
109
expected_lines_re = (
110
'#bazaar dirstate flat format 1\n'
111
'adler32: [0-9-][0-9]*\n'
113
'2\x00.*\x00.*\x00\n\x00'
115
'\x00\x00d\x00TREE_ROOT\x000\x00[0-9a-zA-Z+/]{32}\x00\x00%s\x00d\x00\x00\x00\x00n\x00\x00%s\x00d\x00\x00\x00\x00n\x00\x00\n'
116
'\x00$') % (rev_id.encode('utf8'), rev_id2.encode('utf8'))
117
self.assertContainsRe(''.join(lines), expected_lines_re)
119
def test_empty_unknowns_are_ignored_to_dirstate(self):
120
"""We should be able to create a dirstate for an empty tree."""
121
# There are no files on disk and no parents
122
tree = self.make_branch_and_tree('tree')
123
self.build_tree(['tree/unknown'])
124
state = dirstate.DirState.from_tree(tree, 'dirstate')
125
# we want to be able to get the lines of the dirstate that we will
127
lines = state.get_lines()
128
expected_lines_re = (
129
'#bazaar dirstate flat format 1\n'
130
'adler32: [0-9-][0-9]*\n'
134
'\x00\x00d\x00TREE_ROOT\x00[0-9]+\x00[0-9a-zA-Z+/]{32}\x00\x00\n'
136
self.assertContainsRe(''.join(lines), expected_lines_re)
138
def get_tree_with_a_file(self):
139
tree = self.make_branch_and_tree('tree')
140
self.build_tree(['tree/a file'])
141
tree.add('a file', 'a file id')
144
def test_non_empty_no_parents_to_dirstate(self):
145
"""We should be able to create a dirstate for an empty tree."""
146
# There are files on disk and no parents
147
tree = self.get_tree_with_a_file()
148
state = dirstate.DirState.from_tree(tree, 'dirstate')
149
# we want to be able to get the lines of the dirstate that we will
151
lines = state.get_lines()
152
expected_lines_re = (
153
'#bazaar dirstate flat format 1\n'
154
'adler32: [0-9-][0-9]*\n'
158
'\x00\x00d\x00TREE_ROOT\x00[0-9]+\x00[0-9a-zA-Z+/]{32}\x00\x00\n'
159
'\x00\x00a file\x00f\x00a file id\x0024\x00[0-9a-zA-Z+/]{32}\x00c3ed76e4bfd45ff1763ca206055bca8e9fc28aa8\x00'
161
self.assertContainsRe(''.join(lines), expected_lines_re)
163
def test_1_parents_not_empty_to_dirstate(self):
164
# create a parent by doing a commit
165
tree = self.get_tree_with_a_file()
166
rev_id = tree.commit('first post')
167
# change the current content to be different this will alter stat, sha
169
self.build_tree_contents([('tree/a file', 'new content\n')])
170
state = dirstate.DirState.from_tree(tree, 'dirstate')
171
# we want to be able to get the lines of the dirstate that we will
173
lines = state.get_lines()
174
# we now have parent revisions, and all the files in the tree were
175
# last modified in the parent.
176
expected_lines_re = (
177
'#bazaar dirstate flat format 1\n'
178
'adler32: [0-9-][0-9]*\n'
182
'\x00\x00d\x00TREE_ROOT\x00[0-9]+\x00[0-9a-zA-Z+/]{32}\x00\x00%s\x00d\x00\x00\x00\x00n\x00\x00\n'
183
'\x00\x00a file\x00f\x00a file id\x0012\x00[0-9a-zA-Z+/]{32}\x008b787bd9293c8b962c7a637a9fdbf627fe68610e\x00%s\x00f\x00\x00a file\x0024\x00n\x00c3ed76e4bfd45ff1763ca206055bca8e9fc28aa8\x00\n'
184
'\x00$') % (rev_id.encode('utf8'), rev_id.encode('utf8'))
185
self.assertContainsRe(''.join(lines), expected_lines_re)
187
def test_2_parents_not_empty_to_dirstate(self):
188
# create a parent by doing a commit
189
tree = self.get_tree_with_a_file()
190
rev_id = tree.commit('first post')
191
tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
192
# change the current content to be different this will alter stat, sha
194
self.build_tree_contents([('tree2/a file', 'merge content\n')])
195
rev_id2 = tree2.commit('second post')
196
tree.merge_from_branch(tree2.branch)
197
# change the current content to be different this will alter stat, sha
198
# and length again, giving us three distinct values:
199
self.build_tree_contents([('tree/a file', 'new content\n')])
200
state = dirstate.DirState.from_tree(tree, 'dirstate')
201
# we want to be able to get the lines of the dirstate that we will
203
lines = state.get_lines()
204
# we now have parent revisions, and all the files in the tree were
205
# last modified in the parent.
206
expected_lines_re = (
207
'#bazaar dirstate flat format 1\n'
208
'adler32: [0-9-][0-9]*\n'
210
'2\x00.*\x00.*\x00\n\x00'
212
'\x00\x00d\x00TREE_ROOT\x000\x00[0-9a-zA-Z+/]{32}\x00\x00%s\x00d\x00\x00\x00\x00n\x00\x00%s\x00d\x00\x00\x00\x00n\x00\x00\n\x00'
213
'\x00a file\x00f\x00a file id\x0012\x00[0-9a-zA-Z+/]{32}\x008b787bd9293c8b962c7a637a9fdbf627fe68610e\x00%s\x00f\x00\x00a file\x0024\x00n\x00c3ed76e4bfd45ff1763ca206055bca8e9fc28aa8\x00%s\x00f\x00\x00a file\x0014\x00n\x00314d796174c9412647c3ce07dfb5d36a94e72958\x00\n\x00$'
214
% (rev_id.encode('utf8'), rev_id2.encode('utf8'),
215
rev_id.encode('utf8'), rev_id2.encode('utf8')))
216
self.assertContainsRe(''.join(lines), expected_lines_re)
219
class TestDirStateOnFile(TestCaseWithTransport):
221
def test_construct_with_path(self):
222
tree = self.make_branch_and_tree('tree')
223
state = dirstate.DirState.from_tree(tree, 'dirstate')
224
# we want to be able to get the lines of the dirstate that we will
226
lines = state.get_lines()
227
self.build_tree_contents([('dirstate', ''.join(lines))])
229
state = dirstate.DirState.on_file('dirstate')
230
# ask it for a parents list
231
self.assertEqual([], state.get_parent_ids())
232
# doing a save should work here as there have been no changes.
236
class TestDirStateInitialize(TestCaseWithTransport):
238
def test_initialize(self):
239
state = dirstate.DirState.initialize('dirstate')
240
self.assertIsInstance(state, dirstate.DirState)
241
self.assertFileEqual(
242
'#bazaar dirstate flat format 1\n'
243
'adler32: -455929114\n'
247
# after the 0 parent count, there is the \x00\n\x00 line delim
248
# then '' for dir, '' for basame, and then 'd' for directory.
249
# then the root value, 0 size, our constant xxxx packed stat, and
250
# an empty sha value. Finally a new \x00\n\x00 delimiter
251
'\x00\x00d\x00TREE_ROOT\x000\x00xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\x00\x00\n'
255
(('', '', 'directory', 'TREE_ROOT', 0, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ''), [])]
256
self.assertEqual(expected_rows, list(state._iter_rows()))
257
state = dirstate.DirState.on_file('dirstate')
258
self.assertEqual(expected_rows, list(state._iter_rows()))
261
class TestDirstateManipulations(TestCaseWithTransport):
263
def test_add_ghost_tree(self):
264
state = dirstate.DirState.initialize('dirstate')
265
state.add_parent_tree('a-ghost', None)
266
# now the parent list should be changed:
267
self.assertEqual(['a-ghost'], state.get_parent_ids())
268
self.assertEqual(['a-ghost'], state.get_ghosts())
269
# save the state and reopen to check its persistent
271
state = dirstate.DirState.on_file('dirstate')
272
self.assertEqual(['a-ghost'], state.get_parent_ids())
273
self.assertEqual(['a-ghost'], state.get_ghosts())
275
def test_set_state_from_inventory_no_content_no_parents(self):
276
# setting the current inventory is a slow but important api to support.
277
state = dirstate.DirState.initialize('dirstate')
278
tree1 = self.make_branch_and_memory_tree('tree1')
281
revid1 = tree1.commit('foo')
282
root_id = tree1.inventory.root.file_id
283
state.set_state_from_inventory(tree1.inventory)
285
self.assertEqual(DirState.IN_MEMORY_UNMODIFIED, state._header_state)
286
self.assertEqual(DirState.IN_MEMORY_MODIFIED, state._dirblock_state)
287
expected_rows = [(('', '', 'directory', root_id, 0, DirState.NULLSTAT, ''), [])]
288
self.assertEqual(expected_rows, list(state._iter_rows()))
289
# check we can reopen and have the change preserved.
291
state = dirstate.DirState.on_file('dirstate')
292
self.assertEqual(expected_rows, list(state._iter_rows()))
294
def test_set_path_id_no_parents(self):
295
"""The id of a path can be changed trivally with no parents."""
296
state = dirstate.DirState.initialize('dirstate')
297
# check precondition to be sure the state does change appropriately.
299
[(('', '', 'directory', 'TREE_ROOT', 0, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ''), [])],
300
list(state._iter_rows()))
301
state.set_path_id('', 'foobarbaz')
303
(('', '', 'directory', 'foobarbaz', 0, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ''), [])]
304
self.assertEqual(expected_rows, list(state._iter_rows()))
305
# should work across save too
307
state = dirstate.DirState.on_file('dirstate')
308
self.assertEqual(expected_rows, list(state._iter_rows()))
310
def test_set_parent_trees_no_content(self):
311
# set_parent_trees is a slow but important api to support.
312
state = dirstate.DirState.initialize('dirstate')
313
tree1 = self.make_branch_and_memory_tree('tree1')
316
revid1 = tree1.commit('foo')
318
branch2 = tree1.branch.bzrdir.clone('tree2').open_branch()
319
tree2 = MemoryTree.create_on_branch(branch2)
321
revid2 = tree2.commit('foo')
322
root_id = tree2.inventory.root.file_id
323
state.set_path_id('', root_id)
325
state.set_parent_trees(
326
((revid1, tree1.branch.repository.revision_tree(revid1)),
327
(revid2, tree2.branch.repository.revision_tree(revid2)),
328
('ghost-rev', None)),
330
# check we can reopen and use the dirstate after setting parent trees.
332
state = dirstate.DirState.on_file('dirstate')
333
self.assertEqual([revid1, revid2, 'ghost-rev'], state.get_parent_ids())
334
# iterating the entire state ensures that the state is parsable.
335
list(state._iter_rows())
336
# be sure that it sets not appends - change it
337
state.set_parent_trees(
338
((revid1, tree1.branch.repository.revision_tree(revid1)),
339
('ghost-rev', None)),
341
# and now put it back.
342
state.set_parent_trees(
343
((revid1, tree1.branch.repository.revision_tree(revid1)),
344
(revid2, tree2.branch.repository.revision_tree(revid2)),
345
('ghost-rev', tree2.branch.repository.revision_tree(None))),
347
self.assertEqual([revid1, revid2, 'ghost-rev'], state.get_parent_ids())
348
# the ghost should be recorded as such by set_parent_trees.
349
self.assertEqual(['ghost-rev'], state.get_ghosts())
351
[(('', '', 'directory', root_id, 0, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ''), [
352
(revid1, 'directory', '', '', 0, False, ''),
353
(revid2, 'directory', '', '', 0, False, '')])],
354
list(state._iter_rows()))
356
def test_set_parent_trees_file_missing_from_tree(self):
357
# Adding a parent tree may reference files not in the current state.
358
# they should get listed just once by id, even if they are in two
360
# set_parent_trees is a slow but important api to support.
361
state = dirstate.DirState.initialize('dirstate')
362
tree1 = self.make_branch_and_memory_tree('tree1')
365
tree1.add(['a file'], ['file-id'], ['file'])
366
tree1.put_file_bytes_non_atomic('file-id', 'file-content')
367
revid1 = tree1.commit('foo')
369
branch2 = tree1.branch.bzrdir.clone('tree2').open_branch()
370
tree2 = MemoryTree.create_on_branch(branch2)
372
tree2.put_file_bytes_non_atomic('file-id', 'new file-content')
373
revid2 = tree2.commit('foo')
374
root_id = tree2.inventory.root.file_id
375
state.set_path_id('', root_id)
377
state.set_parent_trees(
378
((revid1, tree1.branch.repository.revision_tree(revid1)),
379
(revid2, tree2.branch.repository.revision_tree(revid2)),
381
# check the layout in memory
383
(('', '', 'directory', root_id, 0, DirState.NULLSTAT, ''),
384
[(revid1.encode('utf8'), 'directory', '', '', 0, False, ''),
385
(revid2.encode('utf8'), 'directory', '', '', 0, False, '')]),
386
(('/', 'RECYCLED.BIN', 'file', 'file-id', 0, DirState.NULLSTAT, ''),
387
[(revid1.encode('utf8'), 'file', '', 'a file', 12, False, '2439573625385400f2a669657a7db6ae7515d371'),
388
(revid2.encode('utf8'), 'file', '', 'a file', 16, False, '542e57dc1cda4af37cb8e55ec07ce60364bb3c7d')])
390
self.assertEqual(expected_rows, list(state._iter_rows()))
391
# check we can reopen and use the dirstate after setting parent trees.
393
state = dirstate.DirState.on_file('dirstate')
394
self.assertEqual(expected_rows, list(state._iter_rows()))
396
### add a path via _set_data - so we dont need delta work, just
397
# raw data in, and ensure that it comes out via get_lines happily.
399
def test_add_path_to_root_no_parents_all_data(self):
400
# The most trivial addition of a path is when there are no parents and
401
# its in the root and all data about the file is supplied
402
state = dirstate.DirState.initialize('dirstate')
403
self.build_tree(['a file'])
404
stat = os.lstat('a file')
405
# the 1*20 is the sha1 pretend value.
406
state.add('a file', 'a file id', 'file', stat, '1'*20)
407
# having added it, it should be in the output of iter_rows.
409
(('', '', 'directory', 'TREE_ROOT', 0, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ''), []),
410
(('', 'a file', 'file', 'a file id', 19, dirstate.pack_stat(stat), '1'*20), []),
412
self.assertEqual(expected_rows, list(state._iter_rows()))
413
# saving and reloading should not affect this.
415
state = dirstate.DirState.on_file('dirstate')
416
self.assertEqual(expected_rows, list(state._iter_rows()))
418
def test_add_path_to_unversioned_directory(self):
419
"""Adding a path to an unversioned directory should error."""
420
state = dirstate.DirState.initialize('dirstate')
421
self.build_tree(['unversioned/', 'unversioned/a file'])
422
self.assertRaises(errors.NoSuchFile, state.add, 'unversioned/a file',
423
'a file id', 'file', None, None)
425
def test_add_directory_to_root_no_parents_all_data(self):
426
# The most trivial addition of a dir is when there are no parents and
427
# its in the root and all data about the file is supplied
428
state = dirstate.DirState.initialize('dirstate')
429
self.build_tree(['a dir/'])
430
stat = os.lstat('a dir')
431
state.add('a dir', 'a dir id', 'directory', stat, None)
432
# having added it, it should be in the output of iter_rows.
434
(('', '', 'directory', 'TREE_ROOT', 0, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ''), []),
435
(('', 'a dir', 'directory', 'a dir id', 0, dirstate.pack_stat(stat), ''), []),
437
self.assertEqual(expected_rows, list(state._iter_rows()))
438
# saving and reloading should not affect this.
440
state = dirstate.DirState.on_file('dirstate')
441
self.assertEqual(expected_rows, list(state._iter_rows()))
443
def test_add_symlink_to_root_no_parents_all_data(self):
444
# The most trivial addition of a symlink when there are no parents and
445
# its in the root and all data about the file is supplied
446
state = dirstate.DirState.initialize('dirstate')
447
## TODO: windows: dont fail this test. Also, how are symlinks meant to
448
# be represented on windows.
449
os.symlink('target', 'a link')
450
stat = os.lstat('a link')
451
state.add('a link', 'a link id', 'symlink', stat, 'target')
452
# having added it, it should be in the output of iter_rows.
454
(('', '', 'directory', 'TREE_ROOT', 0, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ''), []),
455
(('', 'a link', 'symlink', 'a link id', 6, dirstate.pack_stat(stat), 'target'), []),
457
self.assertEqual(expected_rows, list(state._iter_rows()))
458
# saving and reloading should not affect this.
460
state = dirstate.DirState.on_file('dirstate')
461
self.assertEqual(expected_rows, list(state._iter_rows()))
463
def test_add_directory_and_child_no_parents_all_data(self):
464
# after adding a directory, we should be able to add children to it.
465
state = dirstate.DirState.initialize('dirstate')
466
self.build_tree(['a dir/', 'a dir/a file'])
467
stat = os.lstat('a dir')
468
state.add('a dir', 'a dir id', 'directory', stat, None)
469
filestat = os.lstat('a dir/a file')
470
state.add('a dir/a file', 'a file id', 'file', filestat, '1'*20)
471
# having added it, it should be in the output of iter_rows.
473
(('', '', 'directory', 'TREE_ROOT', 0, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ''), []),
474
(('', 'a dir', 'directory', 'a dir id', 0, dirstate.pack_stat(stat), ''), []),
475
(('a dir', 'a file', 'file', 'a file id', 25, dirstate.pack_stat(filestat), '1'*20), []),
477
self.assertEqual(expected_rows, list(state._iter_rows()))
478
# saving and reloading should not affect this.
480
state = dirstate.DirState.on_file('dirstate')
481
self.assertEqual(expected_rows, list(state._iter_rows()))
484
class TestGetLines(TestCaseWithTransport):
486
def test_adding_ghost_tree_sets_ghosts_line(self):
487
state = dirstate.DirState.initialize('dirstate')
488
state.add_parent_tree('a-ghost', None)
489
self.assertEqual(['#bazaar dirstate flat format 1\n',
490
'adler32: 1202264142\n',
492
'1\x00a-ghost\x00\n\x00'
493
'1\x00a-ghost\x00\n\x00'
494
'\x00\x00d\x00TREE_ROOT\x000\x00'
495
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\x00\x00\n\x00'],
498
def test_adding_tree_changes_lines(self):
499
state = dirstate.DirState.initialize('dirstate')
500
lines = list(state.get_lines())
501
state.add_parent_tree('a-ghost', None)
502
self.assertNotEqual(lines, state.get_lines())
504
def test_get_line_with_2_rows(self):
505
state = dirstate.DirState.initialize('dirstate')
506
packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
507
root_row_direntry = ('', '', 'directory', 'a-root-value', 0, packed_stat, '')
508
root_row = (root_row_direntry, [])
510
# add a file in the root
511
subdir_row = (['', 'subdir', 'directory', 'subdir-id', 0, packed_stat, ''], [])
512
dirblocks.append(('', [subdir_row]))
513
state._set_data([], root_row, dirblocks)
514
self.assertEqual(['#bazaar dirstate flat format 1\n',
515
'adler32: 1283137489\n',
519
'\x00\x00d\x00a-root-value\x000'
520
'\x00AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk\x00\x00\n\x00\x00subdir\x00'
521
'd\x00subdir-id\x000\x00AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk\x00\x00'
525
def test_row_to_line(self):
526
state = dirstate.DirState.initialize('dirstate')
527
packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
528
root_row_direntry = ('', '', 'directory', 'a-root-value', 0, packed_stat, '')
529
root_parent_direntries = []
530
root_row = (root_row_direntry, root_parent_direntries)
531
self.assertEqual('\x00\x00d\x00a-root-value\x000\x00AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk\x00', state._row_to_line(root_row))
533
def test_row_to_line_with_parent(self):
534
state = dirstate.DirState.initialize('dirstate')
535
packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
536
root_row_direntry = ('', '', 'directory', 'a-root-value', 0, packed_stat, '')
537
# one parent that was a file at path /dirname/basename
538
root_parent_direntries = [('revid', 'file', 'dirname', 'basename', 0, False, '')]
539
root_row = (root_row_direntry, root_parent_direntries)
541
'\x00\x00d\x00a-root-value\x000\x00AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk\x00'
542
'\x00revid\x00f\x00dirname\x00basename\x000\x00n\x00',
543
state._row_to_line(root_row))
545
def test_row_to_line_with_two_parents(self):
546
state = dirstate.DirState.initialize('dirstate')
547
packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
548
root_row_direntry = ('', '', 'directory', 'a-root-value', 0, packed_stat, '')
549
# two parent entires: one that was a file at path /dirname/basename
550
# and one that was a directory at /
551
root_parent_direntries = [('revid', 'file', 'dirname', 'basename', 0, False, ''),
552
('revid2', 'directory', '', '', 0, False, '')]
553
root_row = (root_row_direntry, root_parent_direntries)
555
'\x00\x00d\x00a-root-value\x000\x00AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk\x00'
556
'\x00revid\x00f\x00dirname\x00basename\x000\x00n\x00'
557
'\x00revid2\x00d\x00\x00\x000\x00n\x00',
558
state._row_to_line(root_row))
560
def test_iter_rows(self):
561
# we should be able to iterate the dirstate rows from end to end
562
# this is for get_lines to be easy to read.
563
state = dirstate.DirState.initialize('dirstate')
564
packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
565
root_row_direntry = ('', '', 'directory', 'a-root-value', 0, packed_stat, '')
566
root_row = (root_row_direntry, [])
568
# add two files in the root
569
subdir_row = (['', 'subdir', 'directory', 'subdir-id', 0, packed_stat, ''], [])
570
afile_row = (['', 'afile', 'file', 'afile-id', 34, packed_stat, 'sha1value'], [])
571
dirblocks.append(('', [subdir_row, afile_row]))
573
file_row2 = (['', '2file', 'file', '2file-id', 23, packed_stat, 'sha1value'], [])
574
dirblocks.append(('subdir', [file_row2]))
575
state._set_data([], root_row, dirblocks)
576
expected_rows = [root_row, subdir_row, afile_row, file_row2]
577
self.assertEqual(expected_rows, list(state._iter_rows()))