1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
64
63
MetaDirRepositoryFormat,
67
67
import bzrlib.revision as _mod_revision
68
68
from bzrlib.store.revision.knit import KnitRevisionStore
69
69
from bzrlib.store.versioned import VersionedFileStore
70
from bzrlib.trace import mutter, note, warning
70
from bzrlib.trace import (
73
78
class PackCommitBuilder(CommitBuilder):
201
206
self.pack_transport = pack_transport
202
assert None not in (revision_index, inventory_index, text_index,
203
signature_index, name, pack_transport)
207
if None in (revision_index, inventory_index, text_index,
208
signature_index, name, pack_transport):
209
raise AssertionError()
205
211
def __eq__(self, other):
206
212
return self.__dict__ == other.__dict__
324
330
def access_tuple(self):
325
331
"""Return a tuple (transport, name) for the pack content."""
326
assert self._state in ('open', 'finished')
327
332
if self._state == 'finished':
328
333
return Pack.access_tuple(self)
334
elif self._state == 'open':
330
335
return self.upload_transport, self.random_name
337
raise AssertionError(self._state)
332
339
def data_inserted(self):
333
340
"""True if data has been added to this pack."""
496
503
:param index: An index from the pack parameter.
497
504
:param pack: A Pack instance.
499
assert self.add_callback is None, \
500
"%s already has a writable index through %s" % \
501
(self, self.add_callback)
506
if self.add_callback is not None:
507
raise AssertionError(
508
"%s already has a writable index through %s" % \
509
(self, self.add_callback))
502
510
# allow writing: queue writes to a new index
503
511
self.add_index(index, pack)
504
512
# Updates the index to packs mapping as a side effect,
597
605
return NewPack(self._pack_collection._upload_transport,
598
606
self._pack_collection._index_transport,
599
607
self._pack_collection._pack_transport, upload_suffix=self.suffix,
600
file_mode=self._pack_collection.repo.control_files._file_mode)
608
file_mode=self._pack_collection.repo.bzrdir._get_file_mode())
602
610
def _copy_revision_texts(self):
603
611
"""Copy revision data to the new pack."""
644
652
self.pb.update("Copying inventory texts", 2)
645
653
total_items, readv_group_iter = self._least_readv_node_readv(inv_nodes)
654
# Only grab the output lines if we will be processing them
655
output_lines = bool(self.revision_ids)
646
656
inv_lines = self._copy_nodes_graph(inventory_index_map,
647
657
self.new_pack._writer, self.new_pack.inventory_index,
648
readv_group_iter, total_items, output_lines=True)
658
readv_group_iter, total_items, output_lines=output_lines)
649
659
if self.revision_ids:
650
660
self._process_inventory_lines(inv_lines)
657
667
time.ctime(), self._pack_collection._upload_transport.base,
658
668
self.new_pack.random_name,
659
669
self.new_pack.inventory_index.key_count(),
660
time.time() - new_pack.start_time)
670
time.time() - self.new_pack.start_time)
662
672
def _copy_text_texts(self):
663
673
# select text keys
1060
1070
deltas=True, parents=True)
1061
1071
output_knit = knit.KnitVersionedFile('reconcile-texts',
1062
1072
self._pack_collection.transport,
1064
1073
index=knit_index,
1065
1074
access_method=_PackAccess(
1066
1075
{self.new_pack.text_index:self.new_pack.access_tuple()},
1150
1159
:param pack: A Pack object.
1152
assert pack.name not in self._packs_by_name
1161
if pack.name in self._packs_by_name:
1162
raise AssertionError()
1153
1163
self.packs.append(pack)
1154
1164
self._packs_by_name[pack.name] = pack
1155
1165
self.revision_index.add_index(pack.revision_index, pack)
1613
1623
for key, value in disk_nodes:
1614
1624
builder.add_node(key, value)
1615
1625
self.transport.put_file('pack-names', builder.finish(),
1616
mode=self.repo.control_files._file_mode)
1626
mode=self.repo.bzrdir._get_file_mode())
1617
1627
# move the baseline forward
1618
1628
self._packs_at_load = disk_nodes
1619
# now clear out the obsolete packs directory
1620
1629
if clear_obsolete_packs:
1621
self.transport.clone('obsolete_packs').delete_multi(
1622
self.transport.list_dir('obsolete_packs'))
1630
self._clear_obsolete_packs()
1624
1632
self._unlock_names()
1625
1633
# synchronise the memory packs list with what we just wrote:
1651
1659
self._names[name] = collection, sizes
1652
1660
self.get_pack_by_name(name)
1662
def _clear_obsolete_packs(self):
1663
"""Delete everything from the obsolete-packs directory.
1665
obsolete_pack_transport = self.transport.clone('obsolete_packs')
1666
for filename in obsolete_pack_transport.list_dir('.'):
1668
obsolete_pack_transport.delete(filename)
1669
except (errors.PathError, errors.TransportError), e:
1670
warning("couldn't delete obsolete pack, skipping it:\n%s" % (e,))
1654
1672
def _start_write_group(self):
1655
1673
# Do not permit preparation for writing if we're not in a 'write lock'.
1656
1674
if not self.repo.is_write_locked():
1657
1675
raise errors.NotWriteLocked(self)
1658
1676
self._new_pack = NewPack(self._upload_transport, self._index_transport,
1659
1677
self._pack_transport, upload_suffix='.pack',
1660
file_mode=self.repo.control_files._file_mode)
1678
file_mode=self.repo.bzrdir._get_file_mode())
1661
1679
# allow writing: queue writes to a new index
1662
1680
self.revision_index.add_writable_index(self._new_pack.revision_index,
1663
1681
self._new_pack)
1740
1758
add_callback=add_callback)
1741
1759
self.repo._revision_knit = knit.KnitVersionedFile(
1742
1760
'revisions', self.transport.clone('..'),
1743
self.repo.control_files._file_mode,
1744
create=False, access_mode=self.repo._access_mode(),
1761
self.repo.bzrdir._get_file_mode(),
1745
1763
index=knit_index, delta=False, factory=knit.KnitPlainFactory(),
1746
1764
access_method=self.repo._pack_collection.revision_index.knit_access)
1747
1765
return self.repo._revision_knit
1758
1776
add_callback=add_callback, parents=False)
1759
1777
self.repo._signature_knit = knit.KnitVersionedFile(
1760
1778
'signatures', self.transport.clone('..'),
1761
self.repo.control_files._file_mode,
1762
create=False, access_mode=self.repo._access_mode(),
1779
self.repo.bzrdir._get_file_mode(),
1763
1781
index=knit_index, delta=False, factory=knit.KnitPlainFactory(),
1764
1782
access_method=self.repo._pack_collection.signature_index.knit_access)
1765
1783
return self.repo._signature_knit
1847
1865
add_callback=add_callback, deltas=True, parents=True)
1848
1866
return knit.KnitVersionedFile(
1849
1867
'inventory', self.transport.clone('..'),
1850
self.repo.control_files._file_mode,
1851
create=False, access_mode=self.repo._access_mode(),
1868
self.repo.bzrdir._get_file_mode(),
1852
1870
index=knit_index, delta=True, factory=knit.KnitPlainFactory(),
1853
1871
access_method=self.repo._pack_collection.inventory_index.knit_access)
1856
1874
class KnitPackRepository(KnitRepository):
1857
"""Experimental graph-knit using repository."""
1875
"""Repository with knit objects stored inside pack containers."""
1859
1877
def __init__(self, _format, a_bzrdir, control_files, _revision_store,
1860
1878
control_store, text_store, _commit_builder_class, _serializer):
1861
1879
KnitRepository.__init__(self, _format, a_bzrdir, control_files,
1862
1880
_revision_store, control_store, text_store, _commit_builder_class,
1864
index_transport = control_files._transport.clone('indices')
1865
self._pack_collection = RepositoryPackCollection(self, control_files._transport,
1882
index_transport = self._transport.clone('indices')
1883
self._pack_collection = RepositoryPackCollection(self,
1866
1885
index_transport,
1867
control_files._transport.clone('upload'),
1868
control_files._transport.clone('packs'))
1886
self._transport.clone('upload'),
1887
self._transport.clone('packs'))
1869
1888
self._revision_store = KnitPackRevisionStore(self, index_transport, self._revision_store)
1870
1889
self.weave_store = KnitPackTextStore(self, index_transport, self.weave_store)
1871
1890
self._inv_thunk = InventoryKnitThunk(self, index_transport)
1884
1903
def _abort_write_group(self):
1885
1904
self._pack_collection._abort_write_group()
1887
def _access_mode(self):
1888
"""Return 'w' or 'r' for depending on whether a write lock is active.
1890
This method is a helper for the Knit-thunking support objects.
1892
if self.is_write_locked():
1896
1906
def _add_fallback_repository_check(self, repository):
1897
1907
"""Check that this repository can fallback to repository safely.
1957
1967
self._pack_collection.ensure_loaded()
1958
1968
index = self._pack_collection.revision_index.combined_index
1959
1969
keys = set(keys)
1971
raise ValueError('get_parent_map(None) is not valid')
1960
1972
if _mod_revision.NULL_REVISION in keys:
1961
1973
keys.discard(_mod_revision.NULL_REVISION)
1962
1974
found_parents = {_mod_revision.NULL_REVISION:()}
2110
2122
repo_transport,
2111
2123
prefixed=False,
2112
2124
file_mode=control_files._file_mode,
2113
versionedfile_class=knit.KnitVersionedFile,
2125
versionedfile_class=knit.make_file_knit,
2114
2126
versionedfile_kwargs={'factory': knit.KnitPlainFactory()},
2121
2133
file_mode=control_files._file_mode,
2122
2134
prefixed=False,
2124
versionedfile_class=knit.KnitVersionedFile,
2136
versionedfile_class=knit.make_file_knit,
2125
2137
versionedfile_kwargs={'delta': False,
2126
2138
'factory': knit.KnitPlainFactory(),
2134
2146
return self._get_versioned_file_store('knits',
2137
versionedfile_class=knit.KnitVersionedFile,
2149
versionedfile_class=knit.make_file_knit,
2138
2150
versionedfile_kwargs={
2139
2151
'create_parent_dir': True,
2140
2152
'delay_create': True,
2170
2182
format = RepositoryFormat.find_format(a_bzrdir)
2171
assert format.__class__ == self.__class__
2172
2183
if _override_transport is not None:
2173
2184
repo_transport = _override_transport
2175
2186
repo_transport = a_bzrdir.get_repository_transport(None)
2176
2187
control_files = lockable_files.LockableFiles(repo_transport,
2177
'lock', lockdir.LockDir)
2188
'lock', lockdir.LockDir)
2178
2189
text_store = self._get_text_store(repo_transport, control_files)
2179
2190
control_store = self._get_control_store(repo_transport, control_files)
2180
2191
_revision_store = self._get_revision_store(repo_transport, control_files)
2377
2388
class RepositoryFormatPackDevelopment1(RepositoryFormatPackDevelopment0):
2378
2389
"""A no-subtrees development repository.
2380
This format should be retained until the second release after bzr 1.2.
2391
This format should be retained until the second release after bzr 1.5.
2382
2393
Supports external lookups, which results in non-truncated ghosts after
2383
2394
reconcile compared to pack-0.92 formats.
2396
2407
def get_format_string(self):
2397
2408
"""See RepositoryFormat.get_format_string()."""
2398
return "Bazaar development format 1 (needs bzr.dev from before 1.3)\n"
2409
return "Bazaar development format 1 (needs bzr.dev from before 1.6)\n"
2400
2411
def get_format_description(self):
2401
2412
"""See RepositoryFormat.get_format_description()."""
2409
2420
class RepositoryFormatPackDevelopment1Subtree(RepositoryFormatPackDevelopment0Subtree):
2410
2421
"""A subtrees development repository.
2412
This format should be retained until the second release after bzr 1.2.
2423
This format should be retained until the second release after bzr 1.5.
2414
2425
Supports external lookups, which results in non-truncated ghosts after
2415
2426
reconcile compared to pack-0.92 formats.
2437
2448
def get_format_string(self):
2438
2449
"""See RepositoryFormat.get_format_string()."""
2439
2450
return ("Bazaar development format 1 with subtree support "
2440
"(needs bzr.dev from before 1.3)\n")
2451
"(needs bzr.dev from before 1.6)\n")
2442
2453
def get_format_description(self):
2443
2454
"""See RepositoryFormat.get_format_description()."""