14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
from bzrlib.lazy_import import lazy_import
17
from __future__ import absolute_import
19
from ..lazy_import import lazy_import
18
20
lazy_import(globals(), """
26
29
revision as _mod_revision,
33
from breezy.bzr import (
38
from bzrlib.decorators import needs_read_lock, needs_write_lock
39
from bzrlib.repository import (
41
from ..decorators import needs_read_lock, needs_write_lock
42
from ..repository import (
41
44
IsInWriteGroupError,
43
MetaDirRepositoryFormat,
46
from ..bzr.repository import (
47
RepositoryFormatMetaDir,
49
from ..bzr.vf_repository import (
50
InterSameDataRepository,
51
MetaDirVersionedFileRepository,
52
MetaDirVersionedFileRepositoryFormat,
53
VersionedFileCommitBuilder,
54
VersionedFileRootCommitBuilder,
113
122
_commit_builder_class = None
114
123
_serializer = None
116
def __init__(self, _format, a_bzrdir, control_files, _commit_builder_class,
125
def __init__(self, _format, a_controldir, control_files, _commit_builder_class,
118
MetaDirRepository.__init__(self, _format, a_bzrdir, control_files)
127
super(KnitRepository, self).__init__(_format, a_controldir, control_files)
119
128
self._commit_builder_class = _commit_builder_class
120
129
self._serializer = _serializer
121
130
self._reconcile_fixes_text_parents = True
177
186
result.get_parent_map([('A',)])
180
def fileid_involved_between_revs(self, from_revid, to_revid):
181
"""Find file_id(s) which are involved in the changes between revisions.
183
This determines the set of revisions which are involved, and then
184
finds all file ids affected by those revisions.
186
vf = self._get_revision_vf()
187
from_set = set(vf.get_ancestry(from_revid))
188
to_set = set(vf.get_ancestry(to_revid))
189
changed = to_set.difference(from_set)
190
return self._fileid_involved_by_set(changed)
192
def fileid_involved(self, last_revid=None):
193
"""Find all file_ids modified in the ancestry of last_revid.
195
:param last_revid: If None, last_revision() will be used.
198
changed = set(self.all_revision_ids())
200
changed = set(self.get_ancestry(last_revid))
203
return self._fileid_involved_by_set(changed)
206
190
def get_revision(self, revision_id):
207
191
"""Return the Revision object for a named revision"""
232
216
def _make_parents_provider(self):
233
217
return _KnitsParentsProvider(self.revisions)
235
def _find_inconsistent_revision_parents(self, revisions_iterator=None):
236
"""Find revisions with different parent lists in the revision object
237
and in the index graph.
239
:param revisions_iterator: None, or an iterator of (revid,
240
Revision-or-None). This iterator controls the revisions checked.
241
:returns: an iterator yielding tuples of (revison-id, parents-in-index,
242
parents-in-revision).
244
if not self.is_locked():
245
raise AssertionError()
247
if revisions_iterator is None:
248
revisions_iterator = self._iter_revisions(None)
249
for revid, revision in revisions_iterator:
252
parent_map = vf.get_parent_map([(revid,)])
253
parents_according_to_index = tuple(parent[-1] for parent in
254
parent_map[(revid,)])
255
parents_according_to_revision = tuple(revision.parent_ids)
256
if parents_according_to_index != parents_according_to_revision:
257
yield (revid, parents_according_to_index,
258
parents_according_to_revision)
260
def _check_for_inconsistent_revision_parents(self):
261
inconsistencies = list(self._find_inconsistent_revision_parents())
263
raise errors.BzrCheckError(
264
"Revision knit has inconsistent parents.")
266
def revision_graph_can_have_wrong_parents(self):
267
# The revision.kndx could potentially claim a revision has a different
268
# parent to the revision text.
272
class RepositoryFormatKnit(MetaDirRepositoryFormat):
220
class RepositoryFormatKnit(MetaDirVersionedFileRepositoryFormat):
273
221
"""Bzr repository knit format (generalized).
275
223
This repository format has:
304
252
_fetch_order = 'topological'
305
253
_fetch_uses_deltas = True
306
254
fast_deltas = False
255
supports_funky_characters = True
256
# The revision.kndx could potentially claim a revision has a different
257
# parent to the revision text.
258
revision_graph_can_have_wrong_parents = True
308
260
def _get_inventories(self, repo_transport, repo, name='inventory'):
309
261
mapper = versionedfile.ConstantMapper(name)
337
289
return _mod_knit.KnitVersionedFiles(index, access, max_delta_chain=200,
340
def initialize(self, a_bzrdir, shared=False):
292
def initialize(self, a_controldir, shared=False):
341
293
"""Create a knit format 1 repository.
343
:param a_bzrdir: bzrdir to contain the new repository; must already
295
:param a_controldir: bzrdir to contain the new repository; must already
345
297
:param shared: If true the repository will be initialized as a shared
348
trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
300
trace.mutter('creating repository in %s.', a_controldir.transport.base)
351
303
utf8_files = [('format', self.get_format_string())]
353
self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
354
repo_transport = a_bzrdir.get_repository_transport(None)
305
self._upload_blank_content(a_controldir, dirs, files, utf8_files, shared)
306
repo_transport = a_controldir.get_repository_transport(None)
355
307
control_files = lockable_files.LockableFiles(repo_transport,
356
308
'lock', lockdir.LockDir)
357
309
transaction = transactions.WriteTransaction()
358
result = self.open(a_bzrdir=a_bzrdir, _found=True)
310
result = self.open(a_controldir=a_controldir, _found=True)
359
311
result.lock_write()
360
312
# the revision id here is irrelevant: it will not be stored, and cannot
361
313
# already exist, we do this to create files on disk for older clients.
363
315
result.revisions.get_parent_map([('A',)])
364
316
result.signatures.get_parent_map([('A',)])
366
self._run_post_repo_init_hooks(result, a_bzrdir, shared)
318
self._run_post_repo_init_hooks(result, a_controldir, shared)
369
def open(self, a_bzrdir, _found=False, _override_transport=None):
321
def open(self, a_controldir, _found=False, _override_transport=None):
370
322
"""See RepositoryFormat.open().
372
324
:param _override_transport: INTERNAL USE ONLY. Allows opening the
374
326
than normal. I.e. during 'upgrade'.
377
format = RepositoryFormat.find_format(a_bzrdir)
329
format = RepositoryFormatMetaDir.find_format(a_controldir)
378
330
if _override_transport is not None:
379
331
repo_transport = _override_transport
381
repo_transport = a_bzrdir.get_repository_transport(None)
333
repo_transport = a_controldir.get_repository_transport(None)
382
334
control_files = lockable_files.LockableFiles(repo_transport,
383
335
'lock', lockdir.LockDir)
384
336
repo = self.repository_class(_format=self,
337
a_controldir=a_controldir,
386
338
control_files=control_files,
387
339
_commit_builder_class=self._commit_builder_class,
388
340
_serializer=self._serializer)
455
408
return xml7.serializer_v7
457
410
def _get_matching_bzrdir(self):
458
return bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
411
return controldir.format_registry.make_controldir('dirstate-with-subtree')
460
413
def _ignore_setting_bzrdir(self, format):
463
416
_matchingbzrdir = property(_get_matching_bzrdir, _ignore_setting_bzrdir)
465
def get_format_string(self):
419
def get_format_string(cls):
466
420
"""See RepositoryFormat.get_format_string()."""
467
421
return "Bazaar Knit Repository Format 3 (bzr 0.15)\n"
496
450
return xml6.serializer_v6
498
452
def _get_matching_bzrdir(self):
499
return bzrdir.format_registry.make_bzrdir('rich-root')
453
return controldir.format_registry.make_controldir('rich-root')
501
455
def _ignore_setting_bzrdir(self, format):
504
458
_matchingbzrdir = property(_get_matching_bzrdir, _ignore_setting_bzrdir)
506
def get_format_string(self):
461
def get_format_string(cls):
507
462
"""See RepositoryFormat.get_format_string()."""
508
463
return 'Bazaar Knit Repository Format 4 (bzr 1.0)\n'
510
465
def get_format_description(self):
511
466
"""See RepositoryFormat.get_format_description()."""
512
467
return "Knit repository format 4"
470
class InterKnitRepo(InterSameDataRepository):
471
"""Optimised code paths between Knit based repositories."""
474
def _get_repo_format_to_test(self):
475
return RepositoryFormatKnit1()
478
def is_compatible(source, target):
479
"""Be compatible with known Knit formats.
481
We don't test for the stores being of specific types because that
482
could lead to confusing results, and there is no need to be
486
are_knits = (isinstance(source._format, RepositoryFormatKnit) and
487
isinstance(target._format, RepositoryFormatKnit))
488
except AttributeError:
490
return are_knits and InterRepository._same_model(source, target)
493
def search_missing_revision_ids(self,
494
find_ghosts=True, revision_ids=None, if_present_ids=None,
496
"""See InterRepository.search_missing_revision_ids()."""
497
source_ids_set = self._present_source_revisions_for(
498
revision_ids, if_present_ids)
499
# source_ids is the worst possible case we may need to pull.
500
# now we want to filter source_ids against what we actually
501
# have in target, but don't try to check for existence where we know
502
# we do not have a revision as that would be pointless.
503
target_ids = set(self.target.all_revision_ids())
504
possibly_present_revisions = target_ids.intersection(source_ids_set)
505
actually_present_revisions = set(
506
self.target._eliminate_revisions_not_present(possibly_present_revisions))
507
required_revisions = source_ids_set.difference(actually_present_revisions)
508
if revision_ids is not None:
509
# we used get_ancestry to determine source_ids then we are assured all
510
# revisions referenced are present as they are installed in topological order.
511
# and the tip revision was validated by get_ancestry.
512
result_set = required_revisions
514
# if we just grabbed the possibly available ids, then
515
# we only have an estimate of whats available and need to validate
516
# that against the revision records.
518
self.source._eliminate_revisions_not_present(required_revisions))
519
if limit is not None:
520
topo_ordered = self.source.get_graph().iter_topo_order(result_set)
521
result_set = set(itertools.islice(topo_ordered, limit))
522
return self.source.revision_ids_to_search_result(result_set)
525
InterRepository.register_optimiser(InterKnitRepo)