Skip to content

Commit ab7a872

Browse files
committed
Updated file locking for Windows platform
1 parent d437f88 commit ab7a872

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

git/util.py

+52-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66
from __future__ import unicode_literals
77

8-
from fcntl import flock, LOCK_UN, LOCK_EX, LOCK_NB
98
import getpass
109
import logging
1110
import os
@@ -49,6 +48,57 @@
4948

5049
#{ Utility Methods
5150

51+
if platform.system() == 'Windows':
52+
# This code is a derivative work of Portalocker http://code.activestate.com/recipes/65203/
53+
import win32con
54+
import win32file
55+
import pywintypes
56+
57+
LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
58+
LOCK_SH = 0 # the default
59+
LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
60+
LOCK_UN = 1 << 2
61+
62+
__overlapped = pywintypes.OVERLAPPED()
63+
64+
def flock(fd, flags=0):
65+
hfile = win32file._get_osfhandle(fd)
66+
67+
if flags & LOCK_UN != 0:
68+
# Unlock file descriptor
69+
try:
70+
win32file.UnlockFileEx(hfile, 0, -0x10000, __overlapped)
71+
except pywintypes.error, exc_value:
72+
# error: (158, 'UnlockFileEx', 'The segment is already unlocked.')
73+
# To match the 'posix' implementation, silently ignore this error
74+
if exc_value[0] == 158:
75+
pass
76+
else:
77+
# Q: Are there exceptions/codes we should be dealing with here?
78+
raise
79+
80+
elif flags & LOCK_EX != 0:
81+
# Lock file
82+
try:
83+
win32file.LockFileEx(hfile, flags, 0, -0x10000, __overlapped)
84+
except pywintypes.error, exc_value:
85+
if exc_value[0] == 33:
86+
# error: (33, 'LockFileEx',
87+
# 'The process cannot access the file because another process has locked
88+
# a portion of the file.')
89+
raise IOError(33, exc_value[2])
90+
else:
91+
# Q: Are there exceptions/codes we should be dealing with here?
92+
raise
93+
94+
else:
95+
raise NotImplementedError("Unsupported set of bitflags {}".format(bin(flags)))
96+
97+
98+
else:
99+
# from fcntl import flock, LOCK_UN, LOCK_EX, LOCK_NB
100+
pass
101+
52102

53103
def unbare_repo(func):
54104
"""Methods with this decorator raise InvalidGitRepositoryError if they
@@ -620,6 +670,7 @@ def _release_lock(self):
620670
rmfile(lock_file)
621671
except OSError:
622672
pass
673+
623674
self._owns_lock = False
624675
self._file_descriptor = None
625676

0 commit comments

Comments
 (0)