1
# Copyright (C) 2006 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 repository related request implmentations."""
20
from bzrlib import errors
21
from bzrlib.bzrdir import BzrDir
22
from bzrlib.smart.request import SmartServerRequest, SmartServerResponse
25
class SmartServerRepositoryRequest(SmartServerRequest):
26
"""Common base class for Repository requests."""
28
def do(self, path, *args):
29
"""Execute a repository request.
31
The repository must be at the exact path - no searching is done.
33
The actual logic is delegated to self.do_repository_request.
35
:param path: The path for the repository.
36
:return: A smart server from self.do_repository_request().
38
transport = self._backing_transport.clone(path)
39
bzrdir = BzrDir.open_from_transport(transport)
40
repository = bzrdir.open_repository()
41
return self.do_repository_request(repository, *args)
44
class SmartServerRepositoryGetRevisionGraph(SmartServerRepositoryRequest):
46
def do_repository_request(self, repository, revision_id):
47
"""Return the result of repository.get_revision_graph(revision_id).
49
:param repository: The repository to query in.
50
:param revision_id: The utf8 encoded revision_id to get a graph from.
51
:return: A smart server response where the body contains an utf8
52
encoded flattened list of the revision graph.
54
decoded_revision_id = revision_id.decode('utf8')
55
if not decoded_revision_id:
56
decoded_revision_id = None
60
revision_graph = repository.get_revision_graph(decoded_revision_id)
61
except errors.NoSuchRevision:
62
return SmartServerResponse(('nosuchrevision', revision_id))
64
for revision, parents in revision_graph.items():
65
lines.append(' '.join([revision,] + parents))
67
return SmartServerResponse(('ok', ), '\n'.join(lines).encode('utf8'))
70
class SmartServerRequestHasRevision(SmartServerRepositoryRequest):
72
def do_repository_request(self, repository, revision_id):
73
"""Return ok if a specific revision is in the repository at path.
75
:param repository: The repository to query in.
76
:param revision_id: The utf8 encoded revision_id to lookup.
77
:return: A smart server response of ('ok', ) if the revision is
80
decoded_revision_id = revision_id.decode('utf8')
81
if repository.has_revision(decoded_revision_id):
82
return SmartServerResponse(('ok', ))
84
return SmartServerResponse(('no', ))
87
class SmartServerRepositoryGatherStats(SmartServerRepositoryRequest):
89
def do_repository_request(self, repository, revid, committers):
90
"""Return the result of repository.gather_stats().
92
:param repository: The repository to query in.
93
:param revid: utf8 encoded rev id or an empty string to indicate None
94
:param committers: 'yes' or 'no'.
96
:return: A SmartServerResponse ('ok',), a encoded body looking like
99
latestrev: 345.700 3600
103
But containing only fields returned by the gather_stats() call
106
decoded_revision_id = None
108
decoded_revision_id = revid.decode('utf8')
109
if committers == 'yes':
110
decoded_committers = True
112
decoded_committers = None
113
stats = repository.gather_stats(decoded_revision_id, decoded_committers)
116
if stats.has_key('committers'):
117
body += 'committers: %d\n' % stats['committers']
118
if stats.has_key('firstrev'):
119
body += 'firstrev: %.3f %d\n' % stats['firstrev']
120
if stats.has_key('latestrev'):
121
body += 'latestrev: %.3f %d\n' % stats['latestrev']
122
if stats.has_key('revisions'):
123
body += 'revisions: %d\n' % stats['revisions']
124
if stats.has_key('size'):
125
body += 'size: %d\n' % stats['size']
127
return SmartServerResponse(('ok', ), body)
130
class SmartServerRepositoryIsShared(SmartServerRepositoryRequest):
132
def do_repository_request(self, repository):
133
"""Return the result of repository.is_shared().
135
:param repository: The repository to query in.
136
:return: A smart server response of ('yes', ) if the repository is
137
shared, and ('no', ) if it is not.
139
if repository.is_shared():
140
return SmartServerResponse(('yes', ))
142
return SmartServerResponse(('no', ))
145
class SmartServerRepositoryLockWrite(SmartServerRepositoryRequest):
147
def do_repository_request(self, repository, token):
148
# XXX: this probably should not have a token.
152
token = repository.lock_write(token=token)
153
except errors.LockContention, e:
154
return SmartServerResponse(('LockContention',))
155
repository.leave_lock_in_place()
159
return SmartServerResponse(('ok', token))
162
class SmartServerRepositoryUnlock(SmartServerRepositoryRequest):
164
def do_repository_request(self, repository, token):
166
repository.lock_write(token=token)
167
except errors.TokenMismatch, e:
168
return SmartServerResponse(('TokenMismatch',))
169
repository.dont_leave_lock_in_place()
171
return SmartServerResponse(('ok',))