Help us shape the future of Go! Take the 2026 Go Developer Survey

libfossil

package module
v0.17.0 Latest Latest
Warning

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

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 40 Imported by: 4

README

go-libfossil

go-libfossil

Docs Go Reference Go Report Card Tests License Go

Pure-Go library and CLI for Fossil repositories. Drop-in compatible with Fossil's .fossil SQLite format, with no CGo and no upstream fossil binary required.

The repository and module path are go-libfossil (go get github.com/danmestas/go-libfossil), but the Go package is still imported as libfossil and the CLI installs as the libfossil command. Only the path moved; the package and binary names are unchanged.

Why libfossil

  • Pure Go, no CGo. Static binaries, trivial cross-compilation, works under GOOS=wasip1 GOARCH=wasm.
  • Drop-in compatible. Repositories produced by upstream Fossil are readable, and vice versa — it's the same SQLite schema.
  • Embeddable. Use the full Repo API directly in your Go service. No subprocess calls, no temp files.
  • Instrumented. Sync and checkout observer interfaces make OpenTelemetry (or your own metrics) a few lines of code.
  • Deterministically testable. Deterministic simulation testing (DST) with BUGGIFY fault injection.

Installation

CLI

go install github.com/danmestas/go-libfossil/cmd/libfossil@latest

The binary is named libfossil to avoid $PATH collisions with upstream fossil.

Library

go get github.com/danmestas/go-libfossil

CLI quick start

libfossil repo new my.fossil
libfossil -R my.fossil repo ci -m "first commit" hello.txt
libfossil -R my.fossil repo timeline
libfossil -R my.fossil repo ls
libfossil -R my.fossil repo annotate hello.txt
libfossil -R my.fossil repo verify

Full command list: libfossil --help. See docs/guides/migrating-from-fossil.md for a command-by-command comparison with upstream Fossil.

Library quick start

package main

import (
    "log"

    libfossil "github.com/danmestas/go-libfossil"
    _ "github.com/danmestas/go-libfossil/db/driver/modernc"
)

func main() {
    r, err := libfossil.Create("my.fossil", libfossil.CreateOpts{User: "admin"})
    if err != nil {
        log.Fatal(err)
    }
    defer r.Close()

    rid, uuid, err := r.Commit(libfossil.CommitOpts{
        Files:   []libfossil.FileToCommit{{Name: "hello.txt", Content: []byte("hello")}},
        Comment: "initial commit",
        User:    "admin",
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("committed rid=%d uuid=%s", rid, uuid[:12])

    entries, err := r.Timeline(libfossil.TimelineOpts{Limit: 10})
    if err != nil {
        log.Fatal(err)
    }
    for _, e := range entries {
        log.Printf("  %s  %s", e.UUID[:12], e.Comment)
    }
}

Working example: examples/embed-repo-api/.

Sync

// Sync with a remote Fossil server.
result, err := r.Sync(ctx,
    libfossil.NewHTTPTransport("http://host/repo"),
    libfossil.SyncOpts{Push: true, Pull: true},
)

// Serve the sync protocol (e.g. for leaf agents, bridges, mirrors).
http.Handle("/", r.XferHandler())

Served repositories enforce the user table the way fossil does. A request without credentials runs as nobody, which a new repository lets clone and pull but not push. Give clients an account, or grant nobody more with r.SetCaps("nobody", ...).

The Transport interface is pluggable — swap HTTP for NATS, WebSocket, libp2p, or anything that delivers bytes round-trip.

Embedding the CLI

cli/ exposes Kong command structs you can mount inside your own CLI:

import (
    "github.com/alecthomas/kong"
    "github.com/danmestas/go-libfossil/cli"
    _ "github.com/danmestas/go-libfossil/db/driver/modernc"
)

type MyCLI struct {
    cli.Globals
    Repo cli.RepoCmd `cmd:"" help:"Fossil repo operations"`
    // Add your own commands here.
}

func main() {
    var c MyCLI
    ctx := kong.Parse(&c)
    ctx.FatalIfErrorf(ctx.Run(&c.Globals))
}

Project layout

Package Purpose
root (libfossil) Repo handle, Transport, SyncObserver, CheckoutObserver
cli/ Embeddable Kong command structs for the repo subcommands
cmd/libfossil/ Standalone CLI binary
db/ SQLite abstraction with pluggable drivers
db/driver/modernc Pure-Go SQLite driver (default)
db/driver/ncruces wasm-capable SQLite driver
observer/otel/ Optional OpenTelemetry observer (separate submodule)
dst/ Deterministic simulation tests + BUGGIFY harness
simio/ Clock, Rand, Storage interfaces for deterministic testing
testutil/ Shared test helpers

Deep dive: docs/concepts/architecture.md.

SQLite drivers

Driver Import When to use
modernc (default) _ "github.com/danmestas/go-libfossil/db/driver/modernc" Default for any server, CLI, or desktop use
ncruces _ "github.com/danmestas/go-libfossil/db/driver/ncruces" wasm targets (GOOS=wasip1 or browser/OPFS)

Library embedders select exactly one driver with a blank import at link time; importing both panics. The shipped cmd/libfossil CLI uses modernc by default; go build -tags test_ncruces ./cmd/libfossil selects ncruces. See docs/guides/extension-points.md for the registration contract.

Observers

// Built-in, zero dependencies.
libfossil.NopSyncObserver()     // silent
libfossil.StdoutSyncObserver()  // human-readable stderr

// Optional OpenTelemetry (separate submodule — no OTel deps in core).
import "github.com/danmestas/go-libfossil/observer/otel"
obs := otel.NewSyncObserver()

Both SyncObserver and CheckoutObserver are small interfaces you can implement directly. Details: docs/guides/extension-points.md.

WASI / wasm

libfossil compiles to a generic WASI Preview 1 module via the ncruces driver:

GOOS=wasip1 GOARCH=wasm go build -o libfossil.wasm ./examples/wasm/

See examples/wasm/ for a runnable demo and current runtime caveats (the non-js ncruces driver variant has a known locking-mode quirk under wasmtime).

Testing

  • make test — unit tests with the default modernc driver
  • make test-drivers — unit tests against both modernc and ncruces
  • make test-otel — OTel submodule tests (runs with GOWORK=off)
  • make test-all — everything, including the binary build
  • make setup-hooks — install the pre-commit hook (~45s/commit)

Test strategy — unit tests, dual-driver matrix, and deterministic simulation (DST) with BUGGIFY fault injection: docs/guides/testing.md.

Documentation

Full documentation: https://libfossil-docs.daniel-mestas.workers.dev.

Local preview: make docs-serve, then visit http://localhost:1313/.

Markdown sources: docs/site/content/.

Doc Audience
docs/concepts/architecture.md Contributors learning the codebase
docs/guides/testing.md Contributors writing or debugging tests
docs/guides/extension-points.md Consumers adding observers or custom drivers
docs/guides/migrating-from-fossil.md Users coming from upstream fossil
CONTRIBUTING.md Anyone submitting a PR
CHANGELOG.md Release notes

Contributing

See CONTRIBUTING.md.

Acknowledgements

This project stands on the work of others.

  • Stephan Beal — author of libfossil, the C library that gives this project its name. This is an indirect Go port: it follows the shape and intent of Stephan's libfossil rather than transliterating it, and leans on the original as a reference for how a Fossil library ought to be organized.
  • Dr. D. Richard Hipp and the Fossil SCM project — the Fossil source code was the implementation guide of record. Where this library and upstream Fossil had to agree on the bytes — SQLite schema, manifest format, delta and sync wire formats — Fossil's source was the authority.
  • TigerBeetle and TigerStyle — the testing philosophy: assertions everywhere, bounded everything, and treating tests as a first-class engineering surface.
  • John Ousterhout and A Philosophy of Software Design — the engineering principles for keeping modules deep and interfaces narrow as the codebase grew.
  • Antithesis and deterministic simulation testing — the model behind this project's own DST harness, where time, randomness, and faults are controlled so that every failure is perfectly reproducible.

License

MIT — see LICENSE.

Documentation

Index

Constants

View Source
const (
	CheckpointPassive  = db.CheckpointPassive
	CheckpointFull     = db.CheckpointFull
	CheckpointRestart  = db.CheckpointRestart
	CheckpointTruncate = db.CheckpointTruncate
)
View Source
const (
	PhantomSize         FslSize = fsltype.PhantomSize
	FossilApplicationID int32   = fsltype.FossilApplicationID
)
View Source
const SettingClearsign = clearsign.SettingClearsign

SettingClearsign names the boolean repository setting, read as fossil reads one, that signs every check-in a commit or a branch creation stores, as fossil and zit sign them. Off by default. It signs no horizon seed: see SettingHorizonSeedCommand. The signed text is the artifact, so a signed check-in's name is the hash of the signed bytes; a signer that fails abandons the commit. CommitOpts.NoSign and CheckoutCommitOpts.NoSign store one check-in unsigned, as fossil's --nosign does, and fossil's legacy omitsign setting turns signing off.

View Source
const SettingHorizonHistoryURL = repo.SettingHorizonHistoryURL

SettingHorizonHistoryURL names the repository setting an origin appends to pragma horizon-served as the interface, outside the sync protocol, at which history below a horizon can be queried (draft-fossil-horizon-00 §6.2.5). It must be one http or https URL with a host, no white space and no credentials; SetConfig refuses any other value, and an empty one names none. Horizon clients report it as CloneResult.HorizonHistoryURL and SyncResult.HorizonHistoryURL.

View Source
const SettingHorizonSeedCommand = clearsign.SettingSeedCommand

SettingHorizonSeedCommand names the command an origin signs the structural horizon seeds it mints with (draft-fossil-horizon-00 §5.2.4), configured apart from SettingClearsign and SettingPGPCommand: unset or off, seeds go out unsigned even when check-ins are signed. It follows pgp-command's contract, and an SSH signer must sign in the namespace fossil-horizon-seed, never fossilscm, so that a check-in's signature cannot stand in for a seed's:

ssh-keygen -q -Y sign -n fossil-horizon-seed -f ~/.ssh/id_ed25519

An origin whose command signs in another namespace serves no seed: the request fails.

View Source
const SettingHorizonSeedKey = clearsign.SettingSeedKey

SettingHorizonSeedKey names the setting holding the public key a clone verifies its origin's structural horizon seeds with (draft-fossil-horizon-00 §5.2.4): an SSH public key line, verified in process, or the fingerprint of an OpenPGP key in the user's gpg keyring, verified by gpg. With a key set, a seed that is unsigned or not signed by that key is discarded and the clone falls back to the content horizon; unset, an unsigned seed is accepted. An SSH signature must carry the namespace fossil-horizon-seed. CloneOpts.SeedKey sets it when the clone is made. It is the clone's own: an origin never sends it.

SSH signatures are verified only in a program that imports package github.com/danmestas/go-libfossil/sshverify; without it, a seed under an SSH key is refused with ErrSSHVerifierUnavailable.

View Source
const SettingPGPCommand = clearsign.SettingPGPCommand

SettingPGPCommand names the signing command, as fossil names it. Unset, it is fossil's default, "gpg --clearsign -o ", run as COMMAND OUTFILE INFILE. A command whose name starts with "ssh" is run as COMMAND INFILE and writes a detached INFILE.sig, which is wrapped in fossil's SSH envelope; to sign with an SSH key, set it to

ssh-keygen -q -Y sign -n fossilscm -f ~/.ssh/id_ed25519

The namespace must be fossilscm for a clone to verify the signature. The command runs through the shell, so ~ and environment variables expand.

View Source
const SettingPartialMirror = internalsync.SettingPartialMirror

SettingPartialMirror names the boolean repository setting, read as fossil reads one ("on", "yes", "true" or a nonzero number), that lets a sparse store serve a clone its cone does not cover (draft-fossil-sparse-cone-00 §5.3). Unset, such a clone is refused with one error card and no content, since the clone would receive elided phantoms it must resolve elsewhere. It governs every serving surface: HandleSync, XferHandler and ServeHTTP.

Variables

View Source
var ErrAmbiguousVersion = errors.New("libfossil: ambiguous version prefix")

ErrAmbiguousVersion is returned by ResolveVersion when a UUID prefix matches more than one artifact (collision). Callers can match with errors.Is.

View Source
var ErrArtifactNotFound = errors.New("libfossil: artifact not found")

ErrArtifactNotFound is returned by UUIDFromRID when the given RID does not correspond to any artifact in the repository's blob table, and by ReadBlob for a hash the blob table does not name. Callers can match with errors.Is.

View Source
var ErrAttachmentNotFound = errors.New("libfossil: attachment not found")

ErrAttachmentNotFound is returned when a target has no current attachment by the name asked for: none was ever added, or the latest was deleted. Callers can match with errors.Is.

View Source
var ErrBelowHorizon = content.ErrBelowHorizon

ErrBelowHorizon is matched by the error of an operation that needs history below the store's structural horizon (draft-fossil-horizon-00 §5.5), such as a merge whose base lies there. The message names the horizon and the remedy, a deepen (Repo.DeepenHorizon).

View Source
var ErrFileNotFound = errors.New("libfossil: file not found in checkin")

ErrFileNotFound is returned by ReadFile when the requested filePath is not tracked in the given checkin. Callers can match with errors.Is.

View Source
var ErrHorizonCheckout = errors.New("libfossil: a horizon is a property of the repository's store, not of a checkout")

ErrHorizonCheckout is returned when a checkout is given a cone that carries a horizon. A content horizon (draft-fossil-horizon-00 §3.2) is a property of the repository's store, not of a checkout: set it on the store cone with Repo.SetStoreCone.

View Source
var ErrMergeConflict = errors.New("libfossil: merge has conflicts")

ErrMergeConflict is returned (wrapped in a MergeConflictError) when Merge detects any unresolved three-way conflicts. Callers can check with errors.Is(err, ErrMergeConflict) without caring about the file list.

View Source
var ErrNoStoreCone = errors.New("libfossil: the store has no cone")

ErrNoStoreCone is returned by CompactStore on a dense store: with no cone on record nothing is elided, and compaction never guesses a policy.

View Source
var ErrOutsideCone = checkout.ErrOutsideCone

ErrOutsideCone is wrapped by the refusal of a checkout operation that would act on a path its sparse cone does not cover: adding, removing, renaming, reverting or committing such a path, or a merge that would change one. The message names the path, the cone and the member that excluded it.

View Source
var ErrSSHVerifierUnavailable = clearsign.ErrSSHVerifierUnavailable

ErrSSHVerifierUnavailable is the error, wrapped, of an operation that had to verify an SSH signature in a program that does not link the verifier: a sync or rebuild of a store whose SettingHorizonSeedKey is an SSH key fails with it, and the seed is neither accepted nor discarded. Import package github.com/danmestas/go-libfossil/sshverify for its side effect to verify SSH signatures; the library leaves that cryptography out of programs that never verify one.

View Source
var ErrVersionNotFound = errors.New("libfossil: version not found")

ErrVersionNotFound is returned by ResolveVersion when the requested version string does not match any artifact in the repository. Callers can match with errors.Is.

Functions

func Clone

func Clone(ctx context.Context, path string, t Transport, opts CloneOpts) (*Repo, *CloneResult, error)

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 JulianToTime

func JulianToTime(j float64) time.Time

JulianToTime converts a Fossil Julian day number to time.Time.

func TimeToJulian

func TimeToJulian(t time.Time) float64

TimeToJulian converts a time.Time to a Fossil Julian day number.

Types

type AnnotateOpts

type AnnotateOpts struct {
	FilePath string
	StartRID int64
}

AnnotateOpts configures an annotate operation.

type AnnotatedLine

type AnnotatedLine struct {
	Text         string
	UUID         string
	User         string
	Date         time.Time
	BelowHorizon bool
}

AnnotatedLine is a single line of blame/annotate output.

BelowHorizon marks a line whose origin lies at or below the store's horizon C (draft-fossil-horizon-00 §5.5), which the store does not hold the history to attribute: UUID, User and Date then describe C itself, at which the line is reported as originating, not the check-in that added it. A deepen (repo cone deepen) brings the history that attributes it; on a content-horizon store AnnotateContext fetches it.

Such a result is partial, and the marks are its only signal: Annotate returns it with no error, as does an AnnotateContext that reached its demand-fetch limit or whose peer could not supply a version.

type Attachment added in v0.17.0

type Attachment struct {
	// Artifact is the hash of the control artifact that attached the file.
	Artifact string `json:"artifact"`
	// Target is the full ticket id, wiki page name or tech note id.
	Target string `json:"target"`
	Name   string `json:"name"`
	// Source is the hash of the blob the A card names: the file itself, or
	// the stub when External is set.
	Source  string    `json:"source"`
	Comment string    `json:"comment"`
	User    string    `json:"user"`
	Time    time.Time `json:"time"`
	// Size is the file's length in bytes: the blob's, or External.Size. It
	// is -1 when the blob has not arrived in this repository.
	Size int64 `json:"size"`
	// External, when not nil, says the bytes live outside the repository:
	// Source is a stub, and AttachmentRead returns no content.
	External *ExternalRef `json:"external,omitempty"`
}

Attachment is one current attachment: the latest artifact for its name on its target, when that artifact adds a file rather than deleting it.

type AttachmentOpts added in v0.17.0

type AttachmentOpts struct {
	// User is the change's author, its U card.
	User string
	// Comment is the attachment's description, its C card. Fossil writes
	// none on a deletion, so AttachmentDelete refuses one.
	Comment string
	// Time is the change's D card; zero means now.
	Time time.Time
}

AttachmentOpts is who makes an attachment change, when, and why.

type BisectSession

type BisectSession struct {
	// contains filtered or unexported fields
}

BisectSession holds state for a binary-search bisect operation.

type BuggifyChecker

type BuggifyChecker interface {
	Check(site string, probability float64) bool
}

BuggifyChecker controls fault injection for deterministic simulation testing.

type Checkout

type Checkout struct {
	// contains filtered or unexported fields
}

Checkout represents a working directory linked to a Fossil repository. A Checkout is not safe for concurrent use. Callers must serialize access to a single Checkout instance.

func (*Checkout) Add

func (c *Checkout) Add(patterns []string) (int, error)

Add adds files to version tracking. Returns the number of files added. Files already tracked are silently skipped.

func (*Checkout) Checkin

func (c *Checkout) Checkin(opts CheckoutCommitOpts) (rid int64, uuid string, err error)

Checkin creates a new checkin from the checkout working directory: every change, or only opts.Files (a directory names every tracked file under it). Pending merges become merge parents. Like fossil's commit, it refuses a name it does not track, a commit with nothing changed and no merge pending (unless opts.AllowEmpty), files that still hold merge conflict markers (unless opts.AllowConflict), and committing only some files of a pending merge. Returns the RID and UUID of the new checkin manifest.

func (*Checkout) CheckinContext added in v0.14.0

func (c *Checkout) CheckinContext(
	ctx context.Context, opts CheckoutCommitOpts, required RequiredContentOpts,
) (int64, string, error)

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 (*Checkout) Close

func (c *Checkout) Close() error

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

func (*Checkout) Cone added in v0.14.0

func (c *Checkout) Cone() *Cone

Cone returns the checkout's cone, or nil when the checkout is dense.

func (*Checkout) Conflicts added in v0.11.0

func (c *Checkout) Conflicts() ([]string, error)

Conflicts lists the files, sorted, that hold merge conflict markers: the files a merge or update left in conflict and nobody has resolved yet.

func (*Checkout) Dir

func (c *Checkout) Dir() string

Dir returns the checkout directory path.

func (*Checkout) Extract

func (c *Checkout) Extract(rid int64, opts ExtractOpts) error

Extract writes files from the specified checkin to the working directory and makes it the checkout's current version. Unless opts.Force is set it refuses, changing nothing, when the checkout has unsaved changes or when an untracked file sits where the checkin would write different content.

func (*Checkout) HasChanges

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

HasChanges reports whether the checkout has any added, removed, renamed or modified files. It reads only the checkout database, so an edit on disk counts once Status (or an Extract or Commit) has scanned it; adds, removals and renames always count. Missing files need the disk; Status reports them.

func (*Checkout) Merge added in v0.11.0

Merge merges another checkin into the checkout, as fossil's merge command does, leaving the result for the next Checkin to commit with the merged-in checkin as a merge parent. A file both sides changed is merged by its strategy; when the strategy cannot reconcile the changes, fossil's conflict markers are written into the file, and the file is in conflict until they are edited out (see Conflicts). A conflicted merge is not an error.

Merge refuses, changing nothing, when the repository lacks content it needs or an added file would overwrite an untracked one. A file edited here but deleted in the merged-in version is kept and reported. Renames are followed as fossil's merge follows them: a change made under one name is merged into the file under another, and a file the merged-in checkin renamed is renamed here too (CheckoutMergeFile.RenamedTo); Merge refuses to rename one onto a file the checkout keeps or an untracked file. Merging the checkout's own version or one of its ancestors does nothing. The common ancestor is the one fossil's merge diffs against: the most recent common ancestor of the merged-in checkin and the checkout's version with every checkin already merged into it.

Under a structural horizon Merge refuses, with an error matching ErrBelowHorizon, a merge whose base it does not hold or whose sides' ancestry crosses the horizon (draft-fossil-horizon-00 §5.5): only the origin can name that base, and MergeContext with a Peer asks it.

func (*Checkout) MergeContext added in v0.15.0

func (c *Checkout) MergeContext(
	ctx context.Context, opts CheckoutMergeOpts, required RequiredContentOpts,
) (CheckoutMergeResult, error)

MergeContext is Merge with the remedy of draft-fossil-horizon-00 §5.5. Under a structural horizon, when Peer is given and the ancestry of either side crosses the horizon, it asks the origin for the base (§6.2.4) even when the store's own walk finds one, since over part of the graph the common ancestor found need not be the nearest. It deepens the horizon to the base the origin names when the store does not hold it (Repo.DeepenHorizon) and merges over that base. When the origin does not answer, or without a Peer, it is Merge, which refuses a merge whose ancestry crosses the horizon; when nothing crosses it is Merge. A merge never runs against a base the store does not hold.

The query names the merged-in version over the checkout's version and each plain merge pending in it. It carries at most two such secondaries, so a merge that must ask with two merges already pending is refused: asking without them would name a base Fossil's merge would not choose.

func (*Checkout) Redo added in v0.14.0

func (c *Checkout) Redo() (UndoResult, error)

Redo reverses the last Undo, reporting the files it changed as Undo does.

func (*Checkout) Remove

func (c *Checkout) Remove(patterns []string) error

Remove removes files from version tracking. Newly added files are deleted from vfile; committed files are marked as deleted.

func (*Checkout) Rename

func (c *Checkout) Rename(oldName, newName string) error

Rename marks a tracked file as renamed and moves it on disk.

func (*Checkout) ResolveVersion added in v0.12.0

func (c *Checkout) ResolveVersion(name string) (int64, error)

ResolveVersion resolves name as Repo.ResolveVersion does and also resolves the names relative to this checkout (repo-state-00 Section 8.3), tried after "tip" and before every other form, as fossil's symbolic_name_to_rid does (src/name.c):

"current"            the checkout's version
"prev", "previous"   its primary parent
"next"               a child: a primary child first, then the newest link

A keyword that names nothing, such as "prev" at a root, falls through to the other forms, as in fossil. The forms that take a name, such as "root:current", resolve it the same way. "ckout" is an ordinary name here: it is a keyword only in the checkout-inclusive request, ResolveWorking.

func (*Checkout) ResolveWorking added in v0.12.0

func (c *Checkout) ResolveWorking(name string) (WorkingVersion, error)

ResolveWorking is fossil's checkout-inclusive request ("ci+", symbolic_name_to_rid in src/name.c): while the checkout has a version, "ckout" names its working files, reported as Working. Every other name, and "ckout" in a checkout with no version, resolves as ResolveVersion does, except that only check-ins can answer: the request is a check-in request, so a technote or wiki page carrying the tag does not.

As repo-state-00 Section 8.3 says, only "ci+" has the keyword, so ResolveVersion and Repo.ResolveBranchStart read "ckout" as an ordinary name. It is a keyword only as the whole name: in "root:ckout" or "ckout." the inner name is resolved as a plain check-in request, as in fossil.

func (*Checkout) Revert

func (c *Checkout) Revert(opts RevertOpts) error

Revert restores files to their checkout version state. If opts.Files is empty, reverts all changed files. A renamed file goes back to its committed name, whatever holds that name now. Each file it writes or deletes is saved for undo first, so Undo brings it back.

func (*Checkout) SetCone added in v0.14.0

func (c *Checkout) SetCone(next *Cone) (ConeChange, error)

SetCone replaces the checkout's cone; nil makes it dense. Files of the checked-out version that the new cone covers and the old one did not are written; files it no longer covers are removed from the working directory (the repository keeps them). It refuses, changing nothing, when a file leaving the cone has local changes or a file entering it would overwrite an untracked file. A cone with a horizon is refused with ErrHorizonCheckout.

func (*Checkout) SetConeContext added in v0.14.0

func (c *Checkout) SetConeContext(
	ctx context.Context, next *Cone, required RequiredContentOpts,
) (ConeChange, error)

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 (*Checkout) Status

func (c *Checkout) Status() ([]CheckoutChange, error)

Status scans the working directory and returns the changed files, each classified as added, deleted, missing, renamed or modified, the way fossil's changes command classifies them. Wraps ScanChanges + VisitChanges.

func (*Checkout) Undo added in v0.14.0

func (c *Checkout) Undo() (UndoResult, error)

Undo reverses the last operation that saved undo state, such as Update, as fossil's undo does: the files it changed come back, and the checkout's file list and version are as they were before it. Fossil's undo reads the same state, so either tool can undo the other's update.

func (*Checkout) Update

func (c *Checkout) Update(opts UpdateOpts) (UpdateResult, error)

Update moves the checkout to a new version as fossil's update does, carrying uncommitted changes into it: a locally edited file is merged three ways (the checkout's version as base, the working file as local, the target as other), one the target deletes is kept untracked, and pending adds and removals stay pending. See UpdateResult for how to distinguish a clean update from one that wrote conflict markers into working-tree files.

func (*Checkout) UpdateContext added in v0.14.0

func (c *Checkout) UpdateContext(
	ctx context.Context, opts UpdateOpts, required RequiredContentOpts,
) (UpdateResult, error)

UpdateContext recovers necessary structure and selected update payloads from an explicit peer before checkout mutation. An implicit target is resolved once; after recovery the local update replans against fresh working files.

func (*Checkout) Version

func (c *Checkout) Version() (int64, string, error)

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

func (*Checkout) WouldFork

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

WouldFork reports whether committing on the checkout's version would create a fork: the version already has a child on its own branch (for example after a pull), so the commit would become a second leaf. This is fossil's "Would fork" commit refusal; run Update first, or commit to a new branch. Another open leaf elsewhere on the branch does not count.

type CheckoutChange

type CheckoutChange struct {
	Name   string
	Change string
}

CheckoutChange describes a single file change in the checkout.

Change is "added", "modified", "deleted", "renamed" or "missing", or one of the mode changes fossil's changes command reports: "executable" (became executable), "symlink" (became a symlink), "unexec" (lost the executable bit) or "unlink" (was a symlink, now is not).

type CheckoutCommitOpts

type CheckoutCommitOpts struct {
	Message string
	User    string
	Branch  string   // empty = current branch
	Tags    []string // additional tag names
	Delta   bool
	// Files limits the commit to these checkout-relative paths; empty
	// commits every change.
	Files []string
	// AllowConflict commits files that still hold merge conflict markers,
	// which Checkin otherwise refuses, as fossil's commit does.
	AllowConflict bool
	// AllowEmpty commits even when nothing changed, which Checkin otherwise
	// refuses, as fossil's commit does.
	AllowEmpty bool
	// NoSign stores the check-in unsigned even when the repository's
	// clearsign setting is on (SettingClearsign): fossil's commit --nosign.
	NoSign bool
}

CommitOpts configures creating a checkin from the checkout. (This type is distinct from the existing libfossil.CommitOpts which takes explicit file content for direct repo commits without a checkout.)

type CheckoutCreateOpts

type CheckoutCreateOpts struct {
	Env      *simio.Env       // nil = real env
	Observer CheckoutObserver // nil = nop
	// Cone makes the checkout sparse: Extract, Update and Status work only on
	// the files it covers, and Checkin carries the others from the parent
	// unchanged. nil is dense. A cone with a horizon is refused with
	// ErrHorizonCheckout. See Cone and Checkout.SetCone.
	Cone *Cone
}

CheckoutCreateOpts configures creating a new checkout.

type CheckoutMergeFile added in v0.11.0

type CheckoutMergeFile struct {
	Name      string
	Action    string
	Strategy  string // the strategy that merged it, when one ran
	Reason    string // why the file was kept, for "kept"
	RenamedTo string // its new name, when the merge renamed it
}

CheckoutMergeFile reports what a merge did to one file. Action is one of:

"updated"  - only the merged-in version changed it; its content was taken
"merged"   - both sides changed it and the strategy combined them cleanly
"conflict" - merged with conflict markers written into the file
"kept"     - could not be merged; the checkout's copy is unchanged (see Reason)
"forked"   - the conflict-fork strategy recorded every version for later
"added"    - new in the merged-in version
"deleted"  - deleted in the merged-in version, unchanged here
"mode"     - only the merged-in version changed its executable bit; taken
"renamed"  - only renamed: the merged-in version renamed it, this checkout did not

Name is the file's name in the checkout before the merge. RenamedTo is set when the merge also renamed it, as fossil's merge does a file the merged-in version renamed and the checkout did not.

type CheckoutMergeOpts added in v0.11.0

type CheckoutMergeOpts struct {
	Version  int64  // rid of the checkin to merge in; required
	Strategy string // strategy for every file; "" picks one per file
	DryRun   bool   // report what the merge would do, changing nothing
}

CheckoutMergeOpts configures Checkout.Merge.

type CheckoutMergeResult added in v0.11.0

type CheckoutMergeResult struct {
	Ancestor int64               // the common ancestor the merge diffed against
	Files    []CheckoutMergeFile // sorted by name; empty when there was nothing to merge
}

CheckoutMergeResult reports a merge.

type CheckoutObserver

type CheckoutObserver interface {
	ExtractStarted(info ExtractStart)
	ExtractFileCompleted(name string, change UpdateChange)
	ExtractCompleted(info ExtractEnd)
	ScanStarted(dir string)
	ScanCompleted(info ScanEnd)
	CommitStarted(info CommitStart)
	CommitCompleted(info CommitEnd)
	Error(err error)
}

CheckoutObserver receives lifecycle callbacks during checkout/commit operations. Use NopCheckoutObserver() for a silent no-op, or StdoutCheckoutObserver() for stderr logging.

func NopCheckoutObserver

func NopCheckoutObserver() CheckoutObserver

NopCheckoutObserver returns a CheckoutObserver that silently discards all events.

func StdoutCheckoutObserver

func StdoutCheckoutObserver() CheckoutObserver

StdoutCheckoutObserver returns a CheckoutObserver that logs events to stderr.

type CheckoutOpenOpts

type CheckoutOpenOpts struct {
	SearchParents bool       // search parent dirs for .fslckout
	Env           *simio.Env // nil = real env
	Observer      CheckoutObserver
}

CheckoutOpenOpts configures opening an existing checkout.

type CheckpointMode

type CheckpointMode = db.CheckpointMode

CheckpointMode mirrors SQLite's PRAGMA wal_checkpoint(<mode>) argument.

type CloneOpts

type CloneOpts struct {
	User     string
	Password string
	Observer SyncObserver
	Buggify  BuggifyChecker // fault injection for DST (nil = no faults)
	// PullPhantoms, when set, makes Clone fetch the artifacts the clone
	// rounds left missing with a follow-up pull session, and fail with an
	// error if any are still missing after it. That pull departs from
	// Section 8.2 of the sync draft, which sends no clone, pull or push card
	// after clone_seqno 0, so it is off by default: like fossil(1)'s clone,
	// Clone then succeeds with those artifacts left as phantoms.
	PullPhantoms bool
	// StoreCone, when non-nil, clones straight into a sparse store: only the
	// artifacts the cone covers are fetched, and the cone becomes the store's
	// policy. With a horizon (NewHorizonCone) it clones a content-horizon
	// store, eliding the blobs below the horizon; CloneResult.HorizonServed
	// counts the replies whose server cut at the horizon, the others being
	// classified locally. A server that will not serve a sparse clone
	// refuses it (SettingPartialMirror).
	StoreCone *Cone
	// SeedKey, when set, is the origin's public key, kept as the clone's
	// SettingHorizonSeedKey: every structural horizon seed is verified against
	// it, in this clone and every later pull and rebuild.
	SeedKey string
	// Horizon, when set, is the horizon to clone at, its Checkin a full hash
	// or a name: "tip", a branch or tag. HorizonDepth steps it back that
	// many check-ins along primary parents. A name, or any depth, is
	// resolved by the origin (draft-fossil-horizon-00 §6.2.7); against one
	// that does not, the clone resolves it over what it received at the
	// content horizon and says so in CloneResult. Only the resolved check-in
	// is stored. StoreCone then gives the path members alone: a horizon on
	// both is an error, as is a depth without a Horizon.
	Horizon      *Horizon
	HorizonDepth int
}

CloneOpts configures a clone operation.

type CloneResult

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
	// HorizonServed counts the replies whose server served the store's
	// horizon (pragma horizon-served, draft-fossil-horizon-00 §6.2.5); the
	// other rounds were classified locally. StructuralServed counts those
	// served at the structural level, and HorizonFallback reports a
	// structural clone that kept the content horizon instead (§6.3).
	HorizonServed    int
	StructuralServed int
	HorizonFallback  bool
	// HorizonHistoryURL is the interface outside the sync protocol at which
	// the origin says history below a horizon can be queried (pragma
	// horizon-served URL, draft-fossil-horizon-00 §6.2.5), the last a reply
	// named; "" when none did. An origin names it with
	// SettingHorizonHistoryURL.
	HorizonHistoryURL string
	// HorizonResolved is the check-in CloneOpts.Horizon named resolved to and
	// HorizonSteps the steps back it took, fewer than HorizonDepth when
	// history ran out; HorizonResolvedLocally reports that the origin did
	// not resolve the name and the clone did, at the content horizon.
	HorizonResolved        string
	HorizonSteps           int
	HorizonResolvedLocally bool
}

CloneResult reports what happened during a clone.

type CommitEnd

type CommitEnd struct {
	UUID string
	RID  int64
}

CommitEnd describes the completion of a commit operation.

type CommitOpts

type CommitOpts struct {
	// Files is the caller-supplied subset of the new commit's tree. When
	// ParentID is non-zero, Files is MERGED with the parent's tracked files:
	// any name in Files overrides the parent's entry, and any file tracked
	// at the parent but not in Files is carried forward into the new manifest.
	// This matches `fossil ci`'s full-tree semantics — supplying just the
	// changed files does not erase the rest of the tree.
	Files    []FileToCommit
	Comment  string
	User     string
	Tags     []TagSpec
	Time     time.Time
	ParentID int64
	// MergeParents lists additional parents for a merge commit. The resulting
	// manifest's P-card is [ParentID, MergeParents...]; ParentID is the primary
	// parent (branch tip being committed onto), and each MergeParent contributes
	// a secondary plink row (isprim=0).
	MergeParents []int64
	Delta        bool
	// PartialManifest, when true, skips the parent-file merge: the resulting
	// manifest contains only Files. This is the legacy pre-fix behavior and
	// effectively erases every file tracked at the parent that is not in
	// Files. Default false matches `fossil ci`. Set true only when the
	// caller intentionally wants omission-to-mean-deletion (e.g., tests for
	// the diff/deletion path); a dedicated deletion API may replace this
	// escape hatch later.
	PartialManifest bool
	// NoSign stores the check-in unsigned even when the repository's
	// clearsign setting is on (SettingClearsign): fossil's commit --nosign.
	NoSign bool
}

CommitOpts configures a commit operation.

type CommitStart

type CommitStart struct {
	Comment string
	User    string
	Files   int
}

CommitStart describes the beginning of a commit operation.

type Cone added in v0.14.0

type Cone struct {
	// contains filtered or unexported fields
}

Cone is a sparse checkout's cone (draft-fossil-sparse-cone-00 §3): a set of repository paths, each a directory subtree or a single file, included or excluded. The longest member covering a path decides whether the cone covers it, so an exclusion carves a part out of an inclusion, and a deeper inclusion re-includes part of an exclusion. Members are literal prefixes, never patterns. A Cone is immutable; With and Without return new ones.

func NewCone added in v0.14.0

func NewCone(include, exclude []string) (*Cone, error)

NewCone builds a cone from inclusion and exclusion members. Members are validated as tracked paths, sorted, and reduced to the minimal set with the same coverage, so input order never matters. It refuses an empty inclusion list, more than 255 members, an exclusion no inclusion covers, and a path given with both polarities.

func NewHorizonCone added in v0.15.0

func NewHorizonCone(include, exclude []string, h Horizon) (*Cone, error)

NewHorizonCone builds a cone with a horizon and optional path members. With no include members the cone is horizon-only: it covers every path and only the horizon narrows what is held. Checkin is normalized to lower case.

func (*Cone) Covers added in v0.14.0

func (c *Cone) Covers(path string) bool

Covers reports whether the cone covers path.

func (*Cone) Decide added in v0.14.0

func (c *Cone) Decide(path string) (covered bool, member string)

Decide reports whether the cone covers path and the member that decided: the longest member covering it, of either polarity, or "" when none does. Under longest match the deciding member is often not the first one listed, so naming it is what explains a verdict.

func (*Cone) Digest added in v0.14.0

func (c *Cone) Digest() string

Digest is the SHA3-256 of the cone's canonical serialization, in hex: equal for equal coverage, and the same value zit computes.

func (*Cone) Exclude added in v0.14.0

func (c *Cone) Exclude() []string

Exclude returns the exclusion members, sorted.

func (*Cone) Horizon added in v0.15.0

func (c *Cone) Horizon() (Horizon, bool)

Horizon returns the cone's horizon, if it has one.

func (*Cone) Include added in v0.14.0

func (c *Cone) Include() []string

Include returns the inclusion members, sorted.

func (*Cone) String added in v0.14.0

func (c *Cone) String() string

String lists the members in sorted order, an exclusion marked with '!'. A horizon leads, as "horizon <check-in> <rule> content".

func (*Cone) With added in v0.14.0

func (c *Cone) With(include, exclude []string) (*Cone, error)

With returns the cone with more members: the incremental form of widening (or, with exclusions, of narrowing).

func (*Cone) WithHorizon added in v0.15.0

func (c *Cone) WithHorizon(h *Horizon) (*Cone, error)

WithHorizon returns the cone with its horizon replaced by h, keeping the path members; nil drops the horizon. Dropping the horizon of a horizon-only cone is an error, since nothing is left: make the store dense with Repo.SetStoreCone(nil).

func (*Cone) Without added in v0.14.0

func (c *Cone) Without(paths []string) (*Cone, error)

Without returns the cone with every member equal to one of paths removed, of either polarity. A path that is not a member removes nothing.

type ConeChange added in v0.14.0

type ConeChange struct {
	Materialized   []string // newly covered files written, sorted
	Dematerialized []string // newly uncovered files removed, sorted
}

ConeChange reports what Checkout.SetCone did to the working directory.

type CreateOpts

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
}

CreateOpts configures repository creation.

type Cursor

type Cursor = fsltype.Cursor

Cursor is an opaque pagination token for Timeline. Obtain one from a returned TimelineEntry's Cursor field and pass it back as the next TimelineOpts.After to resume enumeration immediately after that entry. The zero Cursor means "start from the newest event".

Cursor's representation is deliberately hidden: it cannot be constructed from a timestamp and a rid by calling code, only obtained from a TimelineEntry the library already produced. See fsltype.Cursor's doc comment for why — a hand-built cursor derived from a rounded time.Time is not guaranteed to match the row it claims to follow exactly, which is what silently reintroduces skipped or duplicated rows at a page boundary. LogEntry, Ancestry's result type, has no Cursor field at all: Ancestry's pagination is by Start/Limit, so there is no valid cursor to obtain from it, and the type reflects that instead of documenting it as a hazard.

type DiffEntry

type DiffEntry struct {
	Name    string
	Unified string
}

DiffEntry describes a unified diff for a single file.

type EventKind

type EventKind = fsltype.EventKind

EventKind is the type discriminator on a Timeline entry: one of the single-letter codes fossil assigns per event.type row. The zero value means "all kinds" — the default Timeline uses when no Type is given.

const (
	// EventKindCheckin is a check-in ('ci').
	EventKindCheckin EventKind = fsltype.EventKindCheckin
	// EventKindTechnote is a technote / event artifact ('e').
	EventKindTechnote EventKind = fsltype.EventKindTechnote
	// EventKindForum is a forum post ('f').
	EventKindForum EventKind = fsltype.EventKindForum
	// EventKindTag is a tag/control artifact ('g').
	EventKindTag EventKind = fsltype.EventKindTag
	// EventKindTicket is a ticket change ('t').
	EventKindTicket EventKind = fsltype.EventKindTicket
	// EventKindWiki is a wiki page edit ('w').
	EventKindWiki EventKind = fsltype.EventKindWiki
)

type ExternalRef added in v0.17.0

type ExternalRef struct {
	// SHA256 is the bytes' SHA-256, 64 lowercase hex digits.
	SHA256 string `json:"sha256"`
	// Size is the bytes' length.
	Size int64 `json:"size"`
	// Type is the declared mimetype.
	Type string `json:"type"`
	// Name is the file's name, a bare name with no directory.
	Name string `json:"name"`
}

ExternalRef names an attachment's bytes held outside the repository, in a bucket the host binds and keys attachments/<SHA256> (Quarry RFC 0016). The repository holds only a stub naming them; this library never reads or writes the bytes themselves.

type ExtractEnd

type ExtractEnd struct {
	FilesWritten int
}

ExtractEnd describes the completion of a checkout extraction.

type ExtractOpts

type ExtractOpts struct {
	Force bool // overwrite uncommitted changes
	// Warn receives what fossil's checkout warns about and proceeds past:
	// a present R card that disagrees with the files the check-in names,
	// checked over every file, whatever the cone. nil discards warnings.
	Warn func(message string)
}

ExtractOpts configures file extraction from a checkin.

type ExtractStart

type ExtractStart struct {
	RID int64
	Dir string
}

ExtractStart describes the beginning of a checkout extraction.

type FileEntry

type FileEntry struct {
	Name string
	UUID string
	Perm string
}

FileEntry describes a file in a manifest.

type FileToCommit

type FileToCommit struct {
	Name    string
	Content []byte
	Perm    string
	OldName string
	UUID    string
}

FileToCommit describes a file to include in a commit. OldName, when set, records that the file was renamed from that name in the parent, as fossil's commit records a rename (the F card's old-name field).

UUID, when set, carries an artifact the repository already holds into the check-in by its name: the F card names it verbatim and nothing is read or stored, so a caller that knows a file's hash from ListFiles can carry it forward without its content. Content must be nil when UUID is set, and UUID must be a lowercase SHA1 or SHA3-256 hash. The artifact must be held, except under a store cone that elides it (draft-fossil-sparse-cone-00 §5.3); an unknown or phantom UUID fails the commit. This is what PartialManifest callers use to name the unchanged part of a tree without reading it.

type Fork

type Fork struct {
	Ancestor  int64
	LocalTip  int64
	RemoteTip int64
}

Fork describes a divergence point between two branches.

type FramedTransport

type FramedTransport interface {
	Transport
	// RoundTripFramed behaves like RoundTrip but also returns the framing
	// signal (e.g. the reply's Content-Type) the wire carried for this reply,
	// or "" when the transport observed none.
	RoundTripFramed(ctx context.Context, payload []byte) (resp []byte, contentType string, err error)
}

FramedTransport is an optional interface a Transport may also implement when it can report the framing signal — such as an HTTP Content-Type header — that accompanied a reply. Sync uses that signal to select the reply's §4 framing instead of assuming the §4.1 compressed container, which matters when the peer is a different Fossil-protocol implementation that legitimately replies with the uncompressed plain-card framing (e.g. a real Fossil server's clone reply).

It is optional in the same way http.Flusher is optional on an http.ResponseWriter: a Transport whose framing is fixed by convention (both ends always emit the compressed container) need not implement it, and sync falls back to assuming the compressed framing for such a Transport. Callers type-assert a Transport to FramedTransport and use RoundTripFramed when it is available. Reporting the signal as a return value keeps it per-call, with no shared mutable state to make a reused Transport unsafe across concurrent calls.

type FslError

type FslError struct {
	Code  RC
	Msg   string
	Cause error
}

func (*FslError) Error

func (e *FslError) Error() string

func (*FslError) Unwrap

func (e *FslError) Unwrap() error

type FslID

type FslID = fsltype.FslID

FslID is a row-id in the blob table (content-addressed artifacts).

type FslSize

type FslSize = fsltype.FslSize

FslSize represents a blob size; negative values indicate phantom blobs.

type HTTPOption

type HTTPOption func(*httpTransport)

HTTPOption configures an HTTP transport.

func WithHTTPClient

func WithHTTPClient(c *http.Client) HTTPOption

WithHTTPClient sets a custom http.Client for the transport.

type HandleEnd

type HandleEnd struct {
	FilesSent, FilesRecvd int
}

HandleEnd describes the completion of a server-side sync handle.

type HandleOpts

type HandleOpts struct {
	Observer SyncObserver
	Buggify  BuggifyChecker
	// LoginCookie is the value of the request's x-f-l-c cookie, which
	// carries the login card once the client has seen a server-version
	// that reads it (§6.5). This server announces such a release, so fossil
	// and go-libfossil clients move their login there after the first
	// round: an embedder that serves HandleSyncWithOpts over HTTP must pass
	// the cookie through, or those rounds arrive as nobody. XferHandler and
	// ServeHTTP read it themselves.
	LoginCookie string
	// RemoteAddr is the address the request came from, recorded in the
	// rcvfrom row of whatever it pushes, as fossil records REMOTE_ADDR.
	// XferHandler and ServeHTTP fill it themselves.
	RemoteAddr string
	// MaxStoredBytes, when positive, is the most bytes one pushed artifact
	// may occupy as this repository stores it (compressed, and as a delta
	// when pushed as one). Set it when the host's storage caps a single
	// value: a push carrying a bigger artifact is refused whole with an
	// error naming the artifact, its stored size and the limit, and the
	// file and check-in when this repository already holds a check-in
	// listing it, so nothing from that request is stored, and
	// HandleSyncWithOpts returns a *RefusedError with that reply. 0, the
	// default, stores any size. Clones and pulls served from the repository
	// are not limited. XferHandler and ServeHTTP serve without a budget: a
	// host that needs one serves HandleSyncWithOpts itself.
	MaxStoredBytes int
}

HandleOpts configures server-side sync handling.

type HandleStart

type HandleStart struct {
	RemoteAddr string
}

HandleStart describes the beginning of a server-side sync handle.

type Horizon added in v0.15.0

type Horizon struct {
	// Checkin is the check-in's full artifact hash, 40 or 64 hex digits; as
	// CloneOpts.Horizon it may also be a name the origin resolves.
	Checkin string
	Rule    HorizonRule
	// Structural takes the structural cut (§5): the manifests below the
	// check-in are elided too, and a seed the origin mints stands in for the
	// branch and tag state they carried. A clone or pull whose origin does
	// not serve it falls back to the content horizon and reports so.
	Structural bool
}

Horizon is the temporal member of a store cone (draft-fossil-horizon-00 §3.1): blobs only check-ins outside the held set name are elided. The zero value of Structural is the content horizon (§4), which keeps every manifest.

type HorizonRule added in v0.15.0

type HorizonRule int

HorizonRule is the held-set rule a horizon names (draft-fossil-horizon-00 §3.1).

const (
	// HorizonDescendants holds the check-in and every descendant of it. It is
	// the zero value.
	HorizonDescendants HorizonRule = iota
	// HorizonLeaves holds the descendants plus every open leaf's ancestry back
	// to its nearest common ancestor with the check-in. Choose it knowingly
	// (§3.1): it is what lets a client merge across live branches offline, and
	// it holds every descendant of where each childless check-in's history
	// meets the check-in's. On a repository with old unmerged branches that is
	// nearly the whole history: 20,907 of 21,008 check-ins of fossil-scm.org's.
	HorizonLeaves
)

func (HorizonRule) String added in v0.15.0

func (r HorizonRule) String() string

String names the rule as the operator spells it.

type HorizonRuleCost added in v0.15.0

type HorizonRuleCost struct {
	Rule          HorizonRule
	Checkins      int   // check-ins in K
	Blobs         int   // distinct blobs K's check-ins name, held here
	StoredBytes   int64 // what those blobs occupy in the repository, compressed and delta-encoded
	ExpandedBytes int64 // their sizes once expanded
}

HorizonRuleCost is what one rule would hold for a horizon at a check-in (draft-fossil-horizon-00 §3.4): the check-ins of the held set K and the blobs those check-ins' F cards name, the contents a clone at that horizon keeps.

type LogEntry

type LogEntry struct {
	RID     int64
	UUID    string
	Comment string
	User    string
	Time    time.Time
	Kind    EventKind
	Parents []string
	// HorizonParents is the subset of Parents that the store's origin
	// labelled below its structural horizon: each is the horizon, not a
	// missing parent and not damage (draft-fossil-horizon-00 §5.4). Ancestry
	// ends at such a parent without an error.
	HorizonParents []string
}

LogEntry represents a single event, as returned by Ancestry. Parents is populated for Kind == EventKindCheckin and empty for every other kind — plink, which Parents is derived from, only relates check-in artifacts, so that is correct, not a gap.

LogEntry carries no pagination cursor: Ancestry paginates by LogOpts.Start/Limit, not by cursor, so there would be nothing valid to put in one. See TimelineEntry, Timeline's result type, for the cursor-carrying counterpart — this split means an Ancestry entry's (necessarily invalid) cursor can no longer be obtained at all, let alone passed to Timeline by mistake.

type LogOpts

type LogOpts struct {
	Start int64
	Limit int
}

LogOpts configures an Ancestry query: a first-parent walk starting from a specific check-in.

type MergeConflict

type MergeConflict struct {
	Name      string
	StartLine int
	EndLine   int
}

MergeConflict describes a conflict region in a file.

type MergeConflictError

type MergeConflictError struct {
	Files []string
}

MergeConflictError reports which files had unresolved merge conflicts. Files is sorted alphabetically for deterministic output.

func (*MergeConflictError) Error

func (e *MergeConflictError) Error() string

func (*MergeConflictError) Is

func (e *MergeConflictError) Is(target error) bool

type MergeResult

type MergeResult struct {
	Clean     bool
	Conflicts []MergeConflict
}

MergeResult describes the outcome of a merge.

type MockTransport

type MockTransport struct {
	Handler func(req []byte) []byte
}

MockTransport is a test double that delegates to a handler function.

func (*MockTransport) RoundTrip

func (t *MockTransport) RoundTrip(_ context.Context, payload []byte) ([]byte, error)

RoundTrip calls the Handler function if set, otherwise returns empty bytes.

type OriginNamer added in v0.16.2

type OriginNamer interface {
	Transport
	SyncOrigin() string
}

OriginNamer is an optional interface a Transport may also implement to name the peer it addresses. Sync and Clone keep the horizon cursor of draft-fossil-horizon-00 §6.2.6 per origin under that name: "A client that converged records the cursor of the last reply together with the count of its own artifacts at the end of the exchange, per origin", and "A client holding a cursor for the origin it addresses sends it on every request, and MAY then announce nothing with igot on a pull-only request."

The name must identify the same peer across sessions and must carry no credential, since it is written into the repository's config table; the HTTP transport uses its URL with any password removed. A Transport that does not implement it, or returns "", keeps no cursor, and each of its pulls announces the client's whole holding with igot, which §6.2.6 allows.

type PullOpts

type PullOpts struct {
	// ProjectCode optionally pins the expected server project code. Empty
	// accepts whatever the peer advertises (matches existing Sync semantics).
	ProjectCode string

	// MaxSend caps the bytes the client will send per round (mostly clones
	// of clients with UV files). Zero leaves the existing default in place.
	MaxSend int

	// Observer receives sync-progress events. nil disables observation.
	Observer SyncObserver
}

PullOpts configures a pull-only sync. Fields are a subset of SyncOpts; Pull is hard-coded true and Push is hard-coded false to keep the API surface honest about what Pull does.

type RC

type RC int
const (
	RCOK               RC = 0
	RCError            RC = 100
	RCNYI              RC = 101
	RCOOM              RC = 102
	RCMisuse           RC = 103
	RCRange            RC = 104
	RCAccess           RC = 105
	RCIO               RC = 106
	RCNotFound         RC = 107
	RCAlreadyExists    RC = 108
	RCConsistency      RC = 109
	RCRepoNeedsRebuild RC = 110
	RCNotARepo         RC = 111
	RCRepoVersion      RC = 112
	RCDB               RC = 113
	RCBreak            RC = 114
	RCStepRow          RC = 115
	RCStepDone         RC = 116
	RCStepError        RC = 117
	RCType             RC = 118
	RCNotACkout        RC = 119
	RCRepoMismatch     RC = 120
	RCChecksumMismatch RC = 121
	RCLocked           RC = 122
	RCConflict         RC = 123
	RCSizeMismatch     RC = 124
	RCPhantom          RC = 125
	RCUnsupported      RC = 126
)

func (RC) String

func (rc RC) String() string

type RefusedError added in v0.17.0

type RefusedError struct {
	Message string
}

RefusedError is the error HandleSyncWithOpts returns, beside the reply, when HandleOpts.MaxStoredBytes refused the request. Message is the text of the reply's one error card.

func (*RefusedError) Error added in v0.17.0

func (e *RefusedError) Error() string

Error returns Message.

type Repo

type Repo struct {
	// contains filtered or unexported fields
}

Repo is an opaque handle to a Fossil repository.

func Create

func Create(path string, opts CreateOpts) (*Repo, error)

Create creates a new Fossil repository at the given path.

func Open

func Open(path string) (*Repo, error)

Open opens an existing Fossil repository.

func (*Repo) Ancestry

func (r *Repo) Ancestry(opts LogOpts) ([]LogEntry, error)

Ancestry walks the primary-parent chain starting from opts.Start: it emits that check-in, follows plink where isprim=1 to its parent, and repeats until the chain ends or opts.Limit is reached. This only ever sees first-parent ancestors of opts.Start — a merge's second parent, a sibling branch head, or any check-in outside that one chain will never appear. Use Timeline for a repository-wide view.

func (*Repo) Annotate

func (r *Repo) Annotate(opts AnnotateOpts) ([]AnnotatedLine, error)

Annotate attributes each line of a file to the commit that last changed it.

On a store whose cone has a horizon, lines the walk cannot attribute past the horizon are reported as originating at it, marked BelowHorizon; AnnotateContext fetches the history that attributes them on a content horizon store.

func (*Repo) AnnotateContext added in v0.17.0

func (r *Repo) AnnotateContext(
	ctx context.Context, opts AnnotateOpts, required RequiredContentOpts,
) ([]AnnotatedLine, error)

AnnotateContext is Annotate with a demand fetch: on a content-horizon store, each version of the file the walk reads below the horizon and the store does not hold is fetched from Peer as the walk reaches it, so only what the walk reads is fetched and lines are attributed to the check-ins below the horizon that added them. A walk needing more than one demand fetch's 200 payloads stops there and returns what it attributed, the rest marked BelowHorizon, as does a walk that crosses a structural horizon, since naming those check-ins is a deepen. A start check-in below the horizon is fetched as ReadFileContext fetches it.

func (*Repo) AttachmentAdd added in v0.17.0

func (r *Repo) AttachmentAdd(target, name string, content []byte, opts AttachmentOpts) (artifact string, err error)

AttachmentAdd attaches content to target under name, as `fossil attachment add` does, and returns the hash of the control artifact. content is stored as one ordinary blob; only name's final path component is kept. The attachment table and timeline reflect it when AttachmentAdd returns, and both artifacts are queued to sync. The attachment becomes the latest for name: a zero opts.Time stamps it after whatever is latest now, and an explicit one no later than that is refused.

target is a wiki page's exact name, or a ticket's or tech note's id or a unique prefix of it. Fossil is told the kind; here it is inferred, and a name more than one kind answers to is refused as ambiguous.

Content that is a well-formed external-attachment stub is refused, since it would read back as an external attachment rather than as the bytes given: use AttachmentAddExternal. Content that parses as a fossil artifact is compressed and its name gains ".gz", as fossil does.

func (*Repo) AttachmentAddExternal added in v0.17.0

func (r *Repo) AttachmentAddExternal(target string, ref ExternalRef, opts AttachmentOpts) (artifact string, err error)

AttachmentAddExternal attaches the file ref names without its bytes, and returns the hash of the control artifact. The blob stored is the stub Quarry writes, and the control artifact's N card carries ref.Type, so stock fossil shows a small text file under ref.Name. The host stores the bytes; this records only where they are found. target resolves as in AttachmentAdd.

func (*Repo) AttachmentDelete added in v0.17.0

func (r *Repo) AttachmentDelete(target, name string, opts AttachmentOpts) (artifact string, err error)

AttachmentDelete removes the current attachment name from target, as fossil's attachment page does: a new control artifact whose A card names no file. The bytes stay in history. It returns the artifact's hash, and ErrAttachmentNotFound when target has no current attachment by that name. opts.Time, when set, must be later than the attachment's; when zero, the deletion is stamped after it even if it lies in the future.

func (*Repo) AttachmentRead added in v0.17.0

func (r *Repo) AttachmentRead(target, name string) (a Attachment, content []byte, err error)

AttachmentRead returns target's current attachment name and its bytes. For an external attachment the bytes are not here: content is nil and a.External says where the host keeps them. It returns ErrAttachmentNotFound when there is no such current attachment.

func (*Repo) Attachments added in v0.17.0

func (r *Repo) Attachments(target string) ([]Attachment, error)

Attachments returns target's current attachments, the most recently attached first: one per name, leaving out deleted ones, as fossil lists them on the target's page. target resolves as in AttachmentAdd.

func (*Repo) BranchOpenLeaf added in v0.12.0

func (r *Repo) BranchOpenLeaf(name string) (rid int64, open bool, err error)

BranchOpenLeaf names one open leaf of the named branch (repo-state-00 Section 9): a check-in whose active branch tag is name, that is a leaf and that is not closed. When the branch has several, the one with the greatest event.mtime is returned, as the draft requires of any report that names a single open leaf. open is false, with a nil error, when the branch has no open leaf: it is not open. An empty name is an error, as in BranchTip; the main branch is named by CurrentTrunk and MainBranch.

Unlike BranchTip, which returns the branch's newest check-in whether or not it is a leaf or closed, this is fossil's `branch info` answer. fossil's query (branch_is_open, src/branch.c) takes whichever open leaf it meets first; this follows the draft's greatest-mtime rule.

func (*Repo) BranchTip

func (r *Repo) BranchTip(name string) (int64, error)

BranchTip returns the RID of the most recent checkin on the named branch. Resolves via the 'branch' propagating tag: the tip is the checkin with the latest event.mtime whose tagxref still has that branch value active. Returns an error if no such branch exists in the repository.

func (*Repo) Checkpoint

func (r *Repo) Checkpoint(mode CheckpointMode) error

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 (*Repo) Close

func (r *Repo) Close() error

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 (*Repo) Commit

func (r *Repo) Commit(opts CommitOpts) (int64, string, error)

Commit creates a new checkin manifest with the given files and returns the RID (row ID) and UUID of the newly created artifact. When ParentID is non-zero, files tracked at the parent but absent from opts.Files are carried forward into the new manifest (full-tree semantics — see the CommitOpts.Files doc).

func (*Repo) CommitContext added in v0.14.0

func (r *Repo) CommitContext(
	ctx context.Context, opts CommitOpts, required RequiredContentOpts,
) (int64, string, error)

CommitContext creates a commit, recovering required parent structure from Peer when necessary. Recovery runs without a write transaction and never broadens the store cone. The operation is retried once from the caller's original inputs after revalidating immutable parents and construction policy.

func (*Repo) CompactStore added in v0.14.0

func (r *Repo) CompactStore(ctx context.Context) (int, error)

CompactStore is the narrow-then-compact deletion (§5.4), the only one the sparse draft defines: it turns held blobs that only out-of-cone F cards name into elided phantoms and returns how many it dropped. Structural artifacts, sub-manifest nodes whose cards prove an elision, unsent or private content and the delta bases of retained artifacts stay held. A later widening fetches the dropped blobs again; it is not reversible locally.

func (*Repo) Config

func (r *Repo) Config(key string) (string, error)

Config reads a configuration value from the repo's config table.

func (*Repo) CreateCheckout

func (r *Repo) CreateCheckout(dir string, opts CheckoutCreateOpts) (*Checkout, error)

CreateCheckout creates a new checkout directory linked to this repository. The directory is created if it does not exist. The checkout is initialized to the tip checkin.

func (*Repo) CreateUser

func (r *Repo) CreateUser(opts UserOpts) error

CreateUser creates a new user in the repository.

func (*Repo) CurrentTrunk added in v0.12.0

func (r *Repo) CurrentTrunk() (int64, error)

CurrentTrunk returns the current trunk (repo-state-00 Section 9): the check-in that the main-branch setting's name resolves to by ResolveVersion's procedure, "trunk" when the setting is unset. Only check-ins can answer, as in fossil's check-in request, so a technote tagged with the name does not. The setting is local and not synced, so two repositories holding the same artifacts can name different trunks. fossil resolves it the same way where it needs one: update outside a checkout (src/update.c, a "ci" request) and open with no version (src/db.c). A name that resolves to nothing returns ErrVersionNotFound (wrapped).

func (*Repo) DB

func (r *Repo) DB() *db.DB

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 (*Repo) DeepenHorizon added in v0.15.0

func (r *Repo) DeepenHorizon(
	ctx context.Context, target string, required RequiredContentOpts,
) (*SyncResult, error)

DeepenHorizon moves the store cone's horizon to an ancestor C' of its C from which target is reachable, and synchronizes at C' through Peer (draft-fossil-horizon-00 §5.8): target itself when it is C's ancestor, else a common ancestor of the two, asked of the origin when the store cannot see one. The rule, the depth and the path members stay; nothing held is replaced. A structural store discards the seed for C before it takes the one for C', and a transfer that fails puts both back.

target is a full check-in hash, which may name a check-in the store does not hold, or any name ResolveVersion resolves. Deepening needs a Peer and a store cone with a horizon.

func (*Repo) DeleteUser

func (r *Repo) DeleteUser(login string) error

DeleteUser removes a user from the repository.

func (*Repo) DetectForks

func (r *Repo) DetectForks() ([]Fork, error)

DetectForks finds divergent branches in the repository.

func (*Repo) Diff

func (r *Repo) Diff(ridA, ridB int64, filePath string) ([]DiffEntry, error)

Diff returns the unified diff(s) between ridA and ridB.

When filePath is non-empty, returns 0 or 1 entries for that single file: the file is treated as empty bytes on any side where it is absent, so additions and deletions render as pure insert/delete hunks. An empty slice is returned when both sides are byte-identical.

When filePath is empty, returns one entry per file that changed between the two checkins (the union of files across both sides where the content UUID differs or the file exists on only one side). Entries are sorted by Name for deterministic ordering. An empty slice is returned when the two checkins have identical file sets and content.

Whole-checkin enumeration is currently name-keyed: a rename with no content change surfaces as a delete of the old name plus an add of the new name, and permission-only changes are not reflected. Proper rename and perm-change detection (via the underlying mlink table) is tracked as a follow-up; per-file diff behaviour for an explicitly named file is unchanged.

func (*Repo) DiffContext added in v0.17.0

func (r *Repo) DiffContext(
	ctx context.Context, ridA, ridB int64, filePath string, required RequiredContentOpts,
) ([]DiffEntry, error)

DiffContext is Diff with ReadFileContext's demand fetch: what both sides lack below the horizon is fetched in one round.

func (*Repo) DisableSubmanifests added in v0.14.0

func (r *Repo) DisableSubmanifests() error

DisableSubmanifests turns tree manifest emission off: later commits are flat, and the pinned k is kept for a later EnableSubmanifests. Existing trees remain -- artifact names are immutable, so they cannot be retired -- and keep being served, though peers that do not announce sub-manifest support are still refused them. Unlike the CLI's disable, it returns no note saying so; an embedder that wants to tell its operator must do it itself.

func (*Repo) EnableSubmanifests added in v0.14.0

func (r *Repo) EnableSubmanifests(k int) (pinned int, warning string, err error)

EnableSubmanifests turns on tree manifest emission (draft-fossil-submanifests-00 §8.1): from the next commit, check-ins carry their file sets as sub-manifest trees. k is the partition parameter, 1 to 12, or 0 to select one. A valid pinned k is kept, and an explicit k that differs from it is refused: changing it is RetuneSubmanifests. A stored k outside 1..12 is no valid pin: an explicit k replaces it, and k = 0 is refused, naming the stored value. With no stored k, an explicit k is pinned, or one is selected as zit selects it: the §6.3 cost over one check-in's file set, refined by replaying recent history. The check-in analyzed is the current trunk (CurrentTrunk, the main-branch tip, which the next commit most plausibly descends from); when no check-in is on the main branch, it is the newest check-in by time, the highest rid breaking a tie. A request that cannot be met -- k outside 1..12, no check-in at all to select from, or a file set no k partitions -- changes neither setting. It returns the pinned k and the warning the operator must be shown: peers that do not announce sub-manifest support, every fossil among them, are refused trees, and trees cannot be retired.

func (*Repo) FindCommonAncestor

func (r *Repo) FindCommonAncestor(ridA, ridB int64) (int64, error)

FindCommonAncestor finds the most recent common ancestor of two checkins, the merge base fossil's merge-base command names.

func (*Repo) GetUser

func (r *Repo) GetUser(login string) (User, error)

GetUser returns information about a user.

func (*Repo) HandleSync

func (r *Repo) HandleSync(ctx context.Context, payload []byte) ([]byte, error)

HandleSync processes an incoming xfer request (server-side). The payload is a raw xfer-encoded byte slice; the response is also raw bytes.

func (*Repo) HandleSyncWithOpts

func (r *Repo) HandleSyncWithOpts(ctx context.Context, payload []byte, opts HandleOpts) ([]byte, error)

HandleSyncWithOpts processes an incoming xfer request with optional configuration.

When opts.MaxStoredBytes refuses the request, it returns both the encoded reply, which holds only the error card naming the artifact, and a *RefusedError carrying that card's text (match it with errors.As). The request was rolled back, so nothing from it is stored. A host serving the reply over HTTP sends it as usual, and the client prints the error; a host whose storage aborts the whole call on any rollback can report RefusedError.Message itself. Every other error returns a nil reply.

func (*Repo) HorizonCost added in v0.15.0

func (r *Repo) HorizonCost(checkin string) ([]HorizonRuleCost, error)

HorizonCost reports, for each rule in order (descendants, leaves), what a horizon at checkin would hold, so the choice of rule is made with its cost in view (§3.4). checkin is any name ResolveVersion accepts. The figures are read from this repository, which must hold the history: a blob it does not hold is left out of the byte counts, and a sub-manifest it lacks is an error.

func (*Repo) Inner

func (r *Repo) Inner() *repo.Repo

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 (*Repo) ListConflictForks

func (r *Repo) ListConflictForks() ([]string, error)

ListConflictForks returns filenames with unresolved conflict-fork entries.

func (*Repo) ListFiles

func (r *Repo) ListFiles(rid int64) ([]FileEntry, error)

ListFiles returns the files in a manifest identified by blob row-id.

func (*Repo) ListFilesIn added in v0.16.2

func (r *Repo) ListFilesIn(rid int64, c *Cone) ([]FileEntry, error)

ListFilesIn is ListFiles narrowed to the files c covers; a nil cone lists every file. The cone is applied as a range predicate at the one enumeration seam every file set comes from (draft-fossil-sparse-cone-00 §4.1), so the result is ListFiles filtered by c.Covers, flat or tree, and a cone's horizon plays no part. On a tree manifest the walk skips every sub-manifest whose key range c cannot cover, so the cost follows the cone plus the spine rather than the whole tree (§4.5). Over a sparse store that makes it the listing that does not reach an elided out-of-cone node; a cone that reaches a node the store lacks still fails, naming it.

func (*Repo) ListUsers

func (r *Repo) ListUsers() ([]User, error)

ListUsers returns all users in the repository.

func (*Repo) Merge

func (r *Repo) Merge(srcBranch, dstBranch, message, user string) (int64, string, error)

Merge performs a three-way merge of srcBranch into dstBranch and creates a merge commit whose primary parent is dstBranch's tip and whose secondary parent is srcBranch's tip. Returns (rid, uuid) of the new commit on success.

Conflict policy: any unresolved conflict in any file aborts the whole operation with a *MergeConflictError — no commit is written. Callers should check errors.Is(err, ErrMergeConflict) to detect this case.

File handling:

  • Present on both sides: three-way merge against the common ancestor.
  • Present on only one side (new file): kept as-is.
  • In ancestor, missing on one side, unchanged on the other: agreed deletion.
  • In ancestor, missing on one side, modified on the other: modify/delete conflict.

Files are matched across the three versions following renames, as fossil's merge matches them: a file srcBranch renamed and dstBranch did not takes srcBranch's name, and the commit records the rename; a file dstBranch renamed keeps its name.

func (*Repo) OpenCheckout

func (r *Repo) OpenCheckout(dir string, opts CheckoutOpenOpts) (*Checkout, error)

OpenCheckout opens an existing checkout directory linked to this repository.

func (*Repo) Path

func (r *Repo) Path() string

Path returns the filesystem path to the repository file.

func (*Repo) Pull

func (r *Repo) Pull(ctx context.Context, url string, opts PullOpts) (*SyncResult, error)

Pull fetches commits and ancillary objects from a Fossil HTTP peer and applies them to this repo. It is a strict pull — nothing is sent.

Tiger Style: hostile inputs panic via assert at the boundary; transport failures return wrapped errors. Idempotent on a repo already at peer's tip (returns a SyncResult with Rounds=0–1 and FilesRecvd=0).

func (*Repo) ReadBlob added in v0.16.2

func (r *Repo) ReadBlob(uuid string) ([]byte, error)

ReadBlob returns the content of the artifact named uuid, a full SHA1 or SHA3-256 hash in lowercase hex, such as the UUID ListFiles reports for a file. An unknown hash returns ErrArtifactNotFound (wrapped). An artifact the store knows but does not hold, such as one elided below a horizon or outside a sparse cone, fails as ReadFile of a path naming it does.

func (*Repo) ReadFile

func (r *Repo) ReadFile(rid int64, filePath string) ([]byte, error)

ReadFile returns the bytes of filePath as they existed in checkin rid. Returns ErrFileNotFound (wrapped) if the file is not tracked in that checkin. A file that exists but is empty returns ([]byte{}, nil).

func (*Repo) ReadFileAt

func (r *Repo) ReadFileAt(version string, filePath string) ([]byte, error)

ReadFileAt reads filePath from the checkin identified by a symbolic version name (e.g. "tip", "trunk", a branch name, a UUID, or a UUID prefix). It calls ResolveVersion to obtain the RID, then delegates to ReadFile. Use ReadFile directly when you already have a numeric RID.

func (*Repo) ReadFileAtContext added in v0.17.0

func (r *Repo) ReadFileAtContext(
	ctx context.Context, version string, filePath string, required RequiredContentOpts,
) ([]byte, error)

ReadFileAtContext is ReadFileAt with ReadFileContext's demand fetch. The version is resolved locally; a structural store resolves a check-in below its horizon by the full hash its phantom carries.

func (*Repo) ReadFileContext added in v0.17.0

func (r *Repo) ReadFileContext(
	ctx context.Context, rid int64, filePath string, required RequiredContentOpts,
) ([]byte, error)

ReadFileContext is ReadFile that, when the check-in's file lies below the store cone's horizon and the store does not hold it, fetches exactly the artifacts the read needs from Peer and reads again: the payload, and for a structural store first the check-in's manifest, baseline and nodes. This is the targeted demand fetch of draft-fossil-horizon-00 §4.4: the store cone and its horizon do not move, and what is fetched is held content a later CompactStore may drop. Without a Peer the read fails as ReadFile does, matching ErrBelowHorizon and naming the horizon. A read needing more than one demand fetch carries is refused; DeepenHorizon is its remedy.

func (*Repo) Redo

func (r *Repo) Redo(dir string) error

Redo re-applies the last undone operation. Requires a checkout database; not yet wired.

func (*Repo) ResolveBranchStart added in v0.12.0

func (r *Repo) ResolveBranchStart(name string) (int64, error)

ResolveBranchStart resolves name as ResolveVersion does, then returns the first check-in of the branch the result is on: fossil's branch-type ("br") request (repo-state-00 Section 8.3), the start of the branch rather than the check-in its name most recently points at. As Section 8.3 requires, the request is rewritten to a check-in request first: only check-ins can match, so a technote tagged with the branch name does not shadow the branch.

Section 8.3 walks back from the result of every form. fossil(1) walks only from a "tag:NAME" or plain-name result (symbolic_name_to_rid, src/name.c), so there a hash, "tip" or a date names the check-in itself; this follows the draft.

func (*Repo) ResolveConflictFork

func (r *Repo) ResolveConflictFork(filename string) error

ResolveConflictFork marks a conflict-fork entry as resolved.

func (*Repo) ResolveVersion

func (r *Repo) ResolveVersion(name string) (int64, error)

ResolveVersion resolves a symbolic version name to a repository artifact RID.

It follows fossil's symbolic_name_to_rid (src/name.c) for the forms go-libfossil supports, in fossil's order:

  1. "tip" — newest check-in by event.mtime. "" is treated as "tip".
  2. "rid:N" — the literal RID N, when that artifact exists.
  3. "tag:NAME" — the check-in carrying sym-NAME with the greatest event.mtime (forces a tag lookup even for a hex NAME).
  4. "root:BR" / "start:BR" / "merge-in:BR" — the origin, first check-in, or most recent merge-in of branch BR (BR itself resolved recursively).
  5. "NAME:TIMESTAMP" — the check-in carrying sym-NAME with the greatest event.mtime at or before TIMESTAMP (UTC).
  6. Artifact hash or 4–64 char hex prefix — unique match against blob.uuid, tried before a plain tag; more than one match is ambiguous.
  7. Plain symbolic name — the check-in carrying sym-NAME with the greatest event.mtime (resolves "trunk" and branch names).
  8. Trailing-punctuation retry — a name pasted from prose that ends in one or two punctuation characters is retried without them.

No match returns ErrVersionNotFound (wrapped); a hex prefix matching more than one artifact returns ErrAmbiguousVersion (wrapped).

The names relative to an open checkout ("current", "prev", "next") are ordinary names here, as in fossil outside a checkout; Checkout's ResolveVersion resolves them.

func (*Repo) RetuneSubmanifests added in v0.14.0

func (r *Repo) RetuneSubmanifests(k int) error

RetuneSubmanifests pins a new partition parameter k, 1 to 12, for the commits that follow (draft-fossil-submanifests-00 §6.4). It is forward only: existing check-ins are unchanged, and the next tree shares only the sub-manifests whose bytes are the same under both values.

func (*Repo) ServeHTTP

func (r *Repo) ServeHTTP(ctx context.Context, addr string) error

ServeHTTP starts an HTTP server that accepts Fossil xfer requests. Blocks until ctx is cancelled.

Requests are authorized against the user table: one without a login card gets nobody's capabilities, which in a new repository allow clone and pull but not push. Grant more with SetCaps. Like XferHandler it serves with default HandleOpts, so no HandleOpts.MaxStoredBytes budget applies.

func (*Repo) SetCaps

func (r *Repo) SetCaps(login, caps string) error

SetCaps updates a user's capability string.

func (*Repo) SetConfig

func (r *Repo) SetConfig(key, value string) error

SetConfig writes a configuration value to the repo's config table. A SettingHorizonSeedKey value that is neither an SSH public key nor an OpenPGP fingerprint is refused.

func (*Repo) SetContentCache added in v0.16.2

func (r *Repo) SetContentCache(bytes int64)

SetContentCache attaches a cache of expanded artifact content, bounded by bytes, that ReadFile, ReadFileAt, ReadBlob, ListFiles, ListFilesIn, Diff and Annotate share. It replaces any cache already attached; bytes <= 0 detaches it. The default is no cache. It is safe to call while other goroutines read.

The bound covers expanded content; the parses of the few check-in manifests read most recently are kept beside it. Any write through this Repo empties the cache. A write by another process, or through another Repo opened on the same file, does not: attach a cache only where this Repo is the store's one writer, or where no other writer purges, compacts or narrows it.

func (*Repo) SetHashPolicy added in v0.12.0

func (r *Repo) SetHashPolicy(name string) error

SetHashPolicy sets the repository's hash policy by name, as `fossil hash-policy NEW-POLICY` does. name must be exactly one of sha1, auto, sha3, sha3-only or shun-sha1: the match is case-sensitive, and any other string is an error that leaves the policy unchanged. Asking for auto in a repository that already holds a SHA3-named artifact sets sha3.

func (*Repo) SetPassword

func (r *Repo) SetPassword(login, password string) error

SetPassword updates a user's password.

func (*Repo) SetStoreCone added in v0.14.0

func (r *Repo) SetStoreCone(c *Cone) error

SetStoreCone replaces the store cone; nil makes the store dense. It moves no content. Narrowing deletes nothing (§5.4). Widening makes the newly covered elided phantoms wanted again, and the next pull fetches them. While a cone is set, a commit carries no R card (§4.3).

A cone may carry a horizon (draft-fossil-horizon-00): setting one elides blobs only check-ins below it name, and SetStoreCone moves no content, as for any narrowing. Setting an older check-in, or nil, widens, and SetStoreConeContext fetches what the deeper horizon keeps.

func (*Repo) SetStoreConeContext added in v0.14.0

func (r *Repo) SetStoreConeContext(
	ctx context.Context, next *Cone, required RequiredContentOpts,
) (*SyncResult, error)

SetStoreConeContext is the policy form of demand fetch (draft-fossil-sparse-cone-00 §6.4): it replaces the store cone and, when that makes elided artifacts wanted again, pulls them from Peer through an ordinary cone-scoped synchronization. With artifacts to fetch and no Peer it refuses, naming the elided count and the missing peer, and leaves the cone unchanged. A transfer that fails after the cone is replaced keeps the wider policy, so the next ordinary pull heals it. Narrowing needs no peer.

func (*Repo) StashApply

func (r *Repo) StashApply(dir string, id int64) error

StashApply restores a stash entry by ID without removing it.

func (*Repo) StashClear

func (r *Repo) StashClear() error

StashClear removes all stash entries.

func (*Repo) StashDrop

func (r *Repo) StashDrop(id int64) error

StashDrop removes a stash entry by ID.

func (*Repo) StashList

func (r *Repo) StashList() ([]StashEntry, error)

StashList returns all stash entries.

func (*Repo) StashPop

func (r *Repo) StashPop(dir string) error

StashPop restores the most recent stash entry and removes it.

func (*Repo) StashSave

func (r *Repo) StashSave(dir, comment string) error

StashSave saves working-tree changes to the stash. Requires a checkout database; not yet wired (Repo only wraps the repo DB).

func (*Repo) StoreCone added in v0.14.0

func (r *Repo) StoreCone() (*Cone, error)

StoreCone returns the repository's store cone, or nil when the store is dense. A store cone (draft-fossil-sparse-cone-00 §5) is local policy: an artifact the cone leaves out may be deliberately absent, an elided phantom, which synchronization does not request and verification counts apart from damage. A cone this version cannot read is lost policy and reads as nil, so the store heals toward dense.

func (*Repo) Sync

func (r *Repo) Sync(ctx context.Context, t Transport, opts SyncOpts) (*SyncResult, error)

Sync runs a sync session against the given transport.

func (*Repo) Tag

func (r *Repo) Tag(opts TagOpts) (int64, error)

Tag creates a control artifact that adds a tag to a target artifact. Returns the UUID of the tag control artifact.

As `fossil tag add` does, a name with a reserved prefix ("wiki-", "tkt-", "event-") is refused, and when the target is a check-in the name is placed in the symbolic namespace with a "sym-" prefix so it resolves as a tag in commands such as update and merge; other artifact types keep the name bare. Pass the raw name: fossil prefixes the raw name, so "x" becomes "sym-x" and "sym-x" becomes "sym-sym-x" on a check-in.

func (*Repo) TicketAdd added in v0.17.0

func (r *Repo) TicketAdd(opts TicketOpts) (ticketUUID, artifact string, err error)

TicketAdd creates a ticket, as `fossil ticket add` does, and returns its new id and the hash of the artifact that created it. The ticket table reflects it when TicketAdd returns, and the artifact is queued to sync.

func (*Repo) TicketChanges added in v0.17.0

func (r *Repo) TicketChanges(ticket string) ([]TicketChange, error)

TicketChanges returns the changes of the ticket whose id is or starts with ticket, oldest first: the order fossil applies them in, as `fossil ticket history` lists them.

func (*Repo) TicketList added in v0.17.0

func (r *Repo) TicketList() ([]Ticket, error)

TicketList returns every ticket, the most recently changed first.

func (*Repo) TicketSet added in v0.17.0

func (r *Repo) TicketSet(ticket string, opts TicketOpts) (artifact string, err error)

TicketSet changes the ticket whose id is or starts with ticket, as `fossil ticket set` does, and returns the hash of the change artifact.

func (*Repo) Timeline

func (r *Repo) Timeline(opts TimelineOpts) ([]TimelineEntry, error)

Timeline enumerates the repository's events newest-first: every row of the event table by default, or just the rows matching opts.Type when set (canonical `fossil timeline`'s -t/--type default: no filter unless one is given). Unlike Ancestry, this does not start from or require any particular check-in — it is a repository-wide view, not a walk.

Ordering is (mtime DESC, rid DESC), a total order with rid as a true tie-break at exact mtime equality — a deliberate improvement over canonical fossil, which orders by mtime DESC alone with no tie-break, and paginates with a bare-timestamp web cursor carrying a one-second slop, so rows at a page boundary there can repeat or be skipped. Do not "fix" this back to canonical: it is intentional. To page through the full result set, pass the last entry's Cursor back as the next call's TimelineOpts.After — never construct a cursor from a TimelineEntry's Time by hand; see Cursor's doc comment for why that round trip is lossy.

func (*Repo) TimelineSince added in v0.17.0

func (r *Repo) TimelineSince(hash string, kinds ...EventKind) ([]TimelineEntry, error)

TimelineSince returns the timeline entries whose artifacts arrived in this repository after the artifact with full hash hash: stored by a later receipt (a later push, pull or local write), or later within the same one. kinds, when given, keeps only entries of those kinds. The entries are in Timeline's order, newest first; an empty result is an empty slice, not nil. A hash the repository does not hold is an error.

Arrival, not timestamp, is what "after" means, because the question this answers is what a push brought in: an artifact made on a machine whose clock runs behind the given artifact's still arrived after it. Arrival order is this repository's own, so two clones can answer differently.

func (*Repo) UUIDFromRID

func (r *Repo) UUIDFromRID(rid int64) (string, error)

UUIDFromRID returns the UUID (manifest hash) of the artifact identified by rid. The UUID is the stable, content-addressed identifier for the artifact; the rid is a repository-local integer that may differ across clones.

Returns ErrArtifactNotFound (wrapped) if no artifact with the given rid exists in the repository. The wrapped error message includes the offending rid. Other errors surface as-is.

func (*Repo) UVDelete

func (r *Repo) UVDelete(name string, mtime time.Time) error

UVDelete marks an unversioned file as deleted (tombstone).

func (*Repo) UVList

func (r *Repo) UVList() ([]UVEntry, error)

UVList returns all unversioned file entries.

func (*Repo) UVRead

func (r *Repo) UVRead(name string) ([]byte, int64, string, error)

UVRead reads an unversioned file from the repository. Returns the content, mtime (unix seconds), and content hash.

func (*Repo) UVWrite

func (r *Repo) UVWrite(name string, content []byte, mtime time.Time) error

UVWrite writes an unversioned file to the repository.

func (*Repo) Undo

func (r *Repo) Undo(dir string) error

Undo reverts the last commit or merge. Requires a checkout database; not yet wired.

func (*Repo) Verify

func (r *Repo) Verify() error

Verify checks repository integrity (blob checksums, delta chains).

func (*Repo) VerifySeed added in v0.15.0

func (r *Repo) VerifySeed(ctx context.Context, required RequiredContentOpts) (*SeedVerification, error)

VerifySeed verifies a structural store's seed by deepening (draft-fossil-horizon-00 §5.9): it fetches every manifest below the horizon from Peer, so the store holds the real tag artifacts and primary-parent chains, discards the seed, and compares what the store now derives at each entry with what the seed asserted. The price is that history, and the store stays a content-horizon store at the same C, which holds no seed; a failed transfer puts the structural cone and seed back.

func (*Repo) WithTx

func (r *Repo) WithTx(fn func(tx *db.Tx) error) error

WithTx executes fn within a database transaction.

func (*Repo) XferHandler

func (r *Repo) XferHandler() http.HandlerFunc

XferHandler returns an http.HandlerFunc that decodes Fossil xfer requests, dispatches to HandleSync, and encodes the response. Use this to compose a custom mux alongside operational endpoints (e.g., /healthz). It serves with default HandleOpts, so no HandleOpts.MaxStoredBytes budget applies.

type RequiredContentOpts added in v0.14.0

type RequiredContentOpts struct {
	Peer Transport
	Sync SyncOpts
}

RequiredContentOpts authorizes read-only recovery from an explicit peer. Neither the peer nor credentials are saved. A nil Peer keeps the operation local. Sync accepts authentication, project/server identity, Pull and Private; push, unversioned, extension-table and link-sharing options are refused. Existing context-free operations never discover or contact a peer.

type RevertOpts

type RevertOpts struct {
	Files []string // empty = revert all
}

RevertOpts configures reverting file changes.

type RoundStats

type RoundStats struct {
	FilesSent, FilesRecvd, BytesSent, BytesRecvd, Gimmes, IGots int
}

RoundStats describes the outcome of a single sync round.

type ScanEnd

type ScanEnd struct {
	FilesScanned int
}

ScanEnd describes the completion of a working-tree scan.

type SeedMismatch added in v0.15.0

type SeedMismatch struct {
	Checkin, Tag, Seeded, Derived string
}

SeedMismatch is one tag on which a seed and the derivation disagree at a check-in. Seeded and Derived spell the tag as a T card does, sign then value ("*red", "+"), and are "" where it is absent.

type SeedVerification added in v0.15.0

type SeedVerification struct {
	Checked    int
	Mismatches []SeedMismatch
}

SeedVerification reports VerifySeed: how many of the seed's T cards were checked, and each tag at an entry of the held set where the seed and the derivation over real artifacts disagree.

type SessionEnd

type SessionEnd struct {
	Rounds, FilesSent, FilesRecvd int
}

SessionEnd describes the completion of a sync session.

type SessionStart

type SessionStart struct {
	ProjectCode    string
	Push, Pull, UV bool
}

SessionStart describes the beginning of a sync session.

type StashEntry

type StashEntry struct {
	ID      int64
	Comment string
	Time    string
}

StashEntry describes a saved stash.

type StatusEntry

type StatusEntry struct {
	Name   string
	Change string
}

StatusEntry describes a changed file in the working tree.

type SyncObserver

type SyncObserver interface {
	Started(info SessionStart)
	RoundStarted(round int)
	RoundCompleted(round int, stats RoundStats)
	Completed(info SessionEnd)
	Error(err error)
	HandleStarted(info HandleStart)
	HandleCompleted(info HandleEnd)
	TableSyncStarted(info TableSyncStart)
	TableSyncCompleted(info TableSyncEnd)
}

SyncObserver receives lifecycle callbacks during sync operations. Use NopSyncObserver() for a silent no-op, or StdoutSyncObserver() for stderr logging.

func NopSyncObserver

func NopSyncObserver() SyncObserver

NopSyncObserver returns a SyncObserver that silently discards all events.

func StdoutSyncObserver

func StdoutSyncObserver() SyncObserver

StdoutSyncObserver returns a SyncObserver that logs events to stderr.

type SyncOpts

type SyncOpts struct {
	Push        bool
	Pull        bool
	UV          bool
	ProjectCode string
	ServerCode  string
	User        string
	Password    string
	PeerID      string // identifies this leaf agent instance
	MaxSend     int
	XTableSync  bool // enable extension table sync (peer_registry, etc.)
	Private     bool // enable private artifact sync
	// ShareLinks is fossil's --share-links mode (§9.5): a pulling session
	// asks the server for the URLs of other copies of the repository and
	// keeps each valid one as config link:URL. Off by default.
	ShareLinks bool
	Observer   SyncObserver
	Buggify    BuggifyChecker
}

SyncOpts configures a sync operation.

type SyncResult

type SyncResult struct {
	Rounds       int
	FilesSent    int
	FilesRecvd   int
	UVFilesSent  int
	UVFilesRecvd int
	UVGimmesSent int
	BytesSent    int64
	BytesRecvd   int64
	Errors       []string
	// Elided counts the artifacts left absent under the store cone, and
	// ConeServed the replies whose peer acknowledged applying it (pragma
	// cone-served, draft-fossil-sparse-cone-00 §6.3); the rest of a sparse
	// store's rounds were served densely and filtered locally.
	Elided, ConeServed int
	// HorizonServed counts the replies whose peer served the store's
	// horizon (pragma horizon-served, draft-fossil-horizon-00 §6.2.5); the
	// other rounds were classified locally. StructuralServed counts those
	// served at the structural level, and HorizonFallback reports a
	// structural store that fell back to the content horizon for good (§6.3).
	HorizonServed    int
	StructuralServed int
	HorizonFallback  bool
	// HorizonHistoryURL is the interface outside the sync protocol at which
	// the origin says history below a horizon can be queried (pragma
	// horizon-served URL, draft-fossil-horizon-00 §6.2.5), the last a reply
	// named; "" when none did. An origin names it with
	// SettingHorizonHistoryURL.
	HorizonHistoryURL string
}

SyncResult describes the outcome of a sync session.

type TableSyncEnd

type TableSyncEnd struct {
	Table               string
	RowsSent, RowsRecvd int
}

TableSyncEnd describes the completion of a config table sync.

type TableSyncStart

type TableSyncStart struct {
	Table string
}

TableSyncStart describes the beginning of a config table sync.

type TagOpts

type TagOpts struct {
	Name     string
	TargetID int64
	Value    string
	User     string
	Time     time.Time
}

TagOpts configures a tag operation.

type TagSpec

type TagSpec struct {
	Name  string
	Value string
}

TagSpec describes a tag to attach to an artifact.

type Ticket added in v0.17.0

type Ticket struct {
	UUID   string `json:"uuid"`
	Status string `json:"status"`
	// Changed is the time of the ticket's latest change.
	Changed time.Time `json:"changed"`
	// Fields holds every ticket-table field that has a value.
	Fields map[string]string `json:"fields"`
}

Ticket is one ticket as the ticket table holds it after every change.

type TicketChange added in v0.17.0

type TicketChange struct {
	// Artifact is the change artifact's hash.
	Artifact string    `json:"artifact"`
	User     string    `json:"user"`
	Time     time.Time `json:"time"`
	// Comment is the remark the change added, or "".
	Comment string `json:"comment"`
	// Fields holds the change's fields exactly as written, the remark's
	// included: "+name" for an append.
	Fields map[string]string `json:"fields"`
}

TicketChange is one change artifact of a ticket.

type TicketOpts added in v0.17.0

type TicketOpts struct {
	// Fields maps a ticket field (a column of the repository's ticket
	// schema: title, status, type, resolution, comment, ...) to its new
	// value. A "+name" key appends the value to the field instead. A field
	// with an empty value is left out, as `fossil ticket` leaves it out.
	Fields map[string]string
	// User is the change's author, its U card.
	User string
	// Comment, when not empty, is a remark added with the change, stored as
	// the stock ticket forms store one: the icomment field, with login and
	// username set to User and mimetype text/plain.
	Comment string
	// Time is the change's D card; zero means now.
	Time time.Time
}

TicketOpts is one change to a ticket.

type TimelineEntry

type TimelineEntry struct {
	LogEntry
	Cursor Cursor
}

TimelineEntry represents a single event as returned by Timeline. It extends LogEntry with Cursor, the pagination token for this row: pass it back as the next call's TimelineOpts.After to resume enumeration immediately after this entry. Cursor is always valid (Cursor.Valid() == true) on every TimelineEntry Timeline produces.

TimelineEntry values should come from Timeline, not be hand-assembled. A TimelineEntry built by embedding a LogEntry from Ancestry carries a zero-value Cursor, which Timeline treats as "start from newest" rather than as an error.

type TimelineOpts

type TimelineOpts struct {
	// Type restricts the enumeration to a single event kind. The zero
	// value means "all kinds" — the canonical `fossil timeline` default.
	Type EventKind
	// After, when valid, resumes enumeration immediately following this
	// cursor — the next page after whatever TimelineEntry produced it. The
	// zero Cursor means "start from the newest event". See Repo.Timeline's
	// doc comment for the pagination contract this forms, and Cursor's doc
	// comment for why it must come from a TimelineEntry rather than be
	// built by hand.
	After Cursor
	// Limit caps the number of entries returned. Zero or negative means
	// unbounded.
	Limit int
}

TimelineOpts configures a Timeline query: a repository-wide enumeration of the event table.

type Transport

type Transport interface {
	RoundTrip(ctx context.Context, payload []byte) ([]byte, error)
}

Transport delivers sync payloads between peers. Implementations handle the network layer (HTTP, NATS, etc.). Payloads are opaque zlib-compressed xfer card streams.

func NewHTTPTransport

func NewHTTPTransport(url string, opts ...HTTPOption) Transport

NewHTTPTransport creates a Transport that speaks Fossil's HTTP /xfer protocol.

type TransportFunc

type TransportFunc func(ctx context.Context, payload []byte) ([]byte, error)

TransportFunc adapts a plain function to the Transport interface. This is the Transport equivalent of http.HandlerFunc.

func (TransportFunc) RoundTrip

func (f TransportFunc) RoundTrip(ctx context.Context, payload []byte) ([]byte, error)

RoundTrip calls the function.

type UVEntry

type UVEntry struct {
	Name  string
	Size  int64
	Mtime time.Time
	Hash  string
}

UVEntry describes an unversioned file.

type UndoResult added in v0.14.0

type UndoResult struct {
	FilesRestored []string // existing files given back their saved content
	FilesCreated  []string // files written that were not on disk
	FilesRemoved  []string // files deleted from the working tree
}

UndoResult reports the working files Undo or Redo changed, each list in the order they were changed, fossil's order. Fossil's undo prints them as UNDO (or REDO), NEW and DELETE lines; a caller shows them as it likes.

type UpdateChange

type UpdateChange string

UpdateChange classifies how a file changed.

const (
	ChangeAdded    UpdateChange = "added"
	ChangeModified UpdateChange = "modified"
	ChangeDeleted  UpdateChange = "deleted"
)

type UpdateOpts

type UpdateOpts struct {
	// TargetRID is the check-in to update to. 0 picks it as fossil's update
	// does with no version named: the newest open leaf descended from the
	// checkout on its branch. Update fails when several such leaves remain.
	TargetRID int64
}

UpdateOpts configures updating to a new version with merge.

type UpdateResult

type UpdateResult struct {
	FilesWritten []string // paths written (added, updated, or merged, clean or not); includes every Conflicted path
	FilesRemoved []string // paths deleted from the working tree
	Conflicted   []string // paths that now contain conflict markers — not an error; also present in FilesWritten
	Unmerged     []string // paths left to reconcile without markers — not an error
	// OutOfCone counts the changes a sparse checkout's update applied to files
	// outside its cone: recorded for the next checkin, never written to disk.
	OutOfCone int
}

UpdateResult reports what Update actually did. Paths, not counts: a caller needs to know which files to show a user, not merely how many changed. All three slices are sorted (sort.Strings) before Update returns, so the order is deterministic — safe for golden-file tests or reflect.DeepEqual — rather than depending on Go's randomized map iteration order.

Outcome mapping (Update's error return is the other half of this):

clean       - err == nil, Conflicted empty
conflicted  - err == nil, Conflicted non-empty
failed      - err != nil, UpdateResult is the zero value

A non-empty Conflicted means three-way merge could not resolve those files cleanly and wrote "<<<<<<<"-style conflict markers directly into them on disk. That is NOT an error — Update still returns a nil error, because the update itself succeeded and the working tree is usable; it just isn't clean. A caller that only checks the returned error gets today's pre-conflict-detection behavior. A caller that needs to warn a user about marker text in their files must check Conflicted. Every path in Conflicted also appears in FilesWritten: the marker text is what was written there.

Unmerged lists files left for the caller to reconcile that hold no markers: a file edited locally that the target deletes (kept on disk, no longer tracked), a file added both locally and by the target (the local file kept, so it shows as edited), a binary file both sides changed (the target's content written, the working copy saved as NAME-original), and a file edited locally that the target renamed without changing it (left under its old name, untracked; the new name shows as missing, as in fossil). Like Conflicted, it is not an error.

type User

type User struct {
	Login string
	Caps  string
}

User describes a Fossil user.

type UserOpts

type UserOpts struct {
	Login    string
	Password string
	Caps     string
}

UserOpts configures a user creation or update.

type WorkingVersion added in v0.12.0

type WorkingVersion struct {
	// RID is the check-in the name resolves to. When Working is set it is
	// the checkout's version, the check-in the working files started from.
	RID int64
	// Working reports that the name was "ckout": the request asks for the
	// files on disk, edits included, rather than for any stored check-in.
	Working bool
}

WorkingVersion is the answer of a checkout-inclusive request: a check-in, or the checkout's working files.

Directories

Path Synopsis
Package apitest holds go-libfossil's black-box tests of the root package.
Package apitest holds go-libfossil's black-box tests of the root package.
cmd
libfossil command
Package conformance checks go-libfossil against the Fossil Internet-Drafts in rfcs/, requirement by requirement.
Package conformance checks go-libfossil against the Fossil Internet-Drafts in rfcs/, requirement by requirement.
db
Package db provides a SQLite database layer with pluggable drivers.
Package db provides a SQLite database layer with pluggable drivers.
examples
embed-repo-api command
Example: embed libfossil as a library in a Go application.
Example: embed libfossil as a library in a Go application.
tinygo command
Example: the whole public API, sync included, built with TinyGo for the js/wasm target, as an application ships go-libfossil to a browser or an edge runtime.
Example: the whole public API, sync included, built with TinyGo for the js/wasm target, as an application ships go-libfossil to a browser or an edge runtime.
wasm command
Example: build libfossil for a generic WASI Preview 1 wasm target.
Example: build libfossil for a generic WASI Preview 1 wasm target.
internal
attachstub
Package attachstub reads and writes the stub Quarry stores in place of an attachment's bytes (Quarry RFC 0016, "The stub"): a few lines of plain text naming a file by its SHA-256, kept in an ordinary blob that an A card names as its source, while the bytes live in a bucket the host binds.
Package attachstub reads and writes the stub Quarry stores in place of an attachment's bytes (Quarry RFC 0016, "The stub"): a few lines of plain text naming a file by its SHA-256, kept in an ordinary blob that an A card names as its source, while the bytes live in a bucket the host binds.
bisect
Package bisect implements binary search through Fossil commit history.
Package bisect implements binary search through Fossil commit history.
blob
Package blob handles content-addressed blob storage in Fossil repository databases.
Package blob handles content-addressed blob storage in Fossil repository databases.
checkout
Package checkout provides working directory management for Fossil repositories.
Package checkout provides working directory management for Fossil repositories.
clearsign
Package clearsign signs artifacts and verifies their signatures, in the clear-signing envelopes of draft-fossil-artifact-format-00 §4.1.1: a PGP clear-signed message, or the SSH envelope fossil assembles around a detached ssh-keygen signature.
Package clearsign signs artifacts and verifies their signatures, in the clear-signing envelopes of draft-fossil-artifact-format-00 §4.1.1: a PGP clear-signed message, or the SSH envelope fossil assembles around a detached ssh-keygen signature.
clearsign/signtest
Package signtest makes throwaway signing keys for tests: an ssh-keygen key, or a gpg key in a private GNUPGHOME.
Package signtest makes throwaway signing keys for tests: an ssh-keygen key, or a gpg key in a private GNUPGHOME.
cone
Package cone is the cone specification of draft-fossil-sparse-cone-00 §3: a finite, normalized set of repository-relative path prefixes, each an inclusion or an exclusion, that decides which files a sparse checkout materializes and tracks.
Package cone is the cone specification of draft-fossil-sparse-cone-00 §3: a finite, normalized set of repository-relative path prefixes, each an inclusion or an exclusion, that decides which files a sparse checkout materializes and tracks.
content
Package content reconstructs full artifact content from Fossil's delta-chain storage.
Package content reconstructs full artifact content from Fossil's delta-chain storage.
diff
Package diff produces unified diff output from two byte slices using the Myers diff algorithm.
Package diff produces unified diff output from two byte slices using the Myers diff algorithm.
fsltype
Package fsltype defines shared types used across internal packages.
Package fsltype defines shared types used across internal packages.
horizon
Package horizon computes the held set of draft-fossil-horizon-00: the check-ins whose trees a horizon clone keeps the content of.
Package horizon computes the held set of draft-fossil-horizon-00: the check-ins whose trees a horizon clone keeps the content of.
horizon/seed
Package seed mints, holds and applies the seed of draft-fossil-horizon-00 §5.2: the control artifact an origin mints so that a structural-horizon clone, which lacks C's ancestry, derives the branch, tag and closed state of every check-in in the held set K exactly as a dense repository does.
Package seed mints, holds and applies the seed of draft-fossil-horizon-00 §5.2: the control artifact an origin mints so that a structural-horizon clone, which lacks C's ancestry, derives the branch, tag and closed state of every check-in in the held set K exactly as a dense repository does.
leaf
Package leaf maintains the leaf table, in one place so every writer of a branch tag -- crosslinking, a local commit, a tag control artifact -- and the explicit rebuild agree on what a leaf is and on when one is rechecked.
Package leaf maintains the leaf table, in one place so every writer of a branch tag -- crosslinking, a local commit, a tag control artifact -- and the explicit rebuild agree on what a leaf is and on when one is rechecked.
merge
Package merge provides three-way merge with pluggable strategies.
Package merge provides three-way merge with pluggable strategies.
repo
Package repo manages Fossil repository database files.
Package repo manages Fossil repository database files.
seedcheck
Package seedcheck keeps a store from linking or serving a horizon seed it did not receive through a horizon-seed announcement (draft-fossil-horizon-00 §5.2.3).
Package seedcheck keeps a store from linking or serving a horizon seed it did not receive through a horizon-seed announcement (draft-fossil-horizon-00 §5.2.3).
stash
Package stash saves and restores working directory changes, storing deltas against baseline blobs in the checkout database (.fslckout).
Package stash saves and restores working directory changes, storing deltas against baseline blobs in the checkout database (.fslckout).
sync
Package sync implements Fossil's multi-round sync and clone protocol.
Package sync implements Fossil's multi-round sync and clone protocol.
tag
undo
Package undo saves, restores, and redoes checkout state in a Fossil .fslckout database.
Package undo saves, restores, and redoes checkout state in a Fossil .fslckout database.
uv
verify
Package verify provides comprehensive repository verification and rebuild.
Package verify provides comprehensive repository verification and rebuild.
vfile
Package vfile reads a checkout's vfile table and says what each row means.
Package vfile reads a checkout's vfile table and says what each row means.
xfer
Package xfer implements Fossil's sync protocol card codec.
Package xfer implements Fossil's sync protocol card codec.
observer
otel module
Package sshverify links in-process verification of SSH signatures into a program that uses go-libfossil.
Package sshverify links in-process verification of SSH signatures into a program that uses go-libfossil.
tools
docsgen/conformance command
Command conformance turns the Markdown report TestCoverage writes into the docs site's conformance data: per-draft counts for the landing page and every requirement row for the reference page.
Command conformance turns the Markdown report TestCoverage writes into the docs site's conformance data: per-draft counts for the landing page and every requirement row for the reference page.
docsgen/engine command
Command engine writes the docs site's hero figure data: one check-in as an artifact, as the rows storing it derives, and on the wire as a clone pulls it.
Command engine writes the docs site's hero figure data: one check-in as an artifact, as the rows storing it derives, and on the wire as a clone pulls it.

Jump to

Keyboard shortcuts

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