diff --git a/pre_commit/clientlib/validate_config.py b/pre_commit/clientlib/validate_config.py index 1da54f91..8991850e 100644 --- a/pre_commit/clientlib/validate_config.py +++ b/pre_commit/clientlib/validate_config.py @@ -32,6 +32,7 @@ CONFIG_JSON_SCHEMA = { 'type': 'object', 'properties': { 'id': {'type': 'string'}, + 'always_run': {'type': 'boolean'}, 'files': {'type': 'string'}, 'exclude': {'type': 'string'}, 'language_version': {'type': 'string'}, diff --git a/pre_commit/clientlib/validate_manifest.py b/pre_commit/clientlib/validate_manifest.py index 094c8e5d..d11ce2b8 100644 --- a/pre_commit/clientlib/validate_manifest.py +++ b/pre_commit/clientlib/validate_manifest.py @@ -17,6 +17,7 @@ MANIFEST_JSON_SCHEMA = { 'type': 'object', 'properties': { 'id': {'type': 'string'}, + 'always_run': {'type': 'boolean', 'default': False}, 'name': {'type': 'string'}, 'description': {'type': 'string', 'default': ''}, 'entry': {'type': 'string'}, diff --git a/pre_commit/commands/run.py b/pre_commit/commands/run.py index e01c7f9f..f45e7089 100644 --- a/pre_commit/commands/run.py +++ b/pre_commit/commands/run.py @@ -76,7 +76,7 @@ def _run_single_hook(hook, repo, args, write, skips=frozenset()): if hook['id'] in skips: _print_user_skipped(hook, write, args) return 0 - elif not filenames: + elif not filenames and not hook['always_run']: _print_no_files_skipped(hook, write, args) return 0 diff --git a/tests/commands/run_test.py b/tests/commands/run_test.py index 120dce2a..a0795f28 100644 --- a/tests/commands/run_test.py +++ b/tests/commands/run_test.py @@ -184,6 +184,12 @@ def test_run( _test_run(repo_with_passing_hook, options, outputs, expected_ret, stage) +def test_always_run(repo_with_passing_hook, mock_out_store_directory): + with modify_config() as config: + config[0]['hooks'][0]['always_run'] = True + _test_run(repo_with_passing_hook, {}, (b'Bash hook', b'Passed'), 0, False) + + @pytest.mark.parametrize( ('origin', 'source', 'expect_failure'), ( diff --git a/tests/manifest_test.py b/tests/manifest_test.py index f28862ae..174f201f 100644 --- a/tests/manifest_test.py +++ b/tests/manifest_test.py @@ -19,6 +19,7 @@ def manifest(store, tempdir_factory): def test_manifest_contents(manifest): # Should just retrieve the manifest contents assert manifest.manifest_contents == [{ + 'always_run': False, 'args': [], 'description': '', 'entry': 'bin/hook.sh', @@ -35,6 +36,7 @@ def test_manifest_contents(manifest): def test_hooks(manifest): assert manifest.hooks['bash_hook'] == { + 'always_run': False, 'args': [], 'description': '', 'entry': 'bin/hook.sh',