Skip to content

Instantly share code, notes, and snippets.

@taylormck
Last active December 27, 2015 15:09
Show Gist options
  • Save taylormck/7345972 to your computer and use it in GitHub Desktop.
Save taylormck/7345972 to your computer and use it in GitHub Desktop.
Strong pre-commit hook I'm working on.Not done yet, but getting there.
#!/bin/sh
# Rebase commits run in headless branches named with 'no branch'
# If we're in a branch with that name, assume we're rebasing
# If we really want to run checks during rebasing,
# there's a pre-rebase hook available
BRANCH_NAME=$(git branch | grep '*' | grep -c 'no branch')
if [ "$BRANCH_NAME" != "0" ]
then
exit 0
fi
# Run a program, making sure to use only changes that are staged for commit
# Otherwise, errors could slip through the cracks
# {@link #RESULT} modifies RESULT to the exit status of the given program
runWithStagedFiles () {
if [[ UNSTAGED_FILES -ne 0 ]]; then
git stash --quiet --keep-index
fi
"$@"
RESULT=$?
if [[ UNSTAGED_FILES -ne 0 ]]; then
git stash pop --quiet
fi
}
# Check if we need to stash
git diff-files --quiet
UNSTAGED_FILES=$?
# Deploy the safety net
runWithStagedFiles grunt lint
if [[ $RESULT -ne 0 ]]; then
echo ""
echo "JSHint detected syntax problems."
echo "Commit aborted."
exit 1
fi
echo "--------------------------------------\n"
# Check style guide compliance
STAGED_FILES=$(git diff --cached --name-only -z | tr '\0' ' ')
runWithStagedFiles ./node_modules/.bin/jscs $STAGED_FILES
if [[ $RESULT -ne 0 ]]; then
echo ""
echo "Style guide linting failed."
echo "Commit aborted."
exit 1
fi
echo "--------------------------------------\n"
runWithStagedFiles grunt lint-templates
if [[ $RESULT -ne 0 ]]; then
echo ""
echo "Template linting failed."
echo "Commit aborted."
exit 1
fi
echo "--------------------------------------\n"
echo "Checking localizable messages..."
runWithStagedFiles grunt validate-messages
if [[ $RESULT -ne 0 ]]; then
echo "Commit aborted."
exit 1
fi
echo "--------------------------------------\n"
echo "Running unit tests."
runWithStagedFiles grunt unit-tests > /dev/null
if [[ $RESULT -ne 0 ]]; then
echo "Unit test failures."
echo "Commit aborted."
exit 1
fi
echo "Unit tests passed.\n"
echo "--------------------------------------\n"
echo "All clear to commit\n"
exit 0
@taylormck
Copy link
Author

There is still a small problem where using both git stash -k and git stash pop on a file with both staged and unstaged changes will lose the unstaged changes.
Looking for a fix.

Still, it will safely run any validations against the staged commits. This helps guard against committing code that wouldn't pass lint / unit tests.

@charleshimmer
Copy link

Taylor what does "$@" do?

@taylormck
Copy link
Author

"$@" runs all the arguments passed to the function as a command.
So, for example, when runWithStagedFiles grunt lint runs, the $@ becomes grunt lint, and runs like it normally would.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment