From 468e2cc938e2fec567dcb7d242dc31a89125710b Mon Sep 17 00:00:00 2001 From: Abdelrahman Shawki Hassan Date: Fri, 6 Dec 2024 16:55:39 +0100 Subject: [PATCH 01/10] fix: use xdg dir as default cli Path --- src/snyk/cli/cliExecutable.ts | 31 +++++++++--- .../common/configuration/configuration.ts | 8 +-- src/snyk/common/download/downloader.ts | 5 +- .../common/languageServer/languageServer.ts | 6 +-- src/snyk/common/languageServer/middleware.ts | 1 - src/snyk/common/languageServer/settings.ts | 4 +- src/snyk/common/services/downloadService.ts | 6 +-- src/test/unit/cli/cliExecutable.test.ts | 49 ++++++++++++------- src/test/unit/common/configuration.test.ts | 2 +- .../common/languageServer/middleware.test.ts | 2 +- .../common/languageServer/settings.test.ts | 1 - 11 files changed, 65 insertions(+), 50 deletions(-) diff --git a/src/snyk/cli/cliExecutable.ts b/src/snyk/cli/cliExecutable.ts index b87d4e78c..dc3d18b51 100644 --- a/src/snyk/cli/cliExecutable.ts +++ b/src/snyk/cli/cliExecutable.ts @@ -5,6 +5,22 @@ import { Checksum } from './checksum'; import { Platform } from '../common/platform'; export class CliExecutable { + public static defaultPaths: Record = { + linux: process.env.XDG_DATA_HOME ?? '/.local/share/', + // eslint-disable-next-line camelcase + linux_arm64: process.env.XDG_DATA_HOME ?? '/.local/share/', + // eslint-disable-next-line camelcase + linux_alpine: process.env.XDG_DATA_HOME ?? '/.local/share/', + // eslint-disable-next-line camelcase + linux_alpine_arm64: process.env.XDG_DATA_HOME ?? '/.local/share/', + macos: process.env.XDG_DATA_HOME ?? '/Library/Application Support/', + // eslint-disable-next-line camelcase + macos_arm64: process.env.XDG_DATA_HOME ?? '/Library/Application Support/', + windows: process.env.XDG_DATA_HOME ?? '\\AppData\\Local\\', + // eslint-disable-next-line camelcase + windows_arm64: process.env.XDG_DATA_HOME ?? '\\AppData\\Local\\', + }; + public static filenameSuffixes: Record = { linux: 'snyk-linux', // eslint-disable-next-line camelcase @@ -20,16 +36,19 @@ export class CliExecutable { // eslint-disable-next-line camelcase windows_arm64: 'snyk-win.exe', }; - constructor(public readonly version: string, public readonly checksum: Checksum) {} - static async getPath(extensionDir: string, customPath?: string): Promise { + constructor(public readonly version: string, public readonly checksum: Checksum) { } + + static async getPath(customPath?: string): Promise { if (customPath) { return customPath; } - const platform = await CliExecutable.getCurrentWithArch(); + const homeDir = Platform.getHomeDir(); + const defaultPath = this.defaultPaths[platform]; const fileName = CliExecutable.getFileName(platform); - return path.join(extensionDir, fileName); + const cliDir = path.join(homeDir, defaultPath, 'snyk', 'vscode-cli'); + return path.join(cliDir, fileName); } static getFileName(platform: CliSupportedPlatform): string { @@ -67,9 +86,9 @@ export class CliExecutable { return platform; } - static async exists(extensionDir: string, customPath?: string): Promise { + static async exists(customPath?: string): Promise { return fs - .access(await CliExecutable.getPath(extensionDir, customPath)) + .access(await CliExecutable.getPath(customPath)) .then(() => true) .catch(() => false); } diff --git a/src/snyk/common/configuration/configuration.ts b/src/snyk/common/configuration/configuration.ts index 51065a7f3..de082b13b 100644 --- a/src/snyk/common/configuration/configuration.ts +++ b/src/snyk/common/configuration/configuration.ts @@ -122,7 +122,7 @@ export interface IConfiguration { isAutomaticDependencyManagementEnabled(): boolean; - getCliPath(): Promise; + getCliPath(): Promise; getCliReleaseChannel(): Promise; getCliBaseDownloadUrl(): string; getInsecure(): boolean; @@ -352,7 +352,7 @@ export class Configuration implements IConfiguration { async setCliPath(cliPath: string | undefined): Promise { if (!cliPath) { - cliPath = await CliExecutable.getPath(extensionContext.extensionPath); + cliPath = await CliExecutable.getPath(); } return this.workspace.updateConfiguration( CONFIGURATION_IDENTIFIER, @@ -555,7 +555,7 @@ export class Configuration implements IConfiguration { ); } - async getCliPath(): Promise { + async getCliPath(): Promise { let cliPath = this.workspace.getConfiguration( CONFIGURATION_IDENTIFIER, this.getConfigName(ADVANCED_CLI_PATH), @@ -574,7 +574,7 @@ export class Configuration implements IConfiguration { const isAutomaticDependencyManagementEnabled = this.isAutomaticDependencyManagementEnabled(); const snykLsPath = this.getSnykLanguageServerPath(); if (!isAutomaticDependencyManagementEnabled && snykLsPath) return snykLsPath; - const defaultPath = await CliExecutable.getPath(extensionContext.extensionPath); + const defaultPath = await CliExecutable.getPath(); return defaultPath; } getTrustedFolders(): string[] { diff --git a/src/snyk/common/download/downloader.ts b/src/snyk/common/download/downloader.ts index 8ab54f425..4281508c3 100644 --- a/src/snyk/common/download/downloader.ts +++ b/src/snyk/common/download/downloader.ts @@ -43,10 +43,7 @@ export class Downloader { } private async getCliExecutable(platform: CliSupportedPlatform): Promise { - const cliPath = await CliExecutable.getPath( - this.extensionContext.extensionPath, - await this.configuration.getCliPath(), - ); + const cliPath = await this.configuration.getCliPath(); if (await this.binaryExists(cliPath)) { await this.deleteFileAtPath(cliPath); } diff --git a/src/snyk/common/languageServer/languageServer.ts b/src/snyk/common/languageServer/languageServer.ts index 2dc10243b..3cfa6d2dc 100644 --- a/src/snyk/common/languageServer/languageServer.ts +++ b/src/snyk/common/languageServer/languageServer.ts @@ -78,10 +78,7 @@ export class LanguageServer implements ILanguageServer { }; } - const cliBinaryPath = await CliExecutable.getPath( - this.extensionContext.extensionPath, - await this.configuration.getCliPath(), - ); + const cliBinaryPath = await this.configuration.getCliPath(); // log level is set to info by default let logLevel = 'info'; @@ -167,7 +164,6 @@ export class LanguageServer implements ILanguageServer { const settings = await LanguageServerSettings.fromConfiguration( this.configuration, this.user, - this.extensionContext, ); return settings; } diff --git a/src/snyk/common/languageServer/middleware.ts b/src/snyk/common/languageServer/middleware.ts index 8f6d4fe41..02ed80453 100644 --- a/src/snyk/common/languageServer/middleware.ts +++ b/src/snyk/common/languageServer/middleware.ts @@ -44,7 +44,6 @@ export class LanguageClientMiddleware implements Middleware { const serverSettings = await LanguageServerSettings.fromConfiguration( this.configuration, this.user, - this.extensionContext, ); return [serverSettings]; }, diff --git a/src/snyk/common/languageServer/settings.ts b/src/snyk/common/languageServer/settings.ts index 54a3be767..80fcdda1c 100644 --- a/src/snyk/common/languageServer/settings.ts +++ b/src/snyk/common/languageServer/settings.ts @@ -3,7 +3,6 @@ import { CLI_INTEGRATION_NAME } from '../../cli/contants/integration'; import { Configuration, FolderConfig, IConfiguration, SeverityFilter } from '../configuration/configuration'; import { User } from '../user'; import { PROTOCOL_VERSION } from '../constants/languageServer'; -import { CliExecutable } from '../../cli/cliExecutable'; import { ExtensionContext } from '../vscode/extensionContext'; export type ServerSettings = { @@ -53,7 +52,6 @@ export class LanguageServerSettings { static async fromConfiguration( configuration: IConfiguration, user: User, - extensionContext: ExtensionContext, ): Promise { const featuresConfiguration = configuration.getFeaturesConfiguration(); @@ -74,7 +72,7 @@ export class LanguageServerSettings { activateSnykIac: `${iacEnabled}`, enableDeltaFindings: `${configuration.getDeltaFindingsEnabled()}`, sendErrorReports: `${configuration.shouldReportErrors}`, - cliPath: await CliExecutable.getPath(extensionContext.extensionPath, await configuration.getCliPath()), + cliPath: await configuration.getCliPath(), endpoint: configuration.snykApiEndpoint, organization: configuration.organization, token: await configuration.getToken(), diff --git a/src/snyk/common/services/downloadService.ts b/src/snyk/common/services/downloadService.ts index bb7814002..c1df823bf 100644 --- a/src/snyk/common/services/downloadService.ts +++ b/src/snyk/common/services/downloadService.ts @@ -91,7 +91,6 @@ export class DownloadService { async isCliInstalled() { const cliExecutableExists = await CliExecutable.exists( this.extensionContext.extensionPath, - await this.configuration.getCliPath(), ); const cliChecksumWritten = !!this.getCliChecksum(); @@ -105,10 +104,7 @@ export class DownloadService { return false; } const latestChecksum = await this.cliApi.getSha256Checksum(version, platform); - const path = await CliExecutable.getPath( - this.extensionContext.extensionPath, - await this.configuration.getCliPath(), - ); + const path = await this.configuration.getCliPath(); // Update is available if fetched checksum not matching the current one const checksum = await Checksum.getChecksumOf(path, latestChecksum); diff --git a/src/test/unit/cli/cliExecutable.test.ts b/src/test/unit/cli/cliExecutable.test.ts index c23a946d2..efe768e33 100644 --- a/src/test/unit/cli/cliExecutable.test.ts +++ b/src/test/unit/cli/cliExecutable.test.ts @@ -1,5 +1,6 @@ import { strictEqual } from 'assert'; import path from 'path'; +import os from 'os'; import fs from 'fs/promises'; import sinon from 'sinon'; import { CliExecutable } from '../../../snyk/cli/cliExecutable'; @@ -19,52 +20,62 @@ suite('CliExecutable', () => { }); test('Returns correct extension paths', async () => { - const unixExtensionDir = '/Users/user/.vscode/extensions/snyk-security.snyk-vulnerability-scanner-1.1.0'; - const winExtensionDir = `C:\\Users\\user\\.vscode\\extensions`; + const homedirStub = sinon.stub(os, 'homedir'); + const unixExtensionDir = '/.local/share/snyk/vscode-cli'; + const macOsExtensionDir = '/Library/Application Support/snyk/vscode-cli'; + const winExtensionDir = `\\AppData\\Local\\snyk\\vscode-cli`; const osStub = sinon.stub(Platform, 'getCurrent').returns('darwin'); const archStub = sinon.stub(Platform, 'getArch').returns('x64'); const fsStub = sinon.stub(fs, 'access').returns(Promise.reject()); + let homedir = '/home/user'; + homedirStub.returns(homedir); - let expectedCliPath = path.join(unixExtensionDir, 'snyk-macos'); - strictEqual(await CliExecutable.getPath(unixExtensionDir), expectedCliPath); + let expectedCliPath = path.join(Platform.getHomeDir(), macOsExtensionDir, 'snyk-macos'); + strictEqual(await CliExecutable.getPath(), expectedCliPath); osStub.returns('linux'); - expectedCliPath = path.join(unixExtensionDir, 'snyk-linux'); - strictEqual(await CliExecutable.getPath(unixExtensionDir), expectedCliPath); + expectedCliPath = path.join(Platform.getHomeDir(), unixExtensionDir, 'snyk-linux'); + strictEqual(await CliExecutable.getPath(), expectedCliPath); fsStub.returns(Promise.resolve()); - expectedCliPath = path.join(unixExtensionDir, 'snyk-alpine'); - strictEqual(await CliExecutable.getPath(unixExtensionDir), expectedCliPath); + expectedCliPath = path.join(Platform.getHomeDir(), unixExtensionDir, 'snyk-alpine'); + strictEqual(await CliExecutable.getPath(), expectedCliPath); fsStub.returns(Promise.reject()); osStub.returns('win32'); - expectedCliPath = path.join(winExtensionDir, 'snyk-win.exe'); - strictEqual(await CliExecutable.getPath(winExtensionDir), expectedCliPath); + homedir = 'C:\\Users\\user'; + homedirStub.returns(homedir); + expectedCliPath = path.join(Platform.getHomeDir(), winExtensionDir, 'snyk-win.exe'); + strictEqual(await CliExecutable.getPath(), expectedCliPath); // test arm64 archStub.returns('arm64'); osStub.returns('darwin'); - expectedCliPath = path.join(unixExtensionDir, 'snyk-macos-arm64'); - strictEqual(await CliExecutable.getPath(unixExtensionDir), expectedCliPath); + homedir = '/home/user'; + homedirStub.returns(homedir); + expectedCliPath = path.join(Platform.getHomeDir(), unixExtensionDir, 'snyk-macos-arm64'); + strictEqual(await CliExecutable.getPath(), expectedCliPath); osStub.returns('linux'); - expectedCliPath = path.join(unixExtensionDir, 'snyk-linux-arm64'); - strictEqual(await CliExecutable.getPath(unixExtensionDir), expectedCliPath); + expectedCliPath = path.join(Platform.getHomeDir(), unixExtensionDir, 'snyk-linux-arm64'); + strictEqual(await CliExecutable.getPath(), expectedCliPath); fsStub.returns(Promise.resolve()); - expectedCliPath = path.join(unixExtensionDir, 'snyk-alpine-arm64'); - strictEqual(await CliExecutable.getPath(unixExtensionDir), expectedCliPath); + expectedCliPath = path.join(Platform.getHomeDir(), unixExtensionDir, 'snyk-alpine-arm64'); + strictEqual(await CliExecutable.getPath(), expectedCliPath); fsStub.returns(Promise.reject()); osStub.returns('win32'); - expectedCliPath = path.join(winExtensionDir, 'snyk-win.exe'); - strictEqual(await CliExecutable.getPath(winExtensionDir), expectedCliPath); + homedir = 'C:\\Users\\user'; + homedirStub.returns(homedir); + expectedCliPath = path.join(Platform.getHomeDir(), winExtensionDir, 'snyk-win.exe'); + strictEqual(await CliExecutable.getPath(), expectedCliPath); }); test('Return custom path, if provided', async () => { const customPath = '/path/to/cli'; - strictEqual(await CliExecutable.getPath('', customPath), customPath); + strictEqual(await CliExecutable.getPath(customPath), customPath); }); }); diff --git a/src/test/unit/common/configuration.test.ts b/src/test/unit/common/configuration.test.ts index 96f6c6871..f8398148d 100644 --- a/src/test/unit/common/configuration.test.ts +++ b/src/test/unit/common/configuration.test.ts @@ -149,7 +149,7 @@ suite('Configuration', () => { const cliPath = await configuration.getCliPath(); - const expectedCliPath = path.join('path/to/extension/', 'snyk-linux'); + const expectedCliPath = path.join(Platform.getHomeDir(), '.local/share/snyk/vscode-cli', 'snyk-linux'); strictEqual(cliPath, expectedCliPath); }); diff --git a/src/test/unit/common/languageServer/middleware.test.ts b/src/test/unit/common/languageServer/middleware.test.ts index 2dbbd054e..b0a3d2d8f 100644 --- a/src/test/unit/common/languageServer/middleware.test.ts +++ b/src/test/unit/common/languageServer/middleware.test.ts @@ -112,7 +112,7 @@ suite('Language Server: Middleware', () => { ); assert.strictEqual( serverResult.cliPath, - await CliExecutable.getPath(extensionContextMock.extensionPath, await configuration.getCliPath()), + await configuration.getCliPath(), ); assert.strictEqual(serverResult.enableTrustedFoldersFeature, 'true'); assert.deepStrictEqual(serverResult.trustedFolders, configuration.getTrustedFolders()); diff --git a/src/test/unit/common/languageServer/settings.test.ts b/src/test/unit/common/languageServer/settings.test.ts index dfc82d8f5..526b1dc9d 100644 --- a/src/test/unit/common/languageServer/settings.test.ts +++ b/src/test/unit/common/languageServer/settings.test.ts @@ -49,7 +49,6 @@ suite('LanguageServerSettings', () => { const serverSettings = await LanguageServerSettings.fromConfiguration( mockConfiguration, mockUser, - extensionContextMock, ); assert.strictEqual(serverSettings.activateSnykCodeSecurity, 'true'); From 911d7d1992899af065d6b5c5c2e81d4f6b1a3b36 Mon Sep 17 00:00:00 2001 From: Abdelrahman Shawki Hassan Date: Mon, 9 Dec 2024 08:48:11 +0100 Subject: [PATCH 02/10] chore: update axios --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index ac1912397..6ffcf13ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@babel/traverse": "^7.23.9", "@babel/types": "^7.23.9", "@deepcode/dcignore": "^1.0.4", - "axios": "^1.7.4", + "axios": "^1.7.8", "diff": "^5.2.0", "glob": "^9.3.5", "he": "^1.2.0", @@ -2514,9 +2514,9 @@ } }, "node_modules/axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -10494,9 +10494,9 @@ } }, "axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "requires": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", diff --git a/package.json b/package.json index 697fb08da..628aed4a3 100644 --- a/package.json +++ b/package.json @@ -553,7 +553,7 @@ "@babel/traverse": "^7.23.9", "@babel/types": "^7.23.9", "@deepcode/dcignore": "^1.0.4", - "axios": "^1.7.4", + "axios": "^1.7.8", "diff": "^5.2.0", "glob": "^9.3.5", "he": "^1.2.0", From c09433856a60a51c3cfd3bd7dc117bb17fe0f747 Mon Sep 17 00:00:00 2001 From: Abdelrahman Shawki Hassan Date: Mon, 9 Dec 2024 09:11:36 +0100 Subject: [PATCH 03/10] fix: cli executable tests --- src/test/unit/cli/cliExecutable.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/unit/cli/cliExecutable.test.ts b/src/test/unit/cli/cliExecutable.test.ts index efe768e33..748c7f1a8 100644 --- a/src/test/unit/cli/cliExecutable.test.ts +++ b/src/test/unit/cli/cliExecutable.test.ts @@ -23,7 +23,6 @@ suite('CliExecutable', () => { const homedirStub = sinon.stub(os, 'homedir'); const unixExtensionDir = '/.local/share/snyk/vscode-cli'; const macOsExtensionDir = '/Library/Application Support/snyk/vscode-cli'; - const winExtensionDir = `\\AppData\\Local\\snyk\\vscode-cli`; const osStub = sinon.stub(Platform, 'getCurrent').returns('darwin'); const archStub = sinon.stub(Platform, 'getArch').returns('x64'); @@ -45,17 +44,18 @@ suite('CliExecutable', () => { osStub.returns('win32'); homedir = 'C:\\Users\\user'; - homedirStub.returns(homedir); - expectedCliPath = path.join(Platform.getHomeDir(), winExtensionDir, 'snyk-win.exe'); - strictEqual(await CliExecutable.getPath(), expectedCliPath); + homedirStub.returns(homedir); + expectedCliPath = path.join(Platform.getHomeDir(), '\\AppData\\Local\\', 'snyk', 'vscode-cli', 'snyk-win.exe'); + const actualPath = await CliExecutable.getPath(); + strictEqual(actualPath, expectedCliPath); // test arm64 archStub.returns('arm64'); osStub.returns('darwin'); homedir = '/home/user'; - homedirStub.returns(homedir); - expectedCliPath = path.join(Platform.getHomeDir(), unixExtensionDir, 'snyk-macos-arm64'); + homedirStub.returns(homedir); + expectedCliPath = path.join(Platform.getHomeDir(), macOsExtensionDir, 'snyk-macos-arm64'); strictEqual(await CliExecutable.getPath(), expectedCliPath); osStub.returns('linux'); @@ -69,8 +69,8 @@ suite('CliExecutable', () => { osStub.returns('win32'); homedir = 'C:\\Users\\user'; - homedirStub.returns(homedir); - expectedCliPath = path.join(Platform.getHomeDir(), winExtensionDir, 'snyk-win.exe'); + homedirStub.returns(homedir); + expectedCliPath = path.join(Platform.getHomeDir(), '\\AppData\\Local\\', 'snyk', 'vscode-cli', 'snyk-win.exe'); strictEqual(await CliExecutable.getPath(), expectedCliPath); }); From 3b35b74843758c7784b48b7e6db614aa4b7bda4d Mon Sep 17 00:00:00 2001 From: Abdelrahman Shawki Hassan Date: Mon, 9 Dec 2024 09:18:14 +0100 Subject: [PATCH 04/10] fix: ensure dir exists --- src/snyk/common/download/downloader.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/snyk/common/download/downloader.ts b/src/snyk/common/download/downloader.ts index 4281508c3..016d79792 100644 --- a/src/snyk/common/download/downloader.ts +++ b/src/snyk/common/download/downloader.ts @@ -2,6 +2,7 @@ import axios, { CancelTokenSource } from 'axios'; import * as fs from 'fs'; import * as fsPromises from 'fs/promises'; import * as stream from 'stream'; +import { mkdirSync } from 'fs'; import { Progress } from 'vscode'; import { Checksum } from '../../cli/checksum'; import { messages } from '../../cli/messages/messages'; @@ -44,6 +45,7 @@ export class Downloader { private async getCliExecutable(platform: CliSupportedPlatform): Promise { const cliPath = await this.configuration.getCliPath(); + mkdirSync(cliPath, { recursive: true }); if (await this.binaryExists(cliPath)) { await this.deleteFileAtPath(cliPath); } From dbb086022f771321034f4e0362946877d59d473b Mon Sep 17 00:00:00 2001 From: Abdelrahman Shawki Hassan Date: Mon, 9 Dec 2024 10:02:43 +0100 Subject: [PATCH 05/10] fix: move existing CLI path to xdg dir --- src/snyk/cli/cliExecutable.ts | 7 +++++++ src/snyk/common/download/downloader.ts | 4 +++- src/snyk/common/services/downloadService.ts | 11 ++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/snyk/cli/cliExecutable.ts b/src/snyk/cli/cliExecutable.ts index dc3d18b51..8275636ea 100644 --- a/src/snyk/cli/cliExecutable.ts +++ b/src/snyk/cli/cliExecutable.ts @@ -86,6 +86,13 @@ export class CliExecutable { return platform; } + public static isPathInExtensionDirectory(dirPath: string, filePath: string): boolean { + const normalizedDir = path.resolve(dirPath) + path.sep; + const normalizedFile = path.resolve(filePath); + + return normalizedFile.toLowerCase().startsWith(normalizedDir.toLowerCase()); + } + static async exists(customPath?: string): Promise { return fs .access(await CliExecutable.getPath(customPath)) diff --git a/src/snyk/common/download/downloader.ts b/src/snyk/common/download/downloader.ts index 016d79792..818d04d44 100644 --- a/src/snyk/common/download/downloader.ts +++ b/src/snyk/common/download/downloader.ts @@ -1,5 +1,6 @@ import axios, { CancelTokenSource } from 'axios'; import * as fs from 'fs'; +import * as path from 'path'; import * as fsPromises from 'fs/promises'; import * as stream from 'stream'; import { mkdirSync } from 'fs'; @@ -45,7 +46,8 @@ export class Downloader { private async getCliExecutable(platform: CliSupportedPlatform): Promise { const cliPath = await this.configuration.getCliPath(); - mkdirSync(cliPath, { recursive: true }); + const cliDir = path.dirname(cliPath);; + mkdirSync(cliDir, { recursive: true }); if (await this.binaryExists(cliPath)) { await this.deleteFileAtPath(cliPath); } diff --git a/src/snyk/common/services/downloadService.ts b/src/snyk/common/services/downloadService.ts index c1df823bf..2e368c891 100644 --- a/src/snyk/common/services/downloadService.ts +++ b/src/snyk/common/services/downloadService.ts @@ -1,4 +1,5 @@ import { ReplaySubject } from 'rxjs'; +import * as fsPromises from 'fs/promises'; import { Checksum } from '../../cli/checksum'; import { messages } from '../../cli/messages/messages'; import { IConfiguration } from '../configuration/configuration'; @@ -105,7 +106,15 @@ export class DownloadService { } const latestChecksum = await this.cliApi.getSha256Checksum(version, platform); const path = await this.configuration.getCliPath(); - + // migration for moving from default extension path to xdg dirs. + if (CliExecutable.isPathInExtensionDirectory(this.extensionContext.extensionPath, path)) { + try { + await fsPromises.unlink(path); + } catch { + } + await this.configuration.setCliPath(await CliExecutable.getPath()); + return true; + } // Update is available if fetched checksum not matching the current one const checksum = await Checksum.getChecksumOf(path, latestChecksum); if (checksum.verify()) { From 583ad612beed4405fd5bca8797c02f24c1e6c631 Mon Sep 17 00:00:00 2001 From: Abdelrahman Shawki Hassan Date: Mon, 9 Dec 2024 10:04:57 +0100 Subject: [PATCH 06/10] chore: lint --- src/snyk/common/download/downloader.ts | 2 +- src/snyk/common/languageServer/middleware.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/snyk/common/download/downloader.ts b/src/snyk/common/download/downloader.ts index 818d04d44..ce89fda7a 100644 --- a/src/snyk/common/download/downloader.ts +++ b/src/snyk/common/download/downloader.ts @@ -26,7 +26,7 @@ export class Downloader { private readonly window: IVSCodeWindow, private readonly logger: ILog, private readonly extensionContext: ExtensionContext, - ) {} + ) { } /** * Downloads CLI. Existing executable is deleted. */ diff --git a/src/snyk/common/languageServer/middleware.ts b/src/snyk/common/languageServer/middleware.ts index 02ed80453..11941e91c 100644 --- a/src/snyk/common/languageServer/middleware.ts +++ b/src/snyk/common/languageServer/middleware.ts @@ -20,7 +20,7 @@ type LanguageClientWorkspaceMiddleware = Partial & { }; export class LanguageClientMiddleware implements Middleware { - constructor(private configuration: IConfiguration, private user: User, private extensionContext: ExtensionContext) {} + constructor(private configuration: IConfiguration, private user: User, private extensionContext: ExtensionContext) { } workspace: LanguageClientWorkspaceMiddleware = { configuration: async ( From fe126ef0a9dec3d309d5208f1c64f5bd387638e7 Mon Sep 17 00:00:00 2001 From: Abdelrahman Shawki Hassan Date: Mon, 9 Dec 2024 10:12:04 +0100 Subject: [PATCH 07/10] chore: lint --- src/snyk/cli/cliExecutable.ts | 2 +- src/snyk/common/download/downloader.ts | 4 ++-- src/snyk/common/languageServer/languageServer.ts | 5 +---- src/snyk/common/languageServer/middleware.ts | 7 ++----- src/snyk/common/languageServer/settings.ts | 5 +---- src/snyk/common/services/downloadService.ts | 5 ++--- src/test/unit/common/languageServer/middleware.test.ts | 5 +---- src/test/unit/common/languageServer/settings.test.ts | 5 +---- 8 files changed, 11 insertions(+), 27 deletions(-) diff --git a/src/snyk/cli/cliExecutable.ts b/src/snyk/cli/cliExecutable.ts index 8275636ea..4db555edd 100644 --- a/src/snyk/cli/cliExecutable.ts +++ b/src/snyk/cli/cliExecutable.ts @@ -37,7 +37,7 @@ export class CliExecutable { windows_arm64: 'snyk-win.exe', }; - constructor(public readonly version: string, public readonly checksum: Checksum) { } + constructor(public readonly version: string, public readonly checksum: Checksum) {} static async getPath(customPath?: string): Promise { if (customPath) { diff --git a/src/snyk/common/download/downloader.ts b/src/snyk/common/download/downloader.ts index ce89fda7a..11542e9cc 100644 --- a/src/snyk/common/download/downloader.ts +++ b/src/snyk/common/download/downloader.ts @@ -26,7 +26,7 @@ export class Downloader { private readonly window: IVSCodeWindow, private readonly logger: ILog, private readonly extensionContext: ExtensionContext, - ) { } + ) {} /** * Downloads CLI. Existing executable is deleted. */ @@ -46,7 +46,7 @@ export class Downloader { private async getCliExecutable(platform: CliSupportedPlatform): Promise { const cliPath = await this.configuration.getCliPath(); - const cliDir = path.dirname(cliPath);; + const cliDir = path.dirname(cliPath); mkdirSync(cliDir, { recursive: true }); if (await this.binaryExists(cliPath)) { await this.deleteFileAtPath(cliPath); diff --git a/src/snyk/common/languageServer/languageServer.ts b/src/snyk/common/languageServer/languageServer.ts index 3cfa6d2dc..11ee70504 100644 --- a/src/snyk/common/languageServer/languageServer.ts +++ b/src/snyk/common/languageServer/languageServer.ts @@ -161,10 +161,7 @@ export class LanguageServer implements ILanguageServer { // Initialization options are not semantically equal to server settings, thus separated here // https://github.com/microsoft/language-server-protocol/issues/567 async getInitializationOptions(): Promise { - const settings = await LanguageServerSettings.fromConfiguration( - this.configuration, - this.user, - ); + const settings = await LanguageServerSettings.fromConfiguration(this.configuration, this.user); return settings; } diff --git a/src/snyk/common/languageServer/middleware.ts b/src/snyk/common/languageServer/middleware.ts index 11941e91c..3f920fb23 100644 --- a/src/snyk/common/languageServer/middleware.ts +++ b/src/snyk/common/languageServer/middleware.ts @@ -20,7 +20,7 @@ type LanguageClientWorkspaceMiddleware = Partial & { }; export class LanguageClientMiddleware implements Middleware { - constructor(private configuration: IConfiguration, private user: User, private extensionContext: ExtensionContext) { } + constructor(private configuration: IConfiguration, private user: User, private extensionContext: ExtensionContext) {} workspace: LanguageClientWorkspaceMiddleware = { configuration: async ( @@ -41,10 +41,7 @@ export class LanguageClientMiddleware implements Middleware { return []; } - const serverSettings = await LanguageServerSettings.fromConfiguration( - this.configuration, - this.user, - ); + const serverSettings = await LanguageServerSettings.fromConfiguration(this.configuration, this.user); return [serverSettings]; }, }; diff --git a/src/snyk/common/languageServer/settings.ts b/src/snyk/common/languageServer/settings.ts index 80fcdda1c..ad4eb9764 100644 --- a/src/snyk/common/languageServer/settings.ts +++ b/src/snyk/common/languageServer/settings.ts @@ -49,10 +49,7 @@ export type ServerSettings = { }; export class LanguageServerSettings { - static async fromConfiguration( - configuration: IConfiguration, - user: User, - ): Promise { + static async fromConfiguration(configuration: IConfiguration, user: User): Promise { const featuresConfiguration = configuration.getFeaturesConfiguration(); const ossEnabled = _.isUndefined(featuresConfiguration.ossEnabled) ? true : featuresConfiguration.ossEnabled; diff --git a/src/snyk/common/services/downloadService.ts b/src/snyk/common/services/downloadService.ts index 2e368c891..9d30706ba 100644 --- a/src/snyk/common/services/downloadService.ts +++ b/src/snyk/common/services/downloadService.ts @@ -90,9 +90,7 @@ export class DownloadService { } async isCliInstalled() { - const cliExecutableExists = await CliExecutable.exists( - this.extensionContext.extensionPath, - ); + const cliExecutableExists = await CliExecutable.exists(this.extensionContext.extensionPath); const cliChecksumWritten = !!this.getCliChecksum(); return cliExecutableExists && cliChecksumWritten; @@ -111,6 +109,7 @@ export class DownloadService { try { await fsPromises.unlink(path); } catch { + // eslint-disable-next-line no-empty } await this.configuration.setCliPath(await CliExecutable.getPath()); return true; diff --git a/src/test/unit/common/languageServer/middleware.test.ts b/src/test/unit/common/languageServer/middleware.test.ts index b0a3d2d8f..95ce7342c 100644 --- a/src/test/unit/common/languageServer/middleware.test.ts +++ b/src/test/unit/common/languageServer/middleware.test.ts @@ -110,10 +110,7 @@ suite('Language Server: Middleware', () => { serverResult.manageBinariesAutomatically, `${configuration.isAutomaticDependencyManagementEnabled()}`, ); - assert.strictEqual( - serverResult.cliPath, - await configuration.getCliPath(), - ); + assert.strictEqual(serverResult.cliPath, await configuration.getCliPath()); assert.strictEqual(serverResult.enableTrustedFoldersFeature, 'true'); assert.deepStrictEqual(serverResult.trustedFolders, configuration.getTrustedFolders()); }); diff --git a/src/test/unit/common/languageServer/settings.test.ts b/src/test/unit/common/languageServer/settings.test.ts index 526b1dc9d..d40fb7ef2 100644 --- a/src/test/unit/common/languageServer/settings.test.ts +++ b/src/test/unit/common/languageServer/settings.test.ts @@ -46,10 +46,7 @@ suite('LanguageServerSettings', () => { scanningMode: 'scan-mode', } as unknown as IConfiguration; - const serverSettings = await LanguageServerSettings.fromConfiguration( - mockConfiguration, - mockUser, - ); + const serverSettings = await LanguageServerSettings.fromConfiguration(mockConfiguration, mockUser); assert.strictEqual(serverSettings.activateSnykCodeSecurity, 'true'); assert.strictEqual(serverSettings.activateSnykCodeQuality, 'true'); From 1359ffc2448f20aca091d9d92b809cac10fa09f3 Mon Sep 17 00:00:00 2001 From: Abdelrahman Shawki Hassan Date: Mon, 9 Dec 2024 10:53:21 +0100 Subject: [PATCH 08/10] fix: delete unused import --- src/snyk/common/configuration/configuration.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/snyk/common/configuration/configuration.ts b/src/snyk/common/configuration/configuration.ts index de082b13b..48d2a7c5e 100644 --- a/src/snyk/common/configuration/configuration.ts +++ b/src/snyk/common/configuration/configuration.ts @@ -33,7 +33,6 @@ import { import SecretStorageAdapter from '../vscode/secretStorage'; import { IVSCodeWorkspace } from '../vscode/workspace'; import { CliExecutable } from '../../cli/cliExecutable'; -import { extensionContext } from '../vscode/extensionContext'; const NEWISSUES = 'Net new issues'; @@ -161,7 +160,7 @@ export class Configuration implements IConfiguration { private featureFlag: { [key: string]: boolean } = {}; private extensionId: string; - constructor(private processEnv: NodeJS.ProcessEnv = process.env, private workspace: IVSCodeWorkspace) {} + constructor(private processEnv: NodeJS.ProcessEnv = process.env, private workspace: IVSCodeWorkspace) { } getExtensionId(): string { return this.extensionId; From 9262328901a9d8be692f4f9b12c2e74927d37e5b Mon Sep 17 00:00:00 2001 From: Abdelrahman Shawki Hassan Date: Mon, 9 Dec 2024 10:54:18 +0100 Subject: [PATCH 09/10] chore: unused import --- src/snyk/common/languageServer/settings.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/snyk/common/languageServer/settings.ts b/src/snyk/common/languageServer/settings.ts index ad4eb9764..e1351d348 100644 --- a/src/snyk/common/languageServer/settings.ts +++ b/src/snyk/common/languageServer/settings.ts @@ -3,7 +3,6 @@ import { CLI_INTEGRATION_NAME } from '../../cli/contants/integration'; import { Configuration, FolderConfig, IConfiguration, SeverityFilter } from '../configuration/configuration'; import { User } from '../user'; import { PROTOCOL_VERSION } from '../constants/languageServer'; -import { ExtensionContext } from '../vscode/extensionContext'; export type ServerSettings = { // Feature toggles From cf596700b100d0ad646b7a3678d374cc669dc842 Mon Sep 17 00:00:00 2001 From: Abdelrahman Shawki Hassan Date: Mon, 9 Dec 2024 11:20:03 +0100 Subject: [PATCH 10/10] chore: lint --- src/snyk/common/configuration/configuration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snyk/common/configuration/configuration.ts b/src/snyk/common/configuration/configuration.ts index 48d2a7c5e..187d8e68b 100644 --- a/src/snyk/common/configuration/configuration.ts +++ b/src/snyk/common/configuration/configuration.ts @@ -160,7 +160,7 @@ export class Configuration implements IConfiguration { private featureFlag: { [key: string]: boolean } = {}; private extensionId: string; - constructor(private processEnv: NodeJS.ProcessEnv = process.env, private workspace: IVSCodeWorkspace) { } + constructor(private processEnv: NodeJS.ProcessEnv = process.env, private workspace: IVSCodeWorkspace) {} getExtensionId(): string { return this.extensionId;