summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--AUTHORS1
-rw-r--r--git/test/test_util.py2
-rw-r--r--git/util.py24
4 files changed, 21 insertions, 7 deletions
diff --git a/.gitignore b/.gitignore
index d35cddeb..a672c3f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@ nbproject
.DS_Store
/*egg-info
/.tox
+.cache
diff --git a/AUTHORS b/AUTHORS
index e2c3293c..b06c5b46 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -15,5 +15,6 @@ Contributors are:
-Jonathan Chu <jonathan.chu _at_ me.com>
-Vincent Driessen <me _at_ nvie.com>
-Phil Elson <pelson _dot_ pub _at_ gmail.com>
+-Daniele Esposti <daniele.esposti _at_ gmail.com>
Portions derived from other open source works and are clearly marked.
diff --git a/git/test/test_util.py b/git/test/test_util.py
index e07417b4..6ba3d0d4 100644
--- a/git/test/test_util.py
+++ b/git/test/test_util.py
@@ -5,6 +5,7 @@
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import tempfile
+import gc
from git.test.lib import (
TestBase,
@@ -80,6 +81,7 @@ class TestUtils(TestBase):
# auto-release on destruction
del(other_lock_file)
+ gc.collect()
lock_file._obtain_lock_or_raise()
lock_file._release_lock()
diff --git a/git/util.py b/git/util.py
index c96a6b08..9f8ccea5 100644
--- a/git/util.py
+++ b/git/util.py
@@ -5,6 +5,7 @@
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
from __future__ import unicode_literals
+from fcntl import flock, LOCK_UN, LOCK_EX, LOCK_NB
import getpass
import logging
import os
@@ -555,9 +556,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
@@ -579,20 +581,21 @@ 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 file and lock
try:
- flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
+ flags = os.O_CREAT
if is_win:
flags |= os.O_SHORT_LIVED
fd = os.open(lock_file, flags, 0)
- os.close(fd)
except OSError as e:
raise IOError(str(e))
+ flock(fd, LOCK_EX | LOCK_NB)
+
+ self._file_descriptor = fd
self._owns_lock = True
def _obtain_lock(self):
@@ -605,6 +608,12 @@ class LockFile(object):
if not self._has_lock():
return
+ fd = self._file_descriptor
+ lock_file = self._lock_file_path()
+
+ flock(fd, LOCK_UN)
+ os.close(fd)
+
# if someone removed our file beforhand, lets just flag this issue
# instead of failing, to make it more usable.
lfp = self._lock_file_path()
@@ -613,6 +622,7 @@ class LockFile(object):
except OSError:
pass
self._owns_lock = False
+ self._file_descriptor = None
class BlockingLockFile(LockFile):
@@ -647,7 +657,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())):