Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pre_commit/clientlib/validate_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class InvalidManifestError(ValueError):
'exclude': {'type': 'string', 'default': '^$'},
'language': {'type': 'string'},
'language_version': {'type': 'string', 'default': 'default'},
'minimum_pre_commit_version': {
'type': 'string', 'default': '0.0.0',
},
'files': {'type': 'string'},
'stages': {
'type': 'array',
Expand Down
17 changes: 17 additions & 0 deletions pre_commit/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import shutil
from collections import defaultdict

import pkg_resources
from cached_property import cached_property

from pre_commit import git
Expand All @@ -18,6 +19,10 @@

logger = logging.getLogger('pre_commit')

_pre_commit_version = pkg_resources.parse_version(
pkg_resources.get_distribution('pre-commit').version
)


class Repository(object):
def __init__(self, repo_config, repo_path_getter):
Expand Down Expand Up @@ -71,6 +76,18 @@ def hooks(self):
)
)
exit(1)
hook_version = pkg_resources.parse_version(
self.manifest.hooks[hook['id']]['minimum_pre_commit_version'],
)
if hook_version > _pre_commit_version:
logger.error(
'The hook `{0}` requires pre-commit version {1} but '
'version {2} is installed. '
'Perhaps run `pip install --upgrade pre-commit`.'.format(
hook['id'], hook_version, _pre_commit_version,
)
)
exit(1)
return tuple(
(hook['id'], dict(self.manifest.hooks[hook['id']], **hook))
for hook in self.repo_config['hooks']
Expand Down
13 changes: 13 additions & 0 deletions testing/fixtures.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from __future__ import absolute_import
from __future__ import unicode_literals

import contextlib
import io
import os.path

from aspy.yaml import ordered_dump
from aspy.yaml import ordered_load

import pre_commit.constants as C
from pre_commit.clientlib.validate_config import CONFIG_JSON_SCHEMA
Expand Down Expand Up @@ -35,6 +37,17 @@ def make_repo(tempdir_factory, repo_source):
return path


@contextlib.contextmanager
def modify_manifest(path):
"""Modify the manifest yielded by this context to write to hooks.yaml."""
manifest_path = os.path.join(path, C.MANIFEST_FILE)
manifest = ordered_load(io.open(manifest_path).read())
yield manifest
with io.open(manifest_path, 'w') as manifest_file:
manifest_file.write(ordered_dump(manifest, **C.YAML_DUMP_KWARGS))
cmd_output('git', 'commit', '-am', 'update hooks.yaml', cwd=path)


def config_with_local_hooks():
return OrderedDict((
('repo', 'local'),
Expand Down
2 changes: 2 additions & 0 deletions tests/manifest_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def test_manifest_contents(manifest):
'id': 'bash_hook',
'language': 'script',
'language_version': 'default',
'minimum_pre_commit_version': '0.0.0',
'name': 'Bash hook',
'stages': [],
}]
Expand All @@ -42,6 +43,7 @@ def test_hooks(manifest):
'id': 'bash_hook',
'language': 'script',
'language_version': 'default',
'minimum_pre_commit_version': '0.0.0',
'name': 'Bash hook',
'stages': [],
}
33 changes: 33 additions & 0 deletions tests/repository_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import logging
import os
import os.path
import re
import shutil

import mock
import pkg_resources
import pytest

from pre_commit import five
Expand All @@ -24,6 +26,7 @@
from testing.fixtures import git_dir
from testing.fixtures import make_config_from_repo
from testing.fixtures import make_repo
from testing.fixtures import modify_manifest
from testing.util import skipif_slowtests_false
from testing.util import xfailif_no_pcre_support
from testing.util import xfailif_windows_no_node
Expand Down Expand Up @@ -525,3 +528,33 @@ def test_hook_id_not_present(tempdir_factory, store, fake_log_handler):
'Typo? Perhaps it is introduced in a newer version? '
'Often `pre-commit autoupdate` fixes this.'.format(path)
)


def test_too_new_version(tempdir_factory, store, fake_log_handler):
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)
repo = Repository.create(config, store)
with pytest.raises(SystemExit):
repo.install()
msg = fake_log_handler.handle.call_args[0][0].msg
assert re.match(
r'^The hook `bash_hook` requires pre-commit version 999\.0\.0 but '
r'version \d+\.\d+\.\d+ is installed. '
r'Perhaps run `pip install --upgrade pre-commit`\.$',
msg,
)


@pytest.mark.parametrize(
'version',
('0.1.0', pkg_resources.get_distribution('pre-commit').version),
)
def test_versions_ok(tempdir_factory, store, version):
path = make_repo(tempdir_factory, 'script_hooks_repo')
with modify_manifest(path) as manifest:
manifest[0]['minimum_pre_commit_version'] = version
config = make_config_from_repo(path)
# Should succeed
Repository.create(config, store).install()