-
Notifications
You must be signed in to change notification settings - Fork 0
/
invoke.go
65 lines (54 loc) · 1.69 KB
/
invoke.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// Copyright 2020 Manlio Perillo. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The implementation of invokeGo is based on
// github.com/perillo/cmdgo/internal/invoke, but simplified to match the
// requirements of goprint.
package packages
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"strings"
)
// gocmd is the go command to use.
var gocmd = "go"
// attr holds the attributes that will be applied to the cmd/go command.
type attr struct {
// Env specifies the environment of the cmd/go command.
// Each entry is of the form "key=value".
// If Env is nil, the cmd/go command uses the current process's
// environment.
Env []string
// Dir specifies the working directory of the cmd/go command.
// If Dir is the empty string, the cmd/go command runs in the calling
// process's current directory.
Dir string
}
// invokeGo invokes a cmd/go command.
//
// If the cmd/go command returns a non 0 exit status, invokeGo will return a
// nil io.Reader and an error.
//
// If the cmd/go command returns a 0 exit status, invokeGo will return the
// stdout content as an io.Reader and a nil error.
//
// The child process stderr will be redirected to the parent process stderr.
func invokeGo(verb string, argv []string, attr *attr) (io.Reader, error) {
argv = append([]string{verb}, argv...)
stdout := new(bytes.Buffer)
cmd := exec.Command(gocmd, argv...)
cmd.Stdout = stdout
cmd.Stderr = os.Stderr
if attr != nil {
cmd.Dir = attr.Dir
cmd.Env = attr.Env
}
if err := cmd.Run(); err != nil {
argv := strings.Trim(fmt.Sprint(argv), "[]")
return nil, fmt.Errorf("%s %s: %v", gocmd, argv, err)
}
return stdout, nil
}