Skip to content

Commit e031c30

Browse files
committed
spdx: use go.mod module path for root package
1 parent 16e0165 commit e031c30

3 files changed

Lines changed: 62 additions & 0 deletions

File tree

mage.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//go:build ignore
12
// +build ignore
23

34
/*

pkg/spdx/gomod_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package spdx
1818

1919
import (
20+
"os"
21+
"path/filepath"
2022
"strings"
2123
"testing"
2224

@@ -49,6 +51,29 @@ func TestToSPDXPackage(t *testing.T) {
4951
}
5052
}
5153

54+
func TestPackageFromDirectory_UsesGoModModulePath(t *testing.T) {
55+
// Create a temporary directory structure with a go.mod at a nested path
56+
dir := t.TempDir()
57+
// Simulate extraction where files are under a subdir
58+
sub := filepath.Join(dir, "submodule")
59+
require.NoError(t, os.MkdirAll(sub, 0o755))
60+
// Write go.mod with module directive
61+
gomod := "module example.com/my/module\n"
62+
require.NoError(t, os.WriteFile(filepath.Join(sub, "go.mod"), []byte(gomod), 0o644))
63+
64+
// Create a dummy file so PackageFromDirectory has something to scan
65+
require.NoError(t, os.WriteFile(filepath.Join(sub, "main.go"), []byte("package main"), 0o644))
66+
67+
// Call PackageFromDirectory on the parent dir; implementation should
68+
// discover go.mod in scanned file tree and use module path.
69+
di := &spdxDefaultImplementation{}
70+
opts := &Options{IgnorePatterns: []string{}}
71+
pkg, err := di.PackageFromDirectory(opts, dir)
72+
require.NoError(t, err)
73+
require.NotNil(t, pkg)
74+
require.Equal(t, "example.com/my/module", pkg.Name)
75+
}
76+
5277
func TestPackageURL(t *testing.T) {
5378
for _, tc := range []struct {
5479
pkg GoPackage

pkg/spdx/implementation.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,43 @@ func (di *spdxDefaultImplementation) PackageFromDirectory(opts *Options, dirPath
10281028

10291029
pkg = NewPackage()
10301030
pkg.FilesAnalyzed = true
1031+
// Default package name is the directory base name. If this directory
1032+
// (or one of its top-level children created during extraction) contains
1033+
// a go.mod, prefer the module path defined there so the root package
1034+
// reflects the module import path instead of a temp dirname.
10311035
pkg.Name = filepath.Base(dirPath)
1036+
1037+
// Look for a go.mod either at the root dirPath or in the scanned file
1038+
// tree (which may contain a nested module after extraction). Prefer an
1039+
// explicit go.mod at dirPath if present, otherwise use the first
1040+
// occurrence from fileList.
1041+
goModDir := ""
1042+
if helpers.Exists(filepath.Join(dirPath, GoModFileName)) {
1043+
goModDir = dirPath
1044+
} else {
1045+
for _, p := range fileList {
1046+
if filepath.Base(p) == GoModFileName {
1047+
// p is a relative path; derive the directory containing go.mod
1048+
goModDir = filepath.Join(dirPath, filepath.Dir(p))
1049+
break
1050+
}
1051+
}
1052+
}
1053+
1054+
if goModDir != "" {
1055+
// Try to read the module path from go.mod without doing full module
1056+
// processing. NewGoModuleFromPath provides a GoModule with the
1057+
// GoModDefaultImpl which implements OpenModule for parsing only.
1058+
if gm, err := NewGoModuleFromPath(goModDir); err == nil {
1059+
if gomod, err := gm.impl.OpenModule(gm.Options()); err == nil {
1060+
if gomod != nil && gomod.Module != nil && gomod.Module.Mod.Path != "" {
1061+
pkg.Name = gomod.Module.Mod.Path
1062+
}
1063+
} else {
1064+
logrus.Debugf("unable to parse go.mod for %s: %v", goModDir, err)
1065+
}
1066+
}
1067+
}
10321068
if pkg.Name == "" {
10331069
pkg.Name = uuid.NewString()
10341070
}

0 commit comments

Comments
 (0)