Documentation
¶
Overview ¶
Package gocmd runs the go command.
Runner is the seam: ExecRunner runs the real binary, WithTimeout bounds any runner, and tests substitute a fake. A Runner returns an error only when go could not be run at all; a non-zero exit is reported in Result.Code.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNotFound = errors.New("go not installed")
ErrNotFound reports that the go command is not installed.
Functions ¶
func SignalCause ¶
SignalCause is the cause to cancel a context with (context.WithCancelCause) when sig ended the run. A process started on that context is then sent sig, not SIGTERM, and SignalOf tells which signal it was.
Types ¶
type Call ¶
type Call struct {
Dir string // child working directory
Env []string // KEY=VALUE pairs overriding the process environment
Args []string // arguments after "go"
}
Call is one invocation of the go command. The process working directory is never changed; Dir is applied to the child only.
type ExecProcessRunner ¶
type ExecProcessRunner struct{}
ExecProcessRunner runs the real program. The child stays in gotools' process group, so the terminal delivers Ctrl-C to it directly and it may read the terminal; cancelling the context sends it SIGTERM, and it is killed if it does not stop. If the context was cancelled with SignalCause, the child gets that signal, else SIGTERM.
type ExecRunner ¶
type ExecRunner struct {
Bin string // defaults to "go" from PATH
Verbose io.Writer // when set, " ↳ go <args>" is written before each call
// Env is KEY=VALUE pairs added to the environment of every call; a call's
// own Env still wins over it.
Env []string
}
ExecRunner runs the real go binary with stdin empty. The child gets its own process group, so cancelling stops the compiler and linker go spawns too.
type Process ¶
type Process struct {
Bin string // the program to run
Args []string // its arguments
Dir string // child working directory; the process's own when empty
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
}
Process is a child run with the caller's own streams, as exec runs a tool.
type ProcessRunner ¶
ProcessRunner runs a Process. The code is the child's exit status, 128+n when signal n killed it. The error is non-nil only when the child could not be run at all: a child stopped by the context reports its signal as the code.
type Runner ¶
Runner runs the go command. The error is non-nil only when go could not be run (ErrNotFound, a cancelled context, a *TimeoutError).
func WithTimeout ¶
WithTimeout returns a Runner whose calls are bounded by d. A d of 0 or less disables the bound. A context cancelled by the caller is reported as itself, not as a timeout.
Example ¶
A timeout bounds any runner, so the same code runs with the real go or a fake.
package main
import (
"context"
"fmt"
"time"
"github.com/piusalfred/gotools/internal/gocmd"
)
type slow struct{ d time.Duration }
func (s slow) Run(ctx context.Context, _ gocmd.Call) (gocmd.Result, error) {
select {
case <-time.After(s.d):
return gocmd.Result{}, nil
case <-ctx.Done():
return gocmd.Result{}, ctx.Err()
}
}
func main() {
var r gocmd.Runner = slow{time.Minute}
_, err := gocmd.WithTimeout(r, 10*time.Millisecond).
Run(context.Background(), gocmd.Call{Args: []string{"get", "-tool", "example.com/x"}})
fmt.Println(err)
}
Output: timed out after 10ms
type TimeoutError ¶
TimeoutError reports that a bounded run exceeded its limit.
func (*TimeoutError) Error ¶
func (e *TimeoutError) Error() string