@cdxgen/cdxgen 13.3.0 → 13.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/bin/cdxgen.js +90 -26
- package/bin/evinse.js +18 -1
- package/bin/repl.js +86 -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/helpers/init.gradle +46 -21
- package/data/remediations.json +61 -0
- package/data/rules/dependency-sources.yaml +67 -0
- package/data/rules/scala-evidence.yaml +115 -0
- package/lib/audit/index.js +38 -6
- package/lib/cli/index.js +113 -54
- package/lib/cli/jsBom.js +50 -29
- package/lib/cli/jvmBom.js +665 -138
- package/lib/cli/managedBom.js +320 -200
- package/lib/cli/nativeBom.js +139 -30
- package/lib/core/activity.js +12 -0
- package/lib/core/env.js +17 -9
- package/lib/core/fs.js +3 -2
- package/lib/core/httpClient.js +159 -24
- package/lib/core/pluginRun.js +184 -0
- package/lib/core/processTree.js +100 -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 +28 -12
- package/lib/ecosystems/gradleutils.js +314 -30
- 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 +567 -151
- package/lib/ecosystems/parsers-elm.js +46 -28
- package/lib/ecosystems/parsers-gleam.js +3 -4
- package/lib/ecosystems/parsers-go.js +324 -61
- package/lib/ecosystems/parsers-js.js +92 -26
- package/lib/ecosystems/parsers-julia.js +2 -3
- package/lib/ecosystems/parsers-jvm.js +204 -12
- package/lib/ecosystems/parsers-misc.js +182 -55
- package/lib/ecosystems/parsers-python.js +141 -10
- 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 +67 -17
- package/lib/ecosystems/rusi.js +22 -9
- package/lib/ecosystems/sbtutils.js +243 -187
- package/lib/ecosystems/scalacliutils.js +342 -0
- package/lib/ecosystems/scalasem.js +2618 -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 +578 -69
- package/lib/helpers/agenticToolutils.js +2 -2
- package/lib/helpers/bomSigner.js +576 -128
- package/lib/inventory/aiCollector.js +4 -1
- package/lib/inventory/analyzer.js +110 -127
- package/lib/inventory/atomUtils.js +171 -48
- package/lib/inventory/auditCategories.js +7 -0
- package/lib/inventory/buildToolRateLimit.js +144 -0
- package/lib/inventory/cacheCommands.js +2 -1
- package/lib/inventory/cmakeBuildDirs.js +254 -0
- package/lib/inventory/deps.js +501 -124
- package/lib/inventory/dosai.js +248 -44
- package/lib/inventory/dosaiParsers.js +310 -15
- package/lib/inventory/dynamic.js +52 -6
- package/lib/inventory/evidenceUtils.js +154 -109
- package/lib/inventory/fetchBatch.js +574 -38
- package/lib/inventory/fetchDiskCache.js +597 -0
- package/lib/inventory/forgeEnricher.js +14 -5
- package/lib/inventory/jvmLocalRepos.js +917 -0
- package/lib/inventory/mcpConfigParser.js +2 -3
- package/lib/inventory/parentSelection.js +146 -0
- package/lib/inventory/rustFormulationParser.js +3 -4
- package/lib/inventory/scalaCoords.js +153 -0
- package/lib/inventory/source.js +8 -8
- package/lib/inventory/spdx.js +101 -0
- package/lib/inventory/traceRunner.js +88 -7
- package/lib/inventory/tracedCrypto.js +294 -0
- package/lib/managers/docker.js +33 -32
- 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/strictJson.js +322 -0
- package/lib/parsers/terraformConfig.js +1073 -0
- package/lib/parsers/terraformSource.js +652 -0
- package/lib/server/server.js +23 -0
- package/lib/stages/postgen/introspection/markers.js +1 -1
- package/lib/stages/postgen/postgen.js +15 -1
- package/lib/stages/postgen/specVersionCompat.js +32 -0
- package/lib/validator/index.js +25 -10
- package/lib/validator/reporters/json.js +1 -0
- package/package.json +21 -21
- package/types/lib/audit/index.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 +24 -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 +9 -0
- 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/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 +18 -2
- 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.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +50 -0
- 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 +118 -4
- 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 +44 -2
- 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 +46 -1
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +3 -1
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +53 -3
- 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 +27 -2
- 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 +75 -8
- package/types/lib/evinser/evinser.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/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/analyzer.d.ts.map +1 -1
- package/types/lib/inventory/atomUtils.d.ts +82 -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/cmakeBuildDirs.d.ts +58 -0
- package/types/lib/inventory/cmakeBuildDirs.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +59 -1
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +57 -8
- 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 +10 -0
- package/types/lib/inventory/dynamic.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts +19 -4
- 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/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/parentSelection.d.ts +34 -0
- package/types/lib/inventory/parentSelection.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.map +1 -1
- package/types/lib/inventory/spdx.d.ts +9 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -1
- package/types/lib/inventory/traceRunner.d.ts +12 -0
- package/types/lib/inventory/traceRunner.d.ts.map +1 -1
- package/types/lib/inventory/tracedCrypto.d.ts +42 -0
- package/types/lib/inventory/tracedCrypto.d.ts.map +1 -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/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.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.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
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { recordDegradation } from "../core/buildLedger.js";
|
|
2
|
+
import { registerRunReset } from "../core/runState.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Text a build tool prints when its Maven repository answers HTTP 429, as
|
|
6
|
+
* recorded from each tool against a repository that rate limits. One small
|
|
7
|
+
* matcher per tool, plain substring tests on the combined output: the tools
|
|
8
|
+
* reword their messages between versions, so the matched fragment is the one
|
|
9
|
+
* every observed phrasing keeps (the status number in the tool's own wording).
|
|
10
|
+
*
|
|
11
|
+
* sbt, Mill and scala-cli resolve through Coursier, so they share the
|
|
12
|
+
* coursier matcher. The Coursier inside sbt 1.x reports the JDK's
|
|
13
|
+
* `Server returned HTTP response code: 429`; the one in sbt 2, Mill and
|
|
14
|
+
* scala-cli reports `retryable HTTP error: <url> (HTTP 429)`, with a
|
|
15
|
+
* `Retry-After` inside the parentheses when the server sent one.
|
|
16
|
+
*
|
|
17
|
+
* @type {Object<string, string[]>}
|
|
18
|
+
*/
|
|
19
|
+
const RATE_LIMIT_MARKERS = {
|
|
20
|
+
maven: ["status code: 429", "Too Many Requests"],
|
|
21
|
+
gradle: ["Received status code 429", "[HTTP 429: http"],
|
|
22
|
+
coursier: ["response code: 429", "(HTTP 429"],
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The matcher family a tool belongs to.
|
|
27
|
+
*
|
|
28
|
+
* @type {Object<string, string>}
|
|
29
|
+
*/
|
|
30
|
+
const TOOL_MATCHER = {
|
|
31
|
+
maven: "maven",
|
|
32
|
+
gradle: "gradle",
|
|
33
|
+
sbt: "coursier",
|
|
34
|
+
mill: "coursier",
|
|
35
|
+
"scala-cli": "coursier",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* How each tool is moved to a mirror, named in one hint per tool and scan.
|
|
40
|
+
* sbt reads its own repositories file; Mill and scala-cli read Coursier's
|
|
41
|
+
* mirror.properties, whose entry spells the semicolon-separated format
|
|
42
|
+
* because a comma list is silently ignored.
|
|
43
|
+
*
|
|
44
|
+
* @type {Object<string, string>}
|
|
45
|
+
*/
|
|
46
|
+
const MIRROR_SETTINGS = {
|
|
47
|
+
maven:
|
|
48
|
+
"Point Maven at a mirror with a <mirror> entry in the Maven settings.xml, or set MVNW_REPOURL for the Maven wrapper.",
|
|
49
|
+
gradle:
|
|
50
|
+
"Point Gradle at a mirror by declaring the repository in a Gradle init script.",
|
|
51
|
+
sbt: "Point sbt at a mirror by listing it in ~/.sbt/repositories and passing -Dsbt.override.build.repos=true in SBT_OPTS or .sbtopts.",
|
|
52
|
+
coursier:
|
|
53
|
+
"Point Coursier at a mirror with mirror.properties, setting central.from and central.to (separate several central.from URLs with semicolons, not commas).",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Tools whose later invocations or retries cdxgen skips once one met a rate
|
|
58
|
+
* limit. Mill and scala-cli resolve in a single invocation.
|
|
59
|
+
*
|
|
60
|
+
* @type {Set<string>}
|
|
61
|
+
*/
|
|
62
|
+
const STOPPED_TOOLS = new Set(["maven", "gradle", "sbt"]);
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Tools whose repository answered HTTP 429 during the current scan. Further
|
|
66
|
+
* invocations of that tool would only pay the same back-off for the same
|
|
67
|
+
* empty answer.
|
|
68
|
+
*
|
|
69
|
+
* @type {Set<string>}
|
|
70
|
+
*/
|
|
71
|
+
const rateLimitedTools = new Set();
|
|
72
|
+
|
|
73
|
+
registerRunReset("inventory.buildToolRateLimit", () => {
|
|
74
|
+
rateLimitedTools.clear();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Whether a tool's combined output names a rate limit from its repository.
|
|
79
|
+
* The answer text is treated as untrusted: only fixed substrings are looked
|
|
80
|
+
* for, nothing from the output is kept.
|
|
81
|
+
*
|
|
82
|
+
* @param {string} output Combined stdout and stderr of one invocation.
|
|
83
|
+
* @param {string} tool One of maven, gradle, sbt, mill, scala-cli.
|
|
84
|
+
* @returns {boolean} True when the output names an HTTP 429 answer.
|
|
85
|
+
*/
|
|
86
|
+
export function detectBuildToolRateLimit(output, tool) {
|
|
87
|
+
const markers = RATE_LIMIT_MARKERS[TOOL_MATCHER[tool]];
|
|
88
|
+
if (!markers || typeof output !== "string" || !output) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return markers.some((marker) => output.includes(marker));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Whether a tool was already found rate limited in this scan, so the caller
|
|
96
|
+
* can skip its remaining invocations.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} tool One of maven, gradle, sbt, mill, scala-cli.
|
|
99
|
+
* @returns {boolean}
|
|
100
|
+
*/
|
|
101
|
+
export function isBuildToolRateLimited(tool) {
|
|
102
|
+
return rateLimitedTools.has(tool);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Read a completed invocation's output for a rate limit. When one is found,
|
|
107
|
+
* the tool is remembered for the scan, one hint naming the tool's mirror
|
|
108
|
+
* setting is printed, and the `build.rate-limited` degradation is recorded.
|
|
109
|
+
* The first invocation that shows the rate limit is the one recorded; later
|
|
110
|
+
* ones add nothing, because the same answer ends them all.
|
|
111
|
+
*
|
|
112
|
+
* @param {string} tool One of maven, gradle, sbt, mill, scala-cli.
|
|
113
|
+
* @param {string|undefined} output Combined output, as commandOutputText
|
|
114
|
+
* returns it for a spawn result.
|
|
115
|
+
* @param {Object} [context] Call-site facts for the degradation event.
|
|
116
|
+
* @param {string} [context.command] The redacted command that was attempted.
|
|
117
|
+
* @param {number} [context.exitCode] The invocation's exit status.
|
|
118
|
+
* @returns {boolean} True when this output names a rate limit.
|
|
119
|
+
*/
|
|
120
|
+
export function noteBuildToolRateLimit(tool, output, context = {}) {
|
|
121
|
+
if (!detectBuildToolRateLimit(output, tool)) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
if (isBuildToolRateLimited(tool)) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
rateLimitedTools.add(tool);
|
|
128
|
+
const stopped = STOPPED_TOOLS.has(tool)
|
|
129
|
+
? `, so cdxgen runs no further ${tool} resolution in this scan and`
|
|
130
|
+
: ", so";
|
|
131
|
+
console.warn(
|
|
132
|
+
`The repository ${tool} downloads from is rate limiting this machine (HTTP 429)${stopped} its dependency tree is incomplete. ${MIRROR_SETTINGS[tool] || MIRROR_SETTINGS[TOOL_MATCHER[tool]]} cdxgen's own lookups can be moved with MAVEN_CENTRAL_URL.`,
|
|
133
|
+
);
|
|
134
|
+
recordDegradation("build.rate-limited", {
|
|
135
|
+
ecosystem: "java",
|
|
136
|
+
tool,
|
|
137
|
+
impact: "transitive-deps",
|
|
138
|
+
command: context.command,
|
|
139
|
+
exitCode: context.exitCode,
|
|
140
|
+
detail: `The repository ${tool} downloads from answered HTTP 429, so ${tool} resolved no dependencies.`,
|
|
141
|
+
outputExcerpt: output,
|
|
142
|
+
});
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `cdxgen cache` subcommand — inspect and purge the metadata fetch cache
|
|
2
|
+
* `cdxgen cache` subcommand — inspect and purge the metadata fetch cache that
|
|
3
|
+
* cdxrs and the JS batch pool share.
|
|
3
4
|
*
|
|
4
5
|
* This module operates directly on the filesystem because JS is the authority
|
|
5
6
|
* for the cache directory. The cache layout is:
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a C/C++ project's build trees are: the build directories its CMake
|
|
3
|
+
* presets configure, and the conventional ones (`build`, `build-<name>`,
|
|
4
|
+
* `out`, `builddir`, `cmake-build-<name>`). Shared by the lookups for
|
|
5
|
+
* `CMakeCache.txt` and for the compilation database, so both search the same
|
|
6
|
+
* places in the same order.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
10
|
+
import { platform } from "node:os";
|
|
11
|
+
import {
|
|
12
|
+
basename,
|
|
13
|
+
delimiter,
|
|
14
|
+
dirname,
|
|
15
|
+
isAbsolute,
|
|
16
|
+
join,
|
|
17
|
+
relative,
|
|
18
|
+
resolve,
|
|
19
|
+
} from "node:path";
|
|
20
|
+
|
|
21
|
+
import { isSecureMode, readEnvironmentVariable } from "../core/activity.js";
|
|
22
|
+
import {
|
|
23
|
+
expandPresetMacros,
|
|
24
|
+
parseCmakePresets,
|
|
25
|
+
resolveConfigurePresets,
|
|
26
|
+
} from "../parsers/cmakePresets.js";
|
|
27
|
+
|
|
28
|
+
/** Presets files CMake reads from the source directory, in order. */
|
|
29
|
+
const PRESETS_FILES = ["CMakePresets.json", "CMakeUserPresets.json"];
|
|
30
|
+
|
|
31
|
+
/** A presets file larger than this is not read. */
|
|
32
|
+
const MAX_PRESETS_FILE_BYTES = 4 * 1024 * 1024;
|
|
33
|
+
|
|
34
|
+
/** At most this many presets files are read, includes counted. */
|
|
35
|
+
const MAX_PRESETS_FILES = 64;
|
|
36
|
+
|
|
37
|
+
/** At most this many build directories are proposed. */
|
|
38
|
+
const MAX_BUILD_DIRS = 128;
|
|
39
|
+
|
|
40
|
+
const HOST_SYSTEM_NAMES = {
|
|
41
|
+
darwin: "Darwin",
|
|
42
|
+
linux: "Linux",
|
|
43
|
+
win32: "Windows",
|
|
44
|
+
freebsd: "FreeBSD",
|
|
45
|
+
openbsd: "OpenBSD",
|
|
46
|
+
netbsd: "NetBSD",
|
|
47
|
+
sunos: "SunOS",
|
|
48
|
+
aix: "AIX",
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Whether `child` is `parent` or inside it.
|
|
53
|
+
*
|
|
54
|
+
* @param {string} child Path to test
|
|
55
|
+
* @param {string} parent Directory
|
|
56
|
+
* @returns {boolean}
|
|
57
|
+
*/
|
|
58
|
+
export function isInsideDir(child, parent) {
|
|
59
|
+
const rel = relative(resolve(parent), resolve(child));
|
|
60
|
+
return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function isDirectory(p) {
|
|
64
|
+
try {
|
|
65
|
+
return statSync(p).isDirectory();
|
|
66
|
+
} catch (_err) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function readSmallFile(p) {
|
|
72
|
+
try {
|
|
73
|
+
const stat = statSync(p);
|
|
74
|
+
if (!stat.isFile() || stat.size > MAX_PRESETS_FILE_BYTES) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
return readFileSync(p, "utf-8");
|
|
78
|
+
} catch (_err) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* CMake's `${hostSystemName}` for this host.
|
|
85
|
+
*
|
|
86
|
+
* @returns {string}
|
|
87
|
+
*/
|
|
88
|
+
export function hostSystemName() {
|
|
89
|
+
return HOST_SYSTEM_NAMES[platform()] || platform();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Read a project's presets documents: `CMakePresets.json` and
|
|
94
|
+
* `CMakeUserPresets.json`, each followed by the files it includes (schema
|
|
95
|
+
* version 4 and later). In secure mode an include outside the project is not
|
|
96
|
+
* read.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} root Project source directory
|
|
99
|
+
* @returns {Array<{file: string, fileDir: string, document: Object}>}
|
|
100
|
+
*/
|
|
101
|
+
export function readCmakePresetDocuments(root) {
|
|
102
|
+
const sourceDir = resolve(root);
|
|
103
|
+
const documents = [];
|
|
104
|
+
const seen = new Set();
|
|
105
|
+
const visit = (file) => {
|
|
106
|
+
const abs = resolve(file);
|
|
107
|
+
if (seen.has(abs) || seen.size >= MAX_PRESETS_FILES) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
seen.add(abs);
|
|
111
|
+
if (isSecureMode && !isInsideDir(abs, sourceDir)) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const document = parseCmakePresets(readSmallFile(abs));
|
|
115
|
+
if (!document) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const fileDir = dirname(abs);
|
|
119
|
+
documents.push({ file: abs, fileDir, document });
|
|
120
|
+
for (const include of document.include) {
|
|
121
|
+
const expanded = expandPresetMacros(include, {
|
|
122
|
+
sourceDir,
|
|
123
|
+
sourceParentDir: dirname(sourceDir),
|
|
124
|
+
sourceDirName: basename(sourceDir),
|
|
125
|
+
fileDir,
|
|
126
|
+
pathListSep: delimiter,
|
|
127
|
+
hostSystemName: hostSystemName(),
|
|
128
|
+
penv: readEnvironmentVariable,
|
|
129
|
+
});
|
|
130
|
+
visit(isAbsolute(expanded) ? expanded : join(fileDir, expanded));
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
for (const name of PRESETS_FILES) {
|
|
134
|
+
visit(join(sourceDir, name));
|
|
135
|
+
}
|
|
136
|
+
return documents;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The visible configure presets of a project, resolved and with their macros
|
|
141
|
+
* expanded for this host.
|
|
142
|
+
*
|
|
143
|
+
* @param {string} root Project source directory
|
|
144
|
+
* @returns {Object[]} See `resolveConfigurePresets`
|
|
145
|
+
*/
|
|
146
|
+
export function readCmakeConfigurePresets(root) {
|
|
147
|
+
const sourceDir = resolve(root);
|
|
148
|
+
const documents = readCmakePresetDocuments(sourceDir);
|
|
149
|
+
if (!documents.length) {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
return resolveConfigurePresets(documents, {
|
|
153
|
+
sourceDir,
|
|
154
|
+
sourceParentDir: dirname(sourceDir),
|
|
155
|
+
sourceDirName: basename(sourceDir),
|
|
156
|
+
hostSystemName: hostSystemName(),
|
|
157
|
+
pathListSep: delimiter,
|
|
158
|
+
penv: readEnvironmentVariable,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function childDirs(dir, accept = () => true) {
|
|
163
|
+
try {
|
|
164
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
165
|
+
.filter((e) => e.isDirectory() && accept(e.name))
|
|
166
|
+
.map((e) => join(dir, e.name))
|
|
167
|
+
.sort();
|
|
168
|
+
} catch (_err) {
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** The order conventional build directories are searched in. */
|
|
174
|
+
function conventionalRank(dir) {
|
|
175
|
+
const name = basename(dir);
|
|
176
|
+
if (name === "build") {
|
|
177
|
+
return 0;
|
|
178
|
+
}
|
|
179
|
+
if (name === "out") {
|
|
180
|
+
return 2;
|
|
181
|
+
}
|
|
182
|
+
if (name === "builddir") {
|
|
183
|
+
return 3;
|
|
184
|
+
}
|
|
185
|
+
if (name.startsWith("cmake-build-")) {
|
|
186
|
+
return 4;
|
|
187
|
+
}
|
|
188
|
+
return 1;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* The directories a project's build trees may be in, most specific first:
|
|
193
|
+
* the directory of an explicit `--cmake-cache`, the build directories of its
|
|
194
|
+
* configure presets, then the `build`, `build-<name>`, `out`, `builddir` and
|
|
195
|
+
* `cmake-build-<name>` directories at the project root, and the directories
|
|
196
|
+
* one level below `build`, `out` and `out/build` (where Visual Studio puts
|
|
197
|
+
* preset builds). Only existing directories are listed; in secure mode, only
|
|
198
|
+
* those inside the project.
|
|
199
|
+
*
|
|
200
|
+
* @param {string} root Project source directory
|
|
201
|
+
* @param {Object} [options] CLI options (`cmakeCache`)
|
|
202
|
+
* @returns {string[]} Absolute directories, without duplicates
|
|
203
|
+
*/
|
|
204
|
+
export function cmakeBuildDirCandidates(root, options = {}) {
|
|
205
|
+
const sourceDir = resolve(root);
|
|
206
|
+
const dirs = [];
|
|
207
|
+
const add = (d) => {
|
|
208
|
+
if (!d || dirs.length >= MAX_BUILD_DIRS) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const abs = resolve(d);
|
|
212
|
+
if (dirs.includes(abs) || abs === sourceDir) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (isSecureMode && !isInsideDir(abs, sourceDir)) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (isDirectory(abs)) {
|
|
219
|
+
dirs.push(abs);
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
if (options.cmakeCache) {
|
|
223
|
+
add(dirname(resolve(`${options.cmakeCache}`)));
|
|
224
|
+
}
|
|
225
|
+
if (!isDirectory(sourceDir)) {
|
|
226
|
+
return dirs;
|
|
227
|
+
}
|
|
228
|
+
for (const preset of readCmakeConfigurePresets(sourceDir)) {
|
|
229
|
+
add(preset.binaryDir);
|
|
230
|
+
}
|
|
231
|
+
const rootBuildDirs = childDirs(
|
|
232
|
+
sourceDir,
|
|
233
|
+
(name) =>
|
|
234
|
+
name.startsWith("build") ||
|
|
235
|
+
name === "out" ||
|
|
236
|
+
name.startsWith("cmake-build-"),
|
|
237
|
+
);
|
|
238
|
+
rootBuildDirs.sort(
|
|
239
|
+
(a, b) => conventionalRank(a) - conventionalRank(b) || a.localeCompare(b),
|
|
240
|
+
);
|
|
241
|
+
for (const d of rootBuildDirs) {
|
|
242
|
+
add(d);
|
|
243
|
+
}
|
|
244
|
+
for (const parent of [
|
|
245
|
+
join(sourceDir, "build"),
|
|
246
|
+
join(sourceDir, "out"),
|
|
247
|
+
join(sourceDir, "out", "build"),
|
|
248
|
+
]) {
|
|
249
|
+
for (const d of childDirs(parent)) {
|
|
250
|
+
add(d);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return dirs;
|
|
254
|
+
}
|