Artifact 86c8e3d22dc2886420a49bf41b2f43c1e13f1898920188c3471ccde3fd98ac7a:
- File
required_content_checkout.go
— part of check-in
[e5904fc85b]
at
2026-10-22 14:47:23
on branch feat/horizon-cones
— feat(horizon): expose content horizons in the public API and CLI
A store cone could carry a horizon only through internal/cone, so library users and the CLI had no way to clone into or edit a content-horizon store. Add Horizon, HorizonRule, NewHorizonCone, Cone.Horizon and Cone.WithHorizon over the internal cone (always the content cut), carry it through SetStoreCone/SetStoreConeContext (deepening fetches what the older check-in keeps) and CloneOpts.StoreCone, and add --horizon, --leaves, --no-horizon and --cone to repo clone and repo cone store.
A horizon is a property of the store, not of a checkout (draft-fossil-horizon-00 3.2), so checkout cones carrying one are refused with ErrHorizonCheckout, and widening the store from a checkout cone keeps the store's horizon. (user: [email protected], size: 3878) [annotate] [blame] [check-ins using] [more...]
package libfossil import ( "context" "fmt" "github.com/danmestas/go-libfossil/internal/fsltype" "github.com/danmestas/go-libfossil/internal/manifest" ) // CheckinContext recovers necessary parent structure from an explicit peer, // outside checkout locks and repository transactions. It then gathers checkout // changes afresh; no stale file list is replayed after network I/O. func (c *Checkout) CheckinContext( ctx context.Context, opts CheckoutCommitOpts, required RequiredContentOpts, ) (int64, string, error) { if err := required.validate(ctx); err != nil { return 0, "", err } _, state, err := c.requiredState() if err != nil { return 0, "", err } r := c.inner.Repo() err = c.inner.RequireCommitContent(ctx) if err != nil { if err := required.recover(ctx, r, err); err != nil { return 0, "", err } if err := c.checkRequiredState(state); err != nil { return 0, "", err } } if err := required.checkinFiles(ctx, c, opts); err != nil { return 0, "", err } if err := c.checkRequiredState(state); err != nil { return 0, "", err } return c.checkin(ctx, opts) } // SetConeContext recovers only structure needed to enumerate next and payloads // newly entering the checkout. Explicit widening durably extends store coverage; // an attempted fetch retains that intent even on failure. No-peer refusal does // not change policy. Planning and local checks repeat before files move. A // cone with a horizon is refused with ErrHorizonCheckout before anything moves. func (c *Checkout) SetConeContext( ctx context.Context, next *Cone, required RequiredContentOpts, ) (ConeChange, error) { if err := required.validate(ctx); err != nil { return ConeChange{}, err } if _, err := checkoutCone(next); err != nil { return ConeChange{}, err } parent, state, err := c.requiredState() if err != nil { return ConeChange{}, err } if required.Peer != nil || parent == 0 { state, err = c.requiredStorePolicy(next, state) if err != nil { return ConeChange{}, err } } if parent == 0 { return c.SetCone(next) } r := c.inner.Repo() var filter manifest.FileFilter if next != nil { filter = next.inner } files, err := manifest.ListFilesFiltered(r, parent, filter) if err != nil { refusal := manifest.RequireParentContent(ctx, r.DB(), []fsltype.FslID{parent}) if refusal == nil { return ConeChange{}, err } if err := required.recover(ctx, r, refusal); err != nil { return ConeChange{}, err } if err := c.checkRequiredState(state); err != nil { return ConeChange{}, err } files, err = manifest.ListFilesFiltered(r, parent, filter) if err != nil { return ConeChange{}, err } } old := c.Cone() names, err := requiredFileNames(ctx, r, files, func(name string) bool { return old != nil && !old.Covers(name) }) if err != nil { return ConeChange{}, err } if err := required.recoverFiles(ctx, r, names); err != nil { return ConeChange{}, err } if _, err := c.requiredStorePolicy(next, state); err != nil { return ConeChange{}, err } return c.SetCone(next) } func (c *Checkout) requiredState() (fsltype.FslID, string, error) { parent, uuid, err := c.inner.Version() if err != nil { return 0, "", err } state, err := requiredState(c.inner.Repo(), []fsltype.FslID{parent}) if err != nil { return 0, "", err } if cone := c.Cone(); cone != nil { state += "\ncheckout-cone=" + cone.Digest() } snapshot, err := c.inner.RecoverySnapshot() if err != nil { return 0, "", err } state += "\ncheckout-snapshot=" + snapshot return parent, fmt.Sprintf("%d:%s\n%s", parent, uuid, state), nil } func (c *Checkout) checkRequiredState(before string) error { _, after, err := c.requiredState() if err != nil { return err } if after != before { return fmt.Errorf("libfossil: checkout snapshot or policy changed " + "during required-content recovery") } return nil }