53
57
def __repr__(self):
54
58
return 'KnitParentsProvider(%r)' % self._knit
56
def get_parent_map(self, keys):
57
"""See graph.StackedParentsProvider.get_parent_map"""
59
for revision_id in keys:
60
if revision_id is None:
61
raise ValueError('get_parent_map(None) is not valid')
60
def get_parents(self, revision_ids):
62
for revision_id in revision_ids:
62
63
if revision_id == _mod_revision.NULL_REVISION:
63
parent_map[revision_id] = ()
67
self._knit.get_parents_with_ghosts(revision_id))
67
parents = self._knit.get_parents_with_ghosts(revision_id)
68
68
except errors.RevisionNotPresent:
71
71
if len(parents) == 0:
72
parents = (_mod_revision.NULL_REVISION,)
73
parent_map[revision_id] = parents
77
class _KnitsParentsProvider(object):
79
def __init__(self, knit, prefix=()):
80
"""Create a parent provider for string keys mapped to tuple keys."""
85
return 'KnitsParentsProvider(%r)' % self._knit
87
def get_parent_map(self, keys):
88
"""See graph.StackedParentsProvider.get_parent_map"""
89
parent_map = self._knit.get_parent_map(
90
[self._prefix + (key,) for key in keys])
92
for key, parents in parent_map.items():
95
parents = (_mod_revision.NULL_REVISION,)
97
parents = tuple(parent[-1] for parent in parents)
98
result[revid] = parents
99
for revision_id in keys:
100
if revision_id == _mod_revision.NULL_REVISION:
101
result[revision_id] = ()
72
parents = [_mod_revision.NULL_REVISION]
73
parents_list.append(parents)
105
77
class KnitRepository(MetaDirRepository):
106
78
"""Knit format repository."""
108
# These attributes are inherited from the Repository base class. Setting
109
# them to None ensures that if the constructor is changed to not initialize
110
# them, or a subclass fails to call the constructor, that an error will
111
# occur rather than the system working but generating incorrect data.
112
_commit_builder_class = None
115
def __init__(self, _format, a_bzrdir, control_files, _commit_builder_class,
117
MetaDirRepository.__init__(self, _format, a_bzrdir, control_files)
118
self._commit_builder_class = _commit_builder_class
119
self._serializer = _serializer
120
self._reconcile_fixes_text_parents = True
80
_serializer = xml5.serializer_v5
82
def _warn_if_deprecated(self):
83
# This class isn't deprecated
86
def _inventory_add_lines(self, inv_vf, revid, parents, lines):
87
inv_vf.add_lines_with_ghosts(revid, parents, lines)
123
90
def _all_revision_ids(self):
124
91
"""See Repository.all_revision_ids()."""
125
return [key[0] for key in self.revisions.keys()]
127
def _activate_new_inventory(self):
128
"""Put a replacement inventory.new into use as inventories."""
129
# Copy the content across
131
t.copy('inventory.new.kndx', 'inventory.kndx')
133
t.copy('inventory.new.knit', 'inventory.knit')
134
except errors.NoSuchFile:
135
# empty inventories knit
136
t.delete('inventory.knit')
137
# delete the temp inventory
138
t.delete('inventory.new.kndx')
140
t.delete('inventory.new.knit')
141
except errors.NoSuchFile:
142
# empty inventories knit
144
# Force index reload (sanity check)
145
self.inventories._index._reset_cache()
146
self.inventories.keys()
148
def _backup_inventory(self):
150
t.copy('inventory.kndx', 'inventory.backup.kndx')
151
t.copy('inventory.knit', 'inventory.backup.knit')
153
def _move_file_id(self, from_id, to_id):
154
t = self._transport.clone('knits')
155
from_rel_url = self.texts._index._mapper.map((from_id, None))
156
to_rel_url = self.texts._index._mapper.map((to_id, None))
157
# We expect both files to always exist in this case.
158
for suffix in ('.knit', '.kndx'):
159
t.rename(from_rel_url + suffix, to_rel_url + suffix)
161
def _remove_file_id(self, file_id):
162
t = self._transport.clone('knits')
163
rel_url = self.texts._index._mapper.map((file_id, None))
164
for suffix in ('.kndx', '.knit'):
166
t.delete(rel_url + suffix)
167
except errors.NoSuchFile:
170
def _temp_inventories(self):
171
result = self._format._get_inventories(self._transport, self,
173
# Reconciling when the output has no revisions would result in no
174
# writes - but we want to ensure there is an inventory for
175
# compatibility with older clients that don't lazy-load.
176
result.get_parent_map([('A',)])
92
# Knits get the revision graph from the index of the revision knit, so
93
# it's always possible even if they're on an unlistable transport.
94
return self._revision_store.all_revision_ids(self.get_transaction())
179
96
def fileid_involved_between_revs(self, from_revid, to_revid):
180
97
"""Find file_id(s) which are involved in the changes between revisions.
202
121
return self._fileid_involved_by_set(changed)
124
def get_ancestry(self, revision_id, topo_sorted=True):
125
"""Return a list of revision-ids integrated by a revision.
127
This is topologically sorted, unless 'topo_sorted' is specified as
130
if _mod_revision.is_null(revision_id):
132
revision_id = osutils.safe_revision_id(revision_id)
133
vf = self._get_revision_vf()
135
return [None] + vf.get_ancestry(revision_id, topo_sorted)
136
except errors.RevisionNotPresent:
137
raise errors.NoSuchRevision(self, revision_id)
205
140
def get_revision(self, revision_id):
206
141
"""Return the Revision object for a named revision"""
207
142
revision_id = osutils.safe_revision_id(revision_id)
208
143
return self.get_revision_reconcile(revision_id)
210
def _refresh_data(self):
211
if not self.is_locked():
213
# Create a new transaction to force all knits to see the scope change.
214
# This is safe because we're outside a write group.
215
self.control_files._finish_transaction()
216
if self.is_write_locked():
217
self.control_files._set_write_transaction()
219
self.control_files._set_read_transaction()
146
def get_revision_graph(self, revision_id=None):
147
"""Return a dictionary containing the revision graph.
149
:param revision_id: The revision_id to get a graph from. If None, then
150
the entire revision graph is returned. This is a deprecated mode of
151
operation and will be removed in the future.
152
:return: a dictionary of revision_id->revision_parents_list.
154
# special case NULL_REVISION
155
if revision_id == _mod_revision.NULL_REVISION:
157
revision_id = osutils.safe_revision_id(revision_id)
158
a_weave = self._get_revision_vf()
159
if revision_id is None:
160
return a_weave.get_graph()
161
if revision_id not in a_weave:
162
raise errors.NoSuchRevision(self, revision_id)
164
return a_weave.get_graph([revision_id])
167
def get_revision_graph_with_ghosts(self, revision_ids=None):
168
"""Return a graph of the revisions with ghosts marked as applicable.
170
:param revision_ids: an iterable of revisions to graph or None for all.
171
:return: a Graph object with the graph reachable from revision_ids.
173
result = deprecated_graph.Graph()
174
vf = self._get_revision_vf()
175
versions = set(vf.versions())
177
pending = set(self.all_revision_ids())
180
pending = set(osutils.safe_revision_id(r) for r in revision_ids)
181
# special case NULL_REVISION
182
if _mod_revision.NULL_REVISION in pending:
183
pending.remove(_mod_revision.NULL_REVISION)
184
required = set(pending)
187
revision_id = pending.pop()
188
if not revision_id in versions:
189
if revision_id in required:
190
raise errors.NoSuchRevision(self, revision_id)
192
result.add_ghost(revision_id)
193
# mark it as done so we don't try for it again.
194
done.add(revision_id)
196
parent_ids = vf.get_parents_with_ghosts(revision_id)
197
for parent_id in parent_ids:
198
# is this queued or done ?
199
if (parent_id not in pending and
200
parent_id not in done):
202
pending.add(parent_id)
203
result.add_node(revision_id, parent_ids)
204
done.add(revision_id)
207
def _get_revision_vf(self):
208
""":return: a versioned file containing the revisions."""
209
vf = self._revision_store.get_revision_file(self.get_transaction())
212
def _get_history_vf(self):
213
"""Get a versionedfile whose history graph reflects all revisions.
215
For knit repositories, this is the revision knit.
217
return self._get_revision_vf()
221
219
@needs_write_lock
222
220
def reconcile(self, other=None, thorough=False):
225
223
reconciler = KnitReconciler(self, thorough=thorough)
226
224
reconciler.reconcile()
227
225
return reconciler
227
def revision_parents(self, revision_id):
228
revision_id = osutils.safe_revision_id(revision_id)
229
return self._get_revision_vf().get_parents(revision_id)
229
231
def _make_parents_provider(self):
230
return _KnitsParentsProvider(self.revisions)
232
def _find_inconsistent_revision_parents(self, revisions_iterator=None):
233
"""Find revisions with different parent lists in the revision object
234
and in the index graph.
236
:param revisions_iterator: None, or an iterator of (revid,
237
Revision-or-None). This iterator controls the revisions checked.
238
:returns: an iterator yielding tuples of (revison-id, parents-in-index,
239
parents-in-revision).
241
if not self.is_locked():
242
raise AssertionError()
244
if revisions_iterator is None:
245
revisions_iterator = self._iter_revisions(None)
246
for revid, revision in revisions_iterator:
249
parent_map = vf.get_parent_map([(revid,)])
250
parents_according_to_index = tuple(parent[-1] for parent in
251
parent_map[(revid,)])
252
parents_according_to_revision = tuple(revision.parent_ids)
253
if parents_according_to_index != parents_according_to_revision:
254
yield (revid, parents_according_to_index,
255
parents_according_to_revision)
257
def _check_for_inconsistent_revision_parents(self):
258
inconsistencies = list(self._find_inconsistent_revision_parents())
260
raise errors.BzrCheckError(
261
"Revision knit has inconsistent parents.")
263
def revision_graph_can_have_wrong_parents(self):
264
# The revision.kndx could potentially claim a revision has a different
265
# parent to the revision text.
232
return _KnitParentsProvider(self._get_revision_vf())
235
class KnitRepository3(KnitRepository):
237
def __init__(self, _format, a_bzrdir, control_files, _revision_store,
238
control_store, text_store):
239
KnitRepository.__init__(self, _format, a_bzrdir, control_files,
240
_revision_store, control_store, text_store)
241
self._serializer = xml7.serializer_v7
243
def deserialise_inventory(self, revision_id, xml):
244
"""Transform the xml into an inventory object.
246
:param revision_id: The expected revision id of the inventory.
247
:param xml: A serialised inventory.
249
result = self._serializer.read_inventory_from_string(xml)
250
assert result.root.revision is not None
253
def serialise_inventory(self, inv):
254
"""Transform the inventory object into XML text.
256
:param revision_id: The expected revision id of the inventory.
257
:param xml: A serialised inventory.
259
assert inv.revision_id is not None
260
assert inv.root.revision is not None
261
return KnitRepository.serialise_inventory(self, inv)
263
def get_commit_builder(self, branch, parents, config, timestamp=None,
264
timezone=None, committer=None, revprops=None,
266
"""Obtain a CommitBuilder for this repository.
268
:param branch: Branch to commit to.
269
:param parents: Revision ids of the parents of the new revision.
270
:param config: Configuration to use.
271
:param timestamp: Optional timestamp recorded for commit.
272
:param timezone: Optional timezone for timestamp.
273
:param committer: Optional committer to set for commit.
274
:param revprops: Optional dictionary of revision properties.
275
:param revision_id: Optional revision id.
277
revision_id = osutils.safe_revision_id(revision_id)
278
result = RootCommitBuilder(self, parents, config, timestamp, timezone,
279
committer, revprops, revision_id)
280
self.start_write_group()
284
class GraphKnitRevisionStore(KnitRevisionStore):
285
"""An object to adapt access from RevisionStore's to use GraphKnits.
287
This should not live through to production: by production time we should
288
have fully integrated the new indexing and have new data for the
289
repository classes; also we may choose not to do a Knit1 compatible
290
new repository, just a Knit3 one. If neither of these happen, this
291
should definately be cleaned up before merging.
293
This class works by replacing the original RevisionStore.
294
We need to do this because the GraphKnitRevisionStore is less
295
isolated in its layering - it uses services from the repo.
298
- unlock writes an index even on error. This is fine while we are writing
299
data to knits, but we really should not use unlock to trigger writes,
300
rather operations should finish explicitly.
303
def __init__(self, repo, revisionstore):
304
"""Create a GraphKnitRevisionStore on repo with revisionstore.
306
This will store its state in the Repository, use the
307
revision-indices FileNames to provide a KnitGraphIndex,
308
and at the end of transactions write new indices.
310
KnitRevisionStore.__init__(self, revisionstore.versioned_file_store)
312
self._serializer = revisionstore._serializer
314
def _ensure_names_loaded(self):
315
if self.repo._revision_indices is None:
316
index_transport = self.get_indices_transport()
317
self.repo._revision_indices = file_names.FileNames(
318
index_transport, 'index')
319
self.repo._revision_indices.load()
321
def get_indices_transport(self):
322
return self.versioned_file_store._transport.clone('indices')
324
def get_revision_file(self, transaction):
325
"""Get the revision versioned file object."""
326
if getattr(self.repo, '_revision_knit', None) is not None:
327
return self.repo._revision_knit
328
index_transport = self.get_indices_transport()
330
self._ensure_names_loaded()
331
def _cmp(x, y): return cmp(int(x), int(y))
332
for name in sorted(self.repo._revision_indices.names(), cmp=_cmp, reverse=True):
333
# TODO: maybe this should expose size to us to allow
334
# sorting of the indices for better performance ?
335
index_name = self.name_to_revision_index_name(name)
336
indices.append(GraphIndex(index_transport, index_name))
337
if self.repo.is_in_write_group():
338
# allow writing: queue writes to a new index
339
indices.append(self.repo._revision_write_index)
340
add_callback = self.repo._revision_write_index.add_nodes
342
add_callback = None # no data-adding permitted.
343
self.repo._revision_all_indices = CombinedGraphIndex(indices)
344
knit_index = KnitGraphIndex(self.repo._revision_all_indices,
345
add_callback=add_callback)
346
self.repo._revision_knit = knit.KnitVersionedFile(
347
'revisions', index_transport.clone('..'),
348
self.repo.control_files._file_mode,
349
create=False, access_mode=self.repo.control_files._lock_mode,
350
index=knit_index, delta=False, factory=knit.KnitPlainFactory())
351
return self.repo._revision_knit
353
def get_signature_file(self, transaction):
354
"""Get the signature versioned file object."""
355
if getattr(self.repo, '_signature_knit', None) is not None:
356
return self.repo._signature_knit
357
index_transport = self.get_indices_transport()
359
self._ensure_names_loaded()
360
def _cmp(x, y): return cmp(int(x), int(y))
361
for name in sorted(self.repo._revision_indices.names(), cmp=_cmp, reverse=True):
362
# TODO: maybe this should expose size to us to allow
363
# sorting of the indices for better performance ?
364
index_name = self.name_to_signature_index_name(name)
365
indices.append(GraphIndex(index_transport, index_name))
366
if self.repo.is_in_write_group():
367
# allow writing: queue writes to a new index
368
indices.append(self.repo._signature_write_index)
369
add_callback = self.repo._signature_write_index.add_nodes
371
add_callback = None # no data-adding permitted.
372
self.repo._signature_all_indices = CombinedGraphIndex(indices)
373
knit_index = KnitGraphIndex(self.repo._signature_all_indices,
374
add_callback=add_callback, parents=False)
375
self.repo._signature_knit = knit.KnitVersionedFile(
376
'signatures', index_transport.clone('..'),
377
self.repo.control_files._file_mode,
378
create=False, access_mode=self.repo.control_files._lock_mode,
379
index=knit_index, delta=False, factory=knit.KnitPlainFactory())
380
return self.repo._signature_knit
383
"""Write out pending indices."""
384
# if any work has been done, allocate a new name
385
if (getattr(self.repo, '_revision_knit', None) is not None or
386
getattr(self.repo, '_signature_knit', None) is not None):
387
new_name = self.repo._revision_indices.allocate()
388
self.repo._revision_indices.save()
390
# no knits actually accessed
392
index_transport = self.get_indices_transport()
393
# write a revision index (might be empty)
394
new_index_name = self.name_to_revision_index_name(new_name)
395
index_transport.put_file(new_index_name,
396
self.repo._revision_write_index.finish())
397
self.repo._revision_write_index = None
398
if self.repo._revision_all_indices is not None:
399
# revisions 'knit' accessed : update it.
400
self.repo._revision_all_indices.insert_index(0,
401
GraphIndex(index_transport, new_index_name))
402
# remove the write buffering index. XXX: API break
403
# - clearly we need a remove_index call too.
404
del self.repo._revision_all_indices._indices[-1]
405
# write a signatures index (might be empty)
406
new_index_name = self.name_to_signature_index_name(new_name)
407
index_transport.put_file(new_index_name,
408
self.repo._signature_write_index.finish())
409
self.repo._signature_write_index = None
410
if self.repo._signature_all_indices is not None:
411
# sigatures 'knit' accessed : update it.
412
self.repo._signature_all_indices.insert_index(0,
413
GraphIndex(index_transport, new_index_name))
414
# remove the write buffering index. XXX: API break
415
# - clearly we need a remove_index call too.
416
del self.repo._signature_all_indices._indices[-1]
418
def name_to_revision_index_name(self, name):
419
"""The revision index is the name + .rix."""
422
def name_to_signature_index_name(self, name):
423
"""The signature index is the name + .six."""
427
"""Clear all cached data."""
428
# the packs that exist
429
self.repo._revision_indices = None
430
# cached revision data
431
self.repo._revision_knit = None
432
self.repo._revision_write_index = None
433
self.repo._revision_all_indices = None
434
# cached signature data
435
self.repo._signature_knit = None
436
self.repo._signature_write_index = None
437
self.repo._signature_all_indices = None
440
# setup in-memory indices to accumulate data.
441
if self.repo.control_files._lock_mode != 'w':
442
raise errors.NotWriteLocked(self)
443
self.repo._revision_write_index = InMemoryGraphIndex(1)
444
self.repo._signature_write_index = InMemoryGraphIndex(0)
445
# if knit indices have been handed out, add a mutable
447
if self.repo._revision_knit is not None:
448
self.repo._revision_all_indices.insert_index(0, self.repo._revision_write_index)
449
self.repo._revision_knit._index._add_callback = self.repo._revision_write_index.add_nodes
450
if self.repo._signature_knit is not None:
451
self.repo._signature_all_indices.insert_index(0, self.repo._signature_write_index)
452
self.repo._signature_knit._index._add_callback = self.repo._signature_write_index.add_nodes
455
class GraphKnitRepository1(KnitRepository):
456
"""Experimental graph-knit using repository."""
458
def __init__(self, _format, a_bzrdir, control_files, _revision_store,
459
control_store, text_store):
460
KnitRepository.__init__(self, _format, a_bzrdir, control_files,
461
_revision_store, control_store, text_store)
462
self._revision_store = GraphKnitRevisionStore(self, self._revision_store)
464
def _abort_write_group(self):
465
# FIXME: just drop the transient index.
466
self._revision_store.reset()
468
def _refresh_data(self):
469
if self.control_files._lock_count==1:
470
self._revision_store.reset()
472
def _start_write_group(self):
473
self._revision_store.setup()
475
def _commit_write_group(self):
476
self._revision_store.flush()
477
self._revision_store.reset()
480
class GraphKnitRepository3(KnitRepository3):
481
"""Experimental graph-knit using subtrees repository."""
483
def __init__(self, _format, a_bzrdir, control_files, _revision_store,
484
control_store, text_store):
485
KnitRepository3.__init__(self, _format, a_bzrdir, control_files,
486
_revision_store, control_store, text_store)
487
self._revision_store = GraphKnitRevisionStore(self, self._revision_store)
489
def _abort_write_group(self):
490
# FIXME: just drop the transient index.
491
self._revision_store.reset()
493
def _refresh_data(self):
494
if self.control_files._lock_count==1:
495
self._revision_store.reset()
497
def _start_write_group(self):
498
self._revision_store.setup()
500
def _commit_write_group(self):
501
self._revision_store.flush()
502
self._revision_store.reset()
269
505
class RepositoryFormatKnit(MetaDirRepositoryFormat):
270
"""Bzr repository knit format (generalized).
506
"""Bzr repository knit format (generalized).
272
508
This repository format has:
273
509
- knits for file texts and inventory
283
# Set this attribute in derived classes to control the repository class
284
# created by open and initialize.
285
repository_class = None
286
# Set this attribute in derived classes to control the
287
# _commit_builder_class that the repository objects will have passed to
289
_commit_builder_class = None
290
# Set this attribute in derived clases to control the _serializer that the
291
# repository objects will have passed to their constructor.
293
def _serializer(self):
294
return xml5.serializer_v5
295
# Knit based repositories handle ghosts reasonably well.
296
supports_ghosts = True
297
# External lookups are not supported in this format.
298
supports_external_lookups = False
300
supports_chks = False
301
_fetch_order = 'topological'
302
_fetch_uses_deltas = True
305
def _get_inventories(self, repo_transport, repo, name='inventory'):
306
mapper = versionedfile.ConstantMapper(name)
307
index = _mod_knit._KndxIndex(repo_transport, mapper,
308
repo.get_transaction, repo.is_write_locked, repo.is_locked)
309
access = _mod_knit._KnitKeyAccess(repo_transport, mapper)
310
return _mod_knit.KnitVersionedFiles(index, access, annotated=False)
312
def _get_revisions(self, repo_transport, repo):
313
mapper = versionedfile.ConstantMapper('revisions')
314
index = _mod_knit._KndxIndex(repo_transport, mapper,
315
repo.get_transaction, repo.is_write_locked, repo.is_locked)
316
access = _mod_knit._KnitKeyAccess(repo_transport, mapper)
317
return _mod_knit.KnitVersionedFiles(index, access, max_delta_chain=0,
320
def _get_signatures(self, repo_transport, repo):
321
mapper = versionedfile.ConstantMapper('signatures')
322
index = _mod_knit._KndxIndex(repo_transport, mapper,
323
repo.get_transaction, repo.is_write_locked, repo.is_locked)
324
access = _mod_knit._KnitKeyAccess(repo_transport, mapper)
325
return _mod_knit.KnitVersionedFiles(index, access, max_delta_chain=0,
328
def _get_texts(self, repo_transport, repo):
329
mapper = versionedfile.HashEscapedPrefixMapper()
330
base_transport = repo_transport.clone('knits')
331
index = _mod_knit._KndxIndex(base_transport, mapper,
332
repo.get_transaction, repo.is_write_locked, repo.is_locked)
333
access = _mod_knit._KnitKeyAccess(base_transport, mapper)
334
return _mod_knit.KnitVersionedFiles(index, access, max_delta_chain=200,
519
def _get_control_store(self, repo_transport, control_files):
520
"""Return the control store for this repository."""
521
return VersionedFileStore(
524
file_mode=control_files._file_mode,
525
versionedfile_class=knit.KnitVersionedFile,
526
versionedfile_kwargs={'factory':knit.KnitPlainFactory()},
529
def _get_revision_store(self, repo_transport, control_files):
530
"""See RepositoryFormat._get_revision_store()."""
531
versioned_file_store = VersionedFileStore(
533
file_mode=control_files._file_mode,
536
versionedfile_class=knit.KnitVersionedFile,
537
versionedfile_kwargs={'delta':False,
538
'factory':knit.KnitPlainFactory(),
542
return KnitRevisionStore(versioned_file_store)
544
def _get_text_store(self, transport, control_files):
545
"""See RepositoryFormat._get_text_store()."""
546
return self._get_versioned_file_store('knits',
549
versionedfile_class=knit.KnitVersionedFile,
550
versionedfile_kwargs={
551
'create_parent_dir':True,
553
'dir_mode':control_files._dir_mode,
337
557
def initialize(self, a_bzrdir, shared=False):
338
558
"""Create a knit format 1 repository.
342
562
:param shared: If true the repository will be initialized as a shared
345
trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
565
mutter('creating repository in %s.', a_bzrdir.transport.base)
566
dirs = ['revision-store', 'knits']
348
568
utf8_files = [('format', self.get_format_string())]
350
570
self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
351
571
repo_transport = a_bzrdir.get_repository_transport(None)
352
572
control_files = lockable_files.LockableFiles(repo_transport,
353
573
'lock', lockdir.LockDir)
574
control_store = self._get_control_store(repo_transport, control_files)
354
575
transaction = transactions.WriteTransaction()
355
result = self.open(a_bzrdir=a_bzrdir, _found=True)
576
# trigger a write of the inventory store.
577
control_store.get_weave_or_empty('inventory', transaction)
578
_revision_store = self._get_revision_store(repo_transport, control_files)
357
579
# the revision id here is irrelevant: it will not be stored, and cannot
358
# already exist, we do this to create files on disk for older clients.
359
result.inventories.get_parent_map([('A',)])
360
result.revisions.get_parent_map([('A',)])
361
result.signatures.get_parent_map([('A',)])
363
self._run_post_repo_init_hooks(result, a_bzrdir, shared)
581
_revision_store.has_revision_id('A', transaction)
582
_revision_store.get_signature_file(transaction)
583
return self.open(a_bzrdir=a_bzrdir, _found=True)
366
585
def open(self, a_bzrdir, _found=False, _override_transport=None):
367
586
"""See RepositoryFormat.open().
369
588
:param _override_transport: INTERNAL USE ONLY. Allows opening the
370
589
repository at a slightly different url
371
590
than normal. I.e. during 'upgrade'.
374
593
format = RepositoryFormat.find_format(a_bzrdir)
594
assert format.__class__ == self.__class__
375
595
if _override_transport is not None:
376
596
repo_transport = _override_transport
378
598
repo_transport = a_bzrdir.get_repository_transport(None)
379
599
control_files = lockable_files.LockableFiles(repo_transport,
380
600
'lock', lockdir.LockDir)
381
repo = self.repository_class(_format=self,
601
text_store = self._get_text_store(repo_transport, control_files)
602
control_store = self._get_control_store(repo_transport, control_files)
603
_revision_store = self._get_revision_store(repo_transport, control_files)
604
return self.repository_class(_format=self,
382
605
a_bzrdir=a_bzrdir,
383
606
control_files=control_files,
384
_commit_builder_class=self._commit_builder_class,
385
_serializer=self._serializer)
386
repo.revisions = self._get_revisions(repo_transport, repo)
387
repo.signatures = self._get_signatures(repo_transport, repo)
388
repo.inventories = self._get_inventories(repo_transport, repo)
389
repo.texts = self._get_texts(repo_transport, repo)
390
repo.chk_bytes = None
391
repo._transport = repo_transport
607
_revision_store=_revision_store,
608
control_store=control_store,
609
text_store=text_store)
395
612
class RepositoryFormatKnit1(RepositoryFormatKnit):
468
687
return "Knit repository format 3"
471
class RepositoryFormatKnit4(RepositoryFormatKnit):
472
"""Bzr repository knit format 4.
474
This repository format has everything in format 3, except for
476
- knits for file texts and inventory
477
- hash subdirectory based stores.
478
- knits for revisions and signatures
690
class RepositoryFormatGraphKnit1(RepositoryFormatKnit):
691
"""Experimental repository with knit1 style data.
693
This repository format has:
694
- knits for file texts and inventory
695
- hash subdirectory based stores.
696
- knits for revisions and signatures
697
- uses a GraphKnitIndex for revisions.knit.
698
- TextStores for revisions and signatures.
699
- a format marker of its own
700
- an optional 'shared-storage' flag
701
- an optional 'no-working-trees' flag
704
This format was introduced in bzr.dev.
707
repository_class = GraphKnitRepository1
709
def _get_matching_bzrdir(self):
710
return bzrdir.format_registry.make_bzrdir('experimental')
712
def _ignore_setting_bzrdir(self, format):
715
_matchingbzrdir = property(_get_matching_bzrdir, _ignore_setting_bzrdir)
717
def __ne__(self, other):
718
return self.__class__ is not other.__class__
720
def get_format_string(self):
721
"""See RepositoryFormat.get_format_string()."""
722
return "Bazaar Experimental no-subtrees\n"
724
def get_format_description(self):
725
"""See RepositoryFormat.get_format_description()."""
726
return "Experimental no-subtrees"
728
def check_conversion_target(self, target_format):
731
def initialize(self, a_bzrdir, shared=False):
732
"""Create an experimental repository.
734
:param a_bzrdir: bzrdir to contain the new repository; must already
736
:param shared: If true the repository will be initialized as a shared
739
# setup a basic Knit1 repository.
740
result = RepositoryFormatKnit.initialize(self, a_bzrdir, shared)
741
_knit_to_experimental(result, a_bzrdir)
745
def _knit_to_experimental(result, a_bzrdir):
746
"""Convert a knit1/3 repo to an experimental layout repo."""
747
# and adapt it to a GraphKnit repo
748
mutter('changing to GraphKnit1 repository in %s.', a_bzrdir.transport.base)
749
repo_transport = a_bzrdir.get_repository_transport(None)
750
repo_transport.mkdir('indices')
751
names = file_names.FileNames(
752
repo_transport.clone('indices'), 'index')
755
repo_transport.delete('revisions.kndx')
756
repo_transport.delete('signatures.kndx')
759
class RepositoryFormatGraphKnit3(RepositoryFormatKnit3):
760
"""Experimental repository with knit3 style data.
762
This repository format has:
763
- knits for file texts and inventory
764
- hash subdirectory based stores.
765
- knits for revisions and signatures
766
- uses a GraphKnitIndex for revisions.knit.
479
767
- TextStores for revisions and signatures.
480
768
- a format marker of its own
481
769
- an optional 'shared-storage' flag
482
770
- an optional 'no-working-trees' flag
484
772
- support for recording full info about the tree root
773
- support for recording tree-references
487
repository_class = KnitRepository
488
_commit_builder_class = RootCommitBuilder
489
rich_root_data = True
490
supports_tree_reference = False
492
def _serializer(self):
493
return xml6.serializer_v6
776
repository_class = GraphKnitRepository3
495
778
def _get_matching_bzrdir(self):
496
return bzrdir.format_registry.make_bzrdir('rich-root')
779
return bzrdir.format_registry.make_bzrdir('experimental-subtree')
498
781
def _ignore_setting_bzrdir(self, format):