Skip to content

Commit

Permalink
Allow the GetDependenciesList for Go to accept an error handler (#255)
Browse files Browse the repository at this point in the history
  • Loading branch information
asafambar authored Jun 9, 2024
1 parent c0659f1 commit f93a07f
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
2 changes: 1 addition & 1 deletion build/golang.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (gm *GoModule) loadDependencies() ([]entities.Dependency, error) {
}

func (gm *GoModule) getGoDependencies(cachePath string) (map[string]entities.Dependency, error) {
modulesMap, err := utils.GetDependenciesList(gm.srcPath, gm.containingBuild.logger)
modulesMap, err := utils.GetDependenciesList(gm.srcPath, gm.containingBuild.logger, nil)
if err != nil || len(modulesMap) == 0 {
return nil, err
}
Expand Down
13 changes: 11 additions & 2 deletions utils/goutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,25 @@ func getListCmdArgs() (cmdArgs []string, err error) {
return []string{"list", "-mod=mod"}, nil
}

// The handle error function is designed to manage errors that occur while running the
// 'go list' command. If the function returns true, the error will be propagated back to the caller.
type HandleErrorFunc func(err error) (bool, error)

// Runs go list -f {{with .Module}}{{.Path}}:{{.Version}}{{end}} all command and returns map of the dependencies
func GetDependenciesList(projectDir string, log Log) (map[string]bool, error) {
func GetDependenciesList(projectDir string, log Log, handleError HandleErrorFunc) (map[string]bool, error) {
cmdArgs, err := getListCmdArgs()
if err != nil {
return nil, err
}
output, err := runDependenciesCmd(projectDir, append(cmdArgs, "-f", "{{with .Module}}{{.Path}}:{{.Version}}{{end}}", "all"), log)
if err != nil {
// Errors occurred while running "go list". Run again and this time ignore errors (with '-e')
log.Warn("Errors occurred while building the Go dependency tree. The dependency tree may be incomplete: " + err.Error())
if handleError != nil {
if stop, newErr := handleError(err); stop {
return nil, newErr
}
}
// Errors occurred while running "go list". Run again and this time ignore errors (with '-e')
output, err = runDependenciesCmd(projectDir, append(cmdArgs, "-e", "-f", "{{with .Module}}{{.Path}}:{{.Version}}{{end}}", "all"), log)
if err != nil {
return nil, err
Expand Down
20 changes: 16 additions & 4 deletions utils/goutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,24 @@ func TestGetProjectRoot(t *testing.T) {
}

func TestGetDependenciesList(t *testing.T) {
testGetDependenciesList(t, "testGoList")
testGetDependenciesList(t, "testGoList", nil)
}

func TestGetDependenciesListWithIgnoreErrors(t *testing.T) {
// In some cases, we see that running go list on some Go packages may fail.
// We should allow ignoring the errors in such cases and build the Go dependency tree, even if partial.
testGetDependenciesList(t, "testBadGoList")
testGetDependenciesList(t, "testBadGoList", nil)
// In some cases we would like to exit after we receive an error. This can be done with custom error handle func.
// This test handleErrorFunc return an error
testGetDependenciesList(t, "testBadGoList", func(err error) (bool, error) {
if err != nil {
return true, err
}
return false, nil
})
}

func testGetDependenciesList(t *testing.T, testDir string) {
func testGetDependenciesList(t *testing.T, testDir string, errorFunc HandleErrorFunc) {
log := NewDefaultLogger(ERROR)
goModPath := filepath.Join("testdata", "mods", testDir)
err := os.Rename(filepath.Join(goModPath, "go.mod.txt"), filepath.Join(goModPath, "go.mod"))
Expand All @@ -113,7 +121,11 @@ func testGetDependenciesList(t *testing.T, testDir string) {
err = os.Rename(filepath.Join(goModPath, "test.go"), filepath.Join(goModPath, "test.go.txt"))
assert.NoError(t, err)
}()
actual, err := GetDependenciesList(goModPath, log)
actual, err := GetDependenciesList(goModPath, log, errorFunc)
if errorFunc != nil {
assert.Error(t, err)
return
}
assert.NoError(t, err)

// Since Go 1.16 'go list' command won't automatically update go.mod and go.sum.
Expand Down

0 comments on commit f93a07f

Please sign in to comment.