~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-04-26 08:34:14 UTC
  • mfrom: (2018.18.25 hpss-faster-copy)
  • Revision ID: pqm@pqm.ubuntu.com-20070426083414-8xgtmyk47txgquaw
Repository.tarball operation to speed initial checkouts

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
from bzrlib.lockable_files import LockableFiles
29
29
from bzrlib.revision import NULL_REVISION
30
30
from bzrlib.smart import client, vfs
 
31
from bzrlib.trace import note
31
32
 
32
33
# Note: RemoteBzrDirFormat is in bzrdir.py
33
34
 
431
432
        self._ensure_real()
432
433
        return self._real_repository.break_lock()
433
434
 
 
435
    def _get_tarball(self, compression):
 
436
        """Return a TemporaryFile containing a repository tarball"""
 
437
        import tempfile
 
438
        path = self.bzrdir._path_for_remote_call(self._client)
 
439
        response, protocol = self._client.call_expecting_body(
 
440
            'Repository.tarball', path, compression)
 
441
        assert response[0] in ('ok', 'failure'), \
 
442
            'unexpected response code %s' % (response,)
 
443
        if response[0] == 'ok':
 
444
            # Extract the tarball and return it
 
445
            t = tempfile.NamedTemporaryFile()
 
446
            # TODO: rpc layer should read directly into it...
 
447
            t.write(protocol.read_body_bytes())
 
448
            t.seek(0)
 
449
            return t
 
450
        else:
 
451
            raise errors.SmartServerError(error_code=response)
 
452
 
 
453
    def sprout(self, to_bzrdir, revision_id=None):
 
454
        # TODO: Option to control what format is created?
 
455
        to_repo = to_bzrdir.create_repository()
 
456
        self._copy_repository_tarball(to_repo, revision_id)
 
457
        return to_repo
 
458
 
434
459
    ### These methods are just thin shims to the VFS object for now.
435
460
 
436
461
    def revision_tree(self, revision_id):
571
596
        return self._real_repository.copy_content_into(
572
597
            destination, revision_id=revision_id)
573
598
 
 
599
    def _copy_repository_tarball(self, destination, revision_id=None):
 
600
        # get a tarball of the remote repository, and copy from that into the
 
601
        # destination
 
602
        from bzrlib import osutils
 
603
        import tarfile
 
604
        import tempfile
 
605
        from StringIO import StringIO
 
606
        # TODO: Maybe a progress bar while streaming the tarball?
 
607
        note("Copying repository content as tarball...")
 
608
        tar_file = self._get_tarball('bz2')
 
609
        try:
 
610
            tar = tarfile.open('repository', fileobj=tar_file,
 
611
                mode='r|bz2')
 
612
            tmpdir = tempfile.mkdtemp()
 
613
            try:
 
614
                _extract_tar(tar, tmpdir)
 
615
                tmp_bzrdir = BzrDir.open(tmpdir)
 
616
                tmp_repo = tmp_bzrdir.open_repository()
 
617
                tmp_repo.copy_content_into(destination, revision_id)
 
618
            finally:
 
619
                osutils.rmtree(tmpdir)
 
620
        finally:
 
621
            tar_file.close()
 
622
        # TODO: if the server doesn't support this operation, maybe do it the
 
623
        # slow way using the _real_repository?
 
624
        #
 
625
        # TODO: Suggestion from john: using external tar is much faster than
 
626
        # python's tarfile library, but it may not work on windows.
 
627
 
574
628
    def set_make_working_trees(self, new_value):
575
629
        raise NotImplementedError(self.set_make_working_trees)
576
630
 
927
981
        # format, because RemoteBranches can't be created at arbitrary URLs.
928
982
        # XXX: if to_bzrdir is a RemoteBranch, this should perhaps do
929
983
        # to_bzrdir.create_branch...
930
 
        self._ensure_real()
931
984
        result = branch.BranchFormat.get_default_format().initialize(to_bzrdir)
932
 
        self._real_branch.copy_content_into(result, revision_id=revision_id)
 
985
        self.copy_content_into(result, revision_id=revision_id)
933
986
        result.set_parent(self.bzrdir.root_transport.base)
934
987
        return result
935
988
 
991
1044
            self._branch_data_config = TreeConfig(self.branch._real_branch)
992
1045
        return self._branch_data_config
993
1046
 
 
1047
 
 
1048
def _extract_tar(tar, to_dir):
 
1049
    """Extract all the contents of a tarfile object.
 
1050
 
 
1051
    A replacement for extractall, which is not present in python2.4
 
1052
    """
 
1053
    for tarinfo in tar:
 
1054
        tar.extract(tarinfo, to_dir)