diff --git a/go/packages/golist.go b/go/packages/golist.go index 3a0d4b01..53898490 100644 --- a/go/packages/golist.go +++ b/go/packages/golist.go @@ -777,6 +777,22 @@ func invokeGo(cfg *Config, args ...string) (*bytes.Buffer, error) { return bytes.NewBufferString(output), nil } + // Workaround for an instance of golang.org/issue/26755: go list -e will return a non-zero exit + // status if there's a dependency on a package that doesn't exist. But it should return + // a zero exit status and set an error on that package. + if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "no Go files in") { + // try to extract package name from string + stderrStr := stderr.String() + var importPath string + colon := strings.Index(stderrStr, ":") + if colon > 0 && strings.HasPrefix(stderrStr, "go build ") { + importPath = stderrStr[len("go build "):colon] + } + output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`, + importPath, strings.Trim(stderrStr, "\n")) + return bytes.NewBufferString(output), nil + } + // Export mode entails a build. // If that build fails, errors appear on stderr // (despite the -e flag) and the Export field is blank. diff --git a/go/packages/packages_test.go b/go/packages/packages_test.go index d9ba0f47..20a94a77 100644 --- a/go/packages/packages_test.go +++ b/go/packages/packages_test.go @@ -1828,6 +1828,28 @@ func testReturnErrorWhenUsingNonGoFiles(t *testing.T, exporter packagestest.Expo } } +func TestMissingDependency(t *testing.T) { packagestest.TestAll(t, testMissingDependency) } +func testMissingDependency(t *testing.T, exporter packagestest.Exporter) { + exported := packagestest.Export(t, exporter, []packagestest.Module{{ + Name: "golang.org/fake", + Files: map[string]interface{}{ + "a/a.go": `package a; import _ "this/package/doesnt/exist"`, + }}}) + defer exported.Cleanup() + + exported.Config.Mode = packages.LoadAllSyntax + pkgs, err := packages.Load(exported.Config, "golang.org/fake/a") + if err != nil { + t.Fatal(err) + } + if len(pkgs) != 1 && pkgs[0].PkgPath != "golang.org/fake/a" { + t.Fatalf("packages.Load: want [golang.org/fake/a], got %v", pkgs) + } + if len(pkgs[0].Errors) == 0 { + t.Errorf("result of Load: want package with errors, got none: %+v", pkgs[0]) + } +} + func errorMessages(errors []packages.Error) []string { var msgs []string for _, err := range errors {