From 20d890d995d573c1d56fc528f26e7d1d3bef57ac Mon Sep 17 00:00:00 2001 From: Rob Figueiredo Date: Thu, 19 Nov 2020 21:40:36 -0500 Subject: [PATCH] WIP: proof of concept for relativizing paths in error messages This specifically addresses Go compile errors and nogo errors. Before: /private/var/tmp/_bazel_robfig/1db08896ecff7e5e96a745981c3b77e6/sandbox/darwin-sandbox/28708/execroot/corp/gocode/src/corp/analytics/searchterms/redshiftcopier.go:14:2: imported and not used: "corp/net/rpc" compilepkg: nogo: errors found by nogo during build-time code analysis: /private/var/tmp/_bazel_robfig/1db08896ecff7e5e96a745981c3b77e6/sandbox/darwin-sandbox/29923/execroot/corp/gocode/src/corp/net/rpc/server.go:125:7: the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak After: gocode/src/corp/analytics/searchterms/redshiftcopier.go:14:2: imported and not used: "corp/net/rpc" compilepkg: nogo: errors found by nogo during build-time code analysis: gocode/src/corp/net/rpc/server.go:125:7: the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak Fixes #2061 --- go/tools/builders/compilepkg.go | 2 +- go/tools/builders/env.go | 41 +++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/go/tools/builders/compilepkg.go b/go/tools/builders/compilepkg.go index 77bc28b116..7c94ebd82b 100644 --- a/go/tools/builders/compilepkg.go +++ b/go/tools/builders/compilepkg.go @@ -460,7 +460,7 @@ func runNogo(ctx context.Context, workDir string, nogoPath string, srcs []string cmdLine := strings.Join(args, " ") return fmt.Errorf("nogo command '%s' exited unexpectedly: %s", cmdLine, exitErr.String()) } - return errors.New(out.String()) + return errors.New(rel(out.String())) } else { if out.Len() != 0 { fmt.Fprintln(os.Stderr, out.String()) diff --git a/go/tools/builders/env.go b/go/tools/builders/env.go index 842fc03e53..19325216d4 100644 --- a/go/tools/builders/env.go +++ b/go/tools/builders/env.go @@ -60,6 +60,8 @@ type env struct { workDirPath string shouldPreserveWorkDir bool + + pwd string } // envFlags registers flags common to multiple builders and returns an env @@ -71,6 +73,7 @@ func envFlags(flags *flag.FlagSet) *env { flags.StringVar(&env.installSuffix, "installsuffix", "", "Standard library under GOROOT/pkg") flags.BoolVar(&env.verbose, "v", false, "Whether subprocess command lines should be printed") flags.BoolVar(&env.shouldPreserveWorkDir, "work", false, "if true, the temporary work directory will be preserved") + env.pwd, _ = os.Getwd() return env } @@ -133,8 +136,9 @@ func (e *env) runCommand(args []string) error { cmd := exec.Command(args[0], args[1:]...) // Redirecting stdout to stderr. This mirrors behavior in the go command: // https://go.googlesource.com/go/+/refs/tags/go1.15.2/src/cmd/go/internal/work/exec.go#1958 - cmd.Stdout = os.Stderr - cmd.Stderr = os.Stderr + wr := absToRelativePathWriter{pwd: e.pwd, delegate: os.Stderr} + cmd.Stdout = wr + cmd.Stderr = wr return runAndLogCommand(cmd, e.verbose) } @@ -333,6 +337,39 @@ func absArgs(args []string, flags []string) { } } +// absToRelativePathWriter filters the output stream from a compile command, +// replacing any absolute paths with relative equivalents. +// +// This is done on a best-effort basis, and not much effort is undertaken. If a +// path is split across multiple Write calls, it will not be relativized. +type absToRelativePathWriter struct { + pwd string + delegate io.Writer +} + +func (wr absToRelativePathWriter) Write(p []byte) (nn int, err error) { + if wr.pwd == "" { + return wr.delegate.Write(p) + } + if !strings.HasSuffix(wr.pwd, "/") { + wr.pwd += "/" + } + return wr.delegate.Write(bytes.ReplaceAll(p, []byte(wr.pwd), nil)) +} + +// rel converts absolute paths found in the given output string to relative, if +// they are within the PWD. +func rel(output string) string { + dir, err := os.Getwd() + if dir == "" || err != nil { + return output + } + if !strings.HasSuffix(dir, "/") { + dir += "/" + } + return strings.ReplaceAll(output, dir, "") +} + // formatCommand writes cmd to w in a format where it can be pasted into a // shell. Spaces in environment variables and arguments are escaped as needed. func formatCommand(cmd *exec.Cmd) string {