package syw import ( "bytes" "context" "errors" "os/exec" "sync" ) var mut sync.Mutex var gitbinpath string func findbin() string { if gitbinpath == "" { mut.Lock() gitbinpath, _ = exec.LookPath("git") mut.Unlock() if gitbinpath == "" { panic("failed to find 'git' executable") } } return gitbinpath } func runCmd(ctx context.Context, args []string) (*cmdResult, error) { cmd := exec.CommandContext(ctx, findbin(), args...) outbuf := &bytes.Buffer{} cmd.Stdout = outbuf errbuf := &bytes.Buffer{} cmd.Stderr = errbuf var eerr *exec.ExitError if err := cmd.Run(); err != nil && !errors.As(err, &eerr) { return nil, err } return &cmdResult{ status: cmd.ProcessState.ExitCode(), out: outbuf, err: errbuf, }, nil } type cmdResult struct { status int out *bytes.Buffer err *bytes.Buffer }