@cdxgen/cdxgen 0.0.1 → 13.0.1
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 +921 -87
- package/bin/audit.js +239 -0
- package/bin/cdxgen.js +2335 -0
- package/bin/convert.js +220 -0
- package/bin/evinse.js +353 -0
- package/bin/hbom.js +504 -0
- package/bin/repl.js +2224 -0
- package/bin/sign.js +195 -0
- package/bin/tracebom.js +303 -0
- package/bin/validate.js +268 -0
- package/bin/verify.js +189 -0
- package/data/README.md +307 -0
- package/data/bom-1.4.schema.json +1605 -0
- package/data/bom-1.5.schema.json +3660 -0
- package/data/bom-1.6.schema.json +5511 -0
- package/data/bom-1.7.schema.json +6700 -0
- package/data/cbomosdb-queries.json +68 -0
- package/data/component-tags.json +339 -0
- package/data/container-knowledge-index.json +125 -0
- package/data/cosdb-queries.json +17 -0
- package/data/crypto-oid.json +1998 -0
- package/data/cryptography-defs.json +3793 -0
- package/data/cryptography-defs.schema.json +576 -0
- package/data/cyclonedx-2.0-bundled.schema.json +7182 -0
- package/data/frameworks-list.json +219 -0
- package/data/glibc-stdlib.json +117 -0
- package/data/gtfobins-index.json +6296 -0
- package/data/helpers/init.gradle +71 -0
- package/data/jsf-0.82.schema.json +211 -0
- package/data/known-licenses.json +82 -0
- package/data/lic-mapping.json +338 -0
- package/data/license-aliases.json +6624 -0
- package/data/license-db.json +39059 -0
- package/data/license-deprecations.json +302 -0
- package/data/lolbas-index.json +150 -0
- package/data/predictive-audit-allowlist.json +11 -0
- package/data/pypi-pkg-aliases.json +1199 -0
- package/data/python-stdlib.json +308 -0
- package/data/queries-darwin.json +193 -0
- package/data/queries-win.json +257 -0
- package/data/queries.json +268 -0
- package/data/ruby-known-modules.json +281 -0
- package/data/rules/ai-agent-governance.yaml +323 -0
- package/data/rules/ai-bom.yaml +268 -0
- package/data/rules/ai-oversight.yaml +186 -0
- package/data/rules/ai-provenance.yaml +92 -0
- package/data/rules/asar-archives.yaml +150 -0
- package/data/rules/cbom-security.yaml +165 -0
- package/data/rules/chrome-extensions.yaml +248 -0
- package/data/rules/ci-permissions.yaml +802 -0
- package/data/rules/container-risk.yaml +353 -0
- package/data/rules/dependency-sources.yaml +236 -0
- package/data/rules/golem-go.yaml +229 -0
- package/data/rules/hbom-compliance.yaml +325 -0
- package/data/rules/hbom-performance.yaml +307 -0
- package/data/rules/hbom-security.yaml +248 -0
- package/data/rules/host-topology.yaml +165 -0
- package/data/rules/mcp-servers.yaml +388 -0
- package/data/rules/obom-runtime.yaml +1776 -0
- package/data/rules/package-integrity.yaml +364 -0
- package/data/rules/rootfs-hardening.yaml +179 -0
- package/data/rules/vscode-extensions.yaml +237 -0
- package/data/spdx-export.schema.json +6794 -0
- package/data/spdx-license-list.json +7449 -0
- package/data/spdx-licenses.json +759 -0
- package/data/spdx.schema.json +819 -0
- package/data/templates/README.md +3 -0
- package/data/templates/asvs-4.0.3.cdx.json +2943 -0
- package/data/templates/asvs-5.0.cdx.json +3046 -0
- package/data/templates/bsimm-v13.cdx.json +1008 -0
- package/data/templates/masvs-2.0.0.cdx.json +225 -0
- package/data/templates/nist-ssdf-1.1.cdx.json +828 -0
- package/data/templates/pcissc-secure-slc-1.1.cdx.json +1027 -0
- package/data/templates/scvs-1.0.0.cdx.json +813 -0
- package/data/templates/ssaf-DRAFT-2023-11.cdx.json +127 -0
- package/data/vendor-alias.json +41967 -0
- package/data/wrapdb-releases.json +4227 -0
- package/index.cjs +15 -0
- package/lib/audit/index.js +2800 -0
- package/lib/audit/progress.js +114 -0
- package/lib/audit/reporters.js +937 -0
- package/lib/audit/scoring.js +560 -0
- package/lib/audit/targets.js +798 -0
- package/lib/cli/bomAssembly.js +1882 -0
- package/lib/cli/cliOptions.js +543 -0
- package/lib/cli/index.js +2759 -0
- package/lib/cli/jsBom.js +2087 -0
- package/lib/cli/jvmBom.js +1858 -0
- package/lib/cli/managedBom.js +2083 -0
- package/lib/cli/nativeBom.js +2125 -0
- package/lib/core/activity.js +1087 -0
- package/lib/core/env.js +719 -0
- package/lib/core/fs.js +1058 -0
- package/lib/core/httpClient.js +730 -0
- package/lib/core/logger.js +280 -0
- package/lib/core/parallel.js +323 -0
- package/lib/core/paths.js +70 -0
- package/lib/core/projectConfig.js +122 -0
- package/lib/core/propertySanitizer.js +174 -0
- package/lib/core/spdx.js +5 -0
- package/lib/core/state.js +59 -0
- package/lib/core/text.js +207 -0
- package/lib/core/ui.js +920 -0
- package/lib/core/urls.js +84 -0
- package/lib/ecosystems/asarutils.js +1636 -0
- package/lib/ecosystems/bunutils.js +402 -0
- package/lib/ecosystems/caxa.js +77 -0
- package/lib/ecosystems/chromextutils.js +1174 -0
- package/lib/ecosystems/cmakeResolver.js +587 -0
- package/lib/ecosystems/cppEvidence.js +305 -0
- package/lib/ecosystems/denoutils.js +1094 -0
- package/lib/ecosystems/dotnetutils.js +132 -0
- package/lib/ecosystems/ecosystems.js +2772 -0
- package/lib/ecosystems/golem.js +1807 -0
- package/lib/ecosystems/gradleutils.js +1048 -0
- package/lib/ecosystems/jsEvidence.js +317 -0
- package/lib/ecosystems/npmutils.js +586 -0
- package/lib/ecosystems/parsers-bazel.js +875 -0
- package/lib/ecosystems/parsers-dotnet.js +1430 -0
- package/lib/ecosystems/parsers-gleam.js +302 -0
- package/lib/ecosystems/parsers-go.js +818 -0
- package/lib/ecosystems/parsers-js.js +4222 -0
- package/lib/ecosystems/parsers-jvm.js +948 -0
- package/lib/ecosystems/parsers-misc.js +3191 -0
- package/lib/ecosystems/parsers-python.js +2070 -0
- package/lib/ecosystems/parsers-rust.js +1294 -0
- package/lib/ecosystems/parsers-zig.js +861 -0
- package/lib/ecosystems/pep770.js +341 -0
- package/lib/ecosystems/pylockutils.js +427 -0
- package/lib/ecosystems/pythonutils.js +1281 -0
- package/lib/ecosystems/registryProvenance.js +1003 -0
- package/lib/ecosystems/remote/huggingface.js +1343 -0
- package/lib/ecosystems/rubyutils.js +1629 -0
- package/lib/ecosystems/rusi.js +820 -0
- package/lib/ecosystems/sbtutils.js +972 -0
- package/lib/ecosystems/tea.js +607 -0
- package/lib/ecosystems/utils.js +583 -0
- package/lib/ecosystems/zigResolver.js +410 -0
- package/lib/evinser/db.js +145 -0
- package/lib/evinser/evinser.js +2362 -0
- package/lib/evinser/scalasem.js +65 -0
- package/lib/evinser/swiftsem.js +767 -0
- package/lib/helpers/annotationFormatter.js +84 -0
- package/lib/helpers/bomSigner.js +312 -0
- package/lib/helpers/exportUtils.js +160 -0
- package/lib/helpers/remote/dependency-track.js +117 -0
- package/lib/helpers/versutils.js +202 -0
- package/lib/helpers/vsixutils.js +1069 -0
- package/lib/inventory/agentFormulationParser.js +322 -0
- package/lib/inventory/aiCollector.js +2140 -0
- package/lib/inventory/aiInventory.js +414 -0
- package/lib/inventory/aiModelVariants.js +121 -0
- package/lib/inventory/aiOversightCollector.js +661 -0
- package/lib/inventory/aiProvenanceCollector.js +822 -0
- package/lib/inventory/analyzer.js +6089 -0
- package/lib/inventory/analyzerScope.js +807 -0
- package/lib/inventory/astWorker.js +20 -0
- package/lib/inventory/atomUtils.js +1092 -0
- package/lib/inventory/auditCategories.js +192 -0
- package/lib/inventory/bomUtils.js +369 -0
- package/lib/inventory/cacheCommands.js +182 -0
- package/lib/inventory/cacheDir.js +104 -0
- package/lib/inventory/cbomutils.js +590 -0
- package/lib/inventory/cdxrs.js +434 -0
- package/lib/inventory/ciParsers/azurePipelines.js +295 -0
- package/lib/inventory/ciParsers/circleCi.js +286 -0
- package/lib/inventory/ciParsers/common.js +24 -0
- package/lib/inventory/ciParsers/githubActions.js +2434 -0
- package/lib/inventory/ciParsers/gitlabCi.js +213 -0
- package/lib/inventory/ciParsers/jenkins.js +180 -0
- package/lib/inventory/citations.js +234 -0
- package/lib/inventory/communityAiConfigParser.js +756 -0
- package/lib/inventory/containerRisk.js +204 -0
- package/lib/inventory/cryptoAlgorithmFamily.js +258 -0
- package/lib/inventory/deps.js +807 -0
- package/lib/inventory/depsUtils.js +588 -0
- package/lib/inventory/display.js +2128 -0
- package/lib/inventory/dosai.js +601 -0
- package/lib/inventory/dosaiParsers.js +154 -0
- package/lib/inventory/dynamic.js +145 -0
- package/lib/inventory/envcontext.js +1793 -0
- package/lib/inventory/evidenceUtils.js +774 -0
- package/lib/inventory/fetchBatch.js +779 -0
- package/lib/inventory/fetchRate.js +255 -0
- package/lib/inventory/forgeEnricher.js +300 -0
- package/lib/inventory/formulationParsers.js +422 -0
- package/lib/inventory/gtfobins.js +339 -0
- package/lib/inventory/hbom.js +719 -0
- package/lib/inventory/hbomAnalysis.js +310 -0
- package/lib/inventory/hbomLoader.js +35 -0
- package/lib/inventory/hostTopology.js +835 -0
- package/lib/inventory/inventoryStats.js +100 -0
- package/lib/inventory/jsonLike.js +121 -0
- package/lib/inventory/licenseEnhancer.js +918 -0
- package/lib/inventory/lolbas.js +285 -0
- package/lib/inventory/mcp.js +253 -0
- package/lib/inventory/mcpConfigParser.js +683 -0
- package/lib/inventory/mcpDiscovery.js +112 -0
- package/lib/inventory/mcpPinning.js +209 -0
- package/lib/inventory/osPackageResolver.js +493 -0
- package/lib/inventory/osinfo.js +383 -0
- package/lib/inventory/osqueryTransform.js +274 -0
- package/lib/inventory/plugins.js +466 -0
- package/lib/inventory/protobom.js +231 -0
- package/lib/inventory/protobomLoader.js +43 -0
- package/lib/inventory/provenanceUtils.js +224 -0
- package/lib/inventory/purl.js +749 -0
- package/lib/inventory/rustFormulationParser.js +339 -0
- package/lib/inventory/sbomDocument.js +340 -0
- package/lib/inventory/source.js +1488 -0
- package/lib/inventory/spdx.js +361 -0
- package/lib/inventory/spdxExpression.js +512 -0
- package/lib/inventory/spdxUtils.js +107 -0
- package/lib/inventory/table.js +267 -0
- package/lib/inventory/traceRunner.js +439 -0
- package/lib/inventory/unicodeScan.js +147 -0
- package/lib/managers/binary.js +3459 -0
- package/lib/managers/containerutils.js +125 -0
- package/lib/managers/docker.js +2145 -0
- package/lib/managers/dockerConnection.js +162 -0
- package/lib/managers/oci.js +704 -0
- package/lib/managers/piptree.js +267 -0
- package/lib/parsers/cmakeCache.js +199 -0
- package/lib/parsers/gguf.js +492 -0
- package/lib/parsers/gitAiNotes.js +233 -0
- package/lib/parsers/gitmodules.js +239 -0
- package/lib/parsers/htmlExtract.js +610 -0
- package/lib/parsers/huggingfaceManifest.js +551 -0
- package/lib/parsers/huggingfaceUtils.js +506 -0
- package/lib/parsers/iri.js +618 -0
- package/lib/parsers/npmrc.js +99 -0
- package/lib/parsers/ollama.js +101 -0
- package/lib/parsers/xml.js +841 -0
- package/lib/server/openapi.yaml +433 -0
- package/lib/server/server.js +616 -0
- package/lib/stages/postgen/annotator.js +977 -0
- package/lib/stages/postgen/auditBom.js +468 -0
- package/lib/stages/postgen/postgen.js +1239 -0
- package/lib/stages/postgen/ruleEngine.js +731 -0
- package/lib/stages/postgen/sortBom.js +195 -0
- package/lib/stages/postgen/spdxConverter.js +796 -0
- package/lib/stages/postgen/specVersionCompat.js +703 -0
- package/lib/stages/pregen/envAudit.js +388 -0
- package/lib/stages/pregen/pregen.js +637 -0
- package/lib/third-party/README.md +9 -0
- package/lib/third-party/arborist/CHANGELOG.md +1109 -0
- package/lib/third-party/arborist/LICENSE.md +20 -0
- package/lib/third-party/arborist/README.md +315 -0
- package/lib/third-party/arborist/lib/arborist/index.js +258 -0
- package/lib/third-party/arborist/lib/arborist/load-actual.js +605 -0
- package/lib/third-party/arborist/lib/arborist/load-virtual.js +300 -0
- package/lib/third-party/arborist/lib/bin-links.js +120 -0
- package/lib/third-party/arborist/lib/calc-dep-flags.js +130 -0
- package/lib/third-party/arborist/lib/case-insensitive-map.js +51 -0
- package/lib/third-party/arborist/lib/consistent-resolve.js +42 -0
- package/lib/third-party/arborist/lib/debug.js +50 -0
- package/lib/third-party/arborist/lib/dep-valid.js +190 -0
- package/lib/third-party/arborist/lib/edge.js +417 -0
- package/lib/third-party/arborist/lib/from-path.js +36 -0
- package/lib/third-party/arborist/lib/gather-dep-set.js +43 -0
- package/lib/third-party/arborist/lib/index.js +22 -0
- package/lib/third-party/arborist/lib/inventory.js +138 -0
- package/lib/third-party/arborist/lib/link.js +169 -0
- package/lib/third-party/arborist/lib/node.js +1673 -0
- package/lib/third-party/arborist/lib/npm-extension.js +45 -0
- package/lib/third-party/arborist/lib/override-resolves.js +11 -0
- package/lib/third-party/arborist/lib/override-set.js +319 -0
- package/lib/third-party/arborist/lib/package-extensions.js +289 -0
- package/lib/third-party/arborist/lib/printable.js +210 -0
- package/lib/third-party/arborist/lib/proc-log.js +30 -0
- package/lib/third-party/arborist/lib/realpath.js +100 -0
- package/lib/third-party/arborist/lib/relpath.js +4 -0
- package/lib/third-party/arborist/lib/shrinkwrap.js +1291 -0
- package/lib/third-party/arborist/lib/spec-from-lock.js +34 -0
- package/lib/third-party/arborist/lib/tree-check.js +165 -0
- package/lib/third-party/arborist/lib/validate-npm-package-name.js +107 -0
- package/lib/third-party/arborist/lib/version-from-tgz.js +51 -0
- package/lib/third-party/arborist/lib/yarn-lock.js +397 -0
- package/lib/validator/bomValidator.js +985 -0
- package/lib/validator/complianceEngine.js +241 -0
- package/lib/validator/complianceRules.js +1680 -0
- package/lib/validator/generated/runtime.mjs +17 -0
- package/lib/validator/generated/validate-1.6.mjs +21258 -0
- package/lib/validator/generated/validate-1.7.mjs +24803 -0
- package/lib/validator/generated/validate-2.0.mjs +22931 -0
- package/lib/validator/index.js +246 -0
- package/lib/validator/reporters/annotations.js +142 -0
- package/lib/validator/reporters/console.js +160 -0
- package/lib/validator/reporters/index.js +41 -0
- package/lib/validator/reporters/json.js +37 -0
- package/lib/validator/reporters/sarif.js +184 -0
- package/package.json +209 -26
- package/types/bin/audit.d.ts +3 -0
- package/types/bin/audit.d.ts.map +1 -0
- package/types/bin/cdxgen.d.ts +3 -0
- package/types/bin/cdxgen.d.ts.map +1 -0
- package/types/bin/convert.d.ts +3 -0
- package/types/bin/convert.d.ts.map +1 -0
- package/types/bin/evinse.d.ts +3 -0
- package/types/bin/evinse.d.ts.map +1 -0
- package/types/bin/hbom.d.ts +3 -0
- package/types/bin/hbom.d.ts.map +1 -0
- package/types/bin/repl.d.ts +3 -0
- package/types/bin/repl.d.ts.map +1 -0
- package/types/bin/sign.d.ts +3 -0
- package/types/bin/sign.d.ts.map +1 -0
- package/types/bin/tracebom.d.ts +3 -0
- package/types/bin/tracebom.d.ts.map +1 -0
- package/types/bin/validate.d.ts +14 -0
- package/types/bin/validate.d.ts.map +1 -0
- package/types/bin/verify.d.ts +3 -0
- package/types/bin/verify.d.ts.map +1 -0
- package/types/lib/audit/index.d.ts +153 -0
- package/types/lib/audit/index.d.ts.map +1 -0
- package/types/lib/audit/progress.d.ts +31 -0
- package/types/lib/audit/progress.d.ts.map +1 -0
- package/types/lib/audit/reporters.d.ts +62 -0
- package/types/lib/audit/reporters.d.ts.map +1 -0
- package/types/lib/audit/scoring.d.ts +36 -0
- package/types/lib/audit/scoring.d.ts.map +1 -0
- package/types/lib/audit/targets.d.ts +77 -0
- package/types/lib/audit/targets.d.ts.map +1 -0
- package/types/lib/cli/bomAssembly.d.ts +329 -0
- package/types/lib/cli/bomAssembly.d.ts.map +1 -0
- package/types/lib/cli/cliOptions.d.ts +156 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -0
- package/types/lib/cli/index.d.ts +107 -0
- package/types/lib/cli/index.d.ts.map +1 -0
- package/types/lib/cli/jsBom.d.ts +94 -0
- package/types/lib/cli/jsBom.d.ts.map +1 -0
- package/types/lib/cli/jvmBom.d.ts +54 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -0
- package/types/lib/cli/managedBom.d.ts +105 -0
- package/types/lib/cli/managedBom.d.ts.map +1 -0
- package/types/lib/cli/nativeBom.d.ts +143 -0
- package/types/lib/cli/nativeBom.d.ts.map +1 -0
- package/types/lib/core/activity.d.ts +178 -0
- package/types/lib/core/activity.d.ts.map +1 -0
- package/types/lib/core/env.d.ts +192 -0
- package/types/lib/core/env.d.ts.map +1 -0
- package/types/lib/core/fs.d.ts +158 -0
- package/types/lib/core/fs.d.ts.map +1 -0
- package/types/lib/core/httpClient.d.ts +149 -0
- package/types/lib/core/httpClient.d.ts.map +1 -0
- package/types/lib/core/logger.d.ts +50 -0
- package/types/lib/core/logger.d.ts.map +1 -0
- package/types/lib/core/parallel.d.ts +95 -0
- package/types/lib/core/parallel.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +36 -0
- package/types/lib/core/paths.d.ts.map +1 -0
- package/types/lib/core/projectConfig.d.ts +23 -0
- package/types/lib/core/projectConfig.d.ts.map +1 -0
- package/types/lib/core/propertySanitizer.d.ts +23 -0
- package/types/lib/core/propertySanitizer.d.ts.map +1 -0
- package/types/lib/core/spdx.d.ts +5 -0
- package/types/lib/core/spdx.d.ts.map +1 -0
- package/types/lib/core/state.d.ts +20 -0
- package/types/lib/core/state.d.ts.map +1 -0
- package/types/lib/core/text.d.ts +78 -0
- package/types/lib/core/text.d.ts.map +1 -0
- package/types/lib/core/ui.d.ts +87 -0
- package/types/lib/core/ui.d.ts.map +1 -0
- package/types/lib/core/urls.d.ts +43 -0
- package/types/lib/core/urls.d.ts.map +1 -0
- package/types/lib/ecosystems/asarutils.d.ts +71 -0
- package/types/lib/ecosystems/asarutils.d.ts.map +1 -0
- package/types/lib/ecosystems/bunutils.d.ts +38 -0
- package/types/lib/ecosystems/bunutils.d.ts.map +1 -0
- package/types/lib/ecosystems/caxa.d.ts +8 -0
- package/types/lib/ecosystems/caxa.d.ts.map +1 -0
- package/types/lib/ecosystems/chromextutils.d.ts +97 -0
- package/types/lib/ecosystems/chromextutils.d.ts.map +1 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts +176 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +35 -0
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -0
- package/types/lib/ecosystems/denoutils.d.ts +76 -0
- package/types/lib/ecosystems/denoutils.d.ts.map +1 -0
- package/types/lib/ecosystems/dotnetutils.d.ts +45 -0
- package/types/lib/ecosystems/dotnetutils.d.ts.map +1 -0
- package/types/lib/ecosystems/ecosystems.d.ts +279 -0
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -0
- package/types/lib/ecosystems/golem.d.ts +60 -0
- package/types/lib/ecosystems/golem.d.ts.map +1 -0
- package/types/lib/ecosystems/gradleutils.d.ts +139 -0
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -0
- package/types/lib/ecosystems/jsEvidence.d.ts +17 -0
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -0
- package/types/lib/ecosystems/npmutils.d.ts +183 -0
- package/types/lib/ecosystems/npmutils.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts +36 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts +116 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-gleam.d.ts +33 -0
- package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-go.d.ts +92 -0
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-js.d.ts +242 -0
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-jvm.d.ts +100 -0
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-misc.d.ts +450 -0
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-python.d.ts +145 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-rust.d.ts +56 -0
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-zig.d.ts +83 -0
- package/types/lib/ecosystems/parsers-zig.d.ts.map +1 -0
- package/types/lib/ecosystems/pep770.d.ts +38 -0
- package/types/lib/ecosystems/pep770.d.ts.map +1 -0
- package/types/lib/ecosystems/pylockutils.d.ts +68 -0
- package/types/lib/ecosystems/pylockutils.d.ts.map +1 -0
- package/types/lib/ecosystems/pythonutils.d.ts +70 -0
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -0
- package/types/lib/ecosystems/registryProvenance.d.ts +26 -0
- package/types/lib/ecosystems/registryProvenance.d.ts.map +1 -0
- package/types/lib/ecosystems/remote/huggingface.d.ts +31 -0
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -0
- package/types/lib/ecosystems/rubyutils.d.ts +182 -0
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -0
- package/types/lib/ecosystems/rusi.d.ts +40 -0
- package/types/lib/ecosystems/rusi.d.ts.map +1 -0
- package/types/lib/ecosystems/sbtutils.d.ts +179 -0
- package/types/lib/ecosystems/sbtutils.d.ts.map +1 -0
- package/types/lib/ecosystems/tea.d.ts +180 -0
- package/types/lib/ecosystems/tea.d.ts.map +1 -0
- package/types/lib/ecosystems/utils.d.ts +41 -0
- package/types/lib/ecosystems/utils.d.ts.map +1 -0
- package/types/lib/ecosystems/zigResolver.d.ts +70 -0
- package/types/lib/ecosystems/zigResolver.d.ts.map +1 -0
- package/types/lib/evinser/db.d.ts +17 -0
- package/types/lib/evinser/db.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +354 -0
- package/types/lib/evinser/evinser.d.ts.map +1 -0
- package/types/lib/evinser/scalasem.d.ts +15 -0
- package/types/lib/evinser/scalasem.d.ts.map +1 -0
- package/types/lib/evinser/swiftsem.d.ts +103 -0
- package/types/lib/evinser/swiftsem.d.ts.map +1 -0
- package/types/lib/helpers/annotationFormatter.d.ts +23 -0
- package/types/lib/helpers/annotationFormatter.d.ts.map +1 -0
- package/types/lib/helpers/bomSigner.d.ts +28 -0
- package/types/lib/helpers/bomSigner.d.ts.map +1 -0
- package/types/lib/helpers/exportUtils.d.ts +52 -0
- package/types/lib/helpers/exportUtils.d.ts.map +1 -0
- package/types/lib/helpers/remote/dependency-track.d.ts +23 -0
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -0
- package/types/lib/helpers/versutils.d.ts +8 -0
- package/types/lib/helpers/versutils.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +130 -0
- package/types/lib/helpers/vsixutils.d.ts.map +1 -0
- package/types/lib/inventory/agentFormulationParser.d.ts +21 -0
- package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts +61 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -0
- package/types/lib/inventory/aiInventory.d.ts +103 -0
- package/types/lib/inventory/aiInventory.d.ts.map +1 -0
- package/types/lib/inventory/aiModelVariants.d.ts +31 -0
- package/types/lib/inventory/aiModelVariants.d.ts.map +1 -0
- package/types/lib/inventory/aiOversightCollector.d.ts +28 -0
- package/types/lib/inventory/aiOversightCollector.d.ts.map +1 -0
- package/types/lib/inventory/aiProvenanceCollector.d.ts +13 -0
- package/types/lib/inventory/aiProvenanceCollector.d.ts.map +1 -0
- package/types/lib/inventory/analyzer.d.ts +157 -0
- package/types/lib/inventory/analyzer.d.ts.map +1 -0
- package/types/lib/inventory/analyzerScope.d.ts +106 -0
- package/types/lib/inventory/analyzerScope.d.ts.map +1 -0
- package/types/lib/inventory/astWorker.d.ts +9 -0
- package/types/lib/inventory/astWorker.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +159 -0
- package/types/lib/inventory/atomUtils.d.ts.map +1 -0
- package/types/lib/inventory/auditCategories.d.ts +80 -0
- package/types/lib/inventory/auditCategories.d.ts.map +1 -0
- package/types/lib/inventory/bomUtils.d.ts +145 -0
- package/types/lib/inventory/bomUtils.d.ts.map +1 -0
- package/types/lib/inventory/cacheCommands.d.ts +28 -0
- package/types/lib/inventory/cacheCommands.d.ts.map +1 -0
- package/types/lib/inventory/cacheDir.d.ts +55 -0
- package/types/lib/inventory/cacheDir.d.ts.map +1 -0
- package/types/lib/inventory/cbomutils.d.ts +37 -0
- package/types/lib/inventory/cbomutils.d.ts.map +1 -0
- package/types/lib/inventory/cdxrs.d.ts +90 -0
- package/types/lib/inventory/cdxrs.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/azurePipelines.d.ts +27 -0
- package/types/lib/inventory/ciParsers/azurePipelines.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/circleCi.d.ts +27 -0
- package/types/lib/inventory/ciParsers/circleCi.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/common.d.ts +11 -0
- package/types/lib/inventory/ciParsers/common.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/githubActions.d.ts +38 -0
- package/types/lib/inventory/ciParsers/githubActions.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/gitlabCi.d.ts +26 -0
- package/types/lib/inventory/ciParsers/gitlabCi.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/jenkins.d.ts +26 -0
- package/types/lib/inventory/ciParsers/jenkins.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +90 -0
- package/types/lib/inventory/citations.d.ts.map +1 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts +14 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -0
- package/types/lib/inventory/containerRisk.d.ts +20 -0
- package/types/lib/inventory/containerRisk.d.ts.map +1 -0
- package/types/lib/inventory/cryptoAlgorithmFamily.d.ts +37 -0
- package/types/lib/inventory/cryptoAlgorithmFamily.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +140 -0
- package/types/lib/inventory/deps.d.ts.map +1 -0
- package/types/lib/inventory/depsUtils.d.ts +74 -0
- package/types/lib/inventory/depsUtils.d.ts.map +1 -0
- package/types/lib/inventory/display.d.ts +227 -0
- package/types/lib/inventory/display.d.ts.map +1 -0
- package/types/lib/inventory/dosai.d.ts +130 -0
- package/types/lib/inventory/dosai.d.ts.map +1 -0
- package/types/lib/inventory/dosaiParsers.d.ts +59 -0
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -0
- package/types/lib/inventory/dynamic.d.ts +25 -0
- package/types/lib/inventory/dynamic.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +377 -0
- package/types/lib/inventory/envcontext.d.ts.map +1 -0
- package/types/lib/inventory/evidenceUtils.d.ts +74 -0
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -0
- package/types/lib/inventory/fetchBatch.d.ts +127 -0
- package/types/lib/inventory/fetchBatch.d.ts.map +1 -0
- package/types/lib/inventory/fetchRate.d.ts +118 -0
- package/types/lib/inventory/fetchRate.d.ts.map +1 -0
- package/types/lib/inventory/forgeEnricher.d.ts +31 -0
- package/types/lib/inventory/forgeEnricher.d.ts.map +1 -0
- package/types/lib/inventory/formulationParsers.d.ts +50 -0
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/gtfobins.d.ts +27 -0
- package/types/lib/inventory/gtfobins.d.ts.map +1 -0
- package/types/lib/inventory/hbom.d.ts +58 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -0
- package/types/lib/inventory/hbomAnalysis.d.ts +56 -0
- package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -0
- package/types/lib/inventory/hbomLoader.d.ts +7 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -0
- package/types/lib/inventory/hostTopology.d.ts +47 -0
- package/types/lib/inventory/hostTopology.d.ts.map +1 -0
- package/types/lib/inventory/inventoryStats.d.ts +42 -0
- package/types/lib/inventory/inventoryStats.d.ts.map +1 -0
- package/types/lib/inventory/jsonLike.d.ts +23 -0
- package/types/lib/inventory/jsonLike.d.ts.map +1 -0
- package/types/lib/inventory/licenseEnhancer.d.ts +70 -0
- package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -0
- package/types/lib/inventory/lolbas.d.ts +16 -0
- package/types/lib/inventory/lolbas.d.ts.map +1 -0
- package/types/lib/inventory/mcp.d.ts +29 -0
- package/types/lib/inventory/mcp.d.ts.map +1 -0
- package/types/lib/inventory/mcpConfigParser.d.ts +20 -0
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -0
- package/types/lib/inventory/mcpDiscovery.d.ts +33 -0
- package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -0
- package/types/lib/inventory/mcpPinning.d.ts +11 -0
- package/types/lib/inventory/mcpPinning.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +49 -0
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -0
- package/types/lib/inventory/osinfo.d.ts +201 -0
- package/types/lib/inventory/osinfo.d.ts.map +1 -0
- package/types/lib/inventory/osqueryTransform.d.ts +84 -0
- package/types/lib/inventory/osqueryTransform.d.ts.map +1 -0
- package/types/lib/inventory/plugins.d.ts +58 -0
- package/types/lib/inventory/plugins.d.ts.map +1 -0
- package/types/lib/inventory/protobom.d.ts +71 -0
- package/types/lib/inventory/protobom.d.ts.map +1 -0
- package/types/lib/inventory/protobomLoader.d.ts +17 -0
- package/types/lib/inventory/protobomLoader.d.ts.map +1 -0
- package/types/lib/inventory/provenanceUtils.d.ts +98 -0
- package/types/lib/inventory/provenanceUtils.d.ts.map +1 -0
- package/types/lib/inventory/purl.d.ts +313 -0
- package/types/lib/inventory/purl.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +17 -0
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -0
- package/types/lib/inventory/sbomDocument.d.ts +59 -0
- package/types/lib/inventory/sbomDocument.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +163 -0
- package/types/lib/inventory/source.d.ts.map +1 -0
- package/types/lib/inventory/spdx.d.ts +66 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -0
- package/types/lib/inventory/spdxExpression.d.ts +58 -0
- package/types/lib/inventory/spdxExpression.d.ts.map +1 -0
- package/types/lib/inventory/spdxUtils.d.ts +12 -0
- package/types/lib/inventory/spdxUtils.d.ts.map +1 -0
- package/types/lib/inventory/table.d.ts +22 -0
- package/types/lib/inventory/table.d.ts.map +1 -0
- package/types/lib/inventory/traceRunner.d.ts +80 -0
- package/types/lib/inventory/traceRunner.d.ts.map +1 -0
- package/types/lib/inventory/unicodeScan.d.ts +46 -0
- package/types/lib/inventory/unicodeScan.d.ts.map +1 -0
- package/types/lib/managers/binary.d.ts +147 -0
- package/types/lib/managers/binary.d.ts.map +1 -0
- package/types/lib/managers/containerutils.d.ts +30 -0
- package/types/lib/managers/containerutils.d.ts.map +1 -0
- package/types/lib/managers/docker.d.ts +157 -0
- package/types/lib/managers/docker.d.ts.map +1 -0
- package/types/lib/managers/dockerConnection.d.ts +42 -0
- package/types/lib/managers/dockerConnection.d.ts.map +1 -0
- package/types/lib/managers/oci.d.ts +21 -0
- package/types/lib/managers/oci.d.ts.map +1 -0
- package/types/lib/managers/piptree.d.ts +13 -0
- package/types/lib/managers/piptree.d.ts.map +1 -0
- package/types/lib/parsers/cmakeCache.d.ts +70 -0
- package/types/lib/parsers/cmakeCache.d.ts.map +1 -0
- package/types/lib/parsers/gguf.d.ts +39 -0
- package/types/lib/parsers/gguf.d.ts.map +1 -0
- package/types/lib/parsers/gitAiNotes.d.ts +15 -0
- package/types/lib/parsers/gitAiNotes.d.ts.map +1 -0
- package/types/lib/parsers/gitmodules.d.ts +88 -0
- package/types/lib/parsers/gitmodules.d.ts.map +1 -0
- package/types/lib/parsers/htmlExtract.d.ts +34 -0
- package/types/lib/parsers/htmlExtract.d.ts.map +1 -0
- package/types/lib/parsers/huggingfaceManifest.d.ts +153 -0
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts +155 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -0
- package/types/lib/parsers/iri.d.ts +68 -0
- package/types/lib/parsers/iri.d.ts.map +1 -0
- package/types/lib/parsers/npmrc.d.ts +33 -0
- package/types/lib/parsers/npmrc.d.ts.map +1 -0
- package/types/lib/parsers/ollama.d.ts +22 -0
- package/types/lib/parsers/ollama.d.ts.map +1 -0
- package/types/lib/parsers/xml.d.ts +47 -0
- package/types/lib/parsers/xml.d.ts.map +1 -0
- package/types/lib/server/server.d.ts +51 -0
- package/types/lib/server/server.d.ts.map +1 -0
- package/types/lib/stages/postgen/annotator.d.ts +36 -0
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -0
- package/types/lib/stages/postgen/auditBom.d.ts +92 -0
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -0
- package/types/lib/stages/postgen/postgen.d.ts +59 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -0
- package/types/lib/stages/postgen/ruleEngine.d.ts +18 -0
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -0
- package/types/lib/stages/postgen/sortBom.d.ts +34 -0
- package/types/lib/stages/postgen/sortBom.d.ts.map +1 -0
- package/types/lib/stages/postgen/spdxConverter.d.ts +11 -0
- package/types/lib/stages/postgen/spdxConverter.d.ts.map +1 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts +71 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -0
- package/types/lib/stages/pregen/envAudit.d.ts +14 -0
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -0
- package/types/lib/stages/pregen/pregen.d.ts +59 -0
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/index.d.ts +47 -0
- package/types/lib/third-party/arborist/lib/arborist/index.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts +4 -0
- package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts +4 -0
- package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/bin-links.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/bin-links.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts +9 -0
- package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/debug.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/debug.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/dep-valid.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/dep-valid.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/edge.d.ts +46 -0
- package/types/lib/third-party/arborist/lib/edge.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/from-path.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/from-path.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/index.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/index.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/inventory.d.ts +14 -0
- package/types/lib/third-party/arborist/lib/inventory.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/link.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/link.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/node.d.ts +112 -0
- package/types/lib/third-party/arborist/lib/node.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/npm-extension.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/npm-extension.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/override-resolves.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/override-resolves.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/override-set.d.ts +27 -0
- package/types/lib/third-party/arborist/lib/override-set.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/package-extensions.d.ts +36 -0
- package/types/lib/third-party/arborist/lib/package-extensions.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/printable.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/printable.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/proc-log.d.ts +20 -0
- package/types/lib/third-party/arborist/lib/proc-log.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/realpath.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/realpath.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/relpath.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/relpath.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts +54 -0
- package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/tree-check.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/tree-check.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts +13 -0
- package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts +6 -0
- package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/yarn-lock.d.ts +35 -0
- package/types/lib/third-party/arborist/lib/yarn-lock.d.ts.map +1 -0
- package/types/lib/validator/bomValidator.d.ts +40 -0
- package/types/lib/validator/bomValidator.d.ts.map +1 -0
- package/types/lib/validator/complianceEngine.d.ts +72 -0
- package/types/lib/validator/complianceEngine.d.ts.map +1 -0
- package/types/lib/validator/complianceRules.d.ts +61 -0
- package/types/lib/validator/complianceRules.d.ts.map +1 -0
- package/types/lib/validator/index.d.ts +101 -0
- package/types/lib/validator/index.d.ts.map +1 -0
- package/types/lib/validator/reporters/annotations.d.ts +37 -0
- package/types/lib/validator/reporters/annotations.d.ts.map +1 -0
- package/types/lib/validator/reporters/console.d.ts +34 -0
- package/types/lib/validator/reporters/console.d.ts.map +1 -0
- package/types/lib/validator/reporters/index.d.ts +30 -0
- package/types/lib/validator/reporters/index.d.ts.map +1 -0
- package/types/lib/validator/reporters/json.d.ts +11 -0
- package/types/lib/validator/reporters/json.d.ts.map +1 -0
- package/types/lib/validator/reporters/sarif.d.ts +22 -0
- package/types/lib/validator/reporters/sarif.d.ts.map +1 -0
- package/mod.d.ts +0 -7
- package/mod.js +0 -22
|
@@ -0,0 +1,1858 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
|
|
7
|
+
import { build } from "@cdxgen/cdx-purl";
|
|
8
|
+
import { gte, lte } from "semver";
|
|
9
|
+
|
|
10
|
+
import { DEBUG_MODE, readEnvironmentVariable } from "../core/activity.js";
|
|
11
|
+
import {
|
|
12
|
+
hasAnyProjectType,
|
|
13
|
+
includeMavenTestScope,
|
|
14
|
+
isFeatureEnabled,
|
|
15
|
+
isPackageManagerAllowed,
|
|
16
|
+
PREFER_MAVEN_DEPS_TREE,
|
|
17
|
+
parseMavenArgs,
|
|
18
|
+
} from "../core/env.js";
|
|
19
|
+
import {
|
|
20
|
+
getAllFiles,
|
|
21
|
+
getTmpDir,
|
|
22
|
+
MAX_BUFFER,
|
|
23
|
+
safeExistsSync,
|
|
24
|
+
safeMkdirSync,
|
|
25
|
+
safeMkdtempSync,
|
|
26
|
+
safeRmSync,
|
|
27
|
+
safeSpawnSync,
|
|
28
|
+
safeUnlinkSync,
|
|
29
|
+
safeWriteSync,
|
|
30
|
+
} from "../core/fs.js";
|
|
31
|
+
import { thoughtLog } from "../core/logger.js";
|
|
32
|
+
import { dirNameStr } from "../core/paths.js";
|
|
33
|
+
import { extractJarArchive, getMvnMetadata } from "../ecosystems/ecosystems.js";
|
|
34
|
+
import {
|
|
35
|
+
buildGradleCommandArguments,
|
|
36
|
+
buildObjectForGradleModule,
|
|
37
|
+
collectGradleDependencies,
|
|
38
|
+
executeParallelGradleProperties,
|
|
39
|
+
getGradleCommand,
|
|
40
|
+
getMavenCommand,
|
|
41
|
+
getMillCommand,
|
|
42
|
+
parseGradleDep,
|
|
43
|
+
parseGradleInfoLogsForUrls,
|
|
44
|
+
parseGradleProperties,
|
|
45
|
+
parseGradleResolvedDistributions,
|
|
46
|
+
splitOutputByGradleProjects,
|
|
47
|
+
} from "../ecosystems/gradleutils.js";
|
|
48
|
+
import {
|
|
49
|
+
parseModuleBazel,
|
|
50
|
+
parseModuleBazelLock,
|
|
51
|
+
} from "../ecosystems/parsers-bazel.js";
|
|
52
|
+
import {
|
|
53
|
+
parseBazelActionGraph,
|
|
54
|
+
parseBazelSkyframe,
|
|
55
|
+
parseMavenTree,
|
|
56
|
+
parseMavenTreeJson,
|
|
57
|
+
parseMillDependency,
|
|
58
|
+
parsePom,
|
|
59
|
+
} from "../ecosystems/parsers-jvm.js";
|
|
60
|
+
import {
|
|
61
|
+
addPlugin,
|
|
62
|
+
cleanupPlugin,
|
|
63
|
+
determineSbtVersion,
|
|
64
|
+
discoverSbtProjects,
|
|
65
|
+
parseSbtLock,
|
|
66
|
+
parseSbtProjects,
|
|
67
|
+
parseSbtRootProject,
|
|
68
|
+
parseSbtTree,
|
|
69
|
+
} from "../ecosystems/sbtutils.js";
|
|
70
|
+
import {
|
|
71
|
+
collectJarNS,
|
|
72
|
+
collectMvnDependencies,
|
|
73
|
+
convertJarNSToPackages,
|
|
74
|
+
} from "../inventory/deps.js";
|
|
75
|
+
import { mergeDependencies, trimComponents } from "../inventory/depsUtils.js";
|
|
76
|
+
import {
|
|
77
|
+
attachIdentityTools,
|
|
78
|
+
extractToolRefs,
|
|
79
|
+
} from "../inventory/evidenceUtils.js";
|
|
80
|
+
import { applyPurl, mavenPurl } from "../inventory/purl.js";
|
|
81
|
+
import {
|
|
82
|
+
buildBomNSData,
|
|
83
|
+
createDefaultParentComponent,
|
|
84
|
+
shouldIncludeNodeModulesDir,
|
|
85
|
+
} from "./bomAssembly.js";
|
|
86
|
+
|
|
87
|
+
const isWin = process.platform === "win32";
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resolved path to the Gradle modules cache directory, derived from
|
|
91
|
+
* `GRADLE_CACHE_DIR`, `GRADLE_USER_HOME`, or `~/.gradle/caches/modules-2/files-2.1`.
|
|
92
|
+
*
|
|
93
|
+
* @type {string}
|
|
94
|
+
*/
|
|
95
|
+
export let GRADLE_CACHE_DIR =
|
|
96
|
+
readEnvironmentVariable("GRADLE_CACHE_DIR") ||
|
|
97
|
+
join(homedir(), ".gradle", "caches", "modules-2", "files-2.1");
|
|
98
|
+
if (readEnvironmentVariable("GRADLE_USER_HOME")) {
|
|
99
|
+
GRADLE_CACHE_DIR = join(
|
|
100
|
+
readEnvironmentVariable("GRADLE_USER_HOME"),
|
|
101
|
+
"caches",
|
|
102
|
+
"modules-2",
|
|
103
|
+
"files-2.1",
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Absolute path to the bundled `init.gradle` helper script under `data/helpers`.
|
|
109
|
+
*
|
|
110
|
+
* @type {string}
|
|
111
|
+
*/
|
|
112
|
+
// Construct path to gradle init script
|
|
113
|
+
export const GRADLE_INIT_SCRIPT = resolve(
|
|
114
|
+
dirNameStr,
|
|
115
|
+
"data",
|
|
116
|
+
"helpers",
|
|
117
|
+
"init.gradle",
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Resolved path to the sbt/Ivy2 cache directory, derived from `SBT_CACHE_DIR`
|
|
122
|
+
* or `~/.ivy2/cache`.
|
|
123
|
+
*
|
|
124
|
+
* @type {string}
|
|
125
|
+
*/
|
|
126
|
+
// Construct sbt cache directory
|
|
127
|
+
export const SBT_CACHE_DIR =
|
|
128
|
+
readEnvironmentVariable("SBT_CACHE_DIR") || join(homedir(), ".ivy2", "cache");
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Function to create bom string for Java jars
|
|
132
|
+
*
|
|
133
|
+
* @param {string} path to the project
|
|
134
|
+
* @param {Object} options Parse options from the cli
|
|
135
|
+
*
|
|
136
|
+
* @returns {Object} BOM with namespace mapping
|
|
137
|
+
*/
|
|
138
|
+
export async function createJarBom(path, options) {
|
|
139
|
+
let pkgList = [];
|
|
140
|
+
let jarFiles;
|
|
141
|
+
let nsMapping = {};
|
|
142
|
+
const searchOptions = {
|
|
143
|
+
...options,
|
|
144
|
+
exclude: [...(options.exclude || [])],
|
|
145
|
+
};
|
|
146
|
+
if (typeof searchOptions.includeNodeModulesDir === "undefined") {
|
|
147
|
+
searchOptions.includeNodeModulesDir = shouldIncludeNodeModulesDir(options, [
|
|
148
|
+
"jar",
|
|
149
|
+
"war",
|
|
150
|
+
"ear",
|
|
151
|
+
]);
|
|
152
|
+
}
|
|
153
|
+
// Exclude certain directories during oci sbom generation
|
|
154
|
+
if (hasAnyProjectType(["oci"], options, false)) {
|
|
155
|
+
searchOptions.exclude.push("**/android-sdk*/**");
|
|
156
|
+
searchOptions.exclude.push("**/.sdkman/**");
|
|
157
|
+
}
|
|
158
|
+
const parentComponent = createDefaultParentComponent(path, "maven", options);
|
|
159
|
+
if (options.useGradleCache) {
|
|
160
|
+
nsMapping = await collectGradleDependencies(
|
|
161
|
+
getGradleCommand(path, null),
|
|
162
|
+
path,
|
|
163
|
+
false,
|
|
164
|
+
true,
|
|
165
|
+
);
|
|
166
|
+
} else if (options.useMavenCache) {
|
|
167
|
+
nsMapping = await collectMvnDependencies(
|
|
168
|
+
getMavenCommand(path, null),
|
|
169
|
+
null,
|
|
170
|
+
false,
|
|
171
|
+
true,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
if (path.endsWith(".jar")) {
|
|
175
|
+
jarFiles = [resolve(path)];
|
|
176
|
+
} else {
|
|
177
|
+
jarFiles = getAllFiles(
|
|
178
|
+
path,
|
|
179
|
+
`${options.multiProject ? "**/" : ""}*.[jw]ar`,
|
|
180
|
+
searchOptions,
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
// Jenkins plugins
|
|
184
|
+
const hpiFiles = getAllFiles(
|
|
185
|
+
path,
|
|
186
|
+
`${options.multiProject ? "**/" : ""}*.hpi`,
|
|
187
|
+
searchOptions,
|
|
188
|
+
);
|
|
189
|
+
if (hpiFiles.length) {
|
|
190
|
+
jarFiles = jarFiles.concat(hpiFiles);
|
|
191
|
+
}
|
|
192
|
+
for (const jar of jarFiles) {
|
|
193
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "jar-deps-"));
|
|
194
|
+
if (DEBUG_MODE) {
|
|
195
|
+
console.log(`Parsing ${jar}`);
|
|
196
|
+
}
|
|
197
|
+
const dlist = await extractJarArchive(jar, tempDir);
|
|
198
|
+
if (dlist?.length) {
|
|
199
|
+
pkgList = pkgList.concat(dlist);
|
|
200
|
+
}
|
|
201
|
+
if (pkgList.length) {
|
|
202
|
+
pkgList = await getMvnMetadata(pkgList);
|
|
203
|
+
}
|
|
204
|
+
// Clean up
|
|
205
|
+
if (tempDir?.startsWith(getTmpDir())) {
|
|
206
|
+
safeRmSync(tempDir, { recursive: true, force: true });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
pkgList = pkgList.concat(await convertJarNSToPackages(nsMapping));
|
|
210
|
+
return buildBomNSData(options, pkgList, "maven", {
|
|
211
|
+
src: path,
|
|
212
|
+
parentComponent,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Discover the real sbt project ids for a build by invoking sbt's own
|
|
218
|
+
* `projects` command. This is more reliable than scraping the build files with
|
|
219
|
+
* a regex, since it uses sbt's project resolution and avoids false positives
|
|
220
|
+
* (commented-out code, examples, values that merely resemble project defs) that
|
|
221
|
+
* can lead to hangs when those bogus scopes are later passed to `dependencyTree`.
|
|
222
|
+
*
|
|
223
|
+
* Falls back to the regex-based {@link discoverSbtProjects} heuristic when the
|
|
224
|
+
* sbt invocation fails or yields nothing useful.
|
|
225
|
+
*
|
|
226
|
+
* @param {string} basePath Directory of the sbt build
|
|
227
|
+
* @param {string} sbtCmd sbt executable
|
|
228
|
+
* @param {Object} env Environment for the spawned process
|
|
229
|
+
* @returns {string[]} List of sbt project ids
|
|
230
|
+
*/
|
|
231
|
+
export function discoverSbtProjectsFromCmd(basePath, sbtCmd, env) {
|
|
232
|
+
try {
|
|
233
|
+
const result = safeSpawnSync(
|
|
234
|
+
sbtCmd,
|
|
235
|
+
["-batch", "-no-colors", '"projects"'],
|
|
236
|
+
{
|
|
237
|
+
cwd: basePath,
|
|
238
|
+
shell: true,
|
|
239
|
+
env,
|
|
240
|
+
encoding: "utf-8",
|
|
241
|
+
},
|
|
242
|
+
);
|
|
243
|
+
if (result.status === 0 && !result.error) {
|
|
244
|
+
const { projects, root } = parseSbtProjects(result.stdout || "");
|
|
245
|
+
// Exclude the aggregating root project - its own dependencyTree is
|
|
246
|
+
// usually a subset of the aggregated subprojects and re-resolving it
|
|
247
|
+
// only adds noise/time.
|
|
248
|
+
const subprojects = projects.filter((p) => p !== root);
|
|
249
|
+
if (subprojects.length > 0) {
|
|
250
|
+
if (DEBUG_MODE) {
|
|
251
|
+
console.log(
|
|
252
|
+
`Discovered sbt projects via sbt: ${subprojects.join(", ")}`,
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
return subprojects;
|
|
256
|
+
}
|
|
257
|
+
// Single-project builds (root only): resolve at the root scope.
|
|
258
|
+
if (projects.length > 0) {
|
|
259
|
+
return [];
|
|
260
|
+
}
|
|
261
|
+
} else if (DEBUG_MODE) {
|
|
262
|
+
console.log(
|
|
263
|
+
"sbt projects command did not succeed. Falling back to heuristic project discovery.",
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
} catch (err) {
|
|
267
|
+
if (DEBUG_MODE) {
|
|
268
|
+
console.log("Unable to run sbt projects command.", err);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Fallback to the regex-based heuristic.
|
|
272
|
+
return discoverSbtProjects(basePath);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Function to create bom string for Java projects
|
|
277
|
+
*
|
|
278
|
+
* @param {string} path to the project
|
|
279
|
+
* @param {Object} options Parse options from the cli
|
|
280
|
+
* @returns {Promise<Object>} Promise resolving to BOM object
|
|
281
|
+
*/
|
|
282
|
+
export async function createJavaBom(path, options) {
|
|
283
|
+
let jarNSMapping = {};
|
|
284
|
+
let pkgList = [];
|
|
285
|
+
let dependencies = [];
|
|
286
|
+
// cyclone-dx-maven plugin creates a component for the app under metadata
|
|
287
|
+
// This is subsequently referred to in the dependencies list
|
|
288
|
+
let parentComponent = {};
|
|
289
|
+
// Support for tracking all the tools that created the BOM
|
|
290
|
+
// For java, this would correctly include the cyclonedx maven plugin.
|
|
291
|
+
let tools;
|
|
292
|
+
let possible_misses = false;
|
|
293
|
+
let parallelPropTaskOut = "";
|
|
294
|
+
// war/ear mode
|
|
295
|
+
if (path.endsWith(".war") || path.endsWith(".jar")) {
|
|
296
|
+
// Check if the file exists
|
|
297
|
+
if (safeExistsSync(path)) {
|
|
298
|
+
if (DEBUG_MODE) {
|
|
299
|
+
console.log(`Retrieving packages from ${path}`);
|
|
300
|
+
}
|
|
301
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "war-deps-"));
|
|
302
|
+
jarNSMapping = await collectJarNS(tempDir);
|
|
303
|
+
pkgList = await extractJarArchive(path, tempDir, jarNSMapping);
|
|
304
|
+
if (pkgList.length) {
|
|
305
|
+
pkgList = await getMvnMetadata(pkgList);
|
|
306
|
+
}
|
|
307
|
+
// Clean up
|
|
308
|
+
if (tempDir?.startsWith(getTmpDir())) {
|
|
309
|
+
console.log(`Cleaning up ${tempDir}`);
|
|
310
|
+
safeRmSync(tempDir, { recursive: true, force: true });
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
console.log(`${path} doesn't exist`);
|
|
314
|
+
}
|
|
315
|
+
return buildBomNSData(options, pkgList, "maven", {
|
|
316
|
+
src: dirname(path),
|
|
317
|
+
filename: path,
|
|
318
|
+
nsMapping: jarNSMapping,
|
|
319
|
+
dependencies,
|
|
320
|
+
parentComponent,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
// -t quarkus is supported
|
|
324
|
+
let isQuarkus = options?.projectType?.includes("quarkus");
|
|
325
|
+
let useMavenDepsTree = isQuarkus ? false : PREFER_MAVEN_DEPS_TREE;
|
|
326
|
+
// Is this a multi-module project
|
|
327
|
+
let rootModules;
|
|
328
|
+
// maven - pom.xml
|
|
329
|
+
const pomFiles = getAllFiles(
|
|
330
|
+
path,
|
|
331
|
+
`${options.multiProject ? "**/" : ""}pom.xml`,
|
|
332
|
+
options,
|
|
333
|
+
);
|
|
334
|
+
// gradle
|
|
335
|
+
const gradleFiles = getAllFiles(
|
|
336
|
+
path,
|
|
337
|
+
`${options.multiProject ? "**/" : ""}build.gradle*`,
|
|
338
|
+
options,
|
|
339
|
+
);
|
|
340
|
+
// mill
|
|
341
|
+
const millFiles = getAllFiles(
|
|
342
|
+
path,
|
|
343
|
+
`${options.multiProject ? "**/" : ""}build.mill`,
|
|
344
|
+
options,
|
|
345
|
+
);
|
|
346
|
+
let bomJsonFiles = [];
|
|
347
|
+
if (
|
|
348
|
+
pomFiles?.length &&
|
|
349
|
+
isPackageManagerAllowed(
|
|
350
|
+
"maven",
|
|
351
|
+
["bazel", "sbt", "gradle", "mill"],
|
|
352
|
+
options,
|
|
353
|
+
)
|
|
354
|
+
) {
|
|
355
|
+
if (gradleFiles.length) {
|
|
356
|
+
thoughtLog(
|
|
357
|
+
`Is this a Gradle project? I recommend invoking cdxgen with the "-t gradle" option if you're encountering build errors.`,
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
if (!isQuarkus) {
|
|
361
|
+
// Quarkus projects require special treatment. To detect quarkus, we parse the first 3 maven file to look for a hit
|
|
362
|
+
for (const pf of pomFiles.slice(0, 3)) {
|
|
363
|
+
const pomMap = parsePom(pf);
|
|
364
|
+
if (!rootModules && pomMap?.modules?.length) {
|
|
365
|
+
rootModules = pomMap.modules;
|
|
366
|
+
}
|
|
367
|
+
// In quarkus mode, we cannot use the maven deps tree
|
|
368
|
+
if (pomMap.isQuarkus) {
|
|
369
|
+
isQuarkus = true;
|
|
370
|
+
useMavenDepsTree = false;
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
let result;
|
|
376
|
+
let mvnArgs;
|
|
377
|
+
// FIXME: How do we motivate everyone to upgrade to 1.7?
|
|
378
|
+
const toolsSpecVersion = 1.6;
|
|
379
|
+
if (isQuarkus) {
|
|
380
|
+
thoughtLog(
|
|
381
|
+
"This appears to be a Quarkus project. Let's use the right Maven plugin.",
|
|
382
|
+
);
|
|
383
|
+
// disable analytics. See: https://quarkus.io/usage/
|
|
384
|
+
mvnArgs = [
|
|
385
|
+
"-fn",
|
|
386
|
+
"quarkus:dependency-sbom",
|
|
387
|
+
"-Dquarkus.analytics.disabled=true",
|
|
388
|
+
];
|
|
389
|
+
if (options.specVersion >= 1.6) {
|
|
390
|
+
mvnArgs = mvnArgs.concat(
|
|
391
|
+
`-Dquarkus.dependency.sbom.schema-version=${toolsSpecVersion}`,
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
} else {
|
|
395
|
+
// FIXME: The last maven plugin release was on November 28th, 2024.
|
|
396
|
+
// Should we fork this repo and maintain it ourselves?
|
|
397
|
+
const cdxMavenPlugin =
|
|
398
|
+
readEnvironmentVariable("CDX_MAVEN_PLUGIN") ||
|
|
399
|
+
"org.cyclonedx:cyclonedx-maven-plugin:2.9.1";
|
|
400
|
+
const cdxMavenGoal =
|
|
401
|
+
readEnvironmentVariable("CDX_MAVEN_GOAL") || "makeAggregateBom";
|
|
402
|
+
mvnArgs = [
|
|
403
|
+
"-fn",
|
|
404
|
+
`${cdxMavenPlugin}:${cdxMavenGoal}`,
|
|
405
|
+
"-DoutputName=bom",
|
|
406
|
+
];
|
|
407
|
+
if (includeMavenTestScope) {
|
|
408
|
+
mvnArgs.push("-DincludeTestScope=true");
|
|
409
|
+
}
|
|
410
|
+
// By using quiet mode we can reduce the maxBuffer used and avoid crashes
|
|
411
|
+
if (!DEBUG_MODE) {
|
|
412
|
+
mvnArgs.push("-q");
|
|
413
|
+
}
|
|
414
|
+
// Support for passing additional settings and profile to maven
|
|
415
|
+
if (readEnvironmentVariable("MVN_ARGS")) {
|
|
416
|
+
const addArgs = parseMavenArgs(readEnvironmentVariable("MVN_ARGS"));
|
|
417
|
+
mvnArgs = mvnArgs.concat(addArgs);
|
|
418
|
+
}
|
|
419
|
+
// specVersion 1.4 doesn't support externalReferences.type=distribution-intake
|
|
420
|
+
// so we need to run the plugin with the correct version
|
|
421
|
+
if (options.specVersion >= 1.6) {
|
|
422
|
+
mvnArgs = mvnArgs.concat(`-DschemaVersion=${toolsSpecVersion}`);
|
|
423
|
+
} else if (options.specVersion > 1.4) {
|
|
424
|
+
mvnArgs = mvnArgs.concat(`-DschemaVersion=${options.specVersion}`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
const firstPom = pomFiles.length ? pomFiles[0] : undefined;
|
|
428
|
+
let mavenCmd = getMavenCommand(path, path);
|
|
429
|
+
for (const f of pomFiles) {
|
|
430
|
+
const basePath = dirname(f);
|
|
431
|
+
if (
|
|
432
|
+
isQuarkus &&
|
|
433
|
+
!options.deep &&
|
|
434
|
+
rootModules?.includes(basename(basePath))
|
|
435
|
+
) {
|
|
436
|
+
if (DEBUG_MODE) {
|
|
437
|
+
console.log("Skipped sub-module", basePath);
|
|
438
|
+
}
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
const settingsXml = join(basePath, "settings.xml");
|
|
442
|
+
if (safeExistsSync(settingsXml)) {
|
|
443
|
+
console.log(
|
|
444
|
+
`maven settings.xml found in ${basePath}. Please set the MVN_ARGS environment variable based on the full mvn build command used for this project.\nExample: MVN_ARGS='--settings ${settingsXml}'`,
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
if (mavenCmd?.endsWith("mvn")) {
|
|
448
|
+
mavenCmd = getMavenCommand(basePath, path);
|
|
449
|
+
}
|
|
450
|
+
// Should we attempt to resolve class names
|
|
451
|
+
if (options.resolveClass || options.deep) {
|
|
452
|
+
const tmpjarNSMapping = await collectMvnDependencies(
|
|
453
|
+
mavenCmd,
|
|
454
|
+
basePath,
|
|
455
|
+
true,
|
|
456
|
+
false,
|
|
457
|
+
);
|
|
458
|
+
if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) {
|
|
459
|
+
jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
// Use the cyclonedx maven plugin if there is no preference for maven deps tree
|
|
463
|
+
if (!useMavenDepsTree) {
|
|
464
|
+
thoughtLog("The user wants me to use the cyclonedx-maven plugin.");
|
|
465
|
+
console.log(`Executing '${mavenCmd}' in`, basePath);
|
|
466
|
+
result = safeSpawnSync(mavenCmd, mvnArgs, {
|
|
467
|
+
cwd: basePath,
|
|
468
|
+
shell: isWin,
|
|
469
|
+
});
|
|
470
|
+
// Check if the cyclonedx plugin created the required bom.json file
|
|
471
|
+
// Sometimes the plugin fails silently for complex maven projects
|
|
472
|
+
bomJsonFiles = getAllFiles(
|
|
473
|
+
path,
|
|
474
|
+
"**/target/*{cdx,bom,cyclonedx}*.json",
|
|
475
|
+
options,
|
|
476
|
+
);
|
|
477
|
+
// Check if the bom json files got created in a directory other than target
|
|
478
|
+
if (!bomJsonFiles.length) {
|
|
479
|
+
bomJsonFiles = getAllFiles(
|
|
480
|
+
path,
|
|
481
|
+
"target/**/*{cdx,bom,cyclonedx}*.json",
|
|
482
|
+
options,
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
// Also check if the user has a preference for maven deps tree command
|
|
487
|
+
if (
|
|
488
|
+
useMavenDepsTree ||
|
|
489
|
+
!bomJsonFiles.length ||
|
|
490
|
+
result?.status !== 0 ||
|
|
491
|
+
result?.error
|
|
492
|
+
) {
|
|
493
|
+
const tempRoot = getTmpDir();
|
|
494
|
+
const tempDir = safeMkdtempSync(join(tempRoot, "cdxgen-mvn-"));
|
|
495
|
+
const tempMvnTree = join(tempDir, "cdxgen-mvn-tree.json");
|
|
496
|
+
const tempMvnTreeText = join(tempDir, "cdxgen-mvn-tree.txt");
|
|
497
|
+
const tempMvnParentTree = join(tempDir, "cdxgen-mvn-parent-tree.json");
|
|
498
|
+
const tempMvnParentTreeText = join(
|
|
499
|
+
tempDir,
|
|
500
|
+
"cdxgen-mvn-parent-tree.txt",
|
|
501
|
+
);
|
|
502
|
+
try {
|
|
503
|
+
let mvnTreeArgs = [
|
|
504
|
+
"dependency:tree",
|
|
505
|
+
`-DoutputFile=${tempMvnTree}`,
|
|
506
|
+
"-DoutputType=json",
|
|
507
|
+
];
|
|
508
|
+
let addArgs = [];
|
|
509
|
+
if (readEnvironmentVariable("MVN_ARGS")) {
|
|
510
|
+
addArgs = parseMavenArgs(readEnvironmentVariable("MVN_ARGS"));
|
|
511
|
+
mvnTreeArgs = mvnTreeArgs.concat(addArgs);
|
|
512
|
+
}
|
|
513
|
+
// Automatically use settings.xml to improve the success for fallback
|
|
514
|
+
if (safeExistsSync(settingsXml)) {
|
|
515
|
+
mvnTreeArgs.push("-s");
|
|
516
|
+
mvnTreeArgs.push(settingsXml);
|
|
517
|
+
}
|
|
518
|
+
// For the first pom alone, we need to execute first in non-recursive mode to capture
|
|
519
|
+
// the parent component. Then, we execute all of them in recursive mode
|
|
520
|
+
if (f === firstPom) {
|
|
521
|
+
thoughtLog(
|
|
522
|
+
"What is the parent component here? Let's use maven command to find out.",
|
|
523
|
+
);
|
|
524
|
+
let findParentComponentArgs = [
|
|
525
|
+
"dependency:tree",
|
|
526
|
+
"-N",
|
|
527
|
+
`-DoutputFile=${tempMvnParentTree}`,
|
|
528
|
+
"-DoutputType=json",
|
|
529
|
+
];
|
|
530
|
+
if (addArgs.length) {
|
|
531
|
+
findParentComponentArgs = findParentComponentArgs.concat(addArgs);
|
|
532
|
+
}
|
|
533
|
+
result = safeSpawnSync(mavenCmd, findParentComponentArgs, {
|
|
534
|
+
cwd: basePath,
|
|
535
|
+
shell: isWin,
|
|
536
|
+
});
|
|
537
|
+
// If json is empty or unparseable, fallback to text parsing
|
|
538
|
+
let emptyJson = !safeExistsSync(tempMvnParentTree);
|
|
539
|
+
if (safeExistsSync(tempMvnParentTree)) {
|
|
540
|
+
const mvnTreeString = readFileSync(tempMvnParentTree, {
|
|
541
|
+
encoding: "utf-8",
|
|
542
|
+
});
|
|
543
|
+
const parsedList = parseMavenTreeJson(mvnTreeString, f);
|
|
544
|
+
if (!parsedList?.pkgList?.length) {
|
|
545
|
+
emptyJson = true;
|
|
546
|
+
// Remove the invalid json file so text output is preferred below.
|
|
547
|
+
if (safeExistsSync(tempMvnParentTree)) {
|
|
548
|
+
safeUnlinkSync(tempMvnParentTree);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
if (result.status !== 0 || result.error || emptyJson) {
|
|
553
|
+
findParentComponentArgs = [
|
|
554
|
+
"dependency:tree",
|
|
555
|
+
"-N",
|
|
556
|
+
`-DoutputFile=${tempMvnParentTreeText}`,
|
|
557
|
+
];
|
|
558
|
+
if (addArgs.length) {
|
|
559
|
+
findParentComponentArgs =
|
|
560
|
+
findParentComponentArgs.concat(addArgs);
|
|
561
|
+
}
|
|
562
|
+
result = safeSpawnSync(mavenCmd, findParentComponentArgs, {
|
|
563
|
+
cwd: basePath,
|
|
564
|
+
shell: isWin,
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
if (result.status === 0) {
|
|
568
|
+
const parentTreeFile = safeExistsSync(tempMvnParentTreeText)
|
|
569
|
+
? tempMvnParentTreeText
|
|
570
|
+
: tempMvnParentTree;
|
|
571
|
+
if (safeExistsSync(parentTreeFile)) {
|
|
572
|
+
const mvnTreeString = readFileSync(parentTreeFile, {
|
|
573
|
+
encoding: "utf-8",
|
|
574
|
+
});
|
|
575
|
+
const parsedList = parentTreeFile.endsWith(".json")
|
|
576
|
+
? parseMavenTreeJson(mvnTreeString, f)
|
|
577
|
+
: parseMavenTree(mvnTreeString, f);
|
|
578
|
+
const dlist = parsedList.pkgList || [];
|
|
579
|
+
if (dlist.length) {
|
|
580
|
+
const tmpParentComponent = dlist.splice(0, 1)[0];
|
|
581
|
+
tmpParentComponent.type = "application";
|
|
582
|
+
parentComponent = tmpParentComponent;
|
|
583
|
+
parentComponent.components = [];
|
|
584
|
+
if (parentComponent.name) {
|
|
585
|
+
thoughtLog(
|
|
586
|
+
`Parent component is called ${parentComponent.name}!`,
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
thoughtLog(
|
|
594
|
+
`**MAVEN**: Let's use Maven to collect packages from ${basePath}.`,
|
|
595
|
+
);
|
|
596
|
+
if (DEBUG_MODE) {
|
|
597
|
+
console.log(
|
|
598
|
+
`Executing '${basename(mavenCmd)} dependency:tree ...' in ${basePath}`,
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
result = safeSpawnSync(mavenCmd, mvnTreeArgs, {
|
|
602
|
+
cwd: basePath,
|
|
603
|
+
shell: isWin,
|
|
604
|
+
});
|
|
605
|
+
let emptyJson = !safeExistsSync(tempMvnTree);
|
|
606
|
+
if (safeExistsSync(tempMvnTree)) {
|
|
607
|
+
const mvnTreeString = readFileSync(tempMvnTree, {
|
|
608
|
+
encoding: "utf-8",
|
|
609
|
+
});
|
|
610
|
+
const parsedList = parseMavenTreeJson(mvnTreeString, f);
|
|
611
|
+
if (!parsedList?.pkgList?.length) {
|
|
612
|
+
emptyJson = true;
|
|
613
|
+
// Remove the invalid json file so text output is preferred below.
|
|
614
|
+
if (safeExistsSync(tempMvnTree)) {
|
|
615
|
+
safeUnlinkSync(tempMvnTree);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
if (result.status !== 0 || result.error || emptyJson) {
|
|
620
|
+
mvnTreeArgs = [
|
|
621
|
+
"dependency:tree",
|
|
622
|
+
`-DoutputFile=${tempMvnTreeText}`,
|
|
623
|
+
];
|
|
624
|
+
if (addArgs.length) {
|
|
625
|
+
mvnTreeArgs = mvnTreeArgs.concat(addArgs);
|
|
626
|
+
}
|
|
627
|
+
if (safeExistsSync(settingsXml)) {
|
|
628
|
+
mvnTreeArgs.push("-s");
|
|
629
|
+
mvnTreeArgs.push(settingsXml);
|
|
630
|
+
}
|
|
631
|
+
result = safeSpawnSync(mavenCmd, mvnTreeArgs, {
|
|
632
|
+
cwd: basePath,
|
|
633
|
+
shell: isWin,
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
if (result.status !== 0 || result.error) {
|
|
637
|
+
possible_misses = true;
|
|
638
|
+
// Our approach to recursively invoking the maven plugin for each sub-module is bound to result in failures
|
|
639
|
+
// These could be due to a range of reasons that are covered below.
|
|
640
|
+
if (pomFiles.length === 1 || DEBUG_MODE || PREFER_MAVEN_DEPS_TREE) {
|
|
641
|
+
if (result.stdout) {
|
|
642
|
+
console.log(result.stdout);
|
|
643
|
+
}
|
|
644
|
+
if (result.stderr) {
|
|
645
|
+
console.log(result.stderr);
|
|
646
|
+
console.log("The above build errors could be due to:\n");
|
|
647
|
+
}
|
|
648
|
+
if (
|
|
649
|
+
result.stdout &&
|
|
650
|
+
(result.stdout.includes("Non-resolvable parent POM") ||
|
|
651
|
+
result.stdout.includes("points at wrong local POM"))
|
|
652
|
+
) {
|
|
653
|
+
console.log(
|
|
654
|
+
"1. Check if the pom.xml contains valid settings for parent and modules. Some projects can be built only from a specific directory.",
|
|
655
|
+
);
|
|
656
|
+
} else if (
|
|
657
|
+
result.stdout &&
|
|
658
|
+
(result.stdout.includes("Could not resolve dependencies") ||
|
|
659
|
+
result.stdout.includes(
|
|
660
|
+
"no dependency information available",
|
|
661
|
+
) ||
|
|
662
|
+
result.stdout.includes(
|
|
663
|
+
"The following artifacts could not be resolved",
|
|
664
|
+
))
|
|
665
|
+
) {
|
|
666
|
+
console.log(
|
|
667
|
+
"1. Try building the project with 'mvn package -Dmaven.test.skip=true' using the correct version of Java and maven before invoking cdxgen.",
|
|
668
|
+
);
|
|
669
|
+
} else if (
|
|
670
|
+
result.stdout?.includes(
|
|
671
|
+
"Could not resolve target platform specification",
|
|
672
|
+
)
|
|
673
|
+
) {
|
|
674
|
+
console.log(
|
|
675
|
+
"1. Some projects can be built only from the root directory. Invoke cdxgen with --no-recurse option",
|
|
676
|
+
);
|
|
677
|
+
} else {
|
|
678
|
+
console.log(
|
|
679
|
+
"1. Java version requirement: cdxgen container image bundles Java 24 with maven 3.9 which might be incompatible. Try running cdxgen with the custom JDK11-based image `ghcr.io/cdxgen/cdxgen-java11:v13`.",
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
console.log(
|
|
683
|
+
"2. Private dependencies cannot be downloaded: Check if any additional arguments must be passed to maven and set them via MVN_ARGS environment variable.",
|
|
684
|
+
);
|
|
685
|
+
console.log(
|
|
686
|
+
"3. Check if all required environment variables including any maven profile arguments are passed correctly to this tool.",
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
// Do not fall back to methods that can produce incomplete results when failOnError is set
|
|
690
|
+
options.failOnError && process.exit(1);
|
|
691
|
+
console.log(
|
|
692
|
+
"\nFalling back to parsing pom.xml files. Only direct dependencies would get included!",
|
|
693
|
+
);
|
|
694
|
+
thoughtLog(
|
|
695
|
+
"**MAVEN**: There appear to be build errors, so the SBOM will be incomplete.",
|
|
696
|
+
);
|
|
697
|
+
const pomMap = parsePom(f);
|
|
698
|
+
const dlist = pomMap?.dependencies || [];
|
|
699
|
+
if (dlist.length) {
|
|
700
|
+
pkgList = pkgList.concat(dlist);
|
|
701
|
+
}
|
|
702
|
+
} else {
|
|
703
|
+
const treeFile = safeExistsSync(tempMvnTreeText)
|
|
704
|
+
? tempMvnTreeText
|
|
705
|
+
: tempMvnTree;
|
|
706
|
+
if (safeExistsSync(treeFile)) {
|
|
707
|
+
const mvnTreeString = readFileSync(treeFile, {
|
|
708
|
+
encoding: "utf-8",
|
|
709
|
+
});
|
|
710
|
+
const parsedList = treeFile.endsWith(".json")
|
|
711
|
+
? parseMavenTreeJson(mvnTreeString, f)
|
|
712
|
+
: parseMavenTree(mvnTreeString, f);
|
|
713
|
+
const dlist = parsedList.pkgList || [];
|
|
714
|
+
const tmpParentComponent = dlist.splice(0, 1)[0];
|
|
715
|
+
if (tmpParentComponent) {
|
|
716
|
+
tmpParentComponent.type = "application";
|
|
717
|
+
}
|
|
718
|
+
if (dlist.length) {
|
|
719
|
+
pkgList = pkgList.concat(dlist);
|
|
720
|
+
if (dlist.length > 1) {
|
|
721
|
+
thoughtLog(`Obtained ${dlist.length} components from maven.`);
|
|
722
|
+
} else {
|
|
723
|
+
thoughtLog(
|
|
724
|
+
`"Received very few components from the maven dependency tree command for ${basePath}."`,
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
// Retain the parent hierarchy
|
|
729
|
+
if (!tmpParentComponent) {
|
|
730
|
+
thoughtLog(
|
|
731
|
+
`No parseable components were found after executing '${basename(mavenCmd)}'.`,
|
|
732
|
+
);
|
|
733
|
+
} else if (!Object.keys(parentComponent).length) {
|
|
734
|
+
parentComponent = tmpParentComponent;
|
|
735
|
+
parentComponent.components = [];
|
|
736
|
+
} else {
|
|
737
|
+
parentComponent.components.push(tmpParentComponent);
|
|
738
|
+
}
|
|
739
|
+
if (parsedList?.dependenciesList?.length) {
|
|
740
|
+
dependencies = mergeDependencies(
|
|
741
|
+
dependencies,
|
|
742
|
+
parsedList.dependenciesList,
|
|
743
|
+
tmpParentComponent,
|
|
744
|
+
);
|
|
745
|
+
} else {
|
|
746
|
+
if (dlist?.length) {
|
|
747
|
+
thoughtLog(
|
|
748
|
+
`Hmm, I didn't find any dependencies after executing '${basename(mavenCmd)}'. However, I did get ${dlist.length} components, which is confusing.`,
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
} finally {
|
|
755
|
+
if (!DEBUG_MODE && tempDir?.startsWith(tempRoot)) {
|
|
756
|
+
safeRmSync(tempDir, { recursive: true, force: true });
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
} // for
|
|
761
|
+
// Locate and parse all bom.json files from the maven plugin
|
|
762
|
+
if (!useMavenDepsTree) {
|
|
763
|
+
for (const abjson of bomJsonFiles) {
|
|
764
|
+
let bomJsonObj;
|
|
765
|
+
try {
|
|
766
|
+
if (DEBUG_MODE) {
|
|
767
|
+
console.log(`Extracting data from generated bom file ${abjson}`);
|
|
768
|
+
}
|
|
769
|
+
bomJsonObj = JSON.parse(
|
|
770
|
+
readFileSync(abjson, {
|
|
771
|
+
encoding: "utf-8",
|
|
772
|
+
}),
|
|
773
|
+
);
|
|
774
|
+
if (bomJsonObj) {
|
|
775
|
+
if (
|
|
776
|
+
!tools &&
|
|
777
|
+
bomJsonObj.metadata &&
|
|
778
|
+
bomJsonObj.metadata.tools &&
|
|
779
|
+
(Array.isArray(bomJsonObj.metadata.tools) ||
|
|
780
|
+
bomJsonObj.metadata.tools.components ||
|
|
781
|
+
bomJsonObj.metadata.tools.services)
|
|
782
|
+
) {
|
|
783
|
+
tools = bomJsonObj.metadata.tools;
|
|
784
|
+
}
|
|
785
|
+
const toolRefs = extractToolRefs(
|
|
786
|
+
bomJsonObj?.metadata?.tools,
|
|
787
|
+
(tool) => tool?.name !== "cdxgen",
|
|
788
|
+
);
|
|
789
|
+
if (
|
|
790
|
+
bomJsonObj.metadata?.component &&
|
|
791
|
+
!Object.keys(parentComponent).length
|
|
792
|
+
) {
|
|
793
|
+
parentComponent = bomJsonObj.metadata.component;
|
|
794
|
+
options.parentComponent = parentComponent;
|
|
795
|
+
}
|
|
796
|
+
if (bomJsonObj.components) {
|
|
797
|
+
// Inject evidence into the components. #994
|
|
798
|
+
if (options.specVersion >= 1.5) {
|
|
799
|
+
// maven would usually generate a target directory closest to the pom.xml
|
|
800
|
+
// I am sure there would be cases where this assumption is not true :)
|
|
801
|
+
const srcPomFile = join(dirname(abjson), "..", "pom.xml");
|
|
802
|
+
for (const acomp of bomJsonObj.components) {
|
|
803
|
+
if (!acomp.evidence) {
|
|
804
|
+
acomp.evidence = {
|
|
805
|
+
identity: {
|
|
806
|
+
field: "purl",
|
|
807
|
+
confidence: 0.8,
|
|
808
|
+
methods: [
|
|
809
|
+
{
|
|
810
|
+
technique: "manifest-analysis",
|
|
811
|
+
confidence: 0.8,
|
|
812
|
+
value: srcPomFile,
|
|
813
|
+
},
|
|
814
|
+
],
|
|
815
|
+
},
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
if (!acomp.properties) {
|
|
819
|
+
acomp.properties = [];
|
|
820
|
+
}
|
|
821
|
+
acomp.properties.push({
|
|
822
|
+
name: "internal:SrcFile",
|
|
823
|
+
value: srcPomFile,
|
|
824
|
+
});
|
|
825
|
+
attachIdentityTools(acomp, toolRefs);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
pkgList = pkgList.concat(bomJsonObj.components);
|
|
829
|
+
}
|
|
830
|
+
if (bomJsonObj.dependencies) {
|
|
831
|
+
dependencies = mergeDependencies(
|
|
832
|
+
dependencies,
|
|
833
|
+
bomJsonObj.dependencies,
|
|
834
|
+
parentComponent,
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
} catch (err) {
|
|
839
|
+
if (options.failOnError || DEBUG_MODE) {
|
|
840
|
+
console.log(err);
|
|
841
|
+
options.failOnError && process.exit(1);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
if (possible_misses) {
|
|
847
|
+
if (gradleFiles.length) {
|
|
848
|
+
console.log(
|
|
849
|
+
"Is this a gradle project? Try running cdxgen with `-t gradle`.",
|
|
850
|
+
);
|
|
851
|
+
} else if (!DEBUG_MODE) {
|
|
852
|
+
console.warn(
|
|
853
|
+
"Multiple errors occurred while building this project with maven. The SBOM is therefore incomplete!",
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
const allProjects = [];
|
|
859
|
+
const allProjectsAddedPurls = [];
|
|
860
|
+
const rootDependsOn = new Set();
|
|
861
|
+
const gradleModules = new Map();
|
|
862
|
+
// Determine the root path for gradle
|
|
863
|
+
// Fixes gradle invocation for microservices-demo
|
|
864
|
+
let gradleRootPath = path;
|
|
865
|
+
if (
|
|
866
|
+
gradleFiles?.length &&
|
|
867
|
+
!safeExistsSync(join(path, "settings.gradle")) &&
|
|
868
|
+
!safeExistsSync(join(path, "settings.gradle.kts")) &&
|
|
869
|
+
!safeExistsSync(join(path, "build.gradle")) &&
|
|
870
|
+
!safeExistsSync(join(path, "build.gradle.kts"))
|
|
871
|
+
) {
|
|
872
|
+
gradleRootPath = dirname(gradleFiles[0]);
|
|
873
|
+
}
|
|
874
|
+
if (safeExistsSync(join(gradleRootPath, "gradle.properties"))) {
|
|
875
|
+
thoughtLog(
|
|
876
|
+
"Hmm, there is a gradle.properties file. Do we need any private modules or custom JVM arguments for this project 🤔?",
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
// Execute gradle properties
|
|
880
|
+
if (
|
|
881
|
+
gradleFiles?.length &&
|
|
882
|
+
isPackageManagerAllowed(
|
|
883
|
+
"gradle",
|
|
884
|
+
["maven", "bazel", "sbt", "mill"],
|
|
885
|
+
options,
|
|
886
|
+
)
|
|
887
|
+
) {
|
|
888
|
+
const wrapperPropPath = join(
|
|
889
|
+
gradleRootPath,
|
|
890
|
+
"gradle",
|
|
891
|
+
"wrapper",
|
|
892
|
+
"gradle-wrapper.properties",
|
|
893
|
+
);
|
|
894
|
+
if (safeExistsSync(wrapperPropPath)) {
|
|
895
|
+
try {
|
|
896
|
+
const propContent = readFileSync(wrapperPropPath, "utf-8");
|
|
897
|
+
const distUrlLine = propContent
|
|
898
|
+
.split("\n")
|
|
899
|
+
.find((l) => l.startsWith("distributionUrl="));
|
|
900
|
+
if (distUrlLine) {
|
|
901
|
+
const distributionUrl = distUrlLine
|
|
902
|
+
.split("=")[1]
|
|
903
|
+
.trim()
|
|
904
|
+
.replace(/\\:/g, ":");
|
|
905
|
+
const versionMatch = distributionUrl.match(
|
|
906
|
+
/gradle-(.*?)-(bin|all)\.zip/,
|
|
907
|
+
);
|
|
908
|
+
const gradleVersion = versionMatch ? versionMatch[1] : "unknown";
|
|
909
|
+
thoughtLog(
|
|
910
|
+
`Found Gradle wrapper with distributionUrl: ${distributionUrl}, version: ${gradleVersion}`,
|
|
911
|
+
);
|
|
912
|
+
if (!tools) {
|
|
913
|
+
tools = [];
|
|
914
|
+
}
|
|
915
|
+
let toolsArr = tools;
|
|
916
|
+
if (!Array.isArray(toolsArr)) {
|
|
917
|
+
if (toolsArr.components) {
|
|
918
|
+
toolsArr = toolsArr.components;
|
|
919
|
+
} else {
|
|
920
|
+
toolsArr = [];
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
if (!toolsArr.find((c) => c.name === "gradle")) {
|
|
924
|
+
const distShaLine = propContent
|
|
925
|
+
.split("\n")
|
|
926
|
+
.find((l) => l.startsWith("distributionSha256Sum="));
|
|
927
|
+
let hashes;
|
|
928
|
+
if (distShaLine) {
|
|
929
|
+
const sha256Sum = distShaLine.split("=")[1].trim();
|
|
930
|
+
if (sha256Sum) {
|
|
931
|
+
hashes = [
|
|
932
|
+
{
|
|
933
|
+
alg: "SHA-256",
|
|
934
|
+
content: sha256Sum,
|
|
935
|
+
},
|
|
936
|
+
];
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
const gradleComponent = {
|
|
940
|
+
type: "application",
|
|
941
|
+
group: "org.gradle",
|
|
942
|
+
name: "gradle",
|
|
943
|
+
version: gradleVersion,
|
|
944
|
+
externalReferences: [
|
|
945
|
+
{
|
|
946
|
+
type: "distribution",
|
|
947
|
+
url: distributionUrl,
|
|
948
|
+
},
|
|
949
|
+
],
|
|
950
|
+
isExternal: true,
|
|
951
|
+
};
|
|
952
|
+
applyPurl(
|
|
953
|
+
gradleComponent,
|
|
954
|
+
mavenPurl("org.gradle", "gradle", gradleVersion, {
|
|
955
|
+
type: "bin",
|
|
956
|
+
}),
|
|
957
|
+
);
|
|
958
|
+
if (hashes) {
|
|
959
|
+
gradleComponent.hashes = hashes;
|
|
960
|
+
}
|
|
961
|
+
toolsArr.push(gradleComponent);
|
|
962
|
+
}
|
|
963
|
+
if (Array.isArray(tools)) {
|
|
964
|
+
tools = toolsArr;
|
|
965
|
+
} else {
|
|
966
|
+
tools.components = toolsArr;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
} catch (_err) {
|
|
970
|
+
// ignore
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
let includedBuilds = [];
|
|
974
|
+
let allProjectsStr = [];
|
|
975
|
+
if (readEnvironmentVariable("GRADLE_INCLUDED_BUILDS")) {
|
|
976
|
+
includedBuilds = readEnvironmentVariable("GRADLE_INCLUDED_BUILDS")
|
|
977
|
+
.split(",")
|
|
978
|
+
.map((b) => (!b.startsWith(":") ? `:${b}` : b));
|
|
979
|
+
}
|
|
980
|
+
const resolveGradleDistribution = isFeatureEnabled(
|
|
981
|
+
options,
|
|
982
|
+
"resolve-gradle-distribution",
|
|
983
|
+
);
|
|
984
|
+
const gradleInitArgs = readEnvironmentVariable("GRADLE_INCLUDED_BUILDS")
|
|
985
|
+
? []
|
|
986
|
+
: ["--init-script", GRADLE_INIT_SCRIPT];
|
|
987
|
+
if (resolveGradleDistribution && gradleInitArgs.length) {
|
|
988
|
+
gradleInitArgs.push("-PcdxgenResolveDistribution=true");
|
|
989
|
+
}
|
|
990
|
+
parallelPropTaskOut = executeParallelGradleProperties(
|
|
991
|
+
gradleRootPath,
|
|
992
|
+
[null].concat(includedBuilds),
|
|
993
|
+
gradleInitArgs,
|
|
994
|
+
);
|
|
995
|
+
if (readEnvironmentVariable("GRADLE_INCLUDED_BUILDS") === undefined) {
|
|
996
|
+
const outputLines = parallelPropTaskOut.split("\n");
|
|
997
|
+
for (const [_i, line] of outputLines.entries()) {
|
|
998
|
+
if (line.startsWith("Root project '") || line.startsWith("Project '")) {
|
|
999
|
+
break;
|
|
1000
|
+
}
|
|
1001
|
+
if (line.startsWith("<CDXGEN:includedBuild>")) {
|
|
1002
|
+
const includedBuild = line.split(">");
|
|
1003
|
+
if (!includedBuilds.includes(includedBuild[1].trim())) {
|
|
1004
|
+
includedBuilds.push(includedBuild[1].trim());
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
if (includedBuilds.length > 0) {
|
|
1009
|
+
thoughtLog(
|
|
1010
|
+
`Wait, this gradle project uses composite builds. I must carefully process these ${includedBuilds.length} projects, in addition to the root.`,
|
|
1011
|
+
);
|
|
1012
|
+
if (DEBUG_MODE) {
|
|
1013
|
+
console.log(`Composite builds: ${includedBuilds.join(" ").trim()}.`);
|
|
1014
|
+
}
|
|
1015
|
+
parallelPropTaskOut = parallelPropTaskOut.concat(
|
|
1016
|
+
"\n",
|
|
1017
|
+
executeParallelGradleProperties(gradleRootPath, includedBuilds),
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
const splitPropTaskOut = splitOutputByGradleProjects(parallelPropTaskOut, [
|
|
1022
|
+
"properties",
|
|
1023
|
+
]);
|
|
1024
|
+
for (const [key, propTaskOut] of splitPropTaskOut.entries()) {
|
|
1025
|
+
const retMap = parseGradleProperties(propTaskOut);
|
|
1026
|
+
const rootProject = retMap.rootProject;
|
|
1027
|
+
if (rootProject) {
|
|
1028
|
+
const rootComponent = await buildObjectForGradleModule(
|
|
1029
|
+
rootProject,
|
|
1030
|
+
retMap.metadata,
|
|
1031
|
+
);
|
|
1032
|
+
if (!includedBuilds.includes(key)) {
|
|
1033
|
+
parentComponent = rootComponent;
|
|
1034
|
+
}
|
|
1035
|
+
gradleModules.set(key, rootComponent);
|
|
1036
|
+
if (!allProjectsAddedPurls.includes(rootComponent["purl"])) {
|
|
1037
|
+
allProjects.push(rootComponent);
|
|
1038
|
+
rootDependsOn.add(rootComponent["bom-ref"]);
|
|
1039
|
+
allProjectsAddedPurls.push(rootComponent["purl"]);
|
|
1040
|
+
}
|
|
1041
|
+
allProjectsStr = allProjectsStr.concat(retMap.projects);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
// Get the sub-project properties and set the root dependencies
|
|
1045
|
+
if (allProjectsStr?.length) {
|
|
1046
|
+
const modulesToSkip = readEnvironmentVariable("GRADLE_SKIP_MODULES")
|
|
1047
|
+
? readEnvironmentVariable("GRADLE_SKIP_MODULES").split(",")
|
|
1048
|
+
: [];
|
|
1049
|
+
if (modulesToSkip.length) {
|
|
1050
|
+
thoughtLog(
|
|
1051
|
+
`Good news. I know there are ${allProjectsStr.length} gradle modules at ${gradleRootPath}. I must skip ${modulesToSkip.length} out of these.`,
|
|
1052
|
+
);
|
|
1053
|
+
}
|
|
1054
|
+
parallelPropTaskOut = executeParallelGradleProperties(
|
|
1055
|
+
gradleRootPath,
|
|
1056
|
+
allProjectsStr.filter((module) => !modulesToSkip.includes(module)),
|
|
1057
|
+
);
|
|
1058
|
+
const splitPropTaskOut = splitOutputByGradleProjects(
|
|
1059
|
+
parallelPropTaskOut,
|
|
1060
|
+
["properties"],
|
|
1061
|
+
);
|
|
1062
|
+
|
|
1063
|
+
for (const subProject of allProjectsStr) {
|
|
1064
|
+
const retMap = parseGradleProperties(
|
|
1065
|
+
splitPropTaskOut.get(subProject),
|
|
1066
|
+
subProject,
|
|
1067
|
+
);
|
|
1068
|
+
const rootSubProject = retMap.rootProject;
|
|
1069
|
+
if (rootSubProject) {
|
|
1070
|
+
const rootSubProjectObj = await buildObjectForGradleModule(
|
|
1071
|
+
rootSubProject === "root" ? subProject : rootSubProject,
|
|
1072
|
+
retMap.metadata,
|
|
1073
|
+
);
|
|
1074
|
+
if (!allProjectsAddedPurls.includes(rootSubProjectObj["purl"])) {
|
|
1075
|
+
allProjects.push(rootSubProjectObj);
|
|
1076
|
+
rootDependsOn.add(rootSubProjectObj["bom-ref"]);
|
|
1077
|
+
allProjectsAddedPurls.push(rootSubProjectObj["purl"]);
|
|
1078
|
+
}
|
|
1079
|
+
gradleModules.set(subProject, rootSubProjectObj);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
// Bug #317 fix
|
|
1083
|
+
parentComponent.components = allProjects.flatMap((s) => {
|
|
1084
|
+
delete s.qualifiers;
|
|
1085
|
+
delete s.evidence;
|
|
1086
|
+
return s;
|
|
1087
|
+
});
|
|
1088
|
+
dependencies.push({
|
|
1089
|
+
ref: parentComponent["bom-ref"],
|
|
1090
|
+
dependsOn: [...rootDependsOn].sort(),
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
if (
|
|
1095
|
+
gradleFiles?.length &&
|
|
1096
|
+
options.installDeps &&
|
|
1097
|
+
isPackageManagerAllowed(
|
|
1098
|
+
"gradle",
|
|
1099
|
+
["maven", "bazel", "sbt", "mill"],
|
|
1100
|
+
options,
|
|
1101
|
+
)
|
|
1102
|
+
) {
|
|
1103
|
+
allProjects.push(parentComponent);
|
|
1104
|
+
const gradleCmd = getGradleCommand(gradleRootPath, null);
|
|
1105
|
+
const gradleDepTask = readEnvironmentVariable("GRADLE_DEPENDENCY_TASK")
|
|
1106
|
+
? readEnvironmentVariable("GRADLE_DEPENDENCY_TASK")
|
|
1107
|
+
: "dependencies";
|
|
1108
|
+
|
|
1109
|
+
const gradleSubCommands = [];
|
|
1110
|
+
let modulesToSkip = readEnvironmentVariable("GRADLE_SKIP_MODULES")
|
|
1111
|
+
? readEnvironmentVariable("GRADLE_SKIP_MODULES").split(",")
|
|
1112
|
+
: [];
|
|
1113
|
+
if (readEnvironmentVariable("GRADLE_SKIP_MODULE_DEPENDENCIES")) {
|
|
1114
|
+
modulesToSkip = modulesToSkip.concat(
|
|
1115
|
+
readEnvironmentVariable("GRADLE_SKIP_MODULE_DEPENDENCIES").split(","),
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
if (!modulesToSkip.includes("root")) {
|
|
1119
|
+
gradleSubCommands.push(gradleDepTask);
|
|
1120
|
+
}
|
|
1121
|
+
for (const [key, sp] of gradleModules) {
|
|
1122
|
+
//create single command for dependencies tasks on all subprojects
|
|
1123
|
+
if (sp.purl !== parentComponent.purl && !modulesToSkip.includes(key)) {
|
|
1124
|
+
gradleSubCommands.push(`${key}:${gradleDepTask}`);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
const gradleArguments = buildGradleCommandArguments(
|
|
1128
|
+
readEnvironmentVariable("GRADLE_ARGS")
|
|
1129
|
+
? readEnvironmentVariable("GRADLE_ARGS").split(" ")
|
|
1130
|
+
: [],
|
|
1131
|
+
gradleSubCommands,
|
|
1132
|
+
readEnvironmentVariable("GRADLE_ARGS_DEPENDENCIES")
|
|
1133
|
+
? readEnvironmentVariable("GRADLE_ARGS_DEPENDENCIES").split(" ")
|
|
1134
|
+
: [],
|
|
1135
|
+
gradleCmd.length,
|
|
1136
|
+
);
|
|
1137
|
+
const allOutputs = [];
|
|
1138
|
+
for (const gradleArg of gradleArguments) {
|
|
1139
|
+
if (DEBUG_MODE) {
|
|
1140
|
+
console.log(
|
|
1141
|
+
`Executing ${gradleCmd} with arguments ${gradleArg.join(" ").substring(0, 150)}... in ${gradleRootPath}`,
|
|
1142
|
+
);
|
|
1143
|
+
}
|
|
1144
|
+
thoughtLog(
|
|
1145
|
+
`Let's invoke '${basename(gradleCmd)}' with the arguments '${gradleArg.join(" ").substring(0, 100)} ...'.`,
|
|
1146
|
+
);
|
|
1147
|
+
const finalGradleArg = gradleArg.includes("--info")
|
|
1148
|
+
? gradleArg
|
|
1149
|
+
: gradleArg.concat(["--info"]);
|
|
1150
|
+
const sresult = safeSpawnSync(gradleCmd, finalGradleArg, {
|
|
1151
|
+
cwd: gradleRootPath,
|
|
1152
|
+
shell: isWin,
|
|
1153
|
+
});
|
|
1154
|
+
if (sresult.status !== 0 || sresult.error) {
|
|
1155
|
+
if (options.failOnError || DEBUG_MODE) {
|
|
1156
|
+
console.error(sresult.stdout, sresult.stderr);
|
|
1157
|
+
}
|
|
1158
|
+
options.failOnError && process.exit(1);
|
|
1159
|
+
}
|
|
1160
|
+
if (sresult.stdout !== null) {
|
|
1161
|
+
allOutputs.push(sresult.stdout);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
const sstdout = allOutputs.join("\n");
|
|
1165
|
+
if (sstdout) {
|
|
1166
|
+
const cmdOutput = Buffer.from(sstdout).toString();
|
|
1167
|
+
const perProjectOutput = splitOutputByGradleProjects(cmdOutput, [
|
|
1168
|
+
gradleDepTask,
|
|
1169
|
+
]);
|
|
1170
|
+
for (const key of gradleModules.keys()) {
|
|
1171
|
+
const parsedList = await parseGradleDep(
|
|
1172
|
+
perProjectOutput.has(key) ? perProjectOutput.get(key) : "",
|
|
1173
|
+
key,
|
|
1174
|
+
gradleModules,
|
|
1175
|
+
gradleRootPath,
|
|
1176
|
+
);
|
|
1177
|
+
const dlist = parsedList.pkgList;
|
|
1178
|
+
if (parsedList?.dependenciesList?.length) {
|
|
1179
|
+
dependencies = mergeDependencies(
|
|
1180
|
+
dependencies,
|
|
1181
|
+
parsedList.dependenciesList,
|
|
1182
|
+
parentComponent,
|
|
1183
|
+
);
|
|
1184
|
+
} else {
|
|
1185
|
+
if (dlist?.length) {
|
|
1186
|
+
thoughtLog(
|
|
1187
|
+
`Hmm, I didn't find any dependencies after executing '${basename(gradleCmd)}' for the project ${key}. However, I did get ${dlist.length} components, which is confusing.`,
|
|
1188
|
+
);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
if (dlist?.length) {
|
|
1192
|
+
pkgList = pkgList.concat(dlist);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
if (pkgList.length) {
|
|
1197
|
+
const fileToUrlMap = parseGradleInfoLogsForUrls(sstdout);
|
|
1198
|
+
// When the `resolve-gradle-distribution` feature flag is enabled, the init script
|
|
1199
|
+
// probes each repository for the actual artifact and emits the resolved URL keyed
|
|
1200
|
+
// by `group:name:version`. This is more accurate than guessing the first repository.
|
|
1201
|
+
const resolvedDistributions =
|
|
1202
|
+
parseGradleResolvedDistributions(parallelPropTaskOut);
|
|
1203
|
+
|
|
1204
|
+
for (const p of pkgList) {
|
|
1205
|
+
if (!p.externalReferences) {
|
|
1206
|
+
p.externalReferences = [];
|
|
1207
|
+
}
|
|
1208
|
+
if (!p.externalReferences.find((r) => r.type === "distribution")) {
|
|
1209
|
+
const groupPath = p.group.replace(/\./g, "/");
|
|
1210
|
+
const matchPath = `${groupPath}/${p.name}/${p.version}/`;
|
|
1211
|
+
let matchedUrl = Object.values(fileToUrlMap).find((url) =>
|
|
1212
|
+
url.includes(matchPath),
|
|
1213
|
+
);
|
|
1214
|
+
if (!matchedUrl) {
|
|
1215
|
+
matchedUrl =
|
|
1216
|
+
resolvedDistributions[`${p.group}:${p.name}:${p.version}`];
|
|
1217
|
+
}
|
|
1218
|
+
if (matchedUrl) {
|
|
1219
|
+
p.externalReferences.push({
|
|
1220
|
+
type: "distribution",
|
|
1221
|
+
url: matchedUrl,
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
if (parentComponent.components?.length) {
|
|
1227
|
+
for (const subProj of parentComponent.components) {
|
|
1228
|
+
pkgList = pkgList.filter(
|
|
1229
|
+
(pkg) =>
|
|
1230
|
+
pkg["bom-ref"] !== subProj["bom-ref"] &&
|
|
1231
|
+
pkg["bom-ref"] !== parentComponent["bom-ref"],
|
|
1232
|
+
);
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
thoughtLog(
|
|
1236
|
+
`Obtained ${pkgList.length} components by executing the '${basename(gradleCmd)}' command.`,
|
|
1237
|
+
);
|
|
1238
|
+
if (DEBUG_MODE) {
|
|
1239
|
+
console.log("Obtained", pkgList.length, "from this gradle project.");
|
|
1240
|
+
}
|
|
1241
|
+
} else {
|
|
1242
|
+
thoughtLog(
|
|
1243
|
+
"**GRADLE:** SBOM is incomplete. I recommend troubleshooting the issue to improve the BOM precision.",
|
|
1244
|
+
);
|
|
1245
|
+
if (!DEBUG_MODE) {
|
|
1246
|
+
console.log(
|
|
1247
|
+
"No packages found. Set the environment variable 'CDXGEN_DEBUG_MODE=debug' to troubleshoot any gradle related errors.",
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1250
|
+
options.failOnError && process.exit(1);
|
|
1251
|
+
}
|
|
1252
|
+
if (
|
|
1253
|
+
(!readEnvironmentVariable("GRADLE_STOP_DAEMON") &&
|
|
1254
|
+
(!readEnvironmentVariable("GRADLE_USE_DAEMON") ||
|
|
1255
|
+
["true", "1"].includes(
|
|
1256
|
+
readEnvironmentVariable("GRADLE_USE_DAEMON"),
|
|
1257
|
+
))) ||
|
|
1258
|
+
["true", "1"].includes(readEnvironmentVariable("GRADLE_STOP_DAEMON"))
|
|
1259
|
+
) {
|
|
1260
|
+
if (DEBUG_MODE) {
|
|
1261
|
+
console.log("Stopping gradle daemon...");
|
|
1262
|
+
}
|
|
1263
|
+
const sresult = safeSpawnSync(gradleCmd, ["--stop"], {
|
|
1264
|
+
cwd: gradleRootPath,
|
|
1265
|
+
shell: isWin,
|
|
1266
|
+
});
|
|
1267
|
+
if (sresult.status !== 0 || sresult.error) {
|
|
1268
|
+
if (options.failOnError || DEBUG_MODE) {
|
|
1269
|
+
console.error(sresult.stdout, sresult.stderr);
|
|
1270
|
+
}
|
|
1271
|
+
options.failOnError && process.exit(1);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
// Should we attempt to resolve class names
|
|
1275
|
+
if (options.resolveClass || options.deep) {
|
|
1276
|
+
const tmpjarNSMapping = await collectJarNS(GRADLE_CACHE_DIR);
|
|
1277
|
+
if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) {
|
|
1278
|
+
jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
// Bazel
|
|
1284
|
+
// Look for the BUILD file only in the root directory
|
|
1285
|
+
// NOTE: This can match BUILD files used by perl, so could lead to errors in some projects
|
|
1286
|
+
const bazelFiles = getAllFiles(
|
|
1287
|
+
path,
|
|
1288
|
+
`${options.multiProject ? "**/" : ""}{WORKSPACE{,.bazel},MODULE.bazel}`,
|
|
1289
|
+
options,
|
|
1290
|
+
);
|
|
1291
|
+
if (
|
|
1292
|
+
bazelFiles?.length &&
|
|
1293
|
+
!hasAnyProjectType(["docker", "oci", "container", "os"], options, false) &&
|
|
1294
|
+
isPackageManagerAllowed(
|
|
1295
|
+
"bazel",
|
|
1296
|
+
["maven", "gradle", "sbt", "mill"],
|
|
1297
|
+
options,
|
|
1298
|
+
)
|
|
1299
|
+
) {
|
|
1300
|
+
let BAZEL_CMD = "bazel";
|
|
1301
|
+
const bazelHome = readEnvironmentVariable("BAZEL_HOME");
|
|
1302
|
+
if (bazelHome) {
|
|
1303
|
+
BAZEL_CMD = join(bazelHome, "bin", "bazel");
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
// bzlmod: parse MODULE.bazel and MODULE.bazel.lock for BCR modules and
|
|
1307
|
+
// ecosystem dependencies (Maven, etc.). This works from the manifest and
|
|
1308
|
+
// lock alone, so BCR/Maven packages are extracted even when the bazel
|
|
1309
|
+
// toolchain is absent. Resolved third-party deps map to their true
|
|
1310
|
+
// ecosystem purl (pkg:maven, ...); only BCR modules use pkg:bazel.
|
|
1311
|
+
const moduleBazelFiles = bazelFiles.filter(
|
|
1312
|
+
(f) => basename(f) === "MODULE.bazel",
|
|
1313
|
+
);
|
|
1314
|
+
for (const moduleFile of moduleBazelFiles) {
|
|
1315
|
+
const baseDir = dirname(moduleFile);
|
|
1316
|
+
const moduleResult = parseModuleBazel(moduleFile);
|
|
1317
|
+
if (moduleResult.pkgList?.length) {
|
|
1318
|
+
pkgList = pkgList.concat(moduleResult.pkgList);
|
|
1319
|
+
}
|
|
1320
|
+
if (moduleResult.parentComponent?.name) {
|
|
1321
|
+
parentComponent = moduleResult.parentComponent;
|
|
1322
|
+
}
|
|
1323
|
+
const lockFile = join(baseDir, "MODULE.bazel.lock");
|
|
1324
|
+
if (safeExistsSync(lockFile)) {
|
|
1325
|
+
const lockResult = parseModuleBazelLock(lockFile);
|
|
1326
|
+
if (lockResult.pkgList?.length) {
|
|
1327
|
+
pkgList = pkgList.concat(lockResult.pkgList);
|
|
1328
|
+
}
|
|
1329
|
+
if (lockResult.dependencies?.length) {
|
|
1330
|
+
dependencies = mergeDependencies(
|
|
1331
|
+
dependencies,
|
|
1332
|
+
lockResult.dependencies,
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
// Querying bazel means building the project first, which is the most
|
|
1339
|
+
// expensive thing cdxgen can do and needs network access. Like every other
|
|
1340
|
+
// package-manager invocation it therefore runs only when dependency
|
|
1341
|
+
// installation is permitted; `--lifecycle pre-build` and secure mode both
|
|
1342
|
+
// turn it off, leaving the manifest and lock as the inventory source.
|
|
1343
|
+
for (const f of options.installDeps ? bazelFiles : []) {
|
|
1344
|
+
const basePath = dirname(f);
|
|
1345
|
+
// Invoke bazel build first
|
|
1346
|
+
const bazelTarget = readEnvironmentVariable("BAZEL_TARGET") || "//...";
|
|
1347
|
+
let bArgs = [
|
|
1348
|
+
...(readEnvironmentVariable("BAZEL_ARGS")?.split(" ") || []),
|
|
1349
|
+
"build",
|
|
1350
|
+
bazelTarget,
|
|
1351
|
+
];
|
|
1352
|
+
// Automatically load any bazelrc file
|
|
1353
|
+
if (
|
|
1354
|
+
!readEnvironmentVariable("BAZEL_ARGS") &&
|
|
1355
|
+
safeExistsSync(join(basePath, ".bazelrc"))
|
|
1356
|
+
) {
|
|
1357
|
+
bArgs = ["--bazelrc=.bazelrc", "build", bazelTarget];
|
|
1358
|
+
}
|
|
1359
|
+
console.log("Executing", BAZEL_CMD, "in", basePath);
|
|
1360
|
+
let result = safeSpawnSync(BAZEL_CMD, bArgs, {
|
|
1361
|
+
cwd: basePath,
|
|
1362
|
+
shell: isWin,
|
|
1363
|
+
});
|
|
1364
|
+
if (result.status !== 0 || result.error) {
|
|
1365
|
+
if (result.stderr) {
|
|
1366
|
+
console.error(result.stdout, result.stderr);
|
|
1367
|
+
}
|
|
1368
|
+
console.log(
|
|
1369
|
+
"1. Check if bazel is installed and available in PATH.\n2. Try building your app with bazel prior to invoking cdxgen",
|
|
1370
|
+
);
|
|
1371
|
+
options.failOnError && process.exit(1);
|
|
1372
|
+
} else {
|
|
1373
|
+
const target = readEnvironmentVariable("BAZEL_TARGET") || "//...";
|
|
1374
|
+
let query = [
|
|
1375
|
+
...(readEnvironmentVariable("BAZEL_ARGS")?.split(" ") || []),
|
|
1376
|
+
];
|
|
1377
|
+
let bazelParser;
|
|
1378
|
+
// Automatically load any bazelrc file
|
|
1379
|
+
if (
|
|
1380
|
+
!readEnvironmentVariable("BAZEL_ARGS") &&
|
|
1381
|
+
safeExistsSync(join(basePath, ".bazelrc"))
|
|
1382
|
+
) {
|
|
1383
|
+
query = ["--bazelrc=.bazelrc"];
|
|
1384
|
+
}
|
|
1385
|
+
if (
|
|
1386
|
+
["true", "1"].includes(
|
|
1387
|
+
readEnvironmentVariable("BAZEL_USE_ACTION_GRAPH"),
|
|
1388
|
+
)
|
|
1389
|
+
) {
|
|
1390
|
+
query = query.concat(["query", `deps(${target})`, "--output=label"]);
|
|
1391
|
+
bazelParser = parseBazelActionGraph;
|
|
1392
|
+
} else {
|
|
1393
|
+
query = query.concat([
|
|
1394
|
+
"aquery",
|
|
1395
|
+
"--output=textproto",
|
|
1396
|
+
"--skyframe_state",
|
|
1397
|
+
]);
|
|
1398
|
+
bazelParser = parseBazelSkyframe;
|
|
1399
|
+
}
|
|
1400
|
+
console.log("Executing", BAZEL_CMD, `${query.join(" ")} in`, basePath);
|
|
1401
|
+
result = safeSpawnSync(BAZEL_CMD, query, {
|
|
1402
|
+
cwd: basePath,
|
|
1403
|
+
});
|
|
1404
|
+
if (result.status !== 0 || result.error) {
|
|
1405
|
+
console.error(result.stdout, result.stderr);
|
|
1406
|
+
options.failOnError && process.exit(1);
|
|
1407
|
+
}
|
|
1408
|
+
const stdout = result.stdout;
|
|
1409
|
+
if (stdout) {
|
|
1410
|
+
const cmdOutput = Buffer.from(stdout).toString();
|
|
1411
|
+
const dlist = bazelParser(cmdOutput);
|
|
1412
|
+
if (dlist?.length) {
|
|
1413
|
+
pkgList = pkgList.concat(dlist);
|
|
1414
|
+
} else {
|
|
1415
|
+
console.log(
|
|
1416
|
+
"No packages were detected.\n1. Build your project using bazel build command before running cdxgen\n2. Try running the bazel aquery command manually to see if skyframe state can be retrieved.",
|
|
1417
|
+
);
|
|
1418
|
+
console.log(
|
|
1419
|
+
"If your project requires a different query, please file a bug at cyclonedx/cdxgen repo!",
|
|
1420
|
+
);
|
|
1421
|
+
options.failOnError && process.exit(1);
|
|
1422
|
+
}
|
|
1423
|
+
} else {
|
|
1424
|
+
console.log("Bazel unexpectedly didn't produce any output");
|
|
1425
|
+
options.failOnError && process.exit(1);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
// scala sbt
|
|
1432
|
+
// Identify sbt projects via its `project` directory:
|
|
1433
|
+
// - all SBT project _should_ define build.properties file with sbt version info
|
|
1434
|
+
// - SBT projects _typically_ have some configs/plugins defined in .sbt files
|
|
1435
|
+
// - SBT projects that are still on 0.13.x, can still use the old approach,
|
|
1436
|
+
// where configs are defined via Scala files
|
|
1437
|
+
// Detecting one of those should be enough to determine an SBT project.
|
|
1438
|
+
let sbtProjectFiles = getAllFiles(
|
|
1439
|
+
path,
|
|
1440
|
+
`${
|
|
1441
|
+
options.multiProject ? "**/" : ""
|
|
1442
|
+
}project/{build.properties,*.sbt,*.scala}`,
|
|
1443
|
+
options,
|
|
1444
|
+
);
|
|
1445
|
+
|
|
1446
|
+
let sbtProjects = [];
|
|
1447
|
+
for (const i in sbtProjectFiles) {
|
|
1448
|
+
// parent dir of sbtProjectFile is the `project` directory
|
|
1449
|
+
// parent dir of `project` is the sbt root project directory
|
|
1450
|
+
const baseDir = dirname(dirname(sbtProjectFiles[i]));
|
|
1451
|
+
sbtProjects = sbtProjects.concat(baseDir);
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// Fallback in case sbt's project directory is non-existent
|
|
1455
|
+
if (!sbtProjects.length) {
|
|
1456
|
+
sbtProjectFiles = getAllFiles(
|
|
1457
|
+
path,
|
|
1458
|
+
`${options.multiProject ? "**/" : ""}*.sbt`,
|
|
1459
|
+
options,
|
|
1460
|
+
);
|
|
1461
|
+
for (const i in sbtProjectFiles) {
|
|
1462
|
+
const baseDir = dirname(sbtProjectFiles[i]);
|
|
1463
|
+
sbtProjects = sbtProjects.concat(baseDir);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
// eliminate duplicates and ignore project directories
|
|
1467
|
+
sbtProjects = [...new Set(sbtProjects)].filter(
|
|
1468
|
+
(p) => !p.endsWith(`${sep}project`) && !p.includes(`target${sep}`),
|
|
1469
|
+
);
|
|
1470
|
+
const sbtLockFiles = getAllFiles(
|
|
1471
|
+
path,
|
|
1472
|
+
`${options.multiProject ? "**/" : ""}build.sbt.lock`,
|
|
1473
|
+
options,
|
|
1474
|
+
);
|
|
1475
|
+
const tempCacheDir = safeMkdtempSync(join(getTmpDir(), "sbt-cache-"));
|
|
1476
|
+
safeMkdirSync(tempCacheDir, { recursive: true });
|
|
1477
|
+
if (
|
|
1478
|
+
sbtProjects?.length &&
|
|
1479
|
+
isPackageManagerAllowed(
|
|
1480
|
+
"sbt",
|
|
1481
|
+
["bazel", "maven", "gradle", "mill"],
|
|
1482
|
+
options,
|
|
1483
|
+
)
|
|
1484
|
+
) {
|
|
1485
|
+
// If the project use sbt lock files
|
|
1486
|
+
if (sbtLockFiles?.length) {
|
|
1487
|
+
for (const f of sbtLockFiles) {
|
|
1488
|
+
const dlist = await parseSbtLock(f);
|
|
1489
|
+
if (dlist?.length) {
|
|
1490
|
+
pkgList = pkgList.concat(dlist);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
} else {
|
|
1494
|
+
const SBT_CMD = readEnvironmentVariable("SBT_CMD") || "sbt";
|
|
1495
|
+
let sbtVersion = determineSbtVersion(path);
|
|
1496
|
+
// If can't find sbt version at the root of repository then search in
|
|
1497
|
+
// sbt project array too because sometimes the project folder isn't at
|
|
1498
|
+
// root of repository
|
|
1499
|
+
if (sbtVersion == null) {
|
|
1500
|
+
for (const i in sbtProjects) {
|
|
1501
|
+
sbtVersion = determineSbtVersion(sbtProjects[i]);
|
|
1502
|
+
if (sbtVersion != null) {
|
|
1503
|
+
break;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
if (DEBUG_MODE) {
|
|
1508
|
+
console.log(`Detected sbt version: ${sbtVersion}`);
|
|
1509
|
+
}
|
|
1510
|
+
// Introduced in 1.2.0 https://www.scala-sbt.org/1.x/docs/sbt-1.2-Release-Notes.html#addPluginSbtFile+command,
|
|
1511
|
+
// however working properly for real only since 1.3.4: https://github.com/sbt/sbt/releases/tag/v1.3.4
|
|
1512
|
+
const standalonePluginFile =
|
|
1513
|
+
sbtVersion != null &&
|
|
1514
|
+
gte(sbtVersion, "1.3.4") &&
|
|
1515
|
+
lte(sbtVersion, "1.4.0");
|
|
1516
|
+
const useSlashSyntax = !sbtVersion || gte(sbtVersion, "1.5.0");
|
|
1517
|
+
const isDependencyTreeBuiltIn =
|
|
1518
|
+
sbtVersion != null && gte(sbtVersion, "1.4.0");
|
|
1519
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "cdxsbt-"));
|
|
1520
|
+
const tempSbtgDir = safeMkdtempSync(join(getTmpDir(), "cdxsbtg-"));
|
|
1521
|
+
safeMkdirSync(tempSbtgDir, { recursive: true });
|
|
1522
|
+
// Create temporary plugins file
|
|
1523
|
+
const tempSbtPlugins = join(tempSbtgDir, "dep-plugins.sbt");
|
|
1524
|
+
|
|
1525
|
+
// Requires a custom version of `sbt-dependency-graph` that
|
|
1526
|
+
// supports `--append` for `toFile` subtask.
|
|
1527
|
+
let sbtPluginDefinition = `\naddSbtPlugin("io.shiftleft" % "sbt-dependency-graph" % "0.10.0-append-to-file3")\n`;
|
|
1528
|
+
if (isDependencyTreeBuiltIn) {
|
|
1529
|
+
sbtPluginDefinition = "\naddDependencyTreePlugin\n";
|
|
1530
|
+
if (DEBUG_MODE) {
|
|
1531
|
+
console.log("Using addDependencyTreePlugin as the custom plugin");
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
safeWriteSync(tempSbtPlugins, sbtPluginDefinition);
|
|
1535
|
+
let sbtExtraArgs = "";
|
|
1536
|
+
const env = { ...process.env };
|
|
1537
|
+
// We need to collect the jars from the cache
|
|
1538
|
+
if (options.deep) {
|
|
1539
|
+
sbtExtraArgs = " updateClassifiers";
|
|
1540
|
+
env["COURSIER_CACHE"] = tempCacheDir;
|
|
1541
|
+
env["SBT_IVY_HOME"] = tempCacheDir;
|
|
1542
|
+
}
|
|
1543
|
+
for (const i in sbtProjects) {
|
|
1544
|
+
const basePath = sbtProjects[i];
|
|
1545
|
+
const dlFile = join(tempDir, `dl-${i}.tmp`);
|
|
1546
|
+
let sbtArgs = [];
|
|
1547
|
+
let pluginFile = null;
|
|
1548
|
+
const subDlFiles = [];
|
|
1549
|
+
if (standalonePluginFile) {
|
|
1550
|
+
sbtArgs = [
|
|
1551
|
+
`-addPluginSbtFile=${tempSbtPlugins}`,
|
|
1552
|
+
`"dependencyList::toFile ${dlFile} --force"`,
|
|
1553
|
+
];
|
|
1554
|
+
subDlFiles.push(dlFile);
|
|
1555
|
+
} else {
|
|
1556
|
+
// write to the existing plugins file
|
|
1557
|
+
// Discover the real sbt project ids by asking sbt itself, falling
|
|
1558
|
+
// back to the regex-based heuristic if that fails. A per-subproject
|
|
1559
|
+
// `dependencyTree` fan-out yields a far more complete tree than a
|
|
1560
|
+
// single root resolution (which only captures the root project's own
|
|
1561
|
+
// libraryDependencies). See https://github.com/cdxgen/cdxgen/issues/4291
|
|
1562
|
+
const subprojects = discoverSbtProjectsFromCmd(
|
|
1563
|
+
basePath,
|
|
1564
|
+
SBT_CMD,
|
|
1565
|
+
env,
|
|
1566
|
+
);
|
|
1567
|
+
if (subprojects.length > 0 && useSlashSyntax) {
|
|
1568
|
+
sbtArgs = [
|
|
1569
|
+
`'set ThisBuild / asciiGraphWidth := 800'${sbtExtraArgs}`,
|
|
1570
|
+
];
|
|
1571
|
+
for (const sp of subprojects) {
|
|
1572
|
+
const subDlFile = join(tempDir, `dl-${i}-${sp}.tmp`);
|
|
1573
|
+
subDlFiles.push(subDlFile);
|
|
1574
|
+
sbtArgs.push(
|
|
1575
|
+
`"${sp}/dependencyTree / toFile ${subDlFile} --force"`,
|
|
1576
|
+
);
|
|
1577
|
+
}
|
|
1578
|
+
} else if (useSlashSyntax) {
|
|
1579
|
+
sbtArgs = [
|
|
1580
|
+
`'set ThisBuild / asciiGraphWidth := 800'${sbtExtraArgs} "dependencyTree / toFile ${dlFile} --force"`,
|
|
1581
|
+
];
|
|
1582
|
+
subDlFiles.push(dlFile);
|
|
1583
|
+
} else {
|
|
1584
|
+
sbtArgs = [
|
|
1585
|
+
`'set asciiGraphWidth in ThisBuild := 800'${sbtExtraArgs} "dependencyTree::toFile ${dlFile} --force"`,
|
|
1586
|
+
];
|
|
1587
|
+
subDlFiles.push(dlFile);
|
|
1588
|
+
}
|
|
1589
|
+
pluginFile = addPlugin(basePath, sbtPluginDefinition);
|
|
1590
|
+
}
|
|
1591
|
+
// Run sbt in non-interactive batch mode so it never blocks waiting for
|
|
1592
|
+
// input on stdin (which can otherwise appear as an indefinite hang) and
|
|
1593
|
+
// does not emit ANSI colour codes into the dependency tree output.
|
|
1594
|
+
sbtArgs = ["-batch", "-no-colors", ...sbtArgs];
|
|
1595
|
+
console.log(
|
|
1596
|
+
"Executing",
|
|
1597
|
+
SBT_CMD,
|
|
1598
|
+
sbtArgs.join(" "),
|
|
1599
|
+
"in",
|
|
1600
|
+
basePath,
|
|
1601
|
+
"using plugins",
|
|
1602
|
+
tempSbtgDir,
|
|
1603
|
+
);
|
|
1604
|
+
// Note that the command has to be invoked with `shell: true` to properly execut sbt
|
|
1605
|
+
const result = safeSpawnSync(SBT_CMD, sbtArgs, {
|
|
1606
|
+
cwd: basePath,
|
|
1607
|
+
shell: true,
|
|
1608
|
+
env,
|
|
1609
|
+
});
|
|
1610
|
+
if (result.status !== 0 || result.error) {
|
|
1611
|
+
console.error(result.stdout, result.stderr);
|
|
1612
|
+
console.log(
|
|
1613
|
+
"1. Check if scala and sbt is installed and available in PATH. Only scala 2.10 + sbt 0.13.6+ and 2.12 + sbt 1.0+ is supported for now.",
|
|
1614
|
+
);
|
|
1615
|
+
console.log(
|
|
1616
|
+
"2. Check if the plugin net.virtual-void:sbt-dependency-graph 0.10.0-RC1 can be used in the environment",
|
|
1617
|
+
);
|
|
1618
|
+
console.log(
|
|
1619
|
+
"3. Consider creating a lockfile using sbt-dependency-lock plugin. See https://github.com/stringbean/sbt-dependency-lock",
|
|
1620
|
+
);
|
|
1621
|
+
options.failOnError && process.exit(1);
|
|
1622
|
+
}
|
|
1623
|
+
if (!standalonePluginFile) {
|
|
1624
|
+
cleanupPlugin(basePath, pluginFile);
|
|
1625
|
+
}
|
|
1626
|
+
const sbtSubprojectRoots = [];
|
|
1627
|
+
for (const subDlFile of subDlFiles) {
|
|
1628
|
+
if (safeExistsSync(subDlFile)) {
|
|
1629
|
+
const retMap = await parseSbtTree(subDlFile);
|
|
1630
|
+
if (retMap.pkgList?.length) {
|
|
1631
|
+
const tmpParentComponent = retMap.pkgList.splice(0, 1)[0];
|
|
1632
|
+
tmpParentComponent.type = "application";
|
|
1633
|
+
pkgList = pkgList.concat(retMap.pkgList);
|
|
1634
|
+
pkgList.push(tmpParentComponent);
|
|
1635
|
+
sbtSubprojectRoots.push(tmpParentComponent);
|
|
1636
|
+
}
|
|
1637
|
+
if (retMap.dependenciesList) {
|
|
1638
|
+
dependencies = mergeDependencies(
|
|
1639
|
+
dependencies,
|
|
1640
|
+
retMap.dependenciesList,
|
|
1641
|
+
parentComponent,
|
|
1642
|
+
);
|
|
1643
|
+
}
|
|
1644
|
+
} else {
|
|
1645
|
+
if (options.failOnError || DEBUG_MODE) {
|
|
1646
|
+
console.log(`sbt dependencyList did not yield ${subDlFile}`);
|
|
1647
|
+
}
|
|
1648
|
+
options.failOnError && process.exit(1);
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
// Construct a synthetic root component from build.sbt name/org/version
|
|
1652
|
+
// that aggregates all subproject roots as its direct dependencies.
|
|
1653
|
+
const sbtRoot = parseSbtRootProject(basePath);
|
|
1654
|
+
if (sbtRoot && sbtSubprojectRoots.length > 0) {
|
|
1655
|
+
const rootPurl = build({
|
|
1656
|
+
type: "maven",
|
|
1657
|
+
namespace: sbtRoot.group || null,
|
|
1658
|
+
name: sbtRoot.name,
|
|
1659
|
+
version: sbtRoot.version || null,
|
|
1660
|
+
qualifiers: { type: "jar" } || null,
|
|
1661
|
+
});
|
|
1662
|
+
const rootComponent = {
|
|
1663
|
+
group: sbtRoot.group,
|
|
1664
|
+
name: sbtRoot.name,
|
|
1665
|
+
version: sbtRoot.version,
|
|
1666
|
+
type: "application",
|
|
1667
|
+
purl: rootPurl,
|
|
1668
|
+
"bom-ref": decodeURIComponent(rootPurl),
|
|
1669
|
+
};
|
|
1670
|
+
parentComponent = rootComponent;
|
|
1671
|
+
dependencies.push({
|
|
1672
|
+
ref: decodeURIComponent(rootPurl),
|
|
1673
|
+
dependsOn: sbtSubprojectRoots
|
|
1674
|
+
.map((c) => c["bom-ref"])
|
|
1675
|
+
.filter(Boolean),
|
|
1676
|
+
});
|
|
1677
|
+
} else if (sbtSubprojectRoots.length > 0 && !parentComponent) {
|
|
1678
|
+
parentComponent = sbtSubprojectRoots[0];
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
// Cleanup
|
|
1683
|
+
safeUnlinkSync(tempSbtPlugins);
|
|
1684
|
+
} // else
|
|
1685
|
+
|
|
1686
|
+
if (DEBUG_MODE) {
|
|
1687
|
+
console.log(`Found ${pkgList.length} packages`);
|
|
1688
|
+
}
|
|
1689
|
+
// Should we attempt to resolve class names
|
|
1690
|
+
if (options.resolveClass || options.deep) {
|
|
1691
|
+
const tmpjarNSMapping = await collectJarNS(tempCacheDir);
|
|
1692
|
+
if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) {
|
|
1693
|
+
jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
|
|
1694
|
+
}
|
|
1695
|
+
// sbt can store jars in the target directory
|
|
1696
|
+
const jarNSData = await createJarBom(path, options);
|
|
1697
|
+
if (jarNSData?.bomJson?.components) {
|
|
1698
|
+
pkgList = pkgList.concat(jarNSData?.bomJson?.components);
|
|
1699
|
+
const targetJarNSMapping = {};
|
|
1700
|
+
for (const p of jarNSData.bomJson.components) {
|
|
1701
|
+
if (!p?.purl || !p?.properties?.length) {
|
|
1702
|
+
continue;
|
|
1703
|
+
}
|
|
1704
|
+
const nsProp = p.properties.filter(
|
|
1705
|
+
(prop) => prop.name === "internal:Namespaces",
|
|
1706
|
+
);
|
|
1707
|
+
if (nsProp.length) {
|
|
1708
|
+
targetJarNSMapping[p.purl] = nsProp[0].value;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
jarNSMapping = { ...jarNSMapping, ...targetJarNSMapping };
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
if (tempCacheDir?.startsWith(getTmpDir())) {
|
|
1716
|
+
safeRmSync(tempCacheDir, {
|
|
1717
|
+
recursive: true,
|
|
1718
|
+
force: true,
|
|
1719
|
+
});
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
if (
|
|
1723
|
+
millFiles?.length &&
|
|
1724
|
+
isPackageManagerAllowed(
|
|
1725
|
+
"mill",
|
|
1726
|
+
["bazel", "sbt", "gradle", "maven"],
|
|
1727
|
+
options,
|
|
1728
|
+
)
|
|
1729
|
+
) {
|
|
1730
|
+
const millRootPath = dirname(millFiles[0]);
|
|
1731
|
+
parentComponent = createDefaultParentComponent(
|
|
1732
|
+
millRootPath,
|
|
1733
|
+
"maven",
|
|
1734
|
+
options,
|
|
1735
|
+
);
|
|
1736
|
+
const millCmd = getMillCommand(millRootPath);
|
|
1737
|
+
const millCommonArgs = [
|
|
1738
|
+
"--color",
|
|
1739
|
+
"false",
|
|
1740
|
+
"--disable-callgraph",
|
|
1741
|
+
"--disable-prompt",
|
|
1742
|
+
"--keep-going",
|
|
1743
|
+
"--silent",
|
|
1744
|
+
];
|
|
1745
|
+
if (!["true", "1"].includes(readEnvironmentVariable("MILL_USE_SERVER"))) {
|
|
1746
|
+
millCommonArgs.unshift("--no-server");
|
|
1747
|
+
}
|
|
1748
|
+
const millArgs = [...millCommonArgs, "__.ivyDepsTree"];
|
|
1749
|
+
if (DEBUG_MODE) {
|
|
1750
|
+
console.log("Executing", millCmd, "in", millRootPath);
|
|
1751
|
+
}
|
|
1752
|
+
let sresult = safeSpawnSync(millCmd, millArgs, {
|
|
1753
|
+
cwd: millRootPath,
|
|
1754
|
+
shell: isWin,
|
|
1755
|
+
maxBuffer: MAX_BUFFER * 10,
|
|
1756
|
+
});
|
|
1757
|
+
if (sresult.status !== 0 || sresult.error) {
|
|
1758
|
+
if (options.failOnError || DEBUG_MODE) {
|
|
1759
|
+
console.error(sresult.stdout, sresult.stderr);
|
|
1760
|
+
}
|
|
1761
|
+
options.failOnError && process.exit(1);
|
|
1762
|
+
}
|
|
1763
|
+
const millResolveArgs = [...millCommonArgs, "resolve", "__.ivyDepsTree"];
|
|
1764
|
+
if (DEBUG_MODE) {
|
|
1765
|
+
console.log(
|
|
1766
|
+
"Executing",
|
|
1767
|
+
millCmd,
|
|
1768
|
+
millResolveArgs.join(" "),
|
|
1769
|
+
"in",
|
|
1770
|
+
millRootPath,
|
|
1771
|
+
);
|
|
1772
|
+
}
|
|
1773
|
+
sresult = safeSpawnSync(millCmd, millResolveArgs, {
|
|
1774
|
+
cwd: millRootPath,
|
|
1775
|
+
shell: isWin,
|
|
1776
|
+
});
|
|
1777
|
+
if (sresult.status !== 0 || sresult.error) {
|
|
1778
|
+
if (options.failOnError || DEBUG_MODE) {
|
|
1779
|
+
console.error(sresult.stdout, sresult.stderr);
|
|
1780
|
+
}
|
|
1781
|
+
options.failOnError && process.exit(1);
|
|
1782
|
+
}
|
|
1783
|
+
const sstdout = sresult.stdout;
|
|
1784
|
+
if (sstdout) {
|
|
1785
|
+
parentComponent.components = [];
|
|
1786
|
+
const modules = sstdout
|
|
1787
|
+
.trim()
|
|
1788
|
+
.split("\n")
|
|
1789
|
+
.map((a) => a.substring(0, a.lastIndexOf(".")))
|
|
1790
|
+
.filter((a) =>
|
|
1791
|
+
["true", "1"].includes(readEnvironmentVariable("MILL_EXCLUDE_TEST"))
|
|
1792
|
+
? !a.endsWith(".test")
|
|
1793
|
+
: true,
|
|
1794
|
+
);
|
|
1795
|
+
const moduleBomRefs = [];
|
|
1796
|
+
const packages = new Map();
|
|
1797
|
+
const relations = new Map();
|
|
1798
|
+
relations.set(parentComponent["bom-ref"], []);
|
|
1799
|
+
for (const module of modules) {
|
|
1800
|
+
moduleBomRefs.push(
|
|
1801
|
+
parseMillDependency(module, packages, relations, millRootPath),
|
|
1802
|
+
);
|
|
1803
|
+
}
|
|
1804
|
+
for (const module of moduleBomRefs) {
|
|
1805
|
+
parentComponent.components.push(packages.get(module));
|
|
1806
|
+
relations.get(parentComponent["bom-ref"]).push(module);
|
|
1807
|
+
packages.delete(module);
|
|
1808
|
+
}
|
|
1809
|
+
const newDependencies = [];
|
|
1810
|
+
for (const [ref, dependsOn] of relations.entries()) {
|
|
1811
|
+
newDependencies.push({
|
|
1812
|
+
ref,
|
|
1813
|
+
dependsOn,
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
if (DEBUG_MODE) {
|
|
1817
|
+
console.log(
|
|
1818
|
+
`Obtained ${packages.size} components and ${relations.size} dependencies from mill.`,
|
|
1819
|
+
);
|
|
1820
|
+
}
|
|
1821
|
+
pkgList = pkgList.concat(...packages.values());
|
|
1822
|
+
dependencies = mergeDependencies(
|
|
1823
|
+
dependencies,
|
|
1824
|
+
newDependencies,
|
|
1825
|
+
parentComponent,
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
if (
|
|
1829
|
+
(!readEnvironmentVariable("MILL_SHUTDOWN_SERVER") &&
|
|
1830
|
+
["true", "1"].includes(readEnvironmentVariable("MILL_USE_SERVER"))) ||
|
|
1831
|
+
["true", "1"].includes(readEnvironmentVariable("MILL_SHUTDOWN_SERVER"))
|
|
1832
|
+
) {
|
|
1833
|
+
if (DEBUG_MODE) {
|
|
1834
|
+
console.log("Shutting down mill server...");
|
|
1835
|
+
}
|
|
1836
|
+
const sresult = safeSpawnSync(millCmd, ["shutdown"], {
|
|
1837
|
+
cwd: millRootPath,
|
|
1838
|
+
shell: isWin,
|
|
1839
|
+
});
|
|
1840
|
+
if (sresult.status !== 0 || sresult.error) {
|
|
1841
|
+
if (options.failOnError || DEBUG_MODE) {
|
|
1842
|
+
console.error(sresult.stdout, sresult.stderr);
|
|
1843
|
+
}
|
|
1844
|
+
options.failOnError && process.exit(1);
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
pkgList = trimComponents(pkgList);
|
|
1850
|
+
pkgList = await getMvnMetadata(pkgList, jarNSMapping, options.deep);
|
|
1851
|
+
return buildBomNSData(options, pkgList, "maven", {
|
|
1852
|
+
src: path,
|
|
1853
|
+
nsMapping: jarNSMapping,
|
|
1854
|
+
dependencies,
|
|
1855
|
+
parentComponent,
|
|
1856
|
+
tools,
|
|
1857
|
+
});
|
|
1858
|
+
}
|