mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-02-17 00:04:42 +04:00
Merge 98aea48511 into 8416413a0e
This commit is contained in:
commit
3ebf851ac6
7 changed files with 553 additions and 0 deletions
3
.github/workflows/languages.yaml
vendored
3
.github/workflows/languages.yaml
vendored
|
|
@ -41,6 +41,9 @@ jobs:
|
|||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
if: matrix.language == 'bun'
|
||||
|
||||
- run: echo "$CONDA\Scripts" >> "$GITHUB_PATH"
|
||||
shell: bash
|
||||
if: matrix.os == 'windows-latest' && matrix.language == 'conda'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pre_commit.lang_base import Language
|
||||
from pre_commit.languages import bun
|
||||
from pre_commit.languages import conda
|
||||
from pre_commit.languages import coursier
|
||||
from pre_commit.languages import dart
|
||||
|
|
@ -25,6 +26,7 @@ from pre_commit.languages import unsupported_script
|
|||
|
||||
|
||||
languages: dict[str, Language] = {
|
||||
'bun': bun,
|
||||
'conda': conda,
|
||||
'coursier': coursier,
|
||||
'dart': dart,
|
||||
|
|
|
|||
195
pre_commit/languages/bun.py
Normal file
195
pre_commit/languages/bun.py
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import functools
|
||||
import os.path
|
||||
import platform
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
import zipfile
|
||||
from collections.abc import Generator
|
||||
from collections.abc import Sequence
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit import lang_base
|
||||
from pre_commit.envcontext import envcontext
|
||||
from pre_commit.envcontext import PatchesT
|
||||
from pre_commit.envcontext import Var
|
||||
from pre_commit.languages.python import bin_dir
|
||||
from pre_commit.prefix import Prefix
|
||||
from pre_commit.util import cmd_output_b
|
||||
|
||||
ENVIRONMENT_DIR = 'bunenv'
|
||||
run_hook = lang_base.basic_run_hook
|
||||
|
||||
# Architecture mapping for Bun binary downloads
|
||||
_ARCH_ALIASES = {
|
||||
'x86_64': 'x64',
|
||||
'amd64': 'x64',
|
||||
'aarch64': 'aarch64',
|
||||
'arm64': 'aarch64',
|
||||
}
|
||||
_ARCH = platform.machine().lower()
|
||||
_ARCH = _ARCH_ALIASES.get(_ARCH, _ARCH)
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=1)
|
||||
def get_default_version() -> str:
|
||||
"""Detect if Bun is installed system-wide."""
|
||||
# Check for system-installed bun
|
||||
if lang_base.exe_exists('bun'):
|
||||
return 'system'
|
||||
else:
|
||||
return C.DEFAULT
|
||||
|
||||
|
||||
def _get_platform() -> str:
|
||||
"""Get platform string for Bun binary downloads."""
|
||||
if sys.platform == 'darwin':
|
||||
return 'darwin'
|
||||
elif sys.platform == 'win32':
|
||||
return 'windows'
|
||||
elif sys.platform.startswith('linux'):
|
||||
return 'linux'
|
||||
else:
|
||||
raise AssertionError(f'Unsupported platform: {sys.platform}')
|
||||
|
||||
|
||||
def _normalize_version(version: str) -> str:
|
||||
"""Normalize version string for download URL."""
|
||||
if version == C.DEFAULT:
|
||||
return 'latest'
|
||||
# Ensure version has 'bun-v' prefix for download URL
|
||||
if not version.startswith('bun-v'):
|
||||
if version.startswith('v'):
|
||||
return f'bun-{version}'
|
||||
else:
|
||||
return f'bun-v{version}'
|
||||
return version
|
||||
|
||||
|
||||
def _get_download_url(version: str) -> str:
|
||||
"""Construct Bun binary download URL from GitHub releases."""
|
||||
platform_name = _get_platform()
|
||||
normalized_version = _normalize_version(version)
|
||||
|
||||
# Bun release URL format:
|
||||
# https://github.com/oven-sh/bun/releases/download/bun-v1.1.42/bun-darwin-x64.zip
|
||||
# https://github.com/oven-sh/bun/releases/download/bun-v1.1.42/bun-linux-x64.zip
|
||||
# https://github.com/oven-sh/bun/releases/download/bun-v1.1.42/bun-windows-x64.zip
|
||||
base_url = 'https://github.com/oven-sh/bun/releases'
|
||||
|
||||
if normalized_version == 'latest':
|
||||
# Use latest release
|
||||
return f'{base_url}/latest/download/bun-{platform_name}-{_ARCH}.zip'
|
||||
else:
|
||||
# Use specific version
|
||||
return (
|
||||
f'{base_url}/download/{normalized_version}/'
|
||||
f'bun-{platform_name}-{_ARCH}.zip'
|
||||
)
|
||||
|
||||
|
||||
def _install_bun(version: str, dest: str) -> None:
|
||||
"""Download and extract Bun binary to destination directory."""
|
||||
url = _get_download_url(version)
|
||||
|
||||
try:
|
||||
resp = urllib.request.urlopen(url)
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code == 404:
|
||||
raise ValueError(
|
||||
f'Could not find Bun version matching your requirements '
|
||||
f'(version={version}; os={_get_platform()}; '
|
||||
f'arch={_ARCH}). Check available versions at '
|
||||
f'https://github.com/oven-sh/bun/releases',
|
||||
) from e
|
||||
else:
|
||||
raise
|
||||
|
||||
with tempfile.TemporaryFile() as f:
|
||||
shutil.copyfileobj(resp, f)
|
||||
f.seek(0)
|
||||
|
||||
with zipfile.ZipFile(f) as zipf:
|
||||
zipf.extractall(dest)
|
||||
|
||||
# Bun zipfile contains a directory like 'bun-darwin-x64' or 'bun-linux-x64'
|
||||
# Move the binary from the extracted directory to dest/bin/
|
||||
bin_dir_path = os.path.join(dest, 'bin')
|
||||
os.makedirs(bin_dir_path, exist_ok=True)
|
||||
|
||||
# Find the extracted directory
|
||||
for item in os.listdir(dest):
|
||||
item_path = os.path.join(dest, item)
|
||||
if os.path.isdir(item_path) and item.startswith('bun-'):
|
||||
# Move bun executable to bin directory
|
||||
bun_exe = 'bun.exe' if sys.platform == 'win32' else 'bun'
|
||||
src_exe = os.path.join(item_path, bun_exe)
|
||||
if os.path.exists(src_exe):
|
||||
shutil.move(src_exe, os.path.join(bin_dir_path, bun_exe))
|
||||
# Remove the extracted directory
|
||||
shutil.rmtree(item_path)
|
||||
break
|
||||
|
||||
|
||||
def get_env_patch(venv: str) -> PatchesT:
|
||||
"""Prepare environment variables for Bun execution."""
|
||||
# Bun is much simpler than Node - primarily just needs PATH
|
||||
return (
|
||||
('PATH', (bin_dir(venv), os.pathsep, Var('PATH'))),
|
||||
# BUN_INSTALL controls where global packages are installed
|
||||
('BUN_INSTALL', venv),
|
||||
)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def in_env(prefix: Prefix, version: str) -> Generator[None]:
|
||||
"""Context manager for Bun environment."""
|
||||
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
|
||||
with envcontext(get_env_patch(envdir)):
|
||||
yield
|
||||
|
||||
|
||||
def health_check(prefix: Prefix, version: str) -> str | None:
|
||||
"""Check if Bun environment is healthy."""
|
||||
with in_env(prefix, version):
|
||||
retcode, _, _ = cmd_output_b('bun', '--version', check=False)
|
||||
if retcode != 0: # pragma: no cover
|
||||
return f'`bun --version` returned {retcode}'
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def install_environment(
|
||||
prefix: Prefix,
|
||||
version: str,
|
||||
additional_dependencies: Sequence[str],
|
||||
) -> None:
|
||||
"""Install Bun environment and dependencies."""
|
||||
assert prefix.exists('package.json')
|
||||
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
|
||||
|
||||
# Install Bun binary (unless using system version)
|
||||
if version != 'system':
|
||||
_install_bun(version, envdir)
|
||||
|
||||
with in_env(prefix, version):
|
||||
# Install local dependencies from package.json
|
||||
# Use --no-progress to avoid cluttering output
|
||||
install_cmd = ('bun', 'install', '--no-progress')
|
||||
lang_base.setup_cmd(prefix, install_cmd)
|
||||
|
||||
# Install the package globally from the current directory
|
||||
# Bun's global install uses `bun add -g` with file: protocol
|
||||
# We need to install from an absolute file path, so we use file:.
|
||||
# Note: Unlike npm, bun creates symlinks to the local package,
|
||||
# so we must NOT delete node_modules or the bin directory.
|
||||
abs_prefix = os.path.abspath(prefix.prefix_dir)
|
||||
install = ['bun', 'add', '-g', f'file:{abs_prefix}']
|
||||
if additional_dependencies:
|
||||
install.extend(additional_dependencies)
|
||||
lang_base.setup_cmd(prefix, tuple(install))
|
||||
5
testing/resources/bun-hook-repo/.pre-commit-hooks.yaml
Normal file
5
testing/resources/bun-hook-repo/.pre-commit-hooks.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
- id: test-bun-hook
|
||||
name: Test Bun Hook
|
||||
entry: test-bun-hook
|
||||
language: bun
|
||||
files: \.txt$
|
||||
16
testing/resources/bun-hook-repo/bin/test-hook.js
Executable file
16
testing/resources/bun-hook-repo/bin/test-hook.js
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env node
|
||||
// Simple test hook that validates file content
|
||||
const fs = require('fs');
|
||||
|
||||
const files = process.argv.slice(2);
|
||||
let failed = false;
|
||||
|
||||
files.forEach(file => {
|
||||
const content = fs.readFileSync(file, 'utf8');
|
||||
if (content.includes('bad')) {
|
||||
console.error(`Error in ${file}: contains 'bad'`);
|
||||
failed = true;
|
||||
}
|
||||
});
|
||||
|
||||
process.exit(failed ? 1 : 0);
|
||||
7
testing/resources/bun-hook-repo/package.json
Normal file
7
testing/resources/bun-hook-repo/package.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "test-bun-hook",
|
||||
"version": "1.0.0",
|
||||
"bin": {
|
||||
"test-bun-hook": "./bin/test-hook.js"
|
||||
}
|
||||
}
|
||||
325
tests/languages/bun_test.py
Normal file
325
tests/languages/bun_test.py
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit import lang_base
|
||||
from pre_commit import parse_shebang
|
||||
from pre_commit.languages import bun
|
||||
from pre_commit.prefix import Prefix
|
||||
from pre_commit.store import _make_local_repo
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
ACTUAL_GET_DEFAULT_VERSION = bun.get_default_version.__wrapped__
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def find_exe_mck():
|
||||
with mock.patch.object(parse_shebang, 'find_executable') as mck:
|
||||
yield mck
|
||||
|
||||
|
||||
def test_sets_system_when_bun_is_available(find_exe_mck):
|
||||
find_exe_mck.return_value = '/path/to/exe'
|
||||
assert ACTUAL_GET_DEFAULT_VERSION() == 'system'
|
||||
|
||||
|
||||
def test_uses_default_when_bun_is_not_available(find_exe_mck):
|
||||
find_exe_mck.return_value = None
|
||||
assert ACTUAL_GET_DEFAULT_VERSION() == C.DEFAULT
|
||||
|
||||
|
||||
def _make_hello_world(tmp_path):
|
||||
"""Create a simple Node/Bun package for testing."""
|
||||
package_json = '''\
|
||||
{
|
||||
"name": "test-bun-hook",
|
||||
"version": "1.0.0",
|
||||
"bin": {"bun-hello": "./bin/bun-hello.js"}
|
||||
}
|
||||
'''
|
||||
bin_script = '''\
|
||||
#!/usr/bin/env node
|
||||
console.log('Hello World');
|
||||
'''
|
||||
|
||||
tmp_path.joinpath('package.json').write_text(package_json)
|
||||
bin_dir = tmp_path.joinpath('bin')
|
||||
bin_dir.mkdir()
|
||||
bin_dir.joinpath('bun-hello.js').write_text(bin_script)
|
||||
|
||||
|
||||
def test_bun_default_version():
|
||||
"""Test default version detection."""
|
||||
version = bun.get_default_version()
|
||||
# Should return either 'system' or 'default'
|
||||
assert version in {'system', 'default'}
|
||||
|
||||
|
||||
def test_bun_hook_system(tmp_path):
|
||||
"""Test running a hook with system Bun."""
|
||||
_make_hello_world(tmp_path)
|
||||
ret = run_language(tmp_path, bun, 'bun-hello')
|
||||
assert ret == (0, b'Hello World\n')
|
||||
|
||||
|
||||
def test_bun_hook_default_version(tmp_path):
|
||||
"""Test running a hook with downloaded Bun (default/latest)."""
|
||||
_make_hello_world(tmp_path)
|
||||
ret = run_language(tmp_path, bun, 'bun-hello', version=C.DEFAULT)
|
||||
assert ret == (0, b'Hello World\n')
|
||||
|
||||
|
||||
def test_bun_hook_specific_version(tmp_path):
|
||||
"""Test running a hook with specific Bun version."""
|
||||
_make_hello_world(tmp_path)
|
||||
# Use a known stable version
|
||||
ret = run_language(tmp_path, bun, 'bun-hello', version='1.1.42')
|
||||
assert ret == (0, b'Hello World\n')
|
||||
|
||||
|
||||
def test_bun_additional_dependencies(tmp_path):
|
||||
"""Test installing additional dependencies."""
|
||||
_make_local_repo(str(tmp_path))
|
||||
ret, out = run_language(
|
||||
tmp_path,
|
||||
bun,
|
||||
'bun pm ls -g',
|
||||
deps=('lodash',),
|
||||
)
|
||||
assert b'lodash' in out
|
||||
|
||||
|
||||
def test_bun_with_package_json_only(tmp_path):
|
||||
"""Test that package.json is required."""
|
||||
# Don't create package.json - just create a Prefix
|
||||
prefix = Prefix(str(tmp_path))
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
bun.install_environment(prefix, 'system', ())
|
||||
|
||||
|
||||
def test_environment_dir():
|
||||
"""Test ENVIRONMENT_DIR is set correctly."""
|
||||
assert bun.ENVIRONMENT_DIR == 'bunenv'
|
||||
|
||||
|
||||
def test_run_hook_uses_basic():
|
||||
"""Test that run_hook is set to basic implementation."""
|
||||
assert bun.run_hook is lang_base.basic_run_hook
|
||||
|
||||
|
||||
def test_bun_health_check_success(tmp_path):
|
||||
"""Test health check with valid environment."""
|
||||
_make_hello_world(tmp_path)
|
||||
|
||||
_make_local_repo(str(tmp_path))
|
||||
prefix = Prefix(str(tmp_path))
|
||||
bun.install_environment(prefix, 'system', ())
|
||||
|
||||
health = bun.health_check(prefix, 'system')
|
||||
assert health is None # None means healthy
|
||||
|
||||
|
||||
def test_get_platform_darwin():
|
||||
"""Test platform detection for macOS."""
|
||||
with mock.patch.object(sys, 'platform', 'darwin'):
|
||||
assert bun._get_platform() == 'darwin'
|
||||
|
||||
|
||||
def test_get_platform_linux():
|
||||
"""Test platform detection for Linux."""
|
||||
with mock.patch.object(sys, 'platform', 'linux'):
|
||||
assert bun._get_platform() == 'linux'
|
||||
|
||||
|
||||
def test_get_platform_linux_with_suffix():
|
||||
"""Test platform detection for Linux with version suffix."""
|
||||
with mock.patch.object(sys, 'platform', 'linux2'):
|
||||
assert bun._get_platform() == 'linux'
|
||||
|
||||
|
||||
def test_get_platform_windows():
|
||||
"""Test platform detection for Windows."""
|
||||
with mock.patch.object(sys, 'platform', 'win32'):
|
||||
assert bun._get_platform() == 'windows'
|
||||
|
||||
|
||||
def test_get_platform_unsupported():
|
||||
"""Test platform detection fails for unsupported platform."""
|
||||
with mock.patch.object(sys, 'platform', 'freebsd'):
|
||||
with pytest.raises(
|
||||
AssertionError, match='Unsupported platform: freebsd',
|
||||
):
|
||||
bun._get_platform()
|
||||
|
||||
|
||||
def test_normalize_version_default():
|
||||
"""Test version normalization for default version."""
|
||||
assert bun._normalize_version(C.DEFAULT) == 'latest'
|
||||
|
||||
|
||||
def test_normalize_version_latest():
|
||||
"""Test version normalization for 'latest' string.
|
||||
|
||||
Note: 'latest' as a direct string gets treated as a version tag,
|
||||
not as the special latest keyword. Use C.DEFAULT for that.
|
||||
"""
|
||||
assert bun._normalize_version('latest') == 'bun-vlatest'
|
||||
|
||||
|
||||
def test_normalize_version_plain_number():
|
||||
"""Test version normalization for plain version number."""
|
||||
assert bun._normalize_version('1.1.42') == 'bun-v1.1.42'
|
||||
|
||||
|
||||
def test_normalize_version_with_v_prefix():
|
||||
"""Test version normalization for version with 'v' prefix."""
|
||||
assert bun._normalize_version('v1.1.42') == 'bun-v1.1.42'
|
||||
|
||||
|
||||
def test_normalize_version_with_bun_v_prefix():
|
||||
"""Test version normalization for version already with 'bun-v' prefix."""
|
||||
assert bun._normalize_version('bun-v1.1.42') == 'bun-v1.1.42'
|
||||
|
||||
|
||||
def test_install_bun_invalid_version_raises_error(tmp_path):
|
||||
"""Test that installing invalid Bun version raises ValueError."""
|
||||
import urllib.error
|
||||
|
||||
# Create a mock HTTPError with 404 status
|
||||
mock_error = urllib.error.HTTPError(
|
||||
url='https://github.com/oven-sh/bun/releases/'
|
||||
'download/bun-v99.99.99/bun-darwin-x64.zip',
|
||||
code=404,
|
||||
msg='Not Found',
|
||||
hdrs=None, # type: ignore
|
||||
fp=None,
|
||||
)
|
||||
|
||||
with mock.patch('urllib.request.urlopen', side_effect=mock_error):
|
||||
with pytest.raises(
|
||||
ValueError, match='Could not find Bun version',
|
||||
):
|
||||
bun._install_bun('99.99.99', str(tmp_path))
|
||||
|
||||
|
||||
def test_install_bun_other_http_error_propagates(tmp_path):
|
||||
"""Test that non-404 HTTP errors are propagated."""
|
||||
import urllib.error
|
||||
|
||||
# Create a mock HTTPError with 500 status
|
||||
mock_error = urllib.error.HTTPError(
|
||||
url='https://github.com/oven-sh/bun/releases/'
|
||||
'download/bun-v1.1.42/bun-darwin-x64.zip',
|
||||
code=500,
|
||||
msg='Internal Server Error',
|
||||
hdrs=None, # type: ignore
|
||||
fp=None,
|
||||
)
|
||||
|
||||
with mock.patch('urllib.request.urlopen', side_effect=mock_error):
|
||||
with pytest.raises(urllib.error.HTTPError) as exc_info:
|
||||
bun._install_bun('1.1.42', str(tmp_path))
|
||||
assert exc_info.value.code == 500
|
||||
|
||||
|
||||
def test_install_bun_no_bun_directory_found(tmp_path):
|
||||
"""Test extraction works even if no bun directory found."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
dest = str(tmp_path / 'bunenv')
|
||||
os.makedirs(dest, exist_ok=True)
|
||||
|
||||
# Create a file after extraction (not a bun- directory)
|
||||
(tmp_path / 'bunenv' / 'some-other-file.txt').write_text('content')
|
||||
|
||||
# Create a mock zip file that does nothing on extractall
|
||||
mock_zipfile = MagicMock()
|
||||
mock_zipfile.__enter__.return_value = mock_zipfile
|
||||
mock_zipfile.__exit__.return_value = None
|
||||
mock_zipfile.extractall = MagicMock()
|
||||
|
||||
with mock.patch('urllib.request.urlopen') as mock_urlopen, \
|
||||
mock.patch('shutil.copyfileobj'), \
|
||||
mock.patch('zipfile.ZipFile', return_value=mock_zipfile):
|
||||
|
||||
# Mock urlopen to return a fake response
|
||||
mock_response = MagicMock()
|
||||
mock_urlopen.return_value = mock_response
|
||||
|
||||
# Should complete without error (loop exits)
|
||||
bun._install_bun('1.1.42', dest)
|
||||
|
||||
# Verify bin directory was still created
|
||||
assert os.path.exists(os.path.join(dest, 'bin'))
|
||||
|
||||
|
||||
def test_install_bun_missing_executable_in_directory(tmp_path):
|
||||
"""Test extraction handles missing executable gracefully."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
dest = str(tmp_path / 'bunenv')
|
||||
os.makedirs(dest, exist_ok=True)
|
||||
|
||||
# Create a bun directory without the executable
|
||||
bun_dir = tmp_path / 'bunenv' / 'bun-darwin-x64'
|
||||
bun_dir.mkdir()
|
||||
(bun_dir / 'README.md').write_text('readme')
|
||||
|
||||
# Create a mock zip file that does nothing
|
||||
mock_zipfile = MagicMock()
|
||||
mock_zipfile.__enter__.return_value = mock_zipfile
|
||||
mock_zipfile.__exit__.return_value = None
|
||||
mock_zipfile.extractall = MagicMock()
|
||||
|
||||
with mock.patch('urllib.request.urlopen') as mock_urlopen, \
|
||||
mock.patch('shutil.copyfileobj'), \
|
||||
mock.patch('zipfile.ZipFile', return_value=mock_zipfile):
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_urlopen.return_value = mock_response
|
||||
|
||||
# Should complete without error
|
||||
bun._install_bun('1.1.42', dest)
|
||||
|
||||
# Verify the bun directory was still removed
|
||||
assert not bun_dir.exists()
|
||||
|
||||
|
||||
def test_install_environment_system_version_skips_download(tmp_path):
|
||||
"""Test that system version doesn't download Bun binary."""
|
||||
_make_hello_world(tmp_path)
|
||||
_make_local_repo(str(tmp_path))
|
||||
prefix = Prefix(str(tmp_path))
|
||||
|
||||
# Mock _install_bun to ensure it's never called
|
||||
with mock.patch.object(bun, '_install_bun') as mock_install:
|
||||
bun.install_environment(prefix, 'system', ())
|
||||
|
||||
# Verify _install_bun was NOT called
|
||||
mock_install.assert_not_called()
|
||||
|
||||
# Verify environment still works
|
||||
assert bun.health_check(prefix, 'system') is None
|
||||
|
||||
|
||||
def test_install_environment_system_version_skips_download_mock(tmp_path):
|
||||
"""Test that system version doesn't download Bun binary (mocked)."""
|
||||
_make_hello_world(tmp_path)
|
||||
_make_local_repo(str(tmp_path))
|
||||
prefix = Prefix(str(tmp_path))
|
||||
|
||||
# Mock all the bun commands to avoid needing system bun
|
||||
with mock.patch.object(bun, '_install_bun') as mock_install, \
|
||||
mock.patch('pre_commit.lang_base.setup_cmd'):
|
||||
|
||||
bun.install_environment(prefix, 'system', ())
|
||||
|
||||
# Verify _install_bun was NOT called for system version
|
||||
mock_install.assert_not_called()
|
||||
Loading…
Add table
Add a link
Reference in a new issue