~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-01-12 17:21:32 UTC
  • mfrom: (5557.1.18 2.3-commit-to-stacked)
  • Revision ID: pqm@pqm.ubuntu.com-20110112172132-p7n9cxhslpn6svhh
(jameinel) Allow commits to stacked branches (John A Meinel)

Show diffs side-by-side

added added

removed removed

Lines of Context:
176
176
            self._validate_unicode_text(value,
177
177
                                        'revision property (%s)' % (key,))
178
178
 
 
179
    def _ensure_fallback_inventories(self):
 
180
        """Ensure that appropriate inventories are available.
 
181
 
 
182
        This only applies to repositories that are stacked, and is about
 
183
        enusring the stacking invariants. Namely, that for any revision that is
 
184
        present, we either have all of the file content, or we have the parent
 
185
        inventory and the delta file content.
 
186
        """
 
187
        if not self.repository._fallback_repositories:
 
188
            return
 
189
        if not self.repository._format.supports_chks:
 
190
            raise errors.BzrError("Cannot commit directly to a stacked branch"
 
191
                " in pre-2a formats. See "
 
192
                "https://bugs.launchpad.net/bzr/+bug/375013 for details.")
 
193
        # This is a stacked repo, we need to make sure we have the parent
 
194
        # inventories for the parents.
 
195
        parent_keys = [(p,) for p in self.parents]
 
196
        parent_map = self.repository.inventories._index.get_parent_map(parent_keys)
 
197
        missing_parent_keys = set([pk for pk in parent_keys
 
198
                                       if pk not in parent_map])
 
199
        fallback_repos = list(reversed(self.repository._fallback_repositories))
 
200
        missing_keys = [('inventories', pk[0])
 
201
                        for pk in missing_parent_keys]
 
202
        resume_tokens = []
 
203
        while missing_keys and fallback_repos:
 
204
            fallback_repo = fallback_repos.pop()
 
205
            source = fallback_repo._get_source(self.repository._format)
 
206
            sink = self.repository._get_sink()
 
207
            stream = source.get_stream_for_missing_keys(missing_keys)
 
208
            missing_keys = sink.insert_stream_without_locking(stream,
 
209
                self.repository._format)
 
210
        if missing_keys:
 
211
            raise errors.BzrError('Unable to fill in parent inventories for a'
 
212
                                  ' stacked branch')
 
213
 
179
214
    def commit(self, message):
180
215
        """Make the actual commit.
181
216
 
193
228
        rev.parent_ids = self.parents
194
229
        self.repository.add_revision(self._new_revision_id, rev,
195
230
            self.new_inventory, self._config)
 
231
        self._ensure_fallback_inventories()
196
232
        self.repository.commit_write_group()
197
233
        return self._new_revision_id
198
234
 
1761
1797
        :param revprops: Optional dictionary of revision properties.
1762
1798
        :param revision_id: Optional revision id.
1763
1799
        """
1764
 
        if self._fallback_repositories:
1765
 
            raise errors.BzrError("Cannot commit from a lightweight checkout "
1766
 
                "to a stacked branch. See "
 
1800
        if self._fallback_repositories and not self._format.supports_chks:
 
1801
            raise errors.BzrError("Cannot commit directly to a stacked branch"
 
1802
                " in pre-2a formats. See "
1767
1803
                "https://bugs.launchpad.net/bzr/+bug/375013 for details.")
1768
1804
        result = self._commit_builder_class(self, parents, config,
1769
1805
            timestamp, timezone, committer, revprops, revision_id)
4054
4090
                is_resume = False
4055
4091
            try:
4056
4092
                # locked_insert_stream performs a commit|suspend.
4057
 
                return self._locked_insert_stream(stream, src_format,
4058
 
                    is_resume)
 
4093
                missing_keys = self.insert_stream_without_locking(stream,
 
4094
                                    src_format, is_resume)
 
4095
                if missing_keys:
 
4096
                    # suspend the write group and tell the caller what we is
 
4097
                    # missing. We know we can suspend or else we would not have
 
4098
                    # entered this code path. (All repositories that can handle
 
4099
                    # missing keys can handle suspending a write group).
 
4100
                    write_group_tokens = self.target_repo.suspend_write_group()
 
4101
                    return write_group_tokens, missing_keys
 
4102
                hint = self.target_repo.commit_write_group()
 
4103
                to_serializer = self.target_repo._format._serializer
 
4104
                src_serializer = src_format._serializer
 
4105
                if (to_serializer != src_serializer and
 
4106
                    self.target_repo._format.pack_compresses):
 
4107
                    self.target_repo.pack(hint=hint)
 
4108
                return [], set()
4059
4109
            except:
4060
4110
                self.target_repo.abort_write_group(suppress_errors=True)
4061
4111
                raise
4062
4112
        finally:
4063
4113
            self.target_repo.unlock()
4064
4114
 
4065
 
    def _locked_insert_stream(self, stream, src_format, is_resume):
 
4115
    def insert_stream_without_locking(self, stream, src_format,
 
4116
                                      is_resume=False):
 
4117
        """Insert a stream's content into the target repository.
 
4118
 
 
4119
        This assumes that you already have a locked repository and an active
 
4120
        write group.
 
4121
 
 
4122
        :param src_format: a bzr repository format.
 
4123
        :param is_resume: Passed down to get_missing_parent_inventories to
 
4124
            indicate if we should be checking for missing texts at the same
 
4125
            time.
 
4126
 
 
4127
        :return: A set of keys that are missing.
 
4128
        """
 
4129
        if not self.target_repo.is_write_locked():
 
4130
            raise errors.ObjectNotLocked(self)
 
4131
        if not self.target_repo.is_in_write_group():
 
4132
            raise errors.BzrError('you must already be in a write group')
4066
4133
        to_serializer = self.target_repo._format._serializer
4067
4134
        src_serializer = src_format._serializer
4068
4135
        new_pack = None
4147
4214
            # cannot even attempt suspending, and missing would have failed
4148
4215
            # during stream insertion.
4149
4216
            missing_keys = set()
4150
 
        else:
4151
 
            if missing_keys:
4152
 
                # suspend the write group and tell the caller what we is
4153
 
                # missing. We know we can suspend or else we would not have
4154
 
                # entered this code path. (All repositories that can handle
4155
 
                # missing keys can handle suspending a write group).
4156
 
                write_group_tokens = self.target_repo.suspend_write_group()
4157
 
                return write_group_tokens, missing_keys
4158
 
        hint = self.target_repo.commit_write_group()
4159
 
        if (to_serializer != src_serializer and
4160
 
            self.target_repo._format.pack_compresses):
4161
 
            self.target_repo.pack(hint=hint)
4162
 
        return [], set()
 
4217
        return missing_keys
4163
4218
 
4164
4219
    def _extract_and_insert_inventory_deltas(self, substream, serializer):
4165
4220
        target_rich_root = self.target_repo._format.rich_root_data