~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

Merge in knit repository use of knits - still not a stable format, but can be experimented with.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
add a revision to the store until everything it refers to is also
27
27
stored, so that if a revision is present we can totally recreate it.
28
28
However, we can't know what files are included in a revision until we
29
 
read its inventory.  Therefore, we first pull the XML and hold it in
30
 
memory until we've updated all of the files referenced.
 
29
read its inventory.  So we query the inventory store of the source for
 
30
the ids we need, and then pull those ids and finally actually join
 
31
the inventories.
31
32
"""
32
33
 
33
34
import bzrlib
34
35
import bzrlib.errors as errors
35
 
from bzrlib.errors import (InstallFailed, NoSuchRevision, WeaveError,
 
36
from bzrlib.errors import (InstallFailed, NoSuchRevision,
36
37
                           MissingText)
37
38
from bzrlib.trace import mutter
38
39
from bzrlib.progress import ProgressBar
150
151
        except errors.NoSuchRevision:
151
152
            raise InstallFailed([self._last_revision])
152
153
 
153
 
    def _fetch_revision_texts(self, revs):
154
 
        self.to_repository.revision_store.copy_multi(
155
 
            self.from_repository.revision_store,
156
 
            revs,
157
 
            pb=self.pb)
158
 
        # fixup inventory if needed:
159
 
        # this is expensive because we have no inverse index to current ghosts.
160
 
        # but on local disk its a few seconds and sftp push is already insane.
161
 
        # so we just-do-it.
162
 
        # FIXME: the generic code path should not need this, if it truely is
163
 
        # generic.
164
 
        reconciler = RepoReconciler(self.to_repository)
165
 
        reconciler.reconcile()
166
 
 
167
154
    def _fetch_weave_texts(self, revs):
168
155
        file_ids = self.from_repository.fileid_involved_by_set(revs)
169
156
        count = 0
173
160
            count +=1
174
161
            to_weave = self.to_weaves.get_weave_or_empty(file_id,
175
162
                self.to_repository.get_transaction())
176
 
            from_weave = self.from_weaves.get_weave(file_id,
177
 
                self.from_repository.get_transaction())
178
163
 
179
 
            if to_weave.numversions() > 0:
 
164
            if to_weave.num_versions() > 0:
180
165
                # destination has contents, must merge
181
 
                try:
182
 
                    to_weave.join(from_weave)
183
 
                except errors.WeaveParentMismatch:
184
 
                    to_weave.reweave(from_weave)
 
166
                from_weave = self.from_weaves.get_weave(file_id,
 
167
                    self.from_repository.get_transaction())
 
168
                # we fetch all the texts, because texts do
 
169
                # not reference anything, and its cheap enough
 
170
                to_weave.join(from_weave)
185
171
            else:
186
172
                # destination is empty, just replace it
187
 
                to_weave = from_weave.copy()
188
 
 
189
 
            self.to_weaves.put_weave(file_id, to_weave,
190
 
                self.to_repository.get_transaction())
 
173
                self.to_weaves.copy_multi(self.from_weaves, [file_id], self.pb,
 
174
                                          self.from_repository.get_transaction(),
 
175
                                          self.to_repository.get_transaction())
191
176
        self.pb.clear()
192
177
 
193
178
    def _fetch_inventory_weave(self, revs):
194
179
        self.pb.update("inventory fetch", 0, 2)
195
 
        from_weave = self.from_repository.get_inventory_weave()
196
 
        self.to_inventory_weave = self.to_repository.get_inventory_weave()
197
 
        self.pb.update("inventory fetch", 1, 2)
198
 
        self.to_inventory_weave = self.to_control.get_weave('inventory',
 
180
        to_weave = self.to_control.get_weave('inventory',
199
181
                self.to_repository.get_transaction())
200
 
        self.pb.update("inventory fetch", 2, 2)
201
182
 
202
 
        if self.to_inventory_weave.numversions() > 0:
 
183
        if to_weave.num_versions() > 0:
203
184
            # destination has contents, must merge
204
 
            try:
205
 
                self.to_inventory_weave.join(from_weave, pb=self.pb, msg='merge inventory')
206
 
            except errors.WeaveParentMismatch:
207
 
                self.to_inventory_weave.reweave(from_weave, pb=self.pb, msg='reweave inventory')
 
185
            self.pb.update("inventory fetch", 1, 2)
 
186
            from_weave = self.from_repository.get_inventory_weave()
 
187
            self.pb.update("inventory fetch", 2, 2)
 
188
            # we fetch only the referenced inventories because we do not
 
189
            # know for unselected inventories whether all their required
 
190
            # texts are present in the other repository - it could be
 
191
            # corrupt.
 
192
            to_weave.join(from_weave, pb=self.pb, msg='merge inventory',
 
193
                          version_ids=revs)
208
194
        else:
209
195
            # destination is empty, just replace it
210
 
            self.to_inventory_weave = from_weave.copy()
211
 
 
212
 
        # must be written before pulling any revisions
213
 
        self.to_control.put_weave('inventory', self.to_inventory_weave,
214
 
            self.to_repository.get_transaction())
 
196
            self.to_control.copy_multi(self.from_control,
 
197
                                       ['inventory'],
 
198
                                       self.pb,
 
199
                                       self.from_repository.get_transaction(),
 
200
                                       self.to_repository.get_transaction())
215
201
 
216
202
        self.pb.clear()
217
203
 
218
204
 
 
205
class GenericRepoFetcher(RepoFetcher):
 
206
    """This is a generic repo to repo fetcher.
 
207
 
 
208
    This makes minimal assumptions about repo layout and contents.
 
209
    It triggers a reconciliation after fetching to ensure integrity.
 
210
    """
 
211
 
 
212
    def _fetch_revision_texts(self, revs):
 
213
        self.to_transaction = self.to_repository.get_transaction()
 
214
        count = 0
 
215
        total = len(revs)
 
216
        for rev in revs:
 
217
            self.pb.update('copying revisions', count, total)
 
218
            try:
 
219
                sig_text = self.from_repository.get_signature_text(rev)
 
220
                self.to_repository._revision_store.add_revision_signature_text(
 
221
                    rev, sig_text, self.to_transaction)
 
222
            except errors.NoSuchRevision:
 
223
                # not signed.
 
224
                pass
 
225
            self.to_repository._revision_store.add_revision(
 
226
                self.from_repository.get_revision(rev),
 
227
                self.to_transaction)
 
228
            count += 1
 
229
        self.pb.update('copying revisions', count, total)
 
230
        # fixup inventory if needed: 
 
231
        # this is expensive because we have no inverse index to current ghosts.
 
232
        # but on local disk its a few seconds and sftp push is already insane.
 
233
        # so we just-do-it.
 
234
        # FIXME: repository should inform if this is needed.
 
235
        reconciler = RepoReconciler(self.to_repository)
 
236
        reconciler.reconcile()
 
237
    
 
238
 
 
239
class KnitRepoFetcher(RepoFetcher):
 
240
    """This is a knit format repository specific fetcher.
 
241
 
 
242
    This differs from the GenericRepoFetcher by not doing a 
 
243
    reconciliation after copying, and using knit joining to
 
244
    copy revision texts.
 
245
    """
 
246
 
 
247
    def _fetch_revision_texts(self, revs):
 
248
        # may need to be a InterRevisionStore call here.
 
249
        from_transaction = self.from_repository.get_transaction()
 
250
        to_transaction = self.to_repository.get_transaction()
 
251
        to_sf = self.to_repository._revision_store.get_signature_file(
 
252
            to_transaction)
 
253
        from_sf = self.from_repository._revision_store.get_signature_file(
 
254
            from_transaction)
 
255
        to_sf.join(from_sf, version_ids=revs, pb=self.pb, ignore_missing=True)
 
256
        to_rf = self.to_repository._revision_store.get_revision_file(
 
257
            to_transaction)
 
258
        from_rf = self.from_repository._revision_store.get_revision_file(
 
259
            from_transaction)
 
260
        to_rf.join(from_rf, version_ids=revs, pb=self.pb)
 
261
        reconciler = RepoReconciler(self.to_repository)
 
262
        reconciler.reconcile()
 
263
 
 
264
 
219
265
class Fetcher(object):
220
266
    """Backwards compatability glue for branch.fetch()."""
221
267