summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniele Esposti <daniele.esposti@gmail.com>2016-09-12 17:19:20 +0100
committerDaniele Esposti <daniele.esposti@gmail.com>2016-09-12 17:19:20 +0100
commit547e6f0e2e9ace80e6d6b08db3c15fe91efe880f (patch)
treedd4894302cde719138f4816a52d3179c5105ca1c
parent48c149c16a9bb06591c2eb0be4cca729b7feac3e (diff)
downloadgitpython-547e6f0e2e9ace80e6d6b08db3c15fe91efe880f.tar.gz
Replaced lock file code with flock()
-rw-r--r--git/util.py47
1 files changed, 26 insertions, 21 deletions
diff --git a/git/util.py b/git/util.py
index f5c69231..fff8ddc0 100644
--- a/git/util.py
+++ b/git/util.py
@@ -4,6 +4,7 @@
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
+from fcntl import flock, LOCK_UN, LOCK_EX, LOCK_NB
import os
import re
import sys
@@ -324,12 +325,12 @@ class RemoteProgress(object):
You may read the contents of the current line in self._cur_line"""
pass
-
+
class CallableRemoteProgress(RemoteProgress):
"""An implementation forwarding updates to any callable"""
__slots__ = ('_callable')
-
+
def __init__(self, fn):
self._callable = fn
super(CallableRemoteProgress, self).__init__()
@@ -535,9 +536,10 @@ class LockFile(object):
As we are a utility class to be derived from, we only use protected methods.
Locks will automatically be released on destruction"""
- __slots__ = ("_file_path", "_owns_lock")
+ __slots__ = ("_file_path", "_owns_lock", "_file_descriptor")
def __init__(self, file_path):
+ self._file_descriptor = None
self._file_path = file_path
self._owns_lock = False
@@ -559,17 +561,24 @@ class LockFile(object):
:raise IOError: if a lock was already present or a lock file could not be written"""
if self._has_lock():
return
+
lock_file = self._lock_file_path()
- if os.path.isfile(lock_file):
- raise IOError("Lock for file %r did already exist, delete %r in case the lock is illegal" %
- (self._file_path, lock_file))
+
+ # Create lock file
+ try:
+ open(lock_file, 'a').close()
+ except OSError as e:
+ # Silence error only if file exists
+ if e.errno != 17: # 17 -> File exists
+ raise
try:
- fd = os.open(lock_file, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0)
- os.close(fd)
+ fd = os.open(lock_file, os.O_WRONLY, 0)
+ flock(fd, LOCK_EX | LOCK_NB)
except OSError as e:
raise IOError(str(e))
+ self._file_descriptor = fd
self._owns_lock = True
def _obtain_lock(self):
@@ -582,19 +591,15 @@ class LockFile(object):
if not self._has_lock():
return
- # if someone removed our file beforhand, lets just flag this issue
- # instead of failing, to make it more usable.
- lfp = self._lock_file_path()
- try:
- # on bloody windows, the file needs write permissions to be removable.
- # Why ...
- if os.name == 'nt':
- os.chmod(lfp, 0o777)
- # END handle win32
- os.remove(lfp)
- except OSError:
- pass
+ fd = self._file_descriptor
+ lock_file = self._lock_file_path()
+
+ flock(fd, LOCK_UN)
+ os.close(fd)
+ os.remove(lock_file)
+
self._owns_lock = False
+ self._file_descriptor = None
class BlockingLockFile(LockFile):
@@ -629,7 +634,7 @@ class BlockingLockFile(LockFile):
try:
super(BlockingLockFile, self)._obtain_lock()
except IOError:
- # synity check: if the directory leading to the lockfile is not
+ # sanity check: if the directory leading to the lockfile is not
# readable anymore, raise an execption
curtime = time.time()
if not os.path.isdir(os.path.dirname(self._lock_file_path())):