-
Notifications
You must be signed in to change notification settings - Fork 378
Add new API dotnet.findPath to find the .NET host to use if one already exists that meets a requirement.
#1954
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 57 commits
d028fd6
b3bf76d
f8fa947
14f2930
63f943d
2e890ee
ccaf4fe
baaf910
5ad07f3
1ad0921
4e1b2c6
e3c23a7
c66895b
61911be
78fa558
058f209
0989525
81aa6a0
f119def
efc75a5
b43b737
a88e0e2
a16491a
b43a96a
57f52ce
3c385b1
2918dfe
ac7fa96
f18bca3
1e7958a
9376b6d
59c6dc3
22a8eca
0b9d6bc
ae1b06b
7d4ed97
3755f24
236b667
1b7dd99
99387e3
a91f6f3
0902d6d
42b03ee
1a5b9f0
c502c6b
3428c75
baf5760
2801e1b
76a553d
24cf0e2
9386062
9b803ef
f34c963
4289ff9
183d0de
1aee50e
3ea71a7
17ef50e
31c0d5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,12 +8,14 @@ import * as path from 'path'; | |
| import * as vscode from 'vscode'; | ||
| import { | ||
| DotnetInstallMode, | ||
| DotnetVersionSpecRequirement, | ||
| IDotnetAcquireContext, | ||
| IDotnetAcquireResult, | ||
| IDotnetFindPathContext, | ||
| IDotnetListVersionsResult, | ||
| } from 'vscode-dotnet-runtime-library'; | ||
| import * as runtimeExtension from 'vscode-dotnet-runtime'; | ||
| import * as sdkExtension from 'vscode-dotnet-sdk'; | ||
| import * as runtimeExtension from 'vscode-dotnet-runtime'; // comment this out when packing the extension | ||
| import * as sdkExtension from 'vscode-dotnet-sdk'; // comment this out when packing the extension | ||
| import { install } from 'source-map-support'; | ||
|
|
||
| export function activate(context: vscode.ExtensionContext) { | ||
|
|
@@ -33,8 +35,8 @@ export function activate(context: vscode.ExtensionContext) { | |
| */ | ||
|
|
||
| const requestingExtensionId = 'ms-dotnettools.sample-extension'; | ||
| runtimeExtension.activate(context); | ||
| sdkExtension.activate(context); | ||
| runtimeExtension.activate(context); // comment this out when packing the extension | ||
| sdkExtension.activate(context); // comment this out when packing the extension | ||
|
|
||
|
|
||
| // -------------------------------------------------------------------------- | ||
|
|
@@ -167,17 +169,6 @@ ${stderr}`); | |
| } | ||
| }); | ||
|
|
||
| context.subscriptions.push( | ||
| sampleHelloWorldRegistration, | ||
| sampleAcquireRegistration, | ||
| sampleAcquireASPNETRegistration, | ||
| sampleAcquireStatusRegistration, | ||
| sampleDotnetUninstallAllRegistration, | ||
| sampleConcurrentTest, | ||
| sampleConcurrentASPNETTest, | ||
| sampleShowAcquisitionLogRegistration, | ||
| ); | ||
|
|
||
| const sampleGlobalSDKFromRuntimeRegistration = vscode.commands.registerCommand('sample.dotnet.acquireGlobalSDK', async (version) => { | ||
| if (!version) { | ||
| version = await vscode.window.showInputBox({ | ||
|
|
@@ -199,6 +190,47 @@ ${stderr}`); | |
| } | ||
| }); | ||
|
|
||
| const sampleFindPathRegistration = vscode.commands.registerCommand('sample.dotnet.findPath', async () => | ||
| { | ||
| const version = await vscode.window.showInputBox({ | ||
| placeHolder: '8.0', | ||
| value: '8.0', | ||
| prompt: 'The .NET runtime version.', | ||
|
||
| }); | ||
|
|
||
| const arch = await vscode.window.showInputBox({ | ||
| placeHolder: 'x64', | ||
| value: 'x64', | ||
| prompt: 'The .NET runtime architecture.', | ||
| }); | ||
|
|
||
| const requirement = await vscode.window.showInputBox({ | ||
| placeHolder: 'greater_than_or_equal', | ||
| value: 'greater_than_or_equal', | ||
| prompt: 'The condition to search for a requirement.', | ||
| }); | ||
|
|
||
| let commandContext : IDotnetFindPathContext = { acquireContext: {version: version, requestingExtensionId: requestingExtensionId, architecture : arch, mode : 'runtime'} as IDotnetAcquireContext, | ||
| versionSpecRequirement: requirement as DotnetVersionSpecRequirement}; | ||
|
|
||
| const result = await vscode.commands.executeCommand('dotnet.findPath', commandContext); | ||
|
|
||
| vscode.window.showInformationMessage(`.NET Path Discovered\n | ||
| ${JSON.stringify(result) ?? 'undefined'}`); | ||
| }); | ||
|
|
||
| context.subscriptions.push( | ||
| sampleHelloWorldRegistration, | ||
| sampleAcquireRegistration, | ||
| sampleAcquireASPNETRegistration, | ||
| sampleAcquireStatusRegistration, | ||
| sampleDotnetUninstallAllRegistration, | ||
| sampleConcurrentTest, | ||
| sampleConcurrentASPNETTest, | ||
| sampleShowAcquisitionLogRegistration, | ||
| sampleFindPathRegistration, | ||
| ); | ||
|
|
||
| // -------------------------------------------------------------------------- | ||
|
|
||
| // ---------------------sdk extension registrations-------------------------- | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,6 +66,16 @@ import { | |
| getMajorMinor, | ||
| DotnetOfflineWarning, | ||
| IUtilityContext, | ||
| IDotnetFindPathContext, | ||
| DotnetVersionSpecRequirement, | ||
| DotnetConditionValidator, | ||
| DotnetPathFinder, | ||
| IDotnetConditionValidator, | ||
| DotnetFindPathSettingFound, | ||
| DotnetFindPathLookupSetting, | ||
| DotnetFindPathDidNotMeetCondition, | ||
| DotnetFindPathMetCondition, | ||
| DotnetFindPathCommandInvoked, | ||
| } from 'vscode-dotnet-runtime-library'; | ||
| import { dotnetCoreAcquisitionExtensionId } from './DotnetCoreAcquisitionId'; | ||
| import { InstallTrackerSingleton } from 'vscode-dotnet-runtime-library/dist/Acquisition/InstallTrackerSingleton'; | ||
|
|
@@ -87,6 +97,7 @@ namespace commandKeys { | |
| export const acquireGlobalSDK = 'acquireGlobalSDK'; | ||
| export const acquireStatus = 'acquireStatus'; | ||
| export const uninstall = 'uninstall'; | ||
| export const findPath = 'findPath'; | ||
| export const uninstallPublic = 'uninstallPublic' | ||
| export const uninstallAll = 'uninstallAll'; | ||
| export const listVersions = 'listVersions'; | ||
|
|
@@ -432,6 +443,95 @@ export function activate(vsCodeContext: vscode.ExtensionContext, extensionContex | |
| return uninstall(commandContext); | ||
| }); | ||
|
|
||
| /** | ||
| * @param commandContext The context of the request to find the dotnet path. | ||
| * We wrap an AcquisitionContext which must include the version, requestingExtensionId, architecture of .NET desired, and mode. | ||
| * The architecture should be of the node format ('x64', 'x86', 'arm64', etc.) | ||
| * | ||
| * @returns the path to the dotnet executable, if one can be found. This should be the true path to the executable. undefined if none can be found. | ||
| * | ||
| * @remarks Priority Order for path lookup: | ||
| * VSCode Setting -> PATH -> Realpath of PATH -> DOTNET_ROOT (Emulation DOTNET_ROOT if set first) | ||
| * | ||
| * This accounts for pmc installs, snap installs, bash configurations, and other non-standard installations such as homebrew. | ||
| */ | ||
| const dotnetFindPathRegistration = vscode.commands.registerCommand(`${commandPrefix}.${commandKeys.findPath}`, async (commandContext : IDotnetFindPathContext) => | ||
| { | ||
| globalEventStream.post(new DotnetFindPathCommandInvoked(`The find path command was invoked.`, commandContext)); | ||
|
|
||
| if(!commandContext.acquireContext.mode || !commandContext.acquireContext.requestingExtensionId || !commandContext.acquireContext.version || !commandContext.acquireContext.architecture) | ||
| { | ||
| throw new EventCancellationError('BadContextualFindPathError', `The find path request was missing required information: a mode, version, architecture, and requestingExtensionId.`); | ||
| } | ||
|
|
||
| globalEventStream.post(new DotnetFindPathLookupSetting(`Looking up vscode setting.`)); | ||
| const workerContext = getAcquisitionWorkerContext(commandContext.acquireContext.mode, commandContext.acquireContext); | ||
| const existingPath = await resolveExistingPathIfExists(existingPathConfigWorker, commandContext.acquireContext, workerContext, utilContext, commandContext.versionSpecRequirement); | ||
|
|
||
| if(existingPath) | ||
| { | ||
| globalEventStream.post(new DotnetFindPathSettingFound(`Found vscode setting.`)); | ||
nagilson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| outputChannel.show(true); | ||
| return existingPath; | ||
| } | ||
|
|
||
| const validator = new DotnetConditionValidator(workerContext, utilContext); | ||
| const finder = new DotnetPathFinder(workerContext, utilContext); | ||
|
|
||
| const dotnetsOnPATH = await finder.findRawPathEnvironmentSetting(); | ||
| for(const dotnetPath of dotnetsOnPATH ?? []) | ||
| { | ||
| const validatedPATH = await getPathIfValid(dotnetPath, validator, commandContext); | ||
| if(validatedPATH) | ||
| { | ||
| outputChannel.show(true); | ||
| return validatedPATH; | ||
| } | ||
| } | ||
|
|
||
| const dotnetOnRealPATH = await finder.findRealPathEnvironmentSetting(); | ||
| for(const dotnetPath of dotnetsOnPATH ?? []) | ||
| { | ||
| const validatedRealPATH = await getPathIfValid(dotnetPath, validator, commandContext); | ||
| if(validatedRealPATH) | ||
| { | ||
| outputChannel.show(true); | ||
| return validatedRealPATH; | ||
| } | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These both have the same for-loop with only a const named differently. But the calls above the for-loops to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ooo youre right, that's a very subtle bug. :) This is why redundant code is bad but it didn't feel like enough to make its own function. Will fix. Thank you. |
||
|
|
||
| const dotnetOnROOT = await finder.findDotnetRootPath(commandContext.acquireContext.architecture); | ||
| const validatedRoot = await getPathIfValid(dotnetOnROOT, validator, commandContext); | ||
| if(validatedRoot) | ||
| { | ||
| outputChannel.show(true); | ||
|
|
||
| return validatedRoot; | ||
| } | ||
|
|
||
| outputChannel.show(true); | ||
| return undefined; | ||
| }); | ||
|
|
||
| async function getPathIfValid(path : string | undefined, validator : IDotnetConditionValidator, commandContext : IDotnetFindPathContext) : Promise<string | undefined> | ||
| { | ||
| if(path) | ||
| { | ||
| const validated = await validator.dotnetMeetsRequirement(path, commandContext); | ||
| if(validated) | ||
| { | ||
| globalEventStream.post(new DotnetFindPathMetCondition(`${path} met the conditions.`)); | ||
| return path; | ||
| } | ||
| else | ||
| { | ||
| globalEventStream.post(new DotnetFindPathDidNotMeetCondition(`${path} did NOT satisfy the conditions.`)); | ||
| } | ||
| } | ||
|
|
||
| return undefined; | ||
| } | ||
|
|
||
| async function uninstall(commandContext: IDotnetAcquireContext | undefined, force = false) : Promise<string> | ||
| { | ||
| let result = '1'; | ||
|
|
@@ -515,11 +615,11 @@ export function activate(vsCodeContext: vscode.ExtensionContext, extensionContex | |
|
|
||
| // Helper Functions | ||
| async function resolveExistingPathIfExists(configResolver : ExtensionConfigurationWorker, commandContext : IDotnetAcquireContext, | ||
| workerContext : IAcquisitionWorkerContext, utilityContext : IUtilityContext) : Promise<IDotnetAcquireResult | null> | ||
| workerContext : IAcquisitionWorkerContext, utilityContext : IUtilityContext, requirement? : DotnetVersionSpecRequirement) : Promise<IDotnetAcquireResult | null> | ||
| { | ||
| const existingPathResolver = new ExistingPathResolver(workerContext, utilityContext); | ||
|
|
||
| const existingPath = await existingPathResolver.resolveExistingPath(configResolver.getAllPathConfigurationValues(), commandContext.requestingExtensionId, displayWorker); | ||
| const existingPath = await existingPathResolver.resolveExistingPath(configResolver.getAllPathConfigurationValues(), commandContext.requestingExtensionId, displayWorker, requirement); | ||
| if (existingPath) { | ||
| globalEventStream.post(new DotnetExistingPathResolutionCompleted(existingPath.dotnetPath)); | ||
| return new Promise((resolve) => { | ||
|
|
@@ -663,6 +763,7 @@ We will try to install .NET, but are unlikely to be able to connect to the serve | |
| dotnetAcquireStatusRegistration, | ||
| dotnetAcquireGlobalSDKRegistration, | ||
| acquireGlobalSDKPublicRegistration, | ||
| dotnetFindPathRegistration, | ||
| dotnetListVersionsRegistration, | ||
| dotnetRecommendedVersionRegistration, | ||
| dotnetUninstallRegistration, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.