Create util.ExecWithOutput and util.ExecRun to consolidate repeated exec.Command patterns across witness/handlers.go and refinery/manager.go. Changes: - Add internal/util/exec.go with ExecWithOutput (returns stdout) and ExecRun (runs command without output) - Refactor witness/handlers.go to use utility functions (7 call sites) - Refactor refinery/manager.go, removing unused gitRun/gitOutput methods - Add comprehensive tests in exec_test.go 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
50 lines
1.2 KiB
Go
50 lines
1.2 KiB
Go
package util
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// ExecWithOutput runs a command in the specified directory and returns stdout.
|
|
// If the command fails, stderr content is included in the error message.
|
|
func ExecWithOutput(workDir, cmd string, args ...string) (string, error) {
|
|
c := exec.Command(cmd, args...) //nolint:gosec // G204: callers validate args
|
|
c.Dir = workDir
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
c.Stdout = &stdout
|
|
c.Stderr = &stderr
|
|
|
|
if err := c.Run(); err != nil {
|
|
errMsg := strings.TrimSpace(stderr.String())
|
|
if errMsg != "" {
|
|
return "", fmt.Errorf("%s", errMsg)
|
|
}
|
|
return "", err
|
|
}
|
|
|
|
return strings.TrimSpace(stdout.String()), nil
|
|
}
|
|
|
|
// ExecRun runs a command in the specified directory.
|
|
// If the command fails, stderr content is included in the error message.
|
|
func ExecRun(workDir, cmd string, args ...string) error {
|
|
c := exec.Command(cmd, args...) //nolint:gosec // G204: callers validate args
|
|
c.Dir = workDir
|
|
|
|
var stderr bytes.Buffer
|
|
c.Stderr = &stderr
|
|
|
|
if err := c.Run(); err != nil {
|
|
errMsg := strings.TrimSpace(stderr.String())
|
|
if errMsg != "" {
|
|
return fmt.Errorf("%s", errMsg)
|
|
}
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|