summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/clientlib_test.py97
-rw-r--r--tests/commands/run_test.py1
-rw-r--r--tests/conftest.py9
-rw-r--r--tests/git_test.py20
-rw-r--r--tests/main_test.py5
-rw-r--r--tests/repository_test.py65
6 files changed, 173 insertions, 24 deletions
diff --git a/tests/clientlib_test.py b/tests/clientlib_test.py
index bfb754b..6bdb0d6 100644
--- a/tests/clientlib_test.py
+++ b/tests/clientlib_test.py
@@ -166,7 +166,85 @@ def test_validate_warn_on_unknown_keys_at_top_level(tmpdir, caplog):
]
-def test_validate_optional_sensible_regex(caplog):
+def test_ci_map_key_allowed_at_top_level(caplog):
+ cfg = {
+ 'ci': {'skip': ['foo']},
+ 'repos': [{'repo': 'meta', 'hooks': [{'id': 'identity'}]}],
+ }
+ cfgv.validate(cfg, CONFIG_SCHEMA)
+ assert not caplog.record_tuples
+
+
+def test_ci_key_must_be_map():
+ with pytest.raises(cfgv.ValidationError):
+ cfgv.validate({'ci': 'invalid', 'repos': []}, CONFIG_SCHEMA)
+
+
+@pytest.mark.parametrize(
+ 'rev',
+ (
+ 'v0.12.4',
+ 'b27f281',
+ 'b27f281eb9398fc8504415d7fbdabf119ea8c5e1',
+ '19.10b0',
+ '4.3.21-2',
+ ),
+)
+def test_warn_mutable_rev_ok(caplog, rev):
+ config_obj = {
+ 'repo': 'https://gitlab.com/pycqa/flake8',
+ 'rev': rev,
+ 'hooks': [{'id': 'flake8'}],
+ }
+ cfgv.validate(config_obj, CONFIG_REPO_DICT)
+
+ assert caplog.record_tuples == []
+
+
+@pytest.mark.parametrize(
+ 'rev',
+ (
+ '',
+ 'HEAD',
+ 'stable',
+ 'master',
+ 'some_branch_name',
+ ),
+)
+def test_warn_mutable_rev_invalid(caplog, rev):
+ config_obj = {
+ 'repo': 'https://gitlab.com/pycqa/flake8',
+ 'rev': rev,
+ 'hooks': [{'id': 'flake8'}],
+ }
+ cfgv.validate(config_obj, CONFIG_REPO_DICT)
+
+ assert caplog.record_tuples == [
+ (
+ 'pre_commit',
+ logging.WARNING,
+ "The 'rev' field of repo 'https://gitlab.com/pycqa/flake8' "
+ 'appears to be a mutable reference (moving tag / branch). '
+ 'Mutable references are never updated after first install and are '
+ 'not supported. '
+ 'See https://pre-commit.com/#using-the-latest-version-for-a-repository ' # noqa: E501
+ 'for more details.',
+ ),
+ ]
+
+
+def test_warn_mutable_rev_conditional():
+ config_obj = {
+ 'repo': 'meta',
+ 'rev': '3.7.7',
+ 'hooks': [{'id': 'flake8'}],
+ }
+
+ with pytest.raises(cfgv.ValidationError):
+ cfgv.validate(config_obj, CONFIG_REPO_DICT)
+
+
+def test_validate_optional_sensible_regex_at_hook_level(caplog):
config_obj = {
'id': 'flake8',
'files': 'dir/*.py',
@@ -183,6 +261,23 @@ def test_validate_optional_sensible_regex(caplog):
]
+def test_validate_optional_sensible_regex_at_top_level(caplog):
+ config_obj = {
+ 'files': 'dir/*.py',
+ 'repos': [],
+ }
+ cfgv.validate(config_obj, CONFIG_SCHEMA)
+
+ assert caplog.record_tuples == [
+ (
+ 'pre_commit',
+ logging.WARNING,
+ "The top-level 'files' field is a regex, not a glob -- matching "
+ "'/*' probably isn't what you want here",
+ ),
+ ]
+
+
@pytest.mark.parametrize('fn', (validate_config_main, validate_manifest_main))
def test_mains_not_ok(tmpdir, fn):
not_yaml = tmpdir.join('f.notyaml')
diff --git a/tests/commands/run_test.py b/tests/commands/run_test.py
index 914d567..eaea813 100644
--- a/tests/commands/run_test.py
+++ b/tests/commands/run_test.py
@@ -486,6 +486,7 @@ def test_from_ref_to_ref_error_msg_error(
def test_all_push_options_ok(cap_out, store, repo_with_passing_hook):
args = run_opts(
from_ref='master', to_ref='master',
+ remote_branch='master',
remote_name='origin', remote_url='https://example.com/repo',
)
ret, printed = _do_run(cap_out, store, repo_with_passing_hook, args)
diff --git a/tests/conftest.py b/tests/conftest.py
index 335d261..b36ce5a 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -261,15 +261,6 @@ def cap_out():
yield Fixture(stream)
-@pytest.fixture
-def fake_log_handler():
- handler = mock.Mock(level=logging.INFO)
- logger = logging.getLogger('pre_commit')
- logger.addHandler(handler)
- yield handler
- logger.removeHandler(handler)
-
-
@pytest.fixture(scope='session', autouse=True)
def set_git_templatedir(tmpdir_factory):
tdir = str(tmpdir_factory.mktemp('git_template_dir'))
diff --git a/tests/git_test.py b/tests/git_test.py
index fafd4a6..69fd206 100644
--- a/tests/git_test.py
+++ b/tests/git_test.py
@@ -3,6 +3,7 @@ import os.path
import pytest
from pre_commit import git
+from pre_commit.error_handler import FatalError
from pre_commit.util import cmd_output
from testing.util import git_commit
@@ -18,6 +19,25 @@ def test_get_root_deeper(in_git_dir):
assert os.path.normcase(git.get_root()) == expected
+def test_in_exactly_dot_git(in_git_dir):
+ with in_git_dir.join('.git').as_cwd(), pytest.raises(FatalError):
+ git.get_root()
+
+
+def test_get_root_bare_worktree(tmpdir):
+ src = tmpdir.join('src').ensure_dir()
+ cmd_output('git', 'init', str(src))
+ git_commit(cwd=str(src))
+
+ bare = tmpdir.join('bare.git').ensure_dir()
+ cmd_output('git', 'clone', '--bare', str(src), str(bare))
+
+ cmd_output('git', 'worktree', 'add', 'foo', 'HEAD', cwd=bare)
+
+ with bare.join('foo').as_cwd():
+ assert git.get_root() == os.path.abspath('.')
+
+
def test_get_staged_files_deleted(in_git_dir):
in_git_dir.join('test').ensure()
cmd_output('git', 'add', 'test')
diff --git a/tests/main_test.py b/tests/main_test.py
index 6738df6..2460bd8 100644
--- a/tests/main_test.py
+++ b/tests/main_test.py
@@ -35,11 +35,6 @@ def test_adjust_args_and_chdir_not_in_git_dir(in_tmpdir):
main._adjust_args_and_chdir(_args())
-def test_adjust_args_and_chdir_in_dot_git_dir(in_git_dir):
- with in_git_dir.join('.git').as_cwd(), pytest.raises(FatalError):
- main._adjust_args_and_chdir(_args())
-
-
def test_adjust_args_and_chdir_noop(in_git_dir):
args = _args(command='run', files=['f1', 'f2'])
main._adjust_args_and_chdir(args)
diff --git a/tests/repository_test.py b/tests/repository_test.py
index d513cb7..8540db3 100644
--- a/tests/repository_test.py
+++ b/tests/repository_test.py
@@ -569,7 +569,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 = ['github.com/golang/example/hello']
+ deps = ['golang.org/x/example/hello']
config['hooks'][0]['additional_dependencies'] = deps
hook = _get_hook(config, store, 'golang-hook')
binaries = os.listdir(
@@ -590,7 +590,7 @@ def test_local_golang_additional_dependencies(store):
'name': 'hello',
'entry': 'hello',
'language': 'golang',
- 'additional_dependencies': ['github.com/golang/example/hello'],
+ 'additional_dependencies': ['golang.org/x/example/hello'],
}],
}
hook = _get_hook(config, store, 'hello')
@@ -640,7 +640,7 @@ def test_fail_hooks(store):
)
-def test_unknown_keys(store, fake_log_handler):
+def test_unknown_keys(store, caplog):
config = {
'repo': 'local',
'hooks': [{
@@ -653,8 +653,8 @@ def test_unknown_keys(store, fake_log_handler):
}],
}
_get_hook(config, store, 'too-much')
- expected = 'Unexpected key(s) present on local => too-much: foo, hello'
- assert fake_log_handler.handle.call_args[0][0].msg == expected
+ msg, = caplog.messages
+ assert msg == 'Unexpected key(s) present on local => too-much: foo, hello'
def test_reinstall(tempdir_factory, store, log_info_mock):
@@ -832,27 +832,28 @@ def test_default_stages(store, local_python_config):
assert hook.stages == ['push']
-def test_hook_id_not_present(tempdir_factory, store, fake_log_handler):
+def test_hook_id_not_present(tempdir_factory, store, caplog):
path = make_repo(tempdir_factory, 'script_hooks_repo')
config = make_config_from_repo(path)
config['hooks'][0]['id'] = 'i-dont-exist'
with pytest.raises(SystemExit):
_get_hook(config, store, 'i-dont-exist')
- assert fake_log_handler.handle.call_args[0][0].msg == (
+ _, msg = caplog.messages
+ assert msg == (
f'`i-dont-exist` is not present in repository file://{path}. '
f'Typo? Perhaps it is introduced in a newer version? '
f'Often `pre-commit autoupdate` fixes this.'
)
-def test_too_new_version(tempdir_factory, store, fake_log_handler):
+def test_too_new_version(tempdir_factory, store, caplog):
path = make_repo(tempdir_factory, 'script_hooks_repo')
with modify_manifest(path) as manifest:
manifest[0]['minimum_pre_commit_version'] = '999.0.0'
config = make_config_from_repo(path)
with pytest.raises(SystemExit):
_get_hook(config, store, 'bash_hook')
- msg = fake_log_handler.handle.call_args[0][0].msg
+ _, msg = caplog.messages
pattern = re_assert.Matches(
r'^The hook `bash_hook` requires pre-commit version 999\.0\.0 but '
r'version \d+\.\d+\.\d+ is installed. '
@@ -942,3 +943,49 @@ def test_dotnet_hook(tempdir_factory, store, 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',
+ 'hooks': [{
+ 'id': 'system-hook',
+ 'name': 'system-hook',
+ 'language': 'system',
+ 'entry': 'python3 -c "import sys; print(sys.version)"',
+ 'language_version': 'python3.10',
+ }],
+ }
+ with pytest.raises(SystemExit) as excinfo:
+ _get_hook(config, store, 'system-hook')
+ assert excinfo.value.code == 1
+
+ msg, = caplog.messages
+ assert msg == (
+ 'The hook `system-hook` specifies `language_version` but is using '
+ 'language `system` which does not install an environment. '
+ 'Perhaps you meant to use a specific language?'
+ )
+
+
+def test_non_installable_hook_error_for_additional_dependencies(store, caplog):
+ config = {
+ 'repo': 'local',
+ 'hooks': [{
+ 'id': 'system-hook',
+ 'name': 'system-hook',
+ 'language': 'system',
+ 'entry': 'python3 -c "import sys; print(sys.version)"',
+ 'additional_dependencies': ['astpretty'],
+ }],
+ }
+ with pytest.raises(SystemExit) as excinfo:
+ _get_hook(config, store, 'system-hook')
+ assert excinfo.value.code == 1
+
+ msg, = caplog.messages
+ assert msg == (
+ 'The hook `system-hook` specifies `additional_dependencies` but is '
+ 'using language `system` which does not install an environment. '
+ 'Perhaps you meant to use a specific language?'
+ )