~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

Merge up bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
157
157
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
158
158
        try:
159
159
            revs = search.get_keys()
160
 
            data_to_fetch = self.from_repository.item_keys_introduced_by(revs, pb)
 
160
            graph = self.from_repository.get_graph()
 
161
            revs = list(graph.iter_topo_order(revs))
 
162
            data_to_fetch = self.from_repository.item_keys_introduced_by(revs,
 
163
                                                                         pb)
161
164
            for knit_kind, file_id, revisions in data_to_fetch:
162
165
                if knit_kind != phase:
163
166
                    phase = knit_kind
214
217
        from_weave = self.from_weaves.get_weave(file_id,
215
218
            self.from_repository.get_transaction())
216
219
        # Fetch all the texts.
217
 
        to_weave.insert_record_stream(from_weave.get_record_stream(required_versions,
218
 
            'topological', False))
 
220
        to_weave.insert_record_stream(from_weave.get_record_stream(
 
221
            required_versions, 'topological', False))
219
222
 
220
223
    def _fetch_inventory_weave(self, revs, pb):
221
224
        pb.update("fetch inventory", 0, 2)
267
270
            except errors.NoSuchRevision:
268
271
                # not signed.
269
272
                pass
270
 
            to_store.add_revision(self.from_repository.get_revision(rev),
271
 
                                  to_txn)
 
273
            self._copy_revision(rev, to_txn)
272
274
            count += 1
273
275
        # fixup inventory if needed: 
274
276
        # this is expensive because we have no inverse index to current ghosts.
276
278
        # so we just-do-it.
277
279
        # FIXME: repository should inform if this is needed.
278
280
        self.to_repository.reconcile()
279
 
    
 
281
 
 
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
 
280
286
 
281
287
class KnitRepoFetcher(RepoFetcher):
282
288
    """This is a knit format repository specific fetcher.
297
303
        # A missing signature is just skipped.
298
304
        to_sf.insert_record_stream(filter_absent(from_sf.get_record_stream(revs,
299
305
            'unordered', False)))
 
306
        self._fetch_just_revision_texts(revs, from_transaction, to_transaction)
 
307
 
 
308
    def _fetch_just_revision_texts(self, version_ids, from_transaction,
 
309
                                   to_transaction):
300
310
        to_rf = self.to_repository._revision_store.get_revision_file(
301
311
            to_transaction)
302
312
        from_rf = self.from_repository._revision_store.get_revision_file(
303
313
            from_transaction)
304
 
        to_rf.insert_record_stream(from_rf.get_record_stream(revs,
 
314
        to_rf.insert_record_stream(from_rf.get_record_stream(version_ids,
305
315
            'topological', False))
306
316
 
307
317
 
339
349
                yield tree
340
350
            revs = revs[100:]
341
351
 
 
352
    def _find_root_ids(self, revs, parent_map, graph):
 
353
        revision_root = {}
 
354
        planned_versions = {}
 
355
        for tree in self.iter_rev_trees(revs):
 
356
            revision_id = tree.inventory.root.revision
 
357
            root_id = tree.get_root_id()
 
358
            planned_versions.setdefault(root_id, []).append(revision_id)
 
359
            revision_root[revision_id] = root_id
 
360
        # Find out which parents we don't already know root ids for
 
361
        parents = set()
 
362
        for revision_parents in parent_map.itervalues():
 
363
            parents.update(revision_parents)
 
364
        parents.difference_update(revision_root.keys() + [NULL_REVISION])
 
365
        # Limit to revisions present in the versionedfile
 
366
        parents = graph.get_parent_map(parents).keys()
 
367
        for tree in self.iter_rev_trees(parents):
 
368
            root_id = tree.get_root_id()
 
369
            revision_root[tree.get_revision_id()] = root_id
 
370
        return revision_root, planned_versions
 
371
 
342
372
    def generate_root_texts(self, revs):
343
373
        """Generate VersionedFiles for all root ids.
344
 
        
 
374
 
345
375
        :param revs: the revisions to include
346
376
        """
347
 
        inventory_weave = self.source.get_inventory_weave()
348
 
        parent_texts = {}
349
 
        versionedfile = {}
350
377
        to_store = self.target.weave_store
351
 
        parent_map = self.source.get_graph().get_parent_map(revs)
352
 
        for tree in self.iter_rev_trees(revs):
353
 
            revision_id = tree.inventory.root.revision
354
 
            root_id = tree.get_root_id()
355
 
            parents = parent_map[revision_id]
356
 
            if parents[0] == NULL_REVISION:
357
 
                parents = ()
358
 
            if root_id not in versionedfile:
359
 
                versionedfile[root_id] = to_store.get_weave_or_empty(root_id,
360
 
                    self.target.get_transaction())
361
 
            _, _, parent_texts[root_id] = versionedfile[root_id].add_lines(
362
 
                revision_id, parents, [], parent_texts)
 
378
        graph = self.source.get_graph()
 
379
        parent_map = graph.get_parent_map(revs)
 
380
        revision_root, planned_versions = self._find_root_ids(
 
381
            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())
 
385
            parent_texts = {}
 
386
            for revision_id in versions:
 
387
                if revision_id in versionedfile:
 
388
                    continue
 
389
                parents = parent_map[revision_id]
 
390
                # We drop revision parents with different file-ids, because
 
391
                # a version cannot have a version with another file-id as its
 
392
                # parent.
 
393
                # When a parent revision is a ghost, we guess that its root id
 
394
                # was unchanged.
 
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]
363
400
 
364
401
    def regenerate_inventory(self, revs):
365
402
        """Generate a new inventory versionedfile in target, convertin data.
373
410
            self.target.add_inventory(tree.get_revision_id(), tree.inventory,
374
411
                                      parents)
375
412
 
 
413
    def fetch_revisions(self, revision_ids):
 
414
        for revision in self.source.get_revisions(revision_ids):
 
415
            self.target.add_revision(revision.revision_id, revision)
 
416
 
376
417
 
377
418
class Model1toKnit2Fetcher(GenericRepoFetcher):
378
419
    """Fetch from a Model1 repository into a Knit2 repository
388
429
 
389
430
    def _fetch_inventory_weave(self, revs, pb):
390
431
        self.helper.regenerate_inventory(revs)
391
 
 
 
432
 
 
433
    def _copy_revision(self, rev, to_txn):
 
434
        self.helper.fetch_revisions([rev])
 
435
 
392
436
 
393
437
class Knit1to2Fetcher(KnitRepoFetcher):
394
438
    """Fetch from a Knit1 repository into a Knit2 repository"""
405
449
    def _fetch_inventory_weave(self, revs, pb):
406
450
        self.helper.regenerate_inventory(revs)
407
451
 
 
452
    def _fetch_just_revision_texts(self, version_ids, from_transaction,
 
453
                                   to_transaction):
 
454
        self.helper.fetch_revisions(version_ids)
 
455
 
408
456
 
409
457
class RemoteToOtherFetcher(GenericRepoFetcher):
410
458