~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

  • Committer: Martin Pool
  • Date: 2006-03-09 07:14:10 UTC
  • mfrom: (1600 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1602.
  • Revision ID: mbp@sourcefrog.net-20060309071410-4ab7d54905541c75
[merge] from bzr.dev

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
94
95
        # must not mutate self._last_revision as its potentially a shared instance
95
96
        self._last_revision = last_revision
96
97
        if pb is None:
97
 
            self.pb = bzrlib.ui.ui_factory.progress_bar()
 
98
            self.pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
99
            self.nested_pb = self.pb
98
100
        else:
99
101
            self.pb = pb
 
102
            self.nested_pb = None
100
103
        self.from_repository.lock_read()
101
104
        try:
102
105
            self.to_repository.lock_write()
103
106
            try:
104
107
                self.__fetch()
105
108
            finally:
 
109
                if self.nested_pb is not None:
 
110
                    self.nested_pb.finished()
106
111
                self.to_repository.unlock()
107
112
        finally:
108
113
            self.from_repository.unlock()
146
151
        except errors.NoSuchRevision:
147
152
            raise InstallFailed([self._last_revision])
148
153
 
149
 
    def _fetch_revision_texts(self, revs):
150
 
        self.to_repository.revision_store.copy_multi(
151
 
            self.from_repository.revision_store,
152
 
            revs,
153
 
            pb=self.pb)
154
 
        # fixup inventory if needed:
155
 
        # this is expensive because we have no inverse index to current ghosts.
156
 
        # but on local disk its a few seconds and sftp push is already insane.
157
 
        # so we just-do-it.
158
 
        # FIXME: the generic code path should not need this, if it truely is
159
 
        # generic.
160
 
        reconciler = RepoReconciler(self.to_repository)
161
 
        reconciler.reconcile()
162
 
 
163
154
    def _fetch_weave_texts(self, revs):
164
155
        file_ids = self.from_repository.fileid_involved_by_set(revs)
165
156
        count = 0
169
160
            count +=1
170
161
            to_weave = self.to_weaves.get_weave_or_empty(file_id,
171
162
                self.to_repository.get_transaction())
172
 
            from_weave = self.from_weaves.get_weave(file_id,
173
 
                self.from_repository.get_transaction())
174
163
 
175
 
            if to_weave.numversions() > 0:
 
164
            if to_weave.num_versions() > 0:
176
165
                # destination has contents, must merge
177
 
                try:
178
 
                    to_weave.join(from_weave)
179
 
                except errors.WeaveParentMismatch:
180
 
                    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)
181
171
            else:
182
172
                # destination is empty, just replace it
183
 
                to_weave = from_weave.copy()
184
 
 
185
 
            self.to_weaves.put_weave(file_id, to_weave,
186
 
                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())
187
176
        self.pb.clear()
188
177
 
189
178
    def _fetch_inventory_weave(self, revs):
190
179
        self.pb.update("inventory fetch", 0, 2)
191
 
        from_weave = self.from_repository.get_inventory_weave()
192
 
        self.to_inventory_weave = self.to_repository.get_inventory_weave()
193
 
        self.pb.update("inventory fetch", 1, 2)
194
 
        self.to_inventory_weave = self.to_control.get_weave('inventory',
 
180
        to_weave = self.to_control.get_weave('inventory',
195
181
                self.to_repository.get_transaction())
196
 
        self.pb.update("inventory fetch", 2, 2)
197
182
 
198
 
        if self.to_inventory_weave.numversions() > 0:
 
183
        if to_weave.num_versions() > 0:
199
184
            # destination has contents, must merge
200
 
            try:
201
 
                self.to_inventory_weave.join(from_weave, pb=self.pb, msg='merge inventory')
202
 
            except errors.WeaveParentMismatch:
203
 
                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)
204
194
        else:
205
195
            # destination is empty, just replace it
206
 
            self.to_inventory_weave = from_weave.copy()
207
 
 
208
 
        # must be written before pulling any revisions
209
 
        self.to_control.put_weave('inventory', self.to_inventory_weave,
210
 
            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())
211
201
 
212
202
        self.pb.clear()
213
203
 
214
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
 
215
265
class Fetcher(object):
216
266
    """Backwards compatability glue for branch.fetch()."""
217
267