~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/branch.py

  • Committer: John Arbash Meinel
  • Author(s): Mark Hammond
  • Date: 2008-09-09 17:02:21 UTC
  • mto: This revision was merged to the branch mainline in revision 3697.
  • Revision ID: john@arbash-meinel.com-20080909170221-svim3jw2mrz0amp3
An updated transparent icon for bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Server-side branch related request implmentations."""
18
18
 
19
 
from __future__ import absolute_import
20
19
 
21
 
from bzrlib import (
22
 
    bencode,
23
 
    errors,
24
 
    revision as _mod_revision,
25
 
    )
26
 
from bzrlib.controldir import ControlDir
 
20
from bzrlib import errors
 
21
from bzrlib.bzrdir import BzrDir
27
22
from bzrlib.smart.request import (
28
23
    FailedSmartServerResponse,
29
24
    SmartServerRequest,
37
32
 
38
33
    def do(self, path, *args):
39
34
        """Execute a request for a branch at path.
40
 
 
 
35
    
41
36
        All Branch requests take a path to the branch as their first argument.
42
37
 
43
38
        If the branch is a branch reference, NotBranchError is raised.
47
42
        :return: A SmartServerResponse from self.do_with_branch().
48
43
        """
49
44
        transport = self.transport_from_client_path(path)
50
 
        controldir = ControlDir.open_from_transport(transport)
51
 
        if controldir.get_branch_reference() is not None:
 
45
        bzrdir = BzrDir.open_from_transport(transport)
 
46
        if bzrdir.get_branch_reference() is not None:
52
47
            raise errors.NotBranchError(transport.base)
53
 
        branch = controldir.open_branch(ignore_fallbacks=True)
 
48
        branch = bzrdir.open_branch()
54
49
        return self.do_with_branch(branch, *args)
55
50
 
56
51
 
78
73
            branch.repository.unlock()
79
74
 
80
75
 
81
 
class SmartServerBranchBreakLock(SmartServerBranchRequest):
82
 
 
83
 
    def do_with_branch(self, branch):
84
 
        """Break a branch lock.
85
 
        """
86
 
        branch.break_lock()
87
 
        return SuccessfulSmartServerResponse(('ok', ), )
88
 
 
89
 
 
90
76
class SmartServerBranchGetConfigFile(SmartServerBranchRequest):
91
 
 
 
77
    
92
78
    def do_with_branch(self, branch):
93
79
        """Return the content of branch.conf
94
 
 
 
80
        
95
81
        The body is not utf8 decoded - its the literal bytestream from disk.
96
82
        """
 
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.
97
88
        try:
98
 
            content = branch.control_transport.get_bytes('branch.conf')
 
89
            content = branch._transport.get_bytes('branch.conf')
99
90
        except errors.NoSuchFile:
100
91
            content = ''
101
92
        return SuccessfulSmartServerResponse( ('ok', ), content)
102
93
 
103
94
 
104
 
class SmartServerBranchPutConfigFile(SmartServerBranchRequest):
105
 
    """Set the configuration data for a branch.
106
 
 
107
 
    New in 2.5.
108
 
    """
109
 
 
110
 
    def do_with_branch(self, branch, branch_token, repo_token):
111
 
        """Set the content of branch.conf.
112
 
 
113
 
        The body is not utf8 decoded - its the literal bytestream for disk.
114
 
        """
115
 
        self._branch = branch
116
 
        self._branch_token = branch_token
117
 
        self._repo_token = repo_token
118
 
        # Signal we want a body
119
 
        return None
120
 
 
121
 
    def do_body(self, body_bytes):
122
 
        self._branch.repository.lock_write(token=self._repo_token)
123
 
        try:
124
 
            self._branch.lock_write(token=self._branch_token)
125
 
            try:
126
 
                self._branch.control_transport.put_bytes(
127
 
                    'branch.conf', body_bytes)
128
 
            finally:
129
 
                self._branch.unlock()
130
 
        finally:
131
 
            self._branch.repository.unlock()
132
 
        return SuccessfulSmartServerResponse(('ok', ))
133
 
 
134
 
 
135
 
class SmartServerBranchGetParent(SmartServerBranchRequest):
136
 
 
137
 
    def do_with_branch(self, branch):
138
 
        """Return the parent of branch."""
139
 
        parent = branch._get_parent_location() or ''
140
 
        return SuccessfulSmartServerResponse((parent,))
141
 
 
142
 
 
143
 
class SmartServerBranchGetTagsBytes(SmartServerBranchRequest):
144
 
 
145
 
    def do_with_branch(self, branch):
146
 
        """Return the _get_tags_bytes for a branch."""
147
 
        bytes = branch._get_tags_bytes()
148
 
        return SuccessfulSmartServerResponse((bytes,))
149
 
 
150
 
 
151
 
class SmartServerBranchSetTagsBytes(SmartServerLockedBranchRequest):
152
 
 
153
 
    def __init__(self, backing_transport, root_client_path='/', jail_root=None):
154
 
        SmartServerLockedBranchRequest.__init__(
155
 
            self, backing_transport, root_client_path, jail_root)
156
 
        self.locked = False
157
 
        
158
 
    def do_with_locked_branch(self, branch):
159
 
        """Call _set_tags_bytes for a branch.
160
 
 
161
 
        New in 1.18.
162
 
        """
163
 
        # We need to keep this branch locked until we get a body with the tags
164
 
        # bytes.
165
 
        self.branch = branch
166
 
        self.branch.lock_write()
167
 
        self.locked = True
168
 
 
169
 
    def do_body(self, bytes):
170
 
        self.branch._set_tags_bytes(bytes)
171
 
        return SuccessfulSmartServerResponse(())
172
 
 
173
 
    def do_end(self):
174
 
        # TODO: this request shouldn't have to do this housekeeping manually.
175
 
        # Some of this logic probably belongs in a base class.
176
 
        if not self.locked:
177
 
            # We never acquired the branch successfully in the first place, so
178
 
            # there's nothing more to do.
179
 
            return
180
 
        try:
181
 
            return SmartServerLockedBranchRequest.do_end(self)
182
 
        finally:
183
 
            # Only try unlocking if we locked successfully in the first place
184
 
            self.branch.unlock()
185
 
 
186
 
 
187
 
class SmartServerBranchHeadsToFetch(SmartServerBranchRequest):
188
 
 
189
 
    def do_with_branch(self, branch):
190
 
        """Return the heads-to-fetch for a Branch as two bencoded lists.
191
 
        
192
 
        See Branch.heads_to_fetch.
193
 
 
194
 
        New in 2.4.
195
 
        """
196
 
        must_fetch, if_present_fetch = branch.heads_to_fetch()
197
 
        return SuccessfulSmartServerResponse(
198
 
            (list(must_fetch), list(if_present_fetch)))
199
 
 
200
 
 
201
 
class SmartServerBranchRequestGetStackedOnURL(SmartServerBranchRequest):
202
 
 
203
 
    def do_with_branch(self, branch):
204
 
        stacked_on_url = branch.get_stacked_on_url()
205
 
        return SuccessfulSmartServerResponse(('ok', stacked_on_url))
206
 
 
207
 
 
208
95
class SmartServerRequestRevisionHistory(SmartServerBranchRequest):
209
96
 
210
97
    def do_with_branch(self, branch):
213
100
        The revision list is returned as the body content,
214
101
        with each revision utf8 encoded and \x00 joined.
215
102
        """
216
 
        branch.lock_read()
217
 
        try:
218
 
            graph = branch.repository.get_graph()
219
 
            stop_revisions = (None, _mod_revision.NULL_REVISION)
220
 
            history = list(graph.iter_lefthand_ancestry(
221
 
                branch.last_revision(), stop_revisions))
222
 
        finally:
223
 
            branch.unlock()
224
103
        return SuccessfulSmartServerResponse(
225
 
            ('ok', ), ('\x00'.join(reversed(history))))
 
104
            ('ok', ), ('\x00'.join(branch.revision_history())))
226
105
 
227
106
 
228
107
class SmartServerBranchRequestLastRevisionInfo(SmartServerBranchRequest):
229
 
 
 
108
    
230
109
    def do_with_branch(self, branch):
231
110
        """Return branch.last_revision_info().
232
 
 
 
111
        
233
112
        The revno is encoded in decimal, the revision_id is encoded as utf8.
234
113
        """
235
114
        revno, last_revision = branch.last_revision_info()
236
115
        return SuccessfulSmartServerResponse(('ok', str(revno), last_revision))
237
116
 
238
117
 
239
 
class SmartServerBranchRequestRevisionIdToRevno(SmartServerBranchRequest):
240
 
 
241
 
    def do_with_branch(self, branch, revid):
242
 
        """Return branch.revision_id_to_revno().
243
 
 
244
 
        New in 2.5.
245
 
 
246
 
        The revno is encoded in decimal, the revision_id is encoded as utf8.
247
 
        """
248
 
        try:
249
 
            dotted_revno = branch.revision_id_to_dotted_revno(revid)
250
 
        except errors.NoSuchRevision:
251
 
            return FailedSmartServerResponse(('NoSuchRevision', revid))
252
 
        return SuccessfulSmartServerResponse(
253
 
            ('ok', ) + tuple(map(str, dotted_revno)))
254
 
 
255
 
 
256
118
class SmartServerSetTipRequest(SmartServerLockedBranchRequest):
257
119
    """Base class for handling common branch request logic for requests that
258
120
    update the branch tip.
268
130
            return FailedSmartServerResponse(('TipChangeRejected', msg))
269
131
 
270
132
 
271
 
class SmartServerBranchRequestSetConfigOption(SmartServerLockedBranchRequest):
272
 
    """Set an option in the branch configuration."""
273
 
 
274
 
    def do_with_locked_branch(self, branch, value, name, section):
275
 
        if not section:
276
 
            section = None
277
 
        branch._get_config().set_option(value.decode('utf8'), name, section)
278
 
        return SuccessfulSmartServerResponse(())
279
 
 
280
 
 
281
 
class SmartServerBranchRequestSetConfigOptionDict(SmartServerLockedBranchRequest):
282
 
    """Set an option in the branch configuration.
283
 
    
284
 
    New in 2.2.
285
 
    """
286
 
 
287
 
    def do_with_locked_branch(self, branch, value_dict, name, section):
288
 
        utf8_dict = bencode.bdecode(value_dict)
289
 
        value_dict = {}
290
 
        for key, value in utf8_dict.items():
291
 
            value_dict[key.decode('utf8')] = value.decode('utf8')
292
 
        if not section:
293
 
            section = None
294
 
        branch._get_config().set_option(value_dict, name, section)
295
 
        return SuccessfulSmartServerResponse(())
296
 
 
297
 
 
298
133
class SmartServerBranchRequestSetLastRevision(SmartServerSetTipRequest):
299
 
 
 
134
    
300
135
    def do_tip_change_with_locked_branch(self, branch, new_last_revision_id):
301
136
        if new_last_revision_id == 'null:':
302
 
            branch.set_last_revision_info(0, new_last_revision_id)
 
137
            branch.set_revision_history([])
303
138
        else:
304
139
            if not branch.repository.has_revision(new_last_revision_id):
305
140
                return FailedSmartServerResponse(
306
141
                    ('NoSuchRevision', new_last_revision_id))
307
 
            branch.generate_revision_history(new_last_revision_id, None, None)
 
142
            branch.generate_revision_history(new_last_revision_id)
308
143
        return SuccessfulSmartServerResponse(('ok',))
309
144
 
310
145
 
311
146
class SmartServerBranchRequestSetLastRevisionEx(SmartServerSetTipRequest):
312
 
 
 
147
    
313
148
    def do_tip_change_with_locked_branch(self, branch, new_last_revision_id,
314
149
            allow_divergence, allow_overwrite_descendant):
315
150
        """Set the last revision of the branch.
316
151
 
317
152
        New in 1.6.
318
 
 
 
153
        
319
154
        :param new_last_revision_id: the revision ID to set as the last
320
155
            revision of the branch.
321
156
        :param allow_divergence: A flag.  If non-zero, change the revision ID
362
197
 
363
198
    New in bzrlib 1.4.
364
199
    """
365
 
 
 
200
    
366
201
    def do_tip_change_with_locked_branch(self, branch, new_revno,
367
202
            new_last_revision_id):
368
203
        try:
373
208
        return SuccessfulSmartServerResponse(('ok',))
374
209
 
375
210
 
376
 
class SmartServerBranchRequestSetParentLocation(SmartServerLockedBranchRequest):
377
 
    """Set the parent location for a branch.
378
 
    
379
 
    Takes a location to set, which must be utf8 encoded.
380
 
    """
381
 
 
382
 
    def do_with_locked_branch(self, branch, location):
383
 
        branch._set_parent_location(location)
384
 
        return SuccessfulSmartServerResponse(())
385
 
 
386
 
 
387
211
class SmartServerBranchRequestLockWrite(SmartServerBranchRequest):
388
 
 
 
212
    
389
213
    def do_with_branch(self, branch, branch_token='', repo_token=''):
390
214
        if branch_token == '':
391
215
            branch_token = None
392
216
        if repo_token == '':
393
217
            repo_token = None
394
218
        try:
395
 
            repo_token = branch.repository.lock_write(
396
 
                token=repo_token).repository_token
 
219
            repo_token = branch.repository.lock_write(token=repo_token)
397
220
            try:
398
 
                branch_token = branch.lock_write(
399
 
                    token=branch_token).branch_token
 
221
                branch_token = branch.lock_write(token=branch_token)
400
222
            finally:
401
223
                # this leaves the repository with 1 lock
402
224
                branch.repository.unlock()
433
255
        branch.dont_leave_lock_in_place()
434
256
        branch.unlock()
435
257
        return SuccessfulSmartServerResponse(('ok',))
436
 
 
437
 
 
438
 
class SmartServerBranchRequestGetPhysicalLockStatus(SmartServerBranchRequest):
439
 
    """Get the physical lock status for a branch.
440
 
 
441
 
    New in 2.5.
442
 
    """
443
 
 
444
 
    def do_with_branch(self, branch):
445
 
        if branch.get_physical_lock_status():
446
 
            return SuccessfulSmartServerResponse(('yes',))
447
 
        else:
448
 
            return SuccessfulSmartServerResponse(('no',))
 
258