Skip to content

Commit

Permalink
[FAB-4819] Fix locating system packages in vendoring
Browse files Browse the repository at this point in the history
This patchset fixes some bugs addressed in [FAB-4819].

When the GOROOT environment variable is not set (i.e. Go is installed in the
standard location), Go uses its default value for GOROOT.
This patch introduces getGoEnv() to properly get GOROOT by using the "go
env" command instead of directly reading an environment variable.

This patch also fixes list() to prevent from obtaining empty string in error
from the output of the "go list" command.

Change-Id: Ie8007087aff40d5f8eab6021e4e184534d3074e4
Signed-off-by: Taku Shimosawa <taku.shimosawa@hal.hitachi.com>
  • Loading branch information
shimos committed Jun 19, 2017
1 parent f20846c commit 6e6c6bf
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 16 deletions.
24 changes: 23 additions & 1 deletion core/chaincode/platforms/golang/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ import (
"os"
"path/filepath"
"strings"
"time"
)

type Env map[string]string

func getEnv() Env {
env := make(Env)
for _, entry := range os.Environ() {
tokens := strings.Split(entry, "=")
tokens := strings.SplitN(entry, "=", 2)
if len(tokens) > 1 {
env[tokens[0]] = tokens[1]
}
Expand All @@ -36,6 +37,27 @@ func getEnv() Env {
return env
}

func getGoEnv() (Env, error) {
env := getEnv()

goenvbytes, err := runProgram(env, 10*time.Second, "go", "env")
if err != nil {
return nil, err
}

goenv := make(Env)

envout := strings.Split(string(goenvbytes), "\n")
for _, entry := range envout {
tokens := strings.SplitN(entry, "=", 2)
if len(tokens) > 1 {
goenv[tokens[0]] = strings.Trim(tokens[1], "\"")
}
}

return goenv, nil
}

func flattenEnv(env Env) []string {
result := make([]string, 0)
for k, v := range env {
Expand Down
11 changes: 11 additions & 0 deletions core/chaincode/platforms/golang/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,14 @@ func Test_splitEnvPath(t *testing.T) {
paths := splitEnvPaths("foo" + string(os.PathListSeparator) + "bar" + string(os.PathListSeparator) + "baz")
assert.Equal(t, len(paths), 3)
}

func Test_getGoEnv(t *testing.T) {
goenv, err := getGoEnv()
assert.NilError(t, err)

_, ok := goenv["GOPATH"]
assert.Equal(t, ok, true)

_, ok = goenv["GOROOT"]
assert.Equal(t, ok, true)
}
34 changes: 23 additions & 11 deletions core/chaincode/platforms/golang/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,15 @@ import (
"time"
)

// Logic inspired by: https://dave.cheney.net/2014/09/14/go-list-your-swiss-army-knife
func list(env Env, template, pkg string) ([]string, error) {

//runProgram non-nil Env, timeout (typically secs or millisecs), program name and args
func runProgram(env Env, timeout time.Duration, pgm string, args ...string) ([]byte, error) {
if env == nil {
env = getEnv()
return nil, fmt.Errorf("<%s, %v>: nil env provided", pgm, args)
}

var stdOut bytes.Buffer
var stdErr bytes.Buffer

cmd := exec.Command("go", "list", "-f", template, pkg)
cmd := exec.Command(pgm, args...)
cmd.Env = flattenEnv(env)
cmd.Stdout = &stdOut
cmd.Stderr = &stdErr
Expand All @@ -48,21 +46,35 @@ func list(env Env, template, pkg string) ([]string, error) {
}()

select {
case <-time.After(60 * time.Second):
case <-time.After(timeout):
if err = cmd.Process.Kill(); err != nil {
return nil, fmt.Errorf("go list: failed to kill: %s", err)
return nil, fmt.Errorf("<%s, %v>: failed to kill: %s", pgm, args, err)
} else {
return nil, errors.New("go list: timeout")
return nil, errors.New(fmt.Sprintf("<%s, %v>: timeout(%d msecs)", pgm, args, timeout/time.Millisecond))
}
case err = <-done:
if err != nil {
return nil, fmt.Errorf("go list: failed with error: \"%s\"\n%s", err, string(stdErr.Bytes()))
return nil, fmt.Errorf("<%s, %v>: failed with error: \"%s\"\n%s", pgm, args, err, string(stdErr.Bytes()))
}

return strings.Split(string(stdOut.Bytes()), "\n"), nil
return stdOut.Bytes(), nil
}
}

// Logic inspired by: https://dave.cheney.net/2014/09/14/go-list-your-swiss-army-knife
func list(env Env, template, pkg string) ([]string, error) {
if env == nil {
env = getEnv()
}

lst, err := runProgram(env, 60*time.Second, "go", "list", "-f", template, pkg)
if err != nil {
return nil, err
}

return strings.Split(strings.Trim(string(lst), "\n"), "\n"), nil
}

func listDeps(env Env, pkg string) ([]string, error) {
return list(env, "{{ join .Deps \"\\n\"}}", pkg)
}
Expand Down
14 changes: 10 additions & 4 deletions core/chaincode/platforms/golang/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,14 @@ func decodeUrl(spec *pb.ChaincodeSpec) (string, error) {
}

func getGopath() (string, error) {
gopath := os.Getenv("GOPATH")
env, err := getGoEnv()
if err != nil {
return "", err
}
// Only take the first element of GOPATH
splitGoPath := filepath.SplitList(gopath)
splitGoPath := filepath.SplitList(env["GOPATH"])
if len(splitGoPath) == 0 {
return "", fmt.Errorf("invalid GOPATH environment variable value:[%s]", gopath)
return "", fmt.Errorf("invalid GOPATH environment variable value:[%s]", env["GOPATH"])
}
return splitGoPath[0], nil
}
Expand Down Expand Up @@ -194,7 +197,10 @@ func (goPlatform *Platform) GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte
// --------------------------------------------------------------------------------------
// Update our environment for the purposes of executing go-list directives
// --------------------------------------------------------------------------------------
env := getEnv()
env, err := getGoEnv()
if err != nil {
return nil, err
}
gopaths := splitEnvPaths(env["GOPATH"])
goroots := splitEnvPaths(env["GOROOT"])
gopaths[code.Gopath] = true
Expand Down

0 comments on commit 6e6c6bf

Please sign in to comment.