Engram::Hooks
Installs/uninstalls the three git hooks (post-checkout, post-merge,
post-rewrite) that keep the per-clone cache in sync automatically. Each
hook body invokes the absolute path of the engram binary that ran
hook install (resolved via Process.executable_path), not a bare
engram — git runs hooks under a minimal, noninteractive PATH that most
shells' interactive PATH never touches, so a bare command silently
no-ops (hook exits nonzero, cache goes stale, git checkout never fails
loudly) unless engram happens to be installed to a directory already on
that noninteractive PATH. Baking in the absolute path makes the hook work
regardless of PATH. Every managed block is wrapped in marker comments so
uninstall can remove exactly what install added, regardless of
whatever else lives in the hook file; a comment line inside the block also
records the baked-in path in a form doctor (and a repeat install) can
read back out without re-parsing shell quoting.
Callers must pass the effective hooks directory — the one git itself
will actually run hooks from, resolved via git rev-parse --git-path hooks (see Cli.hooks_dir_for). That's not always <repo>/.git/hooks:
core.hooksPath can point anywhere, and in a linked worktree the hooks
git runs live in the shared common dir, not the worktree's own private
gitdir. This module never reconstructs that path itself — it only
reads/writes files directly under whatever directory it's given.
Constants
The comment line, inside the marker block, that records the baked-in absolute
engram path in a directly-greppable form — no shell-quote parsing required to
read it back (used by installed_engram_path and, transitively, doctor).
The three lifecycle hooks that correspond to "the working tree just changed underneath us".
Closes the engram-managed block in a hook file.
Opens the engram-managed block in a hook file.
Class methods
Installs the engram sync snippet into each of HOOK_NAMES under the effective
hooks_dir (creating the hook file with a shebang if it doesn't exist yet;
appending, guarded by the marker comments, if it does). engram_path defaults
to the currently-running binary's own absolute path — that's what gets baked
into the hook body, so pass an explicit value only in tests or other unusual
callers. Returns the names actually installed or refreshed: a hook whose
existing block already bakes in engram_path is left untouched and excluded
from the result; a hook whose block bakes in some other path (the binary was
rebuilt or moved since the last install) has its block rewritten in place, so
re-running hook install after moving the binary actually repairs a hook
doctor flagged as stale, rather than being a permanent no-op.
The absolute engram path baked into path's marker block by install, or nil
if path doesn't exist, carries no engram block, or (a hook installed before
this hardening landed) has a block with no # engram-bin: line. doctor uses
this to confirm an "installed" hook would actually resolve engram at run time
rather than silently no-op under git's minimal noninteractive PATH.
The absolute path of the engram binary currently running this process. Falls back to the bare command name only if the OS can't report it (rare, exotic platforms) — that fallback reproduces the pre-hardening PATH-dependent behavior rather than baking in something worse than a bare command.