diff --git a/news/2 Fixes/18510.md b/news/2 Fixes/18510.md new file mode 100644 index 000000000000..9060834af7f1 --- /dev/null +++ b/news/2 Fixes/18510.md @@ -0,0 +1 @@ +Do not show inherit env prompt for conda envs when running "remotely". diff --git a/src/client/common/application/applicationEnvironment.ts b/src/client/common/application/applicationEnvironment.ts index 9feda1f2b73d..e3d78477996d 100644 --- a/src/client/common/application/applicationEnvironment.ts +++ b/src/client/common/application/applicationEnvironment.ts @@ -64,6 +64,9 @@ export class ApplicationEnvironment implements IApplicationEnvironment { public get machineId(): string { return vscode.env.machineId; } + public get remoteName(): string | undefined { + return vscode.env.remoteName; + } public get extensionName(): string { return this.packageJson.displayName; } diff --git a/src/client/common/application/types.ts b/src/client/common/application/types.ts index 015258bab20b..a91aeed75b04 100644 --- a/src/client/common/application/types.ts +++ b/src/client/common/application/types.ts @@ -1072,6 +1072,16 @@ export interface IApplicationEnvironment { * from a desktop application or a web browser. */ readonly uiKind: UIKind; + /** + * The name of a remote. Defined by extensions, popular samples are `wsl` for the Windows + * Subsystem for Linux or `ssh-remote` for remotes using a secure shell. + * + * *Note* that the value is `undefined` when there is no remote extension host but that the + * value is defined in all extension hosts (local and remote) in case a remote extension host + * exists. Use {@link Extension.extensionKind} to know if + * a specific extension runs remote or not. + */ + readonly remoteName: string | undefined; } export const ILanguageService = Symbol('ILanguageService'); diff --git a/src/client/interpreter/virtualEnvs/condaInheritEnvPrompt.ts b/src/client/interpreter/virtualEnvs/condaInheritEnvPrompt.ts index c842d5b2c45e..495e7181264b 100644 --- a/src/client/interpreter/virtualEnvs/condaInheritEnvPrompt.ts +++ b/src/client/interpreter/virtualEnvs/condaInheritEnvPrompt.ts @@ -4,7 +4,7 @@ import { inject, injectable, optional } from 'inversify'; import { ConfigurationTarget, Uri } from 'vscode'; import { IExtensionActivationService } from '../../activation/types'; -import { IApplicationShell, IWorkspaceService } from '../../common/application/types'; +import { IApplicationEnvironment, IApplicationShell, IWorkspaceService } from '../../common/application/types'; import { IPlatformService } from '../../common/platform/types'; import { IBrowserService, IPersistentStateFactory } from '../../common/types'; import { Common, Interpreters } from '../../common/utils/localize'; @@ -26,6 +26,7 @@ export class CondaInheritEnvPrompt implements IExtensionActivationService { @inject(IApplicationShell) private readonly appShell: IApplicationShell, @inject(IPersistentStateFactory) private readonly persistentStateFactory: IPersistentStateFactory, @inject(IPlatformService) private readonly platformService: IPlatformService, + @inject(IApplicationEnvironment) private readonly appEnvironment: IApplicationEnvironment, @optional() public hasPromptBeenShownInCurrentSession: boolean = false, ) {} @@ -76,6 +77,11 @@ export class CondaInheritEnvPrompt implements IExtensionActivationService { if (this.hasPromptBeenShownInCurrentSession) { return false; } + if (this.appEnvironment.remoteName) { + // `terminal.integrated.inheritEnv` is only applicable user scope, so won't apply + // in remote scenarios: https://github.com/microsoft/vscode/issues/147421 + return false; + } if (this.platformService.isWindows) { return false; } diff --git a/src/test/interpreters/virtualEnvs/condaInheritEnvPrompt.unit.test.ts b/src/test/interpreters/virtualEnvs/condaInheritEnvPrompt.unit.test.ts index 2fd8913b2d8d..5c1b803395e8 100644 --- a/src/test/interpreters/virtualEnvs/condaInheritEnvPrompt.unit.test.ts +++ b/src/test/interpreters/virtualEnvs/condaInheritEnvPrompt.unit.test.ts @@ -8,7 +8,11 @@ import * as sinon from 'sinon'; import { instance, mock, verify, when } from 'ts-mockito'; import * as TypeMoq from 'typemoq'; import { ConfigurationTarget, Uri, WorkspaceConfiguration } from 'vscode'; -import { IApplicationShell, IWorkspaceService } from '../../../client/common/application/types'; +import { + IApplicationEnvironment, + IApplicationShell, + IWorkspaceService, +} from '../../../client/common/application/types'; import { PersistentStateFactory } from '../../../client/common/persistentState'; import { IPlatformService } from '../../../client/common/platform/types'; import { IBrowserService, IPersistentState, IPersistentStateFactory } from '../../../client/common/types'; @@ -28,6 +32,7 @@ suite('Conda Inherit Env Prompt', async () => { let interpreterService: TypeMoq.IMock; let platformService: TypeMoq.IMock; let browserService: TypeMoq.IMock; + let applicationEnvironment: TypeMoq.IMock; let persistentStateFactory: IPersistentStateFactory; let notificationPromptEnabled: TypeMoq.IMock>; let condaInheritEnvPrompt: CondaInheritEnvPrompt; @@ -45,13 +50,17 @@ suite('Conda Inherit Env Prompt', async () => { interpreterService = TypeMoq.Mock.ofType(); persistentStateFactory = mock(PersistentStateFactory); platformService = TypeMoq.Mock.ofType(); + applicationEnvironment = TypeMoq.Mock.ofType(); + applicationEnvironment.setup((a) => a.remoteName).returns(() => undefined); condaInheritEnvPrompt = new CondaInheritEnvPrompt( interpreterService.object, workspaceService.object, browserService.object, appShell.object, instance(persistentStateFactory), + platformService.object, + applicationEnvironment.object, ); }); test('Returns false if prompt has already been shown in the current session', async () => { @@ -61,7 +70,9 @@ suite('Conda Inherit Env Prompt', async () => { browserService.object, appShell.object, instance(persistentStateFactory), + platformService.object, + applicationEnvironment.object, true, ); const workspaceConfig = TypeMoq.Mock.ofType(); @@ -78,6 +89,14 @@ suite('Conda Inherit Env Prompt', async () => { expect(condaInheritEnvPrompt.hasPromptBeenShownInCurrentSession).to.equal(true, 'Should be true'); verifyAll(); }); + test('Returns false if running on remote', async () => { + applicationEnvironment.reset(); + applicationEnvironment.setup((a) => a.remoteName).returns(() => 'ssh'); + const result = await condaInheritEnvPrompt.shouldShowPrompt(resource); + expect(result).to.equal(false, 'Prompt should not be shown'); + expect(condaInheritEnvPrompt.hasPromptBeenShownInCurrentSession).to.equal(false, 'Should be false'); + verifyAll(); + }); test('Returns false if on Windows', async () => { platformService .setup((ps) => ps.isWindows) @@ -245,6 +264,8 @@ suite('Conda Inherit Env Prompt', async () => { interpreterService = TypeMoq.Mock.ofType(); persistentStateFactory = mock(PersistentStateFactory); platformService = TypeMoq.Mock.ofType(); + applicationEnvironment = TypeMoq.Mock.ofType(); + applicationEnvironment.setup((a) => a.remoteName).returns(() => undefined); }); teardown(() => { @@ -261,7 +282,9 @@ suite('Conda Inherit Env Prompt', async () => { browserService.object, appShell.object, instance(persistentStateFactory), + platformService.object, + applicationEnvironment.object, ); const promise = condaInheritEnvPrompt.activate(resource); @@ -285,7 +308,9 @@ suite('Conda Inherit Env Prompt', async () => { browserService.object, appShell.object, instance(persistentStateFactory), + platformService.object, + applicationEnvironment.object, ); await condaInheritEnvPrompt.activate(resource); assert.ok(initializeInBackground.calledOnce); @@ -302,6 +327,8 @@ suite('Conda Inherit Env Prompt', async () => { interpreterService = TypeMoq.Mock.ofType(); persistentStateFactory = mock(PersistentStateFactory); platformService = TypeMoq.Mock.ofType(); + applicationEnvironment = TypeMoq.Mock.ofType(); + applicationEnvironment.setup((a) => a.remoteName).returns(() => undefined); }); teardown(() => { @@ -319,7 +346,9 @@ suite('Conda Inherit Env Prompt', async () => { browserService.object, appShell.object, instance(persistentStateFactory), + platformService.object, + applicationEnvironment.object, ); await condaInheritEnvPrompt.initializeInBackground(resource); assert.ok(shouldShowPrompt.calledOnce); @@ -337,7 +366,9 @@ suite('Conda Inherit Env Prompt', async () => { browserService.object, appShell.object, instance(persistentStateFactory), + platformService.object, + applicationEnvironment.object, ); await condaInheritEnvPrompt.initializeInBackground(resource); assert.ok(shouldShowPrompt.calledOnce); @@ -355,6 +386,8 @@ suite('Conda Inherit Env Prompt', async () => { browserService = TypeMoq.Mock.ofType(); notificationPromptEnabled = TypeMoq.Mock.ofType>(); platformService = TypeMoq.Mock.ofType(); + applicationEnvironment = TypeMoq.Mock.ofType(); + applicationEnvironment.setup((a) => a.remoteName).returns(() => undefined); when(persistentStateFactory.createGlobalPersistentState(condaInheritEnvPromptKey, true)).thenReturn( notificationPromptEnabled.object, ); @@ -364,7 +397,9 @@ suite('Conda Inherit Env Prompt', async () => { browserService.object, appShell.object, instance(persistentStateFactory), + platformService.object, + applicationEnvironment.object, ); });