@@ -269,6 +269,17 @@ func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, q
269
269
// modCacheRegexp splits a path in a module cache into module, module version, and package.
270
270
var modCacheRegexp = regexp .MustCompile (`(.*)@([^/\\]*)(.*)` )
271
271
272
+ // noFileRe looks for a package name in a "no Go files in" errors line that is output by go list.
273
+ var noFileRe = regexp .MustCompile (`(?m)^go build ([\p{L}\p{Nd}\/.]+): (no Go files in.*)$` )
274
+
275
+ // cgoErrRe attempts to detect cgo errors from go list stderr output
276
+ var cgoErrRe = regexp .MustCompile (
277
+ `(collect2: error: ld returned)|(could not determine kind of name for C\.)|` +
278
+ `(fatal error: \S+.(c|h): No such file or directory)` )
279
+
280
+ // goListErrRe attempts to extract errors from go list stderr output
281
+ var goListErrRe = regexp .MustCompile (`(?m)^# ([\p{L}\p{Nd}\/.]+)\n((?:[^#].*\n)+)` )
282
+
272
283
func runNamedQueries (cfg * Config , driver driver , response * responseDeduper , queries []string ) error {
273
284
// calling `go env` isn't free; bail out if there's nothing to do.
274
285
if len (queries ) == 0 {
@@ -553,6 +564,8 @@ type jsonPackage struct {
553
564
ForTest string // q in a "p [q.test]" package, else ""
554
565
DepOnly bool
555
566
567
+ Gen bool // generated by this code
568
+
556
569
Error * jsonPackageError
557
570
}
558
571
@@ -611,11 +624,15 @@ func golistDriver(cfg *Config, words ...string) (*driverResponse, error) {
611
624
}
612
625
613
626
if old , found := seen [p .ImportPath ]; found {
614
- if ! reflect .DeepEqual (p , old ) {
627
+ if p .Gen {
628
+ // new package is generated, skip it
629
+ continue
630
+ } else if ! reflect .DeepEqual (p , old ) {
615
631
return nil , fmt .Errorf ("internal error: go list gives conflicting information for package %v" , p .ImportPath )
632
+ } else if ! old .Gen {
633
+ // skip the duplicate if the old package wasn't generated
634
+ continue
616
635
}
617
- // skip the duplicate
618
- continue
619
636
}
620
637
seen [p .ImportPath ] = p
621
638
@@ -804,15 +821,23 @@ func invokeGo(cfg *Config, args ...string) (*bytes.Buffer, error) {
804
821
// a zero exit status and set an error on that package.
805
822
if len (stderr .String ()) > 0 && strings .Contains (stderr .String (), "no Go files in" ) {
806
823
// try to extract package name from string
807
- stderrStr := stderr .String ()
808
- var importPath string
809
- colon := strings .Index (stderrStr , ":" )
810
- if colon > 0 && strings .HasPrefix (stderrStr , "go build " ) {
811
- importPath = stderrStr [len ("go build " ):colon ]
824
+ for _ , matches := range noFileRe .FindAllStringSubmatch (stderr .String (), - 1 ) {
825
+ stdout .WriteString (fmt .Sprintf ("\n " + `{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q},"Gen": true}` ,
826
+ matches [1 ], matches [2 ]))
812
827
}
813
- output := fmt .Sprintf (`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}` ,
814
- importPath , strings .Trim (stderrStr , "\n " ))
815
- return bytes .NewBufferString (output ), nil
828
+ return stdout , nil
829
+ }
830
+
831
+ // Workaround for an instance of golang.org/issue/26755: go list -e will
832
+ // return a non-zero exit status if cgo preprocessing fails. But it should
833
+ // return a zero exit status and set an error on that package.
834
+ if len (stderr .String ()) > 0 && cgoErrRe .MatchString (stderr .String ()) {
835
+ for _ , matches := range goListErrRe .FindAllStringSubmatch (stderr .String (), - 1 ) {
836
+ stdout .WriteString (fmt .Sprintf ("\n " + `{"ImportPath": %q,"Incomplete":true,"Error": {"Pos": "","Err": %q},"Gen": true}` ,
837
+ matches [1 ], strings .Trim (matches [2 ], "\n " )))
838
+ }
839
+
840
+ return stdout , nil
816
841
}
817
842
818
843
// Export mode entails a build.
0 commit comments