stdin-from-command: implemented suggestions in #4254

The code has been refactored so that the archiver is back to the original code, and the stderr is handled using a go routine to avoid deadlock.
This commit is contained in:
Enrico204
2023-08-27 09:57:02 +02:00
committed by Michael Eischer
parent c133065a9f
commit 4e5caab114
3 changed files with 55 additions and 31 deletions

View File

@@ -2,9 +2,7 @@ package archiver
import (
"context"
"io"
"os"
"os/exec"
"path"
"runtime"
"sort"
@@ -683,8 +681,6 @@ type SnapshotOptions struct {
Time time.Time
ParentSnapshot *restic.Snapshot
ProgramVersion string
Command *exec.Cmd
CommandStderr io.ReadCloser
}
// loadParentTree loads a tree referenced by snapshot id. If id is null, nil is returned.
@@ -796,15 +792,6 @@ func (arch *Archiver) Snapshot(ctx context.Context, targets []string, opts Snaps
return nil, restic.ID{}, err
}
if opts.Command != nil {
errBytes, _ := io.ReadAll(opts.CommandStderr)
cmdErr := opts.Command.Wait()
if cmdErr != nil {
debug.Log("error while executing command: %v", cmdErr)
return nil, restic.ID{}, errors.New(string(errBytes))
}
}
sn, err := restic.NewSnapshot(targets, opts.Tags, opts.Hostname, opts.Time)
if err != nil {
return nil, restic.ID{}, err

View File

@@ -0,0 +1,23 @@
package fs
import (
"io"
"os/exec"
)
// ReadCloserCommand wraps an exec.Cmd and its standard output to provide an
// io.ReadCloser that waits for the command to terminate on Close(), reporting
// any error in the command.Wait() function back to the Close() caller.
type ReadCloserCommand struct {
Cmd *exec.Cmd
Stdout io.ReadCloser
}
func (fp *ReadCloserCommand) Read(p []byte) (n int, err error) {
return fp.Stdout.Read(p)
}
func (fp *ReadCloserCommand) Close() error {
// No need to close fp.Stdout as Wait() closes all pipes.
return fp.Cmd.Wait()
}