2019-09-06 16:25:36 -06:00
|
|
|
package source
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"os/exec"
|
2020-01-14 11:59:17 -07:00
|
|
|
|
|
|
|
errors "golang.org/x/xerrors"
|
2019-09-06 16:25:36 -06:00
|
|
|
)
|
|
|
|
|
2020-01-14 11:59:17 -07:00
|
|
|
// InvokeGo returns the output of a go command invocation.
|
|
|
|
// It does not try to recover from errors.
|
2019-12-16 13:40:24 -07:00
|
|
|
func InvokeGo(ctx context.Context, dir string, env []string, args ...string) (*bytes.Buffer, error) {
|
2019-09-06 16:25:36 -06:00
|
|
|
stdout := new(bytes.Buffer)
|
|
|
|
stderr := new(bytes.Buffer)
|
|
|
|
cmd := exec.CommandContext(ctx, "go", args...)
|
|
|
|
// On darwin the cwd gets resolved to the real path, which breaks anything that
|
|
|
|
// expects the working directory to keep the original path, including the
|
|
|
|
// go command when dealing with modules.
|
|
|
|
// The Go stdlib has a special feature where if the cwd and the PWD are the
|
|
|
|
// same node then it trusts the PWD, so by setting it in the env for the child
|
|
|
|
// process we fix up all the paths returned by the go command.
|
|
|
|
cmd.Env = append(append([]string{}, env...), "PWD="+dir)
|
|
|
|
cmd.Dir = dir
|
|
|
|
cmd.Stdout = stdout
|
|
|
|
cmd.Stderr = stderr
|
|
|
|
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
// Check for 'go' executable not being found.
|
|
|
|
if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound {
|
|
|
|
return nil, fmt.Errorf("'gopls requires 'go', but %s", exec.ErrNotFound)
|
|
|
|
}
|
2020-01-14 11:59:17 -07:00
|
|
|
if ctx.Err() != nil {
|
|
|
|
return nil, ctx.Err()
|
2019-09-06 16:25:36 -06:00
|
|
|
}
|
2020-01-14 11:59:17 -07:00
|
|
|
return stdout, errors.Errorf("err: %v: stderr: %s", err, stderr)
|
2019-09-06 16:25:36 -06:00
|
|
|
}
|
|
|
|
return stdout, nil
|
|
|
|
}
|