Skip to content

Commit 2a98e27

Browse files
committed
Check profiles for conda init before adding conda sourcing
1 parent 95761d9 commit 2a98e27

5 files changed

Lines changed: 97 additions & 25 deletions

File tree

src/features/terminal/shells/bash/bashStartup.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ async function isGitBashInstalled(): Promise<boolean> {
2727
return false;
2828
}
2929

30-
async function getBashProfiles(): Promise<string> {
30+
export async function getBashProfiles(): Promise<string> {
3131
const homeDir = os.homedir();
3232
const profile: string = path.join(homeDir, '.bashrc');
3333

3434
return profile;
3535
}
3636

37-
async function getZshProfiles(): Promise<string> {
37+
export async function getZshProfiles(): Promise<string> {
3838
const homeDir = os.homedir();
3939
const profile: string = path.join(homeDir, '.zshrc');
4040

src/features/terminal/shells/fish/fishStartup.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ async function isFishInstalled(): Promise<boolean> {
1919
}
2020
}
2121

22-
async function getFishProfile(): Promise<string> {
22+
export async function getFishProfile(): Promise<string> {
2323
const homeDir = os.homedir();
2424
// Fish configuration is typically at ~/.config/fish/config.fish
2525
const profilePath = path.join(homeDir, '.config', 'fish', 'config.fish');
@@ -155,4 +155,8 @@ export class FishStartupProvider implements ShellStartupScriptProvider {
155155
clearCache(): Promise<void> {
156156
return Promise.resolve();
157157
}
158+
159+
getProfilePath(): Promise<string | undefined> {
160+
return getFishProfile();
161+
}
158162
}

src/features/terminal/shells/pwsh/pwshStartup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ async function isPowerShellInstalled(shell: string): Promise<boolean> {
5252
}
5353
}
5454

55-
async function getProfileForShell(shell: 'powershell' | 'pwsh'): Promise<string> {
55+
export async function getProfileForShell(shell: 'powershell' | 'pwsh'): Promise<string> {
5656
const cachedPath = getProfilePathCache(shell);
5757
if (cachedPath) {
5858
traceInfo(`SHELL: ${shell} profile path from cache: ${cachedPath}`);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as os from 'os';
2+
import * as path from 'path';
3+
4+
/**
5+
* Returns an array of possible sh profile paths in order of preference.
6+
*/
7+
export async function getShProfiles(): Promise<string> {
8+
const home = os.homedir();
9+
return path.join(home, '.profile');
10+
}

src/managers/conda/condaUtils.ts

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ import {
4444
import { getConfiguration } from '../../common/workspace.apis';
4545
import { ShellConstants } from '../../features/common/shellConstants';
4646
import { quoteArgs } from '../../features/execution/execUtils';
47+
import { getBashProfiles, getZshProfiles } from '../../features/terminal/shells/bash/bashStartup';
48+
import { getProfileForShell } from '../../features/terminal/shells/pwsh/pwshStartup';
49+
import { getShProfiles } from '../../features/terminal/shells/sh/shStartup';
4750
import {
4851
isNativeEnvInfo,
4952
NativeEnvInfo,
@@ -293,41 +296,51 @@ async function getNamedCondaPythonInfo(
293296

294297
if (conda.includes('/') || conda.includes('\\')) {
295298
const shActivate = path.join(path.dirname(path.dirname(conda)), 'etc', 'profile.d', 'conda.sh');
299+
const profileInit = await checkProfileForCondaInitialization();
296300

297301
if (isWindows()) {
298-
shellActivation.set(ShellConstants.GITBASH, [
299-
{ executable: '.', args: [pathForGitBash(shActivate)] },
300-
{ executable: 'conda', args: ['activate', name] },
301-
]);
302+
// didn't find gitbash
303+
const rcGitBash: PythonCommandRunConfiguration[] = [{ executable: 'conda', args: ['activate', name] }];
304+
if (!profileInit.get(ShellConstants.GITBASH)) {
305+
rcGitBash.unshift({ executable: '.', args: [pathForGitBash(shActivate)] });
306+
}
307+
shellActivation.set(ShellConstants.GITBASH, rcGitBash);
302308
shellDeactivation.set(ShellConstants.GITBASH, [{ executable: 'conda', args: ['deactivate'] }]);
303309

310+
// not sure about cmd and how to find profile
304311
const cmdActivate = path.join(path.dirname(conda), 'activate.bat');
305312
shellActivation.set(ShellConstants.CMD, [{ executable: cmdActivate, args: [name] }]);
306313
shellDeactivation.set(ShellConstants.CMD, [{ executable: 'conda', args: ['deactivate'] }]);
307314
} else {
308-
shellActivation.set(ShellConstants.BASH, [
309-
{ executable: '.', args: [shActivate] },
310-
{ executable: 'conda', args: ['activate', name] },
311-
]);
315+
// bash
316+
const rc: PythonCommandRunConfiguration[] = [{ executable: 'conda', args: ['activate', name] }];
317+
if (!profileInit.get(ShellConstants.BASH)) {
318+
rc.unshift({ executable: '.', args: [shActivate] });
319+
}
320+
shellActivation.set(ShellConstants.BASH, rc);
312321
shellDeactivation.set(ShellConstants.BASH, [{ executable: 'conda', args: ['deactivate'] }]);
313322

314-
shellActivation.set(ShellConstants.SH, [
315-
{ executable: '.', args: [shActivate] },
316-
{ executable: 'conda', args: ['activate', name] },
317-
]);
323+
const rcSh: PythonCommandRunConfiguration[] = [{ executable: 'conda', args: ['activate', name] }];
324+
if (!profileInit.get(ShellConstants.SH)) {
325+
rcSh.unshift({ executable: '.', args: [shActivate] });
326+
}
327+
shellActivation.set(ShellConstants.SH, rcSh);
318328
shellDeactivation.set(ShellConstants.SH, [{ executable: 'conda', args: ['deactivate'] }]);
319329

320-
shellActivation.set(ShellConstants.ZSH, [
321-
{ executable: '.', args: [shActivate] },
322-
{ executable: 'conda', args: ['activate', name] },
323-
]);
330+
// zsh
331+
const rcZsh: PythonCommandRunConfiguration[] = [{ executable: 'conda', args: ['activate', name] }];
332+
if (!profileInit.get(ShellConstants.ZSH)) {
333+
rcZsh.unshift({ executable: '.', args: [shActivate] });
334+
}
335+
shellActivation.set(ShellConstants.ZSH, rcZsh);
324336
shellDeactivation.set(ShellConstants.ZSH, [{ executable: 'conda', args: ['deactivate'] }]);
325337
}
326-
const psActivate = await getCondaHookPs1Path(conda);
327-
shellActivation.set(ShellConstants.PWSH, [
328-
{ executable: '&', args: [psActivate] },
329-
{ executable: 'conda', args: ['activate', name] },
330-
]);
338+
const rcPwsh: PythonCommandRunConfiguration[] = [{ executable: 'conda', args: ['activate', name] }];
339+
if (!profileInit.get(ShellConstants.PWSH)) {
340+
const psActivate = await getCondaHookPs1Path(conda);
341+
rcPwsh.unshift({ executable: '.', args: [psActivate] });
342+
}
343+
shellActivation.set(ShellConstants.PWSH, rcPwsh);
331344
shellDeactivation.set(ShellConstants.PWSH, [{ executable: 'conda', args: ['deactivate'] }]);
332345
} else {
333346
shellActivation.set(ShellConstants.GITBASH, [{ executable: 'conda', args: ['activate', name] }]);
@@ -374,6 +387,51 @@ async function getNamedCondaPythonInfo(
374387
};
375388
}
376389

390+
async function checkProfileForCondaInitialization(): Promise<Map<string, boolean>> {
391+
const profileStatusMap = new Map<string, boolean>();
392+
393+
// bash
394+
const bashProfiles = await getBashProfiles();
395+
const containsInitBash = await readProfile(bashProfiles);
396+
profileStatusMap.set(ShellConstants.BASH, containsInitBash);
397+
// zsh
398+
const zshProfiles = await getZshProfiles();
399+
const containsInitZsh = await readProfile(zshProfiles);
400+
profileStatusMap.set(ShellConstants.ZSH, containsInitZsh);
401+
402+
// sh
403+
const shProfiles = await getShProfiles();
404+
const containsInitSh = await readProfile(shProfiles);
405+
profileStatusMap.set(ShellConstants.SH, containsInitSh);
406+
407+
const pwshProfiles = await getProfileForShell('pwsh');
408+
const containsInitPwsh = await readProfile(pwshProfiles);
409+
profileStatusMap.set(ShellConstants.PWSH, containsInitPwsh);
410+
411+
return profileStatusMap;
412+
}
413+
async function readProfile(profilePath: string): Promise<boolean> {
414+
if (await fse.pathExists(profilePath)) {
415+
const content = await fse.readFile(profilePath, 'utf8');
416+
return content.includes('# >>> conda initialize >>>#');
417+
}
418+
return false;
419+
}
420+
421+
// async function readCmdCondaInit(): Promise<boolean> {
422+
// if (!isWindows()) {
423+
// return false;
424+
// }
425+
// try {
426+
// const { stdout } = await exec('reg query "HKCU\\Software\\Microsoft\\Command Processor" /v AutoRun', {
427+
// windowsHide: true,
428+
// });
429+
// return stdout.includes('conda') && stdout.includes('activate');
430+
// } catch {
431+
// return false;
432+
// }
433+
// }
434+
377435
async function getPrefixesCondaPythonInfo(
378436
prefix: string,
379437
executable: string,

0 commit comments

Comments
 (0)