Skip to content

Commit c9b09b9

Browse files
committed
fix: use conda.sh for Git Bash activation on Windows (Fixes microsoft#1247)
1 parent 33e8098 commit c9b09b9

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

src/managers/conda/condaSourcingUtils.ts

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ import * as path from 'path';
66
import { traceError, traceInfo, traceVerbose } from '../../common/logging';
77
import { isWindows } from '../../common/utils/platformUtils';
88

9+
/**
10+
* Shell-specific sourcing scripts for conda activation.
11+
* Each field is optional since not all scripts may be available on all systems.
12+
*/
13+
export interface ShellSourcingScripts {
14+
/** PowerShell hook script (conda-hook.ps1) */
15+
ps1?: string;
16+
/** Bash/sh initialization script (conda.sh) */
17+
sh?: string;
18+
/** Windows CMD batch file (activate.bat) */
19+
cmd?: string;
20+
}
21+
922
/**
1023
* Represents the status of conda sourcing in the current environment
1124
*/
@@ -16,14 +29,14 @@ export class CondaSourcingStatus {
1629
* @param condaFolder Path to the conda installation folder (derived from condaPath)
1730
* @param isActiveOnLaunch Whether conda was activated before VS Code launch
1831
* @param globalSourcingScript Path to the global sourcing script (if exists)
19-
* @param shellSourcingScripts List of paths to shell-specific sourcing scripts
32+
* @param shellSourcingScripts Shell-specific sourcing scripts (if found)
2033
*/
2134
constructor(
2235
public readonly condaPath: string,
2336
public readonly condaFolder: string,
2437
public isActiveOnLaunch?: boolean,
2538
public globalSourcingScript?: string,
26-
public shellSourcingScripts?: string[],
39+
public shellSourcingScripts?: ShellSourcingScripts,
2740
) {}
2841

2942
/**
@@ -40,15 +53,23 @@ export class CondaSourcingStatus {
4053
lines.push(`├─ Global Sourcing Script: ${this.globalSourcingScript}`);
4154
}
4255

43-
if (this.shellSourcingScripts?.length) {
44-
lines.push('└─ Shell-specific Sourcing Scripts:');
45-
this.shellSourcingScripts.forEach((script, index, array) => {
46-
const isLast = index === array.length - 1;
47-
if (script) {
48-
// Only include scripts that exist
49-
lines.push(` ${isLast ? '└─' : '├─'} ${script}`);
50-
}
51-
});
56+
if (this.shellSourcingScripts) {
57+
const scripts = this.shellSourcingScripts;
58+
const entries = [
59+
scripts.ps1 && `PowerShell: ${scripts.ps1}`,
60+
scripts.sh && `Bash/sh: ${scripts.sh}`,
61+
scripts.cmd && `CMD: ${scripts.cmd}`,
62+
].filter(Boolean);
63+
64+
if (entries.length > 0) {
65+
lines.push('└─ Shell-specific Sourcing Scripts:');
66+
entries.forEach((entry, index, array) => {
67+
const isLast = index === array.length - 1;
68+
lines.push(` ${isLast ? '└─' : '├─'} ${entry}`);
69+
});
70+
} else {
71+
lines.push('└─ No Shell-specific Sourcing Scripts Found');
72+
}
5273
} else {
5374
lines.push('└─ No Shell-specific Sourcing Scripts Found');
5475
}
@@ -120,7 +141,7 @@ export async function findGlobalSourcingScript(condaFolder: string): Promise<str
120141
}
121142
}
122143

123-
export async function findShellSourcingScripts(sourcingStatus: CondaSourcingStatus): Promise<string[]> {
144+
export async function findShellSourcingScripts(sourcingStatus: CondaSourcingStatus): Promise<ShellSourcingScripts> {
124145
const logs: string[] = [];
125146
logs.push('=== Conda Sourcing Shell Script Search ===');
126147

@@ -170,7 +191,7 @@ export async function findShellSourcingScripts(sourcingStatus: CondaSourcingStat
170191
traceVerbose(logs.join('\n'));
171192
}
172193

173-
return [ps1Script, shScript, cmdActivate] as string[];
194+
return { ps1: ps1Script, sh: shScript, cmd: cmdActivate };
174195
}
175196

176197
/**

src/managers/conda/condaUtils.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,10 +512,16 @@ async function buildShellActivationMapForConda(
512512
// P3: Handle Windows specifically ;this is carryover from vscode-python
513513
if (isWindows()) {
514514
logs.push('✓ Using Windows-specific activation configuration');
515+
// Get conda.sh for bash-based shells (Git Bash, WSL bash)
516+
const condaShPath = envManager.sourcingInformation.shellSourcingScripts?.sh;
517+
if (!condaShPath) {
518+
logs.push('conda.sh not found, falling back to global sourcing script for bash activation');
519+
}
515520
shellMaps = await windowsExceptionGenerateConfig(
516521
preferredSourcingPath,
517522
envIdentifier,
518523
envManager.sourcingInformation.condaFolder,
524+
condaShPath,
519525
);
520526
return shellMaps;
521527
}
@@ -580,6 +586,7 @@ async function windowsExceptionGenerateConfig(
580586
sourceInitPath: string,
581587
prefix: string,
582588
condaFolder: string,
589+
condaShPath?: string,
583590
): Promise<ShellCommandMaps> {
584591
const shellActivation: Map<string, PythonCommandRunConfiguration[]> = new Map();
585592
const shellDeactivation: Map<string, PythonCommandRunConfiguration[]> = new Map();
@@ -593,7 +600,10 @@ async function windowsExceptionGenerateConfig(
593600
const pwshActivate = [{ executable: activation }, { executable: 'conda', args: ['activate', quotedPrefix] }];
594601
const cmdActivate = [{ executable: sourceInitPath }, { executable: 'conda', args: ['activate', quotedPrefix] }];
595602

596-
const bashActivate = [{ executable: 'source', args: [sourceInitPath.replace(/\\/g, '/'), quotedPrefix] }];
603+
// Use conda.sh for bash-based shells (Git Bash) instead of activate.bat
604+
// conda.sh is the proper initialization script for bash shells
605+
const bashSourcePath = condaShPath ?? sourceInitPath;
606+
const bashActivate = [{ executable: 'source', args: [bashSourcePath.replace(/\\/g, '/'), quotedPrefix] }];
597607
traceVerbose(
598608
`Windows activation commands:
599609
PowerShell: ${JSON.stringify(pwshActivate)},

0 commit comments

Comments
 (0)