~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/repository.py

Merge tarball branch that's already with PQM, resolving conflicts.

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
177
180
        repository.unlock()
178
181
        return SuccessfulSmartServerResponse(('ok',))
179
182
 
 
183
 
 
184
class SmartServerRepositoryTarball(SmartServerRepositoryRequest):
 
185
    """Get the raw repository files as a tarball.
 
186
 
 
187
    The returned tarball contains a .bzr control directory which in turn
 
188
    contains a repository.
 
189
    
 
190
    This takes one parameter, compression, which currently must be 
 
191
    "", "gz", or "bz2".
 
192
 
 
193
    This is used to implement the Repository.copy_content_into operation.
 
194
    """
 
195
 
 
196
    def do_repository_request(self, repository, compression):
 
197
        from bzrlib import osutils
 
198
        repo_transport = repository.control_files._transport
 
199
        tmp_dirname, tmp_repo = self._copy_to_tempdir(repository)
 
200
        try:
 
201
            controldir_name = tmp_dirname + '/.bzr'
 
202
            return self._tarfile_response(controldir_name, compression)
 
203
        finally:
 
204
            osutils.rmtree(tmp_dirname)
 
205
 
 
206
    def _copy_to_tempdir(self, from_repo):
 
207
        tmp_dirname = tempfile.mkdtemp(prefix='tmpbzrclone')
 
208
        tmp_bzrdir = from_repo.bzrdir._format.initialize(tmp_dirname)
 
209
        tmp_repo = from_repo._format.initialize(tmp_bzrdir)
 
210
        from_repo.copy_content_into(tmp_repo)
 
211
        return tmp_dirname, tmp_repo
 
212
 
 
213
    def _tarfile_response(self, tmp_dirname, compression):
 
214
        temp = tempfile.NamedTemporaryFile()
 
215
        try:
 
216
            self._tarball_of_dir(tmp_dirname, compression, temp.name)
 
217
            # all finished; write the tempfile out to the network
 
218
            temp.seek(0)
 
219
            return SuccessfulSmartServerResponse(('ok',), temp.read())
 
220
            # FIXME: Don't read the whole thing into memory here; rather stream it
 
221
            # out from the file onto the network. mbp 20070411
 
222
        finally:
 
223
            temp.close()
 
224
 
 
225
    def _tarball_of_dir(self, dirname, compression, tarfile_name):
 
226
        tarball = tarfile.open(tarfile_name, mode='w:' + compression)
 
227
        try:
 
228
            # The tarball module only accepts ascii names, and (i guess)
 
229
            # packs them with their 8bit names.  We know all the files
 
230
            # within the repository have ASCII names so the should be safe
 
231
            # to pack in.
 
232
            dirname = dirname.encode(sys.getfilesystemencoding())
 
233
            # python's tarball module includes the whole path by default so
 
234
            # override it
 
235
            assert dirname.endswith('.bzr')
 
236
            tarball.add(dirname, '.bzr') # recursive by default
 
237
        finally:
 
238
            tarball.close()