~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/repository.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:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006, 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""Server-side repository related request implmentations."""
18
18
 
 
19
import sys
 
20
import tempfile
 
21
import tarfile
19
22
 
20
23
from bzrlib import errors
21
24
from bzrlib.bzrdir import BzrDir
22
25
from bzrlib.smart.request import SmartServerRequest, SmartServerResponse
 
26
from bzrlib.transport.local import LocalTransport
23
27
 
24
28
 
25
29
class SmartServerRepositoryRequest(SmartServerRequest):
173
177
        repository.unlock()
174
178
        return SmartServerResponse(('ok',))
175
179
 
 
180
 
 
181
class SmartServerRepositoryTarball(SmartServerRepositoryRequest):
 
182
    """Get the raw repository files as a tarball.
 
183
 
 
184
    The returned tarball contains a .bzr control directory which in turn
 
185
    contains a repository.
 
186
    
 
187
    This takes one parameter, compression, which currently must be 
 
188
    "", "gz", or "bz2".
 
189
 
 
190
    This is used to implement the Repository.copy_content_into operation.
 
191
    """
 
192
 
 
193
    def do_repository_request(self, repository, compression):
 
194
        from bzrlib import osutils
 
195
        repo_transport = repository.control_files._transport
 
196
        tmp_dirname, tmp_repo = self._copy_to_tempdir(repository)
 
197
        try:
 
198
            controldir_name = tmp_dirname + '/.bzr'
 
199
            return self._tarfile_response(controldir_name, compression)
 
200
        finally:
 
201
            osutils.rmtree(tmp_dirname)
 
202
 
 
203
    def _copy_to_tempdir(self, from_repo):
 
204
        tmp_dirname = tempfile.mkdtemp(prefix='tmpbzrclone')
 
205
        tmp_bzrdir = from_repo.bzrdir._format.initialize(tmp_dirname)
 
206
        tmp_repo = from_repo._format.initialize(tmp_bzrdir)
 
207
        from_repo.copy_content_into(tmp_repo)
 
208
        return tmp_dirname, tmp_repo
 
209
 
 
210
    def _tarfile_response(self, tmp_dirname, compression):
 
211
        temp = tempfile.NamedTemporaryFile()
 
212
        try:
 
213
            self._tarball_of_dir(tmp_dirname, compression, temp.name)
 
214
            # all finished; write the tempfile out to the network
 
215
            temp.seek(0)
 
216
            return SmartServerResponse(('ok',), temp.read())
 
217
            # FIXME: Don't read the whole thing into memory here; rather stream it
 
218
            # out from the file onto the network. mbp 20070411
 
219
        finally:
 
220
            temp.close()
 
221
 
 
222
    def _tarball_of_dir(self, dirname, compression, tarfile_name):
 
223
        tarball = tarfile.open(tarfile_name, mode='w:' + compression)
 
224
        try:
 
225
            # The tarball module only accepts ascii names, and (i guess)
 
226
            # packs them with their 8bit names.  We know all the files
 
227
            # within the repository have ASCII names so the should be safe
 
228
            # to pack in.
 
229
            dirname = dirname.encode(sys.getfilesystemencoding())
 
230
            # python's tarball module includes the whole path by default so
 
231
            # override it
 
232
            assert dirname.endswith('.bzr')
 
233
            tarball.add(dirname, '.bzr') # recursive by default
 
234
        finally:
 
235
            tarball.close()