pygrep pre-commit hook to check string is present

1.3k views Asked by At

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]
1

There are 1 answers

5
anthony sottile On BEST ANSWER

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:

  • use the rough negative lookbehind pattern from this answer
  • use args: [--multiline] to push pygrep into whole-file matching mode
  • switch from ^ 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