better go mod detection from partial package builds (#3060)

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Alex Goodman
2024-07-24 09:34:40 -04:00
committed by GitHub
parent ca945d16e0
commit 9573f557d1
3 changed files with 141 additions and 12 deletions
+44 -10
View File
@@ -11,6 +11,7 @@ import (
"io"
"regexp"
"runtime/debug"
"slices"
"strings"
"time"
@@ -97,17 +98,19 @@ func createModuleRelationships(main pkg.Package, deps []pkg.Package) []artifact.
return relationships
}
var emptyModule debug.Module
var moduleFromPartialPackageBuild = debug.Module{Path: "command-line-arguments"}
func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file.Location, mod *extendedBuildInfo, arch string, reader io.ReadSeekCloser) (*pkg.Package, []pkg.Package) {
var pkgs []pkg.Package
if mod == nil {
return nil, pkgs
return nil, nil
}
var empty debug.Module
if mod.Main == empty && mod.Path != "" {
mod.Main = createMainModuleFromPath(mod.Path)
if missingMainModule(mod) {
mod.Main = createMainModuleFromPath(mod)
}
var pkgs []pkg.Package
for _, dep := range mod.Deps {
if dep == nil {
continue
@@ -130,7 +133,7 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file
}
}
if mod.Main == empty {
if mod.Main == emptyModule {
return nil, pkgs
}
@@ -139,6 +142,16 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file
return &main, pkgs
}
func missingMainModule(mod *extendedBuildInfo) bool {
if mod.Main == emptyModule && mod.Path != "" {
return true
}
// special case: when invoking go build with a source file and not a package (directory) then you will
// see "command-line-arguments" as the main module path... even though that's not the main module. In this
// circumstance, we should treat the main module as missing and search for it within the dependencies.
return mod.Main == moduleFromPartialPackageBuild
}
func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *extendedBuildInfo, arch string, location file.Location, reader io.ReadSeekCloser) pkg.Package {
gbs := getBuildSettings(mod.Settings)
gover, experiments := getExperimentsFromVersion(mod.GoVersion)
@@ -358,8 +371,29 @@ func getExperimentsFromVersion(version string) (string, []string) {
return version, experiments
}
func createMainModuleFromPath(path string) (mod debug.Module) {
mod.Path = path
mod.Version = devel
return
func createMainModuleFromPath(existing *extendedBuildInfo) debug.Module {
// search for a main module candidate within the dependencies
var mainModuleCandidates []debug.Module
var usedIndex int
for i, dep := range existing.Deps {
if dep == nil {
continue
}
if dep.Version == devel {
usedIndex = i
mainModuleCandidates = append(mainModuleCandidates, *dep)
}
}
if len(mainModuleCandidates) == 1 {
// we need to prune the dependency from module list
existing.Deps = slices.Delete(existing.Deps, usedIndex, usedIndex+1)
return mainModuleCandidates[0]
}
// otherwise craft a main module from the path (a bit of a cop out, but allows us to have a main module)
return debug.Module{
Path: existing.Path,
Version: devel,
}
}