Artifact d9db79a32b3208498f41ca0e222c321ae0cd8bd913670f671b5f18c0f6aebc54:
- File
fossil.go
— part of check-in
[b5a64230b3]
at
2026-10-21 14:43:59
on branch feat/submanifest-reader
— feat(sparse): adopt sparse-cone at horizon-rfc a5741263ab
The draft now settles zit #257 to #260, so the four rows that waited on it close against code:
- Compaction and local filtering keep every manifest and sub-manifest node, interiors included (5.4, 6.3). RetainProvenance previously let an outside interior whose children were all held leaves go; the draft now requires it held, since it is the range proof that reaches the leaf. - A server answering a cone request acknowledges the reply with pragma cone-served in its leading pragma run (6.3). This server applies a request's whole cone or refuses it, and a refusal resets the reply, so the pragma is never sent for a refused or dense reply. SyncResult and CloneResult report ConeServed beside Elided, now public too. - An empty cone is refused (3.2); a new row and case pin it, locally and over the wire. - The per-round bound covers the tree walk only (6.2). A new row tests that a requester does not act on a dense inventory. It stays partial: an out-of-cone blob announced in the same reply as its check-in cannot be classified yet and is fetched, then filtered; zit #262 asks the draft to account for that cost. (user: [email protected], size: 4045) [annotate] [blame] [check-ins using] [more...]
package libfossil import ( "context" "fmt" "os" "path/filepath" "github.com/danmestas/go-libfossil/internal/repo" internalsync "github.com/danmestas/go-libfossil/internal/sync" "github.com/danmestas/go-libfossil/simio" ) // CreateOpts configures repository creation. type CreateOpts struct { User string // ProjectCode optionally sets the repo's project-code. Empty // generates a fresh one (current behavior). When non-empty, must // be 40-char lowercase hex (^[0-9a-f]{40}$) — matching the format // of generated project-codes. Invalid values return an error // before any file is written. ProjectCode string // Rand provides random bytes for project-code and server-code generation. // Nil defaults to crypto/rand (production). Set to simio.NewSeededRand // for deterministic simulation testing. Rand simio.Rand } // Create creates a new Fossil repository at the given path. func Create(path string, opts CreateOpts) (*Repo, error) { if opts.ProjectCode != "" && !isProjectCode40HexLower(opts.ProjectCode) { return nil, fmt.Errorf("libfossil: invalid CreateOpts.ProjectCode %q: must be 40-char lowercase hex", opts.ProjectCode) } if _, err := os.Stat(path); err == nil { return nil, fmt.Errorf("libfossil: repository already exists: %s", path) } if dir := filepath.Dir(path); !isDir(dir) { return nil, fmt.Errorf("libfossil: create %s: parent directory does not exist: %s", path, dir) } user := opts.User if user == "" { user = os.Getenv("USER") } rng := opts.Rand if rng == nil { rng = simio.CryptoRand{} } inner, err := repo.Create(path, user, rng, opts.ProjectCode) if err != nil { return nil, fmt.Errorf("libfossil: create: %w", err) } return &Repo{inner: inner, path: path}, nil } func isDir(path string) bool { info, err := os.Stat(path) return err == nil && info.IsDir() } func isProjectCode40HexLower(s string) bool { if len(s) != 40 { return false } for i := 0; i < len(s); i++ { c := s[i] if (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') { continue } return false } return true } // Open opens an existing Fossil repository. func Open(path string) (*Repo, error) { inner, err := repo.Open(path) if err != nil { return nil, fmt.Errorf("libfossil: open: %w", err) } return &Repo{inner: inner, path: path}, nil } // CloneResult reports what happened during a clone. type CloneResult struct { Rounds int BlobsRecvd int ArtifactsLinked int ProjectCode string ServerCode string Messages []string // Elided counts the artifacts left absent under the store cone, and // ConeServed the replies whose server acknowledged applying it (pragma // cone-served, draft-fossil-sparse-cone-00 §6.3). Both are zero for a // dense clone. Elided, ConeServed int } // Clone performs a full repository clone from a remote Fossil server. // It creates a new repository at the given path, runs the clone protocol // until convergence, and returns the opened Repo handle and a result summary. // On error, the partially-created repo file is removed. Artifacts the clone // rounds leave missing stay phantoms unless opts.PullPhantoms is set. func Clone(ctx context.Context, path string, t Transport, opts CloneOpts) (*Repo, *CloneResult, error) { adapter := &transportAdapter{pub: t} iOpts := internalsync.CloneOpts{ User: opts.User, Password: opts.Password, Observer: adaptObserver(opts.Observer), Buggify: opts.Buggify, PullPhantoms: opts.PullPhantoms, } inner, iResult, err := internalsync.Clone(ctx, path, adapter, iOpts) if err != nil { return nil, nil, fmt.Errorf("libfossil: clone: %w", err) } result := &CloneResult{ Rounds: iResult.Rounds, BlobsRecvd: iResult.BlobsRecvd, ArtifactsLinked: iResult.ArtifactsLinked, ProjectCode: iResult.ProjectCode, ServerCode: iResult.ServerCode, Messages: iResult.Messages, Elided: iResult.Elided, ConeServed: iResult.ConeServed, } return &Repo{inner: inner, path: path}, result, nil }