This repository has been archived on 2026-08-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
tend/internal/process/run.go
T
gamertan b68fa2487d feat: publish Gamertan Tend preview source
Sanitized root snapshot from private source commit a72903c63e1753f9e6ffbf40453c0830bdfc05c5 and tree 295641e67eef5979da76746d8ae271249568263e. Private development history and workflows are excluded by the exact allowlist.

AI-assisted: OpenAI Codex helped implement, test, and audit this preview.
Signed-off-by: Cole Speelman <crspeelman@gmail.com>
2026-08-14 14:01:02 -04:00

73 lines
1.6 KiB
Go

// SPDX-License-Identifier: AGPL-3.0-only
package process
import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
"sort"
"strings"
)
const maxOutput = 4 << 20
type Runner interface {
Run(ctx context.Context, dir string, env map[string]string, name string, args ...string) ([]byte, error)
}
type ExecRunner struct{}
func (ExecRunner) Run(ctx context.Context, dir string, env map[string]string, name string, args ...string) ([]byte, error) {
cmd := exec.CommandContext(ctx, name, args...)
cmd.Dir = dir
cmd.Env = mergeEnv(os.Environ(), env)
var output limitedBuffer
cmd.Stdout = &output
cmd.Stderr = &output
err := cmd.Run()
if err != nil {
return output.Bytes(), fmt.Errorf("%s failed: %w: %s", name, err, strings.TrimSpace(output.String()))
}
return output.Bytes(), nil
}
type limitedBuffer struct{ bytes.Buffer }
func (b *limitedBuffer) Write(p []byte) (int, error) {
written := len(p)
remaining := maxOutput - b.Len()
if remaining > 0 {
if len(p) > remaining {
p = p[:remaining]
}
_, _ = b.Buffer.Write(p)
}
return written, nil
}
func mergeEnv(base []string, extra map[string]string) []string {
values := make(map[string]string, len(base)+len(extra))
for _, pair := range base {
key, value, ok := strings.Cut(pair, "=")
if ok {
values[key] = value
}
}
for key, value := range extra {
values[key] = value
}
keys := make([]string, 0, len(values))
for key := range values {
keys = append(keys, key)
}
sort.Strings(keys)
out := make([]string, 0, len(keys))
for _, key := range keys {
out = append(out, key+"="+values[key])
}
return out
}