Skip to content

Commit

Permalink
go: use "shell" params file format instead of "multiline" (#2655)
Browse files Browse the repository at this point in the history
This lets arguments contain newlines.

Fixes #2635
  • Loading branch information
Jay Conrod committed Sep 22, 2020
1 parent 3d680bd commit fab3573
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 28 deletions.
4 changes: 2 additions & 2 deletions go/private/context.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def _new_args(go):
def _builder_args(go, command = None):
args = go.actions.args()
args.use_param_file("-param=%s")
args.set_param_file_format("multiline")
args.set_param_file_format("shell")
if command:
args.add(command)
args.add("-sdk", go.sdk.root_file.dirname)
Expand All @@ -139,7 +139,7 @@ def _builder_args(go, command = None):
def _tool_args(go):
args = go.actions.args()
args.use_param_file("-param=%s")
args.set_param_file_format("multiline")
args.set_param_file_format("shell")
return args

def _new_library(go, name = None, importpath = None, resolver = None, importable = True, testfilter = None, is_main = False, **kwargs):
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/asm.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
// Go rules as an action.
func asm(args []string) error {
// Parse arguments.
args, err := readParamsFiles(args)
args, err := expandParamsFiles(args)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func main() {
log.SetFlags(0)
log.SetPrefix("builder: ")

args, err := readParamsFiles(os.Args[1:])
args, err := expandParamsFiles(os.Args[1:])
if err != nil {
log.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (

func compile(args []string) error {
// Parse arguments.
args, err := readParamsFiles(args)
args, err := expandParamsFiles(args)
if err != nil {
return err
}
Expand Down
11 changes: 5 additions & 6 deletions go/tools/builders/compilepkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (

func compilePkg(args []string) error {
// Parse arguments.
args, err := readParamsFiles(args)
args, err := expandParamsFiles(args)
if err != nil {
return err
}
Expand Down Expand Up @@ -446,13 +446,12 @@ func runNogo(ctx context.Context, workDir string, nogoPath string, srcs []string
args = append(args, "-x", outFactsPath)
args = append(args, srcs...)

paramFile := filepath.Join(workDir, "nogo.param")
params := strings.Join(args[1:], "\n")
if err := ioutil.WriteFile(paramFile, []byte(params), 0666); err != nil {
return fmt.Errorf("error writing nogo paramfile: %v", err)
paramsFile := filepath.Join(workDir, "nogo.param")
if err := writeParamsFile(paramsFile, args[1:]); err != nil {
return fmt.Errorf("error writing nogo params file: %v", err)
}

cmd := exec.CommandContext(ctx, args[0], "-param="+paramFile)
cmd := exec.CommandContext(ctx, args[0], "-param="+paramsFile)
out := &bytes.Buffer{}
cmd.Stdout, cmd.Stderr = out, out
if err := cmd.Run(); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/cover.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
// cover transforms a source file with "go tool cover". It is invoked by the
// Go rules as an action.
func cover(args []string) error {
args, err := readParamsFiles(args)
args, err := expandParamsFiles(args)
if err != nil {
return err
}
Expand Down
84 changes: 74 additions & 10 deletions go/tools/builders/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,10 @@ func runAndLogCommand(cmd *exec.Cmd, verbose bool) error {
return nil
}

// readParamsFile looks for arguments in args of the form
// expandParamsFiles looks for arguments in args of the form
// "-param=filename". When it finds these arguments it reads the file "filename"
// and replaces the argument with its content (each argument must be on a
// separate line; blank lines are ignored).
func readParamsFiles(args []string) ([]string, error) {
// and replaces the argument with its content.
func expandParamsFiles(args []string) ([]string, error) {
var paramsIndices []int
for i, arg := range args {
if strings.HasPrefix(arg, "-param=") {
Expand All @@ -190,21 +189,86 @@ func readParamsFiles(args []string) ([]string, error) {
last = pi + 1

fileName := args[pi][len("-param="):]
content, err := ioutil.ReadFile(fileName)
fileArgs, err := readParamsFile(fileName)
if err != nil {
return nil, err
}
fileArgs := strings.Split(string(content), "\n")
if len(fileArgs) >= 0 && fileArgs[len(fileArgs)-1] == "" {
// Ignore final empty line.
fileArgs = fileArgs[:len(fileArgs)-1]
}
expandedArgs = append(expandedArgs, fileArgs...)
}
expandedArgs = append(expandedArgs, args[last:]...)
return expandedArgs, nil
}

// readParamsFiles parses a Bazel params file in "shell" format. The file
// should contain one argument per line. Arguments may be quoted with single
// quotes. All characters within quoted strings are interpreted literally
// including newlines and excepting single quotes. Characters outside quoted
// strings may be escaped with a backslash.
func readParamsFile(name string) ([]string, error) {
data, err := ioutil.ReadFile(name)
if err != nil {
return nil, err
}

var args []string
var arg []byte
quote := false
escape := false
for p := 0; p < len(data); p++ {
b := data[p]
switch {
case escape:
arg = append(arg, b)
escape = false

case b == '\'':
quote = !quote

case !quote && b == '\\':
escape = true

case !quote && b == '\n':
args = append(args, string(arg))
arg = arg[:0]

default:
arg = append(arg, b)
}
}
if quote {
return nil, fmt.Errorf("unterminated quote")
}
if escape {
return nil, fmt.Errorf("unterminated escape")
}
if len(arg) > 0 {
args = append(args, string(arg))
}
return args, nil
}

// writeParamsFile formats a list of arguments in Bazel's "shell" format and writes
// it to a file.
func writeParamsFile(path string, args []string) error {
buf := new(bytes.Buffer)
for _, arg := range args {
if !strings.ContainsAny(arg, "'\n\\") {
fmt.Fprintln(buf, arg)
continue
}
buf.WriteByte('\'')
for _, r := range arg {
if r == '\'' {
buf.WriteString(`'\''`)
} else {
buf.WriteRune(r)
}
}
buf.WriteString("'\n")
}
return ioutil.WriteFile(path, buf.Bytes(), 0666)
}

// splitArgs splits a list of command line arguments into two parts: arguments
// that should be interpreted by the builder (before "--"), and arguments
// that should be passed through to the underlying tool (after "--").
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/generate_test_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ func main() {

func genTestMain(args []string) error {
// Prepare our flags
args, err := readParamsFiles(args)
args, err := expandParamsFiles(args)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
)

func run(args []string) error {
args, err := readParamsFiles(args)
args, err := expandParamsFiles(args)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (

func link(args []string) error {
// Parse arguments.
args, err := readParamsFiles(args)
args, err := expandParamsFiles(args)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/nogo_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func main() {
// run returns an error if there is a problem loading the package or if any
// analysis fails.
func run(args []string) error {
args, err := readParamsFiles(args)
args, err := expandParamsFiles(args)
if err != nil {
return fmt.Errorf("error reading paramfiles: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import (
// handle them, and ar may not be available (cpp.ar_executable is libtool
// on darwin).
func pack(args []string) error {
args, err := readParamsFiles(args)
args, err := expandParamsFiles(args)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/protoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type genFileInfo struct {

func run(args []string) error {
// process the args
args, err := readParamsFiles(args)
args, err := expandParamsFiles(args)
if err != nil {
return err
}
Expand Down

0 comments on commit fab3573

Please sign in to comment.