From 7b21874c40df22973a7de6b6c0c3c52ad6a74b59 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 00:01:42 +0000 Subject: [PATCH 1/4] Initial plan From e30a070f7ba4f3365f8f6a6fed16926892d01179 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 00:04:52 +0000 Subject: [PATCH 2/4] Fix Windows path calculation in pyenvUtils for environment grouping On Windows, pyenv-win is at ~/.pyenv/pyenv-win/bin/pyenv.bat, so we need to go up 3 directory levels (not 2) to reach the pyenv root directory (~/.pyenv). This fixes environment grouping (PYENV_VERSIONS vs PYENV_ENVIRONMENTS) which was broken because versionsPath and envsPaths were calculated from the wrong parent directory. Co-authored-by: karthiknadig <3840081+karthiknadig@users.noreply.github.com> --- package-lock.json | 20 +++++++++-- src/managers/pyenv/pyenvUtils.ts | 17 ++++++++-- .../managers/pyenv/pyenvUtils.unit.test.ts | 33 +++++++++++++++++++ 3 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/test/managers/pyenv/pyenvUtils.unit.test.ts diff --git a/package-lock.json b/package-lock.json index 42751388..1b975f18 100644 --- a/package-lock.json +++ b/package-lock.json @@ -795,6 +795,7 @@ "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.16.0", "@typescript-eslint/types": "8.16.0", @@ -1480,6 +1481,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1523,6 +1525,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1713,6 +1716,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001580", "electron-to-chromium": "^1.4.648", @@ -2423,6 +2427,7 @@ "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -5176,6 +5181,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5301,6 +5307,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, + "peer": true, "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -5347,6 +5354,7 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, + "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", @@ -6144,6 +6152,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz", "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", "dev": true, + "peer": true, "requires": { "@typescript-eslint/scope-manager": "8.16.0", "@typescript-eslint/types": "8.16.0", @@ -6639,7 +6648,8 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true + "dev": true, + "peer": true }, "acorn-import-attributes": { "version": "1.9.5", @@ -6669,6 +6679,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6801,6 +6812,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", "dev": true, + "peer": true, "requires": { "caniuse-lite": "^1.0.30001580", "electron-to-chromium": "^1.4.648", @@ -7295,6 +7307,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz", "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, + "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -9280,7 +9293,8 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true + "dev": true, + "peer": true }, "uc.micro": { "version": "1.0.6", @@ -9366,6 +9380,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, + "peer": true, "requires": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -9397,6 +9412,7 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, + "peer": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", diff --git a/src/managers/pyenv/pyenvUtils.ts b/src/managers/pyenv/pyenvUtils.ts index 8ab51fb0..b388e800 100644 --- a/src/managers/pyenv/pyenvUtils.ts +++ b/src/managers/pyenv/pyenvUtils.ts @@ -23,6 +23,18 @@ import { } from '../common/nativePythonFinder'; import { shortVersion, sortEnvironments } from '../common/utils'; +/** + * Returns the pyenv root directory from the pyenv executable path. + * On Windows, pyenv-win is at `~/.pyenv/pyenv-win/bin/pyenv.bat` (3 levels up). + * On POSIX, pyenv is at `~/.pyenv/bin/pyenv` (2 levels up). + */ +export function getPyenvDir(pyenv: string): string { + if (isWindows()) { + return path.dirname(path.dirname(path.dirname(pyenv))); + } + return path.dirname(path.dirname(pyenv)); +} + async function findPyenv(): Promise { try { return await which('pyenv'); @@ -174,8 +186,9 @@ function nativeToPythonEnv( return undefined; } - const versionsPath = normalizePath(path.join(path.dirname(path.dirname(pyenv)), 'versions')); - const envsPaths = normalizePath(path.join(path.dirname(versionsPath), 'envs')); + const pyenvDir = getPyenvDir(pyenv); + const versionsPath = normalizePath(path.join(pyenvDir, 'versions')); + const envsPaths = normalizePath(path.join(pyenvDir, 'envs')); let group = undefined; const normPrefix = normalizePath(info.prefix); if (normPrefix.startsWith(versionsPath)) { diff --git a/src/test/managers/pyenv/pyenvUtils.unit.test.ts b/src/test/managers/pyenv/pyenvUtils.unit.test.ts new file mode 100644 index 00000000..0345f3c2 --- /dev/null +++ b/src/test/managers/pyenv/pyenvUtils.unit.test.ts @@ -0,0 +1,33 @@ +import assert from 'node:assert'; +import * as path from 'path'; +import * as sinon from 'sinon'; +import * as platformUtils from '../../../common/utils/platformUtils'; +import { getPyenvDir } from '../../../managers/pyenv/pyenvUtils'; + +suite('pyenvUtils - getPyenvDir', () => { + let isWindowsStub: sinon.SinonStub; + + setup(() => { + isWindowsStub = sinon.stub(platformUtils, 'isWindows'); + }); + + teardown(() => { + sinon.restore(); + }); + + test('should go up 2 levels on POSIX (bin/pyenv -> pyenv root)', () => { + isWindowsStub.returns(false); + // e.g. /home/user/.pyenv/bin/pyenv + const pyenvBin = path.join('home', 'user', '.pyenv', 'bin', 'pyenv'); + const result = getPyenvDir(pyenvBin); + assert.strictEqual(result, path.join('home', 'user', '.pyenv')); + }); + + test('should go up 3 levels on Windows (pyenv-win/bin/pyenv.bat -> pyenv root)', () => { + isWindowsStub.returns(true); + // e.g. C:\Users\user\.pyenv\pyenv-win\bin\pyenv.bat + const pyenvBin = path.join('C:', 'Users', 'user', '.pyenv', 'pyenv-win', 'bin', 'pyenv.bat'); + const result = getPyenvDir(pyenvBin); + assert.strictEqual(result, path.join('C:', 'Users', 'user', '.pyenv')); + }); +}); From 92717241436a481cb9b28eba792ae37700be5d03 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 00:05:11 +0000 Subject: [PATCH 3/4] Revert unintended package-lock.json changes from npm install Co-authored-by: karthiknadig <3840081+karthiknadig@users.noreply.github.com> --- package-lock.json | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1b975f18..42751388 100644 --- a/package-lock.json +++ b/package-lock.json @@ -795,7 +795,6 @@ "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.16.0", "@typescript-eslint/types": "8.16.0", @@ -1481,7 +1480,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1525,7 +1523,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1716,7 +1713,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001580", "electron-to-chromium": "^1.4.648", @@ -2427,7 +2423,6 @@ "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -5181,7 +5176,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5307,7 +5301,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, - "peer": true, "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -5354,7 +5347,6 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, - "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", @@ -6152,7 +6144,6 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz", "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", "dev": true, - "peer": true, "requires": { "@typescript-eslint/scope-manager": "8.16.0", "@typescript-eslint/types": "8.16.0", @@ -6648,8 +6639,7 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "peer": true + "dev": true }, "acorn-import-attributes": { "version": "1.9.5", @@ -6679,7 +6669,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6812,7 +6801,6 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", "dev": true, - "peer": true, "requires": { "caniuse-lite": "^1.0.30001580", "electron-to-chromium": "^1.4.648", @@ -7307,7 +7295,6 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz", "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, - "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -9293,8 +9280,7 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, - "peer": true + "dev": true }, "uc.micro": { "version": "1.0.6", @@ -9380,7 +9366,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, - "peer": true, "requires": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -9412,7 +9397,6 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, - "peer": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", From 12033b0d3bb115f01d868550a8ab6d5ea8c43432 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 20:28:18 +0000 Subject: [PATCH 4/4] Address review feedback: use PYENV_ROOT, revert to 2-levels-up, fix tests - Use PYENV_ROOT env var as primary source for pyenv root directory - Revert 3-levels-up Windows logic to 2-levels-up (pyenv-win versions are at ~/.pyenv/pyenv-win/versions/, not ~/.pyenv/versions/) - Add test for PYENV_ROOT preference - Fix POSIX test to use absolute paths with path.sep - Fix Windows test expectation to reflect correct 2-levels-up behavior Co-authored-by: karthiknadig <3840081+karthiknadig@users.noreply.github.com> --- src/managers/pyenv/pyenvUtils.ts | 11 ++++--- .../managers/pyenv/pyenvUtils.unit.test.ts | 33 ++++++++++++------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/managers/pyenv/pyenvUtils.ts b/src/managers/pyenv/pyenvUtils.ts index b388e800..8dde2213 100644 --- a/src/managers/pyenv/pyenvUtils.ts +++ b/src/managers/pyenv/pyenvUtils.ts @@ -25,12 +25,15 @@ import { shortVersion, sortEnvironments } from '../common/utils'; /** * Returns the pyenv root directory from the pyenv executable path. - * On Windows, pyenv-win is at `~/.pyenv/pyenv-win/bin/pyenv.bat` (3 levels up). - * On POSIX, pyenv is at `~/.pyenv/bin/pyenv` (2 levels up). + * Prefers `PYENV_ROOT` env var when set, otherwise goes up 2 levels from the binary. + * On POSIX, pyenv binary is at `/bin/pyenv` (e.g. `~/.pyenv/bin/pyenv`). + * On Windows, pyenv-win binary is at `/bin/pyenv.bat` (e.g. `~/.pyenv/pyenv-win/bin/pyenv.bat`, + * where `` is `~/.pyenv/pyenv-win`). */ export function getPyenvDir(pyenv: string): string { - if (isWindows()) { - return path.dirname(path.dirname(path.dirname(pyenv))); + const pyenvRoot = process.env.PYENV_ROOT; + if (pyenvRoot) { + return pyenvRoot; } return path.dirname(path.dirname(pyenv)); } diff --git a/src/test/managers/pyenv/pyenvUtils.unit.test.ts b/src/test/managers/pyenv/pyenvUtils.unit.test.ts index 0345f3c2..0f7024d7 100644 --- a/src/test/managers/pyenv/pyenvUtils.unit.test.ts +++ b/src/test/managers/pyenv/pyenvUtils.unit.test.ts @@ -1,33 +1,44 @@ import assert from 'node:assert'; import * as path from 'path'; import * as sinon from 'sinon'; -import * as platformUtils from '../../../common/utils/platformUtils'; import { getPyenvDir } from '../../../managers/pyenv/pyenvUtils'; suite('pyenvUtils - getPyenvDir', () => { - let isWindowsStub: sinon.SinonStub; + let originalPyenvRoot: string | undefined; setup(() => { - isWindowsStub = sinon.stub(platformUtils, 'isWindows'); + originalPyenvRoot = process.env.PYENV_ROOT; + delete process.env.PYENV_ROOT; }); teardown(() => { sinon.restore(); + if (originalPyenvRoot !== undefined) { + process.env.PYENV_ROOT = originalPyenvRoot; + } else { + delete process.env.PYENV_ROOT; + } }); - test('should go up 2 levels on POSIX (bin/pyenv -> pyenv root)', () => { - isWindowsStub.returns(false); + test('should use PYENV_ROOT when set', () => { + const pyenvRoot = path.join(path.sep, 'custom', 'pyenv', 'root'); + process.env.PYENV_ROOT = pyenvRoot; + const pyenvBin = path.join(path.sep, 'other', 'bin', 'pyenv'); + const result = getPyenvDir(pyenvBin); + assert.strictEqual(result, pyenvRoot); + }); + + test('should go up 2 levels on POSIX when PYENV_ROOT is not set (bin/pyenv -> pyenv root)', () => { // e.g. /home/user/.pyenv/bin/pyenv - const pyenvBin = path.join('home', 'user', '.pyenv', 'bin', 'pyenv'); + const pyenvBin = path.join(path.sep, 'home', 'user', '.pyenv', 'bin', 'pyenv'); const result = getPyenvDir(pyenvBin); - assert.strictEqual(result, path.join('home', 'user', '.pyenv')); + assert.strictEqual(result, path.join(path.sep, 'home', 'user', '.pyenv')); }); - test('should go up 3 levels on Windows (pyenv-win/bin/pyenv.bat -> pyenv root)', () => { - isWindowsStub.returns(true); - // e.g. C:\Users\user\.pyenv\pyenv-win\bin\pyenv.bat + test('should go up 2 levels on Windows when PYENV_ROOT is not set (pyenv-win/bin/pyenv.bat -> pyenv-win)', () => { + // e.g. C:\Users\user\.pyenv\pyenv-win\bin\pyenv.bat -> C:\Users\user\.pyenv\pyenv-win const pyenvBin = path.join('C:', 'Users', 'user', '.pyenv', 'pyenv-win', 'bin', 'pyenv.bat'); const result = getPyenvDir(pyenvBin); - assert.strictEqual(result, path.join('C:', 'Users', 'user', '.pyenv')); + assert.strictEqual(result, path.join('C:', 'Users', 'user', '.pyenv', 'pyenv-win')); }); });