/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
7143.15.2 by Jelmer Vernooij
Run autopep8.
53
3724.1.1 by Martin Pool
Move Lock hooks onto a base Lock class and make them more consistent with other lock classes
54
class LockHooks(Hooks):
55
5622.3.10 by Jelmer Vernooij
Don't require arguments to hooks.
56
    def __init__(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
57
        Hooks.__init__(self, "breezy.lock", "Lock.hooks")
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
58
        self.add_hook(
59
            'lock_acquired',
60
            "Called with a breezy.lock.LockResult when a physical lock is "
61
            "acquired.", (1, 8))
62
        self.add_hook(
63
            'lock_released',
64
            "Called with a breezy.lock.LockResult when a physical lock is "
65
            "released.", (1, 8))
66
        self.add_hook(
67
            'lock_broken',
68
            "Called with a breezy.lock.LockResult when a physical lock is "
69
            "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
70
71
72
class Lock(object):
73
    """Base class for locks.
74
75
    :cvar hooks: Hook dictionary for operations on locks.
76
    """
77
5622.3.10 by Jelmer Vernooij
Don't require arguments to hooks.
78
    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
79
80
3331.3.1 by Robert Collins
* ``LockDir`` lock acquisition and release now trigger hooks allowing
81
class LockResult(object):
3331.3.5 by Martin Pool
Move physical lock hooks onto new PhysicalLock class variable
82
    """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
83
3331.3.2 by Robert Collins
Polish on lock hooks to be easier to use.
84
    def __init__(self, lock_url, details=None):
3331.3.1 by Robert Collins
* ``LockDir`` lock acquisition and release now trigger hooks allowing
85
        """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.
86
        self.lock_url = lock_url
3331.3.1 by Robert Collins
* ``LockDir`` lock acquisition and release now trigger hooks allowing
87
        self.details = details
88
89
    def __eq__(self, other):
3331.3.2 by Robert Collins
Polish on lock hooks to be easier to use.
90
        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
91
4327.1.1 by Vincent Ladeuil
Start addressing test failing when run with -Dlock.
92
    def __repr__(self):
4634.146.9 by Danny van Heumen
Changed representation of LockResult: separate path and nonce with a comma.
93
        return '%s(%s, %s)' % (self.__class__.__name__,
7143.15.2 by Jelmer Vernooij
Run autopep8.
94
                               self.lock_url, self.details)
4327.1.1 by Vincent Ladeuil
Start addressing test failing when run with -Dlock.
95
577 by Martin Pool
- merge portable lock module from John
96
5200.3.6 by Robert Collins
Make all lock methods return Result objects, rather than lock_read returning self, as per John's review.
97
class LogicalLockResult(object):
98
    """The result of a lock_read/lock_write/lock_tree_write call on lockables.
99
100
    :ivar unlock: A callable which will unlock the lock.
101
    """
102
6754.8.4 by Jelmer Vernooij
Use new context stuff.
103
    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.
104
        self.unlock = unlock
6754.8.4 by Jelmer Vernooij
Use new context stuff.
105
        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.
106
107
    def __repr__(self):
108
        return "LogicalLockResult(%s)" % (self.unlock)
109
6754.8.1 by Jelmer Vernooij
Add context manager on LogicalLockResult.
110
    def __enter__(self):
6754.8.9 by Jelmer Vernooij
Fix more tests.
111
        return self
6754.8.1 by Jelmer Vernooij
Add context manager on LogicalLockResult.
112
113
    def __exit__(self, exc_type, exc_val, exc_tb):
6754.8.12 by Jelmer Vernooij
FIx remaining tests.
114
        # If there was an error raised, prefer the original one
115
        try:
116
            self.unlock()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
117
        except BaseException:
6754.8.12 by Jelmer Vernooij
FIx remaining tests.
118
            if exc_type is None:
119
                raise
6754.8.1 by Jelmer Vernooij
Add context manager on LogicalLockResult.
120
        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.
121
122
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
123
def cant_unlock_not_held(locked_object):
124
    """An attempt to unlock failed because the object was not locked.
125
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
126
    This provides a policy point from which we can generate either a warning or
127
    an exception.
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
128
    """
129
    # 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
130
    # 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
131
    # here.  You can use -Werror to make it fatal.  It should possibly also
132
    # raise LockNotHeld.
4509.3.27 by Martin Pool
Change debug flag to -Dunlock and document it
133
    if 'unlock' in debug.debug_flags:
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
134
        warnings.warn("%r is already unlocked" % (locked_object,),
7143.15.2 by Jelmer Vernooij
Run autopep8.
135
                      stacklevel=3)
4509.3.25 by Martin Pool
Add an option for unlock errors to be non-fatal
136
    else:
137
        raise errors.LockNotHeld(locked_object)
138
139
3224.5.32 by Andrew Bennetts
Tidy conditional imports in bzrlib/lock.py as suggested by John's review.
140
try:
141
    import fcntl
142
    have_fcntl = True
143
except ImportError:
144
    have_fcntl = False
145
146
have_ctypes_win32 = False
147
if sys.platform == 'win32':
148
    import msvcrt
149
    try:
150
        import ctypes
151
        have_ctypes_win32 = True
152
    except ImportError:
153
        pass
154
155
2555.3.2 by Martin Pool
rename _base_Lock to _OSLock
156
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.
157
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
158
    def __init__(self):
159
        self.f = None
2353.3.10 by John Arbash Meinel
Cleanup errors, and change ReadOnlyLockError to pass around more details.
160
        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.
161
615 by Martin Pool
Major rework of locking code:
162
    def _open(self, filename, filemode):
2353.3.11 by John Arbash Meinel
Code cleanup
163
        self.filename = osutils.realpath(filename)
656 by Martin Pool
- create branch lock files if they don't exist
164
        try:
2353.3.10 by John Arbash Meinel
Cleanup errors, and change ReadOnlyLockError to pass around more details.
165
            self.f = open(self.filename, filemode)
656 by Martin Pool
- create branch lock files if they don't exist
166
            return self.f
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
167
        except IOError as e:
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
168
            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).
169
                raise errors.LockFailed(self.filename, str(e))
656 by Martin Pool
- create branch lock files if they don't exist
170
            if e.errno != errno.ENOENT:
171
                raise
172
173
            # maybe this is an old branch (before may 2005)
2353.3.11 by John Arbash Meinel
Code cleanup
174
            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
175
2353.3.10 by John Arbash Meinel
Cleanup errors, and change ReadOnlyLockError to pass around more details.
176
            self.f = open(self.filename, 'wb+')
656 by Martin Pool
- create branch lock files if they don't exist
177
            return self.f
178
2353.3.4 by John Arbash Meinel
Clean up the lock.py code to use less indenting, and conform to better coding practise.
179
    def _clear_f(self):
180
        """Clear the self.f attribute cleanly."""
181
        if self.f:
182
            self.f.close()
183
            self.f = None
184
615 by Martin Pool
Major rework of locking code:
185
    def unlock(self):
186
        raise NotImplementedError()
187
188
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
189
_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.
190
191
192
if have_fcntl:
615 by Martin Pool
Major rework of locking code:
193
2555.3.2 by Martin Pool
rename _base_Lock to _OSLock
194
    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.
195
196
        def _unlock(self):
1185.9.2 by Harald Meland
Use fcntl.lockf() rather than fcntl.flock() to support NFS file systems.
197
            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.
198
            self._clear_f()
199
615 by Martin Pool
Major rework of locking code:
200
    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.
201
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
202
        _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.
203
615 by Martin Pool
Major rework of locking code:
204
        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.
205
            super(_fcntl_WriteLock, self).__init__()
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
206
            # Check we can grab a lock before we actually open the file.
207
            self.filename = osutils.realpath(filename)
4523.4.9 by John Arbash Meinel
Change the flags around a bit.
208
            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.
209
                self._clear_f()
210
                raise errors.LockContention(self.filename)
4523.4.9 by John Arbash Meinel
Change the flags around a bit.
211
            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.
212
                if 'strict_locks' in debug.debug_flags:
4523.4.9 by John Arbash Meinel
Change the flags around a bit.
213
                    self._clear_f()
214
                    raise errors.LockContention(self.filename)
215
                else:
216
                    trace.mutter('Write lock taken w/ an open read lock on: %s'
217
                                 % (self.filename,))
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
218
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
219
            self._open(self.filename, 'rb+')
2255.10.2 by John Arbash Meinel
Update to dirstate locking.
220
            # reserve a slot for this lock - even if the lockf call fails,
5009.1.1 by Vincent Ladeuil
(trivial) Fix typos
221
            # at this point unlock() will be called, because self.f is set.
2255.10.2 by John Arbash Meinel
Update to dirstate locking.
222
            # 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.
223
            _fcntl_WriteLock._open_locks.add(self.filename)
615 by Martin Pool
Major rework of locking code:
224
            try:
2255.10.2 by John Arbash Meinel
Update to dirstate locking.
225
                # LOCK_NB will cause IOError to be raised if we can't grab a
226
                # lock right away.
227
                fcntl.lockf(self.f, fcntl.LOCK_EX | fcntl.LOCK_NB)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
228
            except IOError as e:
2255.10.2 by John Arbash Meinel
Update to dirstate locking.
229
                if e.errno in (errno.EAGAIN, errno.EACCES):
230
                    # We couldn't grab the lock
231
                    self.unlock()
1185.65.29 by Robert Collins
Implement final review suggestions.
232
                # we should be more precise about whats a locking
233
                # error and whats a random-other error
4100.1.4 by Martin Pool
LockContention on OS locks now includes the filename
234
                raise errors.LockContention(self.filename, e)
615 by Martin Pool
Major rework of locking code:
235
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
236
        def unlock(self):
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
237
            _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.
238
            self._unlock()
239
615 by Martin Pool
Major rework of locking code:
240
    class _fcntl_ReadLock(_fcntl_FileLock):
1185.65.29 by Robert Collins
Implement final review suggestions.
241
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
242
        _open_locks = {}
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
243
2353.4.11 by John Arbash Meinel
Remove the unused _ignore_write_lock parameter.
244
        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.
245
            super(_fcntl_ReadLock, self).__init__()
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
246
            self.filename = osutils.realpath(filename)
4523.4.9 by John Arbash Meinel
Change the flags around a bit.
247
            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.
248
                if 'strict_locks' in debug.debug_flags:
4523.4.14 by John Arbash Meinel
Fix the direct lock tests.
249
                    # We raise before calling _open so we don't need to
250
                    # _clear_f
4523.4.9 by John Arbash Meinel
Change the flags around a bit.
251
                    raise errors.LockContention(self.filename)
252
                else:
253
                    trace.mutter('Read lock taken w/ an open write lock on: %s'
254
                                 % (self.filename,))
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
255
            _fcntl_ReadLock._open_locks.setdefault(self.filename, 0)
256
            _fcntl_ReadLock._open_locks[self.filename] += 1
1185.65.29 by Robert Collins
Implement final review suggestions.
257
            self._open(filename, 'rb')
615 by Martin Pool
Major rework of locking code:
258
            try:
2255.10.2 by John Arbash Meinel
Update to dirstate locking.
259
                # LOCK_NB will cause IOError to be raised if we can't grab a
260
                # lock right away.
261
                fcntl.lockf(self.f, fcntl.LOCK_SH | fcntl.LOCK_NB)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
262
            except IOError as e:
1185.65.29 by Robert Collins
Implement final review suggestions.
263
                # we should be more precise about whats a locking
264
                # error and whats a random-other error
4100.1.4 by Martin Pool
LockContention on OS locks now includes the filename
265
                raise errors.LockContention(self.filename, e)
615 by Martin Pool
Major rework of locking code:
266
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
267
        def unlock(self):
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
268
            count = _fcntl_ReadLock._open_locks[self.filename]
269
            if count == 1:
270
                del _fcntl_ReadLock._open_locks[self.filename]
271
            else:
272
                _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.
273
            self._unlock()
274
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
275
        def temporary_write_lock(self):
276
            """Try to grab a write lock on the file.
277
278
            On platforms that support it, this will upgrade to a write lock
279
            without unlocking the file.
280
            Otherwise, this will release the read lock, and try to acquire a
281
            write lock.
282
283
            :return: A token which can be used to switch back to a read lock.
284
            """
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
285
            if self.filename in _fcntl_WriteLock._open_locks:
286
                raise AssertionError('file already locked: %r'
7143.15.2 by Jelmer Vernooij
Run autopep8.
287
                                     % (self.filename,))
2353.4.7 by John Arbash Meinel
Change the temporary_write_lock api, so that it always returns a lock object,
288
            try:
289
                wlock = _fcntl_TemporaryWriteLock(self)
290
            except errors.LockError:
291
                # We didn't unlock, so we can just return 'self'
292
                return False, self
293
            return True, wlock
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
294
2555.3.2 by Martin Pool
rename _base_Lock to _OSLock
295
    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.
296
        """A token used when grabbing a temporary_write_lock.
297
298
        Call restore_read_lock() when you are done with the write lock.
299
        """
300
301
        def __init__(self, read_lock):
302
            super(_fcntl_TemporaryWriteLock, self).__init__()
303
            self._read_lock = read_lock
304
            self.filename = read_lock.filename
305
306
            count = _fcntl_ReadLock._open_locks[self.filename]
307
            if count > 1:
308
                # Something else also has a read-lock, so we cannot grab a
309
                # write lock.
310
                raise errors.LockContention(self.filename)
311
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
312
            if self.filename in _fcntl_WriteLock._open_locks:
313
                raise AssertionError('file already locked: %r'
7143.15.2 by Jelmer Vernooij
Run autopep8.
314
                                     % (self.filename,))
2353.4.3 by John Arbash Meinel
Implement a 'ReadLock.temporary_write_lock()' to upgrade to a write-lock in-process.
315
316
            # See if we can open the file for writing. Another process might
317
            # have a read lock. We don't use self._open() because we don't want
318
            # to create the file if it exists. That would have already been
319
            # done by _fcntl_ReadLock
320
            try:
321
                new_f = open(self.filename, 'rb+')
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
322
            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.
323
                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).
324
                    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.
325
                raise
326
            try:
327
                # LOCK_NB will cause IOError to be raised if we can't grab a
328
                # lock right away.
2379.3.1 by John Arbash Meinel
Cherry-pick the 2 locking fixes from the 0.15 branch.
329
                fcntl.lockf(new_f, fcntl.LOCK_EX | fcntl.LOCK_NB)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
330
            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.
331
                # 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
332
                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.
333
            _fcntl_WriteLock._open_locks.add(self.filename)
334
335
            self.f = new_f
336
337
        def restore_read_lock(self):
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
338
            """Restore the original ReadLock."""
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
339
            # For fcntl, since we never released the read lock, just release
340
            # the 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.
341
            fcntl.lockf(self.f, fcntl.LOCK_UN)
342
            self._clear_f()
343
            _fcntl_WriteLock._open_locks.remove(self.filename)
344
            # Avoid reference cycles
345
            read_lock = self._read_lock
346
            self._read_lock = None
347
            return read_lock
348
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
349
    _lock_classes.append(('fcntl', _fcntl_WriteLock, _fcntl_ReadLock))
577 by Martin Pool
- merge portable lock module from John
350
2353.3.11 by John Arbash Meinel
Code cleanup
351
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.
352
if have_ctypes_win32:
7143.11.1 by Jelmer Vernooij
Remove some unused imports.
353
    from ctypes.wintypes import DWORD, LPWSTR
7143.15.2 by Jelmer Vernooij
Run autopep8.
354
    LPSECURITY_ATTRIBUTES = ctypes.c_void_p  # used as NULL no need to declare
355
    HANDLE = ctypes.c_int  # rather than unsigned as in ctypes.wintypes
6658.6.1 by Martin
Remove winver, win98 support code, and deprecated code
356
    _function_name = "CreateFileW"
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
357
358
    # CreateFile <http://msdn.microsoft.com/en-us/library/aa363858.aspx>
359
    _CreateFile = ctypes.WINFUNCTYPE(
7143.15.2 by Jelmer Vernooij
Run autopep8.
360
        HANDLE,                # return value
361
        LPWSTR,                # lpFileName
362
        DWORD,                 # dwDesiredAccess
363
        DWORD,                 # dwShareMode
364
        LPSECURITY_ATTRIBUTES,  # lpSecurityAttributes
365
        DWORD,                 # dwCreationDisposition
366
        DWORD,                 # dwFlagsAndAttributes
367
        HANDLE                 # hTemplateFile
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
368
        )((_function_name, ctypes.windll.kernel32))
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
369
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
370
    INVALID_HANDLE_VALUE = -1
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
371
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
372
    GENERIC_READ = 0x80000000
373
    GENERIC_WRITE = 0x40000000
374
    FILE_SHARE_READ = 1
375
    OPEN_ALWAYS = 4
376
    FILE_ATTRIBUTE_NORMAL = 128
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
377
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
378
    ERROR_ACCESS_DENIED = 5
379
    ERROR_SHARING_VIOLATION = 32
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
380
2555.3.2 by Martin Pool
rename _base_Lock to _OSLock
381
    class _ctypes_FileLock(_OSLock):
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
382
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
383
        def _open(self, filename, access, share, cflags, pymode):
384
            self.filename = osutils.realpath(filename)
385
            handle = _CreateFile(filename, access, share, None, OPEN_ALWAYS,
7143.15.2 by Jelmer Vernooij
Run autopep8.
386
                                 FILE_ATTRIBUTE_NORMAL, 0)
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
387
            if handle in (INVALID_HANDLE_VALUE, 0):
388
                e = ctypes.WinError()
4459.3.2 by Martin
Fix issue with change of semantics of WindowsError.errno in Python 2.5
389
                if e.args[0] == ERROR_ACCESS_DENIED:
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
390
                    raise errors.LockFailed(filename, e)
4459.3.2 by Martin
Fix issue with change of semantics of WindowsError.errno in Python 2.5
391
                if e.args[0] == ERROR_SHARING_VIOLATION:
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
392
                    raise errors.LockContention(filename, e)
393
                raise e
394
            fd = msvcrt.open_osfhandle(handle, cflags)
395
            self.f = os.fdopen(fd, pymode)
396
            return self.f
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
397
398
        def unlock(self):
4404.1.1 by Martin
Correct use of GetLastError in ctypes windows locking code
399
            self._clear_f()
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
400
401
    class _ctypes_ReadLock(_ctypes_FileLock):
402
        def __init__(self, filename):
403
            super(_ctypes_ReadLock, self).__init__()
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
404
            self._open(filename, GENERIC_READ, FILE_SHARE_READ, os.O_RDONLY,
7143.15.2 by Jelmer Vernooij
Run autopep8.
405
                       "rb")
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
406
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
407
        def temporary_write_lock(self):
408
            """Try to grab a write lock on the file.
409
410
            On platforms that support it, this will upgrade to a write lock
411
            without unlocking the file.
412
            Otherwise, this will release the read lock, and try to acquire a
413
            write lock.
414
415
            :return: A token which can be used to switch back to a read lock.
416
            """
417
            # I can't find a way to upgrade a read lock to a write lock without
418
            # unlocking first. So here, we do just that.
419
            self.unlock()
2353.4.7 by John Arbash Meinel
Change the temporary_write_lock api, so that it always returns a lock object,
420
            try:
421
                wlock = _ctypes_WriteLock(self.filename)
422
            except errors.LockError:
423
                return False, _ctypes_ReadLock(self.filename)
424
            return True, wlock
2353.3.11 by John Arbash Meinel
Code cleanup
425
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
426
    class _ctypes_WriteLock(_ctypes_FileLock):
427
        def __init__(self, filename):
428
            super(_ctypes_WriteLock, self).__init__()
4459.3.1 by Martin
Implement bzrlib.lock with CreateFile rather than LockFileEx on win32
429
            self._open(filename, GENERIC_READ | GENERIC_WRITE, 0, os.O_RDWR,
7143.15.2 by Jelmer Vernooij
Run autopep8.
430
                       "rb+")
2353.3.5 by John Arbash Meinel
Fall back on ctypes to get LockFileEx, because msvcrt.locking()
431
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
432
        def restore_read_lock(self):
433
            """Restore the original ReadLock."""
434
            # For win32 we had to completely let go of the original lock, so we
435
            # just unlock and create a new read lock.
436
            self.unlock()
2353.4.6 by John Arbash Meinel
ctypes locks should return ctypes locks.
437
            return _ctypes_ReadLock(self.filename)
2353.4.4 by John Arbash Meinel
Implement temporary_write_lock, and restore_read_lock for win32 locks.
438
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
439
    _lock_classes.append(('ctypes', _ctypes_WriteLock, _ctypes_ReadLock))
440
441
442
if len(_lock_classes) == 0:
2353.3.11 by John Arbash Meinel
Code cleanup
443
    raise NotImplementedError(
7341.1.1 by Martin
Remove win32 code using pywin32 library
444
        "We must have one of fcntl or ctypes available"
2353.3.11 by John Arbash Meinel
Code cleanup
445
        " to support OS locking."
446
        )
447
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
448
449
# We default to using the first available lock class.
450
_lock_type, WriteLock, ReadLock = _lock_classes[0]
451
4731.1.2 by Andrew Bennetts
Refactor to reduce duplication.
452
453
class _RelockDebugMixin(object):
454
    """Mixin support for -Drelock flag.
455
456
    Add this as a base class then call self._note_lock with 'r' or 'w' when
457
    acquiring a read- or write-lock.  If this object was previously locked (and
458
    locked the same way), and -Drelock is set, then this will trace.note a
459
    message about it.
460
    """
6076.1.1 by Vincent Ladeuil
Add the missing config stacks and store
461
4731.1.2 by Andrew Bennetts
Refactor to reduce duplication.
462
    _prev_lock = None
463
464
    def _note_lock(self, lock_type):
465
        if 'relock' in debug.debug_flags and self._prev_lock == lock_type:
466
            if lock_type == 'r':
467
                type_name = 'read'
468
            else:
469
                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
470
            trace.note(gettext('{0!r} was {1} locked again'), self, type_name)
4731.1.2 by Andrew Bennetts
Refactor to reduce duplication.
471
        self._prev_lock = lock_type
472
7143.15.2 by Jelmer Vernooij
Run autopep8.
473
6538.1.11 by Aaron Bentley
Switch to much simpler implementation of restore_uncommitted.
474
@contextlib.contextmanager
475
def write_locked(lockable):
476
    lockable.lock_write()
477
    try:
478
        yield lockable
479
    finally:
480
        lockable.unlock()