fix(config): round-trip the fetchRecurse config key correctly#63
Merged
Conversation
submod silently dropped the documented `fetchRecurse` TOML key on load and could not read back the fetch-recurse setting it wrote: - The serde field was `fetch_recurse` with no rename, so the documented `fetchRecurse` key (per README) deserialized to nothing. - Both config writers emitted `fetch = "<to_gitmodules>"` — the wrong TOML key *and* git's `true`/`false` value encoding instead of the serde `always`/`never` form — so a written value never parsed back. Standardize on the documented `fetchRecurse` key via `#[serde(rename)]` (matching how `ignore`/`update` already behave, and avoiding the figment layered-merge duplicate-key error that `alias` would trigger), add `SerializableFetchRecurse::as_config_value()` for the TOML value form, and fix both writers plus the known-key lists. Update the sample config comments. Tests: a deserialize test for the documented key, an as_config_value unit test, and a write->read round-trip regression test through write_full_config. Corrects test_change_global_sets_update_and_fetch, which previously asserted the broken `fetch = "true"` output. config.rs and git_manager.rs also pick up rustfmt (1.8.0) normalization of pre-existing unformatted lines, required to pass the cargo fmt gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T8D5ZK1473YCiZkbueAY2X
Codecov Report❌ Patch coverage is
🚀 New features to boost your workflow:
|
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.
What & why
Fixes the P0-3 finding from the test audit (#62): submod silently dropped the documented
fetchRecurseconfig key and could not read back the fetch-recurse setting it wrote.Two distinct defects, both real and round-trip-breaking:
fetch_recursewith no rename, while the README (and the test suite, and the bundled sample) document the key asfetchRecurse. So a config written per the docs deserialized toNone— the value was silently dropped.save_configandwrite_full_config) emittedfetch = "<to_gitmodules>". That's the wrong key (fetch, neither documentedfetchRecursenor fieldfetch_recurse) and the wrong value form (to_gitmodules()yields git'strue/false, but the deserializer expects the serdealways/never). So submod could not parse a config it had just written.The existing
test_change_global_sets_update_and_fetchactually enshrined the bug — it asserted the output containedfetch = "true", with a comment rationalizing it.Approach
fetchRecursekey via#[serde(rename = "fetchRecurse")]on all three structs (SubmoduleGitOptions,SubmoduleDefaults,SubmoduleEntry).rename(notalias) is required becauseConfig::loadmerges layers through figment at the raw-dict level — analiaswould leave the file layer (fetchRecurse) and the CLI-provider layer (fetch_recurse) as two different keys, which serde then rejects as a duplicate field. A single canonical spelling matches howignore/updatealready behave.SerializableFetchRecurse::as_config_value()returning the serde kebab form (on-demand/always/never), explicitly distinct fromto_gitmodules()(git'strue/false), and use it in both writers.fetchRecurseand add it to the known-key lists.sample_config/submod.tomlcomments.Tests (TDD — each watched fail first)
test_config_toml_fetch_recurse_camelcase_key_is_parsed— deserializes the documentedfetchRecursekey and asserts the parsed value (not file text).test_write_full_config_fetch_recurse_round_trips— writes config viawrite_full_config, reloads, assertsAlways/Neversurvive — the core regression test.test_fetch_recurse_as_config_value_uses_serde_form_not_git_bools— pins the TOML value form against regressing to the git encoding.test_change_global_sets_update_and_fetchto assert the round-trippablefetchRecurse = "always"and that a subsequentchecksucceeds.Full suite: 518 tests pass.
Notes
config.rsandgit_manager.rsalso pick up rustfmt (1.8.0) normalization of pre-existing unformatted lines — required to pass thecargo fmtpre-commit gate, which currently fails on ~154 pre-existing diffs across the repo. Reformatting was confined to the two files this PR already touches.schemas/v1.0.0,schemas/v1.1.0) still define the key asfetchwithadditionalProperties: false, so they'd reject the documentedfetchRecurse; andschemas/v1.1.0/...jsonis currently malformed JSON (a stray""). The repo-wide rustfmt drift (~154 diffs across 13 files) is also worth a standalonestyle:commit.Closes the P0-3 item in #62.
🤖 Generated with Claude Code