Skip to content

Commit 74feffc

Browse files
committed
fix: improve shell startup profile update handling
1 parent f4b60b6 commit 74feffc

7 files changed

Lines changed: 281 additions & 217 deletions

File tree

src/common/localize.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export namespace Common {
1212
export const viewLogs = l10n.t('View Logs');
1313
export const yes = l10n.t('Yes');
1414
export const no = l10n.t('No');
15+
export const ok = l10n.t('Ok');
1516
export const quickCreate = l10n.t('Quick Create');
1617
export const installPython = l10n.t('Install Python');
1718
}
@@ -165,20 +166,7 @@ export namespace EnvViewStrings {
165166
}
166167

167168
export namespace ShellStartupActivationStrings {
168-
export const shellStartupScriptEditPrompt = l10n.t(
169-
'To support Python Terminal activation using `shellStartup` we need to modify your shell profile. Do you want to proceed?',
170-
);
171-
export const updatingTheseProfiles = l10n.t('Updating these profiles');
172-
export const updateScript = l10n.t('Update Shell Profile');
173169
export const envCollectionDescription = l10n.t('Environment variables for shell activation');
174-
export const shellStartupScriptEditComplete = l10n.t(
175-
'Shell startup profile updated with code for Python environment activation. See [logs](command:{0})',
176-
Commands.viewLogs,
177-
);
178-
export const shellStartupScriptEditFailed = l10n.t(
179-
'Failed to update shell startup profile. See [logs](command:{0})',
180-
Commands.viewLogs,
181-
);
182170
export const revertedShellStartupScripts = l10n.t(
183171
'Removed shell startup profile code for Python environment activation. See [logs](command:{0})',
184172
Commands.viewLogs,

src/extension.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@ import { PythonProjectManagerImpl } from './features/projectManager';
4646
import { getPythonApi, setPythonApi } from './features/pythonApi';
4747
import { registerCompletionProvider } from './features/settings/settingCompletions';
4848
import { setActivateMenuButtonContext } from './features/terminal/activateMenuButton';
49-
import { ShellStartupActivationManagerImpl } from './features/terminal/activateUsingShellStartup';
5049
import { normalizeShellPath } from './features/terminal/shells/common/shellUtils';
5150
import {
5251
clearShellProfileCache,
5352
createShellEnvProviders,
5453
createShellStartupProviders,
5554
} from './features/terminal/shells/providers';
55+
import { ShellStartupActivationVariablesManagerImpl } from './features/terminal/shellStartupActivationVariablesManager';
56+
import { cleanupStartupScripts } from './features/terminal/shellStartupSetupHandlers';
5657
import { TerminalActivationImpl } from './features/terminal/terminalActivationState';
5758
import { TerminalManager, TerminalManagerImpl } from './features/terminal/terminalManager';
5859
import { getEnvironmentForTerminal } from './features/terminal/utils';
@@ -92,9 +93,8 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
9293
const terminalActivation = new TerminalActivationImpl();
9394
const shellEnvsProviders = createShellEnvProviders();
9495
const shellStartupProviders = createShellStartupProviders();
95-
const shellStartupActivationManager = new ShellStartupActivationManagerImpl(
96+
const shellStartupVarsMgr = new ShellStartupActivationVariablesManagerImpl(
9697
context.environmentVariableCollection,
97-
shellStartupProviders,
9898
shellEnvsProviders,
9999
envManagers,
100100
);
@@ -103,7 +103,7 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
103103
shellEnvsProviders,
104104
shellStartupProviders,
105105
);
106-
context.subscriptions.push(terminalActivation, terminalManager, shellStartupActivationManager);
106+
context.subscriptions.push(terminalActivation, terminalManager, shellStartupVarsMgr);
107107

108108
const projectCreators: ProjectCreators = new ProjectCreatorsImpl();
109109
context.subscriptions.push(
@@ -129,7 +129,7 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
129129
registerTools('python_environment', new GetEnvironmentInfoTool(api, envManagers)),
130130
registerTools('python_install_package', new InstallPackageTool(api)),
131131
commands.registerCommand('python-envs.terminal.revertStartupScriptChanges', async () => {
132-
await shellStartupActivationManager.cleanupStartupScripts();
132+
await cleanupStartupScripts(shellStartupProviders);
133133
}),
134134
commands.registerCommand('python-envs.viewLogs', () => outputChannel.show()),
135135
commands.registerCommand('python-envs.refreshManager', async (item) => {
@@ -290,7 +290,7 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
290290
await Promise.all([
291291
registerSystemPythonFeatures(nativeFinder, context.subscriptions, outputChannel),
292292
registerCondaFeatures(nativeFinder, context.subscriptions, outputChannel),
293-
shellStartupActivationManager.initialize(),
293+
shellStartupVarsMgr.initialize(),
294294
]);
295295

296296
sendTelemetryEvent(EventNames.EXTENSION_MANAGER_REGISTRATION_DURATION, start.elapsedTime);

src/features/terminal/activateUsingShellStartup.ts

Lines changed: 0 additions & 178 deletions
This file was deleted.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { ConfigurationChangeEvent, Disposable, GlobalEnvironmentVariableCollection } from 'vscode';
2+
import { DidChangeEnvironmentEventArgs } from '../../api';
3+
import { ShellStartupActivationStrings } from '../../common/localize';
4+
import { getWorkspaceFolder, getWorkspaceFolders, onDidChangeConfiguration } from '../../common/workspace.apis';
5+
import { EnvironmentManagers } from '../../internal.api';
6+
import { ShellEnvsProvider } from './shells/startupProvider';
7+
import { getAutoActivationType } from './utils';
8+
9+
export interface ShellStartupActivationVariablesManager extends Disposable {
10+
initialize(): Promise<void>;
11+
}
12+
13+
export class ShellStartupActivationVariablesManagerImpl implements ShellStartupActivationVariablesManager {
14+
private readonly disposables: Disposable[] = [];
15+
constructor(
16+
private readonly envCollection: GlobalEnvironmentVariableCollection,
17+
private readonly shellEnvsProviders: ShellEnvsProvider[],
18+
private readonly em: EnvironmentManagers,
19+
) {
20+
this.envCollection.description = ShellStartupActivationStrings.envCollectionDescription;
21+
this.disposables.push(
22+
onDidChangeConfiguration(async (e: ConfigurationChangeEvent) => {
23+
await this.handleConfigurationChange(e);
24+
}),
25+
this.em.onDidChangeEnvironmentFiltered(async (e: DidChangeEnvironmentEventArgs) => {
26+
await this.handleEnvironmentChange(e);
27+
}),
28+
);
29+
}
30+
31+
private async handleConfigurationChange(e: ConfigurationChangeEvent) {
32+
if (e.affectsConfiguration('python-envs.terminal.autoActivationType')) {
33+
const autoActType = getAutoActivationType();
34+
if (autoActType === 'shellStartup') {
35+
await this.initializeInternal();
36+
} else {
37+
const workspaces = getWorkspaceFolders() ?? [];
38+
if (workspaces.length > 0) {
39+
workspaces.forEach((workspace) => {
40+
const collection = this.envCollection.getScoped({ workspaceFolder: workspace });
41+
this.shellEnvsProviders.forEach((provider) => provider.removeEnvVariables(collection));
42+
});
43+
} else {
44+
this.shellEnvsProviders.forEach((provider) => provider.removeEnvVariables(this.envCollection));
45+
}
46+
}
47+
}
48+
}
49+
50+
private async handleEnvironmentChange(e: DidChangeEnvironmentEventArgs) {
51+
const autoActType = getAutoActivationType();
52+
if (autoActType === 'shellStartup' && e.uri) {
53+
const wf = getWorkspaceFolder(e.uri);
54+
if (wf) {
55+
const envVars = this.envCollection.getScoped({ workspaceFolder: wf });
56+
if (envVars) {
57+
this.shellEnvsProviders.forEach((provider) => {
58+
if (e.new) {
59+
provider.updateEnvVariables(envVars, e.new);
60+
} else {
61+
provider.removeEnvVariables(envVars);
62+
}
63+
});
64+
}
65+
}
66+
}
67+
}
68+
69+
private async initializeInternal(): Promise<void> {
70+
const workspaces = getWorkspaceFolders() ?? [];
71+
72+
if (workspaces.length > 0) {
73+
const promises: Promise<void>[] = [];
74+
workspaces.forEach((workspace) => {
75+
const collection = this.envCollection.getScoped({ workspaceFolder: workspace });
76+
promises.push(
77+
...this.shellEnvsProviders.map(async (provider) => {
78+
const env = await this.em.getEnvironment(workspace.uri);
79+
if (env) {
80+
provider.updateEnvVariables(collection, env);
81+
} else {
82+
provider.removeEnvVariables(collection);
83+
}
84+
}),
85+
);
86+
});
87+
await Promise.all(promises);
88+
} else {
89+
const env = await this.em.getEnvironment(undefined);
90+
await Promise.all(
91+
this.shellEnvsProviders.map(async (provider) => {
92+
if (env) {
93+
provider.updateEnvVariables(this.envCollection, env);
94+
} else {
95+
provider.removeEnvVariables(this.envCollection);
96+
}
97+
}),
98+
);
99+
}
100+
}
101+
102+
public async initialize(): Promise<void> {
103+
const autoActType = getAutoActivationType();
104+
if (autoActType === 'shellStartup') {
105+
await this.initializeInternal();
106+
}
107+
}
108+
109+
dispose() {
110+
this.disposables.forEach((disposable) => disposable.dispose());
111+
}
112+
}

0 commit comments

Comments
 (0)