7

I'm writing a git pre-commit hook to check if any of the staged files are containing disallowed text and abort if that's the case.

Not an expert at this. So far I've got this

git diff --cached --name-status | while read x file; do
        if [ "$x" == 'D' ]; then continue; fi
        if [[ egrep "DISALLOWED_TEXT" ${file}]]; then
                echo "ERROR: Disallowed text in file: ${file}"
                exit 1
        fi
done

Doesn't seem to work. I'm getting these errors while commiting:

.git/hooks/pre-commit: line 16: conditional binary operator expected
.git/hooks/pre-commit: line 16: syntax error near `"DISALLOWED_TEXT"'
.git/hooks/pre-commit: line 16: `        if [[ egrep "DISALLOWED_TEXT" ${file}]]; then'

Any suggestions, ideas and help appreciated. Thanks!

SOLVED: (syntax errors and dysfunctional exit call)

disallowed="word1 word2"

git diff --cached --name-status | while read x file; do
        if [ "$x" == 'D' ]; then continue; fi
        for word in $disallowed
        do
            if egrep $word $file ; then
                echo "ERROR: Disallowed expression \"${word}\" in file: ${file}"
                exit 1
            fi
        done
done || exit $?
Saras101
  • 113
  • 1
  • 5
  • 4
    You missed a space between `${file}` and `]]` and you don't actually want `[[` or `]]` around the `egrep` call if you want to use the return status of `egrep` as your test in the `if` statement. – Etan Reisner Sep 02 '15 at 14:58
  • Thank you for noticing. Other issue now is that commit process is not aborted after the error is found. – Saras101 Sep 03 '15 at 06:25
  • You are seeing your error output and the `exit` is working but the commit isn't failing? It looks like that should be working (and the `|| exit $?` probably isn't necessary). – Etan Reisner Sep 03 '15 at 12:48
  • AFAIU, first exit is called from a subshell because its in a loop. Therefore, second exit has to be called to abort with the latest returned value, using $? directive. – Saras101 Sep 24 '15 at 06:54
  • The while is running in a sub-shell but it is the right-hand side of the pipe so when it exits there's nothing left running. Try it: `printf %s\\n a b c | while IFS= read -r line; do echo "$line"; exit 5; done; echo $?` – Etan Reisner Sep 24 '15 at 13:06
  • Also if you have a solution you should post it (with explanation) as an answer and accept it. Not edit it into your question. – Etan Reisner Sep 24 '15 at 13:07
  • In my case, git hook didn't abort with the first exit call, and if it is the way you described it, i'm not sure how to explain it. Thanks for help anyway. – Saras101 Sep 25 '15 at 06:13

2 Answers2

7

Answer to mark this question as having an answer:

OP ended up with:

disallowed="word1 word2"

git diff --cached --name-status | while read x file; do
        if [ "$x" == 'D' ]; then continue; fi
        for word in $disallowed
        do
            if egrep $word $file ; then
                echo "ERROR: Disallowed expression \"${word}\" in file: ${file}"
                exit 1
            fi
        done
done || exit $?
John Weldon
  • 39,849
  • 11
  • 94
  • 127
1

I am using the same logic as above and even though the stagged file contains the disallowed word, it commits the changes to the branch. Any lead would be greatly appreciated.

#!/bin/bash
import os
echo "Running pre-commit hook" 
checks=os.environ["APPSETTING_DEVPASSWORD"],os.environ["APPSETTING_DEVUSER"],os.environ["APPSETTING_DEVPASS_ELMAH"]


git diff --cached --name-status | while read x file; do

          if [ "$x" == 'D' ]; then continue; fi
        for word in $checks
        do
            if egrep $word $file ; then
                echo "ERROR: Disallowed expression \"${word}\" in file: ${file}"
                exit 1
            fi
        done
done || exit $?
Opps
  • 59
  • 1
  • 8