diff options
author | Daniele Esposti <daniele.esposti@gmail.com> | 2016-09-12 17:19:20 +0100 |
---|---|---|
committer | Daniele Esposti <daniele.esposti@gmail.com> | 2016-09-12 17:19:20 +0100 |
commit | 547e6f0e2e9ace80e6d6b08db3c15fe91efe880f (patch) | |
tree | dd4894302cde719138f4816a52d3179c5105ca1c | |
parent | 48c149c16a9bb06591c2eb0be4cca729b7feac3e (diff) | |
download | gitpython-547e6f0e2e9ace80e6d6b08db3c15fe91efe880f.tar.gz |
Replaced lock file code with flock()
-rw-r--r-- | git/util.py | 47 |
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())): |