@cdxgen/cdxgen 13.3.0 → 13.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -9
- package/bin/cdxgen-secure.js +15 -0
- package/bin/cdxgen.js +115 -31
- package/bin/evinse.js +23 -1
- package/bin/hbom.js +15 -7
- package/bin/repl.js +115 -0
- package/bin/sign.js +45 -15
- package/bin/tracebom.js +5 -1
- package/bin/validate.js +84 -18
- package/bin/verify.js +155 -86
- package/data/cbomosdb-queries.json +13 -1
- package/data/component-tags.json +8 -0
- package/data/helpers/init.gradle +46 -21
- package/data/queries-darwin.json +25 -1
- package/data/queries-win.json +19 -1
- package/data/queries.json +41 -0
- package/data/remediations.json +344 -1
- package/data/rules/cbom-security.yaml +235 -4
- package/data/rules/dependency-sources.yaml +67 -0
- package/data/rules/go-binaries.yaml +46 -0
- package/data/rules/golem-go.yaml +80 -0
- package/data/rules/hbom-compliance.yaml +40 -22
- package/data/rules/hbom-performance.yaml +7 -1
- package/data/rules/host-topology.yaml +1 -1
- package/data/rules/obom-runtime.yaml +31 -2
- package/data/rules/php-runtime.yaml +143 -0
- package/data/rules/scala-evidence.yaml +115 -0
- package/lib/audit/index.js +52 -6
- package/lib/cli/bomAssembly.js +28 -3
- package/lib/cli/cliOptions.js +110 -3
- package/lib/cli/index.js +186 -58
- package/lib/cli/jsBom.js +50 -29
- package/lib/cli/jvmBom.js +779 -146
- package/lib/cli/managedBom.js +1021 -261
- package/lib/cli/nativeBom.js +364 -58
- package/lib/core/activity.js +12 -0
- package/lib/core/env.js +47 -17
- package/lib/core/fs.js +31 -21
- package/lib/core/httpClient.js +233 -69
- package/lib/core/pluginRun.js +184 -0
- package/lib/core/processTree.js +100 -0
- package/lib/core/projectConfig.js +1 -0
- package/lib/core/projectTooling.js +97 -0
- package/lib/core/propertySanitizer.js +72 -0
- package/lib/core/runState.js +39 -0
- package/lib/core/toml.js +72 -0
- package/lib/ecosystems/asarutils.js +4 -2
- package/lib/ecosystems/bunutils.js +5 -7
- package/lib/ecosystems/cargoCache.js +231 -8
- package/lib/ecosystems/cmakeResolver.js +10 -21
- package/lib/ecosystems/cppBuildContext.js +631 -0
- package/lib/ecosystems/cppEvidence.js +337 -22
- package/lib/ecosystems/cppIncludeResolver.js +294 -0
- package/lib/ecosystems/denoutils.js +93 -66
- package/lib/ecosystems/ecosystems.js +1967 -788
- package/lib/ecosystems/golem.js +578 -18
- package/lib/ecosystems/gradleutils.js +340 -46
- package/lib/ecosystems/jsEvidence.js +85 -24
- package/lib/ecosystems/kosi.js +21 -4
- package/lib/ecosystems/npmutils.js +64 -0
- package/lib/ecosystems/parsers-dotnet.js +668 -153
- package/lib/ecosystems/parsers-elm.js +46 -28
- package/lib/ecosystems/parsers-gleam.js +3 -4
- package/lib/ecosystems/parsers-go.js +1283 -297
- package/lib/ecosystems/parsers-js.js +92 -26
- package/lib/ecosystems/parsers-julia.js +2 -3
- package/lib/ecosystems/parsers-jvm.js +463 -29
- package/lib/ecosystems/parsers-misc.js +405 -93
- package/lib/ecosystems/parsers-python.js +152 -20
- package/lib/ecosystems/parsers-rust.js +4 -4
- package/lib/ecosystems/parsers-terraform.js +1573 -19
- package/lib/ecosystems/pythonutils.js +102 -6
- package/lib/ecosystems/remote/huggingface.js +3 -0
- package/lib/ecosystems/rubyutils.js +73 -20
- package/lib/ecosystems/rusi.js +32 -9
- package/lib/ecosystems/sbtutils.js +243 -187
- package/lib/ecosystems/scalacliutils.js +343 -0
- package/lib/ecosystems/scalasem.js +2620 -0
- package/lib/ecosystems/terraformRegistry.js +288 -0
- package/lib/ecosystems/utils.js +2 -0
- package/lib/ecosystems/vendoredCode.js +156 -0
- package/lib/evinser/evinser.js +695 -78
- package/lib/evinser/swiftsem.js +68 -5
- package/lib/helpers/agenticToolutils.js +2 -2
- package/lib/helpers/bomSigner.js +576 -128
- package/lib/inventory/agentSkillSpec.js +17 -0
- package/lib/inventory/aiCollector.js +4 -1
- package/lib/inventory/analyzer.js +110 -127
- package/lib/inventory/apkInstalledDb.js +243 -0
- package/lib/inventory/atomUtils.js +204 -48
- package/lib/inventory/auditCategories.js +10 -3
- package/lib/inventory/buildToolRateLimit.js +144 -0
- package/lib/inventory/cacheCommands.js +2 -1
- package/lib/inventory/cacheDir.js +52 -9
- package/lib/inventory/certificates.js +2371 -0
- package/lib/inventory/cmakeBuildDirs.js +254 -0
- package/lib/inventory/communityAiConfigParser.js +4 -9
- package/lib/inventory/deps.js +507 -128
- package/lib/inventory/display.js +200 -3
- package/lib/inventory/dosai.js +747 -101
- package/lib/inventory/dosaiParsers.js +310 -15
- package/lib/inventory/dynamic.js +96 -8
- package/lib/inventory/envcontext.js +168 -5
- package/lib/inventory/evidenceUtils.js +590 -132
- package/lib/inventory/fetchBatch.js +574 -38
- package/lib/inventory/fetchDiskCache.js +597 -0
- package/lib/inventory/forgeEnricher.js +14 -5
- package/lib/inventory/formulationParsers.js +3 -2
- package/lib/inventory/goBuildInfo.js +140 -0
- package/lib/inventory/hbom.js +67 -7
- package/lib/inventory/hbomAnalysis.js +16 -0
- package/lib/inventory/hostTopology.js +21 -0
- package/lib/inventory/jvmLocalRepos.js +917 -0
- package/lib/inventory/mcpConfigParser.js +2 -3
- package/lib/inventory/osPackagePurl.js +244 -0
- package/lib/inventory/osPackageResolver.js +89 -87
- package/lib/inventory/osinfo.js +79 -31
- package/lib/inventory/osqueryTransform.js +114 -5
- package/lib/inventory/parentSelection.js +146 -0
- package/lib/inventory/phpBuildInfo.js +487 -0
- package/lib/inventory/phpHostProbe.js +641 -0
- package/lib/inventory/rootfsCerts.js +426 -0
- package/lib/inventory/rustFormulationParser.js +3 -4
- package/lib/inventory/scalaCoords.js +153 -0
- package/lib/inventory/source.js +215 -11
- package/lib/inventory/spdx.js +245 -0
- package/lib/inventory/traceRunner.js +93 -8
- package/lib/inventory/tracedCrypto.js +423 -0
- package/lib/managers/binary.js +529 -183
- package/lib/managers/docker.js +199 -44
- package/lib/managers/oci.js +24 -2
- package/lib/parsers/cmakeCache.js +69 -0
- package/lib/parsers/cmakeLists.js +16 -2
- package/lib/parsers/cmakePresets.js +400 -0
- package/lib/parsers/compileCommands.js +557 -0
- package/lib/parsers/email.js +277 -0
- package/lib/parsers/largeJson.js +34 -2
- package/lib/parsers/strictJson.js +322 -0
- package/lib/parsers/terraformConfig.js +1073 -0
- package/lib/parsers/terraformSource.js +652 -0
- package/lib/server/server.js +209 -1
- package/lib/stages/postgen/annotator.js +17 -1
- package/lib/stages/postgen/introspection/markers.js +1 -1
- package/lib/stages/postgen/introspection/reflect.js +4 -1
- package/lib/stages/postgen/postgen.js +20 -6
- package/lib/stages/postgen/ruleEngine.js +58 -1
- package/lib/stages/postgen/specVersionCompat.js +62 -0
- package/lib/stages/pregen/pregen.js +117 -5
- package/lib/validator/bomValidator.js +26 -5
- package/lib/validator/generated/runtime.mjs +13 -0
- package/lib/validator/generated/validate-1.6.mjs +26 -7
- package/lib/validator/generated/validate-1.7.mjs +31 -12
- package/lib/validator/generated/validate-2.0.mjs +30 -11
- package/lib/validator/index.js +25 -10
- package/lib/validator/reporters/json.js +1 -0
- package/package.json +23 -23
- package/types/bin/cdxgen-secure.d.ts +3 -0
- package/types/bin/cdxgen-secure.d.ts.map +1 -0
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +9 -2
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +43 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +44 -1
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts +7 -4
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts +3 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/activity.d.ts.map +1 -1
- package/types/lib/core/env.d.ts +27 -2
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/httpClient.d.ts +13 -8
- package/types/lib/core/httpClient.d.ts.map +1 -1
- package/types/lib/core/pluginRun.d.ts +97 -0
- package/types/lib/core/pluginRun.d.ts.map +1 -0
- package/types/lib/core/processTree.d.ts +36 -0
- package/types/lib/core/processTree.d.ts.map +1 -0
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/projectTooling.d.ts +41 -0
- package/types/lib/core/projectTooling.d.ts.map +1 -0
- package/types/lib/core/propertySanitizer.d.ts +26 -0
- package/types/lib/core/propertySanitizer.d.ts.map +1 -1
- package/types/lib/core/runState.d.ts +29 -0
- package/types/lib/core/runState.d.ts.map +1 -0
- package/types/lib/core/toml.d.ts +20 -0
- package/types/lib/core/toml.d.ts.map +1 -0
- package/types/lib/ecosystems/asarutils.d.ts.map +1 -1
- package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
- package/types/lib/ecosystems/cargoCache.d.ts +12 -0
- package/types/lib/ecosystems/cargoCache.d.ts.map +1 -1
- package/types/lib/ecosystems/cmakeResolver.d.ts +5 -3
- package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
- package/types/lib/ecosystems/cppBuildContext.d.ts +55 -0
- package/types/lib/ecosystems/cppBuildContext.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +19 -3
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts +92 -0
- package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -0
- package/types/lib/ecosystems/denoutils.d.ts +9 -3
- package/types/lib/ecosystems/denoutils.d.ts.map +1 -1
- package/types/lib/ecosystems/ecosystems.d.ts +62 -13
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
- package/types/lib/ecosystems/golem.d.ts +81 -1
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +59 -7
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts.map +1 -1
- package/types/lib/ecosystems/npmutils.d.ts +15 -0
- package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-dotnet.d.ts +155 -5
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-go.d.ts +119 -5
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +6 -1
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-jvm.d.ts +74 -3
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +21 -59
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +57 -6
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-terraform.d.ts +38 -21
- package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +26 -1
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts +21 -1
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/sbtutils.d.ts +88 -2
- package/types/lib/ecosystems/sbtutils.d.ts.map +1 -1
- package/types/lib/ecosystems/scalacliutils.d.ts +56 -0
- package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -0
- package/types/lib/ecosystems/scalasem.d.ts +311 -0
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -0
- package/types/lib/ecosystems/terraformRegistry.d.ts +9 -0
- package/types/lib/ecosystems/terraformRegistry.d.ts.map +1 -0
- package/types/lib/ecosystems/utils.d.ts +2 -2
- package/types/lib/ecosystems/utils.d.ts.map +1 -1
- package/types/lib/ecosystems/vendoredCode.d.ts +32 -0
- package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +100 -8
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/swiftsem.d.ts +10 -0
- package/types/lib/evinser/swiftsem.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +80 -4
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/inventory/agentSkillSpec.d.ts +13 -0
- package/types/lib/inventory/agentSkillSpec.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/analyzer.d.ts.map +1 -1
- package/types/lib/inventory/apkInstalledDb.d.ts +42 -0
- package/types/lib/inventory/apkInstalledDb.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +96 -10
- package/types/lib/inventory/atomUtils.d.ts.map +1 -1
- package/types/lib/inventory/auditCategories.d.ts +3 -0
- package/types/lib/inventory/auditCategories.d.ts.map +1 -1
- package/types/lib/inventory/buildToolRateLimit.d.ts +38 -0
- package/types/lib/inventory/buildToolRateLimit.d.ts.map +1 -0
- package/types/lib/inventory/cacheCommands.d.ts +2 -1
- package/types/lib/inventory/cacheCommands.d.ts.map +1 -1
- package/types/lib/inventory/cacheDir.d.ts +12 -4
- package/types/lib/inventory/cacheDir.d.ts.map +1 -1
- package/types/lib/inventory/certificates.d.ts +205 -0
- package/types/lib/inventory/certificates.d.ts.map +1 -0
- package/types/lib/inventory/cmakeBuildDirs.d.ts +58 -0
- package/types/lib/inventory/cmakeBuildDirs.d.ts.map +1 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/deps.d.ts +61 -2
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/display.d.ts +18 -0
- package/types/lib/inventory/display.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +202 -14
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dosaiParsers.d.ts +53 -7
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
- package/types/lib/inventory/dynamic.d.ts +16 -1
- package/types/lib/inventory/dynamic.d.ts.map +1 -1
- package/types/lib/inventory/envcontext.d.ts +40 -2
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts +48 -14
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/fetchBatch.d.ts +83 -14
- package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
- package/types/lib/inventory/fetchDiskCache.d.ts +169 -0
- package/types/lib/inventory/fetchDiskCache.d.ts.map +1 -0
- package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/goBuildInfo.d.ts +10 -0
- package/types/lib/inventory/goBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomAnalysis.d.ts +10 -0
- package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -1
- package/types/lib/inventory/hostTopology.d.ts.map +1 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts +178 -0
- package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -0
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/osPackagePurl.d.ts +99 -0
- package/types/lib/inventory/osPackagePurl.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +6 -2
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
- package/types/lib/inventory/osinfo.d.ts +31 -6
- package/types/lib/inventory/osinfo.d.ts.map +1 -1
- package/types/lib/inventory/osqueryTransform.d.ts +51 -0
- package/types/lib/inventory/osqueryTransform.d.ts.map +1 -1
- package/types/lib/inventory/parentSelection.d.ts +34 -0
- package/types/lib/inventory/parentSelection.d.ts.map +1 -0
- package/types/lib/inventory/phpBuildInfo.d.ts +142 -0
- package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/phpHostProbe.d.ts +35 -0
- package/types/lib/inventory/phpHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/rootfsCerts.d.ts +27 -0
- package/types/lib/inventory/rootfsCerts.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/scalaCoords.d.ts +80 -0
- package/types/lib/inventory/scalaCoords.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +28 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/inventory/spdx.d.ts +24 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -1
- package/types/lib/inventory/traceRunner.d.ts +16 -1
- package/types/lib/inventory/traceRunner.d.ts.map +1 -1
- package/types/lib/inventory/tracedCrypto.d.ts +64 -0
- package/types/lib/inventory/tracedCrypto.d.ts.map +1 -0
- package/types/lib/managers/binary.d.ts +10 -0
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +12 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/managers/oci.d.ts +3 -1
- package/types/lib/managers/oci.d.ts.map +1 -1
- package/types/lib/parsers/cmakeCache.d.ts +16 -0
- package/types/lib/parsers/cmakeCache.d.ts.map +1 -1
- package/types/lib/parsers/cmakeLists.d.ts +2 -1
- package/types/lib/parsers/cmakeLists.d.ts.map +1 -1
- package/types/lib/parsers/cmakePresets.d.ts +78 -0
- package/types/lib/parsers/cmakePresets.d.ts.map +1 -0
- package/types/lib/parsers/compileCommands.d.ts +115 -0
- package/types/lib/parsers/compileCommands.d.ts.map +1 -0
- package/types/lib/parsers/email.d.ts +19 -0
- package/types/lib/parsers/email.d.ts.map +1 -0
- package/types/lib/parsers/largeJson.d.ts +13 -0
- package/types/lib/parsers/largeJson.d.ts.map +1 -1
- package/types/lib/parsers/strictJson.d.ts +46 -0
- package/types/lib/parsers/strictJson.d.ts.map +1 -0
- package/types/lib/parsers/terraformConfig.d.ts +70 -0
- package/types/lib/parsers/terraformConfig.d.ts.map +1 -0
- package/types/lib/parsers/terraformSource.d.ts +66 -0
- package/types/lib/parsers/terraformSource.d.ts.map +1 -0
- package/types/lib/server/server.d.ts +8 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/introspection/reflect.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts +7 -4
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +14 -1
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +8 -0
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
- package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +0 -462
|
@@ -1,27 +1,80 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import {
|
|
1
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import {
|
|
3
|
+
basename,
|
|
4
|
+
dirname,
|
|
5
|
+
isAbsolute,
|
|
6
|
+
join,
|
|
7
|
+
relative,
|
|
8
|
+
resolve,
|
|
9
|
+
} from "node:path";
|
|
3
10
|
|
|
4
11
|
import { build } from "@cdxgen/cdx-purl";
|
|
5
12
|
import { parseEDNString } from "edn-data";
|
|
6
13
|
|
|
7
|
-
import { readEnvironmentVariable } from "../core/activity.js";
|
|
14
|
+
import { DEBUG_MODE, readEnvironmentVariable } from "../core/activity.js";
|
|
8
15
|
import { recordDegradation } from "../core/buildLedger.js";
|
|
9
16
|
import { includeMavenTestScope } from "../core/env.js";
|
|
17
|
+
import { safeExistsSync } from "../core/fs.js";
|
|
10
18
|
import { thoughtLog } from "../core/logger.js";
|
|
11
19
|
import { applyPurl } from "../inventory/purl.js";
|
|
20
|
+
import { parseScalaArtifact } from "../inventory/scalaCoords.js";
|
|
12
21
|
import { xml2js } from "../parsers/xml.js";
|
|
13
22
|
|
|
23
|
+
/** Bound on the `${...}` references one pom value may expand through. */
|
|
24
|
+
const POM_PROPERTY_EXPANSION_LIMIT = 10;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Expand the `${name}` references in a pom value. The value is returned only
|
|
28
|
+
* when every reference resolves, so a version is never half expanded.
|
|
29
|
+
*
|
|
30
|
+
* @param {string} value Raw pom value
|
|
31
|
+
* @param {Function} lookup Returns the value of a property name, or undefined
|
|
32
|
+
* @returns {string|undefined} Expanded value, or undefined
|
|
33
|
+
*/
|
|
34
|
+
function expandPomValue(value, lookup) {
|
|
35
|
+
let expanded = value;
|
|
36
|
+
for (
|
|
37
|
+
let i = 0;
|
|
38
|
+
i < POM_PROPERTY_EXPANSION_LIMIT && expanded?.includes("${");
|
|
39
|
+
i++
|
|
40
|
+
) {
|
|
41
|
+
const start = expanded.indexOf("${");
|
|
42
|
+
const end = expanded.indexOf("}", start + 2);
|
|
43
|
+
if (end < 0) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const replacement = lookup(expanded.slice(start + 2, end));
|
|
47
|
+
if (typeof replacement !== "string") {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
expanded = `${expanded.slice(0, start)}${replacement}${expanded.slice(end + 1)}`;
|
|
51
|
+
}
|
|
52
|
+
return expanded?.includes("${") ? undefined : expanded;
|
|
53
|
+
}
|
|
54
|
+
|
|
14
55
|
/**
|
|
15
56
|
* Parse pom file
|
|
16
57
|
*
|
|
58
|
+
* Versions resolve from the pom's own properties and dependencyManagement.
|
|
59
|
+
* A caller that has read the pom's parents passes what they define in
|
|
60
|
+
* `inherited`, so versions the parents manage resolve too. Imported BOMs and
|
|
61
|
+
* parents outside the scanned directory are not read.
|
|
62
|
+
*
|
|
17
63
|
* @param {string} pomFile pom file to parse
|
|
18
|
-
* @
|
|
64
|
+
* @param {Object} [inherited] Properties and managed versions from parent poms
|
|
65
|
+
* @param {Object} [inherited.properties] Property name to raw value
|
|
66
|
+
* @param {Object} [inherited.managedVersions] `groupId:artifactId` to version
|
|
67
|
+
* @returns {Object} Object containing pom properties, modules, the parent
|
|
68
|
+
* reference, the user properties and managed versions this pom defines, and
|
|
69
|
+
* array of dependencies
|
|
19
70
|
*/
|
|
20
|
-
export function parsePom(pomFile) {
|
|
71
|
+
export function parsePom(pomFile, inherited = {}) {
|
|
21
72
|
const deps = [];
|
|
22
73
|
let modules;
|
|
23
74
|
let pomPurl;
|
|
24
75
|
const properties = {};
|
|
76
|
+
const userProperties = {};
|
|
77
|
+
const managedVersions = {};
|
|
25
78
|
let isQuarkus = false;
|
|
26
79
|
const xmlData = readFileSync(pomFile, "utf-8");
|
|
27
80
|
const project = xml2js(xmlData, {
|
|
@@ -54,25 +107,30 @@ export function parsePom(pomFile) {
|
|
|
54
107
|
}
|
|
55
108
|
}
|
|
56
109
|
// Take the version from the parent if available
|
|
57
|
-
if (!properties.version && project
|
|
110
|
+
if (!properties.version && project?.parent?.version?._) {
|
|
58
111
|
properties.version = project.parent.version._;
|
|
59
112
|
}
|
|
60
113
|
// Take the groupId from the parent if available
|
|
61
|
-
if (!properties.groupId && project
|
|
114
|
+
if (!properties.groupId && project?.parent?.groupId?._) {
|
|
62
115
|
properties.groupId = project.parent.groupId._;
|
|
63
116
|
}
|
|
117
|
+
let parent;
|
|
118
|
+
if (project?.parent) {
|
|
119
|
+
parent = {
|
|
120
|
+
groupId: project.parent.groupId?._,
|
|
121
|
+
artifactId: project.parent.artifactId?._,
|
|
122
|
+
version: project.parent.version?._,
|
|
123
|
+
// An empty <relativePath/> tells Maven not to look for the parent on
|
|
124
|
+
// disk; a missing one means ../pom.xml.
|
|
125
|
+
relativePath:
|
|
126
|
+
project.parent.relativePath === undefined
|
|
127
|
+
? "../pom.xml"
|
|
128
|
+
: project.parent.relativePath?._ || "",
|
|
129
|
+
};
|
|
130
|
+
}
|
|
64
131
|
if (project?.scm?.url?._) {
|
|
65
132
|
properties.scm = project.scm.url._;
|
|
66
133
|
}
|
|
67
|
-
if (properties.groupId || properties.artifactId) {
|
|
68
|
-
pomPurl = build({
|
|
69
|
-
type: "maven",
|
|
70
|
-
namespace: properties.groupId || "" || null,
|
|
71
|
-
name: properties.artifactId,
|
|
72
|
-
version: properties.version || null,
|
|
73
|
-
qualifiers: { type: properties.packaging || "jar" } || null,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
134
|
const moduleEntries = [];
|
|
77
135
|
if (project?.modules?.module) {
|
|
78
136
|
moduleEntries.push(project.modules.module);
|
|
@@ -91,11 +149,80 @@ export function parsePom(pomFile) {
|
|
|
91
149
|
if (project?.properties) {
|
|
92
150
|
for (const aprop of Object.keys(project.properties)) {
|
|
93
151
|
properties[aprop] = project.properties[aprop]?._;
|
|
152
|
+
userProperties[aprop] = project.properties[aprop]?._;
|
|
94
153
|
if (!isQuarkus && aprop.startsWith("quarkus.platform")) {
|
|
95
154
|
isQuarkus = true;
|
|
96
155
|
}
|
|
97
156
|
}
|
|
98
157
|
}
|
|
158
|
+
const inheritedProperties = inherited?.properties || {};
|
|
159
|
+
const lookupProperty = (name) => {
|
|
160
|
+
switch (name) {
|
|
161
|
+
case "project.version":
|
|
162
|
+
case "pom.version":
|
|
163
|
+
case "version":
|
|
164
|
+
return properties.version;
|
|
165
|
+
case "project.groupId":
|
|
166
|
+
case "pom.groupId":
|
|
167
|
+
case "groupId":
|
|
168
|
+
return properties.groupId;
|
|
169
|
+
case "project.artifactId":
|
|
170
|
+
case "pom.artifactId":
|
|
171
|
+
case "artifactId":
|
|
172
|
+
return properties.artifactId;
|
|
173
|
+
case "project.parent.version":
|
|
174
|
+
return parent?.version;
|
|
175
|
+
case "project.parent.groupId":
|
|
176
|
+
return parent?.groupId;
|
|
177
|
+
default:
|
|
178
|
+
return Object.hasOwn(userProperties, name)
|
|
179
|
+
? userProperties[name]
|
|
180
|
+
: inheritedProperties[name];
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
// A property can refer to another, so each lookup expands its value too.
|
|
184
|
+
const expand = (value) =>
|
|
185
|
+
expandPomValue(value, (name) => {
|
|
186
|
+
const raw = lookupProperty(name);
|
|
187
|
+
return raw?.includes("${")
|
|
188
|
+
? expandPomValue(raw, (inner) =>
|
|
189
|
+
inner === name ? undefined : lookupProperty(inner),
|
|
190
|
+
)
|
|
191
|
+
: raw;
|
|
192
|
+
});
|
|
193
|
+
let managedEntries = project?.dependencyManagement?.dependencies?.dependency;
|
|
194
|
+
if (managedEntries && !Array.isArray(managedEntries)) {
|
|
195
|
+
managedEntries = [managedEntries];
|
|
196
|
+
}
|
|
197
|
+
for (const amanaged of managedEntries || []) {
|
|
198
|
+
// An imported BOM manages versions this pom cannot see without fetching it
|
|
199
|
+
if (amanaged?.scope?._ === "import" || !amanaged?.version?._) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const group = expand(amanaged.groupId?._);
|
|
203
|
+
const name = expand(amanaged.artifactId?._);
|
|
204
|
+
const version = expand(amanaged.version._);
|
|
205
|
+
if (group && name && version) {
|
|
206
|
+
managedVersions[`${group}:${name}`] = version;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const inheritedManagedVersions = inherited?.managedVersions || {};
|
|
210
|
+
// CI friendly versions such as ${revision} resolve from the properties
|
|
211
|
+
for (const coordinate of ["groupId", "version"]) {
|
|
212
|
+
if (properties[coordinate]?.includes("${")) {
|
|
213
|
+
properties[coordinate] =
|
|
214
|
+
expand(properties[coordinate]) || properties[coordinate];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (properties.groupId || properties.artifactId) {
|
|
218
|
+
pomPurl = build({
|
|
219
|
+
type: "maven",
|
|
220
|
+
namespace: properties.groupId || "" || null,
|
|
221
|
+
name: properties.artifactId,
|
|
222
|
+
version: properties.version || null,
|
|
223
|
+
qualifiers: { type: properties.packaging || "jar" } || null,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
99
226
|
// Check the plugins for quarkus
|
|
100
227
|
if (!isQuarkus && project?.build?.plugins?.plugin) {
|
|
101
228
|
if (Array.isArray(project.build.plugins.plugin)) {
|
|
@@ -129,7 +256,18 @@ export function parsePom(pomFile) {
|
|
|
129
256
|
versionStr = version._;
|
|
130
257
|
}
|
|
131
258
|
if (versionStr?.includes("$")) {
|
|
132
|
-
versionStr =
|
|
259
|
+
versionStr = expand(versionStr);
|
|
260
|
+
}
|
|
261
|
+
let groupStr = adep.groupId ? adep.groupId._ : "";
|
|
262
|
+
if (groupStr?.includes("${")) {
|
|
263
|
+
groupStr = expand(groupStr) || groupStr;
|
|
264
|
+
}
|
|
265
|
+
const nameStr = adep.artifactId ? adep.artifactId._ : "";
|
|
266
|
+
if (!versionStr && !version?._) {
|
|
267
|
+
const managedKey = `${groupStr}:${nameStr}`;
|
|
268
|
+
versionStr = Object.hasOwn(managedVersions, managedKey)
|
|
269
|
+
? managedVersions[managedKey]
|
|
270
|
+
: inheritedManagedVersions[managedKey];
|
|
133
271
|
}
|
|
134
272
|
const scope = adep.scope?._;
|
|
135
273
|
const type = adep.type?._ || "jar";
|
|
@@ -147,8 +285,8 @@ export function parsePom(pomFile) {
|
|
|
147
285
|
}
|
|
148
286
|
if (includeMavenTestScope || scope !== "test") {
|
|
149
287
|
deps.push({
|
|
150
|
-
group:
|
|
151
|
-
name:
|
|
288
|
+
group: groupStr,
|
|
289
|
+
name: nameStr,
|
|
152
290
|
version: versionStr,
|
|
153
291
|
qualifiers,
|
|
154
292
|
scope: mapMavenScope(scope, optional === "true"),
|
|
@@ -170,7 +308,272 @@ export function parsePom(pomFile) {
|
|
|
170
308
|
}
|
|
171
309
|
}
|
|
172
310
|
}
|
|
173
|
-
return {
|
|
311
|
+
return {
|
|
312
|
+
isQuarkus,
|
|
313
|
+
pomPurl,
|
|
314
|
+
modules,
|
|
315
|
+
parent,
|
|
316
|
+
properties,
|
|
317
|
+
userProperties,
|
|
318
|
+
managedVersions,
|
|
319
|
+
dependencies: deps,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/** Bound on the chain of parent poms read from disk. */
|
|
324
|
+
const LOCAL_PARENT_DEPTH_LIMIT = 10;
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* The pom file a `<parent>` reference points at on disk, when it lies inside
|
|
328
|
+
* the scanned directory and declares the coordinates the reference names.
|
|
329
|
+
*
|
|
330
|
+
* @param {string} pomFile Child pom file
|
|
331
|
+
* @param {Object} parentRef Parent reference from parsePom
|
|
332
|
+
* @param {string} rootDir Scanned directory
|
|
333
|
+
* @returns {string|undefined} Parent pom file
|
|
334
|
+
*/
|
|
335
|
+
function locateLocalParentPom(pomFile, parentRef, rootDir) {
|
|
336
|
+
if (!parentRef?.relativePath || !rootDir) {
|
|
337
|
+
return undefined;
|
|
338
|
+
}
|
|
339
|
+
let candidate = resolve(dirname(pomFile), parentRef.relativePath);
|
|
340
|
+
if (!candidate.endsWith(".xml")) {
|
|
341
|
+
candidate = join(candidate, "pom.xml");
|
|
342
|
+
}
|
|
343
|
+
const rel = relative(resolve(rootDir), candidate);
|
|
344
|
+
if (!rel || rel.startsWith("..") || isAbsolute(rel)) {
|
|
345
|
+
return undefined;
|
|
346
|
+
}
|
|
347
|
+
if (!safeExistsSync(candidate)) {
|
|
348
|
+
return undefined;
|
|
349
|
+
}
|
|
350
|
+
try {
|
|
351
|
+
const { groupId, artifactId } = parsePom(candidate).properties || {};
|
|
352
|
+
if (
|
|
353
|
+
artifactId !== parentRef.artifactId ||
|
|
354
|
+
(parentRef.groupId && groupId !== parentRef.groupId)
|
|
355
|
+
) {
|
|
356
|
+
return undefined;
|
|
357
|
+
}
|
|
358
|
+
} catch (_err) {
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
return candidate;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* What a pom passes on to its children: its user properties and managed
|
|
366
|
+
* versions over those of its own local parents.
|
|
367
|
+
*
|
|
368
|
+
* @param {string} pomFile Pom file
|
|
369
|
+
* @param {string} rootDir Scanned directory
|
|
370
|
+
* @param {Map} cache Results by pom file
|
|
371
|
+
* @param {number} depth Current depth of the parent chain
|
|
372
|
+
* @returns {Object} Inherited properties and managed versions
|
|
373
|
+
*/
|
|
374
|
+
function localPomInheritance(pomFile, rootDir, cache, depth) {
|
|
375
|
+
if (cache.has(pomFile)) {
|
|
376
|
+
return cache.get(pomFile);
|
|
377
|
+
}
|
|
378
|
+
const empty = { properties: {}, managedVersions: {} };
|
|
379
|
+
// A parent chain that loops back reads as having no parent
|
|
380
|
+
cache.set(pomFile, empty);
|
|
381
|
+
let inherited = empty;
|
|
382
|
+
try {
|
|
383
|
+
const parentPom =
|
|
384
|
+
depth < LOCAL_PARENT_DEPTH_LIMIT
|
|
385
|
+
? locateLocalParentPom(pomFile, parsePom(pomFile).parent, rootDir)
|
|
386
|
+
: undefined;
|
|
387
|
+
if (parentPom) {
|
|
388
|
+
inherited = localPomInheritance(parentPom, rootDir, cache, depth + 1);
|
|
389
|
+
}
|
|
390
|
+
const own = parsePom(pomFile, inherited);
|
|
391
|
+
const result = {
|
|
392
|
+
properties: { ...inherited.properties, ...own.userProperties },
|
|
393
|
+
managedVersions: { ...inherited.managedVersions, ...own.managedVersions },
|
|
394
|
+
};
|
|
395
|
+
cache.set(pomFile, result);
|
|
396
|
+
return result;
|
|
397
|
+
} catch (_err) {
|
|
398
|
+
return empty;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Parse a pom file together with the parent poms it names that are present
|
|
404
|
+
* inside the scanned directory, without running Maven. Properties and
|
|
405
|
+
* dependencyManagement versions from those parents resolve the versions the
|
|
406
|
+
* pom leaves to them. Parents outside the directory and imported BOMs are not
|
|
407
|
+
* read, so the versions they manage stay empty.
|
|
408
|
+
*
|
|
409
|
+
* @param {string} pomFile Pom file to parse
|
|
410
|
+
* @param {string} rootDir Scanned directory; parents outside it are ignored
|
|
411
|
+
* @param {Map} [cache] Reused across the poms of one scan
|
|
412
|
+
* @returns {Object} Same shape as parsePom
|
|
413
|
+
*/
|
|
414
|
+
export function parsePomWithLocalParents(pomFile, rootDir, cache = new Map()) {
|
|
415
|
+
const pomPath = resolve(pomFile);
|
|
416
|
+
const parentPom = locateLocalParentPom(
|
|
417
|
+
pomPath,
|
|
418
|
+
parsePom(pomPath).parent,
|
|
419
|
+
rootDir,
|
|
420
|
+
);
|
|
421
|
+
if (!parentPom) {
|
|
422
|
+
return parsePom(pomFile);
|
|
423
|
+
}
|
|
424
|
+
return parsePom(pomFile, localPomInheritance(parentPom, rootDir, cache, 1));
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/** Bound on the reactor walk. A pom's module list is untrusted input, so the
|
|
428
|
+
* walk cannot trust it to stay finite. */
|
|
429
|
+
const REACTOR_MODULE_LIMIT = 500;
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Every pom file of the reactor an aggregator pom builds: its own modules,
|
|
433
|
+
* recursively through nested aggregators. A recursive dependency:tree run
|
|
434
|
+
* from the aggregator resolves all of them, so their own runs repeat it.
|
|
435
|
+
*
|
|
436
|
+
* A module entry names a directory relative to its pom, sometimes a direct
|
|
437
|
+
* path to a pom file. Entries that are absolute, or that climb out of the
|
|
438
|
+
* aggregator's directory, are ignored: the scan never listed them, and the
|
|
439
|
+
* walk must not follow a pom's pointers outside its own tree.
|
|
440
|
+
*
|
|
441
|
+
* @param {string} rootPom Path of the aggregator pom.
|
|
442
|
+
* @returns {Set<string>} Pom files of the reactor, excluding the aggregator.
|
|
443
|
+
*/
|
|
444
|
+
export function resolveReactorPomFiles(rootPom) {
|
|
445
|
+
const pomFiles = new Set();
|
|
446
|
+
const visited = new Set();
|
|
447
|
+
const rootDir = dirname(resolve(rootPom));
|
|
448
|
+
const queue = [resolve(rootPom)];
|
|
449
|
+
while (queue.length > 0 && pomFiles.size < REACTOR_MODULE_LIMIT) {
|
|
450
|
+
const pom = queue.shift();
|
|
451
|
+
if (visited.has(pom)) {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
visited.add(pom);
|
|
455
|
+
let modules;
|
|
456
|
+
try {
|
|
457
|
+
modules = parsePom(pom)?.modules;
|
|
458
|
+
} catch (_err) {
|
|
459
|
+
// An unreadable module pom ends this branch of the walk.
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
for (const module of modules || []) {
|
|
463
|
+
if (typeof module !== "string") {
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
const cleaned = module.trim().replaceAll("\\", "/");
|
|
467
|
+
if (
|
|
468
|
+
!cleaned ||
|
|
469
|
+
cleaned.includes("\0") ||
|
|
470
|
+
cleaned.startsWith("/") ||
|
|
471
|
+
/^[A-Za-z]:/.test(cleaned)
|
|
472
|
+
) {
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
const modulePom = resolve(
|
|
476
|
+
dirname(pom),
|
|
477
|
+
cleaned.endsWith(".xml") ? cleaned : join(cleaned, "pom.xml"),
|
|
478
|
+
);
|
|
479
|
+
const withinRoot = relative(rootDir, modulePom);
|
|
480
|
+
if (
|
|
481
|
+
!withinRoot ||
|
|
482
|
+
withinRoot.startsWith("..") ||
|
|
483
|
+
isAbsolute(withinRoot) ||
|
|
484
|
+
!safeExistsSync(modulePom)
|
|
485
|
+
) {
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
if (visited.has(modulePom)) {
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
pomFiles.add(modulePom);
|
|
492
|
+
queue.push(modulePom);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return pomFiles;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* File name stem for the trees of one recursive dependency:tree run. Maven
|
|
500
|
+
* expands the project expressions for each reactor module, so every module
|
|
501
|
+
* writes its own file; a fixed name would hold only the last module's tree.
|
|
502
|
+
*/
|
|
503
|
+
export const MAVEN_MODULE_TREE_STEM =
|
|
504
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Maven expands these project expressions itself
|
|
505
|
+
"${project.groupId}-${project.artifactId}";
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* The groupId-artifactId key a module's tree file is named by.
|
|
509
|
+
*
|
|
510
|
+
* @param {string} pomFile Path of the module pom.
|
|
511
|
+
* @returns {string|undefined} The key, or undefined when the pom cannot be read.
|
|
512
|
+
*/
|
|
513
|
+
function moduleTreeKey(pomFile) {
|
|
514
|
+
try {
|
|
515
|
+
const { groupId, artifactId } = parsePom(pomFile)?.properties || {};
|
|
516
|
+
return groupId && artifactId ? `${groupId}-${artifactId}` : undefined;
|
|
517
|
+
} catch (_err) {
|
|
518
|
+
return undefined;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Read the trees one dependency:tree run wrote, one file per reactor module
|
|
524
|
+
* (see MAVEN_MODULE_TREE_STEM), and tell which of the reactor's pom files
|
|
525
|
+
* they cover. The pom the run started from comes first, then its modules in
|
|
526
|
+
* reactor order. A module pom counts as covered only when its own tree is
|
|
527
|
+
* among the files, so a module the run left out still runs on its own.
|
|
528
|
+
*
|
|
529
|
+
* @param {string} treeDir Directory the run wrote its trees into.
|
|
530
|
+
* @param {string} rootPom The pom file the run started from.
|
|
531
|
+
* @returns {{trees: Array<{pomFile: string, text: string}>, covered: Set<string>}}
|
|
532
|
+
*/
|
|
533
|
+
export function readMavenModuleTrees(treeDir, rootPom) {
|
|
534
|
+
const trees = [];
|
|
535
|
+
const covered = new Set();
|
|
536
|
+
let names;
|
|
537
|
+
try {
|
|
538
|
+
names = readdirSync(treeDir).sort();
|
|
539
|
+
} catch (_err) {
|
|
540
|
+
return { trees, covered };
|
|
541
|
+
}
|
|
542
|
+
const byKey = new Map();
|
|
543
|
+
for (const name of names) {
|
|
544
|
+
const stem = name.replace(/\.(json|txt)$/, "");
|
|
545
|
+
if (stem !== name && !byKey.has(stem)) {
|
|
546
|
+
byKey.set(stem, name);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
const take = (key, pomFile) => {
|
|
550
|
+
const name = byKey.get(key);
|
|
551
|
+
if (!name) {
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
byKey.delete(key);
|
|
555
|
+
trees.push({
|
|
556
|
+
pomFile,
|
|
557
|
+
text: readFileSync(join(treeDir, name), { encoding: "utf-8" }),
|
|
558
|
+
});
|
|
559
|
+
return true;
|
|
560
|
+
};
|
|
561
|
+
const rootKey = moduleTreeKey(rootPom);
|
|
562
|
+
if (rootKey) {
|
|
563
|
+
take(rootKey, rootPom);
|
|
564
|
+
}
|
|
565
|
+
for (const modulePom of resolveReactorPomFiles(rootPom)) {
|
|
566
|
+
const key = moduleTreeKey(modulePom);
|
|
567
|
+
if (key && take(key, modulePom)) {
|
|
568
|
+
covered.add(modulePom);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
// Trees no pom of the reactor names, such as the single file of a Maven
|
|
572
|
+
// that did not expand the expressions, are kept under the root pom.
|
|
573
|
+
for (const key of [...byKey.keys()]) {
|
|
574
|
+
take(key, rootPom);
|
|
575
|
+
}
|
|
576
|
+
return { trees, covered };
|
|
174
577
|
}
|
|
175
578
|
|
|
176
579
|
function mapMavenScope(componentScope, isOptional = false) {
|
|
@@ -471,10 +874,16 @@ export function parseMavenTree(rawOutput, pomFile) {
|
|
|
471
874
|
/**
|
|
472
875
|
* Parse mill dependencies from file
|
|
473
876
|
*
|
|
877
|
+
* Scala artifacts are emitted in the sbt purl form: the Scala binary suffix
|
|
878
|
+
* is stripped from the artifact name and the version it carried is recorded
|
|
879
|
+
* in the cdx:scala:compilerVersion property, so one library keeps a single
|
|
880
|
+
* purl whichever build tool reported it.
|
|
881
|
+
*
|
|
474
882
|
* @param {string} module name of the module
|
|
475
883
|
* @param {map} dependencies the parsed dependencies
|
|
476
884
|
* @param {map} relations a map containing all relations
|
|
477
885
|
* @param {string} millRootPath root of the project
|
|
886
|
+
* @param {string} logFileName name of the tree log the module wrote
|
|
478
887
|
*
|
|
479
888
|
* @returns the bom-ref of the module
|
|
480
889
|
*/
|
|
@@ -483,6 +892,7 @@ export function parseMillDependency(
|
|
|
483
892
|
dependencies,
|
|
484
893
|
relations,
|
|
485
894
|
millRootPath,
|
|
895
|
+
logFileName = "ivyDepsTree.log",
|
|
486
896
|
) {
|
|
487
897
|
const treeRegex = /^(?<treeIndentation>(?:[?├│└─ ]{3})+)(?<dependency>.*)/m;
|
|
488
898
|
const ESC = "\\x1B";
|
|
@@ -522,12 +932,7 @@ export function parseMillDependency(
|
|
|
522
932
|
// Now put the versions we removed above back into the path and replace the brackets at the same time
|
|
523
933
|
moduleFilePath = moduleFilePath.replace("[]", `/${versionNumber}/`);
|
|
524
934
|
}
|
|
525
|
-
moduleFilePath = resolve(
|
|
526
|
-
millRootPath,
|
|
527
|
-
"out",
|
|
528
|
-
moduleFilePath,
|
|
529
|
-
"ivyDepsTree.log",
|
|
530
|
-
);
|
|
935
|
+
moduleFilePath = resolve(millRootPath, "out", moduleFilePath, logFileName);
|
|
531
936
|
moduleComponent.properties = [
|
|
532
937
|
{
|
|
533
938
|
name: "internal:SrcFile",
|
|
@@ -547,7 +952,27 @@ export function parseMillDependency(
|
|
|
547
952
|
],
|
|
548
953
|
},
|
|
549
954
|
};
|
|
550
|
-
|
|
955
|
+
let dependencyTreeLog;
|
|
956
|
+
try {
|
|
957
|
+
dependencyTreeLog = readFileSync(moduleFilePath, "utf-8");
|
|
958
|
+
} catch (_err) {
|
|
959
|
+
// A cross-published module writes its log under the dotted version
|
|
960
|
+
// directory (0.23.38) while the resolve output prints it with
|
|
961
|
+
// underscores (0_23_38)
|
|
962
|
+
try {
|
|
963
|
+
dependencyTreeLog = readFileSync(
|
|
964
|
+
moduleFilePath.replace(/(\d+)_(\d+)_(\d+)/, "$1.$2.$3"),
|
|
965
|
+
"utf-8",
|
|
966
|
+
);
|
|
967
|
+
} catch (_err2) {
|
|
968
|
+
if (DEBUG_MODE) {
|
|
969
|
+
console.log(
|
|
970
|
+
`No Mill dependency tree log was written for the module ${module}.`,
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
return moduleComponent["bom-ref"];
|
|
974
|
+
}
|
|
975
|
+
}
|
|
551
976
|
const dependencyTreeLines = dependencyTreeLog
|
|
552
977
|
.trim()
|
|
553
978
|
.split("\n")
|
|
@@ -568,11 +993,20 @@ export function parseMillDependency(
|
|
|
568
993
|
[group, name, version] = match.groups.dependency.split(":");
|
|
569
994
|
version = versionRegex.exec(version).groups.version;
|
|
570
995
|
}
|
|
996
|
+
const scalaInfo = parseScalaArtifact(name);
|
|
571
997
|
const component = completeComponent({
|
|
572
998
|
group,
|
|
573
|
-
name,
|
|
999
|
+
name: scalaInfo.purlName,
|
|
574
1000
|
version,
|
|
575
1001
|
});
|
|
1002
|
+
if (scalaInfo.binaryVersion) {
|
|
1003
|
+
component.properties = [
|
|
1004
|
+
{
|
|
1005
|
+
name: "cdx:scala:compilerVersion",
|
|
1006
|
+
value: scalaInfo.binaryVersion,
|
|
1007
|
+
},
|
|
1008
|
+
];
|
|
1009
|
+
}
|
|
576
1010
|
if (!dependencies.has(component["bom-ref"])) {
|
|
577
1011
|
dependencies.set(component["bom-ref"], component);
|
|
578
1012
|
relations.set(component["bom-ref"], []);
|
|
@@ -587,7 +1021,7 @@ export function parseMillDependency(
|
|
|
587
1021
|
return moduleComponent["bom-ref"];
|
|
588
1022
|
}
|
|
589
1023
|
|
|
590
|
-
function completeComponent(component) {
|
|
1024
|
+
export function completeComponent(component) {
|
|
591
1025
|
component["type"] = component.group ? "library" : "application";
|
|
592
1026
|
try {
|
|
593
1027
|
const purl = build({
|