/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4988.10.5 by John Arbash Meinel
Merge bzr.dev 5021 to resolve NEWS
1
# Copyright (C) 2005-2010 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
577 by Martin Pool
- merge portable lock module from John
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
#
577 by Martin Pool
- merge portable lock module from John
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
#
577 by Martin Pool
- merge portable lock module from John
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
577 by Martin Pool
- merge portable lock module from John
16
1553.5.39 by Martin Pool
More lock docs
17
"""Locking using OS file locks or file existence.
577 by Martin Pool
- merge portable lock module from John
18
1553.5.46 by Martin Pool
doc
19
Note: This method of locking is generally deprecated in favour of LockDir, but
20
is used to lock local WorkingTrees, and by some old formats.  It's accessed
21
through Transport.lock_read(), etc.
577 by Martin Pool
- merge portable lock module from John
22
23
This module causes two methods, lock() and unlock() to be defined in
24
any way that works on the current platform.
25
26
It is not specified whether these locks are reentrant (i.e. can be
27
taken repeatedly by a single process) or whether they exclude
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
28
different threads in a single process.  That reentrancy is provided by
1553.5.39 by Martin Pool
More lock docs
29
LockableFiles.
615 by Martin Pool
Major rework of locking code:
30
31
This defines two classes: ReadLock and WriteLock, which can be
32
implemented in different ways on different platforms.  Both have an
33
unlock() method.
614 by Martin Pool
- unify two defintions of LockError
34
"""
577 by Martin Pool
- merge portable lock module from John
35
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
36
from __future__ import absolute_import
37
6538.1.11 by Aaron Bentley
Switch to much simpler implementation of restore_uncommitted.
38
import contextlib
1185.65.29 by Robert Collins
Implement final review suggestions.
39
import errno
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
40
import os
2353.3.12 by John Arbash Meinel
Don't create the alternative lock types unless we are on windows.
41
import sys
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
42
import warnings
577 by Martin Pool
- merge portable lock module from John
43
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
44
from . import (
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
45
    debug,
2353.3.11 by John Arbash Meinel
Code cleanup
46
    errors,
47
    osutils,
48
    trace,
49
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
50
from .hooks import Hooks
51
from .i18n import gettext
3331.3.1 by Robert Collins
* ``LockDir`` lock acquisition and release now trigger hooks allowing
52
3724.1.1 by Martin Pool
Move Lock hooks onto a base Lock class and make them more consistent with other lock classes
53
class LockHooks(Hooks):
54
5622.3.10 by Jelmer Vernooij
Don't require arguments to hooks.
55
    def __init__(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
56
        Hooks.__init__(self, "breezy.lock", "Lock.hooks")
5622.3.2 by Jelmer Vernooij
Add more lazily usable hook points.
57
        self.add_hook('lock_acquired',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
58
            "Called with a breezy.lock.LockResult when a physical lock is "
5622.3.2 by Jelmer Vernooij
Add more lazily usable hook points.
59
            "acquired.", (1, 8))
60
        self.add_hook('lock_released',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
61
            "Called with a breezy.lock.LockResult when a physical lock is "
5622.3.2 by Jelmer Vernooij
Add more lazily usable hook points.
62
            "released.", (1, 8))
63
        self.add_hook('lock_broken',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
64
            "Called with a breezy.lock.LockResult when a physical lock is "
5622.3.2 by Jelmer Vernooij
Add more lazily usable hook points.
65
            "broken.", (1, 15))
3724.1.1 by Martin Pool
Move Lock hooks onto a base Lock class and make them more consistent with other lock classes
66
67
68
class Lock(object):
69
    """Base class for locks.
70
71
    :cvar hooks: Hook dictionary for operations on locks.
72
    """
73
5622.3.10 by Jelmer Vernooij
Don't require arguments to hooks.
74
    hooks = LockHooks()
3724.1.1 by Martin Pool
Move Lock hooks onto a base Lock class and make them more consistent with other lock classes
75
76
3331.3.1 by Robert Collins
* ``LockDir`` lock acquisition and release now trigger hooks allowing
77
class LockResult(object):
3331.3.5 by Martin Pool
Move physical lock hooks onto new PhysicalLock class variable
78
    """Result of an operation on a lock; passed to a hook"""
3331.3.1 by Robert Collins
* ``LockDir`` lock acquisition and release now trigger hooks allowing
79
3331.3.2 by Robert Collins
Polish on lock hooks to be easier to use.
80
    def __init__(self, lock_url, details=None):
3331.3.1 by Robert Collins
* ``LockDir`` lock acquisition and release now trigger hooks allowing
81
        """Create a lock result for lock with optional details about the lock."""
3331.3.2 by Robert Collins
Polish on lock hooks to be easier to use.
82
        self.lock_url = lock_url
3331.3.1 by Robert Collins
* ``LockDir`` lock acquisition and release now trigger hooks allowing
83
        self.details = details
84
85
    def __eq__(self, other):
3331.3.2 by Robert Collins
Polish on lock hooks to be easier to use.
86
        return self.lock_url == other.lock_url and self.details == other.details
1711.8.1 by John Arbash Meinel
Branch.lock_read/lock_write/unlock should handle failures
87
4327.1.1 by Vincent Ladeuil
Start addressing test failing when run with -Dlock.
88
    def __repr__(self):
4634.146.9 by Danny van Heumen
Changed representation of LockResult: separate path and nonce with a comma.
89
        return '%s(%s, %s)' % (self.__class__.__name__,
4327.1.1 by Vincent Ladeuil
Start addressing test failing when run with -Dlock.
90
                             self.lock_url, self.details)
91
577 by Martin Pool
- merge portable lock module from John
92
5200.3.6 by Robert Collins
Make all lock methods return Result objects, rather than lock_read returning self, as per John's review.
93
class LogicalLockResult(object):
94
    """The result of a lock_read/lock_write/lock_tree_write call on lockables.
95
96
    :ivar unlock: A callable which will unlock the lock.
97
    """
98
6754.8.4 by Jelmer Vernooij
Use new context stuff.
99
    def __init__(self, unlock, token=None):
5200.3.6 by Robert Collins
Make all lock methods return Result objects, rather than lock_read returning self, as per John's review.
100
        self.unlock = unlock
6754.8.4 by Jelmer Vernooij
Use new context stuff.
101
        self.token = token
5200.3.6 by Robert Collins
Make all lock methods return Result objects, rather than lock_read returning self, as per John's review.
102
103
    def __repr__(self):
104
        return "LogicalLockResult(%s)" % (self.unlock)
105
6754.8.1 by Jelmer Vernooij
Add context manager on LogicalLockResult.
106
    def __enter__(self):
6754.8.9 by Jelmer Vernooij
Fix more tests.
107
        return self
6754.8.1 by Jelmer Vernooij
Add context manager on LogicalLockResult.
108
109
    def __exit__(self, exc_type, exc_val, exc_tb):
6754.8.12 by Jelmer Vernooij
FIx remaining tests.
110
        # If there was an error raised, prefer the original one
111
        try:
112
            self.unlock()
113
        except:
114
            if exc_type is None:
115
                raise
6754.8.1 by Jelmer Vernooij
Add context manager on LogicalLockResult.
116
        return False
5200.3.6 by Robert Collins
Make all lock methods return Result objects, rather than lock_read returning self, as per John's review.
117
118
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
119
def cant_unlock_not_held(locked_object):
120
    """An attempt to unlock failed because the object was not locked.
121
122
    This provides a policy point from which we can generate either a warning 
123
    or an exception.
124
    """
125
    # This is typically masking some other error and called from a finally
4509.3.36 by Martin Pool
Review cleanups of typos and unneeded imports
126
    # block, so it's useful to have the option not to generate a new error
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
127
    # here.  You can use -Werror to make it fatal.  It should possibly also
128
    # raise LockNotHeld.
4509.3.27 by Martin Pool
Change debug flag to -Dunlock and document it
129
    if 'unlock' in debug.debug_flags:
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
130
        warnings.warn("%r is already unlocked" % (locked_object,),
131
            stacklevel=3)
132
    else:
133
        raise errors.LockNotHeld(locked_object)
134
135
3224.5.32 by Andrew Bennetts
Tidy conditional imports in bzrlib/lock.py as suggested by John's review.
136
try:
137
    import fcntl
138
    have_fcntl = True
139
except ImportError:
140
    have_fcntl = False
141
142
have_pywin32 = False
143
have_ctypes_win32 = False
144
if sys.platform == 'win32':
145
    import msvcrt
146
    try:
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
147
        import win32file, pywintypes, winerror
3224.5.32 by Andrew Bennetts
Tidy conditional imports in bzrlib/lock.py as suggested by John's review.
148
        have_pywin32 = True
149
    except ImportError:
150
        pass
151
152
    try:
153
        import ctypes
154
        have_ctypes_win32 = True
155
    except ImportError:
156
        pass
157
158
2555.3.2 by Martin Pool
rename _base_Lock to _OSLock
159
class _OSLock(object):
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
160
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
161
    def __init__(self):
162
        self.f = None
2353.3.10 by John Arbash Meinel
Cleanup errors, and change ReadOnlyLockError to pass around more details.
163
        self.filename = None
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
164
615 by Martin Pool
Major rework of locking code:
165
    def _open(self, filename, filemode):
2353.3.11 by John Arbash Meinel
Code cleanup
166
        self.filename = osutils.realpath(filename)
656 by Martin Pool
- create branch lock files if they don't exist
167
        try:
2353.3.10 by John Arbash Meinel
Cleanup errors, and change ReadOnlyLockError to pass around more details.
168
            self.f = open(self.filename, filemode)
656 by Martin Pool
- create branch lock files if they don't exist
169
            return self.f
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
170
        except IOError as e:
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
171
            if e.errno in (errno.EACCES, errno.EPERM):
2872.5.1 by Martin Pool
Avoid internal error tracebacks on failure to lock on readonly transport (#129701).
172
                raise errors.LockFailed(self.filename, str(e))
656 by Martin Pool
- create branch lock files if they don't exist
173
            if e.errno != errno.ENOENT:
174
                raise
175
176
            # maybe this is an old branch (before may 2005)
2353.3.11 by John Arbash Meinel
Code cleanup
177
            trace.mutter("trying to create missing lock %r", self.filename)
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
178
2353.3.10 by John Arbash Meinel
Cleanup errors, and change ReadOnlyLockError to pass around more details.
179
            self.f = open(self.filename, 'wb+')
656 by Martin Pool
- create branch lock files if they don't exist
180
            return self.f
181
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
182
    def _clear_f(self):
183
        """Clear the self.f attribute cleanly."""
184
        if self.f:
185
            self.f.close()
186
            self.f = None
187
615 by Martin Pool
Major rework of locking code:
188
    def unlock(self):
189
        raise NotImplementedError()
190
191
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
192
_lock_classes = []
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
193
194
195
if have_fcntl:
615 by Martin Pool
Major rework of locking code:
196
2555.3.2 by Martin Pool
rename _base_Lock to _OSLock
197
    class _fcntl_FileLock(_OSLock):
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
198
199
        def _unlock(self):
1185.9.2 by Harald Meland
Use fcntl.lockf() rather than fcntl.flock() to support NFS file systems.
200
            fcntl.lockf(self.f, fcntl.LOCK_UN)
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
201
            self._clear_f()
202
203
615 by Martin Pool
Major rework of locking code:
204
    class _fcntl_WriteLock(_fcntl_FileLock):
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
205
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
206
        _open_locks = set()
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
207
615 by Martin Pool
Major rework of locking code:
208
        def __init__(self, filename):
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
209
            super(_fcntl_WriteLock, self).__init__()
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
210
            # Check we can grab a lock before we actually open the file.
211
            self.filename = osutils.realpath(filename)
4523.4.9 by John Arbash Meinel
Change the flags around a bit.
212
            if self.filename in _fcntl_WriteLock._open_locks:
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
213
                self._clear_f()
214
                raise errors.LockContention(self.filename)
4523.4.9 by John Arbash Meinel
Change the flags around a bit.
215
            if self.filename in _fcntl_ReadLock._open_locks:
4523.4.10 by John Arbash Meinel
Update the various documentation and use strict_locks instead of strict-locks.
216
                if 'strict_locks' in debug.debug_flags:
4523.4.9 by John Arbash Meinel
Change the flags around a bit.
217
                    self._clear_f()
218
                    raise errors.LockContention(self.filename)
219
                else:
220
                    trace.mutter('Write lock taken w/ an open read lock on: %s'
221
                                 % (self.filename,))
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
222
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
223
            self._open(self.filename, 'rb+')
2255.10.2 by John Arbash Meinel
Update to dirstate locking.
224
            # reserve a slot for this lock - even if the lockf call fails,
5009.1.1 by Vincent Ladeuil
(trivial) Fix typos
225
            # at this point unlock() will be called, because self.f is set.
2255.10.2 by John Arbash Meinel
Update to dirstate locking.
226
            # TODO: make this fully threadsafe, if we decide we care.
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
227
            _fcntl_WriteLock._open_locks.add(self.filename)
615 by Martin Pool
Major rework of locking code:
228
            try:
2255.10.2 by John Arbash Meinel
Update to dirstate locking.
229
                # LOCK_NB will cause IOError to be raised if we can't grab a
230
                # lock right away.
231
                fcntl.lockf(self.f, fcntl.LOCK_EX | fcntl.LOCK_NB)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
232
            except IOError as e:
2255.10.2 by John Arbash Meinel
Update to dirstate locking.
233
                if e.errno in (errno.EAGAIN, errno.EACCES):
234
                    # We couldn't grab the lock
235
                    self.unlock()
1185.65.29 by Robert Collins
Implement final review suggestions.
236
                # we should be more precise about whats a locking
237
                # error and whats a random-other error
4100.1.4 by Martin Pool
LockContention on OS locks now includes the filename
238
                raise errors.LockContention(self.filename, e)
615 by Martin Pool
Major rework of locking code:
239
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
240
        def unlock(self):
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
241
            _fcntl_WriteLock._open_locks.remove(self.filename)
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
242
            self._unlock()
243
244
615 by Martin Pool
Major rework of locking code:
245
    class _fcntl_ReadLock(_fcntl_FileLock):
1185.65.29 by Robert Collins
Implement final review suggestions.
246
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
247
        _open_locks = {}
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
248
2353.4.11 by John Arbash Meinel
Remove the unused _ignore_write_lock parameter.
249
        def __init__(self, filename):
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
250
            super(_fcntl_ReadLock, self).__init__()
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
251
            self.filename = osutils.realpath(filename)
4523.4.9 by John Arbash Meinel
Change the flags around a bit.
252
            if self.filename in _fcntl_WriteLock._open_locks:
4523.4.10 by John Arbash Meinel
Update the various documentation and use strict_locks instead of strict-locks.
253
                if 'strict_locks' in debug.debug_flags:
4523.4.14 by John Arbash Meinel
Fix the direct lock tests.
254
                    # We raise before calling _open so we don't need to
255
                    # _clear_f
4523.4.9 by John Arbash Meinel
Change the flags around a bit.
256
                    raise errors.LockContention(self.filename)
257
                else:
258
                    trace.mutter('Read lock taken w/ an open write lock on: %s'
259
                                 % (self.filename,))
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
260
            _fcntl_ReadLock._open_locks.setdefault(self.filename, 0)
261
            _fcntl_ReadLock._open_locks[self.filename] += 1
1185.65.29 by Robert Collins
Implement final review suggestions.
262
            self._open(filename, 'rb')
615 by Martin Pool
Major rework of locking code:
263
            try:
2255.10.2 by John Arbash Meinel
Update to dirstate locking.
264
                # LOCK_NB will cause IOError to be raised if we can't grab a
265
                # lock right away.
266
                fcntl.lockf(self.f, fcntl.LOCK_SH | fcntl.LOCK_NB)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
267
            except IOError as e:
1185.65.29 by Robert Collins
Implement final review suggestions.
268
                # we should be more precise about whats a locking
269
                # error and whats a random-other error
4100.1.4 by Martin Pool
LockContention on OS locks now includes the filename
270
                raise errors.LockContention(self.filename, e)
615 by Martin Pool
Major rework of locking code:
271
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
272
        def unlock(self):
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
273
            count = _fcntl_ReadLock._open_locks[self.filename]
274
            if count == 1:
275
                del _fcntl_ReadLock._open_locks[self.filename]
276
            else:
277
                _fcntl_ReadLock._open_locks[self.filename] = count - 1
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
278
            self._unlock()
279
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
280
        def temporary_write_lock(self):
281
            """Try to grab a write lock on the file.
282
283
            On platforms that support it, this will upgrade to a write lock
284
            without unlocking the file.
285
            Otherwise, this will release the read lock, and try to acquire a
286
            write lock.
287
288
            :return: A token which can be used to switch back to a read lock.
289
            """
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
290
            if self.filename in _fcntl_WriteLock._open_locks:
291
                raise AssertionError('file already locked: %r'
292
                    % (self.filename,))
2353.4.7 by John Arbash Meinel
Change the temporary_write_lock api, so that it always returns a lock object,
293
            try:
294
                wlock = _fcntl_TemporaryWriteLock(self)
295
            except errors.LockError:
296
                # We didn't unlock, so we can just return 'self'
297
                return False, self
298
            return True, wlock
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
299
300
2555.3.2 by Martin Pool
rename _base_Lock to _OSLock
301
    class _fcntl_TemporaryWriteLock(_OSLock):
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
302
        """A token used when grabbing a temporary_write_lock.
303
304
        Call restore_read_lock() when you are done with the write lock.
305
        """
306
307
        def __init__(self, read_lock):
308
            super(_fcntl_TemporaryWriteLock, self).__init__()
309
            self._read_lock = read_lock
310
            self.filename = read_lock.filename
311
312
            count = _fcntl_ReadLock._open_locks[self.filename]
313
            if count > 1:
314
                # Something else also has a read-lock, so we cannot grab a
315
                # write lock.
316
                raise errors.LockContention(self.filename)
317
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
318
            if self.filename in _fcntl_WriteLock._open_locks:
319
                raise AssertionError('file already locked: %r'
320
                    % (self.filename,))
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
321
322
            # See if we can open the file for writing. Another process might
323
            # have a read lock. We don't use self._open() because we don't want
324
            # to create the file if it exists. That would have already been
325
            # done by _fcntl_ReadLock
326
            try:
327
                new_f = open(self.filename, 'rb+')
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
328
            except IOError as e:
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
329
                if e.errno in (errno.EACCES, errno.EPERM):
2872.5.1 by Martin Pool
Avoid internal error tracebacks on failure to lock on readonly transport (#129701).
330
                    raise errors.LockFailed(self.filename, str(e))
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
331
                raise
332
            try:
333
                # LOCK_NB will cause IOError to be raised if we can't grab a
334
                # lock right away.
2379.3.1 by John Arbash Meinel
Cherry-pick the 2 locking fixes from the 0.15 branch.
335
                fcntl.lockf(new_f, fcntl.LOCK_EX | fcntl.LOCK_NB)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
336
            except IOError as e:
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
337
                # TODO: Raise a more specific error based on the type of error
4100.1.4 by Martin Pool
LockContention on OS locks now includes the filename
338
                raise errors.LockContention(self.filename, e)
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
339
            _fcntl_WriteLock._open_locks.add(self.filename)
340
341
            self.f = new_f
342
343
        def restore_read_lock(self):
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
344
            """Restore the original ReadLock."""
345
            # For fcntl, since we never released the read lock, just release the
346
            # write lock, and return the original lock.
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
347
            fcntl.lockf(self.f, fcntl.LOCK_UN)
348
            self._clear_f()
349
            _fcntl_WriteLock._open_locks.remove(self.filename)
350
            # Avoid reference cycles
351
            read_lock = self._read_lock
352
            self._read_lock = None
353
            return read_lock
354
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
355
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
356
    _lock_classes.append(('fcntl', _fcntl_WriteLock, _fcntl_ReadLock))
577 by Martin Pool
- merge portable lock module from John
357
2353.3.11 by John Arbash Meinel
Code cleanup
358
2353.3.12 by John Arbash Meinel
Don't create the alternative lock types unless we are on windows.
359
if have_pywin32 and sys.platform == 'win32':
6658.6.1 by Martin
Remove winver, win98 support code, and deprecated code
360
    win32file_CreateFile = win32file.CreateFileW
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
361
2555.3.2 by Martin Pool
rename _base_Lock to _OSLock
362
    class _w32c_FileLock(_OSLock):
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
363
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
364
        def _open(self, filename, access, share, cflags, pymode):
365
            self.filename = osutils.realpath(filename)
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
366
            try:
4513.1.1 by Alexander Belchenko
improved unicode support for OS locks @ win32.
367
                self._handle = win32file_CreateFile(filename, access, share,
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
368
                    None, win32file.OPEN_ALWAYS,
369
                    win32file.FILE_ATTRIBUTE_NORMAL, None)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
370
            except pywintypes.error as e:
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
371
                if e.args[0] == winerror.ERROR_ACCESS_DENIED:
372
                    raise errors.LockFailed(filename, e)
373
                if e.args[0] == winerror.ERROR_SHARING_VIOLATION:
374
                    raise errors.LockContention(filename, e)
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
375
                raise
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
376
            fd = win32file._open_osfhandle(self._handle, cflags)
377
            self.f = os.fdopen(fd, pymode)
378
            return self.f
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
379
380
        def unlock(self):
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
381
            self._clear_f()
382
            self._handle = None
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
383
384
385
    class _w32c_ReadLock(_w32c_FileLock):
386
        def __init__(self, filename):
387
            super(_w32c_ReadLock, self).__init__()
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
388
            self._open(filename, win32file.GENERIC_READ,
389
                win32file.FILE_SHARE_READ, os.O_RDONLY, "rb")
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
390
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
391
        def temporary_write_lock(self):
392
            """Try to grab a write lock on the file.
393
394
            On platforms that support it, this will upgrade to a write lock
395
            without unlocking the file.
396
            Otherwise, this will release the read lock, and try to acquire a
397
            write lock.
398
399
            :return: A token which can be used to switch back to a read lock.
400
            """
401
            # I can't find a way to upgrade a read lock to a write lock without
402
            # unlocking first. So here, we do just that.
403
            self.unlock()
2353.4.7 by John Arbash Meinel
Change the temporary_write_lock api, so that it always returns a lock object,
404
            try:
405
                wlock = _w32c_WriteLock(self.filename)
406
            except errors.LockError:
407
                return False, _w32c_ReadLock(self.filename)
408
            return True, wlock
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
409
2353.3.11 by John Arbash Meinel
Code cleanup
410
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
411
    class _w32c_WriteLock(_w32c_FileLock):
412
        def __init__(self, filename):
413
            super(_w32c_WriteLock, self).__init__()
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
414
            self._open(filename,
415
                win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0,
416
                os.O_RDWR, "rb+")
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
417
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
418
        def restore_read_lock(self):
419
            """Restore the original ReadLock."""
420
            # For win32 we had to completely let go of the original lock, so we
421
            # just unlock and create a new read lock.
422
            self.unlock()
423
            return _w32c_ReadLock(self.filename)
424
2353.3.11 by John Arbash Meinel
Code cleanup
425
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
426
    _lock_classes.append(('pywin32', _w32c_WriteLock, _w32c_ReadLock))
427
2353.3.11 by John Arbash Meinel
Code cleanup
428
3224.5.1 by Andrew Bennetts
Lots of assorted hackery to reduce the number of imports for common operations. Improves 'rocks', 'st' and 'help' times by ~50ms on my laptop.
429
if have_ctypes_win32:
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
430
    from ctypes.wintypes import DWORD, LPCSTR, LPCWSTR
431
    LPSECURITY_ATTRIBUTES = ctypes.c_void_p # used as NULL no need to declare
432
    HANDLE = ctypes.c_int # rather than unsigned as in ctypes.wintypes
6658.6.1 by Martin
Remove winver, win98 support code, and deprecated code
433
    _function_name = "CreateFileW"
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
434
435
    # CreateFile <http://msdn.microsoft.com/en-us/library/aa363858.aspx>
436
    _CreateFile = ctypes.WINFUNCTYPE(
437
            HANDLE,                # return value
6658.6.1 by Martin
Remove winver, win98 support code, and deprecated code
438
            LPWSTR,                # lpFileName
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
439
            DWORD,                 # dwDesiredAccess
440
            DWORD,                 # dwShareMode
441
            LPSECURITY_ATTRIBUTES, # lpSecurityAttributes
442
            DWORD,                 # dwCreationDisposition
443
            DWORD,                 # dwFlagsAndAttributes
444
            HANDLE                 # hTemplateFile
445
        )((_function_name, ctypes.windll.kernel32))
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
446
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
447
    INVALID_HANDLE_VALUE = -1
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
448
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
449
    GENERIC_READ = 0x80000000
450
    GENERIC_WRITE = 0x40000000
451
    FILE_SHARE_READ = 1
452
    OPEN_ALWAYS = 4
453
    FILE_ATTRIBUTE_NORMAL = 128
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
454
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
455
    ERROR_ACCESS_DENIED = 5
456
    ERROR_SHARING_VIOLATION = 32
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
457
2555.3.2 by Martin Pool
rename _base_Lock to _OSLock
458
    class _ctypes_FileLock(_OSLock):
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
459
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
460
        def _open(self, filename, access, share, cflags, pymode):
461
            self.filename = osutils.realpath(filename)
462
            handle = _CreateFile(filename, access, share, None, OPEN_ALWAYS,
463
                FILE_ATTRIBUTE_NORMAL, 0)
464
            if handle in (INVALID_HANDLE_VALUE, 0):
465
                e = ctypes.WinError()
4459.3.2 by Martin
Fix issue with change of semantics of WindowsError.errno in Python 2.5
466
                if e.args[0] == ERROR_ACCESS_DENIED:
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
467
                    raise errors.LockFailed(filename, e)
4459.3.2 by Martin
Fix issue with change of semantics of WindowsError.errno in Python 2.5
468
                if e.args[0] == ERROR_SHARING_VIOLATION:
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
469
                    raise errors.LockContention(filename, e)
470
                raise e
471
            fd = msvcrt.open_osfhandle(handle, cflags)
472
            self.f = os.fdopen(fd, pymode)
473
            return self.f
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
474
475
        def unlock(self):
4404.1.1 by Martin
Correct use of GetLastError in ctypes windows locking code
476
            self._clear_f()
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
477
478
479
    class _ctypes_ReadLock(_ctypes_FileLock):
480
        def __init__(self, filename):
481
            super(_ctypes_ReadLock, self).__init__()
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
482
            self._open(filename, GENERIC_READ, FILE_SHARE_READ, os.O_RDONLY,
483
                "rb")
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
484
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
485
        def temporary_write_lock(self):
486
            """Try to grab a write lock on the file.
487
488
            On platforms that support it, this will upgrade to a write lock
489
            without unlocking the file.
490
            Otherwise, this will release the read lock, and try to acquire a
491
            write lock.
492
493
            :return: A token which can be used to switch back to a read lock.
494
            """
495
            # I can't find a way to upgrade a read lock to a write lock without
496
            # unlocking first. So here, we do just that.
497
            self.unlock()
2353.4.7 by John Arbash Meinel
Change the temporary_write_lock api, so that it always returns a lock object,
498
            try:
499
                wlock = _ctypes_WriteLock(self.filename)
500
            except errors.LockError:
501
                return False, _ctypes_ReadLock(self.filename)
502
            return True, wlock
2353.3.11 by John Arbash Meinel
Code cleanup
503
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
504
    class _ctypes_WriteLock(_ctypes_FileLock):
505
        def __init__(self, filename):
506
            super(_ctypes_WriteLock, self).__init__()
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
507
            self._open(filename, GENERIC_READ | GENERIC_WRITE, 0, os.O_RDWR,
508
                "rb+")
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
509
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
510
        def restore_read_lock(self):
511
            """Restore the original ReadLock."""
512
            # For win32 we had to completely let go of the original lock, so we
513
            # just unlock and create a new read lock.
514
            self.unlock()
2353.4.6 by John Arbash Meinel
ctypes locks should return ctypes locks.
515
            return _ctypes_ReadLock(self.filename)
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
516
2353.3.11 by John Arbash Meinel
Code cleanup
517
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
518
    _lock_classes.append(('ctypes', _ctypes_WriteLock, _ctypes_ReadLock))
519
520
521
if len(_lock_classes) == 0:
2353.3.11 by John Arbash Meinel
Code cleanup
522
    raise NotImplementedError(
523
        "We must have one of fcntl, pywin32, or ctypes available"
524
        " to support OS locking."
525
        )
526
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
527
528
# We default to using the first available lock class.
529
_lock_type, WriteLock, ReadLock = _lock_classes[0]
530
4731.1.2 by Andrew Bennetts
Refactor to reduce duplication.
531
532
class _RelockDebugMixin(object):
533
    """Mixin support for -Drelock flag.
534
535
    Add this as a base class then call self._note_lock with 'r' or 'w' when
536
    acquiring a read- or write-lock.  If this object was previously locked (and
537
    locked the same way), and -Drelock is set, then this will trace.note a
538
    message about it.
539
    """
6076.1.1 by Vincent Ladeuil
Add the missing config stacks and store
540
4731.1.2 by Andrew Bennetts
Refactor to reduce duplication.
541
    _prev_lock = None
542
543
    def _note_lock(self, lock_type):
544
        if 'relock' in debug.debug_flags and self._prev_lock == lock_type:
545
            if lock_type == 'r':
546
                type_name = 'read'
547
            else:
548
                type_name = 'write'
6147.1.1 by Jonathan Riddell
use .format() instead of % for string formatting where there are multiple formats in one string to allow for translations
549
            trace.note(gettext('{0!r} was {1} locked again'), self, type_name)
4731.1.2 by Andrew Bennetts
Refactor to reduce duplication.
550
        self._prev_lock = lock_type
551
6538.1.11 by Aaron Bentley
Switch to much simpler implementation of restore_uncommitted.
552
@contextlib.contextmanager
553
def write_locked(lockable):
554
    lockable.lock_write()
555
    try:
556
        yield lockable
557
    finally:
558
        lockable.unlock()