summaryrefslogtreecommitdiffstats
path: root/pre_commit/commands/run.py
diff options
context:
space:
mode:
Diffstat (limited to 'pre_commit/commands/run.py')
-rw-r--r--pre_commit/commands/run.py39
1 files changed, 29 insertions, 10 deletions
diff --git a/pre_commit/commands/run.py b/pre_commit/commands/run.py
index 8c8401c..567b7cd 100644
--- a/pre_commit/commands/run.py
+++ b/pre_commit/commands/run.py
@@ -72,13 +72,7 @@ def filter_by_include_exclude(
class Classifier:
- def __init__(self, filenames: Sequence[str]) -> None:
- # on windows we normalize all filenames to use forward slashes
- # this makes it easier to filter using the `files:` regex
- # this also makes improperly quoted shell-based hooks work better
- # see #1173
- if os.altsep == '/' and os.sep == '\\':
- filenames = [f.replace(os.sep, os.altsep) for f in filenames]
+ def __init__(self, filenames: Collection[str]) -> None:
self.filenames = [f for f in filenames if os.path.lexists(f)]
@functools.lru_cache(maxsize=None)
@@ -105,6 +99,22 @@ class Classifier:
names = self.by_types(names, hook.types, hook.exclude_types)
return tuple(names)
+ @classmethod
+ def from_config(
+ cls,
+ filenames: Collection[str],
+ include: str,
+ exclude: str,
+ ) -> 'Classifier':
+ # on windows we normalize all filenames to use forward slashes
+ # this makes it easier to filter using the `files:` regex
+ # this also makes improperly quoted shell-based hooks work better
+ # see #1173
+ if os.altsep == '/' and os.sep == '\\':
+ filenames = [f.replace(os.sep, os.altsep) for f in filenames]
+ filenames = filter_by_include_exclude(filenames, include, exclude)
+ return Classifier(filenames)
+
def _get_skips(environ: EnvironT) -> Set[str]:
skips = environ.get('SKIP', '')
@@ -221,7 +231,8 @@ def _compute_cols(hooks: Sequence[Hook]) -> int:
def _all_filenames(args: argparse.Namespace) -> Collection[str]:
- if args.hook_stage == 'post-checkout': # no files for post-checkout
+ # these hooks do not operate on files
+ if args.hook_stage in {'post-checkout', 'post-commit'}:
return ()
elif args.hook_stage in {'prepare-commit-msg', 'commit-msg'}:
return (args.commit_msg_filename,)
@@ -246,10 +257,9 @@ def _run_hooks(
"""Actually run the hooks."""
skips = _get_skips(environ)
cols = _compute_cols(hooks)
- filenames = filter_by_include_exclude(
+ classifier = Classifier.from_config(
_all_filenames(args), config['files'], config['exclude'],
)
- classifier = Classifier(filenames)
retval = 0
for hook in hooks:
retval |= _run_single_hook(
@@ -323,6 +333,12 @@ def run(
f'`--hook-stage {args.hook_stage}`',
)
return 1
+ # prevent recursive post-checkout hooks (#1418)
+ if (
+ args.hook_stage == 'post-checkout' and
+ environ.get('_PRE_COMMIT_SKIP_POST_CHECKOUT')
+ ):
+ return 0
# Expose from-ref / to-ref as environment variables for hooks to consume
if args.from_ref and args.to_ref:
@@ -340,6 +356,9 @@ def run(
if args.checkout_type:
environ['PRE_COMMIT_CHECKOUT_TYPE'] = args.checkout_type
+ # Set pre_commit flag
+ environ['PRE_COMMIT'] = '1'
+
with contextlib.ExitStack() as exit_stack:
if stash:
exit_stack.enter_context(staged_files_only(store.directory))