mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
pass install paths to notebooks (#8008)
* pass install paths to notebooks * onComplete * discover and publish actual installation Path * pass the path to notebook * minor fixes needed post merge of code from remote * fix some errors * remove unused variable
This commit is contained in:
committed by
Alan Ren
parent
3b1c9e910d
commit
af9984f73b
@@ -57,7 +57,7 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
"### **Setup**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a56d3413-a730-4997-b5c2-c8abd972757e"
|
||||
@@ -78,11 +78,7 @@
|
||||
" !{command}\n",
|
||||
" if _exit_code != 0:\n",
|
||||
" sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{command}\\n')\n",
|
||||
" print(f'Successfully executed: {command}')\n",
|
||||
"\n",
|
||||
"run_command('kubectl version --client=true')\n",
|
||||
"run_command('azdata --version')\n",
|
||||
"run_command('az --version')"
|
||||
" print(f'Successfully executed: {command}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "326645cf-022a-47f2-8aff-37de71da8955",
|
||||
@@ -103,6 +99,31 @@
|
||||
"azdata_cell_guid": "8716915b-1439-431b-ab0a-0221ef94cb7f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "db8b1e21-eb2c-4c35-b973-bc4ef38bb1d0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command('kubectl version --client=true')\n",
|
||||
"run_command('azdata --version')\n",
|
||||
"run_command('az --version')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "9361deaf-28b1-4d02-912d-2011cae97e8a",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": 0
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
"### **Setup**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e3dd8e75-e15f-44b4-81fc-1f54d6f0b1e2"
|
||||
@@ -77,10 +77,7 @@
|
||||
" !{command}\n",
|
||||
" if _exit_code != 0:\n",
|
||||
" sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{command}\\n')\n",
|
||||
" print(f'Successfully executed: {command}')\n",
|
||||
"\n",
|
||||
"run_command('kubectl version --client=true')\n",
|
||||
"run_command('azdata --version')"
|
||||
" print(f'Successfully executed: {command}')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "d973d5b4-7f0a-4a9d-b204-a16480f3940d",
|
||||
@@ -101,6 +98,30 @@
|
||||
"azdata_cell_guid": "4b266b2d-bd1b-4565-92c9-3fc146cdce6d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "2544648b-59c9-4ce5-a3b6-87086e214d4c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command('kubectl version --client=true')\n",
|
||||
"run_command('azdata --version')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "691671d7-3f05-406c-a183-4cff7d17f83d",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": 0
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
"### **Setup**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "a31f9894-903f-4e19-a5a8-6fd888ff013b"
|
||||
@@ -101,6 +101,30 @@
|
||||
"azdata_cell_guid": "e70640d0-6059-4cab-939e-e985a978c0da"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Check dependencies**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "869d0397-a280-4dc4-be76-d652189b5131"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_command('kubectl version --client=true')\n",
|
||||
"run_command('azdata --version')"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "c38afb67-1132-495e-9af1-35bf067acbeb",
|
||||
"tags": [
|
||||
"hide_input"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": 0
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
|
||||
@@ -226,7 +226,7 @@ export const enum ToolStatus {
|
||||
}
|
||||
|
||||
export interface ITool {
|
||||
isInstalling: any;
|
||||
readonly isInstalling: boolean;
|
||||
readonly name: string;
|
||||
readonly displayName: string;
|
||||
readonly description: string;
|
||||
@@ -237,6 +237,7 @@ export interface ITool {
|
||||
readonly autoInstallSupported: boolean;
|
||||
readonly autoInstallRequired: boolean;
|
||||
readonly isNotInstalled: boolean;
|
||||
readonly installationPath: string;
|
||||
readonly needsInstallation: boolean;
|
||||
readonly outputChannelName: string;
|
||||
readonly fullVersion: string | undefined;
|
||||
|
||||
@@ -232,9 +232,9 @@ export class PlatformService implements IPlatformService {
|
||||
// Add listeners to print stdout and stderr and exit code
|
||||
child.on('exit', (code: number | null, signal: string | null) => {
|
||||
if (code !== null) {
|
||||
outputChannel.appendLine(localize('platformService.RunStreamedCommand.ExitedWithCode', " >>> ${0} ... exited with code: ${1}", command, code));
|
||||
outputChannel.appendLine(localize('platformService.RunStreamedCommand.ExitedWithCode', " >>> {0} ... exited with code: {1}", command, code));
|
||||
} else {
|
||||
outputChannel.appendLine(localize('platformService.RunStreamedCommand.ExitedWithSignal', " >>> ${0} ... exited with signal: ${1}", command, signal));
|
||||
outputChannel.appendLine(localize('platformService.RunStreamedCommand.ExitedWithSignal', " >>> {0} ... exited with signal: {1}", command, signal));
|
||||
}
|
||||
});
|
||||
child.stdout.on('data', (data: string | Buffer) => {
|
||||
|
||||
@@ -42,12 +42,12 @@ export class AzCliTool extends ToolBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async getInstallationPath(): Promise<string | undefined> {
|
||||
protected async getSearchPaths(): Promise<string[]> {
|
||||
switch (this.osType) {
|
||||
case OsType.win32:
|
||||
return win32InstallationRoot;
|
||||
return [win32InstallationRoot];
|
||||
default:
|
||||
return defaultInstallationRoot;
|
||||
return [defaultInstallationRoot];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,11 +65,18 @@ export class AzCliTool extends ToolBase {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
protected get versionCommand(): Command {
|
||||
return {
|
||||
command: 'az --version'
|
||||
};
|
||||
}
|
||||
|
||||
protected get discoveryCommand(): Command {
|
||||
return {
|
||||
command: this.discoveryCommandString('az')
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const win32InstallationCommands = [
|
||||
|
||||
@@ -13,7 +13,6 @@ import { ToolBase } from './toolBase';
|
||||
import { DeploymentConfigurationKey, AzdataPipInstallUriKey, azdataPipInstallArgsKey } from '../../constants';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
const installationRoot = '~/.local/bin';
|
||||
|
||||
export class AzdataTool extends ToolBase {
|
||||
constructor(platformService: IPlatformService) {
|
||||
@@ -46,6 +45,12 @@ export class AzdataTool extends ToolBase {
|
||||
};
|
||||
}
|
||||
|
||||
protected get discoveryCommand(): Command {
|
||||
return {
|
||||
command: this.discoveryCommandString('azdata')
|
||||
};
|
||||
}
|
||||
|
||||
protected getVersionFromOutput(output: string): SemVer | undefined {
|
||||
let version: SemVer | undefined = undefined;
|
||||
if (output && output.split(EOL).length > 0) {
|
||||
@@ -58,13 +63,15 @@ export class AzdataTool extends ToolBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async getInstallationPath(): Promise<string | undefined> {
|
||||
protected async getSearchPaths(): Promise<string[]> {
|
||||
switch (this.osType) {
|
||||
case OsType.linux:
|
||||
return installationRoot;
|
||||
default:
|
||||
const azdataCliInstallLocation = await this.getPip3InstallLocation('azdata-cli');
|
||||
return azdataCliInstallLocation && path.join(azdataCliInstallLocation, '..', 'Scripts');
|
||||
if (azdataCliInstallLocation) {
|
||||
return [path.join(azdataCliInstallLocation, '..', 'Scripts'), path.join(azdataCliInstallLocation, '..', '..', '..', 'bin')];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,11 +85,7 @@ export class AzdataTool extends ToolBase {
|
||||
}
|
||||
|
||||
protected get uninstallCommand(): string | undefined {
|
||||
if (this.osType !== OsType.linux) {
|
||||
return this.defaultUninstallCommand;
|
||||
} else {
|
||||
return super.uninstallCommand;
|
||||
}
|
||||
}
|
||||
|
||||
private get defaultInstallationCommands(): Command[] {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ToolBase } from './toolBase';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class DockerTool extends ToolBase {
|
||||
protected discoveryCommand: Command = { command: '' };
|
||||
constructor(platformService: IPlatformService) {
|
||||
super(platformService);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import { ToolBase } from './toolBase';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const defaultInstallationRoot = '/usr/local/bin';
|
||||
|
||||
export class KubeCtlTool extends ToolBase {
|
||||
constructor(platformService: IPlatformService) {
|
||||
super(platformService);
|
||||
@@ -49,10 +51,24 @@ export class KubeCtlTool extends ToolBase {
|
||||
return { command: 'kubectl version -o json --client' };
|
||||
}
|
||||
|
||||
protected get discoveryCommand(): Command {
|
||||
return {
|
||||
command: this.discoveryCommandString('kubectl')
|
||||
};
|
||||
}
|
||||
|
||||
get autoInstallSupported(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async getSearchPaths(): Promise<string[]> {
|
||||
switch (this.osType) {
|
||||
case OsType.win32:
|
||||
return [this.storagePath];
|
||||
default:
|
||||
return [defaultInstallationRoot];
|
||||
}
|
||||
}
|
||||
protected readonly allInstallationCommands: Map<OsType, Command[]> = new Map<OsType, Command[]>([
|
||||
[OsType.linux, linuxInstallationCommands],
|
||||
[OsType.win32, win32InstallationCommands],
|
||||
|
||||
@@ -14,7 +14,7 @@ import { IPlatformService } from '../platformService';
|
||||
const localize = nls.loadMessageBundle();
|
||||
const toolStatusNotInstalled: string = localize('deploymentDialog.ToolStatus.NotInstalled', "Not Installed");
|
||||
const toolStatusInstalled: string = localize('deploymentDialog.ToolStatus.Installed', "Installed");
|
||||
const toolStatusInstalling: string = localize('deploymentDialog.ToolStatus.NotInstalling', "Installing ...");
|
||||
const toolStatusInstalling: string = localize('deploymentDialog.ToolStatus.Installing', "Installing");
|
||||
const toolStatusError: string = localize('deploymentDialog.ToolStatus.Error', "Error");
|
||||
const toolStatusFailed: string = localize('deploymentDialog.ToolStatus.Failed', "Failed");
|
||||
|
||||
@@ -45,12 +45,10 @@ export abstract class ToolBase implements ITool {
|
||||
|
||||
protected abstract readonly versionCommand: Command;
|
||||
|
||||
protected async getInstallationPath(): Promise<string | undefined> {
|
||||
return undefined;
|
||||
}
|
||||
protected abstract readonly discoveryCommand: Command;
|
||||
|
||||
protected get installationSearchPaths(): (string | undefined)[] {
|
||||
return [this.storagePath];
|
||||
protected async getSearchPaths(): Promise<string[]> {
|
||||
return [];
|
||||
}
|
||||
|
||||
protected get downloadPath(): string {
|
||||
@@ -125,6 +123,9 @@ export abstract class ToolBase implements ITool {
|
||||
return this._statusDescription;
|
||||
}
|
||||
|
||||
public get installationPath(): string {
|
||||
return this._installationPath;
|
||||
}
|
||||
protected get installationCommands(): Command[] | undefined {
|
||||
return this.allInstallationCommands.get(this.osType);
|
||||
}
|
||||
@@ -164,6 +165,7 @@ export abstract class ToolBase implements ITool {
|
||||
this.status = ToolStatus.Error;
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Since we just completed installation, the status should be ToolStatus.Installed
|
||||
// but if it is ToolStatus.NotInstalled then it means that installation failed with 0 exit code.
|
||||
if (this.status === ToolStatus.NotInstalled) {
|
||||
@@ -196,27 +198,28 @@ export abstract class ToolBase implements ITool {
|
||||
}
|
||||
|
||||
protected async addInstallationSearchPathsToSystemPath(): Promise<void> {
|
||||
const installationPath = await this.getInstallationPath();
|
||||
const searchPaths = [installationPath, ...this.installationSearchPaths].filter(path => !!path);
|
||||
const searchPaths = [...await this.getSearchPaths(), this.storagePath].filter(path => !!path);
|
||||
this.logToOutputChannel(localize('toolBase.addInstallationSearchPathsToSystemPath.SearchPaths', "Search Paths for tool '{0}': {1}", this.displayName, JSON.stringify(searchPaths, undefined, '\t'))); //this.displayName is localized and searchPaths are OS filesystem paths.
|
||||
searchPaths.forEach(installationSearchPath => {
|
||||
searchPaths.forEach(searchPath => {
|
||||
if (process.env.PATH) {
|
||||
if (!`${delimiter}${process.env.PATH}${delimiter}`.includes(`${delimiter}${installationSearchPath}${delimiter}`)) {
|
||||
process.env.PATH += `${delimiter}${installationSearchPath}`;
|
||||
console.log(`Appending to Path -> ${delimiter}${installationSearchPath}`);
|
||||
if (!`${delimiter}${process.env.PATH}${delimiter}`.includes(`${delimiter}${searchPath}${delimiter}`)) {
|
||||
process.env.PATH += `${delimiter}${searchPath}`;
|
||||
console.log(`Appending to Path -> '${delimiter}${searchPath}'`);
|
||||
}
|
||||
} else {
|
||||
process.env.PATH = installationSearchPath;
|
||||
console.log(`Appending to Path -> '${delimiter}${installationSearchPath}':${delimiter}${installationSearchPath}`);
|
||||
process.env.PATH = searchPath;
|
||||
console.log(`Setting PATH to -> '${searchPath}'`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async loadInformation(): Promise<void> {
|
||||
if (this.status === ToolStatus.NotInstalled) {
|
||||
await this.addInstallationSearchPathsToSystemPath();
|
||||
this.status = await this.updateVersionAndGetStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private async updateVersionAndGetStatus(): Promise<ToolStatus> {
|
||||
const commandOutput = await this._platformService.runCommand(
|
||||
this.versionCommand.command,
|
||||
@@ -229,6 +232,8 @@ export abstract class ToolBase implements ITool {
|
||||
);
|
||||
this.version = this.getVersionFromOutput(commandOutput);
|
||||
if (this.version) {
|
||||
// discover and set the installationPath
|
||||
await this.setInstallationPath();
|
||||
return ToolStatus.Installed;
|
||||
}
|
||||
else {
|
||||
@@ -237,10 +242,39 @@ export abstract class ToolBase implements ITool {
|
||||
}
|
||||
}
|
||||
|
||||
protected discoveryCommandString(toolBinary: string) {
|
||||
switch (this.osType) {
|
||||
case OsType.win32:
|
||||
return `where.exe ${toolBinary}`;
|
||||
case OsType.darwin:
|
||||
return `command -v ${toolBinary}`;
|
||||
default:
|
||||
return `which ${toolBinary}`;
|
||||
}
|
||||
}
|
||||
|
||||
protected async setInstallationPath() {
|
||||
const commandOutput = await this._platformService.runCommand(
|
||||
this.discoveryCommand.command,
|
||||
{
|
||||
workingDirectory: this.discoveryCommand.workingDirectory,
|
||||
additionalEnvironmentVariables: this.discoveryCommand.additionalEnvironmentVariables,
|
||||
sudo: false,
|
||||
ignoreError: false
|
||||
},
|
||||
);
|
||||
if (!commandOutput) {
|
||||
throw new Error(`Install location of tool:'${this.displayName}' could not be discovered`);
|
||||
} else {
|
||||
this._installationPath = commandOutput.split(EOL)[0];
|
||||
}
|
||||
}
|
||||
|
||||
private _storagePathEnsured: boolean = false;
|
||||
private _status: ToolStatus = ToolStatus.NotInstalled;
|
||||
private _osType: OsType;
|
||||
private _version?: SemVer;
|
||||
private _statusDescription?: string;
|
||||
private _installationPath!: string;
|
||||
|
||||
}
|
||||
|
||||
@@ -69,3 +69,4 @@ export const DockerRegistry_VariableName = 'AZDATA_NB_VAR_BDC_REGISTRY';
|
||||
export const DockerImageTag_VariableName = 'AZDATA_NB_VAR_BDC_DOCKER_IMAGE_TAG';
|
||||
export const DockerUsername_VariableName = 'AZDATA_NB_VAR_BDC_DOCKER_USERNAME';
|
||||
export const DockerPassword_VariableName = 'AZDATA_NB_VAR_BDC_DOCKER_PASSWORD';
|
||||
export const ToolsInstallPath = 'AZDATA_NB_VAR_TOOLS_INSTALLATION_PATH';
|
||||
|
||||
@@ -8,6 +8,7 @@ import * as VariableNames from './constants';
|
||||
import { BigDataClusterDeploymentProfile, DataResource, SqlServerMasterResource, HdfsResource } from '../../services/bigDataClusterDeploymentProfile';
|
||||
import { BdcDeploymentType } from '../../interfaces';
|
||||
import { EOL } from 'os';
|
||||
import { delimiter } from 'path';
|
||||
|
||||
export class DeployClusterWizardModel extends Model {
|
||||
constructor(public deploymentTarget: BdcDeploymentType) {
|
||||
@@ -162,6 +163,7 @@ export class DeployClusterWizardModel extends Model {
|
||||
statements.push(`os.environ["DOCKER_USERNAME"] = '${this.getStringValue(VariableNames.DockerUsername_VariableName)}'`);
|
||||
statements.push(`os.environ["DOCKER_PASSWORD"] = os.environ["${VariableNames.DockerPassword_VariableName}"]`);
|
||||
}
|
||||
statements.push(`os.environ["PATH"] = os.environ["PATH"] + "${delimiter}" + "${process.env[VariableNames.ToolsInstallPath]}"`);
|
||||
statements.push(`print('Variables have been set successfully.')`);
|
||||
return statements.map(line => line + EOL);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ export abstract class DialogBase {
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
protected onComplete(): void { }
|
||||
protected onComplete(): void {
|
||||
}
|
||||
|
||||
protected dispose(): void {
|
||||
this._toDispose.forEach(disposable => disposable.dispose());
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as nls from 'vscode-nls';
|
||||
import { AgreementInfo, DeploymentProvider, ITool, ResourceType } from '../interfaces';
|
||||
import { IResourceTypeService } from '../services/resourceTypeService';
|
||||
import { IToolsService } from '../services/toolsService';
|
||||
import { getErrorMessage } from '../utils';
|
||||
import { getErrorMessage, setEnvironmentVariablesForInstallPaths } from '../utils';
|
||||
import { DialogBase } from './dialogBase';
|
||||
import { createFlexContainer } from './modelViewUtils';
|
||||
|
||||
@@ -288,6 +288,7 @@ export class ResourceTypePickerDialog extends DialogBase {
|
||||
}
|
||||
|
||||
protected onComplete(): void {
|
||||
setEnvironmentVariablesForInstallPaths(this._tools);
|
||||
this.resourceTypeService.startDeployment(this.getCurrentProvider());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { ITool, NoteBookEnvironmentVariablePrefix } from './interfaces';
|
||||
import * as path from 'path';
|
||||
import { ToolsInstallPath } from './ui/deployClusterWizard/constants';
|
||||
|
||||
export function getErrorMessage(error: any): string {
|
||||
return (error instanceof Error)
|
||||
@@ -12,3 +15,18 @@ export function getErrorMessage(error: any): string {
|
||||
export function getDateTimeString(): string {
|
||||
return new Date().toISOString().slice(0, 19).replace(/[^0-9]/g, ''); // Take the date time information and only leaving the numbers
|
||||
}
|
||||
|
||||
export function setEnvironmentVariablesForInstallPaths(tools: ITool[]): void {
|
||||
let installationPaths: Set<string> = new Set<string>();
|
||||
tools.forEach(t => {
|
||||
// construct an env variable name with NoteBookEnvironmentVariablePrefix prefix
|
||||
// and tool.name as suffix, making sure of using all uppercase characters and only _ as separator
|
||||
const envVarName: string = `${NoteBookEnvironmentVariablePrefix}${t.name.toUpperCase().replace(/ |-/, '_')}`;
|
||||
process.env[envVarName] = t.installationPath;
|
||||
installationPaths.add(path.resolve(path.dirname(t.installationPath)));
|
||||
console.log(`setting env var:'${envVarName}' to: '${t.installationPath}'`);
|
||||
});
|
||||
const envVarToolsInstallationPath: string = [...installationPaths.values()].join(path.delimiter);
|
||||
process.env[ToolsInstallPath] = envVarToolsInstallationPath;
|
||||
console.log(`setting env var:'${ToolsInstallPath}' to: '${envVarToolsInstallationPath}'`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user