1
# Copyright (C) 2008 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Server-side versioned files related request implmentations."""
23
from bzrlib.bzrdir import BzrDir
24
from bzrlib.smart.request import (
25
FailedSmartServerResponse,
26
SuccessfulSmartServerResponse,
28
from bzrlib.smart.repository import SmartServerRepositoryRequest
29
from bzrlib.util import bencode
32
class SmartServerVersionedFilesRequest(SmartServerRepositoryRequest):
33
"""Common base class for Repository requests."""
35
def do(self, path, *args):
36
"""Execute a repository request.
38
All Repository requests take a path to the repository as their first
39
argument. The repository must be at the exact path given by the
40
client - no searching is done.
42
The actual logic is delegated to self.do_repository_request.
44
:param client_path: The path for the repository as received from the
46
:return: A SmartServerResponse from self.do_repository_request().
48
transport = self.transport_from_client_path(path)
49
bzrdir = BzrDir.open_from_transport(transport)
50
# Save the repository for use with do_body.
51
self._repository = bzrdir.open_repository()
52
return self.do_repository_request(self._repository, *args)
54
def do_repository_request(self, repository, vf_name, *args):
55
if vf_name not in ['texts', 'inventories', 'signatures', 'revisions']:
56
return FailedSmartServerResponse(('NoSuchVersionedFile', vf_name))
57
versioned_files = getattr(repository, vf_name)
58
return self.do_versioned_files_request(versioned_files, *args)
60
def do_versioned_files_request(self, versioned_files, *args):
61
"""Override to provide an implementation for a verb."""
64
class SmartServerVersionedFilesInsertRecordStream(SmartServerVersionedFilesRequest):
66
def do_versioned_files_request(self, versioned_files, lock_token):
67
self._repository.lock_write(token=lock_token)
68
self._repository.start_write_group()
69
self.versioned_files = versioned_files
71
def do_chunk(self, stream_chunk):
72
# XXX: we shouldn't rely on one stream_chunk corresponding exactly to a
73
# single serialised record.
74
record = deserialise_record(stream_chunk)
75
# trace.mutter('inserting record %s (kind: %s, parents: %r)',
76
# record.key, record.storage_kind, record.parents)
77
self.versioned_files.insert_record_stream([record])
80
self._repository.commit_write_group()
81
self._repository.unlock()
82
self._repository = self.versioned_files = None
83
return SuccessfulSmartServerResponse(('ok',))
86
from bzrlib.knit import KnitContentFactory
88
def deserialise_record(stream_chunk):
89
struct = bencode.bdecode(stream_chunk)
91
(sha1, storage_kind, key, parents, build_details, bytes) = struct
96
if storage_kind.startswith('knit-'):
97
annotated = bool(storage_kind.startswith('knit-annotated-'))
98
record = KnitContentFactory(key, parents, build_details, sha1, bytes,
100
if record.storage_kind != storage_kind:
101
raise AssertionError(
102
'Reconstructed record kind %r does not match expected kind %r'
103
% (record.storage_kind, storage_kind))
104
elif storage_kind == 'fulltext':
105
record = versionedfile.FulltextContentFactory(
106
key, parents, sha1, bytes)