Artifact e7e65bd8ee988d7fdf5bb364317c1bbe1f63a9ee6a952fead2c7f8133d265936:
- File
repo_submanifest.go
— part of check-in
[05a53c393d]
at
2026-10-19 21:50:52
on branch feat/submanifest-reader
— fix(sync): gate sub-manifest trees on the send-submanifests pragma
draft-fossil-submanifests-00 §7.2 no longer gates S-bearing artifacts on the peer's announced version: fossil 2.29 announces 22900 and reads no tree. A peer that reads trees now says so with pragma send-submanifests, which go-libfossil sends in every request right after client-version and in every reply, clone replies included, right after server-version, whatever the sub-manifest settings. The version threshold and the 22900 reader marker are gone; client-version and server-version announce 22800, the fossil release whose protocol this library speaks.
A tree manifest or sub-manifest is refused to a peer that has not sent the pragma with "Peer does not accept sub-manifests.", never converted or omitted. A server decides from the whole request it answers, a client from the replies it has received in the exchange. avoid-submanifests moves from the ci-lock answer into the same leading run of every reply.
Enabling emission over a stored submanifest-k outside 1 to 12 without an explicit k is refused, naming the stored value (§8.1).
The conformance suite pins the draft with the 2026-10-19 errata applied: SM-7.2-1 and SM-6.3-3 are met rather than deviations, SM-7.2-2, SM-7.2-3, SM-6.3-1/2/7 and SM-8.1-3 follow the corrected text, and SM-7.2-4 covers the pragma's placement. The zit interop pushes a tree go-libfossil wrote to zit and checks both sides refuse trees when the pragma is stripped.
Tracked in #452. (user: [email protected], size: 3127) [annotate] [blame] [check-ins using] [more...]
package libfossil import ( "errors" "fmt" fsltype "github.com/danmestas/go-libfossil/internal/fsltype" "github.com/danmestas/go-libfossil/internal/manifest" ) // EnableSubmanifests turns on tree manifest emission // (draft-fossil-submanifests-00 §8.1): from the next commit, check-ins carry // their file sets as sub-manifest trees. k is the partition parameter, 1 to // 12, or 0 to select one. A valid pinned k is kept, and an explicit k that // differs from it is refused: changing it is RetuneSubmanifests. A stored k // outside 1..12 is no valid pin: an explicit k replaces it, and k = 0 is // refused, naming the stored value. With no stored k, an explicit k is // pinned, or one is selected as zit selects it: // the §6.3 cost over one check-in's file set, refined by replaying recent // history. The check-in analyzed is the current trunk (CurrentTrunk, the // main-branch tip, which the next commit most plausibly descends from); // when no check-in is on the main branch, it is the newest check-in by // time, the highest rid breaking a tie. A request that cannot be met -- k // outside 1..12, no check-in at all to select from, or a file set no k // partitions -- changes neither setting. It returns the pinned k and the // warning the operator must be shown: peers that do not announce // sub-manifest support, every fossil among them, are refused trees, and // trees cannot be retired. func (r *Repo) EnableSubmanifests(k int) (pinned int, warning string, err error) { current, err := r.CurrentTrunk() if errors.Is(err, ErrVersionNotFound) { var newest fsltype.FslID newest, err = manifest.NewestCheckin(r.inner.DB()) current = int64(newest) } if err != nil { return 0, "", fmt.Errorf("libfossil: enable sub-manifests: %w", err) } pinned, err = manifest.EnableSubmanifests(r.inner, fsltype.FslID(current), k) if err != nil { return 0, "", fmt.Errorf("libfossil: enable sub-manifests: %w", err) } return pinned, manifest.SubmanifestEnableWarning, nil } // RetuneSubmanifests pins a new partition parameter k, 1 to 12, for the // commits that follow (draft-fossil-submanifests-00 §6.4). It is forward // only: existing check-ins are unchanged, and the next tree shares only the // sub-manifests whose bytes are the same under both values. func (r *Repo) RetuneSubmanifests(k int) error { if err := manifest.RetuneSubmanifests(r.inner, k); err != nil { return fmt.Errorf("libfossil: re-tune sub-manifests: %w", err) } return nil } // DisableSubmanifests turns tree manifest emission off: later commits are // flat, and the pinned k is kept for a later EnableSubmanifests. Existing // trees remain -- artifact names are immutable, so they cannot be retired -- // and keep being served, though peers that do not announce sub-manifest // support are still refused them. Unlike the CLI's disable, it returns no note saying so; an // embedder that wants to tell its operator must do it itself. func (r *Repo) DisableSubmanifests() error { if _, err := manifest.DisableSubmanifests(r.inner); err != nil { return fmt.Errorf("libfossil: disable sub-manifests: %w", err) } return nil }