Artifact 882a567f84e7831bea93826f982e882e948176d1d14eb31efa57dcad6b78bd5d:
- File
conformance/repostate_gaps_test.go
— part of check-in
[15762adeb6]
at
2026-10-13 10:52:58
on branch main
— fix(manifest): link a check-in atop an absent parent despite absent files (#407)
* fix(manifest): link a check-in atop an absent parent despite absent files
The crosslink deferral held back a check-in until every F-card blob was stored. When the primary parent's manifest is itself absent, no mlink row depends on those files (fossil's add_mlink returns before reading one, and the parent's crosslink derives the transition once it arrives), so the wait could never complete for files the repository will not receive. The libfossil repository holds one such check-in, a fossil-scm commit imported without its history; the sweep lost its event and plink rows that fossil rebuild writes (RS-4.2-2).
missingCheckinRefs now skips the F-cards when the primary parent is unavailable; the baseline is still required. Adds conformance case repostate.4.2.phantom-parent-absent-file and a unit test that also checks the child's mlink is derived once the parent arrives.
Tracked in #398.
* fix(manifest): record the remaining crosslink deferral gaps
Adds gap case repostate.4.2.root-absent-file, a receive-linker ordering test for the child-before-parent path, and notes the narrowed exemption. Tracked in #398 and #406. (user: [email protected], size: 2785) [annotate] [blame] [check-ins using]
package conformance import "testing" // repostateGaps marks the repository-state cases go-libfossil is known to // fail, by case ID, grouped by the code at fault, each with the issue // tracking its fix. var repostateGaps = map[string]string{ // Name resolution (repo_history.go ResolveVersion): no checkout context // and no requested type. These cases do not yet call the API #386 will // add (the branch-type case calls nothing it could pass): rewire them to // the new entry points when it lands, do not just delete these entries. "repostate.8.3.current": "#386", "repostate.8.3.prev": "#386", "repostate.8.3.previous": "#386", "repostate.8.3.next": "#386", "repostate.8.3.branch-type": "#386", // Crosslink deferral (internal/manifest/crosslink.go missingCheckinRefs). "repostate.4.2.root-absent-file": "#406", } // repostateDeviations marks the cases where go-libfossil follows fossil(1) // rather than the draft text, by case ID. var repostateDeviations = map[string]string{ "repostate.7.3.parentless-untagged": parentlessDeviation, // verify.Rebuild now derives leaves through the crosslink sweep, so it shares // the same branch-aware leaf rule and the same ยง7.3 deviation. "repostate.7.3.parentless-untagged.rebuild": parentlessDeviation, // The same check-in seen from Section 7.3's crosslink trigger: linking it // does not recheck it, as fossil's does not. "repostate.7.3.recheck-lone-untagged": parentlessDeviation, // An untagged child of a tagged check-in: Section 7.3 rechecks it and // its parent when it is linked. "repostate.7.3.recheck-untagged-child": untaggedChildDeviation, "repostate.7.3.recheck-untagged-child.rebuild": untaggedChildDeviation, } const untaggedChildDeviation = "follows fossil(1): a check-in with a parent but no branch " + "tag is never rechecked, so it is no leaf and its parent keeps its verdict, where " + "Section 7.3 rechecks every crosslinked check-in and its parents; widening the " + "candidates changed the leaf table of a real fossil-authored repository (the " + "libfossil corpus)" const parentlessDeviation = "follows fossil(1): an untagged parentless check-in is " + "never a leaf, where Section 7.3 makes every check-in without a same-branch " + "child one (the section's informative note records fossil's behavior)" // TestRepoStateGapKeys checks that every marked case exists. func TestRepoStateGapKeys(t *testing.T) { ids := map[string]bool{} for _, c := range repostateSuiteCases() { ids[c.ID] = true } for id := range repostateGaps { if !ids[id] { t.Errorf("repostateGaps names %s, which is not a case", id) } } for id := range repostateDeviations { if !ids[id] { t.Errorf("repostateDeviations names %s, which is not a case", id) } } }