Repository navigation
fix(config): read an option on the same line as its section header - #2307
Closed
Keerthana-64 wants to merge 1 commit into
Closed
Keerthana-64 wants to merge 1 commit into
Keerthana-64 wants to merge 1 commit into
Conversation
`GitConfigParser._read` recognized a section header with the inherited
`configparser` pattern `\[(?P<header>.+)\]`, matched against the
stripped line, and discarded everything after the match. git ends a
header at its first `]` outside a quoted subsection name and parses the
rest of the line as an ordinary config line, so `[core] bare = true`
sets `core.bare` in git and nothing in GitPython.
`.gitmodules` is read with this parser and is controlled by whoever
authored the superproject. For
[submodule "lib"]
path = lib
url = https://good.example/lib
[submodule "lib"] url = https://evil.example/lib
`git config -f .gitmodules --list` shows both URLs, and
`git submodule init` registers and later clones
`https://evil.example/lib`, while `Repo.submodules` reports
`https://good.example/lib`. A tool that uses GitPython to check which
URLs a repository's submodules point at approves a different URL than
the one git fetches. The greedy match also misread other lines:
`[c] k = v ]` became a section named `c] k = v` with no options, and
`[d] k = "multi\` continued on the next line produced an option named
`line"` instead of `d.k = multi line`.
The header now ends at the first unquoted `]`, with backslash escapes
honored inside the quoted subsection name, and the text after it is fed
back through the parse loop as a line of its own. That reuses the
existing comment, option, continuation and header handling, so
`[e] ; comment` adds nothing, `[b]flag` is an implicit boolean, and
`[f] [g] k = v` sets `g.k`, all as git reads them. A header with
unbalanced quotes keeps the previous reading up to the last `]`, and
files whose headers stand alone on their lines parse exactly as before.
`test_option_after_section_header_is_read_like_git` in
`test/test_config.py` checks each case above against what
`git config -f <file> --list` prints on git 2.54.0. It fails before this
change and passes after. `ruff check`, `ruff format --check` and `mypy`
pass. In a full clone prepared with `init-tests-after-clone.sh`, the
pytest suite passes except `test_diff_with_staged_file`,
`test_empty_repo` and `test_rebasing`, which fail the same way without
this change.
Byron
pushed a commit
that referenced
this pull request
Oct 24, 2026
Cover the configuration regressions from PRs #2305 and #2307 against actual `git config` output. The current configuration facade already delegates these operations to Git, so the valid cases pass without a runtime change. Use scripted fixtures for a real home-relative conditional include and the complete inline-header sample. Preserve native `HOME` and `USERPROFILE` separators so the same test exercises the Windows path case on Windows. Check both matching and nonmatching repositories and file/stream readers. Also check adjacent headers, an escaped quote before `]`, and rejection of unbalanced quotes, missing/stray brackets, malformed keys and sections. Git accepts multiple section headers on one line but omits empty sections from `git config list`. Reflect that output and the facade's documented empty-section limitation instead of restoring a separate Python parser. Document the existing `GIX-12` fallback without claiming native coverage. Validation on macOS, Git 2.54.0, Python 3.12 and GixPython 0.2.0: - All 11 added cases passed against the unchanged runtime. - `test/test_config.py`: 62 passed with each of the CLI and Gix backends. - `ruff check`, `ruff format --check`, `bash -n` and `git diff --check` passed. Windows and Linux execution was not available for this local check.
Byron
pushed a commit
that referenced
this pull request
Oct 24, 2026
Cover the configuration regressions from PRs #2305 and #2307 against actual `git config` output. The current configuration facade already delegates these operations to Git, so the valid cases pass without a runtime change. Use scripted fixtures for a real home-relative conditional include and the complete inline-header sample. Preserve native `HOME` and `USERPROFILE` separators so the same test exercises the Windows path case on Windows. Check both matching and nonmatching repositories and file/stream readers. Also check adjacent headers, an escaped quote before `]`, and rejection of unbalanced quotes, missing/stray brackets, malformed keys and sections. Git accepts multiple section headers on one line but omits empty sections from `git config list`. Reflect that output and the facade's documented empty-section limitation instead of restoring a separate Python parser. Document the existing `GIX-12` fallback without claiming native coverage. Validation on macOS, Git 2.54.0, Python 3.12 and GixPython 0.2.0: - All 11 added cases passed against the unchanged runtime. - `test/test_config.py`: 62 passed with each of the CLI and Gix backends. - `ruff check`, `ruff format --check`, `bash -n` and `git diff --check` passed. Windows and Linux execution was not available for this local check.
Member
|
Codex, operating on behalf of Byron: This PR has been superseded by #2274. Its regression coverage has been integrated there, with assertions checked against Git’s behavior and fixes included where needed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
.gitmoduleswith an option on a section header line, git 2.54.0:GitConfigParser._readmatches headers with configparser's greedy\[(?P<header>.+)\]and drops the rest of the line, while git ends a header at its first unquoted]and parses what follows as a normal config line. a tool that checks submodule URLs with GitPython therefore approves a different URL than the one git clones, and the same match turns[c] k = v ]into a section namedc] k = v. the header now ends at the first unquoted]and the remainder goes back through the parse loop as its own line, which matches git for options, comments and a second header ([f] [g] k = vsetsg.k); a header with unbalanced quotes keeps the previous reading.test_option_after_section_header_is_read_like_gitfails before and passes after, and the three full-suite failures on this machine (test_diff_with_staged_file,test_empty_repo,test_rebasing) fail the same way without the change.