diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2009-12-10 21:05:57 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2009-12-10 21:05:57 +0100 |
commit | 54844a90b97fd7854e53a9aec85bf60564362a02 (patch) | |
tree | d91b8c7e3a7783edb6106753bb593ba567d4bd99 /lib/git | |
parent | a97d21936200f1221d8ddd89202042faed1b9bcb (diff) | |
download | gitpython-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.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): """ |