M0AGX / LB9MG

Amateur radio and embedded systems

Git - checking JavaScript files for debugger statements

We developers, when working on a common codebase, often step on each other's toes. Recently, while debugging code of a complex application server I have been hit with JavaScript debugger statements placed by another developer all around, that should not get to the common branch. So what is better than complaining to your colleagues to be more careful every time they commit code? Present them with a Git hook that does the checking for them and solves the problem once and for all :-) This hook is an expansion of the previous one.

The previous hook only checked the branch name against a pattern to avoid unintended commits to stable branches. This hook gets a list of files in a commit, picks only .js files and searches them for "debugger" string. If such files are found, the script lists them and asks what to do:

  • commit anyway
  • cancel the commit
  • commit and remove "debugger" statements

I avoid breaking someone else's workflows as far as possible so there is still an option to just commit the code. I could also implement a server-side pre-push hook that would do the checking and simply reject unwanted stuff but that would force the developers to reset their branches and do the cleaning themselves. I think that problems are best dealt with as early as possible so this hook is executed in the pre-commit phase.

The last option is especially useful, because it saves the time needed to walk through all the files and clean code manually. Replacing the "debugger" string with a semicolon is probably the safest option. As a side-effect the script will also do replacements in comments but that should not be a big problem.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/bin/bash
# This hooks prevents unintentional committing to a branch.
# Customize PATTERN to suit your needs. It also checks JavaScript
# files for debugger statements and can replace them with semicolons.
#
# Place this file in .git/hooks/pre-commit and make executable.

PATTERN="stable"
BRANCH=`git rev-parse --abbrev-ref HEAD`

function confirm { #first argument - message
    PS3=$1
    options=("Yes" "No")
    select opt in "${options[@]}"
    do
        case $opt in
            ${options[0]})
                break
                ;;
            ${options[1]})
                exit 1
                ;;
            *) echo invalid option;;
        esac
    done < /dev/tty
}

function clean_js_files {
    JS_FILES=`git diff  --cached --name-only | grep .js`
    DEBUGGER_STATEMENT_PRESENT=0
    echo
    echo "The following lines will be modified:"
    for FILE in $JS_FILES; do
        grep --color=auto -Hn 'debugger' $FILE
    done
    confirm "Are you sure? "
    #script will exit if not sure
    for FILE in $JS_FILES; do
        sed --in-place  's/debugger/;/' $FILE
    done
}

function confirm_js_files {
    PS3='Do you really want to commit?: '
    options=("Yes" "No" "Remove debugger statements (substitute with semicolons)")
    select opt in "${options[@]}"
    do
        case $opt in
            ${options[0]})
                break
                ;;
            ${options[1]})
                exit 1
                ;;
            ${options[2]})
        clean_js_files
                break
                ;;
            *) echo invalid option;;
        esac
    done < /dev/tty
}

function check_js_files_for_debugger {
    JS_FILES=`git diff  --cached --name-only | grep .js`
    DEBUGGER_STATEMENT_PRESENT=0
    for FILE in $JS_FILES; do
        grep -Hn 'debugger' $FILE
        STATUS=$?
        if [ $STATUS -eq 0 ]; then
            DEBUGGER_STATEMENT_PRESENT=1
        fi
    done
    return "$DEBUGGER_STATEMENT_PRESENT"
}

if [[ $BRANCH = *$PATTERN* ]]; then
    echo "----------------------------------------------------------------"
    echo "WARNING: You are committing to stable branch:" $BRANCH
    echo "----------------------------------------------------------------"
    confirm "Do you really want to commit? "
fi

check_js_files_for_debugger $JS_FILES
A=$? #exit code of previous function call
if [ $A -eq 1 ]; then
    echo "----------------------------------------------------------------"
    echo "WARNING: Debugger statements detected in JavaScript files."
    echo "----------------------------------------------------------------"
    confirm_js_files
fi

exit 0