Adding metadata fields when parsing yarn.lock and poetry.lock (#2350)

* Adding the resolved and integrity fields of yarn.lock to the parsed metadata. This addition is similar to the metadata added when parsing package-lock.json.

Signed-off-by: asi-cider <88270351+asi-cider@users.noreply.github.com>

* fix comment

Signed-off-by: asi-cider <88270351+asi-cider@users.noreply.github.com>

* Adding the Index field to metadeta when parsing poetry.lock similarly to the existing Pipfile metadata

Signed-off-by: asi-cider <88270351+asi-cider@users.noreply.github.com>

* fixing struct accoding to tests

Signed-off-by: asi-cider <88270351+asi-cider@users.noreply.github.com>

* remove old schema change

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* remove empty constants

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* re-generate JSON schema

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* update document ref

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix linting

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: asi-cider <88270351+asi-cider@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Asi Greenholts 2024-02-02 21:53:42 +02:00 committed by GitHub
parent d7b9cc70b0
commit 98de2e2f62
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 2398 additions and 36 deletions

View File

@ -3,5 +3,5 @@ package internal
const ( const (
// JSONSchemaVersion is the current schema version output by the JSON encoder // JSONSchemaVersion is the current schema version output by the JSON encoder
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment. // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
JSONSchemaVersion = "16.0.1" JSONSchemaVersion = "16.0.2"
) )

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,7 @@ func AllTypes() []any {
pkg.PortageEntry{}, pkg.PortageEntry{},
pkg.PythonPackage{}, pkg.PythonPackage{},
pkg.PythonPipfileLockEntry{}, pkg.PythonPipfileLockEntry{},
pkg.PythonPoetryLockEntry{},
pkg.PythonRequirementsEntry{}, pkg.PythonRequirementsEntry{},
pkg.RDescription{}, pkg.RDescription{},
pkg.RpmArchive{}, pkg.RpmArchive{},
@ -44,5 +45,6 @@ func AllTypes() []any {
pkg.RustBinaryAuditEntry{}, pkg.RustBinaryAuditEntry{},
pkg.RustCargoLockEntry{}, pkg.RustCargoLockEntry{},
pkg.SwiftPackageManagerResolvedEntry{}, pkg.SwiftPackageManagerResolvedEntry{},
pkg.YarnLockEntry{},
} }
} }

View File

@ -86,11 +86,13 @@ var jsonTypes = makeJSONTypes(
jsonNames(pkg.NixStoreEntry{}, "nix-store-entry", "NixStoreMetadata"), jsonNames(pkg.NixStoreEntry{}, "nix-store-entry", "NixStoreMetadata"),
jsonNames(pkg.NpmPackage{}, "javascript-npm-package", "NpmPackageJsonMetadata"), jsonNames(pkg.NpmPackage{}, "javascript-npm-package", "NpmPackageJsonMetadata"),
jsonNames(pkg.NpmPackageLockEntry{}, "javascript-npm-package-lock-entry", "NpmPackageLockJsonMetadata"), jsonNames(pkg.NpmPackageLockEntry{}, "javascript-npm-package-lock-entry", "NpmPackageLockJsonMetadata"),
jsonNames(pkg.YarnLockEntry{}, "javascript-yarn-lock-entry", "YarnLockJsonMetadata"),
jsonNames(pkg.PhpComposerLockEntry{}, "php-composer-lock-entry", "PhpComposerJsonMetadata"), jsonNames(pkg.PhpComposerLockEntry{}, "php-composer-lock-entry", "PhpComposerJsonMetadata"),
jsonNamesWithoutLookup(pkg.PhpComposerInstalledEntry{}, "php-composer-installed-entry", "PhpComposerJsonMetadata"), // the legacy value is split into two types, where the other is preferred jsonNamesWithoutLookup(pkg.PhpComposerInstalledEntry{}, "php-composer-installed-entry", "PhpComposerJsonMetadata"), // the legacy value is split into two types, where the other is preferred
jsonNames(pkg.PortageEntry{}, "portage-db-entry", "PortageMetadata"), jsonNames(pkg.PortageEntry{}, "portage-db-entry", "PortageMetadata"),
jsonNames(pkg.PythonPackage{}, "python-package", "PythonPackageMetadata"), jsonNames(pkg.PythonPackage{}, "python-package", "PythonPackageMetadata"),
jsonNames(pkg.PythonPipfileLockEntry{}, "python-pipfile-lock-entry", "PythonPipfileLockMetadata"), jsonNames(pkg.PythonPipfileLockEntry{}, "python-pipfile-lock-entry", "PythonPipfileLockMetadata"),
jsonNames(pkg.PythonPoetryLockEntry{}, "python-poetry-lock-entry", "PythonPoetryLockMetadata"),
jsonNames(pkg.PythonRequirementsEntry{}, "python-pip-requirements-entry", "PythonRequirementsMetadata"), jsonNames(pkg.PythonRequirementsEntry{}, "python-pip-requirements-entry", "PythonRequirementsMetadata"),
jsonNames(pkg.ErlangRebarLockEntry{}, "erlang-rebar-lock-entry", "RebarLockMetadataType"), jsonNames(pkg.ErlangRebarLockEntry{}, "erlang-rebar-lock-entry", "RebarLockMetadataType"),
jsonNames(pkg.RDescription{}, "r-description", "RDescriptionFileMetadataType"), jsonNames(pkg.RDescription{}, "r-description", "RDescriptionFileMetadataType"),

View File

@ -110,7 +110,7 @@ func newPnpmPackage(resolver file.Resolver, location file.Location, name, versio
) )
} }
func newYarnLockPackage(cfg CatalogerConfig, resolver file.Resolver, location file.Location, name, version string) pkg.Package { func newYarnLockPackage(cfg CatalogerConfig, resolver file.Resolver, location file.Location, name, version string, resolved string, integrity string) pkg.Package {
var licenseSet pkg.LicenseSet var licenseSet pkg.LicenseSet
if cfg.SearchRemoteLicenses { if cfg.SearchRemoteLicenses {
@ -123,7 +123,6 @@ func newYarnLockPackage(cfg CatalogerConfig, resolver file.Resolver, location fi
log.Warnf("unable to extract licenses from javascript yarn.lock for package %s:%s: %+v", name, version, err) log.Warnf("unable to extract licenses from javascript yarn.lock for package %s:%s: %+v", name, version, err)
} }
} }
return finalizeLockPkg( return finalizeLockPkg(
resolver, resolver,
location, location,
@ -135,6 +134,7 @@ func newYarnLockPackage(cfg CatalogerConfig, resolver file.Resolver, location fi
PURL: packageURL(name, version), PURL: packageURL(name, version),
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{Resolved: resolved, Integrity: integrity},
}, },
) )
} }

View File

@ -34,11 +34,18 @@ var (
// `resolved "https://registry.yarnpkg.com/@4lolo/resize-observer-polyfill/-/resize-observer-polyfill-1.5.2.tgz#58868fc7224506236b5550d0c68357f0a874b84b"` // `resolved "https://registry.yarnpkg.com/@4lolo/resize-observer-polyfill/-/resize-observer-polyfill-1.5.2.tgz#58868fc7224506236b5550d0c68357f0a874b84b"`
// would return "@4lolo/resize-observer-polyfill" and "1.5.2" // would return "@4lolo/resize-observer-polyfill" and "1.5.2"
packageURLExp = regexp.MustCompile(`^\s+resolved\s+"https://registry\.(?:yarnpkg\.com|npmjs\.org)/(.+?)/-/(?:.+?)-(\d+\..+?)\.tgz`) packageURLExp = regexp.MustCompile(`^\s+resolved\s+"https://registry\.(?:yarnpkg\.com|npmjs\.org)/(.+?)/-/(?:.+?)-(\d+\..+?)\.tgz`)
)
const ( // resolvedExp matches the resolved of the dependency in yarn.lock
noPackage = "" // For example:
noVersion = "" // resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
// would return "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
resolvedExp = regexp.MustCompile(`^\s+resolved\s+"(.+?)"`)
// integrityExp matches the integrity of the dependency in yarn.lock
// For example:
// integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
// would return "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==""
integrityExp = regexp.MustCompile(`^\s+integrity\s+([^\s]+)`)
) )
type genericYarnLockAdapter struct { type genericYarnLockAdapter struct {
@ -59,37 +66,43 @@ func (a genericYarnLockAdapter) parseYarnLock(_ context.Context, resolver file.R
} }
var pkgs []pkg.Package var pkgs []pkg.Package
var currentPackage, currentVersion, currentResolved, currentIntegrity string
scanner := bufio.NewScanner(reader) scanner := bufio.NewScanner(reader)
parsedPackages := strset.New() parsedPackages := strset.New()
currentPackage := noPackage
currentVersion := noVersion
for scanner.Scan() { for scanner.Scan() {
line := scanner.Text() line := scanner.Text()
if packageName := findPackageName(line); packageName != noPackage { if packageName := findPackageName(line); packageName != "" {
// When we find a new package, check if we have unsaved identifiers // When we find a new package, check if we have unsaved identifiers
if currentPackage != noPackage && currentVersion != noVersion && !parsedPackages.Has(currentPackage+"@"+currentVersion) { if currentPackage != "" && currentVersion != "" && !parsedPackages.Has(currentPackage+"@"+currentVersion) {
pkgs = append(pkgs, newYarnLockPackage(a.cfg, resolver, reader.Location, currentPackage, currentVersion)) pkgs = append(pkgs, newYarnLockPackage(a.cfg, resolver, reader.Location, currentPackage, currentVersion, currentResolved, currentIntegrity))
parsedPackages.Add(currentPackage + "@" + currentVersion) parsedPackages.Add(currentPackage + "@" + currentVersion)
} }
currentPackage = packageName currentPackage = packageName
} else if version := findPackageVersion(line); version != noVersion { } else if version := findPackageVersion(line); version != "" {
currentVersion = version currentVersion = version
} else if packageName, version := findPackageAndVersion(line); packageName != noPackage && version != noVersion && !parsedPackages.Has(packageName+"@"+version) { } else if packageName, version, resolved := findResolvedPackageAndVersion(line); packageName != "" && version != "" && resolved != "" {
pkgs = append(pkgs, newYarnLockPackage(a.cfg, resolver, reader.Location, packageName, version)) currentResolved = resolved
parsedPackages.Add(packageName + "@" + version) currentPackage = packageName
currentVersion = version
} else if integrity := findIntegrity(line); integrity != "" && !parsedPackages.Has(currentPackage+"@"+currentVersion) {
pkgs = append(pkgs, newYarnLockPackage(a.cfg, resolver, reader.Location, currentPackage, currentVersion, currentResolved, integrity))
parsedPackages.Add(currentPackage + "@" + currentVersion)
// Cleanup to indicate no unsaved identifiers // Cleanup to indicate no unsaved identifiers
currentPackage = noPackage currentPackage = ""
currentVersion = noVersion currentVersion = ""
currentResolved = ""
currentIntegrity = ""
} }
} }
// check if we have valid unsaved data after end-of-file has reached // check if we have valid unsaved data after end-of-file has reached
if currentPackage != noPackage && currentVersion != noVersion && !parsedPackages.Has(currentPackage+"@"+currentVersion) { if currentPackage != "" && currentVersion != "" && !parsedPackages.Has(currentPackage+"@"+currentVersion) {
pkgs = append(pkgs, newYarnLockPackage(a.cfg, resolver, reader.Location, currentPackage, currentVersion)) pkgs = append(pkgs, newYarnLockPackage(a.cfg, resolver, reader.Location, currentPackage, currentVersion, currentResolved, currentIntegrity))
parsedPackages.Add(currentPackage + "@" + currentVersion) parsedPackages.Add(currentPackage + "@" + currentVersion)
} }
@ -107,7 +120,7 @@ func findPackageName(line string) string {
return matches[1] return matches[1]
} }
return noPackage return ""
} }
func findPackageVersion(line string) string { func findPackageVersion(line string) string {
@ -115,13 +128,25 @@ func findPackageVersion(line string) string {
return matches[1] return matches[1]
} }
return noVersion return ""
} }
func findPackageAndVersion(line string) (string, string) { func findResolvedPackageAndVersion(line string) (string, string, string) {
var resolved string
if matches := resolvedExp.FindStringSubmatch(line); len(matches) >= 2 {
resolved = matches[1]
}
if matches := packageURLExp.FindStringSubmatch(line); len(matches) >= 2 { if matches := packageURLExp.FindStringSubmatch(line); len(matches) >= 2 {
return matches[1], matches[2] return matches[1], matches[2], resolved
} }
return noPackage, noVersion return "", "", ""
}
func findIntegrity(line string) string {
if matches := integrityExp.FindStringSubmatch(line); len(matches) >= 2 {
return matches[1]
}
return ""
} }

View File

@ -28,6 +28,7 @@ func TestParseYarnBerry(t *testing.T) {
PURL: "pkg:npm/%40babel/code-frame@7.10.4", PURL: "pkg:npm/%40babel/code-frame@7.10.4",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{},
}, },
{ {
Name: "@types/minimatch", Name: "@types/minimatch",
@ -36,6 +37,7 @@ func TestParseYarnBerry(t *testing.T) {
PURL: "pkg:npm/%40types/minimatch@3.0.3", PURL: "pkg:npm/%40types/minimatch@3.0.3",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{},
}, },
{ {
Name: "@types/qs", Name: "@types/qs",
@ -44,6 +46,7 @@ func TestParseYarnBerry(t *testing.T) {
PURL: "pkg:npm/%40types/qs@6.9.4", PURL: "pkg:npm/%40types/qs@6.9.4",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{},
}, },
{ {
Name: "ajv", Name: "ajv",
@ -52,6 +55,7 @@ func TestParseYarnBerry(t *testing.T) {
PURL: "pkg:npm/ajv@6.12.3", PURL: "pkg:npm/ajv@6.12.3",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{},
}, },
{ {
Name: "asn1.js", Name: "asn1.js",
@ -60,6 +64,7 @@ func TestParseYarnBerry(t *testing.T) {
PURL: "pkg:npm/asn1.js@4.10.1", PURL: "pkg:npm/asn1.js@4.10.1",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{},
}, },
{ {
Name: "atob", Name: "atob",
@ -68,6 +73,7 @@ func TestParseYarnBerry(t *testing.T) {
PURL: "pkg:npm/atob@2.1.2", PURL: "pkg:npm/atob@2.1.2",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{},
}, },
{ {
Name: "aws-sdk", Name: "aws-sdk",
@ -76,6 +82,7 @@ func TestParseYarnBerry(t *testing.T) {
Locations: locations, Locations: locations,
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{},
}, },
{ {
Name: "c0n-fab_u.laTION", Name: "c0n-fab_u.laTION",
@ -84,6 +91,7 @@ func TestParseYarnBerry(t *testing.T) {
PURL: "pkg:npm/c0n-fab_u.laTION@7.7.7", PURL: "pkg:npm/c0n-fab_u.laTION@7.7.7",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{},
}, },
{ {
Name: "jhipster-core", Name: "jhipster-core",
@ -92,6 +100,7 @@ func TestParseYarnBerry(t *testing.T) {
PURL: "pkg:npm/jhipster-core@7.3.4", PURL: "pkg:npm/jhipster-core@7.3.4",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{},
}, },
} }
@ -112,6 +121,10 @@ func TestParseYarnLock(t *testing.T) {
PURL: "pkg:npm/%40babel/code-frame@7.10.4", PURL: "pkg:npm/%40babel/code-frame@7.10.4",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{
Resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a",
Integrity: "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
},
}, },
{ {
Name: "@types/minimatch", Name: "@types/minimatch",
@ -120,6 +133,10 @@ func TestParseYarnLock(t *testing.T) {
PURL: "pkg:npm/%40types/minimatch@3.0.3", PURL: "pkg:npm/%40types/minimatch@3.0.3",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{
Resolved: "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d",
Integrity: "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
},
}, },
{ {
Name: "@types/qs", Name: "@types/qs",
@ -128,6 +145,10 @@ func TestParseYarnLock(t *testing.T) {
PURL: "pkg:npm/%40types/qs@6.9.4", PURL: "pkg:npm/%40types/qs@6.9.4",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{
Resolved: "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.4.tgz#a59e851c1ba16c0513ea123830dd639a0a15cb6a",
Integrity: "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==",
},
}, },
{ {
Name: "ajv", Name: "ajv",
@ -136,6 +157,10 @@ func TestParseYarnLock(t *testing.T) {
PURL: "pkg:npm/ajv@6.12.3", PURL: "pkg:npm/ajv@6.12.3",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{
Resolved: "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706",
Integrity: "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
},
}, },
{ {
Name: "asn1.js", Name: "asn1.js",
@ -144,6 +169,10 @@ func TestParseYarnLock(t *testing.T) {
PURL: "pkg:npm/asn1.js@4.10.1", PURL: "pkg:npm/asn1.js@4.10.1",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{
Resolved: "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0",
Integrity: "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
},
}, },
{ {
Name: "atob", Name: "atob",
@ -153,6 +182,10 @@ func TestParseYarnLock(t *testing.T) {
PURL: "pkg:npm/atob@2.1.2", PURL: "pkg:npm/atob@2.1.2",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{
Resolved: "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9",
Integrity: "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
},
}, },
{ {
Name: "aws-sdk", Name: "aws-sdk",
@ -161,6 +194,10 @@ func TestParseYarnLock(t *testing.T) {
PURL: "pkg:npm/aws-sdk@2.706.0", PURL: "pkg:npm/aws-sdk@2.706.0",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{
Resolved: "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.706.0.tgz#09f65e9a91ecac5a635daf934082abae30eca953",
Integrity: "sha512-7GT+yrB5Wb/zOReRdv/Pzkb2Qt+hz6B/8FGMVaoysX3NryHvQUdz7EQWi5yhg9CxOjKxdw5lFwYSs69YlSp1KA==",
},
}, },
{ {
Name: "jhipster-core", Name: "jhipster-core",
@ -169,8 +206,11 @@ func TestParseYarnLock(t *testing.T) {
PURL: "pkg:npm/jhipster-core@7.3.4", PURL: "pkg:npm/jhipster-core@7.3.4",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{
Resolved: "https://registry.yarnpkg.com/jhipster-core/-/jhipster-core-7.3.4.tgz#c34b8c97c7f4e8b7518dae015517e2112c73cc80",
Integrity: "sha512-AUhT69kNkqppaJZVfan/xnKG4Gs9Ggj7YLtTZFVe+xg+THrbMb5Ng7PL07PDlDw4KAEA33GMCwuAf65E8EpC4g==",
},
}, },
{ {
Name: "something-i-made-up", Name: "something-i-made-up",
Version: "7.7.7", Version: "7.7.7",
@ -178,6 +218,10 @@ func TestParseYarnLock(t *testing.T) {
PURL: "pkg:npm/something-i-made-up@7.7.7", PURL: "pkg:npm/something-i-made-up@7.7.7",
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{
Resolved: "https://registry.yarnpkg.com/something-i-made-up/-/c0n-fab_u.laTION-7.7.7.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0",
Integrity: "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
},
}, },
} }
@ -221,6 +265,10 @@ func TestSearchYarnForLicenses(t *testing.T) {
Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")),
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
Metadata: pkg.YarnLockEntry{
Resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a",
Integrity: "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
},
}, },
}, },
}, },

View File

@ -25,7 +25,7 @@ func newPackageForIndex(name, version string, locations ...file.Location) pkg.Pa
return p return p
} }
func newPackageForIndexWithMetadata(name, version string, metadata pkg.PythonPipfileLockEntry, locations ...file.Location) pkg.Package { func newPackageForIndexWithMetadata(name, version string, metadata interface{}, locations ...file.Location) pkg.Package {
p := pkg.Package{ p := pkg.Package{
Name: name, Name: name,
Version: version, Version: version,

View File

@ -62,7 +62,7 @@ func parsePipfileLock(_ context.Context, _ file.Resolver, _ *generic.Environment
if pkgMeta.Index != "" { if pkgMeta.Index != "" {
index = sourcesMap[pkgMeta.Index] index = sourcesMap[pkgMeta.Index]
} else { } else {
// https://pipenv.pypa.io/en/latest/advanced/#specifying-package-indexes // https://pipenv.pypa.io/en/latest/indexes.html
index = "https://pypi.org/simple" index = "https://pypi.org/simple"
} }
version := strings.TrimPrefix(pkgMeta.Version, "==") version := strings.TrimPrefix(pkgMeta.Version, "==")

View File

@ -15,13 +15,18 @@ import (
// integrity check // integrity check
var _ generic.Parser = parsePoetryLock var _ generic.Parser = parsePoetryLock
type poetryMetadata struct { type poetryPackageSource struct {
URL string `toml:"url"`
}
type poetryPackages struct {
Packages []struct { Packages []struct {
Name string `toml:"name"` Name string `toml:"name"`
Version string `toml:"version"` Version string `toml:"version"`
Category string `toml:"category"` Category string `toml:"category"`
Description string `toml:"description"` Description string `toml:"description"`
Optional bool `toml:"optional"` Optional bool `toml:"optional"`
Source poetryPackageSource `toml:"source"`
} `toml:"package"` } `toml:"package"`
} }
@ -32,7 +37,7 @@ func parsePoetryLock(_ context.Context, _ file.Resolver, _ *generic.Environment,
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)
} }
metadata := poetryMetadata{} metadata := poetryPackages{}
err = tree.Unmarshal(&metadata) err = tree.Unmarshal(&metadata)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("unable to parse poetry.lock: %w", err) return nil, nil, fmt.Errorf("unable to parse poetry.lock: %w", err)
@ -40,11 +45,19 @@ func parsePoetryLock(_ context.Context, _ file.Resolver, _ *generic.Environment,
var pkgs []pkg.Package var pkgs []pkg.Package
for _, p := range metadata.Packages { for _, p := range metadata.Packages {
var index string
if p.Source.URL != "" {
index = p.Source.URL
} else {
// https://python-poetry.org/docs/repositories/
index = "https://pypi.org/simple"
}
pkgs = append( pkgs = append(
pkgs, pkgs,
newPackageForIndex( newPackageForIndexWithMetadata(
p.Name, p.Name,
p.Version, p.Version,
pkg.PythonPoetryLockEntry{Index: index},
reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
), ),
) )

View File

@ -20,6 +20,7 @@ func TestParsePoetryLock(t *testing.T) {
Locations: locations, Locations: locations,
Language: pkg.Python, Language: pkg.Python,
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPoetryLockEntry{Index: "https://test.pypi.org/simple"},
}, },
{ {
Name: "alabaster", Name: "alabaster",
@ -28,6 +29,7 @@ func TestParsePoetryLock(t *testing.T) {
Locations: locations, Locations: locations,
Language: pkg.Python, Language: pkg.Python,
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"},
}, },
{ {
Name: "appnope", Name: "appnope",
@ -36,6 +38,7 @@ func TestParsePoetryLock(t *testing.T) {
Locations: locations, Locations: locations,
Language: pkg.Python, Language: pkg.Python,
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"},
}, },
{ {
Name: "asciitree", Name: "asciitree",
@ -44,6 +47,7 @@ func TestParsePoetryLock(t *testing.T) {
Locations: locations, Locations: locations,
Language: pkg.Python, Language: pkg.Python,
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"},
}, },
} }

View File

@ -12,6 +12,11 @@ natsort = "*"
six = "*" six = "*"
sphinx = "*" sphinx = "*"
[package.source]
type = "legacy"
url = "https://test.pypi.org/simple"
reference = "test"
[package.extras] [package.extras]
deploy = ["bumpversion", "twine", "wheel"] deploy = ["bumpversion", "twine", "wheel"]
docs = ["sphinx", "sphinx-rtd-theme"] docs = ["sphinx", "sphinx-rtd-theme"]

View File

@ -16,3 +16,9 @@ type NpmPackageLockEntry struct {
Resolved string `mapstructure:"resolved" json:"resolved"` Resolved string `mapstructure:"resolved" json:"resolved"`
Integrity string `mapstructure:"integrity" json:"integrity"` Integrity string `mapstructure:"integrity" json:"integrity"`
} }
// YarnLockEntry represents a single entry section of a yarn.lock file.
type YarnLockEntry struct {
Resolved string `mapstructure:"resolved" json:"resolved"`
Integrity string `mapstructure:"integrity" json:"integrity"`
}

View File

@ -61,6 +61,11 @@ type PythonPipfileLockEntry struct {
Index string `mapstructure:"index" json:"index"` Index string `mapstructure:"index" json:"index"`
} }
// PythonPoetryLockEntry represents a single package entry within a Pipfile.lock file.
type PythonPoetryLockEntry struct {
Index string `mapstructure:"index" json:"index"`
}
// PythonRequirementsEntry represents a single entry within a [*-]requirements.txt file. // PythonRequirementsEntry represents a single entry within a [*-]requirements.txt file.
type PythonRequirementsEntry struct { type PythonRequirementsEntry struct {
Name string `json:"name" mapstruct:"Name"` Name string `json:"name" mapstruct:"Name"`