package lanegit import ( "context" "errors" "fmt" "os" "os/exec" "strings" ) type Runner interface { Run(ctx context.Context, workdir string, env map[string]string, name string, args ...string) (string, error) } type ExecRunner struct{} func (ExecRunner) Run(ctx context.Context, workdir string, env map[string]string, name string, args ...string) (string, error) { cmd := exec.CommandContext(ctx, name, args...) if strings.TrimSpace(workdir) != "" { cmd.Dir = workdir } cmd.Env = os.Environ() for key, value := range env { cmd.Env = append(cmd.Env, key+"="+value) } out, err := cmd.CombinedOutput() return strings.TrimSpace(string(out)), err } func Run(ctx context.Context, runner Runner, worktree string, env map[string]string, args ...string) (string, error) { out, err := runner.Run(ctx, worktree, env, "git", args...) if err == nil { return out, nil } out = strings.TrimSpace(out) if out == "" { return "", fmt.Errorf("git %s: %w", strings.Join(args, " "), err) } return "", fmt.Errorf("git %s: %s: %w", strings.Join(args, " "), out, err) } func IsExitCode(err error, code int) bool { var exitErr *exec.ExitError return errors.As(err, &exitErr) && exitErr.ExitCode() == code }