1524
1563
@needs_read_lock
1525
def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
1564
def search_missing_revision_ids(self, other,
1565
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
1566
find_ghosts=True, revision_ids=None, if_present_ids=None):
1526
1567
"""Return the revision ids that other has that this does not.
1528
1569
These are returned in topological order.
1530
1571
revision_id: only return revision ids included by revision_id.
1573
if symbol_versioning.deprecated_passed(revision_id):
1574
symbol_versioning.warn(
1575
'search_missing_revision_ids(revision_id=...) was '
1576
'deprecated in 2.3. Use revision_ids=[...] instead.',
1577
DeprecationWarning, stacklevel=3)
1578
if revision_ids is not None:
1579
raise AssertionError(
1580
'revision_ids is mutually exclusive with revision_id')
1581
if revision_id is not None:
1582
revision_ids = [revision_id]
1532
1583
return InterRepository.get(other, self).search_missing_revision_ids(
1533
revision_id, find_ghosts)
1584
find_ghosts=find_ghosts, revision_ids=revision_ids,
1585
if_present_ids=if_present_ids)
1536
1588
def open(base):
3325
3365
'bzrlib.repofmt.pack_repo',
3326
3366
'RepositoryFormatKnitPack6RichRoot',
3368
format_registry.register_lazy(
3369
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
3370
'bzrlib.repofmt.groupcompress_repo',
3371
'RepositoryFormat2a',
3329
3374
# Development formats.
3330
# Obsolete but kept pending a CHK based subtree format.
3375
# Check their docstrings to see if/when they are obsolete.
3331
3376
format_registry.register_lazy(
3332
3377
("Bazaar development format 2 with subtree support "
3333
3378
"(needs bzr.dev from before 1.8)\n"),
3334
3379
'bzrlib.repofmt.pack_repo',
3335
3380
'RepositoryFormatPackDevelopment2Subtree',
3338
# 1.14->1.16 go below here
3339
format_registry.register_lazy(
3340
'Bazaar development format - group compression and chk inventory'
3341
' (needs bzr.dev from 1.14)\n',
3342
'bzrlib.repofmt.groupcompress_repo',
3343
'RepositoryFormatCHK1',
3346
format_registry.register_lazy(
3347
'Bazaar development format - chk repository with bencode revision '
3348
'serialization (needs bzr.dev from 1.16)\n',
3349
'bzrlib.repofmt.groupcompress_repo',
3350
'RepositoryFormatCHK2',
3352
format_registry.register_lazy(
3353
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
3354
'bzrlib.repofmt.groupcompress_repo',
3355
'RepositoryFormat2a',
3382
format_registry.register_lazy(
3383
'Bazaar development format 8\n',
3384
'bzrlib.repofmt.groupcompress_repo',
3385
'RepositoryFormat2aSubtree',
3466
3500
return searcher.get_result()
3468
3502
@needs_read_lock
3469
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3503
def search_missing_revision_ids(self,
3504
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
3505
find_ghosts=True, revision_ids=None, if_present_ids=None):
3470
3506
"""Return the revision ids that source has that target does not.
3472
3508
:param revision_id: only return revision ids included by this
3510
:param revision_ids: return revision ids included by these
3511
revision_ids. NoSuchRevision will be raised if any of these
3512
revisions are not present.
3513
:param if_present_ids: like revision_ids, but will not cause
3514
NoSuchRevision if any of these are absent, instead they will simply
3515
not be in the result. This is useful for e.g. finding revisions
3516
to fetch for tags, which may reference absent revisions.
3474
3517
:param find_ghosts: If True find missing revisions in deep history
3475
3518
rather than just finding the surface difference.
3476
3519
:return: A bzrlib.graph.SearchResult.
3521
if symbol_versioning.deprecated_passed(revision_id):
3522
symbol_versioning.warn(
3523
'search_missing_revision_ids(revision_id=...) was '
3524
'deprecated in 2.3. Use revision_ids=[...] instead.',
3525
DeprecationWarning, stacklevel=2)
3526
if revision_ids is not None:
3527
raise AssertionError(
3528
'revision_ids is mutually exclusive with revision_id')
3529
if revision_id is not None:
3530
revision_ids = [revision_id]
3478
3532
# stop searching at found target revisions.
3479
if not find_ghosts and revision_id is not None:
3480
return self._walk_to_common_revisions([revision_id])
3533
if not find_ghosts and (revision_ids is not None or if_present_ids is
3535
return self._walk_to_common_revisions(revision_ids,
3536
if_present_ids=if_present_ids)
3481
3537
# generic, possibly worst case, slow code path.
3482
3538
target_ids = set(self.target.all_revision_ids())
3483
if revision_id is not None:
3484
source_ids = self.source.get_ancestry(revision_id)
3485
if source_ids[0] is not None:
3486
raise AssertionError()
3489
source_ids = self.source.all_revision_ids()
3539
source_ids = self._present_source_revisions_for(
3540
revision_ids, if_present_ids)
3490
3541
result_set = set(source_ids).difference(target_ids)
3491
3542
return self.source.revision_ids_to_search_result(result_set)
3544
def _present_source_revisions_for(self, revision_ids, if_present_ids=None):
3545
"""Returns set of all revisions in ancestry of revision_ids present in
3548
:param revision_ids: if None, all revisions in source are returned.
3549
:param if_present_ids: like revision_ids, but if any/all of these are
3550
absent no error is raised.
3552
if revision_ids is not None or if_present_ids is not None:
3553
# First, ensure all specified revisions exist. Callers expect
3554
# NoSuchRevision when they pass absent revision_ids here.
3555
if revision_ids is None:
3556
revision_ids = set()
3557
if if_present_ids is None:
3558
if_present_ids = set()
3559
revision_ids = set(revision_ids)
3560
if_present_ids = set(if_present_ids)
3561
all_wanted_ids = revision_ids.union(if_present_ids)
3562
graph = self.source.get_graph()
3563
present_revs = set(graph.get_parent_map(all_wanted_ids))
3564
missing = revision_ids.difference(present_revs)
3566
raise errors.NoSuchRevision(self.source, missing.pop())
3567
found_ids = all_wanted_ids.intersection(present_revs)
3568
source_ids = [rev_id for (rev_id, parents) in
3569
graph.iter_ancestry(found_ids)
3570
if rev_id != _mod_revision.NULL_REVISION
3571
and parents is not None]
3573
source_ids = self.source.all_revision_ids()
3574
return set(source_ids)
3494
3577
def _same_model(source, target):
3495
3578
"""True if source and target have the same data representation.
3536
3619
return InterRepository._same_model(source, target)
3539
class InterWeaveRepo(InterSameDataRepository):
3540
"""Optimised code paths between Weave based repositories.
3542
This should be in bzrlib/repofmt/weaverepo.py but we have not yet
3543
implemented lazy inter-object optimisation.
3547
def _get_repo_format_to_test(self):
3548
from bzrlib.repofmt import weaverepo
3549
return weaverepo.RepositoryFormat7()
3552
def is_compatible(source, target):
3553
"""Be compatible with known Weave formats.
3555
We don't test for the stores being of specific types because that
3556
could lead to confusing results, and there is no need to be
3559
from bzrlib.repofmt.weaverepo import (
3565
return (isinstance(source._format, (RepositoryFormat5,
3567
RepositoryFormat7)) and
3568
isinstance(target._format, (RepositoryFormat5,
3570
RepositoryFormat7)))
3571
except AttributeError:
3575
def copy_content(self, revision_id=None):
3576
"""See InterRepository.copy_content()."""
3577
# weave specific optimised path:
3579
self.target.set_make_working_trees(self.source.make_working_trees())
3580
except (errors.RepositoryUpgradeRequired, NotImplemented):
3582
# FIXME do not peek!
3583
if self.source._transport.listable():
3584
pb = ui.ui_factory.nested_progress_bar()
3586
self.target.texts.insert_record_stream(
3587
self.source.texts.get_record_stream(
3588
self.source.texts.keys(), 'topological', False))
3589
pb.update('Copying inventory', 0, 1)
3590
self.target.inventories.insert_record_stream(
3591
self.source.inventories.get_record_stream(
3592
self.source.inventories.keys(), 'topological', False))
3593
self.target.signatures.insert_record_stream(
3594
self.source.signatures.get_record_stream(
3595
self.source.signatures.keys(),
3597
self.target.revisions.insert_record_stream(
3598
self.source.revisions.get_record_stream(
3599
self.source.revisions.keys(),
3600
'topological', True))
3604
self.target.fetch(self.source, revision_id=revision_id)
3607
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3608
"""See InterRepository.missing_revision_ids()."""
3609
# we want all revisions to satisfy revision_id in source.
3610
# but we don't want to stat every file here and there.
3611
# we want then, all revisions other needs to satisfy revision_id
3612
# checked, but not those that we have locally.
3613
# so the first thing is to get a subset of the revisions to
3614
# satisfy revision_id in source, and then eliminate those that
3615
# we do already have.
3616
# this is slow on high latency connection to self, but as this
3617
# disk format scales terribly for push anyway due to rewriting
3618
# inventory.weave, this is considered acceptable.
3620
if revision_id is not None:
3621
source_ids = self.source.get_ancestry(revision_id)
3622
if source_ids[0] is not None:
3623
raise AssertionError()
3626
source_ids = self.source._all_possible_ids()
3627
source_ids_set = set(source_ids)
3628
# source_ids is the worst possible case we may need to pull.
3629
# now we want to filter source_ids against what we actually
3630
# have in target, but don't try to check for existence where we know
3631
# we do not have a revision as that would be pointless.
3632
target_ids = set(self.target._all_possible_ids())
3633
possibly_present_revisions = target_ids.intersection(source_ids_set)
3634
actually_present_revisions = set(
3635
self.target._eliminate_revisions_not_present(possibly_present_revisions))
3636
required_revisions = source_ids_set.difference(actually_present_revisions)
3637
if revision_id is not None:
3638
# we used get_ancestry to determine source_ids then we are assured all
3639
# revisions referenced are present as they are installed in topological order.
3640
# and the tip revision was validated by get_ancestry.
3641
result_set = required_revisions
3643
# if we just grabbed the possibly available ids, then
3644
# we only have an estimate of whats available and need to validate
3645
# that against the revision records.
3647
self.source._eliminate_revisions_not_present(required_revisions))
3648
return self.source.revision_ids_to_search_result(result_set)
3651
class InterKnitRepo(InterSameDataRepository):
3652
"""Optimised code paths between Knit based repositories."""
3655
def _get_repo_format_to_test(self):
3656
from bzrlib.repofmt import knitrepo
3657
return knitrepo.RepositoryFormatKnit1()
3660
def is_compatible(source, target):
3661
"""Be compatible with known Knit formats.
3663
We don't test for the stores being of specific types because that
3664
could lead to confusing results, and there is no need to be
3667
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit
3669
are_knits = (isinstance(source._format, RepositoryFormatKnit) and
3670
isinstance(target._format, RepositoryFormatKnit))
3671
except AttributeError:
3673
return are_knits and InterRepository._same_model(source, target)
3676
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3677
"""See InterRepository.missing_revision_ids()."""
3678
if revision_id is not None:
3679
source_ids = self.source.get_ancestry(revision_id)
3680
if source_ids[0] is not None:
3681
raise AssertionError()
3684
source_ids = self.source.all_revision_ids()
3685
source_ids_set = set(source_ids)
3686
# source_ids is the worst possible case we may need to pull.
3687
# now we want to filter source_ids against what we actually
3688
# have in target, but don't try to check for existence where we know
3689
# we do not have a revision as that would be pointless.
3690
target_ids = set(self.target.all_revision_ids())
3691
possibly_present_revisions = target_ids.intersection(source_ids_set)
3692
actually_present_revisions = set(
3693
self.target._eliminate_revisions_not_present(possibly_present_revisions))
3694
required_revisions = source_ids_set.difference(actually_present_revisions)
3695
if revision_id is not None:
3696
# we used get_ancestry to determine source_ids then we are assured all
3697
# revisions referenced are present as they are installed in topological order.
3698
# and the tip revision was validated by get_ancestry.
3699
result_set = required_revisions
3701
# if we just grabbed the possibly available ids, then
3702
# we only have an estimate of whats available and need to validate
3703
# that against the revision records.
3705
self.source._eliminate_revisions_not_present(required_revisions))
3706
return self.source.revision_ids_to_search_result(result_set)
3709
3622
class InterDifferingSerializer(InterRepository):