1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
# Copyright (C) 2006 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Server-side repository related request implmentations."""
from bzrlib import errors
from bzrlib.bzrdir import BzrDir
from bzrlib.smart.request import SmartServerRequest, SmartServerResponse
class SmartServerRepositoryRequest(SmartServerRequest):
"""Common base class for Repository requests."""
def do(self, path, *args):
"""Execute a repository request.
The repository must be at the exact path - no searching is done.
The actual logic is delegated to self.do_repository_request.
:param path: The path for the repository.
:return: A smart server from self.do_repository_request().
"""
transport = self._backing_transport.clone(path)
bzrdir = BzrDir.open_from_transport(transport)
repository = bzrdir.open_repository()
return self.do_repository_request(repository, *args)
class SmartServerRepositoryGetRevisionGraph(SmartServerRepositoryRequest):
def do_repository_request(self, repository, revision_id):
"""Return the result of repository.get_revision_graph(revision_id).
:param repository: The repository to query in.
:param revision_id: The utf8 encoded revision_id to get a graph from.
:return: A smart server response where the body contains an utf8
encoded flattened list of the revision graph.
"""
decoded_revision_id = revision_id.decode('utf8')
if not decoded_revision_id:
decoded_revision_id = None
lines = []
try:
revision_graph = repository.get_revision_graph(decoded_revision_id)
except errors.NoSuchRevision:
return SmartServerResponse(('nosuchrevision', revision_id))
for revision, parents in revision_graph.items():
lines.append(' '.join([revision,] + parents))
return SmartServerResponse(('ok', ), '\n'.join(lines).encode('utf8'))
class SmartServerRequestHasRevision(SmartServerRepositoryRequest):
def do_repository_request(self, repository, revision_id):
"""Return ok if a specific revision is in the repository at path.
:param repository: The repository to query in.
:param revision_id: The utf8 encoded revision_id to lookup.
:return: A smart server response of ('ok', ) if the revision is
present.
"""
decoded_revision_id = revision_id.decode('utf8')
if repository.has_revision(decoded_revision_id):
return SmartServerResponse(('ok', ))
else:
return SmartServerResponse(('no', ))
class SmartServerRepositoryGatherStats(SmartServerRepositoryRequest):
def do_repository_request(self, repository, revid, committers):
"""Return the result of repository.gather_stats().
:param repository: The repository to query in.
:param revid: utf8 encoded rev id or an empty string to indicate None
:param committers: 'yes' or 'no'.
:return: A SmartServerResponse ('ok',), a encoded body looking like
committers: 1
firstrev: 1234.230 0
latestrev: 345.700 3600
revisions: 2
size:45
But containing only fields returned by the gather_stats() call
"""
if revid == '':
decoded_revision_id = None
else:
decoded_revision_id = revid.decode('utf8')
if committers == 'yes':
decoded_committers = True
else:
decoded_committers = None
stats = repository.gather_stats(decoded_revision_id, decoded_committers)
body = ''
if stats.has_key('committers'):
body += 'committers: %d\n' % stats['committers']
if stats.has_key('firstrev'):
body += 'firstrev: %.3f %d\n' % stats['firstrev']
if stats.has_key('latestrev'):
body += 'latestrev: %.3f %d\n' % stats['latestrev']
if stats.has_key('revisions'):
body += 'revisions: %d\n' % stats['revisions']
if stats.has_key('size'):
body += 'size: %d\n' % stats['size']
return SmartServerResponse(('ok', ), body)
class SmartServerRepositoryIsShared(SmartServerRepositoryRequest):
def do_repository_request(self, repository):
"""Return the result of repository.is_shared().
:param repository: The repository to query in.
:return: A smart server response of ('yes', ) if the repository is
shared, and ('no', ) if it is not.
"""
if repository.is_shared():
return SmartServerResponse(('yes', ))
else:
return SmartServerResponse(('no', ))
class SmartServerRepositoryLockWrite(SmartServerRepositoryRequest):
def do_repository_request(self, repository, token):
# XXX: this probably should not have a token.
if token == '':
token = None
try:
token = repository.lock_write(token=token)
except errors.LockContention, e:
return SmartServerResponse(('LockContention',))
repository.leave_lock_in_place()
repository.unlock()
if token is None:
token = ''
return SmartServerResponse(('ok', token))
class SmartServerRepositoryUnlock(SmartServerRepositoryRequest):
def do_repository_request(self, repository, token):
try:
repository.lock_write(token=token)
except errors.TokenMismatch, e:
return SmartServerResponse(('TokenMismatch',))
repository.dont_leave_lock_in_place()
repository.unlock()
return SmartServerResponse(('ok',))
|