Allow relative config paths with includes - #2169
Conversation
GitConfigParser asserted while resolving a relative include whenever the top-level configuration file had itself been supplied as a relative path. A regression test constructs that combination and verifies the included value is available. Normalize path-based inputs to absolute paths before reading them. This lets relative includes resolve against the containing file and ensures cycle detection uses the same canonical spelling for top-level and included paths. This matches Git's documented include behavior and the relative and chained-relative coverage in t/t1305-config-include.sh. Validation: - uv run pytest -q test/test_config.py - uv run pre-commit run --files git/config.py test/test_config.py - uv run mypy git/config.py - git diff --check - full pytest: 631 passed, 75 skipped, 34 unrelated environment failures (uninitialized nested submodules and missing legacy master branch)
|
Merged due to simplicity, without waiting for CI which basically doesn't finish today. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because no GitHub Actions runner was available. Make sure your repository has a runner available to run Copilot's review, or add a copilot-setup-steps.yml file specifying one with the runs-on attribute. See the docs for more details.
Normalize config parser input paths so relative includes resolve correctly when the top-level config file is provided as a relative path (avoiding assertion/cycle-detection inconsistencies).
Changes:
- Normalize
GitConfigParser.read()input file paths to absolute paths before processing includes. - Add a regression test covering relative top-level config path with a relative
[include] path.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| test/test_config.py | Adds coverage for relative config path + relative include behavior. |
| git/config.py | Normalizes initial config paths to absolute to make include resolution and cycle detection consistent. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| files_to_read = list(self._file_or_files) | ||
| # END ensure we have a copy of the paths to handle | ||
|
|
||
| files_to_read = [osp.abspath(path) if isinstance(path, (str, os.PathLike)) else path for path in files_to_read] |
| @with_rw_directory | ||
| def test_config_relative_path_include(self, rw_dir): | ||
| included_path = osp.join(rw_dir, "included") | ||
| with GitConfigParser(included_path, read_only=False) as cw: | ||
| cw.set_value("included", "value", "included") | ||
|
|
||
| config_path = osp.join(rw_dir, "config") | ||
| with GitConfigParser(config_path, read_only=False) as cw: | ||
| cw.set_value("include", "path", "included") | ||
|
|
||
| relative_config_path = osp.relpath(config_path) | ||
| with GitConfigParser(relative_config_path, read_only=True) as cr: | ||
| assert cr.get_value("included", "value") == "included" |
This MR contains the following updates: | Package | Type | Update | Change | OpenSSF | |---|---|---|---|---| | [gitpython](https://github.com/gitpython-developers/GitPython) | dev | patch | `3.1.50` → `3.1.52` | [](https://securityscorecards.dev/viewer/?uri=github.com/gitpython-developers/GitPython) | --- ### Release Notes <details> <summary>gitpython-developers/GitPython (gitpython)</summary> ### [`v3.1.52`](https://github.com/gitpython-developers/GitPython/releases/tag/3.1.52): Security [Compare Source](gitpython-developers/GitPython@3.1.51...3.1.52) <GHSA-rwj8-pgh3-r573>: Environment-variable exfiltration via os.path.expandvars() on Repo.clone\_from() URL #### What's Changed - Skip cross-drive relative config test on Windows by [@​Byron](https://github.com/Byron) in [#​2171](gitpython-developers/GitPython#2171) - fix: preserve literal clone URLs by [@​Byron](https://github.com/Byron) in [#​2172](gitpython-developers/GitPython#2172) **Full Changelog**: <gitpython-developers/GitPython@3.1.51...3.1.52> ### [`v3.1.51`](https://github.com/gitpython-developers/GitPython/releases/tag/3.1.51): - Security [Compare Source](gitpython-developers/GitPython@3.1.50...3.1.51) #### What's Changed - Add AI-disclosure and quality requirements to the contribution guidelines by [@​Byron](https://github.com/Byron) in [#​2143](gitpython-developers/GitPython#2143) - docs(cmd): clarify Git.execute() string vs list command argument by [@​mvanhorn](https://github.com/mvanhorn) in [#​2144](gitpython-developers/GitPython#2144) - Rewrite Git.execute() command parameter docstring per [#​2146](gitpython-developers/GitPython#2146) by [@​EliahKagan](https://github.com/EliahKagan) in [#​2147](gitpython-developers/GitPython#2147) - Document init script behavior with multiple master remotes by [@​EliahKagan](https://github.com/EliahKagan) in [#​2148](gitpython-developers/GitPython#2148) - Bump git/ext/gitdb from `335c0f6` to `0a019a2` by [@​dependabot](https://github.com/dependabot)\[bot] in [#​2149](gitpython-developers/GitPython#2149) - Support relative worktree paths (git 2.48+ worktree.useRelativePaths) by [@​elovelan](https://github.com/elovelan) in [#​2151](gitpython-developers/GitPython#2151) - Defer xfail condition evaluation with xfail\_if\_raises context manager by [@​elovelan](https://github.com/elovelan) in [#​2153](gitpython-developers/GitPython#2153) - Run more submodule tests on Cygwin (fix flaky xfails) by [@​EliahKagan](https://github.com/EliahKagan) in [#​2154](gitpython-developers/GitPython#2154) - Cut xtrace noise from POSIX-ownership diagnostic steps by [@​EliahKagan](https://github.com/EliahKagan) in [#​2156](gitpython-developers/GitPython#2156) - Support index diffs against the empty tree by [@​puneetdixit200](https://github.com/puneetdixit200) in [#​2155](gitpython-developers/GitPython#2155) - refactor: seperate out Progress type by [@​LoeschMaximilian](https://github.com/LoeschMaximilian) in [#​2157](gitpython-developers/GitPython#2157) - Bump <https://github.com/astral-sh/ruff-pre-commit> from v0.15.12 to 0.15.15 in the pre-commit group by [@​dependabot](https://github.com/dependabot)\[bot] in [#​2160](gitpython-developers/GitPython#2160) - Bump actions/checkout from 6 to 7 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​2164](gitpython-developers/GitPython#2164) - Bump git/ext/gitdb from `0a019a2` to `4950ea9` by [@​dependabot](https://github.com/dependabot)\[bot] in [#​2165](gitpython-developers/GitPython#2165) - Bump <https://github.com/astral-sh/ruff-pre-commit> from v0.15.15 to 0.15.20 in the pre-commit group by [@​dependabot](https://github.com/dependabot)\[bot] in [#​2166](gitpython-developers/GitPython#2166) - Add Commit.is\_shallow property; document stats() limitation at shallow boundary by [@​harshitayadavv](https://github.com/harshitayadavv) in [#​2167](gitpython-developers/GitPython#2167) - Allow relative config paths with includes by [@​Byron](https://github.com/Byron) in [#​2169](gitpython-developers/GitPython#2169) - Reject abbreviated forms of unsafe git options by [@​Byron](https://github.com/Byron) in [#​2168](gitpython-developers/GitPython#2168) - guard unsafe git command options by [@​Byron](https://github.com/Byron) in [#​2163](gitpython-developers/GitPython#2163) #### New Contributors - [@​elovelan](https://github.com/elovelan) made their first contribution in [#​2151](gitpython-developers/GitPython#2151) - [@​puneetdixit200](https://github.com/puneetdixit200) made their first contribution in [#​2155](gitpython-developers/GitPython#2155) - [@​LoeschMaximilian](https://github.com/LoeschMaximilian) made their first contribution in [#​2157](gitpython-developers/GitPython#2157) - [@​harshitayadavv](https://github.com/harshitayadavv) made their first contribution in [#​2167](gitpython-developers/GitPython#2167) **Full Changelog**: <gitpython-developers/GitPython@3.1.50...3.1.51> </details> --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNzAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI3MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiLCJyZW5vdmF0ZSJdfQ==--> See merge request swiss-armed-forces/cyber-command/cea/loom!679 Co-authored-by: Loom MR Pipeline Trigger <group_103951964_bot_9504bb8dead6d4e406ad817a607f24be@noreply.gitlab.com>
Tasks
This section is for Byron only. Models continuing this PR must not add, remove, check, uncheck, rename, or reorder checkboxes here.
Everything below this line was generated by
GPT-5.Created by Codex on behalf of Byron. Byron will review before this is ready to merge.
Summary
GitPython already supports relative include paths, but raised an
AssertionErrorwhen the top-level configuration file was itself passed as a relative path. Normalize path-based parser inputs before reading so relative includes resolve against their containing config file and cycle detection uses consistent absolute paths.Fixes #2103
Git behavior reference
This matches Git documentation and the relative and chained-relative include cases in
t/t1305-config-include.sh.Validation
uv run pytest -q test/test_config.py(31 passed, 1 skipped)uv run pre-commit run --files git/config.py test/test_config.pyuv run mypy git/config.pygit diff --checkmasterbranch