gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/golang.org/x/tools/go/packages/external.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file enables an external tool to intercept package requests. 6 // If the tool is present then its results are used in preference to 7 // the go list command. 8 9 package packages 10 11 import ( 12 "bytes" 13 "encoding/json" 14 "fmt" 15 "os/exec" 16 "strings" 17 ) 18 19 // Driver 20 type driverRequest struct { 21 Command string `json "command"` 22 Mode LoadMode `json:"mode"` 23 Env []string `json:"env"` 24 BuildFlags []string `json:"build_flags"` 25 Tests bool `json:"tests"` 26 Overlay map[string][]byte `json:"overlay"` 27 } 28 29 // findExternalDriver returns the file path of a tool that supplies 30 // the build system package structure, or "" if not found." 31 // If GOPACKAGESDRIVER is set in the environment findExternalTool returns its 32 // value, otherwise it searches for a binary named gopackagesdriver on the PATH. 33 func findExternalDriver(cfg *Config) driver { 34 const toolPrefix = "GOPACKAGESDRIVER=" 35 tool := "" 36 for _, env := range cfg.Env { 37 if val := strings.TrimPrefix(env, toolPrefix); val != env { 38 tool = val 39 } 40 } 41 if tool != "" && tool == "off" { 42 return nil 43 } 44 if tool == "" { 45 var err error 46 tool, err = exec.LookPath("gopackagesdriver") 47 if err != nil { 48 return nil 49 } 50 } 51 return func(cfg *Config, words ...string) (*driverResponse, error) { 52 req, err := json.Marshal(driverRequest{ 53 Mode: cfg.Mode, 54 Env: cfg.Env, 55 BuildFlags: cfg.BuildFlags, 56 Tests: cfg.Tests, 57 Overlay: cfg.Overlay, 58 }) 59 if err != nil { 60 return nil, fmt.Errorf("failed to encode message to driver tool: %v", err) 61 } 62 63 buf := new(bytes.Buffer) 64 cmd := exec.CommandContext(cfg.Context, tool, words...) 65 cmd.Dir = cfg.Dir 66 cmd.Env = cfg.Env 67 cmd.Stdin = bytes.NewReader(req) 68 cmd.Stdout = buf 69 cmd.Stderr = new(bytes.Buffer) 70 if err := cmd.Run(); err != nil { 71 return nil, fmt.Errorf("%v: %v: %s", tool, err, cmd.Stderr) 72 } 73 var response driverResponse 74 if err := json.Unmarshal(buf.Bytes(), &response); err != nil { 75 return nil, err 76 } 77 return &response, nil 78 } 79 }