Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions git/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,34 @@
import abc
import configparser as cp
import fnmatch
from functools import wraps
import inspect
from io import BufferedReader, IOBase
import logging
import os
import os.path as osp
import re
import sys

from git.compat import defenc, force_text
from git.util import LockFile
from functools import wraps
from io import BufferedReader, IOBase

# typing-------------------------------------------------------

from typing import (
IO,
TYPE_CHECKING,
Any,
Callable,
Dict,
Generic,
IO,
List,
Dict,
Sequence,
TYPE_CHECKING,
Tuple,
TypeVar,
Union,
cast,
)

from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, assert_never, _T
from git.compat import defenc, force_text
from git.types import _T, ConfigLevels_Tup, Lit_config_levels, PathLike, assert_never
from git.util import LockFile

if TYPE_CHECKING:
from io import BytesIO
Expand Down Expand Up @@ -958,9 +956,9 @@ def _string_to_value(self, valuestr: str) -> Union[int, float, str, bool]:

# Try boolean values as git uses them.
vl = valuestr.lower()
if vl == "false":
if vl in ("false", "no", "off"):
return False
if vl == "true":
if vl in ("true", "yes", "on"):
return True

if not isinstance(valuestr, str):
Expand Down
32 changes: 32 additions & 0 deletions test/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,38 @@ def test_backslash_line_continuation(self):
key = "co" if section == "alias" else "k"
self.assertEqual(config.get_value(section, key), expected)

def test_get_value_reads_git_boolean_spellings(self):
# git accepts yes/no and on/off as well as true/false, and getboolean on
# this class already did. get_value returned them as strings, so "no" and
# "off" arrived as non-empty (truthy) values for a caller testing them.
cases = [
(b"true", True),
(b"TRUE", True),
(b"yes", True),
(b"Yes", True),
(b"on", True),
(b"On", True),
(b"false", False),
(b"no", False),
(b"off", False),
(b"Off", False),
]
for raw, expected in cases:
config_file = io.BytesIO(b"[core]\n\tflag = " + raw + b"\n")
config_file.name = "boolean_spellings.config"
config = GitConfigParser(config_file)
config.read()
self.assertIs(config.get_value("core", "flag"), expected, raw.decode())
# The two accessors must not disagree about the same value.
self.assertIs(config.getboolean("core", "flag"), expected, raw.decode())

# A value that is not a boolean at all still comes back untouched.
config_file = io.BytesIO(b"[core]\n\tflag = meld\n")
config_file.name = "boolean_spellings.config"
config = GitConfigParser(config_file)
config.read()
self.assertEqual(config.get_value("core", "flag"), "meld")

@with_rw_directory
def test_comment_backslash_does_not_continue_value(self, rw_dir):
config_path = osp.join(rw_dir, "config")
Expand Down
Loading