Skip to content

Commit 0160412

Browse files
matloobgopherbot
authored andcommitted
cmd/go: do not exit with non-zero code from go list -e -export
go list -e -export puts errors running build actions on the load.Package corresponding to the failed action rather than exiting with a non zero exit code. For #25842 Change-Id: I1fea85cc5a0557f514fe9d4ed3b6a858376fdcde Reviewed-on: https://go-review.googlesource.com/c/go/+/437298 Run-TryBot: Bryan Mills <bcmills@google.com> Reviewed-by: Bryan Mills <bcmills@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Michael Matloob <matloob@golang.org>
1 parent f1e50a1 commit 0160412

File tree

5 files changed

+84
-38
lines changed

5 files changed

+84
-38
lines changed

src/cmd/go/internal/list/list.go

+3
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,9 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
690690
needStale := (listJson && listJsonFields.needAny("Stale", "StaleReason")) || strings.Contains(*listFmt, ".Stale")
691691
if needStale || *listExport || *listCompiled {
692692
b := work.NewBuilder("")
693+
if *listE {
694+
b.AllowErrors = true
695+
}
693696
defer func() {
694697
if err := b.Close(); err != nil {
695698
base.Fatalf("go: %v", err)

src/cmd/go/internal/work/action.go

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type Builder struct {
4343
NeedError bool // list needs p.Error
4444
NeedExport bool // list needs p.Export
4545
NeedCompiledGoFiles bool // list needs p.CompiledGoFiles
46+
AllowErrors bool // errors don't immediately exit the program
4647

4748
objdirSeq int // counter for NewObjdir
4849
pkgSeq int

src/cmd/go/internal/work/exec.go

+59-36
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,10 @@ func (b *Builder) Do(ctx context.Context, root *Action) {
153153
defer b.exec.Unlock()
154154

155155
if err != nil {
156-
if err == errPrintedOutput {
157-
base.SetExitStatus(2)
156+
if b.AllowErrors {
157+
if a.Package.Error == nil {
158+
a.Package.Error = &load.PackageError{Err: err}
159+
}
158160
} else {
159161
base.Errorf("%s", err)
160162
}
@@ -512,7 +514,7 @@ func (b *Builder) build(ctx context.Context, a *Action) (err error) {
512514
}
513515

514516
defer func() {
515-
if err != nil && err != errPrintedOutput {
517+
if err != nil {
516518
err = fmt.Errorf("go build %s: %v", p.ImportPath, err)
517519
}
518520
if err != nil && b.IsCmdList && b.NeedError && p.Error == nil {
@@ -861,9 +863,11 @@ OverlayLoop:
861863
if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
862864
output += "note: module requires Go " + p.Module.GoVersion + "\n"
863865
}
864-
b.showOutput(a, p.Dir, p.Desc(), output)
866+
865867
if err != nil {
866-
return errPrintedOutput
868+
return errors.New(fmt.Sprint(formatOutput(b.WorkDir, p.Dir, p.Desc(), output)))
869+
} else {
870+
b.showOutput(a, p.Dir, p.Desc(), output)
867871
}
868872
}
869873
if err != nil {
@@ -1542,9 +1546,8 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
15421546
var out []byte
15431547
out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs)
15441548
if err != nil {
1545-
b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
1546-
b.Print(err.Error() + "\n")
1547-
return nil, nil, errPrintedOutput
1549+
prefix, suffix := formatOutput(b.WorkDir, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
1550+
return nil, nil, errors.New(fmt.Sprint(prefix, suffix+err.Error()))
15481551
}
15491552
if len(out) > 0 {
15501553
cflags, err = splitPkgConfigOutput(out)
@@ -1557,9 +1560,8 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
15571560
}
15581561
out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs)
15591562
if err != nil {
1560-
b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
1561-
b.Print(err.Error() + "\n")
1562-
return nil, nil, errPrintedOutput
1563+
prefix, suffix := formatOutput(b.WorkDir, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
1564+
return nil, nil, errors.New(fmt.Sprint(prefix, suffix+err.Error()))
15631565
}
15641566
if len(out) > 0 {
15651567
// NOTE: we don't attempt to parse quotes and unescapes here. pkg-config
@@ -1651,7 +1653,7 @@ func (b *Builder) linkShared(ctx context.Context, a *Action) (err error) {
16511653
// BuildInstallFunc is the action for installing a single package or executable.
16521654
func BuildInstallFunc(b *Builder, ctx context.Context, a *Action) (err error) {
16531655
defer func() {
1654-
if err != nil && err != errPrintedOutput {
1656+
if err != nil {
16551657
// a.Package == nil is possible for the go install -buildmode=shared
16561658
// action that installs libmangledname.so, which corresponds to
16571659
// a list of packages, not just one.
@@ -2103,15 +2105,7 @@ func (b *Builder) Showcmd(dir string, format string, args ...any) {
21032105
// If a is not nil and a.output is not nil, showOutput appends to that slice instead of
21042106
// printing to b.Print.
21052107
func (b *Builder) showOutput(a *Action, dir, desc, out string) {
2106-
prefix := "# " + desc
2107-
suffix := "\n" + out
2108-
if reldir := base.ShortPath(dir); reldir != dir {
2109-
suffix = strings.ReplaceAll(suffix, " "+dir, " "+reldir)
2110-
suffix = strings.ReplaceAll(suffix, "\n"+dir, "\n"+reldir)
2111-
suffix = strings.ReplaceAll(suffix, "\n\t"+dir, "\n\t"+reldir)
2112-
}
2113-
suffix = strings.ReplaceAll(suffix, " "+b.WorkDir, " $WORK")
2114-
2108+
prefix, suffix := formatOutput(b.WorkDir, dir, desc, out)
21152109
if a != nil && a.output != nil {
21162110
a.output = append(a.output, prefix...)
21172111
a.output = append(a.output, suffix...)
@@ -2123,12 +2117,41 @@ func (b *Builder) showOutput(a *Action, dir, desc, out string) {
21232117
b.Print(prefix, suffix)
21242118
}
21252119

2126-
// errPrintedOutput is a special error indicating that a command failed
2127-
// but that it generated output as well, and that output has already
2128-
// been printed, so there's no point showing 'exit status 1' or whatever
2129-
// the wait status was. The main executor, builder.do, knows not to
2130-
// print this error.
2131-
var errPrintedOutput = errors.New("already printed output - no need to show error")
2120+
// formatOutput prints "# desc" followed by the given output.
2121+
// The output is expected to contain references to 'dir', usually
2122+
// the source directory for the package that has failed to build.
2123+
// formatOutput rewrites mentions of dir with a relative path to dir
2124+
// when the relative path is shorter. This is usually more pleasant.
2125+
// For example, if fmt doesn't compile and we are in src/html,
2126+
// the output is
2127+
//
2128+
// $ go build
2129+
// # fmt
2130+
// ../fmt/print.go:1090: undefined: asdf
2131+
// $
2132+
//
2133+
// instead of
2134+
//
2135+
// $ go build
2136+
// # fmt
2137+
// /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf
2138+
// $
2139+
//
2140+
// formatOutput also replaces references to the work directory with $WORK.
2141+
// formatOutput returns the output in a prefix with the description and a
2142+
// suffix with the actual output.
2143+
func formatOutput(workDir, dir, desc, out string) (prefix, suffix string) {
2144+
prefix = "# " + desc
2145+
suffix = "\n" + out
2146+
if reldir := base.ShortPath(dir); reldir != dir {
2147+
suffix = strings.ReplaceAll(suffix, " "+dir, " "+reldir)
2148+
suffix = strings.ReplaceAll(suffix, "\n"+dir, "\n"+reldir)
2149+
suffix = strings.ReplaceAll(suffix, "\n\t"+dir, "\n\t"+reldir)
2150+
}
2151+
suffix = strings.ReplaceAll(suffix, " "+workDir, " $WORK")
2152+
2153+
return prefix, suffix
2154+
}
21322155

21332156
var cgoLine = lazyregexp.New(`\[[^\[\]]+\.(cgo1|cover)\.go:[0-9]+(:[0-9]+)?\]`)
21342157
var cgoTypeSigRe = lazyregexp.New(`\b_C2?(type|func|var|macro)_\B`)
@@ -2142,9 +2165,10 @@ func (b *Builder) run(a *Action, dir string, desc string, env []string, cmdargs
21422165
if desc == "" {
21432166
desc = b.fmtcmd(dir, "%s", strings.Join(str.StringList(cmdargs...), " "))
21442167
}
2145-
b.showOutput(a, dir, desc, b.processOutput(out))
21462168
if err != nil {
2147-
err = errPrintedOutput
2169+
err = errors.New(fmt.Sprint(formatOutput(b.WorkDir, dir, desc, b.processOutput(out))))
2170+
} else {
2171+
b.showOutput(a, dir, desc, b.processOutput(out))
21482172
}
21492173
}
21502174
return err
@@ -2488,11 +2512,10 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
24882512
}
24892513
}
24902514

2491-
b.showOutput(a, p.Dir, desc, b.processOutput(output))
2492-
if err != nil {
2493-
err = errPrintedOutput
2494-
} else if os.Getenv("GO_BUILDER_NAME") != "" {
2495-
return errors.New("C compiler warning promoted to error on Go builders")
2515+
if err != nil || os.Getenv("GO_BUILDER_NAME") != "" {
2516+
err = errors.New(fmt.Sprintf(formatOutput(b.WorkDir, p.Dir, desc, b.processOutput(output))))
2517+
} else {
2518+
b.showOutput(a, p.Dir, desc, b.processOutput(output))
24962519
}
24972520
}
24982521
return err
@@ -3410,8 +3433,8 @@ func (b *Builder) swigOne(a *Action, p *load.Package, file, objdir string, pcCFL
34103433
if bytes.Contains(out, []byte("-intgosize")) || bytes.Contains(out, []byte("-cgo")) {
34113434
return "", "", errors.New("must have SWIG version >= 3.0.6")
34123435
}
3413-
b.showOutput(a, p.Dir, p.Desc(), b.processOutput(out)) // swig error
3414-
return "", "", errPrintedOutput
3436+
// swig error
3437+
return "", "", errors.New(fmt.Sprint(formatOutput(b.WorkDir, p.Dir, p.Desc(), b.processOutput(out))))
34153438
}
34163439
return "", "", err
34173440
}

src/cmd/go/internal/work/gc.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package work
77
import (
88
"bufio"
99
"bytes"
10+
"errors"
1011
"fmt"
1112
"internal/platform"
1213
"io"
@@ -506,8 +507,7 @@ func (gcToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) er
506507
return nil
507508
}
508509
if err := packInternal(absAfile, absOfiles); err != nil {
509-
b.showOutput(a, p.Dir, p.Desc(), err.Error()+"\n")
510-
return errPrintedOutput
510+
return errors.New(fmt.Sprint(formatOutput(b.WorkDir, p.Dir, p.Desc(), err.Error()+"\n")))
511511
}
512512
return nil
513513
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
go list -e -export ./...
2+
! stderr '.'
3+
go list -e -export -json ...
4+
5+
-- go.mod --
6+
module example.com
7+
-- p1/p1.go --
8+
package p1
9+
10+
const Name = "p1"
11+
-- p2/main.go --
12+
package main
13+
14+
import "fmt"
15+
import "example.com/p1"
16+
17+
func main() {
18+
fmt.Println(p1.Name == 5)
19+
}

0 commit comments

Comments
 (0)