pygrep pre-commit hook to check string is present
Asked Answered
H

1

7

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]
Hamm answered 13/10, 2020 at 16:14 Comment(0)
I
10

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

Industrials answered 13/10, 2020 at 23:30 Comment(5)
"disclaimer: I'm the author of pre-commit" Looks like flattery is a good strategy :) Thanks!Hamm
I'm finding this solution to be slow, even though it works - is there an option to reverse the exit code of pygrep? If not, would you take a pull request to add that?Hamm
there is not or I would have suggested it. A PR may be considered if you can demonstrate a real use case for itIndustrials
@AnthonySottile Did inverting the condition every become a thing? I have a use case where we have a version file with a magic string we never want changed. A tox job replaces it. If someone runs it locally we want to make sure they can't commit it if the magic string isn't still there.Doig
@MikeBarry easy to check the docsIndustrials

© 2022 - 2024 — McMap. All rights reserved.