~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/branch.py

(jameinel) Allow 'bzr serve' to interpret SIGHUP as a graceful shutdown.
 (bug #795025) (John A Meinel)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Server-side branch related request implmentations."""
18
18
 
19
19
 
20
 
from bzrlib import errors
 
20
from bzrlib import (
 
21
    bencode,
 
22
    errors,
 
23
    )
21
24
from bzrlib.bzrdir import BzrDir
22
25
from bzrlib.smart.request import (
23
26
    FailedSmartServerResponse,
32
35
 
33
36
    def do(self, path, *args):
34
37
        """Execute a request for a branch at path.
35
 
    
 
38
 
36
39
        All Branch requests take a path to the branch as their first argument.
37
40
 
38
41
        If the branch is a branch reference, NotBranchError is raised.
45
48
        bzrdir = BzrDir.open_from_transport(transport)
46
49
        if bzrdir.get_branch_reference() is not None:
47
50
            raise errors.NotBranchError(transport.base)
48
 
        branch = bzrdir.open_branch()
 
51
        branch = bzrdir.open_branch(ignore_fallbacks=True)
49
52
        return self.do_with_branch(branch, *args)
50
53
 
51
54
 
74
77
 
75
78
 
76
79
class SmartServerBranchGetConfigFile(SmartServerBranchRequest):
77
 
    
 
80
 
78
81
    def do_with_branch(self, branch):
79
82
        """Return the content of branch.conf
80
 
        
 
83
 
81
84
        The body is not utf8 decoded - its the literal bytestream from disk.
82
85
        """
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
87
 
        # access.
88
86
        try:
89
87
            content = branch._transport.get_bytes('branch.conf')
90
88
        except errors.NoSuchFile:
92
90
        return SuccessfulSmartServerResponse( ('ok', ), content)
93
91
 
94
92
 
 
93
class SmartServerBranchGetParent(SmartServerBranchRequest):
 
94
 
 
95
    def do_with_branch(self, branch):
 
96
        """Return the parent of branch."""
 
97
        parent = branch._get_parent_location() or ''
 
98
        return SuccessfulSmartServerResponse((parent,))
 
99
 
 
100
 
 
101
class SmartServerBranchGetTagsBytes(SmartServerBranchRequest):
 
102
 
 
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,))
 
107
 
 
108
 
 
109
class SmartServerBranchSetTagsBytes(SmartServerLockedBranchRequest):
 
110
 
 
111
    def __init__(self, backing_transport, root_client_path='/', jail_root=None):
 
112
        SmartServerLockedBranchRequest.__init__(
 
113
            self, backing_transport, root_client_path, jail_root)
 
114
        self.locked = False
 
115
        
 
116
    def do_with_locked_branch(self, branch):
 
117
        """Call _set_tags_bytes for a branch.
 
118
 
 
119
        New in 1.18.
 
120
        """
 
121
        # We need to keep this branch locked until we get a body with the tags
 
122
        # bytes.
 
123
        self.branch = branch
 
124
        self.branch.lock_write()
 
125
        self.locked = True
 
126
 
 
127
    def do_body(self, bytes):
 
128
        self.branch._set_tags_bytes(bytes)
 
129
        return SuccessfulSmartServerResponse(())
 
130
 
 
131
    def do_end(self):
 
132
        # TODO: this request shouldn't have to do this housekeeping manually.
 
133
        # Some of this logic probably belongs in a base class.
 
134
        if not self.locked:
 
135
            # We never acquired the branch successfully in the first place, so
 
136
            # there's nothing more to do.
 
137
            return
 
138
        try:
 
139
            return SmartServerLockedBranchRequest.do_end(self)
 
140
        finally:
 
141
            # Only try unlocking if we locked successfully in the first place
 
142
            self.branch.unlock()
 
143
 
 
144
 
 
145
class SmartServerBranchHeadsToFetch(SmartServerBranchRequest):
 
146
 
 
147
    def do_with_branch(self, branch):
 
148
        """Return the heads-to-fetch for a Branch as two bencoded lists.
 
149
        
 
150
        See Branch.heads_to_fetch.
 
151
 
 
152
        New in 2.4.
 
153
        """
 
154
        must_fetch, if_present_fetch = branch.heads_to_fetch()
 
155
        return SuccessfulSmartServerResponse(
 
156
            (list(must_fetch), list(if_present_fetch)))
 
157
 
 
158
 
95
159
class SmartServerBranchRequestGetStackedOnURL(SmartServerBranchRequest):
96
160
 
97
161
    def do_with_branch(self, branch):
112
176
 
113
177
 
114
178
class SmartServerBranchRequestLastRevisionInfo(SmartServerBranchRequest):
115
 
    
 
179
 
116
180
    def do_with_branch(self, branch):
117
181
        """Return branch.last_revision_info().
118
 
        
 
182
 
119
183
        The revno is encoded in decimal, the revision_id is encoded as utf8.
120
184
        """
121
185
        revno, last_revision = branch.last_revision_info()
137
201
            return FailedSmartServerResponse(('TipChangeRejected', msg))
138
202
 
139
203
 
 
204
class SmartServerBranchRequestSetConfigOption(SmartServerLockedBranchRequest):
 
205
    """Set an option in the branch configuration."""
 
206
 
 
207
    def do_with_locked_branch(self, branch, value, name, section):
 
208
        if not section:
 
209
            section = None
 
210
        branch._get_config().set_option(value.decode('utf8'), name, section)
 
211
        return SuccessfulSmartServerResponse(())
 
212
 
 
213
 
 
214
class SmartServerBranchRequestSetConfigOptionDict(SmartServerLockedBranchRequest):
 
215
    """Set an option in the branch configuration.
 
216
    
 
217
    New in 2.2.
 
218
    """
 
219
 
 
220
    def do_with_locked_branch(self, branch, value_dict, name, section):
 
221
        utf8_dict = bencode.bdecode(value_dict)
 
222
        value_dict = {}
 
223
        for key, value in utf8_dict.items():
 
224
            value_dict[key.decode('utf8')] = value.decode('utf8')
 
225
        if not section:
 
226
            section = None
 
227
        branch._get_config().set_option(value_dict, name, section)
 
228
        return SuccessfulSmartServerResponse(())
 
229
 
 
230
 
140
231
class SmartServerBranchRequestSetLastRevision(SmartServerSetTipRequest):
141
 
    
 
232
 
142
233
    def do_tip_change_with_locked_branch(self, branch, new_last_revision_id):
143
234
        if new_last_revision_id == 'null:':
144
 
            branch.set_revision_history([])
 
235
            branch._set_revision_history([])
145
236
        else:
146
237
            if not branch.repository.has_revision(new_last_revision_id):
147
238
                return FailedSmartServerResponse(
148
239
                    ('NoSuchRevision', new_last_revision_id))
149
 
            branch.generate_revision_history(new_last_revision_id)
 
240
            branch._set_revision_history(branch._lefthand_history(
 
241
                new_last_revision_id, None, None))
150
242
        return SuccessfulSmartServerResponse(('ok',))
151
243
 
152
244
 
153
245
class SmartServerBranchRequestSetLastRevisionEx(SmartServerSetTipRequest):
154
 
    
 
246
 
155
247
    def do_tip_change_with_locked_branch(self, branch, new_last_revision_id,
156
248
            allow_divergence, allow_overwrite_descendant):
157
249
        """Set the last revision of the branch.
158
250
 
159
251
        New in 1.6.
160
 
        
 
252
 
161
253
        :param new_last_revision_id: the revision ID to set as the last
162
254
            revision of the branch.
163
255
        :param allow_divergence: A flag.  If non-zero, change the revision ID
204
296
 
205
297
    New in bzrlib 1.4.
206
298
    """
207
 
    
 
299
 
208
300
    def do_tip_change_with_locked_branch(self, branch, new_revno,
209
301
            new_last_revision_id):
210
302
        try:
215
307
        return SuccessfulSmartServerResponse(('ok',))
216
308
 
217
309
 
 
310
class SmartServerBranchRequestSetParentLocation(SmartServerLockedBranchRequest):
 
311
    """Set the parent location for a branch.
 
312
    
 
313
    Takes a location to set, which must be utf8 encoded.
 
314
    """
 
315
 
 
316
    def do_with_locked_branch(self, branch, location):
 
317
        branch._set_parent_location(location)
 
318
        return SuccessfulSmartServerResponse(())
 
319
 
 
320
 
218
321
class SmartServerBranchRequestLockWrite(SmartServerBranchRequest):
219
 
    
 
322
 
220
323
    def do_with_branch(self, branch, branch_token='', repo_token=''):
221
324
        if branch_token == '':
222
325
            branch_token = None
223
326
        if repo_token == '':
224
327
            repo_token = None
225
328
        try:
226
 
            repo_token = branch.repository.lock_write(token=repo_token)
 
329
            repo_token = branch.repository.lock_write(
 
330
                token=repo_token).repository_token
227
331
            try:
228
 
                branch_token = branch.lock_write(token=branch_token)
 
332
                branch_token = branch.lock_write(
 
333
                    token=branch_token).branch_token
229
334
            finally:
230
335
                # this leaves the repository with 1 lock
231
336
                branch.repository.unlock()
262
367
        branch.dont_leave_lock_in_place()
263
368
        branch.unlock()
264
369
        return SuccessfulSmartServerResponse(('ok',))
265
 
        
 
370