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
|
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{}
|
args := []string{}
|
||||||
if rcmd.GlobalOpts != nil {
|
if rcmd.GlobalOpts != nil {
|
||||||
args = rcmd.GlobalOpts.ToArgs()
|
args = rcmd.GlobalOpts.ToArgs()
|
||||||
@ -285,22 +289,22 @@ func (rcmd Restic) RunRestic(command string, options CommandOptions, commandArgs
|
|||||||
|
|
||||||
cmd := exec.Command("restic", args...)
|
cmd := exec.Command("restic", args...)
|
||||||
|
|
||||||
output := NewCapturedLogWriter(rcmd.Logger)
|
output := NewCapturedCommandLogWriter(rcmd.Logger)
|
||||||
cmd.Stdout = output
|
cmd.Stdout = output.Stdout
|
||||||
cmd.Stderr = output
|
cmd.Stderr = output.Stderr
|
||||||
cmd.Env = rcmd.BuildEnv()
|
cmd.Env = rcmd.BuildEnv()
|
||||||
cmd.Dir = rcmd.Cwd
|
cmd.Dir = rcmd.Cwd
|
||||||
|
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
responseErr := ErrRestic
|
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
|
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 {
|
func (rcmd Restic) Backup(files []string, opts BackupOpts) error {
|
||||||
@ -341,15 +345,18 @@ type Snapshot struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rcmd Restic) ReadSnapshots() ([]Snapshot, error) {
|
func (rcmd Restic) ReadSnapshots() ([]Snapshot, error) {
|
||||||
lines, err := rcmd.RunRestic("snapshots", GenericOpts{"--json"})
|
output, err := rcmd.RunRestic("snapshots", GenericOpts{"--json"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
snapshots := new([]Snapshot)
|
||||||
return nil, fmt.Errorf("failed parsing snapshot results from %s: %w", lines[0], err)
|
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
|
return *snapshots, nil
|
||||||
|
29
shell.go
29
shell.go
@ -5,6 +5,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ func NewCapturedLogWriter(logger *log.Logger) *CapturedLogWriter {
|
|||||||
return &CapturedLogWriter{Lines: []string{}, logger: logger}
|
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) {
|
func (w *CapturedLogWriter) Write(content []byte) (n int, err error) {
|
||||||
message := string(content)
|
message := string(content)
|
||||||
for _, line := range strings.Split(message, "\n") {
|
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
|
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 {
|
func RunShell(script string, cwd string, env map[string]string, logger *log.Logger) error {
|
||||||
cmd := exec.Command("sh", "-c", strings.TrimSpace(script)) //nolint:gosec
|
cmd := exec.Command("sh", "-c", strings.TrimSpace(script)) //nolint:gosec
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user