From 822c04043efb5ff551c93442b68c3c3354fbb861 Mon Sep 17 00:00:00 2001 From: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com> Date: Wed, 25 Mar 2026 11:46:02 -0700 Subject: [PATCH 1/2] prioritize workspace selected env over process.env.CONDA_PREFIX --- src/managers/conda/condaUtils.ts | 18 ++-- ...ndaUtils.getCondaForWorkspace.unit.test.ts | 94 +++++++++++++++++++ 2 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 src/test/managers/conda/condaUtils.getCondaForWorkspace.unit.test.ts diff --git a/src/managers/conda/condaUtils.ts b/src/managers/conda/condaUtils.ts index 098aa9c7..09153bcb 100644 --- a/src/managers/conda/condaUtils.ts +++ b/src/managers/conda/condaUtils.ts @@ -82,19 +82,25 @@ export function getCondaPathSetting(): string | undefined { } export async function getCondaForWorkspace(fsPath: string): Promise { - if (process.env.CONDA_PREFIX) { - return process.env.CONDA_PREFIX; - } - + // Check persisted user selection first so explicit choices survive restarts const state = await getWorkspacePersistentState(); const data: { [key: string]: string } | undefined = await state.get(CONDA_WORKSPACE_KEY); if (data) { try { - return data[fsPath]; + const saved = data[fsPath]; + if (saved) { + return saved; + } } catch { - return undefined; + // fall through to CONDA_PREFIX fallback } } + + // Fall back to CONDA_PREFIX only when no explicit selection exists + if (process.env.CONDA_PREFIX) { + return process.env.CONDA_PREFIX; + } + return undefined; } diff --git a/src/test/managers/conda/condaUtils.getCondaForWorkspace.unit.test.ts b/src/test/managers/conda/condaUtils.getCondaForWorkspace.unit.test.ts new file mode 100644 index 00000000..664e5f66 --- /dev/null +++ b/src/test/managers/conda/condaUtils.getCondaForWorkspace.unit.test.ts @@ -0,0 +1,94 @@ +import assert from 'assert'; +import * as sinon from 'sinon'; +import * as persistentState from '../../../common/persistentState'; +import { CONDA_WORKSPACE_KEY, getCondaForWorkspace } from '../../../managers/conda/condaUtils'; + +suite('Conda Utils - getCondaForWorkspace prioritization', () => { + let mockState: { get: sinon.SinonStub; set: sinon.SinonStub }; + let getWorkspacePersistentStateStub: sinon.SinonStub; + let originalCondaPrefix: string | undefined; + + setup(() => { + originalCondaPrefix = process.env.CONDA_PREFIX; + + mockState = { + get: sinon.stub(), + set: sinon.stub().resolves(), + }; + getWorkspacePersistentStateStub = sinon.stub(persistentState, 'getWorkspacePersistentState'); + getWorkspacePersistentStateStub.resolves(mockState); + }); + + teardown(() => { + if (originalCondaPrefix === undefined) { + delete process.env.CONDA_PREFIX; + } else { + process.env.CONDA_PREFIX = originalCondaPrefix; + } + sinon.restore(); + }); + + test('Persisted selection takes priority over CONDA_PREFIX', async () => { + const workspacePath = '/home/user/project'; + const userSelectedEnv = '/home/user/miniconda3/envs/myenv'; + process.env.CONDA_PREFIX = '/home/user/miniconda3'; + + mockState.get.withArgs(CONDA_WORKSPACE_KEY).resolves({ + [workspacePath]: userSelectedEnv, + }); + + const result = await getCondaForWorkspace(workspacePath); + + assert.strictEqual(result, userSelectedEnv); + }); + + test('CONDA_PREFIX is used as fallback when no persisted selection exists', async () => { + const workspacePath = '/home/user/project'; + const condaBase = '/home/user/miniconda3'; + process.env.CONDA_PREFIX = condaBase; + + mockState.get.withArgs(CONDA_WORKSPACE_KEY).resolves(undefined); + + const result = await getCondaForWorkspace(workspacePath); + + assert.strictEqual(result, condaBase); + }); + + test('CONDA_PREFIX is used when persisted data exists but not for this workspace', async () => { + const workspacePath = '/home/user/project'; + const condaBase = '/home/user/miniconda3'; + process.env.CONDA_PREFIX = condaBase; + + mockState.get.withArgs(CONDA_WORKSPACE_KEY).resolves({ + '/home/user/other-project': '/home/user/miniconda3/envs/other', + }); + + const result = await getCondaForWorkspace(workspacePath); + + assert.strictEqual(result, condaBase); + }); + + test('Returns undefined when no persisted selection and no CONDA_PREFIX', async () => { + delete process.env.CONDA_PREFIX; + + mockState.get.withArgs(CONDA_WORKSPACE_KEY).resolves(undefined); + + const result = await getCondaForWorkspace('/home/user/project'); + + assert.strictEqual(result, undefined); + }); + + test('Returns persisted selection when CONDA_PREFIX is not set', async () => { + const workspacePath = '/home/user/project'; + const userSelectedEnv = '/home/user/miniconda3/envs/myenv'; + delete process.env.CONDA_PREFIX; + + mockState.get.withArgs(CONDA_WORKSPACE_KEY).resolves({ + [workspacePath]: userSelectedEnv, + }); + + const result = await getCondaForWorkspace(workspacePath); + + assert.strictEqual(result, userSelectedEnv); + }); +}); From 3f13dcbe404e902c83a46843d967378403625b70 Mon Sep 17 00:00:00 2001 From: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com> Date: Wed, 25 Mar 2026 13:36:47 -0700 Subject: [PATCH 2/2] address copilot comments --- src/managers/conda/condaUtils.ts | 14 +++++--------- .../condaUtils.getCondaForWorkspace.unit.test.ts | 13 +++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/managers/conda/condaUtils.ts b/src/managers/conda/condaUtils.ts index 09153bcb..24d18265 100644 --- a/src/managers/conda/condaUtils.ts +++ b/src/managers/conda/condaUtils.ts @@ -84,15 +84,11 @@ export function getCondaPathSetting(): string | undefined { export async function getCondaForWorkspace(fsPath: string): Promise { // Check persisted user selection first so explicit choices survive restarts const state = await getWorkspacePersistentState(); - const data: { [key: string]: string } | undefined = await state.get(CONDA_WORKSPACE_KEY); - if (data) { - try { - const saved = data[fsPath]; - if (saved) { - return saved; - } - } catch { - // fall through to CONDA_PREFIX fallback + const data = await state.get(CONDA_WORKSPACE_KEY); + if (data && typeof data === 'object') { + const workspaceSelections = data as { [key: string]: string }; + if (Object.prototype.hasOwnProperty.call(workspaceSelections, fsPath)) { + return workspaceSelections[fsPath]; } } diff --git a/src/test/managers/conda/condaUtils.getCondaForWorkspace.unit.test.ts b/src/test/managers/conda/condaUtils.getCondaForWorkspace.unit.test.ts index 664e5f66..22a10dc7 100644 --- a/src/test/managers/conda/condaUtils.getCondaForWorkspace.unit.test.ts +++ b/src/test/managers/conda/condaUtils.getCondaForWorkspace.unit.test.ts @@ -91,4 +91,17 @@ suite('Conda Utils - getCondaForWorkspace prioritization', () => { assert.strictEqual(result, userSelectedEnv); }); + + test('Returns persisted empty string without falling back to CONDA_PREFIX', async () => { + const workspacePath = '/home/user/project'; + process.env.CONDA_PREFIX = '/home/user/miniconda3'; + + mockState.get.withArgs(CONDA_WORKSPACE_KEY).resolves({ + [workspacePath]: '', + }); + + const result = await getCondaForWorkspace(workspacePath); + + assert.strictEqual(result, ''); + }); });