-
-
Save guilherme/9604324 to your computer and use it in GitHub Desktop.
#!/bin/sh | |
# Redirect output to stderr. | |
exec 1>&2 | |
# enable user input | |
exec < /dev/tty | |
consoleregexp='console.log' | |
# CHECK | |
if test $(git diff --cached | grep $consoleregexp | wc -l) != 0 | |
then | |
exec git diff --cached | grep -ne $consoleregexp | |
read -p "There are some occurrences of console.log at your modification. Are you sure want to continue? (y/n)" yn | |
echo $yn | grep ^[Yy]$ | |
if [ $? -eq 0 ] | |
then | |
exit 0; #THE USER WANTS TO CONTINUE | |
else | |
exit 1; # THE USER DONT WANT TO CONTINUE SO ROLLBACK | |
fi | |
fi |
👍
👍
👍 Thank you for sharing it!
You have a typo in the word ocurrences.
In case it trips anyone else up, this also catches removal of console.log
lines too (:
thanks @ctrl-alt-delete
👍
👍
Hi!
Any idea if I can make this global somehow?
Hi, thanks for sharing. I think this needs an adjustment. If you are removing the console.log, you can not commit!!
I have done a similar thing. Check my regexp, it ensures the line is starting with a plus that indicates you have added a "console.log" and so when removing, git let you commit.
Hope this helps:
regexp='^\+.*console\.log('
I would recommend using git diff -U0
to make sure that no lines of context are matched (so that only changes made will trigger the failure). This (combined with @brughara's proposal of only matching additions and not deletions) would result in much fewer false-positives.
@brugnara Another problem, If you add // console.log(...)
,it is invalid, but comment shouldn't be denied,I'm poor at regexp, look forward your help
@justforuse here is a regex to accomplish what you're looking for: ^\+((?!\/\/).)*console\.log\(
Weird; I had something similar to this working a few months ago but then revisiting I am now getting an error message:
test: !=: unary operator expected
Here's the relevant part of my script:
idchangeregexp='\sid:\s"'
# CHECK
if test $(git diff --cached | grep $idchangeregexp | wc -l) != 0
Any ideas?
Thanks a lot Bro
modified the script to the below to use egrep (grep wouldn't work on osx mojave for me, complained of unbalanced parentheses), and to include the filenames in the output:
#!/bin/sh
# sourced from https://gist.github.com/guilherme/9604324 on 2020-07-07
# Redirect output to stderr.
exec 1>&2
# enable user input
exec < /dev/tty
# original: consoleregexp='console.log'
# search for 'console.log(' in added files
consoleregexp='^\+.*console\.log\('
if test `git diff --cached | egrep $consoleregexp | wc -l` != 0
then
exec git diff --cached | egrep "($consoleregexp|\+{3})"
# todo note: read -p will break in zsh I think
read -p "There are some console.log calls in the diff. Do you want to continue? (y/n)" yn
echo $yn | grep ^[Yy]$
if [ $? -eq 0 ]
then
exit 0; #THE USER WANTS TO CONTINUE
else
exit 1; # THE USER DONT WANT TO CONTINUE SO ROLLBACK
fi
fi
this outputs a result like this:
11:36:29 wcarss@host:~/code (some-branch +)$ git ci
+++ b/onefile
+ console.log("hello");
+++ b/src/SomeDirectory/index.js
+ console.log('test');
There are some console.log calls in the diff. Do you want to continue? (y/n)
Hi, thanks for sharing. I think this needs an adjustment. If you are removing the console.log, you can not commit!!
I have done a similar thing. Check my regexp, it ensures the line is starting with a plus that indicates you have added a "console.log" and so when removing, git let you commit.Hope this helps:
regexp='^\+.*console\.log('
Worked this out...
consoleregexp='^[^-]**console.log'
Also this prints out the file names before the console logs...
#!/bin/sh
# Redirect output to stderr.
exec 1>&2
# enable user input
exec < /dev/tty
consoleregexp='^[^-]**console.log'
filenamewithconsole='\(^[^-]**console.log(\|^+++\)'
# CHECK
if test $(git diff --cached | grep $consoleregexp | wc -l) != 0
then
exec git diff --cached | grep -ne $filenamewithconsole | grep -B 1 $consoleregexp
read -p "There are some occurrences of console.log at your modification. Are you sure want to continue? (y/n) " yn
echo $yn | grep ^[Yy]$
if [ $? -eq 0 ]
then
exit 0; #THE USER WANTS TO CONTINUE
else
exit 1; # THE USER DONT WANT TO CONTINUE SO ROLLBACK
fi
fi
Hi, thanks for sharing. I think this needs an adjustment. If you are removing the console.log, you can not commit!!
I have done a similar thing. Check my regexp, it ensures the line is starting with a plus that indicates you have added a "console.log" and so when removing, git let you commit.Hope this helps:
regexp='^\+.*console\.log('
thanks!!
The above script did not quite work for me. I kept getting grep: repetition-operator operand invalid
errors.
Here is my tweaked code that I got working:
#!/bin/bash
# Redirect output to stderr.
exec 1>&2
# enable user input
exec < /dev/tty
consoleRegexp='^[^-].*console.log'
filenameRegexp='^[^-].*console.log(\|^+++'
if test "$(git diff --cached | grep -c "$consoleRegexp")" != 0
then
exec git diff --cached | grep -ne "$filenameRegexp" | grep -B 1 "$consoleRegexp"
read -rp "There are some occurrences of console.log at your modification. Are you sure want to continue? (y/n) " yn
if echo "$yn" | grep "^[Yy]$"
then
exit 0; #THE USER WANTS TO CONTINUE
else
exit 1; # THE USER DONT WANT TO CONTINUE SO ROLLBACK
fi
fi
Hope this helps someone!
@TimCreasman Thanks, that's helpful. You can simplify a bit: .*
means "any number of characters", so it is redundant to have .*.*
. Also, the outer parentheses in filenameRegexp
aren't being used, so they can be removed. Thus:
consoleRegexp='^[^-].*console.log'
filenameRegexp='^[^-].*console.log(\|^+++'
@TheophileMot Thanks for the input! I updated the code with your changes 👍
@TimCreasman Glad to help! I worked on this myself yesterday; it's starting to get away from the original topic, but other people might find this useful. I wanted to check for a few things (e.g., warn when committing directly to main
), so I wrapped the console.log
check in a function called no_console
, and made another function called check_branch
to see whether the current branch is master
or main
. Each of these calls another function, confirm
, when there is a potential problem.
Another small fix: after the "y/n" prompt, I didn't like the duplication of the user input, so instead of the line if echo "$yn" | grep "^[Yy]$"
, which is a bit hacky, it now just checks the variable directly with if test "$yn" == "y" || test "$yn" == "Y"
.
I also added some fancy colours.
#!/bin/bash
# Redirect output to stderr.
exec 1>&2
# enable user input
exec < /dev/tty
LRED='\033[1;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # NO COLOUR
confirm () {
printf "${YELLOW}"
read -rp "Continue with commit? (y/n) " yn
printf "${NC}"
if test "$yn" == "y" || test "$yn" == "Y"
then
printf "\n" # CONTINUE
else
exit 1
fi
}
check_branch () {
if test "$(git branch --show-current)" == "master" || test "$(git branch --show-current)" == "main"
then
printf "You are on ${LRED}$(git branch --show-current)${NC}.\n"
confirm
fi
}
no_console () {
consoleRegexp='^[^-].*console.log'
filenameRegexp='^[^-].*console.log(\|^+++'
if test "$(git diff --cached | grep -c "$consoleRegexp")" != 0
then
git diff --cached | grep -ne "$filenameRegexp" | grep -B1 "$consoleRegexp"
printf "\nSome files include ${LRED}console.log${NC}.\n"
confirm
fi
}
### RUN THROUGH CHECKS AND STOP IF THERE IS A PROBLEM
check_branch
no_console
printf "${GREEN}Proceeding with commit...${NC}\n"
This gives a little framework that makes it easier to add further pre-commit checks.
Exercise for the reader: on success, the code as written now displays a "Proceeding with commit" message even when there was no problem. Some people might find this a nuisance. Add a variable to flag whenever the user decides to proceed despite a problem (it can go in the confirm
function), and display the "Proceeding" message only when this flag is true.
Hello, you are very smart people. Can you help how i add test npm run lint -s && run before this comment. If this command throw error don`t go check console log
@Kasik-D Sure. A couple of helpful things to know: $?
gives the exit code of whatever command was previously run (the standard is 0
for success, 1
or another number otherwise); also, there are ways to compare numbers in a script, like [[ $x -ne $y ]]
. Here -ne
stands for "Not Equal to".
So try this:
run_linter () {
npm lint -s # or npx eslint *.js, or whatever your lint command is
if [[ $? -ne 0 ]]
then
printf "Oh no\n"
exit 1
fi
}
# ...
run_linter
no_console
whatever_other_stuff
@TheophileMot Thank you, one more qustions what is this programming language ? Where i see instruction of this
@Kasik-D You're welcome. This language is Bash shell scripting. Bash (or a similar shell, like zsh) is what the terminal runs on MacOS or Linux machines. On Windows, you would have to download it. Learning Bash is a life-long journey, but there are many excellent resources. This looks like a good place to start: https://linuxconfig.org/bash-scripting-tutorial-for-beginners. Have fun!
@TheophileMot Thanks again
I've been working on a more general solution that takes a text file of blocked phrases as input and will detect if any of these phrases are in your commit. I also incorporated the color changes @TheophileMot added and formatted some additional things.
If you have a file block-list.txt
with the following:
console.log
// TODO
other thing
It will detect these phrases and print out the offending diff statement.
Also disclaimer: I only tested this on OSX, but anyway here's the code:
#!/bin/bash
# Redirect output to stderr.
exec 1>&2
# Block list file location: Update this to point to your own list
blockListFile=".husky/_/block-list.txt"
# Terminal colors and formats
lightRed='\033[1;31m'
green='\033[0;32m'
yellow='\033[1;33m'
clearFormat='\033[0m'
underline='\033[4m'
# Flags
errorFoundFlag=0
confirm () {
printf '%b\n' "$yellow"
read -rp "Commit anyway? (y/n) " yn </dev/tty # Enable user input.
printf '%b' "$clearFormat"
if echo "$yn" | grep "^[Yy]$"; then
printf "%bProceeding with commit...%b\n" "$green" "$clearFormat" # The user wants to continue.
else
exit 1 # The user does not wish to continue, so rollback.
fi
}
# Finds the section of the diff that has the blocked phrase
offendingDiff () {
# Skip this method if there is no parameter passed in
if [ -z "$1" ]; then
return 0
fi
git diff --cached --color=always | tail -r | awk "/$1/{flag=1}/diff/{flag=0}flag" | tail -r
}
checkRegexp () {
# Skip this method if there is no parameter passed in
if [ -z "$1" ]; then
return 0
fi
# Here we prepend the regex with [^-] which will ensure we won't be blocked committing changes that remove the blocked phrase
regex="^[^-].*$1"
if [ "$(git diff --cached | grep -c "$regex")" != 0 ]; then
printf "%b\nError: you are attempting to commit the blocked phrase: %b%s:%b\n" "$lightRed" "$underline" "$1" "$clearFormat"
# Highlights and adds error arrows to the printout
offendingDiff "$1" | sed "s/$1/$(printf "%b$1" "$underline")/" | sed "/$1/ s/$/ $(printf "%b<<<<<<<%b" "$lightRed" "$clearFormat")/"
errorFoundFlag=1
fi
}
checkBlockList () {
while read -r line
do
checkRegexp "$line"
done < "$blockListFile"
if [ "$errorFoundFlag" = 1 ]; then
confirm
fi
}
checkBlockList
@TimCreasman thanks for this script, I tested it on Windows / Linux and it seems that the -r
argument on tail -r
in your OffendingDiff is unkown.
I found the tac
command that works just fine
git diff --cached --color=always | tac | awk "/$1/{flag=1}/diff/{flag=0}flag" | tac
Update : on MacOS, make sure you have coreutils installed (brew install coreutils
)
To install: simply download and paste into your .git/hooks/pre-commit file