@@ -47,6 +47,7 @@ type GoParser struct {
4747 types map [types.Type ]Identity
4848 files map [string ][]byte
4949 exclues []* regexp.Regexp
50+ cgoPkgs map [string ]bool // CGO packages
5051}
5152
5253type moduleInfo struct {
@@ -98,6 +99,7 @@ func newGoParser(name string, homePageDir string, opts Options) *GoParser {
9899func (p * GoParser ) collectGoMods (startDir string ) error {
99100 hasGoWork := false
100101 deps := map [string ]string {}
102+ var cgoPkgs map [string ]bool
101103 err := filepath .Walk (startDir , func (path string , info fs.FileInfo , err error ) error {
102104 if err != nil || ! strings .HasSuffix (path , "go.mod" ) {
103105 return nil
@@ -115,10 +117,18 @@ func (p *GoParser) collectGoMods(startDir string) error {
115117 p .repo .Modules [name ] = newModule (name , rel )
116118 p .modules = append (p .modules , newModuleInfo (name , rel , name ))
117119
118- deps , hasGoWork , err = getDeps (filepath .Dir (path ), hasGoWork )
120+ deps , hasGoWork , cgoPkgs , err = getDeps (filepath .Dir (path ), hasGoWork )
119121 if err != nil {
120122 return err
121123 }
124+ if p .cgoPkgs == nil {
125+ p .cgoPkgs = make (map [string ]bool )
126+ }
127+ for pkgPath := range cgoPkgs {
128+ if strings .HasPrefix (pkgPath , name ) {
129+ p .cgoPkgs [pkgPath ] = true
130+ }
131+ }
122132 for k , v := range deps {
123133 p .repo .Modules [name ].Dependencies [k ] = v
124134 p .modules = append (p .modules , newModuleInfo (k , "" , v ))
@@ -148,18 +158,29 @@ type dep struct {
148158 Dir string `json:"Dir"`
149159 GoMod string `json:"GoMod"`
150160 } `json:"Module"`
161+ CgoFiles []string `json:"CgoFiles"`
151162}
152163
153- func getDeps (dir string , goWork bool ) (a map [string ]string , hasGoWork bool , err error ) {
164+ func getDeps (dir string , goWork bool ) (a map [string ]string , hasGoWork bool , cgoPkgs map [string ]bool , err error ) {
165+ cgoPkgs = make (map [string ]bool )
154166 // run go mod tidy first to ensure all dependencies are resolved
155167 cmd := exec .Command ("go" , "mod" , "tidy" , "-e" )
156168 cmd .Dir = dir
169+ cmd .Env = append (os .Environ (), "GONOSUMDB=*" )
157170 output , err := cmd .CombinedOutput ()
158171 if err != nil {
159- return nil , hasGoWork , fmt .Errorf ("failed to execute 'go mod tidy', err: %v, output: %s" , err , string (output ))
172+ fmt .Fprintf (os .Stderr , "failed to execute 'go mod tidy', err: %v, output: %s, remove go.sum file reexecute\n " , err , string (output ))
173+ os .Remove (filepath .Join (dir , "go.sum" ))
174+ cmd = exec .Command ("go" , "mod" , "tidy" , "-e" )
175+ cmd .Dir = dir
176+ cmd .Env = append (os .Environ (), "GOSUMDB=off" )
177+ output , err = cmd .CombinedOutput ()
178+ if err != nil {
179+ return nil , hasGoWork , cgoPkgs , fmt .Errorf ("failed to execute 'go mod tidy', err: %v, output: %s" , err , string (output ))
180+ }
160181 }
161182 if hasNoDeps (filepath .Join (dir , "go.mod" )) {
162- return map [string ]string {}, hasGoWork , nil
183+ return map [string ]string {}, hasGoWork , cgoPkgs , nil
163184 }
164185 // -mod=mod to use go mod when go mod is inconsistent with go vendor
165186 // if go.work exist, it's no need to set -mod=mod
@@ -170,14 +191,15 @@ func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, err
170191 cmd = exec .Command ("go" , "list" , "-e" , "-json" , "-mod=mod" , "all" )
171192 }
172193 cmd .Dir = dir
194+ cmd .Env = append (os .Environ (), "GOSUMDB=off" )
173195 output , err = cmd .CombinedOutput ()
174196 if err != nil {
175- return nil , hasGoWork , fmt .Errorf ("failed to execute 'go list -json all', err: %v, output: %s, cmd string: %s, dir: %s" , err , string (output ), cmd .String (), dir )
197+ return nil , hasGoWork , cgoPkgs , fmt .Errorf ("failed to execute 'go list -json all', err: %v, output: %s, cmd string: %s, dir: %s" , err , string (output ), cmd .String (), dir )
176198 }
177199 // ignore content until first open
178200 index := strings .Index (string (output ), "{" )
179201 if index == - 1 {
180- return nil , hasGoWork , fmt .Errorf ("failed to find '{' in output, output: %s" , string (output ))
202+ return nil , hasGoWork , cgoPkgs , fmt .Errorf ("failed to find '{' in output, output: %s" , string (output ))
181203 }
182204 if index > 0 {
183205 log .Info ("go list skip prefix, output: %s" , string (output [:index ]))
@@ -191,13 +213,16 @@ func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, err
191213 if err .Error () == "EOF" {
192214 break
193215 }
194- return nil , hasGoWork , fmt .Errorf ("failed to decode json: %v, output: %s" , err , string (output ))
216+ return nil , hasGoWork , cgoPkgs , fmt .Errorf ("failed to decode json: %v, output: %s" , err , string (output ))
195217 }
196218 module := mod .Module
197219 // golang internal package, ignore it.
198220 if module .Path == "" {
199221 continue
200222 }
223+ if len (mod .CgoFiles ) > 0 {
224+ cgoPkgs [module .Path ] = true
225+ }
201226 if module .Replace != nil {
202227 deps [module .Path ] = module .Replace .Path + "@" + module .Replace .Version
203228 } else {
@@ -214,8 +239,7 @@ func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, err
214239 }
215240 }
216241 }
217-
218- return deps , hasGoWork , nil
242+ return deps , hasGoWork , cgoPkgs , nil
219243}
220244
221245// ParseRepo parse the entiry repo from homePageDir recursively until end
0 commit comments