diff --git a/pre_commit/clientlib.py b/pre_commit/clientlib.py index f6f86191..4570e107 100644 --- a/pre_commit/clientlib.py +++ b/pre_commit/clientlib.py @@ -35,10 +35,7 @@ MANIFEST_HOOK_DICT = cfgv.Map( cfgv.Required('id', cfgv.check_string), cfgv.Required('name', cfgv.check_string), cfgv.Required('entry', cfgv.check_string), - cfgv.Required( - 'language', - cfgv.check_and(cfgv.check_string, cfgv.check_one_of(all_languages)), - ), + cfgv.Required('language', cfgv.check_one_of(all_languages)), cfgv.Optional( 'files', cfgv.check_and(cfgv.check_string, cfgv.check_regex), '', @@ -59,7 +56,7 @@ MANIFEST_HOOK_DICT = cfgv.Map( cfgv.Optional('language_version', cfgv.check_string, 'default'), cfgv.Optional('log_file', cfgv.check_string, ''), cfgv.Optional('minimum_pre_commit_version', cfgv.check_string, '0'), - cfgv.Optional('stages', cfgv.check_array(cfgv.check_string), []), + cfgv.Optional('stages', cfgv.check_array(cfgv.check_one_of(C.STAGES)), []), cfgv.Optional('verbose', cfgv.check_bool, False), ) MANIFEST_SCHEMA = cfgv.Array(MANIFEST_HOOK_DICT) diff --git a/pre_commit/constants.py b/pre_commit/constants.py index 2fa43552..48ba2cb9 100644 --- a/pre_commit/constants.py +++ b/pre_commit/constants.py @@ -20,3 +20,6 @@ LOCAL_REPO_VERSION = '1' VERSION = pkg_resources.get_distribution('pre-commit').version VERSION_PARSED = pkg_resources.parse_version(VERSION) + +# `manual` is not invoked by any installed git hook. See #719 +STAGES = ('commit', 'commit-msg', 'manual', 'push') diff --git a/pre_commit/main.py b/pre_commit/main.py index 92677147..18db533a 100644 --- a/pre_commit/main.py +++ b/pre_commit/main.py @@ -70,9 +70,8 @@ def _add_run_options(parser): help='Filename to check when running during `commit-msg`', ) parser.add_argument( - '--hook-stage', choices=('commit', 'push', 'commit-msg'), - default='commit', - help='The stage during which the hook is fired e.g. commit or push.', + '--hook-stage', choices=C.STAGES, default='commit', + help='The stage during which the hook is fired. One of %(choices)s', ) parser.add_argument( '--show-diff-on-failure', action='store_true', diff --git a/tests/commands/run_test.py b/tests/commands/run_test.py index 931ad4a1..4df65117 100644 --- a/tests/commands/run_test.py +++ b/tests/commands/run_test.py @@ -529,52 +529,37 @@ def test_lots_of_files(mock_out_store_directory, tempdir_factory): ) -def test_push_hook(cap_out, repo_with_passing_hook, mock_out_store_directory): +def test_stages(cap_out, repo_with_passing_hook, mock_out_store_directory): config = OrderedDict(( ('repo', 'local'), ( - 'hooks', ( - OrderedDict(( - ('id', 'flake8'), - ('name', 'hook 1'), - ('entry', "'{}' -m flake8".format(sys.executable)), - ('language', 'system'), - ('types', ['python']), - ('stages', ['commit']), - )), - OrderedDict(( - ('id', 'do_not_commit'), - ('name', 'hook 2'), - ('entry', 'DO NOT COMMIT'), - ('language', 'pygrep'), - ('types', ['text']), - ('stages', ['push']), - )), + 'hooks', tuple( + { + 'id': 'do-not-commit-{}'.format(i), + 'name': 'hook {}'.format(i), + 'entry': 'DO NOT COMMIT', + 'language': 'pygrep', + 'stages': [stage], + } + for i, stage in enumerate(('commit', 'push', 'manual'), 1) ), ), )) add_config_to_repo(repo_with_passing_hook, config) - open('dummy.py', 'a').close() - cmd_output('git', 'add', 'dummy.py') + stage_a_file() - _test_run( - cap_out, - repo_with_passing_hook, - {'hook_stage': 'commit'}, - expected_outputs=[b'hook 1'], - expected_ret=0, - stage=False, - ) + def _run_for_stage(stage): + args = run_opts(hook_stage=stage) + ret, printed = _do_run(cap_out, repo_with_passing_hook, args) + assert not ret, (ret, printed) + # this test should only run one hook + assert printed.count(b'hook ') == 1 + return printed - _test_run( - cap_out, - repo_with_passing_hook, - {'hook_stage': 'push'}, - expected_outputs=[b'hook 2'], - expected_ret=0, - stage=False, - ) + assert _run_for_stage('commit').startswith(b'hook 1...') + assert _run_for_stage('push').startswith(b'hook 2...') + assert _run_for_stage('manual').startswith(b'hook 3...') def test_commit_msg_hook(cap_out, commit_msg_repo, mock_out_store_directory): diff --git a/tests/conftest.py b/tests/conftest.py index 678010f5..2d27a4a4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -180,7 +180,8 @@ class Fixture(object): def get_bytes(self): """Get the output as-if no encoding occurred""" data = self._stream.data.getvalue() - self._stream.data.truncate(0) + self._stream.data.seek(0) + self._stream.data.truncate() return data def get(self):