-
-
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 |
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
)
thanks!!