mirror of
https://github.com/schollz/cowyo.git
synced 2023-08-10 21:13:00 +03:00
73 lines
1.3 KiB
Go
73 lines
1.3 KiB
Go
|
// Package pipeutil provides additional functionality for gopkg.in/pipe.v2 package.
|
||
|
package pipeutil
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"os/exec"
|
||
|
"sync"
|
||
|
|
||
|
"gopkg.in/pipe.v2"
|
||
|
)
|
||
|
|
||
|
// ExecCombinedOutput returns a pipe that runs the named program with the given arguments,
|
||
|
// while forwarding stderr to stdout.
|
||
|
func ExecCombinedOutput(name string, args ...string) pipe.Pipe {
|
||
|
return func(s *pipe.State) error {
|
||
|
s.AddTask(&execCombinedOutputTask{name: name, args: args})
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type execCombinedOutputTask struct {
|
||
|
name string
|
||
|
args []string
|
||
|
|
||
|
m sync.Mutex
|
||
|
p *os.Process
|
||
|
cancel bool
|
||
|
}
|
||
|
|
||
|
func (f *execCombinedOutputTask) Run(s *pipe.State) error {
|
||
|
f.m.Lock()
|
||
|
if f.cancel {
|
||
|
f.m.Unlock()
|
||
|
return nil
|
||
|
}
|
||
|
cmd := exec.Command(f.name, f.args...)
|
||
|
cmd.Dir = s.Dir
|
||
|
cmd.Env = s.Env
|
||
|
cmd.Stdin = s.Stdin
|
||
|
cmd.Stdout = s.Stdout
|
||
|
cmd.Stderr = s.Stdout
|
||
|
err := cmd.Start()
|
||
|
f.p = cmd.Process
|
||
|
f.m.Unlock()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if err := cmd.Wait(); err != nil {
|
||
|
return &execError{f.name, err}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (f *execCombinedOutputTask) Kill() {
|
||
|
f.m.Lock()
|
||
|
p := f.p
|
||
|
f.cancel = true
|
||
|
f.m.Unlock()
|
||
|
if p != nil {
|
||
|
p.Kill()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type execError struct {
|
||
|
name string
|
||
|
err error
|
||
|
}
|
||
|
|
||
|
func (e *execError) Error() string {
|
||
|
return fmt.Sprintf("command %q: %v", e.name, e.err)
|
||
|
}
|