@cdxgen/cdxgen 13.1.0 → 13.3.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 +32 -15
- package/bin/cdxgen.js +243 -122
- package/bin/evinse.js +7 -0
- package/bin/sign.js +88 -14
- package/bin/tracebom.js +64 -4
- package/bin/validate.js +29 -7
- package/bin/verify.js +79 -39
- package/data/crypto-oid.json +88 -12
- package/data/remediations.json +47 -0
- package/data/rules/ai-bom.yaml +78 -0
- package/data/rules/cargo-rust.yaml +132 -0
- package/data/rules/mcp-servers.yaml +122 -0
- package/lib/audit/targets.js +6 -1
- package/lib/cli/bomAssembly.js +117 -15
- package/lib/cli/cliOptions.js +93 -1
- package/lib/cli/index.js +235 -5
- package/lib/cli/jsBom.js +108 -26
- package/lib/cli/jvmBom.js +68 -12
- package/lib/cli/managedBom.js +264 -41
- package/lib/cli/nativeBom.js +923 -15
- package/lib/core/activity.js +120 -2
- package/lib/core/env.js +44 -7
- package/lib/core/fs.js +174 -6
- package/lib/core/metadataProperties.js +97 -0
- package/lib/core/projectConfig.js +31 -4
- package/lib/core/userAgent.js +151 -0
- package/lib/ecosystems/bunutils.js +269 -101
- package/lib/ecosystems/cargoCache.js +364 -0
- package/lib/ecosystems/caxa.js +447 -7
- package/lib/ecosystems/cmakeResolver.js +66 -0
- package/lib/ecosystems/cppEvidence.js +104 -33
- package/lib/ecosystems/ecosystems.js +260 -99
- package/lib/ecosystems/golem.js +11 -1
- package/lib/ecosystems/gradleutils.js +185 -9
- package/lib/ecosystems/jsEvidence.js +19 -20
- package/lib/ecosystems/kosi.js +1263 -0
- package/lib/ecosystems/npmutils.js +110 -9
- package/lib/ecosystems/parsers-crystal.js +179 -0
- package/lib/ecosystems/parsers-dotnet.js +120 -49
- package/lib/ecosystems/parsers-elm.js +816 -0
- package/lib/ecosystems/parsers-gleam.js +1 -1
- package/lib/ecosystems/parsers-go.js +47 -9
- package/lib/ecosystems/parsers-js.js +171 -50
- package/lib/ecosystems/parsers-julia.js +268 -0
- package/lib/ecosystems/parsers-lua.js +218 -0
- package/lib/ecosystems/parsers-misc.js +919 -161
- package/lib/ecosystems/parsers-nim.js +221 -0
- package/lib/ecosystems/parsers-opam.js +180 -0
- package/lib/ecosystems/parsers-perl.js +277 -0
- package/lib/ecosystems/parsers-python.js +27 -15
- package/lib/ecosystems/parsers-r.js +148 -0
- package/lib/ecosystems/parsers-rebar.js +411 -0
- package/lib/ecosystems/parsers-rust.js +954 -33
- package/lib/ecosystems/parsers-spack.js +204 -0
- package/lib/ecosystems/parsers-stack.js +264 -0
- package/lib/ecosystems/parsers-terraform.js +194 -0
- package/lib/ecosystems/rubyutils.js +1426 -166
- package/lib/ecosystems/rusi.js +158 -7
- package/lib/evinser/evinser.js +547 -129
- package/lib/evinser/swiftsem.js +1914 -302
- package/lib/helpers/agenticToolutils.js +925 -0
- package/lib/helpers/bomSigner.js +652 -221
- package/lib/inventory/agentFormulationParser.js +57 -4
- package/lib/inventory/aiCollector.js +504 -10
- package/lib/inventory/aiInventory.js +12 -0
- package/lib/inventory/analyzer.js +488 -30
- package/lib/inventory/astWorker.js +6 -0
- package/lib/inventory/atomUtils.js +568 -31
- package/lib/inventory/auditCategories.js +8 -0
- package/lib/inventory/cbomutils.js +30 -0
- package/lib/inventory/cdxrs.js +110 -14
- package/lib/inventory/communityAiConfigParser.js +215 -2
- package/lib/inventory/depsUtils.js +183 -11
- package/lib/inventory/display.js +4 -5
- package/lib/inventory/dosai.js +627 -13
- package/lib/inventory/dynamic.js +39 -1
- package/lib/inventory/envcontext.js +9 -6
- package/lib/inventory/evidenceUtils.js +26 -5
- package/lib/inventory/fetchBatch.js +190 -19
- package/lib/inventory/fetchRate.js +74 -11
- package/lib/inventory/forgeEnricher.js +3 -2
- package/lib/inventory/jvmToolEnv.js +6 -5
- package/lib/inventory/mcpConfigParser.js +166 -2
- package/lib/inventory/mcpDiscovery.js +11 -0
- package/lib/inventory/mcpServerManifest.js +389 -0
- package/lib/inventory/mcpbBundle.js +419 -0
- package/lib/inventory/plugins.js +3 -0
- package/lib/inventory/protobom.js +62 -89
- package/lib/inventory/protobomLoader.js +4 -0
- package/lib/inventory/purl.js +152 -3
- package/lib/inventory/rustFormulationParser.js +1 -1
- package/lib/inventory/sbomDocument.js +2 -70
- package/lib/inventory/source.js +47 -23
- package/lib/inventory/stylePackageRefs.js +41 -0
- package/lib/inventory/svelteUtils.js +524 -0
- package/lib/inventory/traceRunner.js +210 -21
- package/lib/managers/binary.js +115 -24
- package/lib/managers/docker.js +440 -20
- package/lib/managers/oci.js +39 -1
- package/lib/parsers/cmakeLists.js +452 -0
- package/lib/parsers/huggingfaceUtils.js +15 -7
- package/lib/parsers/largeJson.js +454 -0
- package/lib/parsers/npmrc.js +19 -1
- package/lib/parsers/onnx.js +294 -0
- package/lib/parsers/safetensors.js +114 -0
- package/lib/stages/postgen/introspection/markers.js +29 -6
- package/lib/stages/postgen/postgen.js +237 -16
- package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +462 -0
- package/lib/validator/bomValidator.js +6 -16
- package/lib/validator/index.js +48 -10
- package/lib/validator/reporters/console.js +3 -0
- package/lib/validator/reporters/json.js +1 -0
- package/lib/validator/reporters/sarif.js +7 -0
- package/package.json +27 -27
- package/types/lib/audit/targets.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +2 -1
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +33 -1
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts +2 -2
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts +23 -0
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts +33 -0
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts +88 -8
- 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 +21 -0
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +55 -0
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/metadataProperties.d.ts +39 -0
- package/types/lib/core/metadataProperties.d.ts.map +1 -0
- package/types/lib/core/projectConfig.d.ts +6 -2
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/userAgent.d.ts +56 -0
- package/types/lib/core/userAgent.d.ts.map +1 -0
- package/types/lib/ecosystems/bunutils.d.ts +12 -5
- package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
- package/types/lib/ecosystems/cargoCache.d.ts +75 -0
- package/types/lib/ecosystems/cargoCache.d.ts.map +1 -0
- package/types/lib/ecosystems/caxa.d.ts +14 -0
- package/types/lib/ecosystems/caxa.d.ts.map +1 -1
- package/types/lib/ecosystems/cmakeResolver.d.ts +23 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
- package/types/lib/ecosystems/cppEvidence.d.ts +2 -2
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/ecosystems.d.ts +15 -1
- 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 +40 -4
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts +5 -2
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts +86 -0
- package/types/lib/ecosystems/kosi.d.ts.map +1 -0
- package/types/lib/ecosystems/npmutils.d.ts +42 -0
- package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-crystal.d.ts +27 -0
- package/types/lib/ecosystems/parsers-crystal.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts +19 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-elm.d.ts +79 -0
- package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-go.d.ts +10 -0
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +10 -4
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-julia.d.ts +57 -0
- package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-lua.d.ts +50 -0
- package/types/lib/ecosystems/parsers-lua.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-misc.d.ts +90 -3
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-nim.d.ts +43 -0
- package/types/lib/ecosystems/parsers-nim.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-opam.d.ts +31 -0
- package/types/lib/ecosystems/parsers-opam.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-perl.d.ts +36 -0
- package/types/lib/ecosystems/parsers-perl.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-r.d.ts +35 -0
- package/types/lib/ecosystems/parsers-r.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-rebar.d.ts +42 -0
- package/types/lib/ecosystems/parsers-rebar.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-rust.d.ts +199 -0
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-spack.d.ts +33 -0
- package/types/lib/ecosystems/parsers-spack.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-stack.d.ts +35 -0
- package/types/lib/ecosystems/parsers-stack.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-terraform.d.ts +34 -0
- package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -0
- package/types/lib/ecosystems/pythonutils.d.ts +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts +143 -2
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts +13 -0
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +81 -2
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/swiftsem.d.ts +280 -15
- package/types/lib/evinser/swiftsem.d.ts.map +1 -1
- package/types/lib/helpers/agenticToolutils.d.ts +87 -0
- package/types/lib/helpers/agenticToolutils.d.ts.map +1 -0
- package/types/lib/helpers/bomSigner.d.ts +106 -13
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/aiInventory.d.ts.map +1 -1
- package/types/lib/inventory/analyzer.d.ts.map +1 -1
- package/types/lib/inventory/atomUtils.d.ts +145 -3
- package/types/lib/inventory/atomUtils.d.ts.map +1 -1
- package/types/lib/inventory/auditCategories.d.ts +4 -0
- package/types/lib/inventory/auditCategories.d.ts.map +1 -1
- package/types/lib/inventory/cbomutils.d.ts.map +1 -1
- package/types/lib/inventory/cdxrs.d.ts +8 -3
- package/types/lib/inventory/cdxrs.d.ts.map +1 -1
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/depsUtils.d.ts +15 -0
- package/types/lib/inventory/depsUtils.d.ts.map +1 -1
- package/types/lib/inventory/display.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +87 -1
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dynamic.d.ts.map +1 -1
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/fetchBatch.d.ts +34 -0
- package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
- package/types/lib/inventory/fetchRate.d.ts +9 -6
- package/types/lib/inventory/fetchRate.d.ts.map +1 -1
- package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
- package/types/lib/inventory/jvmToolEnv.d.ts +5 -4
- package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -1
- package/types/lib/inventory/mcpServerManifest.d.ts +19 -0
- package/types/lib/inventory/mcpServerManifest.d.ts.map +1 -0
- package/types/lib/inventory/mcpbBundle.d.ts +19 -0
- package/types/lib/inventory/mcpbBundle.d.ts.map +1 -0
- package/types/lib/inventory/plugins.d.ts.map +1 -1
- package/types/lib/inventory/protobom.d.ts +18 -13
- package/types/lib/inventory/protobom.d.ts.map +1 -1
- package/types/lib/inventory/protobomLoader.d.ts.map +1 -1
- package/types/lib/inventory/purl.d.ts +71 -2
- package/types/lib/inventory/purl.d.ts.map +1 -1
- package/types/lib/inventory/sbomDocument.d.ts.map +1 -1
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/inventory/stylePackageRefs.d.ts +17 -0
- package/types/lib/inventory/stylePackageRefs.d.ts.map +1 -0
- package/types/lib/inventory/svelteUtils.d.ts +124 -0
- package/types/lib/inventory/svelteUtils.d.ts.map +1 -0
- package/types/lib/inventory/traceRunner.d.ts +47 -1
- package/types/lib/inventory/traceRunner.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts +30 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +29 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/managers/oci.d.ts +14 -0
- package/types/lib/managers/oci.d.ts.map +1 -1
- package/types/lib/parsers/cmakeLists.d.ts +76 -0
- package/types/lib/parsers/cmakeLists.d.ts.map +1 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts +8 -1
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
- package/types/lib/parsers/largeJson.d.ts +52 -0
- package/types/lib/parsers/largeJson.d.ts.map +1 -0
- package/types/lib/parsers/npmrc.d.ts +5 -0
- package/types/lib/parsers/npmrc.d.ts.map +1 -1
- package/types/lib/parsers/onnx.d.ts +28 -0
- package/types/lib/parsers/onnx.d.ts.map +1 -0
- package/types/lib/parsers/safetensors.d.ts +22 -0
- package/types/lib/parsers/safetensors.d.ts.map +1 -0
- package/types/lib/stages/postgen/introspection/markers.d.ts +3 -2
- package/types/lib/stages/postgen/introspection/markers.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +33 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +10 -1
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/console.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
- package/types/lib/validator/reporters/sarif.d.ts.map +1 -1
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure parser for CMake language files (`CMakeLists.txt`, `*.cmake`).
|
|
3
|
+
*
|
|
4
|
+
* `parseCmakeCommands` splits a file into command invocations the way CMake
|
|
5
|
+
* reads it: command names are case-insensitive, an invocation may span several
|
|
6
|
+
* lines, and arguments may be quoted, bracketed (`[[...]]`) or interleaved with
|
|
7
|
+
* comments. `cmakeFetchDependencies` reads the commands that download a
|
|
8
|
+
* dependency at configure time: `FetchContent_Declare`, `ExternalProject_Add`
|
|
9
|
+
* and the CPM.cmake `CPMAddPackage` family.
|
|
10
|
+
*
|
|
11
|
+
* This module is layer 1 (text in, data out): no filesystem or subprocess
|
|
12
|
+
* access. `lib/ecosystems/parsers-misc.js` turns the facts into components.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Length of the bracket opener (`[[`, `[=[`, `[==[`, ...) at `text[start]`, or 0.
|
|
17
|
+
*
|
|
18
|
+
* @param {string} text CMake source
|
|
19
|
+
* @param {number} start Index of a `[`
|
|
20
|
+
* @returns {number} Opener length including both brackets, or 0
|
|
21
|
+
*/
|
|
22
|
+
function bracketOpenLength(text, start) {
|
|
23
|
+
if (text[start] !== "[") {
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
let i = start + 1;
|
|
27
|
+
while (text[i] === "=") {
|
|
28
|
+
i++;
|
|
29
|
+
}
|
|
30
|
+
return text[i] === "[" ? i - start + 1 : 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Index just past the bracket closer matching an opener of `openLength`.
|
|
35
|
+
*
|
|
36
|
+
* @param {string} text CMake source
|
|
37
|
+
* @param {number} contentStart First index after the opener
|
|
38
|
+
* @param {number} openLength Opener length (`[==[` is 4)
|
|
39
|
+
* @returns {number} Index after the closer, or the text length when unclosed
|
|
40
|
+
*/
|
|
41
|
+
function bracketCloseEnd(text, contentStart, openLength) {
|
|
42
|
+
const closer = `]${"=".repeat(openLength - 2)}]`;
|
|
43
|
+
const end = text.indexOf(closer, contentStart);
|
|
44
|
+
return end === -1 ? text.length : end + closer.length;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Index of the end of the comment starting at `text[start]` (a `#`).
|
|
49
|
+
*
|
|
50
|
+
* @param {string} text CMake source
|
|
51
|
+
* @param {number} start Index of the `#`
|
|
52
|
+
* @returns {number} Index of the first character after the comment
|
|
53
|
+
*/
|
|
54
|
+
function skipComment(text, start) {
|
|
55
|
+
const openLength = bracketOpenLength(text, start + 1);
|
|
56
|
+
if (openLength) {
|
|
57
|
+
return bracketCloseEnd(text, start + 1 + openLength, openLength);
|
|
58
|
+
}
|
|
59
|
+
const eol = text.indexOf("\n", start);
|
|
60
|
+
return eol === -1 ? text.length : eol;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function isIdentifierStart(c) {
|
|
64
|
+
return (c >= "A" && c <= "Z") || (c >= "a" && c <= "z") || c === "_";
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isIdentifierPart(c) {
|
|
68
|
+
return isIdentifierStart(c) || (c >= "0" && c <= "9");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isSpace(c) {
|
|
72
|
+
return c === " " || c === "\t" || c === "\r" || c === "\n";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Split CMake source into command invocations.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} text Contents of a CMake file
|
|
79
|
+
* @returns {{name: string, args: string[], line: number}[]} Invocations in
|
|
80
|
+
* source order. `name` is lower-cased; `args` have their quotes and bracket
|
|
81
|
+
* delimiters removed; `line` is the 1-based line of the command name.
|
|
82
|
+
*/
|
|
83
|
+
export function parseCmakeCommands(text) {
|
|
84
|
+
const commands = [];
|
|
85
|
+
if (!text || typeof text !== "string") {
|
|
86
|
+
return commands;
|
|
87
|
+
}
|
|
88
|
+
let line = 1;
|
|
89
|
+
let i = 0;
|
|
90
|
+
const advanceTo = (end) => {
|
|
91
|
+
for (let k = i; k < end; k++) {
|
|
92
|
+
if (text[k] === "\n") {
|
|
93
|
+
line++;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
i = end;
|
|
97
|
+
};
|
|
98
|
+
while (i < text.length) {
|
|
99
|
+
const c = text[i];
|
|
100
|
+
if (c === "#") {
|
|
101
|
+
advanceTo(skipComment(text, i));
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (!isIdentifierStart(c) || (i > 0 && isIdentifierPart(text[i - 1]))) {
|
|
105
|
+
advanceTo(i + 1);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
let end = i;
|
|
109
|
+
while (end < text.length && isIdentifierPart(text[end])) {
|
|
110
|
+
end++;
|
|
111
|
+
}
|
|
112
|
+
const name = text.slice(i, end).toLowerCase();
|
|
113
|
+
const commandLine = line;
|
|
114
|
+
let open = end;
|
|
115
|
+
while (text[open] === " " || text[open] === "\t") {
|
|
116
|
+
open++;
|
|
117
|
+
}
|
|
118
|
+
if (text[open] !== "(") {
|
|
119
|
+
advanceTo(end);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
advanceTo(open + 1);
|
|
123
|
+
const args = [];
|
|
124
|
+
let depth = 1;
|
|
125
|
+
let current = "";
|
|
126
|
+
let hasToken = false;
|
|
127
|
+
const flush = () => {
|
|
128
|
+
if (hasToken) {
|
|
129
|
+
args.push(current);
|
|
130
|
+
}
|
|
131
|
+
current = "";
|
|
132
|
+
hasToken = false;
|
|
133
|
+
};
|
|
134
|
+
while (i < text.length && depth > 0) {
|
|
135
|
+
const ch = text[i];
|
|
136
|
+
if (ch === "#") {
|
|
137
|
+
flush();
|
|
138
|
+
advanceTo(skipComment(text, i));
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (ch === '"') {
|
|
142
|
+
let k = i + 1;
|
|
143
|
+
let value = "";
|
|
144
|
+
while (k < text.length && text[k] !== '"') {
|
|
145
|
+
if (text[k] === "\\" && k + 1 < text.length) {
|
|
146
|
+
value += text[k + 1];
|
|
147
|
+
k += 2;
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
value += text[k];
|
|
151
|
+
k++;
|
|
152
|
+
}
|
|
153
|
+
current += value;
|
|
154
|
+
hasToken = true;
|
|
155
|
+
advanceTo(Math.min(k + 1, text.length));
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const openLength = bracketOpenLength(text, i);
|
|
159
|
+
if (openLength && !hasToken) {
|
|
160
|
+
const contentStart = i + openLength;
|
|
161
|
+
const closeEnd = bracketCloseEnd(text, contentStart, openLength);
|
|
162
|
+
const contentEnd = Math.max(contentStart, closeEnd - openLength);
|
|
163
|
+
current += text.slice(contentStart, contentEnd);
|
|
164
|
+
hasToken = true;
|
|
165
|
+
advanceTo(closeEnd);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (ch === "(") {
|
|
169
|
+
depth++;
|
|
170
|
+
} else if (ch === ")") {
|
|
171
|
+
depth--;
|
|
172
|
+
if (depth === 0) {
|
|
173
|
+
flush();
|
|
174
|
+
advanceTo(i + 1);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (isSpace(ch)) {
|
|
179
|
+
flush();
|
|
180
|
+
} else {
|
|
181
|
+
current += ch;
|
|
182
|
+
hasToken = true;
|
|
183
|
+
}
|
|
184
|
+
advanceTo(i + 1);
|
|
185
|
+
}
|
|
186
|
+
commands.push({ name, args, line: commandLine });
|
|
187
|
+
}
|
|
188
|
+
return commands;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Replace `${VAR}` references with the values of simple `set()` calls. A
|
|
193
|
+
* reference to an unknown variable is left in place, so callers can tell a
|
|
194
|
+
* resolved value from an unresolved one.
|
|
195
|
+
*
|
|
196
|
+
* @param {string} value Argument text
|
|
197
|
+
* @param {Map<string,string>} variables Known variable values
|
|
198
|
+
* @returns {string} The expanded text
|
|
199
|
+
*/
|
|
200
|
+
export function expandCmakeVariables(value, variables) {
|
|
201
|
+
let result = value;
|
|
202
|
+
for (let round = 0; round < 5 && result.includes("${"); round++) {
|
|
203
|
+
let next = "";
|
|
204
|
+
let i = 0;
|
|
205
|
+
while (i < result.length) {
|
|
206
|
+
const start = result.indexOf("${", i);
|
|
207
|
+
if (start === -1) {
|
|
208
|
+
next += result.slice(i);
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
const end = result.indexOf("}", start + 2);
|
|
212
|
+
if (end === -1) {
|
|
213
|
+
next += result.slice(i);
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
const key = result.slice(start + 2, end);
|
|
217
|
+
next += result.slice(i, start);
|
|
218
|
+
next += variables.has(key)
|
|
219
|
+
? variables.get(key)
|
|
220
|
+
: result.slice(start, end + 1);
|
|
221
|
+
i = end + 1;
|
|
222
|
+
}
|
|
223
|
+
if (next === result) {
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
result = next;
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* The variables a file sets to a single value: `set(FOO_VERSION 1.2.3)` and
|
|
233
|
+
* `set(FOO_VERSION "1.2.3" CACHE STRING "...")`. Later definitions win.
|
|
234
|
+
*
|
|
235
|
+
* @param {{name: string, args: string[]}[]} commands Parsed commands
|
|
236
|
+
* @returns {Map<string,string>} Variable values
|
|
237
|
+
*/
|
|
238
|
+
export function cmakeSetVariables(commands) {
|
|
239
|
+
const variables = new Map();
|
|
240
|
+
for (const command of commands) {
|
|
241
|
+
if (command.name !== "set" || command.args.length < 2) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
const [key, value, ...rest] = command.args;
|
|
245
|
+
if (
|
|
246
|
+
rest.length === 0 ||
|
|
247
|
+
rest[0] === "CACHE" ||
|
|
248
|
+
rest[0] === "PARENT_SCOPE"
|
|
249
|
+
) {
|
|
250
|
+
variables.set(key, expandCmakeVariables(value, variables));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return variables;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* The value following `keyword` in a keyword-style argument list, skipping the
|
|
258
|
+
* leading positional arguments.
|
|
259
|
+
*
|
|
260
|
+
* @param {string[]} args Command arguments
|
|
261
|
+
* @param {string} keyword Keyword to look up, e.g. `GIT_TAG`
|
|
262
|
+
* @param {number} from First index that may hold a keyword
|
|
263
|
+
* @returns {string|undefined} The value, or undefined when absent
|
|
264
|
+
*/
|
|
265
|
+
function keywordValue(args, keyword, from) {
|
|
266
|
+
for (let i = from; i < args.length - 1; i++) {
|
|
267
|
+
if (args[i] === keyword) {
|
|
268
|
+
return args[i + 1];
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const HOST_SHORTHANDS = {
|
|
275
|
+
gh: "https://github.com/",
|
|
276
|
+
gl: "https://gitlab.com/",
|
|
277
|
+
bb: "https://bitbucket.org/",
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Read a CPM.cmake shorthand such as `gh:fmtlib/fmt#7.1.3`,
|
|
282
|
+
* `gh:nlohmann/json@3.11.2` or `https://example.com/x.git@1.0#v1.0`.
|
|
283
|
+
*
|
|
284
|
+
* @param {string} spec The single CPMAddPackage argument
|
|
285
|
+
* @returns {{name: string, gitRepository?: string, url?: string, gitTag?: string, version?: string}|undefined}
|
|
286
|
+
*/
|
|
287
|
+
function parseCpmShorthand(spec) {
|
|
288
|
+
let rest = spec;
|
|
289
|
+
let gitTag;
|
|
290
|
+
let version;
|
|
291
|
+
const hash = rest.lastIndexOf("#");
|
|
292
|
+
if (hash !== -1) {
|
|
293
|
+
gitTag = rest.slice(hash + 1);
|
|
294
|
+
rest = rest.slice(0, hash);
|
|
295
|
+
}
|
|
296
|
+
const colon = rest.indexOf(":");
|
|
297
|
+
const scheme = colon === -1 ? "" : rest.slice(0, colon);
|
|
298
|
+
let repository;
|
|
299
|
+
if (HOST_SHORTHANDS[scheme]) {
|
|
300
|
+
let path = rest.slice(colon + 1);
|
|
301
|
+
const at = path.lastIndexOf("@");
|
|
302
|
+
if (at !== -1) {
|
|
303
|
+
version = path.slice(at + 1);
|
|
304
|
+
path = path.slice(0, at);
|
|
305
|
+
}
|
|
306
|
+
repository = `${HOST_SHORTHANDS[scheme]}${path}`;
|
|
307
|
+
} else if (scheme === "https" || scheme === "http") {
|
|
308
|
+
const lastSlash = rest.lastIndexOf("/");
|
|
309
|
+
const at = rest.lastIndexOf("@");
|
|
310
|
+
if (at > lastSlash) {
|
|
311
|
+
version = rest.slice(at + 1);
|
|
312
|
+
rest = rest.slice(0, at);
|
|
313
|
+
}
|
|
314
|
+
repository = rest;
|
|
315
|
+
} else {
|
|
316
|
+
return undefined;
|
|
317
|
+
}
|
|
318
|
+
const name = repository
|
|
319
|
+
.split("/")
|
|
320
|
+
.filter(Boolean)
|
|
321
|
+
.pop()
|
|
322
|
+
?.replace(/\.git$/, "");
|
|
323
|
+
if (!name) {
|
|
324
|
+
return undefined;
|
|
325
|
+
}
|
|
326
|
+
return {
|
|
327
|
+
name,
|
|
328
|
+
gitRepository: repository,
|
|
329
|
+
gitTag: gitTag || (version ? `v${version}` : undefined),
|
|
330
|
+
version,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* The dependencies a CMake file downloads at configure time.
|
|
336
|
+
*
|
|
337
|
+
* `FetchContent_Declare(<name> ...)` and `ExternalProject_Add(<name> ...)` are
|
|
338
|
+
* read for `GIT_REPOSITORY`/`GIT_TAG` and `URL`/`URL_HASH`/`URL_MD5`.
|
|
339
|
+
* `CPMAddPackage`, `CPMFindPackage` and `CPMDeclarePackage` are read in both
|
|
340
|
+
* the shorthand form and the keyword form (`NAME`, `VERSION`,
|
|
341
|
+
* `GITHUB_REPOSITORY`, `GITLAB_REPOSITORY`, `BITBUCKET_REPOSITORY`,
|
|
342
|
+
* `GIT_REPOSITORY`, `GIT_TAG`, `URL`, `URL_HASH`). `${VAR}` references are
|
|
343
|
+
* expanded with the file's simple `set()` values; anything still unresolved
|
|
344
|
+
* stays as written.
|
|
345
|
+
*
|
|
346
|
+
* @param {string} text Contents of a CMake file
|
|
347
|
+
* @returns {{kind: string, name: string, line: number, gitRepository?: string, gitTag?: string, url?: string, urlHash?: string, version?: string, madeAvailable: boolean}[]}
|
|
348
|
+
* `kind` is `fetch`, `external-project` or `cpm`; `madeAvailable` is true
|
|
349
|
+
* when a `FetchContent_MakeAvailable` in the same file names the dependency.
|
|
350
|
+
*/
|
|
351
|
+
export function cmakeFetchDependencies(text) {
|
|
352
|
+
const commands = parseCmakeCommands(text);
|
|
353
|
+
const variables = cmakeSetVariables(commands);
|
|
354
|
+
const expand = (value) =>
|
|
355
|
+
value === undefined ? undefined : expandCmakeVariables(value, variables);
|
|
356
|
+
const madeAvailable = new Set();
|
|
357
|
+
for (const command of commands) {
|
|
358
|
+
if (command.name === "fetchcontent_makeavailable") {
|
|
359
|
+
for (const arg of command.args) {
|
|
360
|
+
madeAvailable.add(expand(arg).toLowerCase());
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
const deps = [];
|
|
365
|
+
for (const command of commands) {
|
|
366
|
+
const args = command.args.map(expand);
|
|
367
|
+
let dep;
|
|
368
|
+
if (
|
|
369
|
+
(command.name === "fetchcontent_declare" ||
|
|
370
|
+
command.name === "externalproject_add") &&
|
|
371
|
+
args.length
|
|
372
|
+
) {
|
|
373
|
+
const url = keywordValue(args, "URL", 1);
|
|
374
|
+
const md5 = keywordValue(args, "URL_MD5", 1);
|
|
375
|
+
dep = {
|
|
376
|
+
kind:
|
|
377
|
+
command.name === "fetchcontent_declare"
|
|
378
|
+
? "fetch"
|
|
379
|
+
: "external-project",
|
|
380
|
+
name: args[0],
|
|
381
|
+
gitRepository: keywordValue(args, "GIT_REPOSITORY", 1),
|
|
382
|
+
gitTag: keywordValue(args, "GIT_TAG", 1),
|
|
383
|
+
url: url?.split(";")[0],
|
|
384
|
+
urlHash: keywordValue(args, "URL_HASH", 1) || (md5 && `MD5=${md5}`),
|
|
385
|
+
};
|
|
386
|
+
} else if (
|
|
387
|
+
command.name === "cpmaddpackage" ||
|
|
388
|
+
command.name === "cpmfindpackage" ||
|
|
389
|
+
command.name === "cpmdeclarepackage"
|
|
390
|
+
) {
|
|
391
|
+
const positional = command.name === "cpmdeclarepackage" ? 1 : 0;
|
|
392
|
+
if (args.length === positional + 1) {
|
|
393
|
+
const shorthand = parseCpmShorthand(args[positional]);
|
|
394
|
+
if (shorthand) {
|
|
395
|
+
dep = {
|
|
396
|
+
kind: "cpm",
|
|
397
|
+
...shorthand,
|
|
398
|
+
name: positional ? args[0] : shorthand.name,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
} else if (args.length > positional) {
|
|
402
|
+
const name = positional ? args[0] : keywordValue(args, "NAME", 0);
|
|
403
|
+
const version = keywordValue(args, "VERSION", positional);
|
|
404
|
+
const github = keywordValue(args, "GITHUB_REPOSITORY", positional);
|
|
405
|
+
const gitlab = keywordValue(args, "GITLAB_REPOSITORY", positional);
|
|
406
|
+
const bitbucket = keywordValue(
|
|
407
|
+
args,
|
|
408
|
+
"BITBUCKET_REPOSITORY",
|
|
409
|
+
positional,
|
|
410
|
+
);
|
|
411
|
+
const hosted =
|
|
412
|
+
(github && `${HOST_SHORTHANDS.gh}${github}`) ||
|
|
413
|
+
(gitlab && `${HOST_SHORTHANDS.gl}${gitlab}`) ||
|
|
414
|
+
(bitbucket && `${HOST_SHORTHANDS.bb}${bitbucket}`);
|
|
415
|
+
const gitRepository =
|
|
416
|
+
hosted || keywordValue(args, "GIT_REPOSITORY", positional);
|
|
417
|
+
const url = keywordValue(args, "URL", positional);
|
|
418
|
+
const derivedName =
|
|
419
|
+
name ||
|
|
420
|
+
(gitRepository || url)
|
|
421
|
+
?.split("/")
|
|
422
|
+
.filter(Boolean)
|
|
423
|
+
.pop()
|
|
424
|
+
?.replace(/\.git$/, "");
|
|
425
|
+
if (derivedName) {
|
|
426
|
+
dep = {
|
|
427
|
+
kind: "cpm",
|
|
428
|
+
name: derivedName,
|
|
429
|
+
gitRepository,
|
|
430
|
+
gitTag:
|
|
431
|
+
keywordValue(args, "GIT_TAG", positional) ||
|
|
432
|
+
(gitRepository && version ? `v${version}` : undefined),
|
|
433
|
+
url,
|
|
434
|
+
urlHash: keywordValue(args, "URL_HASH", positional),
|
|
435
|
+
version,
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (dep?.name) {
|
|
441
|
+
for (const key of Object.keys(dep)) {
|
|
442
|
+
if (dep[key] === undefined || dep[key] === "") {
|
|
443
|
+
delete dep[key];
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
dep.line = command.line;
|
|
447
|
+
dep.madeAvailable = madeAvailable.has(dep.name.toLowerCase());
|
|
448
|
+
deps.push(dep);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return deps;
|
|
452
|
+
}
|
|
@@ -237,9 +237,14 @@ export function toHuggingFacePurl(repoId, version, repositoryUrl) {
|
|
|
237
237
|
* Normalize a direct Hugging Face URL or purl into a repo reference.
|
|
238
238
|
*
|
|
239
239
|
* @param {string} value direct URL, API URL, or purl
|
|
240
|
+
* @param {object} [parseOptions] parsing options
|
|
241
|
+
* @param {boolean} [parseOptions.explicitOnly=false] resolve only unambiguous
|
|
242
|
+
* references (`pkg:huggingface/...` purls and huggingface.co URLs) so that
|
|
243
|
+
* ambiguous `owner/repo`-shaped values keep their filesystem-path meaning
|
|
244
|
+
* until an AI inventory type is explicitly selected
|
|
240
245
|
* @returns {{ assetType: string, repoId: string, version?: string }|undefined} normalized reference
|
|
241
246
|
*/
|
|
242
|
-
export function normalizeHuggingFaceReference(value) {
|
|
247
|
+
export function normalizeHuggingFaceReference(value, parseOptions = {}) {
|
|
243
248
|
if (!value) {
|
|
244
249
|
return undefined;
|
|
245
250
|
}
|
|
@@ -276,9 +281,11 @@ export function normalizeHuggingFaceReference(value) {
|
|
|
276
281
|
// Fall through to the remaining parsers.
|
|
277
282
|
}
|
|
278
283
|
}
|
|
279
|
-
const directTypedMatch =
|
|
280
|
-
|
|
281
|
-
|
|
284
|
+
const directTypedMatch = parseOptions.explicitOnly
|
|
285
|
+
? undefined
|
|
286
|
+
: normalizedValue.match(
|
|
287
|
+
/^(models|datasets|spaces)\/([^/\s]+\/[^/\s]+)(?:\/revision\/([^/\s?#]+))?$/u,
|
|
288
|
+
);
|
|
282
289
|
if (directTypedMatch) {
|
|
283
290
|
return {
|
|
284
291
|
assetType:
|
|
@@ -296,9 +303,10 @@ export function normalizeHuggingFaceReference(value) {
|
|
|
296
303
|
const looksLikeFilesystemPath =
|
|
297
304
|
/^(?:\/|\.{1,2}(?:\/|$)|~\/|[a-z]:[\\/])/iu.test(normalizedValue) ||
|
|
298
305
|
normalizedValue.includes("\\");
|
|
299
|
-
const directRepoId =
|
|
300
|
-
|
|
301
|
-
|
|
306
|
+
const directRepoId =
|
|
307
|
+
looksLikeFilesystemPath || parseOptions.explicitOnly
|
|
308
|
+
? undefined
|
|
309
|
+
: sanitizeHuggingFaceRepoId(normalizedValue);
|
|
302
310
|
if (directRepoId) {
|
|
303
311
|
return { assetType: "model", repoId: directRepoId };
|
|
304
312
|
}
|