diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | git/test/test_util.py | 2 | ||||
-rw-r--r-- | git/util.py | 24 |
4 files changed, 21 insertions, 7 deletions
@@ -14,3 +14,4 @@ nbproject .DS_Store /*egg-info /.tox +.cache @@ -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())): |