entiredir

package
v0.11.2 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package entiredir owns access to the repository's .entire directory.

Every non-test read and write under .entire goes through the single *os.Root this package hands out, rather than through an absolute path assembled by the caller. Two properties follow from that, and neither survives if a call site reverts to os.ReadFile/os.WriteFile on a joined path:

  • Containment. .entire holds paths named from agent-supplied session IDs, tool-use IDs, and tree paths. A root confines every open to the directory at the kernel level, so a crafted name cannot escape it, and a symlink swapped in between resolution and open (TOCTOU) surfaces as an error rather than a redirected write.
  • One directory handle per worktree. The root is opened once and memoized, so the hot hook paths stop paying an OpenRoot per state file, and every consumer observes the same directory even if .entire is renamed or replaced underneath a long-running process.

Creation is deliberately lazy and split across two entry points. Open creates .entire because its callers are about to write; OpenForRead never creates, because a command that only looks must leave an untouched repo untouched. That distinction is load-bearing for logging in particular: the log file is created by the first line actually written, so a command that logs nothing (completion, version, help) must not leave an .entire behind.

Reset exists for the paths that delete the directory (entire disable, entire clean) and for tests. A cached root that outlives its directory is a handle to an unlinked inode: writes through it succeed and land nowhere.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MustName

func MustName(repoRelPath string) string

MustName is Name for package-level constants that are known to be under .entire. It panics on a path that is not, which can only be a programming error in a literal.

func Name

func Name(repoRelPath string) (string, error)

Name converts a repo-relative path under .entire (for example paths.EntireTmpDir) to a name relative to the .entire root. The repo-relative constants stay as they are because git paths, settings display, and gitignore entries all need them; this is the one-line bridge to root-relative I/O.

A path outside .entire is an error rather than a silent passthrough: the alternative is a name that resolves inside .entire but means something else.

func Open

func Open(ctx context.Context) (*os.Root, error)

Open returns the shared *os.Root for the current worktree's .entire directory, creating the directory if it does not exist. Use it from write paths; read-only callers want OpenForRead.

The returned root is owned by this package and shared with every other caller. Do not close it.

func OpenAt

func OpenAt(worktreeRoot string) (*os.Root, error)

OpenAt is Open for an explicit worktree root, for the callers that already resolved one (or that act on a worktree other than the current directory).

func OpenAtForRead

func OpenAtForRead(worktreeRoot string) (*os.Root, error)

OpenAtForRead is OpenForRead for an explicit worktree root.

func OpenForRead

func OpenForRead(ctx context.Context) (*os.Root, error)

OpenForRead is Open without creating .entire. A missing directory is reported as fs.ErrNotExist, which callers classify with errors.Is.

func OpenPath

func OpenPath(p string) (root *os.Root, name string, err error)

OpenPath returns the shared root for the .entire directory containing p, together with p's name within it, creating the directory if needed. OpenPathForRead is the same without creation.

These exist for the consumers that already carry an absolute path — settings resolves one per layer, and hands it back to callers that print it — so those APIs keep their shape while the open itself still goes through the one root. A path not under a .entire directory yields ok=false from Split and an error here; callers that legitimately handle both (settings also reads clone preferences out of .git) branch on that rather than guessing.

func OpenPathForRead

func OpenPathForRead(p string) (root *os.Root, name string, err error)

OpenPathForRead is OpenPath without creating .entire.

func Opener

func Opener(ctx context.Context) func() (*os.Root, error)

Opener returns a thunk that calls Open when invoked, for consumers that are handed their storage up front but must not touch the disk until they first write (see logging.Config.Root).

func OpenerAt

func OpenerAt(worktreeRoot string) func() (*os.Root, error)

OpenerAt returns a thunk that calls OpenAt when invoked.

func Path

func Path(ctx context.Context) (string, error)

Path returns the absolute path of the current worktree's .entire directory. It is for messages and for the few consumers that must hand a path to an external process; it is not an invitation to do I/O on the result.

func PathTo

func PathTo(ctx context.Context, repoRelPath string) (string, error)

PathTo returns the absolute path of repoRelPath, which must name something under .entire. It exists for the consumers that carry an absolute path in their own API — settings resolves one per layer and hands it back to callers that print it — so those resolve through this package's anchor rather than paths.AbsPath, whose relative fallback is the thing anchor exists to avoid.

func ReadFile

func ReadFile(root *os.Root, name string) ([]byte, error)

ReadFile reads an Entire-owned file without following a symlink at the leaf.

func Reset

func Reset()

Reset closes and forgets every cached root. Call it after deleting .entire: a root cached across the deletion refers to an unlinked directory, so writes through it succeed and land nowhere.

The registry is shared with the other anchors, so this clears them too. That is the behaviour teardown wants — a repo whose .entire just went away is not a repo whose .git root is worth keeping — and tests get one reset to call.

func Split

func Split(p string) (entireDir, name string, ok bool)

Split splits a path that lies under a .entire directory into that directory and the name of the path within it. It is lexical: the path is cleaned and the innermost ".entire" component wins, which is the directory that actually contains the file if a repo is ever checked out inside another repo's .entire.

A relative path is accepted, because paths.AbsPath still falls back to one when it cannot resolve a worktree root and callers hand that value straight through. The walk is component-by-component with filepath rather than a split on separators so a Windows volume name survives being rejoined.

func WriteFile

func WriteFile(root *os.Root, name string, data []byte, perm os.FileMode) error

WriteFile atomically replaces an Entire-owned file. Renaming a newly-created temporary file over name replaces a planted leaf symlink rather than opening and truncating its target.

Types

This section is empty.

Jump to

Keyboard shortcuts

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