Skip to content

Commit 16added

Browse files
EliahKaganclaude
andcommitted
Add a test that required submodules are initialized
This adds the new test, `test_required_submodule_is_initialized`, to `test_fixture_health.py`. For the gitdb and smmap submodules, the test asserts that the working tree directory exists and contains a `.git` marker (file or directory). The failure message reminds the developer to run `git submodule update --init --recursive`. This is a regression test for a different contract than the preexisting `test_fixture_dir_is_trusted_by_git` in `test_fixture_health.py`. That test verifies git's willingness to operate in each fixture directory (the `safe.directory` / dubious-ownership contract). This one verifies that the directories are populated at all. A bug where they were not populated affected Arch Linux in gitpython-developers#1713 when `init-tests-after-clone.sh` stopped running `git submodule update` on CI. The visible failure was a cascade of test failures across `test_docs.py`, `test_repo.py`, and `test_submodule.py` -- tests that don't set out to check submodule presence but fail when the submodules aren't there. This test checks for that explicitly, with a single clear assertion. The test skips when the source tree is not a git clone (no `.git` at `REPO_ROOT`). This is to accommodate setups that run pytest from an extracted release tarball and prepare submodules in a separately-pointed tree via `GIT_PYTHON_TEST_GIT_REPO_BASE` (e.g. OpenIndiana's package build): in such setups, `git submodule update` cannot operate on the source tree, and the submodule paths checked here would never be populated there -- but the test suite still works because `rorepo` points elsewhere. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 26ffc26 commit 16added

1 file changed

Lines changed: 50 additions & 0 deletions

File tree

test/test_fixture_health.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@
4545
),
4646
]
4747

48+
# Submodule working trees that must be present and initialized for the
49+
# test suite to operate normally: gitdb at `git/ext/gitdb`, and smmap
50+
# nested inside gitdb at `git/ext/gitdb/gitdb/ext/smmap`. The paths
51+
# below are anchored at REPO_ROOT (the GitPython source tree), not at
52+
# any rorepo redirection target.
53+
SUBMODULE_DIRS = [
54+
pytest.param(REPO_ROOT / "git" / "ext" / "gitdb", id="gitdb"),
55+
pytest.param(
56+
REPO_ROOT / "git" / "ext" / "gitdb" / "gitdb" / "ext" / "smmap",
57+
id="smmap",
58+
),
59+
]
60+
4861

4962
@pytest.mark.parametrize("fixture_dir", FIXTURE_DIRS)
5063
def test_fixture_dir_is_trusted_by_git(fixture_dir: Path) -> None:
@@ -92,3 +105,40 @@ def test_fixture_dir_is_trusted_by_git(fixture_dir: Path) -> None:
92105
"This usually means the directory is not an initialized git "
93106
"repository (its `.git` marker may be stale or pointing elsewhere)."
94107
)
108+
109+
110+
@pytest.mark.parametrize("submodule_dir", SUBMODULE_DIRS)
111+
def test_required_submodule_is_initialized(submodule_dir: Path) -> None:
112+
"""The submodule's working tree is present and initialized.
113+
114+
Failure means the source tree is a git clone but the submodule's
115+
working tree hasn't been populated. Skipped when the source tree
116+
itself isn't a git clone (e.g. an extracted release tarball), since
117+
``git submodule update`` cannot operate there; setups that handle
118+
submodules in a separately-prepared tree (via
119+
``GIT_PYTHON_TEST_GIT_REPO_BASE``) are exempted from this check.
120+
"""
121+
if not (REPO_ROOT / ".git").exists():
122+
pytest.skip(
123+
"Source tree is not a git clone (no .git in REPO_ROOT); submodules "
124+
"cannot be initialized via `git submodule update` here. Setups "
125+
"that prepare submodules in a separately-pointed tree (via "
126+
"GIT_PYTHON_TEST_GIT_REPO_BASE) are exempted from this check."
127+
)
128+
# The assertion messages below recommend `git submodule update --init
129+
# --recursive` rather than `init-tests-after-clone.sh`, even though the
130+
# latter is the documented entry point for first-time test setup. Two
131+
# reasons: the script performs `git reset --hard` operations that can
132+
# destroy local work, and #1713 showed the script itself can carry
133+
# submodule-init regressions, in which case recommending it would lead
134+
# developers in a circle. The direct git command is a safe minimal fix
135+
# for this test's specific failure mode and bypasses any such regression.
136+
assert submodule_dir.is_dir(), (
137+
f"Submodule working tree missing: {submodule_dir}.\n"
138+
"Run `git submodule update --init --recursive` from the repo root."
139+
)
140+
assert (submodule_dir / ".git").exists(), (
141+
f"Submodule directory exists but has no .git marker: {submodule_dir}.\n"
142+
"The submodule hasn't been initialized. "
143+
"Run `git submodule update --init --recursive` from the repo root."
144+
)

0 commit comments

Comments
 (0)