170
172
pb = bzrlib.ui.ui_factory.nested_progress_bar()
171
173
if knit_kind == "file":
172
self._fetch_weave_text(file_id, revisions)
174
# Accumulate file texts
175
text_keys.extend([(file_id, revision) for revision in
173
177
elif knit_kind == "inventory":
178
# Now copy the file texts.
179
to_texts = self.to_repository.texts
180
from_texts = self.from_repository.texts
181
to_texts.insert_record_stream(from_texts.get_record_stream(
182
text_keys, 'topological', False))
183
# Cause an error if a text occurs after we have done the
174
186
# Before we process the inventory we generate the root
175
187
# texts (if necessary) so that the inventories references
177
189
self._generate_root_texts(revs)
178
190
# NB: This currently reopens the inventory weave in source;
179
# using a full get_data_stream instead would avoid this.
191
# using a single stream interface instead would avoid this.
180
192
self._fetch_inventory_weave(revs, pb)
181
193
elif knit_kind == "signatures":
182
194
# Nothing to do here; this will be taken care of when
209
221
self.from_repository, self._last_revision,
210
222
find_ghosts=self.find_ghosts)
211
223
except errors.NoSuchRevision, e:
224
import pdb;pdb.set_trace()
212
225
raise InstallFailed([self._last_revision])
214
def _fetch_weave_text(self, file_id, required_versions):
215
to_weave = self.to_weaves.get_weave_or_empty(file_id,
216
self.to_repository.get_transaction())
217
from_weave = self.from_weaves.get_weave(file_id,
218
self.from_repository.get_transaction())
219
# Fetch all the texts.
220
to_weave.insert_record_stream(from_weave.get_record_stream(
221
required_versions, 'topological', False))
223
227
def _fetch_inventory_weave(self, revs, pb):
224
228
pb.update("fetch inventory", 0, 2)
225
to_weave = self.to_repository.get_inventory_weave()
229
to_weave = self.to_repository.inventories
226
230
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
228
232
# just merge, this is optimisable and its means we don't
229
233
# copy unreferenced data such as not-needed inventories.
230
234
pb.update("fetch inventory", 1, 3)
231
from_weave = self.from_repository.get_inventory_weave()
235
from_weave = self.from_repository.inventories
232
236
pb.update("fetch inventory", 2, 3)
233
237
# we fetch only the referenced inventories because we do not
234
238
# know for unselected inventories whether all their required
235
239
# texts are present in the other repository - it could be
237
to_weave.insert_record_stream(from_weave.get_record_stream(revs,
241
to_weave.insert_record_stream(from_weave.get_record_stream(
242
[(rev_id,) for rev_id in revs],
238
243
'topological', False))
240
245
child_pb.finished()
259
264
def _fetch_revision_texts(self, revs, pb):
260
265
"""Fetch revision object texts"""
261
to_txn = self.to_transaction = self.to_repository.get_transaction()
263
267
total = len(revs)
264
to_store = self.to_repository._revision_store
266
269
pb.update('copying revisions', count, total)
268
271
sig_text = self.from_repository.get_signature_text(rev)
269
to_store.add_revision_signature_text(rev, sig_text, to_txn)
272
self.to_repository.add_signature_text(rev, sig_text)
270
273
except errors.NoSuchRevision:
273
self._copy_revision(rev, to_txn)
276
self._copy_revision(rev)
275
278
# fixup inventory if needed:
276
279
# this is expensive because we have no inverse index to current ghosts.
279
282
# FIXME: repository should inform if this is needed.
280
283
self.to_repository.reconcile()
282
def _copy_revision(self, rev, to_txn):
283
to_store = self.to_repository._revision_store
284
to_store.add_revision(self.from_repository.get_revision(rev), to_txn)
285
def _copy_revision(self, rev_id):
286
rev = self.from_repository.get_revision(rev_id)
287
self.to_repository.add_revision(rev_id, rev)
287
290
class KnitRepoFetcher(RepoFetcher):
295
298
def _fetch_revision_texts(self, revs, pb):
296
299
# may need to be a InterRevisionStore call here.
297
from_transaction = self.from_repository.get_transaction()
298
to_transaction = self.to_repository.get_transaction()
299
to_sf = self.to_repository._revision_store.get_signature_file(
301
from_sf = self.from_repository._revision_store.get_signature_file(
300
to_sf = self.to_repository.signatures
301
from_sf = self.from_repository.signatures
303
302
# A missing signature is just skipped.
304
to_sf.insert_record_stream(filter_absent(from_sf.get_record_stream(revs,
303
to_sf.insert_record_stream(filter_absent(from_sf.get_record_stream(
304
[(rev_id,) for rev_id in revs],
305
305
'unordered', False)))
306
self._fetch_just_revision_texts(revs, from_transaction, to_transaction)
306
self._fetch_just_revision_texts(revs)
308
def _fetch_just_revision_texts(self, version_ids, from_transaction,
310
to_rf = self.to_repository._revision_store.get_revision_file(
312
from_rf = self.from_repository._revision_store.get_revision_file(
314
to_rf.insert_record_stream(from_rf.get_record_stream(version_ids,
308
def _fetch_just_revision_texts(self, version_ids):
309
to_rf = self.to_repository.revisions
310
from_rf = self.from_repository.revisions
311
to_rf.insert_record_stream(from_rf.get_record_stream(
312
[(rev_id,) for rev_id in version_ids],
315
313
'topological', False))
375
373
:param revs: the revisions to include
377
to_store = self.target.weave_store
375
to_texts = self.target.texts
378
376
graph = self.source.get_graph()
379
377
parent_map = graph.get_parent_map(revs)
380
revision_root, planned_versions = self._find_root_ids(
378
rev_order = topo_sort(parent_map)
379
rev_id_to_root_id, root_id_to_rev_ids = self._find_root_ids(
381
380
revs, parent_map, graph)
382
for root_id, versions in planned_versions.iteritems():
383
versionedfile = to_store.get_weave_or_empty(root_id,
384
self.target.get_transaction())
386
for revision_id in versions:
387
if revision_id in versionedfile:
389
parents = parent_map[revision_id]
381
root_id_order = [(rev_id_to_root_id[rev_id], rev_id) for rev_id in
383
# Guaranteed stable, this groups all the file id operations together
384
# retaining topological order within the revisions of a file id.
385
# File id splits and joins would invalidate this, but they don't exist
386
# yet, and are unlikely to in non-rich-root environments anyway.
387
root_id_order.sort(key=operator.itemgetter(0))
388
# Create a record stream containing the roots to create.
390
for root_id, rev_id in root_id_order:
391
key = (root_id, rev_id)
392
rev_parents = parent_map[rev_id]
390
393
# We drop revision parents with different file-ids, because
391
# a version cannot have a version with another file-id as its
394
# that represents a rename of the root to a different location
395
# - its not actually a parent for us. (We could look for that
396
# file id in the revision tree at considerably more expense,
397
# but for now this is sufficient (and reconcile will catch and
398
# correct this anyway).
393
399
# When a parent revision is a ghost, we guess that its root id
395
parents = tuple(p for p in parents if p != NULL_REVISION
396
and revision_root.get(p, root_id) == root_id)
397
result = versionedfile.add_lines_with_ghosts(
398
revision_id, parents, [], parent_texts)
399
parent_texts[revision_id] = result[2]
400
# was unchanged (rather than trimming it from the parent list).
401
parent_keys = tuple((root_id, parent) for parent in rev_parents
402
if parent != NULL_REVISION and
403
rev_id_to_root_id.get(parent, root_id) == root_id)
404
yield FulltextContentFactory(key, parent_keys, None, '')
405
to_texts.insert_record_stream(yield_roots())
401
407
def regenerate_inventory(self, revs):
402
408
"""Generate a new inventory versionedfile in target, convertin data.
449
455
def _fetch_inventory_weave(self, revs, pb):
450
456
self.helper.regenerate_inventory(revs)
452
def _fetch_just_revision_texts(self, version_ids, from_transaction,
458
def _fetch_just_revision_texts(self, version_ids):
454
459
self.helper.fetch_revisions(version_ids)
457
class RemoteToOtherFetcher(GenericRepoFetcher):
459
def _fetch_everything_for_search(self, search, pp):
460
data_stream = self.from_repository.get_data_stream_for_search(search)
461
self.to_repository.insert_data_stream(data_stream)