125
105
tree = tree.bzrdir.open_workingtree()
127
107
self.addCleanup(tree.unlock)
128
if not invalid_delta:
130
return tree.root_inventory
133
def _create_repo_revisions(repo, basis, delta, invalid_delta):
134
repo.start_write_group()
136
rev = revision.Revision('basis', timestamp=0, timezone=None,
137
message="", committer="foo@example.com")
138
basis.revision_id = 'basis'
139
create_texts_for_inv(repo, basis)
140
repo.add_revision('basis', rev, basis)
142
# We don't want to apply the delta to the basis, because we expect
143
# the delta is invalid.
145
result_inv.revision_id = 'result'
146
target_entries = None
148
result_inv = basis.create_by_apply_delta(delta, 'result')
149
create_texts_for_inv(repo, result_inv)
150
target_entries = list(result_inv.iter_entries_by_dir())
151
rev = revision.Revision('result', timestamp=0, timezone=None,
152
message="", committer="foo@example.com")
153
repo.add_revision('result', rev, result_inv)
154
repo.commit_write_group()
156
repo.abort_write_group()
158
return target_entries
161
def _get_basis_entries(tree):
162
basis_tree = tree.basis_tree()
163
basis_tree.lock_read()
164
basis_tree_entries = list(basis_tree.inventory.iter_entries_by_dir())
166
return basis_tree_entries
169
def _populate_different_tree(tree, basis, delta):
170
"""Put all entries into tree, but at a unique location."""
173
tree.add(['unique-dir'], ['unique-dir-id'], ['directory'])
174
for path, ie in basis.iter_entries_by_dir():
175
if ie.file_id in added_ids:
177
# We want a unique path for each of these, we use the file-id
178
tree.add(['unique-dir/' + ie.file_id], [ie.file_id], [ie.kind])
179
added_ids.add(ie.file_id)
180
for old_path, new_path, file_id, ie in delta:
181
if file_id in added_ids:
183
tree.add(['unique-dir/' + file_id], [file_id], [ie.kind])
186
def apply_inventory_WT_basis(test, basis, delta, invalid_delta=True):
108
# One could add 'tree._validate' here but that would cause 'early' failues
109
# as far as higher level code is concerned. Possibly adding an
110
# expect_fail parameter to this function and if that is False then do a
112
return tree.inventory
115
def apply_inventory_WT_basis(self, basis, delta):
187
116
"""Apply delta to basis and return the result.
189
118
This sets the parent and then calls update_basis_by_delta.
191
120
allow safety checks made by the WT to succeed, and finally ensures that all
192
121
items in the delta with a new path are present in the WT before calling
193
122
update_basis_by_delta.
195
124
:param basis: An inventory to be used as the basis.
196
125
:param delta: The inventory delta to apply:
197
126
:return: An inventory resulting from the application.
199
control = test.make_bzrdir('tree', format=test.format._matchingbzrdir)
128
control = self.make_bzrdir('tree', format=self.format._matchingbzrdir)
200
129
control.create_repository()
201
130
control.create_branch()
202
tree = test.format.initialize(control)
131
tree = self.format.initialize(control)
203
132
tree.lock_write()
205
target_entries = _create_repo_revisions(tree.branch.repository, basis,
206
delta, invalid_delta)
134
repo = tree.branch.repository
135
repo.start_write_group()
137
rev = revision.Revision('basis', timestamp=0, timezone=None,
138
message="", committer="foo@example.com")
139
basis.revision_id = 'basis'
140
repo.add_revision('basis', rev, basis)
141
# Add a revision for the result, with the basis content -
142
# update_basis_by_delta doesn't check that the delta results in
143
# result, and we want inconsistent deltas to get called on the
144
# tree, or else the code isn't actually checked.
145
rev = revision.Revision('result', timestamp=0, timezone=None,
146
message="", committer="foo@example.com")
147
basis.revision_id = 'result'
148
repo.add_revision('result', rev, basis)
150
repo.abort_write_group()
153
repo.commit_write_group()
207
154
# Set the basis state as the trees current state
208
155
tree._write_inventory(basis)
209
156
# This reads basis from the repo and puts it into the tree's local
210
157
# cache, if it has one.
211
158
tree.set_parent_ids(['basis'])
161
for old, new, id, entry in delta:
162
if None in (new, entry):
164
paths[new] = (entry.file_id, entry.kind)
165
parents.add(osutils.dirname(new))
166
parents = osutils.minimum_path_selection(parents)
168
# Put place holders in the tree to permit adding the other entries.
169
for pos, parent in enumerate(parents):
170
if not tree.path2id(parent):
171
# add a synthetic directory in the tree so we can can put the
172
# tree0 entries in place for dirstate.
173
tree.add([parent], ["id%d" % pos], ["directory"])
175
# Many deltas may cause this mini-apply to fail, but we want to see what
176
# the delta application code says, not the prep that we do to deal with
177
# limitations of dirstate's update_basis code.
178
for path, (file_id, kind) in sorted(paths.items()):
180
tree.add([path], [file_id], [kind])
181
except (KeyboardInterrupt, SystemExit):
214
187
# Fresh lock, reads disk again.
215
188
tree.lock_write()
217
190
tree.update_basis_by_delta('result', delta)
218
if not invalid_delta:
222
193
# reload tree - ensure we get what was written.
223
194
tree = tree.bzrdir.open_workingtree()
224
195
basis_tree = tree.basis_tree()
225
196
basis_tree.lock_read()
226
test.addCleanup(basis_tree.unlock)
227
basis_inv = basis_tree.root_inventory
229
basis_entries = list(basis_inv.iter_entries_by_dir())
230
test.assertEqual(target_entries, basis_entries)
234
def apply_inventory_Repository_add_inventory_by_delta(self, basis, delta,
197
self.addCleanup(basis_tree.unlock)
198
# Note, that if the tree does not have a local cache, the trick above of
199
# setting the result as the basis, will come back to bite us. That said,
200
# all the implementations in bzr do have a local cache.
201
return basis_tree.inventory
204
def apply_inventory_Repository_add_inventory_by_delta(self, basis, delta):
236
205
"""Apply delta to basis and return the result.
238
207
This inserts basis as a whole inventory and then uses
280
249
return repo.get_inventory('result')
283
class TestInventoryUpdates(TestCase):
285
def test_creation_from_root_id(self):
286
# iff a root id is passed to the constructor, a root directory is made
287
inv = inventory.Inventory(root_id='tree-root')
288
self.assertNotEqual(None, inv.root)
289
self.assertEqual('tree-root', inv.root.file_id)
291
def test_add_path_of_root(self):
292
# if no root id is given at creation time, there is no root directory
293
inv = inventory.Inventory(root_id=None)
294
self.assertIs(None, inv.root)
295
# add a root entry by adding its path
296
ie = inv.add_path("", "directory", "my-root")
297
ie.revision = 'test-rev'
298
self.assertEqual("my-root", ie.file_id)
299
self.assertIs(ie, inv.root)
301
def test_add_path(self):
302
inv = inventory.Inventory(root_id='tree_root')
303
ie = inv.add_path('hello', 'file', 'hello-id')
304
self.assertEqual('hello-id', ie.file_id)
305
self.assertEqual('file', ie.kind)
308
"""Make sure copy() works and creates a deep copy."""
309
inv = inventory.Inventory(root_id='some-tree-root')
310
ie = inv.add_path('hello', 'file', 'hello-id')
312
inv.root.file_id = 'some-new-root'
314
self.assertEqual('some-tree-root', inv2.root.file_id)
315
self.assertEqual('hello', inv2['hello-id'].name)
317
def test_copy_empty(self):
318
"""Make sure an empty inventory can be copied."""
319
inv = inventory.Inventory(root_id=None)
321
self.assertIs(None, inv2.root)
323
def test_copy_copies_root_revision(self):
324
"""Make sure the revision of the root gets copied."""
325
inv = inventory.Inventory(root_id='someroot')
326
inv.root.revision = 'therev'
328
self.assertEqual('someroot', inv2.root.file_id)
329
self.assertEqual('therev', inv2.root.revision)
331
def test_create_tree_reference(self):
332
inv = inventory.Inventory('tree-root-123')
333
inv.add(TreeReference('nested-id', 'nested', parent_id='tree-root-123',
334
revision='rev', reference_revision='rev2'))
336
def test_error_encoding(self):
337
inv = inventory.Inventory('tree-root')
338
inv.add(InventoryFile('a-id', u'\u1234', 'tree-root'))
339
e = self.assertRaises(errors.InconsistentDelta, inv.add,
340
InventoryFile('b-id', u'\u1234', 'tree-root'))
341
self.assertContainsRe(str(e), r'\\u1234')
343
def test_add_recursive(self):
344
parent = InventoryDirectory('src-id', 'src', 'tree-root')
345
child = InventoryFile('hello-id', 'hello.c', 'src-id')
346
parent.children[child.file_id] = child
347
inv = inventory.Inventory('tree-root')
349
self.assertEqual('src/hello.c', inv.id2path('hello-id'))
353
252
class TestDeltaApplication(TestCaseWithTransport):
355
scenarios = delta_application_scenarios()
357
254
def get_empty_inventory(self, reference_inv=None):
358
255
"""Get an empty inventory.
600
494
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
603
def test_add_file(self):
604
inv = self.get_empty_inventory()
605
file1 = inventory.InventoryFile('file-id', 'path', inv.root.file_id)
606
file1.revision = 'result'
609
delta = [(None, u'path', 'file-id', file1)]
610
res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
611
self.assertEqual('file-id', res_inv['file-id'].file_id)
613
def test_remove_file(self):
614
inv = self.get_empty_inventory()
615
file1 = inventory.InventoryFile('file-id', 'path', inv.root.file_id)
616
file1.revision = 'result'
620
delta = [(u'path', None, 'file-id', None)]
621
res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
622
self.assertEqual(None, res_inv.path2id('path'))
623
self.assertRaises(errors.NoSuchId, res_inv.id2path, 'file-id')
625
def test_rename_file(self):
626
inv = self.get_empty_inventory()
627
file1 = self.make_file_ie(name='path', parent_id=inv.root.file_id)
629
file2 = self.make_file_ie(name='path2', parent_id=inv.root.file_id)
630
delta = [(u'path', 'path2', 'file-id', file2)]
631
res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
632
self.assertEqual(None, res_inv.path2id('path'))
633
self.assertEqual('file-id', res_inv.path2id('path2'))
635
def test_replaced_at_new_path(self):
636
inv = self.get_empty_inventory()
637
file1 = self.make_file_ie(file_id='id1', parent_id=inv.root.file_id)
639
file2 = self.make_file_ie(file_id='id2', parent_id=inv.root.file_id)
640
delta = [(u'name', None, 'id1', None),
641
(None, u'name', 'id2', file2)]
642
res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
643
self.assertEqual('id2', res_inv.path2id('name'))
645
def test_rename_dir(self):
646
inv = self.get_empty_inventory()
647
dir1 = inventory.InventoryDirectory('dir-id', 'dir1', inv.root.file_id)
648
dir1.revision = 'basis'
649
file1 = self.make_file_ie(parent_id='dir-id')
652
dir2 = inventory.InventoryDirectory('dir-id', 'dir2', inv.root.file_id)
653
dir2.revision = 'result'
654
delta = [('dir1', 'dir2', 'dir-id', dir2)]
655
res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
656
# The file should be accessible under the new path
657
self.assertEqual('file-id', res_inv.path2id('dir2/name'))
659
def test_renamed_dir_with_renamed_child(self):
660
inv = self.get_empty_inventory()
661
dir1 = inventory.InventoryDirectory('dir-id', 'dir1', inv.root.file_id)
662
dir1.revision = 'basis'
663
file1 = self.make_file_ie('file-id-1', 'name1', parent_id='dir-id')
664
file2 = self.make_file_ie('file-id-2', 'name2', parent_id='dir-id')
668
dir2 = inventory.InventoryDirectory('dir-id', 'dir2', inv.root.file_id)
669
dir2.revision = 'result'
670
file2b = self.make_file_ie('file-id-2', 'name2', inv.root.file_id)
671
delta = [('dir1', 'dir2', 'dir-id', dir2),
672
('dir1/name2', 'name2', 'file-id-2', file2b)]
673
res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
674
# The file should be accessible under the new path
675
self.assertEqual('file-id-1', res_inv.path2id('dir2/name1'))
676
self.assertEqual(None, res_inv.path2id('dir2/name2'))
677
self.assertEqual('file-id-2', res_inv.path2id('name2'))
679
def test_is_root(self):
680
"""Ensure our root-checking code is accurate."""
681
inv = inventory.Inventory('TREE_ROOT')
682
self.assertTrue(inv.is_root('TREE_ROOT'))
683
self.assertFalse(inv.is_root('booga'))
684
inv.root.file_id = 'booga'
685
self.assertFalse(inv.is_root('TREE_ROOT'))
686
self.assertTrue(inv.is_root('booga'))
687
# works properly even if no root is set
689
self.assertFalse(inv.is_root('TREE_ROOT'))
690
self.assertFalse(inv.is_root('booga'))
692
def test_entries_for_empty_inventory(self):
693
"""Test that entries() will not fail for an empty inventory"""
694
inv = Inventory(root_id=None)
695
self.assertEqual([], inv.entries())
698
498
class TestInventoryEntry(TestCase):
1310
1123
self.assertIsInstance(ie2.name, unicode)
1311
1124
self.assertEqual(('tree\xce\xa9name', 'tree-root-id', 'tree-rev-id'),
1312
1125
inv._bytes_to_utf8name_key(bytes))
1314
def make_basic_utf8_inventory(self):
1316
inv.revision_id = "revid"
1317
inv.root.revision = "rootrev"
1318
root_id = inv.root.file_id
1319
inv.add(InventoryFile("fileid", u'f\xefle', root_id))
1320
inv["fileid"].revision = "filerev"
1321
inv["fileid"].text_sha1 = "ffff"
1322
inv["fileid"].text_size = 0
1323
inv.add(InventoryDirectory("dirid", u'dir-\N{EURO SIGN}', root_id))
1324
inv.add(InventoryFile("childid", u'ch\xefld', "dirid"))
1325
inv["childid"].revision = "filerev"
1326
inv["childid"].text_sha1 = "ffff"
1327
inv["childid"].text_size = 0
1328
chk_bytes = self.get_chk_bytes()
1329
chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1330
bytes = ''.join(chk_inv.to_lines())
1331
return CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1333
def test__preload_handles_utf8(self):
1334
new_inv = self.make_basic_utf8_inventory()
1335
self.assertEqual({}, new_inv._fileid_to_entry_cache)
1336
self.assertFalse(new_inv._fully_cached)
1337
new_inv._preload_cache()
1339
sorted([new_inv.root_id, "fileid", "dirid", "childid"]),
1340
sorted(new_inv._fileid_to_entry_cache.keys()))
1341
ie_root = new_inv._fileid_to_entry_cache[new_inv.root_id]
1342
self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1343
sorted(ie_root._children.keys()))
1344
ie_dir = new_inv._fileid_to_entry_cache['dirid']
1345
self.assertEqual([u'ch\xefld'], sorted(ie_dir._children.keys()))
1347
def test__preload_populates_cache(self):
1349
inv.revision_id = "revid"
1350
inv.root.revision = "rootrev"
1351
root_id = inv.root.file_id
1352
inv.add(InventoryFile("fileid", "file", root_id))
1353
inv["fileid"].revision = "filerev"
1354
inv["fileid"].executable = True
1355
inv["fileid"].text_sha1 = "ffff"
1356
inv["fileid"].text_size = 1
1357
inv.add(InventoryDirectory("dirid", "dir", root_id))
1358
inv.add(InventoryFile("childid", "child", "dirid"))
1359
inv["childid"].revision = "filerev"
1360
inv["childid"].executable = False
1361
inv["childid"].text_sha1 = "dddd"
1362
inv["childid"].text_size = 1
1363
chk_bytes = self.get_chk_bytes()
1364
chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1365
bytes = ''.join(chk_inv.to_lines())
1366
new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1367
self.assertEqual({}, new_inv._fileid_to_entry_cache)
1368
self.assertFalse(new_inv._fully_cached)
1369
new_inv._preload_cache()
1371
sorted([root_id, "fileid", "dirid", "childid"]),
1372
sorted(new_inv._fileid_to_entry_cache.keys()))
1373
self.assertTrue(new_inv._fully_cached)
1374
ie_root = new_inv._fileid_to_entry_cache[root_id]
1375
self.assertEqual(['dir', 'file'], sorted(ie_root._children.keys()))
1376
ie_dir = new_inv._fileid_to_entry_cache['dirid']
1377
self.assertEqual(['child'], sorted(ie_dir._children.keys()))
1379
def test__preload_handles_partially_evaluated_inventory(self):
1380
new_inv = self.make_basic_utf8_inventory()
1381
ie = new_inv[new_inv.root_id]
1382
self.assertIs(None, ie._children)
1383
self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1384
sorted(ie.children.keys()))
1385
# Accessing .children loads _children
1386
self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1387
sorted(ie._children.keys()))
1388
new_inv._preload_cache()
1390
self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1391
sorted(ie._children.keys()))
1392
ie_dir = new_inv["dirid"]
1393
self.assertEqual([u'ch\xefld'],
1394
sorted(ie_dir._children.keys()))
1396
def test_filter_change_in_renamed_subfolder(self):
1397
inv = Inventory('tree-root')
1398
src_ie = inv.add_path('src', 'directory', 'src-id')
1399
inv.add_path('src/sub/', 'directory', 'sub-id')
1400
a_ie = inv.add_path('src/sub/a', 'file', 'a-id')
1401
a_ie.text_sha1 = osutils.sha_string('content\n')
1402
a_ie.text_size = len('content\n')
1403
chk_bytes = self.get_chk_bytes()
1404
inv = CHKInventory.from_inventory(chk_bytes, inv)
1405
inv = inv.create_by_apply_delta([
1406
("src/sub/a", "src/sub/a", "a-id", a_ie),
1407
("src", "src2", "src-id", src_ie),
1409
new_inv = inv.filter(['a-id', 'src-id'])
1413
('src/sub', 'sub-id'),
1414
('src/sub/a', 'a-id'),
1415
], [(path, ie.file_id) for path, ie in new_inv.iter_entries()])
1417
class TestCHKInventoryExpand(tests.TestCaseWithMemoryTransport):
1419
def get_chk_bytes(self):
1420
factory = groupcompress.make_pack_factory(True, True, 1)
1421
trans = self.get_transport('')
1422
return factory(trans)
1424
def make_dir(self, inv, name, parent_id):
1425
inv.add(inv.make_entry('directory', name, parent_id, name + '-id'))
1427
def make_file(self, inv, name, parent_id, content='content\n'):
1428
ie = inv.make_entry('file', name, parent_id, name + '-id')
1429
ie.text_sha1 = osutils.sha_string(content)
1430
ie.text_size = len(content)
1433
def make_simple_inventory(self):
1434
inv = Inventory('TREE_ROOT')
1435
inv.revision_id = "revid"
1436
inv.root.revision = "rootrev"
1439
# sub-file1 sub-file1-id
1440
# sub-file2 sub-file2-id
1441
# sub-dir1/ sub-dir1-id
1442
# subsub-file1 subsub-file1-id
1444
# sub2-file1 sub2-file1-id
1446
self.make_dir(inv, 'dir1', 'TREE_ROOT')
1447
self.make_dir(inv, 'dir2', 'TREE_ROOT')
1448
self.make_dir(inv, 'sub-dir1', 'dir1-id')
1449
self.make_file(inv, 'top', 'TREE_ROOT')
1450
self.make_file(inv, 'sub-file1', 'dir1-id')
1451
self.make_file(inv, 'sub-file2', 'dir1-id')
1452
self.make_file(inv, 'subsub-file1', 'sub-dir1-id')
1453
self.make_file(inv, 'sub2-file1', 'dir2-id')
1454
chk_bytes = self.get_chk_bytes()
1455
# use a small maximum_size to force internal paging structures
1456
chk_inv = CHKInventory.from_inventory(chk_bytes, inv,
1458
search_key_name='hash-255-way')
1459
bytes = ''.join(chk_inv.to_lines())
1460
return CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1462
def assert_Getitems(self, expected_fileids, inv, file_ids):
1463
self.assertEqual(sorted(expected_fileids),
1464
sorted([ie.file_id for ie in inv._getitems(file_ids)]))
1466
def assertExpand(self, all_ids, inv, file_ids):
1468
val_children) = inv._expand_fileids_to_parents_and_children(file_ids)
1469
self.assertEqual(set(all_ids), val_all_ids)
1470
entries = inv._getitems(val_all_ids)
1471
expected_children = {}
1472
for entry in entries:
1473
s = expected_children.setdefault(entry.parent_id, [])
1474
s.append(entry.file_id)
1475
val_children = dict((k, sorted(v)) for k, v
1476
in val_children.iteritems())
1477
expected_children = dict((k, sorted(v)) for k, v
1478
in expected_children.iteritems())
1479
self.assertEqual(expected_children, val_children)
1481
def test_make_simple_inventory(self):
1482
inv = self.make_simple_inventory()
1484
for path, entry in inv.iter_entries_by_dir():
1485
layout.append((path, entry.file_id))
1488
('dir1', 'dir1-id'),
1489
('dir2', 'dir2-id'),
1491
('dir1/sub-dir1', 'sub-dir1-id'),
1492
('dir1/sub-file1', 'sub-file1-id'),
1493
('dir1/sub-file2', 'sub-file2-id'),
1494
('dir1/sub-dir1/subsub-file1', 'subsub-file1-id'),
1495
('dir2/sub2-file1', 'sub2-file1-id'),
1498
def test__getitems(self):
1499
inv = self.make_simple_inventory()
1501
self.assert_Getitems(['dir1-id'], inv, ['dir1-id'])
1502
self.assertTrue('dir1-id' in inv._fileid_to_entry_cache)
1503
self.assertFalse('sub-file2-id' in inv._fileid_to_entry_cache)
1505
self.assert_Getitems(['dir1-id'], inv, ['dir1-id'])
1507
self.assert_Getitems(['dir1-id', 'sub-file2-id'], inv,
1508
['dir1-id', 'sub-file2-id'])
1509
self.assertTrue('dir1-id' in inv._fileid_to_entry_cache)
1510
self.assertTrue('sub-file2-id' in inv._fileid_to_entry_cache)
1512
def test_single_file(self):
1513
inv = self.make_simple_inventory()
1514
self.assertExpand(['TREE_ROOT', 'top-id'], inv, ['top-id'])
1516
def test_get_all_parents(self):
1517
inv = self.make_simple_inventory()
1518
self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
1520
], inv, ['subsub-file1-id'])
1522
def test_get_children(self):
1523
inv = self.make_simple_inventory()
1524
self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
1525
'sub-file1-id', 'sub-file2-id', 'subsub-file1-id',
1526
], inv, ['dir1-id'])
1528
def test_from_root(self):
1529
inv = self.make_simple_inventory()
1530
self.assertExpand(['TREE_ROOT', 'dir1-id', 'dir2-id', 'sub-dir1-id',
1531
'sub-file1-id', 'sub-file2-id', 'sub2-file1-id',
1532
'subsub-file1-id', 'top-id'], inv, ['TREE_ROOT'])
1534
def test_top_level_file(self):
1535
inv = self.make_simple_inventory()
1536
self.assertExpand(['TREE_ROOT', 'top-id'], inv, ['top-id'])
1538
def test_subsub_file(self):
1539
inv = self.make_simple_inventory()
1540
self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
1541
'subsub-file1-id'], inv, ['subsub-file1-id'])
1543
def test_sub_and_root(self):
1544
inv = self.make_simple_inventory()
1545
self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id', 'top-id',
1546
'subsub-file1-id'], inv, ['top-id', 'subsub-file1-id'])
1549
class TestMutableInventoryFromTree(TestCaseWithTransport):
1551
def test_empty(self):
1552
repository = self.make_repository('.')
1553
tree = repository.revision_tree(revision.NULL_REVISION)
1554
inv = mutable_inventory_from_tree(tree)
1555
self.assertEqual(revision.NULL_REVISION, inv.revision_id)
1556
self.assertEqual(0, len(inv))
1558
def test_some_files(self):
1559
wt = self.make_branch_and_tree('.')
1560
self.build_tree(['a'])
1561
wt.add(['a'], ['thefileid'])
1562
revid = wt.commit("commit")
1563
tree = wt.branch.repository.revision_tree(revid)
1564
inv = mutable_inventory_from_tree(tree)
1565
self.assertEqual(revid, inv.revision_id)
1566
self.assertEqual(2, len(inv))
1567
self.assertEqual("a", inv['thefileid'].name)
1568
# The inventory should be mutable and independent of
1570
self.assertFalse(tree.root_inventory['thefileid'].executable)
1571
inv['thefileid'].executable = True
1572
self.assertFalse(tree.root_inventory['thefileid'].executable)