1
0
Fork 0

Merging upstream version 3.1.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-09 21:38:08 +01:00
parent f7ee0eb8fc
commit c4c52947de
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
88 changed files with 1083 additions and 974 deletions

View file

@ -0,0 +1,48 @@
from __future__ import annotations
from pre_commit.lang_base import Language
from pre_commit.languages import conda
from pre_commit.languages import coursier
from pre_commit.languages import dart
from pre_commit.languages import docker
from pre_commit.languages import docker_image
from pre_commit.languages import dotnet
from pre_commit.languages import fail
from pre_commit.languages import golang
from pre_commit.languages import lua
from pre_commit.languages import node
from pre_commit.languages import perl
from pre_commit.languages import pygrep
from pre_commit.languages import python
from pre_commit.languages import r
from pre_commit.languages import ruby
from pre_commit.languages import rust
from pre_commit.languages import script
from pre_commit.languages import swift
from pre_commit.languages import system
languages: dict[str, Language] = {
'conda': conda,
'coursier': coursier,
'dart': dart,
'docker': docker,
'docker_image': docker_image,
'dotnet': dotnet,
'fail': fail,
'golang': golang,
'lua': lua,
'node': node,
'perl': perl,
'pygrep': pygrep,
'python': python,
'r': r,
'ruby': ruby,
'rust': rust,
'script': script,
'swift': swift,
'system': system,
# TODO: fully deprecate `python_venv`
'python_venv': python,
}
language_names = sorted(languages)

View file

@ -12,8 +12,8 @@ import cfgv
from identify.identify import ALL_TAGS
import pre_commit.constants as C
from pre_commit.all_languages import language_names
from pre_commit.errors import FatalError
from pre_commit.languages.all import all_languages
from pre_commit.yaml import yaml_load
logger = logging.getLogger('pre_commit')
@ -49,7 +49,7 @@ MANIFEST_HOOK_DICT = cfgv.Map(
cfgv.Required('id', cfgv.check_string),
cfgv.Required('name', cfgv.check_string),
cfgv.Required('entry', cfgv.check_string),
cfgv.Required('language', cfgv.check_one_of(all_languages)),
cfgv.Required('language', cfgv.check_one_of(language_names)),
cfgv.Optional('alias', cfgv.check_string, ''),
cfgv.Optional('files', check_string_regex, ''),
@ -281,8 +281,8 @@ CONFIG_REPO_DICT = cfgv.Map(
)
DEFAULT_LANGUAGE_VERSION = cfgv.Map(
'DefaultLanguageVersion', None,
cfgv.NoAdditionalKeys(all_languages),
*(cfgv.Optional(x, cfgv.check_string, C.DEFAULT) for x in all_languages),
cfgv.NoAdditionalKeys(language_names),
*(cfgv.Optional(x, cfgv.check_string, C.DEFAULT) for x in language_names),
)
CONFIG_SCHEMA = cfgv.Map(
'Config', None,

View file

@ -42,6 +42,14 @@ def _migrate_sha_to_rev(contents: str) -> str:
return re.sub(r'(\n\s+)sha:', r'\1rev:', contents)
def _migrate_python_venv(contents: str) -> str:
return re.sub(
r'(\n\s+)language: python_venv\b',
r'\1language: python',
contents,
)
def migrate_config(config_file: str, quiet: bool = False) -> int:
with open(config_file) as f:
orig_contents = contents = f.read()
@ -55,6 +63,7 @@ def migrate_config(config_file: str, quiet: bool = False) -> int:
contents = _migrate_map(contents)
contents = _migrate_sha_to_rev(contents)
contents = _migrate_python_venv(contents)
if contents != orig_contents:
with open(config_file, 'w') as f:

View file

@ -19,9 +19,9 @@ from identify.identify import tags_from_path
from pre_commit import color
from pre_commit import git
from pre_commit import output
from pre_commit.all_languages import languages
from pre_commit.clientlib import load_config
from pre_commit.hook import Hook
from pre_commit.languages.all import languages
from pre_commit.repository import all_hooks
from pre_commit.repository import install_hook_envs
from pre_commit.staged_files_only import staged_files_only

View file

@ -7,8 +7,10 @@ import random
import re
import shlex
from typing import Any
from typing import ContextManager
from typing import Generator
from typing import NoReturn
from typing import Protocol
from typing import Sequence
import pre_commit.constants as C
@ -22,6 +24,42 @@ FIXED_RANDOM_SEED = 1542676187
SHIMS_RE = re.compile(r'[/\\]shims[/\\]')
class Language(Protocol):
# Use `None` for no installation / environment
@property
def ENVIRONMENT_DIR(self) -> str | None: ...
# return a value to replace `'default` for `language_version`
def get_default_version(self) -> str: ...
# return whether the environment is healthy (or should be rebuilt)
def health_check(self, prefix: Prefix, version: str) -> str | None: ...
# install a repository for the given language and language_version
def install_environment(
self,
prefix: Prefix,
version: str,
additional_dependencies: Sequence[str],
) -> None:
...
# modify the environment for hook execution
def in_env(self, prefix: Prefix, version: str) -> ContextManager[None]: ...
# execute a hook and return the exit code and output
def run_hook(
self,
prefix: Prefix,
entry: str,
args: Sequence[str],
file_args: Sequence[str],
*,
is_local: bool,
require_serial: bool,
color: bool,
) -> tuple[int, bytes]:
...
def exe_exists(exe: str) -> bool:
found = parse_shebang.find_executable(exe)
if found is None: # exe exists
@ -45,7 +83,7 @@ def exe_exists(exe: str) -> bool:
)
def run_setup_cmd(prefix: Prefix, cmd: tuple[str, ...], **kwargs: Any) -> None:
def setup_cmd(prefix: Prefix, cmd: tuple[str, ...], **kwargs: Any) -> None:
cmd_output_b(*cmd, cwd=prefix.prefix_dir, **kwargs)

View file

@ -1,99 +0,0 @@
from __future__ import annotations
from typing import ContextManager
from typing import Protocol
from typing import Sequence
from pre_commit.languages import conda
from pre_commit.languages import coursier
from pre_commit.languages import dart
from pre_commit.languages import docker
from pre_commit.languages import docker_image
from pre_commit.languages import dotnet
from pre_commit.languages import fail
from pre_commit.languages import golang
from pre_commit.languages import lua
from pre_commit.languages import node
from pre_commit.languages import perl
from pre_commit.languages import pygrep
from pre_commit.languages import python
from pre_commit.languages import r
from pre_commit.languages import ruby
from pre_commit.languages import rust
from pre_commit.languages import script
from pre_commit.languages import swift
from pre_commit.languages import system
from pre_commit.prefix import Prefix
class Language(Protocol):
# Use `None` for no installation / environment
@property
def ENVIRONMENT_DIR(self) -> str | None: ...
# return a value to replace `'default` for `language_version`
def get_default_version(self) -> str: ...
# return whether the environment is healthy (or should be rebuilt)
def health_check(
self,
prefix: Prefix,
language_version: str,
) -> str | None:
...
# install a repository for the given language and language_version
def install_environment(
self,
prefix: Prefix,
version: str,
additional_dependencies: Sequence[str],
) -> None:
...
# modify the environment for hook execution
def in_env(
self,
prefix: Prefix,
version: str,
) -> ContextManager[None]:
...
# execute a hook and return the exit code and output
def run_hook(
self,
prefix: Prefix,
entry: str,
args: Sequence[str],
file_args: Sequence[str],
*,
is_local: bool,
require_serial: bool,
color: bool,
) -> tuple[int, bytes]:
...
languages: dict[str, Language] = {
'conda': conda,
'coursier': coursier,
'dart': dart,
'docker': docker,
'docker_image': docker_image,
'dotnet': dotnet,
'fail': fail,
'golang': golang,
'lua': lua,
'node': node,
'perl': perl,
'pygrep': pygrep,
'python': python,
'r': r,
'ruby': ruby,
'rust': rust,
'script': script,
'swift': swift,
'system': system,
# TODO: fully deprecate `python_venv`
'python_venv': python,
}
all_languages = sorted(languages)

View file

@ -5,19 +5,19 @@ import os
from typing import Generator
from typing import Sequence
from pre_commit import lang_base
from pre_commit.envcontext import envcontext
from pre_commit.envcontext import PatchesT
from pre_commit.envcontext import SubstitutionT
from pre_commit.envcontext import UNSET
from pre_commit.envcontext import Var
from pre_commit.languages import helpers
from pre_commit.prefix import Prefix
from pre_commit.util import cmd_output_b
ENVIRONMENT_DIR = 'conda'
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
run_hook = helpers.basic_run_hook
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
run_hook = lang_base.basic_run_hook
def get_env_patch(env: str) -> PatchesT:
@ -41,7 +41,7 @@ def get_env_patch(env: str) -> PatchesT:
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir)):
yield
@ -60,11 +60,11 @@ def install_environment(
version: str,
additional_dependencies: Sequence[str],
) -> None:
helpers.assert_version_default('conda', version)
lang_base.assert_version_default('conda', version)
conda_exe = _conda_exe()
env_dir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
env_dir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
cmd_output_b(
conda_exe, 'env', 'create', '-p', env_dir, '--file',
'environment.yml', cwd=prefix.prefix_dir,

View file

@ -5,19 +5,19 @@ import os.path
from typing import Generator
from typing import Sequence
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.errors import FatalError
from pre_commit.languages import helpers
from pre_commit.parse_shebang import find_executable
from pre_commit.prefix import Prefix
ENVIRONMENT_DIR = 'coursier'
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
run_hook = helpers.basic_run_hook
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
run_hook = lang_base.basic_run_hook
def install_environment(
@ -25,7 +25,7 @@ def install_environment(
version: str,
additional_dependencies: Sequence[str],
) -> None:
helpers.assert_version_default('coursier', version)
lang_base.assert_version_default('coursier', version)
# Support both possible executable names (either "cs" or "coursier")
cs = find_executable('cs') or find_executable('coursier')
@ -35,12 +35,12 @@ def install_environment(
'executables in the application search path',
)
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
def _install(*opts: str) -> None:
assert cs is not None
helpers.run_setup_cmd(prefix, (cs, 'fetch', *opts))
helpers.run_setup_cmd(prefix, (cs, 'install', '--dir', envdir, *opts))
lang_base.setup_cmd(prefix, (cs, 'fetch', *opts))
lang_base.setup_cmd(prefix, (cs, 'install', '--dir', envdir, *opts))
with in_env(prefix, version):
channel = prefix.path('.pre-commit-channel')
@ -71,6 +71,6 @@ def get_env_patch(target_dir: str) -> PatchesT:
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir)):
yield

View file

@ -7,19 +7,19 @@ import tempfile
from typing import Generator
from typing import Sequence
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 import helpers
from pre_commit.prefix import Prefix
from pre_commit.util import win_exe
from pre_commit.yaml import yaml_load
ENVIRONMENT_DIR = 'dartenv'
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
run_hook = helpers.basic_run_hook
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
run_hook = lang_base.basic_run_hook
def get_env_patch(venv: str) -> PatchesT:
@ -30,7 +30,7 @@ def get_env_patch(venv: str) -> PatchesT:
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir)):
yield
@ -40,9 +40,9 @@ def install_environment(
version: str,
additional_dependencies: Sequence[str],
) -> None:
helpers.assert_version_default('dart', version)
lang_base.assert_version_default('dart', version)
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
bin_dir = os.path.join(envdir, 'bin')
def _install_dir(prefix_p: Prefix, pub_cache: str) -> None:
@ -51,10 +51,10 @@ def install_environment(
with open(prefix_p.path('pubspec.yaml')) as f:
pubspec_contents = yaml_load(f)
helpers.run_setup_cmd(prefix_p, ('dart', 'pub', 'get'), env=dart_env)
lang_base.setup_cmd(prefix_p, ('dart', 'pub', 'get'), env=dart_env)
for executable in pubspec_contents['executables']:
helpers.run_setup_cmd(
lang_base.setup_cmd(
prefix_p,
(
'dart', 'compile', 'exe',
@ -77,7 +77,7 @@ def install_environment(
else:
dep_cmd = (dep,)
helpers.run_setup_cmd(
lang_base.setup_cmd(
prefix,
('dart', 'pub', 'cache', 'add', *dep_cmd),
env={**os.environ, 'PUB_CACHE': dep_tmp},

View file

@ -5,16 +5,16 @@ import json
import os
from typing import Sequence
from pre_commit.languages import helpers
from pre_commit import lang_base
from pre_commit.prefix import Prefix
from pre_commit.util import CalledProcessError
from pre_commit.util import cmd_output_b
ENVIRONMENT_DIR = 'docker'
PRE_COMMIT_LABEL = 'PRE_COMMIT'
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
in_env = helpers.no_env # no special environment for docker
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
in_env = lang_base.no_env # no special environment for docker
def _is_in_docker() -> bool:
@ -84,16 +84,16 @@ def build_docker_image(
cmd += ('--pull',)
# This must come last for old versions of docker. See #477
cmd += ('.',)
helpers.run_setup_cmd(prefix, cmd)
lang_base.setup_cmd(prefix, cmd)
def install_environment(
prefix: Prefix, version: str, additional_dependencies: Sequence[str],
) -> None: # pragma: win32 no cover
helpers.assert_version_default('docker', version)
helpers.assert_no_additional_deps('docker', additional_dependencies)
lang_base.assert_version_default('docker', version)
lang_base.assert_no_additional_deps('docker', additional_dependencies)
directory = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
directory = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
# Docker doesn't really have relevant disk environment, but pre-commit
# still needs to cleanup its state files on failure
@ -135,12 +135,11 @@ def run_hook(
# automated cleanup of docker images.
build_docker_image(prefix, pull=False)
entry_exe, *cmd_rest = helpers.hook_cmd(entry, args)
entry_exe, *cmd_rest = lang_base.hook_cmd(entry, args)
entry_tag = ('--entrypoint', entry_exe, docker_tag(prefix))
cmd = (*docker_cmd(), *entry_tag, *cmd_rest)
return helpers.run_xargs(
cmd,
return lang_base.run_xargs(
(*docker_cmd(), *entry_tag, *cmd_rest),
file_args,
require_serial=require_serial,
color=color,

View file

@ -2,15 +2,15 @@ from __future__ import annotations
from typing import Sequence
from pre_commit.languages import helpers
from pre_commit import lang_base
from pre_commit.languages.docker import docker_cmd
from pre_commit.prefix import Prefix
ENVIRONMENT_DIR = None
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
install_environment = helpers.no_install
in_env = helpers.no_env
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
install_environment = lang_base.no_install
in_env = lang_base.no_env
def run_hook(
@ -23,8 +23,8 @@ def run_hook(
require_serial: bool,
color: bool,
) -> tuple[int, bytes]: # pragma: win32 no cover
cmd = docker_cmd() + helpers.hook_cmd(entry, args)
return helpers.run_xargs(
cmd = docker_cmd() + lang_base.hook_cmd(entry, args)
return lang_base.run_xargs(
cmd,
file_args,
require_serial=require_serial,

View file

@ -9,18 +9,18 @@ import zipfile
from typing import Generator
from typing import Sequence
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 import helpers
from pre_commit.prefix import Prefix
ENVIRONMENT_DIR = 'dotnetenv'
BIN_DIR = 'bin'
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
run_hook = helpers.basic_run_hook
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
run_hook = lang_base.basic_run_hook
def get_env_patch(venv: str) -> PatchesT:
@ -31,7 +31,7 @@ def get_env_patch(venv: str) -> PatchesT:
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir)):
yield
@ -57,19 +57,19 @@ def install_environment(
version: str,
additional_dependencies: Sequence[str],
) -> None:
helpers.assert_version_default('dotnet', version)
helpers.assert_no_additional_deps('dotnet', additional_dependencies)
lang_base.assert_version_default('dotnet', version)
lang_base.assert_no_additional_deps('dotnet', additional_dependencies)
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
build_dir = 'pre-commit-build'
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
build_dir = prefix.path('pre-commit-build')
# Build & pack nupkg file
helpers.run_setup_cmd(
lang_base.setup_cmd(
prefix,
(
'dotnet', 'pack',
'--configuration', 'Release',
'--output', build_dir,
'--property', f'PackageOutputPath={build_dir}',
),
)
@ -99,7 +99,7 @@ def install_environment(
# Install to bin dir
with _nuget_config_no_sources() as nuget_config:
helpers.run_setup_cmd(
lang_base.setup_cmd(
prefix,
(
'dotnet', 'tool', 'install',
@ -109,7 +109,3 @@ def install_environment(
tool_id,
),
)
# Clean the git dir, ignoring the environment dir
clean_cmd = ('git', 'clean', '-ffxd', '-e', f'{ENVIRONMENT_DIR}-*')
helpers.run_setup_cmd(prefix, clean_cmd)

View file

@ -2,14 +2,14 @@ from __future__ import annotations
from typing import Sequence
from pre_commit.languages import helpers
from pre_commit import lang_base
from pre_commit.prefix import Prefix
ENVIRONMENT_DIR = None
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
install_environment = helpers.no_install
in_env = helpers.no_env
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
install_environment = lang_base.no_install
in_env = lang_base.no_env
def run_hook(

View file

@ -19,17 +19,17 @@ from typing import Protocol
from typing 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 import helpers
from pre_commit.prefix import Prefix
from pre_commit.util import cmd_output
from pre_commit.util import rmtree
ENVIRONMENT_DIR = 'golangenv'
health_check = helpers.basic_health_check
run_hook = helpers.basic_run_hook
health_check = lang_base.basic_health_check
run_hook = lang_base.basic_run_hook
_ARCH_ALIASES = {
'x86_64': 'amd64',
@ -60,7 +60,7 @@ else: # pragma: win32 no cover
@functools.lru_cache(maxsize=1)
def get_default_version() -> str:
if helpers.exe_exists('go'):
if lang_base.exe_exists('go'):
return 'system'
else:
return C.DEFAULT
@ -121,7 +121,7 @@ def _install_go(version: str, dest: str) -> None:
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir, version)):
yield
@ -131,7 +131,7 @@ def install_environment(
version: str,
additional_dependencies: Sequence[str],
) -> None:
env_dir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
env_dir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
if version != 'system':
_install_go(version, env_dir)
@ -149,9 +149,9 @@ def install_environment(
os.path.join(env_dir, '.go', 'bin'), os.environ['PATH'],
))
helpers.run_setup_cmd(prefix, ('go', 'install', './...'), env=env)
lang_base.setup_cmd(prefix, ('go', 'install', './...'), env=env)
for dependency in additional_dependencies:
helpers.run_setup_cmd(prefix, ('go', 'install', dependency), env=env)
lang_base.setup_cmd(prefix, ('go', 'install', dependency), env=env)
# save some disk space -- we don't need this after installation
pkgdir = os.path.join(env_dir, 'pkg')

View file

@ -6,17 +6,17 @@ import sys
from typing import Generator
from typing import Sequence
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 import helpers
from pre_commit.prefix import Prefix
from pre_commit.util import cmd_output
ENVIRONMENT_DIR = 'lua_env'
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
run_hook = helpers.basic_run_hook
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
run_hook = lang_base.basic_run_hook
def _get_lua_version() -> str: # pragma: win32 no cover
@ -45,7 +45,7 @@ def get_env_patch(d: str) -> PatchesT: # pragma: win32 no cover
@contextlib.contextmanager # pragma: win32 no cover
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir)):
yield
@ -55,9 +55,9 @@ def install_environment(
version: str,
additional_dependencies: Sequence[str],
) -> None: # pragma: win32 no cover
helpers.assert_version_default('lua', version)
lang_base.assert_version_default('lua', version)
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with in_env(prefix, version):
# luarocks doesn't bootstrap a tree prior to installing
# so ensure the directory exists.
@ -66,10 +66,10 @@ def install_environment(
# Older luarocks (e.g., 2.4.2) expect the rockspec as an arg
for rockspec in prefix.star('.rockspec'):
make_cmd = ('luarocks', '--tree', envdir, 'make', rockspec)
helpers.run_setup_cmd(prefix, make_cmd)
lang_base.setup_cmd(prefix, make_cmd)
# luarocks can't install multiple packages at once
# so install them individually.
for dependency in additional_dependencies:
cmd = ('luarocks', '--tree', envdir, 'install', dependency)
helpers.run_setup_cmd(prefix, cmd)
lang_base.setup_cmd(prefix, cmd)

View file

@ -8,11 +8,11 @@ from typing import Generator
from typing 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 UNSET
from pre_commit.envcontext import Var
from pre_commit.languages import helpers
from pre_commit.languages.python import bin_dir
from pre_commit.prefix import Prefix
from pre_commit.util import cmd_output
@ -20,7 +20,7 @@ from pre_commit.util import cmd_output_b
from pre_commit.util import rmtree
ENVIRONMENT_DIR = 'node_env'
run_hook = helpers.basic_run_hook
run_hook = lang_base.basic_run_hook
@functools.lru_cache(maxsize=1)
@ -30,7 +30,7 @@ def get_default_version() -> str:
return C.DEFAULT
# if node is already installed, we can save a bunch of setup time by
# using the installed version
elif all(helpers.exe_exists(exe) for exe in ('node', 'npm')):
elif all(lang_base.exe_exists(exe) for exe in ('node', 'npm')):
return 'system'
else:
return C.DEFAULT
@ -60,13 +60,13 @@ def get_env_patch(venv: str) -> PatchesT:
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir)):
yield
def health_check(prefix: Prefix, language_version: str) -> str | None:
with in_env(prefix, language_version):
def health_check(prefix: Prefix, version: str) -> str | None:
with in_env(prefix, version):
retcode, _, _ = cmd_output_b('node', '--version', check=False)
if retcode != 0: # pragma: win32 no cover
return f'`node --version` returned {retcode}'
@ -78,7 +78,7 @@ def install_environment(
prefix: Prefix, version: str, additional_dependencies: Sequence[str],
) -> None:
assert prefix.exists('package.json')
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx?f=255&MSPPError=-2147217396#maxpath
if sys.platform == 'win32': # pragma: no cover
@ -96,13 +96,13 @@ def install_environment(
'npm', 'install', '--dev', '--prod',
'--ignore-prepublish', '--no-progress', '--no-save',
)
helpers.run_setup_cmd(prefix, local_install_cmd)
lang_base.setup_cmd(prefix, local_install_cmd)
_, pkg, _ = cmd_output('npm', 'pack', cwd=prefix.prefix_dir)
pkg = prefix.path(pkg.strip())
install = ('npm', 'install', '-g', pkg, *additional_dependencies)
helpers.run_setup_cmd(prefix, install)
lang_base.setup_cmd(prefix, install)
# clean these up after installation
if prefix.exists('node_modules'): # pragma: win32 no cover

View file

@ -6,16 +6,16 @@ import shlex
from typing import Generator
from typing import Sequence
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 import helpers
from pre_commit.prefix import Prefix
ENVIRONMENT_DIR = 'perl_env'
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
run_hook = helpers.basic_run_hook
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
run_hook = lang_base.basic_run_hook
def get_env_patch(venv: str) -> PatchesT:
@ -34,7 +34,7 @@ def get_env_patch(venv: str) -> PatchesT:
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir)):
yield
@ -42,9 +42,9 @@ def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
def install_environment(
prefix: Prefix, version: str, additional_dependencies: Sequence[str],
) -> None:
helpers.assert_version_default('perl', version)
lang_base.assert_version_default('perl', version)
with in_env(prefix, version):
helpers.run_setup_cmd(
lang_base.setup_cmd(
prefix, ('cpan', '-T', '.', *additional_dependencies),
)

View file

@ -7,16 +7,16 @@ from typing import NamedTuple
from typing import Pattern
from typing import Sequence
from pre_commit import lang_base
from pre_commit import output
from pre_commit.languages import helpers
from pre_commit.prefix import Prefix
from pre_commit.xargs import xargs
ENVIRONMENT_DIR = None
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
install_environment = helpers.no_install
in_env = helpers.no_env
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
install_environment = lang_base.no_install
in_env = lang_base.no_env
def _process_filename_by_line(pattern: Pattern[bytes], filename: str) -> int:

View file

@ -8,11 +8,11 @@ from typing import Generator
from typing 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 UNSET
from pre_commit.envcontext import Var
from pre_commit.languages import helpers
from pre_commit.parse_shebang import find_executable
from pre_commit.prefix import Prefix
from pre_commit.util import CalledProcessError
@ -21,7 +21,7 @@ from pre_commit.util import cmd_output_b
from pre_commit.util import win_exe
ENVIRONMENT_DIR = 'py_env'
run_hook = helpers.basic_run_hook
run_hook = lang_base.basic_run_hook
@functools.lru_cache(maxsize=None)
@ -153,13 +153,13 @@ def norm_version(version: str) -> str | None:
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir)):
yield
def health_check(prefix: Prefix, language_version: str) -> str | None:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, language_version)
def health_check(prefix: Prefix, version: str) -> str | None:
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
pyvenv_cfg = os.path.join(envdir, 'pyvenv.cfg')
# created with "old" virtualenv
@ -202,7 +202,7 @@ def install_environment(
version: str,
additional_dependencies: Sequence[str],
) -> None:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
venv_cmd = [sys.executable, '-mvirtualenv', envdir]
python = norm_version(version)
if python is not None:
@ -211,4 +211,4 @@ def install_environment(
cmd_output_b(*venv_cmd, cwd='/')
with in_env(prefix, version):
helpers.run_setup_cmd(prefix, install_cmd)
lang_base.setup_cmd(prefix, install_cmd)

View file

@ -7,18 +7,18 @@ import shutil
from typing import Generator
from typing import Sequence
from pre_commit import lang_base
from pre_commit.envcontext import envcontext
from pre_commit.envcontext import PatchesT
from pre_commit.envcontext import UNSET
from pre_commit.languages import helpers
from pre_commit.prefix import Prefix
from pre_commit.util import cmd_output_b
from pre_commit.util import win_exe
ENVIRONMENT_DIR = 'renv'
RSCRIPT_OPTS = ('--no-save', '--no-restore', '--no-site-file', '--no-environ')
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
def get_env_patch(venv: str) -> PatchesT:
@ -30,7 +30,7 @@ def get_env_patch(venv: str) -> PatchesT:
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir)):
yield
@ -93,7 +93,7 @@ def install_environment(
version: str,
additional_dependencies: Sequence[str],
) -> None:
env_dir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
env_dir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
os.makedirs(env_dir, exist_ok=True)
shutil.copy(prefix.path('renv.lock'), env_dir)
shutil.copytree(prefix.path('renv'), os.path.join(env_dir, 'renv'))
@ -166,7 +166,7 @@ def run_hook(
color: bool,
) -> tuple[int, bytes]:
cmd = _cmd_from_hook(prefix, entry, args, is_local=is_local)
return helpers.run_xargs(
return lang_base.run_xargs(
cmd,
file_args,
require_serial=require_serial,

View file

@ -2,30 +2,35 @@ from __future__ import annotations
import contextlib
import functools
import importlib.resources
import os.path
import shutil
import tarfile
from typing import Generator
from typing import IO
from typing 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 UNSET
from pre_commit.envcontext import Var
from pre_commit.languages import helpers
from pre_commit.prefix import Prefix
from pre_commit.util import CalledProcessError
from pre_commit.util import resource_bytesio
ENVIRONMENT_DIR = 'rbenv'
health_check = helpers.basic_health_check
run_hook = helpers.basic_run_hook
health_check = lang_base.basic_health_check
run_hook = lang_base.basic_run_hook
def _resource_bytesio(filename: str) -> IO[bytes]:
return importlib.resources.open_binary('pre_commit.resources', filename)
@functools.lru_cache(maxsize=1)
def get_default_version() -> str:
if all(helpers.exe_exists(exe) for exe in ('ruby', 'gem')):
if all(lang_base.exe_exists(exe) for exe in ('ruby', 'gem')):
return 'system'
else:
return C.DEFAULT
@ -68,13 +73,13 @@ def get_env_patch(
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir, version)):
yield
def _extract_resource(filename: str, dest: str) -> None:
with resource_bytesio(filename) as bio:
with _resource_bytesio(filename) as bio:
with tarfile.open(fileobj=bio) as tf:
tf.extractall(dest)
@ -83,7 +88,7 @@ def _install_rbenv(
prefix: Prefix,
version: str,
) -> None: # pragma: win32 no cover
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
_extract_resource('rbenv.tar.gz', prefix.path('.'))
shutil.move(prefix.path('rbenv'), envdir)
@ -100,10 +105,10 @@ def _install_ruby(
version: str,
) -> None: # pragma: win32 no cover
try:
helpers.run_setup_cmd(prefix, ('rbenv', 'download', version))
lang_base.setup_cmd(prefix, ('rbenv', 'download', version))
except CalledProcessError: # pragma: no cover (usually find with download)
# Failed to download from mirror for some reason, build it instead
helpers.run_setup_cmd(prefix, ('rbenv', 'install', version))
lang_base.setup_cmd(prefix, ('rbenv', 'install', version))
def install_environment(
@ -114,17 +119,17 @@ def install_environment(
with in_env(prefix, version):
# Need to call this before installing so rbenv's directories
# are set up
helpers.run_setup_cmd(prefix, ('rbenv', 'init', '-'))
lang_base.setup_cmd(prefix, ('rbenv', 'init', '-'))
if version != C.DEFAULT:
_install_ruby(prefix, version)
# Need to call this after installing to set up the shims
helpers.run_setup_cmd(prefix, ('rbenv', 'rehash'))
lang_base.setup_cmd(prefix, ('rbenv', 'rehash'))
with in_env(prefix, version):
helpers.run_setup_cmd(
lang_base.setup_cmd(
prefix, ('gem', 'build', *prefix.star('.gemspec')),
)
helpers.run_setup_cmd(
lang_base.setup_cmd(
prefix,
(
'gem', 'install',

View file

@ -11,19 +11,19 @@ from typing import Generator
from typing import Sequence
import pre_commit.constants as C
from pre_commit import lang_base
from pre_commit import parse_shebang
from pre_commit.envcontext import envcontext
from pre_commit.envcontext import PatchesT
from pre_commit.envcontext import Var
from pre_commit.languages import helpers
from pre_commit.prefix import Prefix
from pre_commit.util import cmd_output_b
from pre_commit.util import make_executable
from pre_commit.util import win_exe
ENVIRONMENT_DIR = 'rustenv'
health_check = helpers.basic_health_check
run_hook = helpers.basic_run_hook
health_check = lang_base.basic_health_check
run_hook = lang_base.basic_run_hook
@functools.lru_cache(maxsize=1)
@ -63,7 +63,7 @@ def get_env_patch(target_dir: str, version: str) -> PatchesT:
@contextlib.contextmanager
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir, version)):
yield
@ -78,7 +78,7 @@ def _add_dependencies(
crate = f'{name}@{spec or "*"}'
crates.append(crate)
helpers.run_setup_cmd(prefix, ('cargo', 'add', *crates))
lang_base.setup_cmd(prefix, ('cargo', 'add', *crates))
def install_rust_with_toolchain(toolchain: str) -> None:
@ -116,7 +116,7 @@ def install_environment(
version: str,
additional_dependencies: Sequence[str],
) -> None:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
# There are two cases where we might want to specify more dependencies:
# as dependencies for the library being built, and as binary packages

View file

@ -2,14 +2,14 @@ from __future__ import annotations
from typing import Sequence
from pre_commit.languages import helpers
from pre_commit import lang_base
from pre_commit.prefix import Prefix
ENVIRONMENT_DIR = None
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
install_environment = helpers.no_install
in_env = helpers.no_env
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
install_environment = lang_base.no_install
in_env = lang_base.no_env
def run_hook(
@ -22,9 +22,9 @@ def run_hook(
require_serial: bool,
color: bool,
) -> tuple[int, bytes]:
cmd = helpers.hook_cmd(entry, args)
cmd = lang_base.hook_cmd(entry, args)
cmd = (prefix.path(cmd[0]), *cmd[1:])
return helpers.run_xargs(
return lang_base.run_xargs(
cmd,
file_args,
require_serial=require_serial,

View file

@ -5,10 +5,10 @@ import os
from typing import Generator
from typing import Sequence
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 import helpers
from pre_commit.prefix import Prefix
from pre_commit.util import cmd_output_b
@ -16,9 +16,9 @@ BUILD_DIR = '.build'
BUILD_CONFIG = 'release'
ENVIRONMENT_DIR = 'swift_env'
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
run_hook = helpers.basic_run_hook
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
run_hook = lang_base.basic_run_hook
def get_env_patch(venv: str) -> PatchesT: # pragma: win32 no cover
@ -28,7 +28,7 @@ def get_env_patch(venv: str) -> PatchesT: # pragma: win32 no cover
@contextlib.contextmanager # pragma: win32 no cover
def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
with envcontext(get_env_patch(envdir)):
yield
@ -36,9 +36,9 @@ def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
def install_environment(
prefix: Prefix, version: str, additional_dependencies: Sequence[str],
) -> None: # pragma: win32 no cover
helpers.assert_version_default('swift', version)
helpers.assert_no_additional_deps('swift', additional_dependencies)
envdir = helpers.environment_dir(prefix, ENVIRONMENT_DIR, version)
lang_base.assert_version_default('swift', version)
lang_base.assert_no_additional_deps('swift', additional_dependencies)
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
# Build the swift package
os.mkdir(envdir)

View file

@ -1,10 +1,10 @@
from __future__ import annotations
from pre_commit.languages import helpers
from pre_commit import lang_base
ENVIRONMENT_DIR = None
get_default_version = helpers.basic_get_default_version
health_check = helpers.basic_health_check
install_environment = helpers.no_install
in_env = helpers.no_env
run_hook = helpers.basic_run_hook
get_default_version = lang_base.basic_get_default_version
health_check = lang_base.basic_health_check
install_environment = lang_base.no_install
in_env = lang_base.no_env
run_hook = lang_base.basic_run_hook

View file

@ -3,17 +3,18 @@ from __future__ import annotations
import json
import logging
import os
import shlex
from typing import Any
from typing import Sequence
import pre_commit.constants as C
from pre_commit.all_languages import languages
from pre_commit.clientlib import load_manifest
from pre_commit.clientlib import LOCAL
from pre_commit.clientlib import META
from pre_commit.clientlib import parse_version
from pre_commit.hook import Hook
from pre_commit.languages.all import languages
from pre_commit.languages.helpers import environment_dir
from pre_commit.lang_base import environment_dir
from pre_commit.prefix import Prefix
from pre_commit.store import Store
from pre_commit.util import clean_path_on_failure
@ -32,7 +33,7 @@ def _state_filename_v2(venv: str) -> str:
def _state(additional_deps: Sequence[str]) -> object:
return {'additional_dependencies': sorted(additional_deps)}
return {'additional_dependencies': additional_deps}
def _read_state(venv: str) -> object | None:
@ -68,6 +69,14 @@ def _hook_install(hook: Hook) -> None:
logger.info('Once installed this environment will be reused.')
logger.info('This may take a few minutes...')
if hook.language == 'python_venv':
logger.warning(
f'`repo: {hook.src}` uses deprecated `language: python_venv`. '
f'This is an alias for `language: python`. '
f'Often `pre-commit autoupdate --repo {shlex.quote(hook.src)}` '
f'will fix this.',
)
lang = languages[hook.language]
assert lang.ENVIRONMENT_DIR is not None

View file

@ -7,6 +7,7 @@ import time
from typing import Generator
from pre_commit import git
from pre_commit.errors import FatalError
from pre_commit.util import CalledProcessError
from pre_commit.util import cmd_output
from pre_commit.util import cmd_output_b
@ -49,12 +50,16 @@ def _intent_to_add_cleared() -> Generator[None, None, None]:
@contextlib.contextmanager
def _unstaged_changes_cleared(patch_dir: str) -> Generator[None, None, None]:
tree = cmd_output('git', 'write-tree')[1].strip()
retcode, diff_stdout_binary, _ = cmd_output_b(
diff_cmd = (
'git', 'diff-index', '--ignore-submodules', '--binary',
'--exit-code', '--no-color', '--no-ext-diff', tree, '--',
check=False,
)
if retcode and diff_stdout_binary.strip():
retcode, diff_stdout, diff_stderr = cmd_output_b(*diff_cmd, check=False)
if retcode == 0:
# There weren't any staged files so we don't need to do anything
# special
yield
elif retcode == 1 and diff_stdout.strip():
patch_filename = f'patch{int(time.time())}-{os.getpid()}'
patch_filename = os.path.join(patch_dir, patch_filename)
logger.warning('Unstaged files detected.')
@ -62,7 +67,7 @@ def _unstaged_changes_cleared(patch_dir: str) -> Generator[None, None, None]:
# Save the current unstaged changes as a patch
os.makedirs(patch_dir, exist_ok=True)
with open(patch_filename, 'wb') as patch_file:
patch_file.write(diff_stdout_binary)
patch_file.write(diff_stdout)
# prevent recursive post-checkout hooks (#1418)
no_checkout_env = dict(os.environ, _PRE_COMMIT_SKIP_POST_CHECKOUT='1')
@ -86,10 +91,12 @@ def _unstaged_changes_cleared(patch_dir: str) -> Generator[None, None, None]:
_git_apply(patch_filename)
logger.info(f'Restored changes from {patch_filename}.')
else:
# There weren't any staged files so we don't need to do anything
# special
yield
else: # pragma: win32 no cover
# some error occurred while requesting the diff
e = CalledProcessError(retcode, diff_cmd, b'', diff_stderr)
raise FatalError(
f'pre-commit failed to diff -- perhaps due to permissions?\n\n{e}',
)
@contextlib.contextmanager

View file

@ -125,7 +125,7 @@ class Store:
@classmethod
def db_repo_name(cls, repo: str, deps: Sequence[str]) -> str:
if deps:
return f'{repo}:{",".join(sorted(deps))}'
return f'{repo}:{",".join(deps)}'
else:
return repo

View file

@ -12,7 +12,6 @@ from types import TracebackType
from typing import Any
from typing import Callable
from typing import Generator
from typing import IO
from pre_commit import parse_shebang
@ -36,10 +35,6 @@ def clean_path_on_failure(path: str) -> Generator[None, None, None]:
raise
def resource_bytesio(filename: str) -> IO[bytes]:
return importlib.resources.open_binary('pre_commit.resources', filename)
def resource_text(filename: str) -> str:
return importlib.resources.read_text('pre_commit.resources', filename)
@ -67,7 +62,7 @@ class CalledProcessError(RuntimeError):
def __bytes__(self) -> bytes:
def _indent_or_none(part: bytes | None) -> bytes:
if part:
return b'\n ' + part.replace(b'\n', b'\n ')
return b'\n ' + part.replace(b'\n', b'\n ').rstrip()
else:
return b' (none)'