summaryrefslogtreecommitdiff
path: root/git/test/test_config.py
diff options
context:
space:
mode:
authorSebastian Thiel <sebastian.thiel@icloud.com>2020-07-12 18:04:26 +0800
committerSebastian Thiel <sebastian.thiel@icloud.com>2020-07-12 18:04:26 +0800
commitd5f0d48745727684473cf583a002e2c31174de2d (patch)
tree2c499fe4cb719e8b95d74449363bc20cf280bcce /git/test/test_config.py
parentfe65adc904f3e3ebf74e983e91b4346d5bacc468 (diff)
downloadgitpython-d5f0d48745727684473cf583a002e2c31174de2d.tar.gz
Revert moving tests out of 'git' folder, related to #1030
Diffstat (limited to 'git/test/test_config.py')
-rw-r--r--git/test/test_config.py373
1 files changed, 373 insertions, 0 deletions
diff --git a/git/test/test_config.py b/git/test/test_config.py
new file mode 100644
index 00000000..8418299f
--- /dev/null
+++ b/git/test/test_config.py
@@ -0,0 +1,373 @@
+# 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.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"
+ oname = "mykey"
+ 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"
+ oname_new = "new_key"
+ 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 as e:
+ raise SkipTest(
+ 'Known failure -- included values are not in effect right away'
+ ) from e
+
+ @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!(/^<+ .*\\nActiveRecord::Schema\\.define.:version => (\\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?(%(<)*%L)'"
+ self.assertEqual(config.get('merge "railsschema"', 'driver'), ev)
+ self.assertEqual(config.get('alias', 'lg'),
+ "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset'"
+ " --abbrev-commit --date=relative")
+ self.assertEqual(len(config.sections()), 23)
+
+ def test_base(self):
+ path_repo = fixture_path("git_config")
+ path_global = fixture_path("git_config_global")
+ r_config = GitConfigParser([path_repo, path_global], read_only=True)
+ assert r_config.read_only
+ num_sections = 0
+ num_options = 0
+
+ # test reader methods
+ assert r_config._is_initialized is False
+ for section in r_config.sections():
+ num_sections += 1
+ for option in r_config.options(section):
+ num_options += 1
+ val = r_config.get(section, option)
+ val_typed = r_config.get_value(section, option)
+ assert isinstance(val_typed, (bool, int, float, str))
+ assert val
+ assert "\n" not in option
+ assert "\n" not in val
+
+ # writing must fail
+ with self.assertRaises(IOError):
+ r_config.set(section, option, None)
+ with self.assertRaises(IOError):
+ r_config.remove_option(section, option)
+ # END for each option
+ with self.assertRaises(IOError):
+ r_config.remove_section(section)
+ # END for each section
+ assert num_sections and num_options
+ assert r_config._is_initialized is True
+
+ # get value which doesnt exist, with default
+ default = "my default value"
+ assert r_config.get_value("doesnt", "exist", default) == default
+
+ # it raises if there is no default though
+ with self.assertRaises(cp.NoSectionError):
+ r_config.get_value("doesnt", "exist")
+
+ @with_rw_directory
+ def test_config_include(self, rw_dir):
+ def write_test_value(cw, value):
+ cw.set_value(value, 'value', value)
+ # end
+
+ def check_test_value(cr, value):
+ assert cr.get_value(value, 'value') == value
+ # end
+
+ # PREPARE CONFIG FILE A
+ fpa = osp.join(rw_dir, 'a')
+ with GitConfigParser(fpa, read_only=False) as cw:
+ write_test_value(cw, 'a')
+
+ fpb = osp.join(rw_dir, 'b')
+ fpc = osp.join(rw_dir, 'c')
+ cw.set_value('include', 'relative_path_b', 'b')
+ cw.set_value('include', 'doesntexist', 'foobar')
+ cw.set_value('include', 'relative_cycle_a_a', 'a')
+ cw.set_value('include', 'absolute_cycle_a_a', fpa)
+ assert osp.exists(fpa)
+
+ # PREPARE CONFIG FILE B
+ with GitConfigParser(fpb, read_only=False) as cw:
+ write_test_value(cw, 'b')
+ cw.set_value('include', 'relative_cycle_b_a', 'a')
+ cw.set_value('include', 'absolute_cycle_b_a', fpa)
+ cw.set_value('include', 'relative_path_c', 'c')
+ cw.set_value('include', 'absolute_path_c', fpc)
+
+ # PREPARE CONFIG FILE C
+ with GitConfigParser(fpc, read_only=False) as cw:
+ write_test_value(cw, 'c')
+
+ with GitConfigParser(fpa, read_only=True) as cr:
+ for tv in ('a', 'b', 'c'):
+ check_test_value(cr, tv)
+ # end for each test to verify
+ assert len(cr.items('include')) == 8, "Expected all include sections to be merged"
+
+ # test writable config writers - assure write-back doesn't involve includes
+ with GitConfigParser(fpa, read_only=False, merge_includes=True) as cw:
+ tv = 'x'
+ write_test_value(cw, tv)
+
+ with GitConfigParser(fpa, read_only=True) as cr:
+ with self.assertRaises(cp.NoSectionError):
+ check_test_value(cr, tv)
+
+ # But can make it skip includes altogether, and thus allow write-backs
+ with GitConfigParser(fpa, read_only=False, merge_includes=False) as cw:
+ write_test_value(cw, tv)
+
+ with GitConfigParser(fpa, read_only=True) as cr:
+ check_test_value(cr, tv)
+
+ def test_rename(self):
+ file_obj = self._to_memcache(fixture_path('git_config'))
+ with GitConfigParser(file_obj, read_only=False, merge_includes=False) as cw:
+ with self.assertRaises(ValueError):
+ cw.rename_section("doesntexist", "foo")
+ with self.assertRaises(ValueError):
+ cw.rename_section("core", "include")
+
+ nn = "bee"
+ assert cw.rename_section('core', nn) is cw
+ assert not cw.has_section('core')
+ assert len(cw.items(nn)) == 4
+
+ def test_complex_aliases(self):
+ file_obj = self._to_memcache(fixture_path('.gitconfig'))
+ with GitConfigParser(file_obj, read_only=False) as w_config:
+ self.assertEqual(w_config.get('alias', 'rbi'), '"!g() { git rebase -i origin/${1:-master} ; } ; g"')
+ self.assertEqual(file_obj.getvalue(), self._to_memcache(fixture_path('.gitconfig')).getvalue())
+
+ def test_empty_config_value(self):
+ cr = GitConfigParser(fixture_path('git_config_with_empty_value'), read_only=True)
+
+ assert cr.get_value('core', 'filemode'), "Should read keys with values"
+
+ with self.assertRaises(cp.NoOptionError):
+ cr.get_value('color', 'ui')
+
+ def test_multiple_values(self):
+ file_obj = self._to_memcache(fixture_path('git_config_multiple'))
+ with GitConfigParser(file_obj, read_only=False) as cw:
+ self.assertEqual(cw.get('section0', 'option0'), 'value0')
+ self.assertEqual(cw.get_values('section0', 'option0'), ['value0'])
+ self.assertEqual(cw.items('section0'), [('option0', 'value0')])
+
+ # Where there are multiple values, "get" returns the last.
+ self.assertEqual(cw.get('section1', 'option1'), 'value1b')
+ self.assertEqual(cw.get_values('section1', 'option1'),
+ ['value1a', 'value1b'])
+ self.assertEqual(cw.items('section1'),
+ [('option1', 'value1b'),
+ ('other_option1', 'other_value1')])
+ self.assertEqual(cw.items_all('section1'),
+ [('option1', ['value1a', 'value1b']),
+ ('other_option1', ['other_value1'])])
+ with self.assertRaises(KeyError):
+ cw.get_values('section1', 'missing')
+
+ self.assertEqual(cw.get_values('section1', 'missing', 1), [1])
+ self.assertEqual(cw.get_values('section1', 'missing', 's'), ['s'])
+
+ def test_multiple_values_rename(self):
+ file_obj = self._to_memcache(fixture_path('git_config_multiple'))
+ with GitConfigParser(file_obj, read_only=False) as cw:
+ cw.rename_section('section1', 'section2')
+ cw.write()
+ file_obj.seek(0)
+ cr = GitConfigParser(file_obj, read_only=True)
+ self.assertEqual(cr.get_value('section2', 'option1'), 'value1b')
+ self.assertEqual(cr.get_values('section2', 'option1'),
+ ['value1a', 'value1b'])
+ self.assertEqual(cr.items('section2'),
+ [('option1', 'value1b'),
+ ('other_option1', 'other_value1')])
+ self.assertEqual(cr.items_all('section2'),
+ [('option1', ['value1a', 'value1b']),
+ ('other_option1', ['other_value1'])])
+
+ def test_multiple_to_single(self):
+ file_obj = self._to_memcache(fixture_path('git_config_multiple'))
+ with GitConfigParser(file_obj, read_only=False) as cw:
+ cw.set_value('section1', 'option1', 'value1c')
+
+ cw.write()
+ file_obj.seek(0)
+ cr = GitConfigParser(file_obj, read_only=True)
+ self.assertEqual(cr.get_value('section1', 'option1'), 'value1c')
+ self.assertEqual(cr.get_values('section1', 'option1'), ['value1c'])
+ self.assertEqual(cr.items('section1'),
+ [('option1', 'value1c'),
+ ('other_option1', 'other_value1')])
+ self.assertEqual(cr.items_all('section1'),
+ [('option1', ['value1c']),
+ ('other_option1', ['other_value1'])])
+
+ def test_single_to_multiple(self):
+ file_obj = self._to_memcache(fixture_path('git_config_multiple'))
+ with GitConfigParser(file_obj, read_only=False) as cw:
+ cw.add_value('section1', 'other_option1', 'other_value1a')
+
+ cw.write()
+ file_obj.seek(0)
+ cr = GitConfigParser(file_obj, read_only=True)
+ self.assertEqual(cr.get_value('section1', 'option1'), 'value1b')
+ self.assertEqual(cr.get_values('section1', 'option1'),
+ ['value1a', 'value1b'])
+ self.assertEqual(cr.get_value('section1', 'other_option1'),
+ 'other_value1a')
+ self.assertEqual(cr.get_values('section1', 'other_option1'),
+ ['other_value1', 'other_value1a'])
+ self.assertEqual(cr.items('section1'),
+ [('option1', 'value1b'),
+ ('other_option1', 'other_value1a')])
+ self.assertEqual(
+ cr.items_all('section1'),
+ [('option1', ['value1a', 'value1b']),
+ ('other_option1', ['other_value1', 'other_value1a'])])
+
+ def test_add_to_multiple(self):
+ file_obj = self._to_memcache(fixture_path('git_config_multiple'))
+ with GitConfigParser(file_obj, read_only=False) as cw:
+ cw.add_value('section1', 'option1', 'value1c')
+ cw.write()
+ file_obj.seek(0)
+ cr = GitConfigParser(file_obj, read_only=True)
+ self.assertEqual(cr.get_value('section1', 'option1'), 'value1c')
+ self.assertEqual(cr.get_values('section1', 'option1'),
+ ['value1a', 'value1b', 'value1c'])
+ self.assertEqual(cr.items('section1'),
+ [('option1', 'value1c'),
+ ('other_option1', 'other_value1')])
+ self.assertEqual(cr.items_all('section1'),
+ [('option1', ['value1a', 'value1b', 'value1c']),
+ ('other_option1', ['other_value1'])])
+
+ def test_setlast(self):
+ # Test directly, not covered by higher-level tests.
+ omd = _OMD()
+ omd.setlast('key', 'value1')
+ self.assertEqual(omd['key'], 'value1')
+ self.assertEqual(omd.getall('key'), ['value1'])
+ omd.setlast('key', 'value2')
+ self.assertEqual(omd['key'], 'value2')
+ self.assertEqual(omd.getall('key'), ['value2'])