/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/smart/branch.py

  • Committer: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

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
16
16
 
17
17
"""Server-side branch related request implmentations."""
18
18
 
19
 
from __future__ import absolute_import
20
19
 
21
 
from ... import (
22
 
    bencode,
23
 
    errors,
24
 
    revision as _mod_revision,
25
 
    )
26
 
from ...controldir import ControlDir
27
 
from ...sixish import text_type
28
 
from .request import (
 
20
from bzrlib import errors
 
21
from bzrlib.bzrdir import BzrDir
 
22
from bzrlib.smart.request import (
29
23
    FailedSmartServerResponse,
30
24
    SmartServerRequest,
31
25
    SuccessfulSmartServerResponse,
48
42
        :return: A SmartServerResponse from self.do_with_branch().
49
43
        """
50
44
        transport = self.transport_from_client_path(path)
51
 
        controldir = ControlDir.open_from_transport(transport)
52
 
        if controldir.get_branch_reference() is not None:
 
45
        bzrdir = BzrDir.open_from_transport(transport)
 
46
        if bzrdir.get_branch_reference() is not None:
53
47
            raise errors.NotBranchError(transport.base)
54
 
        branch = controldir.open_branch(ignore_fallbacks=True)
 
48
        branch = bzrdir.open_branch(ignore_fallbacks=True)
55
49
        return self.do_with_branch(branch, *args)
56
50
 
57
51
 
68
62
        processed.  The physical lock state won't be changed.
69
63
        """
70
64
        # XXX: write a test for LockContention
71
 
        with branch.repository.lock_write(token=repo_token), \
72
 
                branch.lock_write(token=branch_token):
73
 
            return self.do_with_locked_branch(branch, *args)
74
 
 
75
 
 
76
 
class SmartServerBranchBreakLock(SmartServerBranchRequest):
77
 
 
78
 
    def do_with_branch(self, branch):
79
 
        """Break a branch lock.
80
 
        """
81
 
        branch.break_lock()
82
 
        return SuccessfulSmartServerResponse((b'ok', ), )
 
65
        branch.repository.lock_write(token=repo_token)
 
66
        try:
 
67
            branch.lock_write(token=branch_token)
 
68
            try:
 
69
                return self.do_with_locked_branch(branch, *args)
 
70
            finally:
 
71
                branch.unlock()
 
72
        finally:
 
73
            branch.repository.unlock()
83
74
 
84
75
 
85
76
class SmartServerBranchGetConfigFile(SmartServerBranchRequest):
90
81
        The body is not utf8 decoded - its the literal bytestream from disk.
91
82
        """
92
83
        try:
93
 
            content = branch.control_transport.get_bytes('branch.conf')
 
84
            content = branch._transport.get_bytes('branch.conf')
94
85
        except errors.NoSuchFile:
95
 
            content = b''
96
 
        return SuccessfulSmartServerResponse((b'ok', ), content)
97
 
 
98
 
 
99
 
class SmartServerBranchPutConfigFile(SmartServerBranchRequest):
100
 
    """Set the configuration data for a branch.
101
 
 
102
 
    New in 2.5.
103
 
    """
104
 
 
105
 
    def do_with_branch(self, branch, branch_token, repo_token):
106
 
        """Set the content of branch.conf.
107
 
 
108
 
        The body is not utf8 decoded - its the literal bytestream for disk.
109
 
        """
110
 
        self._branch = branch
111
 
        self._branch_token = branch_token
112
 
        self._repo_token = repo_token
113
 
        # Signal we want a body
114
 
        return None
115
 
 
116
 
    def do_body(self, body_bytes):
117
 
        with self._branch.repository.lock_write(token=self._repo_token), \
118
 
                self._branch.lock_write(token=self._branch_token):
119
 
            self._branch.control_transport.put_bytes(
120
 
                'branch.conf', body_bytes)
121
 
        return SuccessfulSmartServerResponse((b'ok', ))
 
86
            content = ''
 
87
        return SuccessfulSmartServerResponse( ('ok', ), content)
122
88
 
123
89
 
124
90
class SmartServerBranchGetParent(SmartServerBranchRequest):
126
92
    def do_with_branch(self, branch):
127
93
        """Return the parent of branch."""
128
94
        parent = branch._get_parent_location() or ''
129
 
        return SuccessfulSmartServerResponse((parent.encode('utf-8'),))
 
95
        return SuccessfulSmartServerResponse((parent,))
130
96
 
131
97
 
132
98
class SmartServerBranchGetTagsBytes(SmartServerBranchRequest):
143
109
        SmartServerLockedBranchRequest.__init__(
144
110
            self, backing_transport, root_client_path, jail_root)
145
111
        self.locked = False
146
 
 
 
112
        
147
113
    def do_with_locked_branch(self, branch):
148
114
        """Call _set_tags_bytes for a branch.
149
115
 
173
139
            self.branch.unlock()
174
140
 
175
141
 
176
 
class SmartServerBranchHeadsToFetch(SmartServerBranchRequest):
177
 
 
178
 
    def do_with_branch(self, branch):
179
 
        """Return the heads-to-fetch for a Branch as two bencoded lists.
180
 
 
181
 
        See Branch.heads_to_fetch.
182
 
 
183
 
        New in 2.4.
184
 
        """
185
 
        must_fetch, if_present_fetch = branch.heads_to_fetch()
186
 
        return SuccessfulSmartServerResponse(
187
 
            (list(must_fetch), list(if_present_fetch)))
188
 
 
189
 
 
190
142
class SmartServerBranchRequestGetStackedOnURL(SmartServerBranchRequest):
191
143
 
192
144
    def do_with_branch(self, branch):
193
145
        stacked_on_url = branch.get_stacked_on_url()
194
 
        return SuccessfulSmartServerResponse((b'ok', stacked_on_url.encode('ascii')))
 
146
        return SuccessfulSmartServerResponse(('ok', stacked_on_url))
195
147
 
196
148
 
197
149
class SmartServerRequestRevisionHistory(SmartServerBranchRequest):
202
154
        The revision list is returned as the body content,
203
155
        with each revision utf8 encoded and \x00 joined.
204
156
        """
205
 
        with branch.lock_read():
206
 
            graph = branch.repository.get_graph()
207
 
            stop_revisions = (None, _mod_revision.NULL_REVISION)
208
 
            history = list(graph.iter_lefthand_ancestry(
209
 
                branch.last_revision(), stop_revisions))
210
157
        return SuccessfulSmartServerResponse(
211
 
            (b'ok', ), (b'\x00'.join(reversed(history))))
 
158
            ('ok', ), ('\x00'.join(branch.revision_history())))
212
159
 
213
160
 
214
161
class SmartServerBranchRequestLastRevisionInfo(SmartServerBranchRequest):
219
166
        The revno is encoded in decimal, the revision_id is encoded as utf8.
220
167
        """
221
168
        revno, last_revision = branch.last_revision_info()
222
 
        return SuccessfulSmartServerResponse(
223
 
            (b'ok', str(revno).encode('ascii'), last_revision))
224
 
 
225
 
 
226
 
class SmartServerBranchRequestRevisionIdToRevno(SmartServerBranchRequest):
227
 
 
228
 
    def do_with_branch(self, branch, revid):
229
 
        """Return branch.revision_id_to_revno().
230
 
 
231
 
        New in 2.5.
232
 
 
233
 
        The revno is encoded in decimal, the revision_id is encoded as utf8.
234
 
        """
235
 
        try:
236
 
            dotted_revno = branch.revision_id_to_dotted_revno(revid)
237
 
        except errors.NoSuchRevision:
238
 
            return FailedSmartServerResponse((b'NoSuchRevision', revid))
239
 
        return SuccessfulSmartServerResponse(
240
 
            (b'ok', ) + tuple([b'%d' % x for x in dotted_revno]))
 
169
        return SuccessfulSmartServerResponse(('ok', str(revno), last_revision))
241
170
 
242
171
 
243
172
class SmartServerSetTipRequest(SmartServerLockedBranchRequest):
248
177
    def do_with_locked_branch(self, branch, *args):
249
178
        try:
250
179
            return self.do_tip_change_with_locked_branch(branch, *args)
251
 
        except errors.TipChangeRejected as e:
 
180
        except errors.TipChangeRejected, e:
252
181
            msg = e.msg
253
 
            if isinstance(msg, text_type):
 
182
            if isinstance(msg, unicode):
254
183
                msg = msg.encode('utf-8')
255
 
            return FailedSmartServerResponse((b'TipChangeRejected', msg))
 
184
            return FailedSmartServerResponse(('TipChangeRejected', msg))
256
185
 
257
186
 
258
187
class SmartServerBranchRequestSetConfigOption(SmartServerLockedBranchRequest):
261
190
    def do_with_locked_branch(self, branch, value, name, section):
262
191
        if not section:
263
192
            section = None
264
 
        branch._get_config().set_option(
265
 
            value.decode('utf-8'), name.decode('utf-8'),
266
 
            section.decode('utf-8') if section is not None else None)
267
 
        return SuccessfulSmartServerResponse(())
268
 
 
269
 
 
270
 
class SmartServerBranchRequestSetConfigOptionDict(SmartServerLockedBranchRequest):
271
 
    """Set an option in the branch configuration.
272
 
 
273
 
    New in 2.2.
274
 
    """
275
 
 
276
 
    def do_with_locked_branch(self, branch, value_dict, name, section):
277
 
        utf8_dict = bencode.bdecode(value_dict)
278
 
        value_dict = {}
279
 
        for key, value in utf8_dict.items():
280
 
            value_dict[key.decode('utf8')] = value.decode('utf8')
281
 
        if not section:
282
 
            section = None
283
 
        else:
284
 
            section = section.decode('utf-8')
285
 
        branch._get_config().set_option(value_dict, name.decode('utf-8'), section)
 
193
        branch._get_config().set_option(value.decode('utf8'), name, section)
286
194
        return SuccessfulSmartServerResponse(())
287
195
 
288
196
 
289
197
class SmartServerBranchRequestSetLastRevision(SmartServerSetTipRequest):
290
198
 
291
199
    def do_tip_change_with_locked_branch(self, branch, new_last_revision_id):
292
 
        if new_last_revision_id == b'null:':
293
 
            branch.set_last_revision_info(0, new_last_revision_id)
 
200
        if new_last_revision_id == 'null:':
 
201
            branch.set_revision_history([])
294
202
        else:
295
203
            if not branch.repository.has_revision(new_last_revision_id):
296
204
                return FailedSmartServerResponse(
297
 
                    (b'NoSuchRevision', new_last_revision_id))
298
 
            branch.generate_revision_history(new_last_revision_id, None, None)
299
 
        return SuccessfulSmartServerResponse((b'ok',))
 
205
                    ('NoSuchRevision', new_last_revision_id))
 
206
            branch.set_revision_history(branch._lefthand_history(
 
207
                new_last_revision_id, None, None))
 
208
        return SuccessfulSmartServerResponse(('ok',))
300
209
 
301
210
 
302
211
class SmartServerBranchRequestSetLastRevisionEx(SmartServerSetTipRequest):
303
212
 
304
213
    def do_tip_change_with_locked_branch(self, branch, new_last_revision_id,
305
 
                                         allow_divergence, allow_overwrite_descendant):
 
214
            allow_divergence, allow_overwrite_descendant):
306
215
        """Set the last revision of the branch.
307
216
 
308
217
        New in 1.6.
333
242
                relation = branch._revision_relations(
334
243
                    last_rev, new_last_revision_id, graph)
335
244
                if relation == 'diverged' and not allow_divergence:
336
 
                    return FailedSmartServerResponse((b'Diverged',))
 
245
                    return FailedSmartServerResponse(('Diverged',))
337
246
                if relation == 'a_descends_from_b' and do_not_overwrite_descendant:
338
247
                    return SuccessfulSmartServerResponse(
339
 
                        (b'ok', last_revno, last_rev))
 
248
                        ('ok', last_revno, last_rev))
340
249
            new_revno = graph.find_distance_to_null(
341
250
                new_last_revision_id, [(last_rev, last_revno)])
342
251
            branch.set_last_revision_info(new_revno, new_last_revision_id)
343
252
        except errors.GhostRevisionsHaveNoRevno:
344
253
            return FailedSmartServerResponse(
345
 
                (b'NoSuchRevision', new_last_revision_id))
 
254
                ('NoSuchRevision', new_last_revision_id))
346
255
        return SuccessfulSmartServerResponse(
347
 
            (b'ok', new_revno, new_last_revision_id))
 
256
            ('ok', new_revno, new_last_revision_id))
348
257
 
349
258
 
350
259
class SmartServerBranchRequestSetLastRevisionInfo(SmartServerSetTipRequest):
351
260
    """Branch.set_last_revision_info.  Sets the revno and the revision ID of
352
261
    the specified branch.
353
262
 
354
 
    New in breezy 1.4.
 
263
    New in bzrlib 1.4.
355
264
    """
356
265
 
357
266
    def do_tip_change_with_locked_branch(self, branch, new_revno,
358
 
                                         new_last_revision_id):
 
267
            new_last_revision_id):
359
268
        try:
360
269
            branch.set_last_revision_info(int(new_revno), new_last_revision_id)
361
270
        except errors.NoSuchRevision:
362
271
            return FailedSmartServerResponse(
363
 
                (b'NoSuchRevision', new_last_revision_id))
364
 
        return SuccessfulSmartServerResponse((b'ok',))
 
272
                ('NoSuchRevision', new_last_revision_id))
 
273
        return SuccessfulSmartServerResponse(('ok',))
365
274
 
366
275
 
367
276
class SmartServerBranchRequestSetParentLocation(SmartServerLockedBranchRequest):
368
277
    """Set the parent location for a branch.
369
 
 
 
278
    
370
279
    Takes a location to set, which must be utf8 encoded.
371
280
    """
372
281
 
373
282
    def do_with_locked_branch(self, branch, location):
374
 
        branch._set_parent_location(location.decode('utf-8'))
 
283
        branch._set_parent_location(location)
375
284
        return SuccessfulSmartServerResponse(())
376
285
 
377
286
 
378
287
class SmartServerBranchRequestLockWrite(SmartServerBranchRequest):
379
288
 
380
 
    def do_with_branch(self, branch, branch_token=b'', repo_token=b''):
381
 
        if branch_token == b'':
 
289
    def do_with_branch(self, branch, branch_token='', repo_token=''):
 
290
        if branch_token == '':
382
291
            branch_token = None
383
 
        if repo_token == b'':
 
292
        if repo_token == '':
384
293
            repo_token = None
385
294
        try:
386
 
            repo_token = branch.repository.lock_write(
387
 
                token=repo_token).repository_token
 
295
            repo_token = branch.repository.lock_write(token=repo_token)
388
296
            try:
389
 
                branch_token = branch.lock_write(
390
 
                    token=branch_token).token
 
297
                branch_token = branch.lock_write(token=branch_token)
391
298
            finally:
392
299
                # this leaves the repository with 1 lock
393
300
                branch.repository.unlock()
394
301
        except errors.LockContention:
395
 
            return FailedSmartServerResponse((b'LockContention',))
 
302
            return FailedSmartServerResponse(('LockContention',))
396
303
        except errors.TokenMismatch:
397
 
            return FailedSmartServerResponse((b'TokenMismatch',))
 
304
            return FailedSmartServerResponse(('TokenMismatch',))
398
305
        except errors.UnlockableTransport:
399
 
            return FailedSmartServerResponse((b'UnlockableTransport',))
400
 
        except errors.LockFailed as e:
401
 
            return FailedSmartServerResponse((b'LockFailed',
402
 
                                              str(e.lock).encode('utf-8'), str(e.why).encode('utf-8')))
 
306
            return FailedSmartServerResponse(('UnlockableTransport',))
 
307
        except errors.LockFailed, e:
 
308
            return FailedSmartServerResponse(('LockFailed', str(e.lock), str(e.why)))
403
309
        if repo_token is None:
404
 
            repo_token = b''
 
310
            repo_token = ''
405
311
        else:
406
312
            branch.repository.leave_lock_in_place()
407
313
        branch.leave_lock_in_place()
408
314
        branch.unlock()
409
 
        return SuccessfulSmartServerResponse((b'ok', branch_token, repo_token))
 
315
        return SuccessfulSmartServerResponse(('ok', branch_token, repo_token))
410
316
 
411
317
 
412
318
class SmartServerBranchRequestUnlock(SmartServerBranchRequest):
413
319
 
414
320
    def do_with_branch(self, branch, branch_token, repo_token):
415
321
        try:
416
 
            with branch.repository.lock_write(token=repo_token):
 
322
            branch.repository.lock_write(token=repo_token)
 
323
            try:
417
324
                branch.lock_write(token=branch_token)
 
325
            finally:
 
326
                branch.repository.unlock()
418
327
        except errors.TokenMismatch:
419
 
            return FailedSmartServerResponse((b'TokenMismatch',))
 
328
            return FailedSmartServerResponse(('TokenMismatch',))
420
329
        if repo_token:
421
330
            branch.repository.dont_leave_lock_in_place()
422
331
        branch.dont_leave_lock_in_place()
423
332
        branch.unlock()
424
 
        return SuccessfulSmartServerResponse((b'ok',))
425
 
 
426
 
 
427
 
class SmartServerBranchRequestGetPhysicalLockStatus(SmartServerBranchRequest):
428
 
    """Get the physical lock status for a branch.
429
 
 
430
 
    New in 2.5.
431
 
    """
432
 
 
433
 
    def do_with_branch(self, branch):
434
 
        if branch.get_physical_lock_status():
435
 
            return SuccessfulSmartServerResponse((b'yes',))
436
 
        else:
437
 
            return SuccessfulSmartServerResponse((b'no',))
 
333
        return SuccessfulSmartServerResponse(('ok',))
 
334