gitcmd

package
v0.9.1 Latest Latest
Warning

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

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

Documentation

Overview

Package gitcmd provides Git command execution and output handling. This package wraps the Git CLI and provides a safe, structured interface for executing Git commands with proper error handling and output parsing.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CanonicalRemoteEndpoint

func CanonicalRemoteEndpoint(raw string) (string, error)

CanonicalRemoteEndpoint returns the strict, credential-free representation used when a configuration must bind to one exact Git remote endpoint. It is intentionally narrower than SanitizeURL: a URL that is safe to pass to Git is not necessarily safe to use as an authorization identity.

func SanitizeArgs

func SanitizeArgs(args []string) ([]string, error)

SanitizeArgs validates and sanitizes Git command arguments.

Git is executed via exec.CommandContext without a shell, so a flag allowlist provides no shell-injection defense — it only blocks legitimate flags until each one is manually added. The residual threat is option injection (a user-supplied value parsed by git as a flag), which is handled by the '--' end-of-options separator and the per-value validators (SanitizeBranchName, SanitizePath, SanitizeURL, SanitizeCommitMessage) at the call sites.

Returns an error if any argument contains dangerous patterns. Returns the sanitized arguments if all checks pass.

func SanitizeBranchName

func SanitizeBranchName(name string) error

SanitizeBranchName validates a Git branch name. This ensures the branch name follows Git conventions.

func SanitizeCommitMessage

func SanitizeCommitMessage(message string) error

SanitizeCommitMessage validates a commit message. This ensures the message doesn't contain problematic characters.

func SanitizePath

func SanitizePath(path string) error

SanitizePath validates a file system path. This prevents path traversal attacks and access to system directories.

func SanitizeRemoteName

func SanitizeRemoteName(name string) error

SanitizeRemoteName validates a remote name before it is passed to git. Remote names are configuration keys, not arbitrary command arguments; a deliberately narrow character set also prevents option injection and malformed ref namespaces.

func SanitizeURL

func SanitizeURL(value string) error

SanitizeURL validates a Git repository URL. This ensures the URL is in a safe format (HTTPS, SSH, or file).

Types

type Executor

type Executor struct {
	// contains filtered or unexported fields
}

Executor executes Git commands and captures their output. It provides a safe wrapper around os/exec with input sanitization, timeout support, and structured result handling.

func NewExecutor

func NewExecutor(opts ...Option) *Executor

NewExecutor creates a new Git command executor.

func (*Executor) GetGitVersion

func (e *Executor) GetGitVersion(ctx context.Context) (string, error)

GetGitVersion returns the Git version string. Example: "2.40.0".

func (*Executor) IsGitRepository

func (e *Executor) IsGitRepository(ctx context.Context, dir string) bool

IsGitRepository checks if the directory is a Git repository root. It verifies that the directory itself contains a .git directory or file, not just that it's inside a Git repository (which git rev-parse would detect).

func (*Executor) Run

func (e *Executor) Run(ctx context.Context, dir string, args ...string) (*Result, error)

Run executes a Git command in the specified directory. The args are sanitized before execution to prevent command injection.

Example:

result, err := executor.Run(ctx, "/path/to/repo", "status", "--porcelain")

func (*Executor) RunLines

func (e *Executor) RunLines(ctx context.Context, dir string, args ...string) ([]string, error)

RunLines executes a Git command and returns stdout as a slice of lines. Empty lines are filtered out. Returns an error if the command fails.

Example:

files, err := executor.RunLines(ctx, "/path/to/repo", "ls-files")

func (*Executor) RunOutput

func (e *Executor) RunOutput(ctx context.Context, dir string, args ...string) (string, error)

RunOutput executes a Git command and returns only stdout. This is useful for commands where you need to parse the output. Returns an error if the command fails (non-zero exit code).

Example:

branch, err := executor.RunOutput(ctx, "/path/to/repo", "rev-parse", "--abbrev-ref", "HEAD")

func (*Executor) RunQuiet

func (e *Executor) RunQuiet(ctx context.Context, dir string, args ...string) (bool, error)

RunQuiet executes a Git command and returns only success/failure. This is useful for commands where you only care about the exit code.

Example:

success, err := executor.RunQuiet(ctx, "/path/to/repo", "rev-parse", "--git-dir")

func (*Executor) RunWithEnv

func (e *Executor) RunWithEnv(ctx context.Context, dir string, extraEnv []string, args ...string) (*Result, error)

RunWithEnv executes a Git command with additional environment variables. The extraEnv variables are appended to the executor's base environment. This is useful for per-command authentication (e.g., GIT_SSH_COMMAND).

Example:

env := []string{"GIT_SSH_COMMAND=ssh -i /path/to/key -o IdentitiesOnly=yes"}
result, err := executor.RunWithEnv(ctx, "/path/to/repo", env, "clone", url)

func (*Executor) RunWithOutputLimit

func (e *Executor) RunWithOutputLimit(ctx context.Context, dir string, extraEnv []string, limit int64, args ...string) (*Result, bool, error)

RunWithOutputLimit runs Git with the same binary, timeout, environment, and argument validation as RunWithEnv while retaining at most limit bytes of stdout. overflow reports that the process was canceled after crossing the limit; callers must treat it as a failed command.

func (*Executor) RunWithOutputLimitCleanEnv

func (e *Executor) RunWithOutputLimitCleanEnv(ctx context.Context, dir string, env []string, limit int64, args ...string) (*Result, bool, error)

RunWithOutputLimitCleanEnv runs Git with exactly env, omitting the process and executor environments. Callers use it when a repository's local config must not be combined with ambient Git configuration injection.

type GitError

type GitError struct {
	// Command is the Git command that failed.
	Command string

	// ExitCode is the Git exit code.
	ExitCode int

	// Stderr is the error output from Git.
	Stderr string

	// Cause is the underlying error, if any.
	Cause error
}

GitError represents a Git command execution error.

func (*GitError) Error

func (e *GitError) Error() string

Error implements the error interface.

func (*GitError) Is

func (e *GitError) Is(target error) bool

Is implements error comparison.

func (*GitError) Unwrap

func (e *GitError) Unwrap() error

Unwrap implements error unwrapping.

type Option

type Option func(*Executor)

Option configures an Executor.

func WithEnv

func WithEnv(env []string) Option

WithEnv sets environment variables for Git commands.

func WithGitBinary

func WithGitBinary(path string) Option

WithGitBinary sets a custom Git binary path.

func WithTimeout

func WithTimeout(timeout time.Duration) Option

WithTimeout sets the default timeout for Git commands.

type Result

type Result struct {
	// Stdout contains the command's standard output.
	Stdout string

	// Stderr contains the command's standard error output.
	Stderr string

	// ExitCode is the command's exit code.
	// 0 indicates success, non-zero indicates an error.
	ExitCode int

	// Duration is how long the command took to execute.
	Duration time.Duration

	// Error is the error returned by exec, if any.
	// This may be nil even if ExitCode is non-zero.
	Error error
}

Result contains the result of a Git command execution.

Jump to

Keyboard shortcuts

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