Skip to content

Commit efa9773

Browse files
committed
address comments
1 parent afb0a7f commit efa9773

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

src/managers/conda/condaUtils.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -703,10 +703,21 @@ export function nonWindowsGenerateConfig(
703703
bashActivate = [{ executable: 'source', args: [sourceInitPath, envIdentifier] }];
704704
}
705705

706+
// POSIX sh (e.g. dash) does not support `source`; use `.` (dot) instead
707+
let shActivate: PythonCommandRunConfiguration[];
708+
if (condaShPath) {
709+
shActivate = [
710+
{ executable: '.', args: [condaShPath] },
711+
{ executable: 'conda', args: ['activate', envIdentifier] },
712+
];
713+
} else {
714+
shActivate = [{ executable: '.', args: [sourceInitPath, envIdentifier] }];
715+
}
716+
706717
shellActivation.set(ShellConstants.BASH, bashActivate);
707718
shellDeactivation.set(ShellConstants.BASH, deactivate);
708719

709-
shellActivation.set(ShellConstants.SH, bashActivate);
720+
shellActivation.set(ShellConstants.SH, shActivate);
710721
shellDeactivation.set(ShellConstants.SH, deactivate);
711722

712723
shellActivation.set(ShellConstants.ZSH, bashActivate);
@@ -734,7 +745,10 @@ export function nonWindowsGenerateConfig(
734745
// was run — if so, bare `conda` works; if not, use the full conda path.
735746
let pwshActivate: PythonCommandRunConfiguration[];
736747
if (condaPs1Path) {
737-
pwshActivate = [{ executable: condaPs1Path }, { executable: 'conda', args: ['activate', envIdentifier] }];
748+
pwshActivate = [
749+
{ executable: '&', args: [condaPs1Path] },
750+
{ executable: 'conda', args: ['activate', envIdentifier] },
751+
];
738752
} else {
739753
pwshActivate = [{ executable: condaExe('pwsh'), args: ['activate', envIdentifier] }];
740754
}
@@ -745,6 +759,7 @@ export function nonWindowsGenerateConfig(
745759
traceVerbose(
746760
`Non-Windows activation commands:
747761
Bash: ${JSON.stringify(bashActivate)},
762+
SH: ${JSON.stringify(shActivate)},
748763
Fish: ${JSON.stringify(fishActivate)},
749764
PowerShell: ${JSON.stringify(pwshActivate)}`,
750765
);

src/test/managers/conda/condaUtils.nonWindowsActivation.unit.test.ts

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import { nonWindowsGenerateConfig } from '../../../managers/conda/condaUtils';
66
* Tests for nonWindowsGenerateConfig - Non-Windows shell activation commands.
77
*
88
* Key behavior tested:
9-
* - Bash/ZSH/SH use conda.sh + conda activate when condaShPath is available
10-
* - Bash/ZSH/SH fall back to source <activate> <env> when condaShPath is unavailable
9+
* - Bash/ZSH use conda.sh + conda activate when condaShPath is available
10+
* - SH uses dot (.) instead of source for POSIX compliance
11+
* - Bash/ZSH fall back to source <activate> <env> when condaShPath is unavailable
12+
* - SH falls back to . <activate> <env> when condaShPath is unavailable
1113
* - Fish uses conda.fish + conda activate when condaFishPath is available
1214
* - Fish fallback uses bare `conda` if conda init fish was run, else full conda path
13-
* - PowerShell uses conda-hook.ps1 + conda activate when condaPs1Path is available
15+
* - PowerShell uses & conda-hook.ps1 + conda activate when condaPs1Path is available
1416
* - PowerShell fallback uses bare `conda` if conda init pwsh was run, else full conda path
1517
*/
1618
suite('Conda Utils - nonWindowsGenerateConfig', () => {
@@ -30,7 +32,7 @@ suite('Conda Utils - nonWindowsGenerateConfig', () => {
3032
condaShPath,
3133
);
3234

33-
for (const shell of [ShellConstants.BASH, ShellConstants.ZSH, ShellConstants.SH, ShellConstants.GITBASH]) {
35+
for (const shell of [ShellConstants.BASH, ShellConstants.ZSH, ShellConstants.GITBASH]) {
3436
const activation = result.shellActivation.get(shell);
3537
assert.ok(activation, `${shell} activation should be defined`);
3638
assert.strictEqual(activation.length, 2, `${shell} should have 2 commands`);
@@ -41,17 +43,46 @@ suite('Conda Utils - nonWindowsGenerateConfig', () => {
4143
}
4244
});
4345

46+
test('SH uses dot instead of source with conda.sh', () => {
47+
const condaShPath = '/home/user/miniforge3/etc/profile.d/conda.sh';
48+
const result = nonWindowsGenerateConfig(
49+
sourceInitPath,
50+
envIdentifier,
51+
condaDeactivate,
52+
condaPath,
53+
condaShPath,
54+
);
55+
56+
const activation = result.shellActivation.get(ShellConstants.SH);
57+
assert.ok(activation, 'SH activation should be defined');
58+
assert.strictEqual(activation.length, 2, 'SH should have 2 commands');
59+
assert.strictEqual(activation[0].executable, '.', 'SH should use dot instead of source');
60+
assert.deepStrictEqual(activation[0].args, [condaShPath]);
61+
assert.strictEqual(activation[1].executable, 'conda');
62+
assert.deepStrictEqual(activation[1].args, ['activate', envIdentifier]);
63+
});
64+
4465
test('Falls back to source activate when condaShPath is not provided', () => {
4566
const result = nonWindowsGenerateConfig(sourceInitPath, envIdentifier, condaDeactivate, condaPath);
4667

47-
for (const shell of [ShellConstants.BASH, ShellConstants.ZSH, ShellConstants.SH, ShellConstants.GITBASH]) {
68+
for (const shell of [ShellConstants.BASH, ShellConstants.ZSH, ShellConstants.GITBASH]) {
4869
const activation = result.shellActivation.get(shell);
4970
assert.ok(activation, `${shell} activation should be defined`);
5071
assert.strictEqual(activation.length, 1, `${shell} should have 1 command`);
5172
assert.strictEqual(activation[0].executable, 'source');
5273
assert.deepStrictEqual(activation[0].args, [sourceInitPath, envIdentifier]);
5374
}
5475
});
76+
77+
test('SH falls back to dot activate when condaShPath is not provided', () => {
78+
const result = nonWindowsGenerateConfig(sourceInitPath, envIdentifier, condaDeactivate, condaPath);
79+
80+
const activation = result.shellActivation.get(ShellConstants.SH);
81+
assert.ok(activation, 'SH activation should be defined');
82+
assert.strictEqual(activation.length, 1, 'SH should have 1 command');
83+
assert.strictEqual(activation[0].executable, '.', 'SH should use dot instead of source');
84+
assert.deepStrictEqual(activation[0].args, [sourceInitPath, envIdentifier]);
85+
});
5586
});
5687

5788
suite('Fish shell activation', () => {
@@ -125,7 +156,7 @@ suite('Conda Utils - nonWindowsGenerateConfig', () => {
125156
});
126157

127158
suite('PowerShell activation', () => {
128-
test('Uses conda-hook.ps1 + conda activate when condaPs1Path is provided', () => {
159+
test('Uses & conda-hook.ps1 + conda activate when condaPs1Path is provided', () => {
129160
const condaPs1Path = '/home/user/miniforge3/shell/condabin/conda-hook.ps1';
130161
const result = nonWindowsGenerateConfig(
131162
sourceInitPath,
@@ -140,7 +171,8 @@ suite('Conda Utils - nonWindowsGenerateConfig', () => {
140171
const activation = result.shellActivation.get(ShellConstants.PWSH);
141172
assert.ok(activation, 'PowerShell activation should be defined');
142173
assert.strictEqual(activation.length, 2, 'Should have 2 commands');
143-
assert.strictEqual(activation[0].executable, condaPs1Path);
174+
assert.strictEqual(activation[0].executable, '&');
175+
assert.deepStrictEqual(activation[0].args, [condaPs1Path]);
144176
assert.strictEqual(activation[1].executable, 'conda');
145177
assert.deepStrictEqual(activation[1].args, ['activate', envIdentifier]);
146178
});
@@ -224,10 +256,11 @@ suite('Conda Utils - nonWindowsGenerateConfig', () => {
224256
assert.strictEqual(fishActivation[0].executable, 'source');
225257
assert.deepStrictEqual(fishActivation[0].args, [condaFishPath]);
226258

227-
// PowerShell uses conda-hook.ps1
259+
// PowerShell uses & conda-hook.ps1
228260
const pwshActivation = result.shellActivation.get(ShellConstants.PWSH);
229261
assert.ok(pwshActivation);
230-
assert.strictEqual(pwshActivation[0].executable, condaPs1Path);
262+
assert.strictEqual(pwshActivation[0].executable, '&');
263+
assert.deepStrictEqual(pwshActivation[0].args, [condaPs1Path]);
231264
});
232265
});
233266
});

0 commit comments

Comments
 (0)