This commit adds and passes context around to (almost) every function. This allows cancelling (almost) every function call globally.
65 lines
1.4 KiB
Go
65 lines
1.4 KiB
Go
package environment
|
|
|
|
import (
|
|
"context"
|
|
"os/exec"
|
|
|
|
"github.com/FAU-CDI/wisski-distillery/pkg/cancel"
|
|
"github.com/tkw1536/goprogram/stream"
|
|
)
|
|
|
|
// Exec executes a system command with the specified input/output streams, working directory, and arguments.
|
|
//
|
|
// If the command executes, it's exit code will be returned.
|
|
// If the command can not be executed, returns [ExecCommandError].
|
|
func (*Native) Exec(ctx context.Context, io stream.IOStream, workdir string, exe string, argv ...string) int {
|
|
// setup the command
|
|
cmd := exec.Command(exe, argv...)
|
|
cmd.Dir = workdir
|
|
cmd.Stdin = io.Stdin
|
|
cmd.Stdout = io.Stdout
|
|
cmd.Stderr = io.Stderr
|
|
|
|
// run the process in a cancelable fashion
|
|
err, cErr := cancel.WithContext(ctx, func(cancelable func()) error {
|
|
// start the process
|
|
err := cmd.Start()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// allow it to be cancellable
|
|
cancelable()
|
|
|
|
// and wait for the rest of the process
|
|
return cmd.Wait()
|
|
}, func() {
|
|
if cmd.Process != nil {
|
|
cmd.Process.Kill()
|
|
}
|
|
})
|
|
if err == nil {
|
|
err = cErr
|
|
}
|
|
|
|
// non-zero exit
|
|
if err, ok := err.(*exec.ExitError); ok {
|
|
return err.ExitCode()
|
|
}
|
|
|
|
// unknown error
|
|
if err != nil {
|
|
return ExecCommandError
|
|
}
|
|
|
|
// everything is fine!
|
|
return 0
|
|
}
|
|
|
|
func (n *Native) LookPathAbs(file string) (string, error) {
|
|
path, err := exec.LookPath(file)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return n.Abs(path)
|
|
}
|