Documentation
¶
Overview ¶
Package toolkit provides testable abstractions and helpers for CLI programs.
The central type is Runtime, an explicit dependency container that bundles environment variables, filesystem operations, clock, logger, streams, and hasher. Production code uses NewRuntime or NewOsRuntime; test code uses NewTestRuntime which wires in-memory implementations and a jailed filesystem.
Key interfaces:
- Env for environment variable access (implemented by OsEnv and TestEnv)
- FileSystem for filesystem operations (implemented by OsFS)
- Hasher for deterministic content hashing
Helper functions provide cross-platform user path resolution (UserConfigPath, UserDataPath, UserStatePath, UserCachePath) and environment variable expansion (ExpandEnv, ExpandPath).
Index ¶
- Variables
- func CreateTestStdio(content string) (*os.File, func())deprecated
- func DumpEnv(env Env) string
- func Edit(ctx context.Context, rt *Runtime, path string) error
- func EnsureInJail(jail, p string) string
- func EnsureInJailFor(jail, p string) string
- func ExpandEnv(env Env, s string) string
- func ExpandPath(env Env, p string) (string, error)
- func GetDefault(env Env, key, other string) string
- func IsInJail(jail, rel string) bool
- func IsInteractiveTerminal(f *os.File) bool
- func IsJailed(j Jailed) bool
- func RemoveJailPrefix(jail, path string) string
- func StdinHasData(f *os.File) bool
- func UserCachePath(env Env) (string, error)
- func UserConfigPath(env Env) (string, error)
- func UserDataPath(env Env) (string, error)
- func UserStatePath(env Env) (string, error)
- type Env
- type EnvCloner
- type FileSystem
- type Hasher
- type Jailed
- type MD5Hasher
- type OsEnv
- type OsFS
- type ProcessInfo
- type Runtime
- func (rt *Runtime) AbsPath(rel string) (string, error)
- func (rt *Runtime) AppendFile(rel string, data []byte, perm os.FileMode) error
- func (rt *Runtime) AtomicWriteFile(rel string, data []byte, perm os.FileMode) error
- func (rt *Runtime) Clock() clock.Clock
- func (rt *Runtime) Clone() *Runtime
- func (rt *Runtime) Env() Env
- func (rt *Runtime) Environ() []string
- func (rt *Runtime) FS() FileSystem
- func (rt *Runtime) Get(key string) string
- func (rt *Runtime) GetHome() (string, error)
- func (rt *Runtime) GetJail() string
- func (rt *Runtime) GetTempDir() string
- func (rt *Runtime) GetUser() (string, error)
- func (rt *Runtime) Getwd() (string, error)
- func (rt *Runtime) Glob(pattern string) ([]string, error)
- func (rt *Runtime) Has(key string) bool
- func (rt *Runtime) Hasher() Hasher
- func (rt *Runtime) Logger() *slog.Logger
- func (rt *Runtime) Mkdir(rel string, perm os.FileMode, all bool) error
- func (rt *Runtime) Name() string
- func (rt *Runtime) OpenFile(rel string, flag int, perm os.FileMode) (io.WriteCloser, error)
- func (rt *Runtime) Process() *ProcessInfo
- func (rt *Runtime) ReadDir(rel string) ([]os.DirEntry, error)
- func (rt *Runtime) ReadFile(rel string) ([]byte, error)
- func (rt *Runtime) Rel(basePath, targetPath string) (string, error)
- func (rt *Runtime) RelativePath(basepath, path string) string
- func (rt *Runtime) Remove(rel string, all bool) error
- func (rt *Runtime) Rename(src, dst string) error
- func (rt *Runtime) ResolvePath(rel string, follow bool) (string, error)
- func (rt *Runtime) Set(key, value string) error
- func (rt *Runtime) SetClock(c clock.Clock) error
- func (rt *Runtime) SetHasher(h Hasher) error
- func (rt *Runtime) SetHome(home string) error
- func (rt *Runtime) SetJail(jailPath string) error
- func (rt *Runtime) SetLogger(lg *slog.Logger) error
- func (rt *Runtime) SetStream(s *Stream) error
- func (rt *Runtime) SetUser(user string) error
- func (rt *Runtime) Setwd(dir string) error
- func (rt *Runtime) Stat(rel string, follow bool) (os.FileInfo, error)
- func (rt *Runtime) Stream() *Stream
- func (rt *Runtime) Symlink(oldName, newName string) error
- func (rt *Runtime) Unset(key string)
- func (rt *Runtime) Validate() error
- func (rt *Runtime) WriteFile(rel string, data []byte, perm os.FileMode) error
- type RuntimeOption
- func WithProcessInfo(p ProcessInfo) RuntimeOption
- func WithRuntimeClock(c clock.Clock) RuntimeOption
- func WithRuntimeEnv(env Env) RuntimeOption
- func WithRuntimeFileSystem(fs FileSystem) RuntimeOption
- func WithRuntimeHasher(h Hasher) RuntimeOption
- func WithRuntimeJail(jailPath string) RuntimeOption
- func WithRuntimeLogger(lg *slog.Logger) RuntimeOption
- func WithRuntimeStream(s *Stream) RuntimeOption
- type Stream
- type TestEnv
Constants ¶
This section is empty.
Variables ¶
var ( ErrNoEnvKey = errors.New("env key missing") ErrEscapeAttempt = jailpkg.ErrEscapeAttempt )
var DefaultEditor = "nano"
Functions ¶
func CreateTestStdio
deprecated
Deprecated: CreateTestStdio is unstable and may change in future releases.
CreateTestStdio creates a temporary file prefilled with the given content and seeks it to the beginning, making it suitable to pass as a stand-in for stdin, stdout, or stderr in tests.
It returns the open *os.File and a cleanup function. The cleanup function closes the file and removes it from disk. The function panics on any error while creating, writing, or seeking the temporary file; this makes test setup failures immediately visible.
Example usage in tests:
f, cleanup := CreateTestStdio("input text")
defer cleanup()
// pass f where a *os.File is needed
The returned file is created in the OS temporary directory using the pattern "test-stdio-*".
func EnsureInJail ¶
EnsureInJail returns a path that resides inside jail when possible.
func EnsureInJailFor ¶
EnsureInJailFor is a test-friendly helper that mirrors EnsureInJail.
func ExpandPath ¶
ExpandPath expands a leading tilde in the provided path to the user's home directory obtained from env.
func GetDefault ¶
GetDefault returns the value of key from env when present and non-empty.
func IsInteractiveTerminal ¶
IsInteractiveTerminal reports whether the provided file is connected to an interactive terminal.
This delegates to golang.org/x/term.IsTerminal and returns true when the file descriptor refers to a terminal device (TTY). Pass os.Stdin to check the program's standard input.
Notes:
- The check uses the file descriptor (f.Fd()) and will return false for pipes, redirected files, and other non-terminal descriptors.
- It is a non-destructive check and does not change the file position.
func RemoveJailPrefix ¶
RemoveJailPrefix removes the jail prefix from a path and returns an absolute path.
func StdinHasData ¶
StdinHasData reports whether the provided file appears to be receiving piped or redirected input (for example: `echo hi | myprog` or `myprog < file.txt`).
The implementation performs a lightweight metadata check: it returns true when the file is not a character device (that is, not a terminal). This is a common, portable heuristic used to detect piped input.
Notes and caveats:
- The check does not attempt to read from the file. It only inspects the file mode returned by Stat().
- For pipes this indicates stdin is coming from a pipe or redirect, but it does not strictly guarantee that bytes are immediately available to read. An open pipe may be empty until the writer writes to it.
- If f.Stat() returns an error the function conservatively returns false.
- Callers should pass os.Stdin to check the program's standard input, or a *os.File pointing to another stream for testing.
Example:
if StdinHasData(os.Stdin) {
// read from stdin
}
func UserCachePath ¶
UserCachePath returns the directory that should be used to store per-user cache files.
func UserConfigPath ¶
UserConfigPath returns the directory that should be used to store per-user configuration files.
func UserDataPath ¶
UserDataPath returns the directory that should be used to store per-user application data.
func UserStatePath ¶
UserStatePath returns the directory that should be used to store per-user state files for an application.
Types ¶
type FileSystem ¶
type FileSystem = filesystempkg.FileSystem
FileSystem is retained for backward compatibility. New code can import toolkit/filesystem directly.
type Hasher ¶
Hasher computes a deterministic short hash for a byte slice. Implementations should return a textual representation suitable for inclusion in meta fields.
DefaultHasher is the fallback hasher used when none is provided.
func OrDefaultHasher ¶ added in v1.0.0
OrDefaultHasher returns h unless it is nil, in which case DefaultHasher is returned.
type Jailed ¶ added in v1.0.0
Jailed is retained for backward compatibility. New code can import toolkit/jail directly.
type MD5Hasher ¶
type MD5Hasher struct{}
MD5Hasher is a simple Hasher implementation that returns an MD5 hex digest.
Note: MD5 is used here for deterministic, compact hashes only and is not intended for cryptographic integrity protection.
type OsFS ¶ added in v1.0.0
type OsFS = filesystempkg.OsFS
OsFS is retained for backward compatibility.
type ProcessInfo ¶ added in v1.1.0
type ProcessInfo struct {
PID int // os.Getpid()
Hostname string // os.Hostname()
StartedAt time.Time // process start time
UID string // unique instance ID (UUID)
}
ProcessInfo identifies the current process for lock ownership and stale lock detection.
func NewProcessInfo ¶ added in v1.1.0
func NewProcessInfo(c clock.Clock) ProcessInfo
NewProcessInfo creates ProcessInfo for the current OS process.
type Runtime ¶ added in v1.0.0
type Runtime struct {
// contains filtered or unexported fields
}
Runtime is the explicit dependency container for commands and helpers.
Context values are not used for mutable runtime dependencies; callers pass a Runtime directly.
func NewOsRuntime ¶ added in v1.0.0
func NewRuntime ¶ added in v1.0.0
func NewRuntime(opts ...RuntimeOption) (*Runtime, error)
NewRuntime constructs a Runtime with defaults and applies options.
func NewTestRuntime ¶ added in v1.0.0
func NewTestRuntime(jail, home, user string, opts ...RuntimeOption) (*Runtime, error)
NewTestRuntime constructs a runtime configured for tests with in-memory env and a jailed filesystem. Callers may override defaults via runtime options.
func (*Runtime) AbsPath ¶ added in v1.0.0
AbsPath returns a cleaned absolute runtime path based on runtime env/cwd.
func (*Runtime) AppendFile ¶ added in v1.2.0
func (*Runtime) AtomicWriteFile ¶ added in v1.0.0
func (*Runtime) Clone ¶ added in v1.0.0
Clone returns a shallow clone of runtime dependencies and deep-copies Env and Stream when supported.
func (*Runtime) FS ¶ added in v1.0.0
func (rt *Runtime) FS() FileSystem
FS returns the runtime FileSystem dependency.
func (*Runtime) GetTempDir ¶ added in v1.0.0
func (*Runtime) Process ¶ added in v1.1.0
func (rt *Runtime) Process() *ProcessInfo
Process returns the optional process identity for lock ownership. Returns nil when no process info was configured.
func (*Runtime) RelativePath ¶ added in v1.0.0
RelativePath returns path relative to basepath. If computation fails, target absolute path is returned.
func (*Runtime) ResolvePath ¶ added in v1.0.0
ResolvePath resolves rel to an absolute path and optionally follows symlinks.
func (*Runtime) SetJail ¶ added in v1.0.0
SetJail sets the canonical runtime jail and propagates it to both Env and FS.
func (*Runtime) Setwd ¶ added in v1.0.0
Setwd sets the canonical runtime working directory and propagates it to both Env and FileSystem.
type RuntimeOption ¶ added in v1.0.0
RuntimeOption mutates Runtime construction.
func WithProcessInfo ¶ added in v1.1.0
func WithProcessInfo(p ProcessInfo) RuntimeOption
func WithRuntimeClock ¶ added in v1.0.0
func WithRuntimeClock(c clock.Clock) RuntimeOption
func WithRuntimeEnv ¶ added in v1.0.0
func WithRuntimeEnv(env Env) RuntimeOption
func WithRuntimeFileSystem ¶ added in v1.0.0
func WithRuntimeFileSystem(fs FileSystem) RuntimeOption
func WithRuntimeHasher ¶ added in v1.0.0
func WithRuntimeHasher(h Hasher) RuntimeOption
func WithRuntimeJail ¶ added in v1.0.0
func WithRuntimeJail(jailPath string) RuntimeOption
func WithRuntimeLogger ¶ added in v1.0.0
func WithRuntimeLogger(lg *slog.Logger) RuntimeOption
func WithRuntimeStream ¶ added in v1.0.0
func WithRuntimeStream(s *Stream) RuntimeOption
type Stream ¶
type Stream struct {
// In is the input stream, typically os.Stdin.
In io.Reader
// Out is the output stream, typically os.Stdout.
Out io.Writer
// Err is the error stream, typically os.Stderr.
Err io.Writer
// IsPiped indicates whether stdin appears to be piped or redirected.
IsPiped bool
// IsTTY indicates whether stdout refers to a terminal.
IsTTY bool
}
Stream models the standard IO streams and common stream properties.
Struct field tags are included for clarity to external consumers that may wish to encode some stream metadata. The actual reader and writer fields are not suitable for encoding and therefore are tagged to be ignored.
func DefaultStream ¶
func DefaultStream() *Stream
DefaultStream returns a Stream configured with the real process standard input, output, and error streams. It detects whether stdin is piped and whether stdout is a terminal.
func OrDefaultStream ¶ added in v1.0.0
OrDefaultStream returns s unless it is nil, in which case DefaultStream() is returned.