Extracted duplicate bd command execution pattern from mailbox.go and router.go into a new helper function in bd.go. This reduces code duplication and provides consistent error handling via the bdError type. Changes: - Added internal/mail/bd.go with runBdCommand helper and bdError type - Refactored 5 functions in mailbox.go to use runBdCommand - Refactored 5 functions in router.go to use runBdCommand - Net reduction of 55 lines of code 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
63 lines
1.6 KiB
Go
63 lines
1.6 KiB
Go
package mail
|
|
|
|
import (
|
|
"bytes"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// bdError represents an error from running a bd command.
|
|
// It wraps the underlying error and includes the stderr output for inspection.
|
|
type bdError struct {
|
|
Err error
|
|
Stderr string
|
|
}
|
|
|
|
// Error implements the error interface.
|
|
func (e *bdError) Error() string {
|
|
if e.Stderr != "" {
|
|
return e.Stderr
|
|
}
|
|
if e.Err != nil {
|
|
return e.Err.Error()
|
|
}
|
|
return "unknown bd error"
|
|
}
|
|
|
|
// Unwrap returns the underlying error for errors.Is/As compatibility.
|
|
func (e *bdError) Unwrap() error {
|
|
return e.Err
|
|
}
|
|
|
|
// ContainsError checks if the stderr message contains the given substring.
|
|
func (e *bdError) ContainsError(substr string) bool {
|
|
return strings.Contains(e.Stderr, substr)
|
|
}
|
|
|
|
// runBdCommand executes a bd command with proper environment setup.
|
|
// workDir is the directory to run the command in.
|
|
// beadsDir is the BEADS_DIR environment variable value.
|
|
// extraEnv contains additional environment variables to set (e.g., "BD_IDENTITY=...").
|
|
// Returns stdout bytes on success, or a *bdError on failure.
|
|
func runBdCommand(args []string, workDir, beadsDir string, extraEnv ...string) ([]byte, error) {
|
|
cmd := exec.Command("bd", args...) //nolint:gosec // G204: bd is a trusted internal tool
|
|
cmd.Dir = workDir
|
|
|
|
env := append(cmd.Environ(), "BEADS_DIR="+beadsDir)
|
|
env = append(env, extraEnv...)
|
|
cmd.Env = env
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
cmd.Stdout = &stdout
|
|
cmd.Stderr = &stderr
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
return nil, &bdError{
|
|
Err: err,
|
|
Stderr: strings.TrimSpace(stderr.String()),
|
|
}
|
|
}
|
|
|
|
return stdout.Bytes(), nil
|
|
}
|