79
69
class SmartServerBranchGetConfigFile(SmartServerBranchRequest):
81
71
def do_with_branch(self, branch):
82
"""Return the content of branch.conf
72
"""Return the content of branch.control_files.get('branch.conf').
84
74
The body is not utf8 decoded - its the literal bytestream from disk.
87
content = branch._transport.get_bytes('branch.conf')
77
content = branch.control_files.get('branch.conf').read()
88
78
except errors.NoSuchFile:
90
80
return SuccessfulSmartServerResponse( ('ok', ), content)
93
class SmartServerBranchGetParent(SmartServerBranchRequest):
95
def do_with_branch(self, branch):
96
"""Return the parent of branch."""
97
parent = branch._get_parent_location() or ''
98
return SuccessfulSmartServerResponse((parent,))
101
class SmartServerBranchGetTagsBytes(SmartServerBranchRequest):
103
def do_with_branch(self, branch):
104
"""Return the _get_tags_bytes for a branch."""
105
bytes = branch._get_tags_bytes()
106
return SuccessfulSmartServerResponse((bytes,))
109
class SmartServerBranchSetTagsBytes(SmartServerLockedBranchRequest):
111
def __init__(self, backing_transport, root_client_path='/', jail_root=None):
112
SmartServerLockedBranchRequest.__init__(
113
self, backing_transport, root_client_path, jail_root)
116
def do_with_locked_branch(self, branch):
117
"""Call _set_tags_bytes for a branch.
121
# We need to keep this branch locked until we get a body with the tags
124
self.branch.lock_write()
127
def do_body(self, bytes):
128
self.branch._set_tags_bytes(bytes)
129
return SuccessfulSmartServerResponse(())
132
# TODO: this request shouldn't have to do this housekeeping manually.
133
# Some of this logic probably belongs in a base class.
135
# We never acquired the branch successfully in the first place, so
136
# there's nothing more to do.
139
return SmartServerLockedBranchRequest.do_end(self)
141
# Only try unlocking if we locked successfully in the first place
145
class SmartServerBranchHeadsToFetch(SmartServerBranchRequest):
147
def do_with_branch(self, branch):
148
"""Return the heads-to-fetch for a Branch as two bencoded lists.
150
See Branch.heads_to_fetch.
154
must_fetch, if_present_fetch = branch.heads_to_fetch()
155
return SuccessfulSmartServerResponse(
156
(list(must_fetch), list(if_present_fetch)))
159
class SmartServerBranchRequestGetStackedOnURL(SmartServerBranchRequest):
161
def do_with_branch(self, branch):
162
stacked_on_url = branch.get_stacked_on_url()
163
return SuccessfulSmartServerResponse(('ok', stacked_on_url))
166
83
class SmartServerRequestRevisionHistory(SmartServerBranchRequest):
168
85
def do_with_branch(self, branch):
178
95
class SmartServerBranchRequestLastRevisionInfo(SmartServerBranchRequest):
180
97
def do_with_branch(self, branch):
181
98
"""Return branch.last_revision_info().
183
100
The revno is encoded in decimal, the revision_id is encoded as utf8.
185
102
revno, last_revision = branch.last_revision_info()
186
103
return SuccessfulSmartServerResponse(('ok', str(revno), last_revision))
189
class SmartServerSetTipRequest(SmartServerLockedBranchRequest):
190
"""Base class for handling common branch request logic for requests that
191
update the branch tip.
194
def do_with_locked_branch(self, branch, *args):
196
return self.do_tip_change_with_locked_branch(branch, *args)
197
except errors.TipChangeRejected, e:
199
if isinstance(msg, unicode):
200
msg = msg.encode('utf-8')
201
return FailedSmartServerResponse(('TipChangeRejected', msg))
204
class SmartServerBranchRequestSetConfigOption(SmartServerLockedBranchRequest):
205
"""Set an option in the branch configuration."""
207
def do_with_locked_branch(self, branch, value, name, section):
210
branch._get_config().set_option(value.decode('utf8'), name, section)
211
return SuccessfulSmartServerResponse(())
214
class SmartServerBranchRequestSetConfigOptionDict(SmartServerLockedBranchRequest):
215
"""Set an option in the branch configuration.
106
class SmartServerBranchRequestSetLastRevision(SmartServerLockedBranchRequest):
220
def do_with_locked_branch(self, branch, value_dict, name, section):
221
utf8_dict = bencode.bdecode(value_dict)
223
for key, value in utf8_dict.items():
224
value_dict[key.decode('utf8')] = value.decode('utf8')
227
branch._get_config().set_option(value_dict, name, section)
228
return SuccessfulSmartServerResponse(())
231
class SmartServerBranchRequestSetLastRevision(SmartServerSetTipRequest):
233
def do_tip_change_with_locked_branch(self, branch, new_last_revision_id):
108
def do_with_locked_branch(self, branch, new_last_revision_id):
234
109
if new_last_revision_id == 'null:':
235
branch._set_revision_history([])
110
branch.set_revision_history([])
237
112
if not branch.repository.has_revision(new_last_revision_id):
238
113
return FailedSmartServerResponse(
239
114
('NoSuchRevision', new_last_revision_id))
240
branch._set_revision_history(branch._lefthand_history(
241
new_last_revision_id, None, None))
242
return SuccessfulSmartServerResponse(('ok',))
245
class SmartServerBranchRequestSetLastRevisionEx(SmartServerSetTipRequest):
247
def do_tip_change_with_locked_branch(self, branch, new_last_revision_id,
248
allow_divergence, allow_overwrite_descendant):
249
"""Set the last revision of the branch.
253
:param new_last_revision_id: the revision ID to set as the last
254
revision of the branch.
255
:param allow_divergence: A flag. If non-zero, change the revision ID
256
even if the new_last_revision_id's ancestry has diverged from the
257
current last revision. If zero, a 'Diverged' error will be
258
returned if new_last_revision_id is not a descendant of the current
260
:param allow_overwrite_descendant: A flag. If zero and
261
new_last_revision_id is not a descendant of the current last
262
revision, then the last revision will not be changed. If non-zero
263
and there is no divergence, then the last revision is always
266
:returns: on success, a tuple of ('ok', revno, revision_id), where
267
revno and revision_id are the new values of the current last
268
revision info. The revision_id might be different to the
269
new_last_revision_id if allow_overwrite_descendant was not set.
271
do_not_overwrite_descendant = not allow_overwrite_descendant
273
last_revno, last_rev = branch.last_revision_info()
274
graph = branch.repository.get_graph()
275
if not allow_divergence or do_not_overwrite_descendant:
276
relation = branch._revision_relations(
277
last_rev, new_last_revision_id, graph)
278
if relation == 'diverged' and not allow_divergence:
279
return FailedSmartServerResponse(('Diverged',))
280
if relation == 'a_descends_from_b' and do_not_overwrite_descendant:
281
return SuccessfulSmartServerResponse(
282
('ok', last_revno, last_rev))
283
new_revno = graph.find_distance_to_null(
284
new_last_revision_id, [(last_rev, last_revno)])
285
branch.set_last_revision_info(new_revno, new_last_revision_id)
286
except errors.GhostRevisionsHaveNoRevno:
287
return FailedSmartServerResponse(
288
('NoSuchRevision', new_last_revision_id))
289
return SuccessfulSmartServerResponse(
290
('ok', new_revno, new_last_revision_id))
293
class SmartServerBranchRequestSetLastRevisionInfo(SmartServerSetTipRequest):
294
"""Branch.set_last_revision_info. Sets the revno and the revision ID of
295
the specified branch.
300
def do_tip_change_with_locked_branch(self, branch, new_revno,
301
new_last_revision_id):
303
branch.set_last_revision_info(int(new_revno), new_last_revision_id)
304
except errors.NoSuchRevision:
305
return FailedSmartServerResponse(
306
('NoSuchRevision', new_last_revision_id))
307
return SuccessfulSmartServerResponse(('ok',))
310
class SmartServerBranchRequestSetParentLocation(SmartServerLockedBranchRequest):
311
"""Set the parent location for a branch.
313
Takes a location to set, which must be utf8 encoded.
316
def do_with_locked_branch(self, branch, location):
317
branch._set_parent_location(location)
318
return SuccessfulSmartServerResponse(())
115
branch.generate_revision_history(new_last_revision_id)
116
return SuccessfulSmartServerResponse(('ok',))
321
119
class SmartServerBranchRequestLockWrite(SmartServerBranchRequest):
323
121
def do_with_branch(self, branch, branch_token='', repo_token=''):
324
122
if branch_token == '':
325
123
branch_token = None
326
124
if repo_token == '':
327
125
repo_token = None
329
repo_token = branch.repository.lock_write(
330
token=repo_token).repository_token
127
repo_token = branch.repository.lock_write(token=repo_token)
332
branch_token = branch.lock_write(
333
token=branch_token).branch_token
129
branch_token = branch.lock_write(token=branch_token)
335
131
# this leaves the repository with 1 lock
336
132
branch.repository.unlock()