69
79
class SmartServerBranchGetConfigFile(SmartServerBranchRequest):
71
81
def do_with_branch(self, branch):
72
"""Return the content of branch.control_files.get('branch.conf').
82
"""Return the content of branch.conf
74
84
The body is not utf8 decoded - its the literal bytestream from disk.
77
content = branch.control_files.get('branch.conf').read()
87
content = branch._transport.get_bytes('branch.conf')
78
88
except errors.NoSuchFile:
80
90
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 SmartServerBranchRequestGetStackedOnURL(SmartServerBranchRequest):
147
def do_with_branch(self, branch):
148
stacked_on_url = branch.get_stacked_on_url()
149
return SuccessfulSmartServerResponse(('ok', stacked_on_url))
83
152
class SmartServerRequestRevisionHistory(SmartServerBranchRequest):
85
154
def do_with_branch(self, branch):
95
164
class SmartServerBranchRequestLastRevisionInfo(SmartServerBranchRequest):
97
166
def do_with_branch(self, branch):
98
167
"""Return branch.last_revision_info().
100
169
The revno is encoded in decimal, the revision_id is encoded as utf8.
102
171
revno, last_revision = branch.last_revision_info()
103
172
return SuccessfulSmartServerResponse(('ok', str(revno), last_revision))
106
class SmartServerBranchRequestSetLastRevision(SmartServerLockedBranchRequest):
175
class SmartServerSetTipRequest(SmartServerLockedBranchRequest):
176
"""Base class for handling common branch request logic for requests that
177
update the branch tip.
180
def do_with_locked_branch(self, branch, *args):
182
return self.do_tip_change_with_locked_branch(branch, *args)
183
except errors.TipChangeRejected, e:
185
if isinstance(msg, unicode):
186
msg = msg.encode('utf-8')
187
return FailedSmartServerResponse(('TipChangeRejected', msg))
190
class SmartServerBranchRequestSetConfigOption(SmartServerLockedBranchRequest):
191
"""Set an option in the branch configuration."""
193
def do_with_locked_branch(self, branch, value, name, section):
196
branch._get_config().set_option(value.decode('utf8'), name, section)
197
return SuccessfulSmartServerResponse(())
200
class SmartServerBranchRequestSetConfigOptionDict(SmartServerLockedBranchRequest):
201
"""Set an option in the branch configuration.
108
def do_with_locked_branch(self, branch, new_last_revision_id):
206
def do_with_locked_branch(self, branch, value_dict, name, section):
207
utf8_dict = bencode.bdecode(value_dict)
209
for key, value in utf8_dict.items():
210
value_dict[key.decode('utf8')] = value.decode('utf8')
213
branch._get_config().set_option(value_dict, name, section)
214
return SuccessfulSmartServerResponse(())
217
class SmartServerBranchRequestSetLastRevision(SmartServerSetTipRequest):
219
def do_tip_change_with_locked_branch(self, branch, new_last_revision_id):
109
220
if new_last_revision_id == 'null:':
110
221
branch.set_revision_history([])
112
223
if not branch.repository.has_revision(new_last_revision_id):
113
224
return FailedSmartServerResponse(
114
225
('NoSuchRevision', new_last_revision_id))
115
branch.generate_revision_history(new_last_revision_id)
116
return SuccessfulSmartServerResponse(('ok',))
226
branch.set_revision_history(branch._lefthand_history(
227
new_last_revision_id, None, None))
228
return SuccessfulSmartServerResponse(('ok',))
231
class SmartServerBranchRequestSetLastRevisionEx(SmartServerSetTipRequest):
233
def do_tip_change_with_locked_branch(self, branch, new_last_revision_id,
234
allow_divergence, allow_overwrite_descendant):
235
"""Set the last revision of the branch.
239
:param new_last_revision_id: the revision ID to set as the last
240
revision of the branch.
241
:param allow_divergence: A flag. If non-zero, change the revision ID
242
even if the new_last_revision_id's ancestry has diverged from the
243
current last revision. If zero, a 'Diverged' error will be
244
returned if new_last_revision_id is not a descendant of the current
246
:param allow_overwrite_descendant: A flag. If zero and
247
new_last_revision_id is not a descendant of the current last
248
revision, then the last revision will not be changed. If non-zero
249
and there is no divergence, then the last revision is always
252
:returns: on success, a tuple of ('ok', revno, revision_id), where
253
revno and revision_id are the new values of the current last
254
revision info. The revision_id might be different to the
255
new_last_revision_id if allow_overwrite_descendant was not set.
257
do_not_overwrite_descendant = not allow_overwrite_descendant
259
last_revno, last_rev = branch.last_revision_info()
260
graph = branch.repository.get_graph()
261
if not allow_divergence or do_not_overwrite_descendant:
262
relation = branch._revision_relations(
263
last_rev, new_last_revision_id, graph)
264
if relation == 'diverged' and not allow_divergence:
265
return FailedSmartServerResponse(('Diverged',))
266
if relation == 'a_descends_from_b' and do_not_overwrite_descendant:
267
return SuccessfulSmartServerResponse(
268
('ok', last_revno, last_rev))
269
new_revno = graph.find_distance_to_null(
270
new_last_revision_id, [(last_rev, last_revno)])
271
branch.set_last_revision_info(new_revno, new_last_revision_id)
272
except errors.GhostRevisionsHaveNoRevno:
273
return FailedSmartServerResponse(
274
('NoSuchRevision', new_last_revision_id))
275
return SuccessfulSmartServerResponse(
276
('ok', new_revno, new_last_revision_id))
279
class SmartServerBranchRequestSetLastRevisionInfo(SmartServerSetTipRequest):
280
"""Branch.set_last_revision_info. Sets the revno and the revision ID of
281
the specified branch.
286
def do_tip_change_with_locked_branch(self, branch, new_revno,
287
new_last_revision_id):
289
branch.set_last_revision_info(int(new_revno), new_last_revision_id)
290
except errors.NoSuchRevision:
291
return FailedSmartServerResponse(
292
('NoSuchRevision', new_last_revision_id))
293
return SuccessfulSmartServerResponse(('ok',))
296
class SmartServerBranchRequestSetParentLocation(SmartServerLockedBranchRequest):
297
"""Set the parent location for a branch.
299
Takes a location to set, which must be utf8 encoded.
302
def do_with_locked_branch(self, branch, location):
303
branch._set_parent_location(location)
304
return SuccessfulSmartServerResponse(())
119
307
class SmartServerBranchRequestLockWrite(SmartServerBranchRequest):
121
309
def do_with_branch(self, branch, branch_token='', repo_token=''):
122
310
if branch_token == '':
123
311
branch_token = None
124
312
if repo_token == '':
125
313
repo_token = None
127
repo_token = branch.repository.lock_write(token=repo_token)
315
repo_token = branch.repository.lock_write(
316
token=repo_token).repository_token
129
branch_token = branch.lock_write(token=branch_token)
318
branch_token = branch.lock_write(
319
token=branch_token).branch_token
321
# this leaves the repository with 1 lock
131
322
branch.repository.unlock()
132
323
except errors.LockContention:
133
324
return FailedSmartServerResponse(('LockContention',))