/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-06-03 23:48:08 UTC
  • mfrom: (7316 work)
  • mto: This revision was merged to the branch mainline in revision 7328.
  • Revision ID: jelmer@jelmer.uk-20190603234808-15yk5c7054tj8e2b
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
143
143
except ImportError:
144
144
    have_fcntl = False
145
145
 
 
146
have_pywin32 = False
146
147
have_ctypes_win32 = False
147
148
if sys.platform == 'win32':
148
149
    import msvcrt
149
150
    try:
 
151
        import win32file
 
152
        import pywintypes
 
153
        import winerror
 
154
        have_pywin32 = True
 
155
    except ImportError:
 
156
        pass
 
157
 
 
158
    try:
150
159
        import ctypes
151
160
        have_ctypes_win32 = True
152
161
    except ImportError:
349
358
    _lock_classes.append(('fcntl', _fcntl_WriteLock, _fcntl_ReadLock))
350
359
 
351
360
 
 
361
if have_pywin32 and sys.platform == 'win32':
 
362
    win32file_CreateFile = win32file.CreateFileW
 
363
 
 
364
    class _w32c_FileLock(_OSLock):
 
365
 
 
366
        def _open(self, filename, access, share, cflags, pymode):
 
367
            self.filename = osutils.realpath(filename)
 
368
            try:
 
369
                self._handle = win32file_CreateFile(
 
370
                    filename, access, share, None, win32file.OPEN_ALWAYS,
 
371
                    win32file.FILE_ATTRIBUTE_NORMAL, None)
 
372
            except pywintypes.error as e:
 
373
                if e.args[0] == winerror.ERROR_ACCESS_DENIED:
 
374
                    raise errors.LockFailed(filename, e)
 
375
                if e.args[0] == winerror.ERROR_SHARING_VIOLATION:
 
376
                    raise errors.LockContention(filename, e)
 
377
                raise
 
378
            fd = win32file._open_osfhandle(self._handle, cflags)
 
379
            self.f = os.fdopen(fd, pymode)
 
380
            return self.f
 
381
 
 
382
        def unlock(self):
 
383
            self._clear_f()
 
384
            self._handle = None
 
385
 
 
386
    class _w32c_ReadLock(_w32c_FileLock):
 
387
        def __init__(self, filename):
 
388
            super(_w32c_ReadLock, self).__init__()
 
389
            self._open(filename, win32file.GENERIC_READ,
 
390
                       win32file.FILE_SHARE_READ, os.O_RDONLY, "rb")
 
391
 
 
392
        def temporary_write_lock(self):
 
393
            """Try to grab a write lock on the file.
 
394
 
 
395
            On platforms that support it, this will upgrade to a write lock
 
396
            without unlocking the file.
 
397
            Otherwise, this will release the read lock, and try to acquire a
 
398
            write lock.
 
399
 
 
400
            :return: A token which can be used to switch back to a read lock.
 
401
            """
 
402
            # I can't find a way to upgrade a read lock to a write lock without
 
403
            # unlocking first. So here, we do just that.
 
404
            self.unlock()
 
405
            try:
 
406
                wlock = _w32c_WriteLock(self.filename)
 
407
            except errors.LockError:
 
408
                return False, _w32c_ReadLock(self.filename)
 
409
            return True, wlock
 
410
 
 
411
    class _w32c_WriteLock(_w32c_FileLock):
 
412
        def __init__(self, filename):
 
413
            super(_w32c_WriteLock, self).__init__()
 
414
            self._open(filename,
 
415
                       win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0,
 
416
                       os.O_RDWR, "rb+")
 
417
 
 
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
 
 
425
    _lock_classes.append(('pywin32', _w32c_WriteLock, _w32c_ReadLock))
 
426
 
 
427
 
352
428
if have_ctypes_win32:
353
429
    from ctypes.wintypes import DWORD, LPWSTR
354
430
    LPSECURITY_ATTRIBUTES = ctypes.c_void_p  # used as NULL no need to declare
441
517
 
442
518
if len(_lock_classes) == 0:
443
519
    raise NotImplementedError(
444
 
        "We must have one of fcntl or ctypes available"
 
520
        "We must have one of fcntl, pywin32, or ctypes available"
445
521
        " to support OS locking."
446
522
        )
447
523