1
0
mirror of https://github.com/golang/go synced 2024-10-01 13:18:33 -06:00
go/dashboard/builder/exec.go
Brad Fitzpatrick cd91e8d096 dashboard/builder: modernize ancient exec wrappers
They were from a time before we had the os/exec package, if
memory serves.

Also, make verbose also mean that the main build's stdout
and stderr go to the real stdout and stderr as well.
I'll want that for the Docker-based builder.

LGTM=adg
R=adg
CC=golang-codereviews
https://golang.org/cl/135000043
2014-08-28 14:58:15 -07:00

99 lines
1.9 KiB
Go

// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"io"
"log"
"os/exec"
"time"
)
// run runs a command with optional arguments.
func run(cmd *exec.Cmd, opts ...runOpt) error {
a := runArgs{cmd, *cmdTimeout}
for _, opt := range opts {
opt.modArgs(&a)
}
if *verbose {
log.Printf("running %v", a.cmd.Args)
}
if err := cmd.Start(); err != nil {
return err
}
err := timeout(a.timeout, cmd.Wait)
if _, ok := err.(timeoutError); ok {
cmd.Process.Kill()
}
return err
}
// Zero or more runOpts can be passed to run to modify the command
// before it's run.
type runOpt interface {
modArgs(*runArgs)
}
// allOutput sends both stdout and stderr to w.
func allOutput(w io.Writer) optFunc {
return func(a *runArgs) {
a.cmd.Stdout = w
a.cmd.Stderr = w
}
}
func runTimeout(timeout time.Duration) optFunc {
return func(a *runArgs) {
a.timeout = timeout
}
}
func runDir(dir string) optFunc {
return func(a *runArgs) {
a.cmd.Dir = dir
}
}
func runEnv(env []string) optFunc {
return func(a *runArgs) {
a.cmd.Env = env
}
}
// timeout runs f and returns its error value, or if the function does not
// complete before the provided duration it returns a timeout error.
func timeout(d time.Duration, f func() error) error {
errc := make(chan error, 1)
go func() {
errc <- f()
}()
t := time.NewTimer(d)
defer t.Stop()
select {
case <-t.C:
return timeoutError(d)
case err := <-errc:
return err
}
}
type timeoutError time.Duration
func (e timeoutError) Error() string {
return fmt.Sprintf("timed out after %v", time.Duration(e))
}
// optFunc implements runOpt with a function, like http.HandlerFunc.
type optFunc func(*runArgs)
func (f optFunc) modArgs(a *runArgs) { f(a) }
// internal detail to exec.go:
type runArgs struct {
cmd *exec.Cmd
timeout time.Duration
}