Documentation
¶
Overview ¶
Package checkout provides working directory management for Fossil repositories. It implements file extraction, change tracking, staging, and commit operations, ported from libfossil's checkout API. All filesystem operations go through simio.Env for platform-agnostic operation (native, WASI, browser WASM).
A Checkout is not safe for concurrent use. Callers must serialize access to a single Checkout instance.
Index ¶
- func BranchLeaves(r *repo.Repo, branch string) ([]libfossil.FslID, error)
- func DBNames() []string
- func EnsureTables(db *sql.DB) error
- func FindCheckoutDB(storage simio.Storage, dir string, searchParents bool) (string, error)
- func PreferredDBName() string
- type ChangeEntry
- type ChangeVisitor
- type Checkout
- func (c *Checkout) CalcUpdateVersion() (libfossil.FslID, error)
- func (c *Checkout) CheckFilename(name string) (string, error)
- func (c *Checkout) Close() error
- func (c *Checkout) Commit(opts CommitOpts) (libfossil.FslID, string, error)
- func (c *Checkout) Dequeue(opts DequeueOpts) error
- func (c *Checkout) Dir() string
- func (c *Checkout) DiscardQueue() error
- func (c *Checkout) Enqueue(opts EnqueueOpts) error
- func (c *Checkout) Extract(rid libfossil.FslID, opts ExtractOpts) error
- func (c *Checkout) FileContent(name string) ([]byte, error)
- func (c *Checkout) HasChanges() (bool, error)
- func (c *Checkout) IsEnqueued(name string) (bool, error)
- func (c *Checkout) IsRootedIn(absPath string) bool
- func (c *Checkout) LoadVFile(rid libfossil.FslID, clear bool) (missing uint32, err error)
- func (c *Checkout) Manage(opts ManageOpts) (*ManageCounts, error)
- func (c *Checkout) Rename(opts RenameOpts) error
- func (c *Checkout) Repo() *repo.Repo
- func (c *Checkout) Revert(opts RevertOpts) error
- func (c *Checkout) RevertRename(name string, doFsMove bool) (bool, error)
- func (c *Checkout) ScanChanges(flags ScanFlags) error
- func (c *Checkout) UnloadVFile(rid libfossil.FslID) error
- func (c *Checkout) Unmanage(opts UnmanageOpts) error
- func (c *Checkout) Update(opts UpdateOpts) error
- func (c *Checkout) ValidateFingerprint() error
- func (c *Checkout) Version() (libfossil.FslID, string, error)
- func (c *Checkout) VisitChanges(vid libfossil.FslID, scan bool, fn ChangeVisitor) error
- func (c *Checkout) WouldFork() (bool, error)
- func (c *Checkout) WriteManifest(flags ManifestFlags) error
- type CommitEnd
- type CommitOpts
- type CommitStart
- type CreateOpts
- type DequeueOpts
- type EnqueueOpts
- type ExtractEnd
- type ExtractOpts
- type ExtractStart
- type FileChange
- type ManageCounts
- type ManageOpts
- type ManifestFlags
- type Observer
- type OpenOpts
- type RenameOpts
- type RevertChange
- type RevertOpts
- type ScanEnd
- type ScanFlags
- type UnmanageOpts
- type UpdateChange
- type UpdateOpts
- type VFileChange
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BranchLeaves ¶
BranchLeaves returns the leaf RIDs for a named branch. A branch with >1 leaf is forked. An empty branch name queries trunk.
func DBNames ¶
func DBNames() []string
DBNames returns all possible checkout DB names, with the preferred name first.
func EnsureTables ¶
EnsureTables creates the vfile, vmerge, and vvar tables if they don't exist. This is idempotent — safe to call multiple times.
Panics if db is nil (TigerStyle precondition).
func FindCheckoutDB ¶
FindCheckoutDB searches for a checkout database (.fslckout or _FOSSIL_) in dir, and optionally in parent directories if searchParents is true. Returns the full path to the DB file.
func PreferredDBName ¶
func PreferredDBName() string
PreferredDBName returns the preferred checkout DB name based on the OS. Returns "_FOSSIL_" on Windows, ".fslckout" elsewhere.
Types ¶
type ChangeEntry ¶
type ChangeEntry struct {
Name string
Change FileChange
VFileID libfossil.FslID
IsExec bool
IsLink bool
OrigName string // non-empty if renamed
}
ChangeEntry describes a single file change in the checkout.
type ChangeVisitor ¶
type ChangeVisitor func(entry ChangeEntry) error
ChangeVisitor is called for each changed file during VisitChanges.
type Checkout ¶
type Checkout struct {
// contains filtered or unexported fields
}
Checkout represents an opened or created checkout database. A Checkout owns the checkout DB (*sql.DB) but NOT the repo — the caller owns the repo lifecycle.
func Create ¶
Create creates a new checkout database at dir/.fslckout (or dir/_FOSSIL_ on Windows), finds the tip checkin from the repo, and sets vvar checkout/checkout-hash.
Panics if r or dir is nil/empty (TigerStyle precondition).
func Open ¶
Open opens an existing checkout database. If opts.SearchParents is true, it searches parent directories for the checkout DB using FindCheckoutDB.
Panics if r or dir is nil/empty (TigerStyle precondition).
func (*Checkout) CalcUpdateVersion ¶
CalcUpdateVersion finds the latest leaf checkin to update to. Returns 0 if the checkout is already at the latest version.
Panics if c is nil (TigerStyle precondition).
func (*Checkout) CheckFilename ¶
CheckFilename canonicalizes and validates that a filename is within the checkout directory. Returns the cleaned relative path, or an error if the path escapes the checkout. Panics if c is nil or name is empty (TigerStyle preconditions).
func (*Checkout) Commit ¶
Commit creates a new checkin from staged files in the checkout. Returns the new manifest RID and UUID.
func (*Checkout) Dequeue ¶
func (c *Checkout) Dequeue(opts DequeueOpts) error
Dequeue removes files from the commit staging queue. If opts.Paths is empty, clears the entire queue (restoring implicit all-files behavior). Returns error for API consistency / future-proofing.
func (*Checkout) DiscardQueue ¶
DiscardQueue clears the commit staging queue, restoring implicit all-files behavior. Returns error for API consistency / future-proofing.
func (*Checkout) Enqueue ¶
func (c *Checkout) Enqueue(opts EnqueueOpts) error
Enqueue adds files to the commit staging queue. If the queue is empty (nil), all changed files are implicitly enqueued. Once Enqueue is called, only explicitly enqueued files will be committed.
func (*Checkout) Extract ¶
func (c *Checkout) Extract(rid libfossil.FslID, opts ExtractOpts) error
Extract writes files from the specified checkin to disk via simio.Storage. Populates vfile, updates vvar checkout/checkout-hash to rid.
If opts.DryRun is true, skips writing files but still calls observer and callback. If opts.Force is false (default), fails if locally modified files would be overwritten.
Panics if c is nil (TigerStyle precondition).
func (*Checkout) FileContent ¶
FileContent reads a file from the checkout working directory via Storage. Panics if c is nil or name is empty (TigerStyle preconditions).
func (*Checkout) HasChanges ¶
HasChanges returns true if the checkout has any modified, deleted, or renamed files. This is a DB-only check that does NOT scan the filesystem. Use ScanChanges first if you need to detect on-disk modifications.
Panics if c is nil (TigerStyle precondition).
func (*Checkout) IsEnqueued ¶
IsEnqueued returns true if the named file will be included in the next commit. If the queue is nil (never initialized), all changed files are implicitly enqueued. If the queue exists but is empty (len == 0), nothing is enqueued. Returns error for API consistency / future-proofing.
func (*Checkout) IsRootedIn ¶
IsRootedIn checks if an absolute path is within the checkout directory. Panics if c is nil (TigerStyle precondition).
func (*Checkout) LoadVFile ¶
LoadVFile populates vfile table with entries from the specified checkin manifest. If clear=true, deletes all vfile rows for OTHER versions (keeps only vid=rid). Returns the count of missing blobs (files whose content is not in the repo).
Panics if c is nil (TigerStyle precondition).
func (*Checkout) Manage ¶
func (c *Checkout) Manage(opts ManageOpts) (*ManageCounts, error)
Manage adds files to tracking. For each path: - Checks if already in vfile (skips if present) - Reads file content from Storage - Computes hash - Inserts into vfile with rid=0, chnged=1 (marks as newly added)
Panics if c is nil (TigerStyle precondition).
func (*Checkout) Rename ¶
func (c *Checkout) Rename(opts RenameOpts) error
Rename marks a file as renamed in vfile by updating pathname and origname. Sets chnged=1 to indicate the file has been modified.
If opts.DoFsMove is true, also moves the file in Storage from old to new path.
Panics if c is nil, or if From or To is empty (TigerStyle precondition).
func (*Checkout) Revert ¶
func (c *Checkout) Revert(opts RevertOpts) error
Revert restores files to their checkout version state. If opts.Paths is empty, reverts ALL changed files.
For each file to revert: - If rid==0 (newly added): DELETE from vfile, remove from Storage - If rid>0 (existing, modified/deleted): restore original content, reset chnged=0, deleted=0
Panics if c is nil (TigerStyle precondition).
func (*Checkout) RevertRename ¶
RevertRename restores a renamed file to its original pathname. Returns (true, nil) if the revert succeeded, (false, nil) if there was nothing to revert.
Panics if c is nil or name is empty (TigerStyle precondition).
func (*Checkout) ScanChanges ¶
ScanChanges detects modified and missing files in the checkout. Walks the vfile table, checks each file on disk, and updates vfile.chnged accordingly.
If flags includes ScanHash, hashes file content and compares to vfile.mhash. Otherwise, uses mtime-based detection (future enhancement).
Panics if c is nil (TigerStyle precondition).
func (*Checkout) UnloadVFile ¶
UnloadVFile removes all vfile entries for the specified version.
Panics if c is nil (TigerStyle precondition).
func (*Checkout) Unmanage ¶
func (c *Checkout) Unmanage(opts UnmanageOpts) error
Unmanage removes files from tracking. For each path: - If rid=0 (newly added, never committed): DELETE from vfile - If rid>0 (existing tracked file): UPDATE vfile SET deleted=1
Panics if c is nil (TigerStyle precondition).
func (*Checkout) Update ¶
func (c *Checkout) Update(opts UpdateOpts) error
Update updates the checkout to a new version, performing 3-way merge where needed to preserve local modifications.
If opts.TargetRID is 0, CalcUpdateVersion is used to find the target. If the target equals the current version, Update returns nil (nothing to do).
Panics if c is nil (TigerStyle precondition).
func (*Checkout) ValidateFingerprint ¶
ValidateFingerprint verifies that the checkout-hash vvar matches the blob uuid in the repo.
func (*Checkout) VisitChanges ¶
VisitChanges iterates over all changed files in the checkout, calling fn for each. If scan=true, calls ScanChanges(ScanHash) first to detect on-disk modifications. Otherwise, only reports files marked as changed in the vfile table.
The function classifies each changed file: - deleted > 0 → ChangeRemoved - rid == 0 → ChangeAdded (newly managed file, not yet committed) - origname != "" → ChangeRenamed - chnged > 0 → ChangeModified
If fn returns a non-nil error, iteration stops and that error is returned.
Panics if c is nil (TigerStyle precondition).
func (*Checkout) WouldFork ¶
WouldFork reports whether committing on the current branch would create a fork. Returns true when another leaf exists on the same branch that is not the current checkout version.
func (*Checkout) WriteManifest ¶
func (c *Checkout) WriteManifest(flags ManifestFlags) error
WriteManifest writes manifest and/or manifest.uuid files to the checkout directory. Panics if c is nil (TigerStyle precondition).
type CommitOpts ¶
type CommitOpts struct {
Message string
User string
Branch string // empty → current branch
Tags []string // additional T-cards
Delta bool
Time time.Time // zero → env.Clock.Now()
PreCommitCheck func() error // nil = no check; non-nil error aborts commit
}
CommitOpts configures creating a checkin from staged files.
type CommitStart ¶
CommitStart describes the beginning of a commit operation.
type CreateOpts ¶
CreateOpts configures creating a new checkout from a repo.
type DequeueOpts ¶
type DequeueOpts struct {
Paths []string // empty → dequeue all
}
DequeueOpts configures unstaging files.
type EnqueueOpts ¶
EnqueueOpts configures staging files for commit.
type ExtractEnd ¶
type ExtractEnd struct {
Operation string
TargetRID libfossil.FslID
FilesWritten int
FilesRemoved int
Conflicts int
Err error
}
ExtractEnd describes the result of an extract or update operation.
type ExtractOpts ¶
type ExtractOpts struct {
Callback func(name string, change UpdateChange) error // per-file notification
SetMTime bool // set file mtime to checkin timestamp
DryRun bool
Force bool // overwrite locally modified files
}
ExtractOpts configures file extraction from a checkin.
type ExtractStart ¶
ExtractStart describes the beginning of an extract or update operation.
type FileChange ¶
type FileChange int
FileChange — checkout-level change types (maps to fsl_ckout_change_e)
const ( ChangeNone FileChange = iota ChangeAdded ChangeRemoved ChangeMissing ChangeRenamed ChangeModified )
type ManageCounts ¶
type ManageCounts struct {
Added, Updated, Skipped int
}
ManageCounts reports the result of a Manage operation.
type ManageOpts ¶
ManageOpts configures adding files to tracking.
type ManifestFlags ¶
type ManifestFlags int
ManifestFlags — controls WriteManifest behavior
const ( ManifestMain ManifestFlags = 1 << iota // write manifest file ManifestUUID // write manifest.uuid file )
type Observer ¶
type Observer interface {
// Extract/update lifecycle.
ExtractStarted(ctx context.Context, e ExtractStart) context.Context
ExtractFileCompleted(ctx context.Context, name string, change UpdateChange)
ExtractCompleted(ctx context.Context, e ExtractEnd)
// Scan lifecycle.
ScanStarted(ctx context.Context) context.Context
ScanCompleted(ctx context.Context, e ScanEnd)
// Commit lifecycle.
CommitStarted(ctx context.Context, e CommitStart) context.Context
CommitCompleted(ctx context.Context, e CommitEnd)
// Per-error recording — called on individual errors.
Error(ctx context.Context, err error)
}
Observer receives lifecycle callbacks during checkout operations. A single Observer instance may be shared across multiple concurrent operations. Pass nil for no-op default.
Performance: nopObserver implements all methods as empty functions. The only cost on the hot path is one indirect call per invocation (~2ns).
type OpenOpts ¶
type OpenOpts struct {
Env *simio.Env // nil → RealEnv
Observer Observer // nil → nopObserver
SearchParents bool // search parent dirs for .fslckout
}
OpenOpts configures opening an existing checkout.
type RenameOpts ¶
type RenameOpts struct {
From, To string
DoFsMove bool // also move on filesystem via Storage
Callback func(from, to string) error
}
RenameOpts configures renaming a tracked file.
type RevertChange ¶
type RevertChange int
RevertChange — revert operation types (maps to fsl_ckout_revert_e)
const ( RevertNone RevertChange = iota RevertUnmanage RevertRemove RevertRename RevertPermissions RevertContents )
type RevertOpts ¶
type RevertOpts struct {
Paths []string // empty → revert all
Callback func(name string, change RevertChange) error
}
RevertOpts configures reverting file changes.
type UnmanageOpts ¶
type UnmanageOpts struct {
Paths []string // pathnames to unmanage
VFileIDs []libfossil.FslID // alternative: pass IDs directly
Callback func(name string) error
}
UnmanageOpts configures removing files from tracking.
type UpdateChange ¶
type UpdateChange int
UpdateChange — file states during extract/update (maps to fsl_ckup_fchange_e)
const ( UpdateNone UpdateChange = iota UpdateAdded UpdateAddPropagated UpdateRemoved UpdateRmPropagated UpdateUpdated UpdateUpdatedBinary UpdateMerged UpdateConflictMerged UpdateConflictAdded UpdateConflictUnmanaged UpdateConflictRm UpdateConflictSymlink UpdateConflictBinary UpdateRenamed UpdateEdited )
type UpdateOpts ¶
type UpdateOpts struct {
TargetRID libfossil.FslID // 0 → auto-calculate via CalcUpdateVersion
Callback func(name string, change UpdateChange) error
SetMTime bool // set file mtime to checkin timestamp
DryRun bool
}
UpdateOpts configures updating to a new version with merge.
type VFileChange ¶
type VFileChange int
VFileChange — vfile.chnged column values (matches Fossil's vfile states)
const ( VFileNone VFileChange = 0 // unchanged VFileMod VFileChange = 1 // modified VFileMergeMod VFileChange = 2 // modified via merge VFileMergeAdd VFileChange = 3 // added via merge VFileIntMod VFileChange = 4 // modified via integrate VFileIntAdd VFileChange = 5 // added via integrate VFileIsExec VFileChange = 6 // became executable VFileBecameLink VFileChange = 7 // became symlink VFileNotExec VFileChange = 8 // lost executable VFileNotLink VFileChange = 9 // lost symlink )