~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/repository.py

  • Committer: John Arbash Meinel
  • Date: 2007-04-26 18:53:33 UTC
  • mfrom: (2465 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2466.
  • Revision ID: john@arbash-meinel.com-20070426185333-i1xlyaeyf049kdxc
[merge] bzr.dev 2465

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
 
from bzrlib.smart.request import SmartServerRequest, SmartServerResponse
 
25
from bzrlib.smart.request import (
 
26
    FailedSmartServerResponse,
 
27
    SmartServerRequest,
 
28
    SuccessfulSmartServerResponse,
 
29
    )
23
30
 
24
31
 
25
32
class SmartServerRepositoryRequest(SmartServerRequest):
61
68
            # Note that we return an empty body, rather than omitting the body.
62
69
            # This way the client knows that it can always expect to find a body
63
70
            # in the response for this method, even in the error case.
64
 
            return SmartServerResponse(('nosuchrevision', revision_id), '')
 
71
            return FailedSmartServerResponse(('nosuchrevision', revision_id), '')
65
72
 
66
73
        for revision, parents in revision_graph.items():
67
74
            lines.append(' '.join([revision,] + parents))
68
75
 
69
 
        return SmartServerResponse(('ok', ), '\n'.join(lines))
 
76
        return SuccessfulSmartServerResponse(('ok', ), '\n'.join(lines))
70
77
 
71
78
 
72
79
class SmartServerRequestHasRevision(SmartServerRepositoryRequest):
80
87
            present.
81
88
        """
82
89
        if repository.has_revision(revision_id):
83
 
            return SmartServerResponse(('yes', ))
 
90
            return SuccessfulSmartServerResponse(('yes', ))
84
91
        else:
85
 
            return SmartServerResponse(('no', ))
 
92
            return SuccessfulSmartServerResponse(('no', ))
86
93
 
87
94
 
88
95
class SmartServerRepositoryGatherStats(SmartServerRepositoryRequest):
125
132
        if stats.has_key('size'):
126
133
            body += 'size: %d\n' % stats['size']
127
134
 
128
 
        return SmartServerResponse(('ok', ), body)
 
135
        return SuccessfulSmartServerResponse(('ok', ), body)
129
136
 
130
137
 
131
138
class SmartServerRepositoryIsShared(SmartServerRepositoryRequest):
138
145
            shared, and ('no', ) if it is not.
139
146
        """
140
147
        if repository.is_shared():
141
 
            return SmartServerResponse(('yes', ))
 
148
            return SuccessfulSmartServerResponse(('yes', ))
142
149
        else:
143
 
            return SmartServerResponse(('no', ))
 
150
            return SuccessfulSmartServerResponse(('no', ))
144
151
 
145
152
 
146
153
class SmartServerRepositoryLockWrite(SmartServerRepositoryRequest):
152
159
        try:
153
160
            token = repository.lock_write(token=token)
154
161
        except errors.LockContention, e:
155
 
            return SmartServerResponse(('LockContention',))
 
162
            return FailedSmartServerResponse(('LockContention',))
156
163
        except errors.UnlockableTransport:
157
 
            return SmartServerResponse(('UnlockableTransport',))
 
164
            return FailedSmartServerResponse(('UnlockableTransport',))
158
165
        repository.leave_lock_in_place()
159
166
        repository.unlock()
160
167
        if token is None:
161
168
            token = ''
162
 
        return SmartServerResponse(('ok', token))
 
169
        return SuccessfulSmartServerResponse(('ok', token))
163
170
 
164
171
 
165
172
class SmartServerRepositoryUnlock(SmartServerRepositoryRequest):
168
175
        try:
169
176
            repository.lock_write(token=token)
170
177
        except errors.TokenMismatch, e:
171
 
            return SmartServerResponse(('TokenMismatch',))
 
178
            return FailedSmartServerResponse(('TokenMismatch',))
172
179
        repository.dont_leave_lock_in_place()
173
180
        repository.unlock()
174
 
        return SmartServerResponse(('ok',))
175
 
 
 
181
        return SuccessfulSmartServerResponse(('ok',))
 
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()