Skip to content

Commit 22f137d

Browse files
Byroncodex
andcommitted
review
- [P2] Ignore comment text when validating continued values — /Users/byron/dev/github.com/gitpython-developers/GitPython.fix-config-unquoted -escape-parsing/git/config.py:576-577 With `k = one\` followed by ` two # C:\Users`, the joined value still contains the second line's comment. This check treats its `\U` as an unknown escape and skips `parse_value()`, returning `one two # C:\Users` instead of `one two`, unlike Git and `main`. Updating an unrelated option then persists the comment as part of the value. Strip or skip unquoted comment text before validating escapes. - [P2] Preserve whitespace before an EOF continuation backslash — /Users/byron/dev/github.com/gitpython-developers/GitPython.fix-config-unquoted -escape-parsing/git/config.py:652-653 If the final config line is `k = value \`, with or without a terminating newline, Git and `main` return `"value "`. The EOF branch removes the backslash first, so this newly applied `parse_value()` discards the preceding space and returns `"value"`. Updating an unrelated option also persists that change. Preserve whitespace made significant by the continuation when decoding. Assisted-by: GPT 6.1 Sol Co-authored-by: GPT 6.1 Sol <codex@openai.com>
1 parent 983e182 commit 22f137d

2 files changed

Lines changed: 34 additions & 2 deletions

File tree

‎git/config.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -632,13 +632,15 @@ def escapes_are_known(value: str) -> bool:
632632
# next line is appended before the complete value is
633633
# parsed. An even number means the last backslash is
634634
# escaped and the value ends there.
635+
eof_continuation = False
635636
while True:
636637
if not is_line_continuation(optval):
637638
break
638639
continuation = fp.readline()
639640
if not continuation:
640-
# Backslash at end of file: git drops it.
641-
optval = optval[:-1]
641+
# Keep the backslash until parsing so preceding
642+
# whitespace is significant even though git drops it.
643+
eof_continuation = True
642644
break
643645
lineno = lineno + 1
644646
joined = continuation.decode(defenc)
@@ -649,8 +651,11 @@ def escapes_are_known(value: str) -> bool:
649651
# values, but only a value in which every backslash is part
650652
# of a known escape is decoded, so that a Windows path keeps
651653
# its backslashes instead of losing them one escape at a time.
654+
optval, _ = strip_inline_comment(optval)
652655
if escapes_are_known(optval):
653656
optval = parse_value(optval)
657+
elif eof_continuation:
658+
optval = optval[:-1]
654659
elif quote_open:
655660
# Opens quoting and does not close: appears to start multi-line quoting.
656661
is_multi_line = True

‎test/test_config.py‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,33 @@ def test_backslash_line_continuation(self):
378378
key = "co" if section == "alias" else "k"
379379
self.assertEqual(config.get_value(section, key), expected)
380380

381+
@with_rw_directory
382+
def test_continued_values_preserve_comments_and_eof_whitespace(self, rw_dir):
383+
cases = [
384+
(b"one\\\n two # C:\\Users\n", "one two"),
385+
(b"one\\\n two ; C:\\Users\n", "one two"),
386+
(b"one\\\n two\\tthree # C:\\Users\n", "one two\tthree"),
387+
(b'one\\\n "two # three" # C:\\Users\n', "one two # three"),
388+
(b"value \\", "value "),
389+
(b"value \\\n", "value "),
390+
(b"value \t\\\n", "value \t"),
391+
(b"one\\\n two \\\n", "one two "),
392+
(b"C:\\Users \\\n", "C:\\Users "),
393+
]
394+
config_path = osp.join(rw_dir, "config")
395+
for value, expected in cases:
396+
with self.subTest(value=value):
397+
with open(config_path, "wb") as config_file:
398+
config_file.write(b"[a]\n\tk = " + value)
399+
400+
with GitConfigParser(config_path, read_only=False) as config:
401+
self.assertEqual(config.get_value("a", "k"), expected)
402+
config.set_value("other", "value", "updated")
403+
404+
with GitConfigParser(config_path) as config:
405+
self.assertEqual(config.get_value("a", "k"), expected)
406+
self.assertEqual(config.get_value("other", "value"), "updated")
407+
381408
def test_get_value_reads_git_boolean_spellings(self):
382409
# git accepts yes/no and on/off as well as true/false, and getboolean on
383410
# this class already did. get_value returned them as strings, so "no" and

0 commit comments

Comments
 (0)