@cdxgen/cdxgen 13.4.0 → 13.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/bin/cdxgen-secure.js +15 -0
- package/bin/cdxgen.js +29 -5
- package/bin/evinse.js +8 -0
- package/bin/hbom.js +15 -7
- package/bin/repl.js +29 -0
- package/bin/validate.js +6 -0
- package/data/cbomosdb-queries.json +13 -1
- package/data/component-tags.json +8 -0
- package/data/license-aliases.json +24 -2
- package/data/queries-darwin.json +25 -1
- package/data/queries-win.json +19 -1
- package/data/queries.json +41 -0
- package/data/remediations.json +407 -1
- package/data/rules/ai-bom.yaml +1 -1
- package/data/rules/brotli-decoder.yaml +107 -0
- package/data/rules/cbom-security.yaml +235 -4
- package/data/rules/go-binaries.yaml +46 -0
- package/data/rules/golem-go.yaml +80 -0
- package/data/rules/hbom-compliance.yaml +40 -22
- package/data/rules/hbom-performance.yaml +7 -1
- package/data/rules/host-topology.yaml +1 -1
- package/data/rules/obom-runtime.yaml +31 -2
- package/data/rules/php-runtime.yaml +143 -0
- package/data/rules/vscode-extensions.yaml +75 -0
- package/data/spdx-license-list.json +121 -7
- package/data/spdx-licenses.json +69 -0
- package/data/spdx.schema.json +845 -2
- package/lib/audit/index.js +14 -0
- package/lib/cli/bomAssembly.js +120 -6
- package/lib/cli/cliOptions.js +110 -3
- package/lib/cli/index.js +182 -6
- package/lib/cli/jsBom.js +153 -64
- package/lib/cli/jvmBom.js +363 -66
- package/lib/cli/managedBom.js +853 -87
- package/lib/cli/nativeBom.js +267 -33
- package/lib/core/boundedFile.js +344 -0
- package/lib/core/brotliProbe.js +182 -0
- package/lib/core/env.js +38 -8
- package/lib/core/fs.js +40 -19
- package/lib/core/httpClient.js +172 -46
- package/lib/core/lockPaths.js +38 -0
- package/lib/core/paths.js +24 -1
- package/lib/core/processTree.js +5 -0
- package/lib/core/projectConfig.js +1 -0
- package/lib/core/projectTooling.js +97 -0
- package/lib/core/propertySanitizer.js +72 -0
- package/lib/core/toolRegistry.js +170 -0
- package/lib/ecosystems/cppEvidence.js +263 -106
- package/lib/ecosystems/cppIncludeResolver.js +16 -5
- package/lib/ecosystems/ecosystems.js +25 -10
- package/lib/ecosystems/gemHostProbe.js +301 -0
- package/lib/ecosystems/golem.js +550 -6
- package/lib/ecosystems/gradleutils.js +858 -244
- package/lib/ecosystems/parsers-bazel.js +107 -6
- package/lib/ecosystems/parsers-dotnet.js +117 -18
- package/lib/ecosystems/parsers-go.js +1090 -367
- package/lib/ecosystems/parsers-js.js +505 -22
- package/lib/ecosystems/parsers-jvm.js +259 -17
- package/lib/ecosystems/parsers-misc.js +438 -64
- package/lib/ecosystems/parsers-python.js +100 -12
- package/lib/ecosystems/pythonutils.js +128 -2
- package/lib/ecosystems/rubyutils.js +544 -34
- package/lib/ecosystems/rusi.js +10 -0
- package/lib/ecosystems/scalacliutils.js +4 -1
- package/lib/ecosystems/scalasem.js +798 -151
- package/lib/ecosystems/vendoredCode.js +237 -3
- package/lib/ecosystems/venvProbe.js +360 -0
- package/lib/evinser/evinser.js +472 -61
- package/lib/evinser/swiftsem.js +68 -5
- package/lib/helpers/agenticToolutils.js +413 -93
- package/lib/helpers/vsixutils.js +1574 -315
- package/lib/inventory/agentSkillSpec.js +17 -0
- package/lib/inventory/apkInstalledDb.js +243 -0
- package/lib/inventory/atomUtils.js +110 -0
- package/lib/inventory/auditCategories.js +3 -3
- package/lib/inventory/brotliDecoder.js +142 -0
- package/lib/inventory/buildToolRateLimit.js +1 -1
- package/lib/inventory/cacheDir.js +52 -9
- package/lib/inventory/cbomutils.js +56 -7
- package/lib/inventory/certificates.js +2371 -0
- package/lib/inventory/communityAiConfigParser.js +4 -9
- package/lib/inventory/deps.js +41 -4
- package/lib/inventory/display.js +200 -3
- package/lib/inventory/dosai.js +639 -63
- package/lib/inventory/dotnetRuntime.js +217 -0
- package/lib/inventory/dynamic.js +45 -3
- package/lib/inventory/envcontext.js +475 -18
- package/lib/inventory/evidenceUtils.js +447 -23
- package/lib/inventory/fetchBatch.js +1 -1
- package/lib/inventory/formulationParsers.js +32 -3
- package/lib/inventory/goBuildInfo.js +140 -0
- package/lib/inventory/gtfobins.js +13 -0
- package/lib/inventory/hbom.js +67 -7
- package/lib/inventory/hbomAnalysis.js +16 -0
- package/lib/inventory/hostRuntimeProbe.js +686 -0
- package/lib/inventory/hostTopology.js +21 -0
- package/lib/inventory/jvmLocalRepos.js +9 -2
- package/lib/inventory/jvmToolEnv.js +29 -0
- package/lib/inventory/licenseEnhancer.js +12 -0
- package/lib/inventory/mavenCentralMirror.js +534 -0
- package/lib/inventory/nodeBuildInfo.js +218 -0
- package/lib/inventory/nodeHostProbe.js +202 -0
- package/lib/inventory/osPackagePurl.js +244 -0
- package/lib/inventory/osPackageResolver.js +271 -87
- package/lib/inventory/osinfo.js +79 -31
- package/lib/inventory/osqueryTransform.js +114 -5
- package/lib/inventory/phpBuildInfo.js +438 -0
- package/lib/inventory/phpHostProbe.js +185 -0
- package/lib/inventory/rootfsCerts.js +426 -0
- package/lib/inventory/rubyBuildInfo.js +972 -0
- package/lib/inventory/rubyHostProbe.js +218 -0
- package/lib/inventory/scalaCoords.js +4 -3
- package/lib/inventory/scalaDedupe.js +440 -0
- package/lib/inventory/source.js +256 -5
- package/lib/inventory/spdx.js +144 -0
- package/lib/inventory/traceRunner.js +5 -1
- package/lib/inventory/tracedCrypto.js +129 -0
- package/lib/managers/binary.js +866 -186
- package/lib/managers/docker.js +245 -12
- package/lib/parsers/email.js +277 -0
- package/lib/parsers/largeJson.js +62 -13
- package/lib/parsers/vscodeExtensionId.js +183 -0
- package/lib/server/server.js +198 -2
- package/lib/stages/postgen/annotator.js +17 -1
- package/lib/stages/postgen/introspection/reflect.js +4 -1
- package/lib/stages/postgen/postgen.js +5 -5
- package/lib/stages/postgen/ruleEngine.js +71 -6
- package/lib/stages/postgen/specVersionCompat.js +30 -0
- package/lib/stages/pregen/envAudit.js +1 -0
- package/lib/stages/pregen/pregen.js +231 -62
- package/lib/validator/bomValidator.js +32 -6
- package/lib/validator/generated/runtime.mjs +13 -0
- package/lib/validator/generated/validate-1.6.mjs +27 -8
- package/lib/validator/generated/validate-1.7.mjs +32 -13
- package/lib/validator/generated/validate-2.0.mjs +31 -12
- package/lib/validator/index.js +1 -1
- package/package.json +19 -18
- package/types/bin/cdxgen-secure.d.ts +3 -0
- package/types/bin/cdxgen-secure.d.ts.map +1 -0
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +22 -3
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +43 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts +1 -17
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +20 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/boundedFile.d.ts +70 -0
- package/types/lib/core/boundedFile.d.ts.map +1 -0
- package/types/lib/core/brotliProbe.d.ts +37 -0
- package/types/lib/core/brotliProbe.d.ts.map +1 -0
- package/types/lib/core/env.d.ts +22 -2
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/httpClient.d.ts +24 -0
- package/types/lib/core/httpClient.d.ts.map +1 -1
- package/types/lib/core/lockPaths.d.ts +19 -0
- package/types/lib/core/lockPaths.d.ts.map +1 -0
- package/types/lib/core/processTree.d.ts +2 -0
- package/types/lib/core/processTree.d.ts.map +1 -1
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/projectTooling.d.ts +41 -0
- package/types/lib/core/projectTooling.d.ts.map +1 -0
- package/types/lib/core/propertySanitizer.d.ts +26 -0
- package/types/lib/core/propertySanitizer.d.ts.map +1 -1
- package/types/lib/core/toolRegistry.d.ts +36 -0
- package/types/lib/core/toolRegistry.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +40 -13
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts +2 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -1
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
- package/types/lib/ecosystems/gemHostProbe.d.ts +28 -0
- package/types/lib/ecosystems/gemHostProbe.d.ts.map +1 -0
- package/types/lib/ecosystems/golem.d.ts +81 -1
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +57 -21
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-dotnet.d.ts +40 -4
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-go.d.ts +85 -13
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +17 -20
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-jvm.d.ts +28 -2
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +37 -58
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +14 -3
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +19 -1
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts +144 -12
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -1
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
- package/types/lib/ecosystems/vendoredCode.d.ts +26 -0
- package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -1
- package/types/lib/ecosystems/venvProbe.d.ts +40 -0
- package/types/lib/ecosystems/venvProbe.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +88 -8
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/swiftsem.d.ts +10 -0
- package/types/lib/evinser/swiftsem.d.ts.map +1 -1
- package/types/lib/inventory/agentSkillSpec.d.ts +13 -0
- package/types/lib/inventory/agentSkillSpec.d.ts.map +1 -0
- package/types/lib/inventory/apkInstalledDb.d.ts +42 -0
- package/types/lib/inventory/apkInstalledDb.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +33 -0
- package/types/lib/inventory/atomUtils.d.ts.map +1 -1
- package/types/lib/inventory/brotliDecoder.d.ts +58 -0
- package/types/lib/inventory/brotliDecoder.d.ts.map +1 -0
- package/types/lib/inventory/cacheDir.d.ts +12 -4
- package/types/lib/inventory/cacheDir.d.ts.map +1 -1
- package/types/lib/inventory/cbomutils.d.ts +17 -0
- package/types/lib/inventory/cbomutils.d.ts.map +1 -1
- package/types/lib/inventory/certificates.d.ts +205 -0
- package/types/lib/inventory/certificates.d.ts.map +1 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/deps.d.ts +2 -1
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/display.d.ts +18 -0
- package/types/lib/inventory/display.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +162 -7
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dotnetRuntime.d.ts +44 -0
- package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -0
- package/types/lib/inventory/dynamic.d.ts +6 -1
- package/types/lib/inventory/dynamic.d.ts.map +1 -1
- package/types/lib/inventory/envcontext.d.ts +92 -8
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts +29 -10
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/goBuildInfo.d.ts +10 -0
- package/types/lib/inventory/goBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/gtfobins.d.ts.map +1 -1
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomAnalysis.d.ts +10 -0
- package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -1
- package/types/lib/inventory/hostRuntimeProbe.d.ts +44 -0
- package/types/lib/inventory/hostRuntimeProbe.d.ts.map +1 -0
- package/types/lib/inventory/hostTopology.d.ts.map +1 -1
- package/types/lib/inventory/jvmToolEnv.d.ts +12 -0
- package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
- package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -1
- package/types/lib/inventory/mavenCentralMirror.d.ts +170 -0
- package/types/lib/inventory/mavenCentralMirror.d.ts.map +1 -0
- package/types/lib/inventory/nodeBuildInfo.d.ts +95 -0
- package/types/lib/inventory/nodeBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/nodeHostProbe.d.ts +15 -0
- package/types/lib/inventory/nodeHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/osPackagePurl.d.ts +99 -0
- package/types/lib/inventory/osPackagePurl.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +44 -2
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
- package/types/lib/inventory/osinfo.d.ts +31 -6
- package/types/lib/inventory/osinfo.d.ts.map +1 -1
- package/types/lib/inventory/osqueryTransform.d.ts +51 -0
- package/types/lib/inventory/osqueryTransform.d.ts.map +1 -1
- package/types/lib/inventory/phpBuildInfo.d.ts +142 -0
- package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/phpHostProbe.d.ts +35 -0
- package/types/lib/inventory/phpHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/rootfsCerts.d.ts +27 -0
- package/types/lib/inventory/rootfsCerts.d.ts.map +1 -0
- package/types/lib/inventory/rubyBuildInfo.d.ts +271 -0
- package/types/lib/inventory/rubyBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/rubyHostProbe.d.ts +47 -0
- package/types/lib/inventory/rubyHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +38 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/inventory/spdx.d.ts +15 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -1
- package/types/lib/inventory/traceRunner.d.ts +4 -1
- package/types/lib/inventory/traceRunner.d.ts.map +1 -1
- package/types/lib/inventory/tracedCrypto.d.ts +22 -0
- package/types/lib/inventory/tracedCrypto.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts +10 -0
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +24 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/parsers/email.d.ts +19 -0
- package/types/lib/parsers/email.d.ts.map +1 -0
- package/types/lib/parsers/largeJson.d.ts +17 -3
- package/types/lib/parsers/largeJson.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +8 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/introspection/reflect.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts +7 -4
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +26 -9
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { basename, dirname, join, relative } from "node:path";
|
|
3
|
-
import process from "node:process";
|
|
4
3
|
import { URL } from "node:url";
|
|
5
4
|
|
|
6
5
|
import { build } from "@cdxgen/cdx-purl";
|
|
@@ -889,6 +888,61 @@ export function enrichFromInstalledMetadata(pkgList, installedMetadata) {
|
|
|
889
888
|
return enriched;
|
|
890
889
|
}
|
|
891
890
|
|
|
891
|
+
// The interpreter cdxgen assumes for a lock file's environment. A marker that
|
|
892
|
+
// tests the implementation against it is decidable without a target machine.
|
|
893
|
+
const IMPLEMENTATION_CLAUSE_RE =
|
|
894
|
+
/^(platform_python_implementation|implementation_name)\s*(==|!=)\s*(['"])([A-Za-z]+)\3$/;
|
|
895
|
+
|
|
896
|
+
function implementationClauseIsFalse(clause) {
|
|
897
|
+
const match = IMPLEMENTATION_CLAUSE_RE.exec(clause.trim());
|
|
898
|
+
if (!match) {
|
|
899
|
+
return false;
|
|
900
|
+
}
|
|
901
|
+
const expected = match[1] === "implementation_name" ? "cpython" : "CPython";
|
|
902
|
+
const equal = match[4] === expected;
|
|
903
|
+
return match[2] === "==" ? !equal : equal;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* Whether an environment marker is false for every CPython interpreter. Only
|
|
908
|
+
* `platform_python_implementation` and `implementation_name` clauses are
|
|
909
|
+
* decided; anything else, or a marker with parentheses, is treated as possibly
|
|
910
|
+
* true, so the answer errs towards keeping a package.
|
|
911
|
+
*
|
|
912
|
+
* @param {string} marker PEP 508 environment marker
|
|
913
|
+
* @returns {boolean} true when no CPython environment satisfies the marker
|
|
914
|
+
*/
|
|
915
|
+
export function markerExcludesCPython(marker) {
|
|
916
|
+
if (typeof marker !== "string" || !marker.trim() || /[()]/.test(marker)) {
|
|
917
|
+
return false;
|
|
918
|
+
}
|
|
919
|
+
return marker
|
|
920
|
+
.split(/\s+or\s+/)
|
|
921
|
+
.every((disjunct) =>
|
|
922
|
+
disjunct.split(/\s+and\s+/).some(implementationClauseIsFalse),
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
function recordMarkerEdge(markerEdges, depKey, apkgDep) {
|
|
927
|
+
if (!depKey) {
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
const edge = markerEdges.get(depKey) || {
|
|
931
|
+
total: 0,
|
|
932
|
+
cpythonExcluded: 0,
|
|
933
|
+
markers: new Set(),
|
|
934
|
+
};
|
|
935
|
+
edge.total += 1;
|
|
936
|
+
const marker = typeof apkgDep === "object" ? apkgDep?.marker : undefined;
|
|
937
|
+
if (typeof marker === "string" && marker.trim()) {
|
|
938
|
+
edge.markers.add(marker.trim());
|
|
939
|
+
if (markerExcludesCPython(marker)) {
|
|
940
|
+
edge.cpythonExcluded += 1;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
markerEdges.set(depKey, edge);
|
|
944
|
+
}
|
|
945
|
+
|
|
892
946
|
/**
|
|
893
947
|
* Method to parse python lock files such as poetry.lock, pdm.lock, uv.lock, and pylock.toml.
|
|
894
948
|
*
|
|
@@ -912,6 +966,8 @@ export async function parsePyLockData(
|
|
|
912
966
|
const depsMap = {};
|
|
913
967
|
const existingPkgMap = {};
|
|
914
968
|
const pkgBomRefMap = {};
|
|
969
|
+
// Incoming edges per dependency, with the environment markers they carry.
|
|
970
|
+
const markerEdges = new Map();
|
|
915
971
|
let directDepsKeys = {};
|
|
916
972
|
let groupDepsKeys = {};
|
|
917
973
|
let dependencySourceMap = {};
|
|
@@ -1335,9 +1391,16 @@ export async function parsePyLockData(
|
|
|
1335
1391
|
devDependencies.length ||
|
|
1336
1392
|
optionalDependencies.length
|
|
1337
1393
|
) {
|
|
1338
|
-
|
|
1394
|
+
// A package whose only dependencies are optional (urllib3 has no
|
|
1395
|
+
// required ones, only the `brotli`, `socks` and `zstd` extras) has no
|
|
1396
|
+
// `dependencies` key in uv.lock, but its extras are still edges.
|
|
1397
|
+
if (
|
|
1398
|
+
Array.isArray(apkg.dependencies) ||
|
|
1399
|
+
(!apkg.dependencies &&
|
|
1400
|
+
(devDependencies.length || optionalDependencies.length))
|
|
1401
|
+
) {
|
|
1339
1402
|
// pdm.lock files
|
|
1340
|
-
let allDeps = apkg.dependencies;
|
|
1403
|
+
let allDeps = apkg.dependencies || [];
|
|
1341
1404
|
allDeps = allDeps.concat(devDependencies);
|
|
1342
1405
|
allDeps = allDeps.concat(optionalDependencies);
|
|
1343
1406
|
for (const apkgDep of allDeps) {
|
|
@@ -1349,6 +1412,7 @@ export async function parsePyLockData(
|
|
|
1349
1412
|
const depPkgRef =
|
|
1350
1413
|
existingPkgMap[nameLower] || existingPkgMap[nameStr];
|
|
1351
1414
|
depsMap[pkg["bom-ref"]].add(depPkgRef || nameStr);
|
|
1415
|
+
recordMarkerEdge(markerEdges, depPkgRef || nameLower, apkgDep);
|
|
1352
1416
|
// Propagate the workspace properties to the child components
|
|
1353
1417
|
if (depPkgRef && pkgBomRefMap[depPkgRef]) {
|
|
1354
1418
|
const dependentPkg = pkgBomRefMap[depPkgRef];
|
|
@@ -1422,6 +1486,28 @@ export async function parsePyLockData(
|
|
|
1422
1486
|
}
|
|
1423
1487
|
}
|
|
1424
1488
|
}
|
|
1489
|
+
// A package reached only through edges whose environment marker excludes
|
|
1490
|
+
// CPython (brotlicffi is `platform_python_implementation != 'CPython'`) is
|
|
1491
|
+
// not installed by a CPython environment built from this lock, so it is
|
|
1492
|
+
// optional rather than part of the CPython closure. A direct dependency of
|
|
1493
|
+
// the project is left alone: the manifest asked for it.
|
|
1494
|
+
for (const [depRef, edge] of markerEdges) {
|
|
1495
|
+
const dependentPkg = pkgBomRefMap[depRef];
|
|
1496
|
+
if (
|
|
1497
|
+
!dependentPkg ||
|
|
1498
|
+
!edge.total ||
|
|
1499
|
+
edge.cpythonExcluded !== edge.total ||
|
|
1500
|
+
directDepsKeys[normalizePythonDependencyKey(dependentPkg.name)]
|
|
1501
|
+
) {
|
|
1502
|
+
continue;
|
|
1503
|
+
}
|
|
1504
|
+
dependentPkg.scope = "optional";
|
|
1505
|
+
dependentPkg.properties = dependentPkg.properties || [];
|
|
1506
|
+
dependentPkg.properties.push({
|
|
1507
|
+
name: "cdx:pip:markers",
|
|
1508
|
+
value: Array.from(edge.markers).sort().join(" or "),
|
|
1509
|
+
});
|
|
1510
|
+
}
|
|
1425
1511
|
// Seed the parent component's first-level edges from the manifest. Lock
|
|
1426
1512
|
// files describe the resolved closure but do not say which of the locked
|
|
1427
1513
|
// packages the root project directly depends on; parsePyProjectTomlFile
|
|
@@ -2205,28 +2291,30 @@ export function parsePixiTomlFile(pixiToml) {
|
|
|
2205
2291
|
}
|
|
2206
2292
|
|
|
2207
2293
|
/**
|
|
2208
|
-
* Method to run cli command `pixi install`
|
|
2209
|
-
*
|
|
2294
|
+
* Method to run cli command `pixi install` in the project directory.
|
|
2210
2295
|
*
|
|
2296
|
+
* @param {string} projectPath Directory containing pixi.toml
|
|
2297
|
+
* @returns {boolean} true when pixi install succeeded
|
|
2211
2298
|
*/
|
|
2212
|
-
export function generatePixiLockFile(
|
|
2213
|
-
const result = safeSpawnSync("pixi", ["install"]);
|
|
2299
|
+
export function generatePixiLockFile(projectPath) {
|
|
2300
|
+
const result = safeSpawnSync("pixi", ["install"], { cwd: projectPath });
|
|
2214
2301
|
|
|
2215
2302
|
if (result.status !== 0) {
|
|
2216
|
-
// Handle errors
|
|
2303
|
+
// Handle errors. The caller carries on without a lock file: exiting here
|
|
2304
|
+
// would also stop a long-running cdxgen server.
|
|
2217
2305
|
if (result.error && result.error.code === "ENOENT") {
|
|
2218
2306
|
console.error(
|
|
2219
2307
|
"Error: pixi command not found. Make sure pixi.js is installed globally.",
|
|
2220
2308
|
);
|
|
2221
2309
|
} else {
|
|
2222
2310
|
console.error(
|
|
2223
|
-
`Error executing pixi install: ${result.error || result.stderr
|
|
2311
|
+
`Error executing pixi install: ${result.error || result.stderr?.toString()}`,
|
|
2224
2312
|
);
|
|
2225
2313
|
}
|
|
2226
|
-
|
|
2227
|
-
} else {
|
|
2228
|
-
console.log("Dependencies installed successfully.");
|
|
2314
|
+
return false;
|
|
2229
2315
|
}
|
|
2316
|
+
console.log("Dependencies installed successfully.");
|
|
2317
|
+
return true;
|
|
2230
2318
|
}
|
|
2231
2319
|
|
|
2232
2320
|
/**
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import process from "node:process";
|
|
12
12
|
|
|
13
13
|
import { build } from "@cdxgen/cdx-purl";
|
|
14
|
+
import { coerce, gte } from "semver";
|
|
14
15
|
|
|
15
16
|
import {
|
|
16
17
|
DEBUG_MODE,
|
|
@@ -25,6 +26,7 @@ import {
|
|
|
25
26
|
PYPI_MODULE_PACKAGE_MAPPING,
|
|
26
27
|
PYTHON_STD_MODULES,
|
|
27
28
|
} from "../core/state.js";
|
|
29
|
+
import { parseToml } from "../core/toml.js";
|
|
28
30
|
import { findAppModules } from "../inventory/atomUtils.js";
|
|
29
31
|
import { flattenDeps } from "../inventory/deps.js";
|
|
30
32
|
import { pypiBomRef } from "../inventory/purl.js";
|
|
@@ -612,6 +614,128 @@ export function createUVLock(basePath, options) {
|
|
|
612
614
|
}
|
|
613
615
|
}
|
|
614
616
|
|
|
617
|
+
const CONSTRAINT_OPERATORS = [">=", "<=", "==", "!=", "~=", ">", "<", "^", "="];
|
|
618
|
+
const LOWER_BOUND_OPERATORS = new Set([">=", ">", "==", "~=", "^", "="]);
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Check whether a single version constraint puts the lower bound at version 2
|
|
622
|
+
* or higher.
|
|
623
|
+
*
|
|
624
|
+
* @param {string} constraint Constraint such as ">=2.0.0" or "<3.0.0"
|
|
625
|
+
* @returns {boolean} true when the constraint requires version 2 or newer
|
|
626
|
+
*/
|
|
627
|
+
function requiresVersion2(constraint) {
|
|
628
|
+
let operator = "";
|
|
629
|
+
let version = constraint.trim();
|
|
630
|
+
for (const candidate of CONSTRAINT_OPERATORS) {
|
|
631
|
+
if (version.startsWith(candidate)) {
|
|
632
|
+
operator = candidate;
|
|
633
|
+
version = version.slice(candidate.length).trim();
|
|
634
|
+
break;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
if (!operator || !LOWER_BOUND_OPERATORS.has(operator)) {
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
const coerced = coerce(version);
|
|
641
|
+
return coerced !== null && gte(coerced, "2.0.0");
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Check whether a build requirement names poetry-core with a lower bound of
|
|
646
|
+
* version 2 or higher.
|
|
647
|
+
*
|
|
648
|
+
* @param {string} requirement Build requirement such as "poetry-core>=2.0.0"
|
|
649
|
+
* @returns {boolean} true when poetry-core 2 or newer is required
|
|
650
|
+
*/
|
|
651
|
+
function requiresPoetryCore2(requirement) {
|
|
652
|
+
if (typeof requirement !== "string") {
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
const entry = requirement.trim().toLowerCase();
|
|
656
|
+
if (!entry.startsWith("poetry-core")) {
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
let spec = entry.slice("poetry-core".length);
|
|
660
|
+
if (spec.startsWith("[")) {
|
|
661
|
+
const extrasEnd = spec.indexOf("]");
|
|
662
|
+
if (extrasEnd === -1) {
|
|
663
|
+
return false;
|
|
664
|
+
}
|
|
665
|
+
spec = spec.slice(extrasEnd + 1);
|
|
666
|
+
}
|
|
667
|
+
const next = spec.charAt(0);
|
|
668
|
+
if (next && next !== " " && next !== "\t" && !"><=!~^".includes(next)) {
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
return spec
|
|
672
|
+
.trim()
|
|
673
|
+
.split(",")
|
|
674
|
+
.some((constraint) => requiresVersion2(constraint));
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Check whether a pyproject.toml requires poetry-core 2 or newer to build.
|
|
679
|
+
*
|
|
680
|
+
* @param {string} pyprojectFile Path to pyproject.toml
|
|
681
|
+
* @returns {boolean} true when the project needs Poetry 2 or newer
|
|
682
|
+
*/
|
|
683
|
+
export function isPoetry2Project(pyprojectFile) {
|
|
684
|
+
if (!pyprojectFile || !safeExistsSync(pyprojectFile)) {
|
|
685
|
+
return false;
|
|
686
|
+
}
|
|
687
|
+
let config;
|
|
688
|
+
try {
|
|
689
|
+
config = parseToml(readFileSync(pyprojectFile, "utf-8"));
|
|
690
|
+
} catch (_err) {
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
const requires = config?.["build-system"]?.requires;
|
|
694
|
+
if (!Array.isArray(requires)) {
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
return requires.some((requirement) => requiresPoetryCore2(requirement));
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Find the pyproject.toml belonging to a poetry trigger file.
|
|
702
|
+
*
|
|
703
|
+
* @param {string} triggerFile pyproject.toml or poetry.lock path
|
|
704
|
+
* @returns {string|null} Path to pyproject.toml, or null when there is none
|
|
705
|
+
*/
|
|
706
|
+
function findPoetryPyprojectFile(triggerFile) {
|
|
707
|
+
if (!triggerFile) {
|
|
708
|
+
return null;
|
|
709
|
+
}
|
|
710
|
+
if (triggerFile.endsWith("pyproject.toml")) {
|
|
711
|
+
return triggerFile;
|
|
712
|
+
}
|
|
713
|
+
if (triggerFile.endsWith("poetry.lock")) {
|
|
714
|
+
const sibling = join(dirname(triggerFile), "pyproject.toml");
|
|
715
|
+
return safeExistsSync(sibling) ? sibling : null;
|
|
716
|
+
}
|
|
717
|
+
return null;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Build the poetry install arguments for a poetry project.
|
|
722
|
+
*
|
|
723
|
+
* Poetry 2 installs only the main dependency group and no extras by default,
|
|
724
|
+
* so projects requiring poetry-core 2 or newer also get --all-groups and
|
|
725
|
+
* --all-extras. Callers prepend the python invocation such as -m poetry.
|
|
726
|
+
*
|
|
727
|
+
* @param {string} pyprojectFile pyproject.toml or poetry.lock path of the project
|
|
728
|
+
* @returns {string[]} poetry install arguments
|
|
729
|
+
*/
|
|
730
|
+
export function getPoetryInstallArgs(pyprojectFile) {
|
|
731
|
+
const args = ["install", "-n", "--no-root"];
|
|
732
|
+
const resolvedFile = findPoetryPyprojectFile(pyprojectFile);
|
|
733
|
+
if (resolvedFile && isPoetry2Project(resolvedFile)) {
|
|
734
|
+
args.push("--all-groups", "--all-extras");
|
|
735
|
+
}
|
|
736
|
+
return args;
|
|
737
|
+
}
|
|
738
|
+
|
|
615
739
|
/**
|
|
616
740
|
* Execute pip freeze by creating a virtual env in a temp directory and construct the dependency tree
|
|
617
741
|
*
|
|
@@ -742,7 +866,9 @@ export async function getPipFrozenTree(
|
|
|
742
866
|
shell: isWin,
|
|
743
867
|
});
|
|
744
868
|
thoughtLog("Performing poetry install");
|
|
745
|
-
let poetryInstallArgs = ["-m", "poetry"
|
|
869
|
+
let poetryInstallArgs = ["-m", "poetry"].concat(
|
|
870
|
+
getPoetryInstallArgs(reqOrSetupFile),
|
|
871
|
+
);
|
|
746
872
|
if (isSecureMode) {
|
|
747
873
|
poetryInstallArgs.unshift("-S");
|
|
748
874
|
}
|
|
@@ -756,7 +882,7 @@ export async function getPipFrozenTree(
|
|
|
756
882
|
thoughtLog(
|
|
757
883
|
"Hmm, poetry doesn't seem to be available as a module. Perhaps it was installed directly 🤔?",
|
|
758
884
|
);
|
|
759
|
-
poetryInstallArgs =
|
|
885
|
+
poetryInstallArgs = getPoetryInstallArgs(reqOrSetupFile);
|
|
760
886
|
// Attempt to perform poetry install
|
|
761
887
|
result = safeSpawnSync("poetry", poetryInstallArgs, {
|
|
762
888
|
cwd: basePath,
|