shell

package
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2026 License: MPL-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const MaxFolderSearchDepth = 10

MaxFolderSearchDepth is the maximum depth to search for the project root, shared by GetProjectRoot and the EnsureGitRepository / EnsureProjectAnchor helpers so all walk-up traversals stop at the same boundary.

View Source
const SessionTokenPrefix = ".session."

SessionTokenPrefix is the prefix used for session token files

Variables

View Source
var ErrCommandTimedOut = errors.New("command timed out")

ErrCommandTimedOut marks a command killed for exceeding its timeout.

Functions

func EnsureGitRepository added in v0.9.0

func EnsureGitRepository() error

EnsureGitRepository returns an actionable error when no .git entry exists at or above the current working directory. Windsor relies on git for project- state ownership (trusted directories, blueprint refs, terraform state placement); running init in a bare directory produces opaque errors downstream, so the missing-repo case is surfaced here with a one-line operator hint. The walk caps at MaxFolderSearchDepth to match GetProjectRoot.

func EnsureProjectAnchor added in v0.9.0

func EnsureProjectAnchor() (string, error)

EnsureProjectAnchor writes a minimal windsor.yaml in the current working directory when no project file is found anywhere in the walk-up path. This anchors `windsor init` to the cwd so subsequent runtime resolution does not fall back to global mode and silently operate against $HOME/.config/windsor. If a project file already exists at or above the cwd, this is a no-op. Returns the directory holding the project file: cwd when this call created it, or the ancestor directory when one already existed there.

Types

type DefaultShell

type DefaultShell struct {
	Shell
	// contains filtered or unexported fields
}

DefaultShell is the default implementation of the Shell interface

func NewDefaultShell

func NewDefaultShell() *DefaultShell

NewDefaultShell creates a new instance of DefaultShell

func (*DefaultShell) AddCurrentDirToTrustedFile

func (s *DefaultShell) AddCurrentDirToTrustedFile() error

AddCurrentDirToTrustedFile adds the current directory to a trusted list stored in a file. Creates necessary directories if they don't exist. Checks if the directory is already trusted before adding. In global mode, trust is implicit for $HOME/.config/windsor and this is a no-op.

func (*DefaultShell) CheckResetFlags

func (s *DefaultShell) CheckResetFlags() (bool, error)

CheckResetFlags checks if a reset signal file exists for the current session token. It returns true if the specific session token file exists and always removes all .session.* files.

func (*DefaultShell) CheckTrustedDirectory

func (s *DefaultShell) CheckTrustedDirectory() error

CheckTrustedDirectory verifies that the project root equals a trusted directory or is inside one. It compares path components, so "/a/proj-evil" does not inherit trust from "/a/proj". In global mode, trust is implicit for $HOME/.config/windsor and this check is skipped.

func (*DefaultShell) Exec

func (s *DefaultShell) Exec(command string, args ...string) (string, error)

Exec runs a command with args, capturing stdout and stderr. It prints output and returns stdout as a string. If the command is "sudo", it connects stdin to the terminal for password input. All output is scrubbed to remove registered secrets before being displayed or returned.

func (*DefaultShell) ExecCaptureWithEnv added in v0.9.0

func (s *DefaultShell) ExecCaptureWithEnv(command string, env map[string]string, args ...string) (string, error)

ExecCaptureWithEnv runs a command with merged environment variables and captures its output, never streaming to stdout or stderr even in verbose mode. Use it for internal, machine-only output (e.g. `terraform show -json` state inspection) that is parsed rather than shown and may contain sensitive material such as cluster PKI — unlike ExecSilentWithEnv, which echoes captured output under verbose.

func (*DefaultShell) ExecProgress

func (s *DefaultShell) ExecProgress(message string, command string, args ...string) (string, error)

ExecProgress is a method of the DefaultShell struct that executes a command with a progress indicator. It takes a message, a command, and arguments, using the Exec method if verbose mode is enabled. Otherwise, it captures stdout and stderr with pipes and uses a spinner to show progress. The method returns the command's stdout as a string and any error encountered.

func (*DefaultShell) ExecProgressWithEnv added in v0.9.0

func (s *DefaultShell) ExecProgressWithEnv(message string, command string, env map[string]string, args ...string) (string, error)

ExecProgressWithEnv executes a command with a progress indicator and command-scoped env overrides.

func (*DefaultShell) ExecSilent

func (s *DefaultShell) ExecSilent(command string, args ...string) (string, error)

ExecSilent is a method that runs a command quietly, capturing its output. It returns the command's stdout as a string and any error encountered.

func (*DefaultShell) ExecSilentWithEnv added in v0.9.0

func (s *DefaultShell) ExecSilentWithEnv(command string, env map[string]string, args ...string) (string, error)

ExecSilentWithEnv runs a command with merged environment variables, capturing output silently. In verbose mode, output is streamed directly to stdout and stderr.

func (*DefaultShell) ExecSilentWithEnvAndIdleTimeout added in v0.9.1

func (s *DefaultShell) ExecSilentWithEnvAndIdleTimeout(command string, env map[string]string, args []string, idleTimeout, absoluteTimeout, gracePeriod time.Duration) (string, error)

ExecSilentWithEnvAndIdleTimeout runs command, streaming its output so a stall can be detected without bounding how long a legitimately slow but still-progressing run may take. idleTimeout resets on every line the command emits; only silence for that long counts as stuck. absoluteTimeout is a generous backstop against a command that keeps emitting output without ever finishing. Either firing interrupts the process group first, waits up to gracePeriod for the process to exit, and only then force-kills.

Use this for a long-running command whose own duration varies with what it is acting on, and whose abrupt termination can corrupt external state. `terraform destroy` is the motivating case: a wall-clock timeout kills a slow-but-healthy cloud teardown as readily as a genuinely hung one, and a hard kill mid-run loses its chance to write a state checkpoint and release its backend lock.

Ordinary timeout-bound commands hold no external state and have no progress output to key off of. They should keep using ExecSilentWithEnvAndTimeout, which kills immediately on one flat deadline.

func (*DefaultShell) ExecSilentWithEnvAndTimeout added in v0.9.0

func (s *DefaultShell) ExecSilentWithEnvAndTimeout(command string, env map[string]string, args []string, timeout time.Duration) (string, error)

ExecSilentWithEnvAndTimeout combines ExecSilentWithEnv and ExecSilentWithTimeout: it merges command-scoped env overrides into the inherited environment AND enforces a timeout, killing the child process if it exceeds the deadline. Used by callers that need both behaviors at once — e.g. CheckAuth() running `aws sts get-caller-identity` with the context-scoped AWS_CONFIG_FILE/AWS_PROFILE set, where the env is required for credential resolution and the timeout guards against a hung network call.

func (*DefaultShell) ExecSilentWithTimeout added in v0.9.0

func (s *DefaultShell) ExecSilentWithTimeout(command string, args []string, timeout time.Duration) (string, error)

ExecSilentWithTimeout executes a command with a timeout and returns the output. If the command takes longer than the timeout, it kills the process and returns an error. Uses ExecSilent internally but wraps it with a timeout mechanism.

func (*DefaultShell) ExecSudo

func (s *DefaultShell) ExecSudo(message string, command string, args ...string) (string, error)

ExecSudo runs a command with 'sudo', ensuring elevated privileges. It handles password prompts by connecting to the terminal and captures the command's output. If verbose mode is enabled or no TTY is available (CI/CD environments), it uses direct execution. Otherwise, it connects to /dev/tty for interactive password prompts; the child's stderr is routed through a scrubbingWriter, buffered by line and flushed once the command completes, so registered secrets never reach the terminal raw — a child streaming \r-only progress on stderr won't appear live until it emits \n or exits.

func (*DefaultShell) GetProjectRoot

func (s *DefaultShell) GetProjectRoot() (string, error)

GetProjectRoot finds the project root. It checks for a cached root first. If not found, it looks for "windsor.yaml" or "windsor.yml" in the current directory and its parents up to a maximum depth, returning the first match. When no project file is found, it falls back to $HOME/.config/windsor, creating that directory if needed, and marks the shell as operating in global mode.

func (*DefaultShell) GetSessionToken

func (s *DefaultShell) GetSessionToken() (string, error)

GetSessionToken retrieves or generates a session token. It first checks if a token is already stored in memory. If not, it looks for a token in the environment variable. If no token is found in the environment, it generates a new token.

func (*DefaultShell) InstallHook

func (s *DefaultShell) InstallHook(shellName string) error

InstallHook sets up a shell hook for a specified shell using a template with the Windsor path. It returns an error if the shell is unsupported. For PowerShell, it formats the script into a single line.

func (*DefaultShell) IsGlobal added in v0.9.0

func (s *DefaultShell) IsGlobal() bool

IsGlobal reports whether the shell is operating in global mode. Global mode is set when GetProjectRoot could not locate a windsor.yaml/windsor.yml in the current directory or any of its parents, and the shell has fallen back to the user's $HOME/.config/windsor directory as the effective project root.

func (*DefaultShell) IsVerbose added in v0.9.0

func (s *DefaultShell) IsVerbose() bool

IsVerbose returns the current verbosity flag value.

func (*DefaultShell) PrintEnvVars

func (s *DefaultShell) PrintEnvVars(envVars map[string]string, export bool)

PrintEnvVars is a platform-specific method that will be implemented by Unix/Windows-specific files The export parameter controls whether to use OS-specific export commands or plain KEY=value format

func (*DefaultShell) RegisterResolvedSecret added in v0.9.1

func (s *DefaultShell) RegisterResolvedSecret(value string)

RegisterResolvedSecret registers a value that a secret provider resolved. It skips the length floor of RegisterSecret, because a resolved value is a deliberate secret. Empty values are ignored. A short value hides every occurrence of that text in command output, including inside other words.

func (*DefaultShell) RegisterSecret

func (s *DefaultShell) RegisterSecret(value string)

RegisterSecret adds a secret value to the internal list of secrets that will be scrubbed from all command output. Values shorter than minRegisteredSecretLength are ignored, since scrubbing a short common substring mangles unrelated output while providing no real confidentiality. Duplicate values are automatically filtered out to maintain list efficiency. Safe for concurrent use with scrubString.

func (*DefaultShell) RenderAliases

func (s *DefaultShell) RenderAliases(aliases map[string]string) string

RenderAliases returns the rendered aliases as a string using Unix shell syntax

func (*DefaultShell) RenderEnvVars

func (s *DefaultShell) RenderEnvVars(envVars map[string]string, export bool) string

RenderEnvVars returns the rendered environment variables as a string instead of printing them The export parameter controls whether to use OS-specific export commands or plain KEY=value format

func (*DefaultShell) Reset

func (s *DefaultShell) Reset(quiet ...bool)

Reset removes all managed environment variables and aliases. It uses the environment variables "WINDSOR_MANAGED_ENV" and "WINDSOR_MANAGED_ALIAS" to retrieve the previous set of managed environment variables and aliases, respectively. These environment variables represent the previous set of managed values that need to be reset. The optional quiet parameter controls whether shell commands are printed during reset.

func (*DefaultShell) ResetSessionToken

func (s *DefaultShell) ResetSessionToken()

ResetSessionToken resets the session token - used primarily for testing

func (*DefaultShell) SetVerbosity

func (s *DefaultShell) SetVerbosity(verbose bool)

SetVerbosity sets the verbosity flag

func (*DefaultShell) UnsetAlias

func (s *DefaultShell) UnsetAlias(aliases []string)

UnsetAlias generates individual unalias commands for each alias in Unix shells. It prints a separate 'unalias' command for each alias name provided. If the input slice is empty, no output is produced.

func (*DefaultShell) UnsetEnvs

func (s *DefaultShell) UnsetEnvs(envVars []string)

UnsetEnvs generates a single unset command for multiple environment variables in Unix shells. It prints a single 'unset' command with all provided variable names separated by spaces. If the input slice is empty, no output is produced.

func (*DefaultShell) WriteResetToken

func (s *DefaultShell) WriteResetToken() (string, error)

WriteResetToken writes a reset token file based on the WINDSOR_SESSION_TOKEN environment variable. If the environment variable doesn't exist, no file is written. Returns the path to the written file or an empty string if no file was written.

type HookContext

type HookContext struct {
	// SelfPath is the unescaped absolute path to direnv
	SelfPath string
}

HookContext are the variables available during hook template evaluation

type MockShell

type MockShell struct {
	DefaultShell
	RenderEnvVarsFunc                   func(envVars map[string]string, export bool) string
	RenderAliasesFunc                   func(aliases map[string]string) string
	GetProjectRootFunc                  func() (string, error)
	ExecFunc                            func(command string, args ...string) (string, error)
	ExecSilentFunc                      func(command string, args ...string) (string, error)
	ExecSilentWithEnvFunc               func(command string, env map[string]string, args ...string) (string, error)
	ExecCaptureWithEnvFunc              func(command string, env map[string]string, args ...string) (string, error)
	ExecSilentWithTimeoutFunc           func(command string, args []string, timeout time.Duration) (string, error)
	ExecSilentWithEnvAndTimeoutFunc     func(command string, env map[string]string, args []string, timeout time.Duration) (string, error)
	ExecSilentWithEnvAndIdleTimeoutFunc func(command string, env map[string]string, args []string, idleTimeout, absoluteTimeout, gracePeriod time.Duration) (string, error)
	ExecProgressFunc                    func(message string, command string, args ...string) (string, error)
	ExecProgressWithEnvFunc             func(message string, command string, env map[string]string, args ...string) (string, error)
	ExecSudoFunc                        func(message string, command string, args ...string) (string, error)
	InstallHookFunc                     func(shellName string) error
	SetVerbosityFunc                    func(verbose bool)
	IsVerboseFunc                       func() bool
	IsGlobalFunc                        func() bool
	AddCurrentDirToTrustedFileFunc      func() error
	CheckTrustedDirectoryFunc           func() error
	UnsetEnvsFunc                       func(envVars []string)
	UnsetAliasFunc                      func(aliases []string)
	WriteResetTokenFunc                 func() (string, error)
	GetSessionTokenFunc                 func() (string, error)
	CheckResetFlagsFunc                 func() (bool, error)
	ResetFunc                           func(...bool)
	RegisterSecretFunc                  func(value string)
	RegisterResolvedSecretFunc          func(value string)
}

func NewMockShell

func NewMockShell() *MockShell

NewMockShell creates a new instance of MockShell

func (*MockShell) AddCurrentDirToTrustedFile

func (s *MockShell) AddCurrentDirToTrustedFile() error

AddCurrentDirToTrustedFile calls the custom AddCurrentDirToTrustedFileFunc if provided.

func (*MockShell) CheckResetFlags

func (s *MockShell) CheckResetFlags() (bool, error)

CheckResetFlags checks if a reset signal file exists for the current session

func (*MockShell) CheckTrustedDirectory

func (s *MockShell) CheckTrustedDirectory() error

CheckTrustedDirectory calls the custom CheckTrustedDirectoryFunc if provided.

func (*MockShell) Exec

func (s *MockShell) Exec(command string, args ...string) (string, error)

Exec calls the custom ExecFunc if provided.

func (*MockShell) ExecCaptureWithEnv added in v0.9.0

func (s *MockShell) ExecCaptureWithEnv(command string, env map[string]string, args ...string) (string, error)

ExecCaptureWithEnv calls the custom ExecCaptureWithEnvFunc if provided, otherwise delegates to ExecSilentWithEnv.

func (*MockShell) ExecProgress

func (s *MockShell) ExecProgress(message string, command string, args ...string) (string, error)

ExecProgress calls the custom ExecProgressFunc if provided.

func (*MockShell) ExecProgressWithEnv added in v0.9.0

func (s *MockShell) ExecProgressWithEnv(message string, command string, env map[string]string, args ...string) (string, error)

ExecProgressWithEnv calls the custom ExecProgressWithEnvFunc if provided, otherwise falls back to ExecProgressFunc to preserve existing tests.

func (*MockShell) ExecSilent

func (s *MockShell) ExecSilent(command string, args ...string) (string, error)

ExecSilent calls the custom ExecSilentFunc if provided.

func (*MockShell) ExecSilentWithEnv added in v0.9.0

func (s *MockShell) ExecSilentWithEnv(command string, env map[string]string, args ...string) (string, error)

ExecSilentWithEnv calls the custom ExecSilentWithEnvFunc if provided, otherwise delegates to ExecSilent.

func (*MockShell) ExecSilentWithEnvAndIdleTimeout added in v0.9.1

func (s *MockShell) ExecSilentWithEnvAndIdleTimeout(command string, env map[string]string, args []string, idleTimeout, absoluteTimeout, gracePeriod time.Duration) (string, error)

ExecSilentWithEnvAndIdleTimeout calls the custom ExecSilentWithEnvAndIdleTimeoutFunc if provided. Falls back to ExecSilentWithEnvAndTimeout, reusing idleTimeout as its flat timeout and ignoring absoluteTimeout and gracePeriod, so existing tests that stub a simpler variant keep working.

func (*MockShell) ExecSilentWithEnvAndTimeout added in v0.9.0

func (s *MockShell) ExecSilentWithEnvAndTimeout(command string, env map[string]string, args []string, timeout time.Duration) (string, error)

ExecSilentWithEnvAndTimeout calls the custom ExecSilentWithEnvAndTimeoutFunc if provided. Falls back to ExecSilentWithEnvFunc (then ExecSilentWithTimeoutFunc, then ExecSilent) so existing tests that only stub one of the simpler variants keep working.

func (*MockShell) ExecSilentWithTimeout added in v0.9.0

func (s *MockShell) ExecSilentWithTimeout(command string, args []string, timeout time.Duration) (string, error)

ExecSilentWithTimeout calls the custom ExecSilentWithTimeoutFunc if provided, otherwise delegates to ExecSilent.

func (*MockShell) ExecSudo

func (s *MockShell) ExecSudo(message string, command string, args ...string) (string, error)

ExecSudo calls the custom ExecSudoFunc if provided.

func (*MockShell) GetProjectRoot

func (s *MockShell) GetProjectRoot() (string, error)

GetProjectRoot calls the custom GetProjectRootFunc if provided.

func (*MockShell) GetSessionToken

func (s *MockShell) GetSessionToken() (string, error)

GetSessionToken retrieves or generates a session token

func (*MockShell) InstallHook

func (s *MockShell) InstallHook(shellName string) error

InstallHook calls the custom InstallHook if provided.

func (*MockShell) IsGlobal added in v0.9.0

func (s *MockShell) IsGlobal() bool

IsGlobal calls the custom IsGlobalFunc if provided.

func (*MockShell) IsVerbose added in v0.9.0

func (s *MockShell) IsVerbose() bool

IsVerbose calls the custom IsVerboseFunc if provided.

func (*MockShell) RegisterResolvedSecret added in v0.9.1

func (s *MockShell) RegisterResolvedSecret(value string)

RegisterResolvedSecret calls the custom RegisterResolvedSecretFunc if provided.

func (*MockShell) RegisterSecret

func (s *MockShell) RegisterSecret(value string)

RegisterSecret calls the custom RegisterSecretFunc if provided.

func (*MockShell) RenderAliases

func (s *MockShell) RenderAliases(aliases map[string]string) string

RenderAliases calls the custom RenderAliasesFunc if provided.

func (*MockShell) RenderEnvVars

func (s *MockShell) RenderEnvVars(envVars map[string]string, export bool) string

RenderEnvVars calls the custom RenderEnvVarsFunc if provided.

func (*MockShell) Reset

func (s *MockShell) Reset(quiet ...bool)

Reset calls the custom ResetFunc if provided.

func (*MockShell) SetVerbosity

func (s *MockShell) SetVerbosity(verbose bool)

SetVerbosity calls the custom SetVerbosityFunc if provided.

func (*MockShell) UnsetAlias

func (s *MockShell) UnsetAlias(aliases []string)

UnsetAlias calls the custom UnsetAliasFunc if provided.

func (*MockShell) UnsetEnvs

func (s *MockShell) UnsetEnvs(envVars []string)

UnsetEnvs calls the custom UnsetEnvsFunc if provided.

func (*MockShell) WriteResetToken

func (s *MockShell) WriteResetToken() (string, error)

WriteResetToken writes a reset token file

type Shell

type Shell interface {
	SetVerbosity(verbose bool)
	IsVerbose() bool
	IsGlobal() bool
	RenderEnvVars(envVars map[string]string, export bool) string
	RenderAliases(aliases map[string]string) string
	GetProjectRoot() (string, error)
	Exec(command string, args ...string) (string, error)
	ExecSilent(command string, args ...string) (string, error)
	ExecSilentWithEnv(command string, env map[string]string, args ...string) (string, error)
	ExecCaptureWithEnv(command string, env map[string]string, args ...string) (string, error)
	ExecSilentWithTimeout(command string, args []string, timeout time.Duration) (string, error)
	ExecSilentWithEnvAndTimeout(command string, env map[string]string, args []string, timeout time.Duration) (string, error)
	ExecSilentWithEnvAndIdleTimeout(command string, env map[string]string, args []string, idleTimeout, absoluteTimeout, gracePeriod time.Duration) (string, error)
	ExecSudo(message string, command string, args ...string) (string, error)
	ExecProgress(message string, command string, args ...string) (string, error)
	ExecProgressWithEnv(message string, command string, env map[string]string, args ...string) (string, error)
	InstallHook(shellName string) error
	AddCurrentDirToTrustedFile() error
	CheckTrustedDirectory() error
	UnsetEnvs(envVars []string)
	UnsetAlias(aliases []string)
	WriteResetToken() (string, error)
	GetSessionToken() (string, error)
	CheckResetFlags() (bool, error)
	Reset(quiet ...bool)
	RegisterSecret(value string)
	RegisterResolvedSecret(value string)
}

Shell is the interface that defines shell operations.

type Shims

type Shims struct {
	// OS operations
	Getwd      func() (string, error)
	Stat       func(name string) (os.FileInfo, error)
	Executable func() (string, error)

	// Standard I/O operations
	Stderr    func() io.Writer
	SetStderr func(w io.Writer)
	Stdout    func() io.Writer
	SetStdout func(w io.Writer)
	Pipe      func() (*os.File, *os.File, error)

	// Shell operations
	UnsetEnvs  func(envVars []string)
	UnsetAlias func(aliases []string)

	// Exec operations
	Command     func(name string, arg ...string) *exec.Cmd
	Environ     func() []string
	LookPath    func(file string) (string, error)
	OpenFile    func(name string, flag int, perm os.FileMode) (*os.File, error)
	WriteFile   func(name string, data []byte, perm os.FileMode) error
	ReadFile    func(name string) ([]byte, error)
	MkdirAll    func(path string, perm os.FileMode) error
	Remove      func(name string) error
	RemoveAll   func(path string) error
	Chdir       func(dir string) error
	Setenv      func(key, value string) error
	Getenv      func(key string) string
	UserHomeDir func() (string, error)

	// Exec operations
	CmdRun     func(cmd *exec.Cmd) error
	CmdStart   func(cmd *exec.Cmd) error
	CmdWait    func(cmd *exec.Cmd) error
	StdoutPipe func(cmd *exec.Cmd) (io.ReadCloser, error)
	StderrPipe func(cmd *exec.Cmd) (io.ReadCloser, error)
	StdinPipe  func(cmd *exec.Cmd) (io.WriteCloser, error)

	// Template operations
	NewTemplate     func(name string) *template.Template
	TemplateParse   func(tmpl *template.Template, text string) (*template.Template, error)
	TemplateExecute func(tmpl *template.Template, wr io.Writer, data any) error
	ExecuteTemplate func(tmpl *template.Template, data any) error

	// Bufio operations
	NewScanner  func(r io.Reader) *bufio.Scanner
	ScannerScan func(scanner *bufio.Scanner) bool
	ScannerErr  func(scanner *bufio.Scanner) error
	ScannerText func(scanner *bufio.Scanner) string
	NewWriter   func(w io.Writer) *bufio.Writer

	// Filepath operations
	Glob func(pattern string) ([]string, error)
	Join func(elem ...string) string

	// Random operations
	RandRead func(b []byte) (n int, err error)

	// Terminal operations
	IsTerminal func(fd int) bool

	// Signal operations
	SignalNotify func(c chan<- os.Signal, sig ...os.Signal)
	SignalStop   func(c chan<- os.Signal)

	// Process group operations
	InterruptProcessGroup func(cmd *exec.Cmd) error
	KillProcessGroup      func(cmd *exec.Cmd) error
}

Shims provides mockable wrappers around system and runtime functions

func NewShims

func NewShims() *Shims

NewShims creates a new Shims instance with default implementations

Jump to

Keyboard shortcuts

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