29
29
class SmartServerBranchRequest(SmartServerRequest):
30
"""Base class for handling common branch request logic.
30
"""Base class for handling common branch request logic."""
33
32
def do(self, path, *args):
34
33
"""Execute a request for a branch at path.
36
All Branch requests take a path to the branch as their first argument.
38
35
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().
44
transport = self.transport_from_client_path(path)
37
transport = self._backing_transport.clone(path)
45
38
bzrdir = BzrDir.open_from_transport(transport)
46
39
if bzrdir.get_branch_reference() is not None:
47
40
raise errors.NotBranchError(transport.base)
76
69
class SmartServerBranchGetConfigFile(SmartServerBranchRequest):
78
71
def do_with_branch(self, branch):
79
"""Return the content of branch.conf
72
"""Return the content of branch.control_files.get('branch.conf').
81
74
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
89
content = branch._transport.get_bytes('branch.conf')
77
content = branch.control_files.get('branch.conf').read()
90
78
except errors.NoSuchFile:
92
80
return SuccessfulSmartServerResponse( ('ok', ), content)
95
class SmartServerBranchRequestGetStackedOnURL(SmartServerBranchRequest):
97
def do_with_branch(self, branch):
98
stacked_on_url = branch.get_stacked_on_url()
99
return SuccessfulSmartServerResponse(('ok', stacked_on_url))
102
83
class SmartServerRequestRevisionHistory(SmartServerBranchRequest):
104
85
def do_with_branch(self, branch):
122
103
return SuccessfulSmartServerResponse(('ok', str(revno), last_revision))
125
class SmartServerSetTipRequest(SmartServerLockedBranchRequest):
126
"""Base class for handling common branch request logic for requests that
127
update the branch tip.
130
def do_with_locked_branch(self, branch, *args):
132
return self.do_tip_change_with_locked_branch(branch, *args)
133
except errors.TipChangeRejected, e:
135
if isinstance(msg, unicode):
136
msg = msg.encode('utf-8')
137
return FailedSmartServerResponse(('TipChangeRejected', msg))
140
class SmartServerBranchRequestSetLastRevision(SmartServerSetTipRequest):
106
class SmartServerBranchRequestSetLastRevision(SmartServerLockedBranchRequest):
142
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):
143
109
if new_last_revision_id == 'null:':
144
110
branch.set_revision_history([])
150
116
return SuccessfulSmartServerResponse(('ok',))
153
class SmartServerBranchRequestSetLastRevisionEx(SmartServerSetTipRequest):
155
def do_tip_change_with_locked_branch(self, branch, new_last_revision_id,
156
allow_divergence, allow_overwrite_descendant):
157
"""Set the last revision of the branch.
161
:param new_last_revision_id: the revision ID to set as the last
162
revision of the branch.
163
:param allow_divergence: A flag. If non-zero, change the revision ID
164
even if the new_last_revision_id's ancestry has diverged from the
165
current last revision. If zero, a 'Diverged' error will be
166
returned if new_last_revision_id is not a descendant of the current
168
:param allow_overwrite_descendant: A flag. If zero and
169
new_last_revision_id is not a descendant of the current last
170
revision, then the last revision will not be changed. If non-zero
171
and there is no divergence, then the last revision is always
174
:returns: on success, a tuple of ('ok', revno, revision_id), where
175
revno and revision_id are the new values of the current last
176
revision info. The revision_id might be different to the
177
new_last_revision_id if allow_overwrite_descendant was not set.
179
do_not_overwrite_descendant = not allow_overwrite_descendant
181
last_revno, last_rev = branch.last_revision_info()
182
graph = branch.repository.get_graph()
183
if not allow_divergence or do_not_overwrite_descendant:
184
relation = branch._revision_relations(
185
last_rev, new_last_revision_id, graph)
186
if relation == 'diverged' and not allow_divergence:
187
return FailedSmartServerResponse(('Diverged',))
188
if relation == 'a_descends_from_b' and do_not_overwrite_descendant:
189
return SuccessfulSmartServerResponse(
190
('ok', last_revno, last_rev))
191
new_revno = graph.find_distance_to_null(
192
new_last_revision_id, [(last_rev, last_revno)])
193
branch.set_last_revision_info(new_revno, new_last_revision_id)
194
except errors.GhostRevisionsHaveNoRevno:
195
return FailedSmartServerResponse(
196
('NoSuchRevision', new_last_revision_id))
197
return SuccessfulSmartServerResponse(
198
('ok', new_revno, new_last_revision_id))
201
class SmartServerBranchRequestSetLastRevisionInfo(SmartServerSetTipRequest):
202
"""Branch.set_last_revision_info. Sets the revno and the revision ID of
203
the specified branch.
208
def do_tip_change_with_locked_branch(self, branch, new_revno,
209
new_last_revision_id):
211
branch.set_last_revision_info(int(new_revno), new_last_revision_id)
212
except errors.NoSuchRevision:
213
return FailedSmartServerResponse(
214
('NoSuchRevision', new_last_revision_id))
215
return SuccessfulSmartServerResponse(('ok',))
218
119
class SmartServerBranchRequestLockWrite(SmartServerBranchRequest):
220
121
def do_with_branch(self, branch, branch_token='', repo_token=''):