summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--git/config.py36
-rw-r--r--git/test/test_config.py17
2 files changed, 38 insertions, 15 deletions
diff --git a/git/config.py b/git/config.py
index 21af6159..5bd10975 100644
--- a/git/config.py
+++ b/git/config.py
@@ -133,10 +133,11 @@ class SectionConstraint(object):
return self._config.release()
def __enter__(self):
+ self._config.__enter__()
return self
def __exit__(self, exception_type, exception_value, traceback):
- self.release()
+ self._config.__exit__(exception_type, exception_value, traceback)
class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, object)):
@@ -155,8 +156,7 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, obje
:note:
The config is case-sensitive even when queried, hence section and option names
must match perfectly.
- If used as a context manager, will release the locked file. This parser cannot
- be used afterwards."""
+ If used as a context manager, will release the locked file."""
#{ Configuration
# The lock type determines the type of lock to use in new configuration readers.
@@ -206,18 +206,23 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, obje
self._is_initialized = False
self._merge_includes = merge_includes
self._lock = None
-
- if not read_only:
- if isinstance(file_or_files, (tuple, list)):
- raise ValueError(
- "Write-ConfigParsers can operate on a single file only, multiple files have been passed")
- # END single file check
-
- if not isinstance(file_or_files, string_types):
- file_or_files = file_or_files.name
- # END get filename from handle/stream
- # initialize lock base - we want to write
- self._lock = self.t_lock(file_or_files)
+ self._aquire_lock()
+
+ def _aquire_lock(self):
+ if not self._read_only:
+ if not self._lock:
+ if isinstance(self._file_or_files, (tuple, list)):
+ raise ValueError(
+ "Write-ConfigParsers can operate on a single file only, multiple files have been passed")
+ # END single file check
+
+ file_or_files = self._file_or_files
+ if not isinstance(self._file_or_files, string_types):
+ file_or_files = self._file_or_files.name
+ # END get filename from handle/stream
+ # initialize lock base - we want to write
+ self._lock = self.t_lock(file_or_files)
+ # END lock check
self._lock._obtain_lock()
# END read-only check
@@ -228,6 +233,7 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, obje
self.release()
def __enter__(self):
+ self._aquire_lock()
return self
def __exit__(self, exception_type, exception_value, traceback):
diff --git a/git/test/test_config.py b/git/test/test_config.py
index 81eacd20..c0889c1a 100644
--- a/git/test/test_config.py
+++ b/git/test/test_config.py
@@ -72,6 +72,23 @@ class TestBase(TestCase):
w_config.release()
# END for each filename
+ @with_rw_directory
+ def test_lock_reentry(self, rw_dir):
+ fpl = os.path.join(rw_dir, 'l')
+ gcp = GitConfigParser(fpl, read_only=False)
+ with gcp as cw:
+ cw.set_value('include', 'some_value', 'a')
+ # entering again locks the file again...
+ with gcp as cw:
+ cw.set_value('include', 'some_other_value', 'b')
+ # ...so creating an additional config writer must fail due to exclusive access
+ self.failUnlessRaises(IOError, GitConfigParser, fpl, read_only=False)
+ # but work when the lock is removed
+ with GitConfigParser(fpl, read_only=False):
+ assert os.path.exists(fpl)
+ # reentering with an existing lock must fail due to exclusive access
+ self.failUnlessRaises(IOError, gcp.__enter__)
+
def test_multi_line_config(self):
file_obj = self._to_memcache(fixture_path("git_config_with_comments"))
config = GitConfigParser(file_obj, read_only=False)