39
from bzrlib.branchbuilder import BranchBuilder
37
40
from bzrlib.btree_index import BTreeBuilder, BTreeGraphIndex
38
from bzrlib.index import GraphIndex
41
from bzrlib.index import GraphIndex, InMemoryGraphIndex
39
42
from bzrlib.repository import RepositoryFormat
43
from bzrlib.smart import server
40
44
from bzrlib.tests import (
42
46
TestCaseWithTransport,
44
50
from bzrlib.transport import (
54
from bzrlib.transport.memory import MemoryServer
47
55
from bzrlib import (
53
63
revision as _mod_revision,
454
465
repo = self.make_repository('.',
455
466
format=bzrdir.format_registry.get('knit')())
456
467
inv_xml = '<inventory format="5">\n</inventory>\n'
457
inv = repo._deserialise_inventory('test-rev-id', inv_xml)
468
inv = repo.deserialise_inventory('test-rev-id', inv_xml)
458
469
self.assertEqual('test-rev-id', inv.root.revision)
460
471
def test_deserialise_uses_global_revision_id(self):
466
477
# Arguably, the deserialise_inventory should detect a mismatch, and
467
478
# raise an error, rather than silently using one revision_id over the
469
self.assertRaises(AssertionError, repo._deserialise_inventory,
480
self.assertRaises(AssertionError, repo.deserialise_inventory,
470
481
'test-rev-id', inv_xml)
471
inv = repo._deserialise_inventory('other-rev-id', inv_xml)
482
inv = repo.deserialise_inventory('other-rev-id', inv_xml)
472
483
self.assertEqual('other-rev-id', inv.root.revision)
474
485
def test_supports_external_lookups(self):
1133
1144
packs.ensure_loaded()
1134
1145
return tree, r, packs, [rev1, rev2, rev3]
1136
def test__clear_obsolete_packs(self):
1137
packs = self.get_packs()
1138
obsolete_pack_trans = packs.transport.clone('obsolete_packs')
1139
obsolete_pack_trans.put_bytes('a-pack.pack', 'content\n')
1140
obsolete_pack_trans.put_bytes('a-pack.rix', 'content\n')
1141
obsolete_pack_trans.put_bytes('a-pack.iix', 'content\n')
1142
obsolete_pack_trans.put_bytes('another-pack.pack', 'foo\n')
1143
obsolete_pack_trans.put_bytes('not-a-pack.rix', 'foo\n')
1144
res = packs._clear_obsolete_packs()
1145
self.assertEqual(['a-pack', 'another-pack'], sorted(res))
1146
self.assertEqual([], obsolete_pack_trans.list_dir('.'))
1148
def test__clear_obsolete_packs_preserve(self):
1149
packs = self.get_packs()
1150
obsolete_pack_trans = packs.transport.clone('obsolete_packs')
1151
obsolete_pack_trans.put_bytes('a-pack.pack', 'content\n')
1152
obsolete_pack_trans.put_bytes('a-pack.rix', 'content\n')
1153
obsolete_pack_trans.put_bytes('a-pack.iix', 'content\n')
1154
obsolete_pack_trans.put_bytes('another-pack.pack', 'foo\n')
1155
obsolete_pack_trans.put_bytes('not-a-pack.rix', 'foo\n')
1156
res = packs._clear_obsolete_packs(preserve=set(['a-pack']))
1157
self.assertEqual(['a-pack', 'another-pack'], sorted(res))
1158
self.assertEqual(['a-pack.iix', 'a-pack.pack', 'a-pack.rix'],
1159
sorted(obsolete_pack_trans.list_dir('.')))
1161
1147
def test__max_pack_count(self):
1162
1148
"""The maximum pack count is a function of the number of revisions."""
1163
1149
# no revisions - one pack, so that we can have a revision free repo
1188
1174
self.assertContainsRe(repr(packs),
1189
1175
'RepositoryPackCollection(.*Repository(.*))')
1191
def test__obsolete_packs(self):
1192
tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1193
names = packs.names()
1194
pack = packs.get_pack_by_name(names[0])
1195
# Schedule this one for removal
1196
packs._remove_pack_from_memory(pack)
1197
# Simulate a concurrent update by renaming the .pack file and one of
1199
packs.transport.rename('packs/%s.pack' % (names[0],),
1200
'obsolete_packs/%s.pack' % (names[0],))
1201
packs.transport.rename('indices/%s.iix' % (names[0],),
1202
'obsolete_packs/%s.iix' % (names[0],))
1203
# Now trigger the obsoletion, and ensure that all the remaining files
1205
packs._obsolete_packs([pack])
1206
self.assertEqual([n + '.pack' for n in names[1:]],
1207
sorted(packs._pack_transport.list_dir('.')))
1208
# names[0] should not be present in the index anymore
1209
self.assertEqual(names[1:],
1210
sorted(set([osutils.splitext(n)[0] for n in
1211
packs._index_transport.list_dir('.')])))
1213
1177
def test_pack_distribution_zero(self):
1214
1178
packs = self.get_packs()
1215
1179
self.assertEqual([0], packs.pack_distribution(0))
1403
1367
removed_pack = packs.get_pack_by_name(to_remove_name)
1404
1368
packs._remove_pack_from_memory(removed_pack)
1405
1369
names = packs.names()
1406
all_nodes, deleted_nodes, new_nodes, _ = packs._diff_pack_names()
1370
all_nodes, deleted_nodes, new_nodes = packs._diff_pack_names()
1407
1371
new_names = set([x[0][0] for x in new_nodes])
1408
1372
self.assertEqual(names, sorted([x[0][0] for x in all_nodes]))
1409
1373
self.assertEqual(set(names) - set(orig_names), new_names)
1414
1378
reloaded_names = packs.names()
1415
1379
self.assertEqual(orig_at_load, packs._packs_at_load)
1416
1380
self.assertEqual(names, reloaded_names)
1417
all_nodes, deleted_nodes, new_nodes, _ = packs._diff_pack_names()
1381
all_nodes, deleted_nodes, new_nodes = packs._diff_pack_names()
1418
1382
new_names = set([x[0][0] for x in new_nodes])
1419
1383
self.assertEqual(names, sorted([x[0][0] for x in all_nodes]))
1420
1384
self.assertEqual(set(names) - set(orig_names), new_names)
1422
1386
self.assertEqual([to_remove_name],
1423
1387
sorted([x[0][0] for x in deleted_nodes]))
1425
def test_autopack_obsoletes_new_pack(self):
1426
tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1427
packs._max_pack_count = lambda x: 1
1428
packs.pack_distribution = lambda x: [10]
1429
r.start_write_group()
1430
r.revisions.insert_record_stream([versionedfile.FulltextContentFactory(
1431
('bogus-rev',), (), None, 'bogus-content\n')])
1432
# This should trigger an autopack, which will combine everything into a
1434
new_names = r.commit_write_group()
1435
names = packs.names()
1436
self.assertEqual(1, len(names))
1437
self.assertEqual([names[0] + '.pack'],
1438
packs._pack_transport.list_dir('.'))
1440
1389
def test_autopack_reloads_and_stops(self):
1441
1390
tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1442
1391
# After we have determined what needs to be autopacked, trigger a
1454
1403
self.assertEqual(tree.branch.repository._pack_collection.names(),
1457
def test__save_pack_names(self):
1458
tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1459
names = packs.names()
1460
pack = packs.get_pack_by_name(names[0])
1461
packs._remove_pack_from_memory(pack)
1462
packs._save_pack_names(obsolete_packs=[pack])
1463
cur_packs = packs._pack_transport.list_dir('.')
1464
self.assertEqual([n + '.pack' for n in names[1:]], sorted(cur_packs))
1465
# obsolete_packs will also have stuff like .rix and .iix present.
1466
obsolete_packs = packs.transport.list_dir('obsolete_packs')
1467
obsolete_names = set([osutils.splitext(n)[0] for n in obsolete_packs])
1468
self.assertEqual([pack.name], sorted(obsolete_names))
1470
def test__save_pack_names_already_obsoleted(self):
1471
tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1472
names = packs.names()
1473
pack = packs.get_pack_by_name(names[0])
1474
packs._remove_pack_from_memory(pack)
1475
# We are going to simulate a concurrent autopack by manually obsoleting
1476
# the pack directly.
1477
packs._obsolete_packs([pack])
1478
packs._save_pack_names(clear_obsolete_packs=True,
1479
obsolete_packs=[pack])
1480
cur_packs = packs._pack_transport.list_dir('.')
1481
self.assertEqual([n + '.pack' for n in names[1:]], sorted(cur_packs))
1482
# Note that while we set clear_obsolete_packs=True, it should not
1483
# delete a pack file that we have also scheduled for obsoletion.
1484
obsolete_packs = packs.transport.list_dir('obsolete_packs')
1485
obsolete_names = set([osutils.splitext(n)[0] for n in obsolete_packs])
1486
self.assertEqual([pack.name], sorted(obsolete_names))
1490
1407
class TestPack(TestCaseWithTransport):
1491
1408
"""Tests for the Pack object."""