checkout

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 19, 2026 License: MIT Imports: 19 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func BranchLeaves

func BranchLeaves(r *repo.Repo, branch string) ([]libfossil.FslID, error)

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

func EnsureTables(db *sql.DB) error

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

func FindCheckoutDB(storage simio.Storage, dir string, searchParents bool) (string, error)

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

func Create(r *repo.Repo, dir string, opts CreateOpts) (*Checkout, error)

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

func Open(r *repo.Repo, dir string, opts OpenOpts) (*Checkout, error)

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

func (c *Checkout) CalcUpdateVersion() (libfossil.FslID, error)

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

func (c *Checkout) CheckFilename(name string) (string, error)

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) Close

func (c *Checkout) Close() error

Close closes the checkout database. Does NOT close the repo.

func (*Checkout) Commit

func (c *Checkout) Commit(opts CommitOpts) (libfossil.FslID, string, error)

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) Dir

func (c *Checkout) Dir() string

Dir returns the checkout directory.

func (*Checkout) DiscardQueue

func (c *Checkout) DiscardQueue() error

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

func (c *Checkout) FileContent(name string) ([]byte, error)

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

func (c *Checkout) HasChanges() (bool, error)

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

func (c *Checkout) IsEnqueued(name string) (bool, error)

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

func (c *Checkout) IsRootedIn(absPath string) bool

IsRootedIn checks if an absolute path is within the checkout directory. Panics if c is nil (TigerStyle precondition).

func (*Checkout) LoadVFile

func (c *Checkout) LoadVFile(rid libfossil.FslID, clear bool) (missing uint32, err error)

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) Repo

func (c *Checkout) Repo() *repo.Repo

Repo returns the associated repo.

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

func (c *Checkout) RevertRename(name string, doFsMove bool) (bool, error)

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

func (c *Checkout) ScanChanges(flags ScanFlags) error

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

func (c *Checkout) UnloadVFile(rid libfossil.FslID) error

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

func (c *Checkout) ValidateFingerprint() error

ValidateFingerprint verifies that the checkout-hash vvar matches the blob uuid in the repo.

func (*Checkout) Version

func (c *Checkout) Version() (libfossil.FslID, string, error)

Version returns the current checkout version (RID and UUID).

func (*Checkout) VisitChanges

func (c *Checkout) VisitChanges(vid libfossil.FslID, scan bool, fn ChangeVisitor) error

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

func (c *Checkout) WouldFork() (bool, error)

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 CommitEnd

type CommitEnd struct {
	RID         libfossil.FslID
	UUID        string
	FilesCommit int
	Err         error
}

CommitEnd describes the result of a commit operation.

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

type CommitStart struct {
	FilesEnqueued int
	Branch        string
	User          string
}

CommitStart describes the beginning of a commit operation.

type CreateOpts

type CreateOpts struct {
	Env      *simio.Env // nil → RealEnv
	Observer Observer   // nil → nopObserver
}

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

type EnqueueOpts struct {
	Paths    []string
	Callback func(name string) error
}

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

type ExtractStart struct {
	Operation string // "extract" or "update"
	TargetRID libfossil.FslID
}

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

type ManageOpts struct {
	Paths    []string
	Callback func(name string, added bool) error
}

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 ScanEnd

type ScanEnd struct {
	FilesScanned int
	FilesChanged int
	FilesMissing int
	FilesExtra   int
}

ScanEnd describes the result of a ScanChanges operation.

type ScanFlags

type ScanFlags uint32

ScanFlags — controls ScanChanges behavior

const (
	ScanHash       ScanFlags = 1 << iota // hash file content (not just mtime)
	ScanENotFile                         // mark non-regular files
	ScanSetMTime                         // update mtime in vfile
	ScanKeepOthers                       // keep other version entries
)

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
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL