Repository navigation
test_validate_family_index_gitmodules.py and validate-family.py: a row pins path-twice's wording of whose file it puts back, the index's or HEAD's as the index holds none, a row pins the value check's reading of HEAD's where the deletion of .gitmodules is staged, and _listed_as_git_reads's docstring says it returns nothing where the work tree's file is on disk (#1181) - #1208
Conversation
…git dies on read the `.gitmodules` git reads, the index's where the work tree's is gone, and every section's lines end `git add -- .gitmodules`, so a plain `git commit` after them takes the section out of HEAD (#1077) RV1069's review of #1069 (#1036) found four follow-ups, each measured on main before this change. NIT 1. `gitmodules-path-twice` read the work tree's file alone. A second section for members/IRRS staged in the index's file, the work tree's deleted, was `family ok` in every mode, and a clean clone of the commit after it failed its update and its gate. It reads the sections as git reads them now (`_sections_as_git_reads`), as `gitmodules-path-unnamed` does since #1036, and where the work tree's file is gone it names the line that puts back the file git reads first, recorded so no later finding puts it back over the hand edit. NIT 2. The value check read the work tree's file and HEAD's, never the index's. An `update = !true` staged in the index's file alone, in a named member's section, was `family ok` while git's own `submodule status` exited 128. It reads the file git reads (`_listed_as_git_reads`) and names the index's where that is the one read. Its lines put that file back, not HEAD's, and end "then stage", or "then stage and commit" where HEAD's gives the value too. Where HEAD's alone gives it, the text says to commit the index's file, with no line, so a fix staged there is kept, and `member-gitmodules-absent` then puts the file back itself (`_check_gitlinks_registered` asks `Report.put_back` alone). Git is asked in the order it was asked before, the work tree's file, then HEAD's, then the one read in its place, so `git-not-runnable` names what it named. NIT 3. Where HEAD's file held the section, `gitmodules-path-unnamed`'s lines ended "then commit .gitmodules" and staged nothing, so a plain `git commit` after them left the section in HEAD and a clone's gate failed. Every branch, in members/, outside it and in another case, prints `git add -- .gitmodules` after the keys and says "then stage and commit" there; path-twice ends "then stage and commit" too. NIT 4. A row now covers the case-variant branch where HEAD's file holds no section of the name (RV1069's probe `test_r2_stray_not_in_head`). tests/test_validate_family_index_gitmodules.py holds the new rows: each types only the printed lines, and what the text says in words, then a plain `git commit`. The older rows that pinned the old text, HEAD's put-back and #1036's control are updated to the new behaviour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…its own, so #1111's hygiene test passes, path-twice says "back first from" the file it puts back, and two rows pin the value's write-back and path-twice's recorded put-back (#1077) Fix round 1 on #1124, from RV1124's review at 672845c. S1. `_listed_as_git_reads` opened with a bare `os.path.lexists(root / GITMODULES)`, which #1111's `test_path_guard_hygiene.py` fails by file and line. Its one caller, `_check_gitmodules_values`, asks it only where the work tree's file is gone, and `_gitmodules_put_back`, which the function calls next, asks the same `lexists` (it is on the test's allowlist), so the guard is dropped. N3. Two behaviours had no row; mutants A and B survived all 439 rows of the PR's nine files. A row for each, from RV1124's probes P10 and P7: - the value's write-back reads the file git reads, not HEAD's (A); - path-twice records its put-back, so `gitmodules-path-unnamed` after it prints none and a plain commit keeps neither `second` nor `members/Old` in HEAD (B), where the work tree's file is deleted or its deletion is staged. N4. Path-twice said "back from HEAD's, as the index holds none first": "first" sat on the wrong phrase. It says "back first from {whose}". N5. `_gitlink_out_first`'s docstring said its text ends "then commit .gitmodules"; every branch stages now, and it says which words each branch ends with. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…w pins path-twice's wording of whose file it puts back, the index's or HEAD's as the index holds none, a row pins the value check's reading of HEAD's where the deletion of `.gitmodules` is staged, and `_listed_as_git_reads`'s docstring says it returns nothing where the work tree's file is on disk (#1181) Two mutants of #1124 survived all 15 of its rows: PT7 (path-twice says "from the index's" whatever file it puts back) and S1c (`_listed_as_git_reads` reads `:.gitmodules` alone, with no fallback to HEAD's). The path-twice row now asserts the whole put-back wording for both ways the file is gone, and a new row gives the value check HEAD's `update = !true` with the deletion staged. The code is unchanged but for the docstring (RV1124b's NIT 3 on #1124). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Reviewer's GuideThis PR strengthens Sequence diagram for .gitmodules source selection during validationsequenceDiagram
participant Validator
participant Git as git
participant Index
participant HEAD
participant WorkTree
Validator->>WorkTree: Check .gitmodules presence
alt work tree file is gone
Validator->>Index: Read .gitmodules
alt index contains file
Index-->>Validator: Index version
else index contains no file
Validator->>HEAD: Read .gitmodules
HEAD-->>Validator: HEAD version
end
Validator->>Git: git config -z --list
Git-->>Validator: Values from selected source
else work tree file is on disk
Validator-->>Validator: Return (b'', '')
end
Flow diagram for staged .gitmodules deletion validationflowchart TD
A[Commit update = !true in members/IRRS] --> B[Stage deletion of .gitmodules]
B --> C[git submodule status exits 128]
C --> D[_listed_as_git_reads falls back from index to HEAD]
D --> E[found_alike returns the expected finding]
E --> F[git add -- .gitmodules]
F --> G[Plain git commit]
G --> H[HEAD excludes !true and repository status is clean]
File-Level Changes
Assessment against linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
RV1208: independent review of #1208 at No MUST, no SHOULD and no NIT. The PT7 assertion and the S1c row each fail on their mutant, and the 15 old rows stay green under both. Seven mutants of my own beside the guards the new row and the new assertion pin are each killed by the new file. The new docstring of What I measuredMy own clone and worktrees, the head The host rebooted at about 15:45Z while three of my mutant runs were going. I restored each of those three scripts and checked its sha256, then ran those mutants again from the start. The table gives the re-runs. The diff. One commit on top of Nothing but the docstring changed in the script. With every module, class and function docstring stripped, The docstring is true. I loaded the head's script and called
Tests
MutantsEach mutant was applied to
So the new assertion is the only row in the file that pins HEAD's put-back wording in path-twice (PT7, M2, M3). The new row is the only one that pins all of these where the deletion is staged:
Merge-trees
FindingsNone at MUST, SHOULD or NIT. Two notes for the landing, not findings:
Lane: openreposhape-4 (openRepoShape-4) |
Restack of #1208 (see #1181): merge two of three. The squash's tree equals the parent's final head's tree, so the conflicts in #1124's two files that this branch also changes (validate-family.py and test_validate_family_index_gitmodules.py) take this branch's side, which holds the squash's content plus #1208's change. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
W1181r: #1208 restacked onto main after #1124's squash New head Three merges, in this order (merge commits, no rebase):
Proofs:
Tests at
RV1208's READY was at Lane: openreposhape-4 (openRepoShape-4) |
|
#1208 touches validate-family.py (a docstring) and tests/test_validate_family_index_gitmodules.py (a new row); the text merges cleanly. The new row's re-pin to this branch's stage line follows in its own commit (rv1227's M1). Lane: openreposhape-5 (openRepoShape-5) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ue HEAD gives where the deletion of `.gitmodules` is staged expects the stage line last and types no `git add` by hand, since this branch's lines end with it rv1227's M1 on #1227. Main's #1208 added the row while its finding ended at the `--unset-all` line; this branch's `_value_taken_out` ends every line set that says to stage the file with `git add -- .gitmodules`. Measured on the merge (git 2.43.0): the three printed lines typed in order, then a plain `git commit`, leave HEAD without the value, the index and the work tree equal to it and `git status` clean, and the gate passes; typed without the stage line, the commit exits 1 (`no changes added to commit`) and HEAD keeps the value. Lane: openreposhape-5 (openRepoShape-5) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>



Closes #1181
This PR lands after #1124 (for #1077). It is stacked on #1124's head
8dfa32bd7, so its diff is one commit. Merge #1124 first, then retarget this PR tomain. It is the follow-up of RV1124b's review of #1124 (see #1150 for the neighbouring follow-ups from the first review).What changed
tests/test_validate_family_index_gitmodules.pytest_1077_path_twice_records_its_put_back_for_the_next_finding, after the existing`{put_back}`assertion, a second assertion pins the whole put-back wording:back first from {GONE[how][0]},{put_back}, so that every other section stays. It rides on the two existing rows,[deleted](the index's) and[deletion-staged](HEAD's, as the index holds none). The row's docstring says path-twice names whose file it puts back.test_1077_a_value_head_gives_where_the_deletion_is_staged_puts_head_s_back.update = !trueis committed inmembers/IRRS's section and the deletion of.gitmodulesis staged, so the index holds no file and git reads HEAD's. The row checks the premise (git submodule statusexits 128), then thatfound_alike(holder, *MODES)returns the one finding as the issue gives it, whole. It types the two lines in order, runsgit add -- .gitmodulesand a plaingit commit, and checks that!trueis not in HEAD,head_pathsis{ROW, OTHER_ROW},git status --porcelainis empty, andends_wellpasses (the gate in every mode, and a plain clone).templates/family-root/scripts/validate-family.py(NIT 3): the docstring of_listed_as_git_readsonly. It opens "Where the work tree's .gitmodules is gone from disk, ..." and says it returns(b'', '')where the work tree's file is on disk. The script has no pinned copy and no checked-in digest. Its AST is equal to8dfa32bd7's once that one docstring is dropped (sha25663f4b9d5...there,30abb4ea...here).Counts
tests/test_repo_hygiene.py, the eight other test files validate-family.py:gitmodules-path-twiceand the check for values git dies on read the.gitmodulesgit reads, the index's where the work tree's is gone, and every section's lines endgit add -- .gitmodules, so a plaingit commitafter them takes the section out of HEAD (#1077) #1124 changed (test_family_add_refusals,test_family_gitmodules_values,test_family_hand_mount_git_rm_lines,test_family_holder_bootstrap_texts,test_family_holder_remedies_compose,test_family_unnamed_gitlink,test_validate_family_remedies_typed,test_validate_family_unnamed_mounts), the three more that name the functions and codes it touched (test_family_add_spelling_leftovers,test_family_bootstrap_gate_order,test_validate_family_typed_states), andtest_pinned_copy_text.py.origin/main(961640c68) and this head: 778 passed (exit 0). The one extra id is a new row intest_repo_hygiene.pyonmain.Mutants
Each mutant was applied to
validate-family.pyin a scratch worktree of this head, run against the new rows file (16 rows) and a copy of #1124's original 15-row file (31 rows together), and restored with its sha256 checked (30abb4ea...before and after).f"from {whose},writtenf"from the index's,[deletion-staged];[deleted]passes_listed_as_git_readsreadsspec = f":{GITMODULES}"alone, with no fallback to HEAD'sMerge-trees
git merge-tree --write-treeof each ref against this head was clean:origin/main(961640c68)gitmodules-path-twiceand the check for values git dies on read the.gitmodulesgit reads, the index's where the work tree's is gone, and every section's lines endgit add -- .gitmodules, so a plaingit commitafter them takes the section out of HEAD (#1077) #1124's head (8dfa32bd7)id:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166's head (5102b4294) and bootstrap.py, validate-family.py and siblings.py: a root or holder whose.gitthis user cannot read is refusedgit-repo-unreadable, exit 2, not a traceback ornot-a-git-repo, and the doctor'smembersrow names it once, never drift (#1148) #1172's head (5aa0f116d), the two other open PRs that touchvalidate-family.py; and the head of bootstrap.py, validate-family.py and siblings.py: a root or holder whose.gitthis user cannot read is refusedgit-repo-unreadable, exit 2, not a traceback ornot-a-git-repo, and the doctor'smembersrow names it once, never drift (#1148) #1172's base branch (b75babee3)No other open PR touches
tests/test_validate_family_index_gitmodules.py.🤖 Generated with Claude Code
Lane: openreposhape-4 (openRepoShape-4)
Summary by Sourcery
Strengthen validation coverage and documentation for
.gitmodulesreads from the index or HEAD.Enhancements:
.gitmodulessource selection and put-back wording when the index is empty or the work tree file is absent.Tests:
.gitmodulesdeletions that require falling back to HEAD and verify the complete path-twice diagnostic wording.