summaryrefslogtreecommitdiff
path: root/lib/git
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-12-10 21:05:57 +0100
committerSebastian Thiel <byronimo@gmail.com>2009-12-10 21:05:57 +0100
commit54844a90b97fd7854e53a9aec85bf60564362a02 (patch)
treed91b8c7e3a7783edb6106753bb593ba567d4bd99 /lib/git
parenta97d21936200f1221d8ddd89202042faed1b9bcb (diff)
downloadgitpython-54844a90b97fd7854e53a9aec85bf60564362a02.tar.gz
index: TempFileMover now handles the case that the file to move does not exist more gracefully
Added BlockingLockFile which may be used to wait for the lock according to some criteria
Diffstat (limited to 'lib/git')
-rw-r--r--lib/git/index.py15
-rw-r--r--lib/git/utils.py40
2 files changed, 51 insertions, 4 deletions
diff --git a/lib/git/index.py b/lib/git/index.py
index 64a25a70..991c77da 100644
--- a/lib/git/index.py
+++ b/lib/git/index.py
@@ -57,7 +57,11 @@ class _TemporaryFileSwap(object):
def __init__(self, file_path):
self.file_path = file_path
self.tmp_file_path = self.file_path + tempfile.mktemp('','','')
- os.rename(self.file_path, self.tmp_file_path)
+ # it may be that the source does not exist
+ try:
+ os.rename(self.file_path, self.tmp_file_path)
+ except OSError:
+ pass
def __del__(self):
if os.path.isfile(self.tmp_file_path):
@@ -556,6 +560,7 @@ class IndexFile(LazyMixin, diff.Diffable):
repo.git.read_tree(*arg_list, **kwargs)
index = cls(repo, tmp_index)
index.entries # force it to read the file as we will delete the temp-file
+ del(index_handler) # release as soon as possible
finally:
if os.path.exists(tmp_index):
os.remove(tmp_index)
@@ -763,9 +768,6 @@ class IndexFile(LazyMixin, diff.Diffable):
Returns
Tree object representing this index
"""
- index_path = self._index_path()
- tmp_index_mover = _TemporaryFileSwap(index_path)
-
# IMPORTANT: If we have TREE extension data, it will actually
# ignore the index and write the stored tree instead. Hence we
# temporarily forget about it, and in fact I don't know what git
@@ -776,9 +778,14 @@ class IndexFile(LazyMixin, diff.Diffable):
self._extension_data = ''
# END extension data special handling
+ index_path = self._index_path()
+ tmp_index_mover = _TemporaryFileSwap(index_path)
+
self.write(index_path)
tree_sha = self.repo.git.write_tree(missing_ok=missing_ok)
+ del(tmp_index_mover) # as soon as possible
+
if stored_ext_data:
self._extension_data = stored_ext_data
# END reset stored exstension data
diff --git a/lib/git/utils.py b/lib/git/utils.py
index 1a624ca2..b5364c4c 100644
--- a/lib/git/utils.py
+++ b/lib/git/utils.py
@@ -6,6 +6,7 @@
import os
import sys
+import time
import tempfile
try:
@@ -172,6 +173,45 @@ class LockFile(object):
os.remove(self._lock_file_path())
self._owns_lock = False
+class BlockingLockFile(LockFile):
+ """The lock file will block until a lock could be obtained, or fail after
+ a specified timeout"""
+ __slots__ = ("_check_interval", "_max_block_time")
+ def __init__(self, file_path, check_interval_s=0.3, max_block_time_s=sys.maxint):
+ """Configure the instance
+
+ ``check_interval_s``
+ Period of time to sleep until the lock is checked the next time.
+ By default, it waits a nearly unlimited time
+
+ ``max_block_time_s``
+ Maximum amount of seconds we may lock
+ """
+ super(BlockingLockFile, self).__init__(file_path)
+ self._check_interval = check_interval_s
+ self._max_block_time = max_block_time_s
+
+ def _obtain_lock(self):
+ """This method blocks until it obtained the lock, or raises IOError if
+ it ran out of time.
+ If this method returns, you are guranteed to own the lock"""
+ starttime = time.time()
+ maxtime = starttime + float(self._max_block_time)
+ while True:
+ try:
+ self._obtain_lock_or_raise()
+ except IOError:
+ curtime = time.time()
+ if curtime >= maxtime:
+ msg = "Waited %f seconds for lock at %r" % ( maxtime - starttime, self._lock_file_path())
+ raise IOError(msg)
+ # END abort if we wait too long
+ time.sleep(self._check_interval)
+ else:
+ break
+ # END endless loop
+
+
class ConcurrentWriteOperation(LockFile):
"""