Merging upstream version 3.1.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
f7ee0eb8fc
commit
c4c52947de
88 changed files with 1083 additions and 974 deletions
7
tests/all_languages_test.py
Normal file
7
tests/all_languages_test.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pre_commit.all_languages import languages
|
||||
|
||||
|
||||
def test_python_venv_is_an_alias_to_python():
|
||||
assert languages['python_venv'] is languages['python']
|
|
@ -134,6 +134,39 @@ def test_migrate_config_sha_to_rev(tmpdir):
|
|||
)
|
||||
|
||||
|
||||
def test_migrate_config_language_python_venv(tmp_path):
|
||||
src = '''\
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: example
|
||||
name: example
|
||||
entry: example
|
||||
language: python_venv
|
||||
- id: example
|
||||
name: example
|
||||
entry: example
|
||||
language: system
|
||||
'''
|
||||
expected = '''\
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: example
|
||||
name: example
|
||||
entry: example
|
||||
language: python
|
||||
- id: example
|
||||
name: example
|
||||
entry: example
|
||||
language: system
|
||||
'''
|
||||
cfg = tmp_path.joinpath('cfg.yaml')
|
||||
cfg.write_text(src)
|
||||
assert migrate_config(str(cfg)) == 0
|
||||
assert cfg.read_text() == expected
|
||||
|
||||
|
||||
def test_migrate_config_invalid_yaml(tmpdir):
|
||||
contents = '['
|
||||
cfg = tmpdir.join(C.CONFIG_FILE)
|
||||
|
|
|
@ -8,8 +8,8 @@ from unittest import mock
|
|||
import pytest
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit import lang_base
|
||||
from pre_commit import parse_shebang
|
||||
from pre_commit.languages import helpers
|
||||
from pre_commit.prefix import Prefix
|
||||
from pre_commit.util import CalledProcessError
|
||||
|
||||
|
@ -32,42 +32,42 @@ def homedir_mck():
|
|||
|
||||
def test_exe_exists_does_not_exist(find_exe_mck, homedir_mck):
|
||||
find_exe_mck.return_value = None
|
||||
assert helpers.exe_exists('ruby') is False
|
||||
assert lang_base.exe_exists('ruby') is False
|
||||
|
||||
|
||||
def test_exe_exists_exists(find_exe_mck, homedir_mck):
|
||||
find_exe_mck.return_value = os.path.normpath('/usr/bin/ruby')
|
||||
assert helpers.exe_exists('ruby') is True
|
||||
assert lang_base.exe_exists('ruby') is True
|
||||
|
||||
|
||||
def test_exe_exists_false_if_shim(find_exe_mck, homedir_mck):
|
||||
find_exe_mck.return_value = os.path.normpath('/foo/shims/ruby')
|
||||
assert helpers.exe_exists('ruby') is False
|
||||
assert lang_base.exe_exists('ruby') is False
|
||||
|
||||
|
||||
def test_exe_exists_false_if_homedir(find_exe_mck, homedir_mck):
|
||||
find_exe_mck.return_value = os.path.normpath('/home/me/somedir/ruby')
|
||||
assert helpers.exe_exists('ruby') is False
|
||||
assert lang_base.exe_exists('ruby') is False
|
||||
|
||||
|
||||
def test_exe_exists_commonpath_raises_ValueError(find_exe_mck, homedir_mck):
|
||||
find_exe_mck.return_value = os.path.normpath('/usr/bin/ruby')
|
||||
with mock.patch.object(os.path, 'commonpath', side_effect=ValueError):
|
||||
assert helpers.exe_exists('ruby') is True
|
||||
assert lang_base.exe_exists('ruby') is True
|
||||
|
||||
|
||||
def test_exe_exists_true_when_homedir_is_slash(find_exe_mck):
|
||||
find_exe_mck.return_value = os.path.normpath('/usr/bin/ruby')
|
||||
with mock.patch.object(os.path, 'expanduser', return_value=os.sep):
|
||||
assert helpers.exe_exists('ruby') is True
|
||||
assert lang_base.exe_exists('ruby') is True
|
||||
|
||||
|
||||
def test_basic_get_default_version():
|
||||
assert helpers.basic_get_default_version() == C.DEFAULT
|
||||
assert lang_base.basic_get_default_version() == C.DEFAULT
|
||||
|
||||
|
||||
def test_basic_health_check():
|
||||
assert helpers.basic_health_check(Prefix('.'), 'default') is None
|
||||
assert lang_base.basic_health_check(Prefix('.'), 'default') is None
|
||||
|
||||
|
||||
def test_failed_setup_command_does_not_unicode_error():
|
||||
|
@ -79,12 +79,27 @@ def test_failed_setup_command_does_not_unicode_error():
|
|||
|
||||
# an assertion that this does not raise `UnicodeError`
|
||||
with pytest.raises(CalledProcessError):
|
||||
helpers.run_setup_cmd(Prefix('.'), (sys.executable, '-c', script))
|
||||
lang_base.setup_cmd(Prefix('.'), (sys.executable, '-c', script))
|
||||
|
||||
|
||||
def test_environment_dir(tmp_path):
|
||||
ret = lang_base.environment_dir(Prefix(tmp_path), 'langenv', 'default')
|
||||
assert ret == f'{tmp_path}{os.sep}langenv-default'
|
||||
|
||||
|
||||
def test_assert_version_default():
|
||||
with pytest.raises(AssertionError) as excinfo:
|
||||
lang_base.assert_version_default('lang', '1.2.3')
|
||||
msg, = excinfo.value.args
|
||||
assert msg == (
|
||||
'for now, pre-commit requires system-installed lang -- '
|
||||
'you selected `language_version: 1.2.3`'
|
||||
)
|
||||
|
||||
|
||||
def test_assert_no_additional_deps():
|
||||
with pytest.raises(AssertionError) as excinfo:
|
||||
helpers.assert_no_additional_deps('lang', ['hmmm'])
|
||||
lang_base.assert_no_additional_deps('lang', ['hmmm'])
|
||||
msg, = excinfo.value.args
|
||||
assert msg == (
|
||||
'for now, pre-commit does not support additional_dependencies for '
|
||||
|
@ -93,22 +108,30 @@ def test_assert_no_additional_deps():
|
|||
)
|
||||
|
||||
|
||||
def test_no_env_noop(tmp_path):
|
||||
before = os.environ.copy()
|
||||
with lang_base.no_env(Prefix(tmp_path), '1.2.3'):
|
||||
inside = os.environ.copy()
|
||||
after = os.environ.copy()
|
||||
assert before == inside == after
|
||||
|
||||
|
||||
def test_target_concurrency_normal():
|
||||
with mock.patch.object(multiprocessing, 'cpu_count', return_value=123):
|
||||
with mock.patch.dict(os.environ, {}, clear=True):
|
||||
assert helpers.target_concurrency() == 123
|
||||
assert lang_base.target_concurrency() == 123
|
||||
|
||||
|
||||
def test_target_concurrency_testing_env_var():
|
||||
with mock.patch.dict(
|
||||
os.environ, {'PRE_COMMIT_NO_CONCURRENCY': '1'}, clear=True,
|
||||
):
|
||||
assert helpers.target_concurrency() == 1
|
||||
assert lang_base.target_concurrency() == 1
|
||||
|
||||
|
||||
def test_target_concurrency_on_travis():
|
||||
with mock.patch.dict(os.environ, {'TRAVIS': '1'}, clear=True):
|
||||
assert helpers.target_concurrency() == 2
|
||||
assert lang_base.target_concurrency() == 2
|
||||
|
||||
|
||||
def test_target_concurrency_cpu_count_not_implemented():
|
||||
|
@ -116,20 +139,35 @@ def test_target_concurrency_cpu_count_not_implemented():
|
|||
multiprocessing, 'cpu_count', side_effect=NotImplementedError,
|
||||
):
|
||||
with mock.patch.dict(os.environ, {}, clear=True):
|
||||
assert helpers.target_concurrency() == 1
|
||||
assert lang_base.target_concurrency() == 1
|
||||
|
||||
|
||||
def test_shuffled_is_deterministic():
|
||||
seq = [str(i) for i in range(10)]
|
||||
expected = ['4', '0', '5', '1', '8', '6', '2', '3', '7', '9']
|
||||
assert helpers._shuffled(seq) == expected
|
||||
assert lang_base._shuffled(seq) == expected
|
||||
|
||||
|
||||
def test_xargs_require_serial_is_not_shuffled():
|
||||
ret, out = helpers.run_xargs(
|
||||
ret, out = lang_base.run_xargs(
|
||||
('echo',), [str(i) for i in range(10)],
|
||||
require_serial=True,
|
||||
color=False,
|
||||
)
|
||||
assert ret == 0
|
||||
assert out.strip() == b'0 1 2 3 4 5 6 7 8 9'
|
||||
|
||||
|
||||
def test_basic_run_hook(tmp_path):
|
||||
ret, out = lang_base.basic_run_hook(
|
||||
Prefix(tmp_path),
|
||||
'echo hi',
|
||||
['hello'],
|
||||
['file', 'file', 'file'],
|
||||
is_local=False,
|
||||
require_serial=False,
|
||||
color=False,
|
||||
)
|
||||
assert ret == 0
|
||||
out = out.replace(b'\r\n', b'\n')
|
||||
assert out == b'hi hello file file file\n'
|
27
tests/languages/docker_image_test.py
Normal file
27
tests/languages/docker_image_test.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pre_commit.languages import docker_image
|
||||
from testing.language_helpers import run_language
|
||||
from testing.util import xfailif_windows
|
||||
|
||||
|
||||
@xfailif_windows # pragma: win32 no cover
|
||||
def test_docker_image_hook_via_entrypoint(tmp_path):
|
||||
ret = run_language(
|
||||
tmp_path,
|
||||
docker_image,
|
||||
'--entrypoint echo ubuntu:22.04',
|
||||
args=('hello hello world',),
|
||||
)
|
||||
assert ret == (0, b'hello hello world\n')
|
||||
|
||||
|
||||
@xfailif_windows # pragma: win32 no cover
|
||||
def test_docker_image_hook_via_args(tmp_path):
|
||||
ret = run_language(
|
||||
tmp_path,
|
||||
docker_image,
|
||||
'ubuntu:22.04 echo',
|
||||
args=('hello hello world',),
|
||||
)
|
||||
assert ret == (0, b'hello hello world\n')
|
|
@ -11,6 +11,8 @@ import pytest
|
|||
|
||||
from pre_commit.languages import docker
|
||||
from pre_commit.util import CalledProcessError
|
||||
from testing.language_helpers import run_language
|
||||
from testing.util import xfailif_windows
|
||||
|
||||
DOCKER_CGROUP_EXAMPLE = b'''\
|
||||
12:hugetlb:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
|
||||
|
@ -181,3 +183,15 @@ def test_get_docker_path_in_docker_docker_in_docker(in_docker):
|
|||
err = CalledProcessError(1, (), b'', b'')
|
||||
with mock.patch.object(docker, 'cmd_output_b', side_effect=err):
|
||||
assert docker._get_docker_path('/project') == '/project'
|
||||
|
||||
|
||||
@xfailif_windows # pragma: win32 no cover
|
||||
def test_docker_hook(tmp_path):
|
||||
dockerfile = '''\
|
||||
FROM ubuntu:22.04
|
||||
CMD ["echo", "This is overwritten by the entry"']
|
||||
'''
|
||||
tmp_path.joinpath('Dockerfile').write_text(dockerfile)
|
||||
|
||||
ret = run_language(tmp_path, docker, 'echo hello hello world')
|
||||
assert ret == (0, b'hello hello world\n')
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pre_commit.languages import dotnet
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
def _write_program_cs(tmp_path):
|
||||
program_cs = '''\
|
||||
using System;
|
||||
|
||||
namespace dotnet_tests
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello from dotnet!");
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
tmp_path.joinpath('Program.cs').write_text(program_cs)
|
||||
|
||||
|
||||
def _csproj(tool_name):
|
||||
return f'''\
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<PackAsTool>true</PackAsTool>
|
||||
<ToolCommandName>{tool_name}</ToolCommandName>
|
||||
<PackageOutputPath>./nupkg</PackageOutputPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
'''
|
||||
|
||||
|
||||
def test_dotnet_csproj(tmp_path):
|
||||
csproj = _csproj('testeroni')
|
||||
_write_program_cs(tmp_path)
|
||||
tmp_path.joinpath('dotnet_csproj.csproj').write_text(csproj)
|
||||
ret = run_language(tmp_path, dotnet, 'testeroni')
|
||||
assert ret == (0, b'Hello from dotnet!\n')
|
||||
|
||||
|
||||
def test_dotnet_csproj_prefix(tmp_path):
|
||||
csproj = _csproj('testeroni.tool')
|
||||
_write_program_cs(tmp_path)
|
||||
tmp_path.joinpath('dotnet_hooks_csproj_prefix.csproj').write_text(csproj)
|
||||
ret = run_language(tmp_path, dotnet, 'testeroni.tool')
|
||||
assert ret == (0, b'Hello from dotnet!\n')
|
||||
|
||||
|
||||
def test_dotnet_sln(tmp_path):
|
||||
csproj = _csproj('testeroni')
|
||||
sln = '''\
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26124.0
|
||||
MinimumVisualStudioVersion = 15.0.26124.0
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dotnet_hooks_sln_repo", "dotnet_hooks_sln_repo.csproj", "{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
''' # noqa: E501
|
||||
_write_program_cs(tmp_path)
|
||||
tmp_path.joinpath('dotnet_hooks_sln_repo.csproj').write_text(csproj)
|
||||
tmp_path.joinpath('dotnet_hooks_sln_repo.sln').write_text(sln)
|
||||
|
||||
ret = run_language(tmp_path, dotnet, 'testeroni')
|
||||
assert ret == (0, b'Hello from dotnet!\n')
|
||||
|
||||
|
||||
def _setup_dotnet_combo(tmp_path):
|
||||
sln = '''\
|
||||
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
|
||||
''' # noqa: E501
|
||||
tmp_path.joinpath('dotnet_hooks_combo_repo.sln').write_text(sln)
|
||||
|
||||
csproj1 = _csproj('proj1')
|
||||
proj1 = tmp_path.joinpath('proj1')
|
||||
proj1.mkdir()
|
||||
proj1.joinpath('proj1.csproj').write_text(csproj1)
|
||||
_write_program_cs(proj1)
|
||||
|
||||
csproj2 = _csproj('proj2')
|
||||
proj2 = tmp_path.joinpath('proj2')
|
||||
proj2.mkdir()
|
||||
proj2.joinpath('proj2.csproj').write_text(csproj2)
|
||||
_write_program_cs(proj2)
|
||||
|
||||
|
||||
def test_dotnet_combo_proj1(tmp_path):
|
||||
_setup_dotnet_combo(tmp_path)
|
||||
ret = run_language(tmp_path, dotnet, 'proj1')
|
||||
assert ret == (0, b'Hello from dotnet!\n')
|
||||
|
||||
|
||||
def test_dotnet_combo_proj2(tmp_path):
|
||||
_setup_dotnet_combo(tmp_path)
|
||||
ret = run_language(tmp_path, dotnet, 'proj2')
|
||||
assert ret == (0, b'Hello from dotnet!\n')
|
14
tests/languages/fail_test.py
Normal file
14
tests/languages/fail_test.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pre_commit.languages import fail
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
def test_fail_hooks(tmp_path):
|
||||
ret = run_language(
|
||||
tmp_path,
|
||||
fail,
|
||||
'watch out for',
|
||||
file_args=('bunnies',),
|
||||
)
|
||||
assert ret == (1, b'watch out for\n\nbunnies\n')
|
|
@ -6,8 +6,11 @@ import pytest
|
|||
import re_assert
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit import lang_base
|
||||
from pre_commit.envcontext import envcontext
|
||||
from pre_commit.languages import golang
|
||||
from pre_commit.languages import helpers
|
||||
from pre_commit.store import _make_local_repo
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
ACTUAL_GET_DEFAULT_VERSION = golang.get_default_version.__wrapped__
|
||||
|
@ -15,7 +18,7 @@ ACTUAL_GET_DEFAULT_VERSION = golang.get_default_version.__wrapped__
|
|||
|
||||
@pytest.fixture
|
||||
def exe_exists_mck():
|
||||
with mock.patch.object(helpers, 'exe_exists') as mck:
|
||||
with mock.patch.object(lang_base, 'exe_exists') as mck:
|
||||
yield mck
|
||||
|
||||
|
||||
|
@ -41,3 +44,93 @@ def test_golang_infer_go_version_default():
|
|||
|
||||
assert version != C.DEFAULT
|
||||
re_assert.Matches(r'^\d+\.\d+(?:\.\d+)?$').assert_matches(version)
|
||||
|
||||
|
||||
def _make_hello_world(tmp_path):
|
||||
go_mod = '''\
|
||||
module golang-hello-world
|
||||
|
||||
go 1.18
|
||||
|
||||
require github.com/BurntSushi/toml v1.1.0
|
||||
'''
|
||||
go_sum = '''\
|
||||
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
|
||||
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
''' # noqa: E501
|
||||
hello_world_go = '''\
|
||||
package main
|
||||
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
What string
|
||||
}
|
||||
|
||||
func main() {
|
||||
var conf Config
|
||||
toml.Decode("What = 'world'\\n", &conf)
|
||||
fmt.Printf("hello %v\\n", conf.What)
|
||||
}
|
||||
'''
|
||||
tmp_path.joinpath('go.mod').write_text(go_mod)
|
||||
tmp_path.joinpath('go.sum').write_text(go_sum)
|
||||
mod_dir = tmp_path.joinpath('golang-hello-world')
|
||||
mod_dir.mkdir()
|
||||
main_file = mod_dir.joinpath('main.go')
|
||||
main_file.write_text(hello_world_go)
|
||||
|
||||
|
||||
def test_golang_system(tmp_path):
|
||||
_make_hello_world(tmp_path)
|
||||
|
||||
ret = run_language(tmp_path, golang, 'golang-hello-world')
|
||||
assert ret == (0, b'hello world\n')
|
||||
|
||||
|
||||
def test_golang_default_version(tmp_path):
|
||||
_make_hello_world(tmp_path)
|
||||
|
||||
ret = run_language(
|
||||
tmp_path,
|
||||
golang,
|
||||
'golang-hello-world',
|
||||
version=C.DEFAULT,
|
||||
)
|
||||
assert ret == (0, b'hello world\n')
|
||||
|
||||
|
||||
def test_golang_versioned(tmp_path):
|
||||
_make_local_repo(str(tmp_path))
|
||||
|
||||
ret, out = run_language(
|
||||
tmp_path,
|
||||
golang,
|
||||
'go version',
|
||||
version='1.18.4',
|
||||
)
|
||||
|
||||
assert ret == 0
|
||||
assert out.startswith(b'go version go1.18.4')
|
||||
|
||||
|
||||
def test_local_golang_additional_deps(tmp_path):
|
||||
_make_local_repo(str(tmp_path))
|
||||
|
||||
ret = run_language(
|
||||
tmp_path,
|
||||
golang,
|
||||
'hello',
|
||||
deps=('golang.org/x/example/hello@latest',),
|
||||
)
|
||||
|
||||
assert ret == (0, b'Hello, Go examples!\n')
|
||||
|
||||
|
||||
def test_golang_hook_still_works_when_gobin_is_set(tmp_path):
|
||||
with envcontext((('GOBIN', str(tmp_path.joinpath('gobin'))),)):
|
||||
test_golang_system(tmp_path)
|
||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
|||
import pytest
|
||||
|
||||
from pre_commit.languages import pygrep
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -13,6 +14,9 @@ def some_files(tmpdir):
|
|||
tmpdir.join('f4').write_binary(b'foo\npattern\nbar\n')
|
||||
tmpdir.join('f5').write_binary(b'[INFO] hi\npattern\nbar')
|
||||
tmpdir.join('f6').write_binary(b"pattern\nbarwith'foo\n")
|
||||
tmpdir.join('f7').write_binary(b"hello'hi\nworld\n")
|
||||
tmpdir.join('f8').write_binary(b'foo\nbar\nbaz\n')
|
||||
tmpdir.join('f9').write_binary(b'[WARN] hi\n')
|
||||
with tmpdir.as_cwd():
|
||||
yield
|
||||
|
||||
|
@ -125,3 +129,16 @@ def test_multiline_multiline_flag_is_enabled(cap_out):
|
|||
out = cap_out.get()
|
||||
assert ret == 1
|
||||
assert out == 'f1:1:foo\nbar\n'
|
||||
|
||||
|
||||
def test_grep_hook_matching(some_files, tmp_path):
|
||||
ret = run_language(
|
||||
tmp_path, pygrep, 'ello', file_args=('f7', 'f8', 'f9'),
|
||||
)
|
||||
assert ret == (1, b"f7:1:hello'hi\n")
|
||||
|
||||
|
||||
@pytest.mark.parametrize('regex', ('nope', "foo'bar", r'^\[INFO\]'))
|
||||
def test_grep_hook_not_matching(regex, some_files, tmp_path):
|
||||
ret = run_language(tmp_path, pygrep, regex, file_args=('f7', 'f8', 'f9'))
|
||||
assert ret == (0, b'')
|
||||
|
|
|
@ -12,6 +12,7 @@ from pre_commit.languages import python
|
|||
from pre_commit.prefix import Prefix
|
||||
from pre_commit.util import make_executable
|
||||
from pre_commit.util import win_exe
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
def test_read_pyvenv_cfg(tmpdir):
|
||||
|
@ -210,3 +211,25 @@ def test_unhealthy_then_replaced(python_dir):
|
|||
os.replace(f'{py_exe}.tmp', py_exe)
|
||||
|
||||
assert python.health_check(prefix, C.DEFAULT) is None
|
||||
|
||||
|
||||
def test_language_versioned_python_hook(tmp_path):
|
||||
setup_py = '''\
|
||||
from setuptools import setup
|
||||
setup(
|
||||
name='example',
|
||||
py_modules=['mod'],
|
||||
entry_points={'console_scripts': ['myexe=mod:main']},
|
||||
)
|
||||
'''
|
||||
tmp_path.joinpath('setup.py').write_text(setup_py)
|
||||
tmp_path.joinpath('mod.py').write_text('def main(): print("ohai")')
|
||||
|
||||
# we patch this to force virtualenv executing with `-p` since we can't
|
||||
# reliably have multiple pythons available in CI
|
||||
with mock.patch.object(
|
||||
python,
|
||||
'_sys_executable_matches',
|
||||
return_value=False,
|
||||
):
|
||||
assert run_language(tmp_path, python, 'myexe') == (0, b'ohai\n')
|
||||
|
|
|
@ -9,8 +9,8 @@ import pre_commit.constants as C
|
|||
from pre_commit import parse_shebang
|
||||
from pre_commit.envcontext import envcontext
|
||||
from pre_commit.languages import ruby
|
||||
from pre_commit.languages.ruby import _resource_bytesio
|
||||
from pre_commit.store import _make_local_repo
|
||||
from pre_commit.util import resource_bytesio
|
||||
from testing.language_helpers import run_language
|
||||
from testing.util import cwd
|
||||
from testing.util import xfailif_windows
|
||||
|
@ -40,7 +40,7 @@ def test_uses_system_if_both_gem_and_ruby_are_available(find_exe_mck):
|
|||
('rbenv.tar.gz', 'ruby-build.tar.gz', 'ruby-download.tar.gz'),
|
||||
)
|
||||
def test_archive_root_stat(filename):
|
||||
with resource_bytesio(filename) as f:
|
||||
with _resource_bytesio(filename) as f:
|
||||
with tarfile.open(fileobj=f) as tarf:
|
||||
root, _, _ = filename.partition('.')
|
||||
assert oct(tarf.getmember(root).mode) == '0o755'
|
||||
|
|
14
tests/languages/script_test.py
Normal file
14
tests/languages/script_test.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pre_commit.languages import script
|
||||
from pre_commit.util import make_executable
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
def test_script_language(tmp_path):
|
||||
exe = tmp_path.joinpath('main')
|
||||
exe.write_text('#!/usr/bin/env bash\necho hello hello world\n')
|
||||
make_executable(exe)
|
||||
|
||||
expected = (0, b'hello hello world\n')
|
||||
assert run_language(tmp_path, script, 'main') == expected
|
9
tests/languages/system_test.py
Normal file
9
tests/languages/system_test.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pre_commit.languages import system
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
def test_system_language(tmp_path):
|
||||
expected = (0, b'hello hello world\n')
|
||||
assert run_language(tmp_path, system, 'echo hello hello world') == expected
|
|
@ -10,15 +10,12 @@ import pytest
|
|||
import re_assert
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit import git
|
||||
from pre_commit import lang_base
|
||||
from pre_commit.all_languages import languages
|
||||
from pre_commit.clientlib import CONFIG_SCHEMA
|
||||
from pre_commit.clientlib import load_manifest
|
||||
from pre_commit.envcontext import envcontext
|
||||
from pre_commit.hook import Hook
|
||||
from pre_commit.languages import golang
|
||||
from pre_commit.languages import helpers
|
||||
from pre_commit.languages import python
|
||||
from pre_commit.languages.all import languages
|
||||
from pre_commit.prefix import Prefix
|
||||
from pre_commit.repository import _hook_installed
|
||||
from pre_commit.repository import all_hooks
|
||||
|
@ -28,26 +25,24 @@ from pre_commit.util import cmd_output_b
|
|||
from testing.fixtures import make_config_from_repo
|
||||
from testing.fixtures import make_repo
|
||||
from testing.fixtures import modify_manifest
|
||||
from testing.language_helpers import run_language
|
||||
from testing.util import cwd
|
||||
from testing.util import get_resource_path
|
||||
from testing.util import skipif_cant_run_docker
|
||||
|
||||
|
||||
def _norm_out(b):
|
||||
return b.replace(b'\r\n', b'\n')
|
||||
|
||||
|
||||
def _hook_run(hook, filenames, color):
|
||||
with languages[hook.language].in_env(hook.prefix, hook.language_version):
|
||||
return languages[hook.language].run_hook(
|
||||
hook.prefix,
|
||||
hook.entry,
|
||||
hook.args,
|
||||
filenames,
|
||||
is_local=hook.src == 'local',
|
||||
require_serial=hook.require_serial,
|
||||
color=color,
|
||||
)
|
||||
return run_language(
|
||||
path=hook.prefix.prefix_dir,
|
||||
language=languages[hook.language],
|
||||
exe=hook.entry,
|
||||
args=hook.args,
|
||||
file_args=filenames,
|
||||
version=hook.language_version,
|
||||
deps=hook.additional_dependencies,
|
||||
is_local=hook.src == 'local',
|
||||
require_serial=hook.require_serial,
|
||||
color=color,
|
||||
)
|
||||
|
||||
|
||||
def _get_hook_no_install(repo_config, store, hook_id):
|
||||
|
@ -81,7 +76,7 @@ def _test_hook_repo(
|
|||
hook = _get_hook(config, store, hook_id)
|
||||
ret, out = _hook_run(hook, args, color=color)
|
||||
assert ret == expected_return_code
|
||||
assert _norm_out(out) == expected
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_python_hook(tempdir_factory, store):
|
||||
|
@ -129,66 +124,21 @@ def test_python_hook_weird_setup_cfg(in_git_dir, tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
def test_python_venv(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'python_venv_hooks_repo',
|
||||
'foo', [os.devnull],
|
||||
f'[{os.devnull!r}]\nHello World\n'.encode(),
|
||||
)
|
||||
|
||||
|
||||
def test_language_versioned_python_hook(tempdir_factory, store):
|
||||
# we patch this force virtualenv executing with `-p` since we can't
|
||||
# reliably have multiple pythons available in CI
|
||||
with mock.patch.object(
|
||||
python,
|
||||
'_sys_executable_matches',
|
||||
return_value=False,
|
||||
):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'python3_hooks_repo',
|
||||
'python3-hook',
|
||||
[os.devnull],
|
||||
f'3\n[{os.devnull!r}]\nHello World\n'.encode(),
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_docker # pragma: win32 no cover
|
||||
def test_run_a_docker_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'docker_hooks_repo',
|
||||
'docker-hook',
|
||||
['Hello World from docker'], b'Hello World from docker\n',
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_docker # pragma: win32 no cover
|
||||
def test_run_a_docker_hook_with_entry_args(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'docker_hooks_repo',
|
||||
'docker-hook-arg',
|
||||
['Hello World from docker'], b'Hello World from docker',
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_docker # pragma: win32 no cover
|
||||
def test_run_a_failing_docker_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'docker_hooks_repo',
|
||||
'docker-hook-failing',
|
||||
['Hello World from docker'],
|
||||
mock.ANY, # an error message about `bork` not existing
|
||||
expected_return_code=127,
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_docker # pragma: win32 no cover
|
||||
@pytest.mark.parametrize('hook_id', ('echo-entrypoint', 'echo-cmd'))
|
||||
def test_run_a_docker_image_hook(tempdir_factory, store, hook_id):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'docker_image_hooks_repo',
|
||||
hook_id,
|
||||
['Hello World from docker'], b'Hello World from docker\n',
|
||||
def test_python_venv_deprecation(store, caplog):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'example',
|
||||
'name': 'example',
|
||||
'language': 'python_venv',
|
||||
'entry': 'echo hi',
|
||||
}],
|
||||
}
|
||||
_get_hook(config, store, 'example')
|
||||
assert caplog.messages[-1] == (
|
||||
'`repo: local` uses deprecated `language: python_venv`. '
|
||||
'This is an alias for `language: python`. '
|
||||
'Often `pre-commit autoupdate --repo local` will fix this.'
|
||||
)
|
||||
|
||||
|
||||
|
@ -199,92 +149,6 @@ def test_system_hook_with_spaces(tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
def test_golang_system_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'golang_hooks_repo',
|
||||
'golang-hook', ['system'], b'hello world from system\n',
|
||||
config_kwargs={
|
||||
'hooks': [{
|
||||
'id': 'golang-hook',
|
||||
'language_version': 'system',
|
||||
}],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_golang_versioned_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'golang_hooks_repo',
|
||||
'golang-hook', [], b'hello world from go1.18.4\n',
|
||||
config_kwargs={
|
||||
'hooks': [{
|
||||
'id': 'golang-hook',
|
||||
'language_version': '1.18.4',
|
||||
}],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_golang_hook_still_works_when_gobin_is_set(tempdir_factory, store):
|
||||
gobin_dir = tempdir_factory.get()
|
||||
with envcontext((('GOBIN', gobin_dir),)):
|
||||
test_golang_system_hook(tempdir_factory, store)
|
||||
assert os.listdir(gobin_dir) == []
|
||||
|
||||
|
||||
def test_golang_with_recursive_submodule(tmpdir, tempdir_factory, store):
|
||||
sub_go = '''\
|
||||
package sub
|
||||
|
||||
import "fmt"
|
||||
|
||||
func Func() {
|
||||
fmt.Println("hello hello world")
|
||||
}
|
||||
'''
|
||||
sub = tmpdir.join('sub').ensure_dir()
|
||||
sub.join('sub.go').write(sub_go)
|
||||
cmd_output('git', '-C', str(sub), 'init', '.')
|
||||
cmd_output('git', '-C', str(sub), 'add', '.')
|
||||
git.commit(str(sub))
|
||||
|
||||
pre_commit_hooks = '''\
|
||||
- id: example
|
||||
name: example
|
||||
entry: example
|
||||
language: golang
|
||||
verbose: true
|
||||
'''
|
||||
go_mod = '''\
|
||||
module github.com/asottile/example
|
||||
|
||||
go 1.14
|
||||
'''
|
||||
main_go = '''\
|
||||
package main
|
||||
|
||||
import "github.com/asottile/example/sub"
|
||||
|
||||
func main() {
|
||||
sub.Func()
|
||||
}
|
||||
'''
|
||||
repo = tmpdir.join('repo').ensure_dir()
|
||||
repo.join('.pre-commit-hooks.yaml').write(pre_commit_hooks)
|
||||
repo.join('go.mod').write(go_mod)
|
||||
repo.join('main.go').write(main_go)
|
||||
cmd_output('git', '-C', str(repo), 'init', '.')
|
||||
cmd_output('git', '-C', str(repo), 'add', '.')
|
||||
cmd_output('git', '-C', str(repo), 'submodule', 'add', str(sub), 'sub')
|
||||
git.commit(str(repo))
|
||||
|
||||
config = make_config_from_repo(str(repo))
|
||||
hook = _get_hook(config, store, 'example')
|
||||
ret, out = _hook_run(hook, (), color=False)
|
||||
assert ret == 0
|
||||
assert _norm_out(out) == b'hello hello world\n'
|
||||
|
||||
|
||||
def test_missing_executable(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'not_found_exe',
|
||||
|
@ -345,52 +209,6 @@ def test_output_isatty(tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
def _make_grep_repo(entry, store, args=()):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'grep-hook',
|
||||
'name': 'grep-hook',
|
||||
'language': 'pygrep',
|
||||
'entry': entry,
|
||||
'args': args,
|
||||
'types': ['text'],
|
||||
}],
|
||||
}
|
||||
return _get_hook(config, store, 'grep-hook')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def greppable_files(tmpdir):
|
||||
with tmpdir.as_cwd():
|
||||
cmd_output_b('git', 'init', '.')
|
||||
tmpdir.join('f1').write_binary(b"hello'hi\nworld\n")
|
||||
tmpdir.join('f2').write_binary(b'foo\nbar\nbaz\n')
|
||||
tmpdir.join('f3').write_binary(b'[WARN] hi\n')
|
||||
yield tmpdir
|
||||
|
||||
|
||||
def test_grep_hook_matching(greppable_files, store):
|
||||
hook = _make_grep_repo('ello', store)
|
||||
ret, out = _hook_run(hook, ('f1', 'f2', 'f3'), color=False)
|
||||
assert ret == 1
|
||||
assert _norm_out(out) == b"f1:1:hello'hi\n"
|
||||
|
||||
|
||||
def test_grep_hook_case_insensitive(greppable_files, store):
|
||||
hook = _make_grep_repo('ELLO', store, args=['-i'])
|
||||
ret, out = _hook_run(hook, ('f1', 'f2', 'f3'), color=False)
|
||||
assert ret == 1
|
||||
assert _norm_out(out) == b"f1:1:hello'hi\n"
|
||||
|
||||
|
||||
@pytest.mark.parametrize('regex', ('nope', "foo'bar", r'^\[INFO\]'))
|
||||
def test_grep_hook_not_matching(regex, greppable_files, store):
|
||||
hook = _make_grep_repo(regex, store)
|
||||
ret, out = _hook_run(hook, ('f1', 'f2', 'f3'), color=False)
|
||||
assert (ret, out) == (0, b'')
|
||||
|
||||
|
||||
def _norm_pwd(path):
|
||||
# Under windows bash's temp and windows temp is different.
|
||||
# This normalizes to the bash /tmp
|
||||
|
@ -440,7 +258,7 @@ def test_repository_state_compatibility(tempdir_factory, store, v):
|
|||
|
||||
config = make_config_from_repo(path)
|
||||
hook = _get_hook(config, store, 'foo')
|
||||
envdir = helpers.environment_dir(
|
||||
envdir = lang_base.environment_dir(
|
||||
hook.prefix,
|
||||
python.ENVIRONMENT_DIR,
|
||||
hook.language_version,
|
||||
|
@ -449,67 +267,6 @@ def test_repository_state_compatibility(tempdir_factory, store, v):
|
|||
assert _hook_installed(hook) is True
|
||||
|
||||
|
||||
def test_additional_golang_dependencies_installed(
|
||||
tempdir_factory, store,
|
||||
):
|
||||
path = make_repo(tempdir_factory, 'golang_hooks_repo')
|
||||
config = make_config_from_repo(path)
|
||||
# A small go package
|
||||
deps = ['golang.org/x/example/hello@latest']
|
||||
config['hooks'][0]['additional_dependencies'] = deps
|
||||
hook = _get_hook(config, store, 'golang-hook')
|
||||
envdir = helpers.environment_dir(
|
||||
hook.prefix,
|
||||
golang.ENVIRONMENT_DIR,
|
||||
golang.get_default_version(),
|
||||
)
|
||||
binaries = os.listdir(os.path.join(envdir, 'bin'))
|
||||
# normalize for windows
|
||||
binaries = [os.path.splitext(binary)[0] for binary in binaries]
|
||||
assert 'hello' in binaries
|
||||
|
||||
|
||||
def test_local_golang_additional_dependencies(store):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'hello',
|
||||
'name': 'hello',
|
||||
'entry': 'hello',
|
||||
'language': 'golang',
|
||||
'additional_dependencies': ['golang.org/x/example/hello@latest'],
|
||||
}],
|
||||
}
|
||||
hook = _get_hook(config, store, 'hello')
|
||||
ret, out = _hook_run(hook, (), color=False)
|
||||
assert ret == 0
|
||||
assert _norm_out(out) == b'Hello, Go examples!\n'
|
||||
|
||||
|
||||
def test_fail_hooks(store):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'fail',
|
||||
'name': 'fail',
|
||||
'language': 'fail',
|
||||
'entry': 'make sure to name changelogs as .rst!',
|
||||
'files': r'changelog/.*(?<!\.rst)$',
|
||||
}],
|
||||
}
|
||||
hook = _get_hook(config, store, 'fail')
|
||||
ret, out = _hook_run(
|
||||
hook, ('changelog/123.bugfix', 'changelog/wat'), color=False,
|
||||
)
|
||||
assert ret == 1
|
||||
assert out == (
|
||||
b'make sure to name changelogs as .rst!\n'
|
||||
b'\n'
|
||||
b'changelog/123.bugfix\n'
|
||||
b'changelog/wat\n'
|
||||
)
|
||||
|
||||
|
||||
def test_unknown_keys(store, caplog):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
|
@ -553,7 +310,7 @@ def test_control_c_control_c_on_install(tempdir_factory, store):
|
|||
# raise as well.
|
||||
with pytest.raises(MyKeyboardInterrupt):
|
||||
with mock.patch.object(
|
||||
helpers, 'run_setup_cmd', side_effect=MyKeyboardInterrupt,
|
||||
lang_base, 'setup_cmd', side_effect=MyKeyboardInterrupt,
|
||||
):
|
||||
with mock.patch.object(
|
||||
shutil, 'rmtree', side_effect=MyKeyboardInterrupt,
|
||||
|
@ -562,7 +319,7 @@ def test_control_c_control_c_on_install(tempdir_factory, store):
|
|||
|
||||
# Should have made an environment, however this environment is broken!
|
||||
hook, = hooks
|
||||
envdir = helpers.environment_dir(
|
||||
envdir = lang_base.environment_dir(
|
||||
hook.prefix,
|
||||
python.ENVIRONMENT_DIR,
|
||||
hook.language_version,
|
||||
|
@ -585,7 +342,7 @@ def test_invalidated_virtualenv(tempdir_factory, store):
|
|||
hook = _get_hook(config, store, 'foo')
|
||||
|
||||
# Simulate breaking of the virtualenv
|
||||
envdir = helpers.environment_dir(
|
||||
envdir = lang_base.environment_dir(
|
||||
hook.prefix,
|
||||
python.ENVIRONMENT_DIR,
|
||||
hook.language_version,
|
||||
|
@ -667,7 +424,7 @@ def test_local_python_repo(store, local_python_config):
|
|||
assert hook.language_version != C.DEFAULT
|
||||
ret, out = _hook_run(hook, ('filename',), color=False)
|
||||
assert ret == 0
|
||||
assert _norm_out(out) == b"['filename']\nHello World\n"
|
||||
assert out == b"['filename']\nHello World\n"
|
||||
|
||||
|
||||
def test_default_language_version(store, local_python_config):
|
||||
|
@ -781,22 +538,6 @@ def test_manifest_hooks(tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'repo',
|
||||
(
|
||||
'dotnet_hooks_csproj_repo',
|
||||
'dotnet_hooks_sln_repo',
|
||||
'dotnet_hooks_combo_repo',
|
||||
'dotnet_hooks_csproj_prefix_repo',
|
||||
),
|
||||
)
|
||||
def test_dotnet_hook(tempdir_factory, store, repo):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, repo,
|
||||
'dotnet-example-hook', [], b'Hello from dotnet!\n',
|
||||
)
|
||||
|
||||
|
||||
def test_non_installable_hook_error_for_language_version(store, caplog):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import itertools
|
||||
import os.path
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
import re_assert
|
||||
|
||||
from pre_commit import git
|
||||
from pre_commit.errors import FatalError
|
||||
from pre_commit.staged_files_only import staged_files_only
|
||||
from pre_commit.util import cmd_output
|
||||
from testing.auto_namedtuple import auto_namedtuple
|
||||
|
@ -14,6 +17,7 @@ from testing.fixtures import git_dir
|
|||
from testing.util import cwd
|
||||
from testing.util import get_resource_path
|
||||
from testing.util import git_commit
|
||||
from testing.util import xfailif_windows
|
||||
|
||||
|
||||
FOO_CONTENTS = '\n'.join(('1', '2', '3', '4', '5', '6', '7', '8', ''))
|
||||
|
@ -382,3 +386,49 @@ def test_intent_to_add(in_git_dir, patch_dir):
|
|||
with staged_files_only(patch_dir):
|
||||
assert_no_diff()
|
||||
assert git.intent_to_add_files() == ['foo']
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _unreadable(f):
|
||||
orig = os.stat(f).st_mode
|
||||
os.chmod(f, 0o000)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.chmod(f, orig)
|
||||
|
||||
|
||||
@xfailif_windows # pragma: win32 no cover
|
||||
def test_failed_diff_does_not_discard_changes(in_git_dir, patch_dir):
|
||||
# stage 3 files
|
||||
for i in range(3):
|
||||
with open(str(i), 'w') as f:
|
||||
f.write(str(i))
|
||||
cmd_output('git', 'add', '0', '1', '2')
|
||||
|
||||
# modify all of their contents
|
||||
for i in range(3):
|
||||
with open(str(i), 'w') as f:
|
||||
f.write('new contents')
|
||||
|
||||
with _unreadable('1'):
|
||||
with pytest.raises(FatalError) as excinfo:
|
||||
with staged_files_only(patch_dir):
|
||||
raise AssertionError('should have errored on enter')
|
||||
|
||||
# the diff command failed to produce a diff of `1`
|
||||
msg, = excinfo.value.args
|
||||
re_assert.Matches(
|
||||
r'^pre-commit failed to diff -- perhaps due to permissions\?\n\n'
|
||||
r'command: .*\n'
|
||||
r'return code: 128\n'
|
||||
r'stdout: \(none\)\n'
|
||||
r'stderr:\n'
|
||||
r' error: open\("1"\): Permission denied\n'
|
||||
r' fatal: cannot hash 1$',
|
||||
).assert_matches(msg)
|
||||
|
||||
# even though it errored, the unstaged changes should still be present
|
||||
for i in range(3):
|
||||
with open(str(i)) as f:
|
||||
assert f.read() == 'new contents'
|
||||
|
|
|
@ -180,7 +180,7 @@ def test_create_when_store_already_exists(store):
|
|||
|
||||
def test_db_repo_name(store):
|
||||
assert store.db_repo_name('repo', ()) == 'repo'
|
||||
assert store.db_repo_name('repo', ('b', 'a', 'c')) == 'repo:a,b,c'
|
||||
assert store.db_repo_name('repo', ('b', 'a', 'c')) == 'repo:b,a,c'
|
||||
|
||||
|
||||
def test_local_resources_reflects_reality():
|
||||
|
@ -246,3 +246,27 @@ def test_mark_config_as_used_readonly(tmpdir):
|
|||
# should be skipped due to readonly
|
||||
store.mark_config_used(str(cfg))
|
||||
assert store.select_all_configs() == []
|
||||
|
||||
|
||||
def test_clone_with_recursive_submodules(store, tmp_path):
|
||||
sub = tmp_path.joinpath('sub')
|
||||
sub.mkdir()
|
||||
sub.joinpath('submodule').write_text('i am a submodule')
|
||||
cmd_output('git', '-C', str(sub), 'init', '.')
|
||||
cmd_output('git', '-C', str(sub), 'add', '.')
|
||||
git.commit(str(sub))
|
||||
|
||||
repo = tmp_path.joinpath('repo')
|
||||
repo.mkdir()
|
||||
repo.joinpath('repository').write_text('i am a repo')
|
||||
cmd_output('git', '-C', str(repo), 'init', '.')
|
||||
cmd_output('git', '-C', str(repo), 'add', '.')
|
||||
cmd_output('git', '-C', str(repo), 'submodule', 'add', str(sub), 'sub')
|
||||
git.commit(str(repo))
|
||||
|
||||
rev = git.head_rev(str(repo))
|
||||
ret = store.clone(str(repo), rev)
|
||||
|
||||
assert os.path.exists(ret)
|
||||
assert os.path.exists(os.path.join(ret, str(repo), 'repository'))
|
||||
assert os.path.exists(os.path.join(ret, str(sub), 'submodule'))
|
||||
|
|
|
@ -16,7 +16,7 @@ from pre_commit.util import rmtree
|
|||
|
||||
|
||||
def test_CalledProcessError_str():
|
||||
error = CalledProcessError(1, ('exe',), b'output', b'errors')
|
||||
error = CalledProcessError(1, ('exe',), b'output\n', b'errors\n')
|
||||
assert str(error) == (
|
||||
"command: ('exe',)\n"
|
||||
'return code: 1\n'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue