Skip to content

Commit 6465666

Browse files
committed
try add semaphore
1 parent b0a9363 commit 6465666

File tree

3 files changed

+65
-43
lines changed

3 files changed

+65
-43
lines changed

package-lock.json

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
],
1111
"dependencies": {
1212
"adm-zip": "^0.5.16",
13+
"async-mutex": "^0.5.0",
1314
"axios": "^1.7.7",
1415
"log4js": "^6.9.1",
1516
"node-fetch": "^3.3.2",

src/main/osinstaller/CxInstaller.ts

Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import * as fs from 'fs/promises';
2-
import * as fs1 from "fs"
2+
import * as fs1 from 'fs';
33
import * as path from 'path';
44
import * as tar from 'tar';
55
import axios from 'axios';
6-
import * as unzipper from "unzipper";
7-
6+
import * as unzipper from 'unzipper';
7+
import { Semaphore } from 'async-mutex';
88

99
export class CxInstaller {
1010
private readonly platform: string;
1111
private cliVersion: string;
1212
private readonly resourceDirPath: string;
13+
private static installSemaphore = new Semaphore(1); // Semaphore with 1 slot
1314

1415
constructor(platform: string) {
1516
this.platform = platform;
@@ -41,7 +42,7 @@ export class CxInstaller {
4142

4243
return `https://download.checkmarx.com/CxOne/CLI/${cliVersion}/ast-cli_${cliVersion}_${platformString}_x64.${archiveExtension}`;
4344
}
44-
45+
4546
getExecutablePath(): string {
4647
let executablePath;
4748
if (this.platform === 'win32') {
@@ -53,33 +54,39 @@ export class CxInstaller {
5354
}
5455

5556
async downloadIfNotInstalledCLI() {
56-
if (!this.checkExecutableExists()) {
57+
// Acquire the semaphore, ensuring only one installation happens at a time
58+
const [_, release] = await CxInstaller.installSemaphore.acquire();
59+
try {
60+
if (this.checkExecutableExists()) {
61+
console.log('Executable already installed.');
62+
return;
63+
}
64+
5765
const url = await this.getDownloadURL();
5866
const zipPath = this.getZipPath();
59-
try {
60-
await this.downloadFile(url, zipPath);
61-
console.log('Downloaded CLI to:', zipPath);
62-
63-
await this.extractArchive(zipPath, this.resourceDirPath);
64-
console.log('Extracted CLI to:', this.resourceDirPath);
65-
console.log('Done!');
66-
} catch (error) {
67-
console.error('Error:', error);
68-
}
67+
68+
await this.downloadFile(url, zipPath);
69+
console.log('Downloaded CLI to:', zipPath);
70+
71+
await this.extractArchive(zipPath, this.resourceDirPath);
72+
console.log('Extracted CLI to:', this.resourceDirPath);
73+
} catch (error) {
74+
console.error('Error during installation:', error);
75+
} finally {
76+
// Release the semaphore lock to allow the next waiting process to continue
77+
release(); // Call the release function
6978
}
7079
}
7180

7281
async extractArchive(zipPath: string, extractPath: string): Promise<void> {
7382
if (zipPath.endsWith('.zip')) {
7483
console.log('Extracting ZIP file...');
75-
// Use unzipper to extract ZIP files
7684
await unzipper.Open.file(zipPath)
77-
.then(d => d.extract({path: extractPath}));
85+
.then(d => d.extract({ path: extractPath }));
7886
console.log('Extracted ZIP file to:', extractPath);
7987
} else if (zipPath.endsWith('.tar.gz')) {
8088
console.log('Extracting TAR.GZ file...');
81-
// Use tar.extract to extract TAR.GZ files
82-
await tar.extract({file: zipPath, cwd: extractPath});
89+
await tar.extract({ file: zipPath, cwd: extractPath });
8390
console.log('Extracted TAR.GZ file to:', extractPath);
8491
} else {
8592
console.error('Unsupported file type. Only .zip and .tar.gz are supported.');
@@ -89,52 +96,35 @@ export class CxInstaller {
8996
async downloadFile(url: string, outputPath: string) {
9097
console.log('Downloading file from:', url);
9198
const writer = fs1.createWriteStream(outputPath);
92-
console.log('Downloading file to:', outputPath);
93-
const response = await axios({url, responseType: 'stream'});
94-
console.log('Downloading file...');
99+
const response = await axios({ url, responseType: 'stream' });
95100
response.data.pipe(writer);
96-
console.log('Downloaded file');
101+
97102
return new Promise((resolve, reject) => {
98103
writer.on('finish', resolve);
99104
writer.on('error', reject);
100105
});
101106
}
102107

103108
getZipPath(): string {
104-
let executablePath;
105-
if (this.platform === 'win32') {
106-
executablePath = path.join(this.resourceDirPath, 'cx.zip');
107-
} else {
108-
executablePath = path.join(this.resourceDirPath, 'cx.tar.gz');
109-
}
110-
console.log('Zip path:', executablePath)
111-
return executablePath;
109+
return this.platform === 'win32'
110+
? path.join(this.resourceDirPath, 'cx.zip')
111+
: path.join(this.resourceDirPath, 'cx.tar.gz');
112112
}
113113

114114
checkExecutableExists(): boolean {
115-
if (fs1.existsSync(this.getExecutablePath())){
116-
console.log('Executable exists:', this.getExecutablePath());
117-
return true;
118-
} else {
119-
return false;
120-
}
115+
return fs1.existsSync(this.getExecutablePath());
121116
}
122117

123-
// Method to read the AST CLI version from the file
124118
async readASTCLIVersion(): Promise<string> {
125119
if (this.cliVersion) {
126120
return this.cliVersion;
127121
}
128122
try {
129-
console.log('Reading AST CLI version...');
130123
const versionFilePath = path.join(process.cwd(), 'checkmarx-ast-cli.version');
131124
const versionContent = await fs.readFile(versionFilePath, 'utf-8');
132-
console.log('AST CLI version:', versionContent.trim());
133125
return versionContent.trim();
134126
} catch (error) {
135-
console.error('Error reading AST CLI version:', error);
136-
throw error;
127+
throw new Error('Error reading AST CLI version: ' + error.message);
137128
}
138129
}
139130
}
140-

0 commit comments

Comments
 (0)