diff options
Diffstat (limited to 'lib/git')
-rw-r--r-- | lib/git/index.py | 15 | ||||
-rw-r--r-- | lib/git/utils.py | 40 |
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): """ |