mirror of
https://github.com/anchore/syft.git
synced 2026-05-20 04:05:24 +02:00
chore(deps): update Go version (#4773)
Signed-off-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com> Co-authored-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com>
This commit is contained in:
parent
26e87c7cd3
commit
5b58ec96b7
10
.github/actions/bootstrap/action.yaml
vendored
10
.github/actions/bootstrap/action.yaml
vendored
@ -1,11 +1,10 @@
|
|||||||
name: "Bootstrap"
|
name: "Bootstrap"
|
||||||
|
|
||||||
description: "Bootstrap all tools and dependencies"
|
description: "Bootstrap all tools and dependencies"
|
||||||
inputs:
|
inputs:
|
||||||
go-version:
|
go-version:
|
||||||
description: "Go version to install"
|
description: "Go version to install"
|
||||||
required: true
|
required: true
|
||||||
default: "1.26.x"
|
default: "1.26.2"
|
||||||
go-dependencies:
|
go-dependencies:
|
||||||
description: "Download go dependencies"
|
description: "Download go dependencies"
|
||||||
required: true
|
required: true
|
||||||
@ -24,7 +23,6 @@ inputs:
|
|||||||
bootstrap-apt-packages:
|
bootstrap-apt-packages:
|
||||||
description: "Space delimited list of tools to install via apt"
|
description: "Space delimited list of tools to install via apt"
|
||||||
default: "libxml2-utils"
|
default: "libxml2-utils"
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
@ -34,7 +32,6 @@ runs:
|
|||||||
with:
|
with:
|
||||||
go-version: ${{ inputs.go-version }}
|
go-version: ${{ inputs.go-version }}
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: Restore tool cache
|
- name: Restore tool cache
|
||||||
if: inputs.tools == 'true'
|
if: inputs.tools == 'true'
|
||||||
id: tool-cache
|
id: tool-cache
|
||||||
@ -42,7 +39,6 @@ runs:
|
|||||||
with:
|
with:
|
||||||
path: ${{ github.workspace }}/.tool
|
path: ${{ github.workspace }}/.tool
|
||||||
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }}
|
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }}
|
||||||
|
|
||||||
- name: Install project tools
|
- name: Install project tools
|
||||||
shell: bash
|
shell: bash
|
||||||
if: inputs.tools == 'true'
|
if: inputs.tools == 'true'
|
||||||
@ -50,12 +46,10 @@ runs:
|
|||||||
make tools
|
make tools
|
||||||
.tool/binny list
|
.tool/binny list
|
||||||
.tool/binny check
|
.tool/binny check
|
||||||
|
|
||||||
- name: Install go dependencies
|
- name: Install go dependencies
|
||||||
if: inputs.go-dependencies == 'true'
|
if: inputs.go-dependencies == 'true'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: make ci-bootstrap-go
|
run: make ci-bootstrap-go
|
||||||
|
|
||||||
- name: Install apt packages
|
- name: Install apt packages
|
||||||
if: inputs.bootstrap-apt-packages != ''
|
if: inputs.bootstrap-apt-packages != ''
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -64,14 +58,12 @@ runs:
|
|||||||
run: |
|
run: |
|
||||||
IFS=' ' read -ra packages <<< "$APT_PACKAGES"
|
IFS=' ' read -ra packages <<< "$APT_PACKAGES"
|
||||||
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y "${packages[@]}"
|
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y "${packages[@]}"
|
||||||
|
|
||||||
- name: Restore ORAS cache from github actions
|
- name: Restore ORAS cache from github actions
|
||||||
if: inputs.download-test-fixture-cache == 'true'
|
if: inputs.download-test-fixture-cache == 'true'
|
||||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||||
with:
|
with:
|
||||||
path: ${{ github.workspace }}/.tmp/oras-cache
|
path: ${{ github.workspace }}/.tmp/oras-cache
|
||||||
key: ${{ inputs.cache-key-prefix }}-oras-cache
|
key: ${{ inputs.cache-key-prefix }}-oras-cache
|
||||||
|
|
||||||
- name: Download test fixture cache
|
- name: Download test fixture cache
|
||||||
if: inputs.download-test-fixture-cache == 'true'
|
if: inputs.download-test-fixture-cache == 'true'
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@ -59,7 +59,7 @@ func Attest(app clio.Application) *cobra.Command {
|
|||||||
Use: "attest --output [FORMAT] <IMAGE>",
|
Use: "attest --output [FORMAT] <IMAGE>",
|
||||||
Short: "Generate an SBOM as an attestation for the given [SOURCE] container image",
|
Short: "Generate an SBOM as an attestation for the given [SOURCE] container image",
|
||||||
Long: "Generate a packaged-based Software Bill Of Materials (SBOM) from a container image as the predicate of an in-toto attestation that will be uploaded to the image registry",
|
Long: "Generate a packaged-based Software Bill Of Materials (SBOM) from a container image as the predicate of an in-toto attestation that will be uploaded to the image registry",
|
||||||
Example: internal.Tprintf(attestHelp, map[string]interface{}{
|
Example: internal.Tprintf(attestHelp, map[string]any{
|
||||||
"appName": id.Name,
|
"appName": id.Name,
|
||||||
"command": "attest",
|
"command": "attest",
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -248,12 +249,7 @@ func renderCatalogerInfoJSON(doc *capabilities.Document, catalogers []capabiliti
|
|||||||
|
|
||||||
// isDeprecatedCataloger checks if a cataloger is deprecated based on its selectors
|
// isDeprecatedCataloger checks if a cataloger is deprecated based on its selectors
|
||||||
func isDeprecatedCataloger(selectors []string) bool {
|
func isDeprecatedCataloger(selectors []string) bool {
|
||||||
for _, selector := range selectors {
|
return slices.Contains(selectors, "deprecated")
|
||||||
if selector == "deprecated" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertDetectorPackages converts detector package info to the JSON output format
|
// convertDetectorPackages converts detector package info to the JSON output format
|
||||||
@ -452,7 +448,7 @@ func extractArrayCapability(caps capabilities.CapabilitySet, name string) string
|
|||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
return strings.Join(v, ", ")
|
return strings.Join(v, ", ")
|
||||||
}
|
}
|
||||||
case []interface{}:
|
case []any:
|
||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
strs := make([]string, 0, len(v))
|
strs := make([]string, 0, len(v))
|
||||||
for _, item := range v {
|
for _, item := range v {
|
||||||
@ -475,7 +471,7 @@ func extractNodesCapability(caps capabilities.CapabilitySet) string {
|
|||||||
switch v := cap.Default.(type) {
|
switch v := cap.Default.(type) {
|
||||||
case []string:
|
case []string:
|
||||||
return formatDepthStringArray(v)
|
return formatDepthStringArray(v)
|
||||||
case []interface{}:
|
case []any:
|
||||||
return formatDepthInterfaceArray(v)
|
return formatDepthInterfaceArray(v)
|
||||||
}
|
}
|
||||||
return noStyle.Render("·")
|
return noStyle.Render("·")
|
||||||
@ -496,7 +492,7 @@ func formatDepthStringArray(v []string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// formatDepthInterfaceArray formats a []interface{} dependency depth value
|
// formatDepthInterfaceArray formats a []interface{} dependency depth value
|
||||||
func formatDepthInterfaceArray(v []interface{}) string {
|
func formatDepthInterfaceArray(v []any) string {
|
||||||
if len(v) == 0 {
|
if len(v) == 0 {
|
||||||
return noStyle.Render("·")
|
return noStyle.Render("·")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,7 @@ func Convert(app clio.Application) *cobra.Command {
|
|||||||
Use: "convert [SOURCE-SBOM] -o [FORMAT]",
|
Use: "convert [SOURCE-SBOM] -o [FORMAT]",
|
||||||
Short: "Convert between SBOM formats",
|
Short: "Convert between SBOM formats",
|
||||||
Long: "[Experimental] Convert SBOM files to, and from, SPDX, CycloneDX and Syft's format. For more info about data loss between formats see https://github.com/anchore/syft/wiki/format-conversion",
|
Long: "[Experimental] Convert SBOM files to, and from, SPDX, CycloneDX and Syft's format. For more info about data loss between formats see https://github.com/anchore/syft/wiki/format-conversion",
|
||||||
Example: internal.Tprintf(convertExample, map[string]interface{}{
|
Example: internal.Tprintf(convertExample, map[string]any{
|
||||||
"appName": id.Name,
|
"appName": id.Name,
|
||||||
"command": "convert",
|
"command": "convert",
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -18,7 +18,7 @@ func Packages(app clio.Application, scanCmd *cobra.Command) *cobra.Command {
|
|||||||
Short: scanCmd.Short,
|
Short: scanCmd.Short,
|
||||||
Long: scanCmd.Long,
|
Long: scanCmd.Long,
|
||||||
Args: scanCmd.Args,
|
Args: scanCmd.Args,
|
||||||
Example: internal.Tprintf(scanHelp, map[string]interface{}{
|
Example: internal.Tprintf(scanHelp, map[string]any{
|
||||||
"appName": id.Name,
|
"appName": id.Name,
|
||||||
"command": "packages",
|
"command": "packages",
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -29,7 +29,7 @@ func Test_filterExpressionErrors_expressionErrorsHelp(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "single non-expression error is retained",
|
name: "single non-expression error is retained",
|
||||||
err: errors.New("foo"),
|
err: errors.New("foo"),
|
||||||
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
|
wantErr: func(t assert.TestingT, err error, i ...any) bool {
|
||||||
return assert.Equal(t, "foo", err.Error())
|
return assert.Equal(t, "foo", err.Error())
|
||||||
},
|
},
|
||||||
wantHelp: "",
|
wantHelp: "",
|
||||||
@ -42,7 +42,7 @@ func Test_filterExpressionErrors_expressionErrorsHelp(t *testing.T) {
|
|||||||
err = multierror.Append(err, errors.New("bar"))
|
err = multierror.Append(err, errors.New("bar"))
|
||||||
return err
|
return err
|
||||||
}(),
|
}(),
|
||||||
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
|
wantErr: func(t assert.TestingT, err error, i ...any) bool {
|
||||||
// note: this is the default formatting from the hashicorp multierror object
|
// note: this is the default formatting from the hashicorp multierror object
|
||||||
expected := `2 errors occurred:
|
expected := `2 errors occurred:
|
||||||
* foo
|
* foo
|
||||||
@ -64,7 +64,7 @@ func Test_filterExpressionErrors_expressionErrorsHelp(t *testing.T) {
|
|||||||
err = multierror.Append(err, errors.New("last"))
|
err = multierror.Append(err, errors.New("last"))
|
||||||
return err
|
return err
|
||||||
}(),
|
}(),
|
||||||
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
|
wantErr: func(t assert.TestingT, err error, i ...any) bool {
|
||||||
expected := `5 errors occurred:
|
expected := `5 errors occurred:
|
||||||
* foo
|
* foo
|
||||||
* invalid expression: "foo": tags are not allowed with this operation (must use exact names)
|
* invalid expression: "foo": tags are not allowed with this operation (must use exact names)
|
||||||
@ -103,7 +103,7 @@ func Test_filterExpressionErrors_expressionErrorsHelp(t *testing.T) {
|
|||||||
|
|
||||||
return fmt.Errorf("top: %w", fmt.Errorf("middle: %w", err))
|
return fmt.Errorf("top: %w", fmt.Errorf("middle: %w", err))
|
||||||
}(),
|
}(),
|
||||||
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
|
wantErr: func(t assert.TestingT, err error, i ...any) bool {
|
||||||
expected := `top: middle: 4 errors occurred:
|
expected := `top: middle: 4 errors occurred:
|
||||||
* foo: bar: last
|
* foo: bar: last
|
||||||
* invalid expression: "foo": tags are not allowed with this operation (must use exact names)
|
* invalid expression: "foo": tags are not allowed with this operation (must use exact names)
|
||||||
@ -142,7 +142,7 @@ func Test_filterExpressionErrors_expressionErrorsHelp(t *testing.T) {
|
|||||||
// note we wrap the top error in a chain
|
// note we wrap the top error in a chain
|
||||||
return fmt.Errorf("top: %w", fmt.Errorf("middle: %w", err))
|
return fmt.Errorf("top: %w", fmt.Errorf("middle: %w", err))
|
||||||
}(),
|
}(),
|
||||||
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
|
wantErr: func(t assert.TestingT, err error, i ...any) bool {
|
||||||
expected := `top: middle: 4 errors occurred:
|
expected := `top: middle: 4 errors occurred:
|
||||||
* foo: bar: last
|
* foo: bar: last
|
||||||
* invalid expression: "foo": tags are not allowed with this operation (must use exact names)
|
* invalid expression: "foo": tags are not allowed with this operation (must use exact names)
|
||||||
@ -178,7 +178,7 @@ func Test_filterExpressionErrors_expressionErrorsHelp(t *testing.T) {
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}(),
|
}(),
|
||||||
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
|
wantErr: func(t assert.TestingT, err error, i ...any) bool {
|
||||||
// note: the errors are removed and the help text shows the enriched error help
|
// note: the errors are removed and the help text shows the enriched error help
|
||||||
expected := `2 errors occurred:
|
expected := `2 errors occurred:
|
||||||
* invalid expression: "foo": tags are not allowed with this operation (must use exact names)
|
* invalid expression: "foo": tags are not allowed with this operation (must use exact names)
|
||||||
|
|||||||
@ -92,7 +92,7 @@ func Scan(app clio.Application) *cobra.Command {
|
|||||||
Use: "scan [SOURCE]",
|
Use: "scan [SOURCE]",
|
||||||
Short: "Generate an SBOM",
|
Short: "Generate an SBOM",
|
||||||
Long: "Generate a packaged-based Software Bill Of Materials (SBOM) from container images and filesystems",
|
Long: "Generate a packaged-based Software Bill Of Materials (SBOM) from container images and filesystems",
|
||||||
Example: internal.Tprintf(scanHelp, map[string]interface{}{
|
Example: internal.Tprintf(scanHelp, map[string]any{
|
||||||
"appName": id.Name,
|
"appName": id.Name,
|
||||||
"command": "scan",
|
"command": "scan",
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -60,7 +60,7 @@ func Test_scanOptions_validateLegacyOptionsNotUsed(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func assertErrorContains(contains string) assert.ErrorAssertionFunc {
|
func assertErrorContains(contains string) assert.ErrorAssertionFunc {
|
||||||
return func(t assert.TestingT, err error, i ...interface{}) bool {
|
return func(t assert.TestingT, err error, i ...any) bool {
|
||||||
return assert.ErrorContains(t, err, contains, i...)
|
return assert.ErrorContains(t, err, contains, i...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package options
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -313,10 +314,8 @@ func enrichmentEnabled(enrichDirectives []string, features ...string) *bool {
|
|||||||
directive = directive[1:]
|
directive = directive[1:]
|
||||||
enable = false
|
enable = false
|
||||||
}
|
}
|
||||||
for _, feature := range features {
|
if slices.Contains(features, directive) {
|
||||||
if directive == feature {
|
return &enable
|
||||||
return &enable
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -32,7 +32,7 @@ func Test_MakeSBOMWriter(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "unknown format",
|
name: "unknown format",
|
||||||
outputs: []string{"unknown"},
|
outputs: []string{"unknown"},
|
||||||
wantErr: func(t assert.TestingT, err error, bla ...interface{}) bool {
|
wantErr: func(t assert.TestingT, err error, bla ...any) bool {
|
||||||
return assert.ErrorContains(t, err, `unsupported output format "unknown", supported formats are:`)
|
return assert.ErrorContains(t, err, `unsupported output format "unknown", supported formats are:`)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package integration
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -194,11 +195,8 @@ func assertPackages(t *testing.T, sbom sbom.SBOM, test testCase, observedLanguag
|
|||||||
}
|
}
|
||||||
|
|
||||||
var foundLang bool
|
var foundLang bool
|
||||||
for _, lang := range strings.Split(test.pkgLanguage.String(), ",") {
|
if slices.Contains(strings.Split(test.pkgLanguage.String(), ","), actualPkg.Language.String()) {
|
||||||
if actualPkg.Language.String() == lang {
|
foundLang = true
|
||||||
foundLang = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !foundLang {
|
if !foundLang {
|
||||||
t.Errorf("bad language (pkg=%+v): %+v", actualPkg.Name, actualPkg.Language)
|
t.Errorf("bad language (pkg=%+v): %+v", actualPkg.Name, actualPkg.Language)
|
||||||
|
|||||||
@ -329,7 +329,7 @@ func packageCatalogerExports(t *testing.T) map[string]exportTokenSet {
|
|||||||
}
|
}
|
||||||
exportsPerPackage[pkg].Add(exportToken{
|
exportsPerPackage[pkg].Add(exportToken{
|
||||||
Name: decl.Name.Name,
|
Name: decl.Name.Name,
|
||||||
Type: reflect.TypeOf(decl.Type).String(),
|
Type: reflect.TypeFor[*ast.FuncType]().String(),
|
||||||
SignatureSize: len(decl.Type.Params.List),
|
SignatureSize: len(decl.Type.Params.List),
|
||||||
ReturnTypeNames: returnTypes,
|
ReturnTypeNames: returnTypes,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -36,33 +36,33 @@ func Test_logWriter(t *testing.T) {
|
|||||||
|
|
||||||
type bufferLogger struct{ values []any }
|
type bufferLogger struct{ values []any }
|
||||||
|
|
||||||
func (l *bufferLogger) Tracef(_ string, _ ...interface{}) {}
|
func (l *bufferLogger) Tracef(_ string, _ ...any) {}
|
||||||
|
|
||||||
func (l *bufferLogger) Debugf(_ string, _ ...interface{}) {}
|
func (l *bufferLogger) Debugf(_ string, _ ...any) {}
|
||||||
|
|
||||||
func (l *bufferLogger) Infof(_ string, _ ...interface{}) {}
|
func (l *bufferLogger) Infof(_ string, _ ...any) {}
|
||||||
|
|
||||||
func (l *bufferLogger) Warnf(_ string, _ ...interface{}) {}
|
func (l *bufferLogger) Warnf(_ string, _ ...any) {}
|
||||||
|
|
||||||
func (l *bufferLogger) Errorf(_ string, _ ...interface{}) {}
|
func (l *bufferLogger) Errorf(_ string, _ ...any) {}
|
||||||
|
|
||||||
func (l *bufferLogger) Trace(vals ...interface{}) {
|
func (l *bufferLogger) Trace(vals ...any) {
|
||||||
l.values = append(l.values, vals...)
|
l.values = append(l.values, vals...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *bufferLogger) Debug(_ ...interface{}) {}
|
func (l *bufferLogger) Debug(_ ...any) {}
|
||||||
|
|
||||||
func (l *bufferLogger) Info(_ ...interface{}) {}
|
func (l *bufferLogger) Info(_ ...any) {}
|
||||||
|
|
||||||
func (l *bufferLogger) Warn(vals ...interface{}) {
|
func (l *bufferLogger) Warn(vals ...any) {
|
||||||
l.values = append(l.values, vals...)
|
l.values = append(l.values, vals...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *bufferLogger) Error(_ ...interface{}) {}
|
func (l *bufferLogger) Error(_ ...any) {}
|
||||||
|
|
||||||
func (l *bufferLogger) WithFields(_ ...interface{}) logger.MessageLogger { return l }
|
func (l *bufferLogger) WithFields(_ ...any) logger.MessageLogger { return l }
|
||||||
|
|
||||||
func (l *bufferLogger) Nested(_ ...interface{}) logger.Logger { return l }
|
func (l *bufferLogger) Nested(_ ...any) logger.Logger { return l }
|
||||||
|
|
||||||
func (l *bufferLogger) SetOutput(_ io.Writer) {}
|
func (l *bufferLogger) SetOutput(_ io.Writer) {}
|
||||||
|
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -1,6 +1,6 @@
|
|||||||
module github.com/anchore/syft
|
module github.com/anchore/syft
|
||||||
|
|
||||||
go 1.25.8
|
go 1.26.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.6.0
|
github.com/BurntSushi/toml v1.6.0
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import "reflect"
|
|||||||
// EvaluateCapabilities evaluates a capability set against a given configuration
|
// EvaluateCapabilities evaluates a capability set against a given configuration
|
||||||
// and returns the effective capability values as a flat map.
|
// and returns the effective capability values as a flat map.
|
||||||
// Example: {"license": false, "dependency.depth": ["direct", "indirect"]}
|
// Example: {"license": false, "dependency.depth": ["direct", "indirect"]}
|
||||||
func EvaluateCapabilities(caps CapabilitySet, config map[string]interface{}) map[string]interface{} {
|
func EvaluateCapabilities(caps CapabilitySet, config map[string]any) map[string]any {
|
||||||
result := make(map[string]interface{})
|
result := make(map[string]any)
|
||||||
for _, capField := range caps {
|
for _, capField := range caps {
|
||||||
result[capField.Name] = EvaluateField(capField, config)
|
result[capField.Name] = EvaluateField(capField, config)
|
||||||
}
|
}
|
||||||
@ -16,7 +16,7 @@ func EvaluateCapabilities(caps CapabilitySet, config map[string]interface{}) map
|
|||||||
// EvaluateField evaluates a single capability field against a configuration.
|
// EvaluateField evaluates a single capability field against a configuration.
|
||||||
// Conditions are evaluated in order, and the first matching condition's value is returned.
|
// Conditions are evaluated in order, and the first matching condition's value is returned.
|
||||||
// If no conditions match, the default value is returned.
|
// If no conditions match, the default value is returned.
|
||||||
func EvaluateField(capField CapabilityField, config map[string]interface{}) interface{} {
|
func EvaluateField(capField CapabilityField, config map[string]any) any {
|
||||||
// check conditions in order (first match wins)
|
// check conditions in order (first match wins)
|
||||||
for _, cond := range capField.Conditions {
|
for _, cond := range capField.Conditions {
|
||||||
if ConditionMatches(cond.When, config) {
|
if ConditionMatches(cond.When, config) {
|
||||||
@ -30,7 +30,7 @@ func EvaluateField(capField CapabilityField, config map[string]interface{}) inte
|
|||||||
// ConditionMatches checks if a condition's when clause matches the given configuration.
|
// ConditionMatches checks if a condition's when clause matches the given configuration.
|
||||||
// All fields in the when clause must match the config (AND logic).
|
// All fields in the when clause must match the config (AND logic).
|
||||||
// Returns true if all key-value pairs in when match the config.
|
// Returns true if all key-value pairs in when match the config.
|
||||||
func ConditionMatches(when map[string]interface{}, config map[string]interface{}) bool {
|
func ConditionMatches(when map[string]any, config map[string]any) bool {
|
||||||
// all fields in when must match config (AND logic)
|
// all fields in when must match config (AND logic)
|
||||||
for key, expectedValue := range when {
|
for key, expectedValue := range when {
|
||||||
actualValue, exists := config[key]
|
actualValue, exists := config[key]
|
||||||
@ -46,7 +46,7 @@ func ConditionMatches(when map[string]interface{}, config map[string]interface{}
|
|||||||
|
|
||||||
// valuesEqual compares two values for equality, handling different types appropriately.
|
// valuesEqual compares two values for equality, handling different types appropriately.
|
||||||
// Uses reflect.DeepEqual for complex types like slices and maps.
|
// Uses reflect.DeepEqual for complex types like slices and maps.
|
||||||
func valuesEqual(a, b interface{}) bool {
|
func valuesEqual(a, b any) bool {
|
||||||
// handle nil cases
|
// handle nil cases
|
||||||
if a == nil && b == nil {
|
if a == nil && b == nil {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@ -10,8 +10,8 @@ import (
|
|||||||
func Test_valuesEqual(t *testing.T) {
|
func Test_valuesEqual(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
a interface{}
|
a any
|
||||||
b interface{}
|
b any
|
||||||
want bool
|
want bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@ -123,47 +123,47 @@ func Test_valuesEqual(t *testing.T) {
|
|||||||
func TestConditionMatches(t *testing.T) {
|
func TestConditionMatches(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
when map[string]interface{}
|
when map[string]any
|
||||||
config map[string]interface{}
|
config map[string]any
|
||||||
want bool
|
want bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty when clause matches anything",
|
name: "empty when clause matches anything",
|
||||||
when: map[string]interface{}{},
|
when: map[string]any{},
|
||||||
config: map[string]interface{}{"key": "value"},
|
config: map[string]any{"key": "value"},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty when clause with empty config",
|
name: "empty when clause with empty config",
|
||||||
when: map[string]interface{}{},
|
when: map[string]any{},
|
||||||
config: map[string]interface{}{},
|
config: map[string]any{},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single key match",
|
name: "single key match",
|
||||||
when: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
when: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
config: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single key mismatch",
|
name: "single key mismatch",
|
||||||
when: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
when: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": false},
|
config: map[string]any{"SearchLocalModCacheLicenses": false},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "key missing from config",
|
name: "key missing from config",
|
||||||
when: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
when: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||||
config: map[string]interface{}{},
|
config: map[string]any{},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple keys all match",
|
name: "multiple keys all match",
|
||||||
when: map[string]interface{}{
|
when: map[string]any{
|
||||||
"SearchLocalModCacheLicenses": true,
|
"SearchLocalModCacheLicenses": true,
|
||||||
"UseNetwork": true,
|
"UseNetwork": true,
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{
|
config: map[string]any{
|
||||||
"SearchLocalModCacheLicenses": true,
|
"SearchLocalModCacheLicenses": true,
|
||||||
"UseNetwork": true,
|
"UseNetwork": true,
|
||||||
"ExtraKey": "ignored",
|
"ExtraKey": "ignored",
|
||||||
@ -172,11 +172,11 @@ func TestConditionMatches(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple keys one mismatch",
|
name: "multiple keys one mismatch",
|
||||||
when: map[string]interface{}{
|
when: map[string]any{
|
||||||
"SearchLocalModCacheLicenses": true,
|
"SearchLocalModCacheLicenses": true,
|
||||||
"UseNetwork": true,
|
"UseNetwork": true,
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{
|
config: map[string]any{
|
||||||
"SearchLocalModCacheLicenses": true,
|
"SearchLocalModCacheLicenses": true,
|
||||||
"UseNetwork": false,
|
"UseNetwork": false,
|
||||||
},
|
},
|
||||||
@ -184,31 +184,31 @@ func TestConditionMatches(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple keys one missing",
|
name: "multiple keys one missing",
|
||||||
when: map[string]interface{}{
|
when: map[string]any{
|
||||||
"SearchLocalModCacheLicenses": true,
|
"SearchLocalModCacheLicenses": true,
|
||||||
"UseNetwork": true,
|
"UseNetwork": true,
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{
|
config: map[string]any{
|
||||||
"SearchLocalModCacheLicenses": true,
|
"SearchLocalModCacheLicenses": true,
|
||||||
},
|
},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "string value match",
|
name: "string value match",
|
||||||
when: map[string]interface{}{"mode": "fast"},
|
when: map[string]any{"mode": "fast"},
|
||||||
config: map[string]interface{}{"mode": "fast"},
|
config: map[string]any{"mode": "fast"},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "slice value match",
|
name: "slice value match",
|
||||||
when: map[string]interface{}{"formats": []string{"json", "yaml"}},
|
when: map[string]any{"formats": []string{"json", "yaml"}},
|
||||||
config: map[string]interface{}{"formats": []string{"json", "yaml"}},
|
config: map[string]any{"formats": []string{"json", "yaml"}},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "slice value mismatch",
|
name: "slice value mismatch",
|
||||||
when: map[string]interface{}{"formats": []string{"json", "yaml"}},
|
when: map[string]any{"formats": []string{"json", "yaml"}},
|
||||||
config: map[string]interface{}{"formats": []string{"json", "xml"}},
|
config: map[string]any{"formats": []string{"json", "xml"}},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -225,8 +225,8 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
capField CapabilityField
|
capField CapabilityField
|
||||||
config map[string]interface{}
|
config map[string]any
|
||||||
want interface{}
|
want any
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no conditions returns default",
|
name: "no conditions returns default",
|
||||||
@ -235,7 +235,7 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
Default: false,
|
Default: false,
|
||||||
Conditions: nil,
|
Conditions: nil,
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{},
|
config: map[string]any{},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -245,7 +245,7 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
Default: false,
|
Default: false,
|
||||||
Conditions: []CapabilityCondition{},
|
Conditions: []CapabilityCondition{},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{},
|
config: map[string]any{},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -260,7 +260,7 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
config: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -275,7 +275,7 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": false},
|
config: map[string]any{"SearchLocalModCacheLicenses": false},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -294,7 +294,7 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{
|
config: map[string]any{
|
||||||
"SearchLocalModCacheLicenses": true,
|
"SearchLocalModCacheLicenses": true,
|
||||||
"SearchRemoteLicenses": true,
|
"SearchRemoteLicenses": true,
|
||||||
},
|
},
|
||||||
@ -316,7 +316,7 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{
|
config: map[string]any{
|
||||||
"SearchLocalModCacheLicenses": false,
|
"SearchLocalModCacheLicenses": false,
|
||||||
"SearchRemoteLicenses": true,
|
"SearchRemoteLicenses": true,
|
||||||
},
|
},
|
||||||
@ -338,7 +338,7 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{
|
config: map[string]any{
|
||||||
"SearchLocalModCacheLicenses": false,
|
"SearchLocalModCacheLicenses": false,
|
||||||
"SearchRemoteLicenses": false,
|
"SearchRemoteLicenses": false,
|
||||||
},
|
},
|
||||||
@ -351,7 +351,7 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
Default: []string{"direct", "indirect"},
|
Default: []string{"direct", "indirect"},
|
||||||
Conditions: nil,
|
Conditions: nil,
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{},
|
config: map[string]any{},
|
||||||
want: []string{"direct", "indirect"},
|
want: []string{"direct", "indirect"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -369,7 +369,7 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{
|
config: map[string]any{
|
||||||
"EnableFeatureA": true,
|
"EnableFeatureA": true,
|
||||||
"EnableFeatureB": true,
|
"EnableFeatureB": true,
|
||||||
},
|
},
|
||||||
@ -390,7 +390,7 @@ func TestEvaluateField(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{
|
config: map[string]any{
|
||||||
"EnableFeatureA": true,
|
"EnableFeatureA": true,
|
||||||
"EnableFeatureB": false,
|
"EnableFeatureB": false,
|
||||||
},
|
},
|
||||||
@ -412,14 +412,14 @@ func TestEvaluateCapabilities(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
caps CapabilitySet
|
caps CapabilitySet
|
||||||
config map[string]interface{}
|
config map[string]any
|
||||||
want map[string]interface{}
|
want map[string]any
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty capability set",
|
name: "empty capability set",
|
||||||
caps: CapabilitySet{},
|
caps: CapabilitySet{},
|
||||||
config: map[string]interface{}{},
|
config: map[string]any{},
|
||||||
want: map[string]interface{}{},
|
want: map[string]any{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single capability no conditions",
|
name: "single capability no conditions",
|
||||||
@ -429,8 +429,8 @@ func TestEvaluateCapabilities(t *testing.T) {
|
|||||||
Default: false,
|
Default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{},
|
config: map[string]any{},
|
||||||
want: map[string]interface{}{
|
want: map[string]any{
|
||||||
"license": false,
|
"license": false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -448,8 +448,8 @@ func TestEvaluateCapabilities(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
config: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||||
want: map[string]interface{}{
|
want: map[string]any{
|
||||||
"license": true,
|
"license": true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -475,8 +475,8 @@ func TestEvaluateCapabilities(t *testing.T) {
|
|||||||
Default: "flat",
|
Default: "flat",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
config: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||||
want: map[string]interface{}{
|
want: map[string]any{
|
||||||
"license": true,
|
"license": true,
|
||||||
"dependency.depth": []string{"direct", "indirect"},
|
"dependency.depth": []string{"direct", "indirect"},
|
||||||
"dependency.edges": "flat",
|
"dependency.edges": "flat",
|
||||||
@ -512,11 +512,11 @@ func TestEvaluateCapabilities(t *testing.T) {
|
|||||||
Default: false,
|
Default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: map[string]interface{}{
|
config: map[string]any{
|
||||||
"SearchLocalModCacheLicenses": false,
|
"SearchLocalModCacheLicenses": false,
|
||||||
"SearchRemoteLicenses": true,
|
"SearchRemoteLicenses": true,
|
||||||
},
|
},
|
||||||
want: map[string]interface{}{
|
want: map[string]any{
|
||||||
"license": true,
|
"license": true,
|
||||||
"dependency.depth": []string{"direct", "indirect"},
|
"dependency.depth": []string{"direct", "indirect"},
|
||||||
"dependency.edges": "flat",
|
"dependency.edges": "flat",
|
||||||
@ -526,10 +526,10 @@ func TestEvaluateCapabilities(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "nil capability set",
|
name: "nil capability set",
|
||||||
caps: nil,
|
caps: nil,
|
||||||
config: map[string]interface{}{
|
config: map[string]any{
|
||||||
"anything": true,
|
"anything": true,
|
||||||
},
|
},
|
||||||
want: map[string]interface{}{},
|
want: map[string]any{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,9 +15,9 @@ import (
|
|||||||
|
|
||||||
// AppConfigField represents an application-level configuration field for catalogers
|
// AppConfigField represents an application-level configuration field for catalogers
|
||||||
type AppConfigField struct {
|
type AppConfigField struct {
|
||||||
Key string // e.g., "golang.search-local-mod-cache-licenses"
|
Key string // e.g., "golang.search-local-mod-cache-licenses"
|
||||||
Description string // extracted from DescribeFields() method
|
Description string // extracted from DescribeFields() method
|
||||||
DefaultValue interface{} // extracted from Default*() functions
|
DefaultValue any // extracted from Default*() functions
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractEcosystemConfigFieldsFromCatalog parses catalog.go and extracts the ecosystem-specific
|
// extractEcosystemConfigFieldsFromCatalog parses catalog.go and extracts the ecosystem-specific
|
||||||
@ -390,7 +390,7 @@ func extractDescriptionsFromDescribeFields(f *ast.File) map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extractNestedAppConfigs handles nested config structs like golang.MainModuleVersion
|
// extractNestedAppConfigs handles nested config structs like golang.MainModuleVersion
|
||||||
func extractNestedAppConfigs(f *ast.File, parentKey, parentFieldName string, fieldType ast.Expr, descriptions map[string]string, defaults map[string]interface{}) []AppConfigField {
|
func extractNestedAppConfigs(f *ast.File, parentKey, parentFieldName string, fieldType ast.Expr, descriptions map[string]string, defaults map[string]any) []AppConfigField {
|
||||||
var configs []AppConfigField
|
var configs []AppConfigField
|
||||||
|
|
||||||
// find the nested struct type
|
// find the nested struct type
|
||||||
@ -449,8 +449,8 @@ func extractNestedAppConfigs(f *ast.File, parentKey, parentFieldName string, fie
|
|||||||
description := descriptions[nestedPath]
|
description := descriptions[nestedPath]
|
||||||
|
|
||||||
// try to get default value from nested defaults
|
// try to get default value from nested defaults
|
||||||
var defaultValue interface{}
|
var defaultValue any
|
||||||
if nestedDefaults, ok := defaults[parentFieldName].(map[string]interface{}); ok {
|
if nestedDefaults, ok := defaults[parentFieldName].(map[string]any); ok {
|
||||||
defaultValue = nestedDefaults[fieldName]
|
defaultValue = nestedDefaults[fieldName]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,8 +465,8 @@ func extractNestedAppConfigs(f *ast.File, parentKey, parentFieldName string, fie
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extractAppDefaultValues extracts default values from the default*Config function
|
// extractAppDefaultValues extracts default values from the default*Config function
|
||||||
func extractAppDefaultValues(f *ast.File) map[string]interface{} {
|
func extractAppDefaultValues(f *ast.File) map[string]any {
|
||||||
defaults := make(map[string]interface{})
|
defaults := make(map[string]any)
|
||||||
|
|
||||||
for _, decl := range f.Decls {
|
for _, decl := range f.Decls {
|
||||||
funcDecl, ok := decl.(*ast.FuncDecl)
|
funcDecl, ok := decl.(*ast.FuncDecl)
|
||||||
@ -518,7 +518,7 @@ func extractAppDefaultValues(f *ast.File) map[string]interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extractAppValue extracts a Go value from an AST expression
|
// extractAppValue extracts a Go value from an AST expression
|
||||||
func extractAppValue(expr ast.Expr) interface{} {
|
func extractAppValue(expr ast.Expr) any {
|
||||||
switch v := expr.(type) {
|
switch v := expr.(type) {
|
||||||
case *ast.BasicLit:
|
case *ast.BasicLit:
|
||||||
// string, int, bool literals
|
// string, int, bool literals
|
||||||
@ -543,7 +543,7 @@ func extractAppValue(expr ast.Expr) interface{} {
|
|||||||
}
|
}
|
||||||
case *ast.CompositeLit:
|
case *ast.CompositeLit:
|
||||||
// nested struct literal
|
// nested struct literal
|
||||||
nested := make(map[string]interface{})
|
nested := make(map[string]any)
|
||||||
for _, elt := range v.Elts {
|
for _, elt := range v.Elts {
|
||||||
kvExpr, ok := elt.(*ast.KeyValueExpr)
|
kvExpr, ok := elt.(*ast.KeyValueExpr)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@ -340,7 +340,7 @@ func TestExtractAppValue(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
src string
|
src string
|
||||||
want interface{}
|
want any
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "string literal",
|
name: "string literal",
|
||||||
@ -406,7 +406,7 @@ func TestExtractAppValue_NestedStruct(t *testing.T) {
|
|||||||
got := extractAppValue(compositeLit)
|
got := extractAppValue(compositeLit)
|
||||||
|
|
||||||
// verify it's a map with the expected values
|
// verify it's a map with the expected values
|
||||||
gotMap, ok := got.(map[string]interface{})
|
gotMap, ok := got.(map[string]any)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.Equal(t, "value", gotMap["Field1"])
|
require.Equal(t, "value", gotMap["Field1"])
|
||||||
require.Equal(t, true, gotMap["Field2"])
|
require.Equal(t, true, gotMap["Field2"])
|
||||||
|
|||||||
@ -567,8 +567,8 @@ func resolveImportedConstant(pkgName, constName string, ctx *parseContext) strin
|
|||||||
// resolveImportPath converts an import path to a file system path
|
// resolveImportPath converts an import path to a file system path
|
||||||
func resolveImportPath(importPath, repoRoot string) string {
|
func resolveImportPath(importPath, repoRoot string) string {
|
||||||
// for github.com/anchore/syft/... imports, convert to repo-relative path
|
// for github.com/anchore/syft/... imports, convert to repo-relative path
|
||||||
if strings.HasPrefix(importPath, "github.com/anchore/syft/") {
|
if after, ok := strings.CutPrefix(importPath, "github.com/anchore/syft/"); ok {
|
||||||
relPath := strings.TrimPrefix(importPath, "github.com/anchore/syft/")
|
relPath := after
|
||||||
return filepath.Join(repoRoot, relPath)
|
return filepath.Join(repoRoot, relPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -214,7 +214,7 @@ func mapCatalogerToEcosystem(cat capabilities.CatalogerEntry) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// updateNodeTreeEcosystem updates an existing ecosystem YAML node tree
|
// updateNodeTreeEcosystem updates an existing ecosystem YAML node tree
|
||||||
func updateNodeTreeEcosystem(rootNode *yaml.Node, doc interface{}) error {
|
func updateNodeTreeEcosystem(rootNode *yaml.Node, doc any) error {
|
||||||
var newNode yaml.Node
|
var newNode yaml.Node
|
||||||
if err := newNode.Encode(doc); err != nil {
|
if err := newNode.Encode(doc); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -242,7 +242,7 @@ func updateNodeTreeEcosystem(rootNode *yaml.Node, doc interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// updateNodeTreeAppConfig updates appconfig YAML node tree
|
// updateNodeTreeAppConfig updates appconfig YAML node tree
|
||||||
func updateNodeTreeAppConfig(rootNode *yaml.Node, doc interface{}) error {
|
func updateNodeTreeAppConfig(rootNode *yaml.Node, doc any) error {
|
||||||
return updateNodeTreeEcosystem(rootNode, doc)
|
return updateNodeTreeEcosystem(rootNode, doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ const requireParserObservations = false
|
|||||||
|
|
||||||
// metadataTypeCoverageExceptions lists metadata types that are allowed to not be represented in any cataloger
|
// metadataTypeCoverageExceptions lists metadata types that are allowed to not be represented in any cataloger
|
||||||
var metadataTypeCoverageExceptions = strset.New(
|
var metadataTypeCoverageExceptions = strset.New(
|
||||||
reflect.TypeOf(pkg.MicrosoftKbPatch{}).Name(),
|
reflect.TypeFor[pkg.MicrosoftKbPatch]().Name(),
|
||||||
)
|
)
|
||||||
|
|
||||||
// packageTypeCoverageExceptions lists package types that are allowed to not be represented in any cataloger
|
// packageTypeCoverageExceptions lists package types that are allowed to not be represented in any cataloger
|
||||||
@ -408,7 +408,7 @@ func TestCapabilityValueTypes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validateCapabilityValueType checks if a value matches the expected type for a capability field
|
// validateCapabilityValueType checks if a value matches the expected type for a capability field
|
||||||
func validateCapabilityValueType(fieldPath string, value interface{}) error {
|
func validateCapabilityValueType(fieldPath string, value any) error {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return nil // nil is acceptable
|
return nil // nil is acceptable
|
||||||
}
|
}
|
||||||
@ -428,7 +428,7 @@ func validateCapabilityValueType(fieldPath string, value interface{}) error {
|
|||||||
switch v := value.(type) {
|
switch v := value.(type) {
|
||||||
case []string:
|
case []string:
|
||||||
// ok
|
// ok
|
||||||
case []interface{}:
|
case []any:
|
||||||
// check each element is a string
|
// check each element is a string
|
||||||
for i, elem := range v {
|
for i, elem := range v {
|
||||||
if _, ok := elem.(string); !ok {
|
if _, ok := elem.(string); !ok {
|
||||||
@ -829,7 +829,6 @@ func TestCapabilityEvidenceFieldReferences(t *testing.T) {
|
|||||||
|
|
||||||
// validate each evidence reference
|
// validate each evidence reference
|
||||||
for _, ref := range allReferences {
|
for _, ref := range allReferences {
|
||||||
ref := ref // capture for subtest
|
|
||||||
|
|
||||||
// create test name
|
// create test name
|
||||||
testName := ref.catalogerName
|
testName := ref.catalogerName
|
||||||
@ -989,7 +988,6 @@ func validateCapabilitiesFilled(t *testing.T, catalogers []capabilities.Cataloge
|
|||||||
checkCompletenessTestsEnabled(t)
|
checkCompletenessTestsEnabled(t)
|
||||||
|
|
||||||
for _, c := range catalogers {
|
for _, c := range catalogers {
|
||||||
c := c // capture loop variable for subtest
|
|
||||||
|
|
||||||
t.Run(c.Name, func(t *testing.T) {
|
t.Run(c.Name, func(t *testing.T) {
|
||||||
if c.Type == "generic" {
|
if c.Type == "generic" {
|
||||||
@ -997,7 +995,6 @@ func validateCapabilitiesFilled(t *testing.T, catalogers []capabilities.Cataloge
|
|||||||
require.NotEmpty(t, c.Parsers, "generic cataloger must have at least one parser")
|
require.NotEmpty(t, c.Parsers, "generic cataloger must have at least one parser")
|
||||||
|
|
||||||
for _, p := range c.Parsers {
|
for _, p := range c.Parsers {
|
||||||
p := p // capture loop variable for subtest
|
|
||||||
|
|
||||||
t.Run(p.ParserFunction, func(t *testing.T) {
|
t.Run(p.ParserFunction, func(t *testing.T) {
|
||||||
require.NotEmpty(t, p.Capabilities, "parser must have at least one capability field defined")
|
require.NotEmpty(t, p.Capabilities, "parser must have at least one capability field defined")
|
||||||
@ -1120,7 +1117,6 @@ func TestCatalogerStructure(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for _, c := range catalogerEntries {
|
for _, c := range catalogerEntries {
|
||||||
c := c // capture loop variable for subtest
|
|
||||||
|
|
||||||
t.Run(c.Name, func(t *testing.T) {
|
t.Run(c.Name, func(t *testing.T) {
|
||||||
// ecosystem must always be set (it's MANUAL)
|
// ecosystem must always be set (it's MANUAL)
|
||||||
|
|||||||
@ -151,11 +151,11 @@ func TestGetter_GetToDir_CertConcerns(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertUnknownAuthorityError(t assert.TestingT, err error, _ ...interface{}) bool {
|
func assertUnknownAuthorityError(t assert.TestingT, err error, _ ...any) bool {
|
||||||
return assert.ErrorAs(t, err, &x509.UnknownAuthorityError{})
|
return assert.ErrorAs(t, err, &x509.UnknownAuthorityError{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertErrNonArchiveSource(t assert.TestingT, err error, _ ...interface{}) bool {
|
func assertErrNonArchiveSource(t assert.TestingT, err error, _ ...any) bool {
|
||||||
return assert.ErrorIs(t, err, ErrNonArchiveSource)
|
return assert.ErrorIs(t, err, ErrNonArchiveSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
//go:build !windows
|
//go:build !windows
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package file
|
package file
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
//go:build !windows
|
//go:build !windows
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package file
|
package file
|
||||||
|
|
||||||
@ -242,8 +241,8 @@ func assertZipSourceFixtureContents(t testing.TB, actual map[string]string, expe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// looks like there isn't a helper for this yet? https://github.com/stretchr/testify/issues/497
|
// looks like there isn't a helper for this yet? https://github.com/stretchr/testify/issues/497
|
||||||
func assertErrorAs(expectedErr interface{}) assert.ErrorAssertionFunc {
|
func assertErrorAs(expectedErr any) assert.ErrorAssertionFunc {
|
||||||
return func(t assert.TestingT, actualErr error, i ...interface{}) bool {
|
return func(t assert.TestingT, actualErr error, i ...any) bool {
|
||||||
return errors.As(actualErr, &expectedErr)
|
return errors.As(actualErr, &expectedErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -143,7 +143,7 @@ func build() *jsonschema.Schema {
|
|||||||
// srcMetadataContainer := assembleTypeContainer(sourcemetadata.AllTypes())
|
// srcMetadataContainer := assembleTypeContainer(sourcemetadata.AllTypes())
|
||||||
// srcMetadataContainerType := reflect.TypeOf(srcMetadataContainer)
|
// srcMetadataContainerType := reflect.TypeOf(srcMetadataContainer)
|
||||||
|
|
||||||
documentSchema := reflector.ReflectFromType(reflect.TypeOf(&syftJsonModel.Document{}))
|
documentSchema := reflector.ReflectFromType(reflect.TypeFor[*syftJsonModel.Document]())
|
||||||
pkgMetadataSchema := reflector.ReflectFromType(reflect.TypeOf(pkgMetadataContainer))
|
pkgMetadataSchema := reflector.ReflectFromType(reflect.TypeOf(pkgMetadataContainer))
|
||||||
// srcMetadataSchema := reflector.ReflectFromType(reflect.TypeOf(srcMetadataContainer))
|
// srcMetadataSchema := reflector.ReflectFromType(reflect.TypeOf(srcMetadataContainer))
|
||||||
|
|
||||||
|
|||||||
@ -30,61 +30,61 @@ func Get() logger.Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Errorf takes a formatted template string and template arguments for the error logging level.
|
// Errorf takes a formatted template string and template arguments for the error logging level.
|
||||||
func Errorf(format string, args ...interface{}) {
|
func Errorf(format string, args ...any) {
|
||||||
log.Errorf(format, args...)
|
log.Errorf(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error logs the given arguments at the error logging level.
|
// Error logs the given arguments at the error logging level.
|
||||||
func Error(args ...interface{}) {
|
func Error(args ...any) {
|
||||||
log.Error(args...)
|
log.Error(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warnf takes a formatted template string and template arguments for the warning logging level.
|
// Warnf takes a formatted template string and template arguments for the warning logging level.
|
||||||
func Warnf(format string, args ...interface{}) {
|
func Warnf(format string, args ...any) {
|
||||||
log.Warnf(format, args...)
|
log.Warnf(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn logs the given arguments at the warning logging level.
|
// Warn logs the given arguments at the warning logging level.
|
||||||
func Warn(args ...interface{}) {
|
func Warn(args ...any) {
|
||||||
log.Warn(args...)
|
log.Warn(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Infof takes a formatted template string and template arguments for the info logging level.
|
// Infof takes a formatted template string and template arguments for the info logging level.
|
||||||
func Infof(format string, args ...interface{}) {
|
func Infof(format string, args ...any) {
|
||||||
log.Infof(format, args...)
|
log.Infof(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info logs the given arguments at the info logging level.
|
// Info logs the given arguments at the info logging level.
|
||||||
func Info(args ...interface{}) {
|
func Info(args ...any) {
|
||||||
log.Info(args...)
|
log.Info(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugf takes a formatted template string and template arguments for the debug logging level.
|
// Debugf takes a formatted template string and template arguments for the debug logging level.
|
||||||
func Debugf(format string, args ...interface{}) {
|
func Debugf(format string, args ...any) {
|
||||||
log.Debugf(format, args...)
|
log.Debugf(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug logs the given arguments at the debug logging level.
|
// Debug logs the given arguments at the debug logging level.
|
||||||
func Debug(args ...interface{}) {
|
func Debug(args ...any) {
|
||||||
log.Debug(args...)
|
log.Debug(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tracef takes a formatted template string and template arguments for the trace logging level.
|
// Tracef takes a formatted template string and template arguments for the trace logging level.
|
||||||
func Tracef(format string, args ...interface{}) {
|
func Tracef(format string, args ...any) {
|
||||||
log.Tracef(format, args...)
|
log.Tracef(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trace logs the given arguments at the trace logging level.
|
// Trace logs the given arguments at the trace logging level.
|
||||||
func Trace(args ...interface{}) {
|
func Trace(args ...any) {
|
||||||
log.Trace(args...)
|
log.Trace(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithFields returns a message logger with multiple key-value fields.
|
// WithFields returns a message logger with multiple key-value fields.
|
||||||
func WithFields(fields ...interface{}) logger.MessageLogger {
|
func WithFields(fields ...any) logger.MessageLogger {
|
||||||
return log.WithFields(fields...)
|
return log.WithFields(fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nested returns a new logger with hard coded key-value pairs
|
// Nested returns a new logger with hard coded key-value pairs
|
||||||
func Nested(fields ...interface{}) logger.Logger {
|
func Nested(fields ...any) logger.Logger {
|
||||||
return log.Nested(fields...)
|
return log.Nested(fields...)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,28 +40,28 @@ func TestReflectTypeFromJSONName(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "exact match on ID",
|
name: "exact match on ID",
|
||||||
lookup: "rust-cargo-lock-entry",
|
lookup: "rust-cargo-lock-entry",
|
||||||
wantRecord: reflect.TypeOf(pkg.RustCargoLockEntry{}),
|
wantRecord: reflect.TypeFor[pkg.RustCargoLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "exact match on former name",
|
name: "exact match on former name",
|
||||||
lookup: "RustCargoPackageMetadata",
|
lookup: "RustCargoPackageMetadata",
|
||||||
wantRecord: reflect.TypeOf(pkg.RustCargoLockEntry{}),
|
wantRecord: reflect.TypeFor[pkg.RustCargoLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "case insensitive on ID",
|
name: "case insensitive on ID",
|
||||||
lookup: "RUST-CARGO-lock-entrY",
|
lookup: "RUST-CARGO-lock-entrY",
|
||||||
wantRecord: reflect.TypeOf(pkg.RustCargoLockEntry{}),
|
wantRecord: reflect.TypeFor[pkg.RustCargoLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "case insensitive on alias",
|
name: "case insensitive on alias",
|
||||||
lookup: "rusTcArgopacKagEmEtadATa",
|
lookup: "rusTcArgopacKagEmEtadATa",
|
||||||
wantRecord: reflect.TypeOf(pkg.RustCargoLockEntry{}),
|
wantRecord: reflect.TypeFor[pkg.RustCargoLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "consistent override",
|
name: "consistent override",
|
||||||
// there are two correct answers for this -- we should always get the same answer.
|
// there are two correct answers for this -- we should always get the same answer.
|
||||||
lookup: "HackageMetadataType",
|
lookup: "HackageMetadataType",
|
||||||
wantRecord: reflect.TypeOf(pkg.HackageStackYamlLockEntry{}),
|
wantRecord: reflect.TypeFor[pkg.HackageStackYamlLockEntry](),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -83,142 +83,142 @@ func TestReflectTypeFromJSONName_LegacyValues(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "map pkg.AlpmDBEntry struct type",
|
name: "map pkg.AlpmDBEntry struct type",
|
||||||
input: "AlpmMetadata",
|
input: "AlpmMetadata",
|
||||||
expected: reflect.TypeOf(pkg.AlpmDBEntry{}),
|
expected: reflect.TypeFor[pkg.AlpmDBEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.ApkDBEntry struct type",
|
name: "map pkg.ApkDBEntry struct type",
|
||||||
input: "ApkMetadata",
|
input: "ApkMetadata",
|
||||||
expected: reflect.TypeOf(pkg.ApkDBEntry{}),
|
expected: reflect.TypeFor[pkg.ApkDBEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.BinarySignature struct type",
|
name: "map pkg.BinarySignature struct type",
|
||||||
input: "BinaryMetadata",
|
input: "BinaryMetadata",
|
||||||
expected: reflect.TypeOf(pkg.BinarySignature{}),
|
expected: reflect.TypeFor[pkg.BinarySignature](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.CocoaPodfileLockEntry struct type",
|
name: "map pkg.CocoaPodfileLockEntry struct type",
|
||||||
input: "CocoapodsMetadataType",
|
input: "CocoapodsMetadataType",
|
||||||
expected: reflect.TypeOf(pkg.CocoaPodfileLockEntry{}),
|
expected: reflect.TypeFor[pkg.CocoaPodfileLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.ConanLockEntry struct type",
|
name: "map pkg.ConanLockEntry struct type",
|
||||||
input: "ConanLockMetadataType",
|
input: "ConanLockMetadataType",
|
||||||
expected: reflect.TypeOf(pkg.ConanV1LockEntry{}),
|
expected: reflect.TypeFor[pkg.ConanV1LockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.ConanfileEntry struct type",
|
name: "map pkg.ConanfileEntry struct type",
|
||||||
input: "ConanMetadataType",
|
input: "ConanMetadataType",
|
||||||
expected: reflect.TypeOf(pkg.ConanfileEntry{}),
|
expected: reflect.TypeFor[pkg.ConanfileEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.DartPubspecLockEntry struct type",
|
name: "map pkg.DartPubspecLockEntry struct type",
|
||||||
input: "DartPubMetadata",
|
input: "DartPubMetadata",
|
||||||
expected: reflect.TypeOf(pkg.DartPubspecLockEntry{}),
|
expected: reflect.TypeFor[pkg.DartPubspecLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.DotnetDepsEntry struct type",
|
name: "map pkg.DotnetDepsEntry struct type",
|
||||||
input: "DotnetDepsMetadata",
|
input: "DotnetDepsMetadata",
|
||||||
expected: reflect.TypeOf(pkg.DotnetDepsEntry{}),
|
expected: reflect.TypeFor[pkg.DotnetDepsEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.DpkgDBEntry struct type",
|
name: "map pkg.DpkgDBEntry struct type",
|
||||||
input: "DpkgMetadata",
|
input: "DpkgMetadata",
|
||||||
expected: reflect.TypeOf(pkg.DpkgDBEntry{}),
|
expected: reflect.TypeFor[pkg.DpkgDBEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.RubyGemspec struct type",
|
name: "map pkg.RubyGemspec struct type",
|
||||||
input: "GemMetadata",
|
input: "GemMetadata",
|
||||||
expected: reflect.TypeOf(pkg.RubyGemspec{}),
|
expected: reflect.TypeFor[pkg.RubyGemspec](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.GolangBinaryBuildinfoEntry struct type",
|
name: "map pkg.GolangBinaryBuildinfoEntry struct type",
|
||||||
input: "GolangBinMetadata",
|
input: "GolangBinMetadata",
|
||||||
expected: reflect.TypeOf(pkg.GolangBinaryBuildinfoEntry{}),
|
expected: reflect.TypeFor[pkg.GolangBinaryBuildinfoEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.GolangModuleEntry struct type",
|
name: "map pkg.GolangModuleEntry struct type",
|
||||||
input: "GolangModMetadata",
|
input: "GolangModMetadata",
|
||||||
expected: reflect.TypeOf(pkg.GolangModuleEntry{}),
|
expected: reflect.TypeFor[pkg.GolangModuleEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.JavaArchive struct type",
|
name: "map pkg.JavaArchive struct type",
|
||||||
input: "JavaMetadata",
|
input: "JavaMetadata",
|
||||||
expected: reflect.TypeOf(pkg.JavaArchive{}),
|
expected: reflect.TypeFor[pkg.JavaArchive](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.MicrosoftKbPatch struct type",
|
name: "map pkg.MicrosoftKbPatch struct type",
|
||||||
input: "KbPatchMetadata",
|
input: "KbPatchMetadata",
|
||||||
expected: reflect.TypeOf(pkg.MicrosoftKbPatch{}),
|
expected: reflect.TypeFor[pkg.MicrosoftKbPatch](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.LinuxKernel struct type",
|
name: "map pkg.LinuxKernel struct type",
|
||||||
input: "LinuxKernel",
|
input: "LinuxKernel",
|
||||||
expected: reflect.TypeOf(pkg.LinuxKernel{}),
|
expected: reflect.TypeFor[pkg.LinuxKernel](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.LinuxKernelModule struct type",
|
name: "map pkg.LinuxKernelModule struct type",
|
||||||
input: "LinuxKernelModule",
|
input: "LinuxKernelModule",
|
||||||
expected: reflect.TypeOf(pkg.LinuxKernelModule{}),
|
expected: reflect.TypeFor[pkg.LinuxKernelModule](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.ElixirMixLockEntry struct type",
|
name: "map pkg.ElixirMixLockEntry struct type",
|
||||||
input: "MixLockMetadataType",
|
input: "MixLockMetadataType",
|
||||||
expected: reflect.TypeOf(pkg.ElixirMixLockEntry{}),
|
expected: reflect.TypeFor[pkg.ElixirMixLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.NixStoreEntry struct type",
|
name: "map pkg.NixStoreEntry struct type",
|
||||||
input: "NixStoreMetadata",
|
input: "NixStoreMetadata",
|
||||||
expected: reflect.TypeOf(pkg.NixStoreEntry{}),
|
expected: reflect.TypeFor[pkg.NixStoreEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.NpmPackage struct type",
|
name: "map pkg.NpmPackage struct type",
|
||||||
input: "NpmPackageJsonMetadata",
|
input: "NpmPackageJsonMetadata",
|
||||||
expected: reflect.TypeOf(pkg.NpmPackage{}),
|
expected: reflect.TypeFor[pkg.NpmPackage](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.NpmPackageLockEntry struct type",
|
name: "map pkg.NpmPackageLockEntry struct type",
|
||||||
input: "NpmPackageLockJsonMetadata",
|
input: "NpmPackageLockJsonMetadata",
|
||||||
expected: reflect.TypeOf(pkg.NpmPackageLockEntry{}),
|
expected: reflect.TypeFor[pkg.NpmPackageLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.PortageEntry struct type",
|
name: "map pkg.PortageEntry struct type",
|
||||||
input: "PortageMetadata",
|
input: "PortageMetadata",
|
||||||
expected: reflect.TypeOf(pkg.PortageEntry{}),
|
expected: reflect.TypeFor[pkg.PortageEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.PythonPackage struct type",
|
name: "map pkg.PythonPackage struct type",
|
||||||
input: "PythonPackageMetadata",
|
input: "PythonPackageMetadata",
|
||||||
expected: reflect.TypeOf(pkg.PythonPackage{}),
|
expected: reflect.TypeFor[pkg.PythonPackage](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.PythonPipfileLockEntry struct type",
|
name: "map pkg.PythonPipfileLockEntry struct type",
|
||||||
input: "PythonPipfileLockMetadata",
|
input: "PythonPipfileLockMetadata",
|
||||||
expected: reflect.TypeOf(pkg.PythonPipfileLockEntry{}),
|
expected: reflect.TypeFor[pkg.PythonPipfileLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.PythonRequirementsEntry struct type",
|
name: "map pkg.PythonRequirementsEntry struct type",
|
||||||
input: "PythonRequirementsMetadata",
|
input: "PythonRequirementsMetadata",
|
||||||
expected: reflect.TypeOf(pkg.PythonRequirementsEntry{}),
|
expected: reflect.TypeFor[pkg.PythonRequirementsEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.PhpPeclEntry struct type",
|
name: "map pkg.PhpPeclEntry struct type",
|
||||||
input: "PhpPeclMetadata",
|
input: "PhpPeclMetadata",
|
||||||
expected: reflect.TypeOf(pkg.PhpPeclEntry{}),
|
expected: reflect.TypeFor[pkg.PhpPeclEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.ErlangRebarLockEntry struct type",
|
name: "map pkg.ErlangRebarLockEntry struct type",
|
||||||
input: "RebarLockMetadataType",
|
input: "RebarLockMetadataType",
|
||||||
expected: reflect.TypeOf(pkg.ErlangRebarLockEntry{}),
|
expected: reflect.TypeFor[pkg.ErlangRebarLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.RDescription struct type",
|
name: "map pkg.RDescription struct type",
|
||||||
input: "RDescriptionFileMetadataType",
|
input: "RDescriptionFileMetadataType",
|
||||||
expected: reflect.TypeOf(pkg.RDescription{}),
|
expected: reflect.TypeFor[pkg.RDescription](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.RpmDBEntry struct type",
|
name: "map pkg.RpmDBEntry struct type",
|
||||||
input: "RpmdbMetadata",
|
input: "RpmdbMetadata",
|
||||||
expected: reflect.TypeOf(pkg.RpmDBEntry{}),
|
expected: reflect.TypeFor[pkg.RpmDBEntry](),
|
||||||
},
|
},
|
||||||
// these cases are 1:many
|
// these cases are 1:many
|
||||||
{
|
{
|
||||||
@ -228,28 +228,28 @@ func TestReflectTypeFromJSONName_LegacyValues(t *testing.T) {
|
|||||||
// from a data-shape perspective either would be equally correct
|
// from a data-shape perspective either would be equally correct
|
||||||
// however, the RPMDBMetadata has been around longer and may have been more widely used
|
// however, the RPMDBMetadata has been around longer and may have been more widely used
|
||||||
// so we'll map to that type for backwards compatibility.
|
// so we'll map to that type for backwards compatibility.
|
||||||
expected: reflect.TypeOf(pkg.RpmDBEntry{}),
|
expected: reflect.TypeFor[pkg.RpmDBEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.HackageStackYamlLockEntry struct type - overlap with HackageStack*Metadata",
|
name: "map pkg.HackageStackYamlLockEntry struct type - overlap with HackageStack*Metadata",
|
||||||
input: "HackageMetadataType",
|
input: "HackageMetadataType",
|
||||||
// this used to be shared as a use case for both HackageStackYamlLockEntry and HackageStackYamlEntry
|
// this used to be shared as a use case for both HackageStackYamlLockEntry and HackageStackYamlEntry
|
||||||
// but the HackageStackYamlLockEntry maps most closely to the original data shape.
|
// but the HackageStackYamlLockEntry maps most closely to the original data shape.
|
||||||
expected: reflect.TypeOf(pkg.HackageStackYamlLockEntry{}),
|
expected: reflect.TypeFor[pkg.HackageStackYamlLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.PhpComposerLockEntry struct type",
|
name: "map pkg.PhpComposerLockEntry struct type",
|
||||||
input: "PhpComposerJsonMetadata",
|
input: "PhpComposerJsonMetadata",
|
||||||
// this used to be shared as a use case for both PhpComposerLockEntry and PhpComposerInstalledEntry
|
// this used to be shared as a use case for both PhpComposerLockEntry and PhpComposerInstalledEntry
|
||||||
// neither of these is more correct over the other. These parsers were also introduced at the same time.
|
// neither of these is more correct over the other. These parsers were also introduced at the same time.
|
||||||
expected: reflect.TypeOf(pkg.PhpComposerLockEntry{}),
|
expected: reflect.TypeFor[pkg.PhpComposerLockEntry](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "map pkg.RustCargoLockEntry struct type",
|
name: "map pkg.RustCargoLockEntry struct type",
|
||||||
input: "RustCargoPackageMetadata",
|
input: "RustCargoPackageMetadata",
|
||||||
// this used to be shared as a use case for both RustCargoLockEntry and RustBinaryAuditEntry
|
// this used to be shared as a use case for both RustCargoLockEntry and RustBinaryAuditEntry
|
||||||
// neither of these is more correct over the other.
|
// neither of these is more correct over the other.
|
||||||
expected: reflect.TypeOf(pkg.RustCargoLockEntry{}),
|
expected: reflect.TypeFor[pkg.RustCargoLockEntry](),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -92,10 +92,7 @@ func processReaderInChunks(rdr io.Reader, chunkSize int, handler func(data []byt
|
|||||||
lastRead := 0
|
lastRead := 0
|
||||||
|
|
||||||
for {
|
for {
|
||||||
offset := half
|
offset := min(lastRead, half)
|
||||||
if lastRead < half {
|
|
||||||
offset = lastRead
|
|
||||||
}
|
|
||||||
start := half - offset
|
start := half - offset
|
||||||
if lastRead > 0 {
|
if lastRead > 0 {
|
||||||
copy(buf[start:], buf[half+offset:half+lastRead])
|
copy(buf[start:], buf[half+offset:half+lastRead])
|
||||||
|
|||||||
@ -26,9 +26,9 @@ var (
|
|||||||
pkg.BitnamiPkg,
|
pkg.BitnamiPkg,
|
||||||
}
|
}
|
||||||
binaryMetadataTypes = []string{
|
binaryMetadataTypes = []string{
|
||||||
reflect.TypeOf(pkg.ELFBinaryPackageNoteJSONPayload{}).Name(),
|
reflect.TypeFor[pkg.ELFBinaryPackageNoteJSONPayload]().Name(),
|
||||||
reflect.TypeOf(pkg.BinarySignature{}).Name(),
|
reflect.TypeFor[pkg.BinarySignature]().Name(),
|
||||||
reflect.TypeOf(pkg.JavaVMInstallation{}).Name(),
|
reflect.TypeFor[pkg.JavaVMInstallation]().Name(),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,6 @@ func TestExcludeByFileOwnershipOverlap(t *testing.T) {
|
|||||||
packageC := pkg.Package{Name: "package-c", Type: pkg.BinaryPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{Type: "rpm"}}
|
packageC := pkg.Package{Name: "package-c", Type: pkg.BinaryPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{Type: "rpm"}}
|
||||||
packageD := pkg.Package{Name: "package-d", Type: pkg.BitnamiPkg}
|
packageD := pkg.Package{Name: "package-d", Type: pkg.BitnamiPkg}
|
||||||
for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD} {
|
for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD} {
|
||||||
p := p
|
|
||||||
p.SetID()
|
p.SetID()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,11 +8,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var jsonNameFromType = map[reflect.Type][]string{
|
var jsonNameFromType = map[reflect.Type][]string{
|
||||||
reflect.TypeOf(source.DirectoryMetadata{}): {"directory", "dir"},
|
reflect.TypeFor[source.DirectoryMetadata](): {"directory", "dir"},
|
||||||
reflect.TypeOf(source.FileMetadata{}): {"file"},
|
reflect.TypeFor[source.FileMetadata](): {"file"},
|
||||||
reflect.TypeOf(source.ImageMetadata{}): {"image"},
|
reflect.TypeFor[source.ImageMetadata](): {"image"},
|
||||||
reflect.TypeOf(source.SnapMetadata{}): {"snap"},
|
reflect.TypeFor[source.SnapMetadata](): {"snap"},
|
||||||
reflect.TypeOf(source.OCIModelMetadata{}): {"oci-model"},
|
reflect.TypeFor[source.OCIModelMetadata](): {"oci-model"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func AllTypeNames() []string {
|
func AllTypeNames() []string {
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// HasAnyOfPrefixes returns an indication if the given string has any of the given prefixes.
|
// HasAnyOfPrefixes returns an indication if the given string has any of the given prefixes.
|
||||||
func HasAnyOfPrefixes(input string, prefixes ...string) bool {
|
func HasAnyOfPrefixes(input string, prefixes ...string) bool {
|
||||||
@ -32,12 +35,7 @@ func TruncateMiddleEllipsis(input string, maxLen int) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func StringInSlice(a string, list []string) bool {
|
func StringInSlice(a string, list []string) bool {
|
||||||
for _, b := range list {
|
return slices.Contains(list, a)
|
||||||
if b == a {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SplitAny(s string, seps string) []string {
|
func SplitAny(s string, seps string) []string {
|
||||||
|
|||||||
@ -198,7 +198,7 @@ func TestConcurrentNewChildAndNewFile(t *testing.T) {
|
|||||||
errs := make(chan error, goroutines)
|
errs := make(chan error, goroutines)
|
||||||
paths := make(chan string, goroutines)
|
paths := make(chan string, goroutines)
|
||||||
|
|
||||||
for i := 0; i < goroutines; i++ {
|
for i := range goroutines {
|
||||||
go func(i int) {
|
go func(i int) {
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
child, cleanup, err := td.NewChild("concurrent")
|
child, cleanup, err := td.NewChild("concurrent")
|
||||||
@ -223,7 +223,7 @@ func TestConcurrentNewChildAndNewFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
seen := make(map[string]bool)
|
seen := make(map[string]bool)
|
||||||
for i := 0; i < goroutines; i++ {
|
for range goroutines {
|
||||||
err := <-errs
|
err := <-errs
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ func TestConcurrentNewChildDuringCleanup(t *testing.T) {
|
|||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
// try creating children concurrently with cleanup — should get errors, not panics
|
// try creating children concurrently with cleanup — should get errors, not panics
|
||||||
for i := 0; i < 10; i++ {
|
for range 10 {
|
||||||
_, c, _ := td.NewChild("race")
|
_, c, _ := td.NewChild("race")
|
||||||
if c != nil {
|
if c != nil {
|
||||||
c()
|
c()
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Tprintf renders a string from a given template string and field values
|
// Tprintf renders a string from a given template string and field values
|
||||||
func Tprintf(tmpl string, data map[string]interface{}) string {
|
func Tprintf(tmpl string, data map[string]any) string {
|
||||||
t := template.Must(template.New("").Parse(tmpl))
|
t := template.Must(template.New("").Parse(tmpl))
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
if err := t.Execute(buf, data); err != nil {
|
if err := t.Execute(buf, data); err != nil {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package unknown
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
@ -155,12 +156,7 @@ func containsErr(out []error, err error) bool {
|
|||||||
log.Tracef("error comparing errors: %v", err)
|
log.Tracef("error comparing errors: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
for _, e := range out {
|
return slices.Contains(out, err)
|
||||||
if e == err {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// visitErrors visits every wrapped error. the returned error replaces the provided error, null errors are omitted from
|
// visitErrors visits every wrapped error. the returned error replaces the provided error, null errors are omitted from
|
||||||
|
|||||||
@ -13,7 +13,7 @@ type Identifiable interface {
|
|||||||
ID() ID
|
ID() ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func IDByHash(obj interface{}) (ID, error) {
|
func IDByHash(obj any) (ID, error) {
|
||||||
f, err := hashstructure.Hash(obj, &hashstructure.HashOptions{
|
f, err := hashstructure.Hash(obj, &hashstructure.HashOptions{
|
||||||
ZeroNil: true,
|
ZeroNil: true,
|
||||||
SlicesAsSets: true,
|
SlicesAsSets: true,
|
||||||
|
|||||||
@ -38,5 +38,5 @@ type Relationship struct {
|
|||||||
From Identifiable
|
From Identifiable
|
||||||
To Identifiable
|
To Identifiable
|
||||||
Type RelationshipType
|
Type RelationshipType
|
||||||
Data interface{}
|
Data any
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@ func (cfg configurationAuditTrail) MarshalJSON() ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataMap map[string]interface{}
|
var dataMap map[string]any
|
||||||
if err := json.Unmarshal(initialJSON, &dataMap); err != nil {
|
if err := json.Unmarshal(initialJSON, &dataMap); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -55,13 +55,13 @@ func (cfg configurationAuditTrail) MarshalJSON() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// marshalSorted recursively marshals a map with sorted keys
|
// marshalSorted recursively marshals a map with sorted keys
|
||||||
func marshalSorted(m interface{}) ([]byte, error) {
|
func marshalSorted(m any) ([]byte, error) {
|
||||||
if reflect.TypeOf(m).Kind() != reflect.Map {
|
if reflect.TypeOf(m).Kind() != reflect.Map {
|
||||||
return json.Marshal(m)
|
return json.Marshal(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
val := reflect.ValueOf(m)
|
val := reflect.ValueOf(m)
|
||||||
sortedMap := make(map[string]interface{})
|
sortedMap := make(map[string]any)
|
||||||
|
|
||||||
for _, key := range val.MapKeys() {
|
for _, key := range val.MapKeys() {
|
||||||
value := val.MapIndex(key).Interface()
|
value := val.MapIndex(key).Interface()
|
||||||
|
|||||||
@ -33,7 +33,7 @@ func Test_configurationAuditTrail_StructTags(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getJSONTags(t *testing.T, v interface{}) []string {
|
func getJSONTags(t *testing.T, v any) []string {
|
||||||
var tags []string
|
var tags []string
|
||||||
err := collectJSONTags(t, reflect.ValueOf(v), &tags, "", "")
|
err := collectJSONTags(t, reflect.ValueOf(v), &tags, "", "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -142,7 +142,7 @@ func Test_collectJSONTags(t *testing.T) {
|
|||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
v interface{}
|
v any
|
||||||
want []string
|
want []string
|
||||||
wantErr require.ErrorAssertionFunc
|
wantErr require.ErrorAssertionFunc
|
||||||
}{
|
}{
|
||||||
|
|||||||
@ -34,7 +34,7 @@ type CreateSBOMConfig struct {
|
|||||||
// audit what tool is being used to generate the SBOM
|
// audit what tool is being used to generate the SBOM
|
||||||
ToolName string
|
ToolName string
|
||||||
ToolVersion string
|
ToolVersion string
|
||||||
ToolConfiguration interface{}
|
ToolConfiguration any
|
||||||
|
|
||||||
packageTaskFactories task.Factories
|
packageTaskFactories task.Factories
|
||||||
packageCatalogerReferences []pkgcataloging.CatalogerReference
|
packageCatalogerReferences []pkgcataloging.CatalogerReference
|
||||||
|
|||||||
@ -17,14 +17,14 @@ import (
|
|||||||
type ErrBadPayload struct {
|
type ErrBadPayload struct {
|
||||||
Type partybus.EventType
|
Type partybus.EventType
|
||||||
Field string
|
Field string
|
||||||
Value interface{}
|
Value any
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ErrBadPayload) Error() string {
|
func (e *ErrBadPayload) Error() string {
|
||||||
return fmt.Sprintf("event='%s' has bad event payload field=%q: %q", string(e.Type), e.Field, e.Value)
|
return fmt.Sprintf("event='%s' has bad event payload field=%q: %q", string(e.Type), e.Field, e.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPayloadErr(t partybus.EventType, field string, value interface{}) error {
|
func newPayloadErr(t partybus.EventType, field string, value any) error {
|
||||||
return &ErrBadPayload{
|
return &ErrBadPayload{
|
||||||
Type: t,
|
Type: t,
|
||||||
Field: field,
|
Field: field,
|
||||||
|
|||||||
@ -310,9 +310,9 @@ func toRootPackage(s source.Description) *spdx.Package {
|
|||||||
|
|
||||||
func toSPDXID(identifiable artifact.Identifiable) spdx.ElementID {
|
func toSPDXID(identifiable artifact.Identifiable) spdx.ElementID {
|
||||||
id := string(identifiable.ID())
|
id := string(identifiable.ID())
|
||||||
if strings.HasPrefix(id, "SPDXRef-") {
|
if after, ok := strings.CutPrefix(id, "SPDXRef-"); ok {
|
||||||
// this is already an SPDX ID, no need to change it (except for the prefix)
|
// this is already an SPDX ID, no need to change it (except for the prefix)
|
||||||
return spdx.ElementID(helpers.SanitizeElementID(strings.TrimPrefix(id, "SPDXRef-")))
|
return spdx.ElementID(helpers.SanitizeElementID(after))
|
||||||
}
|
}
|
||||||
maxLen := 40
|
maxLen := 40
|
||||||
switch it := identifiable.(type) {
|
switch it := identifiable.(type) {
|
||||||
|
|||||||
@ -479,7 +479,7 @@ func toSyftLocation(f *spdx.File) file.Location {
|
|||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func requireAndTrimPrefix(val interface{}, prefix string) string {
|
func requireAndTrimPrefix(val any, prefix string) string {
|
||||||
if v, ok := val.(string); ok {
|
if v, ok := val.(string); ok {
|
||||||
if i := strings.Index(v, prefix); i == 0 {
|
if i := strings.Index(v, prefix); i == 0 {
|
||||||
return strings.Replace(v, prefix, "", 1)
|
return strings.Replace(v, prefix, "", 1)
|
||||||
|
|||||||
@ -119,7 +119,7 @@ func Test_extractMetadata(t *testing.T) {
|
|||||||
oneTwoThreeFour := 1234
|
oneTwoThreeFour := 1234
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
pkg spdx.Package
|
pkg spdx.Package
|
||||||
meta interface{}
|
meta any
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
pkg: spdx.Package{
|
pkg: spdx.Package{
|
||||||
|
|||||||
@ -73,6 +73,6 @@ type DependencyGraph map[string]DependencyNode
|
|||||||
|
|
||||||
type ISO8601Date = string
|
type ISO8601Date = string
|
||||||
|
|
||||||
type Scalar interface{} // should be: null | boolean | string | number
|
type Scalar any // should be: null | boolean | string | number
|
||||||
|
|
||||||
type Metadata map[string]Scalar
|
type Metadata map[string]Scalar
|
||||||
|
|||||||
@ -31,7 +31,7 @@ func encodeAuthor(p pkg.Package) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeAuthor(author string, metadata interface{}) {
|
func decodeAuthor(author string, metadata any) {
|
||||||
switch meta := metadata.(type) {
|
switch meta := metadata.(type) {
|
||||||
case *pkg.NpmPackage:
|
case *pkg.NpmPackage:
|
||||||
meta.Author = author
|
meta.Author = author
|
||||||
|
|||||||
@ -202,7 +202,7 @@ func setPackageName(p *pkg.Package, c *cyclonedx.Component) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func decodeLocations(vals map[string]string) file.LocationSet {
|
func decodeLocations(vals map[string]string) file.LocationSet {
|
||||||
v := Decode(reflect.TypeOf([]file.Location{}), vals, "syft:location", CycloneDXFields)
|
v := Decode(reflect.TypeFor[[]file.Location](), vals, "syft:location", CycloneDXFields)
|
||||||
out, ok := v.([]file.Location)
|
out, ok := v.([]file.Location)
|
||||||
if !ok {
|
if !ok {
|
||||||
out = nil
|
out = nil
|
||||||
@ -210,7 +210,7 @@ func decodeLocations(vals map[string]string) file.LocationSet {
|
|||||||
return file.NewLocationSet(out...)
|
return file.NewLocationSet(out...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodePackageMetadata(vals map[string]string, c *cyclonedx.Component, typeName string) interface{} {
|
func decodePackageMetadata(vals map[string]string, c *cyclonedx.Component, typeName string) any {
|
||||||
if typeName != "" && c.Properties != nil {
|
if typeName != "" && c.Properties != nil {
|
||||||
metadataType := packagemetadata.ReflectTypeFromJSONName(typeName)
|
metadataType := packagemetadata.ReflectTypeFromJSONName(typeName)
|
||||||
if metadataType == nil {
|
if metadataType == nil {
|
||||||
|
|||||||
@ -26,7 +26,7 @@ func ToSyftModel(bom *cyclonedx.BOM) (*sbom.SBOM, error) {
|
|||||||
Descriptor: extractDescriptor(bom.Metadata),
|
Descriptor: extractDescriptor(bom.Metadata),
|
||||||
}
|
}
|
||||||
|
|
||||||
idMap := make(map[string]interface{})
|
idMap := make(map[string]any)
|
||||||
|
|
||||||
if err := collectBomPackages(bom, s, idMap); err != nil {
|
if err := collectBomPackages(bom, s, idMap); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -37,7 +37,7 @@ func ToSyftModel(bom *cyclonedx.BOM) (*sbom.SBOM, error) {
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectBomPackages(bom *cyclonedx.BOM, s *sbom.SBOM, idMap map[string]interface{}) error {
|
func collectBomPackages(bom *cyclonedx.BOM, s *sbom.SBOM, idMap map[string]any) error {
|
||||||
componentsPresent := false
|
componentsPresent := false
|
||||||
if bom.Components != nil {
|
if bom.Components != nil {
|
||||||
for i := range *bom.Components {
|
for i := range *bom.Components {
|
||||||
@ -58,7 +58,7 @@ func collectBomPackages(bom *cyclonedx.BOM, s *sbom.SBOM, idMap map[string]inter
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectPackages(component *cyclonedx.Component, s *sbom.SBOM, idMap map[string]interface{}) {
|
func collectPackages(component *cyclonedx.Component, s *sbom.SBOM, idMap map[string]any) {
|
||||||
switch component.Type {
|
switch component.Type {
|
||||||
case cyclonedx.ComponentTypeOS:
|
case cyclonedx.ComponentTypeOS:
|
||||||
case cyclonedx.ComponentTypeContainer:
|
case cyclonedx.ComponentTypeContainer:
|
||||||
@ -168,7 +168,7 @@ func getPropertyValue(component *cyclonedx.Component, name string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectRelationships(bom *cyclonedx.BOM, s *sbom.SBOM, idMap map[string]interface{}) {
|
func collectRelationships(bom *cyclonedx.BOM, s *sbom.SBOM, idMap map[string]any) {
|
||||||
if bom.Dependencies == nil {
|
if bom.Dependencies == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ func encodeDescription(p pkg.Package) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeDescription(description string, metadata interface{}) {
|
func decodeDescription(description string, metadata any) {
|
||||||
switch meta := metadata.(type) {
|
switch meta := metadata.(type) {
|
||||||
case *pkg.ApkDBEntry:
|
case *pkg.ApkDBEntry:
|
||||||
meta.Description = description
|
meta.Description = description
|
||||||
|
|||||||
@ -100,7 +100,7 @@ func toCycloneDXAlgorithm(algorithm string) cyclonedx.HashAlgorithm {
|
|||||||
return validMap[strings.ToLower(algorithm)]
|
return validMap[strings.ToLower(algorithm)]
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeExternalReferences(c *cyclonedx.Component, metadata interface{}) {
|
func decodeExternalReferences(c *cyclonedx.Component, metadata any) {
|
||||||
if c.ExternalReferences == nil {
|
if c.ExternalReferences == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ func encodeGroup(p pkg.Package) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeGroup(group string, metadata interface{}) {
|
func decodeGroup(group string, metadata any) {
|
||||||
if meta, ok := metadata.(*pkg.JavaArchive); ok {
|
if meta, ok := metadata.(*pkg.JavaArchive); ok {
|
||||||
if meta.PomProperties == nil {
|
if meta.PomProperties == nil {
|
||||||
meta.PomProperties = &pkg.JavaPomProperties{}
|
meta.PomProperties = &pkg.JavaPomProperties{}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ var (
|
|||||||
CycloneDXFields = RequiredTag("cyclonedx")
|
CycloneDXFields = RequiredTag("cyclonedx")
|
||||||
)
|
)
|
||||||
|
|
||||||
func EncodeProperties(obj interface{}, prefix string) (out []cyclonedx.Property) {
|
func EncodeProperties(obj any, prefix string) (out []cyclonedx.Property) {
|
||||||
for _, p := range Sorted(Encode(obj, prefix, CycloneDXFields)) {
|
for _, p := range Sorted(Encode(obj, prefix, CycloneDXFields)) {
|
||||||
out = append(out, cyclonedx.Property{
|
out = append(out, cyclonedx.Property{
|
||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
@ -23,8 +23,8 @@ func EncodeProperties(obj interface{}, prefix string) (out []cyclonedx.Property)
|
|||||||
func decodeProperties(properties []cyclonedx.Property, prefix string) map[string]string {
|
func decodeProperties(properties []cyclonedx.Property, prefix string) map[string]string {
|
||||||
labels := make(map[string]string)
|
labels := make(map[string]string)
|
||||||
for _, property := range properties {
|
for _, property := range properties {
|
||||||
if strings.HasPrefix(property.Name, prefix) {
|
if after, ok := strings.CutPrefix(property.Name, prefix); ok {
|
||||||
labelName := strings.TrimPrefix(property.Name, prefix)
|
labelName := after
|
||||||
labels[labelName] = property.Value
|
labels[labelName] = property.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -300,8 +300,8 @@ func decode(vals map[string]string, value reflect.Value, prefix string, fn Field
|
|||||||
// NOTE: this will not work for nested maps
|
// NOTE: this will not work for nested maps
|
||||||
for key := range vals {
|
for key := range vals {
|
||||||
// test for map prefix
|
// test for map prefix
|
||||||
if strings.HasPrefix(key, str) {
|
if after, ok := strings.CutPrefix(key, str); ok {
|
||||||
keyVals[key] = strings.TrimPrefix(key, str)
|
keyVals[key] = after
|
||||||
// create new placeholder and decode key
|
// create new placeholder and decode key
|
||||||
newKeyType := keyType
|
newKeyType := keyType
|
||||||
if keyType.Kind() == reflect.Ptr {
|
if keyType.Kind() == reflect.Ptr {
|
||||||
|
|||||||
@ -46,7 +46,7 @@ func Test_EncodeDecodeCycle(t *testing.T) {
|
|||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
value interface{}
|
value any
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "all values",
|
name: "all values",
|
||||||
|
|||||||
@ -18,7 +18,7 @@ func encodePublisher(p pkg.Package) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodePublisher(publisher string, metadata interface{}) {
|
func decodePublisher(publisher string, metadata any) {
|
||||||
switch meta := metadata.(type) {
|
switch meta := metadata.(type) {
|
||||||
case *pkg.ApkDBEntry:
|
case *pkg.ApkDBEntry:
|
||||||
meta.Maintainer = publisher
|
meta.Maintainer = publisher
|
||||||
|
|||||||
@ -44,7 +44,7 @@ type Descriptor struct {
|
|||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
|
|
||||||
// Configuration contains the tool configuration used during SBOM generation.
|
// Configuration contains the tool configuration used during SBOM generation.
|
||||||
Configuration interface{} `json:"configuration,omitempty"`
|
Configuration any `json:"configuration,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schema specifies the JSON schema version and URL reference that defines the structure and validation rules for this document format.
|
// Schema specifies the JSON schema version and URL reference that defines the structure and validation rules for this document format.
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import (
|
|||||||
func TestIDLikes_UnmarshalJSON(t *testing.T) {
|
func TestIDLikes_UnmarshalJSON(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
data interface{}
|
data any
|
||||||
expected IDLikes
|
expected IDLikes
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
|||||||
@ -205,7 +205,7 @@ func unpackPkgMetadata(p *Package, unpacker packageMetadataUnpacker) error {
|
|||||||
if typ == nil {
|
if typ == nil {
|
||||||
// capture unknown metadata as a generic struct
|
// capture unknown metadata as a generic struct
|
||||||
if len(unpacker.Metadata) > 0 {
|
if len(unpacker.Metadata) > 0 {
|
||||||
var val interface{}
|
var val any
|
||||||
if err := json.Unmarshal(unpacker.Metadata, &val); err != nil {
|
if err := json.Unmarshal(unpacker.Metadata, &val); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -207,7 +207,7 @@ func Test_UnmarshalJSON(t *testing.T) {
|
|||||||
`),
|
`),
|
||||||
assert: func(p *Package) {
|
assert: func(p *Package) {
|
||||||
assert.Equal(t, pkg.RpmPkg, p.Type)
|
assert.Equal(t, pkg.RpmPkg, p.Type)
|
||||||
assert.Equal(t, reflect.TypeOf(pkg.RpmDBEntry{}).Name(), reflect.TypeOf(p.Metadata).Name())
|
assert.Equal(t, reflect.TypeFor[pkg.RpmDBEntry]().Name(), reflect.TypeOf(p.Metadata).Name())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -248,7 +248,7 @@ func Test_UnmarshalJSON(t *testing.T) {
|
|||||||
`),
|
`),
|
||||||
assert: func(p *Package) {
|
assert: func(p *Package) {
|
||||||
assert.Equal(t, pkg.RpmPkg, p.Type)
|
assert.Equal(t, pkg.RpmPkg, p.Type)
|
||||||
assert.Equal(t, reflect.TypeOf(pkg.RpmArchive{}).Name(), reflect.TypeOf(p.Metadata).Name())
|
assert.Equal(t, reflect.TypeFor[pkg.RpmArchive]().Name(), reflect.TypeOf(p.Metadata).Name())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -287,7 +287,7 @@ func Test_UnmarshalJSON(t *testing.T) {
|
|||||||
}`),
|
}`),
|
||||||
assert: func(p *Package) {
|
assert: func(p *Package) {
|
||||||
assert.Equal(t, pkg.HackagePkg, p.Type)
|
assert.Equal(t, pkg.HackagePkg, p.Type)
|
||||||
assert.Equal(t, reflect.TypeOf(pkg.HackageStackYamlEntry{}).Name(), reflect.TypeOf(p.Metadata).Name())
|
assert.Equal(t, reflect.TypeFor[pkg.HackageStackYamlEntry]().Name(), reflect.TypeOf(p.Metadata).Name())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -327,7 +327,7 @@ func Test_UnmarshalJSON(t *testing.T) {
|
|||||||
}`),
|
}`),
|
||||||
assert: func(p *Package) {
|
assert: func(p *Package) {
|
||||||
assert.Equal(t, pkg.HackagePkg, p.Type)
|
assert.Equal(t, pkg.HackagePkg, p.Type)
|
||||||
assert.Equal(t, reflect.TypeOf(pkg.HackageStackYamlLockEntry{}).Name(), reflect.TypeOf(p.Metadata).Name())
|
assert.Equal(t, reflect.TypeFor[pkg.HackageStackYamlLockEntry]().Name(), reflect.TypeOf(p.Metadata).Name())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -355,7 +355,7 @@ func Test_UnmarshalJSON(t *testing.T) {
|
|||||||
}`),
|
}`),
|
||||||
assert: func(p *Package) {
|
assert: func(p *Package) {
|
||||||
assert.Equal(t, pkg.HackagePkg, p.Type)
|
assert.Equal(t, pkg.HackagePkg, p.Type)
|
||||||
assert.Equal(t, reflect.TypeOf(pkg.RustCargoLockEntry{}).Name(), reflect.TypeOf(p.Metadata).Name())
|
assert.Equal(t, reflect.TypeFor[pkg.RustCargoLockEntry]().Name(), reflect.TypeOf(p.Metadata).Name())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -383,7 +383,7 @@ func Test_UnmarshalJSON(t *testing.T) {
|
|||||||
}`),
|
}`),
|
||||||
assert: func(p *Package) {
|
assert: func(p *Package) {
|
||||||
assert.Equal(t, pkg.HackagePkg, p.Type)
|
assert.Equal(t, pkg.HackagePkg, p.Type)
|
||||||
assert.Equal(t, reflect.TypeOf(pkg.RustBinaryAuditEntry{}).Name(), reflect.TypeOf(p.Metadata).Name())
|
assert.Equal(t, reflect.TypeFor[pkg.RustBinaryAuditEntry]().Name(), reflect.TypeOf(p.Metadata).Name())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -654,7 +654,7 @@ func Test_unpackMetadata(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
wantErr: require.Error,
|
wantErr: require.Error,
|
||||||
wantMetadata: map[string]interface{}{
|
wantMetadata: map[string]any{
|
||||||
"thing": "thing-1",
|
"thing": "thing-1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -12,5 +12,5 @@ type Relationship struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
// Metadata contains additional relationship-specific metadata.
|
// Metadata contains additional relationship-specific metadata.
|
||||||
Metadata interface{} `json:"metadata,omitempty"`
|
Metadata any `json:"metadata,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@ type Source struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
// Metadata contains additional source-specific metadata.
|
// Metadata contains additional source-specific metadata.
|
||||||
Metadata interface{} `json:"metadata"`
|
Metadata any `json:"metadata"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// sourceUnpacker is used to unmarshal Source objects
|
// sourceUnpacker is used to unmarshal Source objects
|
||||||
@ -97,7 +97,7 @@ func cleanPreSchemaV9MetadataType(t string) string {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractPreSchemaV9Metadata(t string, target []byte) (interface{}, error) {
|
func extractPreSchemaV9Metadata(t string, target []byte) (any, error) {
|
||||||
switch t {
|
switch t {
|
||||||
case "directory", "dir":
|
case "directory", "dir":
|
||||||
cleanTarget, err := strconv.Unquote(string(target))
|
cleanTarget, err := strconv.Unquote(string(target))
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/iancoleman/strcase"
|
"github.com/iancoleman/strcase"
|
||||||
@ -79,10 +80,8 @@ func isFollowingConvention(path, fieldName string) (bool, string) {
|
|||||||
result := exp == fieldName
|
result := exp == fieldName
|
||||||
|
|
||||||
exception := func(exceptions ...string) (bool, string) {
|
exception := func(exceptions ...string) (bool, string) {
|
||||||
for _, e := range exceptions {
|
if slices.Contains(exceptions, fieldName) {
|
||||||
if e == fieldName {
|
return true, fieldName
|
||||||
return true, fieldName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result, exp
|
return result, exp
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,11 +21,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// MetadataType infers the metadata type value based on the pkg.Metadata payload.
|
// MetadataType infers the metadata type value based on the pkg.Metadata payload.
|
||||||
func MetadataType(metadata interface{}) string {
|
func MetadataType(metadata any) string {
|
||||||
return metadataType(metadata, false)
|
return metadataType(metadata, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func metadataType(metadata interface{}, legacy bool) string {
|
func metadataType(metadata any, legacy bool) string {
|
||||||
if legacy {
|
if legacy {
|
||||||
return packagemetadata.JSONLegacyName(metadata)
|
return packagemetadata.JSONLegacyName(metadata)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -223,7 +223,7 @@ func toInternalLinuxRelease(d model.LinuxRelease) *linux.Release {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func toSyftRelationships(doc *model.Document, catalog *pkg.Collection, relationships []model.Relationship, idAliases map[string]string) ([]artifact.Relationship, []error) {
|
func toSyftRelationships(doc *model.Document, catalog *pkg.Collection, relationships []model.Relationship, idAliases map[string]string) ([]artifact.Relationship, []error) {
|
||||||
idMap := make(map[string]interface{})
|
idMap := make(map[string]any)
|
||||||
|
|
||||||
for _, p := range catalog.Sorted() {
|
for _, p := range catalog.Sorted() {
|
||||||
idMap[string(p.ID())] = p
|
idMap[string(p.ID())] = p
|
||||||
@ -263,7 +263,7 @@ func toSyftSource(s model.Source) source.Source {
|
|||||||
return source.FromDescription(*description)
|
return source.FromDescription(*description)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSyftRelationship(idMap map[string]interface{}, relationship model.Relationship, idAliases map[string]string) (*artifact.Relationship, error) {
|
func toSyftRelationship(idMap map[string]any, relationship model.Relationship, idAliases map[string]string) (*artifact.Relationship, error) {
|
||||||
id := func(id string) string {
|
id := func(id string) string {
|
||||||
aliased, ok := idAliases[id]
|
aliased, ok := idAliases[id]
|
||||||
if ok {
|
if ok {
|
||||||
|
|||||||
@ -448,7 +448,7 @@ func Test_toSyftRelationship(t *testing.T) {
|
|||||||
parentPackage := packageWithId("some-parent-id")
|
parentPackage := packageWithId("some-parent-id")
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
idMap map[string]interface{}
|
idMap map[string]any
|
||||||
idAliases map[string]string
|
idAliases map[string]string
|
||||||
relationships model.Relationship
|
relationships model.Relationship
|
||||||
want *artifact.Relationship
|
want *artifact.Relationship
|
||||||
@ -456,7 +456,7 @@ func Test_toSyftRelationship(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "one relationship no warnings",
|
name: "one relationship no warnings",
|
||||||
idMap: map[string]interface{}{
|
idMap: map[string]any{
|
||||||
"some-child-id": childPackage,
|
"some-child-id": childPackage,
|
||||||
"some-parent-id": parentPackage,
|
"some-parent-id": parentPackage,
|
||||||
},
|
},
|
||||||
@ -474,7 +474,7 @@ func Test_toSyftRelationship(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "relationship unknown type one warning",
|
name: "relationship unknown type one warning",
|
||||||
idMap: map[string]interface{}{
|
idMap: map[string]any{
|
||||||
"some-child-id": childPackage,
|
"some-child-id": childPackage,
|
||||||
"some-parent-id": parentPackage,
|
"some-parent-id": parentPackage,
|
||||||
},
|
},
|
||||||
@ -490,7 +490,7 @@ func Test_toSyftRelationship(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "relationship missing child ID one warning",
|
name: "relationship missing child ID one warning",
|
||||||
idMap: map[string]interface{}{
|
idMap: map[string]any{
|
||||||
"some-parent-id": parentPackage,
|
"some-parent-id": parentPackage,
|
||||||
},
|
},
|
||||||
idAliases: map[string]string{},
|
idAliases: map[string]string{},
|
||||||
@ -505,7 +505,7 @@ func Test_toSyftRelationship(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "relationship missing parent ID one warning",
|
name: "relationship missing parent ID one warning",
|
||||||
idMap: map[string]interface{}{
|
idMap: map[string]any{
|
||||||
"some-child-id": childPackage,
|
"some-child-id": childPackage,
|
||||||
},
|
},
|
||||||
idAliases: map[string]string{},
|
idAliases: map[string]string{},
|
||||||
|
|||||||
@ -34,7 +34,7 @@ func NewFormatEncoder(cfg EncoderConfig) (sbom.FormatEncoder, error) {
|
|||||||
// TODO: revisit this... should no template file be an error or simply render an empty result? or render the json output?
|
// TODO: revisit this... should no template file be an error or simply render an empty result? or render the json output?
|
||||||
// Note: do not check for the existence of the template file here, as the default encoder cannot provide one.
|
// Note: do not check for the existence of the template file here, as the default encoder cannot provide one.
|
||||||
f := sprig.HermeticTxtFuncMap()
|
f := sprig.HermeticTxtFuncMap()
|
||||||
f["getLastIndex"] = func(collection interface{}) int {
|
f["getLastIndex"] = func(collection any) int {
|
||||||
if v := reflect.ValueOf(collection); v.Kind() == reflect.Slice {
|
if v := reflect.ValueOf(collection); v.Kind() == reflect.Slice {
|
||||||
return v.Len() - 1
|
return v.Len() - 1
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ func NewFormatEncoder(cfg EncoderConfig) (sbom.FormatEncoder, error) {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
// Checks if a field is defined
|
// Checks if a field is defined
|
||||||
f["hasField"] = func(obj interface{}, field string) bool {
|
f["hasField"] = func(obj any, field string) bool {
|
||||||
t := reflect.TypeOf(obj)
|
t := reflect.TypeOf(obj)
|
||||||
_, ok := t.FieldByName(field)
|
_, ok := t.FieldByName(field)
|
||||||
return ok
|
return ok
|
||||||
|
|||||||
@ -148,7 +148,7 @@ func TestValidateSourcePlatform_UnsupportedMetadataTypes(t *testing.T) {
|
|||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
metadata interface{}
|
metadata any
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "string metadata",
|
name: "string metadata",
|
||||||
|
|||||||
@ -385,8 +385,8 @@ func (r directoryIndexer) addSymlinkToIndex(p string, info os.FileInfo) (string,
|
|||||||
// we cannot directly concatenate ".." to "/root/symlink",however,
|
// we cannot directly concatenate ".." to "/root/symlink",however,
|
||||||
// the parent directory of linkTarget should be "/root"
|
// the parent directory of linkTarget should be "/root"
|
||||||
for strings.HasPrefix(dir, "..") {
|
for strings.HasPrefix(dir, "..") {
|
||||||
if strings.HasPrefix(dir, "../") {
|
if after, ok := strings.CutPrefix(dir, "../"); ok {
|
||||||
dir = strings.TrimPrefix(dir, "../")
|
dir = after
|
||||||
} else {
|
} else {
|
||||||
dir = strings.TrimPrefix(dir, "..")
|
dir = strings.TrimPrefix(dir, "..")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
//go:build !windows
|
//go:build !windows
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package fileresolver
|
package fileresolver
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
//go:build !windows
|
//go:build !windows
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package fileresolver
|
package fileresolver
|
||||||
|
|
||||||
@ -1355,7 +1354,7 @@ func (t testFileInfo) IsDir() bool {
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t testFileInfo) Sys() interface{} {
|
func (t testFileInfo) Sys() any {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -426,7 +426,7 @@ func assertSkipErr() assert.ErrorAssertionFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func assertErrorIs(want error) assert.ErrorAssertionFunc {
|
func assertErrorIs(want error) assert.ErrorAssertionFunc {
|
||||||
return func(t assert.TestingT, got error, msgAndArgs ...interface{}) bool {
|
return func(t assert.TestingT, got error, msgAndArgs ...any) bool {
|
||||||
return assert.ErrorIs(t, got, want, msgAndArgs...)
|
return assert.ErrorIs(t, got, want, msgAndArgs...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -300,7 +300,7 @@ func (u UnindexedDirectory) resolveLinks(filePath string) []string {
|
|||||||
resolvedPath := ""
|
resolvedPath := ""
|
||||||
|
|
||||||
parts := strings.Split(filePath, "/")
|
parts := strings.Split(filePath, "/")
|
||||||
for i := 0; i < len(parts); i++ {
|
for i := range parts {
|
||||||
part := parts[i]
|
part := parts[i]
|
||||||
if resolvedPath == "" {
|
if resolvedPath == "" {
|
||||||
resolvedPath = part
|
resolvedPath = part
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
//go:build !windows
|
//go:build !windows
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package fileresolver
|
package fileresolver
|
||||||
|
|
||||||
|
|||||||
@ -168,7 +168,7 @@ func TestReaderAtAdapter_ReadAt(t *testing.T) {
|
|||||||
adapter := newReaderAtAdapter(reader)
|
adapter := newReaderAtAdapter(reader)
|
||||||
|
|
||||||
// read the same data multiple times
|
// read the same data multiple times
|
||||||
for i := 0; i < 3; i++ {
|
for i := range 3 {
|
||||||
buf := make([]byte, 5)
|
buf := make([]byte, 5)
|
||||||
n, err := adapter.ReadAt(buf, 7)
|
n, err := adapter.ReadAt(buf, 7)
|
||||||
|
|
||||||
@ -194,12 +194,12 @@ func TestReaderAtAdapter_ReadAt(t *testing.T) {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
results := make(chan bool, numGoroutines*numReads)
|
results := make(chan bool, numGoroutines*numReads)
|
||||||
|
|
||||||
for i := 0; i < numGoroutines; i++ {
|
for i := range numGoroutines {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(goroutineID int) {
|
go func(goroutineID int) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
for j := 0; j < numReads; j++ {
|
for range numReads {
|
||||||
offset := int64(goroutineID % len(td))
|
offset := int64(goroutineID % len(td))
|
||||||
buf := make([]byte, 1)
|
buf := make([]byte, 1)
|
||||||
|
|
||||||
|
|||||||
@ -71,11 +71,11 @@ type spaceDelimitedStringSlice []string
|
|||||||
|
|
||||||
func (m *ApkDBEntry) UnmarshalJSON(data []byte) error {
|
func (m *ApkDBEntry) UnmarshalJSON(data []byte) error {
|
||||||
var fields []reflect.StructField
|
var fields []reflect.StructField
|
||||||
t := reflect.TypeOf(ApkDBEntry{})
|
t := reflect.TypeFor[ApkDBEntry]()
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
f := t.Field(i)
|
f := t.Field(i)
|
||||||
if f.Name == "Dependencies" {
|
if f.Name == "Dependencies" {
|
||||||
f.Type = reflect.TypeOf(spaceDelimitedStringSlice{})
|
f.Type = reflect.TypeFor[spaceDelimitedStringSlice]()
|
||||||
}
|
}
|
||||||
fields = append(fields, f)
|
fields = append(fields, f)
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ func (m *ApkDBEntry) UnmarshalJSON(data []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *spaceDelimitedStringSlice) UnmarshalJSON(data []byte) error {
|
func (a *spaceDelimitedStringSlice) UnmarshalJSON(data []byte) error {
|
||||||
var jsonObj interface{}
|
var jsonObj any
|
||||||
|
|
||||||
if err := json.Unmarshal(data, &jsonObj); err != nil {
|
if err := json.Unmarshal(data, &jsonObj); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -103,7 +103,7 @@ func (a *spaceDelimitedStringSlice) UnmarshalJSON(data []byte) error {
|
|||||||
*a = strings.Split(obj, " ")
|
*a = strings.Split(obj, " ")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case []interface{}:
|
case []any:
|
||||||
s := make([]string, 0, len(obj))
|
s := make([]string, 0, len(obj))
|
||||||
for _, v := range obj {
|
for _, v := range obj {
|
||||||
value, ok := v.(string)
|
value, ok := v.(string)
|
||||||
|
|||||||
@ -76,7 +76,7 @@ func TestGGUFCataloger(t *testing.T) {
|
|||||||
GGUFVersion: 3,
|
GGUFVersion: 3,
|
||||||
TensorCount: 0,
|
TensorCount: 0,
|
||||||
MetadataKeyValuesHash: "6e3d368066455ce4",
|
MetadataKeyValuesHash: "6e3d368066455ce4",
|
||||||
RemainingKeyValues: map[string]interface{}{
|
RemainingKeyValues: map[string]any{
|
||||||
"general.some_random_kv": "foobar",
|
"general.some_random_kv": "foobar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -113,7 +113,7 @@ func TestGGUFCataloger(t *testing.T) {
|
|||||||
GGUFVersion: 3,
|
GGUFVersion: 3,
|
||||||
TensorCount: 0,
|
TensorCount: 0,
|
||||||
MetadataKeyValuesHash: "9dc6f23591062a27",
|
MetadataKeyValuesHash: "9dc6f23591062a27",
|
||||||
RemainingKeyValues: map[string]interface{}{
|
RemainingKeyValues: map[string]any{
|
||||||
"gpt2.context_length": "1024",
|
"gpt2.context_length": "1024",
|
||||||
"gpt2.embedding_length": uint32(768),
|
"gpt2.embedding_length": uint32(768),
|
||||||
},
|
},
|
||||||
|
|||||||
@ -46,8 +46,8 @@ func copyHeader(w io.Writer, r io.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper to convert gguf_parser metadata to simpler types
|
// Helper to convert gguf_parser metadata to simpler types
|
||||||
func convertGGUFMetadataKVs(kvs gguf_parser.GGUFMetadataKVs) map[string]interface{} {
|
func convertGGUFMetadataKVs(kvs gguf_parser.GGUFMetadataKVs) map[string]any {
|
||||||
result := make(map[string]interface{})
|
result := make(map[string]any)
|
||||||
|
|
||||||
for _, kv := range kvs {
|
for _, kv := range kvs {
|
||||||
// Skip standard fields that are extracted separately
|
// Skip standard fields that are extracted separately
|
||||||
|
|||||||
@ -35,7 +35,7 @@ type testGGUFBuilder struct {
|
|||||||
type testKVPair struct {
|
type testKVPair struct {
|
||||||
key string
|
key string
|
||||||
valueType uint32
|
valueType uint32
|
||||||
value interface{}
|
value any
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestGGUFBuilder() *testGGUFBuilder {
|
func newTestGGUFBuilder() *testGGUFBuilder {
|
||||||
|
|||||||
@ -153,7 +153,7 @@ func newScanner(reader io.Reader) *bufio.Scanner {
|
|||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
scanner.Buffer(bufScan, maxScannerCapacity)
|
scanner.Buffer(bufScan, maxScannerCapacity)
|
||||||
onDoubleLF := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
onDoubleLF := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||||
for i := 0; i < len(data); i++ {
|
for i := range data {
|
||||||
if i > 0 && data[i-1] == '\n' && data[i] == '\n' {
|
if i > 0 && data[i-1] == '\n' && data[i] == '\n' {
|
||||||
return i + 1, data[:i-1], nil
|
return i + 1, data[:i-1], nil
|
||||||
}
|
}
|
||||||
@ -188,7 +188,7 @@ func getLocation(path string, resolver file.Resolver) (file.Location, error) {
|
|||||||
|
|
||||||
func parseDatabase(b *bufio.Scanner) (*parsedData, error) {
|
func parseDatabase(b *bufio.Scanner) (*parsedData, error) {
|
||||||
var err error
|
var err error
|
||||||
pkgFields := make(map[string]interface{})
|
pkgFields := make(map[string]any)
|
||||||
for b.Scan() {
|
for b.Scan() {
|
||||||
fields := strings.SplitN(b.Text(), "\n", 2)
|
fields := strings.SplitN(b.Text(), "\n", 2)
|
||||||
|
|
||||||
@ -213,12 +213,12 @@ func parseDatabase(b *bufio.Scanner) (*parsedData, error) {
|
|||||||
}
|
}
|
||||||
pkgFields[key] = files
|
pkgFields[key] = files
|
||||||
case "backup":
|
case "backup":
|
||||||
var backup []map[string]interface{}
|
var backup []map[string]any
|
||||||
for _, f := range strings.Split(value, "\n") {
|
for _, f := range strings.Split(value, "\n") {
|
||||||
fields := strings.SplitN(f, "\t", 2)
|
fields := strings.SplitN(f, "\t", 2)
|
||||||
p := fmt.Sprintf("/%s", fields[0])
|
p := fmt.Sprintf("/%s", fields[0])
|
||||||
if ok := ignoredFiles[p]; !ok {
|
if ok := ignoredFiles[p]; !ok {
|
||||||
backup = append(backup, map[string]interface{}{
|
backup = append(backup, map[string]any{
|
||||||
"path": p,
|
"path": p,
|
||||||
"digests": []file.Digest{{
|
"digests": []file.Digest{{
|
||||||
Algorithm: "md5",
|
Algorithm: "md5",
|
||||||
@ -257,7 +257,7 @@ func processLibrarySpecs(value string) []string {
|
|||||||
return librarySpecs
|
return librarySpecs
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePkgFiles(pkgFields map[string]interface{}) (*parsedData, error) {
|
func parsePkgFiles(pkgFields map[string]any) (*parsedData, error) {
|
||||||
var entry parsedData
|
var entry parsedData
|
||||||
if err := mapstructure.Decode(pkgFields, &entry); err != nil {
|
if err := mapstructure.Decode(pkgFields, &entry); err != nil {
|
||||||
return nil, fmt.Errorf("unable to parse ALPM metadata: %w", err)
|
return nil, fmt.Errorf("unable to parse ALPM metadata: %w", err)
|
||||||
@ -292,7 +292,7 @@ func parseMtree(r io.Reader) ([]pkg.AlpmFileRecord, error) {
|
|||||||
for _, f := range specDh.Entries {
|
for _, f := range specDh.Entries {
|
||||||
var entry pkg.AlpmFileRecord
|
var entry pkg.AlpmFileRecord
|
||||||
entry.Digests = make([]file.Digest, 0)
|
entry.Digests = make([]file.Digest, 0)
|
||||||
fileFields := make(map[string]interface{})
|
fileFields := make(map[string]any)
|
||||||
if ok := ignoredFiles[f.Name]; ok {
|
if ok := ignoredFiles[f.Name]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@ -195,7 +195,7 @@ func Test_CondaCataloger(t *testing.T) {
|
|||||||
name: "badly formatted conda meta json file",
|
name: "badly formatted conda meta json file",
|
||||||
fixture: "testdata/conda-meta-bad-json",
|
fixture: "testdata/conda-meta-bad-json",
|
||||||
expectedPackages: nil,
|
expectedPackages: nil,
|
||||||
wantErr: func(t require.TestingT, err error, msgAndArgs ...interface{}) {
|
wantErr: func(t require.TestingT, err error, msgAndArgs ...any) {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Contains(t, err.Error(), "failed to parse conda-meta package file at conda-meta/package-1.2.3-pyhd8ed1ab_0.json")
|
require.Contains(t, err.Error(), "failed to parse conda-meta package file at conda-meta/package-1.2.3-pyhd8ed1ab_0.json")
|
||||||
require.Contains(t, err.Error(), "invalid character")
|
require.Contains(t, err.Error(), "invalid character")
|
||||||
|
|||||||
@ -194,8 +194,8 @@ func splitPkgList(pkgList string) (ret []string) {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractAllFields(reader *bufio.Reader) (map[string]interface{}, error) {
|
func extractAllFields(reader *bufio.Reader) (map[string]any, error) {
|
||||||
dpkgFields := make(map[string]interface{})
|
dpkgFields := make(map[string]any)
|
||||||
var key string
|
var key string
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@ -234,7 +234,7 @@ func extractAllFields(reader *bufio.Reader) (map[string]interface{}, error) {
|
|||||||
dpkgFields[key] = val
|
dpkgFields[key] = val
|
||||||
default:
|
default:
|
||||||
// parse a new key
|
// parse a new key
|
||||||
var val interface{}
|
var val any
|
||||||
key, val, err = handleNewKeyValue(line)
|
key, val, err = handleNewKeyValue(line)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Tracef("parsing dpkg status: extracting key-value from line: %s err: %v", line, err)
|
log.Tracef("parsing dpkg status: extracting key-value from line: %s err: %v", line, err)
|
||||||
@ -259,7 +259,7 @@ func extractSourceVersion(source string) (string, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handleNewKeyValue parse a new key-value pair from the given unprocessed line
|
// handleNewKeyValue parse a new key-value pair from the given unprocessed line
|
||||||
func handleNewKeyValue(line string) (key string, val interface{}, err error) {
|
func handleNewKeyValue(line string) (key string, val any, err error) {
|
||||||
if i := strings.Index(line, ":"); i > 0 {
|
if i := strings.Index(line, ":"); i > 0 {
|
||||||
key = strings.TrimSpace(line[0:i])
|
key = strings.TrimSpace(line[0:i])
|
||||||
// mapstruct cant handle "-"
|
// mapstruct cant handle "-"
|
||||||
|
|||||||
@ -339,7 +339,7 @@ func TestSourceVersionExtract(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func requireAs(expected error) require.ErrorAssertionFunc {
|
func requireAs(expected error) require.ErrorAssertionFunc {
|
||||||
return func(t require.TestingT, err error, i ...interface{}) {
|
return func(t require.TestingT, err error, i ...any) {
|
||||||
require.ErrorAs(t, err, &expected)
|
require.ErrorAs(t, err, &expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -413,7 +413,7 @@ func Test_handleNewKeyValue(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
line string
|
line string
|
||||||
wantKey string
|
wantKey string
|
||||||
wantVal interface{}
|
wantVal any
|
||||||
wantErr require.ErrorAssertionFunc
|
wantErr require.ErrorAssertionFunc
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type erlangNode struct {
|
type erlangNode struct {
|
||||||
value interface{}
|
value any
|
||||||
}
|
}
|
||||||
|
|
||||||
var errSkipComments = errors.New("")
|
var errSkipComments = errors.New("")
|
||||||
@ -39,7 +39,7 @@ func (e erlangNode) Get(index int) erlangNode {
|
|||||||
return erlangNode{}
|
return erlangNode{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func node(value interface{}) erlangNode {
|
func node(value any) erlangNode {
|
||||||
return erlangNode{
|
return erlangNode{
|
||||||
value: value,
|
value: value,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -143,9 +143,9 @@ func replaceLicenseGroups(licenses []string, groups map[string][]string) []strin
|
|||||||
|
|
||||||
result := make([]string, 0, len(licenses))
|
result := make([]string, 0, len(licenses))
|
||||||
for _, license := range licenses {
|
for _, license := range licenses {
|
||||||
if strings.HasPrefix(license, "@") {
|
if after, ok := strings.CutPrefix(license, "@"); ok {
|
||||||
// this is a license group...
|
// this is a license group...
|
||||||
name := strings.TrimPrefix(license, "@")
|
name := after
|
||||||
if expandedLicenses, ok := groups[name]; ok {
|
if expandedLicenses, ok := groups[name]; ok {
|
||||||
result = append(result, expandedLicenses...)
|
result = append(result, expandedLicenses...)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -346,7 +346,7 @@ func parseELFPTLoadOffsets(elfHeader []byte) []uint64 {
|
|||||||
phnum := binary.LittleEndian.Uint16(elfHeader[0x38:0x3a])
|
phnum := binary.LittleEndian.Uint16(elfHeader[0x38:0x3a])
|
||||||
|
|
||||||
var offsets []uint64
|
var offsets []uint64
|
||||||
for i := uint16(0); i < phnum; i++ {
|
for i := range phnum {
|
||||||
phStart := phoff + uint64(i)*uint64(phentsize)
|
phStart := phoff + uint64(i)*uint64(phentsize)
|
||||||
if phStart+uint64(phentsize) > uint64(len(elfHeader)) {
|
if phStart+uint64(phentsize) > uint64(len(elfHeader)) {
|
||||||
break
|
break
|
||||||
@ -499,10 +499,7 @@ func decompressLZMA(compressedData []byte, uncompressedSize uint32) ([]byte, err
|
|||||||
// it may be that the dictionary size was not considered properly in this code.
|
// it may be that the dictionary size was not considered properly in this code.
|
||||||
const minDictSize = 64 * 1024 // 64KB minimum
|
const minDictSize = 64 * 1024 // 64KB minimum
|
||||||
const maxDictSize = 128 * 1024 * 1024 // 128MB maximum
|
const maxDictSize = 128 * 1024 * 1024 // 128MB maximum
|
||||||
dictSize := nextPowerOf2(uncompressedSize)
|
dictSize := max(nextPowerOf2(uncompressedSize), minDictSize)
|
||||||
if dictSize < minDictSize {
|
|
||||||
dictSize = minDictSize
|
|
||||||
}
|
|
||||||
if dictSize > maxDictSize {
|
if dictSize > maxDictSize {
|
||||||
dictSize = maxDictSize
|
dictSize = maxDictSize
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,8 +42,8 @@ func upstreamCandidates(m pkg.ApkDBEntry) (candidates []upstreamCandidate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for prefix, typ := range prefixesToPackageType {
|
for prefix, typ := range prefixesToPackageType {
|
||||||
if strings.HasPrefix(name, prefix) {
|
if after, ok0 := strings.CutPrefix(name, prefix); ok0 {
|
||||||
t := strings.TrimPrefix(name, prefix)
|
t := after
|
||||||
if t != "" {
|
if t != "" {
|
||||||
candidates = append(candidates, upstreamCandidate{Name: t, Type: typ})
|
candidates = append(candidates, upstreamCandidate{Name: t, Type: typ})
|
||||||
return candidates
|
return candidates
|
||||||
|
|||||||
@ -260,8 +260,8 @@ func addEntryForNPMPackage(indexed *dictionary.Indexed, ref string, cpeItemName
|
|||||||
}
|
}
|
||||||
|
|
||||||
func phpExtensionPackageFromURLFragment(ref string) string {
|
func phpExtensionPackageFromURLFragment(ref string) string {
|
||||||
if strings.HasPrefix(ref, "package/") { // package/HTML_QuickForm/download
|
if after, ok := strings.CutPrefix(ref, "package/"); ok { // package/HTML_QuickForm/download
|
||||||
ref = strings.TrimPrefix(ref, "package/")
|
ref = after
|
||||||
components := strings.Split(ref, "/")
|
components := strings.Split(ref, "/")
|
||||||
|
|
||||||
if len(components) < 1 {
|
if len(components) < 1 {
|
||||||
|
|||||||
@ -206,7 +206,7 @@ func (c *NVDAPIClient) fetchDateRange(ctx context.Context, start, end time.Time)
|
|||||||
func (c *NVDAPIClient) fetchPage(ctx context.Context, startIndex int, start, end time.Time) (NVDProductsResponse, error) {
|
func (c *NVDAPIClient) fetchPage(ctx context.Context, startIndex int, start, end time.Time) (NVDProductsResponse, error) {
|
||||||
var lastErr error
|
var lastErr error
|
||||||
|
|
||||||
for attempt := 0; attempt < maxRetries; attempt++ {
|
for attempt := range maxRetries {
|
||||||
// wait for rate limiter
|
// wait for rate limiter
|
||||||
if err := c.rateLimiter.Wait(ctx); err != nil {
|
if err := c.rateLimiter.Wait(ctx); err != nil {
|
||||||
return NVDProductsResponse{}, fmt.Errorf("rate limiter error: %w", err)
|
return NVDProductsResponse{}, fmt.Errorf("rate limiter error: %w", err)
|
||||||
|
|||||||
@ -33,7 +33,6 @@ func Test_IsLicenseFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
got := IsLicenseFile(tt.input)
|
got := IsLicenseFile(tt.input)
|
||||||
|
|||||||
@ -206,7 +206,7 @@ func readDepsJSONAtOffset(r io.ReadSeeker, offset, size int64) (string, error) {
|
|||||||
|
|
||||||
// findDepsJSONInManifest parses manifest entries to find deps.json (for V1 bundles or fallback)
|
// findDepsJSONInManifest parses manifest entries to find deps.json (for V1 bundles or fallback)
|
||||||
func findDepsJSONInManifest(r io.ReadSeeker, numFiles int32, majorVersion uint32) (string, error) {
|
func findDepsJSONInManifest(r io.ReadSeeker, numFiles int32, majorVersion uint32) (string, error) {
|
||||||
for i := int32(0); i < numFiles; i++ {
|
for range numFiles {
|
||||||
var offset, size int64
|
var offset, size int64
|
||||||
|
|
||||||
if err := binary.Read(r, binary.LittleEndian, &offset); err != nil {
|
if err := binary.Read(r, binary.LittleEndian, &offset); err != nil {
|
||||||
|
|||||||
@ -422,7 +422,7 @@ func parseResourceDirectory(sec *extractedSection, dirs *u32set.Set, fields map[
|
|||||||
return fmt.Errorf("invalid number of entries in resource directory: %d", numEntries)
|
return fmt.Errorf("invalid number of entries in resource directory: %d", numEntries)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < numEntries; i++ {
|
for i := range numEntries {
|
||||||
var entry peImageResourceDirectoryEntry
|
var entry peImageResourceDirectoryEntry
|
||||||
|
|
||||||
entryOffset := offset + int64(binary.Size(directoryHeader)) + int64(i*binary.Size(entry))
|
entryOffset := offset + int64(binary.Size(directoryHeader)) + int64(i*binary.Size(entry))
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -322,7 +323,7 @@ func (t *MetadataTracker) RecordCatalogerObservations(
|
|||||||
|
|
||||||
// getMetadataTypeName returns the fully qualified type name of metadata (e.g., "pkg.ApkDBEntry").
|
// getMetadataTypeName returns the fully qualified type name of metadata (e.g., "pkg.ApkDBEntry").
|
||||||
// extracts just the last package path segment to keep names concise.
|
// extracts just the last package path segment to keep names concise.
|
||||||
func getMetadataTypeName(metadata interface{}) string {
|
func getMetadataTypeName(metadata any) string {
|
||||||
if metadata == nil {
|
if metadata == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -361,7 +362,7 @@ func lastPathSegment(path string) string {
|
|||||||
// hasIntegrityHash checks if metadata contains an integrity hash field.
|
// hasIntegrityHash checks if metadata contains an integrity hash field.
|
||||||
// note: this uses a best-effort approach checking common field names.
|
// note: this uses a best-effort approach checking common field names.
|
||||||
// DO NOT depend on these values in auto-generated capabilities definitions - use for test validation only.
|
// DO NOT depend on these values in auto-generated capabilities definitions - use for test validation only.
|
||||||
func hasIntegrityHash(metadata interface{}) bool {
|
func hasIntegrityHash(metadata any) bool {
|
||||||
v := dereferenceToStruct(metadata)
|
v := dereferenceToStruct(metadata)
|
||||||
if !v.IsValid() || v.Kind() != reflect.Struct {
|
if !v.IsValid() || v.Kind() != reflect.Struct {
|
||||||
return false
|
return false
|
||||||
@ -378,7 +379,7 @@ func hasIntegrityHash(metadata interface{}) bool {
|
|||||||
// hasFileDigests checks if metadata contains file records with digests.
|
// hasFileDigests checks if metadata contains file records with digests.
|
||||||
// note: uses a best-effort approach for detection.
|
// note: uses a best-effort approach for detection.
|
||||||
// DO NOT depend on these values in auto-generated capabilities definitions - use for test validation only.
|
// DO NOT depend on these values in auto-generated capabilities definitions - use for test validation only.
|
||||||
func hasFileDigests(metadata interface{}) bool {
|
func hasFileDigests(metadata any) bool {
|
||||||
v := dereferenceToStruct(metadata)
|
v := dereferenceToStruct(metadata)
|
||||||
if !v.IsValid() || v.Kind() != reflect.Struct {
|
if !v.IsValid() || v.Kind() != reflect.Struct {
|
||||||
return false
|
return false
|
||||||
@ -400,7 +401,7 @@ func hasFileDigests(metadata interface{}) bool {
|
|||||||
|
|
||||||
// dereferenceToStruct handles pointer dereferencing and returns the underlying value.
|
// dereferenceToStruct handles pointer dereferencing and returns the underlying value.
|
||||||
// returns an invalid value if the input is nil or not convertible to a struct.
|
// returns an invalid value if the input is nil or not convertible to a struct.
|
||||||
func dereferenceToStruct(v interface{}) reflect.Value {
|
func dereferenceToStruct(v any) reflect.Value {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return reflect.Value{}
|
return reflect.Value{}
|
||||||
}
|
}
|
||||||
@ -460,12 +461,7 @@ func countDependencyRelationships(relationships []artifact.Relationship) int {
|
|||||||
|
|
||||||
// contains checks if a string slice contains a specific string.
|
// contains checks if a string slice contains a specific string.
|
||||||
func contains(slice []string, item string) bool {
|
func contains(slice []string, item string) bool {
|
||||||
for _, s := range slice {
|
return slices.Contains(slice, item)
|
||||||
if s == item {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Result Writing =====
|
// ===== Result Writing =====
|
||||||
@ -494,7 +490,7 @@ func (t *MetadataTracker) WriteResults() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeJSONFile writes data as pretty-printed JSON to the specified path.
|
// writeJSONFile writes data as pretty-printed JSON to the specified path.
|
||||||
func writeJSONFile(path string, data interface{}) error {
|
func writeJSONFile(path string, data any) error {
|
||||||
file, err := os.Create(path)
|
file, err := os.Create(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/scylladb/go-set/strset"
|
"github.com/scylladb/go-set/strset"
|
||||||
@ -43,10 +44,8 @@ func NewObservingResolver(resolver file.Resolver) *ObservingResolver {
|
|||||||
// ObservedPathQuery checks if a specific path pattern was queried.
|
// ObservedPathQuery checks if a specific path pattern was queried.
|
||||||
func (r *ObservingResolver) ObservedPathQuery(input string) bool {
|
func (r *ObservingResolver) ObservedPathQuery(input string) bool {
|
||||||
for _, queries := range r.pathQueries {
|
for _, queries := range r.pathQueries {
|
||||||
for _, query := range queries {
|
if slices.Contains(queries, input) {
|
||||||
if query == input {
|
return true
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
@ -498,7 +498,7 @@ func stringPackage(p pkg.Package) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getFunctionName extracts the function name from a function pointer using reflection
|
// getFunctionName extracts the function name from a function pointer using reflection
|
||||||
func getFunctionName(fn interface{}) string {
|
func getFunctionName(fn any) string {
|
||||||
// get the function pointer
|
// get the function pointer
|
||||||
ptr := reflect.ValueOf(fn).Pointer()
|
ptr := reflect.ValueOf(fn).Pointer()
|
||||||
|
|
||||||
@ -532,7 +532,7 @@ func getCatalogerName(_ *testing.T, cataloger pkg.Cataloger) string {
|
|||||||
|
|
||||||
// getPackagePath extracts the package path from a function name
|
// getPackagePath extracts the package path from a function name
|
||||||
// e.g., "github.com/anchore/syft/syft/pkg/cataloger/python.parseRequirementsTxt" -> "python"
|
// e.g., "github.com/anchore/syft/syft/pkg/cataloger/python.parseRequirementsTxt" -> "python"
|
||||||
func getPackagePath(fn interface{}) string {
|
func getPackagePath(fn any) string {
|
||||||
ptr := reflect.ValueOf(fn).Pointer()
|
ptr := reflect.ValueOf(fn).Pointer()
|
||||||
funcForPC := runtime.FuncForPC(ptr)
|
funcForPC := runtime.FuncForPC(ptr)
|
||||||
if funcForPC == nil {
|
if funcForPC == nil {
|
||||||
@ -566,7 +566,7 @@ func getPackagePath(fn interface{}) string {
|
|||||||
func getPackagePathFromCataloger(_ pkg.Cataloger) string {
|
func getPackagePathFromCataloger(_ pkg.Cataloger) string {
|
||||||
// walk up the call stack to find the test file
|
// walk up the call stack to find the test file
|
||||||
// we're looking for a file in the cataloger directory structure
|
// we're looking for a file in the cataloger directory structure
|
||||||
for i := 0; i < 10; i++ {
|
for i := range 10 {
|
||||||
_, file, _, ok := runtime.Caller(i)
|
_, file, _, ok := runtime.Caller(i)
|
||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
|
|||||||
@ -395,7 +395,6 @@ func TestParseJar(t *testing.T) {
|
|||||||
|
|
||||||
var parent *pkg.Package
|
var parent *pkg.Package
|
||||||
for _, a := range actual {
|
for _, a := range actual {
|
||||||
a := a
|
|
||||||
if strings.Contains(a.Name, "example-") {
|
if strings.Contains(a.Name, "example-") {
|
||||||
parent = &a
|
parent = &a
|
||||||
}
|
}
|
||||||
@ -682,7 +681,6 @@ func TestParseNestedJar(t *testing.T) {
|
|||||||
|
|
||||||
actualNameVersionPairSet := strset.New()
|
actualNameVersionPairSet := strset.New()
|
||||||
for _, a := range actual {
|
for _, a := range actual {
|
||||||
a := a
|
|
||||||
key := makeKey(&a)
|
key := makeKey(&a)
|
||||||
actualNameVersionPairSet.Add(key)
|
actualNameVersionPairSet.Add(key)
|
||||||
if !expectedNameVersionPairSet.Has(key) {
|
if !expectedNameVersionPairSet.Has(key) {
|
||||||
@ -701,7 +699,6 @@ func TestParseNestedJar(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range actual {
|
for _, a := range actual {
|
||||||
a := a
|
|
||||||
actualKey := makeKey(&a)
|
actualKey := makeKey(&a)
|
||||||
|
|
||||||
metadata := a.Metadata.(pkg.JavaArchive)
|
metadata := a.Metadata.(pkg.JavaArchive)
|
||||||
@ -1493,7 +1490,7 @@ func Test_deterministicMatchingPomProperties(t *testing.T) {
|
|||||||
t.Run(test.fixture, func(t *testing.T) {
|
t.Run(test.fixture, func(t *testing.T) {
|
||||||
fixturePath := generateJavaMetadataJarFixture(t, test.fixture, "jar")
|
fixturePath := generateJavaMetadataJarFixture(t, test.fixture, "jar")
|
||||||
|
|
||||||
for i := 0; i < 5; i++ {
|
for range 5 {
|
||||||
func() {
|
func() {
|
||||||
fixture, err := os.Open(fixturePath)
|
fixture, err := os.Open(fixturePath)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@ -58,14 +58,14 @@ func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this is a new key-value pair
|
// this is a new key-value pair
|
||||||
idx := strings.Index(line, ":")
|
before, after, ok := strings.Cut(line, ":")
|
||||||
if idx == -1 {
|
if !ok {
|
||||||
log.Debugf("java manifest %q: unable to split java manifest key-value pairs: %q", path, line)
|
log.Debugf("java manifest %q: unable to split java manifest key-value pairs: %q", path, line)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
key := strings.TrimSpace(line[0:idx])
|
key := strings.TrimSpace(before)
|
||||||
value := strings.TrimSpace(line[idx+1:])
|
value := strings.TrimSpace(after)
|
||||||
|
|
||||||
if key == "" {
|
if key == "" {
|
||||||
// don't attempt to add new keys or sections unless there is a non-empty key
|
// don't attempt to add new keys or sections unless there is a non-empty key
|
||||||
|
|||||||
@ -446,7 +446,7 @@ func Test_resolveLicenses(t *testing.T) {
|
|||||||
require.Equal(t, "child-one", child1.Name)
|
require.Equal(t, "child-one", child1.Name)
|
||||||
|
|
||||||
got := child1.Licenses.ToSlice()
|
got := child1.Licenses.ToSlice()
|
||||||
for i := 0; i < len(got); i++ {
|
for i := range got {
|
||||||
// ignore locations, just check license text
|
// ignore locations, just check license text
|
||||||
(&got[i]).Locations = file.LocationSet{}
|
(&got[i]).Locations = file.LocationSet{}
|
||||||
}
|
}
|
||||||
@ -810,7 +810,7 @@ func expectedTransientPackageData() expected {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pkgs := make([]pkg.Package, len(allPackages))
|
pkgs := make([]pkg.Package, len(allPackages))
|
||||||
for i := 0; i < len(allPackages); i++ {
|
for i := range allPackages {
|
||||||
pkgs[i] = *allPackages[i]
|
pkgs[i] = *allPackages[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-viper/mapstructure/v2"
|
"github.com/go-viper/mapstructure/v2"
|
||||||
@ -95,7 +96,7 @@ func (p *person) UnmarshalJSON(b []byte) error {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// it's a map that may contain fields of various data types (not just strings)
|
// it's a map that may contain fields of various data types (not just strings)
|
||||||
var fields map[string]interface{}
|
var fields map[string]any
|
||||||
if err := json.Unmarshal(b, &fields); err != nil {
|
if err := json.Unmarshal(b, &fields); err != nil {
|
||||||
return fmt.Errorf("unable to parse package.json author: %w", err)
|
return fmt.Errorf("unable to parse package.json author: %w", err)
|
||||||
}
|
}
|
||||||
@ -210,12 +211,7 @@ func licensesFromJSON(b []byte) ([]npmPackageLicense, error) {
|
|||||||
var filepathSeparator = regexp.MustCompile(`[\\/]`)
|
var filepathSeparator = regexp.MustCompile(`[\\/]`)
|
||||||
|
|
||||||
func pathContainsNodeModulesDirectory(p string) bool {
|
func pathContainsNodeModulesDirectory(p string) bool {
|
||||||
for _, subPath := range filepathSeparator.Split(p, -1) {
|
return slices.Contains(filepathSeparator.Split(p, -1), "node_modules")
|
||||||
if subPath == "node_modules" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *people) UnmarshalJSON(b []byte) error {
|
func (p *people) UnmarshalJSON(b []byte) error {
|
||||||
@ -242,7 +238,7 @@ func (p *people) UnmarshalJSON(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try to unmarshal as an array of objects
|
// Try to unmarshal as an array of objects
|
||||||
var authorObjs []map[string]interface{}
|
var authorObjs []map[string]any
|
||||||
if err := json.Unmarshal(b, &authorObjs); err == nil {
|
if err := json.Unmarshal(b, &authorObjs); err == nil {
|
||||||
// Successfully parsed as an array of objects
|
// Successfully parsed as an array of objects
|
||||||
auths := make([]person, len(authorObjs))
|
auths := make([]person, len(authorObjs))
|
||||||
|
|||||||
@ -41,7 +41,7 @@ type pnpmV6PackageEntry struct {
|
|||||||
|
|
||||||
// pnpmV6LockYaml represents the structure of pnpm lockfiles for versions < 9.0.
|
// pnpmV6LockYaml represents the structure of pnpm lockfiles for versions < 9.0.
|
||||||
type pnpmV6LockYaml struct {
|
type pnpmV6LockYaml struct {
|
||||||
Dependencies map[string]interface{} `yaml:"dependencies"`
|
Dependencies map[string]any `yaml:"dependencies"`
|
||||||
Packages map[string]pnpmV6PackageEntry `yaml:"packages"`
|
Packages map[string]pnpmV6PackageEntry `yaml:"packages"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ type pnpmV9PackageEntry struct {
|
|||||||
// pnpmV9LockYaml represents the structure of pnpm lockfiles for versions >= 9.0.
|
// pnpmV9LockYaml represents the structure of pnpm lockfiles for versions >= 9.0.
|
||||||
type pnpmV9LockYaml struct {
|
type pnpmV9LockYaml struct {
|
||||||
LockfileVersion string `yaml:"lockfileVersion"`
|
LockfileVersion string `yaml:"lockfileVersion"`
|
||||||
Importers map[string]interface{} `yaml:"importers"` // Using interface{} for forward compatibility
|
Importers map[string]any `yaml:"importers"` // Using interface{} for forward compatibility
|
||||||
Packages map[string]pnpmV9PackageEntry `yaml:"packages"`
|
Packages map[string]pnpmV9PackageEntry `yaml:"packages"`
|
||||||
Snapshots map[string]pnpmV9SnapshotEntry `yaml:"snapshots"`
|
Snapshots map[string]pnpmV9SnapshotEntry `yaml:"snapshots"`
|
||||||
}
|
}
|
||||||
@ -214,11 +214,11 @@ func (a genericPnpmLockAdapter) parsePnpmLock(ctx context.Context, resolver file
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseVersionField extracts the version string from a dependency entry.
|
// parseVersionField extracts the version string from a dependency entry.
|
||||||
func parseVersionField(name string, info interface{}) (string, error) {
|
func parseVersionField(name string, info any) (string, error) {
|
||||||
switch v := info.(type) {
|
switch v := info.(type) {
|
||||||
case string:
|
case string:
|
||||||
return v, nil
|
return v, nil
|
||||||
case map[string]interface{}:
|
case map[string]any:
|
||||||
if ver, ok := v["version"].(string); ok {
|
if ver, ok := v["version"].(string); ok {
|
||||||
// e.g., "1.2.3(react@17.0.0)" -> "1.2.3"
|
// e.g., "1.2.3(react@17.0.0)" -> "1.2.3"
|
||||||
return strings.SplitN(ver, "(", 2)[0], nil
|
return strings.SplitN(ver, "(", 2)[0], nil
|
||||||
|
|||||||
@ -14,7 +14,7 @@ type rockspec struct {
|
|||||||
|
|
||||||
type rockspecNode struct {
|
type rockspecNode struct {
|
||||||
key string
|
key string
|
||||||
value interface{}
|
value any
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r rockspecNode) Slice() []rockspecNode {
|
func (r rockspecNode) Slice() []rockspecNode {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user