/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/lock.py

  • Committer: Jelmer Vernooij
  • Date: 2019-05-29 03:22:34 UTC
  • mfrom: (7303 work)
  • mto: This revision was merged to the branch mainline in revision 7306.
  • Revision ID: jelmer@jelmer.uk-20190529032234-mt3fuws8gq03tapi
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
from .hooks import Hooks
51
51
from .i18n import gettext
52
52
 
 
53
 
53
54
class LockHooks(Hooks):
54
55
 
55
56
    def __init__(self):
56
57
        Hooks.__init__(self, "breezy.lock", "Lock.hooks")
57
 
        self.add_hook('lock_acquired',
 
58
        self.add_hook(
 
59
            'lock_acquired',
58
60
            "Called with a breezy.lock.LockResult when a physical lock is "
59
61
            "acquired.", (1, 8))
60
 
        self.add_hook('lock_released',
 
62
        self.add_hook(
 
63
            'lock_released',
61
64
            "Called with a breezy.lock.LockResult when a physical lock is "
62
65
            "released.", (1, 8))
63
 
        self.add_hook('lock_broken',
 
66
        self.add_hook(
 
67
            'lock_broken',
64
68
            "Called with a breezy.lock.LockResult when a physical lock is "
65
69
            "broken.", (1, 15))
66
70
 
87
91
 
88
92
    def __repr__(self):
89
93
        return '%s(%s, %s)' % (self.__class__.__name__,
90
 
                             self.lock_url, self.details)
 
94
                               self.lock_url, self.details)
91
95
 
92
96
 
93
97
class LogicalLockResult(object):
110
114
        # If there was an error raised, prefer the original one
111
115
        try:
112
116
            self.unlock()
113
 
        except:
 
117
        except BaseException:
114
118
            if exc_type is None:
115
119
                raise
116
120
        return False
119
123
def cant_unlock_not_held(locked_object):
120
124
    """An attempt to unlock failed because the object was not locked.
121
125
 
122
 
    This provides a policy point from which we can generate either a warning 
123
 
    or an exception.
 
126
    This provides a policy point from which we can generate either a warning or
 
127
    an exception.
124
128
    """
125
129
    # This is typically masking some other error and called from a finally
126
130
    # block, so it's useful to have the option not to generate a new error
128
132
    # raise LockNotHeld.
129
133
    if 'unlock' in debug.debug_flags:
130
134
        warnings.warn("%r is already unlocked" % (locked_object,),
131
 
            stacklevel=3)
 
135
                      stacklevel=3)
132
136
    else:
133
137
        raise errors.LockNotHeld(locked_object)
134
138
 
144
148
if sys.platform == 'win32':
145
149
    import msvcrt
146
150
    try:
147
 
        import win32file, pywintypes, winerror
 
151
        import win32file
 
152
        import pywintypes
 
153
        import winerror
148
154
        have_pywin32 = True
149
155
    except ImportError:
150
156
        pass
200
206
            fcntl.lockf(self.f, fcntl.LOCK_UN)
201
207
            self._clear_f()
202
208
 
203
 
 
204
209
    class _fcntl_WriteLock(_fcntl_FileLock):
205
210
 
206
211
        _open_locks = set()
241
246
            _fcntl_WriteLock._open_locks.remove(self.filename)
242
247
            self._unlock()
243
248
 
244
 
 
245
249
    class _fcntl_ReadLock(_fcntl_FileLock):
246
250
 
247
251
        _open_locks = {}
289
293
            """
290
294
            if self.filename in _fcntl_WriteLock._open_locks:
291
295
                raise AssertionError('file already locked: %r'
292
 
                    % (self.filename,))
 
296
                                     % (self.filename,))
293
297
            try:
294
298
                wlock = _fcntl_TemporaryWriteLock(self)
295
299
            except errors.LockError:
297
301
                return False, self
298
302
            return True, wlock
299
303
 
300
 
 
301
304
    class _fcntl_TemporaryWriteLock(_OSLock):
302
305
        """A token used when grabbing a temporary_write_lock.
303
306
 
317
320
 
318
321
            if self.filename in _fcntl_WriteLock._open_locks:
319
322
                raise AssertionError('file already locked: %r'
320
 
                    % (self.filename,))
 
323
                                     % (self.filename,))
321
324
 
322
325
            # See if we can open the file for writing. Another process might
323
326
            # have a read lock. We don't use self._open() because we don't want
342
345
 
343
346
        def restore_read_lock(self):
344
347
            """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.
 
348
            # For fcntl, since we never released the read lock, just release
 
349
            # the write lock, and return the original lock.
347
350
            fcntl.lockf(self.f, fcntl.LOCK_UN)
348
351
            self._clear_f()
349
352
            _fcntl_WriteLock._open_locks.remove(self.filename)
352
355
            self._read_lock = None
353
356
            return read_lock
354
357
 
355
 
 
356
358
    _lock_classes.append(('fcntl', _fcntl_WriteLock, _fcntl_ReadLock))
357
359
 
358
360
 
364
366
        def _open(self, filename, access, share, cflags, pymode):
365
367
            self.filename = osutils.realpath(filename)
366
368
            try:
367
 
                self._handle = win32file_CreateFile(filename, access, share,
368
 
                    None, win32file.OPEN_ALWAYS,
 
369
                self._handle = win32file_CreateFile(
 
370
                    filename, access, share, None, win32file.OPEN_ALWAYS,
369
371
                    win32file.FILE_ATTRIBUTE_NORMAL, None)
370
372
            except pywintypes.error as e:
371
373
                if e.args[0] == winerror.ERROR_ACCESS_DENIED:
381
383
            self._clear_f()
382
384
            self._handle = None
383
385
 
384
 
 
385
386
    class _w32c_ReadLock(_w32c_FileLock):
386
387
        def __init__(self, filename):
387
388
            super(_w32c_ReadLock, self).__init__()
388
389
            self._open(filename, win32file.GENERIC_READ,
389
 
                win32file.FILE_SHARE_READ, os.O_RDONLY, "rb")
 
390
                       win32file.FILE_SHARE_READ, os.O_RDONLY, "rb")
390
391
 
391
392
        def temporary_write_lock(self):
392
393
            """Try to grab a write lock on the file.
407
408
                return False, _w32c_ReadLock(self.filename)
408
409
            return True, wlock
409
410
 
410
 
 
411
411
    class _w32c_WriteLock(_w32c_FileLock):
412
412
        def __init__(self, filename):
413
413
            super(_w32c_WriteLock, self).__init__()
414
414
            self._open(filename,
415
 
                win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0,
416
 
                os.O_RDWR, "rb+")
 
415
                       win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0,
 
416
                       os.O_RDWR, "rb+")
417
417
 
418
418
        def restore_read_lock(self):
419
419
            """Restore the original ReadLock."""
422
422
            self.unlock()
423
423
            return _w32c_ReadLock(self.filename)
424
424
 
425
 
 
426
425
    _lock_classes.append(('pywin32', _w32c_WriteLock, _w32c_ReadLock))
427
426
 
428
427
 
429
428
if have_ctypes_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
 
429
    from ctypes.wintypes import DWORD, LPWSTR
 
430
    LPSECURITY_ATTRIBUTES = ctypes.c_void_p  # used as NULL no need to declare
 
431
    HANDLE = ctypes.c_int  # rather than unsigned as in ctypes.wintypes
433
432
    _function_name = "CreateFileW"
434
433
 
435
434
    # CreateFile <http://msdn.microsoft.com/en-us/library/aa363858.aspx>
436
435
    _CreateFile = ctypes.WINFUNCTYPE(
437
 
            HANDLE,                # return value
438
 
            LPWSTR,                # lpFileName
439
 
            DWORD,                 # dwDesiredAccess
440
 
            DWORD,                 # dwShareMode
441
 
            LPSECURITY_ATTRIBUTES, # lpSecurityAttributes
442
 
            DWORD,                 # dwCreationDisposition
443
 
            DWORD,                 # dwFlagsAndAttributes
444
 
            HANDLE                 # hTemplateFile
 
436
        HANDLE,                # return value
 
437
        LPWSTR,                # lpFileName
 
438
        DWORD,                 # dwDesiredAccess
 
439
        DWORD,                 # dwShareMode
 
440
        LPSECURITY_ATTRIBUTES,  # lpSecurityAttributes
 
441
        DWORD,                 # dwCreationDisposition
 
442
        DWORD,                 # dwFlagsAndAttributes
 
443
        HANDLE                 # hTemplateFile
445
444
        )((_function_name, ctypes.windll.kernel32))
446
445
 
447
446
    INVALID_HANDLE_VALUE = -1
460
459
        def _open(self, filename, access, share, cflags, pymode):
461
460
            self.filename = osutils.realpath(filename)
462
461
            handle = _CreateFile(filename, access, share, None, OPEN_ALWAYS,
463
 
                FILE_ATTRIBUTE_NORMAL, 0)
 
462
                                 FILE_ATTRIBUTE_NORMAL, 0)
464
463
            if handle in (INVALID_HANDLE_VALUE, 0):
465
464
                e = ctypes.WinError()
466
465
                if e.args[0] == ERROR_ACCESS_DENIED:
475
474
        def unlock(self):
476
475
            self._clear_f()
477
476
 
478
 
 
479
477
    class _ctypes_ReadLock(_ctypes_FileLock):
480
478
        def __init__(self, filename):
481
479
            super(_ctypes_ReadLock, self).__init__()
482
480
            self._open(filename, GENERIC_READ, FILE_SHARE_READ, os.O_RDONLY,
483
 
                "rb")
 
481
                       "rb")
484
482
 
485
483
        def temporary_write_lock(self):
486
484
            """Try to grab a write lock on the file.
505
503
        def __init__(self, filename):
506
504
            super(_ctypes_WriteLock, self).__init__()
507
505
            self._open(filename, GENERIC_READ | GENERIC_WRITE, 0, os.O_RDWR,
508
 
                "rb+")
 
506
                       "rb+")
509
507
 
510
508
        def restore_read_lock(self):
511
509
            """Restore the original ReadLock."""
514
512
            self.unlock()
515
513
            return _ctypes_ReadLock(self.filename)
516
514
 
517
 
 
518
515
    _lock_classes.append(('ctypes', _ctypes_WriteLock, _ctypes_ReadLock))
519
516
 
520
517
 
549
546
            trace.note(gettext('{0!r} was {1} locked again'), self, type_name)
550
547
        self._prev_lock = lock_type
551
548
 
 
549
 
552
550
@contextlib.contextmanager
553
551
def write_locked(lockable):
554
552
    lockable.lock_write()