summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2016-09-25 17:10:38 +0200
committerSebastian Thiel <byronimo@gmail.com>2016-09-25 17:10:38 +0200
commitd6b1a9272455ef80f01a48ea22efc85b7f976503 (patch)
tree8d545659b488f2c6d77e90f5a3167487563ff414
parent2d37049a815b11b594776d34be50e9c0ba8df497 (diff)
downloadgitpython-d6b1a9272455ef80f01a48ea22efc85b7f976503.tar.gz
fix(index): improve LockedFD handling
Relying on the destructor will not work, even though the code used to rely on it. Now we handle failures more explicitly. Far from perfect, but a good start for a fix. Fixes #514
-rw-r--r--git/index/base.py14
-rw-r--r--git/test/test_index.py17
2 files changed, 29 insertions, 2 deletions
diff --git a/git/index/base.py b/git/index/base.py
index 524b4568..86eda41e 100644
--- a/git/index/base.py
+++ b/git/index/base.py
@@ -118,13 +118,17 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable):
# read the current index
# try memory map for speed
lfd = LockedFD(self._file_path)
+ ok = False
try:
fd = lfd.open(write=False, stream=False)
+ ok = True
except OSError:
- lfd.rollback()
# in new repositories, there may be no index, which means we are empty
self.entries = dict()
return
+ finally:
+ if not ok:
+ lfd.rollback()
# END exception handling
# Here it comes: on windows in python 2.5, memory maps aren't closed properly
@@ -209,8 +213,14 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable):
self.entries
lfd = LockedFD(file_path or self._file_path)
stream = lfd.open(write=True, stream=True)
+ ok = False
- self._serialize(stream, ignore_extension_data)
+ try:
+ self._serialize(stream, ignore_extension_data)
+ ok = True
+ finally:
+ if not ok:
+ lfd.rollback()
lfd.commit()
diff --git a/git/test/test_index.py b/git/test/test_index.py
index ca877838..bce56089 100644
--- a/git/test/test_index.py
+++ b/git/test/test_index.py
@@ -135,6 +135,23 @@ class TestIndex(TestBase):
raise AssertionError("CMP Failed: Missing entries in index: %s, missing in tree: %s" %
(bset - iset, iset - bset))
# END assertion message
+
+ @with_rw_repo('0.1.6')
+ def test_index_lock_handling(self, rw_repo):
+ def add_bad_blob():
+ rw_repo.index.add([Blob(rw_repo, b'f' * 20, 'bad-permissions', 'foo')])
+
+ try:
+ ## 1st fail on purpose adding into index.
+ add_bad_blob()
+ except Exception as ex:
+ assert "cannot convert argument to integer" in str(ex)
+
+ ## 2nd time should not fail due to stray lock file
+ try:
+ add_bad_blob()
+ except Exception as ex:
+ assert "index.lock' could not be obtained" not in str(ex)
@with_rw_repo('0.1.6')
def test_index_file_from_tree(self, rw_repo):