Skip to content

Commit 9332311

Browse files
committed
Improve extractor script comments and file paths
Adds comments in index-files.js to better reflect the documented intentions from the old version of index-files.sh script. Better explains the script magic, in places. Attempts to make the index-files.js (JavaScript) script more useful as a multi-platform solution by normalizing file paths using the path.join() function.
1 parent c9e02ed commit 9332311

File tree

5 files changed

+3646
-13
lines changed

5 files changed

+3646
-13
lines changed

extractors/cds/tools/index-files.cmd

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ if %ERRORLEVEL% neq 0 (
1818
)
1919

2020
set "_response_file_path=%~1"
21+
set "_script_dir=%~dp0"
2122

2223
echo Checking response file for CDS files to index
2324

@@ -26,8 +27,12 @@ if not exist "%_response_file_path%" (
2627
exit /b 0
2728
)
2829

29-
echo Installing node package dependencies and running the 'index-files.js' script
30+
REM Change to the directory of this script to ensure that npm looks up
31+
REM the package.json file in the correct directory and installs the
32+
REM dependencies (i.e. node_modules) relative to this directory.
33+
cd /d "%_script_dir%" && ^
34+
echo Installing node package dependencies and running the 'index-files.js' script && ^
3035
npm install --quiet --no-audit --no-fund --no-package-json && ^
31-
node "%~dp0index-files.js" "%_response_file_path%"
36+
node "%_script_dir%index-files.js" "%_response_file_path%"
3237

3338
exit /b %ERRORLEVEL%

extractors/cds/tools/index-files.js

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,57 @@
1-
const { existsSync, readFileSync, statSync } = require('fs');
21
const { execSync, spawnSync } = require('child_process');
2+
const { existsSync, readFileSync, statSync } = require('fs');
3+
const { arch, platform } = require('os');
34
const { dirname, join, resolve } = require('path');
45

56
console.log('Indexing CDS files');
67

78
const responseFile = process.argv[2];
89

10+
const osPlatform = platform();
11+
const osPlatformArch = arch();
12+
console.log(`Detected OS platform=${osPlatform} : arch=${osPlatformArch}`);
13+
const autobuildScriptName = osPlatform === 'win32' ? 'autobuild.cmd' : 'autobuild.sh';
14+
const codeqlExe = osPlatform === 'win32' ? 'codeql.exe' : 'codeql';
15+
const codeqlExePath = join(process.env.CODEQL_DIST, codeqlExe);
916
const npmInstallCmdWithArgs = 'npm install --quiet --no-audit --no-fund --no-package-lock';
1017

18+
// If the response file does not exist, terminate.
1119
if (!existsSync(responseFile)) {
1220
console.log(`'codeql database index-files --language cds' terminated early as response file '${responseFile}' does not exist. This is because no CDS files were selected or found.`);
1321
process.exit(0);
1422
}
1523

16-
if (statSync(responseFile).size === 0) {
24+
const responseFiles = readFileSync(responseFile, 'utf-8').split('\n').filter(Boolean);
25+
// If the response file is empty, terminate.
26+
if (statSync(responseFile).size === 0 || !responseFiles) {
1727
console.log(`'codeql database index-files --language cds' terminated early as response file '${responseFile}' is empty. This is because no CDS files were selected or found.`);
1828
process.exit(0);
1929
}
2030

31+
// Determine if we have the cds commands available. If not, install the cds develpment kit
32+
// (cds-dk) in the appropriate directories and use npx to run the cds command from there.
2133
let cdsCommand = 'cds';
2234
try {
2335
execSync('cds --version', { stdio: 'ignore' });
2436
} catch {
2537
console.log('Pre-installing cds compiler');
26-
const responseFiles = readFileSync(responseFile, 'utf-8').split('\n').filter(Boolean);
27-
const packageJsonDirs = new Set();
2838

39+
/**
40+
* Find all the directories containing a package.json with a dependency on `@sap/cds`,
41+
* where the directory contains at least one of the files listed in the response file
42+
* (e.g. the cds files we want to extract).
43+
*
44+
* We then install the CDS development kit (`@sap/cds-dk`) in each directory, which
45+
* makes the `cds` command usable from the npx command within that directory.
46+
*
47+
* Nested package.json files simply cause the package to be installed in the parent
48+
* node_modules directory.
49+
*
50+
* TODO : fix implementation or change ^comment^ to reflect the actual implementation.
51+
*
52+
* We also ensure we skip node_modules, as we can end up in a recursive loop.
53+
*/
54+
const packageJsonDirs = new Set();
2955
responseFiles.forEach(file => {
3056
let dir = dirname(file);
3157
while (dir !== resolve(dir, '..')) {
@@ -43,12 +69,20 @@ try {
4369
execSync(npmInstallCmdWithArgs, { cwd: dir });
4470
});
4571

72+
/**
73+
* Use the `npx` command to dynamically install the CDS development kit (`@sap/cds-dk`)
74+
* package if necessary, which then provides the `cds` command line tool in directories
75+
* which are not covered by the package.json install command approach above.
76+
*/
4677
cdsCommand = 'npx -y --package @sap/cds-dk cds';
4778
}
4879

4980
console.log('Processing CDS files to JSON');
5081

51-
const responseFiles = readFileSync(responseFile, 'utf-8').split('\n').filter(Boolean);
82+
/**
83+
* Run the cds compile command on each file in the response files list, outputting the
84+
* compiled JSON to a file with the same name but with a .json extension appended.
85+
*/
5286
responseFiles.forEach(cdsFile => {
5387
const cdsJsonFile = `${cdsFile}.json`;
5488
console.log(`Processing CDS file ${cdsFile} to: ${cdsJsonFile}`);
@@ -57,12 +91,17 @@ responseFiles.forEach(cdsFile => {
5791
const stderrTruncated = result.stderr.toString().split('\n').filter(line => line.startsWith('[ERROR]')).slice(-4).join('\n');
5892
const errorMessage = `Could not compile the file ${cdsFile}.\nReported error(s):\n\`\`\`\n${stderrTruncated}\n\`\`\``;
5993
console.log(errorMessage);
60-
execSync(`${process.env.CODEQL_DIST}/codeql database add-diagnostic --extractor-name cds --ready-for-status-page --source-id cds/compilation-failure --source-name "Failure to compile one or more SAP CAP CDS files" --severity error --markdown-message "${errorMessage}" --file-path "${cdsFile}" "${process.env.CODEQL_EXTRACTOR_CDS_WIP_DATABASE}"`);
94+
execSync(`${codeqlExePath} database add-diagnostic --extractor-name cds --ready-for-status-page --source-id=cds/compilation-failure --source-name="Failure to compile one or more SAP CAP CDS files" --severity=error --markdown-message="${errorMessage}" --file-path="${cdsFile}" -- "${process.env.CODEQL_EXTRACTOR_CDS_WIP_DATABASE}"`);
6195
}
6296
});
6397

98+
// Check if the (JavaScript) JS extractor variables are set, and set them if not.
6499
if (!process.env.CODEQL_EXTRACTOR_JAVASCRIPT_ROOT) {
65-
process.env.CODEQL_EXTRACTOR_JAVASCRIPT_ROOT = execSync(`${process.env.CODEQL_DIST}/codeql resolve extractor --language=javascript`).toString().trim();
100+
// Find the JS extractor location.
101+
process.env.CODEQL_EXTRACTOR_JAVASCRIPT_ROOT = execSync(`${codeqlExePath} resolve extractor --language=javascript`).toString().trim();
102+
// Set the JAVASCRIPT extractor environment variables to the same as the CDS
103+
// extractor environment variables so that the JS extractor will write to the
104+
// CDS database.
66105
process.env.CODEQL_EXTRACTOR_JAVASCRIPT_WIP_DATABASE = process.env.CODEQL_EXTRACTOR_CDS_WIP_DATABASE;
67106
process.env.CODEQL_EXTRACTOR_JAVASCRIPT_DIAGNOSTIC_DIR = process.env.CODEQL_EXTRACTOR_CDS_DIAGNOSTIC_DIR;
68107
process.env.CODEQL_EXTRACTOR_JAVASCRIPT_LOG_DIR = process.env.CODEQL_EXTRACTOR_CDS_LOG_DIR;
@@ -72,17 +111,47 @@ if (!process.env.CODEQL_EXTRACTOR_JAVASCRIPT_ROOT) {
72111
}
73112

74113
let excludeFilters = '';
114+
/**
115+
* Check if LGTM_INDEX_FILTERS is already set. This tyically happens if either
116+
* "paths" and/or "paths-ignore" is set in the lgtm.yml file.
117+
*/
75118
if (process.env.LGTM_INDEX_FILTERS) {
76119
console.log(`Found $LGTM_INDEX_FILTERS already set to:\n${process.env.LGTM_INDEX_FILTERS}`);
77-
excludeFilters = '\n' + process.env.LGTM_INDEX_FILTERS.split('\n').filter(line => line.startsWith('exclude') && !['exclude:**/*', 'exclude:**/*.*'].includes(line)).join('\n');
120+
const allowedExcludePatterns = [
121+
join('exclude:**', '*'),
122+
join('exclude:**', '*.*'),
123+
];
124+
/**
125+
* If it is set, we will try to honor the paths-ignore filter.
126+
*
127+
* Split by `\n` and find all the entries that start with exclude, with some
128+
* exclusions allowed for supported glob patterns, and then join them back
129+
* together with `\n`.
130+
*/
131+
excludeFilters = '\n' + process.env.LGTM_INDEX_FILTERS
132+
.split('\n')
133+
.filter(line =>
134+
line.startsWith('exclude')
135+
&&
136+
!allowedExcludePatterns.includes(line)
137+
).join('\n');
78138
}
79139

80-
process.env.LGTM_INDEX_FILTERS = `exclude:**/*.*\ninclude:**/*.cds.json\ninclude:**/*.cds\nexclude:**/node_modules/**/*.*${excludeFilters}`;
140+
// Enable extraction of the .cds.json files only.
141+
const lgtmIndexFiltersPatterns = join(
142+
'exclude:**', '*.*\ninclude:**', '*.cds.json\ninclude:**', '*.cds\nexclude:**', 'node_modules', '**', '*.*'
143+
);
144+
process.env.LGTM_INDEX_FILTERS = `${lgtmIndexFiltersPatterns}${excludeFilters}`;
81145
console.log(`Setting $LGTM_INDEX_FILTERS to:\n${process.env.LGTM_INDEX_FILTERS}`);
82146
process.env.LGTM_INDEX_TYPESCRIPT = 'NONE';
147+
// Configure to copy over the .cds files as well, by pretending they are JSON.
83148
process.env.LGTM_INDEX_FILETYPES = '.cds:JSON';
149+
// Ignore the LGTM_INDEX_INCLUDE variable for this purpose as it may explicitly
150+
// refer to .js or .ts files.
84151
delete process.env.LGTM_INDEX_INCLUDE;
85152

86153
console.log('Extracting the cds.json files');
87154

88-
execSync(`${process.env.CODEQL_EXTRACTOR_JAVASCRIPT_ROOT}/tools/autobuild.sh`, { stdio: 'inherit' });
155+
// Invoke the JS autobuilder to index the .cds.json files only.
156+
const autobuildScriptPath = join(process.env.CODEQL_EXTRACTOR_JAVASCRIPT_ROOT, 'tools', autobuildScriptName);
157+
execSync(autobuildScriptPath, { stdio: 'inherit' });

extractors/cds/tools/index-files.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ then
2121
fi
2222

2323
_response_file_path="$1"
24+
_script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
2425

2526
echo "Checking response file for CDS files to index"
2627

@@ -35,6 +36,11 @@ then
3536
exit 0
3637
fi
3738

38-
echo "Installing node package dependencies and running the 'index-files.js' script"
39+
# Change to the directory of this script to ensure that npm looks up
40+
# the package.json file in the correct directory and installs the
41+
# dependencies (i.e. node_modules) relative to this directory.
42+
cd "$_script_dir" && \
43+
echo "Installing node package dependencies" && \
3944
npm install --quiet --no-audit --no-fund --no-package-json && \
45+
echo "Running the 'index-files.js' script" && \
4046
node "$(dirname "$0")/index-files.js" "$_response_file_path"

0 commit comments

Comments
 (0)