Skip to content

Commit 547e6f0

Browse files
committed
Replaced lock file code with flock()
1 parent 48c149c commit 547e6f0

File tree

1 file changed

+26
-21
lines changed

1 file changed

+26
-21
lines changed

git/util.py

+26-21
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# This module is part of GitPython and is released under
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

7+
from fcntl import flock, LOCK_UN, LOCK_EX, LOCK_NB
78
import os
89
import re
910
import sys
@@ -324,12 +325,12 @@ def update(self, op_code, cur_count, max_count=None, message=''):
324325
325326
You may read the contents of the current line in self._cur_line"""
326327
pass
327-
328+
328329

329330
class CallableRemoteProgress(RemoteProgress):
330331
"""An implementation forwarding updates to any callable"""
331332
__slots__ = ('_callable')
332-
333+
333334
def __init__(self, fn):
334335
self._callable = fn
335336
super(CallableRemoteProgress, self).__init__()
@@ -535,9 +536,10 @@ class LockFile(object):
535536
As we are a utility class to be derived from, we only use protected methods.
536537
537538
Locks will automatically be released on destruction"""
538-
__slots__ = ("_file_path", "_owns_lock")
539+
__slots__ = ("_file_path", "_owns_lock", "_file_descriptor")
539540

540541
def __init__(self, file_path):
542+
self._file_descriptor = None
541543
self._file_path = file_path
542544
self._owns_lock = False
543545

@@ -559,17 +561,24 @@ def _obtain_lock_or_raise(self):
559561
:raise IOError: if a lock was already present or a lock file could not be written"""
560562
if self._has_lock():
561563
return
564+
562565
lock_file = self._lock_file_path()
563-
if os.path.isfile(lock_file):
564-
raise IOError("Lock for file %r did already exist, delete %r in case the lock is illegal" %
565-
(self._file_path, lock_file))
566+
567+
# Create lock file
568+
try:
569+
open(lock_file, 'a').close()
570+
except OSError as e:
571+
# Silence error only if file exists
572+
if e.errno != 17: # 17 -> File exists
573+
raise
566574

567575
try:
568-
fd = os.open(lock_file, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0)
569-
os.close(fd)
576+
fd = os.open(lock_file, os.O_WRONLY, 0)
577+
flock(fd, LOCK_EX | LOCK_NB)
570578
except OSError as e:
571579
raise IOError(str(e))
572580

581+
self._file_descriptor = fd
573582
self._owns_lock = True
574583

575584
def _obtain_lock(self):
@@ -582,19 +591,15 @@ def _release_lock(self):
582591
if not self._has_lock():
583592
return
584593

585-
# if someone removed our file beforhand, lets just flag this issue
586-
# instead of failing, to make it more usable.
587-
lfp = self._lock_file_path()
588-
try:
589-
# on bloody windows, the file needs write permissions to be removable.
590-
# Why ...
591-
if os.name == 'nt':
592-
os.chmod(lfp, 0o777)
593-
# END handle win32
594-
os.remove(lfp)
595-
except OSError:
596-
pass
594+
fd = self._file_descriptor
595+
lock_file = self._lock_file_path()
596+
597+
flock(fd, LOCK_UN)
598+
os.close(fd)
599+
os.remove(lock_file)
600+
597601
self._owns_lock = False
602+
self._file_descriptor = None
598603

599604

600605
class BlockingLockFile(LockFile):
@@ -629,7 +634,7 @@ def _obtain_lock(self):
629634
try:
630635
super(BlockingLockFile, self)._obtain_lock()
631636
except IOError:
632-
# synity check: if the directory leading to the lockfile is not
637+
# sanity check: if the directory leading to the lockfile is not
633638
# readable anymore, raise an execption
634639
curtime = time.time()
635640
if not os.path.isdir(os.path.dirname(self._lock_file_path())):

0 commit comments

Comments
 (0)