~bzr-pqm/bzr/bzr.dev

4158.2.1 by Martin Pool
merge back 1.13final
1
# Copyright (C) 2005, 2006, 2008, 2009 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.65.22 by Robert Collins
lockable_files was extracted from branch.py - give it a copyright statement
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.65.22 by Robert Collins
lockable_files was extracted from branch.py - give it a copyright statement
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.65.22 by Robert Collins
lockable_files was extracted from branch.py - give it a copyright statement
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.65.22 by Robert Collins
lockable_files was extracted from branch.py - give it a copyright statement
16
1185.65.29 by Robert Collins
Implement final review suggestions.
17
from cStringIO import StringIO
3535.5.1 by John Arbash Meinel
cleanup a few imports to be lazily loaded.
18
19
from bzrlib.lazy_import import lazy_import
20
lazy_import(globals(), """
1185.65.29 by Robert Collins
Implement final review suggestions.
21
import codecs
3535.5.1 by John Arbash Meinel
cleanup a few imports to be lazily loaded.
22
import warnings
23
24
from bzrlib import (
3468.3.3 by Martin Pool
Fix import
25
    counted_lock,
3535.5.1 by John Arbash Meinel
cleanup a few imports to be lazily loaded.
26
    errors,
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
27
    lock,
3535.5.1 by John Arbash Meinel
cleanup a few imports to be lazily loaded.
28
    osutils,
29
    transactions,
30
    urlutils,
31
    )
32
""")
33
34
from bzrlib.decorators import (
35
    needs_read_lock,
36
    needs_write_lock,
37
    )
3388.2.1 by Martin Pool
Deprecate LockableFiles.get_utf8
38
from bzrlib.symbol_versioning import (
39
    deprecated_in,
40
    deprecated_method,
41
    )
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
42
1185.65.10 by Robert Collins
Rename Controlfiles to LockableFiles.
43
1553.5.41 by Martin Pool
Add new LockableFiles.LockDirStrategy; not used yet
44
# XXX: The tracking here of lock counts and whether the lock is held is
45
# somewhat redundant with what's done in LockDir; the main difference is that
46
# LockableFiles permits reentrancy.
1185.65.27 by Robert Collins
Tweak storage towards mergability.
47
4041.1.5 by Michael Hudson
review comments
48
class _LockWarner(object):
49
    """Hold a counter for a lock and warn if GCed while the count is >= 1.
4041.1.4 by Michael Hudson
this makes more sense
50
51
    This is separate from LockableFiles because putting a __del__ on
52
    LockableFiles can result in uncollectable cycles.
53
    """
54
55
    def __init__(self, repr):
56
        self.lock_count = 0
4041.1.1 by Michael Hudson
this is terrible but it works
57
        self.repr = repr
58
59
    def __del__(self):
4041.1.4 by Michael Hudson
this makes more sense
60
        if self.lock_count >= 1:
4041.1.5 by Michael Hudson
review comments
61
            # There should have been a try/finally to unlock this.
4041.1.1 by Michael Hudson
this is terrible but it works
62
            warnings.warn("%r was gc'd while locked" % self.repr)
4041.1.3 by Michael Hudson
_this_ works
63
4041.1.1 by Michael Hudson
this is terrible but it works
64
1185.66.3 by Aaron Bentley
Renamed ControlFiles to LockableFiles
65
class LockableFiles(object):
1553.5.38 by Martin Pool
More explanation for LockableFiles
66
    """Object representing a set of related files locked within the same scope.
67
68
    These files are used by a WorkingTree, Repository or Branch, and should
69
    generally only be touched by that object.
70
71
    LockableFiles also provides some policy on top of Transport for encoding
72
    control files as utf-8.
73
1553.5.39 by Martin Pool
More lock docs
74
    LockableFiles manage a lock count and can be locked repeatedly by
75
    a single caller.  (The underlying lock implementation generally does not
76
    support this.)
77
1553.5.38 by Martin Pool
More explanation for LockableFiles
78
    Instances of this class are often called control_files.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
79
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
80
    This object builds on top of a Transport, which is used to actually write
81
    the files to disk, and an OSLock or LockDir, which controls how access to
82
    the files is controlled.  The particular type of locking used is set when
83
    the object is constructed.  In older formats OSLocks are used everywhere.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
84
    in newer formats a LockDir is used for Repositories and Branches, and
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
85
    OSLocks for the local filesystem.
3407.2.9 by Martin Pool
doc
86
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
87
    This class is now deprecated; code should move to using the Transport
88
    directly for file operations and using the lock or CountedLock for
3407.2.9 by Martin Pool
doc
89
    locking.
3407.2.19 by Martin Pool
CountedLock should manage lock tokens
90
    
91
    :ivar _lock: The real underlying lock (e.g. a LockDir)
92
    :ivar _counted_lock: A lock decorated with a semaphore, so that it 
93
        can be re-entered.
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
94
    """
1185.65.10 by Robert Collins
Rename Controlfiles to LockableFiles.
95
1553.5.47 by Martin Pool
cleanup LockableFiles
96
    # _lock_mode: None, or 'r' or 'w'
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
97
1553.5.47 by Martin Pool
cleanup LockableFiles
98
    # _lock_count: If _lock_mode is true, a positive count of the number of
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
99
    # times the lock has been taken *by this process*.
100
1553.5.63 by Martin Pool
Lock type is now mandatory for LockableFiles constructor
101
    def __init__(self, transport, lock_name, lock_class):
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
102
        """Create a LockableFiles group
103
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
104
        :param transport: Transport pointing to the directory holding the
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
105
            control files and lock.
106
        :param lock_name: Name of the lock guarding these files.
1553.5.47 by Martin Pool
cleanup LockableFiles
107
        :param lock_class: Class of lock strategy to use: typically
108
            either LockDir or TransportLock.
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
109
        """
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
110
        self._transport = transport
111
        self.lock_name = lock_name
112
        self._transaction = None
1553.5.47 by Martin Pool
cleanup LockableFiles
113
        self._lock_mode = None
4041.1.5 by Michael Hudson
review comments
114
        self._lock_warner = _LockWarner(repr(self))
1685.1.43 by John Arbash Meinel
Bug in lockable files when _find_mode throws
115
        self._find_modes()
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
116
        esc_name = self._escape(lock_name)
1608.2.1 by Martin Pool
[merge] Storage filename escaping
117
        self._lock = lock_class(transport, esc_name,
1553.5.59 by Martin Pool
Pass file/mode bits through to creation of lock files/dirs
118
                                file_modebits=self._file_mode,
119
                                dir_modebits=self._dir_mode)
3468.3.3 by Martin Pool
Fix import
120
        self._counted_lock = counted_lock.CountedLock(self._lock)
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
121
1553.5.60 by Martin Pool
New LockableFiles.create_lock() method
122
    def create_lock(self):
123
        """Create the lock.
124
125
        This should normally be called only when the LockableFiles directory
126
        is first created on disk.
127
        """
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
128
        self._lock.create(mode=self._dir_mode)
1553.5.60 by Martin Pool
New LockableFiles.create_lock() method
129
1553.5.53 by Martin Pool
Add LockableFiles __repr__
130
    def __repr__(self):
131
        return '%s(%r)' % (self.__class__.__name__,
132
                           self._transport)
1185.80.2 by John Arbash Meinel
Traced double locking code to WorkingTree creating its own control files.
133
    def __str__(self):
134
        return 'LockableFiles(%s, %s)' % (self.lock_name, self._transport.base)
135
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
136
    def break_lock(self):
137
        """Break the lock of this lockable files group if it is held.
138
139
        The current ui factory will be used to prompt for user conformation.
140
        """
141
        self._lock.break_lock()
142
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
143
    def _escape(self, file_or_path):
3834.2.2 by Martin Pool
Deprecated LockableFiles._escape
144
        """DEPRECATED: Do not use outside this class"""
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
145
        if not isinstance(file_or_path, basestring):
146
            file_or_path = '/'.join(file_or_path)
147
        if file_or_path == '':
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
148
            return u''
3535.5.1 by John Arbash Meinel
cleanup a few imports to be lazily loaded.
149
        return urlutils.escape(osutils.safe_unicode(file_or_path))
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
150
151
    def _find_modes(self):
3416.2.1 by Martin Pool
Add BzrDir._get_file_mode and _get_dir_mode
152
        """Determine the appropriate modes for files and directories.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
153
3416.2.1 by Martin Pool
Add BzrDir._get_file_mode and _get_dir_mode
154
        :deprecated: Replaced by BzrDir._find_modes.
155
        """
3407.2.19 by Martin Pool
CountedLock should manage lock tokens
156
        # XXX: The properties created by this can be removed or deprecated
157
        # once all the _get_text_store methods etc no longer use them.
158
        # -- mbp 20080512
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
159
        try:
1534.4.28 by Robert Collins
first cut at merge from integration.
160
            st = self._transport.stat('.')
161
        except errors.TransportNotPossible:
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
162
            self._dir_mode = 0755
163
            self._file_mode = 0644
164
        else:
3107.2.1 by John Arbash Meinel
Fix LockableFiles to not use modes that allow the user to write to things they create.
165
            # Check the directory mode, but also make sure the created
166
            # directories and files are read-write for this user. This is
167
            # mostly a workaround for filesystems which lie about being able to
168
            # write to a directory (cygwin & win32)
169
            self._dir_mode = (st.st_mode & 07777) | 00700
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
170
            # Remove the sticky and execute bits for files
171
            self._file_mode = self._dir_mode & ~07111
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
172
3407.2.8 by Martin Pool
Deprecate LockableFiles.controlfilename
173
    @deprecated_method(deprecated_in((1, 6, 0)))
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
174
    def controlfilename(self, file_or_path):
3407.2.8 by Martin Pool
Deprecate LockableFiles.controlfilename
175
        """Return location relative to branch.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
176
3407.2.8 by Martin Pool
Deprecate LockableFiles.controlfilename
177
        :deprecated: Use Transport methods instead.
178
        """
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
179
        return self._transport.abspath(self._escape(file_or_path))
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
180
1185.65.29 by Robert Collins
Implement final review suggestions.
181
    @needs_read_lock
3407.2.1 by Martin Pool
Deprecate LockableFiles.get
182
    @deprecated_method(deprecated_in((1, 5, 0)))
1185.65.29 by Robert Collins
Implement final review suggestions.
183
    def get(self, relpath):
3407.2.1 by Martin Pool
Deprecate LockableFiles.get
184
        """Get a file as a bytestream.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
185
3407.2.1 by Martin Pool
Deprecate LockableFiles.get
186
        :deprecated: Use a Transport instead of LockableFiles.
187
        """
1185.65.29 by Robert Collins
Implement final review suggestions.
188
        relpath = self._escape(relpath)
189
        return self._transport.get(relpath)
190
191
    @needs_read_lock
3388.2.1 by Martin Pool
Deprecate LockableFiles.get_utf8
192
    @deprecated_method(deprecated_in((1, 5, 0)))
1185.65.29 by Robert Collins
Implement final review suggestions.
193
    def get_utf8(self, relpath):
3407.2.1 by Martin Pool
Deprecate LockableFiles.get
194
        """Get a file as a unicode stream.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
195
3407.2.1 by Martin Pool
Deprecate LockableFiles.get
196
        :deprecated: Use a Transport instead of LockableFiles.
197
        """
1185.65.29 by Robert Collins
Implement final review suggestions.
198
        relpath = self._escape(relpath)
199
        # DO NOT introduce an errors=replace here.
200
        return codecs.getreader('utf-8')(self._transport.get(relpath))
201
1185.65.27 by Robert Collins
Tweak storage towards mergability.
202
    @needs_write_lock
3407.2.7 by Martin Pool
Deprecate LockableFiles.put_utf8 and put_bytes.
203
    @deprecated_method(deprecated_in((1, 6, 0)))
1185.65.12 by Robert Collins
Remove the only-used-once put_controlfiles, and change put_controlfile to put and put_utf8.
204
    def put(self, path, file):
205
        """Write a file.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
206
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
207
        :param path: The path to put the file, relative to the .bzr control
208
                     directory
3407.2.7 by Martin Pool
Deprecate LockableFiles.put_utf8 and put_bytes.
209
        :param file: A file-like or string object whose contents should be copied.
210
211
        :deprecated: Use Transport methods instead.
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
212
        """
1955.3.8 by John Arbash Meinel
avoid some deprecation warnings in other parts of the code
213
        self._transport.put_file(self._escape(path), file, mode=self._file_mode)
1185.65.12 by Robert Collins
Remove the only-used-once put_controlfiles, and change put_controlfile to put and put_utf8.
214
1185.65.27 by Robert Collins
Tweak storage towards mergability.
215
    @needs_write_lock
3407.2.7 by Martin Pool
Deprecate LockableFiles.put_utf8 and put_bytes.
216
    @deprecated_method(deprecated_in((1, 6, 0)))
2249.5.11 by John Arbash Meinel
Audit Branch to ensure utf8 revision ids.
217
    def put_bytes(self, path, a_string):
218
        """Write a string of bytes.
219
220
        :param path: The path to put the bytes, relative to the transport root.
3407.2.7 by Martin Pool
Deprecate LockableFiles.put_utf8 and put_bytes.
221
        :param a_string: A string object, whose exact bytes are to be copied.
222
223
        :deprecated: Use Transport methods instead.
2249.5.11 by John Arbash Meinel
Audit Branch to ensure utf8 revision ids.
224
        """
225
        self._transport.put_bytes(self._escape(path), a_string,
226
                                  mode=self._file_mode)
227
228
    @needs_write_lock
3407.2.5 by Martin Pool
Deprecate LockableFiles.put_utf8
229
    @deprecated_method(deprecated_in((1, 6, 0)))
1185.65.29 by Robert Collins
Implement final review suggestions.
230
    def put_utf8(self, path, a_string):
231
        """Write a string, encoding as utf-8.
1185.65.12 by Robert Collins
Remove the only-used-once put_controlfiles, and change put_controlfile to put and put_utf8.
232
1185.65.29 by Robert Collins
Implement final review suggestions.
233
        :param path: The path to put the string, relative to the transport root.
2249.5.11 by John Arbash Meinel
Audit Branch to ensure utf8 revision ids.
234
        :param string: A string or unicode object whose contents should be copied.
3407.2.7 by Martin Pool
Deprecate LockableFiles.put_utf8 and put_bytes.
235
236
        :deprecated: Use Transport methods instead.
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
237
        """
1185.67.7 by Aaron Bentley
Refactored a bit
238
        # IterableFile would not be needed if Transport.put took iterables
239
        # instead of files.  ADHB 2005-12-25
1185.65.17 by Robert Collins
Merge from integration, mode-changes are broken.
240
        # RBC 20060103 surely its not needed anyway, with codecs transcode
241
        # file support ?
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
242
        # JAM 20060103 We definitely don't want encode(..., 'replace')
243
        # these are valuable files which should have exact contents.
1185.65.29 by Robert Collins
Implement final review suggestions.
244
        if not isinstance(a_string, basestring):
245
            raise errors.BzrBadParameterNotString(a_string)
2249.5.11 by John Arbash Meinel
Audit Branch to ensure utf8 revision ids.
246
        self.put_bytes(path, a_string.encode('utf-8'))
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
247
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
248
    def leave_in_place(self):
249
        """Set this LockableFiles to not clear the physical lock on unlock."""
250
        self._lock.leave_in_place()
251
252
    def dont_leave_in_place(self):
253
        """Set this LockableFiles to clear the physical lock on unlock."""
254
        self._lock.dont_leave_in_place()
255
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
256
    def lock_write(self, token=None):
257
        """Lock this group of files for writing.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
258
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
259
        :param token: if this is already locked, then lock_write will fail
260
            unless the token matches the existing lock.
261
        :returns: a token if this instance supports tokens, otherwise None.
262
        :raises TokenLockingNotSupported: when a token is given but this
263
            instance doesn't support using token locks.
264
        :raises MismatchedToken: if the specified token doesn't match the token
265
            of the existing lock.
2018.5.145 by Andrew Bennetts
Add a brief explanation of what tokens are used for to lock_write docstrings.
266
267
        A token should be passed in if you know that you have locked the object
268
        some other way, and need to synchronise this object's state with that
269
        fact.
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
270
        """
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
271
        # TODO: Upgrade locking to support using a Transport,
272
        # and potentially a remote locking protocol
273
        if self._lock_mode:
1594.2.22 by Robert Collins
Ensure that lockable files calls finish() on transactions.:
274
            if self._lock_mode != 'w' or not self.get_transaction().writeable():
1694.2.6 by Martin Pool
[merge] bzr.dev
275
                raise errors.ReadOnlyError(self)
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
276
            self._lock.validate_token(token)
4041.1.5 by Michael Hudson
review comments
277
            self._lock_warner.lock_count += 1
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
278
            return self._token_from_lock
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
279
        else:
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
280
            token_from_lock = self._lock.lock_write(token=token)
1185.80.2 by John Arbash Meinel
Traced double locking code to WorkingTree creating its own control files.
281
            #traceback.print_stack()
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
282
            self._lock_mode = 'w'
4041.1.5 by Michael Hudson
review comments
283
            self._lock_warner.lock_count = 1
4145.1.2 by Robert Collins
Add a refresh_data method on Repository allowing cleaner handling of insertions into RemoteRepository objects with _real_repository instances.
284
            self._set_write_transaction()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
285
            self._token_from_lock = token_from_lock
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
286
            return token_from_lock
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
287
288
    def lock_read(self):
289
        if self._lock_mode:
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
290
            if self._lock_mode not in ('r', 'w'):
291
                raise ValueError("invalid lock mode %r" % (self._lock_mode,))
4041.1.5 by Michael Hudson
review comments
292
            self._lock_warner.lock_count += 1
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
293
        else:
1553.5.47 by Martin Pool
cleanup LockableFiles
294
            self._lock.lock_read()
1185.80.2 by John Arbash Meinel
Traced double locking code to WorkingTree creating its own control files.
295
            #traceback.print_stack()
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
296
            self._lock_mode = 'r'
4041.1.5 by Michael Hudson
review comments
297
            self._lock_warner.lock_count = 1
4145.1.2 by Robert Collins
Add a refresh_data method on Repository allowing cleaner handling of insertions into RemoteRepository objects with _real_repository instances.
298
            self._set_read_transaction()
299
300
    def _set_read_transaction(self):
301
        """Setup a read transaction."""
302
        self._set_transaction(transactions.ReadOnlyTransaction())
303
        # 5K may be excessive, but hey, its a knob.
304
        self.get_transaction().set_cache_size(5000)
305
306
    def _set_write_transaction(self):
307
        """Setup a write transaction."""
308
        self._set_transaction(transactions.WriteTransaction())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
309
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
310
    def unlock(self):
311
        if not self._lock_mode:
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
312
            return lock.cant_unlock_not_held(self)
4041.1.5 by Michael Hudson
review comments
313
        if self._lock_warner.lock_count > 1:
314
            self._lock_warner.lock_count -= 1
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
315
        else:
1185.80.2 by John Arbash Meinel
Traced double locking code to WorkingTree creating its own control files.
316
            #traceback.print_stack()
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
317
            self._finish_transaction()
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
318
            try:
319
                self._lock.unlock()
320
            finally:
4041.1.5 by Michael Hudson
review comments
321
                self._lock_mode = self._lock_warner.lock_count = None
4104.4.1 by Robert Collins
Cherrypick bugfixes from bzr.dev for 1.13:
322
4041.1.3 by Michael Hudson
_this_ works
323
    @property
324
    def _lock_count(self):
4041.1.5 by Michael Hudson
review comments
325
        return self._lock_warner.lock_count
4041.1.3 by Michael Hudson
_this_ works
326
1553.5.35 by Martin Pool
Start break-lock --show
327
    def is_locked(self):
328
        """Return true if this LockableFiles group is locked"""
4041.1.5 by Michael Hudson
review comments
329
        return self._lock_warner.lock_count >= 1
1553.5.35 by Martin Pool
Start break-lock --show
330
1694.2.6 by Martin Pool
[merge] bzr.dev
331
    def get_physical_lock_status(self):
332
        """Return physical lock status.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
333
1694.2.6 by Martin Pool
[merge] bzr.dev
334
        Returns true if a lock is held on the transport. If no lock is held, or
335
        the underlying locking mechanism does not support querying lock
336
        status, false is returned.
337
        """
338
        try:
339
            return self._lock.peek() is not None
340
        except NotImplementedError:
341
            return False
342
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
343
    def get_transaction(self):
344
        """Return the current active transaction.
345
346
        If no transaction is active, this returns a passthrough object
347
        for which all data is immediately flushed and no caching happens.
348
        """
349
        if self._transaction is None:
350
            return transactions.PassThroughTransaction()
351
        else:
352
            return self._transaction
353
354
    def _set_transaction(self, new_transaction):
355
        """Set a new active transaction."""
356
        if self._transaction is not None:
357
            raise errors.LockError('Branch %s is in a transaction already.' %
358
                                   self)
359
        self._transaction = new_transaction
360
361
    def _finish_transaction(self):
362
        """Exit the current transaction."""
363
        if self._transaction is None:
364
            raise errors.LockError('Branch %s is not in a transaction' %
365
                                   self)
366
        transaction = self._transaction
367
        self._transaction = None
368
        transaction.finish()
1553.5.40 by Martin Pool
Factor locking strategy out of LockableFiles so that we can use LockDirs in new formats.
369
370
1553.5.45 by Martin Pool
Clean up Transport-based locks for old branches
371
class TransportLock(object):
372
    """Locking method which uses transport-dependent locks.
373
374
    On the local filesystem these transform into OS-managed locks.
375
376
    These do not guard against concurrent access via different
377
    transports.
378
379
    This is suitable for use only in WorkingTrees (which are at present
380
    always local).
1553.5.40 by Martin Pool
Factor locking strategy out of LockableFiles so that we can use LockDirs in new formats.
381
    """
1553.5.59 by Martin Pool
Pass file/mode bits through to creation of lock files/dirs
382
    def __init__(self, transport, escaped_name, file_modebits, dir_modebits):
1553.5.40 by Martin Pool
Factor locking strategy out of LockableFiles so that we can use LockDirs in new formats.
383
        self._transport = transport
384
        self._escaped_name = escaped_name
1553.5.59 by Martin Pool
Pass file/mode bits through to creation of lock files/dirs
385
        self._file_modebits = file_modebits
386
        self._dir_modebits = dir_modebits
1553.5.40 by Martin Pool
Factor locking strategy out of LockableFiles so that we can use LockDirs in new formats.
387
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
388
    def break_lock(self):
389
        raise NotImplementedError(self.break_lock)
390
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
391
    def leave_in_place(self):
392
        raise NotImplementedError(self.leave_in_place)
393
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
394
    def dont_leave_in_place(self):
395
        raise NotImplementedError(self.dont_leave_in_place)
396
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
397
    def lock_write(self, token=None):
398
        if token is not None:
399
            raise errors.TokenLockingNotSupported(self)
1553.5.40 by Martin Pool
Factor locking strategy out of LockableFiles so that we can use LockDirs in new formats.
400
        self._lock = self._transport.lock_write(self._escaped_name)
401
402
    def lock_read(self):
403
        self._lock = self._transport.lock_read(self._escaped_name)
404
405
    def unlock(self):
406
        self._lock.unlock()
407
        self._lock = None
408
1694.2.6 by Martin Pool
[merge] bzr.dev
409
    def peek(self):
410
        raise NotImplementedError()
411
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
412
    def create(self, mode=None):
1553.5.59 by Martin Pool
Pass file/mode bits through to creation of lock files/dirs
413
        """Create lock mechanism"""
414
        # for old-style locks, create the file now
1955.3.8 by John Arbash Meinel
avoid some deprecation warnings in other parts of the code
415
        self._transport.put_bytes(self._escaped_name, '',
1553.5.60 by Martin Pool
New LockableFiles.create_lock() method
416
                            mode=self._file_modebits)
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
417
418
    def validate_token(self, token):
419
        if token is not None:
420
            raise errors.TokenLockingNotSupported(self)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
421