143
157
except errors.NoSuchRevision:
144
158
raise InstallFailed([self._last_revision])
146
def _fetch_revision_texts(self, revs):
147
self.to_repository.revision_store.copy_multi(
148
self.from_repository.revision_store,
152
160
def _fetch_weave_texts(self, revs):
153
file_ids = self.from_repository.fileid_involved_by_set(revs)
155
num_file_ids = len(file_ids)
156
for file_id in file_ids:
157
self.pb.update("merge weave merge", count, num_file_ids)
159
to_weave = self.to_weaves.get_weave_or_empty(file_id,
160
self.to_repository.get_transaction())
161
from_weave = self.from_weaves.get_weave(file_id,
162
self.from_repository.get_transaction())
164
if to_weave.numversions() > 0:
165
# destination has contents, must merge
161
texts_pb = bzrlib.ui.ui_factory.nested_progress_bar()
163
# fileids_altered_by_revision_ids requires reading the inventory
164
# weave, we will need to read the inventory weave again when
165
# all this is done, so enable caching for that specific weave
166
inv_w = self.from_repository.get_inventory_weave()
168
file_ids = self.from_repository.fileids_altered_by_revision_ids(revs)
170
num_file_ids = len(file_ids)
171
for file_id, required_versions in file_ids.items():
172
texts_pb.update("fetch texts", count, num_file_ids)
174
to_weave = self.to_weaves.get_weave_or_empty(file_id,
175
self.to_repository.get_transaction())
176
from_weave = self.from_weaves.get_weave(file_id,
177
self.from_repository.get_transaction())
178
# we fetch all the texts, because texts do
179
# not reference anything, and its cheap enough
180
to_weave.join(from_weave, version_ids=required_versions)
181
# we don't need *all* of this data anymore, but we dont know
182
# what we do. This cache clearing will result in a new read
183
# of the knit data when we do the checkout, but probably we
184
# want to emit the needed data on the fly rather than at the
186
# the from weave should know not to cache data being joined,
187
# but its ok to ask it to clear.
188
from_weave.clear_cache()
189
to_weave.clear_cache()
193
def _fetch_inventory_weave(self, revs):
194
pb = bzrlib.ui.ui_factory.nested_progress_bar()
196
pb.update("fetch inventory", 0, 2)
197
to_weave = self.to_control.get_weave('inventory',
198
self.to_repository.get_transaction())
200
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
202
# just merge, this is optimisable and its means we don't
203
# copy unreferenced data such as not-needed inventories.
204
pb.update("fetch inventory", 1, 3)
205
from_weave = self.from_repository.get_inventory_weave()
206
pb.update("fetch inventory", 2, 3)
207
# we fetch only the referenced inventories because we do not
208
# know for unselected inventories whether all their required
209
# texts are present in the other repository - it could be
211
to_weave.join(from_weave, pb=child_pb, msg='merge inventory',
213
from_weave.clear_cache()
220
class GenericRepoFetcher(RepoFetcher):
221
"""This is a generic repo to repo fetcher.
223
This makes minimal assumptions about repo layout and contents.
224
It triggers a reconciliation after fetching to ensure integrity.
227
def _fetch_revision_texts(self, revs):
228
"""Fetch revision object texts"""
229
rev_pb = bzrlib.ui.ui_factory.nested_progress_bar()
231
to_txn = self.to_transaction = self.to_repository.get_transaction()
234
to_store = self.to_repository._revision_store
236
pb = bzrlib.ui.ui_factory.nested_progress_bar()
167
to_weave.join(from_weave)
168
except errors.WeaveParentMismatch:
169
to_weave.reweave(from_weave)
171
# destination is empty, just replace it
172
to_weave = from_weave.copy()
174
self.to_weaves.put_weave(file_id, to_weave,
175
self.to_repository.get_transaction())
178
def _fetch_inventory_weave(self, revs):
179
self.pb.update("inventory fetch", 0, 2)
180
from_weave = self.from_repository.get_inventory_weave()
181
to_weave = self.to_repository.get_inventory_weave()
182
self.pb.update("inventory fetch", 1, 2)
183
to_weave = self.to_control.get_weave('inventory',
184
self.to_repository.get_transaction())
185
self.pb.update("inventory fetch", 2, 2)
187
if to_weave.numversions() > 0:
188
# destination has contents, must merge
190
to_weave.join(from_weave, pb=self.pb, msg='merge inventory')
191
except errors.WeaveParentMismatch:
192
to_weave.reweave(from_weave, pb=self.pb, msg='reweave inventory')
194
# destination is empty, just replace it
195
to_weave = from_weave.copy()
197
self.to_control.put_weave('inventory', to_weave,
198
self.to_repository.get_transaction())
238
pb.update('copying revisions', count, total)
240
sig_text = self.from_repository.get_signature_text(rev)
241
to_store.add_revision_signature_text(rev, sig_text, to_txn)
242
except errors.NoSuchRevision:
245
to_store.add_revision(self.from_repository.get_revision(rev),
250
# fixup inventory if needed:
251
# this is expensive because we have no inverse index to current ghosts.
252
# but on local disk its a few seconds and sftp push is already insane.
254
# FIXME: repository should inform if this is needed.
255
self.to_repository.reconcile()
260
class KnitRepoFetcher(RepoFetcher):
261
"""This is a knit format repository specific fetcher.
263
This differs from the GenericRepoFetcher by not doing a
264
reconciliation after copying, and using knit joining to
268
def _fetch_revision_texts(self, revs):
269
# may need to be a InterRevisionStore call here.
270
from_transaction = self.from_repository.get_transaction()
271
to_transaction = self.to_repository.get_transaction()
272
to_sf = self.to_repository._revision_store.get_signature_file(
274
from_sf = self.from_repository._revision_store.get_signature_file(
276
to_sf.join(from_sf, version_ids=revs, ignore_missing=True)
277
to_rf = self.to_repository._revision_store.get_revision_file(
279
from_rf = self.from_repository._revision_store.get_revision_file(
281
to_rf.join(from_rf, version_ids=revs)
203
284
class Fetcher(object):
204
"""Pull revisions and texts from one branch to another.
206
This doesn't update the destination's history; that can be done
207
separately if desired.
210
If set, pull only up to this revision_id.
214
last_revision -- if last_revision
215
is given it will be that, otherwise the last revision of
218
count_copied -- number of revisions copied
220
count_weaves -- number of file weaves copied
285
"""Backwards compatibility glue for branch.fetch()."""
287
@deprecated_method(zero_eight)
222
288
def __init__(self, to_branch, from_branch, last_revision=None, pb=None):
223
if to_branch.base == from_branch.base:
224
raise Exception("can't fetch from a branch to itself %s, %s" %
225
(from_branch.base, to_branch.base))
227
self.to_branch = to_branch
228
self.from_branch = from_branch
229
self._last_revision = last_revision
231
self.pb = bzrlib.ui.ui_factory.progress_bar()
234
self.from_branch.lock_read()
236
self.to_branch.lock_write()
240
self.to_branch.unlock()
242
self.from_branch.unlock()
245
self._find_last_revision()
246
repo_fetcher = RepoFetcher(to_repository=self.to_branch.repository,
247
from_repository=self.from_branch.repository,
249
last_revision=self._last_revision)
250
self.failed_revisions = repo_fetcher.failed_revisions
251
self.count_copied = repo_fetcher.count_copied
252
self.count_total = repo_fetcher.count_total
253
self.count_weaves = repo_fetcher.count_weaves
254
self.copied_file_ids = repo_fetcher.copied_file_ids
256
def _find_last_revision(self):
257
"""Find the limiting source revision.
259
Every ancestor of that revision will be merged across.
261
Returns the revision_id, or returns None if there's no history
262
in the source branch."""
263
if self._last_revision:
265
self.pb.update('get source history')
266
from_history = self.from_branch.revision_history()
267
self.pb.update('get destination history')
269
self._last_revision = from_history[-1]
271
# no history in the source branch
272
self._last_revision = NULL_REVISION
289
"""Please see branch.fetch()."""
290
to_branch.fetch(from_branch, last_revision, pb)