Skip to content

Instantly share code, notes, and snippets.

@BillBarnhill
Forked from marchelbling/README.md
Created November 23, 2015 12:20
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 BillBarnhill/6e01bc03c59657d0157a to your computer and use it in GitHub Desktop.
Save BillBarnhill/6e01bc03c59657d0157a to your computer and use it in GitHub Desktop.
git hooks

Git hooks for better pivotal integration:

  • pre-commit:
    • prevents commiting on a branch that is not suffixed by an issue number. Some special branches (develop, master) and hotfixes are not constrained
    • [optional] lints python/js (+ beautification) files (requires to define the AUTO_LINT_FILES environment variable)
  • prepare-commit-msg: prepend issue number to commit message if it's missing and if it is set in the branch name (see pre-commit hook)
  • post-checkout: [optional] automatically update submodules when checkouting a branch (requires to define the AUTO_SUBMODULE_UPDATE environment variable)

For easy setup:

current="$( pwd )" && cd "$( git rev-parse --show-cdup )" && if [ -d .hooks ]; then cd .hooks && git fetch origin && git reset --hard origin/master && cd ..; else git clone https://gist.github.com/7358077.git .hooks; fi && if ([ ! -f .gitignore ] || ! grep .hooks .gitignore >/dev/null ); then echo -e ".hooks\n" >> .gitignore; fi && find .hooks -maxdepth 1 -type f | while read h; do chmod +x "${h}"; ln -s -f "../../${h}" ".git/hooks/$( basename ${h} )"; done && cd "${current}"
#!/bin/bash
function get_branch_name {
echo "$( git rev-parse --abbrev-ref HEAD )"
}
function has_valid_id {
local branch="$1"
echo "${branch}" | grep -e "_[-a-zA-Z]*[0-9]\{1,\}$" 2>&1 1>/dev/null
return $?
}
function get_issue_id {
local branch="$1"
# see http://stackoverflow.com/questions/3162385/how-to-split-a-string-in-shell-and-get-the-last-field
echo "${branch}" | rev | cut -d'_' -f1 | rev | tr '[:lower:]' '[:upper:]'
}
function is_special_branch {
local branch="$1"
echo "${branch}" | grep -i "^\(hotfix\|release\|develop\|master\|HEAD\)" 1>/dev/null 2>&1
return $?
}
function is_not_autosquash_commit {
grep -v '\(fixup\|squash\)!' <<<"$1" >/dev/null
return $?
}
#!/bin/bash
if ${AUTO_SUBMODULE_UPDATE:-false};
then
git submodule update --init >/dev/null && echo "Submodules updated!"
fi
#!/bin/bash
. "$( git rev-parse --show-toplevel )/.hooks/commons.sh"
function lint_js_files {
local js_files="$1"
local result=0
# Check the JS files
if [ -n "${js_files}" ]
then
xargs js-beautify -qr <<<"${js_files}"
if [ -n "$( git diff --name-only )" ]
then
[ ${result} -ne 0 ] && echo
result=1
echo '[JS] Some files seem to not be conforming to the coding style (JSBeautify).'
echo
git diff -U0
fi
fi
# Check the JS files (again :)
if [ -n "${js_files}" ]
then
local lint_errors=$( xargs jshint <<< "${js_files}" | grep : )
if [ -n "${lint_errors}" ]
then
[ ${result} -ne 0 ] && echo
result=1
echo '[JS] Some files seem to not be conforming to the coding style (JSHint).'
echo
cat <<<"${lint_errors}"
fi
fi
return ${result}
}
function lint_scss_files {
local scss_files="$1"
local result=0
# Check the SCSS files
if [ -n "${scss_files}" ]
then
local lint_errors="$( xargs scss-lint <<<"${scss_files}" )"
if [ -n "${lint_errors}" ]
then
[ ${result} -ne 0 ] && echo
result=1
echo '[SCSS] Some files seem to not be conforming to the coding style (SCSS-Lint).'
echo
cat <<<"${lint_errors}"
fi
fi
return ${result}
}
function lint_py_files {
local py_files="$1"
local result=0
if [ -n "${py_files}" ]
then
local lint_errors="$( xargs flake8 <<<"${py_files}" )"
if [ -n "${lint_errors}" ]
then
[ ${result} -ne 0 ] && echo
result=1
echo '[PY] Some files seem to not be conforming to the coding style (Flake8).'
echo
cat <<<"${lint_errors}"
fi
fi
return ${result}
}
function lint_files {
local folder="$( pwd )"
cd "$( git rev-parse --show-toplevel )"
if git status --porcelain 2>/dev/null | grep '^.M '>/dev/null;
then
# Stash the current changes, so that we preserve them
has_unstaged_changes=true
git stash -q --keep-index
else
has_unstaged_changes=false
fi
# Get the list of changed files from the index
update_list=$( git diff --name-only --staged )
# We only have interest in py/js/scss files
py_files=$( grep '\.py$' <<<"${update_list}" )
js_files=$( grep '\.js$' <<<"${update_list}" )
scss_files=$( grep '\.scss$' <<<"${update_list}" )
lint_js_files "${js_files}" &&
lint_scss_files "${scss_files}" &&
lint_py_files "${py_files}"
local status=$?
if ${has_unstaged_changes}; then
# Drop the temporary modifications, and restore the stash
git reset -q --hard
git stash pop -q --index
fi
cd "${folder}"
return ${status}
}
function lint_branch_name {
local branch="$( get_branch_name )"
if ! is_special_branch "${branch}"
then
if ! has_valid_id "${branch}"
then
echo "Bad branch name: should be (feature/bug/chore/)detail_xxxx."
echo "Please use 'git branch -m ${branch} ${branch}_xxxxx'"
exit 1
fi
fi
}
lint_branch_name && \
if ${AUTO_LINT_FILES:-false}; then lint_files; fi
#!/bin/bash
. "$( git rev-parse --show-toplevel )/.hooks/commons.sh"
function get_issue_state {
local msg="$1"
# see http://stackoverflow.com/questions/3162385/how-to-split-a-string-in-shell-and-get-the-last-field
for state in "Fix" "Finish" "Deliver";
do
if echo "${msg}" | grep -i "^+${state}" 2>&1 1>/dev/null
then
# return state
if [ "${state}" == "Deliver" ];
then
echo "Delivers "
else
echo "${state}es "
fi
break
fi
done
}
function format_msg {
local msg="$1"
local id="$2"
local state="$3"
if [ -n "${state}" ]
then
# strip state
msg="$( echo "${msg}" | cut -d' ' -f2- )"
fi
# uppercase first letter
msg="$( tr '[:lower:]' '[:upper:]' <<< ${msg:0:1} )${msg:1}"
if [ -n "${id}" ] && ! echo "${msg}" | grep -F "#${id}" 2>&1 1>/dev/null
then
msg="[${state}#${id}] ${msg}"
fi
echo -e "${msg}\n\n"
}
commit_msg="$( cat $1 )"
if is_not_autosquash_commit "${commit_msg}";
then
branch="$( get_branch_name )"
if has_valid_id "${branch}"
then
issue_id="$( get_issue_id "${branch}" )"
fi
issue_state="$( get_issue_state "$1" )"
commit_msg="$( format_msg "${commit_msg}" "${issue_id}" "${issue_state}" )"
fi
echo "${commit_msg}" > "$1"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment