~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bundle/serializer/v4.py

merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
144
144
    body
145
145
    """
146
146
 
147
 
    def __init__(self, fileobj):
 
147
    def __init__(self, fileobj, stream_input=True):
 
148
        """Constructor
 
149
 
 
150
        :param fileobj: a file containing a bzip-encoded container
 
151
        :param stream_input: If True, the BundleReader stream input rather than
 
152
            reading it all into memory at once.  Reading it into memory all at
 
153
            once is (currently) faster.
 
154
        """
148
155
        line = fileobj.readline()
149
156
        if line != '\n':
150
157
            fileobj.readline()
151
158
        self.patch_lines = []
152
 
        self._container = pack.ContainerReader(
153
 
            iterablefile.IterableFile(self.iter_decode(fileobj)))
 
159
        if stream_input:
 
160
            source_file = iterablefile.IterableFile(self.iter_decode(fileobj))
 
161
        else:
 
162
            source_file = StringIO(bz2.decompress(fileobj.read()))
 
163
        self._container = pack.ContainerReader(source_file)
154
164
 
155
165
    @staticmethod
156
166
    def iter_decode(fileobj):
382
392
    def install(self, repository):
383
393
        return self.install_revisions(repository)
384
394
 
385
 
    def install_revisions(self, repository):
386
 
        """Install this bundle's revisions into the specified repository"""
 
395
    def install_revisions(self, repository, stream_input=True):
 
396
        """Install this bundle's revisions into the specified repository
 
397
 
 
398
        :param target_repo: The repository to install into
 
399
        :param stream_input: If True, will stream input rather than reading it
 
400
            all into memory at once.  Reading it into memory all at once is
 
401
            (currently) faster.
 
402
        """
387
403
        repository.lock_write()
388
404
        try:
389
 
            ri = RevisionInstaller(self.get_bundle_reader(),
 
405
            ri = RevisionInstaller(self.get_bundle_reader(stream_input),
390
406
                                   self._serializer, repository)
391
407
            return ri.install()
392
408
        finally:
399
415
        """
400
416
        return None, self.target, 'inapplicable'
401
417
 
402
 
    def get_bundle_reader(self):
 
418
    def get_bundle_reader(self, stream_input=True):
 
419
        """Return a new BundleReader for the associated bundle
 
420
 
 
421
        :param stream_input: If True, the BundleReader stream input rather than
 
422
            reading it all into memory at once.  Reading it into memory all at
 
423
            once is (currently) faster.
 
424
        """
403
425
        self._fileobj.seek(0)
404
 
        return BundleReader(self._fileobj)
 
426
        return BundleReader(self._fileobj, stream_input)
405
427
 
406
428
    def _get_real_revisions(self):
407
429
        if self.__real_revisions is None:
448
470
        current_file = None
449
471
        current_versionedfile = None
450
472
        pending_file_records = []
 
473
        inventory_vf = None
 
474
        pending_inventory_records = []
451
475
        added_inv = set()
452
476
        target_revision = None
453
477
        for bytes, metadata, repo_kind, revision_id, file_id in\
455
479
            if repo_kind == 'info':
456
480
                assert self._info is None
457
481
                self._handle_info(metadata)
458
 
            if repo_kind != 'file':
 
482
            if ((repo_kind, file_id) != ('file', current_file) and
 
483
                len(pending_file_records) > 0):
459
484
                self._install_mp_records(current_versionedfile,
460
485
                    pending_file_records)
461
486
                current_file = None
462
487
                current_versionedfile = None
463
488
                pending_file_records = []
464
 
                if repo_kind == 'inventory':
465
 
                    self._install_inventory(revision_id, metadata, bytes)
466
 
                if repo_kind == 'revision':
467
 
                    target_revision = revision_id
468
 
                    self._install_revision(revision_id, metadata, bytes)
469
 
                if repo_kind == 'signature':
470
 
                    self._install_signature(revision_id, metadata, bytes)
 
489
            if len(pending_inventory_records) > 0 and repo_kind != 'inventory':
 
490
                self._install_inventory_records(inventory_vf,
 
491
                                                pending_inventory_records)
 
492
                pending_inventory_records = []
 
493
            if repo_kind == 'inventory':
 
494
                if inventory_vf is None:
 
495
                    inventory_vf = self._repository.get_inventory_weave()
 
496
                if revision_id not in inventory_vf:
 
497
                    pending_inventory_records.append((revision_id, metadata,
 
498
                                                      bytes))
 
499
            if repo_kind == 'revision':
 
500
                target_revision = revision_id
 
501
                self._install_revision(revision_id, metadata, bytes)
 
502
            if repo_kind == 'signature':
 
503
                self._install_signature(revision_id, metadata, bytes)
471
504
            if repo_kind == 'file':
472
 
                if file_id != current_file:
473
 
                    self._install_mp_records(current_versionedfile,
474
 
                        pending_file_records)
475
 
                    current_file = file_id
 
505
                current_file = file_id
 
506
                if current_versionedfile is None:
476
507
                    current_versionedfile = \
477
508
                        self._repository.weave_store.get_weave_or_empty(
478
509
                        file_id, self._repository.get_transaction())
501
532
                      records if r not in versionedfile]
502
533
        versionedfile.add_mpdiffs(vf_records)
503
534
 
504
 
    def _install_inventory(self, revision_id, metadata, text):
505
 
        vf = self._repository.get_inventory_weave()
506
 
        if revision_id in vf:
507
 
            return
508
 
        parent_ids = metadata['parents']
 
535
    def _install_inventory_records(self, vf, records):
509
536
        if self._info['serializer'] == self._repository._serializer.format_num:
510
 
            return self._install_mp_records(vf, [(revision_id, metadata,
511
 
                                                  text)])
512
 
        parents = [self._repository.get_inventory(p)
513
 
                   for p in parent_ids]
514
 
        parent_texts = [self._source_serializer.write_inventory_to_string(p)
515
 
                        for p in parents]
516
 
        target_lines = multiparent.MultiParent.from_patch(text).to_lines(
517
 
            parent_texts)
518
 
        sha1 = osutils.sha_strings(target_lines)
519
 
        if sha1 != metadata['sha1']:
520
 
            raise errors.BadBundle("Can't convert to target format")
521
 
        target_inv = self._source_serializer.read_inventory_from_string(
522
 
            ''.join(target_lines))
523
 
        self._handle_root(target_inv, parent_ids)
524
 
        try:
525
 
            self._repository.add_inventory(revision_id, target_inv, parent_ids)
526
 
        except errors.UnsupportedInventoryKind:
527
 
            raise errors.IncompatibleRevision(repr(self._repository))
 
537
            return self._install_mp_records(vf, records)
 
538
        for revision_id, metadata, bytes in records:
 
539
            parent_ids = metadata['parents']
 
540
            parents = [self._repository.get_inventory(p)
 
541
                       for p in parent_ids]
 
542
            p_texts = [self._source_serializer.write_inventory_to_string(p)
 
543
                       for p in parents]
 
544
            target_lines = multiparent.MultiParent.from_patch(bytes).to_lines(
 
545
                p_texts)
 
546
            sha1 = osutils.sha_strings(target_lines)
 
547
            if sha1 != metadata['sha1']:
 
548
                raise errors.BadBundle("Can't convert to target format")
 
549
            target_inv = self._source_serializer.read_inventory_from_string(
 
550
                ''.join(target_lines))
 
551
            self._handle_root(target_inv, parent_ids)
 
552
            try:
 
553
                self._repository.add_inventory(revision_id, target_inv,
 
554
                                               parent_ids)
 
555
            except errors.UnsupportedInventoryKind:
 
556
                raise errors.IncompatibleRevision(repr(self._repository))
528
557
 
529
558
    def _handle_root(self, target_inv, parent_ids):
530
559
        revision_id = target_inv.revision_id