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

paths

package
v0.17.0 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package paths centralizes filesystem path resolution honoring AGENTSYNC_HOME, AGENTSYNC_TARGET_ROOT, and third-party agent home overrides (GROK_HOME), and holds the two directory-containment predicates (lexical ContainsDir; the symlink-resolving, and therefore filesystem-reading, ContainsDirResolved / SameDirResolved). Production code MUST use this package; lint forbids os.UserHomeDir in *_test.go files.

AGENTSYNC_TARGET_ROOT is the sandbox switch: when set, EVERY path this package resolves — the effective home, the canonical source, an agent's own home override — lives under it, and the user-facing overrides (AGENTSYNC_HOME, GROK_HOME) are ignored. That is what lets the test suite run unchanged on a machine that actually uses agentsync (issue #270).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AgentHomeOverride added in v0.16.0

func AgentHomeOverride(e Env, key string) string

AgentHomeOverride returns the value of a third-party agent's own home-override variable (e.g. Grok Build's GROK_HOME), or "" when AGENTSYNC_TARGET_ROOT is set. A redirected run must never escape to the agent's real home, so the redirect wins outright — the same sandbox rule AgentsyncHome applies to AGENTSYNC_HOME. Production code reads such variables ONLY through this helper (never a raw os.Getenv), so they are injectable via Env like every other path input.

func AgentsyncHome

func AgentsyncHome(e Env) string

AgentsyncHome returns the directory where agentsync stores its source repo. Resolution order:

  1. <AGENTSYNC_TARGET_ROOT>/.agentsync — a redirected run is a sandbox: every path, the canonical source included, lives under the redirect root.
  2. $AGENTSYNC_HOME (the user-facing explicit override; absolute path)
  3. <HOME>/.agentsync

The redirect outranks AGENTSYNC_HOME deliberately (issue #270). Tests isolate themselves by setting AGENTSYNC_TARGET_ROOT to a tmp dir; if an ambient AGENTSYNC_HOME — exported by anyone who actually uses agentsync — could beat that redirect, every test resolving the canonical source would silently land on the developer's real ~/.agentsync tree. AGENTSYNC_TARGET_ROOT is a documented testing knob that real users never set, so for them the user-facing contract is unchanged: AGENTSYNC_HOME wins over the $HOME default.

func ContainsDir added in v0.16.0

func ContainsDir(parent, child string) bool

ContainsDir reports whether parent is child itself or one of its ancestors, comparing the paths as SPELLED (cleaned, no filesystem access). Use it for destination-root TOPOLOGY — the git-backup de-nesting pass and its owner map — where the declared spelling is what git backup inits, opens and stages by; see denestRoots in internal/cli for why resolving symlinks there is wrong. For directory IDENTITY (is this GROK_HOME really $HOME under another name?) use ContainsDirResolved / SameDirResolved; a guard whose miss would be costly tests both (the never-at-$HOME guard drops a root that contains the home by spelling OR by identity). The two agree whenever no symlink or case difference is involved.

func ContainsDirResolved added in v0.16.0

func ContainsDirResolved(parent, child string) bool

ContainsDirResolved is ContainsDir on directory IDENTITY rather than spelling: both paths are cleaned, resolved through symlinks, and compared ignoring case on the case-insensitive platforms (macOS, Windows). It backs the guards whose cost of a miss is a repo at or above $HOME — the central never-at-or-above- $HOME check in git backup and Grok's GROK_HOME refusal — where `GROK_HOME=/Users/Alice`, or a symlink to the home directory, must not walk past a check written for `$HOME=/users/alice` (issue #270). Those guards test BOTH predicates and refuse if either says contained: identity catches the aliased spelling, and the lexical check still catches an ancestor of the home's own spelling when the home itself is a symlink elsewhere (`$HOME=/home/alice → /data/alice`, root `/home`).

Resolution goes through the deepest EXISTING ancestor and re-appends the rest of the path unchanged, so a path that does not exist yet and one that does normalize into the same tree (see resolveExistingPrefix). The answer therefore depends on filesystem state and can change once a pending path is created — acceptable for the identity checks above ($HOME always exists), and the reason this predicate is NOT used for de-nesting.

func FromHomeRelative

func FromHomeRelative(userHome, stored string) string

FromHomeRelative is the inverse of HomeRelative: it expands a leading "${HOME}" / "${HOME}/" in a stored state path back to an absolute path rooted at userHome. Paths stored absolute (because they were outside home when recorded) are returned unchanged. Callers that turn a stored state key back into a real filesystem path (e.g. `agent disable --purge`) MUST route through this so they don't operate on the literal "${HOME}/..." string.

func HomeDir

func HomeDir(e Env) string

HomeDir returns the effective home dir. AGENTSYNC_TARGET_ROOT takes precedence (used by tests to redirect away from the real $HOME); otherwise falls back to $HOME.

func HomeRelative

func HomeRelative(home, abs string) string

HomeRelative converts an absolute destination path into the portable form stored in state files: "${HOME}/.claude.json" instead of the machine-specific absolute "/Users/alice/.claude.json". Paths that do not live under home are returned unchanged.

Without this normalization, state.Files / state.Keys keys would embed the absolute path that existed on the machine that wrote them, so a state file synced via chezmoi from /Users/alice/ to /home/alice/ would have every key prefix change and every native file would reclassify as ForeignCollision on the next apply.

HomeRelative uses forward-slash separators in the stored form so the same key is produced on POSIX and Windows when home is the equivalent path.

func SameDirResolved added in v0.16.0

func SameDirResolved(a, b string) bool

SameDirResolved reports whether a and b name the same directory under ContainsDirResolved's normalization.

Types

type Env

type Env interface {
	Get(key string) string
}

Env abstracts environment-variable lookup so tests can inject a fake.

type MapEnv

type MapEnv map[string]string

MapEnv is a fake Env backed by a map (for tests).

func (MapEnv) Get

func (m MapEnv) Get(key string) string

type OSEnv

type OSEnv struct{}

OSEnv reads the live process environment.

func (OSEnv) Get

func (OSEnv) Get(key string) string

Jump to

Keyboard shortcuts

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