/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: Jelmer Vernooij
  • Date: 2009-05-28 16:04:39 UTC
  • mfrom: (4387 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4405.
  • Revision ID: jelmer@samba.org-20090528160439-4z0xlrk5nejobm7q
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1424
1424
    def suspend_write_group(self):
1425
1425
        raise errors.UnsuspendableWriteGroup(self)
1426
1426
 
 
1427
    def get_missing_parent_inventories(self):
 
1428
        """Return the keys of missing inventory parents for revisions added in
 
1429
        this write group.
 
1430
 
 
1431
        A revision is not complete if the inventory delta for that revision
 
1432
        cannot be calculated.  Therefore if the parent inventories of a
 
1433
        revision are not present, the revision is incomplete, and e.g. cannot
 
1434
        be streamed by a smart server.  This method finds missing inventory
 
1435
        parents for revisions added in this write group.
 
1436
        """
 
1437
        if not self._format.supports_external_lookups:
 
1438
            # This is only an issue for stacked repositories
 
1439
            return set()
 
1440
        if not self.is_in_write_group():
 
1441
            raise AssertionError('not in a write group')
 
1442
                
 
1443
        # XXX: We assume that every added revision already has its
 
1444
        # corresponding inventory, so we only check for parent inventories that
 
1445
        # might be missing, rather than all inventories.
 
1446
        parents = set(self.revisions._index.get_missing_parents())
 
1447
        parents.discard(_mod_revision.NULL_REVISION)
 
1448
        unstacked_inventories = self.inventories._index
 
1449
        present_inventories = unstacked_inventories.get_parent_map(
 
1450
            key[-1:] for key in parents)
 
1451
        if len(parents.difference(present_inventories)) == 0:
 
1452
            # No missing parent inventories.
 
1453
            return set()
 
1454
        # Ok, now we have a list of missing inventories.  But these only matter
 
1455
        # if the inventories that reference them are missing some texts they
 
1456
        # appear to introduce.
 
1457
        # XXX: Texts referenced by all added inventories need to be present,
 
1458
        # but at the moment we're only checking for texts referenced by
 
1459
        # inventories at the graph's edge.
 
1460
        key_deps = self.revisions._index._key_dependencies
 
1461
        key_deps.add_keys(present_inventories)
 
1462
        referrers = frozenset(r[0] for r in key_deps.get_referrers())
 
1463
        file_ids = self.fileids_altered_by_revision_ids(referrers)
 
1464
        missing_texts = set()
 
1465
        for file_id, version_ids in file_ids.iteritems():
 
1466
            missing_texts.update(
 
1467
                (file_id, version_id) for version_id in version_ids)
 
1468
        present_texts = self.texts.get_parent_map(missing_texts)
 
1469
        missing_texts.difference_update(present_texts)
 
1470
        if not missing_texts:
 
1471
            # No texts are missing, so all revisions and their deltas are
 
1472
            # reconstructable.
 
1473
            return set()
 
1474
        # Alternatively the text versions could be returned as the missing
 
1475
        # keys, but this is likely to be less data.
 
1476
        missing_keys = set(('inventories', rev_id) for (rev_id,) in parents)
 
1477
        return missing_keys
 
1478
 
1427
1479
    def refresh_data(self):
1428
1480
        """Re-read any data needed to to synchronise with disk.
1429
1481
 
3067
3119
        """
3068
3120
        target_graph = self.target.get_graph()
3069
3121
        revision_ids = frozenset(revision_ids)
3070
 
        # Fast path for the case where all the revisions are already in the
3071
 
        # target repo.
3072
 
        # (Although this does incur an extra round trip for the
3073
 
        # fairly common case where the target doesn't already have the revision
3074
 
        # we're pushing.)
3075
 
        if set(target_graph.get_parent_map(revision_ids)) == revision_ids:
3076
 
            return graph.SearchResult(revision_ids, set(), 0, set())
3077
3122
        missing_revs = set()
3078
3123
        source_graph = self.source.get_graph()
3079
3124
        # ensure we don't pay silly lookup costs.
3365
3410
    @classmethod
3366
3411
    def _get_repo_format_to_test(self):
3367
3412
        from bzrlib.repofmt import pack_repo
3368
 
        return pack_repo.RepositoryFormatKnitPack1()
 
3413
        return pack_repo.RepositoryFormatKnitPack6RichRoot()
3369
3414
 
3370
3415
    @staticmethod
3371
3416
    def is_compatible(source, target):
3435
3480
            # nothing to do:
3436
3481
            return (0, [])
3437
3482
        else:
3438
 
            try:
3439
 
                revision_ids = self.search_missing_revision_ids(revision_id,
3440
 
                    find_ghosts=find_ghosts).get_keys()
3441
 
            except errors.NoSuchRevision:
3442
 
                raise errors.InstallFailed([revision_id])
 
3483
            revision_ids = self.search_missing_revision_ids(revision_id,
 
3484
                find_ghosts=find_ghosts).get_keys()
3443
3485
            if len(revision_ids) == 0:
3444
3486
                return (0, [])
3445
3487
        return self._pack(self.source, self.target, revision_ids)
3542
3584
        """Get the parent keys for a given root id."""
3543
3585
        root_id, rev_id = root_key
3544
3586
        # Include direct parents of the revision, but only if they used
3545
 
        # the same root_id.
 
3587
        # the same root_id and are heads.
3546
3588
        parent_keys = []
3547
3589
        for parent_id in parent_map[rev_id]:
3548
3590
            if parent_id == _mod_revision.NULL_REVISION:
3562
3604
                self._revision_id_to_root_id[parent_id] = None
3563
3605
            else:
3564
3606
                parent_root_id = self._revision_id_to_root_id[parent_id]
3565
 
            if root_id == parent_root_id or parent_root_id is None:
3566
 
                parent_keys.append((root_id, parent_id))
3567
 
        return tuple(parent_keys)
 
3607
            if root_id == parent_root_id:
 
3608
                # With stacking we _might_ want to refer to a non-local
 
3609
                # revision, but this code path only applies when we have the
 
3610
                # full content available, so ghosts really are ghosts, not just
 
3611
                # the edge of local data.
 
3612
                parent_keys.append((parent_id,))
 
3613
            else:
 
3614
                # root_id may be in the parent anyway.
 
3615
                try:
 
3616
                    tree = self.source.revision_tree(parent_id)
 
3617
                except errors.NoSuchRevision:
 
3618
                    # ghost, can't refer to it.
 
3619
                    pass
 
3620
                else:
 
3621
                    try:
 
3622
                        parent_keys.append((tree.inventory[root_id].revision,))
 
3623
                    except errors.NoSuchId:
 
3624
                        # not in the tree
 
3625
                        pass
 
3626
        g = graph.Graph(self.source.revisions)
 
3627
        heads = g.heads(parent_keys)
 
3628
        selected_keys = []
 
3629
        for key in parent_keys:
 
3630
            if key in heads and key not in selected_keys:
 
3631
                selected_keys.append(key)
 
3632
        return tuple([(root_id,)+ key for key in selected_keys])
3568
3633
 
3569
3634
    def _new_root_data_stream(self, root_keys_to_create, parent_map):
3570
3635
        for root_key in root_keys_to_create:
3629
3694
        to_texts.insert_record_stream(from_texts.get_record_stream(
3630
3695
            text_keys, self.target._format._fetch_order,
3631
3696
            not self.target._format._fetch_uses_deltas))
3632
 
        # insert deltas
 
3697
        # insert inventory deltas
3633
3698
        for delta in pending_deltas:
3634
3699
            self.target.add_inventory_by_delta(*delta)
 
3700
        if self.target._fallback_repositories:
 
3701
            # Make sure this stacked repository has all the parent inventories
 
3702
            # for the new revisions that we are about to insert.  We do this
 
3703
            # before adding the revisions so that no revision is added until
 
3704
            # all the inventories it may depend on are added.
 
3705
            parent_ids = set()
 
3706
            revision_ids = set()
 
3707
            for revision in pending_revisions:
 
3708
                revision_ids.add(revision.revision_id)
 
3709
                parent_ids.update(revision.parent_ids)
 
3710
            parent_ids.difference_update(revision_ids)
 
3711
            parent_ids.discard(_mod_revision.NULL_REVISION)
 
3712
            parent_map = self.source.get_parent_map(parent_ids)
 
3713
            for parent_tree in self.source.revision_trees(parent_ids):
 
3714
                basis_id, delta = self._get_delta_for_revision(tree, parent_ids, basis_id, cache)
 
3715
                current_revision_id = parent_tree.get_revision_id()
 
3716
                parents_parents = parent_map[current_revision_id]
 
3717
                self.target.add_inventory_by_delta(
 
3718
                    basis_id, delta, current_revision_id, parents_parents)
3635
3719
        # insert signatures and revisions
3636
3720
        for revision in pending_revisions:
3637
3721
            try:
3936
4020
    def _locked_insert_stream(self, stream, src_format):
3937
4021
        to_serializer = self.target_repo._format._serializer
3938
4022
        src_serializer = src_format._serializer
 
4023
        new_pack = None
3939
4024
        if to_serializer == src_serializer:
3940
4025
            # If serializers match and the target is a pack repository, set the
3941
4026
            # write cache size on the new pack.  This avoids poor performance
3982
4067
                self.target_repo.signatures.insert_record_stream(substream)
3983
4068
            else:
3984
4069
                raise AssertionError('kaboom! %s' % (substream_type,))
 
4070
        # Done inserting data, and the missing_keys calculations will try to
 
4071
        # read back from the inserted data, so flush the writes to the new pack
 
4072
        # (if this is pack format).
 
4073
        if new_pack is not None:
 
4074
            new_pack._write_data('', flush=True)
 
4075
        # Find all the new revisions (including ones from resume_tokens)
 
4076
        missing_keys = self.target_repo.get_missing_parent_inventories()
3985
4077
        try:
3986
 
            missing_keys = set()
3987
4078
            for prefix, versioned_file in (
3988
4079
                ('texts', self.target_repo.texts),
3989
4080
                ('inventories', self.target_repo.inventories),