/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: John Arbash Meinel
  • Date: 2009-03-06 20:42:40 UTC
  • mto: This revision was merged to the branch mainline in revision 4088.
  • Revision ID: john@arbash-meinel.com-20090306204240-mzjavv31z3gu1x7i
Fix a small bug in setup.py when an extension fails to build

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
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
 
16
 
 
17
"""Server-side branch related request implmentations."""
 
18
 
 
19
 
 
20
from bzrlib import errors
 
21
from bzrlib.bzrdir import BzrDir
 
22
from bzrlib.smart.request import (
 
23
    FailedSmartServerResponse,
 
24
    SmartServerRequest,
 
25
    SuccessfulSmartServerResponse,
 
26
    )
 
27
 
 
28
 
 
29
class SmartServerBranchRequest(SmartServerRequest):
 
30
    """Base class for handling common branch request logic.
 
31
    """
 
32
 
 
33
    def do(self, path, *args):
 
34
        """Execute a request for a branch at path.
 
35
 
 
36
        All Branch requests take a path to the branch as their first argument.
 
37
 
 
38
        If the branch is a branch reference, NotBranchError is raised.
 
39
 
 
40
        :param path: The path for the repository as received from the
 
41
            client.
 
42
        :return: A SmartServerResponse from self.do_with_branch().
 
43
        """
 
44
        transport = self.transport_from_client_path(path)
 
45
        bzrdir = BzrDir.open_from_transport(transport)
 
46
        if bzrdir.get_branch_reference() is not None:
 
47
            raise errors.NotBranchError(transport.base)
 
48
        branch = bzrdir.open_branch()
 
49
        return self.do_with_branch(branch, *args)
 
50
 
 
51
 
 
52
class SmartServerLockedBranchRequest(SmartServerBranchRequest):
 
53
    """Base class for handling common branch request logic for requests that
 
54
    need a write lock.
 
55
    """
 
56
 
 
57
    def do_with_branch(self, branch, branch_token, repo_token, *args):
 
58
        """Execute a request for a branch.
 
59
 
 
60
        A write lock will be acquired with the given tokens for the branch and
 
61
        repository locks.  The lock will be released once the request is
 
62
        processed.  The physical lock state won't be changed.
 
63
        """
 
64
        # XXX: write a test for LockContention
 
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()
 
74
 
 
75
 
 
76
class SmartServerBranchGetConfigFile(SmartServerBranchRequest):
 
77
 
 
78
    def do_with_branch(self, branch):
 
79
        """Return the content of branch.conf
 
80
 
 
81
        The body is not utf8 decoded - its the literal bytestream from disk.
 
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.
 
88
        try:
 
89
            content = branch._transport.get_bytes('branch.conf')
 
90
        except errors.NoSuchFile:
 
91
            content = ''
 
92
        return SuccessfulSmartServerResponse( ('ok', ), content)
 
93
 
 
94
 
 
95
class SmartServerBranchGetParent(SmartServerBranchRequest):
 
96
 
 
97
    def do_with_branch(self, branch):
 
98
        """Return the parent of branch."""
 
99
        parent = branch._get_parent_location() or ''
 
100
        return SuccessfulSmartServerResponse((parent,))
 
101
 
 
102
 
 
103
class SmartServerBranchRequestGetStackedOnURL(SmartServerBranchRequest):
 
104
 
 
105
    def do_with_branch(self, branch):
 
106
        stacked_on_url = branch.get_stacked_on_url()
 
107
        return SuccessfulSmartServerResponse(('ok', stacked_on_url))
 
108
 
 
109
 
 
110
class SmartServerRequestRevisionHistory(SmartServerBranchRequest):
 
111
 
 
112
    def do_with_branch(self, branch):
 
113
        """Get the revision history for the branch.
 
114
 
 
115
        The revision list is returned as the body content,
 
116
        with each revision utf8 encoded and \x00 joined.
 
117
        """
 
118
        return SuccessfulSmartServerResponse(
 
119
            ('ok', ), ('\x00'.join(branch.revision_history())))
 
120
 
 
121
 
 
122
class SmartServerBranchRequestLastRevisionInfo(SmartServerBranchRequest):
 
123
 
 
124
    def do_with_branch(self, branch):
 
125
        """Return branch.last_revision_info().
 
126
 
 
127
        The revno is encoded in decimal, the revision_id is encoded as utf8.
 
128
        """
 
129
        revno, last_revision = branch.last_revision_info()
 
130
        return SuccessfulSmartServerResponse(('ok', str(revno), last_revision))
 
131
 
 
132
 
 
133
class SmartServerSetTipRequest(SmartServerLockedBranchRequest):
 
134
    """Base class for handling common branch request logic for requests that
 
135
    update the branch tip.
 
136
    """
 
137
 
 
138
    def do_with_locked_branch(self, branch, *args):
 
139
        try:
 
140
            return self.do_tip_change_with_locked_branch(branch, *args)
 
141
        except errors.TipChangeRejected, e:
 
142
            msg = e.msg
 
143
            if isinstance(msg, unicode):
 
144
                msg = msg.encode('utf-8')
 
145
            return FailedSmartServerResponse(('TipChangeRejected', msg))
 
146
 
 
147
 
 
148
class SmartServerBranchRequestSetLastRevision(SmartServerSetTipRequest):
 
149
 
 
150
    def do_tip_change_with_locked_branch(self, branch, new_last_revision_id):
 
151
        if new_last_revision_id == 'null:':
 
152
            branch.set_revision_history([])
 
153
        else:
 
154
            if not branch.repository.has_revision(new_last_revision_id):
 
155
                return FailedSmartServerResponse(
 
156
                    ('NoSuchRevision', new_last_revision_id))
 
157
            branch.set_revision_history(branch._lefthand_history(
 
158
                new_last_revision_id, None, None))
 
159
        return SuccessfulSmartServerResponse(('ok',))
 
160
 
 
161
 
 
162
class SmartServerBranchRequestSetLastRevisionEx(SmartServerSetTipRequest):
 
163
 
 
164
    def do_tip_change_with_locked_branch(self, branch, new_last_revision_id,
 
165
            allow_divergence, allow_overwrite_descendant):
 
166
        """Set the last revision of the branch.
 
167
 
 
168
        New in 1.6.
 
169
 
 
170
        :param new_last_revision_id: the revision ID to set as the last
 
171
            revision of the branch.
 
172
        :param allow_divergence: A flag.  If non-zero, change the revision ID
 
173
            even if the new_last_revision_id's ancestry has diverged from the
 
174
            current last revision.  If zero, a 'Diverged' error will be
 
175
            returned if new_last_revision_id is not a descendant of the current
 
176
            last revision.
 
177
        :param allow_overwrite_descendant:  A flag.  If zero and
 
178
            new_last_revision_id is not a descendant of the current last
 
179
            revision, then the last revision will not be changed.  If non-zero
 
180
            and there is no divergence, then the last revision is always
 
181
            changed.
 
182
 
 
183
        :returns: on success, a tuple of ('ok', revno, revision_id), where
 
184
            revno and revision_id are the new values of the current last
 
185
            revision info.  The revision_id might be different to the
 
186
            new_last_revision_id if allow_overwrite_descendant was not set.
 
187
        """
 
188
        do_not_overwrite_descendant = not allow_overwrite_descendant
 
189
        try:
 
190
            last_revno, last_rev = branch.last_revision_info()
 
191
            graph = branch.repository.get_graph()
 
192
            if not allow_divergence or do_not_overwrite_descendant:
 
193
                relation = branch._revision_relations(
 
194
                    last_rev, new_last_revision_id, graph)
 
195
                if relation == 'diverged' and not allow_divergence:
 
196
                    return FailedSmartServerResponse(('Diverged',))
 
197
                if relation == 'a_descends_from_b' and do_not_overwrite_descendant:
 
198
                    return SuccessfulSmartServerResponse(
 
199
                        ('ok', last_revno, last_rev))
 
200
            new_revno = graph.find_distance_to_null(
 
201
                new_last_revision_id, [(last_rev, last_revno)])
 
202
            branch.set_last_revision_info(new_revno, new_last_revision_id)
 
203
        except errors.GhostRevisionsHaveNoRevno:
 
204
            return FailedSmartServerResponse(
 
205
                ('NoSuchRevision', new_last_revision_id))
 
206
        return SuccessfulSmartServerResponse(
 
207
            ('ok', new_revno, new_last_revision_id))
 
208
 
 
209
 
 
210
class SmartServerBranchRequestSetLastRevisionInfo(SmartServerSetTipRequest):
 
211
    """Branch.set_last_revision_info.  Sets the revno and the revision ID of
 
212
    the specified branch.
 
213
 
 
214
    New in bzrlib 1.4.
 
215
    """
 
216
 
 
217
    def do_tip_change_with_locked_branch(self, branch, new_revno,
 
218
            new_last_revision_id):
 
219
        try:
 
220
            branch.set_last_revision_info(int(new_revno), new_last_revision_id)
 
221
        except errors.NoSuchRevision:
 
222
            return FailedSmartServerResponse(
 
223
                ('NoSuchRevision', new_last_revision_id))
 
224
        return SuccessfulSmartServerResponse(('ok',))
 
225
 
 
226
 
 
227
class SmartServerBranchRequestLockWrite(SmartServerBranchRequest):
 
228
 
 
229
    def do_with_branch(self, branch, branch_token='', repo_token=''):
 
230
        if branch_token == '':
 
231
            branch_token = None
 
232
        if repo_token == '':
 
233
            repo_token = None
 
234
        try:
 
235
            repo_token = branch.repository.lock_write(token=repo_token)
 
236
            try:
 
237
                branch_token = branch.lock_write(token=branch_token)
 
238
            finally:
 
239
                # this leaves the repository with 1 lock
 
240
                branch.repository.unlock()
 
241
        except errors.LockContention:
 
242
            return FailedSmartServerResponse(('LockContention',))
 
243
        except errors.TokenMismatch:
 
244
            return FailedSmartServerResponse(('TokenMismatch',))
 
245
        except errors.UnlockableTransport:
 
246
            return FailedSmartServerResponse(('UnlockableTransport',))
 
247
        except errors.LockFailed, e:
 
248
            return FailedSmartServerResponse(('LockFailed', str(e.lock), str(e.why)))
 
249
        if repo_token is None:
 
250
            repo_token = ''
 
251
        else:
 
252
            branch.repository.leave_lock_in_place()
 
253
        branch.leave_lock_in_place()
 
254
        branch.unlock()
 
255
        return SuccessfulSmartServerResponse(('ok', branch_token, repo_token))
 
256
 
 
257
 
 
258
class SmartServerBranchRequestUnlock(SmartServerBranchRequest):
 
259
 
 
260
    def do_with_branch(self, branch, branch_token, repo_token):
 
261
        try:
 
262
            branch.repository.lock_write(token=repo_token)
 
263
            try:
 
264
                branch.lock_write(token=branch_token)
 
265
            finally:
 
266
                branch.repository.unlock()
 
267
        except errors.TokenMismatch:
 
268
            return FailedSmartServerResponse(('TokenMismatch',))
 
269
        if repo_token:
 
270
            branch.repository.dont_leave_lock_in_place()
 
271
        branch.dont_leave_lock_in_place()
 
272
        branch.unlock()
 
273
        return SuccessfulSmartServerResponse(('ok',))
 
274