@contrast/contrast 1.0.3 → 1.0.6
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/.prettierignore +4 -0
- package/README.md +20 -14
- package/dist/audit/autodetection/autoDetectLanguage.js +32 -0
- package/dist/audit/catalogueApplication/catalogueApplication.js +2 -11
- package/dist/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +6 -14
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +29 -0
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +101 -234
- package/dist/audit/languageAnalysisEngine/report/models/reportLibraryModel.js +19 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +24 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +24 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +12 -0
- package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +13 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +24 -129
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +99 -0
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +2 -14
- package/dist/commands/audit/auditConfig.js +8 -2
- package/dist/commands/audit/auditController.js +14 -5
- package/dist/commands/scan/processScan.js +10 -6
- package/dist/commands/scan/sca/scaAnalysis.js +49 -0
- package/dist/common/HTTPClient.js +18 -26
- package/dist/common/errorHandling.js +7 -17
- package/dist/common/versionChecker.js +14 -12
- package/dist/constants/constants.js +24 -2
- package/dist/constants/lambda.js +3 -1
- package/dist/constants/locales.js +42 -42
- package/dist/constants.js +25 -1
- package/dist/index.js +2 -2
- package/dist/lambda/help.js +22 -14
- package/dist/lambda/lambda.js +6 -0
- package/dist/scaAnalysis/common/formatMessage.js +19 -0
- package/dist/scaAnalysis/common/treeUpload.js +29 -0
- package/dist/scaAnalysis/go/goAnalysis.js +17 -0
- package/dist/scaAnalysis/go/goParseDeps.js +158 -0
- package/dist/scaAnalysis/go/goReadDepFile.js +23 -0
- package/dist/scaAnalysis/java/analysis.js +108 -0
- package/dist/scaAnalysis/java/index.js +18 -0
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +339 -0
- package/dist/scan/autoDetection.js +46 -1
- package/dist/scan/fileUtils.js +73 -1
- package/dist/scan/formatScanOutput.js +215 -0
- package/dist/scan/help.js +3 -1
- package/dist/scan/models/groupedResultsModel.js +11 -0
- package/dist/scan/models/resultContentModel.js +2 -0
- package/dist/scan/models/scanResultsModel.js +11 -0
- package/dist/scan/scan.js +27 -126
- package/dist/scan/scanConfig.js +1 -1
- package/dist/scan/scanController.js +11 -5
- package/dist/scan/scanResults.js +15 -19
- package/dist/utils/getConfig.js +3 -0
- package/dist/utils/oraWrapper.js +5 -1
- package/package.json +3 -2
- package/src/audit/autodetection/autoDetectLanguage.ts +40 -0
- package/src/audit/catalogueApplication/catalogueApplication.js +4 -16
- package/src/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +11 -21
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +72 -0
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +204 -0
- package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +30 -0
- package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +32 -0
- package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +29 -0
- package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +13 -0
- package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +16 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +56 -0
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +116 -0
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +2 -22
- package/src/commands/audit/auditConfig.ts +12 -3
- package/src/commands/audit/auditController.ts +20 -5
- package/src/commands/audit/processAudit.ts +3 -0
- package/src/commands/scan/processScan.js +13 -9
- package/src/commands/scan/sca/scaAnalysis.js +75 -0
- package/src/common/HTTPClient.js +31 -38
- package/src/common/errorHandling.ts +7 -25
- package/src/common/versionChecker.ts +24 -22
- package/src/constants/constants.js +24 -2
- package/src/constants/lambda.js +3 -1
- package/src/constants/locales.js +47 -56
- package/src/constants.js +29 -1
- package/src/index.ts +2 -3
- package/src/lambda/help.ts +22 -14
- package/src/lambda/lambda.ts +8 -0
- package/src/scaAnalysis/common/formatMessage.js +20 -0
- package/src/scaAnalysis/common/treeUpload.js +30 -0
- package/src/scaAnalysis/go/goAnalysis.js +20 -0
- package/src/scaAnalysis/go/goParseDeps.js +203 -0
- package/src/scaAnalysis/go/goReadDepFile.js +32 -0
- package/src/scaAnalysis/java/analysis.js +143 -0
- package/src/scaAnalysis/java/index.js +21 -0
- package/src/scaAnalysis/java/javaBuildDepsParser.js +404 -0
- package/src/scan/autoDetection.js +54 -1
- package/src/scan/fileUtils.js +91 -1
- package/src/scan/formatScanOutput.ts +250 -0
- package/src/scan/help.js +3 -1
- package/src/scan/models/groupedResultsModel.ts +20 -0
- package/src/scan/models/resultContentModel.ts +86 -0
- package/src/scan/models/scanResultsModel.ts +52 -0
- package/src/scan/scan.ts +63 -0
- package/src/scan/scanConfig.js +1 -1
- package/src/scan/scanController.js +15 -7
- package/src/scan/scanResults.js +21 -18
- package/src/utils/getConfig.ts +10 -0
- package/src/utils/oraWrapper.js +6 -1
- package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -17
- package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -81
- package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -27
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +0 -303
- package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -124
- package/src/audit/languageAnalysisEngine/report/reportingFeature.js +0 -190
- package/src/scan/scan.js +0 -195
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
const parseGoDependencies = goDeps => {
|
|
4
|
+
return parseGo(goDeps);
|
|
5
|
+
};
|
|
6
|
+
const parseGo = modGraphOutput => {
|
|
7
|
+
let splitLines = splitAllLinesIntoArray(modGraphOutput);
|
|
8
|
+
const directDepNames = getDirectDepNames(splitLines);
|
|
9
|
+
const uniqueTransitiveDepNames = getAllUniqueTransitiveDepNames(splitLines, directDepNames);
|
|
10
|
+
let rootNodes = createRootNodes(splitLines);
|
|
11
|
+
createTransitiveDeps(uniqueTransitiveDepNames, splitLines, rootNodes);
|
|
12
|
+
return rootNodes;
|
|
13
|
+
};
|
|
14
|
+
const splitAllLinesIntoArray = modGraphOutput => {
|
|
15
|
+
return modGraphOutput.split(/\r\n|\r|\n/);
|
|
16
|
+
};
|
|
17
|
+
const getAllDepsOfADepAsEdge = (dep, deps) => {
|
|
18
|
+
let edges = {};
|
|
19
|
+
const depRows = deps.filter(line => {
|
|
20
|
+
return line.startsWith(dep);
|
|
21
|
+
});
|
|
22
|
+
depRows.forEach(dep => {
|
|
23
|
+
const edgeName = dep.split(' ')[1];
|
|
24
|
+
edges[edgeName] = edgeName;
|
|
25
|
+
});
|
|
26
|
+
return edges;
|
|
27
|
+
};
|
|
28
|
+
const getAllDepsOfADepAsName = (dep, deps) => {
|
|
29
|
+
let edges = [];
|
|
30
|
+
const depRows = deps.filter(line => {
|
|
31
|
+
return line.startsWith(dep);
|
|
32
|
+
});
|
|
33
|
+
depRows.forEach(dep => {
|
|
34
|
+
const edgeName = dep.split(' ')[1];
|
|
35
|
+
edges.push(edgeName);
|
|
36
|
+
});
|
|
37
|
+
return edges;
|
|
38
|
+
};
|
|
39
|
+
const createRootNodes = deps => {
|
|
40
|
+
let rootDep = {};
|
|
41
|
+
const rootDeps = getRootDeps(deps);
|
|
42
|
+
const edges = rootDeps.map(dep => {
|
|
43
|
+
return dep.split(' ')[1];
|
|
44
|
+
});
|
|
45
|
+
rootDep[rootDeps[0].split(' ')[0]] = {};
|
|
46
|
+
edges.forEach(edge => {
|
|
47
|
+
const splitEdge = edge.split('@');
|
|
48
|
+
const splitGroupName = splitEdge[0].split('/');
|
|
49
|
+
const name = splitGroupName.pop();
|
|
50
|
+
const lastSlash = splitEdge[0].lastIndexOf('/');
|
|
51
|
+
let group = splitEdge[0].substring(0, lastSlash);
|
|
52
|
+
const hash = getHash(splitEdge[0]);
|
|
53
|
+
group = checkGroupExists(group, name);
|
|
54
|
+
const edgesOfDep = getAllDepsOfADepAsEdge(edge, deps);
|
|
55
|
+
rootDep[rootDeps[0].split(' ')[0]][edge] = {
|
|
56
|
+
artifactID: name,
|
|
57
|
+
group: group,
|
|
58
|
+
version: splitEdge[1],
|
|
59
|
+
scope: '"compile',
|
|
60
|
+
type: 'direct',
|
|
61
|
+
hash: hash,
|
|
62
|
+
edges: edgesOfDep
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
return rootDep;
|
|
66
|
+
};
|
|
67
|
+
const getRootDeps = deps => {
|
|
68
|
+
const rootDeps = deps.filter(dep => {
|
|
69
|
+
const parentDep = dep.split(' ')[0];
|
|
70
|
+
if (parentDep.split('@v').length === 1) {
|
|
71
|
+
return dep;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return rootDeps;
|
|
75
|
+
};
|
|
76
|
+
const getHash = library => {
|
|
77
|
+
let shaSum = crypto.createHash('sha1');
|
|
78
|
+
shaSum.update(library);
|
|
79
|
+
return shaSum.digest('hex');
|
|
80
|
+
};
|
|
81
|
+
const getDirectDepNames = deps => {
|
|
82
|
+
const directDepNames = [];
|
|
83
|
+
deps.forEach(dep => {
|
|
84
|
+
const parentDep = dep.split(' ')[0];
|
|
85
|
+
if (parentDep.split('@v').length === 1) {
|
|
86
|
+
dep.split(' ')[1] !== undefined
|
|
87
|
+
? directDepNames.push(dep.split(' ')[1])
|
|
88
|
+
: null;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return directDepNames;
|
|
92
|
+
};
|
|
93
|
+
const getAllUniqueTransitiveDepNames = (deps, directDepNames) => {
|
|
94
|
+
let uniqueDeps = [];
|
|
95
|
+
deps.forEach(dep => {
|
|
96
|
+
const parentDep = dep.split(' ')[0];
|
|
97
|
+
if (parentDep.split('@v').length !== 1) {
|
|
98
|
+
if (!directDepNames.includes(parentDep)) {
|
|
99
|
+
if (!uniqueDeps.includes(parentDep)) {
|
|
100
|
+
parentDep.length > 1 ? uniqueDeps.push(parentDep) : null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return uniqueDeps;
|
|
106
|
+
};
|
|
107
|
+
const checkGroupExists = (group, name) => {
|
|
108
|
+
if (group === null || group === '') {
|
|
109
|
+
return name;
|
|
110
|
+
}
|
|
111
|
+
return group;
|
|
112
|
+
};
|
|
113
|
+
const createTransitiveDeps = (transitiveDeps, splitLines, rootNodes) => {
|
|
114
|
+
transitiveDeps.forEach(dep => {
|
|
115
|
+
const splitEdge = dep.split('@');
|
|
116
|
+
const splitGroupName = splitEdge[0].split('/');
|
|
117
|
+
const name = splitGroupName.pop();
|
|
118
|
+
const lastSlash = splitEdge[0].lastIndexOf('/');
|
|
119
|
+
let group = splitEdge[0].substring(0, lastSlash);
|
|
120
|
+
const hash = getHash(splitEdge[0]);
|
|
121
|
+
group = checkGroupExists(group, name);
|
|
122
|
+
const transitiveDep = {
|
|
123
|
+
artifactID: name,
|
|
124
|
+
group: group,
|
|
125
|
+
version: splitEdge[1],
|
|
126
|
+
scope: 'compile',
|
|
127
|
+
type: 'transitive',
|
|
128
|
+
hash: hash,
|
|
129
|
+
edges: {}
|
|
130
|
+
};
|
|
131
|
+
const edges = getAllDepsOfADepAsEdge(dep, splitLines);
|
|
132
|
+
transitiveDep.edges = edges;
|
|
133
|
+
const edgesAsName = getAllDepsOfADepAsName(dep, splitLines);
|
|
134
|
+
edgesAsName.forEach(dep => {
|
|
135
|
+
const splitEdge = dep.split('@');
|
|
136
|
+
const splitGroupName = splitEdge[0].split('/');
|
|
137
|
+
const name = splitGroupName.pop();
|
|
138
|
+
const lastSlash = splitEdge[0].lastIndexOf('/');
|
|
139
|
+
let group = splitEdge[0].substring(0, lastSlash);
|
|
140
|
+
const hash = getHash(splitEdge[0]);
|
|
141
|
+
group = checkGroupExists(group, name);
|
|
142
|
+
const transitiveDep = {
|
|
143
|
+
artifactID: name,
|
|
144
|
+
group: group,
|
|
145
|
+
version: splitEdge[1],
|
|
146
|
+
scope: 'compile',
|
|
147
|
+
type: 'transitive',
|
|
148
|
+
hash: hash,
|
|
149
|
+
edges: {}
|
|
150
|
+
};
|
|
151
|
+
rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep;
|
|
152
|
+
});
|
|
153
|
+
rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep;
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
module.exports = {
|
|
157
|
+
parseGoDependencies
|
|
158
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const child_process = require('child_process');
|
|
3
|
+
const i18n = require('i18n');
|
|
4
|
+
const getGoDependencies = config => {
|
|
5
|
+
let cmdStdout;
|
|
6
|
+
let cwd = config.projectPath
|
|
7
|
+
? config.projectPath.replace('go.mod', '')
|
|
8
|
+
: process.cwd();
|
|
9
|
+
try {
|
|
10
|
+
cmdStdout = child_process.execSync('go mod graph', { cwd });
|
|
11
|
+
return cmdStdout.toString();
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
if (err.message === 'spawnSync /bin/sh ENOENT') {
|
|
15
|
+
err.message =
|
|
16
|
+
'\n\n*************** No transitive dependencies ***************\n\nWe are unable to build a dependency tree view from your repository as there were no transitive dependencies found.';
|
|
17
|
+
}
|
|
18
|
+
console.log(i18n.__('goReadProjectFile', cwd, `${err.message ? err.message : ''}`));
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
module.exports = {
|
|
22
|
+
getGoDependencies
|
|
23
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const child_process = require('child_process');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const i18n = require('i18n');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const MAVEN = 'maven';
|
|
7
|
+
const GRADLE = 'gradle';
|
|
8
|
+
const determineProjectTypeAndCwd = (files, projectPath) => {
|
|
9
|
+
const projectData = {};
|
|
10
|
+
if (files[0].includes('pom.xml')) {
|
|
11
|
+
projectData.projectType = MAVEN;
|
|
12
|
+
projectData.cwd = projectPath
|
|
13
|
+
? projectPath
|
|
14
|
+
: files[0].replace('pom.xml', '');
|
|
15
|
+
}
|
|
16
|
+
else if (files[0].includes('build.gradle')) {
|
|
17
|
+
projectData.projectType = GRADLE;
|
|
18
|
+
projectData.cwd = projectPath
|
|
19
|
+
? projectPath
|
|
20
|
+
: files[0].replace('pom.xml', '');
|
|
21
|
+
}
|
|
22
|
+
return projectData;
|
|
23
|
+
};
|
|
24
|
+
const buildMaven = (config, projectData, timeout) => {
|
|
25
|
+
let cmdStdout;
|
|
26
|
+
let mvn_settings = '';
|
|
27
|
+
try {
|
|
28
|
+
if (config.mavenSettingsPath) {
|
|
29
|
+
mvn_settings = ' -s ' + config.mavenSettingsPath;
|
|
30
|
+
}
|
|
31
|
+
cmdStdout = child_process.execSync('mvn dependency:tree -B' + mvn_settings, {
|
|
32
|
+
cwd: projectData.cwd,
|
|
33
|
+
timeout
|
|
34
|
+
});
|
|
35
|
+
return cmdStdout.toString();
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
throw new Error(i18n.__('mavenDependencyTreeNonZero', projectData.cwd, `${err.message}`));
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const buildGradle = (config, projectData, timeout) => {
|
|
42
|
+
let cmdStdout;
|
|
43
|
+
let output = {};
|
|
44
|
+
try {
|
|
45
|
+
if (config.subProject) {
|
|
46
|
+
cmdStdout = child_process.execSync('.' +
|
|
47
|
+
path.sep +
|
|
48
|
+
'gradlew :' +
|
|
49
|
+
config.subProject +
|
|
50
|
+
':dependencies --configuration runtimeClasspath', {
|
|
51
|
+
cwd: projectData.cwd,
|
|
52
|
+
timeout
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
cmdStdout = child_process.execSync('.' +
|
|
57
|
+
path.sep +
|
|
58
|
+
'gradlew dependencies --configuration runtimeClasspath', {
|
|
59
|
+
cwd: projectData.cwd,
|
|
60
|
+
timeout
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (cmdStdout
|
|
64
|
+
.toString()
|
|
65
|
+
.includes("runtimeClasspath - Runtime classpath of source set 'main'.\n" +
|
|
66
|
+
'No dependencies')) {
|
|
67
|
+
cmdStdout = child_process.execSync('.' + path.sep + 'gradlew dependencies', {
|
|
68
|
+
cwd: projectData.cwd,
|
|
69
|
+
timeout
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
output = cmdStdout.toString();
|
|
73
|
+
return output;
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
if (fs.existsSync(projectData.cwd + 'gradlew') ||
|
|
77
|
+
fs.existsSync(projectData.cwd + 'gradlew.bat')) {
|
|
78
|
+
throw new Error(i18n.__('gradleDependencyTreeNonZero', projectData.cwd, `${err.message}`));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
throw new Error(i18n.__('gradleWrapperUnavailable', projectData.cwd, `${err.message}`));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const getJavaBuildDeps = (config, files) => {
|
|
86
|
+
const timeout = 960000;
|
|
87
|
+
let output = {
|
|
88
|
+
mvnDependancyTreeOutput: undefined,
|
|
89
|
+
projectType: undefined
|
|
90
|
+
};
|
|
91
|
+
try {
|
|
92
|
+
const projectData = determineProjectTypeAndCwd(files, config.projectPath);
|
|
93
|
+
if (projectData.projectType === MAVEN) {
|
|
94
|
+
output.mvnDependancyTreeOutput = buildMaven(config, projectData, timeout);
|
|
95
|
+
}
|
|
96
|
+
else if (projectData.projectType === GRADLE) {
|
|
97
|
+
output.mvnDependancyTreeOutput = buildGradle(config, projectData, timeout);
|
|
98
|
+
}
|
|
99
|
+
output.projectType = projectData.projectType;
|
|
100
|
+
return output;
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
console.log(err.message.toString());
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
module.exports = {
|
|
107
|
+
getJavaBuildDeps
|
|
108
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const analysis = require('./analysis');
|
|
3
|
+
const { parseBuildDeps } = require('./javaBuildDepsParser');
|
|
4
|
+
const { createJavaTSMessage } = require('../common/formatMessage');
|
|
5
|
+
const javaAnalysis = (config, languageFiles) => {
|
|
6
|
+
languageFiles.java.forEach(file => {
|
|
7
|
+
file.replace('build.gradle.kts', 'build.gradle');
|
|
8
|
+
});
|
|
9
|
+
const javaDeps = buildJavaTree(config, languageFiles.java);
|
|
10
|
+
return createJavaTSMessage(javaDeps);
|
|
11
|
+
};
|
|
12
|
+
const buildJavaTree = (config, files) => {
|
|
13
|
+
const javaBuildDeps = analysis.getJavaBuildDeps(config, files);
|
|
14
|
+
return parseBuildDeps(config, javaBuildDeps);
|
|
15
|
+
};
|
|
16
|
+
module.exports = {
|
|
17
|
+
javaAnalysis
|
|
18
|
+
};
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const i18n = require('i18n');
|
|
3
|
+
const StringBuilder = require('string-builder');
|
|
4
|
+
let sb = new StringBuilder();
|
|
5
|
+
const parseBuildDeps = (config, input) => {
|
|
6
|
+
const { mvnDependancyTreeOutput, projectType } = input;
|
|
7
|
+
try {
|
|
8
|
+
return parseGradle(mvnDependancyTreeOutput, config, projectType);
|
|
9
|
+
}
|
|
10
|
+
catch (err) {
|
|
11
|
+
throw new Error(i18n.__('javaParseProjectFile') + `${err.message}`);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const preParser = shavedOutput => {
|
|
15
|
+
let obj = [];
|
|
16
|
+
for (let dep in shavedOutput) {
|
|
17
|
+
obj.push(shavedOutput[dep]
|
|
18
|
+
.replace('+-', '+---')
|
|
19
|
+
.replace('[INFO]', '')
|
|
20
|
+
.replace('\\-', '\\---')
|
|
21
|
+
.replace(':jar:', ':')
|
|
22
|
+
.replace(':test', '')
|
|
23
|
+
.replace(':compile', '')
|
|
24
|
+
.replace(' +', '+')
|
|
25
|
+
.replace(' |', '|')
|
|
26
|
+
.replace(' \\', '\\')
|
|
27
|
+
.replace(':runtime', ''));
|
|
28
|
+
}
|
|
29
|
+
let depTree = [];
|
|
30
|
+
for (let x in obj) {
|
|
31
|
+
let nodeLevel = computeRelationToLastElement(obj[x]);
|
|
32
|
+
let notLastLevel = obj[x].startsWith('|') ||
|
|
33
|
+
obj[x].startsWith('+') ||
|
|
34
|
+
obj[x].startsWith('\\');
|
|
35
|
+
if (notLastLevel) {
|
|
36
|
+
if (nodeLevel === 0) {
|
|
37
|
+
depTree.push(obj[x]);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
let level = computeLevel(nodeLevel);
|
|
41
|
+
let validatedLevel = addIndentation(nodeLevel === 2 ? 5 : level, obj[x]);
|
|
42
|
+
depTree.push(validatedLevel);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
let level = computeLevel(nodeLevel);
|
|
47
|
+
let validatedLevel = addIndentation(nodeLevel === 3 ? 5 : level, obj[x]);
|
|
48
|
+
depTree.push(validatedLevel);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return depTree;
|
|
52
|
+
};
|
|
53
|
+
const shaveOutput = (gradleDependencyTreeOutput, projectType) => {
|
|
54
|
+
let shavedOutput = gradleDependencyTreeOutput.split('\n');
|
|
55
|
+
if (projectType === 'maven') {
|
|
56
|
+
shavedOutput = preParser(shavedOutput);
|
|
57
|
+
}
|
|
58
|
+
let obj = [];
|
|
59
|
+
for (let key in shavedOutput) {
|
|
60
|
+
if (shavedOutput[key].includes('project :')) {
|
|
61
|
+
}
|
|
62
|
+
else if (shavedOutput[key].includes('+---') ||
|
|
63
|
+
shavedOutput[key].includes('\\---')) {
|
|
64
|
+
obj.push(shavedOutput[key]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return obj;
|
|
68
|
+
};
|
|
69
|
+
const computeIndentation = element => {
|
|
70
|
+
let hasPlus = element.includes('+');
|
|
71
|
+
let hasSlash = element.includes('\\');
|
|
72
|
+
if (hasPlus) {
|
|
73
|
+
return element.substring(element.indexOf('+'));
|
|
74
|
+
}
|
|
75
|
+
if (hasSlash) {
|
|
76
|
+
return element.substring(element.indexOf('\\'));
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const computeLevel = nodeLevel => {
|
|
80
|
+
let num = [5, 8, 11, 14, 17, 20];
|
|
81
|
+
for (let z in num) {
|
|
82
|
+
if (num[z] === nodeLevel) {
|
|
83
|
+
let n = parseInt(z);
|
|
84
|
+
return 5 * (n + 2);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const addIndentation = (number, str) => {
|
|
89
|
+
str = computeIndentation(str);
|
|
90
|
+
sb.clear();
|
|
91
|
+
for (let j = 0; j < number; j++) {
|
|
92
|
+
sb.append(' ');
|
|
93
|
+
}
|
|
94
|
+
sb.append(str);
|
|
95
|
+
return sb.toString();
|
|
96
|
+
};
|
|
97
|
+
const computeRelationToLastElement = element => {
|
|
98
|
+
let hasPlus = element.includes('+---');
|
|
99
|
+
let hasSlash = element.includes('\\---');
|
|
100
|
+
if (hasPlus) {
|
|
101
|
+
return element.split('+---')[0].length;
|
|
102
|
+
}
|
|
103
|
+
if (hasSlash) {
|
|
104
|
+
return element.split('\\---')[0].length;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const stripElement = element => {
|
|
108
|
+
return element
|
|
109
|
+
.replace(/[|]/g, '')
|
|
110
|
+
.replace('+---', '')
|
|
111
|
+
.replace('\\---', '')
|
|
112
|
+
.replace(/[' ']/g, '')
|
|
113
|
+
.replace('(c)', '')
|
|
114
|
+
.replace('->', '@')
|
|
115
|
+
.replace('(*)', '');
|
|
116
|
+
};
|
|
117
|
+
const checkVersion = element => {
|
|
118
|
+
let version = element.split(':');
|
|
119
|
+
return version[version.length - 1];
|
|
120
|
+
};
|
|
121
|
+
const createElement = (element, isRoot) => {
|
|
122
|
+
let tree;
|
|
123
|
+
let cleanElement = stripElement(element);
|
|
124
|
+
let splitGroupName = cleanElement.split(':');
|
|
125
|
+
let validateVersion = false;
|
|
126
|
+
if (!element.includes('->')) {
|
|
127
|
+
validateVersion = true;
|
|
128
|
+
}
|
|
129
|
+
tree = {
|
|
130
|
+
artifactID: splitGroupName[1],
|
|
131
|
+
group: splitGroupName[0],
|
|
132
|
+
version: validateVersion
|
|
133
|
+
? checkVersion(cleanElement)
|
|
134
|
+
: splitGroupName[splitGroupName.length - 1],
|
|
135
|
+
scope: 'compile',
|
|
136
|
+
type: isRoot ? 'direct' : 'transitive',
|
|
137
|
+
edges: {}
|
|
138
|
+
};
|
|
139
|
+
return tree;
|
|
140
|
+
};
|
|
141
|
+
const getElementHeader = element => {
|
|
142
|
+
let elementHeader = stripElement(element);
|
|
143
|
+
elementHeader = elementHeader.replace(':', '/');
|
|
144
|
+
elementHeader = elementHeader.replace(':', '@');
|
|
145
|
+
return elementHeader;
|
|
146
|
+
};
|
|
147
|
+
const buildElement = (element, rootElement, parentOfCurrent, tree, isRoot) => {
|
|
148
|
+
let childElement = createElement(element, isRoot);
|
|
149
|
+
let elementHeader = getElementHeader(element);
|
|
150
|
+
let levelsArray = [rootElement, parentOfCurrent];
|
|
151
|
+
const treeNode = getNestedObject(tree, levelsArray);
|
|
152
|
+
const rootNode = getNestedObject(tree, [rootElement]);
|
|
153
|
+
if (!rootNode.hasOwnProperty(elementHeader)) {
|
|
154
|
+
tree[rootElement][elementHeader] = childElement;
|
|
155
|
+
}
|
|
156
|
+
treeNode.edges[elementHeader] = elementHeader;
|
|
157
|
+
};
|
|
158
|
+
const hasChildren = (nextNodeLevel, nodeLevel) => {
|
|
159
|
+
if (nextNodeLevel > nodeLevel) {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
const lastChild = (nextNodeLevel, nodeLevel) => {
|
|
164
|
+
if (nextNodeLevel < nodeLevel) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const calculateLevels = (nextNodeLevel, nodeLevel) => {
|
|
169
|
+
return (nodeLevel - nextNodeLevel) / 5;
|
|
170
|
+
};
|
|
171
|
+
const buildTree = shavedOutput => {
|
|
172
|
+
let tree = {};
|
|
173
|
+
let rootElement;
|
|
174
|
+
let levelNodes = [];
|
|
175
|
+
shavedOutput.forEach((element, index) => {
|
|
176
|
+
if (index === 0) {
|
|
177
|
+
let cleanElement = stripElement(element);
|
|
178
|
+
let elementHeader = getElementHeader(cleanElement);
|
|
179
|
+
let splitElement = element.split(' ');
|
|
180
|
+
let splitGroupName = splitElement[1].split(':');
|
|
181
|
+
let validateVersion = false;
|
|
182
|
+
if (!element.includes('->')) {
|
|
183
|
+
validateVersion = true;
|
|
184
|
+
}
|
|
185
|
+
tree[splitGroupName[0]] = {};
|
|
186
|
+
tree[splitGroupName[0]][elementHeader] = {
|
|
187
|
+
artifactID: splitGroupName[1],
|
|
188
|
+
group: splitGroupName[0],
|
|
189
|
+
version: validateVersion
|
|
190
|
+
? checkVersion(cleanElement)
|
|
191
|
+
: splitElement[splitElement.length - 1],
|
|
192
|
+
scope: 'compile',
|
|
193
|
+
type: 'direct',
|
|
194
|
+
edges: {}
|
|
195
|
+
};
|
|
196
|
+
rootElement = splitGroupName[0];
|
|
197
|
+
levelNodes.push(elementHeader);
|
|
198
|
+
}
|
|
199
|
+
if (shavedOutput.length - 1 === index) {
|
|
200
|
+
const parentOfCurrent = levelNodes[levelNodes.length - 1];
|
|
201
|
+
let nodeLevel = computeRelationToLastElement(element);
|
|
202
|
+
let validateVersion = false;
|
|
203
|
+
if (!element.includes('->')) {
|
|
204
|
+
validateVersion = true;
|
|
205
|
+
}
|
|
206
|
+
if (nodeLevel === 0) {
|
|
207
|
+
let cleanElement = stripElement(element);
|
|
208
|
+
let elementHeader = getElementHeader(cleanElement);
|
|
209
|
+
let splitElement = element.split(' ');
|
|
210
|
+
let splitGroupName = splitElement[1].split(':');
|
|
211
|
+
tree[rootElement][elementHeader] = {
|
|
212
|
+
artifactID: splitGroupName[1],
|
|
213
|
+
group: splitGroupName[0],
|
|
214
|
+
version: validateVersion
|
|
215
|
+
? checkVersion(cleanElement)
|
|
216
|
+
: splitElement[splitElement.length - 1],
|
|
217
|
+
scope: 'compile',
|
|
218
|
+
type: 'direct',
|
|
219
|
+
edges: {}
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
buildElement(element, rootElement, parentOfCurrent, tree);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (index >= 1 && index < shavedOutput.length - 1) {
|
|
227
|
+
let nodeLevel = computeRelationToLastElement(element);
|
|
228
|
+
let nextNodeLevel = computeRelationToLastElement(shavedOutput[index + 1]);
|
|
229
|
+
const parentOfCurrent = levelNodes[levelNodes.length - 1];
|
|
230
|
+
let isRoot = false;
|
|
231
|
+
if (nodeLevel === 0) {
|
|
232
|
+
isRoot = true;
|
|
233
|
+
}
|
|
234
|
+
if (isRoot) {
|
|
235
|
+
let cleanElement = stripElement(element);
|
|
236
|
+
let elementHeader = getElementHeader(cleanElement);
|
|
237
|
+
let splitElement = element.split(' ');
|
|
238
|
+
let splitGroupName = splitElement[1].split(':');
|
|
239
|
+
let validateVersion = false;
|
|
240
|
+
if (!element.includes('->')) {
|
|
241
|
+
validateVersion = true;
|
|
242
|
+
}
|
|
243
|
+
tree[rootElement][elementHeader] = {
|
|
244
|
+
artifactID: splitGroupName[1],
|
|
245
|
+
group: splitGroupName[0],
|
|
246
|
+
version: validateVersion
|
|
247
|
+
? checkVersion(cleanElement)
|
|
248
|
+
: splitElement[splitElement.length - 1],
|
|
249
|
+
scope: 'compile',
|
|
250
|
+
type: 'direct',
|
|
251
|
+
edges: {}
|
|
252
|
+
};
|
|
253
|
+
levelNodes.push(elementHeader);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
let elementHeader = getElementHeader(element);
|
|
257
|
+
buildElement(element, rootElement, parentOfCurrent, tree, isRoot);
|
|
258
|
+
if (hasChildren(nextNodeLevel, nodeLevel)) {
|
|
259
|
+
buildElement(element, rootElement, parentOfCurrent, tree, isRoot);
|
|
260
|
+
levelNodes.push(elementHeader);
|
|
261
|
+
}
|
|
262
|
+
if (lastChild(nextNodeLevel, nodeLevel)) {
|
|
263
|
+
let levelDifference = calculateLevels(nextNodeLevel, nodeLevel);
|
|
264
|
+
if (levelDifference === 0) {
|
|
265
|
+
levelNodes.pop();
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
let i;
|
|
269
|
+
for (i = 0; i < levelDifference; i++) {
|
|
270
|
+
levelNodes.pop();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
return tree;
|
|
277
|
+
};
|
|
278
|
+
const getNestedObject = (nestedObj, pathArr) => {
|
|
279
|
+
return pathArr.reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), nestedObj);
|
|
280
|
+
};
|
|
281
|
+
const parseSubProject = shavedOutput => {
|
|
282
|
+
let obj = [];
|
|
283
|
+
for (let key in shavedOutput) {
|
|
284
|
+
if (!shavedOutput[key].includes('project')) {
|
|
285
|
+
obj.push(shavedOutput[key]);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return obj;
|
|
289
|
+
};
|
|
290
|
+
const validateIndentation = shavedOutput => {
|
|
291
|
+
let validatedTree = [];
|
|
292
|
+
shavedOutput.forEach((element, index) => {
|
|
293
|
+
let nextNodeLevel;
|
|
294
|
+
let nodeLevel = computeRelationToLastElement(element);
|
|
295
|
+
if (shavedOutput[index + 1] !== undefined) {
|
|
296
|
+
nextNodeLevel = computeRelationToLastElement(shavedOutput[index + 1]);
|
|
297
|
+
}
|
|
298
|
+
if (index === 0) {
|
|
299
|
+
validatedTree.push(shavedOutput[index]);
|
|
300
|
+
validatedTree.push(shavedOutput[index + 1]);
|
|
301
|
+
}
|
|
302
|
+
else if (nextNodeLevel > nodeLevel + 5) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
validatedTree.push(shavedOutput[index + 1]);
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
validatedTree.pop();
|
|
310
|
+
return validatedTree;
|
|
311
|
+
};
|
|
312
|
+
const parseGradle = (gradleDependencyTreeOutput, config, projectType) => {
|
|
313
|
+
let shavedOutput = shaveOutput(gradleDependencyTreeOutput, projectType);
|
|
314
|
+
if (config.subProject) {
|
|
315
|
+
let subProject = parseSubProject(shavedOutput);
|
|
316
|
+
let validatedOutput = validateIndentation(subProject);
|
|
317
|
+
return buildTree(validatedOutput);
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
let validatedOutput = validateIndentation(shavedOutput);
|
|
321
|
+
return buildTree(validatedOutput);
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
module.exports = {
|
|
325
|
+
parseBuildDeps,
|
|
326
|
+
shaveOutput,
|
|
327
|
+
validateIndentation,
|
|
328
|
+
calculateLevels,
|
|
329
|
+
lastChild,
|
|
330
|
+
hasChildren,
|
|
331
|
+
getElementHeader,
|
|
332
|
+
createElement,
|
|
333
|
+
stripElement,
|
|
334
|
+
checkVersion,
|
|
335
|
+
computeRelationToLastElement,
|
|
336
|
+
addIndentation,
|
|
337
|
+
computeLevel,
|
|
338
|
+
computeIndentation
|
|
339
|
+
};
|