Split returned stdout and stderr from Restic commands to improve parsing
This commit is contained in:
parent
fed9224c17
commit
8a8bc23376
29
restic.go
29
restic.go
@ -273,7 +273,11 @@ func (e *ResticError) Unwrap() error {
|
||||
return e.OriginalError
|
||||
}
|
||||
|
||||
func (rcmd Restic) RunRestic(command string, options CommandOptions, commandArgs ...string) ([]string, error) {
|
||||
func (rcmd Restic) RunRestic(
|
||||
command string,
|
||||
options CommandOptions,
|
||||
commandArgs ...string,
|
||||
) (*CapturedCommandLogWriter, error) {
|
||||
args := []string{}
|
||||
if rcmd.GlobalOpts != nil {
|
||||
args = rcmd.GlobalOpts.ToArgs()
|
||||
@ -285,22 +289,22 @@ func (rcmd Restic) RunRestic(command string, options CommandOptions, commandArgs
|
||||
|
||||
cmd := exec.Command("restic", args...)
|
||||
|
||||
output := NewCapturedLogWriter(rcmd.Logger)
|
||||
cmd.Stdout = output
|
||||
cmd.Stderr = output
|
||||
output := NewCapturedCommandLogWriter(rcmd.Logger)
|
||||
cmd.Stdout = output.Stdout
|
||||
cmd.Stderr = output.Stderr
|
||||
cmd.Env = rcmd.BuildEnv()
|
||||
cmd.Dir = rcmd.Cwd
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
responseErr := ErrRestic
|
||||
if lineIn("Is there a repository at the following location?", output.Lines) {
|
||||
if lineIn("Is there a repository at the following location?", output.Stderr.Lines) {
|
||||
responseErr = ErrRepoNotFound
|
||||
}
|
||||
|
||||
return output.Lines, NewResticError(command, output.Lines, responseErr)
|
||||
return output, NewResticError(command, output.AllLines(), responseErr)
|
||||
}
|
||||
|
||||
return output.Lines, nil
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (rcmd Restic) Backup(files []string, opts BackupOpts) error {
|
||||
@ -341,15 +345,18 @@ type Snapshot struct {
|
||||
}
|
||||
|
||||
func (rcmd Restic) ReadSnapshots() ([]Snapshot, error) {
|
||||
lines, err := rcmd.RunRestic("snapshots", GenericOpts{"--json"})
|
||||
output, err := rcmd.RunRestic("snapshots", GenericOpts{"--json"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
snapshots := new([]Snapshot)
|
||||
if len(output.Stdout.Lines) == 0 {
|
||||
return nil, fmt.Errorf("no snapshot output to parse: %w", ErrRestic)
|
||||
}
|
||||
|
||||
if err = json.Unmarshal([]byte(lines[0]), snapshots); err != nil {
|
||||
return nil, fmt.Errorf("failed parsing snapshot results from %s: %w", lines[0], err)
|
||||
snapshots := new([]Snapshot)
|
||||
if err = json.Unmarshal([]byte(output.Stdout.Lines[0]), snapshots); err != nil {
|
||||
return nil, fmt.Errorf("failed parsing snapshot results from %s: %w", output.Stdout.Lines[0], err)
|
||||
}
|
||||
|
||||
return *snapshots, nil
|
||||
|
29
shell.go
29
shell.go
@ -5,6 +5,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -39,6 +40,7 @@ func NewCapturedLogWriter(logger *log.Logger) *CapturedLogWriter {
|
||||
return &CapturedLogWriter{Lines: []string{}, logger: logger}
|
||||
}
|
||||
|
||||
// Write writes the provided byte slice to the logger and stores each captured line.
|
||||
func (w *CapturedLogWriter) Write(content []byte) (n int, err error) {
|
||||
message := string(content)
|
||||
for _, line := range strings.Split(message, "\n") {
|
||||
@ -49,6 +51,33 @@ func (w *CapturedLogWriter) Write(content []byte) (n int, err error) {
|
||||
return len(content), nil
|
||||
}
|
||||
|
||||
// LinesMergedWith returns a slice of lines from this logger merged with another.
|
||||
func (w CapturedLogWriter) LinesMergedWith(other CapturedLogWriter) []string {
|
||||
allLines := []string{}
|
||||
allLines = append(allLines, w.Lines...)
|
||||
allLines = append(allLines, other.Lines...)
|
||||
|
||||
sort.Strings(allLines)
|
||||
|
||||
return allLines
|
||||
}
|
||||
|
||||
type CapturedCommandLogWriter struct {
|
||||
Stdout *CapturedLogWriter
|
||||
Stderr *CapturedLogWriter
|
||||
}
|
||||
|
||||
func NewCapturedCommandLogWriter(logger *log.Logger) *CapturedCommandLogWriter {
|
||||
return &CapturedCommandLogWriter{
|
||||
Stdout: NewCapturedLogWriter(logger),
|
||||
Stderr: NewCapturedLogWriter(logger),
|
||||
}
|
||||
}
|
||||
|
||||
func (cclw CapturedCommandLogWriter) AllLines() []string {
|
||||
return cclw.Stdout.LinesMergedWith(*cclw.Stderr)
|
||||
}
|
||||
|
||||
func RunShell(script string, cwd string, env map[string]string, logger *log.Logger) error {
|
||||
cmd := exec.Command("sh", "-c", strings.TrimSpace(script)) //nolint:gosec
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user