79
_file_ids_altered_regex = lazy_regex.lazy_compile(
80
r'file_id="(?P<file_id>[^"]+)"'
81
r'.*revision="(?P<revision_id>[^"]+)"'
85
def add_inventory(self, revision_id, inv, parents):
86
"""Add the inventory inv to the repository as revision_id.
85
def add_inventory(self, revid, inv, parents):
86
"""Add the inventory inv to the repository as revid.
88
:param parents: The revision ids of the parents that revision_id
88
:param parents: The revision ids of the parents that revid
89
89
is known to have and are in the repository already.
91
91
returns the sha1 of the serialized inventory.
93
revision_id = osutils.safe_revision_id(revision_id)
94
_mod_revision.check_not_reserved_id(revision_id)
95
assert inv.revision_id is None or inv.revision_id == revision_id, \
93
assert inv.revision_id is None or inv.revision_id == revid, \
96
94
"Mismatch between inventory revision" \
97
" id and insertion revid (%r, %r)" % (inv.revision_id, revision_id)
95
" id and insertion revid (%r, %r)" % (inv.revision_id, revid)
98
96
assert inv.root is not None
99
97
inv_text = self.serialise_inventory(inv)
100
98
inv_sha1 = osutils.sha_string(inv_text)
101
99
inv_vf = self.control_weaves.get_weave('inventory',
102
100
self.get_transaction())
103
self._inventory_add_lines(inv_vf, revision_id, parents,
104
osutils.split_lines(inv_text))
101
self._inventory_add_lines(inv_vf, revid, parents, osutils.split_lines(inv_text))
107
def _inventory_add_lines(self, inv_vf, revision_id, parents, lines):
104
def _inventory_add_lines(self, inv_vf, revid, parents, lines):
108
105
final_parents = []
109
106
for parent in parents:
110
107
if parent in inv_vf:
111
108
final_parents.append(parent)
113
inv_vf.add_lines(revision_id, final_parents, lines)
110
inv_vf.add_lines(revid, final_parents, lines)
115
112
@needs_write_lock
116
def add_revision(self, revision_id, rev, inv=None, config=None):
117
"""Add rev to the revision store as revision_id.
113
def add_revision(self, rev_id, rev, inv=None, config=None):
114
"""Add rev to the revision store as rev_id.
119
:param revision_id: the revision id to use.
116
:param rev_id: the revision id to use.
120
117
:param rev: The revision object.
121
118
:param inv: The inventory for the revision. if None, it will be looked
122
119
up in the inventory storer
257
232
def get_physical_lock_status(self):
258
233
return self.control_files.get_physical_lock_status()
260
def leave_lock_in_place(self):
261
"""Tell this repository not to release the physical lock when this
264
If lock_write doesn't return a token, then this method is not supported.
266
self.control_files.leave_in_place()
268
def dont_leave_lock_in_place(self):
269
"""Tell this repository to release the physical lock when this
270
object is unlocked, even if it didn't originally acquire it.
272
If lock_write doesn't return a token, then this method is not supported.
274
self.control_files.dont_leave_in_place()
277
def gather_stats(self, revid=None, committers=None):
278
"""Gather statistics from a revision id.
280
:param revid: The revision id to gather statistics from, if None, then
281
no revision specific statistics are gathered.
282
:param committers: Optional parameter controlling whether to grab
283
a count of committers from the revision specific statistics.
284
:return: A dictionary of statistics. Currently this contains:
285
committers: The number of committers if requested.
286
firstrev: A tuple with timestamp, timezone for the penultimate left
287
most ancestor of revid, if revid is not the NULL_REVISION.
288
latestrev: A tuple with timestamp, timezone for revid, if revid is
289
not the NULL_REVISION.
290
revisions: The total revision count in the repository.
291
size: An estimate disk size of the repository in bytes.
294
if revid and committers:
295
result['committers'] = 0
296
if revid and revid != _mod_revision.NULL_REVISION:
298
all_committers = set()
299
revisions = self.get_ancestry(revid)
300
# pop the leading None
302
first_revision = None
304
# ignore the revisions in the middle - just grab first and last
305
revisions = revisions[0], revisions[-1]
306
for revision in self.get_revisions(revisions):
307
if not first_revision:
308
first_revision = revision
310
all_committers.add(revision.committer)
311
last_revision = revision
313
result['committers'] = len(all_committers)
314
result['firstrev'] = (first_revision.timestamp,
315
first_revision.timezone)
316
result['latestrev'] = (last_revision.timestamp,
317
last_revision.timezone)
319
# now gather global repository information
320
if self.bzrdir.root_transport.listable():
321
c, t = self._revision_store.total_size(self.get_transaction())
322
result['revisions'] = c
327
236
def missing_revision_ids(self, other, revision_id=None):
328
237
"""Return the revision ids that other has that this does not.
959
727
def supports_rich_root(self):
960
728
return self._format.rich_root_data
962
def _check_ascii_revisionid(self, revision_id, method):
963
"""Private helper for ascii-only repositories."""
964
# weave repositories refuse to store revisionids that are non-ascii.
965
if revision_id is not None:
966
# weaves require ascii revision ids.
967
if isinstance(revision_id, unicode):
969
revision_id.encode('ascii')
970
except UnicodeEncodeError:
971
raise errors.NonAsciiRevisionId(method, self)
974
revision_id.decode('ascii')
975
except UnicodeDecodeError:
976
raise errors.NonAsciiRevisionId(method, self)
980
# remove these delegates a while after bzr 0.15
981
def __make_delegated(name, from_module):
982
def _deprecated_repository_forwarder():
983
symbol_versioning.warn('%s moved to %s in bzr 0.15'
984
% (name, from_module),
987
m = __import__(from_module, globals(), locals(), [name])
989
return getattr(m, name)
990
except AttributeError:
991
raise AttributeError('module %s has no name %s'
993
globals()[name] = _deprecated_repository_forwarder
996
'AllInOneRepository',
997
'WeaveMetaDirRepository',
998
'PreSplitOutRepositoryFormat',
1000
'RepositoryFormat5',
1001
'RepositoryFormat6',
1002
'RepositoryFormat7',
1004
__make_delegated(_name, 'bzrlib.repofmt.weaverepo')
1008
'RepositoryFormatKnit',
1009
'RepositoryFormatKnit1',
1011
__make_delegated(_name, 'bzrlib.repofmt.knitrepo')
731
class AllInOneRepository(Repository):
732
"""Legacy support - the repository behaviour for all-in-one branches."""
734
def __init__(self, _format, a_bzrdir, _revision_store, control_store, text_store):
735
# we reuse one control files instance.
736
dir_mode = a_bzrdir._control_files._dir_mode
737
file_mode = a_bzrdir._control_files._file_mode
739
def get_store(name, compressed=True, prefixed=False):
740
# FIXME: This approach of assuming stores are all entirely compressed
741
# or entirely uncompressed is tidy, but breaks upgrade from
742
# some existing branches where there's a mixture; we probably
743
# still want the option to look for both.
744
relpath = a_bzrdir._control_files._escape(name)
745
store = TextStore(a_bzrdir._control_files._transport.clone(relpath),
746
prefixed=prefixed, compressed=compressed,
749
#if self._transport.should_cache():
750
# cache_path = os.path.join(self.cache_root, name)
751
# os.mkdir(cache_path)
752
# store = bzrlib.store.CachedStore(store, cache_path)
755
# not broken out yet because the controlweaves|inventory_store
756
# and text_store | weave_store bits are still different.
757
if isinstance(_format, RepositoryFormat4):
758
# cannot remove these - there is still no consistent api
759
# which allows access to this old info.
760
self.inventory_store = get_store('inventory-store')
761
text_store = get_store('text-store')
762
super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files, _revision_store, control_store, text_store)
766
"""AllInOne repositories cannot be shared."""
770
def set_make_working_trees(self, new_value):
771
"""Set the policy flag for making working trees when creating branches.
773
This only applies to branches that use this repository.
775
The default is 'True'.
776
:param new_value: True to restore the default, False to disable making
779
raise NotImplementedError(self.set_make_working_trees)
781
def make_working_trees(self):
782
"""Returns the policy for making working trees on new branches."""
1014
786
def install_revision(repository, rev, revision_tree):
1100
872
return not self.control_files._transport.has('no-working-trees')
1103
class RepositoryFormatRegistry(registry.Registry):
1104
"""Registry of RepositoryFormats.
1107
def get(self, format_string):
1108
r = registry.Registry.get(self, format_string)
875
class KnitRepository(MetaDirRepository):
876
"""Knit format repository."""
878
def _warn_if_deprecated(self):
879
# This class isn't deprecated
882
def _inventory_add_lines(self, inv_vf, revid, parents, lines):
883
inv_vf.add_lines_with_ghosts(revid, parents, lines)
886
def _all_revision_ids(self):
887
"""See Repository.all_revision_ids()."""
888
# Knits get the revision graph from the index of the revision knit, so
889
# it's always possible even if they're on an unlistable transport.
890
return self._revision_store.all_revision_ids(self.get_transaction())
892
def fileid_involved_between_revs(self, from_revid, to_revid):
893
"""Find file_id(s) which are involved in the changes between revisions.
895
This determines the set of revisions which are involved, and then
896
finds all file ids affected by those revisions.
898
vf = self._get_revision_vf()
899
from_set = set(vf.get_ancestry(from_revid))
900
to_set = set(vf.get_ancestry(to_revid))
901
changed = to_set.difference(from_set)
902
return self._fileid_involved_by_set(changed)
904
def fileid_involved(self, last_revid=None):
905
"""Find all file_ids modified in the ancestry of last_revid.
907
:param last_revid: If None, last_revision() will be used.
910
changed = set(self.all_revision_ids())
912
changed = set(self.get_ancestry(last_revid))
915
return self._fileid_involved_by_set(changed)
918
def get_ancestry(self, revision_id):
919
"""Return a list of revision-ids integrated by a revision.
921
This is topologically sorted.
923
if revision_id is None:
925
vf = self._get_revision_vf()
927
return [None] + vf.get_ancestry(revision_id)
928
except errors.RevisionNotPresent:
929
raise errors.NoSuchRevision(self, revision_id)
932
def get_revision(self, revision_id):
933
"""Return the Revision object for a named revision"""
934
return self.get_revision_reconcile(revision_id)
937
def get_revision_graph(self, revision_id=None):
938
"""Return a dictionary containing the revision graph.
940
:param revision_id: The revision_id to get a graph from. If None, then
941
the entire revision graph is returned. This is a deprecated mode of
942
operation and will be removed in the future.
943
:return: a dictionary of revision_id->revision_parents_list.
945
# special case NULL_REVISION
946
if revision_id == _mod_revision.NULL_REVISION:
948
a_weave = self._get_revision_vf()
949
entire_graph = a_weave.get_graph()
950
if revision_id is None:
951
return a_weave.get_graph()
952
elif revision_id not in a_weave:
953
raise errors.NoSuchRevision(self, revision_id)
955
# add what can be reached from revision_id
957
pending = set([revision_id])
958
while len(pending) > 0:
960
result[node] = a_weave.get_parents(node)
961
for revision_id in result[node]:
962
if revision_id not in result:
963
pending.add(revision_id)
967
def get_revision_graph_with_ghosts(self, revision_ids=None):
968
"""Return a graph of the revisions with ghosts marked as applicable.
970
:param revision_ids: an iterable of revisions to graph or None for all.
971
:return: a Graph object with the graph reachable from revision_ids.
973
result = graph.Graph()
974
vf = self._get_revision_vf()
975
versions = set(vf.versions())
977
pending = set(self.all_revision_ids())
980
pending = set(revision_ids)
981
# special case NULL_REVISION
982
if _mod_revision.NULL_REVISION in pending:
983
pending.remove(_mod_revision.NULL_REVISION)
984
required = set(pending)
987
revision_id = pending.pop()
988
if not revision_id in versions:
989
if revision_id in required:
990
raise errors.NoSuchRevision(self, revision_id)
992
result.add_ghost(revision_id)
993
# mark it as done so we don't try for it again.
994
done.add(revision_id)
996
parent_ids = vf.get_parents_with_ghosts(revision_id)
997
for parent_id in parent_ids:
998
# is this queued or done ?
999
if (parent_id not in pending and
1000
parent_id not in done):
1002
pending.add(parent_id)
1003
result.add_node(revision_id, parent_ids)
1004
done.add(revision_id)
1007
def _get_revision_vf(self):
1008
""":return: a versioned file containing the revisions."""
1009
vf = self._revision_store.get_revision_file(self.get_transaction())
1013
def reconcile(self, other=None, thorough=False):
1014
"""Reconcile this repository."""
1015
from bzrlib.reconcile import KnitReconciler
1016
reconciler = KnitReconciler(self, thorough=thorough)
1017
reconciler.reconcile()
1114
format_registry = RepositoryFormatRegistry()
1115
"""Registry of formats, indexed by their identifying format string.
1117
This can contain either format instances themselves, or classes/factories that
1118
can be called to obtain one.
1122
#####################################################################
1123
# Repository Formats
1020
def revision_parents(self, revision_id):
1021
return self._get_revision_vf().get_parents(revision_id)
1024
class KnitRepository2(KnitRepository):
1026
def __init__(self, _format, a_bzrdir, control_files, _revision_store,
1027
control_store, text_store):
1028
KnitRepository.__init__(self, _format, a_bzrdir, control_files,
1029
_revision_store, control_store, text_store)
1030
self._serializer = xml6.serializer_v6
1032
def deserialise_inventory(self, revision_id, xml):
1033
"""Transform the xml into an inventory object.
1035
:param revision_id: The expected revision id of the inventory.
1036
:param xml: A serialised inventory.
1038
result = self._serializer.read_inventory_from_string(xml)
1039
assert result.root.revision is not None
1042
def serialise_inventory(self, inv):
1043
"""Transform the inventory object into XML text.
1045
:param revision_id: The expected revision id of the inventory.
1046
:param xml: A serialised inventory.
1048
assert inv.revision_id is not None
1049
assert inv.root.revision is not None
1050
return KnitRepository.serialise_inventory(self, inv)
1052
def get_commit_builder(self, branch, parents, config, timestamp=None,
1053
timezone=None, committer=None, revprops=None,
1055
"""Obtain a CommitBuilder for this repository.
1057
:param branch: Branch to commit to.
1058
:param parents: Revision ids of the parents of the new revision.
1059
:param config: Configuration to use.
1060
:param timestamp: Optional timestamp recorded for commit.
1061
:param timezone: Optional timezone for timestamp.
1062
:param committer: Optional committer to set for commit.
1063
:param revprops: Optional dictionary of revision properties.
1064
:param revision_id: Optional revision id.
1066
return RootCommitBuilder(self, parents, config, timestamp, timezone,
1067
committer, revprops, revision_id)
1125
1070
class RepositoryFormat(object):
1126
1071
"""A repository format.
1284
1208
raise NotImplementedError(self.open)
1211
def register_format(klass, format):
1212
klass._formats[format.get_format_string()] = format
1215
def set_default_format(klass, format):
1216
klass._default_format = format
1219
def unregister_format(klass, format):
1220
assert klass._formats[format.get_format_string()] is format
1221
del klass._formats[format.get_format_string()]
1224
class PreSplitOutRepositoryFormat(RepositoryFormat):
1225
"""Base class for the pre split out repository formats."""
1227
rich_root_data = False
1229
def initialize(self, a_bzrdir, shared=False, _internal=False):
1230
"""Create a weave repository.
1232
TODO: when creating split out bzr branch formats, move this to a common
1233
base for Format5, Format6. or something like that.
1236
raise errors.IncompatibleFormat(self, a_bzrdir._format)
1239
# always initialized when the bzrdir is.
1240
return self.open(a_bzrdir, _found=True)
1242
# Create an empty weave
1244
weavefile.write_weave_v5(weave.Weave(), sio)
1245
empty_weave = sio.getvalue()
1247
mutter('creating repository in %s.', a_bzrdir.transport.base)
1248
dirs = ['revision-store', 'weaves']
1249
files = [('inventory.weave', StringIO(empty_weave)),
1252
# FIXME: RBC 20060125 don't peek under the covers
1253
# NB: no need to escape relative paths that are url safe.
1254
control_files = lockable_files.LockableFiles(a_bzrdir.transport,
1255
'branch-lock', lockable_files.TransportLock)
1256
control_files.create_lock()
1257
control_files.lock_write()
1258
control_files._transport.mkdir_multi(dirs,
1259
mode=control_files._dir_mode)
1261
for file, content in files:
1262
control_files.put(file, content)
1264
control_files.unlock()
1265
return self.open(a_bzrdir, _found=True)
1267
def _get_control_store(self, repo_transport, control_files):
1268
"""Return the control store for this repository."""
1269
return self._get_versioned_file_store('',
1274
def _get_text_store(self, transport, control_files):
1275
"""Get a store for file texts for this format."""
1276
raise NotImplementedError(self._get_text_store)
1278
def open(self, a_bzrdir, _found=False):
1279
"""See RepositoryFormat.open()."""
1281
# we are being called directly and must probe.
1282
raise NotImplementedError
1284
repo_transport = a_bzrdir.get_repository_transport(None)
1285
control_files = a_bzrdir._control_files
1286
text_store = self._get_text_store(repo_transport, control_files)
1287
control_store = self._get_control_store(repo_transport, control_files)
1288
_revision_store = self._get_revision_store(repo_transport, control_files)
1289
return AllInOneRepository(_format=self,
1291
_revision_store=_revision_store,
1292
control_store=control_store,
1293
text_store=text_store)
1295
def check_conversion_target(self, target_format):
1299
class RepositoryFormat4(PreSplitOutRepositoryFormat):
1300
"""Bzr repository format 4.
1302
This repository format has:
1304
- TextStores for texts, inventories,revisions.
1306
This format is deprecated: it indexes texts using a text id which is
1307
removed in format 5; initialization and write support for this format
1312
super(RepositoryFormat4, self).__init__()
1313
self._matchingbzrdir = bzrdir.BzrDirFormat4()
1315
def get_format_description(self):
1316
"""See RepositoryFormat.get_format_description()."""
1317
return "Repository format 4"
1319
def initialize(self, url, shared=False, _internal=False):
1320
"""Format 4 branches cannot be created."""
1321
raise errors.UninitializableFormat(self)
1323
def is_supported(self):
1324
"""Format 4 is not supported.
1326
It is not supported because the model changed from 4 to 5 and the
1327
conversion logic is expensive - so doing it on the fly was not
1332
def _get_control_store(self, repo_transport, control_files):
1333
"""Format 4 repositories have no formal control store at this point.
1335
This will cause any control-file-needing apis to fail - this is desired.
1339
def _get_revision_store(self, repo_transport, control_files):
1340
"""See RepositoryFormat._get_revision_store()."""
1341
from bzrlib.xml4 import serializer_v4
1342
return self._get_text_rev_store(repo_transport,
1345
serializer=serializer_v4)
1347
def _get_text_store(self, transport, control_files):
1348
"""See RepositoryFormat._get_text_store()."""
1351
class RepositoryFormat5(PreSplitOutRepositoryFormat):
1352
"""Bzr control format 5.
1354
This repository format has:
1355
- weaves for file texts and inventory
1357
- TextStores for revisions and signatures.
1361
super(RepositoryFormat5, self).__init__()
1362
self._matchingbzrdir = bzrdir.BzrDirFormat5()
1364
def get_format_description(self):
1365
"""See RepositoryFormat.get_format_description()."""
1366
return "Weave repository format 5"
1368
def _get_revision_store(self, repo_transport, control_files):
1369
"""See RepositoryFormat._get_revision_store()."""
1370
"""Return the revision store object for this a_bzrdir."""
1371
return self._get_text_rev_store(repo_transport,
1376
def _get_text_store(self, transport, control_files):
1377
"""See RepositoryFormat._get_text_store()."""
1378
return self._get_versioned_file_store('weaves', transport, control_files, prefixed=False)
1381
class RepositoryFormat6(PreSplitOutRepositoryFormat):
1382
"""Bzr control format 6.
1384
This repository format has:
1385
- weaves for file texts and inventory
1386
- hash subdirectory based stores.
1387
- TextStores for revisions and signatures.
1391
super(RepositoryFormat6, self).__init__()
1392
self._matchingbzrdir = bzrdir.BzrDirFormat6()
1394
def get_format_description(self):
1395
"""See RepositoryFormat.get_format_description()."""
1396
return "Weave repository format 6"
1398
def _get_revision_store(self, repo_transport, control_files):
1399
"""See RepositoryFormat._get_revision_store()."""
1400
return self._get_text_rev_store(repo_transport,
1406
def _get_text_store(self, transport, control_files):
1407
"""See RepositoryFormat._get_text_store()."""
1408
return self._get_versioned_file_store('weaves', transport, control_files)
1287
1411
class MetaDirRepositoryFormat(RepositoryFormat):
1288
1412
"""Common base class for the new repositories using the metadir layout."""
1290
1414
rich_root_data = False
1291
supports_tree_reference = False
1292
_matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1294
1416
def __init__(self):
1295
1417
super(MetaDirRepositoryFormat, self).__init__()
1418
self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1297
1420
def _create_control_files(self, a_bzrdir):
1298
1421
"""Create the required files and the initial control_files object."""
1321
1444
control_files.unlock()
1447
class RepositoryFormat7(MetaDirRepositoryFormat):
1448
"""Bzr repository 7.
1450
This repository format has:
1451
- weaves for file texts and inventory
1452
- hash subdirectory based stores.
1453
- TextStores for revisions and signatures.
1454
- a format marker of its own
1455
- an optional 'shared-storage' flag
1456
- an optional 'no-working-trees' flag
1459
def _get_control_store(self, repo_transport, control_files):
1460
"""Return the control store for this repository."""
1461
return self._get_versioned_file_store('',
1466
def get_format_string(self):
1467
"""See RepositoryFormat.get_format_string()."""
1468
return "Bazaar-NG Repository format 7"
1470
def get_format_description(self):
1471
"""See RepositoryFormat.get_format_description()."""
1472
return "Weave repository format 7"
1474
def check_conversion_target(self, target_format):
1477
def _get_revision_store(self, repo_transport, control_files):
1478
"""See RepositoryFormat._get_revision_store()."""
1479
return self._get_text_rev_store(repo_transport,
1486
def _get_text_store(self, transport, control_files):
1487
"""See RepositoryFormat._get_text_store()."""
1488
return self._get_versioned_file_store('weaves',
1492
def initialize(self, a_bzrdir, shared=False):
1493
"""Create a weave repository.
1495
:param shared: If true the repository will be initialized as a shared
1498
# Create an empty weave
1500
weavefile.write_weave_v5(weave.Weave(), sio)
1501
empty_weave = sio.getvalue()
1503
mutter('creating repository in %s.', a_bzrdir.transport.base)
1504
dirs = ['revision-store', 'weaves']
1505
files = [('inventory.weave', StringIO(empty_weave)),
1507
utf8_files = [('format', self.get_format_string())]
1509
self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1510
return self.open(a_bzrdir=a_bzrdir, _found=True)
1512
def open(self, a_bzrdir, _found=False, _override_transport=None):
1513
"""See RepositoryFormat.open().
1515
:param _override_transport: INTERNAL USE ONLY. Allows opening the
1516
repository at a slightly different url
1517
than normal. I.e. during 'upgrade'.
1520
format = RepositoryFormat.find_format(a_bzrdir)
1521
assert format.__class__ == self.__class__
1522
if _override_transport is not None:
1523
repo_transport = _override_transport
1525
repo_transport = a_bzrdir.get_repository_transport(None)
1526
control_files = lockable_files.LockableFiles(repo_transport,
1527
'lock', lockdir.LockDir)
1528
text_store = self._get_text_store(repo_transport, control_files)
1529
control_store = self._get_control_store(repo_transport, control_files)
1530
_revision_store = self._get_revision_store(repo_transport, control_files)
1531
return MetaDirRepository(_format=self,
1533
control_files=control_files,
1534
_revision_store=_revision_store,
1535
control_store=control_store,
1536
text_store=text_store)
1539
class RepositoryFormatKnit(MetaDirRepositoryFormat):
1540
"""Bzr repository knit format (generalized).
1542
This repository format has:
1543
- knits for file texts and inventory
1544
- hash subdirectory based stores.
1545
- knits for revisions and signatures
1546
- TextStores for revisions and signatures.
1547
- a format marker of its own
1548
- an optional 'shared-storage' flag
1549
- an optional 'no-working-trees' flag
1553
def _get_control_store(self, repo_transport, control_files):
1554
"""Return the control store for this repository."""
1555
return VersionedFileStore(
1558
file_mode=control_files._file_mode,
1559
versionedfile_class=knit.KnitVersionedFile,
1560
versionedfile_kwargs={'factory':knit.KnitPlainFactory()},
1563
def _get_revision_store(self, repo_transport, control_files):
1564
"""See RepositoryFormat._get_revision_store()."""
1565
from bzrlib.store.revision.knit import KnitRevisionStore
1566
versioned_file_store = VersionedFileStore(
1568
file_mode=control_files._file_mode,
1571
versionedfile_class=knit.KnitVersionedFile,
1572
versionedfile_kwargs={'delta':False,
1573
'factory':knit.KnitPlainFactory(),
1577
return KnitRevisionStore(versioned_file_store)
1579
def _get_text_store(self, transport, control_files):
1580
"""See RepositoryFormat._get_text_store()."""
1581
return self._get_versioned_file_store('knits',
1584
versionedfile_class=knit.KnitVersionedFile,
1585
versionedfile_kwargs={
1586
'create_parent_dir':True,
1587
'delay_create':True,
1588
'dir_mode':control_files._dir_mode,
1592
def initialize(self, a_bzrdir, shared=False):
1593
"""Create a knit format 1 repository.
1595
:param a_bzrdir: bzrdir to contain the new repository; must already
1597
:param shared: If true the repository will be initialized as a shared
1600
mutter('creating repository in %s.', a_bzrdir.transport.base)
1601
dirs = ['revision-store', 'knits']
1603
utf8_files = [('format', self.get_format_string())]
1605
self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1606
repo_transport = a_bzrdir.get_repository_transport(None)
1607
control_files = lockable_files.LockableFiles(repo_transport,
1608
'lock', lockdir.LockDir)
1609
control_store = self._get_control_store(repo_transport, control_files)
1610
transaction = transactions.WriteTransaction()
1611
# trigger a write of the inventory store.
1612
control_store.get_weave_or_empty('inventory', transaction)
1613
_revision_store = self._get_revision_store(repo_transport, control_files)
1614
_revision_store.has_revision_id('A', transaction)
1615
_revision_store.get_signature_file(transaction)
1616
return self.open(a_bzrdir=a_bzrdir, _found=True)
1618
def open(self, a_bzrdir, _found=False, _override_transport=None):
1619
"""See RepositoryFormat.open().
1621
:param _override_transport: INTERNAL USE ONLY. Allows opening the
1622
repository at a slightly different url
1623
than normal. I.e. during 'upgrade'.
1626
format = RepositoryFormat.find_format(a_bzrdir)
1627
assert format.__class__ == self.__class__
1628
if _override_transport is not None:
1629
repo_transport = _override_transport
1631
repo_transport = a_bzrdir.get_repository_transport(None)
1632
control_files = lockable_files.LockableFiles(repo_transport,
1633
'lock', lockdir.LockDir)
1634
text_store = self._get_text_store(repo_transport, control_files)
1635
control_store = self._get_control_store(repo_transport, control_files)
1636
_revision_store = self._get_revision_store(repo_transport, control_files)
1637
return KnitRepository(_format=self,
1639
control_files=control_files,
1640
_revision_store=_revision_store,
1641
control_store=control_store,
1642
text_store=text_store)
1645
class RepositoryFormatKnit1(RepositoryFormatKnit):
1646
"""Bzr repository knit format 1.
1648
This repository format has:
1649
- knits for file texts and inventory
1650
- hash subdirectory based stores.
1651
- knits for revisions and signatures
1652
- TextStores for revisions and signatures.
1653
- a format marker of its own
1654
- an optional 'shared-storage' flag
1655
- an optional 'no-working-trees' flag
1658
This format was introduced in bzr 0.8.
1660
def get_format_string(self):
1661
"""See RepositoryFormat.get_format_string()."""
1662
return "Bazaar-NG Knit Repository Format 1"
1664
def get_format_description(self):
1665
"""See RepositoryFormat.get_format_description()."""
1666
return "Knit repository format 1"
1668
def check_conversion_target(self, target_format):
1672
class RepositoryFormatKnit2(RepositoryFormatKnit):
1673
"""Bzr repository knit format 2.
1675
THIS FORMAT IS EXPERIMENTAL
1676
This repository format has:
1677
- knits for file texts and inventory
1678
- hash subdirectory based stores.
1679
- knits for revisions and signatures
1680
- TextStores for revisions and signatures.
1681
- a format marker of its own
1682
- an optional 'shared-storage' flag
1683
- an optional 'no-working-trees' flag
1685
- Support for recording full info about the tree root
1689
rich_root_data = True
1691
def get_format_string(self):
1692
"""See RepositoryFormat.get_format_string()."""
1693
return "Bazaar Knit Repository Format 2\n"
1695
def get_format_description(self):
1696
"""See RepositoryFormat.get_format_description()."""
1697
return "Knit repository format 2"
1699
def check_conversion_target(self, target_format):
1700
if not target_format.rich_root_data:
1701
raise errors.BadConversionTarget(
1702
'Does not support rich root data.', target_format)
1704
def open(self, a_bzrdir, _found=False, _override_transport=None):
1705
"""See RepositoryFormat.open().
1707
:param _override_transport: INTERNAL USE ONLY. Allows opening the
1708
repository at a slightly different url
1709
than normal. I.e. during 'upgrade'.
1712
format = RepositoryFormat.find_format(a_bzrdir)
1713
assert format.__class__ == self.__class__
1714
if _override_transport is not None:
1715
repo_transport = _override_transport
1717
repo_transport = a_bzrdir.get_repository_transport(None)
1718
control_files = lockable_files.LockableFiles(repo_transport, 'lock',
1720
text_store = self._get_text_store(repo_transport, control_files)
1721
control_store = self._get_control_store(repo_transport, control_files)
1722
_revision_store = self._get_revision_store(repo_transport, control_files)
1723
return KnitRepository2(_format=self,
1725
control_files=control_files,
1726
_revision_store=_revision_store,
1727
control_store=control_store,
1728
text_store=text_store)
1324
1732
# formats which have no format string are not discoverable
1325
# and not independently creatable, so are not registered. They're
1326
# all in bzrlib.repofmt.weaverepo now. When an instance of one of these is
1327
# needed, it's constructed directly by the BzrDir. Non-native formats where
1328
# the repository is not separately opened are similar.
1330
format_registry.register_lazy(
1331
'Bazaar-NG Repository format 7',
1332
'bzrlib.repofmt.weaverepo',
1335
# KEEP in sync with bzrdir.format_registry default, which controls the overall
1336
# default control directory format
1338
format_registry.register_lazy(
1339
'Bazaar-NG Knit Repository Format 1',
1340
'bzrlib.repofmt.knitrepo',
1341
'RepositoryFormatKnit1',
1343
format_registry.default_key = 'Bazaar-NG Knit Repository Format 1'
1345
format_registry.register_lazy(
1346
'Bazaar Knit Repository Format 3 (bzr 0.15)\n',
1347
'bzrlib.repofmt.knitrepo',
1348
'RepositoryFormatKnit3',
1733
# and not independently creatable, so are not registered.
1734
RepositoryFormat.register_format(RepositoryFormat7())
1735
_default_format = RepositoryFormatKnit1()
1736
RepositoryFormat.register_format(_default_format)
1737
RepositoryFormat.register_format(RepositoryFormatKnit2())
1738
RepositoryFormat.set_default_format(_default_format)
1739
_legacy_formats = [RepositoryFormat4(),
1740
RepositoryFormat5(),
1741
RepositoryFormat6()]
1352
1744
class InterRepository(InterObject):
1504
1883
@needs_write_lock
1505
def copy_content(self, revision_id=None):
1884
def copy_content(self, revision_id=None, basis=None):
1506
1885
"""See InterRepository.copy_content()."""
1507
1886
# weave specific optimised path:
1508
# TODO: jam 20070210 Internal, should be an assert, not translate
1509
revision_id = osutils.safe_revision_id(revision_id)
1511
self.target.set_make_working_trees(self.source.make_working_trees())
1512
except NotImplementedError:
1514
# FIXME do not peek!
1515
if self.source.control_files._transport.listable():
1516
pb = ui.ui_factory.nested_progress_bar()
1887
if basis is not None:
1888
# copy the basis in, then fetch remaining data.
1889
basis.copy_content_into(self.target, revision_id)
1890
# the basis copy_content_into could miss-set this.
1518
self.target.weave_store.copy_all_ids(
1519
self.source.weave_store,
1521
from_transaction=self.source.get_transaction(),
1522
to_transaction=self.target.get_transaction())
1523
pb.update('copying inventory', 0, 1)
1524
self.target.control_weaves.copy_multi(
1525
self.source.control_weaves, ['inventory'],
1526
from_transaction=self.source.get_transaction(),
1527
to_transaction=self.target.get_transaction())
1528
self.target._revision_store.text_store.copy_all_ids(
1529
self.source._revision_store.text_store,
1892
self.target.set_make_working_trees(self.source.make_working_trees())
1893
except NotImplementedError:
1534
1895
self.target.fetch(self.source, revision_id=revision_id)
1898
self.target.set_make_working_trees(self.source.make_working_trees())
1899
except NotImplementedError:
1901
# FIXME do not peek!
1902
if self.source.control_files._transport.listable():
1903
pb = ui.ui_factory.nested_progress_bar()
1905
self.target.weave_store.copy_all_ids(
1906
self.source.weave_store,
1908
from_transaction=self.source.get_transaction(),
1909
to_transaction=self.target.get_transaction())
1910
pb.update('copying inventory', 0, 1)
1911
self.target.control_weaves.copy_multi(
1912
self.source.control_weaves, ['inventory'],
1913
from_transaction=self.source.get_transaction(),
1914
to_transaction=self.target.get_transaction())
1915
self.target._revision_store.text_store.copy_all_ids(
1916
self.source._revision_store.text_store,
1921
self.target.fetch(self.source, revision_id=revision_id)
1536
1923
@needs_write_lock
1537
1924
def fetch(self, revision_id=None, pb=None):
1739
2114
return f.count_copied, f.failed_revisions
1742
class InterRemoteRepository(InterRepository):
1743
"""Code for converting between RemoteRepository objects.
1745
This just gets an non-remote repository from the RemoteRepository, and calls
1746
InterRepository.get again.
1749
def __init__(self, source, target):
1750
if isinstance(source, remote.RemoteRepository):
1751
source._ensure_real()
1752
real_source = source._real_repository
1754
real_source = source
1755
if isinstance(target, remote.RemoteRepository):
1756
target._ensure_real()
1757
real_target = target._real_repository
1759
real_target = target
1760
self.real_inter = InterRepository.get(real_source, real_target)
1763
def is_compatible(source, target):
1764
if isinstance(source, remote.RemoteRepository):
1766
if isinstance(target, remote.RemoteRepository):
1770
def copy_content(self, revision_id=None):
1771
self.real_inter.copy_content(revision_id=revision_id)
1773
def fetch(self, revision_id=None, pb=None):
1774
self.real_inter.fetch(revision_id=revision_id, pb=pb)
1777
def _get_repo_format_to_test(self):
1781
2117
InterRepository.register_optimiser(InterSameDataRepository)
1782
2118
InterRepository.register_optimiser(InterWeaveRepo)
1783
2119
InterRepository.register_optimiser(InterKnitRepo)
1784
2120
InterRepository.register_optimiser(InterModel1and2)
1785
2121
InterRepository.register_optimiser(InterKnit1and2)
1786
InterRepository.register_optimiser(InterRemoteRepository)
2124
class RepositoryTestProviderAdapter(object):
2125
"""A tool to generate a suite testing multiple repository formats at once.
2127
This is done by copying the test once for each transport and injecting
2128
the transport_server, transport_readonly_server, and bzrdir_format and
2129
repository_format classes into each copy. Each copy is also given a new id()
2130
to make it easy to identify.
2133
def __init__(self, transport_server, transport_readonly_server, formats):
2134
self._transport_server = transport_server
2135
self._transport_readonly_server = transport_readonly_server
2136
self._formats = formats
2138
def adapt(self, test):
2139
result = unittest.TestSuite()
2140
for repository_format, bzrdir_format in self._formats:
2141
new_test = deepcopy(test)
2142
new_test.transport_server = self._transport_server
2143
new_test.transport_readonly_server = self._transport_readonly_server
2144
new_test.bzrdir_format = bzrdir_format
2145
new_test.repository_format = repository_format
2146
def make_new_test_id():
2147
new_id = "%s(%s)" % (new_test.id(), repository_format.__class__.__name__)
2148
return lambda: new_id
2149
new_test.id = make_new_test_id()
2150
result.addTest(new_test)
2154
class InterRepositoryTestProviderAdapter(object):
2155
"""A tool to generate a suite testing multiple inter repository formats.
2157
This is done by copying the test once for each interrepo provider and injecting
2158
the transport_server, transport_readonly_server, repository_format and
2159
repository_to_format classes into each copy.
2160
Each copy is also given a new id() to make it easy to identify.
2163
def __init__(self, transport_server, transport_readonly_server, formats):
2164
self._transport_server = transport_server
2165
self._transport_readonly_server = transport_readonly_server
2166
self._formats = formats
2168
def adapt(self, test):
2169
result = unittest.TestSuite()
2170
for interrepo_class, repository_format, repository_format_to in self._formats:
2171
new_test = deepcopy(test)
2172
new_test.transport_server = self._transport_server
2173
new_test.transport_readonly_server = self._transport_readonly_server
2174
new_test.interrepo_class = interrepo_class
2175
new_test.repository_format = repository_format
2176
new_test.repository_format_to = repository_format_to
2177
def make_new_test_id():
2178
new_id = "%s(%s)" % (new_test.id(), interrepo_class.__name__)
2179
return lambda: new_id
2180
new_test.id = make_new_test_id()
2181
result.addTest(new_test)
2185
def default_test_list():
2186
"""Generate the default list of interrepo permutations to test."""
2188
# test the default InterRepository between format 6 and the current
2190
# XXX: robertc 20060220 reinstate this when there are two supported
2191
# formats which do not have an optimal code path between them.
2192
#result.append((InterRepository,
2193
# RepositoryFormat6(),
2194
# RepositoryFormatKnit1()))
2195
for optimiser in InterRepository._optimisers:
2196
if optimiser._matching_repo_format is not None:
2197
result.append((optimiser,
2198
optimiser._matching_repo_format,
2199
optimiser._matching_repo_format
2201
# if there are specific combinations we want to use, we can add them
2203
result.append((InterModel1and2, RepositoryFormat5(),
2204
RepositoryFormatKnit2()))
2205
result.append((InterKnit1and2, RepositoryFormatKnit1(),
2206
RepositoryFormatKnit2()))
1789
2210
class CopyConverter(object):