refactor: undo specific cmd invocation

This commit is contained in:
Jan De Dobbeleer 2021-12-19 16:42:39 +01:00 committed by Jan De Dobbeleer
parent 12ec9a1738
commit b400f05555

View file

@ -1,10 +1,10 @@
package main
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
@ -13,7 +13,6 @@ import (
"path/filepath"
"runtime"
"strings"
"sync"
"time"
"github.com/distatus/battery"
@ -291,70 +290,19 @@ func (env *environment) runCommand(command string, args ...string) (string, erro
if cmd, ok := env.cmdCache.get(command); ok {
command = cmd
}
copyAndCapture := func(r io.Reader) ([]byte, error) {
var out []byte
buf := make([]byte, 1024)
for {
n, err := r.Read(buf)
if n > 0 {
d := buf[:n]
out = append(out, d...)
}
if err == nil {
continue
}
// Read returns io.EOF at the end of file, which is not an error for us
if err == io.EOF {
err = nil
}
return out, err
}
}
normalizeOutput := func(out []byte) string {
return strings.TrimSuffix(string(out), "\n")
}
cmd := exec.Command(command, args...)
var stdout, stderr []byte
var stdoutErr, stderrErr error
stdoutIn, _ := cmd.StdoutPipe()
stderrIn, _ := cmd.StderrPipe()
err := cmd.Start()
if err != nil {
errorStr := fmt.Sprintf("cmd.Start() failed with '%s'", err)
var out bytes.Buffer
var err bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &err
cmdErr := cmd.Run()
if cmdErr != nil {
output := err.String()
errorStr := fmt.Sprintf("cmd.Start() failed with '%s'", output)
env.log(Error, "runCommand", errorStr)
return "", errors.New(errorStr)
return output, cmdErr
}
// cmd.Wait() should be called only after we finish reading
// from stdoutIn and stderrIn.
// wg ensures that we finish
var wg sync.WaitGroup
wg.Add(1)
go func() {
stdout, stdoutErr = copyAndCapture(stdoutIn)
wg.Done()
}()
stderr, stderrErr = copyAndCapture(stderrIn)
wg.Wait()
err = cmd.Wait()
if err != nil {
env.log(Error, "runCommand", err.Error())
if exitErr, ok := err.(*exec.ExitError); ok {
return "", &commandError{
err: exitErr.Error(),
exitCode: exitErr.ExitCode(),
}
}
}
if stdoutErr != nil || stderrErr != nil {
errString := "failed to capture stdout or stderr"
env.log(Error, "runCommand", errString)
return "", errors.New(errString)
}
stderrStr := normalizeOutput(stderr)
if len(stderrStr) > 0 {
return stderrStr, nil
}
output := normalizeOutput(stdout)
output := strings.TrimSuffix(out.String(), "\n")
env.log(Debug, "runCommand", output)
return output, nil
}