summaryrefslogtreecommitdiff
path: root/lib/git
diff options
context:
space:
mode:
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):
"""