diff --git a/pre_commit/repository.py b/pre_commit/repository.py index 1d046911..4c045c8c 100644 --- a/pre_commit/repository.py +++ b/pre_commit/repository.py @@ -61,7 +61,16 @@ class Repository(object): @cached_property def hooks(self): - # TODO: merging in manifest dicts is a smell imo + for hook in self.repo_config['hooks']: + if hook['id'] not in self.manifest.hooks: + logger.error( + '`{0}` is not present in repository {1}. ' + 'Typo? Perhaps it is introduced in a newer version? ' + 'Often `pre-commit autoupdate` fixes this.'.format( + hook['id'], self.repo_config['repo'], + ) + ) + exit(1) return tuple( (hook['id'], dict(self.manifest.hooks[hook['id']], **hook)) for hook in self.repo_config['hooks'] diff --git a/tests/repository_test.py b/tests/repository_test.py index c6aa1d7b..bb88c87f 100644 --- a/tests/repository_test.py +++ b/tests/repository_test.py @@ -2,6 +2,7 @@ from __future__ import absolute_import from __future__ import unicode_literals import io +import logging import os import os.path import shutil @@ -485,3 +486,26 @@ def test_local_repository(): with pytest.raises(NotImplementedError): local_repo.manifest assert len(local_repo.hooks) == 1 + + +@pytest.yield_fixture +def fake_log_handler(): + handler = mock.Mock(level=logging.INFO) + logger = logging.getLogger('pre_commit') + logger.addHandler(handler) + yield handler + logger.removeHandler(handler) + + +def test_hook_id_not_present(tempdir_factory, store, fake_log_handler): + path = make_repo(tempdir_factory, 'script_hooks_repo') + config = make_config_from_repo(path) + config['hooks'][0]['id'] = 'i-dont-exist' + repo = Repository.create(config, store) + with pytest.raises(SystemExit): + repo.install() + assert fake_log_handler.handle.call_args[0][0].msg == ( + '`i-dont-exist` is not present in repository {0}. ' + 'Typo? Perhaps it is introduced in a newer version? ' + 'Often `pre-commit autoupdate` fixes this.'.format(path) + )