refactor(languages/node): adapt scripts path resolution

Cygwin isn't the only edge-case for a differing bin/ path. In addition there
also is MSYS2, which behaves differently than Cygwin. CPython compiled against
Microsoft Visual C++ Runtime (MSVCRT) through MinGW, will correctly identify as
an 'nt' platform, yet will prefer a POSIX path scheme.

In order to avoid having to patch every edge-case, we can spy on the system
configurations install paths through the `sysconfig` module and get the basename
of the global scripts path, which will be returned in accordance with the
preferred install path scheme of the system/platform.

Fixes: https://github.com/pre-commit/pre-commit/issues/3448
This commit is contained in:
Rodney, Tiara 2025-04-15 15:12:07 +02:00
parent 7c4dfd7779
commit 0d50ffc2b7
No known key found for this signature in database
GPG key ID: 5CD8EC1D46106723

View file

@ -4,6 +4,7 @@ import contextlib
import functools
import os
import sys
import sysconfig
from collections.abc import Generator
from collections.abc import Sequence
@ -37,16 +38,18 @@ def get_default_version() -> str:
def get_env_patch(venv: str) -> PatchesT:
if sys.platform == 'cygwin': # pragma: no cover
_, win_venv, _ = cmd_output('cygpath', '-w', venv)
install_prefix = fr'{win_venv.strip()}\bin'
lib_dir = 'lib'
elif sys.platform == 'win32': # pragma: no cover
install_prefix = bin_dir(venv)
lib_dir = 'Scripts'
else: # pragma: win32 no cover
install_prefix = bin_dir(venv)
lib_dir = 'lib'
# if not a Cygwin platform and not a win32 platform with a Windows path scheme
# catering to the previously defined edge-cases.
if sys.platform != 'cygwin' and (sys.platform == 'win32' and install_prefix.name != 'Scripts'):
install_prefix = venv
lib_dir = 'lib'
if install_prefix.name != 'bin':
lib_dir = install_prefix.name
return (
('NODE_VIRTUAL_ENV', venv),
('NPM_CONFIG_PREFIX', install_prefix),
@ -54,7 +57,7 @@ def get_env_patch(venv: str) -> PatchesT:
('NPM_CONFIG_USERCONFIG', UNSET),
('npm_config_userconfig', UNSET),
('NODE_PATH', os.path.join(venv, lib_dir, 'node_modules')),
('PATH', (bin_dir(venv), os.pathsep, Var('PATH'))),
('PATH', (install_prefix, os.pathsep, Var('PATH'))),
)