Documentation
¶
Overview ¶
Package index manages the .focus/index.json derived cache.
The index is the read path for every command that doesn't load card bodies — `focus board`, `focus list`, `focus epic list`, the TUI's board view, etc. It holds frontmatter only; bodies are loaded on demand by `focus show`/`focus edit`. This is where the speed win over v1's bash implementation comes from.
Writes go through Save which uses google/renameio/v2 for an atomic temp-file → fsync → rename, so a crash mid-write can never leave a truncated index on disk. All mutating callers must hold the .focus/.lock flock for the duration of the read-modify-write cycle (see internal/board/lock).
Index ¶
Constants ¶
const FileName = "index.json"
FileName is the index file's name relative to .focus/.
const SchemaVersion = 2
SchemaVersion is stamped on every index.json we write. Bumped only when the index file format changes in a backwards-incompatible way; independent of the card schema_version.
Variables ¶
This section is empty.
Functions ¶
func Save ¶
Save writes the index to .focus/index.json atomically via renameio/v2 (temp file in the same dir → fsync → rename). The rename is atomic on POSIX, so concurrent readers either see the old snapshot or the new one — never a torn write.
Save also stamps GeneratedAt to the current UTC time and sets SchemaVersion to the constant; callers don't need to fill those.
Sorted by id for stable diffs and deterministic output across platforms.
Types ¶
type Entry ¶
type Entry struct {
ID int `json:"id"`
UUID string `json:"uuid"`
Title string `json:"title"`
Type card.Type `json:"type"`
Status card.Status `json:"status"`
Priority card.Priority `json:"priority"`
Project string `json:"project"`
Epic *int `json:"epic,omitempty"`
Tags []string `json:"tags,omitempty"`
Owner string `json:"owner,omitempty"`
Description string `json:"description,omitempty"`
Area string `json:"area,omitempty"`
Created string `json:"created"`
Dir string `json:"dir"`
}
Entry is one card's row in the index. Frontmatter only — never the body.
type Index ¶
type Index struct {
SchemaVersion int `json:"schema_version"`
GeneratedAt time.Time `json:"generated_at"`
NextID int `json:"next_id"`
Cards []Entry `json:"cards"`
}
Index is the on-disk shape of .focus/index.json.
func Load ¶
Load reads .focus/index.json from a board's .focus/ directory. Returns os.ErrNotExist if no index has been written yet (first `focus new` is the typical writer); callers should treat that as an empty index, not a hard error.
func LoadOrEmpty ¶
LoadOrEmpty returns the existing index or, if none has been written, a fresh empty Index with NextID=1. Convenience for command code that needs to read-then-modify; the alternative is each handler open-coding the os.ErrNotExist check.
func (*Index) AllocateID ¶
AllocateID returns the next available card id and increments NextID in place. The high-water-mark invariant (designs/focus-v2.md §"`next_id` allocation rule") is maintained by callers via Save.
func (*Index) MaxID ¶
MaxID returns the highest id present in the index, or 0 if empty. Used by Reindex to compute the next_id high-water mark.