Documentation
¶
Overview ¶
Package execenv resolves the environment the app runs subprocesses with, and answers what a variable would hold in the user's terminal.
A desktop launch inherits the launcher's environment, not a shell's: macOS starts an .app bundle with PATH=/usr/bin:/bin:/usr/sbin:/sbin. Session hooks and shell actions are the user's own commands, written against the PATH their terminal has, so running them with the inherited one fails on anything a package manager, a version manager or a language toolchain installed (ADR subprocess-environment). The same gap hides hive's own environment overrides from the app, which is what Getenv answers (ADR hive-env-overrides-resolve-through-the-login-shell).
Index ¶
- func SearchDirs() []string
- type Options
- type Resolver
- func (r *Resolver) Environ(ctx context.Context) []string
- func (r *Resolver) Getenv(ctx context.Context, name string) string
- func (r *Resolver) LookPath(ctx context.Context, name string) (string, error)
- func (r *Resolver) Path(ctx context.Context) string
- func (r *Resolver) ProbeErr() error
- func (r *Resolver) SetLogger(logger zerolog.Logger)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func SearchDirs ¶
func SearchDirs() []string
SearchDirs returns those prefixes plus the per-user ones. It is where a binary lives when the environment does not say: tmuxbin searches the list for one executable (ADR tmux-discovery), and the resolver appends it to PATH.
Types ¶
type Options ¶
type Options struct {
Logger zerolog.Logger
// Shell is the login shell to ask. Empty reads $SHELL; still empty skips
// the probe.
Shell string
// Timeout bounds one probe. Zero means defaultTimeout.
Timeout time.Duration
// Probe is the seam tests replace. Zero runs the real login shell.
Probe func(ctx context.Context, shell string) (map[string]string, error)
// Pinned wins over both this process's environment and the login shell's.
Pinned map[string]string
}
Options configures a Resolver. The zero value probes $SHELL with the default timeout and logs nothing.
type Resolver ¶
type Resolver struct {
// contains filtered or unexported fields
}
Resolver answers what PATH a subprocess runs with. It asks the user's login shell once per run and remembers the answer — a shell's PATH does not change under a running app, and re-running a login shell per hook command would charge every command that shell's startup cost.
func NewResolver ¶
func (*Resolver) Environ ¶
Environ returns the environment subprocesses run with: this process's, with PATH replaced by Path and the login shell's remaining variables filling names this process does not define. A launch that names a variable is more specific than a startup file, so the process wins — which keeps a stale rc file from shadowing a HIVE_DESKTOP_* override the app was started with.
The result is shared between callers: append to it, never write into it.
func (*Resolver) Getenv ¶
Getenv answers a variable the way the user's terminal would: this process's value when it has one, otherwise the login shell's. A variable exported from a startup file is invisible to a launched .app, so a config override the CLI reads from the environment is only reachable through the probe (ADR hive-env-overrides-resolve-through-the-login-shell).
func (*Resolver) LookPath ¶
LookPath resolves a command name against the same PATH its child will run with. It exists because os/exec does not: exec.Command searches the PATH of the process that calls it and ignores Cmd.Env, which is the one this package is replacing. A name that is already a path is returned untouched.
func (*Resolver) Path ¶
Path returns the PATH value subprocesses run with: what the login shell reports, then what this process inherited, then the package-manager prefixes, first occurrence winning. A probe that fails is not fatal — the inherited PATH still runs everything in /usr/bin, which is what the app had before.