mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 10:36:45 +01:00
plumb context through catalogers (#2528)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
c5d15d1d6c
commit
cdad5e767a
@ -30,7 +30,7 @@ func NewFileDigestCatalogerTask(selection file.Selection, hashers ...crypto.Hash
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := digestsCataloger.Catalog(resolver, coordinates...)
|
result, err := digestsCataloger.Catalog(ctx, resolver, coordinates...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to catalog file digests: %w", err)
|
return fmt.Errorf("unable to catalog file digests: %w", err)
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ func NewFileMetadataCatalogerTask(selection file.Selection) Task {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := metadataCataloger.Catalog(resolver, coordinates...)
|
result, err := metadataCataloger.Catalog(ctx, resolver, coordinates...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ func NewFileContentCatalogerTask(cfg filecontent.Config) Task {
|
|||||||
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
||||||
accessor := builder.(sbomsync.Accessor)
|
accessor := builder.(sbomsync.Accessor)
|
||||||
|
|
||||||
result, err := cat.Catalog(resolver)
|
result, err := cat.Catalog(ctx, resolver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,7 +100,7 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string
|
|||||||
|
|
||||||
t := bus.StartCatalogerTask(info, -1, "")
|
t := bus.StartCatalogerTask(info, -1, "")
|
||||||
|
|
||||||
pkgs, relationships, err := c.Catalog(resolver)
|
pkgs, relationships, err := c.Catalog(ctx, resolver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to catalog packages with %q: %w", c.Name(), err)
|
return fmt.Errorf("unable to catalog packages with %q: %w", c.Name(), err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package syft
|
package syft
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ func (d dummyCataloger) Name() string {
|
|||||||
return d.name
|
return d.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d dummyCataloger) Catalog(_ file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
func (d dummyCataloger) Catalog(_ context.Context, _ file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package filecontent
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -42,7 +43,7 @@ func NewCataloger(cfg Config) *Cataloger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Cataloger) Catalog(resolver file.Resolver) (map[file.Coordinates]string, error) {
|
func (i *Cataloger) Catalog(_ context.Context, resolver file.Resolver) (map[file.Coordinates]string, error) {
|
||||||
results := make(map[file.Coordinates]string)
|
results := make(map[file.Coordinates]string)
|
||||||
var locations []file.Location
|
var locations []file.Location
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package filecontent
|
package filecontent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -73,7 +74,7 @@ func TestContentsCataloger(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
resolver := file.NewMockResolverForPaths(test.files...)
|
resolver := file.NewMockResolverForPaths(test.files...)
|
||||||
actual, err := c.Catalog(resolver)
|
actual, err := c.Catalog(context.Background(), resolver)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, test.expected, actual, "mismatched contents")
|
assert.Equal(t, test.expected, actual, "mismatched contents")
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package filedigest
|
package filedigest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -29,12 +30,12 @@ func NewCataloger(hashes []crypto.Hash) *Cataloger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Cataloger) Catalog(resolver file.Resolver, coordinates ...file.Coordinates) (map[file.Coordinates][]file.Digest, error) {
|
func (i *Cataloger) Catalog(ctx context.Context, resolver file.Resolver, coordinates ...file.Coordinates) (map[file.Coordinates][]file.Digest, error) {
|
||||||
results := make(map[file.Coordinates][]file.Digest)
|
results := make(map[file.Coordinates][]file.Digest)
|
||||||
var locations []file.Location
|
var locations []file.Location
|
||||||
|
|
||||||
if len(coordinates) == 0 {
|
if len(coordinates) == 0 {
|
||||||
locations = intCataloger.AllRegularFiles(resolver)
|
locations = intCataloger.AllRegularFiles(ctx, resolver)
|
||||||
} else {
|
} else {
|
||||||
for _, c := range coordinates {
|
for _, c := range coordinates {
|
||||||
locs, err := resolver.FilesByPath(c.RealPath)
|
locs, err := resolver.FilesByPath(c.RealPath)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package filedigest
|
package filedigest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -82,7 +83,7 @@ func TestDigestsCataloger(t *testing.T) {
|
|||||||
resolver, err := src.FileResolver(source.SquashedScope)
|
resolver, err := src.FileResolver(source.SquashedScope)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
actual, err := c.Catalog(resolver)
|
actual, err := c.Catalog(context.Background(), resolver)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, test.expected, actual, "mismatched digests")
|
assert.Equal(t, test.expected, actual, "mismatched digests")
|
||||||
@ -138,7 +139,7 @@ func TestDigestsCataloger_MixFileTypes(t *testing.T) {
|
|||||||
t.Run(test.path, func(t *testing.T) {
|
t.Run(test.path, func(t *testing.T) {
|
||||||
c := NewCataloger([]crypto.Hash{crypto.MD5})
|
c := NewCataloger([]crypto.Hash{crypto.MD5})
|
||||||
|
|
||||||
actual, err := c.Catalog(resolver)
|
actual, err := c.Catalog(context.Background(), resolver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not catalog: %+v", err)
|
t.Fatalf("could not catalog: %+v", err)
|
||||||
}
|
}
|
||||||
@ -195,7 +196,7 @@ func TestFileDigestCataloger_GivenCoordinates(t *testing.T) {
|
|||||||
|
|
||||||
// note: an important difference between this test and the previous is that this test is using a list
|
// note: an important difference between this test and the previous is that this test is using a list
|
||||||
// of specific coordinates to catalog
|
// of specific coordinates to catalog
|
||||||
actual, err := c.Catalog(resolver, l.Coordinates)
|
actual, err := c.Catalog(context.Background(), resolver, l.Coordinates)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, actual, 1)
|
require.Len(t, actual, 1)
|
||||||
|
|
||||||
|
|||||||
@ -19,10 +19,10 @@ func NewCataloger() *Cataloger {
|
|||||||
return &Cataloger{}
|
return &Cataloger{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Cataloger) Catalog(resolver file.Resolver, coordinates ...file.Coordinates) (map[file.Coordinates]file.Metadata, error) {
|
func (i *Cataloger) Catalog(ctx context.Context, resolver file.Resolver, coordinates ...file.Coordinates) (map[file.Coordinates]file.Metadata, error) {
|
||||||
results := make(map[file.Coordinates]file.Metadata)
|
results := make(map[file.Coordinates]file.Metadata)
|
||||||
var locations <-chan file.Location
|
var locations <-chan file.Location
|
||||||
ctx, cancel := context.WithCancel(context.TODO())
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if len(coordinates) == 0 {
|
if len(coordinates) == 0 {
|
||||||
locations = resolver.AllLocations(ctx)
|
locations = resolver.AllLocations(ctx)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package filemetadata
|
package filemetadata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ func TestFileMetadataCataloger(t *testing.T) {
|
|||||||
resolver, err := src.FileResolver(source.SquashedScope)
|
resolver, err := src.FileResolver(source.SquashedScope)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
actual, err := c.Catalog(resolver)
|
actual, err := c.Catalog(context.Background(), resolver)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@ -196,7 +197,7 @@ func TestFileMetadataCataloger_GivenCoordinates(t *testing.T) {
|
|||||||
|
|
||||||
// note: an important difference between this test and the previous is that this test is using a list
|
// note: an important difference between this test and the previous is that this test is using a list
|
||||||
// of specific coordinates to catalog
|
// of specific coordinates to catalog
|
||||||
actual, err := c.Catalog(resolver, l.Coordinates)
|
actual, err := c.Catalog(context.Background(), resolver, l.Coordinates)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, actual, 1)
|
require.Len(t, actual, 1)
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,8 @@ import (
|
|||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AllRegularFiles(resolver file.Resolver) (locations []file.Location) {
|
func AllRegularFiles(ctx context.Context, resolver file.Resolver) (locations []file.Location) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
for location := range resolver.AllLocations(ctx) {
|
for location := range resolver.AllLocations(ctx) {
|
||||||
resolvedLocations, err := resolver.FilesByPath(location.RealPath)
|
resolvedLocations, err := resolver.FilesByPath(location.RealPath)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
@ -54,7 +55,7 @@ func Test_allRegularFiles(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
resolver := tt.setup()
|
resolver := tt.setup()
|
||||||
locations := AllRegularFiles(resolver)
|
locations := AllRegularFiles(context.Background(), resolver)
|
||||||
realLocations := strset.New()
|
realLocations := strset.New()
|
||||||
virtualLocations := strset.New()
|
virtualLocations := strset.New()
|
||||||
for _, l := range locations {
|
for _, l := range locations {
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/anchore/syft/syft/artifact"
|
"github.com/anchore/syft/syft/artifact"
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
)
|
)
|
||||||
@ -12,5 +14,5 @@ type Cataloger interface {
|
|||||||
// Name returns a string that uniquely describes a cataloger
|
// Name returns a string that uniquely describes a cataloger
|
||||||
Name() string
|
Name() string
|
||||||
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing the catalog source.
|
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing the catalog source.
|
||||||
Catalog(resolver file.Resolver) ([]Package, []artifact.Relationship, error)
|
Catalog(context.Context, file.Resolver) ([]Package, []artifact.Relationship, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package alpine
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"path"
|
"path"
|
||||||
@ -34,7 +35,7 @@ type parsedData struct {
|
|||||||
// information on specific fields, see https://wiki.alpinelinux.org/wiki/Apk_spec.
|
// information on specific fields, see https://wiki.alpinelinux.org/wiki/Apk_spec.
|
||||||
//
|
//
|
||||||
//nolint:funlen,gocognit
|
//nolint:funlen,gocognit
|
||||||
func parseApkDB(resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseApkDB(_ context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|
||||||
var apks []parsedData
|
var apks []parsedData
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package alpine
|
package alpine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -64,7 +65,7 @@ func TestExtraFileAttributes(t *testing.T) {
|
|||||||
fixturePath := "test-fixtures/extra-file-attributes"
|
fixturePath := "test-fixtures/extra-file-attributes"
|
||||||
lrc := newLocationReadCloser(t, fixturePath)
|
lrc := newLocationReadCloser(t, fixturePath)
|
||||||
|
|
||||||
pkgs, _, err := parseApkDB(nil, new(generic.Environment), lrc)
|
pkgs, _, err := parseApkDB(context.Background(), nil, new(generic.Environment), lrc)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
require.Len(t, pkgs, 1)
|
require.Len(t, pkgs, 1)
|
||||||
metadata := pkgs[0].Metadata.(pkg.ApkDBEntry)
|
metadata := pkgs[0].Metadata.(pkg.ApkDBEntry)
|
||||||
@ -1055,7 +1056,7 @@ func TestPackageDbDependenciesByParse(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Cleanup(func() { require.NoError(t, f.Close()) })
|
t.Cleanup(func() { require.NoError(t, f.Close()) })
|
||||||
|
|
||||||
pkgs, relationships, err := parseApkDB(nil, nil, file.LocationReadCloser{
|
pkgs, relationships, err := parseApkDB(context.Background(), nil, nil, file.LocationReadCloser{
|
||||||
Location: file.NewLocation(test.fixture),
|
Location: file.NewLocation(test.fixture),
|
||||||
ReadCloser: f,
|
ReadCloser: f,
|
||||||
})
|
})
|
||||||
@ -1146,7 +1147,7 @@ func Test_parseApkDB_expectedPkgNames(t *testing.T) {
|
|||||||
fixturePath := filepath.Join("test-fixtures", test.fixture)
|
fixturePath := filepath.Join("test-fixtures", test.fixture)
|
||||||
lrc := newLocationReadCloser(t, fixturePath)
|
lrc := newLocationReadCloser(t, fixturePath)
|
||||||
|
|
||||||
pkgs, _, err := parseApkDB(nil, new(generic.Environment), lrc)
|
pkgs, _, err := parseApkDB(context.Background(), nil, new(generic.Environment), lrc)
|
||||||
test.wantErr(t, err)
|
test.wantErr(t, err)
|
||||||
|
|
||||||
names := toPackageNames(pkgs)
|
names := toPackageNames(pkgs)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package arch
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -36,7 +37,7 @@ type parsedData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseAlpmDB parses the arch linux pacman database flat-files and returns the packages and relationships found within.
|
// parseAlpmDB parses the arch linux pacman database flat-files and returns the packages and relationships found within.
|
||||||
func parseAlpmDB(resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseAlpmDB(_ context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
data, err := parseAlpmDBEntry(reader)
|
data, err := parseAlpmDBEntry(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|||||||
@ -4,6 +4,7 @@ Package binary provides a concrete Cataloger implementations for surfacing possi
|
|||||||
package binary
|
package binary
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
@ -55,7 +56,7 @@ func (c Cataloger) Name() string {
|
|||||||
|
|
||||||
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages
|
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages
|
||||||
// after analyzing the catalog source.
|
// after analyzing the catalog source.
|
||||||
func (c Cataloger) Catalog(resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
func (c Cataloger) Catalog(_ context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var packages []pkg.Package
|
var packages []pkg.Package
|
||||||
var relationships []artifact.Relationship
|
var relationships []artifact.Relationship
|
||||||
|
|
||||||
|
|||||||
@ -902,7 +902,7 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
|
|||||||
resolver, err := src.FileResolver(source.SquashedScope)
|
resolver, err := src.FileResolver(source.SquashedScope)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
packages, _, err := c.Catalog(resolver)
|
packages, _, err := c.Catalog(context.Background(), resolver)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Len(t, packages, 1, "mismatched package count")
|
require.Len(t, packages, 1, "mismatched package count")
|
||||||
@ -942,7 +942,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases_Image(t *testing.T) {
|
|||||||
resolver, err := src.FileResolver(source.SquashedScope)
|
resolver, err := src.FileResolver(source.SquashedScope)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
packages, _, err := c.Catalog(resolver)
|
packages, _, err := c.Catalog(context.Background(), resolver)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for _, p := range packages {
|
for _, p := range packages {
|
||||||
@ -972,7 +972,7 @@ func TestClassifierCataloger_DefaultClassifiers_NegativeCases(t *testing.T) {
|
|||||||
resolver, err := src.FileResolver(source.SquashedScope)
|
resolver, err := src.FileResolver(source.SquashedScope)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
actualResults, _, err := c.Catalog(resolver)
|
actualResults, _, err := c.Catalog(context.Background(), resolver)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 0, len(actualResults))
|
assert.Equal(t, 0, len(actualResults))
|
||||||
}
|
}
|
||||||
@ -1086,7 +1086,7 @@ func Test_Cataloger_CustomClassifiers(t *testing.T) {
|
|||||||
resolver, err := src.FileResolver(source.SquashedScope)
|
resolver, err := src.FileResolver(source.SquashedScope)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
packages, _, err := c.Catalog(resolver)
|
packages, _, err := c.Catalog(context.Background(), resolver)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
if test.expected == nil {
|
if test.expected == nil {
|
||||||
@ -1252,7 +1252,7 @@ func Test_Cataloger_ResilientToErrors(t *testing.T) {
|
|||||||
c := NewCataloger(DefaultCatalogerConfig())
|
c := NewCataloger(DefaultCatalogerConfig())
|
||||||
|
|
||||||
resolver := &panicyResolver{}
|
resolver := &panicyResolver{}
|
||||||
_, _, err := c.Catalog(resolver)
|
_, _, err := c.Catalog(context.Background(), resolver)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, resolver.searchCalled)
|
assert.True(t, resolver.searchCalled)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package cpp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -20,7 +21,7 @@ type Conanfile struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseConanfile is a parser function for conanfile.txt contents, returning all packages discovered.
|
// parseConanfile is a parser function for conanfile.txt contents, returning all packages discovered.
|
||||||
func parseConanfile(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseConanfile(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
r := bufio.NewReader(reader)
|
r := bufio.NewReader(reader)
|
||||||
inRequirements := false
|
inRequirements := false
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package cpp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -78,7 +79,7 @@ func parseFullRequiresLine(line string, reader file.LocationReadCloser, pkgs *[]
|
|||||||
// The conaninfo.txt gives:
|
// The conaninfo.txt gives:
|
||||||
// - package requires (full_requires)
|
// - package requires (full_requires)
|
||||||
// - recipe revision (recipe_hash)
|
// - recipe revision (recipe_hash)
|
||||||
func parseConaninfo(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseConaninfo(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
// First set the base package info by checking the relative path
|
// First set the base package info by checking the relative path
|
||||||
fullFilePath := string(reader.Location.LocationData.Reference().RealPath)
|
fullFilePath := string(reader.Location.LocationData.Reference().RealPath)
|
||||||
if len(fullFilePath) == 0 {
|
if len(fullFilePath) == 0 {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package cpp
|
package cpp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ type conanLock struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseConanlock is a parser function for conan.lock contents, returning all packages discovered.
|
// parseConanlock is a parser function for conan.lock contents, returning all packages discovered.
|
||||||
func parseConanlock(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseConanlock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
var cl conanLock
|
var cl conanLock
|
||||||
if err := json.NewDecoder(reader).Decode(&cl); err != nil {
|
if err := json.NewDecoder(reader).Decode(&cl); err != nil {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package dart
|
package dart
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
@ -55,7 +56,7 @@ func (p *pubspecLockDescription) UnmarshalYAML(value *yaml.Node) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePubspecLock(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parsePubspecLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
|
|
||||||
dec := yaml.NewDecoder(reader)
|
dec := yaml.NewDecoder(reader)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package debian
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -25,7 +26,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// parseDpkgDB reads a dpkg database "status" file (and surrounding data files) and returns the packages and relationships found.
|
// parseDpkgDB reads a dpkg database "status" file (and surrounding data files) and returns the packages and relationships found.
|
||||||
func parseDpkgDB(resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseDpkgDB(_ context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
metadata, err := parseDpkgStatus(reader)
|
metadata, err := parseDpkgStatus(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to catalog dpkg DB=%q: %w", reader.RealPath, err)
|
return nil, nil, fmt.Errorf("unable to catalog dpkg DB=%q: %w", reader.RealPath, err)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package debian
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -519,7 +520,7 @@ func Test_associateRelationships(t *testing.T) {
|
|||||||
|
|
||||||
reader := file.NewLocationReadCloser(file.NewLocation(tt.fixture), f)
|
reader := file.NewLocationReadCloser(file.NewLocation(tt.fixture), f)
|
||||||
|
|
||||||
pkgs, relationships, err := parseDpkgDB(nil, &generic.Environment{}, reader)
|
pkgs, relationships, err := parseDpkgDB(context.Background(), nil, &generic.Environment{}, reader)
|
||||||
require.NotEmpty(t, pkgs)
|
require.NotEmpty(t, pkgs)
|
||||||
require.NotEmpty(t, relationships)
|
require.NotEmpty(t, relationships)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package dotnet
|
package dotnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@ -38,7 +39,7 @@ type dotnetDepsLibrary struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//nolint:funlen
|
//nolint:funlen
|
||||||
func parseDotnetDeps(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseDotnetDeps(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
var pkgMap = make(map[string]pkg.Package)
|
var pkgMap = make(map[string]pkg.Package)
|
||||||
var relationships []artifact.Relationship
|
var relationships []artifact.Relationship
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package dotnet
|
package dotnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -18,7 +19,7 @@ import (
|
|||||||
|
|
||||||
var _ generic.Parser = parseDotnetPortableExecutable
|
var _ generic.Parser = parseDotnetPortableExecutable
|
||||||
|
|
||||||
func parseDotnetPortableExecutable(_ file.Resolver, _ *generic.Environment, f file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseDotnetPortableExecutable(_ context.Context, _ file.Resolver, _ *generic.Environment, f file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
by, err := io.ReadAll(f)
|
by, err := io.ReadAll(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to read file: %w", err)
|
return nil, nil, fmt.Errorf("unable to read file: %w", err)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package elixir
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -20,7 +21,7 @@ var _ generic.Parser = parseMixLock
|
|||||||
var mixLockDelimiter = regexp.MustCompile(`[%{}\n" ,:]+`)
|
var mixLockDelimiter = regexp.MustCompile(`[%{}\n" ,:]+`)
|
||||||
|
|
||||||
// parseMixLock parses a mix.lock and returns the discovered Elixir packages.
|
// parseMixLock parses a mix.lock and returns the discovered Elixir packages.
|
||||||
func parseMixLock(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseMixLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
r := bufio.NewReader(reader)
|
r := bufio.NewReader(reader)
|
||||||
|
|
||||||
var packages []pkg.Package
|
var packages []pkg.Package
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package erlang
|
package erlang
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
"github.com/anchore/syft/syft/artifact"
|
"github.com/anchore/syft/syft/artifact"
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
@ -11,7 +13,7 @@ import (
|
|||||||
// parseRebarLock parses a rebar.lock and returns the discovered Elixir packages.
|
// parseRebarLock parses a rebar.lock and returns the discovered Elixir packages.
|
||||||
//
|
//
|
||||||
//nolint:funlen
|
//nolint:funlen
|
||||||
func parseRebarLock(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseRebarLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
doc, err := parseErlang(reader)
|
doc, err := parseErlang(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package generic
|
package generic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal"
|
"github.com/anchore/syft/internal"
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
"github.com/anchore/syft/syft/artifact"
|
"github.com/anchore/syft/syft/artifact"
|
||||||
@ -104,7 +106,7 @@ func (c *Cataloger) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing the catalog source.
|
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing the catalog source.
|
||||||
func (c *Cataloger) Catalog(resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
func (c *Cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var packages []pkg.Package
|
var packages []pkg.Package
|
||||||
var relationships []artifact.Relationship
|
var relationships []artifact.Relationship
|
||||||
|
|
||||||
@ -126,7 +128,7 @@ func (c *Cataloger) Catalog(resolver file.Resolver) ([]pkg.Package, []artifact.R
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
discoveredPackages, discoveredRelationships, err := parser(resolver, &env, file.NewLocationReadCloser(location, contentReader))
|
discoveredPackages, discoveredRelationships, err := parser(ctx, resolver, &env, file.NewLocationReadCloser(location, contentReader))
|
||||||
internal.CloseAndLogError(contentReader, location.AccessPath)
|
internal.CloseAndLogError(contentReader, location.AccessPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithFields("location", location.RealPath, "error", err).Warnf("cataloger failed")
|
logger.WithFields("location", location.RealPath, "error", err).Warnf("cataloger failed")
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package generic
|
package generic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
@ -15,7 +16,7 @@ import (
|
|||||||
|
|
||||||
func Test_Cataloger(t *testing.T) {
|
func Test_Cataloger(t *testing.T) {
|
||||||
allParsedPaths := make(map[string]bool)
|
allParsedPaths := make(map[string]bool)
|
||||||
parser := func(resolver file.Resolver, env *Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
parser := func(_ context.Context, resolver file.Resolver, env *Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
allParsedPaths[reader.Path()] = true
|
allParsedPaths[reader.Path()] = true
|
||||||
contents, err := io.ReadAll(reader)
|
contents, err := io.ReadAll(reader)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -45,7 +46,7 @@ func Test_Cataloger(t *testing.T) {
|
|||||||
WithParserByPath(parser, "test-fixtures/another-path.txt", "test-fixtures/last/path.txt").
|
WithParserByPath(parser, "test-fixtures/another-path.txt", "test-fixtures/last/path.txt").
|
||||||
WithParserByGlobs(parser, "**/a-path.txt", "**/empty.txt")
|
WithParserByGlobs(parser, "**/a-path.txt", "**/empty.txt")
|
||||||
|
|
||||||
actualPkgs, relationships, err := cataloger.Catalog(resolver)
|
actualPkgs, relationships, err := cataloger.Catalog(context.Background(), resolver)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
expectedPkgs := make(map[string]pkg.Package)
|
expectedPkgs := make(map[string]pkg.Package)
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package generic
|
package generic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/anchore/syft/syft/artifact"
|
"github.com/anchore/syft/syft/artifact"
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
"github.com/anchore/syft/syft/linux"
|
"github.com/anchore/syft/syft/linux"
|
||||||
@ -11,4 +13,4 @@ type Environment struct {
|
|||||||
LinuxRelease *linux.Release
|
LinuxRelease *linux.Release
|
||||||
}
|
}
|
||||||
|
|
||||||
type Parser func(file.Resolver, *Environment, file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error)
|
type Parser func(context.Context, file.Resolver, *Environment, file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package gentoo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -24,7 +25,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// parses individual CONTENTS files from the portage flat-file store (e.g. /var/db/pkg/*/*/CONTENTS).
|
// parses individual CONTENTS files from the portage flat-file store (e.g. /var/db/pkg/*/*/CONTENTS).
|
||||||
func parsePortageContents(resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parsePortageContents(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
cpvMatch := cpvRe.FindStringSubmatch(reader.Location.RealPath)
|
cpvMatch := cpvRe.FindStringSubmatch(reader.Location.RealPath)
|
||||||
if cpvMatch == nil {
|
if cpvMatch == nil {
|
||||||
return nil, nil, fmt.Errorf("failed to match package and version in %s", reader.Location.RealPath)
|
return nil, nil, fmt.Errorf("failed to match package and version in %s", reader.Location.RealPath)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package githubactions
|
package githubactions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ type compositeActionRunsDef struct {
|
|||||||
Steps []stepDef `yaml:"steps"`
|
Steps []stepDef `yaml:"steps"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCompositeActionForActionUsage(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseCompositeActionForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
contents, err := io.ReadAll(reader)
|
contents, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to read yaml composite action file: %w", err)
|
return nil, nil, fmt.Errorf("unable to read yaml composite action file: %w", err)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package githubactions
|
package githubactions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ type stepDef struct {
|
|||||||
} `yaml:"with"`
|
} `yaml:"with"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseWorkflowForWorkflowUsage(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseWorkflowForWorkflowUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
contents, err := io.ReadAll(reader)
|
contents, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", err)
|
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", err)
|
||||||
@ -61,7 +62,7 @@ func parseWorkflowForWorkflowUsage(_ file.Resolver, _ *generic.Environment, read
|
|||||||
return pkgs.Sorted(), nil, nil
|
return pkgs.Sorted(), nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseWorkflowForActionUsage(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseWorkflowForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
contents, err := io.ReadAll(reader)
|
contents, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", err)
|
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", err)
|
||||||
|
|||||||
@ -4,6 +4,7 @@ Package golang provides a concrete Cataloger implementation relating to packages
|
|||||||
package golang
|
package golang
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@ -53,8 +54,8 @@ func (p *progressingCataloger) Name() string {
|
|||||||
return p.cataloger.Name()
|
return p.cataloger.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *progressingCataloger) Catalog(resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
func (p *progressingCataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
pkgs, relationships, err := p.cataloger.Catalog(resolver)
|
pkgs, relationships, err := p.cataloger.Catalog(ctx, resolver)
|
||||||
goCompilerPkgs := []pkg.Package{}
|
goCompilerPkgs := []pkg.Package{}
|
||||||
totalLocations := file.NewLocationSet()
|
totalLocations := file.NewLocationSet()
|
||||||
for _, goPkg := range pkgs {
|
for _, goPkg := range pkgs {
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package golang
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"debug/macho"
|
"debug/macho"
|
||||||
"debug/pe"
|
"debug/pe"
|
||||||
@ -48,7 +49,7 @@ type goBinaryCataloger struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseGoBinary catalogs packages found in the "buildinfo" section of a binary built by the go compiler.
|
// parseGoBinary catalogs packages found in the "buildinfo" section of a binary built by the go compiler.
|
||||||
func (c *goBinaryCataloger) parseGoBinary(resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func (c *goBinaryCataloger) parseGoBinary(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
|
|
||||||
unionReader, err := unionreader.GetUnionReader(reader.ReadCloser)
|
unionReader, err := unionreader.GetUnionReader(reader.ReadCloser)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package golang
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"sort"
|
"sort"
|
||||||
@ -23,7 +24,7 @@ type goModCataloger struct {
|
|||||||
// parseGoModFile takes a go.mod and lists all packages discovered.
|
// parseGoModFile takes a go.mod and lists all packages discovered.
|
||||||
//
|
//
|
||||||
//nolint:funlen
|
//nolint:funlen
|
||||||
func (c *goModCataloger) parseGoModFile(resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
packages := make(map[string]pkg.Package)
|
packages := make(map[string]pkg.Package)
|
||||||
|
|
||||||
contents, err := io.ReadAll(reader)
|
contents, err := io.ReadAll(reader)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package haskell
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -16,7 +17,7 @@ import (
|
|||||||
var _ generic.Parser = parseCabalFreeze
|
var _ generic.Parser = parseCabalFreeze
|
||||||
|
|
||||||
// parseCabalFreeze is a parser function for cabal.project.freeze contents, returning all packages discovered.
|
// parseCabalFreeze is a parser function for cabal.project.freeze contents, returning all packages discovered.
|
||||||
func parseCabalFreeze(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseCabalFreeze(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
r := bufio.NewReader(reader)
|
r := bufio.NewReader(reader)
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
for {
|
for {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package haskell
|
package haskell
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
@ -39,7 +40,7 @@ type completedSnapshot struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseStackLock is a parser function for stack.yaml.lock contents, returning all packages discovered.
|
// parseStackLock is a parser function for stack.yaml.lock contents, returning all packages discovered.
|
||||||
func parseStackLock(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseStackLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
bytes, err := io.ReadAll(reader)
|
bytes, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("failed to load stack.yaml.lock file: %w", err)
|
return nil, nil, fmt.Errorf("failed to load stack.yaml.lock file: %w", err)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package haskell
|
package haskell
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ type stackYaml struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseStackYaml is a parser function for stack.yaml contents, returning all packages discovered.
|
// parseStackYaml is a parser function for stack.yaml contents, returning all packages discovered.
|
||||||
func parseStackYaml(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseStackYaml(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
bytes, err := io.ReadAll(reader)
|
bytes, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("failed to load stack.yaml file: %w", err)
|
return nil, nil, fmt.Errorf("failed to load stack.yaml file: %w", err)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package pkgtest
|
package pkgtest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -221,7 +222,7 @@ func (p *CatalogTester) IgnoreUnfulfilledPathResponses(paths ...string) *Catalog
|
|||||||
|
|
||||||
func (p *CatalogTester) TestParser(t *testing.T, parser generic.Parser) {
|
func (p *CatalogTester) TestParser(t *testing.T, parser generic.Parser) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
pkgs, relationships, err := parser(p.resolver, p.env, p.reader)
|
pkgs, relationships, err := parser(context.Background(), p.resolver, p.env, p.reader)
|
||||||
p.wantErr(t, err)
|
p.wantErr(t, err)
|
||||||
p.assertPkgs(t, pkgs, relationships)
|
p.assertPkgs(t, pkgs, relationships)
|
||||||
}
|
}
|
||||||
@ -231,7 +232,7 @@ func (p *CatalogTester) TestCataloger(t *testing.T, cataloger pkg.Cataloger) {
|
|||||||
|
|
||||||
resolver := NewObservingResolver(p.resolver)
|
resolver := NewObservingResolver(p.resolver)
|
||||||
|
|
||||||
pkgs, relationships, err := cataloger.Catalog(resolver)
|
pkgs, relationships, err := cataloger.Catalog(context.Background(), resolver)
|
||||||
|
|
||||||
// this is a minimum set, the resolver may return more that just this list
|
// this is a minimum set, the resolver may return more that just this list
|
||||||
for _, path := range p.expectedPathResponses {
|
for _, path := range p.expectedPathResponses {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package java
|
package java
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -59,14 +60,14 @@ func newGenericArchiveParserAdapter(cfg ArchiveCatalogerConfig) genericArchivePa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseJavaArchive is a parser function for java archive contents, returning all Java libraries and nested archives.
|
// parseJavaArchive is a parser function for java archive contents, returning all Java libraries and nested archives.
|
||||||
func (gap genericArchiveParserAdapter) parseJavaArchive(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func (gap genericArchiveParserAdapter) parseJavaArchive(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
parser, cleanupFn, err := newJavaArchiveParser(reader, true, gap.cfg)
|
parser, cleanupFn, err := newJavaArchiveParser(reader, true, gap.cfg)
|
||||||
// note: even on error, we should always run cleanup functions
|
// note: even on error, we should always run cleanup functions
|
||||||
defer cleanupFn()
|
defer cleanupFn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return parser.parse()
|
return parser.parse(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// uniquePkgKey creates a unique string to identify the given package.
|
// uniquePkgKey creates a unique string to identify the given package.
|
||||||
@ -106,19 +107,19 @@ func newJavaArchiveParser(reader file.LocationReadCloser, detectNested bool, cfg
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse the loaded archive and return all packages found.
|
// parse the loaded archive and return all packages found.
|
||||||
func (j *archiveParser) parse() ([]pkg.Package, []artifact.Relationship, error) {
|
func (j *archiveParser) parse(ctx context.Context) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
var relationships []artifact.Relationship
|
var relationships []artifact.Relationship
|
||||||
|
|
||||||
// find the parent package from the java manifest
|
// find the parent package from the java manifest
|
||||||
parentPkg, err := j.discoverMainPackage()
|
parentPkg, err := j.discoverMainPackage(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("could not generate package from %s: %w", j.location, err)
|
return nil, nil, fmt.Errorf("could not generate package from %s: %w", j.location, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// find aux packages from pom.properties/pom.xml and potentially modify the existing parentPkg
|
// find aux packages from pom.properties/pom.xml and potentially modify the existing parentPkg
|
||||||
// NOTE: we cannot generate sha1 digests from packages discovered via pom.properties/pom.xml
|
// NOTE: we cannot generate sha1 digests from packages discovered via pom.properties/pom.xml
|
||||||
auxPkgs, err := j.discoverPkgsFromAllMavenFiles(parentPkg)
|
auxPkgs, err := j.discoverPkgsFromAllMavenFiles(ctx, parentPkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -126,7 +127,7 @@ func (j *archiveParser) parse() ([]pkg.Package, []artifact.Relationship, error)
|
|||||||
|
|
||||||
if j.detectNested {
|
if j.detectNested {
|
||||||
// find nested java archive packages
|
// find nested java archive packages
|
||||||
nestedPkgs, nestedRelationships, err := j.discoverPkgsFromNestedArchives(parentPkg)
|
nestedPkgs, nestedRelationships, err := j.discoverPkgsFromNestedArchives(ctx, parentPkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -156,7 +157,7 @@ func (j *archiveParser) parse() ([]pkg.Package, []artifact.Relationship, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// discoverMainPackage parses the root Java manifest used as the parent package to all discovered nested packages.
|
// discoverMainPackage parses the root Java manifest used as the parent package to all discovered nested packages.
|
||||||
func (j *archiveParser) discoverMainPackage() (*pkg.Package, error) {
|
func (j *archiveParser) discoverMainPackage(ctx context.Context) (*pkg.Package, error) {
|
||||||
// search and parse java manifest files
|
// search and parse java manifest files
|
||||||
manifestMatches := j.fileManifest.GlobMatch(false, manifestGlob)
|
manifestMatches := j.fileManifest.GlobMatch(false, manifestGlob)
|
||||||
if len(manifestMatches) > 1 {
|
if len(manifestMatches) > 1 {
|
||||||
@ -186,7 +187,7 @@ func (j *archiveParser) discoverMainPackage() (*pkg.Package, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
licenses, name, version, err := j.parseLicenses(manifest)
|
licenses, name, version, err := j.parseLicenses(ctx, manifest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -209,7 +210,7 @@ func (j *archiveParser) discoverMainPackage() (*pkg.Package, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *archiveParser) parseLicenses(manifest *pkg.JavaManifest) ([]pkg.License, string, string, error) {
|
func (j *archiveParser) parseLicenses(ctx context.Context, manifest *pkg.JavaManifest) ([]pkg.License, string, string, error) {
|
||||||
// we use j.location because we want to associate the license declaration with where we discovered the contents in the manifest
|
// we use j.location because we want to associate the license declaration with where we discovered the contents in the manifest
|
||||||
// TODO: when we support locations of paths within archives we should start passing the specific manifest location object instead of the top jar
|
// TODO: when we support locations of paths within archives we should start passing the specific manifest location object instead of the top jar
|
||||||
licenses := pkg.NewLicensesFromLocation(j.location, selectLicenses(manifest)...)
|
licenses := pkg.NewLicensesFromLocation(j.location, selectLicenses(manifest)...)
|
||||||
@ -220,7 +221,7 @@ func (j *archiveParser) parseLicenses(manifest *pkg.JavaManifest) ([]pkg.License
|
|||||||
3. manifest
|
3. manifest
|
||||||
4. filename
|
4. filename
|
||||||
*/
|
*/
|
||||||
name, version, pomLicenses := j.guessMainPackageNameAndVersionFromPomInfo()
|
name, version, pomLicenses := j.guessMainPackageNameAndVersionFromPomInfo(ctx)
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = selectName(manifest, j.fileInfo)
|
name = selectName(manifest, j.fileInfo)
|
||||||
}
|
}
|
||||||
@ -246,24 +247,24 @@ func (j *archiveParser) parseLicenses(manifest *pkg.JavaManifest) ([]pkg.License
|
|||||||
|
|
||||||
// If we didn't find any licenses in the archive so far, we'll try again in Maven Central using groupIDFromJavaMetadata
|
// If we didn't find any licenses in the archive so far, we'll try again in Maven Central using groupIDFromJavaMetadata
|
||||||
if len(licenses) == 0 && j.cfg.UseNetwork {
|
if len(licenses) == 0 && j.cfg.UseNetwork {
|
||||||
licenses = findLicenseFromJavaMetadata(name, manifest, version, j, licenses)
|
licenses = findLicenseFromJavaMetadata(ctx, name, manifest, version, j, licenses)
|
||||||
}
|
}
|
||||||
|
|
||||||
return licenses, name, version, nil
|
return licenses, name, version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findLicenseFromJavaMetadata(name string, manifest *pkg.JavaManifest, version string, j *archiveParser, licenses []pkg.License) []pkg.License {
|
func findLicenseFromJavaMetadata(ctx context.Context, name string, manifest *pkg.JavaManifest, version string, j *archiveParser, licenses []pkg.License) []pkg.License {
|
||||||
var groupID = name
|
var groupID = name
|
||||||
if gID := groupIDFromJavaMetadata(name, pkg.JavaArchive{Manifest: manifest}); gID != "" {
|
if gID := groupIDFromJavaMetadata(name, pkg.JavaArchive{Manifest: manifest}); gID != "" {
|
||||||
groupID = gID
|
groupID = gID
|
||||||
}
|
}
|
||||||
pomLicenses := recursivelyFindLicensesFromParentPom(groupID, name, version, j.cfg)
|
pomLicenses := recursivelyFindLicensesFromParentPom(ctx, groupID, name, version, j.cfg)
|
||||||
|
|
||||||
if len(pomLicenses) == 0 {
|
if len(pomLicenses) == 0 {
|
||||||
// Try removing the last part of the groupId, as sometimes it duplicates the artifactId
|
// Try removing the last part of the groupId, as sometimes it duplicates the artifactId
|
||||||
packages := strings.Split(groupID, ".")
|
packages := strings.Split(groupID, ".")
|
||||||
groupID = strings.Join(packages[:len(packages)-1], ".")
|
groupID = strings.Join(packages[:len(packages)-1], ".")
|
||||||
pomLicenses = recursivelyFindLicensesFromParentPom(groupID, name, version, j.cfg)
|
pomLicenses = recursivelyFindLicensesFromParentPom(ctx, groupID, name, version, j.cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pomLicenses) > 0 {
|
if len(pomLicenses) > 0 {
|
||||||
@ -280,7 +281,7 @@ type parsedPomProject struct {
|
|||||||
Licenses []pkg.License
|
Licenses []pkg.License
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *archiveParser) guessMainPackageNameAndVersionFromPomInfo() (name, version string, licenses []pkg.License) {
|
func (j *archiveParser) guessMainPackageNameAndVersionFromPomInfo(ctx context.Context) (name, version string, licenses []pkg.License) {
|
||||||
pomPropertyMatches := j.fileManifest.GlobMatch(false, pomPropertiesGlob)
|
pomPropertyMatches := j.fileManifest.GlobMatch(false, pomPropertiesGlob)
|
||||||
pomMatches := j.fileManifest.GlobMatch(false, pomXMLGlob)
|
pomMatches := j.fileManifest.GlobMatch(false, pomXMLGlob)
|
||||||
var pomPropertiesObject pkg.JavaPomProperties
|
var pomPropertiesObject pkg.JavaPomProperties
|
||||||
@ -311,14 +312,14 @@ func (j *archiveParser) guessMainPackageNameAndVersionFromPomInfo() (name, versi
|
|||||||
if j.cfg.UseNetwork {
|
if j.cfg.UseNetwork {
|
||||||
if pomProjectObject == nil {
|
if pomProjectObject == nil {
|
||||||
// If we have no pom.xml, check maven central using pom.properties
|
// If we have no pom.xml, check maven central using pom.properties
|
||||||
parentLicenses := recursivelyFindLicensesFromParentPom(pomPropertiesObject.GroupID, pomPropertiesObject.ArtifactID, pomPropertiesObject.Version, j.cfg)
|
parentLicenses := recursivelyFindLicensesFromParentPom(ctx, pomPropertiesObject.GroupID, pomPropertiesObject.ArtifactID, pomPropertiesObject.Version, j.cfg)
|
||||||
if len(parentLicenses) > 0 {
|
if len(parentLicenses) > 0 {
|
||||||
for _, licenseName := range parentLicenses {
|
for _, licenseName := range parentLicenses {
|
||||||
licenses = append(licenses, pkg.NewLicenseFromFields(licenseName, "", nil))
|
licenses = append(licenses, pkg.NewLicenseFromFields(licenseName, "", nil))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
findPomLicenses(pomProjectObject, j.cfg)
|
findPomLicenses(ctx, pomProjectObject, j.cfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,10 +337,11 @@ func artifactIDMatchesFilename(artifactID, fileName string) bool {
|
|||||||
return strings.HasPrefix(artifactID, fileName) || strings.HasSuffix(fileName, artifactID)
|
return strings.HasPrefix(artifactID, fileName) || strings.HasSuffix(fileName, artifactID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func findPomLicenses(pomProjectObject *parsedPomProject, cfg ArchiveCatalogerConfig) {
|
func findPomLicenses(ctx context.Context, pomProjectObject *parsedPomProject, cfg ArchiveCatalogerConfig) {
|
||||||
// If we don't have any licenses until now, and if we have a parent Pom, then we'll check the parent pom in maven central for licenses.
|
// If we don't have any licenses until now, and if we have a parent Pom, then we'll check the parent pom in maven central for licenses.
|
||||||
if pomProjectObject != nil && pomProjectObject.Parent != nil && len(pomProjectObject.Licenses) == 0 {
|
if pomProjectObject != nil && pomProjectObject.Parent != nil && len(pomProjectObject.Licenses) == 0 {
|
||||||
parentLicenses := recursivelyFindLicensesFromParentPom(
|
parentLicenses := recursivelyFindLicensesFromParentPom(
|
||||||
|
ctx,
|
||||||
pomProjectObject.Parent.GroupID,
|
pomProjectObject.Parent.GroupID,
|
||||||
pomProjectObject.Parent.ArtifactID,
|
pomProjectObject.Parent.ArtifactID,
|
||||||
pomProjectObject.Parent.Version,
|
pomProjectObject.Parent.Version,
|
||||||
@ -357,7 +359,7 @@ func findPomLicenses(pomProjectObject *parsedPomProject, cfg ArchiveCatalogerCon
|
|||||||
// parent package, returning all listed Java packages found for each pom
|
// parent package, returning all listed Java packages found for each pom
|
||||||
// properties discovered and potentially updating the given parentPkg with new
|
// properties discovered and potentially updating the given parentPkg with new
|
||||||
// data.
|
// data.
|
||||||
func (j *archiveParser) discoverPkgsFromAllMavenFiles(parentPkg *pkg.Package) ([]pkg.Package, error) {
|
func (j *archiveParser) discoverPkgsFromAllMavenFiles(ctx context.Context, parentPkg *pkg.Package) ([]pkg.Package, error) {
|
||||||
if parentPkg == nil {
|
if parentPkg == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -382,7 +384,7 @@ func (j *archiveParser) discoverPkgsFromAllMavenFiles(parentPkg *pkg.Package) ([
|
|||||||
pomProject = proj
|
pomProject = proj
|
||||||
}
|
}
|
||||||
|
|
||||||
pkgFromPom := newPackageFromMavenData(propertiesObj, pomProject, parentPkg, j.location, j.cfg)
|
pkgFromPom := newPackageFromMavenData(ctx, propertiesObj, pomProject, parentPkg, j.location, j.cfg)
|
||||||
if pkgFromPom != nil {
|
if pkgFromPom != nil {
|
||||||
pkgs = append(pkgs, *pkgFromPom)
|
pkgs = append(pkgs, *pkgFromPom)
|
||||||
}
|
}
|
||||||
@ -439,30 +441,30 @@ func (j *archiveParser) getLicenseFromFileInArchive() ([]pkg.License, error) {
|
|||||||
return fileLicenses, nil
|
return fileLicenses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *archiveParser) discoverPkgsFromNestedArchives(parentPkg *pkg.Package) ([]pkg.Package, []artifact.Relationship, error) {
|
func (j *archiveParser) discoverPkgsFromNestedArchives(ctx context.Context, parentPkg *pkg.Package) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
// we know that all java archives are zip formatted files, so we can use the shared zip helper
|
// we know that all java archives are zip formatted files, so we can use the shared zip helper
|
||||||
return discoverPkgsFromZip(j.location, j.archivePath, j.contentPath, j.fileManifest, parentPkg, j.cfg)
|
return discoverPkgsFromZip(ctx, j.location, j.archivePath, j.contentPath, j.fileManifest, parentPkg, j.cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// discoverPkgsFromZip finds Java archives within Java archives, returning all listed Java packages found and
|
// discoverPkgsFromZip finds Java archives within Java archives, returning all listed Java packages found and
|
||||||
// associating each discovered package to the given parent package.
|
// associating each discovered package to the given parent package.
|
||||||
func discoverPkgsFromZip(location file.Location, archivePath, contentPath string, fileManifest intFile.ZipFileManifest, parentPkg *pkg.Package, cfg ArchiveCatalogerConfig) ([]pkg.Package, []artifact.Relationship, error) {
|
func discoverPkgsFromZip(ctx context.Context, location file.Location, archivePath, contentPath string, fileManifest intFile.ZipFileManifest, parentPkg *pkg.Package, cfg ArchiveCatalogerConfig) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
// search and parse pom.properties files & fetch the contents
|
// search and parse pom.properties files & fetch the contents
|
||||||
openers, err := intFile.ExtractFromZipToUniqueTempFile(archivePath, contentPath, fileManifest.GlobMatch(false, archiveFormatGlobs...)...)
|
openers, err := intFile.ExtractFromZipToUniqueTempFile(archivePath, contentPath, fileManifest.GlobMatch(false, archiveFormatGlobs...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to extract files from zip: %w", err)
|
return nil, nil, fmt.Errorf("unable to extract files from zip: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return discoverPkgsFromOpeners(location, openers, parentPkg, cfg)
|
return discoverPkgsFromOpeners(ctx, location, openers, parentPkg, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// discoverPkgsFromOpeners finds Java archives within the given files and associates them with the given parent package.
|
// discoverPkgsFromOpeners finds Java archives within the given files and associates them with the given parent package.
|
||||||
func discoverPkgsFromOpeners(location file.Location, openers map[string]intFile.Opener, parentPkg *pkg.Package, cfg ArchiveCatalogerConfig) ([]pkg.Package, []artifact.Relationship, error) {
|
func discoverPkgsFromOpeners(ctx context.Context, location file.Location, openers map[string]intFile.Opener, parentPkg *pkg.Package, cfg ArchiveCatalogerConfig) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
var relationships []artifact.Relationship
|
var relationships []artifact.Relationship
|
||||||
|
|
||||||
for pathWithinArchive, archiveOpener := range openers {
|
for pathWithinArchive, archiveOpener := range openers {
|
||||||
nestedPkgs, nestedRelationships, err := discoverPkgsFromOpener(location, pathWithinArchive, archiveOpener, cfg)
|
nestedPkgs, nestedRelationships, err := discoverPkgsFromOpener(ctx, location, pathWithinArchive, archiveOpener, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields("location", location.Path()).Warnf("unable to discover java packages from opener: %+v", err)
|
log.WithFields("location", location.Path()).Warnf("unable to discover java packages from opener: %+v", err)
|
||||||
continue
|
continue
|
||||||
@ -486,7 +488,7 @@ func discoverPkgsFromOpeners(location file.Location, openers map[string]intFile.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// discoverPkgsFromOpener finds Java archives within the given file.
|
// discoverPkgsFromOpener finds Java archives within the given file.
|
||||||
func discoverPkgsFromOpener(location file.Location, pathWithinArchive string, archiveOpener intFile.Opener, cfg ArchiveCatalogerConfig) ([]pkg.Package, []artifact.Relationship, error) {
|
func discoverPkgsFromOpener(ctx context.Context, location file.Location, pathWithinArchive string, archiveOpener intFile.Opener, cfg ArchiveCatalogerConfig) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
archiveReadCloser, err := archiveOpener.Open()
|
archiveReadCloser, err := archiveOpener.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to open archived file from tempdir: %w", err)
|
return nil, nil, fmt.Errorf("unable to open archived file from tempdir: %w", err)
|
||||||
@ -501,7 +503,7 @@ func discoverPkgsFromOpener(location file.Location, pathWithinArchive string, ar
|
|||||||
nestedLocation := file.NewLocationFromCoordinates(location.Coordinates)
|
nestedLocation := file.NewLocationFromCoordinates(location.Coordinates)
|
||||||
nestedLocation.AccessPath = nestedPath
|
nestedLocation.AccessPath = nestedPath
|
||||||
gap := newGenericArchiveParserAdapter(cfg)
|
gap := newGenericArchiveParserAdapter(cfg)
|
||||||
nestedPkgs, nestedRelationships, err := gap.parseJavaArchive(nil, nil, file.LocationReadCloser{
|
nestedPkgs, nestedRelationships, err := gap.parseJavaArchive(ctx, nil, nil, file.LocationReadCloser{
|
||||||
Location: nestedLocation,
|
Location: nestedLocation,
|
||||||
ReadCloser: archiveReadCloser,
|
ReadCloser: archiveReadCloser,
|
||||||
})
|
})
|
||||||
@ -573,7 +575,7 @@ func pomProjectByParentPath(archivePath string, location file.Location, extractP
|
|||||||
|
|
||||||
// newPackageFromMavenData processes a single Maven POM properties for a given parent package, returning all listed Java packages found and
|
// newPackageFromMavenData processes a single Maven POM properties for a given parent package, returning all listed Java packages found and
|
||||||
// associating each discovered package to the given parent package. Note the pom.xml is optional, the pom.properties is not.
|
// associating each discovered package to the given parent package. Note the pom.xml is optional, the pom.properties is not.
|
||||||
func newPackageFromMavenData(pomProperties pkg.JavaPomProperties, parsedPomProject *parsedPomProject, parentPkg *pkg.Package, location file.Location, cfg ArchiveCatalogerConfig) *pkg.Package {
|
func newPackageFromMavenData(ctx context.Context, pomProperties pkg.JavaPomProperties, parsedPomProject *parsedPomProject, parentPkg *pkg.Package, location file.Location, cfg ArchiveCatalogerConfig) *pkg.Package {
|
||||||
// keep the artifact name within the virtual path if this package does not match the parent package
|
// keep the artifact name within the virtual path if this package does not match the parent package
|
||||||
vPathSuffix := ""
|
vPathSuffix := ""
|
||||||
groupID := ""
|
groupID := ""
|
||||||
@ -601,14 +603,14 @@ func newPackageFromMavenData(pomProperties pkg.JavaPomProperties, parsedPomProje
|
|||||||
if cfg.UseNetwork {
|
if cfg.UseNetwork {
|
||||||
if parsedPomProject == nil {
|
if parsedPomProject == nil {
|
||||||
// If we have no pom.xml, check maven central using pom.properties
|
// If we have no pom.xml, check maven central using pom.properties
|
||||||
parentLicenses := recursivelyFindLicensesFromParentPom(pomProperties.GroupID, pomProperties.ArtifactID, pomProperties.Version, cfg)
|
parentLicenses := recursivelyFindLicensesFromParentPom(ctx, pomProperties.GroupID, pomProperties.ArtifactID, pomProperties.Version, cfg)
|
||||||
if len(parentLicenses) > 0 {
|
if len(parentLicenses) > 0 {
|
||||||
for _, licenseName := range parentLicenses {
|
for _, licenseName := range parentLicenses {
|
||||||
licenses = append(licenses, pkg.NewLicenseFromFields(licenseName, "", nil))
|
licenses = append(licenses, pkg.NewLicenseFromFields(licenseName, "", nil))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
findPomLicenses(parsedPomProject, cfg)
|
findPomLicenses(ctx, parsedPomProject, cfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package java
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -136,7 +137,7 @@ func TestSearchMavenForLicenses(t *testing.T) {
|
|||||||
defer cleanupFn()
|
defer cleanupFn()
|
||||||
|
|
||||||
// assert licenses are discovered from upstream
|
// assert licenses are discovered from upstream
|
||||||
_, _, licenses := ap.guessMainPackageNameAndVersionFromPomInfo()
|
_, _, licenses := ap.guessMainPackageNameAndVersionFromPomInfo(context.Background())
|
||||||
assert.Equal(t, tc.expectedLicenses, licenses)
|
assert.Equal(t, tc.expectedLicenses, licenses)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -405,7 +406,7 @@ func TestParseJar(t *testing.T) {
|
|||||||
defer cleanupFn()
|
defer cleanupFn()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
actual, _, err := parser.parse()
|
actual, _, err := parser.parse(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
if len(actual) != len(test.expected) {
|
if len(actual) != len(test.expected) {
|
||||||
@ -669,7 +670,7 @@ func TestParseNestedJar(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
gap := newGenericArchiveParserAdapter(ArchiveCatalogerConfig{})
|
gap := newGenericArchiveParserAdapter(ArchiveCatalogerConfig{})
|
||||||
|
|
||||||
actual, _, err := gap.parseJavaArchive(nil, nil, file.LocationReadCloser{
|
actual, _, err := gap.parseJavaArchive(context.Background(), nil, nil, file.LocationReadCloser{
|
||||||
Location: file.NewLocation(fixture.Name()),
|
Location: file.NewLocation(fixture.Name()),
|
||||||
ReadCloser: fixture,
|
ReadCloser: fixture,
|
||||||
})
|
})
|
||||||
@ -1089,7 +1090,7 @@ func Test_newPackageFromMavenData(t *testing.T) {
|
|||||||
}
|
}
|
||||||
test.expectedParent.Locations = locations
|
test.expectedParent.Locations = locations
|
||||||
|
|
||||||
actualPackage := newPackageFromMavenData(test.props, test.project, test.parent, file.NewLocation(virtualPath), DefaultArchiveCatalogerConfig())
|
actualPackage := newPackageFromMavenData(context.Background(), test.props, test.project, test.parent, file.NewLocation(virtualPath), DefaultArchiveCatalogerConfig())
|
||||||
if test.expectedPackage == nil {
|
if test.expectedPackage == nil {
|
||||||
require.Nil(t, actualPackage)
|
require.Nil(t, actualPackage)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package java
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
|
"context"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"debug/macho"
|
"debug/macho"
|
||||||
"debug/pe"
|
"debug/pe"
|
||||||
@ -570,7 +571,7 @@ func fetchPkgs(reader unionreader.UnionReader, filename string) []pkg.Package {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Catalog attempts to find any native image executables reachable from a resolver.
|
// Catalog attempts to find any native image executables reachable from a resolver.
|
||||||
func (c *NativeImageCataloger) Catalog(resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
func (c *NativeImageCataloger) Catalog(_ context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
fileMatches, err := resolver.FilesByMIMEType(internal.ExecutableMIMETypeSet.List()...)
|
fileMatches, err := resolver.FilesByMIMEType(internal.ExecutableMIMETypeSet.List()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package java
|
package java
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -28,10 +29,10 @@ func formatMavenPomURL(groupID, artifactID, version, mavenBaseURL string) (reque
|
|||||||
}
|
}
|
||||||
|
|
||||||
// An artifact can have its version defined in a parent's DependencyManagement section
|
// An artifact can have its version defined in a parent's DependencyManagement section
|
||||||
func recursivelyFindVersionFromParentPom(groupID, artifactID, parentGroupID, parentArtifactID, parentVersion string, cfg ArchiveCatalogerConfig) string {
|
func recursivelyFindVersionFromParentPom(ctx context.Context, groupID, artifactID, parentGroupID, parentArtifactID, parentVersion string, cfg ArchiveCatalogerConfig) string {
|
||||||
// As there can be nested parent poms, we'll recursively check for the version until we reach the max depth
|
// As there can be nested parent poms, we'll recursively check for the version until we reach the max depth
|
||||||
for i := 0; i < cfg.MaxParentRecursiveDepth; i++ {
|
for i := 0; i < cfg.MaxParentRecursiveDepth; i++ {
|
||||||
parentPom, err := getPomFromMavenRepo(parentGroupID, parentArtifactID, parentVersion, cfg.MavenBaseURL)
|
parentPom, err := getPomFromMavenRepo(ctx, parentGroupID, parentArtifactID, parentVersion, cfg.MavenBaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// We don't want to abort here as the parent pom might not exist in Maven Central, we'll just log the error
|
// We don't want to abort here as the parent pom might not exist in Maven Central, we'll just log the error
|
||||||
log.Tracef("unable to get parent pom from Maven central: %v", err)
|
log.Tracef("unable to get parent pom from Maven central: %v", err)
|
||||||
@ -54,11 +55,11 @@ func recursivelyFindVersionFromParentPom(groupID, artifactID, parentGroupID, par
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func recursivelyFindLicensesFromParentPom(groupID, artifactID, version string, cfg ArchiveCatalogerConfig) []string {
|
func recursivelyFindLicensesFromParentPom(ctx context.Context, groupID, artifactID, version string, cfg ArchiveCatalogerConfig) []string {
|
||||||
var licenses []string
|
var licenses []string
|
||||||
// As there can be nested parent poms, we'll recursively check for licenses until we reach the max depth
|
// As there can be nested parent poms, we'll recursively check for licenses until we reach the max depth
|
||||||
for i := 0; i < cfg.MaxParentRecursiveDepth; i++ {
|
for i := 0; i < cfg.MaxParentRecursiveDepth; i++ {
|
||||||
parentPom, err := getPomFromMavenRepo(groupID, artifactID, version, cfg.MavenBaseURL)
|
parentPom, err := getPomFromMavenRepo(ctx, groupID, artifactID, version, cfg.MavenBaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// We don't want to abort here as the parent pom might not exist in Maven Central, we'll just log the error
|
// We don't want to abort here as the parent pom might not exist in Maven Central, we'll just log the error
|
||||||
log.Tracef("unable to get parent pom from Maven central: %v", err)
|
log.Tracef("unable to get parent pom from Maven central: %v", err)
|
||||||
@ -78,7 +79,7 @@ func recursivelyFindLicensesFromParentPom(groupID, artifactID, version string, c
|
|||||||
return licenses
|
return licenses
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPomFromMavenRepo(groupID, artifactID, version, mavenBaseURL string) (*gopom.Project, error) {
|
func getPomFromMavenRepo(ctx context.Context, groupID, artifactID, version, mavenBaseURL string) (*gopom.Project, error) {
|
||||||
requestURL, err := formatMavenPomURL(groupID, artifactID, version, mavenBaseURL)
|
requestURL, err := formatMavenPomURL(groupID, artifactID, version, mavenBaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -94,6 +95,8 @@ func getPomFromMavenRepo(groupID, artifactID, version, mavenBaseURL string) (*go
|
|||||||
Timeout: time.Second * 10,
|
Timeout: time.Second * 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mavenRequest = mavenRequest.WithContext(ctx)
|
||||||
|
|
||||||
resp, err := httpClient.Do(mavenRequest)
|
resp, err := httpClient.Do(mavenRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to get pom from Maven central: %w", err)
|
return nil, fmt.Errorf("unable to get pom from Maven central: %w", err)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package java
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/anchore/syft/syft/artifact"
|
"github.com/anchore/syft/syft/artifact"
|
||||||
@ -12,14 +13,14 @@ import (
|
|||||||
|
|
||||||
const gradleLockfileGlob = "**/gradle.lockfile*"
|
const gradleLockfileGlob = "**/gradle.lockfile*"
|
||||||
|
|
||||||
// Dependency represents a single dependency in the gradle.lockfile file
|
// LockfileDependency represents a single dependency in the gradle.lockfile file
|
||||||
type LockfileDependency struct {
|
type LockfileDependency struct {
|
||||||
Group string
|
Group string
|
||||||
Name string
|
Name string
|
||||||
Version string
|
Version string
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseGradleLockfile(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseGradleLockfile(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
|
|
||||||
// Create a new scanner to read the file
|
// Create a new scanner to read the file
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package java
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -24,7 +25,7 @@ const pomXMLGlob = "*pom.xml"
|
|||||||
|
|
||||||
var propertyMatcher = regexp.MustCompile("[$][{][^}]+[}]")
|
var propertyMatcher = regexp.MustCompile("[$][{][^}]+[}]")
|
||||||
|
|
||||||
func (gap genericArchiveParserAdapter) parserPomXML(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func (gap genericArchiveParserAdapter) parserPomXML(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
pom, err := decodePomXML(reader)
|
pom, err := decodePomXML(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -34,6 +35,7 @@ func (gap genericArchiveParserAdapter) parserPomXML(_ file.Resolver, _ *generic.
|
|||||||
if pom.Dependencies != nil {
|
if pom.Dependencies != nil {
|
||||||
for _, dep := range *pom.Dependencies {
|
for _, dep := range *pom.Dependencies {
|
||||||
p := newPackageFromPom(
|
p := newPackageFromPom(
|
||||||
|
ctx,
|
||||||
pom,
|
pom,
|
||||||
dep,
|
dep,
|
||||||
gap.cfg,
|
gap.cfg,
|
||||||
@ -98,7 +100,7 @@ func newPomProject(path string, p gopom.Project, location file.Location) *parsed
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPackageFromPom(pom gopom.Project, dep gopom.Dependency, cfg ArchiveCatalogerConfig, locations ...file.Location) pkg.Package {
|
func newPackageFromPom(ctx context.Context, pom gopom.Project, dep gopom.Dependency, cfg ArchiveCatalogerConfig, locations ...file.Location) pkg.Package {
|
||||||
m := pkg.JavaArchive{
|
m := pkg.JavaArchive{
|
||||||
PomProperties: &pkg.JavaPomProperties{
|
PomProperties: &pkg.JavaPomProperties{
|
||||||
GroupID: resolveProperty(pom, dep.GroupID, "groupId"),
|
GroupID: resolveProperty(pom, dep.GroupID, "groupId"),
|
||||||
@ -114,10 +116,11 @@ func newPackageFromPom(pom gopom.Project, dep gopom.Dependency, cfg ArchiveCatal
|
|||||||
if cfg.UseNetwork {
|
if cfg.UseNetwork {
|
||||||
if version == "" {
|
if version == "" {
|
||||||
// If we have no version then let's try to get it from a parent pom DependencyManagement section
|
// If we have no version then let's try to get it from a parent pom DependencyManagement section
|
||||||
version = recursivelyFindVersionFromParentPom(*dep.GroupID, *dep.ArtifactID, *pom.Parent.GroupID, *pom.Parent.ArtifactID, *pom.Parent.Version, cfg)
|
version = recursivelyFindVersionFromParentPom(ctx, *dep.GroupID, *dep.ArtifactID, *pom.Parent.GroupID, *pom.Parent.ArtifactID, *pom.Parent.Version, cfg)
|
||||||
}
|
}
|
||||||
if version != "" {
|
if version != "" {
|
||||||
parentLicenses := recursivelyFindLicensesFromParentPom(
|
parentLicenses := recursivelyFindLicensesFromParentPom(
|
||||||
|
ctx,
|
||||||
m.PomProperties.GroupID,
|
m.PomProperties.GroupID,
|
||||||
m.PomProperties.ArtifactID,
|
m.PomProperties.ArtifactID,
|
||||||
version,
|
version,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package java
|
package java
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
intFile "github.com/anchore/syft/internal/file"
|
intFile "github.com/anchore/syft/internal/file"
|
||||||
@ -56,7 +57,7 @@ func newGenericTarWrappedJavaArchiveParser(cfg ArchiveCatalogerConfig) genericTa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gtp genericTarWrappedJavaArchiveParser) parseTarWrappedJavaArchive(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func (gtp genericTarWrappedJavaArchiveParser) parseTarWrappedJavaArchive(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
contentPath, archivePath, cleanupFn, err := saveArchiveToTmp(reader.Path(), reader)
|
contentPath, archivePath, cleanupFn, err := saveArchiveToTmp(reader.Path(), reader)
|
||||||
// note: even on error, we should always run cleanup functions
|
// note: even on error, we should always run cleanup functions
|
||||||
defer cleanupFn()
|
defer cleanupFn()
|
||||||
@ -65,14 +66,14 @@ func (gtp genericTarWrappedJavaArchiveParser) parseTarWrappedJavaArchive(_ file.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// look for java archives within the tar archive
|
// look for java archives within the tar archive
|
||||||
return discoverPkgsFromTar(reader.Location, archivePath, contentPath, gtp.cfg)
|
return discoverPkgsFromTar(ctx, reader.Location, archivePath, contentPath, gtp.cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverPkgsFromTar(location file.Location, archivePath, contentPath string, cfg ArchiveCatalogerConfig) ([]pkg.Package, []artifact.Relationship, error) {
|
func discoverPkgsFromTar(ctx context.Context, location file.Location, archivePath, contentPath string, cfg ArchiveCatalogerConfig) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
openers, err := intFile.ExtractGlobsFromTarToUniqueTempFile(archivePath, contentPath, archiveFormatGlobs...)
|
openers, err := intFile.ExtractGlobsFromTarToUniqueTempFile(archivePath, contentPath, archiveFormatGlobs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to extract files from tar: %w", err)
|
return nil, nil, fmt.Errorf("unable to extract files from tar: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return discoverPkgsFromOpeners(location, openers, nil, cfg)
|
return discoverPkgsFromOpeners(ctx, location, openers, nil, cfg)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package java
|
package java
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
@ -41,7 +42,7 @@ func Test_parseTarWrappedJavaArchive(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gtp := newGenericTarWrappedJavaArchiveParser(ArchiveCatalogerConfig{})
|
gtp := newGenericTarWrappedJavaArchiveParser(ArchiveCatalogerConfig{})
|
||||||
actualPkgs, _, err := gtp.parseTarWrappedJavaArchive(nil, nil, file.LocationReadCloser{
|
actualPkgs, _, err := gtp.parseTarWrappedJavaArchive(context.Background(), nil, nil, file.LocationReadCloser{
|
||||||
Location: file.NewLocation(test.fixture),
|
Location: file.NewLocation(test.fixture),
|
||||||
ReadCloser: fixture,
|
ReadCloser: fixture,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package java
|
package java
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
intFile "github.com/anchore/syft/internal/file"
|
intFile "github.com/anchore/syft/internal/file"
|
||||||
@ -28,7 +29,7 @@ func newGenericZipWrappedJavaArchiveParser(cfg ArchiveCatalogerConfig) genericZi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gzp genericZipWrappedJavaArchiveParser) parseZipWrappedJavaArchive(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func (gzp genericZipWrappedJavaArchiveParser) parseZipWrappedJavaArchive(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
contentPath, archivePath, cleanupFn, err := saveArchiveToTmp(reader.Path(), reader)
|
contentPath, archivePath, cleanupFn, err := saveArchiveToTmp(reader.Path(), reader)
|
||||||
// note: even on error, we should always run cleanup functions
|
// note: even on error, we should always run cleanup functions
|
||||||
defer cleanupFn()
|
defer cleanupFn()
|
||||||
@ -46,5 +47,5 @@ func (gzp genericZipWrappedJavaArchiveParser) parseZipWrappedJavaArchive(_ file.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// look for java archives within the zip archive
|
// look for java archives within the zip archive
|
||||||
return discoverPkgsFromZip(reader.Location, archivePath, contentPath, fileManifest, nil, gzp.cfg)
|
return discoverPkgsFromZip(ctx, reader.Location, archivePath, contentPath, fileManifest, nil, gzp.cfg)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package java
|
package java
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
@ -35,7 +36,7 @@ func Test_parseZipWrappedJavaArchive(t *testing.T) {
|
|||||||
|
|
||||||
gzp := newGenericZipWrappedJavaArchiveParser(ArchiveCatalogerConfig{})
|
gzp := newGenericZipWrappedJavaArchiveParser(ArchiveCatalogerConfig{})
|
||||||
|
|
||||||
actualPkgs, _, err := gzp.parseZipWrappedJavaArchive(nil, nil, file.LocationReadCloser{
|
actualPkgs, _, err := gzp.parseZipWrappedJavaArchive(context.Background(), nil, nil, file.LocationReadCloser{
|
||||||
Location: file.NewLocation(test.fixture),
|
Location: file.NewLocation(test.fixture),
|
||||||
ReadCloser: fixture,
|
ReadCloser: fixture,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package javascript
|
package javascript
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -51,7 +52,7 @@ type repository struct {
|
|||||||
var authorPattern = regexp.MustCompile(`^\s*(?P<name>[^<(]*)(\s+<(?P<email>.*)>)?(\s\((?P<url>.*)\))?\s*$`)
|
var authorPattern = regexp.MustCompile(`^\s*(?P<name>[^<(]*)(\s+<(?P<email>.*)>)?(\s\((?P<url>.*)\))?\s*$`)
|
||||||
|
|
||||||
// parsePackageJSON parses a package.json and returns the discovered JavaScript packages.
|
// parsePackageJSON parses a package.json and returns the discovered JavaScript packages.
|
||||||
func parsePackageJSON(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parsePackageJSON(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
dec := json.NewDecoder(reader)
|
dec := json.NewDecoder(reader)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package javascript
|
package javascript
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -44,7 +45,7 @@ type lockPackage struct {
|
|||||||
type packageLockLicense []string
|
type packageLockLicense []string
|
||||||
|
|
||||||
// parsePackageLock parses a package-lock.json and returns the discovered JavaScript packages.
|
// parsePackageLock parses a package-lock.json and returns the discovered JavaScript packages.
|
||||||
func parsePackageLock(resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parsePackageLock(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
// in the case we find package-lock.json files in the node_modules directories, skip those
|
// in the case we find package-lock.json files in the node_modules directories, skip those
|
||||||
// as the whole purpose of the lock file is for the specific dependencies of the root project
|
// as the whole purpose of the lock file is for the specific dependencies of the root project
|
||||||
if pathContainsNodeModulesDirectory(reader.Path()) {
|
if pathContainsNodeModulesDirectory(reader.Path()) {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package javascript
|
package javascript
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -25,7 +26,7 @@ type pnpmLockYaml struct {
|
|||||||
Packages map[string]interface{} `json:"packages" yaml:"packages"`
|
Packages map[string]interface{} `json:"packages" yaml:"packages"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePnpmLock(resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parsePnpmLock(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
bytes, err := io.ReadAll(reader)
|
bytes, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("failed to load pnpm-lock.yaml file: %w", err)
|
return nil, nil, fmt.Errorf("failed to load pnpm-lock.yaml file: %w", err)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package javascript
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ func newGenericYarnLockAdapter(cfg CatalogerConfig) genericYarnLockAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a genericYarnLockAdapter) parseYarnLock(resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func (a genericYarnLockAdapter) parseYarnLock(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
// in the case we find yarn.lock files in the node_modules directories, skip those
|
// in the case we find yarn.lock files in the node_modules directories, skip those
|
||||||
// as the whole purpose of the lock file is for the specific dependencies of the project
|
// as the whole purpose of the lock file is for the specific dependencies of the project
|
||||||
if pathContainsNodeModulesDirectory(reader.Path()) {
|
if pathContainsNodeModulesDirectory(reader.Path()) {
|
||||||
|
|||||||
@ -4,6 +4,8 @@ Package kernel provides a concrete Cataloger implementation for linux kernel and
|
|||||||
package kernel
|
package kernel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
@ -53,12 +55,12 @@ func (l LinuxKernelCataloger) Name() string {
|
|||||||
return "linux-kernel-cataloger"
|
return "linux-kernel-cataloger"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l LinuxKernelCataloger) Catalog(resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
func (l LinuxKernelCataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var allPackages []pkg.Package
|
var allPackages []pkg.Package
|
||||||
var allRelationships []artifact.Relationship
|
var allRelationships []artifact.Relationship
|
||||||
var errs error
|
var errs error
|
||||||
|
|
||||||
kernelPackages, kernelRelationships, err := generic.NewCataloger(l.Name()).WithParserByGlobs(parseLinuxKernelFile, kernelArchiveGlobs...).Catalog(resolver)
|
kernelPackages, kernelRelationships, err := generic.NewCataloger(l.Name()).WithParserByGlobs(parseLinuxKernelFile, kernelArchiveGlobs...).Catalog(ctx, resolver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = multierror.Append(errs, err)
|
errs = multierror.Append(errs, err)
|
||||||
}
|
}
|
||||||
@ -67,7 +69,7 @@ func (l LinuxKernelCataloger) Catalog(resolver file.Resolver) ([]pkg.Package, []
|
|||||||
allPackages = append(allPackages, kernelPackages...)
|
allPackages = append(allPackages, kernelPackages...)
|
||||||
|
|
||||||
if l.cfg.CatalogModules {
|
if l.cfg.CatalogModules {
|
||||||
modulePackages, moduleRelationships, err := generic.NewCataloger(l.Name()).WithParserByGlobs(parseLinuxKernelModuleFile, kernelModuleGlobs...).Catalog(resolver)
|
modulePackages, moduleRelationships, err := generic.NewCataloger(l.Name()).WithParserByGlobs(parseLinuxKernelModuleFile, kernelModuleGlobs...).Catalog(ctx, resolver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = multierror.Append(errs, err)
|
errs = multierror.Append(errs, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package kernel
|
package kernel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -17,7 +18,7 @@ import (
|
|||||||
|
|
||||||
const linuxKernelMagicName = "Linux kernel"
|
const linuxKernelMagicName = "Linux kernel"
|
||||||
|
|
||||||
func parseLinuxKernelFile(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseLinuxKernelFile(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
unionReader, err := unionreader.GetUnionReader(reader)
|
unionReader, err := unionreader.GetUnionReader(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to get union reader for file: %w", err)
|
return nil, nil, fmt.Errorf("unable to get union reader for file: %w", err)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package kernel
|
package kernel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
@ -14,7 +15,7 @@ import (
|
|||||||
|
|
||||||
const modinfoName = ".modinfo"
|
const modinfoName = ".modinfo"
|
||||||
|
|
||||||
func parseLinuxKernelModuleFile(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseLinuxKernelModuleFile(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
unionReader, err := unionreader.GetUnionReader(reader)
|
unionReader, err := unionreader.GetUnionReader(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to get union reader for file: %w", err)
|
return nil, nil, fmt.Errorf("unable to get union reader for file: %w", err)
|
||||||
|
|||||||
@ -28,11 +28,11 @@ func (c *StoreCataloger) Name() string {
|
|||||||
return catalogerName
|
return catalogerName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *StoreCataloger) Catalog(resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
func (c *StoreCataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
// we want to search for only directories, which isn't possible via the stereoscope API, so we need to apply the glob manually on all returned paths
|
// we want to search for only directories, which isn't possible via the stereoscope API, so we need to apply the glob manually on all returned paths
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
var filesByPath = make(map[string]*file.LocationSet)
|
var filesByPath = make(map[string]*file.LocationSet)
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
for location := range resolver.AllLocations(ctx) {
|
for location := range resolver.AllLocations(ctx) {
|
||||||
matchesStorePath, err := doublestar.Match("**/nix/store/*", location.RealPath)
|
matchesStorePath, err := doublestar.Match("**/nix/store/*", location.RealPath)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package php
|
package php
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -25,7 +26,7 @@ type composerLock struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseComposerLock is a parser function for Composer.lock contents, returning "Default" php packages discovered.
|
// parseComposerLock is a parser function for Composer.lock contents, returning "Default" php packages discovered.
|
||||||
func parseComposerLock(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseComposerLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
pkgs := make([]pkg.Package, 0)
|
pkgs := make([]pkg.Package, 0)
|
||||||
dec := json.NewDecoder(reader)
|
dec := json.NewDecoder(reader)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package php
|
package php
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -46,7 +47,7 @@ func (w *installedJSONComposerV2) UnmarshalJSON(data []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseInstalledJSON is a parser function for Composer.lock contents, returning "Default" php packages discovered.
|
// parseInstalledJSON is a parser function for Composer.lock contents, returning "Default" php packages discovered.
|
||||||
func parseInstalledJSON(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseInstalledJSON(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
dec := json.NewDecoder(reader)
|
dec := json.NewDecoder(reader)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package python
|
package python
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -296,7 +297,7 @@ func Test_PackageCataloger_IgnorePackage(t *testing.T) {
|
|||||||
t.Run(test.MetadataFixture, func(t *testing.T) {
|
t.Run(test.MetadataFixture, func(t *testing.T) {
|
||||||
resolver := file.NewMockResolverForPaths(test.MetadataFixture)
|
resolver := file.NewMockResolverForPaths(test.MetadataFixture)
|
||||||
|
|
||||||
actual, _, err := NewInstalledPackageCataloger().Catalog(resolver)
|
actual, _, err := NewInstalledPackageCataloger().Catalog(context.Background(), resolver)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
if len(actual) != 0 {
|
if len(actual) != 0 {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package python
|
package python
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -41,7 +42,7 @@ type Dependency struct {
|
|||||||
var _ generic.Parser = parsePipfileLock
|
var _ generic.Parser = parsePipfileLock
|
||||||
|
|
||||||
// parsePipfileLock is a parser function for Pipfile.lock contents, returning "Default" python packages discovered.
|
// parsePipfileLock is a parser function for Pipfile.lock contents, returning "Default" python packages discovered.
|
||||||
func parsePipfileLock(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parsePipfileLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
pkgs := make([]pkg.Package, 0)
|
pkgs := make([]pkg.Package, 0)
|
||||||
dec := json.NewDecoder(reader)
|
dec := json.NewDecoder(reader)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package python
|
package python
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/pelletier/go-toml"
|
"github.com/pelletier/go-toml"
|
||||||
@ -25,7 +26,7 @@ type poetryMetadata struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parsePoetryLock is a parser function for poetry.lock contents, returning all python packages discovered.
|
// parsePoetryLock is a parser function for poetry.lock contents, returning all python packages discovered.
|
||||||
func parsePoetryLock(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parsePoetryLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
tree, err := toml.LoadReader(reader)
|
tree, err := toml.LoadReader(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to load poetry.lock for parsing: %w", err)
|
return nil, nil, fmt.Errorf("unable to load poetry.lock for parsing: %w", err)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package python
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@ -92,7 +93,7 @@ func newRequirementsParser(cfg CatalogerConfig) requirementsParser {
|
|||||||
|
|
||||||
// parseRequirementsTxt takes a Python requirements.txt file, returning all Python packages that are locked to a
|
// parseRequirementsTxt takes a Python requirements.txt file, returning all Python packages that are locked to a
|
||||||
// specific version.
|
// specific version.
|
||||||
func (rp requirementsParser) parseRequirementsTxt(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func (rp requirementsParser) parseRequirementsTxt(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var packages []pkg.Package
|
var packages []pkg.Package
|
||||||
|
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package python
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ var _ generic.Parser = parseSetup
|
|||||||
// " mypy2 == v0.770", ' mypy3== v0.770', --> match(name=mypy2 version=v0.770), match(name=mypy3, version=v0.770)
|
// " mypy2 == v0.770", ' mypy3== v0.770', --> match(name=mypy2 version=v0.770), match(name=mypy3, version=v0.770)
|
||||||
var pinnedDependency = regexp.MustCompile(`['"]\W?(\w+\W?==\W?[\w.]*)`)
|
var pinnedDependency = regexp.MustCompile(`['"]\W?(\w+\W?==\W?[\w.]*)`)
|
||||||
|
|
||||||
func parseSetup(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseSetup(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var packages []pkg.Package
|
var packages []pkg.Package
|
||||||
|
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package python
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -17,7 +18,7 @@ import (
|
|||||||
|
|
||||||
// parseWheelOrEgg takes the primary metadata file reference and returns the python package it represents. Contained
|
// parseWheelOrEgg takes the primary metadata file reference and returns the python package it represents. Contained
|
||||||
// fields are governed by the PyPA core metadata specification (https://packaging.python.org/en/latest/specifications/core-metadata/).
|
// fields are governed by the PyPA core metadata specification (https://packaging.python.org/en/latest/specifications/core-metadata/).
|
||||||
func parseWheelOrEgg(resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseWheelOrEgg(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
pd, sources, err := assembleEggOrWheelMetadata(resolver, reader.Location)
|
pd, sources, err := assembleEggOrWheelMetadata(resolver, reader.Location)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package r
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@ -28,7 +29,7 @@ License: Part of R 4.3.0
|
|||||||
License: Unlimited
|
License: Unlimited
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func parseDescriptionFile(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseDescriptionFile(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
values := extractFieldsFromDescriptionFile(reader)
|
values := extractFieldsFromDescriptionFile(reader)
|
||||||
m := parseDataFromDescriptionMap(values)
|
m := parseDataFromDescriptionMap(values)
|
||||||
p := newPackage(m, []file.Location{reader.Location}...)
|
p := newPackage(m, []file.Location{reader.Location}...)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package r
|
package r
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
@ -57,7 +58,7 @@ func Test_parseDescriptionFile(t *testing.T) {
|
|||||||
Location: file.NewLocation(tt.fixture),
|
Location: file.NewLocation(tt.fixture),
|
||||||
ReadCloser: f,
|
ReadCloser: f,
|
||||||
}
|
}
|
||||||
got, _, err := parseDescriptionFile(nil, nil, input)
|
got, _, err := parseDescriptionFile(context.Background(), nil, nil, input)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
for _, assertion := range tt.assertions {
|
for _, assertion := range tt.assertions {
|
||||||
assertion(t, got)
|
assertion(t, got)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package redhat
|
package redhat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// parseRpmArchive parses a single RPM
|
// parseRpmArchive parses a single RPM
|
||||||
func parseRpmArchive(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseRpmArchive(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
rpm, err := rpmutils.ReadRpm(reader)
|
rpm, err := rpmutils.ReadRpm(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("RPM file found but unable to read: %s (%w)", reader.Location.RealPath, err)
|
return nil, nil, fmt.Errorf("RPM file found but unable to read: %s (%w)", reader.Location.RealPath, err)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package redhat
|
package redhat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -16,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// parseRpmDb parses an "Packages" RPM DB and returns the Packages listed within it.
|
// parseRpmDb parses an "Packages" RPM DB and returns the Packages listed within it.
|
||||||
func parseRpmDB(resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseRpmDB(_ context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
f, err := os.CreateTemp("", "rpmdb")
|
f, err := os.CreateTemp("", "rpmdb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("failed to create temp rpmdb file: %w", err)
|
return nil, nil, fmt.Errorf("failed to create temp rpmdb file: %w", err)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package redhat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
@ -14,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Parses an RPM manifest file, as used in Mariner distroless containers, and returns the Packages listed
|
// Parses an RPM manifest file, as used in Mariner distroless containers, and returns the Packages listed
|
||||||
func parseRpmManifest(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseRpmManifest(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
r := bufio.NewReader(reader)
|
r := bufio.NewReader(reader)
|
||||||
allPkgs := make([]pkg.Package, 0)
|
allPkgs := make([]pkg.Package, 0)
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package ruby
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/scylladb/go-set/strset"
|
"github.com/scylladb/go-set/strset"
|
||||||
@ -17,7 +18,7 @@ var _ generic.Parser = parseGemFileLockEntries
|
|||||||
var sectionsOfInterest = strset.New("GEM", "GIT", "PATH", "PLUGIN SOURCE")
|
var sectionsOfInterest = strset.New("GEM", "GIT", "PATH", "PLUGIN SOURCE")
|
||||||
|
|
||||||
// parseGemFileLockEntries is a parser function for Gemfile.lock contents, returning all Gems discovered.
|
// parseGemFileLockEntries is a parser function for Gemfile.lock contents, returning all Gems discovered.
|
||||||
func parseGemFileLockEntries(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseGemFileLockEntries(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package ruby
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -65,7 +66,7 @@ func processList(s string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseGemSpecEntries parses the gemspec file and returns the packages and relationships found.
|
// parseGemSpecEntries parses the gemspec file and returns the packages and relationships found.
|
||||||
func parseGemSpecEntries(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseGemSpecEntries(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
var fields = make(map[string]interface{})
|
var fields = make(map[string]interface{})
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package rust
|
package rust
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
rustaudit "github.com/microsoft/go-rustaudit"
|
rustaudit "github.com/microsoft/go-rustaudit"
|
||||||
@ -14,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Catalog identifies executables then attempts to read Rust dependency information from them
|
// Catalog identifies executables then attempts to read Rust dependency information from them
|
||||||
func parseAuditBinary(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseAuditBinary(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
|
|
||||||
unionReader, err := unionreader.GetUnionReader(reader.ReadCloser)
|
unionReader, err := unionreader.GetUnionReader(reader.ReadCloser)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package rust
|
package rust
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/pelletier/go-toml"
|
"github.com/pelletier/go-toml"
|
||||||
@ -18,7 +19,7 @@ type cargoLockFile struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseCargoLock is a parser function for Cargo.lock contents, returning all rust cargo crates discovered.
|
// parseCargoLock is a parser function for Cargo.lock contents, returning all rust cargo crates discovered.
|
||||||
func parseCargoLock(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseCargoLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
tree, err := toml.LoadReader(reader)
|
tree, err := toml.LoadReader(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to load Cargo.lock for parsing: %w", err)
|
return nil, nil, fmt.Errorf("unable to load Cargo.lock for parsing: %w", err)
|
||||||
|
|||||||
@ -5,6 +5,7 @@ package sbom
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ func NewCataloger() pkg.Cataloger {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSBOM(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseSBOM(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
readSeeker, err := adaptToReadSeeker(reader)
|
readSeeker, err := adaptToReadSeeker(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to read SBOM file %q: %w", reader.Location.RealPath, err)
|
return nil, nil, fmt.Errorf("unable to read SBOM file %q: %w", reader.Location.RealPath, err)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package swift
|
package swift
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -57,7 +58,7 @@ type packageState struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parsePackageResolved is a parser for the contents of a Package.resolved file, which is generated by Xcode after it's resolved Swift Package Manger packages.
|
// parsePackageResolved is a parser for the contents of a Package.resolved file, which is generated by Xcode after it's resolved Swift Package Manger packages.
|
||||||
func parsePackageResolved(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parsePackageResolved(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
dec := json.NewDecoder(reader)
|
dec := json.NewDecoder(reader)
|
||||||
var packageResolvedData map[string]interface{}
|
var packageResolvedData map[string]interface{}
|
||||||
for {
|
for {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package swift
|
package swift
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
@ -25,7 +26,7 @@ type podfileLock struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parsePodfileLock is a parser function for Podfile.lock contents, returning all cocoapods pods discovered.
|
// parsePodfileLock is a parser function for Podfile.lock contents, returning all cocoapods pods discovered.
|
||||||
func parsePodfileLock(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parsePodfileLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
bytes, err := io.ReadAll(reader)
|
bytes, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to read file: %w", err)
|
return nil, nil, fmt.Errorf("unable to read file: %w", err)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user