commit - a99f7ffc57dc4c3c349f8b430c9230c23a68bd8a
commit + 4c5ec309ca6064e8c942e1e40491448a8c80c96d
blob - cd475edb8c7a87f47dfce9825d2cfbefa4e97551
blob + 7f09ae57a41e4ec5ad9871016e300ad1652086b9
--- dulwich/config.py
+++ dulwich/config.py
return line
+def _parse_section_header_line(line: bytes) -> Tuple[Section, bytes]:
+ # Parse section header ("[bla]")
+ line = _strip_comments(line).rstrip()
+ in_quotes = False
+ escaped = False
+ for i, c in enumerate(line):
+ if escaped:
+ escaped = False
+ continue
+ if c == ord(b'"'):
+ in_quotes = not in_quotes
+ if c == ord(b'\\'):
+ escaped = True
+ if c == ord(b']') and not in_quotes:
+ last = i
+ break
+ else:
+ raise ValueError("expected trailing ]")
+ pts = line[1:last].split(b" ", 1)
+ line = line[last + 1:]
+ section: Section
+ if len(pts) == 2:
+ if pts[1][:1] != b'"' or pts[1][-1:] != b'"':
+ raise ValueError("Invalid subsection %r" % pts[1])
+ else:
+ pts[1] = pts[1][1:-1]
+ if not _check_section_name(pts[0]):
+ raise ValueError("invalid section name %r" % pts[0])
+ section = (pts[0], pts[1])
+ else:
+ if not _check_section_name(pts[0]):
+ raise ValueError("invalid section name %r" % pts[0])
+ pts = pts[0].split(b".", 1)
+ if len(pts) == 2:
+ section = (pts[0], pts[1])
+ else:
+ section = (pts[0],)
+ return section, line
+
+
class ConfigFile(ConfigDict):
"""A Git configuration file, like .git/config or ~/.gitconfig."""
line = line[3:]
line = line.lstrip()
if setting is None:
- # Parse section header ("[bla]")
if len(line) > 0 and line[:1] == b"[":
- line = _strip_comments(line).rstrip()
- try:
- last = line.index(b"]")
- except ValueError:
- raise ValueError("expected trailing ]")
- pts = line[1:last].split(b" ", 1)
- line = line[last + 1 :]
- if len(pts) == 2:
- if pts[1][:1] != b'"' or pts[1][-1:] != b'"':
- raise ValueError("Invalid subsection %r" % pts[1])
- else:
- pts[1] = pts[1][1:-1]
- if not _check_section_name(pts[0]):
- raise ValueError("invalid section name %r" % pts[0])
- section = (pts[0], pts[1])
- else:
- if not _check_section_name(pts[0]):
- raise ValueError("invalid section name %r" % pts[0])
- pts = pts[0].split(b".", 1)
- if len(pts) == 2:
- section = (pts[0], pts[1])
- else:
- section = (pts[0],)
+ section, line = _parse_section_header_line(line)
ret._values.setdefault(section)
if _strip_comments(line).strip() == b"":
continue
blob - 3078b6e638646abf6b8a5f739aa6d380b89f3cb2
blob + eea02e2c2e0e67ddfcd48c3e07731957da5f22fa
--- dulwich/tests/test_config.py
+++ dulwich/tests/test_config.py
def test_comment_character_within_section_string(self):
cf = self.from_file(b'[branch "foo#bar"] # a comment\nbar= foo\n')
self.assertEqual(ConfigFile({(b"branch", b"foo#bar"): {b"bar": b"foo"}}), cf)
+
+ def test_closing_bracket_within_section_string(self):
+ cf = self.from_file(b'[branch "foo]bar"] # a comment\nbar= foo\n')
+ self.assertEqual(ConfigFile({(b"branch", b"foo]bar"): {b"bar": b"foo"}}), cf)
def test_from_file_section(self):
cf = self.from_file(b"[core]\nfoo = bar\n")