@cyclonedx/cdxgen 10.9.2 → 10.9.4
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/bin/cdxgen.js +6 -0
- package/bin/repl.js +27 -0
- package/display.js +52 -19
- package/envcontext.js +206 -36
- package/envcontext.test.js +10 -0
- package/evinser.js +1 -1
- package/index.js +37 -52
- package/package.json +4 -1
- package/piptree.js +9 -1
- package/postgen.js +53 -10
- package/pregen.js +93 -0
- package/types/display.d.ts +3 -2
- package/types/display.d.ts.map +1 -1
- package/types/envcontext.d.ts +128 -16
- package/types/envcontext.d.ts.map +1 -1
- package/types/evinser.d.ts.map +1 -1
- package/types/index.d.ts.map +1 -1
- package/types/piptree.d.ts.map +1 -1
- package/types/postgen.d.ts +36 -0
- package/types/postgen.d.ts.map +1 -1
- package/types/pregen.d.ts +21 -0
- package/types/pregen.d.ts.map +1 -0
- package/types/utils.d.ts +26 -2
- package/types/utils.d.ts.map +1 -1
- package/utils.js +170 -31
- package/utils.test.js +1 -0
package/bin/cdxgen.js
CHANGED
|
@@ -13,6 +13,7 @@ import jws from "jws";
|
|
|
13
13
|
import {
|
|
14
14
|
printCallStack,
|
|
15
15
|
printDependencyTree,
|
|
16
|
+
printFormulation,
|
|
16
17
|
printOccurrences,
|
|
17
18
|
printReachables,
|
|
18
19
|
printServices,
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
} from "../display.js";
|
|
23
24
|
import { createBom, submitBom } from "../index.js";
|
|
24
25
|
import { postProcess } from "../postgen.js";
|
|
26
|
+
import { prepareEnv } from "../pregen.js";
|
|
25
27
|
import { ATOM_DB } from "../utils.js";
|
|
26
28
|
import { validateBom } from "../validator.js";
|
|
27
29
|
|
|
@@ -502,6 +504,7 @@ const checkPermissions = (filePath) => {
|
|
|
502
504
|
if (!options.usagesSlicesFile) {
|
|
503
505
|
options.usagesSlicesFile = `${options.projectName}-usages.json`;
|
|
504
506
|
}
|
|
507
|
+
prepareEnv(filePath, options);
|
|
505
508
|
let bomNSData = (await createBom(filePath, options)) || {};
|
|
506
509
|
// Add extra metadata and annotations with post processing
|
|
507
510
|
bomNSData = postProcess(bomNSData, options);
|
|
@@ -721,6 +724,9 @@ const checkPermissions = (filePath) => {
|
|
|
721
724
|
}
|
|
722
725
|
if (options.print && bomNSData.bomJson && bomNSData.bomJson.components) {
|
|
723
726
|
printSummary(bomNSData.bomJson);
|
|
727
|
+
if (options.includeFormulation) {
|
|
728
|
+
printFormulation(bomNSData.bomJson);
|
|
729
|
+
}
|
|
724
730
|
printDependencyTree(bomNSData.bomJson);
|
|
725
731
|
printTable(bomNSData.bomJson);
|
|
726
732
|
// CBOM related print
|
package/bin/repl.js
CHANGED
|
@@ -10,6 +10,7 @@ import jsonata from "jsonata";
|
|
|
10
10
|
import {
|
|
11
11
|
printCallStack,
|
|
12
12
|
printDependencyTree,
|
|
13
|
+
printFormulation,
|
|
13
14
|
printOSTable,
|
|
14
15
|
printOccurrences,
|
|
15
16
|
printServices,
|
|
@@ -500,6 +501,32 @@ cdxgenRepl.defineCommand("vulnerabilities", {
|
|
|
500
501
|
this.displayPrompt();
|
|
501
502
|
},
|
|
502
503
|
});
|
|
504
|
+
cdxgenRepl.defineCommand("formulation", {
|
|
505
|
+
help: "view formulation",
|
|
506
|
+
async action() {
|
|
507
|
+
if (sbom) {
|
|
508
|
+
try {
|
|
509
|
+
const expression = jsonata("formulation");
|
|
510
|
+
let formulation = await expression.evaluate(sbom);
|
|
511
|
+
if (!formulation) {
|
|
512
|
+
console.log(
|
|
513
|
+
"No formulation found. Pass the argument --include-formulation to generate SBOM with formulation details.",
|
|
514
|
+
);
|
|
515
|
+
} else {
|
|
516
|
+
if (!Array.isArray(formulation)) {
|
|
517
|
+
formulation = [formulation];
|
|
518
|
+
}
|
|
519
|
+
printFormulation({ formulation });
|
|
520
|
+
}
|
|
521
|
+
} catch (e) {
|
|
522
|
+
console.log(e);
|
|
523
|
+
}
|
|
524
|
+
} else {
|
|
525
|
+
console.log("⚠ No SBOM is loaded. Use .import command to import an SBOM");
|
|
526
|
+
}
|
|
527
|
+
this.displayPrompt();
|
|
528
|
+
},
|
|
529
|
+
});
|
|
503
530
|
cdxgenRepl.defineCommand("osinfocategories", {
|
|
504
531
|
help: "view the category names for the OS info from the obom",
|
|
505
532
|
async action() {
|
package/display.js
CHANGED
|
@@ -18,11 +18,11 @@ const highlightStr = (s, highlight) => {
|
|
|
18
18
|
}
|
|
19
19
|
return s;
|
|
20
20
|
};
|
|
21
|
-
export
|
|
21
|
+
export function printTable(
|
|
22
22
|
bomJson,
|
|
23
23
|
filterTypes = undefined,
|
|
24
24
|
highlight = undefined,
|
|
25
|
-
)
|
|
25
|
+
) {
|
|
26
26
|
if (!bomJson || !bomJson.components) {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
@@ -85,7 +85,7 @@ export const printTable = (
|
|
|
85
85
|
} else {
|
|
86
86
|
console.log(`Components filtered based on type: ${filterTypes.join(", ")}`);
|
|
87
87
|
}
|
|
88
|
-
}
|
|
88
|
+
}
|
|
89
89
|
const formatProps = (props) => {
|
|
90
90
|
const retList = [];
|
|
91
91
|
for (const p of props) {
|
|
@@ -93,7 +93,7 @@ const formatProps = (props) => {
|
|
|
93
93
|
}
|
|
94
94
|
return retList.join("\n");
|
|
95
95
|
};
|
|
96
|
-
export
|
|
96
|
+
export function printOSTable(bomJson) {
|
|
97
97
|
const config = {
|
|
98
98
|
columnDefault: {
|
|
99
99
|
width: 50,
|
|
@@ -111,8 +111,8 @@ export const printOSTable = (bomJson) => {
|
|
|
111
111
|
]);
|
|
112
112
|
}
|
|
113
113
|
console.log();
|
|
114
|
-
}
|
|
115
|
-
export
|
|
114
|
+
}
|
|
115
|
+
export function printServices(bomJson) {
|
|
116
116
|
const data = [["Name", "Endpoints", "Authenticated", "X Trust Boundary"]];
|
|
117
117
|
if (!bomJson || !bomJson.services) {
|
|
118
118
|
return;
|
|
@@ -134,7 +134,30 @@ export const printServices = (bomJson) => {
|
|
|
134
134
|
if (data.length > 1) {
|
|
135
135
|
console.log(table(data, config));
|
|
136
136
|
}
|
|
137
|
-
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function printFormulation(bomJson) {
|
|
140
|
+
const data = [["Tyoe", "Name", "Version"]];
|
|
141
|
+
if (!bomJson || !bomJson.formulation) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
for (const aform of bomJson.formulation) {
|
|
145
|
+
if (aform.components) {
|
|
146
|
+
for (const acomp of aform.components) {
|
|
147
|
+
data.push([acomp.type || "", acomp.name || "", acomp.version || ""]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const config = {
|
|
152
|
+
header: {
|
|
153
|
+
alignment: "center",
|
|
154
|
+
content: "Formulation\nGenerated with \u2665 by cdxgen",
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
if (data.length > 1) {
|
|
158
|
+
console.log(table(data, config));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
138
161
|
|
|
139
162
|
const locationComparator = (a, b) => {
|
|
140
163
|
if (a && b && a.includes("#") && b.includes("#")) {
|
|
@@ -149,7 +172,7 @@ const locationComparator = (a, b) => {
|
|
|
149
172
|
return a.localeCompare(b);
|
|
150
173
|
};
|
|
151
174
|
|
|
152
|
-
export
|
|
175
|
+
export function printOccurrences(bomJson) {
|
|
153
176
|
const data = [["Group", "Name", "Version", "Occurrences"]];
|
|
154
177
|
if (!bomJson || !bomJson.components) {
|
|
155
178
|
return;
|
|
@@ -177,8 +200,8 @@ export const printOccurrences = (bomJson) => {
|
|
|
177
200
|
if (data.length > 1) {
|
|
178
201
|
console.log(table(data, config));
|
|
179
202
|
}
|
|
180
|
-
}
|
|
181
|
-
export
|
|
203
|
+
}
|
|
204
|
+
export function printCallStack(bomJson) {
|
|
182
205
|
const data = [["Group", "Name", "Version", "Call Stack"]];
|
|
183
206
|
if (!bomJson || !bomJson.components) {
|
|
184
207
|
return;
|
|
@@ -224,12 +247,12 @@ export const printCallStack = (bomJson) => {
|
|
|
224
247
|
if (data.length > 1) {
|
|
225
248
|
console.log(table(data, config));
|
|
226
249
|
}
|
|
227
|
-
}
|
|
228
|
-
export
|
|
250
|
+
}
|
|
251
|
+
export function printDependencyTree(
|
|
229
252
|
bomJson,
|
|
230
253
|
mode = "dependsOn",
|
|
231
254
|
highlight = undefined,
|
|
232
|
-
)
|
|
255
|
+
) {
|
|
233
256
|
const dependencies = bomJson.dependencies || [];
|
|
234
257
|
if (!dependencies.length) {
|
|
235
258
|
return;
|
|
@@ -264,7 +287,7 @@ export const printDependencyTree = (
|
|
|
264
287
|
} else {
|
|
265
288
|
console.log(highlightStr(treeGraphics.join("\n"), highlight));
|
|
266
289
|
}
|
|
267
|
-
}
|
|
290
|
+
}
|
|
268
291
|
|
|
269
292
|
const levelPrefix = (level, isLast) => {
|
|
270
293
|
if (level === 0) {
|
|
@@ -324,7 +347,7 @@ const recursePrint = (depMap, subtree, level, shownList, treeGraphics) => {
|
|
|
324
347
|
}
|
|
325
348
|
};
|
|
326
349
|
|
|
327
|
-
export
|
|
350
|
+
export function printReachables(sliceArtefacts) {
|
|
328
351
|
const reachablesSlicesFile = sliceArtefacts.reachablesSlicesFile;
|
|
329
352
|
if (!existsSync(reachablesSlicesFile)) {
|
|
330
353
|
return;
|
|
@@ -355,7 +378,7 @@ export const printReachables = (sliceArtefacts) => {
|
|
|
355
378
|
if (data.length > 1) {
|
|
356
379
|
console.log(table(data, config));
|
|
357
380
|
}
|
|
358
|
-
}
|
|
381
|
+
}
|
|
359
382
|
|
|
360
383
|
export function printVulnerabilities(vulnerabilities) {
|
|
361
384
|
if (!vulnerabilities) {
|
|
@@ -407,7 +430,7 @@ export function printSponsorBanner(options) {
|
|
|
407
430
|
}
|
|
408
431
|
}
|
|
409
432
|
|
|
410
|
-
export
|
|
433
|
+
export function printSummary(bomJson) {
|
|
411
434
|
const config = {
|
|
412
435
|
header: {
|
|
413
436
|
alignment: "center",
|
|
@@ -418,8 +441,18 @@ export const printSummary = (bomJson) => {
|
|
|
418
441
|
if (!metadataProperties) {
|
|
419
442
|
return;
|
|
420
443
|
}
|
|
444
|
+
const tools = bomJson?.metadata?.tools?.components;
|
|
445
|
+
let message = "";
|
|
421
446
|
let bomPkgTypes = [];
|
|
422
447
|
let bomPkgNamespaces = [];
|
|
448
|
+
if (tools) {
|
|
449
|
+
message = "** Generator Tools **";
|
|
450
|
+
for (const atool of tools) {
|
|
451
|
+
if (atool.name && atool.version) {
|
|
452
|
+
message = `${message}\n${atool.name} (${atool.version})`;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
423
456
|
for (const aprop of metadataProperties) {
|
|
424
457
|
if (aprop.name === "cdx:bom:componentTypes") {
|
|
425
458
|
bomPkgTypes = aprop?.value.split("\\n");
|
|
@@ -431,10 +464,10 @@ export const printSummary = (bomJson) => {
|
|
|
431
464
|
if (!bomPkgTypes.length && !bomPkgNamespaces.length) {
|
|
432
465
|
return;
|
|
433
466
|
}
|
|
434
|
-
|
|
467
|
+
message = `${message}\n\n** Package Types (${bomPkgTypes.length}) **\n${bomPkgTypes.join("\n")}`;
|
|
435
468
|
if (bomPkgNamespaces.length) {
|
|
436
469
|
message = `${message}\n\n** Namespaces (${bomPkgNamespaces.length}) **\n${bomPkgNamespaces.join("\n")}`;
|
|
437
470
|
}
|
|
438
471
|
const data = [[message]];
|
|
439
472
|
console.log(table(data, config));
|
|
440
|
-
}
|
|
473
|
+
}
|
package/envcontext.js
CHANGED
|
@@ -1,20 +1,33 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { delimiter, join } from "node:path";
|
|
3
6
|
import process from "node:process";
|
|
4
7
|
import {
|
|
5
8
|
CARGO_CMD,
|
|
9
|
+
DEBUG_MODE,
|
|
6
10
|
DOTNET_CMD,
|
|
7
11
|
GCC_CMD,
|
|
8
12
|
GO_CMD,
|
|
9
|
-
JAVA_CMD,
|
|
10
13
|
NODE_CMD,
|
|
11
14
|
NPM_CMD,
|
|
12
|
-
PYTHON_CMD,
|
|
13
15
|
RUSTC_CMD,
|
|
16
|
+
getJavaCommand,
|
|
17
|
+
getPythonCommand,
|
|
14
18
|
isWin,
|
|
15
19
|
} from "./utils.js";
|
|
16
20
|
|
|
17
|
-
const GIT_COMMAND = process.env.GIT_CMD || "git";
|
|
21
|
+
export const GIT_COMMAND = process.env.GIT_CMD || "git";
|
|
22
|
+
|
|
23
|
+
// sdkman tool aliases
|
|
24
|
+
export const SDKMAN_TOOL_ALIASES = {
|
|
25
|
+
java8: "8.0.422-tem",
|
|
26
|
+
java11: "11.0.24-tem",
|
|
27
|
+
java17: "17.0.12-tem",
|
|
28
|
+
java21: "21.0.4-tem",
|
|
29
|
+
java22: "22.0.2-tem",
|
|
30
|
+
};
|
|
18
31
|
|
|
19
32
|
/**
|
|
20
33
|
* Retrieves a git config item
|
|
@@ -23,9 +36,9 @@ const GIT_COMMAND = process.env.GIT_CMD || "git";
|
|
|
23
36
|
*
|
|
24
37
|
* @returns Output from git config or undefined
|
|
25
38
|
*/
|
|
26
|
-
export
|
|
39
|
+
export function getGitConfig(configKey, dir) {
|
|
27
40
|
return execGitCommand(dir, ["config", "--get", configKey]);
|
|
28
|
-
}
|
|
41
|
+
}
|
|
29
42
|
|
|
30
43
|
/**
|
|
31
44
|
* Retrieves the git origin url
|
|
@@ -33,9 +46,9 @@ export const getGitConfig = (configKey, dir) => {
|
|
|
33
46
|
*
|
|
34
47
|
* @returns Output from git config or undefined
|
|
35
48
|
*/
|
|
36
|
-
export
|
|
49
|
+
export function getOriginUrl(dir) {
|
|
37
50
|
return getGitConfig("remote.origin.url", dir);
|
|
38
|
-
}
|
|
51
|
+
}
|
|
39
52
|
|
|
40
53
|
/**
|
|
41
54
|
* Retrieves the git branch name
|
|
@@ -44,9 +57,9 @@ export const getOriginUrl = (dir) => {
|
|
|
44
57
|
*
|
|
45
58
|
* @returns Output from git config or undefined
|
|
46
59
|
*/
|
|
47
|
-
export
|
|
60
|
+
export function getBranch(configKey, dir) {
|
|
48
61
|
return execGitCommand(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
49
|
-
}
|
|
62
|
+
}
|
|
50
63
|
|
|
51
64
|
/**
|
|
52
65
|
* Retrieves the tree and parent hash for a git repo
|
|
@@ -54,7 +67,7 @@ export const getBranch = (configKey, dir) => {
|
|
|
54
67
|
*
|
|
55
68
|
* @returns Output from git cat-file or undefined
|
|
56
69
|
*/
|
|
57
|
-
export
|
|
70
|
+
export function gitTreeHashes(dir) {
|
|
58
71
|
const treeHashes = {};
|
|
59
72
|
const output = execGitCommand(dir, ["cat-file", "commit", "HEAD"]);
|
|
60
73
|
if (output) {
|
|
@@ -72,7 +85,7 @@ export const gitTreeHashes = (dir) => {
|
|
|
72
85
|
});
|
|
73
86
|
}
|
|
74
87
|
return treeHashes;
|
|
75
|
-
}
|
|
88
|
+
}
|
|
76
89
|
|
|
77
90
|
/**
|
|
78
91
|
* Retrieves the files list from git
|
|
@@ -80,7 +93,7 @@ export const gitTreeHashes = (dir) => {
|
|
|
80
93
|
*
|
|
81
94
|
* @returns Output from git config or undefined
|
|
82
95
|
*/
|
|
83
|
-
export
|
|
96
|
+
export function listFiles(dir) {
|
|
84
97
|
const filesList = [];
|
|
85
98
|
const output = execGitCommand(dir, [
|
|
86
99
|
"ls-tree",
|
|
@@ -108,7 +121,7 @@ export const listFiles = (dir) => {
|
|
|
108
121
|
});
|
|
109
122
|
}
|
|
110
123
|
return filesList;
|
|
111
|
-
}
|
|
124
|
+
}
|
|
112
125
|
|
|
113
126
|
/**
|
|
114
127
|
* Execute a git command
|
|
@@ -118,9 +131,9 @@ export const listFiles = (dir) => {
|
|
|
118
131
|
*
|
|
119
132
|
* @returns Output from the git command
|
|
120
133
|
*/
|
|
121
|
-
export
|
|
134
|
+
export function execGitCommand(dir, args) {
|
|
122
135
|
return getCommandOutput(GIT_COMMAND, dir, args);
|
|
123
|
-
}
|
|
136
|
+
}
|
|
124
137
|
|
|
125
138
|
/**
|
|
126
139
|
* Collect Java version and installed modules
|
|
@@ -128,9 +141,10 @@ export const execGitCommand = (dir, args) => {
|
|
|
128
141
|
* @param {string} dir Working directory
|
|
129
142
|
* @returns Object containing the java details
|
|
130
143
|
*/
|
|
131
|
-
export
|
|
132
|
-
const versionDesc = getCommandOutput(
|
|
133
|
-
const moduleDesc =
|
|
144
|
+
export function collectJavaInfo(dir) {
|
|
145
|
+
const versionDesc = getCommandOutput(getJavaCommand(), dir, ["--version"]);
|
|
146
|
+
const moduleDesc =
|
|
147
|
+
getCommandOutput(getJavaCommand(), dir, ["--list-modules"]) || "";
|
|
134
148
|
if (versionDesc) {
|
|
135
149
|
return {
|
|
136
150
|
type: "platform",
|
|
@@ -146,7 +160,7 @@ export const collectJavaInfo = (dir) => {
|
|
|
146
160
|
};
|
|
147
161
|
}
|
|
148
162
|
return undefined;
|
|
149
|
-
}
|
|
163
|
+
}
|
|
150
164
|
|
|
151
165
|
/**
|
|
152
166
|
* Collect dotnet version
|
|
@@ -154,7 +168,7 @@ export const collectJavaInfo = (dir) => {
|
|
|
154
168
|
* @param {string} dir Working directory
|
|
155
169
|
* @returns Object containing dotnet details
|
|
156
170
|
*/
|
|
157
|
-
export
|
|
171
|
+
export function collectDotnetInfo(dir) {
|
|
158
172
|
const versionDesc = getCommandOutput(DOTNET_CMD, dir, ["--version"]);
|
|
159
173
|
const moduleDesc =
|
|
160
174
|
getCommandOutput(DOTNET_CMD, dir, ["--list-runtimes"]) || "";
|
|
@@ -167,7 +181,7 @@ export const collectDotnetInfo = (dir) => {
|
|
|
167
181
|
};
|
|
168
182
|
}
|
|
169
183
|
return undefined;
|
|
170
|
-
}
|
|
184
|
+
}
|
|
171
185
|
|
|
172
186
|
/**
|
|
173
187
|
* Collect python version
|
|
@@ -175,10 +189,10 @@ export const collectDotnetInfo = (dir) => {
|
|
|
175
189
|
* @param {string} dir Working directory
|
|
176
190
|
* @returns Object containing python details
|
|
177
191
|
*/
|
|
178
|
-
export
|
|
179
|
-
const versionDesc = getCommandOutput(
|
|
192
|
+
export function collectPythonInfo(dir) {
|
|
193
|
+
const versionDesc = getCommandOutput(getPythonCommand(), dir, ["--version"]);
|
|
180
194
|
const moduleDesc =
|
|
181
|
-
getCommandOutput(
|
|
195
|
+
getCommandOutput(getPythonCommand(), dir, ["-m", "pip", "--version"]) || "";
|
|
182
196
|
if (versionDesc) {
|
|
183
197
|
return {
|
|
184
198
|
type: "platform",
|
|
@@ -188,7 +202,7 @@ export const collectPythonInfo = (dir) => {
|
|
|
188
202
|
};
|
|
189
203
|
}
|
|
190
204
|
return undefined;
|
|
191
|
-
}
|
|
205
|
+
}
|
|
192
206
|
|
|
193
207
|
/**
|
|
194
208
|
* Collect node version
|
|
@@ -196,7 +210,7 @@ export const collectPythonInfo = (dir) => {
|
|
|
196
210
|
* @param {string} dir Working directory
|
|
197
211
|
* @returns Object containing node details
|
|
198
212
|
*/
|
|
199
|
-
export
|
|
213
|
+
export function collectNodeInfo(dir) {
|
|
200
214
|
const versionDesc = getCommandOutput(NODE_CMD, dir, ["--version"]);
|
|
201
215
|
let moduleDesc = getCommandOutput(NPM_CMD, dir, ["--version"]);
|
|
202
216
|
if (moduleDesc) {
|
|
@@ -211,7 +225,7 @@ export const collectNodeInfo = (dir) => {
|
|
|
211
225
|
};
|
|
212
226
|
}
|
|
213
227
|
return undefined;
|
|
214
|
-
}
|
|
228
|
+
}
|
|
215
229
|
|
|
216
230
|
/**
|
|
217
231
|
* Collect gcc version
|
|
@@ -219,7 +233,7 @@ export const collectNodeInfo = (dir) => {
|
|
|
219
233
|
* @param {string} dir Working directory
|
|
220
234
|
* @returns Object containing gcc details
|
|
221
235
|
*/
|
|
222
|
-
export
|
|
236
|
+
export function collectGccInfo(dir) {
|
|
223
237
|
const versionDesc = getCommandOutput(GCC_CMD, dir, ["--version"]);
|
|
224
238
|
const moduleDesc = getCommandOutput(GCC_CMD, dir, ["-print-search-dirs"]);
|
|
225
239
|
if (versionDesc) {
|
|
@@ -231,7 +245,7 @@ export const collectGccInfo = (dir) => {
|
|
|
231
245
|
};
|
|
232
246
|
}
|
|
233
247
|
return undefined;
|
|
234
|
-
}
|
|
248
|
+
}
|
|
235
249
|
|
|
236
250
|
/**
|
|
237
251
|
* Collect rust version
|
|
@@ -239,7 +253,7 @@ export const collectGccInfo = (dir) => {
|
|
|
239
253
|
* @param {string} dir Working directory
|
|
240
254
|
* @returns Object containing rust details
|
|
241
255
|
*/
|
|
242
|
-
export
|
|
256
|
+
export function collectRustInfo(dir) {
|
|
243
257
|
const versionDesc = getCommandOutput(RUSTC_CMD, dir, ["--version"]);
|
|
244
258
|
const moduleDesc = getCommandOutput(CARGO_CMD, dir, ["--version"]);
|
|
245
259
|
if (versionDesc) {
|
|
@@ -251,7 +265,7 @@ export const collectRustInfo = (dir) => {
|
|
|
251
265
|
};
|
|
252
266
|
}
|
|
253
267
|
return undefined;
|
|
254
|
-
}
|
|
268
|
+
}
|
|
255
269
|
|
|
256
270
|
/**
|
|
257
271
|
* Collect go version
|
|
@@ -259,7 +273,7 @@ export const collectRustInfo = (dir) => {
|
|
|
259
273
|
* @param {string} dir Working directory
|
|
260
274
|
* @returns Object containing go details
|
|
261
275
|
*/
|
|
262
|
-
export
|
|
276
|
+
export function collectGoInfo(dir) {
|
|
263
277
|
const versionDesc = getCommandOutput(GO_CMD, dir, ["version"]);
|
|
264
278
|
if (versionDesc) {
|
|
265
279
|
return {
|
|
@@ -269,9 +283,9 @@ export const collectGoInfo = (dir) => {
|
|
|
269
283
|
};
|
|
270
284
|
}
|
|
271
285
|
return undefined;
|
|
272
|
-
}
|
|
286
|
+
}
|
|
273
287
|
|
|
274
|
-
export
|
|
288
|
+
export function collectEnvInfo(dir) {
|
|
275
289
|
const infoComponents = [];
|
|
276
290
|
let cmp = collectJavaInfo(dir);
|
|
277
291
|
if (cmp) {
|
|
@@ -302,7 +316,7 @@ export const collectEnvInfo = (dir) => {
|
|
|
302
316
|
infoComponents.push(cmp);
|
|
303
317
|
}
|
|
304
318
|
return infoComponents;
|
|
305
|
-
}
|
|
319
|
+
}
|
|
306
320
|
|
|
307
321
|
/**
|
|
308
322
|
* Execute any command to retrieve the output
|
|
@@ -324,6 +338,162 @@ const getCommandOutput = (cmd, dir, args) => {
|
|
|
324
338
|
const stdout = result.stdout;
|
|
325
339
|
if (stdout) {
|
|
326
340
|
const cmdOutput = Buffer.from(stdout).toString();
|
|
327
|
-
return cmdOutput.trim();
|
|
341
|
+
return cmdOutput.trim().replaceAll("\r", "");
|
|
328
342
|
}
|
|
329
343
|
};
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Method to check if sdkman is available.
|
|
347
|
+
*/
|
|
348
|
+
export function isSdkmanAvailable() {
|
|
349
|
+
let isSdkmanSetup =
|
|
350
|
+
["SDKMAN_DIR", "SDKMAN_CANDIDATES_DIR"].filter(
|
|
351
|
+
(v) => process.env[v] && existsSync(process.env[v]),
|
|
352
|
+
).length >= 1;
|
|
353
|
+
if (!isSdkmanSetup && existsSync(join(homedir(), ".sdkman", "bin"))) {
|
|
354
|
+
process.env.SDKMAN_DIR = join(homedir(), ".sdkman");
|
|
355
|
+
process.env.SDKMAN_CANDIDATES_DIR = join(
|
|
356
|
+
homedir(),
|
|
357
|
+
".sdkman",
|
|
358
|
+
"candidates",
|
|
359
|
+
);
|
|
360
|
+
isSdkmanSetup = true;
|
|
361
|
+
}
|
|
362
|
+
return isSdkmanSetup;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Method to check if a given sdkman tool is installed and available.
|
|
367
|
+
*
|
|
368
|
+
* @param {String} toolType Tool type such as java, gradle, maven etc.
|
|
369
|
+
* @param {String} toolName Tool name with version. Eg: 22.0.2-tem
|
|
370
|
+
*
|
|
371
|
+
* @returns {Boolean} true if the tool is available. false otherwise.
|
|
372
|
+
*/
|
|
373
|
+
export function isSdkmanToolAvailable(toolType, toolName) {
|
|
374
|
+
toolName = getSdkmanToolFullname(toolName);
|
|
375
|
+
let isToolAvailable =
|
|
376
|
+
process.env.SDKMAN_CANDIDATES_DIR &&
|
|
377
|
+
existsSync(
|
|
378
|
+
join(process.env.SDKMAN_CANDIDATES_DIR, toolType, toolName, "bin"),
|
|
379
|
+
);
|
|
380
|
+
if (
|
|
381
|
+
!isToolAvailable &&
|
|
382
|
+
existsSync(
|
|
383
|
+
join(homedir(), ".sdkman", "candidates", toolType, toolName, "bin"),
|
|
384
|
+
)
|
|
385
|
+
) {
|
|
386
|
+
process.env.SDKMAN_CANDIDATES_DIR = join(
|
|
387
|
+
homedir(),
|
|
388
|
+
".sdkman",
|
|
389
|
+
"candidates",
|
|
390
|
+
);
|
|
391
|
+
isToolAvailable = true;
|
|
392
|
+
}
|
|
393
|
+
return isToolAvailable;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Method to install and use a given sdkman tool.
|
|
398
|
+
*
|
|
399
|
+
* @param {String} toolType Tool type such as java, gradle, maven etc.
|
|
400
|
+
* @param {String} toolName Tool name with version. Eg: 22.0.2-tem
|
|
401
|
+
*
|
|
402
|
+
* @returns {Boolean} true if the tool is available. false otherwise.
|
|
403
|
+
*/
|
|
404
|
+
export function installSdkmanTool(toolType, toolName) {
|
|
405
|
+
if (isWin) {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
toolName = getSdkmanToolFullname(toolName);
|
|
409
|
+
let result = undefined;
|
|
410
|
+
if (!isSdkmanToolAvailable(toolType, toolName)) {
|
|
411
|
+
console.log("About to install", toolType, toolName);
|
|
412
|
+
result = spawnSync(
|
|
413
|
+
process.env.SHELL || "bash",
|
|
414
|
+
["-i", "-c", `"echo -e "no" | sdk install ${toolType} ${toolName}"`],
|
|
415
|
+
{
|
|
416
|
+
encoding: "utf-8",
|
|
417
|
+
shell: process.env.SHELL || true,
|
|
418
|
+
},
|
|
419
|
+
);
|
|
420
|
+
if (DEBUG_MODE) {
|
|
421
|
+
if (console.stdout) {
|
|
422
|
+
console.log(result.stdout);
|
|
423
|
+
}
|
|
424
|
+
if (console.stderr) {
|
|
425
|
+
console.log(result.stderr);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (result.status === 1 || result.error) {
|
|
429
|
+
console.log(
|
|
430
|
+
"Unable to install",
|
|
431
|
+
toolType,
|
|
432
|
+
toolName,
|
|
433
|
+
"due to below errors.",
|
|
434
|
+
);
|
|
435
|
+
return false;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
const toolUpper = toolType.toUpperCase();
|
|
439
|
+
// Set process env variables
|
|
440
|
+
if (
|
|
441
|
+
process.env[`${toolUpper}_HOME`] &&
|
|
442
|
+
process.env[`${toolUpper}_HOME`].includes("current")
|
|
443
|
+
) {
|
|
444
|
+
process.env[`${toolUpper}_HOME`] = process.env[`${toolUpper}_HOME`].replace(
|
|
445
|
+
"current",
|
|
446
|
+
toolName,
|
|
447
|
+
);
|
|
448
|
+
console.log(
|
|
449
|
+
`${toolUpper}_HOME`,
|
|
450
|
+
"set to",
|
|
451
|
+
process.env[`${toolUpper}_HOME`],
|
|
452
|
+
);
|
|
453
|
+
} else if (
|
|
454
|
+
process.env.SDKMAN_CANDIDATES_DIR &&
|
|
455
|
+
existsSync(join(process.env.SDKMAN_CANDIDATES_DIR, toolType, toolName))
|
|
456
|
+
) {
|
|
457
|
+
process.env[`${toolUpper}_HOME`] = join(
|
|
458
|
+
process.env.SDKMAN_CANDIDATES_DIR,
|
|
459
|
+
toolType,
|
|
460
|
+
toolName,
|
|
461
|
+
);
|
|
462
|
+
console.log(
|
|
463
|
+
`${toolUpper}_HOME`,
|
|
464
|
+
"set to",
|
|
465
|
+
process.env[`${toolUpper}_HOME`],
|
|
466
|
+
);
|
|
467
|
+
} else {
|
|
468
|
+
console.log(
|
|
469
|
+
"Directory",
|
|
470
|
+
join(process.env.SDKMAN_CANDIDATES_DIR, toolType, toolName),
|
|
471
|
+
"is not found",
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
const toolCurrentBin = join(toolType, "current", "bin");
|
|
475
|
+
if (process.env?.PATH.includes(toolCurrentBin)) {
|
|
476
|
+
process.env.PATH = process.env.PATH.replace(
|
|
477
|
+
toolCurrentBin,
|
|
478
|
+
join(toolType, toolName, "bin"),
|
|
479
|
+
);
|
|
480
|
+
} else if (process.env.SDKMAN_CANDIDATES_DIR) {
|
|
481
|
+
const fullToolBinDir = join(
|
|
482
|
+
process.env.SDKMAN_CANDIDATES_DIR,
|
|
483
|
+
toolType,
|
|
484
|
+
toolName,
|
|
485
|
+
"bin",
|
|
486
|
+
);
|
|
487
|
+
if (!process.env?.PATH?.includes(fullToolBinDir)) {
|
|
488
|
+
process.env.PATH = `${fullToolBinDir}${delimiter}${process.env.PATH}`;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return true;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Retrieve sdkman tool full name
|
|
496
|
+
*/
|
|
497
|
+
function getSdkmanToolFullname(toolName) {
|
|
498
|
+
return SDKMAN_TOOL_ALIASES[toolName] || toolName;
|
|
499
|
+
}
|
package/envcontext.test.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import process from "node:process";
|
|
1
2
|
import { expect, test } from "@jest/globals";
|
|
2
3
|
|
|
3
4
|
import {
|
|
@@ -10,6 +11,8 @@ import {
|
|
|
10
11
|
collectRustInfo,
|
|
11
12
|
getBranch,
|
|
12
13
|
getOriginUrl,
|
|
14
|
+
isSdkmanAvailable,
|
|
15
|
+
isSdkmanToolAvailable,
|
|
13
16
|
listFiles,
|
|
14
17
|
} from "./envcontext.js";
|
|
15
18
|
|
|
@@ -29,3 +32,10 @@ test("tools tests", () => {
|
|
|
29
32
|
expect(collectRustInfo()).toBeDefined();
|
|
30
33
|
expect(collectGoInfo()).toBeDefined();
|
|
31
34
|
});
|
|
35
|
+
|
|
36
|
+
test("sdkman tests", () => {
|
|
37
|
+
if (process.env?.SDKMAN_VERSION) {
|
|
38
|
+
expect(isSdkmanAvailable()).toBeTruthy();
|
|
39
|
+
expect(isSdkmanToolAvailable("java", "22.0.1-tem")).toBeTruthy();
|
|
40
|
+
}
|
|
41
|
+
});
|
package/evinser.js
CHANGED
|
@@ -658,7 +658,7 @@ export const parseSliceUsages = async (
|
|
|
658
658
|
if (purlImportsMap && Object.keys(purlImportsMap).length) {
|
|
659
659
|
for (const apurl of Object.keys(purlImportsMap)) {
|
|
660
660
|
const apurlImports = purlImportsMap[apurl];
|
|
661
|
-
if (
|
|
661
|
+
if (["php", "python"].includes(language)) {
|
|
662
662
|
for (const aimp of apurlImports) {
|
|
663
663
|
if (atype.startsWith(aimp)) {
|
|
664
664
|
if (!purlLocationMap[apurl]) {
|