29
29
class SmartServerBranchRequest(SmartServerRequest):
30
"""Base class for handling common branch request logic."""
30
"""Base class for handling common branch request logic.
32
33
def do(self, path, *args):
33
34
"""Execute a request for a branch at path.
36
All Branch requests take a path to the branch as their first argument.
35
38
If the branch is a branch reference, NotBranchError is raised.
40
:param path: The path for the repository as received from the
42
:return: A SmartServerResponse from self.do_with_branch().
37
transport = self._backing_transport.clone(path)
44
transport = self.transport_from_client_path(path)
38
45
bzrdir = BzrDir.open_from_transport(transport)
39
46
if bzrdir.get_branch_reference() is not None:
40
47
raise errors.NotBranchError(transport.base)
69
76
class SmartServerBranchGetConfigFile(SmartServerBranchRequest):
71
78
def do_with_branch(self, branch):
72
"""Return the content of branch.control_files.get('branch.conf').
79
"""Return the content of branch.conf
74
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
77
content = branch.control_files.get('branch.conf').read()
89
content = branch._transport.get_bytes('branch.conf')
78
90
except errors.NoSuchFile:
80
92
return SuccessfulSmartServerResponse( ('ok', ), content)
103
115
return SuccessfulSmartServerResponse(('ok', str(revno), last_revision))
106
class SmartServerBranchRequestSetLastRevision(SmartServerLockedBranchRequest):
118
class SmartServerSetTipRequest(SmartServerLockedBranchRequest):
119
"""Base class for handling common branch request logic for requests that
120
update the branch tip.
123
def do_with_locked_branch(self, branch, *args):
125
return self.do_tip_change_with_locked_branch(branch, *args)
126
except errors.TipChangeRejected, e:
128
if isinstance(msg, unicode):
129
msg = msg.encode('utf-8')
130
return FailedSmartServerResponse(('TipChangeRejected', msg))
133
class SmartServerBranchRequestSetLastRevision(SmartServerSetTipRequest):
108
def do_with_locked_branch(self, branch, new_last_revision_id):
135
def do_tip_change_with_locked_branch(self, branch, new_last_revision_id):
109
136
if new_last_revision_id == 'null:':
110
137
branch.set_revision_history([])
116
143
return SuccessfulSmartServerResponse(('ok',))
146
class SmartServerBranchRequestSetLastRevisionEx(SmartServerSetTipRequest):
148
def do_tip_change_with_locked_branch(self, branch, new_last_revision_id,
149
allow_divergence, allow_overwrite_descendant):
150
"""Set the last revision of the branch.
154
:param new_last_revision_id: the revision ID to set as the last
155
revision of the branch.
156
:param allow_divergence: A flag. If non-zero, change the revision ID
157
even if the new_last_revision_id's ancestry has diverged from the
158
current last revision. If zero, a 'Diverged' error will be
159
returned if new_last_revision_id is not a descendant of the current
161
:param allow_overwrite_descendant: A flag. If zero and
162
new_last_revision_id is not a descendant of the current last
163
revision, then the last revision will not be changed. If non-zero
164
and there is no divergence, then the last revision is always
167
:returns: on success, a tuple of ('ok', revno, revision_id), where
168
revno and revision_id are the new values of the current last
169
revision info. The revision_id might be different to the
170
new_last_revision_id if allow_overwrite_descendant was not set.
172
do_not_overwrite_descendant = not allow_overwrite_descendant
174
last_revno, last_rev = branch.last_revision_info()
175
graph = branch.repository.get_graph()
176
if not allow_divergence or do_not_overwrite_descendant:
177
relation = branch._revision_relations(
178
last_rev, new_last_revision_id, graph)
179
if relation == 'diverged' and not allow_divergence:
180
return FailedSmartServerResponse(('Diverged',))
181
if relation == 'a_descends_from_b' and do_not_overwrite_descendant:
182
return SuccessfulSmartServerResponse(
183
('ok', last_revno, last_rev))
184
new_revno = graph.find_distance_to_null(
185
new_last_revision_id, [(last_rev, last_revno)])
186
branch.set_last_revision_info(new_revno, new_last_revision_id)
187
except errors.GhostRevisionsHaveNoRevno:
188
return FailedSmartServerResponse(
189
('NoSuchRevision', new_last_revision_id))
190
return SuccessfulSmartServerResponse(
191
('ok', new_revno, new_last_revision_id))
194
class SmartServerBranchRequestSetLastRevisionInfo(SmartServerSetTipRequest):
195
"""Branch.set_last_revision_info. Sets the revno and the revision ID of
196
the specified branch.
201
def do_tip_change_with_locked_branch(self, branch, new_revno,
202
new_last_revision_id):
204
branch.set_last_revision_info(int(new_revno), new_last_revision_id)
205
except errors.NoSuchRevision:
206
return FailedSmartServerResponse(
207
('NoSuchRevision', new_last_revision_id))
208
return SuccessfulSmartServerResponse(('ok',))
119
211
class SmartServerBranchRequestLockWrite(SmartServerBranchRequest):
121
213
def do_with_branch(self, branch, branch_token='', repo_token=''):
135
228
return FailedSmartServerResponse(('TokenMismatch',))
136
229
except errors.UnlockableTransport:
137
230
return FailedSmartServerResponse(('UnlockableTransport',))
138
branch.repository.leave_lock_in_place()
231
except errors.LockFailed, e:
232
return FailedSmartServerResponse(('LockFailed', str(e.lock), str(e.why)))
233
if repo_token is None:
236
branch.repository.leave_lock_in_place()
139
237
branch.leave_lock_in_place()
141
239
return SuccessfulSmartServerResponse(('ok', branch_token, repo_token))