If I want to write a pre-commit hook to check that, e.g., the string "I love pre-commit" isn't anywhere in my source code, I could do
- repo: local
hooks:
- id: love_statement
name: Check that I love pre-commit isn't in source code
types: [python]
entry: 'I love pre-commit'
language: pygrep
However, what if I want to do this opposite - that is, check that "I love pre-commit" is in every source code file? How could I modify my hook so that, instead of failing if "I love pre-commit" is found, it would fail if "I love pre-commit" isn't found?
this can now be done with
args: [--negate]
You can use a few regex tricks to do this:
repos:
- repo: local
hooks:
- id: love_statement
name: Check that I love pre-commit is in source code
types: [python]
args: [--multiline]
entry: '\A((?!I love pre-commit).)*\Z'
language: pygrep
this combines the following:
args: [--multiline]
to push pygrep
into whole-file matching mode^
and $
(per line anchors) to \A
and \Z
(whole string anchors)here's an example execution:
$ git ls-files -- '*.py' | xargs tail -n999
==> t.py <==
print('I do not love pre-commit')
==> t2.py <==
print('I love pre-commit')
$ pre-commit run --all-files
Check that I love pre-commit is in source code...........................Failed
- hook id: love_statement
- exit code: 1
t.py:1:print('I do not love pre-commit')
disclaimer: I'm the author of pre-commit