aboutsummaryrefslogtreecommitdiffstats
path: root/ui/build/exec.go
diff options
context:
space:
mode:
Diffstat (limited to 'ui/build/exec.go')
-rw-r--r--ui/build/exec.go107
1 files changed, 107 insertions, 0 deletions
diff --git a/ui/build/exec.go b/ui/build/exec.go
new file mode 100644
index 00000000..4c45c507
--- /dev/null
+++ b/ui/build/exec.go
@@ -0,0 +1,107 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build
+
+import (
+ "os/exec"
+)
+
+// Cmd is a wrapper of os/exec.Cmd that integrates with the build context for
+// logging, the config's Environment for simpler environment modification, and
+// implements hooks for sandboxing
+type Cmd struct {
+ *exec.Cmd
+
+ Environment *Environment
+ Sandbox Sandbox
+
+ ctx Context
+ config Config
+ name string
+}
+
+func Command(ctx Context, config Config, name string, executable string, args ...string) *Cmd {
+ ret := &Cmd{
+ Cmd: exec.CommandContext(ctx.Context, executable, args...),
+ Environment: config.Environment().Copy(),
+ Sandbox: noSandbox,
+
+ ctx: ctx,
+ config: config,
+ name: name,
+ }
+
+ return ret
+}
+
+func (c *Cmd) prepare() {
+ if c.Env == nil {
+ c.Env = c.Environment.Environ()
+ }
+ if c.sandboxSupported() {
+ c.wrapSandbox()
+ }
+
+ c.ctx.Verboseln(c.Path, c.Args)
+}
+
+func (c *Cmd) Start() error {
+ c.prepare()
+ return c.Cmd.Start()
+}
+
+func (c *Cmd) Run() error {
+ c.prepare()
+ return c.Cmd.Run()
+}
+
+func (c *Cmd) Output() ([]byte, error) {
+ c.prepare()
+ return c.Cmd.Output()
+}
+
+func (c *Cmd) CombinedOutput() ([]byte, error) {
+ c.prepare()
+ return c.Cmd.CombinedOutput()
+}
+
+// StartOrFatal is equivalent to Start, but handles the error with a call to ctx.Fatal
+func (c *Cmd) StartOrFatal() {
+ if err := c.Start(); err != nil {
+ c.ctx.Fatalf("Failed to run %s: %v", c.name, err)
+ }
+}
+
+// RunOrFatal is equivalent to Run, but handles the error with a call to ctx.Fatal
+func (c *Cmd) RunOrFatal() {
+ if err := c.Run(); err != nil {
+ if e, ok := err.(*exec.ExitError); ok {
+ c.ctx.Fatalf("%s failed with: %v", c.name, e.ProcessState.String())
+ } else {
+ c.ctx.Fatalf("Failed to run %s: %v", c.name, err)
+ }
+ }
+}
+
+// WaitOrFatal is equivalent to Wait, but handles the error with a call to ctx.Fatal
+func (c *Cmd) WaitOrFatal() {
+ if err := c.Wait(); err != nil {
+ if e, ok := err.(*exec.ExitError); ok {
+ c.ctx.Fatalf("%s failed with: %v", c.name, e.ProcessState.String())
+ } else {
+ c.ctx.Fatalf("Failed to run %s: %v", c.name, err)
+ }
+ }
+}