~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lockable_files.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-10-24 12:49:17 UTC
  • mfrom: (2935.1.1 ianc-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20071024124917-xb75eckyxx6vkrlg
Makefile fixes - hooks.html generation & allow python to be overridden (Ian Clatworthy)

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
import bzrlib.errors as errors
25
25
from bzrlib.errors import BzrError
26
26
from bzrlib.osutils import file_iterator, safe_unicode
27
 
from bzrlib.symbol_versioning import (deprecated_method, 
28
 
        zero_eight)
 
27
from bzrlib.symbol_versioning import (deprecated_method,
 
28
        )
29
29
from bzrlib.trace import mutter, note
30
30
import bzrlib.transactions as transactions
31
31
import bzrlib.urlutils as urlutils
144
144
        """Return location relative to branch."""
145
145
        return self._transport.abspath(self._escape(file_or_path))
146
146
 
147
 
    @deprecated_method(zero_eight)
148
 
    def controlfile(self, file_or_path, mode='r'):
149
 
        """Open a control file for this branch.
150
 
 
151
 
        There are two classes of file in a lockable directory: text
152
 
        and binary.  binary files are untranslated byte streams.  Text
153
 
        control files are stored with Unix newlines and in UTF-8, even
154
 
        if the platform or locale defaults are different.
155
 
 
156
 
        Such files are not openable in write mode : they are managed via
157
 
        put and put_utf8 which atomically replace old versions using
158
 
        atomicfile.
159
 
        """
160
 
 
161
 
        relpath = self._escape(file_or_path)
162
 
        # TODO: codecs.open() buffers linewise, so it was overloaded with
163
 
        # a much larger buffer, do we need to do the same for getreader/getwriter?
164
 
        if mode == 'rb': 
165
 
            return self.get(relpath)
166
 
        elif mode == 'wb':
167
 
            raise BzrError("Branch.controlfile(mode='wb') is not supported, use put[_utf8]")
168
 
        elif mode == 'r':
169
 
            return self.get_utf8(relpath)
170
 
        elif mode == 'w':
171
 
            raise BzrError("Branch.controlfile(mode='w') is not supported, use put[_utf8]")
172
 
        else:
173
 
            raise BzrError("invalid controlfile mode %r" % mode)
174
 
 
175
147
    @needs_read_lock
176
148
    def get(self, relpath):
177
149
        """Get a file as a bytestream."""
193
165
                     directory
194
166
        :param f: A file-like or string object whose contents should be copied.
195
167
        """
196
 
        self._transport.put(self._escape(path), file, mode=self._file_mode)
 
168
        self._transport.put_file(self._escape(path), file, mode=self._file_mode)
 
169
 
 
170
    @needs_write_lock
 
171
    def put_bytes(self, path, a_string):
 
172
        """Write a string of bytes.
 
173
 
 
174
        :param path: The path to put the bytes, relative to the transport root.
 
175
        :param string: A string object, whose exact bytes are to be copied.
 
176
        """
 
177
        self._transport.put_bytes(self._escape(path), a_string,
 
178
                                  mode=self._file_mode)
197
179
 
198
180
    @needs_write_lock
199
181
    def put_utf8(self, path, a_string):
200
182
        """Write a string, encoding as utf-8.
201
183
 
202
184
        :param path: The path to put the string, relative to the transport root.
203
 
        :param string: A file-like or string object whose contents should be copied.
 
185
        :param string: A string or unicode object whose contents should be copied.
204
186
        """
205
187
        # IterableFile would not be needed if Transport.put took iterables
206
188
        # instead of files.  ADHB 2005-12-25
210
192
        # these are valuable files which should have exact contents.
211
193
        if not isinstance(a_string, basestring):
212
194
            raise errors.BzrBadParameterNotString(a_string)
213
 
        self.put(path, StringIO(a_string.encode('utf-8')))
214
 
 
215
 
    def lock_write(self):
 
195
        self.put_bytes(path, a_string.encode('utf-8'))
 
196
 
 
197
    def leave_in_place(self):
 
198
        """Set this LockableFiles to not clear the physical lock on unlock."""
 
199
        self._lock.leave_in_place()
 
200
 
 
201
    def dont_leave_in_place(self):
 
202
        """Set this LockableFiles to clear the physical lock on unlock."""
 
203
        self._lock.dont_leave_in_place()
 
204
 
 
205
    def lock_write(self, token=None):
 
206
        """Lock this group of files for writing.
 
207
        
 
208
        :param token: if this is already locked, then lock_write will fail
 
209
            unless the token matches the existing lock.
 
210
        :returns: a token if this instance supports tokens, otherwise None.
 
211
        :raises TokenLockingNotSupported: when a token is given but this
 
212
            instance doesn't support using token locks.
 
213
        :raises MismatchedToken: if the specified token doesn't match the token
 
214
            of the existing lock.
 
215
 
 
216
        A token should be passed in if you know that you have locked the object
 
217
        some other way, and need to synchronise this object's state with that
 
218
        fact.
 
219
        """
216
220
        # mutter("lock write: %s (%s)", self, self._lock_count)
217
221
        # TODO: Upgrade locking to support using a Transport,
218
222
        # and potentially a remote locking protocol
219
223
        if self._lock_mode:
220
224
            if self._lock_mode != 'w' or not self.get_transaction().writeable():
221
225
                raise errors.ReadOnlyError(self)
 
226
            self._lock.validate_token(token)
222
227
            self._lock_count += 1
 
228
            return self._token_from_lock
223
229
        else:
224
 
            self._lock.lock_write()
 
230
            token_from_lock = self._lock.lock_write(token=token)
225
231
            #note('write locking %s', self)
226
232
            #traceback.print_stack()
227
233
            self._lock_mode = 'w'
228
234
            self._lock_count = 1
229
235
            self._set_transaction(transactions.WriteTransaction())
 
236
            self._token_from_lock = token_from_lock
 
237
            return token_from_lock
230
238
 
231
239
    def lock_read(self):
232
240
        # mutter("lock read: %s (%s)", self, self._lock_count)
323
331
    def break_lock(self):
324
332
        raise NotImplementedError(self.break_lock)
325
333
 
326
 
    def lock_write(self):
 
334
    def leave_in_place(self):
 
335
        raise NotImplementedError(self.leave_in_place)
 
336
 
 
337
    def dont_leave_in_place(self):
 
338
        raise NotImplementedError(self.dont_leave_in_place)
 
339
 
 
340
    def lock_write(self, token=None):
 
341
        if token is not None:
 
342
            raise errors.TokenLockingNotSupported(self)
327
343
        self._lock = self._transport.lock_write(self._escaped_name)
328
344
 
329
345
    def lock_read(self):
339
355
    def create(self, mode=None):
340
356
        """Create lock mechanism"""
341
357
        # for old-style locks, create the file now
342
 
        self._transport.put(self._escaped_name, StringIO(), 
 
358
        self._transport.put_bytes(self._escaped_name, '',
343
359
                            mode=self._file_modebits)
 
360
 
 
361
    def validate_token(self, token):
 
362
        if token is not None:
 
363
            raise errors.TokenLockingNotSupported(self)
 
364