Skip to content

Commit 1d931f9

Browse files
committed
fix: address some bug see with shell profile setup
1 parent 1d63085 commit 1d931f9

File tree

3 files changed

+65
-124
lines changed

3 files changed

+65
-124
lines changed

src/features/terminal/startup/activateUsingShellStartup.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,16 @@ export class ShellStartupActivationManagerImpl implements ShellStartupActivation
8686
}
8787

8888
private async getSetupRequired(): Promise<ShellStartupProvider[]> {
89-
const providers: ShellStartupProvider[] = [];
90-
91-
await Promise.all(
89+
const results = await Promise.all(
9290
this.shellStartupProviders.map(async (provider) => {
93-
if (await provider.isSetup()) {
94-
providers.push(provider);
91+
if (!(await provider.isSetup())) {
92+
return provider;
9593
}
94+
return undefined;
9695
}),
9796
);
9897

98+
const providers = results.filter((provider): provider is ShellStartupProvider => provider !== undefined);
9999
return providers;
100100
}
101101

src/features/terminal/startup/bashStartup.ts

Lines changed: 55 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -29,46 +29,18 @@ async function isGitBashInstalled(): Promise<boolean> {
2929
return false;
3030
}
3131

32-
async function getBashProfiles(): Promise<string[]> {
32+
async function getBashProfiles(): Promise<string> {
3333
const homeDir = os.homedir();
34-
const profiles: string[] = [path.join(homeDir, '.bashrc')];
35-
36-
// Filter to only existing profiles or the first one if none exist
37-
const existingProfiles = await Promise.all(
38-
profiles.map(async (profile) => ({
39-
profilePath: profile,
40-
exists: await fs.pathExists(profile),
41-
})),
42-
);
43-
44-
const result = existingProfiles.filter((p) => p.exists);
45-
if (result.length === 0) {
46-
// If no profile exists, return the first one so we can create it
47-
return [profiles[0]];
48-
}
34+
const profile: string = path.join(homeDir, '.bashrc');
4935

50-
return result.map((p) => p.profilePath);
36+
return profile;
5137
}
5238

53-
async function getZshProfiles(): Promise<string[]> {
39+
async function getZshProfiles(): Promise<string> {
5440
const homeDir = os.homedir();
55-
const profiles: string[] = [path.join(homeDir, '.zshrc')];
56-
57-
// Filter to only existing profiles or the first one if none exist
58-
const existingProfiles = await Promise.all(
59-
profiles.map(async (profile) => ({
60-
profilePath: profile,
61-
exists: await fs.pathExists(profile),
62-
})),
63-
);
64-
65-
const result = existingProfiles.filter((p) => p.exists);
66-
if (result.length === 0) {
67-
// If no profile exists, return the first one so we can create it
68-
return [profiles[0]];
69-
}
41+
const profile: string = path.join(homeDir, '.zshrc');
7042

71-
return result.map((p) => p.profilePath);
43+
return profile;
7244
}
7345

7446
const regionStart = '# >>> vscode python';
@@ -80,96 +52,65 @@ function getActivationContent(key: string): string {
8052
return ['', '', regionStart, `if [ -n "$${key}" ]; then`, ` eval "$${key}"`, 'fi', regionEnd, ''].join(lineSep);
8153
}
8254

83-
async function isStartupSetup(profiles: string[], key: string): Promise<ShellSetupState> {
84-
if (profiles.length === 0) {
55+
async function isStartupSetup(profile: string, key: string): Promise<ShellSetupState> {
56+
if (await fs.pathExists(profile)) {
57+
const content = await fs.readFile(profile, 'utf8');
58+
return content.includes(key) ? ShellSetupState.Setup : ShellSetupState.NotSetup;
59+
} else {
8560
return ShellSetupState.NotSetup;
8661
}
87-
88-
// Check if any profile has our activation content
89-
const results = await Promise.all(
90-
profiles.map(async (profile) => {
91-
if (await fs.pathExists(profile)) {
92-
const content = await fs.readFile(profile, 'utf8');
93-
if (content.includes(key)) {
94-
return true;
95-
}
96-
}
97-
return false;
98-
}),
99-
);
100-
101-
return results.some((result) => result) ? ShellSetupState.Setup : ShellSetupState.NotSetup;
10262
}
10363

104-
async function setupStartup(profiles: string[], key: string): Promise<boolean> {
105-
if (profiles.length === 0) {
106-
traceVerbose('Cannot setup Bash startup - No profiles found');
107-
return false;
108-
}
109-
64+
async function setupStartup(profile: string, key: string): Promise<boolean> {
11065
const activationContent = getActivationContent(key);
111-
let successfulUpdates = 0;
11266

113-
for (const profile of profiles) {
114-
try {
115-
// Create profile directory if it doesn't exist
116-
await fs.mkdirp(path.dirname(profile));
117-
118-
// Create or update profile
119-
if (!(await fs.pathExists(profile))) {
120-
// Create new profile with our content
121-
await fs.writeFile(profile, activationContent);
122-
traceInfo(`Created new profile at: ${profile}\n${activationContent}`);
123-
successfulUpdates++;
124-
} else {
125-
// Update existing profile
126-
const content = await fs.readFile(profile, 'utf8');
127-
if (!content.includes(key)) {
128-
await fs.writeFile(profile, `${content}${activationContent}`);
129-
traceInfo(`Updated existing profile at: ${profile}\n${activationContent}`);
130-
successfulUpdates++;
131-
} else {
132-
// Already contains our activation code
133-
successfulUpdates++;
134-
}
135-
}
136-
} catch (err) {
137-
traceVerbose(`Failed to setup ${profile} startup`, err);
138-
}
139-
}
67+
try {
68+
// Create profile directory if it doesn't exist
69+
await fs.mkdirp(path.dirname(profile));
14070

141-
// Return true only if all profiles were successfully updated
142-
return profiles.length > 0 && successfulUpdates === profiles.length;
143-
}
144-
145-
async function removeStartup(profiles: string[], key: string): Promise<boolean> {
146-
let successfulRemovals = 0;
147-
148-
for (const profile of profiles) {
71+
// Create or update profile
14972
if (!(await fs.pathExists(profile))) {
150-
successfulRemovals++; // Count as success if file doesn't exist since there's nothing to remove
151-
continue;
152-
}
153-
154-
try {
73+
// Create new profile with our content
74+
await fs.writeFile(profile, activationContent);
75+
traceInfo(`SHELL: Created new profile at: ${profile}\n${activationContent}`);
76+
} else {
77+
// Update existing profile
15578
const content = await fs.readFile(profile, 'utf8');
156-
if (content.includes(key)) {
157-
// Use regex to remove the entire region including newlines
158-
const pattern = new RegExp(`${regionStart}[\\s\\S]*?${regionEnd}\\n?`, 'g');
159-
const newContent = content.replace(pattern, '');
160-
await fs.writeFile(profile, newContent);
161-
traceInfo(`Removed activation from profile at: ${profile}`);
162-
successfulRemovals++;
79+
if (!content.includes(key)) {
80+
await fs.writeFile(profile, `${content}${activationContent}`);
81+
traceInfo(`SHELL: Updated existing profile at: ${profile}\n${activationContent}`);
16382
} else {
164-
successfulRemovals++; // Count as success if activation is not present
83+
// Already contains our activation code
84+
traceInfo(`SHELL: Profile already contains activation code at: ${profile}`);
16585
}
166-
} catch (err) {
167-
traceVerbose(`Failed to remove ${profile} startup`, err);
16886
}
87+
return true;
88+
} catch (err) {
89+
traceError(`SHELL: Failed to setup startup for profile at: ${profile}`, err);
90+
return false;
16991
}
92+
}
17093

171-
// Return true only if all profiles were successfully processed
172-
return profiles.length > 0 && successfulRemovals === profiles.length;
94+
async function removeStartup(profile: string, key: string): Promise<boolean> {
95+
if (!(await fs.pathExists(profile))) {
96+
return true;
97+
} // If the file doesn't exist, we're done. No need to remove anything. Return true to indicate success.
98+
try {
99+
const content = await fs.readFile(profile, 'utf8');
100+
if (content.includes(key)) {
101+
// Use regex to remove the entire region including newlines
102+
const pattern = new RegExp(`${regionStart}[\\s\\S]*?${regionEnd}\\n?`, 'g');
103+
const newContent = content.replace(pattern, '');
104+
await fs.writeFile(profile, newContent);
105+
traceInfo(`SHELL: Removed activation from profile at: ${profile}`);
106+
} else {
107+
traceVerbose(`Profile at ${profile} does not contain activation code`);
108+
}
109+
return true;
110+
} catch (err) {
111+
traceVerbose(`Failed to remove ${profile} startup`, err);
112+
return false;
113+
}
173114
}
174115

175116
function getCommandAsString(command: PythonCommandRunConfiguration[]): string {
@@ -204,8 +145,8 @@ export class BashStartupProvider implements ShellStartupProvider {
204145
}
205146

206147
try {
207-
const bashProfiles = await getBashProfiles();
208-
return await isStartupSetup(bashProfiles, this.bashActivationEnvVarKey);
148+
const bashProfile = await getBashProfiles();
149+
return await isStartupSetup(bashProfile, this.bashActivationEnvVarKey);
209150
} catch (err) {
210151
traceError('Failed to check bash startup scripts', err);
211152
return ShellSetupState.NotSetup;
@@ -235,8 +176,8 @@ export class BashStartupProvider implements ShellStartupProvider {
235176
}
236177

237178
try {
238-
const bashProfiles = await getBashProfiles();
239-
const result = await removeStartup(bashProfiles, this.bashActivationEnvVarKey);
179+
const bashProfile = await getBashProfiles();
180+
const result = await removeStartup(bashProfile, this.bashActivationEnvVarKey);
240181
return result ? ShellScriptEditState.Edited : ShellScriptEditState.NotEdited;
241182
} catch (err) {
242183
traceError('Failed to teardown bash startup scripts', err);

src/features/terminal/startup/cmdStartup.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,12 @@ async function setupRegistryAutoRun(mainBatchFile: string): Promise<boolean> {
147147
}
148148
}
149149

150-
async function isCmdStartupSetup(cmdFiles: CmdFilePaths, key: string): Promise<boolean> {
150+
async function isCmdStartupSetup(cmdFiles: CmdFilePaths, key: string): Promise<ShellSetupState> {
151151
// Check both the startup file and registry AutoRun setting
152152
const fileExists = await fs.pathExists(cmdFiles.startupFile);
153153
const fileHasContent = fileExists ? (await fs.readFile(cmdFiles.startupFile, 'utf8')).includes(key) : false;
154154
if (!fileHasContent) {
155-
return false;
155+
return ShellSetupState.NotSetup;
156156
}
157157

158158
const mainFileExists = await fs.pathExists(cmdFiles.mainBatchFile);
@@ -164,11 +164,11 @@ async function isCmdStartupSetup(cmdFiles: CmdFilePaths, key: string): Promise<b
164164
}
165165

166166
if (!mainFileHasContent) {
167-
return false;
167+
return ShellSetupState.NotSetup;
168168
}
169169

170170
const registrySetup = await checkRegistryAutoRun(cmdFiles.regMainBatchFile, cmdFiles.mainBatchFile);
171-
return registrySetup;
171+
return registrySetup ? ShellSetupState.Setup : ShellSetupState.NotSetup;
172172
}
173173

174174
async function setupCmdStartup(cmdFiles: CmdFilePaths, key: string): Promise<boolean> {
@@ -264,7 +264,7 @@ export class CmdStartupProvider implements ShellStartupProvider {
264264
try {
265265
const cmdFiles = await getCmdFilePaths();
266266
const isSetup = await isCmdStartupSetup(cmdFiles, this.cmdActivationEnvVarKey);
267-
return isSetup ? ShellSetupState.Setup : ShellSetupState.NotSetup;
267+
return isSetup;
268268
} catch (err) {
269269
traceError('Failed to check if CMD startup is setup', err);
270270
return ShellSetupState.NotSetup;

0 commit comments

Comments
 (0)