Artifact 71c36ed16fc006a66a0f09be62456861cf5c27232f133532ca7684a1427fd49d:
- File
repo.go
— part of check-in
[faf57ad9c7]
at
2026-05-05 15:11:07
on branch trunk
— fix: checkpoint WAL on Close so vanilla fossil can read repo (#28)
Closes #27.
libfossil opens repos in WAL journal mode but the Close chain never ran wal_checkpoint, so closed repo files were a 4 KiB stub plus a fat -wal sidecar. Vanilla fossil's validity probe stats the main file before consulting the WAL → repo rejected as "not a valid repository".
- Adds a typed CheckpointMode (Passive / Full / Restart / Truncate) and a Checkpoint(mode) method on the public Repo (mirrored through internal repo and db.DB). CheckpointMode and its constants are re-exported from the package root so callers don't have to import db. - db.DB.Close now runs PRAGMA wal_checkpoint(TRUNCATE) before closing the underlying *sql.DB. Checkpoint errors are joined with the close error via errors.Join so the connection is always closed regardless of checkpoint outcome. - Skips the close-time checkpoint on the WASM/WASI build path where WAL isn't used. (user: [email protected], size: 2069) [annotate] [blame] [check-ins using]
package libfossil import ( "github.com/danmestas/libfossil/db" "github.com/danmestas/libfossil/internal/repo" ) // Repo is an opaque handle to a Fossil repository. type Repo struct { inner *repo.Repo path string } // CheckpointMode mirrors SQLite's PRAGMA wal_checkpoint(<mode>) argument. type CheckpointMode = db.CheckpointMode const ( CheckpointPassive = db.CheckpointPassive CheckpointFull = db.CheckpointFull CheckpointRestart = db.CheckpointRestart CheckpointTruncate = db.CheckpointTruncate ) // Path returns the filesystem path to the repository file. func (r *Repo) Path() string { return r.path } // Inner returns the underlying internal repo handle. // This is exported for use by in-module packages (e.g., cli/) that need // direct access to the repo DB for raw SQL or internal package calls. func (r *Repo) Inner() *repo.Repo { return r.inner } // Close closes the repository and releases resources. As part of close, // a WAL TRUNCATE checkpoint is run so the on-disk repo file is readable // by external fossil/SQLite tooling. func (r *Repo) Close() error { if r.inner == nil { return nil } return r.inner.Close() } // Checkpoint runs PRAGMA wal_checkpoint(<mode>) against the repository. // Safe to call on a live repo. CheckpointPassive is non-blocking and // appropriate for periodic background checkpoints. CheckpointTruncate // produces a maximally compact on-disk file readable by external fossil // tooling without a subsequent Close. func (r *Repo) Checkpoint(mode CheckpointMode) error { if r.inner == nil { return nil } return r.inner.Checkpoint(mode) } // DB returns the underlying database handle for raw SQL queries. // Use this when the high-level Repo methods don't cover your use case. func (r *Repo) DB() *db.DB { return r.inner.DB() } // WithTx executes fn within a database transaction. func (r *Repo) WithTx(fn func(tx *db.Tx) error) error { return r.inner.WithTx(fn) } // Verify checks repository integrity (blob checksums, delta chains). func (r *Repo) Verify() error { return r.inner.Verify() }