From 5a08204b8d99debd836b909bb883f129baa811f5 Mon Sep 17 00:00:00 2001 From: Laurent Sigal Date: Tue, 22 Dec 2015 17:55:04 +0000 Subject: [PATCH 1/4] Allow to simply run a script once - no matter what the changes are --- pre_commit/clientlib/validate_config.py | 1 + pre_commit/clientlib/validate_manifest.py | 1 + pre_commit/commands/run.py | 14 ++++++++++---- 3 files changed, 12 insertions(+), 4 deletions(-) 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..2b7148fd 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'}, '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..82e494dd 100644 --- a/pre_commit/commands/run.py +++ b/pre_commit/commands/run.py @@ -72,13 +72,19 @@ def get_filenames(args, include_expr, exclude_expr): def _run_single_hook(hook, repo, args, write, skips=frozenset()): - filenames = get_filenames(args, hook['files'], hook['exclude']) + filenames = [] + # if the hook is marked as always_run, do not compute the files to run + # in that case, simply run the script once not matter the changes + compute_file_names = 'always_run' not in hook or not hook['always_run'] + if hook['id'] in skips: _print_user_skipped(hook, write, args) return 0 - elif not filenames: - _print_no_files_skipped(hook, write, args) - return 0 + elif compute_file_names: + filenames = get_filenames(args, hook['files'], hook['exclude']) + if not filenames: + _print_no_files_skipped(hook, write, args) + return 0 # Print the hook and the dots first in case the hook takes hella long to # run. From a72ca3d68eafd55c5624b0b569c6056a8b3627dc Mon Sep 17 00:00:00 2001 From: Laurent Sigal Date: Tue, 22 Dec 2015 18:57:25 +0000 Subject: [PATCH 2/4] Less blocking logic --- pre_commit/clientlib/validate_manifest.py | 2 +- pre_commit/commands/run.py | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/pre_commit/clientlib/validate_manifest.py b/pre_commit/clientlib/validate_manifest.py index 2b7148fd..d11ce2b8 100644 --- a/pre_commit/clientlib/validate_manifest.py +++ b/pre_commit/clientlib/validate_manifest.py @@ -17,7 +17,7 @@ MANIFEST_JSON_SCHEMA = { 'type': 'object', 'properties': { 'id': {'type': 'string'}, - 'always_run': {'type': 'boolean'}, + '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 82e494dd..f45e7089 100644 --- a/pre_commit/commands/run.py +++ b/pre_commit/commands/run.py @@ -72,19 +72,13 @@ def get_filenames(args, include_expr, exclude_expr): def _run_single_hook(hook, repo, args, write, skips=frozenset()): - filenames = [] - # if the hook is marked as always_run, do not compute the files to run - # in that case, simply run the script once not matter the changes - compute_file_names = 'always_run' not in hook or not hook['always_run'] - + filenames = get_filenames(args, hook['files'], hook['exclude']) if hook['id'] in skips: _print_user_skipped(hook, write, args) return 0 - elif compute_file_names: - filenames = get_filenames(args, hook['files'], hook['exclude']) - if not filenames: - _print_no_files_skipped(hook, write, args) - return 0 + elif not filenames and not hook['always_run']: + _print_no_files_skipped(hook, write, args) + return 0 # Print the hook and the dots first in case the hook takes hella long to # run. From 5d160e1547ea7b347d6d7557b0d0e0bd3cfd2d93 Mon Sep 17 00:00:00 2001 From: Laurent Sigal Date: Tue, 22 Dec 2015 19:47:22 +0000 Subject: [PATCH 3/4] Fix tests --- tests/manifest_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/manifest_test.py b/tests/manifest_test.py index f28862ae..ffd3b390 100644 --- a/tests/manifest_test.py +++ b/tests/manifest_test.py @@ -30,6 +30,7 @@ def test_manifest_contents(manifest): 'minimum_pre_commit_version': '0.0.0', 'name': 'Bash hook', 'stages': [], + 'always_run': False }] @@ -46,4 +47,5 @@ def test_hooks(manifest): 'minimum_pre_commit_version': '0.0.0', 'name': 'Bash hook', 'stages': [], + 'always_run': False } From 4f58f119b1a63b19fbff736d68f57bf84c02bcba Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Tue, 22 Dec 2015 12:33:17 -0800 Subject: [PATCH 4/4] Add regression test for `always_run` setting --- tests/commands/run_test.py | 6 ++++++ tests/manifest_test.py | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) 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 ffd3b390..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', @@ -30,12 +31,12 @@ def test_manifest_contents(manifest): 'minimum_pre_commit_version': '0.0.0', 'name': 'Bash hook', 'stages': [], - 'always_run': False }] def test_hooks(manifest): assert manifest.hooks['bash_hook'] == { + 'always_run': False, 'args': [], 'description': '', 'entry': 'bin/hook.sh', @@ -47,5 +48,4 @@ def test_hooks(manifest): 'minimum_pre_commit_version': '0.0.0', 'name': 'Bash hook', 'stages': [], - 'always_run': False }