# test_config.py
# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import glob
import io
from git import (
GitConfigParser
)
from git.compat import string_types
from git.config import _OMD, cp
from git.test.lib import (
TestCase,
fixture_path,
SkipTest,
)
from git.test.lib import with_rw_directory
import os.path as osp
from git.util import rmfile
_tc_lock_fpaths = osp.join(osp.dirname(__file__), 'fixtures/*.lock')
def _rm_lock_files():
for lfp in glob.glob(_tc_lock_fpaths):
rmfile(lfp)
class TestBase(TestCase):
def setUp(self):
_rm_lock_files()
def tearDown(self):
for lfp in glob.glob(_tc_lock_fpaths):
if osp.isfile(lfp):
raise AssertionError('Previous TC left hanging git-lock file: {}'.format(lfp))
def _to_memcache(self, file_path):
with open(file_path, "rb") as fp:
sio = io.BytesIO(fp.read())
sio.name = file_path
return sio
def test_read_write(self):
# writer must create the exact same file as the one read before
for filename in ("git_config", "git_config_global"):
file_obj = self._to_memcache(fixture_path(filename))
with GitConfigParser(file_obj, read_only=False) as w_config:
w_config.read() # enforce reading
assert w_config._sections
w_config.write() # enforce writing
# we stripped lines when reading, so the results differ
assert file_obj.getvalue()
self.assertEqual(file_obj.getvalue(), self._to_memcache(fixture_path(filename)).getvalue())
# creating an additional config writer must fail due to exclusive access
with self.assertRaises(IOError):
GitConfigParser(file_obj, read_only=False)
# should still have a lock and be able to make changes
assert w_config._lock._has_lock()
# changes should be written right away
sname = "my_section"
val = "myvalue"
w_config.add_section(sname)
assert w_config.has_section(sname)
w_config.set(sname, oname, val)
assert w_config.has_option(sname, oname)
assert w_config.get(sname, oname) == val
sname_new = "new_section"
ival = 10
w_config.set_value(sname_new, oname_new, ival)
assert w_config.get_value(sname_new, oname_new) == ival
file_obj.seek(0)
r_config = GitConfigParser(file_obj, read_only=True)
assert r_config.has_section(sname)
assert r_config.has_option(sname, oname)
assert r_config.get(sname, oname) == val
# END for each filename
def test_includes_order(self):
with GitConfigParser(list(map(fixture_path, ("git_config", "git_config_global")))) as r_config:
r_config.read() # enforce reading
# Simple inclusions, again checking them taking precedence
assert r_config.get_value('sec', 'var0') == "value0_included"
# This one should take the git_config_global value since included
# values must be considered as soon as they get them
assert r_config.get_value('diff', 'tool') == "meld"
try:
assert r_config.get_value('sec', 'var1') == "value1_main"
except AssertionError:
raise SkipTest(
'Known failure -- included values are not in effect right away'
)
@with_rw_directory
def test_lock_reentry(self, rw_dir):
fpl = osp.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
with self.assertRaises(IOError):
GitConfigParser(fpl, read_only=False)
# but work when the lock is removed
with GitConfigParser(fpl, read_only=False):
assert osp.exists(fpl)
# reentering with an existing lock must fail due to exclusive access
with self.assertRaises(IOError):
gcp.__enter__()
def test_multi_line_config(self):
file_obj = self._to_memcache(fixture_path("git_config_with_comments"))
with GitConfigParser(file_obj, read_only=False) as config:
ev = "ruby -e '\n"
ev += " system %(git), %(merge-file), %(--marker-size=%L), %(%A), %(%O), %(%B)\n"
ev += " b = File.read(%(%A))\n"
ev += " b.sub!(/^ (\\d+). do\\n=+\\nActiveRecord::Schema\\." # noqa E501
ev += "define.:version => (\\d+). do\\n>+ .*/) do\n"
ev += " %(ActiveRecord::Schema.define(:version => #{[$1, $2].max}) do)\n"
ev += " end\n"
ev += " File.open(%(%A), %(w)) {|f| f.write(b)}\n"
ev += " exit 1 if b.include?(%(