78
73
branch.repository.unlock()
81
class SmartServerBranchBreakLock(SmartServerBranchRequest):
83
def do_with_branch(self, branch):
84
"""Break a branch lock.
87
return SuccessfulSmartServerResponse(('ok', ), )
90
76
class SmartServerBranchGetConfigFile(SmartServerBranchRequest):
92
78
def do_with_branch(self, branch):
93
"""Return the content of branch.conf
79
"""Return the content of branch.control_files.get('branch.conf').
95
81
The body is not utf8 decoded - its the literal bytestream from disk.
83
# This was at one time called by RemoteBranchLockableFiles
84
# intercepting access to this file; as of 1.5 it is not called by the
85
# client but retained for compatibility. It may be called again to
86
# allow the client to get the configuration without needing vfs
98
content = branch.control_transport.get_bytes('branch.conf')
89
content = branch.control_files.get('branch.conf').read()
99
90
except errors.NoSuchFile:
101
92
return SuccessfulSmartServerResponse( ('ok', ), content)
104
class SmartServerBranchPutConfigFile(SmartServerBranchRequest):
105
"""Set the configuration data for a branch.
110
def do_with_branch(self, branch, branch_token, repo_token):
111
"""Set the content of branch.conf.
113
The body is not utf8 decoded - its the literal bytestream for disk.
115
self._branch = branch
116
self._branch_token = branch_token
117
self._repo_token = repo_token
118
# Signal we want a body
121
def do_body(self, body_bytes):
122
self._branch.repository.lock_write(token=self._repo_token)
124
self._branch.lock_write(token=self._branch_token)
126
self._branch.control_transport.put_bytes(
127
'branch.conf', body_bytes)
129
self._branch.unlock()
131
self._branch.repository.unlock()
132
return SuccessfulSmartServerResponse(('ok', ))
135
class SmartServerBranchGetParent(SmartServerBranchRequest):
137
def do_with_branch(self, branch):
138
"""Return the parent of branch."""
139
parent = branch._get_parent_location() or ''
140
return SuccessfulSmartServerResponse((parent,))
143
class SmartServerBranchGetTagsBytes(SmartServerBranchRequest):
145
def do_with_branch(self, branch):
146
"""Return the _get_tags_bytes for a branch."""
147
bytes = branch._get_tags_bytes()
148
return SuccessfulSmartServerResponse((bytes,))
151
class SmartServerBranchSetTagsBytes(SmartServerLockedBranchRequest):
153
def __init__(self, backing_transport, root_client_path='/', jail_root=None):
154
SmartServerLockedBranchRequest.__init__(
155
self, backing_transport, root_client_path, jail_root)
158
def do_with_locked_branch(self, branch):
159
"""Call _set_tags_bytes for a branch.
163
# We need to keep this branch locked until we get a body with the tags
166
self.branch.lock_write()
169
def do_body(self, bytes):
170
self.branch._set_tags_bytes(bytes)
171
return SuccessfulSmartServerResponse(())
174
# TODO: this request shouldn't have to do this housekeeping manually.
175
# Some of this logic probably belongs in a base class.
177
# We never acquired the branch successfully in the first place, so
178
# there's nothing more to do.
181
return SmartServerLockedBranchRequest.do_end(self)
183
# Only try unlocking if we locked successfully in the first place
187
class SmartServerBranchHeadsToFetch(SmartServerBranchRequest):
189
def do_with_branch(self, branch):
190
"""Return the heads-to-fetch for a Branch as two bencoded lists.
192
See Branch.heads_to_fetch.
196
must_fetch, if_present_fetch = branch.heads_to_fetch()
197
return SuccessfulSmartServerResponse(
198
(list(must_fetch), list(if_present_fetch)))
201
class SmartServerBranchRequestGetStackedOnURL(SmartServerBranchRequest):
203
def do_with_branch(self, branch):
204
stacked_on_url = branch.get_stacked_on_url()
205
return SuccessfulSmartServerResponse(('ok', stacked_on_url))
208
95
class SmartServerRequestRevisionHistory(SmartServerBranchRequest):
210
97
def do_with_branch(self, branch):
213
100
The revision list is returned as the body content,
214
101
with each revision utf8 encoded and \x00 joined.
218
graph = branch.repository.get_graph()
219
stop_revisions = (None, _mod_revision.NULL_REVISION)
220
history = list(graph.iter_lefthand_ancestry(
221
branch.last_revision(), stop_revisions))
224
103
return SuccessfulSmartServerResponse(
225
('ok', ), ('\x00'.join(reversed(history))))
104
('ok', ), ('\x00'.join(branch.revision_history())))
228
107
class SmartServerBranchRequestLastRevisionInfo(SmartServerBranchRequest):
230
109
def do_with_branch(self, branch):
231
110
"""Return branch.last_revision_info().
233
112
The revno is encoded in decimal, the revision_id is encoded as utf8.
235
114
revno, last_revision = branch.last_revision_info()
236
115
return SuccessfulSmartServerResponse(('ok', str(revno), last_revision))
239
class SmartServerBranchRequestRevisionIdToRevno(SmartServerBranchRequest):
241
def do_with_branch(self, branch, revid):
242
"""Return branch.revision_id_to_revno().
246
The revno is encoded in decimal, the revision_id is encoded as utf8.
249
dotted_revno = branch.revision_id_to_dotted_revno(revid)
250
except errors.NoSuchRevision:
251
return FailedSmartServerResponse(('NoSuchRevision', revid))
252
return SuccessfulSmartServerResponse(
253
('ok', ) + tuple(map(str, dotted_revno)))
256
class SmartServerSetTipRequest(SmartServerLockedBranchRequest):
257
"""Base class for handling common branch request logic for requests that
258
update the branch tip.
261
def do_with_locked_branch(self, branch, *args):
263
return self.do_tip_change_with_locked_branch(branch, *args)
264
except errors.TipChangeRejected, e:
266
if isinstance(msg, unicode):
267
msg = msg.encode('utf-8')
268
return FailedSmartServerResponse(('TipChangeRejected', msg))
271
class SmartServerBranchRequestSetConfigOption(SmartServerLockedBranchRequest):
272
"""Set an option in the branch configuration."""
274
def do_with_locked_branch(self, branch, value, name, section):
277
branch._get_config().set_option(value.decode('utf8'), name, section)
278
return SuccessfulSmartServerResponse(())
281
class SmartServerBranchRequestSetConfigOptionDict(SmartServerLockedBranchRequest):
282
"""Set an option in the branch configuration.
118
class SmartServerBranchRequestSetLastRevision(SmartServerLockedBranchRequest):
287
def do_with_locked_branch(self, branch, value_dict, name, section):
288
utf8_dict = bencode.bdecode(value_dict)
290
for key, value in utf8_dict.items():
291
value_dict[key.decode('utf8')] = value.decode('utf8')
294
branch._get_config().set_option(value_dict, name, section)
295
return SuccessfulSmartServerResponse(())
298
class SmartServerBranchRequestSetLastRevision(SmartServerSetTipRequest):
300
def do_tip_change_with_locked_branch(self, branch, new_last_revision_id):
120
def do_with_locked_branch(self, branch, new_last_revision_id):
301
121
if new_last_revision_id == 'null:':
302
branch.set_last_revision_info(0, new_last_revision_id)
122
branch.set_revision_history([])
304
124
if not branch.repository.has_revision(new_last_revision_id):
305
125
return FailedSmartServerResponse(
306
126
('NoSuchRevision', new_last_revision_id))
307
branch.generate_revision_history(new_last_revision_id, None, None)
127
branch.generate_revision_history(new_last_revision_id)
308
128
return SuccessfulSmartServerResponse(('ok',))
311
class SmartServerBranchRequestSetLastRevisionEx(SmartServerSetTipRequest):
313
def do_tip_change_with_locked_branch(self, branch, new_last_revision_id,
314
allow_divergence, allow_overwrite_descendant):
315
"""Set the last revision of the branch.
319
:param new_last_revision_id: the revision ID to set as the last
320
revision of the branch.
321
:param allow_divergence: A flag. If non-zero, change the revision ID
322
even if the new_last_revision_id's ancestry has diverged from the
323
current last revision. If zero, a 'Diverged' error will be
324
returned if new_last_revision_id is not a descendant of the current
326
:param allow_overwrite_descendant: A flag. If zero and
327
new_last_revision_id is not a descendant of the current last
328
revision, then the last revision will not be changed. If non-zero
329
and there is no divergence, then the last revision is always
332
:returns: on success, a tuple of ('ok', revno, revision_id), where
333
revno and revision_id are the new values of the current last
334
revision info. The revision_id might be different to the
335
new_last_revision_id if allow_overwrite_descendant was not set.
337
do_not_overwrite_descendant = not allow_overwrite_descendant
339
last_revno, last_rev = branch.last_revision_info()
340
graph = branch.repository.get_graph()
341
if not allow_divergence or do_not_overwrite_descendant:
342
relation = branch._revision_relations(
343
last_rev, new_last_revision_id, graph)
344
if relation == 'diverged' and not allow_divergence:
345
return FailedSmartServerResponse(('Diverged',))
346
if relation == 'a_descends_from_b' and do_not_overwrite_descendant:
347
return SuccessfulSmartServerResponse(
348
('ok', last_revno, last_rev))
349
new_revno = graph.find_distance_to_null(
350
new_last_revision_id, [(last_rev, last_revno)])
351
branch.set_last_revision_info(new_revno, new_last_revision_id)
352
except errors.GhostRevisionsHaveNoRevno:
353
return FailedSmartServerResponse(
354
('NoSuchRevision', new_last_revision_id))
355
return SuccessfulSmartServerResponse(
356
('ok', new_revno, new_last_revision_id))
359
class SmartServerBranchRequestSetLastRevisionInfo(SmartServerSetTipRequest):
131
class SmartServerBranchRequestSetLastRevisionInfo(
132
SmartServerLockedBranchRequest):
360
133
"""Branch.set_last_revision_info. Sets the revno and the revision ID of
361
134
the specified branch.
363
136
New in bzrlib 1.4.
366
def do_tip_change_with_locked_branch(self, branch, new_revno,
367
new_last_revision_id):
139
def do_with_locked_branch(self, branch, new_revno, new_last_revision_id):
369
141
branch.set_last_revision_info(int(new_revno), new_last_revision_id)
370
142
except errors.NoSuchRevision: