From 15379d1075127b7af46f2ec7be937b7fcd2d3555 Mon Sep 17 00:00:00 2001 From: Toure Dunnon Date: Wed, 21 Oct 2020 10:44:05 -0400 Subject: [PATCH] Fix for errors+failures parsing `package.json` closes: #230 Signed-off-by: Toure Dunnon --- go.mod | 1 + .../javascript/parse_package_json.go | 35 +++++++++++-------- .../javascript/parse_package_json_test.go | 3 ++ .../pkg-json/package-nested-author.json | 4 +++ syft/pkg/metadata.go | 11 ------ syft/pkg/npm_metadata.go | 1 + 6 files changed, 29 insertions(+), 26 deletions(-) delete mode 100644 syft/pkg/metadata.go diff --git a/go.mod b/go.mod index af71131ea..f7af429f9 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/stereoscope v0.0.0-20200925184903-c82da54e98fe + github.com/apex/log v1.3.0 github.com/bmatcuk/doublestar v1.3.1 github.com/docker/docker v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible github.com/dustin/go-humanize v1.0.0 diff --git a/syft/cataloger/javascript/parse_package_json.go b/syft/cataloger/javascript/parse_package_json.go index 0b3a39a11..a0ebc899f 100644 --- a/syft/cataloger/javascript/parse_package_json.go +++ b/syft/cataloger/javascript/parse_package_json.go @@ -27,6 +27,7 @@ type PackageJSON struct { Homepage string `json:"homepage"` Description string `json:"description"` Dependencies map[string]string `json:"dependencies"` + Repository Repository `json:"repository"` } type Author struct { @@ -35,37 +36,40 @@ type Author struct { URL string `json:"url" mapstruct:"url"` } +type Repository struct { + Type string `json:"type"` + URL string `json:"url"` +} + +// match example: "author": "Isaac Z. Schlueter (http://blog.izs.me)" +// ---> name: "Isaac Z. Schlueter" email: "i@izs.me" url: "http://blog.izs.me" var authorPattern = regexp.MustCompile(`^\s*(?P[^<(]*)(\s+<(?P.*)>)?(\s\((?P.*)\))?\s*$`) +// This method implements the UnmarshalJSON interface to help normalize +// the json structure. func (a *Author) UnmarshalJSON(b []byte) error { var authorStr string + var fields map[string]string + var author Author + if err := json.Unmarshal(b, &authorStr); err != nil { // string parsing did not work, assume a map was given // for more information: https://docs.npmjs.com/files/package.json#people-fields-author-contributors - var fields map[string]string - var author Author if err := json.Unmarshal(b, &fields); err != nil { return fmt.Errorf("unable to parse package.json author: %w", err) } - // translate the map into a structure - if err := mapstructure.Decode(fields, &author); err != nil { - return fmt.Errorf("unable to decode package.json author: %w", err) - } - *a = author } else { // parse out "name (url)" into an Author struct - var fields = internal.MatchCaptureGroups(authorPattern, authorStr) - *a = Author{ - Name: fields["name"], - Email: fields["email"], - URL: fields["url"], - } + fields = internal.MatchCaptureGroups(authorPattern, authorStr) } - if a.Name == "" { - return fmt.Errorf("package.json author name is empty") + // translate the map into a structure + if err := mapstructure.Decode(fields, &author); err != nil { + return fmt.Errorf("unable to decode package.json author: %w", err) } + *a = author + return nil } @@ -102,6 +106,7 @@ func parsePackageJSON(_ string, reader io.Reader) ([]pkg.Package, error) { Metadata: pkg.NpmMetadata{ Author: p.Author.String(), Homepage: p.Homepage, + URL: p.Repository.URL, }, }) } diff --git a/syft/cataloger/javascript/parse_package_json_test.go b/syft/cataloger/javascript/parse_package_json_test.go index b843f199d..b135a8e27 100644 --- a/syft/cataloger/javascript/parse_package_json_test.go +++ b/syft/cataloger/javascript/parse_package_json_test.go @@ -24,6 +24,7 @@ func TestParsePackageJSON(t *testing.T) { Metadata: pkg.NpmMetadata{ Author: "Isaac Z. Schlueter (http://blog.izs.me)", Homepage: "https://docs.npmjs.com/", + URL: "https://github.com/npm/cli", }, }, }, @@ -38,6 +39,7 @@ func TestParsePackageJSON(t *testing.T) { Metadata: pkg.NpmMetadata{ Author: "Isaac Z. Schlueter (http://blog.izs.me)", Homepage: "https://docs.npmjs.com/", + URL: "https://github.com/npm/cli", }, }, }, @@ -62,6 +64,7 @@ func TestParsePackageJSON(t *testing.T) { } for _, d := range deep.Equal(actual[0], test.ExpectedPkg) { + t.Errorf("diff: %+v", d) } }) diff --git a/syft/cataloger/javascript/test-fixtures/pkg-json/package-nested-author.json b/syft/cataloger/javascript/test-fixtures/pkg-json/package-nested-author.json index 436fca091..ac2438a11 100644 --- a/syft/cataloger/javascript/test-fixtures/pkg-json/package-nested-author.json +++ b/syft/cataloger/javascript/test-fixtures/pkg-json/package-nested-author.json @@ -8,5 +8,9 @@ "email": "i@izs.me", "url": "http://blog.izs.me" }, + "repository": { + "type": "git", + "url": "https://github.com/npm/cli" + }, "license": "Artistic-2.0" } \ No newline at end of file diff --git a/syft/pkg/metadata.go b/syft/pkg/metadata.go deleted file mode 100644 index 2d5eb2def..000000000 --- a/syft/pkg/metadata.go +++ /dev/null @@ -1,11 +0,0 @@ -package pkg - -type MetadataType string - -const ( - UnknownMetadataType MetadataType = "UnknownMetadata" - ApkMetadataType MetadataType = "apk-metadata" - DpkgMetadataType MetadataType = "dpkg-metadata" - GemgMetadataType MetadataType = "gem-metadata" - RpmdbMetadataType MetadataType = "rpmdb-metadata" -) diff --git a/syft/pkg/npm_metadata.go b/syft/pkg/npm_metadata.go index af683120b..5b12e5cbc 100644 --- a/syft/pkg/npm_metadata.go +++ b/syft/pkg/npm_metadata.go @@ -9,4 +9,5 @@ type NpmMetadata struct { License string `mapstructure:"license" json:"license"` Homepage string `mapstructure:"homepage" json:"homepage"` Description string `mapstructure:"description" json:"description"` + URL string `mapstructure:"url" json:"url"` }