Skip to content

Instantly share code, notes, and snippets.

@rebelwarrior
Last active November 15, 2017 17:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rebelwarrior/a465388754d51d4842a92dd8eb4c43dd to your computer and use it in GitHub Desktop.
Save rebelwarrior/a465388754d51d4842a92dd8eb4c43dd to your computer and use it in GitHub Desktop.
Rake Task to Add Poirot's pre commit git hooks
namespace :poirot do
desc "Sets up Poirot's Git hooks for the local .git repository."
task :install_githooks do
def poirot_bash_script
<<~HEREDOC
#!/usr/bin/env bash
function setup_poirot()
{
# Output to stderr
exec 1>&2
# Allow user input
exec < /dev/tty
}
function setup_failure()
{
# Don't invoke Poirot for commits made from GitHub Desktop GUI
echo "Couldn't set up Poirot to receive user input."
exit 0
}
function run_poirot()
{
# Color codes for output
RED="\033[1;31m"
BLUE="\033[34m"
RESET="\033[0m"
# Run Poirot
echo "Running Poirot..."
if [ -n "$patterns_folder" ]; then
echo "Pattern files:"
for pattern_file in "$patterns_folder"/*.txt
do
echo $pattern_file
patterns=$patterns","$pattern_file
done
fi
poirot --staged --patterns="$patterns"
# Read sys.exit from Poirot
# Request input if match(es) found
if [ $? -eq 1 ]
then
echo "${RED}Some pattern matches were found in your staged changes. Are you sure want to commit? Choose an option #.${RESET}"
OPTIONS="Commit Cancel"
select opt in $OPTIONS; do
if [ "$opt" = "Commit" ]; then
echo "${BLUE}Committing.${RESET}"
exit 0
elif [ "$opt" = "Cancel" ]; then
echo "${BLUE}Canceling commit. Go ahead and make any new changes.${RESET}"
exit 1
else
clear
fi
done
else
exit 0
fi
}
patterns_folder=""
patterns=""
# Read in optional patterns folder and patterns files
while getopts "f:p:" opt; do
case $opt in
f)
patterns_folder="$OPTARG"
;;
p)
patterns="$OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
setup_poirot || setup_failure
run_poirot
HEREDOC
end
def guards
# checks that all requirements are installed
raise 'No .git directory found.' unless Dir.exist? '.git'
raise 'No poirot installed' unless system('which poirot')
end
def create_precommit_poirot_file
File.open('.git/hooks/pre-commit-poirot', 'w+') do |file|
file.write(poirot_bash_script)
end
end
def create_git_hook_precommit_poirot
# creates file .git/hooks/pre-commit-poirot or overwrites it
if File.exists?('.git/hooks/pre-commit-poirot')
old_content = File.read('.git/hooks/pre-commit-poirot')
unless old_content == poirot_bash_script
puts 'Overwriting .git/hooks/pre-commit-poirot'
create_precommit_poirot_file
end
else
create_precommit_poirot_file
end
end
def create_git_hook_precommit(git_hook_string)
# To make it imdepotent first check that it doesn't contain the content already.
if File.exists?('.git/hooks/pre-commit')
old_content = File.read('.git/hooks/pre-commit')
if old_content['.git/hooks/pre-commit-poirot']
# update_git_hook(pattern_file, old_content)
raise "#{git_hook_string} has to be updated manually on .git/hooks/pre-commit"
else
append_git_hook(git_hook_string)
end
else
append_git_hook(git_hook_string)
end
end
def append_git_hook(git_hook_string)
# append this line git hook string to .git/hooks/pre-commit
File.open('.git/hooks/pre-commit', 'a+') do |file|
file.write git_hook_string
end
end
guards
pattern_file = ''
pattern_list = ''
git_hook_string = ".git/hooks/pre-commit-poirot -f #{pattern_file} -p #{pattern_list}"
create_git_hook_precommit_poirot
create_git_hook_precommit(git_hook_string)
# Add executable bit to .git/hooks/pre-commit-poirot & .git/hooks/pre-commit
FileUtils.chmod '+x', %w[.git/hooks/pre-commit-poirot .git/hooks/pre-commit]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment