/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: Robert Collins
  • Date: 2009-08-26 03:20:32 UTC
  • mfrom: (4637 +trunk)
  • mto: (4634.6.2 2.0)
  • mto: This revision was merged to the branch mainline in revision 4660.
  • Revision ID: robertc@robertcollins.net-20090826032032-mx5kiog3eihaoy13
Merge and cherrypick outstanding 2.0 relevant patches from bzr.dev: Up to rev
4637, then 4639,4641,4643,4646,4649,4650,4651. (Robert Collins)

Log messages of the incorporated fixes:

revno: 4651 [merge]
  (robertc) Enable commit via record_iter_changes for specific file
        comments. (Robert Collins)

revno: 4650 [merge]
  Fix shelve on windows. (Robert Collins, #305006)

revno: 4649 [merge]
  (robertc) Make iter_changes produce output that is always safe to
        generate inventory deltas of in the same direction as the
        changes. (Robert Collins, #347649)

revno: 4646 [merge]
  (mbp) developer documentation about content filtering

revno: 4643 [merge]
  (mbp) small tweaks to release documentation

revno: 4641 [merge]
  (abentley) Shelve will not remove tree root.

revno: 4639 [merge]
  (andrew) Fix 'Revision ... not present' errors when upgrading stacked
        branches.

revno: 4637 [merge]
  Fix upgrade of branches in repositories.

revno: 4636 [merge]
  (mbp) fix crash formatting CannotBindAddress

revno: 4635 [merge]
  (robertc) Fix many locking errors on windows due to a small bug in
        merge.transform_tree. (Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
807
807
                seen_root = True
808
808
        self.new_inventory = None
809
809
        if len(inv_delta):
 
810
            # This should perhaps be guarded by a check that the basis we
 
811
            # commit against is the basis for the commit and if not do a delta
 
812
            # against the basis.
810
813
            self._any_changes = True
811
814
        if not seen_root:
812
815
            # housekeeping root entry changes do not affect no-change commits.
3732
3735
            return False
3733
3736
        return True
3734
3737
 
3735
 
    def _get_delta_for_revision(self, tree, parent_ids, basis_id, cache):
 
3738
    def _get_trees(self, revision_ids, cache):
 
3739
        possible_trees = []
 
3740
        for rev_id in revision_ids:
 
3741
            if rev_id in cache:
 
3742
                possible_trees.append((rev_id, cache[rev_id]))
 
3743
            else:
 
3744
                # Not cached, but inventory might be present anyway.
 
3745
                try:
 
3746
                    tree = self.source.revision_tree(rev_id)
 
3747
                except errors.NoSuchRevision:
 
3748
                    # Nope, parent is ghost.
 
3749
                    pass
 
3750
                else:
 
3751
                    cache[rev_id] = tree
 
3752
                    possible_trees.append((rev_id, tree))
 
3753
        return possible_trees
 
3754
 
 
3755
    def _get_delta_for_revision(self, tree, parent_ids, possible_trees):
3736
3756
        """Get the best delta and base for this revision.
3737
3757
 
3738
3758
        :return: (basis_id, delta)
3739
3759
        """
3740
 
        possible_trees = [(parent_id, cache[parent_id])
3741
 
                          for parent_id in parent_ids
3742
 
                           if parent_id in cache]
3743
 
        if len(possible_trees) == 0:
3744
 
            # There either aren't any parents, or the parents aren't in the
3745
 
            # cache, so just use the last converted tree
3746
 
            possible_trees.append((basis_id, cache[basis_id]))
3747
3760
        deltas = []
 
3761
        # Generate deltas against each tree, to find the shortest.
 
3762
        texts_possibly_new_in_tree = set()
3748
3763
        for basis_id, basis_tree in possible_trees:
3749
3764
            delta = tree.inventory._make_delta(basis_tree.inventory)
 
3765
            for old_path, new_path, file_id, new_entry in delta:
 
3766
                if new_path is None:
 
3767
                    # This file_id isn't present in the new rev, so we don't
 
3768
                    # care about it.
 
3769
                    continue
 
3770
                if not new_path:
 
3771
                    # Rich roots are handled elsewhere...
 
3772
                    continue
 
3773
                kind = new_entry.kind
 
3774
                if kind != 'directory' and kind != 'file':
 
3775
                    # No text record associated with this inventory entry.
 
3776
                    continue
 
3777
                # This is a directory or file that has changed somehow.
 
3778
                texts_possibly_new_in_tree.add((file_id, new_entry.revision))
3750
3779
            deltas.append((len(delta), basis_id, delta))
3751
3780
        deltas.sort()
3752
3781
        return deltas[0][1:]
3753
3782
 
 
3783
    def _fetch_parent_invs_for_stacking(self, parent_map, cache):
 
3784
        """Find all parent revisions that are absent, but for which the
 
3785
        inventory is present, and copy those inventories.
 
3786
 
 
3787
        This is necessary to preserve correctness when the source is stacked
 
3788
        without fallbacks configured.  (Note that in cases like upgrade the
 
3789
        source may be not have _fallback_repositories even though it is
 
3790
        stacked.)
 
3791
        """
 
3792
        parent_revs = set()
 
3793
        for parents in parent_map.values():
 
3794
            parent_revs.update(parents)
 
3795
        present_parents = self.source.get_parent_map(parent_revs)
 
3796
        absent_parents = set(parent_revs).difference(present_parents)
 
3797
        parent_invs_keys_for_stacking = self.source.inventories.get_parent_map(
 
3798
            (rev_id,) for rev_id in absent_parents)
 
3799
        parent_inv_ids = [key[-1] for key in parent_invs_keys_for_stacking]
 
3800
        for parent_tree in self.source.revision_trees(parent_inv_ids):
 
3801
            current_revision_id = parent_tree.get_revision_id()
 
3802
            parents_parents_keys = parent_invs_keys_for_stacking[
 
3803
                (current_revision_id,)]
 
3804
            parents_parents = [key[-1] for key in parents_parents_keys]
 
3805
            basis_id = _mod_revision.NULL_REVISION
 
3806
            basis_tree = self.source.revision_tree(basis_id)
 
3807
            delta = parent_tree.inventory._make_delta(basis_tree.inventory)
 
3808
            self.target.add_inventory_by_delta(
 
3809
                basis_id, delta, current_revision_id, parents_parents)
 
3810
            cache[current_revision_id] = parent_tree
 
3811
 
3754
3812
    def _fetch_batch(self, revision_ids, basis_id, cache):
3755
3813
        """Fetch across a few revisions.
3756
3814
 
3769
3827
        pending_deltas = []
3770
3828
        pending_revisions = []
3771
3829
        parent_map = self.source.get_parent_map(revision_ids)
 
3830
        self._fetch_parent_invs_for_stacking(parent_map, cache)
3772
3831
        for tree in self.source.revision_trees(revision_ids):
 
3832
            # Find a inventory delta for this revision.
 
3833
            # Find text entries that need to be copied, too.
3773
3834
            current_revision_id = tree.get_revision_id()
3774
3835
            parent_ids = parent_map.get(current_revision_id, ())
 
3836
            parent_trees = self._get_trees(parent_ids, cache)
 
3837
            possible_trees = list(parent_trees)
 
3838
            if len(possible_trees) == 0:
 
3839
                # There either aren't any parents, or the parents are ghosts,
 
3840
                # so just use the last converted tree.
 
3841
                possible_trees.append((basis_id, cache[basis_id]))
3775
3842
            basis_id, delta = self._get_delta_for_revision(tree, parent_ids,
3776
 
                                                           basis_id, cache)
 
3843
                                                           possible_trees)
3777
3844
            if self._converting_to_rich_root:
3778
3845
                self._revision_id_to_root_id[current_revision_id] = \
3779
3846
                    tree.get_root_id()
3780
 
            # Find text entries that need to be copied
 
3847
            # Determine which texts are in present in this revision but not in
 
3848
            # any of the available parents.
 
3849
            texts_possibly_new_in_tree = set()
3781
3850
            for old_path, new_path, file_id, entry in delta:
3782
 
                if new_path is not None:
3783
 
                    if not new_path:
3784
 
                        # This is the root
3785
 
                        if not self.target.supports_rich_root():
3786
 
                            # The target doesn't support rich root, so we don't
3787
 
                            # copy
3788
 
                            continue
3789
 
                        if self._converting_to_rich_root:
3790
 
                            # This can't be copied normally, we have to insert
3791
 
                            # it specially
3792
 
                            root_keys_to_create.add((file_id, entry.revision))
3793
 
                            continue
3794
 
                    text_keys.add((file_id, entry.revision))
 
3851
                if new_path is None:
 
3852
                    # This file_id isn't present in the new rev
 
3853
                    continue
 
3854
                if not new_path:
 
3855
                    # This is the root
 
3856
                    if not self.target.supports_rich_root():
 
3857
                        # The target doesn't support rich root, so we don't
 
3858
                        # copy
 
3859
                        continue
 
3860
                    if self._converting_to_rich_root:
 
3861
                        # This can't be copied normally, we have to insert
 
3862
                        # it specially
 
3863
                        root_keys_to_create.add((file_id, entry.revision))
 
3864
                        continue
 
3865
                kind = entry.kind
 
3866
                texts_possibly_new_in_tree.add((file_id, entry.revision))
 
3867
            for basis_id, basis_tree in possible_trees:
 
3868
                basis_inv = basis_tree.inventory
 
3869
                for file_key in list(texts_possibly_new_in_tree):
 
3870
                    file_id, file_revision = file_key
 
3871
                    try:
 
3872
                        entry = basis_inv[file_id]
 
3873
                    except errors.NoSuchId:
 
3874
                        continue
 
3875
                    if entry.revision == file_revision:
 
3876
                        texts_possibly_new_in_tree.remove(file_key)
 
3877
            text_keys.update(texts_possibly_new_in_tree)
3795
3878
            revision = self.source.get_revision(current_revision_id)
3796
3879
            pending_deltas.append((basis_id, delta,
3797
3880
                current_revision_id, revision.parent_ids))
3833
3916
            for parent_tree in self.source.revision_trees(parent_map):
3834
3917
                current_revision_id = parent_tree.get_revision_id()
3835
3918
                parents_parents = parent_map[current_revision_id]
 
3919
                possible_trees = self._get_trees(parents_parents, cache)
 
3920
                if len(possible_trees) == 0:
 
3921
                    # There either aren't any parents, or the parents are
 
3922
                    # ghosts, so just use the last converted tree.
 
3923
                    possible_trees.append((basis_id, cache[basis_id]))
3836
3924
                basis_id, delta = self._get_delta_for_revision(parent_tree,
3837
 
                    parents_parents, basis_id, cache)
 
3925
                    parents_parents, possible_trees)
3838
3926
                self.target.add_inventory_by_delta(
3839
3927
                    basis_id, delta, current_revision_id, parents_parents)
3840
3928
        # insert signatures and revisions