summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug.yaml7
-rw-r--r--.pre-commit-config.yaml12
-rw-r--r--.pre-commit-hooks.yaml4
-rw-r--r--CHANGELOG.md24
-rw-r--r--CONTRIBUTING.md7
-rw-r--r--azure-pipelines.yml2
-rw-r--r--pre_commit/clientlib.py30
-rw-r--r--pre_commit/commands/hook_impl.py3
-rw-r--r--pre_commit/commands/validate_config.py16
-rw-r--r--pre_commit/commands/validate_manifest.py16
-rw-r--r--pre_commit/languages/all.py40
-rw-r--r--pre_commit/languages/conda.py2
-rw-r--r--pre_commit/languages/coursier.py2
-rw-r--r--pre_commit/languages/dart.py2
-rw-r--r--pre_commit/languages/docker.py2
-rw-r--r--pre_commit/languages/docker_image.py2
-rw-r--r--pre_commit/languages/dotnet.py29
-rw-r--r--pre_commit/languages/fail.py2
-rw-r--r--pre_commit/languages/golang.py2
-rw-r--r--pre_commit/languages/helpers.py4
-rw-r--r--pre_commit/languages/lua.py2
-rw-r--r--pre_commit/languages/node.py7
-rw-r--r--pre_commit/languages/perl.py2
-rw-r--r--pre_commit/languages/pygrep.py2
-rw-r--r--pre_commit/languages/python.py35
-rw-r--r--pre_commit/languages/r.py2
-rw-r--r--pre_commit/languages/ruby.py2
-rw-r--r--pre_commit/languages/rust.py2
-rw-r--r--pre_commit/languages/script.py2
-rw-r--r--pre_commit/languages/swift.py2
-rw-r--r--pre_commit/languages/system.py2
-rw-r--r--pre_commit/main.py26
-rw-r--r--pre_commit/repository.py10
-rw-r--r--pre_commit/resources/ruby-build.tar.gzbin72271 -> 72569 bytes
-rw-r--r--setup.cfg2
-rwxr-xr-xtesting/gen-languages-all12
-rwxr-xr-xtesting/get-swift.sh6
-rwxr-xr-xtesting/make-archives2
-rw-r--r--testing/resources/dotnet_hooks_combo_repo/.pre-commit-hooks.yaml12
-rw-r--r--testing/resources/dotnet_hooks_combo_repo/dotnet_hooks_combo_repo.sln28
-rw-r--r--testing/resources/dotnet_hooks_combo_repo/proj1/Program.cs12
-rw-r--r--testing/resources/dotnet_hooks_combo_repo/proj1/proj1.csproj12
-rw-r--r--testing/resources/dotnet_hooks_combo_repo/proj2/Program.cs12
-rw-r--r--testing/resources/dotnet_hooks_combo_repo/proj2/proj2.csproj12
-rw-r--r--testing/resources/golang_hooks_repo/go.mod4
-rw-r--r--testing/resources/golang_hooks_repo/go.sum2
-rw-r--r--tests/clientlib_test.py16
-rw-r--r--tests/commands/hook_impl_test.py12
-rw-r--r--tests/languages/helpers_test.py4
-rw-r--r--tests/languages/node_test.py9
-rw-r--r--tests/languages/python_test.py54
-rw-r--r--tests/main_test.py1
-rw-r--r--tests/repository_test.py7
53 files changed, 392 insertions, 131 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug.yaml b/.github/ISSUE_TEMPLATE/bug.yaml
index 6cce5fe..bfced0f 100644
--- a/.github/ISSUE_TEMPLATE/bug.yaml
+++ b/.github/ISSUE_TEMPLATE/bug.yaml
@@ -9,6 +9,13 @@ body:
[pre-commit.ci]: https://pre-commit.ci
[pre-commit-ci/issues]: https://github.com/pre-commit-ci/issues
+ - type: input
+ id: search
+ attributes:
+ label: search tried in the issue tracker
+ placeholder: ...
+ validations:
+ required: true
- type: textarea
id: freeform
attributes:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 1b93cff..7791f76 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.1.0
+ rev: v4.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
@@ -10,22 +10,22 @@ repos:
- id: name-tests-test
- id: requirements-txt-fixer
- repo: https://github.com/asottile/setup-cfg-fmt
- rev: v1.20.0
+ rev: v1.20.1
hooks:
- id: setup-cfg-fmt
- repo: https://github.com/asottile/reorder_python_imports
- rev: v3.0.1
+ rev: v3.1.0
hooks:
- id: reorder-python-imports
exclude: ^(pre_commit/resources/|testing/resources/python3_hooks_repo/)
args: [--py37-plus, --add-import, 'from __future__ import annotations']
- repo: https://github.com/asottile/add-trailing-comma
- rev: v2.2.1
+ rev: v2.2.3
hooks:
- id: add-trailing-comma
args: [--py36-plus]
- repo: https://github.com/asottile/pyupgrade
- rev: v2.31.1
+ rev: v2.32.0
hooks:
- id: pyupgrade
args: [--py37-plus]
@@ -38,7 +38,7 @@ repos:
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v0.942
+ rev: v0.950
hooks:
- id: mypy
additional_dependencies: [types-all]
diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml
index 3d1ffbc..e1aaf58 100644
--- a/.pre-commit-hooks.yaml
+++ b/.pre-commit-hooks.yaml
@@ -1,6 +1,6 @@
- id: validate_manifest
name: validate pre-commit manifest
description: This validator validates a pre-commit hooks manifest file
- entry: pre-commit-validate-manifest
+ entry: pre-commit validate-manifest
language: python
- files: ^(\.pre-commit-hooks\.yaml|hooks\.yaml)$
+ files: ^\.pre-commit-hooks\.yaml$
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cd31c4b..1b6d8b6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,27 @@
+2.19.0 - 2022-05-05
+===================
+
+### Features
+- Allow multiple outputs from `language: dotnet` hooks.
+ - #2332 PR by @WallucePinkham.
+- Add more information to `healthy()` failure.
+ - #2348 PR by @asottile.
+- Upgrade ruby-build.
+ - #2342 PR by @jalessio.
+- Add `pre-commit validate-config` / `pre-commit validate-manifest` and
+ deprecate `pre-commit-validate-config` and `pre-commit-validate-manifest`.
+ - #2362 PR by @asottile.
+
+### Fixes
+- Fix `pre-push` when pushed ref contains spaces.
+ - #2345 PR by @wwade.
+ - #2344 issue by @wwade.
+
+### Updating
+- Change `pre-commit-validate-config` / `pre-commit-validate-manifest` to
+ `pre-commit validate-config` / `pre-commit validate-manifest`.
+ - #2362 PR by @asottile.
+
2.18.1 - 2022-04-02
===================
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index adce08f..fa1678c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -117,15 +117,16 @@ get_default_version = helpers.basic_default_version
`python` is currently the only language which implements this api
-#### `healthy`
+#### `health_check`
This is used to check whether the installed environment is considered healthy.
-This function should return `True` or `False`.
+This function should return a detailed message if unhealthy or `None` if
+healthy.
You generally don't need to implement this on a first pass and can just use:
```python
-healthy = helpers.basic_healthy
+health_check = helpers.basic_healthy_check
```
`python` is currently the only language which implements this api, for python
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index afb2982..454f6f1 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -10,7 +10,7 @@ resources:
type: github
endpoint: github
name: asottile/azure-pipeline-templates
- ref: refs/tags/v2.1.0
+ ref: refs/tags/v2.4.1
jobs:
- template: job--python-tox.yml@asottile
diff --git a/pre_commit/clientlib.py b/pre_commit/clientlib.py
index bf4e2e4..9b53e81 100644
--- a/pre_commit/clientlib.py
+++ b/pre_commit/clientlib.py
@@ -14,6 +14,8 @@ from identify.identify import ALL_TAGS
import pre_commit.constants as C
from pre_commit.color import add_color_option
+from pre_commit.commands.validate_config import validate_config
+from pre_commit.commands.validate_manifest import validate_manifest
from pre_commit.errors import FatalError
from pre_commit.languages.all import all_languages
from pre_commit.logging_handler import logging_handler
@@ -100,14 +102,12 @@ def validate_manifest_main(argv: Sequence[str] | None = None) -> int:
args = parser.parse_args(argv)
with logging_handler(args.color):
- ret = 0
- for filename in args.filenames:
- try:
- load_manifest(filename)
- except InvalidManifestError as e:
- print(e)
- ret = 1
- return ret
+ logger.warning(
+ 'pre-commit-validate-manifest is deprecated -- '
+ 'use `pre-commit validate-manifest` instead.',
+ )
+
+ return validate_manifest(args.filenames)
LOCAL = 'local'
@@ -409,11 +409,9 @@ def validate_config_main(argv: Sequence[str] | None = None) -> int:
args = parser.parse_args(argv)
with logging_handler(args.color):
- ret = 0
- for filename in args.filenames:
- try:
- load_config(filename)
- except InvalidConfigError as e:
- print(e)
- ret = 1
- return ret
+ logger.warning(
+ 'pre-commit-validate-config is deprecated -- '
+ 'use `pre-commit validate-config` instead.',
+ )
+
+ return validate_config(args.filenames)
diff --git a/pre_commit/commands/hook_impl.py b/pre_commit/commands/hook_impl.py
index 18e5e9f..f315c04 100644
--- a/pre_commit/commands/hook_impl.py
+++ b/pre_commit/commands/hook_impl.py
@@ -114,7 +114,8 @@ def _pre_push_ns(
remote_url = args[1]
for line in stdin.decode().splitlines():
- local_branch, local_sha, remote_branch, remote_sha = line.split()
+ parts = line.rsplit(maxsplit=3)
+ local_branch, local_sha, remote_branch, remote_sha = parts
if local_sha == Z40:
continue
elif remote_sha != Z40 and _rev_exists(remote_sha):
diff --git a/pre_commit/commands/validate_config.py b/pre_commit/commands/validate_config.py
new file mode 100644
index 0000000..91bb017
--- /dev/null
+++ b/pre_commit/commands/validate_config.py
@@ -0,0 +1,16 @@
+from __future__ import annotations
+
+from pre_commit import clientlib
+
+
+def validate_config(filenames: list[str]) -> int:
+ ret = 0
+
+ for filename in filenames:
+ try:
+ clientlib.load_config(filename)
+ except clientlib.InvalidConfigError as e:
+ print(e)
+ ret = 1
+
+ return ret
diff --git a/pre_commit/commands/validate_manifest.py b/pre_commit/commands/validate_manifest.py
new file mode 100644
index 0000000..372a638
--- /dev/null
+++ b/pre_commit/commands/validate_manifest.py
@@ -0,0 +1,16 @@
+from __future__ import annotations
+
+from pre_commit import clientlib
+
+
+def validate_manifest(filenames: list[str]) -> int:
+ ret = 0
+
+ for filename in filenames:
+ try:
+ clientlib.load_manifest(filename)
+ except clientlib.InvalidManifestError as e:
+ print(e)
+ ret = 1
+
+ return ret
diff --git a/pre_commit/languages/all.py b/pre_commit/languages/all.py
index cfcbf68..cfd42ce 100644
--- a/pre_commit/languages/all.py
+++ b/pre_commit/languages/all.py
@@ -34,7 +34,7 @@ class Language(NamedTuple):
# return a value to replace `'default` for `language_version`
get_default_version: Callable[[], str]
# return whether the environment is healthy (or should be rebuilt)
- healthy: Callable[[Prefix, str], bool]
+ health_check: Callable[[Prefix, str], str | None]
# install a repository for the given language and language_version
install_environment: Callable[[Prefix, str, Sequence[str]], None]
# execute a hook and return the exit code and output
@@ -44,25 +44,25 @@ class Language(NamedTuple):
# TODO: back to modules + Protocol: https://github.com/python/mypy/issues/5018
languages = {
# BEGIN GENERATED (testing/gen-languages-all)
- 'conda': Language(name='conda', ENVIRONMENT_DIR=conda.ENVIRONMENT_DIR, get_default_version=conda.get_default_version, healthy=conda.healthy, install_environment=conda.install_environment, run_hook=conda.run_hook), # noqa: E501
- 'coursier': Language(name='coursier', ENVIRONMENT_DIR=coursier.ENVIRONMENT_DIR, get_default_version=coursier.get_default_version, healthy=coursier.healthy, install_environment=coursier.install_environment, run_hook=coursier.run_hook), # noqa: E501
- 'dart': Language(name='dart', ENVIRONMENT_DIR=dart.ENVIRONMENT_DIR, get_default_version=dart.get_default_version, healthy=dart.healthy, install_environment=dart.install_environment, run_hook=dart.run_hook), # noqa: E501
- 'docker': Language(name='docker', ENVIRONMENT_DIR=docker.ENVIRONMENT_DIR, get_default_version=docker.get_default_version, healthy=docker.healthy, install_environment=docker.install_environment, run_hook=docker.run_hook), # noqa: E501
- 'docker_image': Language(name='docker_image', ENVIRONMENT_DIR=docker_image.ENVIRONMENT_DIR, get_default_version=docker_image.get_default_version, healthy=docker_image.healthy, install_environment=docker_image.install_environment, run_hook=docker_image.run_hook), # noqa: E501
- 'dotnet': Language(name='dotnet', ENVIRONMENT_DIR=dotnet.ENVIRONMENT_DIR, get_default_version=dotnet.get_default_version, healthy=dotnet.healthy, install_environment=dotnet.install_environment, run_hook=dotnet.run_hook), # noqa: E501
- 'fail': Language(name='fail', ENVIRONMENT_DIR=fail.ENVIRONMENT_DIR, get_default_version=fail.get_default_version, healthy=fail.healthy, install_environment=fail.install_environment, run_hook=fail.run_hook), # noqa: E501
- 'golang': Language(name='golang', ENVIRONMENT_DIR=golang.ENVIRONMENT_DIR, get_default_version=golang.get_default_version, healthy=golang.healthy, install_environment=golang.install_environment, run_hook=golang.run_hook), # noqa: E501
- 'lua': Language(name='lua', ENVIRONMENT_DIR=lua.ENVIRONMENT_DIR, get_default_version=lua.get_default_version, healthy=lua.healthy, install_environment=lua.install_environment, run_hook=lua.run_hook), # noqa: E501
- 'node': Language(name='node', ENVIRONMENT_DIR=node.ENVIRONMENT_DIR, get_default_version=node.get_default_version, healthy=node.healthy, install_environment=node.install_environment, run_hook=node.run_hook), # noqa: E501
- 'perl': Language(name='perl', ENVIRONMENT_DIR=perl.ENVIRONMENT_DIR, get_default_version=perl.get_default_version, healthy=perl.healthy, install_environment=perl.install_environment, run_hook=perl.run_hook), # noqa: E501
- 'pygrep': Language(name='pygrep', ENVIRONMENT_DIR=pygrep.ENVIRONMENT_DIR, get_default_version=pygrep.get_default_version, healthy=pygrep.healthy, install_environment=pygrep.install_environment, run_hook=pygrep.run_hook), # noqa: E501
- 'python': Language(name='python', ENVIRONMENT_DIR=python.ENVIRONMENT_DIR, get_default_version=python.get_default_version, healthy=python.healthy, install_environment=python.install_environment, run_hook=python.run_hook), # noqa: E501
- 'r': Language(name='r', ENVIRONMENT_DIR=r.ENVIRONMENT_DIR, get_default_version=r.get_default_version, healthy=r.healthy, install_environment=r.install_environment, run_hook=r.run_hook), # noqa: E501
- 'ruby': Language(name='ruby', ENVIRONMENT_DIR=ruby.ENVIRONMENT_DIR, get_default_version=ruby.get_default_version, healthy=ruby.healthy, install_environment=ruby.install_environment, run_hook=ruby.run_hook), # noqa: E501
- 'rust': Language(name='rust', ENVIRONMENT_DIR=rust.ENVIRONMENT_DIR, get_default_version=rust.get_default_version, healthy=rust.healthy, install_environment=rust.install_environment, run_hook=rust.run_hook), # noqa: E501
- 'script': Language(name='script', ENVIRONMENT_DIR=script.ENVIRONMENT_DIR, get_default_version=script.get_default_version, healthy=script.healthy, install_environment=script.install_environment, run_hook=script.run_hook), # noqa: E501
- 'swift': Language(name='swift', ENVIRONMENT_DIR=swift.ENVIRONMENT_DIR, get_default_version=swift.get_default_version, healthy=swift.healthy, install_environment=swift.install_environment, run_hook=swift.run_hook), # noqa: E501
- 'system': Language(name='system', ENVIRONMENT_DIR=system.ENVIRONMENT_DIR, get_default_version=system.get_default_version, healthy=system.healthy, install_environment=system.install_environment, run_hook=system.run_hook), # noqa: E501
+ 'conda': Language(name='conda', ENVIRONMENT_DIR=conda.ENVIRONMENT_DIR, get_default_version=conda.get_default_version, health_check=conda.health_check, install_environment=conda.install_environment, run_hook=conda.run_hook), # noqa: E501
+ 'coursier': Language(name='coursier', ENVIRONMENT_DIR=coursier.ENVIRONMENT_DIR, get_default_version=coursier.get_default_version, health_check=coursier.health_check, install_environment=coursier.install_environment, run_hook=coursier.run_hook), # noqa: E501
+ 'dart': Language(name='dart', ENVIRONMENT_DIR=dart.ENVIRONMENT_DIR, get_default_version=dart.get_default_version, health_check=dart.health_check, install_environment=dart.install_environment, run_hook=dart.run_hook), # noqa: E501
+ 'docker': Language(name='docker', ENVIRONMENT_DIR=docker.ENVIRONMENT_DIR, get_default_version=docker.get_default_version, health_check=docker.health_check, install_environment=docker.install_environment, run_hook=docker.run_hook), # noqa: E501
+ 'docker_image': Language(name='docker_image', ENVIRONMENT_DIR=docker_image.ENVIRONMENT_DIR, get_default_version=docker_image.get_default_version, health_check=docker_image.health_check, install_environment=docker_image.install_environment, run_hook=docker_image.run_hook), # noqa: E501
+ 'dotnet': Language(name='dotnet', ENVIRONMENT_DIR=dotnet.ENVIRONMENT_DIR, get_default_version=dotnet.get_default_version, health_check=dotnet.health_check, install_environment=dotnet.install_environment, run_hook=dotnet.run_hook), # noqa: E501
+ 'fail': Language(name='fail', ENVIRONMENT_DIR=fail.ENVIRONMENT_DIR, get_default_version=fail.get_default_version, health_check=fail.health_check, install_environment=fail.install_environment, run_hook=fail.run_hook), # noqa: E501
+ 'golang': Language(name='golang', ENVIRONMENT_DIR=golang.ENVIRONMENT_DIR, get_default_version=golang.get_default_version, health_check=golang.health_check, install_environment=golang.install_environment, run_hook=golang.run_hook), # noqa: E501
+ 'lua': Language(name='lua', ENVIRONMENT_DIR=lua.ENVIRONMENT_DIR, get_default_version=lua.get_default_version, health_check=lua.health_check, install_environment=lua.install_environment, run_hook=lua.run_hook), # noqa: E501
+ 'node': Language(name='node', ENVIRONMENT_DIR=node.ENVIRONMENT_DIR, get_default_version=node.get_default_version, health_check=node.health_check, install_environment=node.install_environment, run_hook=node.run_hook), # noqa: E501
+ 'perl': Language(name='perl', ENVIRONMENT_DIR=perl.ENVIRONMENT_DIR, get_default_version=perl.get_default_version, health_check=perl.health_check, install_environment=perl.install_environment, run_hook=perl.run_hook), # noqa: E501
+ 'pygrep': Language(name='pygrep', ENVIRONMENT_DIR=pygrep.ENVIRONMENT_DIR, get_default_version=pygrep.get_default_version, health_check=pygrep.health_check, install_environment=pygrep.install_environment, run_hook=pygrep.run_hook), # noqa: E501
+ 'python': Language(name='python', ENVIRONMENT_DIR=python.ENVIRONMENT_DIR, get_default_version=python.get_default_version, health_check=python.health_check, install_environment=python.install_environment, run_hook=python.run_hook), # noqa: E501
+ 'r': Language(name='r', ENVIRONMENT_DIR=r.ENVIRONMENT_DIR, get_default_version=r.get_default_version, health_check=r.health_check, install_environment=r.install_environment, run_hook=r.run_hook), # noqa: E501
+ 'ruby': Language(name='ruby', ENVIRONMENT_DIR=ruby.ENVIRONMENT_DIR, get_default_version=ruby.get_default_version, health_check=ruby.health_check, install_environment=ruby.install_environment, run_hook=ruby.run_hook), # noqa: E501
+ 'rust': Language(name='rust', ENVIRONMENT_DIR=rust.ENVIRONMENT_DIR, get_default_version=rust.get_default_version, health_check=rust.health_check, install_environment=rust.install_environment, run_hook=rust.run_hook), # noqa: E501
+ 'script': Language(name='script', ENVIRONMENT_DIR=script.ENVIRONMENT_DIR, get_default_version=script.get_default_version, health_check=script.health_check, install_environment=script.install_environment, run_hook=script.run_hook), # noqa: E501
+ 'swift': Language(name='swift', ENVIRONMENT_DIR=swift.ENVIRONMENT_DIR, get_default_version=swift.get_default_version, health_check=swift.health_check, install_environment=swift.install_environment, run_hook=swift.run_hook), # noqa: E501
+ 'system': Language(name='system', ENVIRONMENT_DIR=system.ENVIRONMENT_DIR, get_default_version=system.get_default_version, health_check=system.health_check, install_environment=system.install_environment, run_hook=system.run_hook), # noqa: E501
# END GENERATED
}
# TODO: fully deprecate `python_venv`
diff --git a/pre_commit/languages/conda.py b/pre_commit/languages/conda.py
index 88ac53f..f0195e4 100644
--- a/pre_commit/languages/conda.py
+++ b/pre_commit/languages/conda.py
@@ -18,7 +18,7 @@ from pre_commit.util import cmd_output_b
ENVIRONMENT_DIR = 'conda'
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
def get_env_patch(env: str) -> PatchesT:
diff --git a/pre_commit/languages/coursier.py b/pre_commit/languages/coursier.py
index bb3e0b8..9fe43eb 100644
--- a/pre_commit/languages/coursier.py
+++ b/pre_commit/languages/coursier.py
@@ -17,7 +17,7 @@ from pre_commit.util import clean_path_on_failure
ENVIRONMENT_DIR = 'coursier'
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
def install_environment(
diff --git a/pre_commit/languages/dart.py b/pre_commit/languages/dart.py
index 65135f8..55ecbf4 100644
--- a/pre_commit/languages/dart.py
+++ b/pre_commit/languages/dart.py
@@ -21,7 +21,7 @@ from pre_commit.util import yaml_load
ENVIRONMENT_DIR = 'dartenv'
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
def get_env_patch(venv: str) -> PatchesT:
diff --git a/pre_commit/languages/docker.py b/pre_commit/languages/docker.py
index af1860c..eea9f76 100644
--- a/pre_commit/languages/docker.py
+++ b/pre_commit/languages/docker.py
@@ -16,7 +16,7 @@ from pre_commit.util import cmd_output_b
ENVIRONMENT_DIR = 'docker'
PRE_COMMIT_LABEL = 'PRE_COMMIT'
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
def _is_in_docker() -> bool:
diff --git a/pre_commit/languages/docker_image.py b/pre_commit/languages/docker_image.py
index ccc1d67..daa4d1b 100644
--- a/pre_commit/languages/docker_image.py
+++ b/pre_commit/languages/docker_image.py
@@ -8,7 +8,7 @@ from pre_commit.languages.docker import docker_cmd
ENVIRONMENT_DIR = None
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
install_environment = helpers.no_install
diff --git a/pre_commit/languages/dotnet.py b/pre_commit/languages/dotnet.py
index a16e7f0..3983c6f 100644
--- a/pre_commit/languages/dotnet.py
+++ b/pre_commit/languages/dotnet.py
@@ -18,7 +18,7 @@ ENVIRONMENT_DIR = 'dotnetenv'
BIN_DIR = 'bin'
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
def get_env_patch(venv: str) -> PatchesT:
@@ -59,22 +59,19 @@ def install_environment(
# Determine tool from the packaged file <tool_name>.<version>.nupkg
build_outputs = os.listdir(os.path.join(prefix.prefix_dir, build_dir))
- if len(build_outputs) != 1:
- raise NotImplementedError(
- f"Can't handle multiple build outputs. Got {build_outputs}",
+ for output in build_outputs:
+ tool_name = output.split('.')[0]
+
+ # Install to bin dir
+ helpers.run_setup_cmd(
+ prefix,
+ (
+ 'dotnet', 'tool', 'install',
+ '--tool-path', os.path.join(envdir, BIN_DIR),
+ '--add-source', build_dir,
+ tool_name,
+ ),
)
- tool_name = build_outputs[0].split('.')[0]
-
- # Install to bin dir
- helpers.run_setup_cmd(
- prefix,
- (
- 'dotnet', 'tool', 'install',
- '--tool-path', os.path.join(envdir, BIN_DIR),
- '--add-source', build_dir,
- tool_name,
- ),
- )
# Clean the git dir, ignoring the environment dir
clean_cmd = ('git', 'clean', '-ffxd', '-e', f'{ENVIRONMENT_DIR}-*')
diff --git a/pre_commit/languages/fail.py b/pre_commit/languages/fail.py
index 4cb95af..00b06a9 100644
--- a/pre_commit/languages/fail.py
+++ b/pre_commit/languages/fail.py
@@ -7,7 +7,7 @@ from pre_commit.languages import helpers
ENVIRONMENT_DIR = None
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
install_environment = helpers.no_install
diff --git a/pre_commit/languages/golang.py b/pre_commit/languages/golang.py
index 759c268..a5f9dba 100644
--- a/pre_commit/languages/golang.py
+++ b/pre_commit/languages/golang.py
@@ -21,7 +21,7 @@ from pre_commit.util import rmtree
ENVIRONMENT_DIR = 'golangenv'
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
def get_env_patch(venv: str) -> PatchesT:
diff --git a/pre_commit/languages/helpers.py b/pre_commit/languages/helpers.py
index 8080826..05a7165 100644
--- a/pre_commit/languages/helpers.py
+++ b/pre_commit/languages/helpers.py
@@ -88,8 +88,8 @@ def basic_get_default_version() -> str:
return C.DEFAULT
-def basic_healthy(prefix: Prefix, language_version: str) -> bool:
- return True
+def basic_health_check(prefix: Prefix, language_version: str) -> str | None:
+ return None
def no_install(
diff --git a/pre_commit/languages/lua.py b/pre_commit/languages/lua.py
index 38bdf54..49aa730 100644
--- a/pre_commit/languages/lua.py
+++ b/pre_commit/languages/lua.py
@@ -18,7 +18,7 @@ from pre_commit.util import cmd_output
ENVIRONMENT_DIR = 'lua_env'
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
def _get_lua_version() -> str: # pragma: win32 no cover
diff --git a/pre_commit/languages/node.py b/pre_commit/languages/node.py
index b084e8f..39f3000 100644
--- a/pre_commit/languages/node.py
+++ b/pre_commit/languages/node.py
@@ -73,10 +73,13 @@ def in_env(
yield
-def healthy(prefix: Prefix, language_version: str) -> bool:
+def health_check(prefix: Prefix, language_version: str) -> str | None:
with in_env(prefix, language_version):
retcode, _, _ = cmd_output_b('node', '--version', retcode=None)
- return retcode == 0
+ if retcode != 0: # pragma: win32 no cover
+ return f'`node --version` returned {retcode}'
+ else:
+ return None
def install_environment(
diff --git a/pre_commit/languages/perl.py b/pre_commit/languages/perl.py
index 0eee258..78bd65a 100644
--- a/pre_commit/languages/perl.py
+++ b/pre_commit/languages/perl.py
@@ -16,7 +16,7 @@ from pre_commit.util import clean_path_on_failure
ENVIRONMENT_DIR = 'perl_env'
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
def _envdir(prefix: Prefix, version: str) -> str:
diff --git a/pre_commit/languages/pygrep.py b/pre_commit/languages/pygrep.py
index f2758c5..2e2072b 100644
--- a/pre_commit/languages/pygrep.py
+++ b/pre_commit/languages/pygrep.py
@@ -14,7 +14,7 @@ from pre_commit.xargs import xargs
ENVIRONMENT_DIR = None
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
install_environment = helpers.no_install
diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py
index 668ba35..19fa247 100644
--- a/pre_commit/languages/python.py
+++ b/pre_commit/languages/python.py
@@ -163,27 +163,44 @@ def in_env(
yield
-def healthy(prefix: Prefix, language_version: str) -> bool:
+def health_check(prefix: Prefix, language_version: str) -> str | None:
directory = helpers.environment_dir(ENVIRONMENT_DIR, language_version)
envdir = prefix.path(directory)
pyvenv_cfg = os.path.join(envdir, 'pyvenv.cfg')
# created with "old" virtualenv
if not os.path.exists(pyvenv_cfg):
- return False
+ return 'pyvenv.cfg does not exist (old virtualenv?)'
exe_name = win_exe('python')
py_exe = prefix.path(bin_dir(envdir), exe_name)
cfg = _read_pyvenv_cfg(pyvenv_cfg)
- return (
- 'version_info' in cfg and
- # always use uncached lookup here in case we replaced an unhealthy env
- _version_info.__wrapped__(py_exe) == cfg['version_info'] and (
- 'base-executable' not in cfg or
- _version_info(cfg['base-executable']) == cfg['version_info']
+ if 'version_info' not in cfg:
+ return "created virtualenv's pyvenv.cfg is missing `version_info`"
+
+ # always use uncached lookup here in case we replaced an unhealthy env
+ virtualenv_version = _version_info.__wrapped__(py_exe)
+ if virtualenv_version != cfg['version_info']:
+ return (
+ f'virtualenv python version did not match created version:\n'
+ f'- actual version: {virtualenv_version}\n'
+ f'- expected version: {cfg["version_info"]}\n'
)
- )
+
+ # made with an older version of virtualenv? skip `base-executable` check
+ if 'base-executable' not in cfg:
+ return None
+
+ base_exe_version = _version_info(cfg['base-executable'])
+ if base_exe_version != cfg['version_info']:
+ return (
+ f'base executable python version does not match created version:\n'
+ f'- base-executable version: {base_exe_version}\n'
+ f'- expected version: {cfg["version_info"]}\n'
+ )
+ else:
+ return None
def install_environment(
diff --git a/pre_commit/languages/r.py b/pre_commit/languages/r.py
index c736b38..40a001d 100644
--- a/pre_commit/languages/r.py
+++ b/pre_commit/languages/r.py
@@ -19,7 +19,7 @@ from pre_commit.util import cmd_output_b
ENVIRONMENT_DIR = 'renv'
RSCRIPT_OPTS = ('--no-save', '--no-restore', '--no-site-file', '--no-environ')
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
def get_env_patch(venv: str) -> PatchesT:
diff --git a/pre_commit/languages/ruby.py b/pre_commit/languages/ruby.py
index ae64492..6c5cff2 100644
--- a/pre_commit/languages/ruby.py
+++ b/pre_commit/languages/ruby.py
@@ -21,7 +21,7 @@ from pre_commit.util import clean_path_on_failure
from pre_commit.util import resource_bytesio
ENVIRONMENT_DIR = 'rbenv'
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
@functools.lru_cache(maxsize=1)
diff --git a/pre_commit/languages/rust.py b/pre_commit/languages/rust.py
index 39e3628..01c3730 100644
--- a/pre_commit/languages/rust.py
+++ b/pre_commit/languages/rust.py
@@ -19,7 +19,7 @@ from pre_commit.util import cmd_output_b
ENVIRONMENT_DIR = 'rustenv'
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
def get_env_patch(target_dir: str) -> PatchesT:
diff --git a/pre_commit/languages/script.py b/pre_commit/languages/script.py
index 2844b5e..d5e7677 100644
--- a/pre_commit/languages/script.py
+++ b/pre_commit/languages/script.py
@@ -7,7 +7,7 @@ from pre_commit.languages import helpers
ENVIRONMENT_DIR = None
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
install_environment = helpers.no_install
diff --git a/pre_commit/languages/swift.py b/pre_commit/languages/swift.py
index c630953..4c68703 100644
--- a/pre_commit/languages/swift.py
+++ b/pre_commit/languages/swift.py
@@ -17,7 +17,7 @@ from pre_commit.util import cmd_output_b
ENVIRONMENT_DIR = 'swift_env'
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
BUILD_DIR = '.build'
BUILD_CONFIG = 'release'
diff --git a/pre_commit/languages/system.py b/pre_commit/languages/system.py
index 9846c98..c64fb36 100644
--- a/pre_commit/languages/system.py
+++ b/pre_commit/languages/system.py
@@ -8,7 +8,7 @@ from pre_commit.languages import helpers
ENVIRONMENT_DIR = None
get_default_version = helpers.basic_get_default_version
-healthy = helpers.basic_healthy
+health_check = helpers.basic_health_check
install_environment = helpers.no_install
diff --git a/pre_commit/main.py b/pre_commit/main.py
index 645e97f..6d2814b 100644
--- a/pre_commit/main.py
+++ b/pre_commit/main.py
@@ -21,6 +21,8 @@ from pre_commit.commands.migrate_config import migrate_config
from pre_commit.commands.run import run
from pre_commit.commands.sample_config import sample_config
from pre_commit.commands.try_repo import try_repo
+from pre_commit.commands.validate_config import validate_config
+from pre_commit.commands.validate_manifest import validate_manifest
from pre_commit.error_handler import error_handler
from pre_commit.logging_handler import logging_handler
from pre_commit.store import Store
@@ -34,8 +36,10 @@ logger = logging.getLogger('pre_commit')
# pyvenv
os.environ.pop('__PYVENV_LAUNCHER__', None)
-
-COMMANDS_NO_GIT = {'clean', 'gc', 'init-templatedir', 'sample-config'}
+COMMANDS_NO_GIT = {
+ 'clean', 'gc', 'init-templatedir', 'sample-config',
+ 'validate-config', 'validate-manifest',
+}
def _add_config_option(parser: argparse.ArgumentParser) -> None:
@@ -304,6 +308,20 @@ def main(argv: Sequence[str] | None = None) -> int:
_add_config_option(uninstall_parser)
_add_hook_type_option(uninstall_parser)
+ validate_config_parser = subparsers.add_parser(
+ 'validate-config', help='Validate .pre-commit-config.yaml files',
+ )
+ add_color_option(validate_config_parser)
+ _add_config_option(validate_config_parser)
+ validate_config_parser.add_argument('filenames', nargs='*')
+
+ validate_manifest_parser = subparsers.add_parser(
+ 'validate-manifest', help='Validate .pre-commit-hooks.yaml files',
+ )
+ add_color_option(validate_manifest_parser)
+ _add_config_option(validate_manifest_parser)
+ validate_manifest_parser.add_argument('filenames', nargs='*')
+
help = subparsers.add_parser(
'help', help='Show help for a specific command.',
)
@@ -378,6 +396,10 @@ def main(argv: Sequence[str] | None = None) -> int:
config_file=args.config,
hook_types=args.hook_types,
)
+ elif args.command == 'validate-config':
+ return validate_config(args.filenames)
+ elif args.command == 'validate-manifest':
+ return validate_manifest(args.filenames)
else:
raise NotImplementedError(
f'Command {args.command} not implemented.',
diff --git a/pre_commit/repository.py b/pre_commit/repository.py
index ac5d294..4092277 100644
--- a/pre_commit/repository.py
+++ b/pre_commit/repository.py
@@ -57,7 +57,7 @@ def _hook_installed(hook: Hook) -> bool:
_read_state(hook.prefix, venv) ==
_state(hook.additional_dependencies)
) and
- lang.healthy(hook.prefix, hook.language_version)
+ not lang.health_check(hook.prefix, hook.language_version)
)
)
@@ -79,11 +79,13 @@ def _hook_install(hook: Hook) -> None:
lang.install_environment(
hook.prefix, hook.language_version, hook.additional_dependencies,
)
- if not lang.healthy(hook.prefix, hook.language_version):
+ health_error = lang.health_check(hook.prefix, hook.language_version)
+ if health_error:
raise AssertionError(
- f'BUG: expected environment for {hook.language} to be healthy() '
+ f'BUG: expected environment for {hook.language} to be healthy '
f'immediately after install, please open an issue describing '
- f'your environment',
+ f'your environment\n\n'
+ f'more info:\n\n{health_error}',
)
# Write our state to indicate we're installed
_write_state(hook.prefix, venv, _state(hook.additional_dependencies))
diff --git a/pre_commit/resources/ruby-build.tar.gz b/pre_commit/resources/ruby-build.tar.gz
index e248c57..8edb3ca 100644
--- a/pre_commit/resources/ruby-build.tar.gz
+++ b/pre_commit/resources/ruby-build.tar.gz
Binary files differ
diff --git a/setup.cfg b/setup.cfg
index ca92af3..93a485c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = pre_commit
-version = 2.18.1
+version = 2.19.0
description = A framework for managing and maintaining multi-language pre-commit hooks.
long_description = file: README.md
long_description_content_type = text/markdown
diff --git a/testing/gen-languages-all b/testing/gen-languages-all
index dfd92c0..05f8929 100755
--- a/testing/gen-languages-all
+++ b/testing/gen-languages-all
@@ -3,15 +3,15 @@ from __future__ import annotations
import sys
-LANGUAGES = [
+LANGUAGES = (
'conda', 'coursier', 'dart', 'docker', 'docker_image', 'dotnet', 'fail',
'golang', 'lua', 'node', 'perl', 'pygrep', 'python', 'r', 'ruby', 'rust',
'script', 'swift', 'system',
-]
-FIELDS = [
- 'ENVIRONMENT_DIR', 'get_default_version', 'healthy', 'install_environment',
- 'run_hook',
-]
+)
+FIELDS = (
+ 'ENVIRONMENT_DIR', 'get_default_version', 'health_check',
+ 'install_environment', 'run_hook',
+)
def main() -> int:
diff --git a/testing/get-swift.sh b/testing/get-swift.sh
index a05b7b9..b77e18c 100755
--- a/testing/get-swift.sh
+++ b/testing/get-swift.sh
@@ -3,9 +3,9 @@
set -euo pipefail
. /etc/lsb-release
-if [ "$DISTRIB_CODENAME" = "bionic" ]; then
- SWIFT_URL='https://swift.org/builds/swift-5.1.3-release/ubuntu1804/swift-5.1.3-RELEASE/swift-5.1.3-RELEASE-ubuntu18.04.tar.gz'
- SWIFT_HASH='ac82ccd773fe3d586fc340814e31e120da1ff695c6a712f6634e9cc720769610'
+if [ "$DISTRIB_CODENAME" = "focal" ]; then
+ SWIFT_URL='https://download.swift.org/swift-5.6.1-release/ubuntu2004/swift-5.6.1-RELEASE/swift-5.6.1-RELEASE-ubuntu20.04.tar.gz'
+ SWIFT_HASH='2b4f22d4a8b59fe8e050f0b7f020f8d8f12553cbda56709b2340a4a3bb90cfea'
else
echo "unknown dist: ${DISTRIB_CODENAME}" 1>&2
exit 1
diff --git a/testing/make-archives b/testing/make-archives
index 1b825fe..04b42dd 100755
--- a/testing/make-archives
+++ b/testing/make-archives
@@ -17,7 +17,7 @@ from typing import Sequence
REPOS = (
('rbenv', 'https://github.com/rbenv/rbenv', '38e1fbb'),
- ('ruby-build', 'https://github.com/rbenv/ruby-build', 'a5ca3e4'),
+ ('ruby-build', 'https://github.com/rbenv/ruby-build', '2004fd7'),
(
'ruby-download',
'https://github.com/garnieretienne/rvm-download',
diff --git a/testing/resources/dotnet_hooks_combo_repo/.pre-commit-hooks.yaml b/testing/resources/dotnet_hooks_combo_repo/.pre-commit-hooks.yaml
new file mode 100644
index 0000000..f221854
--- /dev/null
+++ b/testing/resources/dotnet_hooks_combo_repo/.pre-commit-hooks.yaml
@@ -0,0 +1,12 @@
+- id: dotnet-example-hook
+ name: Test Project 1
+ description: Test Project 1
+ entry: proj1
+ language: dotnet
+ stages: [commit]
+- id: proj2
+ name: Test Project 2
+ description: Test Project 2
+ entry: proj2
+ language: dotnet
+ stages: [commit]
diff --git a/testing/resources/dotnet_hooks_combo_repo/dotnet_hooks_combo_repo.sln b/testing/resources/dotnet_hooks_combo_repo/dotnet_hooks_combo_repo.sln
new file mode 100644
index 0000000..edb0fcb
--- /dev/null
+++ b/testing/resources/dotnet_hooks_combo_repo/dotnet_hooks_combo_repo.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "proj1", "proj1\proj1.csproj", "{38A939C3-DEA4-47D7-9B75-0418C4249662}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "proj2", "proj2\proj2.csproj", "{4C9916CB-165C-4EF5-8A57-4CB6794C1EBF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {38A939C3-DEA4-47D7-9B75-0418C4249662}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {38A939C3-DEA4-47D7-9B75-0418C4249662}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {38A939C3-DEA4-47D7-9B75-0418C4249662}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {38A939C3-DEA4-47D7-9B75-0418C4249662}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4C9916CB-165C-4EF5-8A57-4CB6794C1EBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4C9916CB-165C-4EF5-8A57-4CB6794C1EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4C9916CB-165C-4EF5-8A57-4CB6794C1EBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4C9916CB-165C-4EF5-8A57-4CB6794C1EBF}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/testing/resources/dotnet_hooks_combo_repo/proj1/Program.cs b/testing/resources/dotnet_hooks_combo_repo/proj1/Program.cs
new file mode 100644
index 0000000..03876f5
--- /dev/null
+++ b/testing/resources/dotnet_hooks_combo_repo/proj1/Program.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace proj1
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.Write("Hello from dotnet!\n");
+ }
+ }
+}
diff --git a/testing/resources/dotnet_hooks_combo_repo/proj1/proj1.csproj b/testing/resources/dotnet_hooks_combo_repo/proj1/proj1.csproj
new file mode 100644
index 0000000..4f714d3
--- /dev/null
+++ b/testing/resources/dotnet_hooks_combo_repo/proj1/proj1.csproj
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net5.0</TargetFramework>
+
+ <PackAsTool>true</PackAsTool>
+ <ToolCommandName>proj1</ToolCommandName>
+ <PackageOutputPath>./nupkg</PackageOutputPath>
+ </PropertyGroup>
+
+</Project>
diff --git a/testing/resources/dotnet_hooks_combo_repo/proj2/Program.cs b/testing/resources/dotnet_hooks_combo_repo/proj2/Program.cs
new file mode 100644
index 0000000..47a99a3
--- /dev/null
+++ b/testing/resources/dotnet_hooks_combo_repo/proj2/Program.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace proj2
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Hello World!");
+ }
+ }
+}
diff --git a/testing/resources/dotnet_hooks_combo_repo/proj2/proj2.csproj b/testing/resources/dotnet_hooks_combo_repo/proj2/proj2.csproj
new file mode 100644
index 0000000..da451f7
--- /dev/null
+++ b/testing/resources/dotnet_hooks_combo_repo/proj2/proj2.csproj
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net5.0</TargetFramework>
+
+ <PackAsTool>true</PackAsTool>
+ <ToolCommandName>proj2</ToolCommandName>
+ <PackageOutputPath>./nupkg</PackageOutputPath>
+ </PropertyGroup>
+
+</Project>
diff --git a/testing/resources/golang_hooks_repo/go.mod b/testing/resources/golang_hooks_repo/go.mod
index 523bfc9..f37d4b6 100644
--- a/testing/resources/golang_hooks_repo/go.mod
+++ b/testing/resources/golang_hooks_repo/go.mod
@@ -1 +1,5 @@
module golang-hello-world
+
+go 1.18
+
+require github.com/BurntSushi/toml v1.1.0
diff --git a/testing/resources/golang_hooks_repo/go.sum b/testing/resources/golang_hooks_repo/go.sum
new file mode 100644
index 0000000..ec0c385
--- /dev/null
+++ b/testing/resources/golang_hooks_repo/go.sum
@@ -0,0 +1,2 @@
+github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
+github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
diff --git a/tests/clientlib_test.py b/tests/clientlib_test.py
index 3fb3af5..fb36bb5 100644
--- a/tests/clientlib_test.py
+++ b/tests/clientlib_test.py
@@ -122,8 +122,8 @@ def test_validate_config_old_list_format_ok(tmpdir, cap_out):
f = tmpdir.join('cfg.yaml')
f.write('- {repo: meta, hooks: [{id: identity}]}')
assert not validate_config_main((f.strpath,))
- start = '[WARNING] normalizing pre-commit configuration to a top-level map'
- assert cap_out.get().startswith(start)
+ msg = '[WARNING] normalizing pre-commit configuration to a top-level map'
+ assert msg in cap_out.get()
def test_validate_warn_on_unknown_keys_at_repo_level(tmpdir, caplog):
@@ -142,6 +142,12 @@ def test_validate_warn_on_unknown_keys_at_repo_level(tmpdir, caplog):
(
'pre_commit',
logging.WARNING,
+ 'pre-commit-validate-config is deprecated -- '
+ 'use `pre-commit validate-config` instead.',
+ ),
+ (
+ 'pre_commit',
+ logging.WARNING,
'Unexpected key(s) present on https://gitlab.com/pycqa/flake8: '
'args',
),
@@ -165,6 +171,12 @@ def test_validate_warn_on_unknown_keys_at_top_level(tmpdir, caplog):
(
'pre_commit',
logging.WARNING,
+ 'pre-commit-validate-config is deprecated -- '
+ 'use `pre-commit validate-config` instead.',
+ ),
+ (
+ 'pre_commit',
+ logging.WARNING,
'Unexpected key(s) present at root: foo',
),
]
diff --git a/tests/commands/hook_impl_test.py b/tests/commands/hook_impl_test.py
index b0159f8..3e20874 100644
--- a/tests/commands/hook_impl_test.py
+++ b/tests/commands/hook_impl_test.py
@@ -242,6 +242,18 @@ def test_run_ns_pre_push_new_branch_existing_rev(push_example):
assert ns is None
+def test_run_ns_pre_push_ref_with_whitespace(push_example):
+ src, src_head, clone, _ = push_example
+
+ with cwd(clone):
+ args = ('origin', src)
+ line = f'HEAD^{{/ }} {src_head} refs/heads/b2 {hook_impl.Z40}\n'
+ stdin = line.encode()
+ ns = hook_impl._run_ns('pre-push', False, args, stdin)
+
+ assert ns is None
+
+
def test_pushing_orphan_branch(push_example):
src, src_head, clone, _ = push_example
diff --git a/tests/languages/helpers_test.py b/tests/languages/helpers_test.py
index 259cb97..f333e79 100644
--- a/tests/languages/helpers_test.py
+++ b/tests/languages/helpers_test.py
@@ -67,8 +67,8 @@ def test_basic_get_default_version():
assert helpers.basic_get_default_version() == C.DEFAULT
-def test_basic_healthy():
- assert helpers.basic_healthy(Prefix('.'), 'default') is True
+def test_basic_health_check():
+ assert helpers.basic_health_check(Prefix('.'), 'default') is None
def test_failed_setup_command_does_not_unicode_error():
diff --git a/tests/languages/node_test.py b/tests/languages/node_test.py
index fb5ae71..b69adfa 100644
--- a/tests/languages/node_test.py
+++ b/tests/languages/node_test.py
@@ -62,7 +62,7 @@ def test_healthy_system_node(tmpdir):
prefix = Prefix(str(tmpdir))
node.install_environment(prefix, 'system', ())
- assert node.healthy(prefix, 'system')
+ assert node.health_check(prefix, 'system') is None
@xfailif_windows # pragma: win32 no cover
@@ -78,10 +78,11 @@ def test_unhealthy_if_system_node_goes_missing(tmpdir):
with envcontext.envcontext((path,)):
prefix = Prefix(str(prefix_dir))
node.install_environment(prefix, 'system', ())
- assert node.healthy(prefix, 'system')
+ assert node.health_check(prefix, 'system') is None
node_bin.remove()
- assert not node.healthy(prefix, 'system')
+ ret = node.health_check(prefix, 'system')
+ assert ret == '`node --version` returned 127'
@xfailif_windows # pragma: win32 no cover
@@ -101,7 +102,7 @@ def test_installs_without_links_outside_env(tmpdir):
prefix = Prefix(str(tmpdir))
node.install_environment(prefix, 'system', ())
- assert node.healthy(prefix, 'system')
+ assert node.health_check(prefix, 'system') is None
# this directory shouldn't exist, make sure we succeed without it existing
cmd_output('rm', '-rf', str(tmpdir.join('node_modules')))
diff --git a/tests/languages/python_test.py b/tests/languages/python_test.py
index 6160669..54fb98f 100644
--- a/tests/languages/python_test.py
+++ b/tests/languages/python_test.py
@@ -93,11 +93,11 @@ def test_healthy_default_creator(python_dir):
python.install_environment(prefix, C.DEFAULT, ())
# should be healthy right after creation
- assert python.healthy(prefix, C.DEFAULT) is True
+ assert python.health_check(prefix, C.DEFAULT) is None
# even if a `types.py` file exists, should still be healthy
tmpdir.join('types.py').ensure()
- assert python.healthy(prefix, C.DEFAULT) is True
+ assert python.health_check(prefix, C.DEFAULT) is None
def test_healthy_venv_creator(python_dir):
@@ -107,7 +107,7 @@ def test_healthy_venv_creator(python_dir):
with envcontext((('VIRTUALENV_CREATOR', 'venv'),)):
python.install_environment(prefix, C.DEFAULT, ())
- assert python.healthy(prefix, C.DEFAULT) is True
+ assert python.health_check(prefix, C.DEFAULT) is None
def test_unhealthy_python_goes_missing(python_dir):
@@ -119,7 +119,12 @@ def test_unhealthy_python_goes_missing(python_dir):
py_exe = prefix.path(python.bin_dir('py_env-default'), exe_name)
os.remove(py_exe)
- assert python.healthy(prefix, C.DEFAULT) is False
+ ret = python.health_check(prefix, C.DEFAULT)
+ assert ret == (
+ f'virtualenv python version did not match created version:\n'
+ f'- actual version: <<error retrieving version from {py_exe}>>\n'
+ f'- expected version: {python._version_info(sys.executable)}\n'
+ )
def test_unhealthy_with_version_change(python_dir):
@@ -127,10 +132,15 @@ def test_unhealthy_with_version_change(python_dir):
python.install_environment(prefix, C.DEFAULT, ())
- with open(prefix.path('py_env-default/pyvenv.cfg'), 'w') as f:
+ with open(prefix.path('py_env-default/pyvenv.cfg'), 'a+') as f:
f.write('version_info = 1.2.3\n')
- assert python.healthy(prefix, C.DEFAULT) is False
+ ret = python.health_check(prefix, C.DEFAULT)
+ assert ret == (
+ f'virtualenv python version did not match created version:\n'
+ f'- actual version: {python._version_info(sys.executable)}\n'
+ f'- expected version: 1.2.3\n'
+ )
def test_unhealthy_system_version_changes(python_dir):
@@ -141,7 +151,12 @@ def test_unhealthy_system_version_changes(python_dir):
with open(prefix.path('py_env-default/pyvenv.cfg'), 'a') as f:
f.write('base-executable = /does/not/exist\n')
- assert python.healthy(prefix, C.DEFAULT) is False
+ ret = python.health_check(prefix, C.DEFAULT)
+ assert ret == (
+ f'base executable python version does not match created version:\n'
+ f'- base-executable version: <<error retrieving version from /does/not/exist>>\n' # noqa: E501
+ f'- expected version: {python._version_info(sys.executable)}\n'
+ )
def test_unhealthy_old_virtualenv(python_dir):
@@ -152,7 +167,21 @@ def test_unhealthy_old_virtualenv(python_dir):
# simulate "old" virtualenv by deleting this file
os.remove(prefix.path('py_env-default/pyvenv.cfg'))
- assert python.healthy(prefix, C.DEFAULT) is False
+ ret = python.health_check(prefix, C.DEFAULT)
+ assert ret == 'pyvenv.cfg does not exist (old virtualenv?)'
+
+
+def test_unhealthy_unexpected_pyvenv(python_dir):
+ prefix, tmpdir = python_dir
+
+ python.install_environment(prefix, C.DEFAULT, ())
+
+ # simulate a buggy environment build (I don't think this is possible)
+ with open(prefix.path('py_env-default/pyvenv.cfg'), 'w'):
+ pass
+
+ ret = python.health_check(prefix, C.DEFAULT)
+ assert ret == "created virtualenv's pyvenv.cfg is missing `version_info`"
def test_unhealthy_then_replaced(python_dir):
@@ -170,9 +199,14 @@ def test_unhealthy_then_replaced(python_dir):
make_executable(py_exe)
# should be unhealthy due to version mismatch
- assert python.healthy(prefix, C.DEFAULT) is False
+ ret = python.health_check(prefix, C.DEFAULT)
+ assert ret == (
+ f'virtualenv python version did not match created version:\n'
+ f'- actual version: 1.2.3\n'
+ f'- expected version: {python._version_info(sys.executable)}\n'
+ )
# now put the exe back and it should be healthy again
os.replace(f'{py_exe}.tmp', py_exe)
- assert python.healthy(prefix, C.DEFAULT) is True
+ assert python.health_check(prefix, C.DEFAULT) is None
diff --git a/tests/main_test.py b/tests/main_test.py
index a645300..a7afd6d 100644
--- a/tests/main_test.py
+++ b/tests/main_test.py
@@ -79,6 +79,7 @@ def test_adjust_args_try_repo_repo_relative(in_git_dir):
FNS = (
'autoupdate', 'clean', 'gc', 'hook_impl', 'install', 'install_hooks',
'migrate_config', 'run', 'sample_config', 'uninstall',
+ 'validate_config', 'validate_manifest',
)
CMDS = tuple(fn.replace('_', '-') for fn in FNS)
diff --git a/tests/repository_test.py b/tests/repository_test.py
index cef6887..3729ab1 100644
--- a/tests/repository_test.py
+++ b/tests/repository_test.py
@@ -173,6 +173,7 @@ def test_python_venv(tempdir_factory, store):
)
+@xfailif_windows # pragma: win32 no cover # no python 2 in GHA
def test_switch_language_versions_doesnt_clobber(tempdir_factory, store):
# We're using the python3 repo because it prints the python version
path = make_repo(tempdir_factory, 'python3_hooks_repo')
@@ -667,7 +668,7 @@ def test_additional_golang_dependencies_installed(
path = make_repo(tempdir_factory, 'golang_hooks_repo')
config = make_config_from_repo(path)
# A small go package
- deps = ['golang.org/x/example/hello']
+ deps = ['golang.org/x/example/hello@latest']
config['hooks'][0]['additional_dependencies'] = deps
hook = _get_hook(config, store, 'golang-hook')
binaries = os.listdir(
@@ -688,7 +689,7 @@ def test_local_golang_additional_dependencies(store):
'name': 'hello',
'entry': 'hello',
'language': 'golang',
- 'additional_dependencies': ['golang.org/x/example/hello'],
+ 'additional_dependencies': ['golang.org/x/example/hello@latest'],
}],
}
hook = _get_hook(config, store, 'hello')
@@ -892,6 +893,7 @@ def test_local_python_repo(store, local_python_config):
assert _norm_out(out) == b"3\n['filename']\nHello World\n"
+@xfailif_windows # pragma: win32 no cover # no python2 in GHA
def test_local_python_repo_python2(store, local_python_config):
local_python_config['hooks'][0]['language_version'] = 'python2'
hook = _get_hook(local_python_config, store, 'python3-hook')
@@ -1042,6 +1044,7 @@ def test_local_perl_additional_dependencies(store):
(
'dotnet_hooks_csproj_repo',
'dotnet_hooks_sln_repo',
+ 'dotnet_hooks_combo_repo',
),
)
def test_dotnet_hook(tempdir_factory, store, repo):