Adding ability to install SDKs
This commit is contained in:
Родитель
23b4f9f190
Коммит
a8c62d6401
|
@ -13,7 +13,7 @@
|
|||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "compile-all"
|
||||
},
|
||||
|
@ -24,10 +24,10 @@
|
|||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"--extensionTestsPath=${workspaceFolder}/out/test/functional"
|
||||
"--extensionTestsPath=${workspaceFolder}/dist/test/functional"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/test/**/*.js"
|
||||
"${workspaceFolder}/dist/test/**/*.js"
|
||||
],
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"preLaunchTask": "compile-all"
|
||||
|
|
|
@ -32,7 +32,7 @@ export class AcquisitionInvoker extends IAcquisitionInvoker {
|
|||
|
||||
public async installDotnet(installContext: IDotnetInstallationContext): Promise<void> {
|
||||
const winOS = os.platform() === 'win32';
|
||||
const installCommand = await this.getInstallCommand(installContext.version, installContext.installDir);
|
||||
const installCommand = await this.getInstallCommand(installContext.version, installContext.installDir, installContext.installRuntime);
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
try {
|
||||
const windowsFullCommand = `powershell.exe -NoProfile -ExecutionPolicy unrestricted -Command "& { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 ; & ${installCommand} }`;
|
||||
|
@ -75,12 +75,14 @@ export class AcquisitionInvoker extends IAcquisitionInvoker {
|
|||
});
|
||||
}
|
||||
|
||||
private async getInstallCommand(version: string, dotnetInstallDir: string): Promise<string> {
|
||||
const args = [
|
||||
private async getInstallCommand(version: string, dotnetInstallDir: string, installRuntime: boolean): Promise<string> {
|
||||
let args = [
|
||||
'-InstallDir', this.escapeFilePath(dotnetInstallDir),
|
||||
'-Runtime', 'dotnet',
|
||||
'-Version', version,
|
||||
];
|
||||
if (installRuntime) {
|
||||
args = args.concat('-Runtime', 'dotnet');
|
||||
}
|
||||
|
||||
const scriptPath = await this.scriptWorker.getDotnetInstallScriptPath();
|
||||
return `${ this.escapeFilePath(scriptPath) } ${ args.join(' ') }`;
|
||||
|
|
|
@ -67,9 +67,15 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
|
|||
}
|
||||
}
|
||||
|
||||
public async acquire(version: string): Promise<IDotnetAcquireResult> {
|
||||
version = await this.context.versionResolver.getFullVersion(version);
|
||||
public async acquireSDK(version: string): Promise<IDotnetAcquireResult> {
|
||||
return this.acquire(version, false);
|
||||
}
|
||||
|
||||
public async acquireRuntime(version: string): Promise<IDotnetAcquireResult> {
|
||||
return this.acquire(version, true);
|
||||
}
|
||||
|
||||
public async acquire(version: string, installRuntime: boolean): Promise<IDotnetAcquireResult> {
|
||||
const existingAcquisitionPromise = this.acquisitionPromises[version];
|
||||
if (existingAcquisitionPromise) {
|
||||
// This version of dotnet is already being acquired. Memoize the promise.
|
||||
|
@ -77,7 +83,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
|
|||
return existingAcquisitionPromise.then((res) => ({ dotnetPath: res }));
|
||||
} else {
|
||||
// We're the only one acquiring this version of dotnet, start the acquisition process.
|
||||
const acquisitionPromise = this.acquireCore(version).catch((error: Error) => {
|
||||
const acquisitionPromise = this.acquireCore(version, installRuntime).catch((error: Error) => {
|
||||
delete this.acquisitionPromises[version];
|
||||
throw new Error(`.NET Acquisition Failed: ${error.message}`);
|
||||
});
|
||||
|
@ -87,7 +93,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
|
|||
}
|
||||
}
|
||||
|
||||
private async acquireCore(version: string): Promise<string> {
|
||||
private async acquireCore(version: string, installRuntime: boolean): Promise<string> {
|
||||
const installingVersions = this.context.extensionState.get<string[]>(this.installingVersionsKey, []);
|
||||
const partialInstall = installingVersions.indexOf(version) >= 0;
|
||||
if (partialInstall) {
|
||||
|
@ -117,6 +123,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
|
|||
version,
|
||||
dotnetPath,
|
||||
timeoutValue: this.timeoutValue,
|
||||
installRuntime,
|
||||
} as IDotnetInstallationContext;
|
||||
this.context.eventStream.post(new DotnetAcquisitionStarted(version));
|
||||
await this.context.acquisitionInvoker.installDotnet(installContext).catch((reason) => {
|
||||
|
|
|
@ -6,14 +6,12 @@ import { Memento } from 'vscode';
|
|||
import { IEventStream } from '../EventStream/EventStream';
|
||||
import { IAcquisitionInvoker } from './IAcquisitionInvoker';
|
||||
import { IInstallationValidator } from './IInstallationValidator';
|
||||
import { IVersionResolver } from './IVersionResolver';
|
||||
|
||||
export interface IAcquisitionWorkerContext {
|
||||
storagePath: string;
|
||||
extensionState: Memento;
|
||||
eventStream: IEventStream;
|
||||
acquisitionInvoker: IAcquisitionInvoker;
|
||||
versionResolver: IVersionResolver;
|
||||
installationValidator: IInstallationValidator;
|
||||
timeoutValue: number;
|
||||
}
|
||||
|
|
|
@ -12,5 +12,7 @@ export interface IDotnetCoreAcquisitionWorker {
|
|||
|
||||
resolveExistingPath(existingPaths: IExistingPath[] | undefined, extensionId: string | undefined, windowDisplayWorker: IWindowDisplayWorker): IDotnetAcquireResult | undefined;
|
||||
|
||||
acquire(version: string): Promise<IDotnetAcquireResult>;
|
||||
acquireRuntime(version: string): Promise<IDotnetAcquireResult>;
|
||||
|
||||
acquireSDK(version: string): Promise<IDotnetAcquireResult>;
|
||||
}
|
||||
|
|
|
@ -8,4 +8,5 @@ export interface IDotnetInstallationContext {
|
|||
version: string;
|
||||
dotnetPath: string;
|
||||
timeoutValue: number;
|
||||
installRuntime: boolean;
|
||||
}
|
||||
|
|
|
@ -4,5 +4,6 @@
|
|||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
export interface IVersionResolver {
|
||||
getFullVersion(version: string): Promise<string>;
|
||||
getFullRuntimeVersion(version: string): Promise<string>;
|
||||
getFullSDKVersion(version: string): Promise<string>;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import { isNullOrUndefined } from 'util';
|
|||
// {
|
||||
// "channel-version": "X.X", --> Major.Minor version this channel represents
|
||||
// "latest-runtime": "X.X.X", --> Most recently released full version of the runtime
|
||||
// "latest-sdk": "X.X.X", --> Most recently released full version of the SDK
|
||||
// ...
|
||||
// },
|
||||
// ...
|
||||
|
@ -24,23 +25,25 @@ export class ReleasesResult {
|
|||
throw new Error('Unable to resolve version: invalid releases data');
|
||||
}
|
||||
this.releasesIndex = releasesJson.map((channel: IReleasesChannel) => {
|
||||
const [ channelVersion, latestRuntime ] = [ channel['channel-version'], channel['latest-runtime'] ];
|
||||
const [ channelVersion, latestRuntime, latestSDK ] = [ channel['channel-version'], channel['latest-runtime'], channel['latest-sdk'] ];
|
||||
if (isNullOrUndefined(channelVersion) || isNullOrUndefined(latestRuntime)) {
|
||||
throw new Error('Unable to resolve version: invalid releases data');
|
||||
}
|
||||
return new ReleasesChannel(channelVersion, latestRuntime);
|
||||
return new ReleasesChannel(channelVersion, latestRuntime, latestSDK);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ReleasesChannel {
|
||||
constructor(public channelVersion: string,
|
||||
public latestRuntime: string) { }
|
||||
public latestRuntime: string,
|
||||
public latestSDK: string) { }
|
||||
}
|
||||
|
||||
interface IReleasesChannel {
|
||||
['channel-version']: string;
|
||||
['latest-runtime']: string;
|
||||
['latest-sdk']: string;
|
||||
}
|
||||
|
||||
type ReleaseChannels = IReleasesChannel[];
|
||||
|
|
|
@ -6,7 +6,10 @@ import * as semver from 'semver';
|
|||
import { isNullOrUndefined } from 'util';
|
||||
import { Memento } from 'vscode';
|
||||
import { IEventStream } from '../EventStream/EventStream';
|
||||
import { DotnetVersionResolutionCompleted, DotnetVersionResolutionError } from '../EventStream/EventStreamEvents';
|
||||
import {
|
||||
DotnetVersionResolutionCompleted,
|
||||
DotnetVersionResolutionError,
|
||||
} from '../EventStream/EventStreamEvents';
|
||||
import { WebRequestWorker } from '../Utils/WebRequestWorker';
|
||||
import { IVersionResolver } from './IVersionResolver';
|
||||
import { ReleasesResult } from './ReleasesResult';
|
||||
|
@ -21,15 +24,18 @@ export class VersionResolver implements IVersionResolver {
|
|||
this.webWorker = new WebRequestWorker(extensionState, eventStream, this.releasesUrl, this.releasesKey);
|
||||
}
|
||||
|
||||
public async getFullVersion(version: string): Promise<string> {
|
||||
try {
|
||||
const response = await this.webWorker.getCachedData();
|
||||
if (!response) {
|
||||
throw new Error('Unable to get the full version.');
|
||||
}
|
||||
public async getFullRuntimeVersion(version: string): Promise<string> {
|
||||
return this.getFullVersion(version, true);
|
||||
}
|
||||
|
||||
const releasesVersions = new ReleasesResult(response);
|
||||
const versionResult = this.resolveVersion(version, releasesVersions);
|
||||
public async getFullSDKVersion(version: string): Promise<string> {
|
||||
return this.getFullVersion(version, false);
|
||||
}
|
||||
|
||||
private async getFullVersion(version: string, runtimeVersion: boolean): Promise<string> {
|
||||
try {
|
||||
const releasesVersions = await this.getReleasesInfo();
|
||||
const versionResult = this.resolveVersion(version, releasesVersions, runtimeVersion);
|
||||
this.eventStream.post(new DotnetVersionResolutionCompleted(version, versionResult));
|
||||
return versionResult;
|
||||
} catch (error) {
|
||||
|
@ -38,15 +44,15 @@ export class VersionResolver implements IVersionResolver {
|
|||
}
|
||||
}
|
||||
|
||||
private resolveVersion(version: string, releases: ReleasesResult): string {
|
||||
private resolveVersion(version: string, releases: ReleasesResult, runtimeVersion: boolean): string {
|
||||
this.validateVersionInput(version);
|
||||
|
||||
const channel = releases.releasesIndex.filter((channelVal) => channelVal.channelVersion === version);
|
||||
if (isNullOrUndefined(channel) || channel.length !== 1) {
|
||||
throw new Error(`Unable to resolve version: ${version}`);
|
||||
}
|
||||
const runtimeVersion = channel[0].latestRuntime;
|
||||
return runtimeVersion;
|
||||
const versionRes = runtimeVersion ? channel[0].latestRuntime : channel[0].latestSDK;
|
||||
return versionRes;
|
||||
}
|
||||
|
||||
private validateVersionInput(version: string) {
|
||||
|
@ -55,4 +61,14 @@ export class VersionResolver implements IVersionResolver {
|
|||
throw new Error(`Invalid version: ${version}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async getReleasesInfo(): Promise<ReleasesResult> {
|
||||
const response = await this.webWorker.getCachedData();
|
||||
if (!response) {
|
||||
throw new Error('Unable to get the full version.');
|
||||
}
|
||||
|
||||
const releasesVersions = new ReleasesResult(response);
|
||||
return releasesVersions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,60 +2,16 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
import * as cp from 'child_process';
|
||||
import open = require('open');
|
||||
import * as os from 'os';
|
||||
import * as vscode from 'vscode';
|
||||
import { IDotnetEnsureDependenciesContext } from '..';
|
||||
import { DotnetCoreDependencyInstaller } from '../Acquisition/DotnetCoreDependencyInstaller';
|
||||
import { IDotnetCoreAcquisitionWorker } from '../Acquisition/IDotnetCoreAcquisitionWorker';
|
||||
import { EventStream } from '../EventStream/EventStream';
|
||||
import { DotnetAcquisitionMissingLinuxDependencies } from '../EventStream/EventStreamEvents';
|
||||
import { IWindowDisplayWorker } from '../EventStream/IWindowDisplayWorker';
|
||||
import { IDotnetUninstallContext } from '../IDotnetUninstallContext';
|
||||
import { AcquireErrorConfiguration, callWithErrorHandling } from '../Utils/ErrorHandler';
|
||||
import { IExtensionConfigurationWorker } from '../Utils/IExtensionConfigurationWorker';
|
||||
import { AcquireErrorConfiguration } from '../Utils/ErrorHandler';
|
||||
import { formatIssueUrl } from '../Utils/IssueReporter';
|
||||
import { commandKeys, ICommand, ICommandProvider, IssueContextCallback } from './ICommandProvider';
|
||||
import { commandKeys, ICommand, ICommandProvider, IExtensionCommandContext, IssueContextCallback } from './ICommandProvider';
|
||||
|
||||
export abstract class BaseCommandProvider implements ICommandProvider {
|
||||
public abstract GetExtensionCommands(acquisitionWorker: IDotnetCoreAcquisitionWorker,
|
||||
extensionConfigWorker: IExtensionConfigurationWorker,
|
||||
displayWorker: IWindowDisplayWorker,
|
||||
eventStream: EventStream,
|
||||
issueContext: IssueContextCallback): ICommand[];
|
||||
public abstract GetExtensionCommands(context: IExtensionCommandContext): ICommand[];
|
||||
|
||||
// Shared commands
|
||||
protected getUninstallAllCommand(acquisitionWorker: IDotnetCoreAcquisitionWorker, issueContext: IssueContextCallback): ICommand {
|
||||
return {
|
||||
name: commandKeys.uninstallAll,
|
||||
callback: async (commandContext: IDotnetUninstallContext | undefined) => {
|
||||
await callWithErrorHandling(() => acquisitionWorker.uninstallAll(), issueContext(commandContext ? commandContext.errorConfiguration : undefined, 'uninstallAll'));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected getEnsureDependenciesCommand(eventStream: EventStream, issueContext: IssueContextCallback): ICommand {
|
||||
return {
|
||||
name: commandKeys.ensureDotnetDependencies,
|
||||
callback: async (commandContext: IDotnetEnsureDependenciesContext) => {
|
||||
await callWithErrorHandling(async () => {
|
||||
if (os.platform() !== 'linux') {
|
||||
// We can't handle installing dependencies for anything other than Linux
|
||||
return;
|
||||
}
|
||||
|
||||
const result = cp.spawnSync(commandContext.command, commandContext.arguments);
|
||||
const installer = new DotnetCoreDependencyInstaller();
|
||||
if (installer.signalIndicatesMissingLinuxDependencies(result.signal)) {
|
||||
eventStream.post(new DotnetAcquisitionMissingLinuxDependencies());
|
||||
await installer.promptLinuxDependencyInstall('Failed to run .NET runtime.');
|
||||
}
|
||||
}, issueContext(commandContext.errorConfiguration, 'ensureDependencies'));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected getReportIssueCommand(issueContext: IssueContextCallback): ICommand {
|
||||
return {
|
||||
name: commandKeys.reportIssue,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
import { IDotnetCoreAcquisitionWorker } from '../Acquisition/IDotnetCoreAcquisitionWorker';
|
||||
import { IVersionResolver } from '../Acquisition/IVersionResolver';
|
||||
import { EventStream } from '../EventStream/EventStream';
|
||||
import { IWindowDisplayWorker } from '../EventStream/IWindowDisplayWorker';
|
||||
import { ErrorConfiguration } from '../Utils/ErrorHandler';
|
||||
|
@ -25,10 +26,15 @@ export namespace commandKeys {
|
|||
export const reportIssue = 'reportIssue';
|
||||
}
|
||||
|
||||
export interface ICommandProvider {
|
||||
GetExtensionCommands(acquisitionWorker: IDotnetCoreAcquisitionWorker,
|
||||
extensionConfigWorker: IExtensionConfigurationWorker,
|
||||
displayWorker: IWindowDisplayWorker,
|
||||
eventStream: EventStream,
|
||||
issueContext: IssueContextCallback): ICommand[];
|
||||
export interface IExtensionCommandContext {
|
||||
acquisitionWorker: IDotnetCoreAcquisitionWorker;
|
||||
extensionConfigWorker: IExtensionConfigurationWorker;
|
||||
displayWorker: IWindowDisplayWorker;
|
||||
versionResolver: IVersionResolver;
|
||||
eventStream: EventStream;
|
||||
issueContext: IssueContextCallback;
|
||||
}
|
||||
|
||||
export interface ICommandProvider {
|
||||
GetExtensionCommands(context: IExtensionCommandContext): ICommand[];
|
||||
}
|
||||
|
|
|
@ -2,34 +2,37 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
import * as cp from 'child_process';
|
||||
import * as os from 'os';
|
||||
import { DotnetCoreDependencyInstaller } from '../Acquisition/DotnetCoreDependencyInstaller';
|
||||
import { IDotnetCoreAcquisitionWorker } from '../Acquisition/IDotnetCoreAcquisitionWorker';
|
||||
import { IVersionResolver } from '../Acquisition/IVersionResolver';
|
||||
import { EventStream } from '../EventStream/EventStream';
|
||||
import { DotnetAcquisitionRequested, DotnetExistingPathResolutionCompleted } from '../EventStream/EventStreamEvents';
|
||||
import { DotnetAcquisitionMissingLinuxDependencies, DotnetAcquisitionRequested, DotnetExistingPathResolutionCompleted } from '../EventStream/EventStreamEvents';
|
||||
import { IWindowDisplayWorker } from '../EventStream/IWindowDisplayWorker';
|
||||
import { IDotnetAcquireContext } from '../IDotnetAcquireContext';
|
||||
import { IDotnetAcquireResult } from '../IDotnetAcquireResult';
|
||||
import { IDotnetEnsureDependenciesContext } from '../IDotnetEnsureDependenciesContext';
|
||||
import { IDotnetUninstallContext } from '../IDotnetUninstallContext';
|
||||
import { callWithErrorHandling } from '../Utils/ErrorHandler';
|
||||
import { IExtensionConfigurationWorker } from '../Utils/IExtensionConfigurationWorker';
|
||||
import { BaseCommandProvider } from './BaseCommandProvider';
|
||||
import { commandKeys, ICommand, IssueContextCallback } from './ICommandProvider';
|
||||
import { commandKeys, ICommand, IExtensionCommandContext, IssueContextCallback } from './ICommandProvider';
|
||||
|
||||
export class RuntimeCommandProvider extends BaseCommandProvider {
|
||||
public GetExtensionCommands(acquisitionWorker: IDotnetCoreAcquisitionWorker,
|
||||
extensionConfigWorker: IExtensionConfigurationWorker,
|
||||
displayWorker: IWindowDisplayWorker,
|
||||
eventStream: EventStream,
|
||||
issueContext: IssueContextCallback): ICommand[] {
|
||||
public GetExtensionCommands(context: IExtensionCommandContext): ICommand[] {
|
||||
return [
|
||||
this.getUninstallAllCommand(acquisitionWorker, issueContext),
|
||||
this.getEnsureDependenciesCommand(eventStream, issueContext),
|
||||
this.getReportIssueCommand(issueContext),
|
||||
this.getAcquireCommand(acquisitionWorker, extensionConfigWorker, displayWorker, eventStream, issueContext),
|
||||
this.getUninstallAllCommand(context.acquisitionWorker, context.issueContext),
|
||||
this.getEnsureDependenciesCommand(context.eventStream, context.issueContext),
|
||||
this.getReportIssueCommand(context.issueContext),
|
||||
this.getAcquireCommand(context.acquisitionWorker, context.extensionConfigWorker, context.displayWorker, context.versionResolver, context.eventStream, context.issueContext),
|
||||
];
|
||||
}
|
||||
|
||||
private getAcquireCommand(acquisitionWorker: IDotnetCoreAcquisitionWorker,
|
||||
extensionConfigWorker: IExtensionConfigurationWorker,
|
||||
displayWorker: IWindowDisplayWorker,
|
||||
versionResolver: IVersionResolver,
|
||||
eventStream: EventStream,
|
||||
issueContext: IssueContextCallback): ICommand {
|
||||
return {
|
||||
|
@ -50,10 +53,41 @@ export class RuntimeCommandProvider extends BaseCommandProvider {
|
|||
});
|
||||
}
|
||||
|
||||
return acquisitionWorker.acquire(commandContext.version);
|
||||
const version = await versionResolver.getFullRuntimeVersion(commandContext.version);
|
||||
return acquisitionWorker.acquireRuntime(version);
|
||||
}, issueContext(commandContext.errorConfiguration, 'acquire', commandContext.version), commandContext.requestingExtensionId);
|
||||
return dotnetPath;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private getUninstallAllCommand(acquisitionWorker: IDotnetCoreAcquisitionWorker, issueContext: IssueContextCallback): ICommand {
|
||||
return {
|
||||
name: commandKeys.uninstallAll,
|
||||
callback: async (commandContext: IDotnetUninstallContext | undefined) => {
|
||||
await callWithErrorHandling(async () => acquisitionWorker.uninstallAll(), issueContext(commandContext ? commandContext.errorConfiguration : undefined, 'uninstallAll'));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private getEnsureDependenciesCommand(eventStream: EventStream, issueContext: IssueContextCallback): ICommand {
|
||||
return {
|
||||
name: commandKeys.ensureDotnetDependencies,
|
||||
callback: async (commandContext: IDotnetEnsureDependenciesContext) => {
|
||||
await callWithErrorHandling(async () => {
|
||||
if (os.platform() !== 'linux') {
|
||||
// We can't handle installing dependencies for anything other than Linux
|
||||
return;
|
||||
}
|
||||
|
||||
const result = cp.spawnSync(commandContext.command, commandContext.arguments);
|
||||
const installer = new DotnetCoreDependencyInstaller();
|
||||
if (installer.signalIndicatesMissingLinuxDependencies(result.signal)) {
|
||||
eventStream.post(new DotnetAcquisitionMissingLinuxDependencies());
|
||||
await installer.promptLinuxDependencyInstall('Failed to run .NET runtime.');
|
||||
}
|
||||
}, issueContext(commandContext.errorConfiguration, 'ensureDependencies'));
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,51 +2,70 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
import { DotnetCoreAcquisitionWorker } from '../Acquisition/DotnetCoreAcquisitionWorker';
|
||||
import * as vscode from 'vscode';
|
||||
import { IDotnetCoreAcquisitionWorker } from '../Acquisition/IDotnetCoreAcquisitionWorker';
|
||||
import { IVersionResolver } from '../Acquisition/IVersionResolver';
|
||||
import { EventStream } from '../EventStream/EventStream';
|
||||
import { DotnetAcquisitionRequested } from '../EventStream/EventStreamEvents';
|
||||
import { IWindowDisplayWorker } from '../EventStream/IWindowDisplayWorker';
|
||||
import { IDotnetAcquireContext } from '../IDotnetAcquireContext';
|
||||
import { IDotnetAcquireResult } from '../IDotnetAcquireResult';
|
||||
import { IDotnetUninstallContext } from '../IDotnetUninstallContext';
|
||||
import { callWithErrorHandling } from '../Utils/ErrorHandler';
|
||||
import { IExtensionConfigurationWorker } from '../Utils/IExtensionConfigurationWorker';
|
||||
import { BaseCommandProvider } from './BaseCommandProvider';
|
||||
import { commandKeys, ICommand, IssueContextCallback } from './ICommandProvider';
|
||||
import { commandKeys, ICommand, IExtensionCommandContext, IssueContextCallback } from './ICommandProvider';
|
||||
|
||||
export class SDKCommandProvider extends BaseCommandProvider {
|
||||
public GetExtensionCommands(acquisitionWorker: DotnetCoreAcquisitionWorker,
|
||||
extensionConfigWorker: IExtensionConfigurationWorker,
|
||||
displayWorker: IWindowDisplayWorker,
|
||||
eventStream: EventStream,
|
||||
issueContext: IssueContextCallback): ICommand[] {
|
||||
public GetExtensionCommands(context: IExtensionCommandContext): ICommand[] {
|
||||
return [
|
||||
this.getUninstallAllCommand(acquisitionWorker, issueContext),
|
||||
this.getEnsureDependenciesCommand(eventStream, issueContext),
|
||||
this.getReportIssueCommand(issueContext),
|
||||
this.getAcquireCommand(acquisitionWorker, displayWorker, eventStream, issueContext),
|
||||
this.getUninstallAllCommand(context.acquisitionWorker, context.displayWorker, context.issueContext),
|
||||
this.getReportIssueCommand(context.issueContext),
|
||||
this.getAcquireCommand(context.acquisitionWorker, context.displayWorker, context.versionResolver, context.eventStream, context.issueContext),
|
||||
];
|
||||
}
|
||||
|
||||
private getAcquireCommand(acquisitionWorker: DotnetCoreAcquisitionWorker,
|
||||
protected getUninstallAllCommand(acquisitionWorker: IDotnetCoreAcquisitionWorker,
|
||||
displayWorker: IWindowDisplayWorker,
|
||||
issueContext: IssueContextCallback): ICommand {
|
||||
return {
|
||||
name: commandKeys.uninstallAll,
|
||||
callback: async (commandContext: IDotnetUninstallContext | undefined) => {
|
||||
await callWithErrorHandling(async () => {
|
||||
await acquisitionWorker.uninstallAll();
|
||||
displayWorker.showInformationMessage('All VS Code copies of the .NET SDK uninstalled.', () => { /* No callback needed */ });
|
||||
}, issueContext(commandContext ? commandContext.errorConfiguration : undefined, 'uninstallAll'));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private getAcquireCommand(acquisitionWorker: IDotnetCoreAcquisitionWorker,
|
||||
displayWorker: IWindowDisplayWorker,
|
||||
versionResolver: IVersionResolver,
|
||||
eventStream: EventStream,
|
||||
issueContext: IssueContextCallback): ICommand {
|
||||
return {
|
||||
name: commandKeys.acquire,
|
||||
callback: async (commandContext: IDotnetAcquireContext) => {
|
||||
const dotnetPath = await callWithErrorHandling<Promise<IDotnetAcquireResult>>(async () => {
|
||||
eventStream.post(new DotnetAcquisitionRequested(commandContext.version, commandContext.requestingExtensionId));
|
||||
callback: async (commandContext?: IDotnetAcquireContext) => {
|
||||
return callWithErrorHandling(async () => {
|
||||
let version: string | undefined = commandContext ? commandContext.version : undefined;
|
||||
if (!version) {
|
||||
version = await vscode.window.showInputBox({
|
||||
placeHolder: '5.0',
|
||||
value: '5.0',
|
||||
prompt: '.NET version, i.e. 5.0',
|
||||
});
|
||||
}
|
||||
if (!version) {
|
||||
displayWorker.showErrorMessage('No .NET SDK version provided', () => { /* No callback needed */ });
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!commandContext.version || commandContext.version === 'latest') {
|
||||
throw new Error(`Cannot acquire .NET SDK version "${commandContext.version}". Please provide a valid version.`);
|
||||
}
|
||||
|
||||
return acquisitionWorker.acquire(commandContext.version);
|
||||
}, issueContext(commandContext.errorConfiguration, 'acquire', commandContext.version), commandContext.requestingExtensionId);
|
||||
|
||||
// TODO add to PATH instead
|
||||
displayWorker.showWarningMessage(`SDK installed: ${dotnetPath}`, () => { /* No callback */ },
|
||||
);
|
||||
eventStream.post(new DotnetAcquisitionRequested(version!));
|
||||
const resolvedVersion = await versionResolver.getFullSDKVersion(version!);
|
||||
const dotnetPath = await acquisitionWorker.acquireSDK(resolvedVersion);
|
||||
displayWorker.showInformationMessage(`.NET SDK ${version} installed to ${dotnetPath.dotnetPath}`, () => { /* No callback needed */ });
|
||||
// TODO add to PATH?
|
||||
return dotnetPath;
|
||||
}, issueContext(undefined, 'acquireSDK'));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ export class OutputChannelObserver implements IEventStreamObserver {
|
|||
}
|
||||
|
||||
const startVersionString = this.inProgressDownloads.join(', ');
|
||||
this.outputChannel.append(`Downloading .NET runtime version(s) ${startVersionString} ...`);
|
||||
this.outputChannel.append(`Downloading .NET version(s) ${startVersionString} ...`);
|
||||
break;
|
||||
case EventType.DotnetAcquisitionCompleted:
|
||||
const acquisitionCompleted = event as DotnetAcquisitionCompleted;
|
||||
|
@ -50,7 +50,7 @@ export class OutputChannelObserver implements IEventStreamObserver {
|
|||
|
||||
if (this.inProgressDownloads.length > 0) {
|
||||
const completedVersionString = `'${this.inProgressDownloads.join('\', \'')}'`;
|
||||
this.outputChannel.append(`Still downloading .NET runtime version(s) ${completedVersionString} ...`);
|
||||
this.outputChannel.append(`Still downloading .NET version(s) ${completedVersionString} ...`);
|
||||
} else {
|
||||
this.stopDownloadIndicator();
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ export class OutputChannelObserver implements IEventStreamObserver {
|
|||
const error = event as DotnetAcquisitionError;
|
||||
this.outputChannel.appendLine(' Error!');
|
||||
if (error instanceof DotnetAcquisitionVersionError) {
|
||||
this.outputChannel.appendLine(`Failed to download .NET runtime ${error.version}:`);
|
||||
this.outputChannel.appendLine(`Failed to download .NET ${error.version}:`);
|
||||
}
|
||||
this.outputChannel.appendLine(error.error.message);
|
||||
this.outputChannel.appendLine('');
|
||||
|
@ -75,7 +75,7 @@ export class OutputChannelObserver implements IEventStreamObserver {
|
|||
|
||||
if (this.inProgressDownloads.length > 0) {
|
||||
const errorVersionString = this.inProgressDownloads.join(', ');
|
||||
this.outputChannel.append(`Still downloading .NET runtime version(s) ${errorVersionString} ...`);
|
||||
this.outputChannel.append(`Still downloading .NET version(s) ${errorVersionString} ...`);
|
||||
} else {
|
||||
this.stopDownloadIndicator();
|
||||
}
|
||||
|
|
|
@ -20,13 +20,13 @@ export class StatusBarObserver implements IEventStreamObserver {
|
|||
public post(event: IEvent): void {
|
||||
switch (event.type) {
|
||||
case EventType.DotnetAcquisitionStart:
|
||||
this.setAndShowStatusBar('$(cloud-download) Downloading .NET runtime...', 'dotnet.showAcquisitionLog', '', 'Downloading .NET runtime...');
|
||||
this.setAndShowStatusBar('$(cloud-download) Downloading .NET...', 'dotnet.showAcquisitionLog', '', 'Downloading .NET...');
|
||||
break;
|
||||
case EventType.DotnetAcquisitionCompleted:
|
||||
this.resetAndHideStatusBar();
|
||||
break;
|
||||
case EventType.DotnetAcquisitionError:
|
||||
this.setAndShowStatusBar('$(alert) Error acquiring .NET runtime!', 'dotnet.showAcquisitionLog', StatusBarColors.Red, 'Error acquiring .NET runtime');
|
||||
this.setAndShowStatusBar('$(alert) Error acquiring .NET!', 'dotnet.showAcquisitionLog', StatusBarColors.Red, 'Error acquiring .NET');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ export interface IExtensionContext {
|
|||
displayChannelName: string;
|
||||
defaultTimeoutValue: number;
|
||||
commandProvider: ICommandProvider;
|
||||
storagePath?: string;
|
||||
telemetryReporter?: ITelemetryReporter;
|
||||
extensionConfiguration?: IExtensionConfiguration;
|
||||
displayWorker?: IWindowDisplayWorker;
|
||||
|
|
|
@ -9,7 +9,7 @@ import { AcquisitionInvoker } from './Acquisition/AcquisitionInvoker';
|
|||
import { DotnetCoreAcquisitionWorker } from './Acquisition/DotnetCoreAcquisitionWorker';
|
||||
import { InstallationValidator } from './Acquisition/InstallationValidator';
|
||||
import { VersionResolver } from './Acquisition/VersionResolver';
|
||||
import { commandKeys } from './Commands/ICommandProvider';
|
||||
import { commandKeys, IExtensionCommandContext } from './Commands/ICommandProvider';
|
||||
import { EventStream } from './EventStream/EventStream';
|
||||
import { IEventStreamObserver } from './EventStream/IEventStreamObserver';
|
||||
import { LoggingObserver } from './EventStream/LoggingObserver';
|
||||
|
@ -76,15 +76,15 @@ export function activate(context: vscode.ExtensionContext, extensionId: string,
|
|||
} as IIssueContext;
|
||||
};
|
||||
const timeoutValue = extensionConfiguration.get<number>(configKeys.installTimeoutValue);
|
||||
if (!fs.existsSync(context.globalStoragePath)) {
|
||||
fs.mkdirSync(context.globalStoragePath);
|
||||
const storagePath = extensionContext.storagePath ? extensionContext.storagePath : context.globalStoragePath;
|
||||
if (!fs.existsSync(storagePath)) {
|
||||
fs.mkdirSync(storagePath);
|
||||
}
|
||||
const acquisitionWorker = new DotnetCoreAcquisitionWorker({
|
||||
storagePath: context.globalStoragePath,
|
||||
storagePath,
|
||||
extensionState: context.globalState,
|
||||
eventStream,
|
||||
acquisitionInvoker: new AcquisitionInvoker(context.globalState, eventStream),
|
||||
versionResolver: new VersionResolver(context.globalState, eventStream), // TODO or sdk version resolver
|
||||
installationValidator: new InstallationValidator(eventStream),
|
||||
timeoutValue: timeoutValue === undefined ? extensionContext.defaultTimeoutValue : timeoutValue,
|
||||
});
|
||||
|
@ -92,7 +92,15 @@ export function activate(context: vscode.ExtensionContext, extensionId: string,
|
|||
const showOutputChannelRegistration = vscode.commands.registerCommand(`${extensionContext.commandPrefix}.${commandKeys.showAcquisitionLog}`, () => outputChannel.show(/* preserveFocus */ false));
|
||||
context.subscriptions.push(showOutputChannelRegistration);
|
||||
|
||||
const commands = extensionContext.commandProvider.GetExtensionCommands(acquisitionWorker, extensionConfigWorker, displayWorker, eventStream, issueContext);
|
||||
const commandContext = {
|
||||
acquisitionWorker,
|
||||
extensionConfigWorker,
|
||||
displayWorker,
|
||||
versionResolver: new VersionResolver(context.globalState, eventStream),
|
||||
eventStream,
|
||||
issueContext,
|
||||
} as IExtensionCommandContext;
|
||||
const commands = extensionContext.commandProvider.GetExtensionCommands(commandContext);
|
||||
for (const command of commands) {
|
||||
const registration = vscode.commands.registerCommand(`${extensionContext.commandPrefix}.${command.name}`, command.callback);
|
||||
context.subscriptions.push(registration);
|
||||
|
|
|
@ -19,10 +19,8 @@ import {
|
|||
MockEventStream,
|
||||
MockExtensionContext,
|
||||
MockInstallationValidator,
|
||||
MockVersionResolver,
|
||||
NoInstallAcquisitionInvoker,
|
||||
RejectingAcquisitionInvoker,
|
||||
versionPairs,
|
||||
} from '../mocks/MockObjects';
|
||||
const assert = chai.assert;
|
||||
chai.use(chaiAsPromised);
|
||||
|
@ -39,7 +37,6 @@ suite('DotnetCoreAcquisitionWorker Unit Tests', function() {
|
|||
extensionState: context,
|
||||
eventStream,
|
||||
acquisitionInvoker: new NoInstallAcquisitionInvoker(eventStream),
|
||||
versionResolver: new MockVersionResolver(context, eventStream),
|
||||
installationValidator: new MockInstallationValidator(eventStream),
|
||||
timeoutValue: 10,
|
||||
});
|
||||
|
@ -84,20 +81,27 @@ suite('DotnetCoreAcquisitionWorker Unit Tests', function() {
|
|||
process.env._VSCODE_DOTNET_INSTALL_FOLDER = dotnetFolderName;
|
||||
});
|
||||
|
||||
test('Acquire Version', async () => {
|
||||
test('Acquire Runtime Version', async () => {
|
||||
const [acquisitionWorker, eventStream, context] = getTestAcquisitionWorker();
|
||||
|
||||
const result = await acquisitionWorker.acquire(versionPairs[0][0]);
|
||||
await assertAcquisitionSucceeded(versionPairs[0][1], result.dotnetPath, eventStream, context);
|
||||
const result = await acquisitionWorker.acquireRuntime('1.0');
|
||||
await assertAcquisitionSucceeded('1.0', result.dotnetPath, eventStream, context);
|
||||
});
|
||||
|
||||
test('Acquire Version Multiple Times', async () => {
|
||||
test('Acquire SDK Version', async () => {
|
||||
const [acquisitionWorker, eventStream, context] = getTestAcquisitionWorker();
|
||||
|
||||
const result = await acquisitionWorker.acquireSDK('5.0');
|
||||
await assertAcquisitionSucceeded('5.0', result.dotnetPath, eventStream, context);
|
||||
});
|
||||
|
||||
test('Acquire Runtime Version Multiple Times', async () => {
|
||||
const numAcquisitions = 3;
|
||||
const [acquisitionWorker, eventStream, context] = getTestAcquisitionWorker();
|
||||
|
||||
for (let i = 0; i < numAcquisitions; i++) {
|
||||
const pathResult = await acquisitionWorker.acquire(versionPairs[0][0]);
|
||||
await assertAcquisitionSucceeded(versionPairs[0][1], pathResult.dotnetPath, eventStream, context);
|
||||
const pathResult = await acquisitionWorker.acquireRuntime('1.0');
|
||||
await assertAcquisitionSucceeded('1.0', pathResult.dotnetPath, eventStream, context);
|
||||
}
|
||||
|
||||
// AcquisitionInvoker was only called once
|
||||
|
@ -107,20 +111,21 @@ suite('DotnetCoreAcquisitionWorker Unit Tests', function() {
|
|||
|
||||
test('Acquire Multiple Versions and UninstallAll', async () => {
|
||||
const [acquisitionWorker, eventStream, context] = getTestAcquisitionWorker();
|
||||
for (const version of versionPairs) {
|
||||
const res = await acquisitionWorker.acquire(version[0]);
|
||||
await assertAcquisitionSucceeded(version[1], res.dotnetPath, eventStream, context);
|
||||
const versions = [ '1.0', '1.1', '2.0', '2.1', '2.2' ];
|
||||
for (const version of versions) {
|
||||
const res = await acquisitionWorker.acquireRuntime(version);
|
||||
await assertAcquisitionSucceeded(version, res.dotnetPath, eventStream, context);
|
||||
}
|
||||
await acquisitionWorker.uninstallAll();
|
||||
assert.exists(eventStream.events.find(event => event instanceof DotnetUninstallAllStarted));
|
||||
assert.exists(eventStream.events.find(event => event instanceof DotnetUninstallAllCompleted));
|
||||
});
|
||||
|
||||
test('Acquire and UninstallAll', async () => {
|
||||
test('Acquire Runtime and UninstallAll', async () => {
|
||||
const [acquisitionWorker, eventStream, context] = getTestAcquisitionWorker();
|
||||
|
||||
const res = await acquisitionWorker.acquire(versionPairs[0][0]);
|
||||
await assertAcquisitionSucceeded(versionPairs[0][1], res.dotnetPath, eventStream, context);
|
||||
const res = await acquisitionWorker.acquireRuntime('1.0');
|
||||
await assertAcquisitionSucceeded('1.0', res.dotnetPath, eventStream, context);
|
||||
|
||||
await acquisitionWorker.uninstallAll();
|
||||
assert.exists(eventStream.events.find(event => event instanceof DotnetUninstallAllStarted));
|
||||
|
@ -130,9 +135,9 @@ suite('DotnetCoreAcquisitionWorker Unit Tests', function() {
|
|||
test('Repeated Acquisition', async () => {
|
||||
const [acquisitionWorker, eventStream, context] = getTestAcquisitionWorker();
|
||||
for (let i = 0; i < 3; i ++) {
|
||||
await acquisitionWorker.acquire(versionPairs[0][0]);
|
||||
await acquisitionWorker.acquireRuntime('1.0');
|
||||
}
|
||||
// We should only actually acquire once
|
||||
// We should only actually Acquire once
|
||||
const events = eventStream.events.filter(event => event instanceof DotnetAcquisitionStarted);
|
||||
assert.equal(events.length, 1);
|
||||
});
|
||||
|
@ -145,11 +150,10 @@ suite('DotnetCoreAcquisitionWorker Unit Tests', function() {
|
|||
extensionState: context,
|
||||
eventStream,
|
||||
acquisitionInvoker: new RejectingAcquisitionInvoker(eventStream),
|
||||
versionResolver: new MockVersionResolver(context, eventStream),
|
||||
installationValidator: new MockInstallationValidator(eventStream),
|
||||
timeoutValue: 10,
|
||||
});
|
||||
|
||||
return assert.isRejected(acquisitionWorker.acquire(versionPairs[0][0]), '.NET Acquisition Failed: Installation failed: Rejecting message');
|
||||
return assert.isRejected(acquisitionWorker.acquireRuntime('1.0'), '.NET Acquisition Failed: Installation failed: Rejecting message');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,20 +14,24 @@ suite('VersionResolver Unit Tests', () => {
|
|||
const resolver: MockVersionResolver = new MockVersionResolver(context, eventStream);
|
||||
|
||||
test('Error With Invalid Version', async () => {
|
||||
return assert.isRejected(resolver.getFullVersion('foo'), Error, 'Invalid version');
|
||||
return assert.isRejected(resolver.getFullRuntimeVersion('foo'), Error, 'Invalid version');
|
||||
});
|
||||
|
||||
test('Error With Three Part Version', async () => {
|
||||
return assert.isRejected(resolver.getFullVersion('1.0.16'), Error, 'Invalid version');
|
||||
return assert.isRejected(resolver.getFullRuntimeVersion('1.0.16'), Error, 'Invalid version');
|
||||
});
|
||||
|
||||
test('Error With Invalid Major.Minor', async () => {
|
||||
return assert.isRejected(resolver.getFullVersion('0.0'), Error, 'Unable to resolve version');
|
||||
return assert.isRejected(resolver.getFullRuntimeVersion('0.0'), Error, 'Unable to resolve version');
|
||||
});
|
||||
|
||||
test('Resolve Valid Versions', async () => {
|
||||
test('Resolve Valid Runtime Versions', async () => {
|
||||
for (const version of versionPairs) {
|
||||
assert.equal(await resolver.getFullVersion(version[0]), version[1]);
|
||||
assert.equal(await resolver.getFullRuntimeVersion(version[0]), version[1]);
|
||||
}
|
||||
});
|
||||
|
||||
test('Resolve Latest SDK Version', async () => {
|
||||
assert.equal(await resolver.getFullSDKVersion('2.2'), '2.2.207');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
* ------------------------------------------------------------------------------------------ */
|
||||
import * as chai from 'chai';
|
||||
import * as chaiAsPromised from 'chai-as-promised';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { DotnetCoreAcquisitionWorker } from '../../Acquisition/DotnetCoreAcquisitionWorker';
|
||||
import { IInstallScriptAcquisitionWorker } from '../../Acquisition/IInstallScriptAcquisitionWorker';
|
||||
|
@ -19,9 +17,7 @@ import {
|
|||
MockExtensionContext,
|
||||
MockInstallationValidator,
|
||||
MockInstallScriptWorker,
|
||||
MockVersionResolver,
|
||||
MockWebRequestWorker,
|
||||
versionPairs,
|
||||
} from '../mocks/MockObjects';
|
||||
const assert = chai.assert;
|
||||
chai.use(chaiAsPromised);
|
||||
|
@ -41,11 +37,10 @@ suite('WebRequestWorker Unit Tests', () => {
|
|||
extensionState: context,
|
||||
eventStream,
|
||||
acquisitionInvoker: new ErrorAcquisitionInvoker(eventStream),
|
||||
versionResolver: new MockVersionResolver(context, eventStream),
|
||||
installationValidator: new MockInstallationValidator(eventStream),
|
||||
timeoutValue: 10,
|
||||
});
|
||||
return assert.isRejected(acquisitionWorker.acquire(versionPairs[0][0]), Error, '.NET Acquisition Failed');
|
||||
return assert.isRejected(acquisitionWorker.acquireRuntime('1.0'), Error, '.NET Acquisition Failed');
|
||||
});
|
||||
|
||||
test('Install Script Request Failure', async () => {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "compile-all"
|
||||
},
|
||||
|
@ -20,10 +20,10 @@
|
|||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"--extensionTestsPath=${workspaceFolder}/out/test/functional"
|
||||
"--extensionTestsPath=${workspaceFolder}/dist/test/functional"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/test/**/*.js"
|
||||
"${workspaceFolder}/dist/test/**/*.js"
|
||||
],
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"preLaunchTask": "compile-all"
|
||||
|
|
|
@ -26,15 +26,55 @@
|
|||
"dotnet",
|
||||
".NET SDK"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onCommand:dotnet-sdk.acquire",
|
||||
"onCommand:dotnet-sdk.uninstallAll",
|
||||
"onCommand:dotnet-sdk.showAcquisitionLog",
|
||||
"onCommand:dotnet-sdk.reportIssue"
|
||||
],
|
||||
"main": "./dist/extension.js",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "dotnet-sdk.reportIssue",
|
||||
"title": "Report an issue with the .NET SDK Install Tool.",
|
||||
"category": ".NET SDK Install Tool"
|
||||
},
|
||||
{
|
||||
"command": "dotnet-sdk.acquire",
|
||||
"title": "Install the .NET SDK.",
|
||||
"category": ".NET SDK Install Tool"
|
||||
},
|
||||
{
|
||||
"command": "dotnet-sdk.uninstallAll",
|
||||
"title": "Uninstall all VS Code copies of .NET SDK.",
|
||||
"category": ".NET SDK Install Tool"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"title": ".NET SDK Install Tool",
|
||||
"properties": {
|
||||
"dotnetSDKAcquisitionExtension.enableTelemetry": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Enable Telemetry for the .NET SDK install tool."
|
||||
},
|
||||
"dotnetSDKAcquisitionExtension.installTimeoutValue": {
|
||||
"type": "number",
|
||||
"default": 120,
|
||||
"description": "Timeout for installing .NET SDK in seconds."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "npm run compile-all && npm install && webpack --mode production",
|
||||
"compile": "npm run clean && tsc -p ./",
|
||||
"watch": "npm run compile && tsc -watch -p ./",
|
||||
"test": "npm run compile --silent && node ./dist/test/functional/runTest.js",
|
||||
"clean": "rimraf dist",
|
||||
"compile-all": "cd ../vscode-dotnet-runtime-library && npm install && npm run compile && cd ../vscode-dotnet-runtime-extension && npm install && npm run compile",
|
||||
"lint": "tslint -c ../tslint.json '../vscode-dotnet-runtime-library/src/**/*.ts' '../vscode-dotnet-runtime-extension/src/**/*.ts'",
|
||||
"compile-all": "cd ../vscode-dotnet-runtime-library && npm install && npm run compile && cd ../vscode-dotnet-sdk-extension && npm install && npm run compile",
|
||||
"lint": "tslint -c ../tslint.json '../vscode-dotnet-runtime-library/src/**/*.ts' '../vscode-dotnet-sdk-extension/src/**/*.ts'",
|
||||
"webpack": "webpack --mode development"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
@ -3,10 +3,78 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
import * as chai from 'chai';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as rimraf from 'rimraf';
|
||||
import * as vscode from 'vscode';
|
||||
import {
|
||||
defaultSDKContext,
|
||||
IDotnetAcquireContext,
|
||||
IDotnetAcquireResult,
|
||||
MockExtensionConfiguration,
|
||||
MockExtensionContext,
|
||||
MockTelemetryReporter,
|
||||
MockWindowDisplayWorker,
|
||||
} from 'vscode-dotnet-runtime-library';
|
||||
import * as extension from '../../extension';
|
||||
const assert = chai.assert;
|
||||
/* tslint:disable:no-any */
|
||||
|
||||
suite('DotnetCoreAcquisitionExtension End to End', () => {
|
||||
test('Test', async () => {
|
||||
assert.isTrue(true);
|
||||
suite('DotnetCoreAcquisitionExtension End to End', function() {
|
||||
this.retries(3);
|
||||
const storagePath = path.join(__dirname, 'tmp');
|
||||
const mockState = new MockExtensionContext();
|
||||
const extensionPath = path.join(__dirname, '/../../..');
|
||||
const logPath = path.join(__dirname, 'logs');
|
||||
const mockDisplayWorker = new MockWindowDisplayWorker();
|
||||
let extensionContext: vscode.ExtensionContext;
|
||||
|
||||
this.beforeAll(async () => {
|
||||
extensionContext = {
|
||||
subscriptions: [],
|
||||
globalStoragePath: storagePath,
|
||||
globalState: mockState,
|
||||
extensionPath,
|
||||
logPath,
|
||||
} as any;
|
||||
const context = defaultSDKContext;
|
||||
context.displayWorker = mockDisplayWorker;
|
||||
context.telemetryReporter = new MockTelemetryReporter();
|
||||
context.extensionConfiguration = new MockExtensionConfiguration([], true);
|
||||
extension.activate(extensionContext, context);
|
||||
});
|
||||
|
||||
this.afterEach(async () => {
|
||||
// Tear down tmp storage for fresh run
|
||||
await vscode.commands.executeCommand<string>(`${defaultSDKContext.commandPrefix}.uninstallAll`);
|
||||
mockState.clear();
|
||||
MockTelemetryReporter.telemetryEvents = [];
|
||||
rimraf.sync(storagePath);
|
||||
});
|
||||
|
||||
test('Activate', async () => {
|
||||
// Commands should now be registered
|
||||
assert.exists(extensionContext);
|
||||
assert.isAbove(extensionContext.subscriptions.length, 0);
|
||||
});
|
||||
|
||||
test('Install Command', async () => {
|
||||
const context: IDotnetAcquireContext = { version: '5.0' };
|
||||
const result = await vscode.commands.executeCommand<IDotnetAcquireResult>(`${defaultSDKContext.commandPrefix}.acquire`, context);
|
||||
assert.exists(result);
|
||||
assert.exists(result!.dotnetPath);
|
||||
assert.include(result!.dotnetPath, context.version);
|
||||
assert.isTrue(fs.existsSync(result!.dotnetPath));
|
||||
}).timeout(100000);
|
||||
|
||||
test('Uninstall Command', async () => {
|
||||
const context: IDotnetAcquireContext = { version: '3.1' };
|
||||
const result = await vscode.commands.executeCommand<IDotnetAcquireResult>(`${defaultSDKContext.commandPrefix}.acquire`, context);
|
||||
assert.exists(result);
|
||||
assert.exists(result!.dotnetPath);
|
||||
assert.include(result!.dotnetPath, context.version);
|
||||
assert.isTrue(fs.existsSync(result!.dotnetPath!));
|
||||
await vscode.commands.executeCommand(`${defaultSDKContext.commandPrefix}.uninstallAll`);
|
||||
assert.isFalse(fs.existsSync(result!.dotnetPath));
|
||||
}).timeout(100000);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
//@ts-check
|
||||
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
|
||||
/**@type {import('webpack').Configuration}*/
|
||||
const config = {
|
||||
target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
|
||||
|
||||
entry: './/src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
|
||||
output: {
|
||||
// the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'extension.js',
|
||||
libraryTarget: 'commonjs2',
|
||||
devtoolModuleFilenameTemplate: '../[resource-path]'
|
||||
},
|
||||
node: {
|
||||
__dirname: false,
|
||||
__filename: false,
|
||||
},
|
||||
devtool: 'source-map',
|
||||
externals: {
|
||||
vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
|
||||
},
|
||||
resolve: {
|
||||
// support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'ts-loader'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new CopyPlugin({ patterns: [
|
||||
{ from: path.resolve(__dirname, '../vscode-dotnet-runtime-library/install scripts'), to: path.resolve(__dirname, 'dist', 'install scripts') },
|
||||
{ from: path.resolve(__dirname, '../images'), to: path.resolve(__dirname, 'images') }
|
||||
]}),
|
||||
]
|
||||
};
|
||||
module.exports = config;
|
Загрузка…
Ссылка в новой задаче