mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-11-26 09:00:57 +02:00
Removed github.com/ionrock/procs for better code coverage
This commit is contained in:
parent
9a99748d3b
commit
ed564adb4a
@ -5,10 +5,10 @@ package commands
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
|
||||
"github.com/ionrock/procs"
|
||||
"github.com/kr/pty"
|
||||
"github.com/mgutz/str"
|
||||
)
|
||||
@ -22,10 +22,8 @@ func RunCommandWithOutputLiveWrapper(c *OSCommand, command string, output func(s
|
||||
splitCmd := str.ToArgv(command)
|
||||
cmd := exec.Command(splitCmd[0], splitCmd[1:]...)
|
||||
|
||||
cmd.Env = procs.Env(map[string]string{
|
||||
"LANG": "en_US.utf8",
|
||||
"LC_ALL": "en_US.UTF-8",
|
||||
}, true)
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(cmd.Env, "LANG=en_US.utf8", "LC_ALL=en_US.UTF-8")
|
||||
|
||||
tty, err := pty.Start(cmd)
|
||||
|
||||
|
30
vendor/github.com/ionrock/procs/Gopkg.toml
generated
vendored
30
vendor/github.com/ionrock/procs/Gopkg.toml
generated
vendored
@ -1,30 +0,0 @@
|
||||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/apoydence/onpar"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/flynn/go-shlex"
|
13
vendor/github.com/ionrock/procs/LICENSE.md
generated
vendored
13
vendor/github.com/ionrock/procs/LICENSE.md
generated
vendored
@ -1,13 +0,0 @@
|
||||
Copyright 2017 Eric Larson <eric@ionrock.org>
|
||||
|
||||
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.
|
32
vendor/github.com/ionrock/procs/Makefile
generated
vendored
32
vendor/github.com/ionrock/procs/Makefile
generated
vendored
@ -1,32 +0,0 @@
|
||||
SOURCEDIR=.
|
||||
SOURCES := $(shell find $(SOURCEDIR) -name '*.go')
|
||||
|
||||
test: dep
|
||||
dep ensure
|
||||
go test .
|
||||
|
||||
race: dep
|
||||
dep ensure
|
||||
go test -race .
|
||||
|
||||
|
||||
dep:
|
||||
ifeq (, $(shell which dep))
|
||||
go get -u github.com/golang/dep/cmd/dep
|
||||
endif
|
||||
|
||||
all: prelog cmdtmpl procmon
|
||||
|
||||
prelog: $(SOURCES)
|
||||
go build ./cmd/prelog
|
||||
|
||||
cmdtmpl: $(SOURCES)
|
||||
go build ./cmd/cmdtmpl
|
||||
|
||||
procmon: $(SOURCES)
|
||||
go build ./cmd/procmon
|
||||
|
||||
clean:
|
||||
rm -f prelog
|
||||
rm -f cmdtmpl
|
||||
rm -f procmon
|
168
vendor/github.com/ionrock/procs/README.md
generated
vendored
168
vendor/github.com/ionrock/procs/README.md
generated
vendored
@ -1,168 +0,0 @@
|
||||
# Procs
|
||||
|
||||
[![](https://travis-ci.org/ionrock/procs.svg?branch=master)](https://travis-ci.org/ionrock/procs)
|
||||
[![Go Report Card](https://goreportcard.com/badge/github.com/ionrock/procs)](https://goreportcard.com/report/github.com/ionrock/procs)
|
||||
[![GoDoc](https://godoc.org/github.com/ionrock/procs?status.svg)](https://godoc.org/github.com/ionrock/procs)
|
||||
|
||||
Procs is a library to make working with command line applications a
|
||||
little nicer.
|
||||
|
||||
The primary use case is when you have to use a command line client in
|
||||
place of an API. Often times you want to do things like output stdout
|
||||
within your own logs or ensure that every time the command is called,
|
||||
there are a standard set of flags that are used.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
The majority of this functionality is intended to be included the
|
||||
procs.Process.
|
||||
|
||||
### Defining a Command
|
||||
|
||||
A command can be defined by a string rather than a []string. Normally,
|
||||
this also implies that the library will run the command in a shell,
|
||||
exposing a potential man in the middle attack. Rather than using a
|
||||
shell, procs [lexically
|
||||
parses](https://github.com/flynn-archive/go-shlex) the command for the
|
||||
different arguments. It also allows for pipes in order to string
|
||||
commands together.
|
||||
|
||||
```go
|
||||
p := procs.NewProcess("kubectl get events | grep dev")
|
||||
```
|
||||
|
||||
You can also define a new `Process` by passing in predefined commands.
|
||||
|
||||
```go
|
||||
cmds := []*exec.Cmd{
|
||||
exec.Command("kubectl", "get", "events"),
|
||||
exec.Command("grep", "dev"),
|
||||
}
|
||||
|
||||
p := procs.Process{Cmds: cmds}
|
||||
```
|
||||
|
||||
### Output Handling
|
||||
|
||||
One use case that is cumbersome is using the piped output from a
|
||||
command. For example, lets say we wanted to start a couple commands
|
||||
and have each command have its own prefix in stdout, while still
|
||||
capturing the output of the command as-is.
|
||||
|
||||
```go
|
||||
p := procs.NewProcess("cmd1")
|
||||
p.OutputHandler = func(line string) string {
|
||||
fmt.Printf("cmd1 | %s\n")
|
||||
return line
|
||||
}
|
||||
out, _ := p.Run()
|
||||
fmt.Println(out)
|
||||
```
|
||||
|
||||
Whatever is returned from the `OutputHandler` will be in the buffered
|
||||
output. In this way you can choose to filter or skip output buffering
|
||||
completely.
|
||||
|
||||
You can also define a `ErrHandler` using the same signature to get the
|
||||
same filtering for stderr.
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Rather than use the `exec.Cmd` `[]string` environment variables, a
|
||||
`procs.Process` uses a `map[string]string` for environment variables.
|
||||
|
||||
```go
|
||||
p := procs.NewProcess("echo $FOO")
|
||||
p.Env = map[string]string{"FOO": "foo"}
|
||||
```
|
||||
|
||||
Also, environment variables defined by the `Process.Env` can be
|
||||
expanded automatically using the `os.Expand` semantics and the
|
||||
provided environment.
|
||||
|
||||
There is a `ParseEnv` function that can help to merge the parent
|
||||
processes' environment with any new values.
|
||||
|
||||
```go
|
||||
env := ParseEnv(os.Environ())
|
||||
env["USER"] = "foo"
|
||||
```
|
||||
|
||||
Finally, if you are building commands manually, the `Env` function can
|
||||
take a `map[string]string` and convert it to a `[]string` for use with
|
||||
an `exec.Cmd`. The `Env` function also accepts a `useEnv` bool to help
|
||||
include the parent process environment.
|
||||
|
||||
```go
|
||||
cmd := exec.Command("knife", "cookbook", "show", cb)
|
||||
cmd.Env = Env(map[string]string{"USER": "knife-user"}, true)
|
||||
```
|
||||
|
||||
## Example Applications
|
||||
|
||||
Take a look in the [`cmd`](./cmd/) dir for some simple applications
|
||||
that use the library. You can also `make all` to build them. The
|
||||
examples below assume you've built them locally.
|
||||
|
||||
### Prelog
|
||||
|
||||
The `prelog` command allows running a command and prefixing the output
|
||||
with a value.
|
||||
|
||||
```bash
|
||||
$ ./prelog -prefix foo -- echo 'hello world!'
|
||||
Running the command
|
||||
foo | hello world!
|
||||
Accessing the output without a prefix.
|
||||
hello world!
|
||||
Running the command with Start / Wait
|
||||
foo | hello world!
|
||||
```
|
||||
|
||||
### Cmdtmpl
|
||||
|
||||
The `cmdtmpl` command uses the `procs.Builder` to create a command
|
||||
based on some paramters. It will take a `data.yml` file and
|
||||
`template.yml` file to create a command.
|
||||
|
||||
```bash
|
||||
$ cat example/data.json
|
||||
{
|
||||
"source": "https://my.example.org",
|
||||
"user": "foo",
|
||||
"model": "widget",
|
||||
"action": "create",
|
||||
"args": "-f new -i improved"
|
||||
}
|
||||
$ cat example/template.json
|
||||
[
|
||||
"mysvc ${model} ${action} ${args}",
|
||||
"--endpoint ${source}",
|
||||
"--username ${user}"
|
||||
]
|
||||
$ ./cmdtmpl -data example/data.json -template example/template.json
|
||||
Command: mysvc foo widget create -f new -i imporoved --endpoint https://my.example.org --username foo
|
||||
$ ./cmdtmpl -data example/data.json -template example/template.json -field user=bar
|
||||
Command: mysvc foo widget create -f new -i imporoved --endpoint https://my.example.org --username bar
|
||||
```
|
||||
|
||||
### Procmon
|
||||
|
||||
The `procmon` command acts like
|
||||
[foreman](https://github.com/ddollar/foreman) with the difference
|
||||
being it uses a JSON file with key value pairs instead of a
|
||||
Procfile. This example uses the `procs.Manager` to manage a set of
|
||||
`procs.Processes`.
|
||||
|
||||
```bash
|
||||
$ cat example/procfile.json
|
||||
{
|
||||
"web": "python -m SimpleHTTPServer"
|
||||
}
|
||||
$ ./procmon -procfile example/procfile.json
|
||||
web | Starting web with python -m SimpleHTTPServer
|
||||
```
|
||||
|
||||
You can then access http://localhost:8000 to see the logs. You can
|
||||
also kill the child process and see `procmon` recognizing it has
|
||||
exited and exit itself.
|
58
vendor/github.com/ionrock/procs/builder.go
generated
vendored
58
vendor/github.com/ionrock/procs/builder.go
generated
vendored
@ -1,58 +0,0 @@
|
||||
package procs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Builder helps construct commands using templates.
|
||||
type Builder struct {
|
||||
Context map[string]string
|
||||
Templates []string
|
||||
}
|
||||
|
||||
func (b *Builder) getConfig(ctx map[string]string) func(string) string {
|
||||
return func(key string) string {
|
||||
if v, ok := ctx[key]; ok {
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Builder) expand(v string, ctx map[string]string) string {
|
||||
return os.Expand(v, b.getConfig(ctx))
|
||||
}
|
||||
|
||||
// Command returns the result of the templates as a single string.
|
||||
func (b *Builder) Command() string {
|
||||
parts := []string{}
|
||||
for _, t := range b.Templates {
|
||||
parts = append(parts, b.expand(t, b.Context))
|
||||
}
|
||||
|
||||
return strings.Join(parts, " ")
|
||||
}
|
||||
|
||||
// CommandContext returns the result of the templates as a single
|
||||
// string, but allows providing an environment context as a
|
||||
// map[string]string for expansions.
|
||||
func (b *Builder) CommandContext(ctx map[string]string) string {
|
||||
// Build our environment context by starting with our Builder
|
||||
// context and overlay the passed in context map.
|
||||
env := make(map[string]string)
|
||||
for k, v := range b.Context {
|
||||
env[k] = b.expand(v, b.Context)
|
||||
}
|
||||
|
||||
for k, v := range ctx {
|
||||
env[k] = b.expand(v, env)
|
||||
}
|
||||
|
||||
parts := []string{}
|
||||
for _, t := range b.Templates {
|
||||
parts = append(parts, b.expand(t, env))
|
||||
}
|
||||
|
||||
return strings.Join(parts, " ")
|
||||
}
|
58
vendor/github.com/ionrock/procs/builder_test.go
generated
vendored
58
vendor/github.com/ionrock/procs/builder_test.go
generated
vendored
@ -1,58 +0,0 @@
|
||||
package procs_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ionrock/procs"
|
||||
)
|
||||
|
||||
func TestCommandContext(t *testing.T) {
|
||||
b := &procs.Builder{
|
||||
Context: map[string]string{
|
||||
"options": "-Fj -s https://example.com/chef -k knife.pem",
|
||||
},
|
||||
|
||||
Templates: []string{
|
||||
"knife",
|
||||
"${model} ${action}",
|
||||
"${args}",
|
||||
"${options}",
|
||||
},
|
||||
}
|
||||
|
||||
cmd := b.CommandContext(map[string]string{
|
||||
"model": "data bag",
|
||||
"action": "from file",
|
||||
"args": "foo data_bags/foo/bar.json",
|
||||
})
|
||||
|
||||
expected := "knife data bag from file foo data_bags/foo/bar.json -Fj -s https://example.com/chef -k knife.pem"
|
||||
if cmd != expected {
|
||||
t.Fatalf("failed building command: %q != %q", cmd, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommand(t *testing.T) {
|
||||
b := &procs.Builder{
|
||||
Context: map[string]string{
|
||||
"options": "-Fj -s https://example.com/chef -k knife.pem",
|
||||
"model": "data bag",
|
||||
"action": "from file",
|
||||
"args": "foo data_bags/foo/bar.json",
|
||||
},
|
||||
|
||||
Templates: []string{
|
||||
"knife",
|
||||
"${model} ${action}",
|
||||
"${args}",
|
||||
"${options}",
|
||||
},
|
||||
}
|
||||
|
||||
cmd := b.CommandContext(map[string]string{})
|
||||
|
||||
expected := "knife data bag from file foo data_bags/foo/bar.json -Fj -s https://example.com/chef -k knife.pem"
|
||||
if cmd != expected {
|
||||
t.Fatalf("failed building command: %q != %q", cmd, expected)
|
||||
}
|
||||
}
|
48
vendor/github.com/ionrock/procs/env.go
generated
vendored
48
vendor/github.com/ionrock/procs/env.go
generated
vendored
@ -1,48 +0,0 @@
|
||||
package procs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParseEnv takes an environment []string and converts it to a map[string]string.
|
||||
func ParseEnv(environ []string) map[string]string {
|
||||
env := make(map[string]string)
|
||||
for _, e := range environ {
|
||||
pair := strings.SplitN(e, "=", 2)
|
||||
|
||||
// There is a chance we can get an env with empty values
|
||||
if len(pair) == 2 {
|
||||
env[pair[0]] = pair[1]
|
||||
}
|
||||
}
|
||||
return env
|
||||
}
|
||||
|
||||
// Env takes a map[string]string and converts it to a []string that
|
||||
// can be used with exec.Cmd. The useEnv boolean flag will include the
|
||||
// current process environment, overlaying the provided env
|
||||
// map[string]string.
|
||||
func Env(env map[string]string, useEnv bool) []string {
|
||||
envlist := []string{}
|
||||
|
||||
// update our env by loading our env and overriding any values in
|
||||
// the provided env.
|
||||
if useEnv {
|
||||
environ := ParseEnv(os.Environ())
|
||||
for k, v := range env {
|
||||
environ[k] = v
|
||||
}
|
||||
env = environ
|
||||
}
|
||||
|
||||
for key, val := range env {
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
envlist = append(envlist, fmt.Sprintf("%s=%s", key, val))
|
||||
}
|
||||
|
||||
return envlist
|
||||
}
|
83
vendor/github.com/ionrock/procs/env_test.go
generated
vendored
83
vendor/github.com/ionrock/procs/env_test.go
generated
vendored
@ -1,83 +0,0 @@
|
||||
package procs_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ionrock/procs"
|
||||
)
|
||||
|
||||
func TestParseEnv(t *testing.T) {
|
||||
env := []string{
|
||||
"FOO=bar",
|
||||
"BAZ=`echo 'hello=world'`",
|
||||
}
|
||||
|
||||
m := procs.ParseEnv(env)
|
||||
|
||||
v, ok := m["FOO"]
|
||||
if !ok {
|
||||
t.Errorf("error missing FOO from env: %#v", m)
|
||||
}
|
||||
|
||||
if v != "bar" {
|
||||
t.Errorf("error FOO != bar: %s", v)
|
||||
}
|
||||
|
||||
v, ok = m["BAZ"]
|
||||
|
||||
if !ok {
|
||||
t.Errorf("error missing BAZ from env: %#v", m)
|
||||
}
|
||||
|
||||
expectBaz := "`echo 'hello=world'`"
|
||||
if v != expectBaz {
|
||||
t.Errorf("error BAZ != %s: %s", expectBaz, v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvBuilder(t *testing.T) {
|
||||
env := procs.Env(map[string]string{
|
||||
"FOO": "bar",
|
||||
"BAZ": "hello world",
|
||||
}, false)
|
||||
|
||||
if len(env) != 2 {
|
||||
t.Errorf("error loading env: %s", env)
|
||||
}
|
||||
}
|
||||
|
||||
func helperEnvCommand(env map[string]string) *exec.Cmd {
|
||||
cmd := exec.Command(os.Args[0], "-test.run=TestEnvBuilderOverrides")
|
||||
cmd.Env = procs.Env(env, false)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func TestEnvBuilderOverrides(t *testing.T) {
|
||||
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
||||
return
|
||||
}
|
||||
for _, envvar := range procs.Env(map[string]string{"FOO": "override"}, true) {
|
||||
fmt.Println(envvar)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvBuilderWithEnv(t *testing.T) {
|
||||
cmd := helperEnvCommand(map[string]string{
|
||||
"GO_WANT_HELPER_PROCESS": "1",
|
||||
"FOO": "default",
|
||||
})
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
t.Fatalf("error running helper: %s", err)
|
||||
}
|
||||
|
||||
env := procs.ParseEnv(strings.Split(string(out), "\n"))
|
||||
|
||||
if env["FOO"] != "override" {
|
||||
t.Errorf("error overriding envvar: %s", string(out))
|
||||
}
|
||||
}
|
33
vendor/github.com/ionrock/procs/example_basic_test.go
generated
vendored
33
vendor/github.com/ionrock/procs/example_basic_test.go
generated
vendored
@ -1,33 +0,0 @@
|
||||
package procs_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ionrock/procs"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
|
||||
b := procs.Builder{
|
||||
Context: map[string]string{
|
||||
"NAME": "eric",
|
||||
},
|
||||
Templates: []string{
|
||||
"echo $NAME |",
|
||||
"grep $NAME",
|
||||
},
|
||||
}
|
||||
|
||||
cmd := b.Command()
|
||||
|
||||
fmt.Println(cmd)
|
||||
|
||||
p := procs.NewProcess(cmd)
|
||||
|
||||
p.Run()
|
||||
out, _ := p.Output()
|
||||
fmt.Println(string(out))
|
||||
// Output:
|
||||
// echo eric | grep eric
|
||||
// eric
|
||||
}
|
23
vendor/github.com/ionrock/procs/example_predefined_cmds_test.go
generated
vendored
23
vendor/github.com/ionrock/procs/example_predefined_cmds_test.go
generated
vendored
@ -1,23 +0,0 @@
|
||||
package procs_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
|
||||
"github.com/ionrock/procs"
|
||||
)
|
||||
|
||||
func Example_predefinedCmds() {
|
||||
p := procs.Process{
|
||||
Cmds: []*exec.Cmd{
|
||||
exec.Command("echo", "foo"),
|
||||
exec.Command("grep", "foo"),
|
||||
},
|
||||
}
|
||||
|
||||
p.Run()
|
||||
out, _ := p.Output()
|
||||
fmt.Println(string(out))
|
||||
// Output:
|
||||
// foo
|
||||
}
|
43
vendor/github.com/ionrock/procs/examples_test.go
generated
vendored
43
vendor/github.com/ionrock/procs/examples_test.go
generated
vendored
@ -1,43 +0,0 @@
|
||||
package procs_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ionrock/procs"
|
||||
)
|
||||
|
||||
func ExampleSplitCommand() {
|
||||
parts := procs.SplitCommand("echo 'hello world'")
|
||||
for i, p := range parts {
|
||||
fmt.Printf("%d %s\n", i+1, p)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 1 echo
|
||||
// 2 hello world
|
||||
}
|
||||
|
||||
func ExampleSplitCommandEnv() {
|
||||
env := map[string]string{
|
||||
"GREETING": "hello",
|
||||
"NAME": "world!",
|
||||
"PASSWORD": "secret",
|
||||
}
|
||||
|
||||
getenv := func(key string) string {
|
||||
if v, ok := env[key]; ok && key != "PASSWORD" {
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
parts := procs.SplitCommandEnv("echo '$GREETING $NAME $PASSWORD'", getenv)
|
||||
|
||||
for i, p := range parts {
|
||||
fmt.Printf("%d %s\n", i+1, p)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 1 echo
|
||||
// 2 hello world!
|
||||
}
|
119
vendor/github.com/ionrock/procs/manager.go
generated
vendored
119
vendor/github.com/ionrock/procs/manager.go
generated
vendored
@ -1,119 +0,0 @@
|
||||
package procs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Manager manages a set of Processes.
|
||||
type Manager struct {
|
||||
Processes map[string]*Process
|
||||
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// NewManager creates a new *Manager.
|
||||
func NewManager() *Manager {
|
||||
return &Manager{
|
||||
Processes: make(map[string]*Process),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// StdoutHandler returns an OutHandler that will ensure the underlying
|
||||
// process has an empty stdout buffer and logs to stdout a prefixed value
|
||||
// of "$name | $line".
|
||||
func (m *Manager) StdoutHandler(name string) OutHandler {
|
||||
return func(line string) string {
|
||||
fmt.Printf("%s | %s\n", name, line)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// StderrHandler returns an OutHandler that will ensure the underlying
|
||||
// process has an empty stderr buffer and logs to stdout a prefixed value
|
||||
// of "$name | $line".
|
||||
func (m *Manager) StderrHandler(name string) OutHandler {
|
||||
return func(line string) string {
|
||||
fmt.Printf("%s | %s\n", name, line)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// Start and managed a new process using the default handlers from a
|
||||
// string.
|
||||
func (m *Manager) Start(name, cmd string) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
p := NewProcess(cmd)
|
||||
p.OutputHandler = m.StdoutHandler(name)
|
||||
p.ErrHandler = m.StderrHandler(name)
|
||||
err := p.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Processes[name] = p
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartProcess starts and manages a predifined process.
|
||||
func (m *Manager) StartProcess(name string, p *Process) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
err := p.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Processes[name] = p
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop will try to stop a managed process. If the process does not
|
||||
// exist, no error is returned.
|
||||
func (m *Manager) Stop(name string) error {
|
||||
p, ok := m.Processes[name]
|
||||
// We don't mind stopping a process that doesn't exist.
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return p.Stop()
|
||||
}
|
||||
|
||||
// Remove will try to stop and remove a managed process.
|
||||
func (m *Manager) Remove(name string) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
err := m.Stop(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Note that if the stop fails we don't remove it from the map of
|
||||
// processes to avoid losing the reference.
|
||||
delete(m.Processes, name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Wait will block until all managed processes have finished.
|
||||
func (m *Manager) Wait() error {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(len(m.Processes))
|
||||
|
||||
for _, p := range m.Processes {
|
||||
go func(proc *Process) {
|
||||
defer wg.Done()
|
||||
proc.Wait()
|
||||
}(p)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
55
vendor/github.com/ionrock/procs/manager_test.go
generated
vendored
55
vendor/github.com/ionrock/procs/manager_test.go
generated
vendored
@ -1,55 +0,0 @@
|
||||
package procs_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/ionrock/procs"
|
||||
)
|
||||
|
||||
func TestManagerStartHelper(t *testing.T) {
|
||||
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
||||
return
|
||||
}
|
||||
|
||||
port := flag.String("p", "12212", "port to serve on")
|
||||
directory := flag.String("d", ".", "the directory of static file to host")
|
||||
flag.Parse()
|
||||
|
||||
http.Handle("/", http.FileServer(http.Dir(*directory)))
|
||||
|
||||
log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
|
||||
log.Fatal(http.ListenAndServe(":"+*port, nil))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func TestManagerStart(t *testing.T) {
|
||||
m := procs.NewManager()
|
||||
|
||||
err := m.Start("test", fmt.Sprintf("%s -test.run=TestManagerStartHelper", os.Args[0]))
|
||||
if err != nil {
|
||||
t.Errorf("failed to start test process: %s", err)
|
||||
}
|
||||
|
||||
if len(m.Processes) != 1 {
|
||||
t.Error("failed to add process")
|
||||
}
|
||||
|
||||
err = m.Stop("test")
|
||||
if err != nil {
|
||||
t.Errorf("error stopping process: %s", err)
|
||||
}
|
||||
|
||||
err = m.Remove("test")
|
||||
if err != nil {
|
||||
t.Errorf("error removing process: %s", err)
|
||||
}
|
||||
|
||||
if len(m.Processes) != 0 {
|
||||
t.Error("failed to remove processes")
|
||||
}
|
||||
}
|
36
vendor/github.com/ionrock/procs/parse.go
generated
vendored
36
vendor/github.com/ionrock/procs/parse.go
generated
vendored
@ -1,36 +0,0 @@
|
||||
package procs
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
shlex "github.com/flynn/go-shlex"
|
||||
)
|
||||
|
||||
// SplitCommand parses a command and splits it into lexical arguments
|
||||
// like a shell, returning a []string that can be used as arguments to
|
||||
// exec.Command.
|
||||
func SplitCommand(cmd string) []string {
|
||||
return SplitCommandEnv(cmd, nil)
|
||||
}
|
||||
|
||||
// SplitCommandEnv parses a command and splits it into lexical
|
||||
// arguments like a shell, returning a []string that can be used as
|
||||
// arguments to exec.Command. It also allows providing an expansion
|
||||
// function that will be used when expanding values within the parsed
|
||||
// arguments.
|
||||
func SplitCommandEnv(cmd string, getenv func(key string) string) []string {
|
||||
parts, err := shlex.Split(strings.TrimSpace(cmd))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if getenv != nil {
|
||||
for i, p := range parts {
|
||||
parts[i] = os.Expand(p, getenv)
|
||||
}
|
||||
}
|
||||
|
||||
return parts
|
||||
}
|
44
vendor/github.com/ionrock/procs/parse_test.go
generated
vendored
44
vendor/github.com/ionrock/procs/parse_test.go
generated
vendored
@ -1,44 +0,0 @@
|
||||
package procs_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/apoydence/onpar"
|
||||
. "github.com/apoydence/onpar/expect"
|
||||
. "github.com/apoydence/onpar/matchers"
|
||||
"github.com/ionrock/procs"
|
||||
)
|
||||
|
||||
func matchSplitCommand(t *testing.T, parts, expected []string) {
|
||||
for i, part := range parts {
|
||||
Expect(t, part).To(Equal(expected[i]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitCommand(t *testing.T) {
|
||||
o := onpar.New()
|
||||
defer o.Run(t)
|
||||
|
||||
o.Group("split with pipe", func() {
|
||||
o.BeforeEach(func(t *testing.T) (*testing.T, []string, []string) {
|
||||
parts := procs.SplitCommand("echo 'foo' | grep o")
|
||||
expected := []string{"echo", "foo", "|", "grep", "o"}
|
||||
return t, parts, expected
|
||||
})
|
||||
|
||||
o.Spec("pass with a pipe", matchSplitCommand)
|
||||
})
|
||||
|
||||
o.Group("replace with specific context", func() {
|
||||
o.BeforeEach(func(t *testing.T) (*testing.T, []string, []string) {
|
||||
parts := procs.SplitCommandEnv("echo ${FOO}", func(k string) string {
|
||||
return "bar"
|
||||
})
|
||||
|
||||
expected := []string{"echo", "bar"}
|
||||
return t, parts, expected
|
||||
})
|
||||
|
||||
o.Spec("expand values found in provided env", matchSplitCommand)
|
||||
})
|
||||
}
|
307
vendor/github.com/ionrock/procs/process.go
generated
vendored
307
vendor/github.com/ionrock/procs/process.go
generated
vendored
@ -1,307 +0,0 @@
|
||||
// Procs is a library to make working with command line applications a
|
||||
// little nicer.
|
||||
//
|
||||
// The goal is to expand on the os/exec package by providing some
|
||||
// features usually accomplished in a shell, without having to resort to
|
||||
// a shell. Procs also tries to make working with output simpler by
|
||||
// providing a simple line handler API over working with io pipes.
|
||||
//
|
||||
// Finally, while the hope is that procs provides some convenience, it
|
||||
// is also a goal to help make it easier to write more secure
|
||||
// code. For example, avoiding a shell and the ability to manage the
|
||||
// environment as a map[string]string are both measures that intend to
|
||||
// make it easier to accomplish things like avoiding outputting
|
||||
// secrets and opening the door for MITM attacks. With that said, it is
|
||||
// always important to consider the security implications, especially
|
||||
// when you are working with untrusted input or sensitive data.
|
||||
package procs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// OutHandler defines the interface for writing output handlers for
|
||||
// Process objects.
|
||||
type OutHandler func(string) string
|
||||
|
||||
// Process is intended to be used like exec.Cmd where possible.
|
||||
type Process struct {
|
||||
// CmdString takes a string and parses it into the relevant cmds
|
||||
CmdString string
|
||||
|
||||
// Cmds is the list of command delmited by pipes.
|
||||
Cmds []*exec.Cmd
|
||||
|
||||
// Env provides a map[string]string that can mutated before
|
||||
// running a command.
|
||||
Env map[string]string
|
||||
|
||||
// Dir defines the directory the command should run in. The
|
||||
// Default is the current dir.
|
||||
Dir string
|
||||
|
||||
// OutputHandler can be defined to perform any sort of processing
|
||||
// on the output. The simple interface is to accept a string (a
|
||||
// line of output) and return a string that will be included in the
|
||||
// buffered output and/or output written to stdout.'
|
||||
//
|
||||
// For example defining the Process as:
|
||||
//
|
||||
// prefix := "myapp"
|
||||
// p := &procs.Process{
|
||||
// OutputHandler: func(line string) string {
|
||||
// return fmt.Sprintf("%s | %s", prefix, line)
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// This would prefix the stdout lines with a "myapp | ".
|
||||
//
|
||||
// By the default, this function is nil and will be skipped, with
|
||||
// the unchanged line being added to the respective output buffer.
|
||||
OutputHandler OutHandler
|
||||
|
||||
// ErrHandler is a OutputHandler for stderr.
|
||||
ErrHandler OutHandler
|
||||
|
||||
// When no output is given, we'll buffer output in these vars.
|
||||
errBuffer bytes.Buffer
|
||||
outBuffer bytes.Buffer
|
||||
|
||||
// When a output handler is provided, we ensure we're handling a
|
||||
// single line at at time.
|
||||
outputWait *sync.WaitGroup
|
||||
}
|
||||
|
||||
// NewProcess creates a new *Process from a command string.
|
||||
//
|
||||
// It is assumed that the user will mutate the resulting *Process by
|
||||
// setting the necessary attributes.
|
||||
func NewProcess(command string) *Process {
|
||||
return &Process{CmdString: command}
|
||||
}
|
||||
|
||||
// internal expand method to use the proc env.
|
||||
func (p *Process) expand(s string) string {
|
||||
return os.Expand(s, func(key string) string {
|
||||
v, _ := p.Env[key]
|
||||
return v
|
||||
})
|
||||
}
|
||||
|
||||
// addCmd adds a new command to the list of commands, ensuring the Dir
|
||||
// and Env have been added to the underlying *exec.Cmd instances.
|
||||
func (p *Process) addCmd(cmdparts []string) {
|
||||
var cmd *exec.Cmd
|
||||
if len(cmdparts) == 1 {
|
||||
cmd = exec.Command(cmdparts[0])
|
||||
} else {
|
||||
cmd = exec.Command(cmdparts[0], cmdparts[1:]...)
|
||||
}
|
||||
|
||||
if p.Dir != "" {
|
||||
cmd.Dir = p.Dir
|
||||
}
|
||||
|
||||
if p.Env != nil {
|
||||
env := []string{}
|
||||
for k, v := range p.Env {
|
||||
env = append(env, fmt.Sprintf("%s=%s", k, p.expand(v)))
|
||||
}
|
||||
|
||||
cmd.Env = env
|
||||
}
|
||||
|
||||
p.Cmds = append(p.Cmds, cmd)
|
||||
}
|
||||
|
||||
// findCmds parses the CmdString to find the commands that should be
|
||||
// run by spliting the lexically parsed command by pipes ("|").
|
||||
func (p *Process) findCmds() {
|
||||
// Skip if the cmd set is already set. This allows manual creation
|
||||
// of piped commands.
|
||||
if len(p.Cmds) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if p.CmdString == "" {
|
||||
return
|
||||
}
|
||||
|
||||
parts := SplitCommand(p.CmdString)
|
||||
for i := range parts {
|
||||
parts[i] = p.expand(parts[i])
|
||||
}
|
||||
|
||||
cmd := []string{}
|
||||
for _, part := range parts {
|
||||
if part == "|" {
|
||||
p.addCmd(cmd)
|
||||
cmd = []string{}
|
||||
} else {
|
||||
cmd = append(cmd, part)
|
||||
}
|
||||
}
|
||||
|
||||
p.addCmd(cmd)
|
||||
}
|
||||
|
||||
// lineReader takes will read a line in the io.Reader and write to the
|
||||
// Process output buffer and use any OutputHandler that exists.
|
||||
func (p *Process) lineReader(wg *sync.WaitGroup, r io.Reader, w *bytes.Buffer, handler OutHandler) {
|
||||
defer wg.Done()
|
||||
|
||||
reader := bufio.NewReader(r)
|
||||
var buffer bytes.Buffer
|
||||
|
||||
for {
|
||||
buf := make([]byte, 1024)
|
||||
|
||||
n, err := reader.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf = buf[:n]
|
||||
|
||||
for {
|
||||
i := bytes.IndexByte(buf, '\n')
|
||||
if i < 0 {
|
||||
break
|
||||
}
|
||||
|
||||
buffer.Write(buf[0:i])
|
||||
outLine := buffer.String()
|
||||
if handler != nil {
|
||||
outLine = handler(outLine)
|
||||
}
|
||||
w.WriteString(outLine)
|
||||
buffer.Reset()
|
||||
buf = buf[i+1:]
|
||||
}
|
||||
buffer.Write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
// checkErr shortens the creation of the pipes by bailing out with a
|
||||
// log.Fatal.
|
||||
func checkErr(msg string, err error) {
|
||||
if err != nil {
|
||||
log.Fatalf("%s: %s", msg, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Process) setupPipes() error {
|
||||
last := len(p.Cmds) - 1
|
||||
|
||||
if last != 0 {
|
||||
for i, cmd := range p.Cmds[:last] {
|
||||
var err error
|
||||
|
||||
p.Cmds[i+1].Stdin, err = cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
fmt.Printf("error creating stdout pipe: %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Stderr = &p.errBuffer
|
||||
}
|
||||
}
|
||||
|
||||
cmd := p.Cmds[last]
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
fmt.Printf("error creating stdout pipe: %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
fmt.Printf("error creating stderr pipe: %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
p.outputWait = new(sync.WaitGroup)
|
||||
p.outputWait.Add(2)
|
||||
|
||||
// These close the stdout/err channels
|
||||
go p.lineReader(p.outputWait, stdout, &p.outBuffer, p.OutputHandler)
|
||||
go p.lineReader(p.outputWait, stderr, &p.errBuffer, p.ErrHandler)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run executes the cmds and returns the output as a string and any error.
|
||||
func (p *Process) Run() error {
|
||||
if err := p.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Wait()
|
||||
}
|
||||
|
||||
// Start will start the list of cmds.
|
||||
func (p *Process) Start() error {
|
||||
p.findCmds()
|
||||
p.setupPipes()
|
||||
|
||||
for i, cmd := range p.Cmds {
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
defer func() {
|
||||
for _, precmd := range p.Cmds[0:i] {
|
||||
precmd.Wait()
|
||||
}
|
||||
}()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Wait will block, waiting for the commands to finish.
|
||||
func (p *Process) Wait() error {
|
||||
if p.outputWait != nil {
|
||||
p.outputWait.Wait()
|
||||
}
|
||||
|
||||
var err error
|
||||
for _, cmd := range p.Cmds {
|
||||
err = cmd.Wait()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Stop tries to stop the process.
|
||||
func (p *Process) Stop() error {
|
||||
for _, cmd := range p.Cmds {
|
||||
// ProcessState means it is already exited.
|
||||
if cmd.ProcessState != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
err := cmd.Process.Kill()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Output returns the buffered output as []byte.
|
||||
func (p *Process) Output() ([]byte, error) {
|
||||
return p.outBuffer.Bytes(), nil
|
||||
}
|
||||
|
||||
// ErrOutput returns the buffered stderr as []byte
|
||||
func (p *Process) ErrOutput() ([]byte, error) {
|
||||
return p.errBuffer.Bytes(), nil
|
||||
}
|
143
vendor/github.com/ionrock/procs/process_test.go
generated
vendored
143
vendor/github.com/ionrock/procs/process_test.go
generated
vendored
@ -1,143 +0,0 @@
|
||||
package procs_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
|
||||
"github.com/ionrock/procs"
|
||||
)
|
||||
|
||||
func newProcess() *procs.Process {
|
||||
return &procs.Process{
|
||||
Cmds: []*exec.Cmd{
|
||||
exec.Command("echo", "foo"),
|
||||
exec.Command("grep", "foo"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcess(t *testing.T) {
|
||||
p := newProcess()
|
||||
|
||||
err := p.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("error running program: %s", err)
|
||||
}
|
||||
|
||||
out, _ := p.Output()
|
||||
if !bytes.Equal(bytes.TrimSpace(out), []byte("foo")) {
|
||||
t.Errorf("wrong output: expected foo but got %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessWithOutput(t *testing.T) {
|
||||
p := newProcess()
|
||||
|
||||
p.OutputHandler = func(line string) string {
|
||||
return fmt.Sprintf("x | %s", line)
|
||||
}
|
||||
|
||||
err := p.Run()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error running program: %s", err)
|
||||
}
|
||||
expected := []byte("x | foo")
|
||||
out, _ := p.Output()
|
||||
if !bytes.Equal(bytes.TrimSpace(out), expected) {
|
||||
t.Errorf("wrong output: expected %q but got %q", expected, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessStartAndWait(t *testing.T) {
|
||||
p := newProcess()
|
||||
|
||||
p.Start()
|
||||
p.Wait()
|
||||
|
||||
out, _ := p.Output()
|
||||
expected := []byte("foo")
|
||||
if !bytes.Equal(bytes.TrimSpace(out), expected) {
|
||||
t.Errorf("wrong output: expected %q but got %q", expected, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessStartAndWaitWithOutput(t *testing.T) {
|
||||
p := newProcess()
|
||||
p.OutputHandler = func(line string) string {
|
||||
return fmt.Sprintf("x | %s", line)
|
||||
}
|
||||
|
||||
p.Start()
|
||||
p.Wait()
|
||||
|
||||
out, _ := p.Output()
|
||||
expected := []byte("x | foo")
|
||||
if !bytes.Equal(bytes.TrimSpace(out), expected) {
|
||||
t.Errorf("wrong output: expected %q but got %q", expected, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessFromString(t *testing.T) {
|
||||
p := procs.NewProcess("echo 'foo'")
|
||||
err := p.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("error running program: %s", err)
|
||||
}
|
||||
out, _ := p.Output()
|
||||
if !bytes.Equal(bytes.TrimSpace(out), []byte("foo")) {
|
||||
t.Errorf("wrong output: expected foo but got %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessFromStringWithPipe(t *testing.T) {
|
||||
p := procs.NewProcess("echo 'foo' | grep foo")
|
||||
err := p.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("error running program: %s", err)
|
||||
}
|
||||
|
||||
out, _ := p.Output()
|
||||
if !bytes.Equal(bytes.TrimSpace(out), []byte("foo")) {
|
||||
t.Errorf("wrong output: expected foo but got %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStderrOutput(t *testing.T) {
|
||||
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, "stdout output")
|
||||
fmt.Fprintln(os.Stderr, "stderr output")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func TestProcessPipeWithFailures(t *testing.T) {
|
||||
|
||||
// This will run a piped command with a failure part way
|
||||
// through. We want to be sure we get output on stderr.
|
||||
p := procs.NewProcess(fmt.Sprintf("echo 'foo' | %s -test.run=TestStderrOutput | grep foo", os.Args[0]))
|
||||
p.Env = map[string]string{"GO_WANT_HELPER_PROCESS": "1"}
|
||||
|
||||
err := p.Run()
|
||||
if err == nil {
|
||||
t.Fatal("expected error running program")
|
||||
|
||||
}
|
||||
|
||||
out, _ := p.Output()
|
||||
expected := []byte("") // expecting no output b/c the grep foo won't run
|
||||
if !bytes.Equal(out, expected) {
|
||||
t.Errorf("wrong stdout output: expected '%s' but got '%s'", expected, out)
|
||||
}
|
||||
|
||||
errOut, _ := p.ErrOutput()
|
||||
expected = []byte("stderr output")
|
||||
if !bytes.Equal(bytes.TrimSpace(errOut), expected) {
|
||||
t.Errorf("wrong stderr output: expected '%s' but got '%s'", expected, out)
|
||||
}
|
||||
}
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@ -8,12 +8,6 @@
|
||||
"revision": "3f9db97f856818214da2e1057f8ad84803971cff",
|
||||
"revisionTime": "2015-05-15T14:53:56Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "AcczqNgc2/sR/+4gklvFe8zs2eE=",
|
||||
"path": "github.com/ionrock/procs",
|
||||
"revision": "f53ef5630f1a1fd42c4e528a04cdaa81265cc66d",
|
||||
"revisionTime": "2018-01-02T00:55:58Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "KU+GT3javo9S9oVEJfqQUKPPUwo=",
|
||||
"path": "github.com/kr/pty",
|
||||
|
Loading…
Reference in New Issue
Block a user