1094
1094
extent possible considering file system caching etc).
1097
def suspend_write_group(self):
1098
raise errors.UnsuspendableWriteGroup(self)
1100
def resume_write_group(self, tokens):
1101
if not self.is_write_locked():
1102
raise errors.NotWriteLocked(self)
1103
if self._write_group:
1104
raise errors.BzrError('already in a write group')
1105
self._resume_write_group(tokens)
1106
# so we can detect unlock/relock - the write group is now entered.
1107
self._write_group = self.get_transaction()
1109
def _resume_write_group(self, tokens):
1110
raise errors.UnsuspendableWriteGroup(self)
1097
1112
def fetch(self, source, revision_id=None, pb=None, find_ghosts=False):
1098
1113
"""Fetch the content required to construct revision_id from source.
2191
2210
class RepositoryFormatRegistry(registry.Registry):
2192
2211
"""Registry of RepositoryFormats."""
2213
def __init__(self, other_registry=None):
2214
registry.Registry.__init__(self)
2215
self._other_registry = other_registry
2217
def register_lazy(self, key, module_name, member_name,
2218
help=None, info=None,
2219
override_existing=False):
2220
# Overridden to allow capturing registrations to two seperate
2221
# registries in a single call.
2222
registry.Registry.register_lazy(self, key, module_name, member_name,
2223
help=help, info=info, override_existing=override_existing)
2224
if self._other_registry is not None:
2225
self._other_registry.register_lazy(key, module_name, member_name,
2226
help=help, info=info, override_existing=override_existing)
2194
2228
def get(self, format_string):
2195
2229
r = registry.Registry.get(self, format_string)
2196
2230
if callable(r):
2201
format_registry = RepositoryFormatRegistry()
2202
"""Registry of formats, indexed by their identifying format string.
2235
network_format_registry = RepositoryFormatRegistry()
2236
"""Registry of formats indexed by their network name.
2238
The network name for a repository format is an identifier that can be used when
2239
referring to formats with smart server operations. See
2240
RepositoryFormat.network_name() for more detail.
2244
format_registry = RepositoryFormatRegistry(network_format_registry)
2245
"""Registry of formats, indexed by their BzrDirMetaFormat format string.
2204
2247
This can contain either format instances themselves, or classes/factories that
2205
2248
can be called to obtain one.
2212
2255
class RepositoryFormat(object):
2213
2256
"""A repository format.
2215
Formats provide three things:
2258
Formats provide four things:
2216
2259
* An initialization routine to construct repository data on disk.
2217
* a format string which is used when the BzrDir supports versioned
2260
* a optional format string which is used when the BzrDir supports
2219
2262
* an open routine which returns a Repository instance.
2263
* A network name for referring to the format in smart server RPC
2221
2266
There is one and only one Format subclass for each on-disk format. But
2222
2267
there can be one Repository subclass that is used for several different
2223
2268
formats. The _format attribute on a Repository instance can be used to
2224
2269
determine the disk format.
2226
Formats are placed in an dict by their format string for reference
2227
during opening. These should be subclasses of RepositoryFormat
2271
Formats are placed in a registry by their format string for reference
2272
during opening. These should be subclasses of RepositoryFormat for
2230
2275
Once a format is deprecated, just deprecate the initialize and open
2231
2276
methods on the format class. Do not deprecate the object, as the
2232
object will be created every system load.
2277
object may be created even when a repository instnace hasn't been
2234
2280
Common instance attributes:
2235
2281
_matchingbzrdir - the bzrdir format that the repository format was
2398
2454
control_files.unlock()
2401
# formats which have no format string are not discoverable
2402
# and not independently creatable, so are not registered. They're
2456
def network_name(self):
2457
"""Metadir formats have matching disk and network format strings."""
2458
return self.get_format_string()
2461
# Pre-0.8 formats that don't have a disk format string (because they are
2462
# versioned by the matching control directory). We use the control directories
2463
# disk format string as a key for the network_name because they meet the
2464
# constraints (simple string, unique, immmutable).
2465
network_format_registry.register_lazy(
2466
"Bazaar-NG branch, format 5\n",
2467
'bzrlib.repofmt.weaverepo',
2468
'RepositoryFormat5',
2470
network_format_registry.register_lazy(
2471
"Bazaar-NG branch, format 6\n",
2472
'bzrlib.repofmt.weaverepo',
2473
'RepositoryFormat6',
2476
# formats which have no format string are not discoverable or independently
2477
# creatable on disk, so are not registered in format_registry. They're
2403
2478
# all in bzrlib.repofmt.weaverepo now. When an instance of one of these is
2404
2479
# needed, it's constructed directly by the BzrDir. Non-native formats where
2405
2480
# the repository is not separately opened are similar.
3413
3488
def _autopack(self):
3414
3489
self.target.autopack()
3492
def fetch(self, revision_id=None, pb=None, find_ghosts=False):
3493
"""See InterRepository.fetch()."""
3494
# Always fetch using the generic streaming fetch code, to allow
3495
# streaming fetching into remote servers.
3496
from bzrlib.fetch import RepoFetcher
3497
fetcher = RepoFetcher(self.target, self.source, revision_id,
3499
self.target.autopack()
3500
return fetcher.count_copied, fetcher.failed_revisions
3416
3502
def _get_target_pack_collection(self):
3417
3503
return self.target._real_repository._pack_collection
3587
3673
revision_graph[key] = tuple(parent for parent in parents if parent
3588
3674
in revision_graph)
3589
3675
return revision_graph
3678
class StreamSink(object):
3679
"""An object that can insert a stream into a repository.
3681
This interface handles the complexity of reserialising inventories and
3682
revisions from different formats, and allows unidirectional insertion into
3683
stacked repositories without looking for the missing basis parents
3687
def __init__(self, target_repo):
3688
self.target_repo = target_repo
3690
def insert_stream(self, stream, src_format):
3691
"""Insert a stream's content into the target repository.
3693
:param src_format: a bzr repository format.
3695
:return: an iterable of keys additional items required before the
3696
insertion can be completed.
3699
to_serializer = self.target_repo._format._serializer
3700
src_serializer = src_format._serializer
3701
for substream_type, substream in stream:
3702
if substream_type == 'texts':
3703
self.target_repo.texts.insert_record_stream(substream)
3704
elif substream_type == 'inventories':
3705
if src_serializer == to_serializer:
3706
self.target_repo.inventories.insert_record_stream(
3709
self._extract_and_insert_inventories(
3710
substream, src_serializer)
3711
elif substream_type == 'revisions':
3712
# This may fallback to extract-and-insert more often than
3713
# required if the serializers are different only in terms of
3715
if src_serializer == to_serializer:
3716
self.target_repo.revisions.insert_record_stream(
3719
self._extract_and_insert_revisions(substream,
3721
elif substream_type == 'signatures':
3722
self.target_repo.signatures.insert_record_stream(substream)
3724
raise AssertionError('kaboom! %s' % (substream_type,))
3727
def _extract_and_insert_inventories(self, substream, serializer):
3728
"""Generate a new inventory versionedfile in target, converting data.
3730
The inventory is retrieved from the source, (deserializing it), and
3731
stored in the target (reserializing it in a different format).
3733
for record in substream:
3734
bytes = record.get_bytes_as('fulltext')
3735
revision_id = record.key[0]
3736
inv = serializer.read_inventory_from_string(bytes, revision_id)
3737
parents = [key[0] for key in record.parents]
3738
self.target_repo.add_inventory(revision_id, inv, parents)
3740
def _extract_and_insert_revisions(self, substream, serializer):
3741
for record in substream:
3742
bytes = record.get_bytes_as('fulltext')
3743
revision_id = record.key[0]
3744
rev = serializer.read_revision_from_string(bytes)
3745
if rev.revision_id != revision_id:
3746
raise AssertionError('wtf: %s != %s' % (rev, revision_id))
3747
self.target_repo.add_revision(revision_id, rev)
3750
if self.target_repo._fetch_reconcile:
3751
self.target_repo.reconcile()