Skip to content

Instantly share code, notes, and snippets.

@cvogt
Created June 16, 2015 19:27
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save cvogt/2676ed6c6d1abafa3d6a to your computer and use it in GitHub Desktop.
Save cvogt/2676ed6c6d1abafa3d6a to your computer and use it in GitHub Desktop.
git pre-commit hook for Scala compile and format checking (put both in your git project root, needs to be installed in each clone)
#!/bin/sh
cd "$(dirname "$0")"
touch .git/hooks/pre-commit
rm .git/hooks/pre-commit
ln -s ../../pre-commit-hook.sh .git/hooks/pre-commit
#!/bin/sh
# checks if locally staged changes are
# formatted properly. Ignores non-staged
# changes.
# Intended as git pre-commit hook
_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
DIR=$( echo $_DIR | sed 's/\/.git\/hooks$//' )
echo ""
echo "Running pre-commit hook ... (you can omit this with --no-verify, but don't)"
git diff --quiet
hadNoNonStagedChanges=$?
if ! [ $hadNoNonStagedChanges -eq 0 ]
then
echo "* Stashing non-staged changes"
git stash --keep-index -u > /dev/null
fi
echo "* Compiling/formatting staged changes"
$DIR/sbt ";test:compile;format" > /dev/null
compiles=$?
echo "* Compiles?"
if [ $compiles -eq 0 ]
then
echo "* Yes!"
echo "* Properly formatted?"
git diff --quiet
formatted=$?
if [ $formatted -eq 0 ]
then
echo "* Yes!"
else
echo "* No!"
echo "The following files need formatting (in stage or commited):"
git diff --name-only
echo ""
fi
else
echo "* No!"
fi
echo "* Undoing formatting"
git stash --keep-index > /dev/null
git stash drop > /dev/null
if ! [ $hadNoNonStagedChanges -eq 0 ]
then
echo "* Scheduling stash pop of previously stashed non-staged changes for 1 second after commit"
sleep 1 && git stash pop --index > /dev/null & # sleep and & otherwise commit fails when this leads to a merge conflict
fi
if [ $compiles -eq 0 ] && [ $formatted -eq 0 ]
then
echo "... done. Proceeding with commit."
exit 0
elif [ $compiles -eq 0 ]
then
echo "... done."
echo "CANCELLING commit due to NON-FORMATTED CODE."
exit 1
else
echo "... done."
echo "CANCELLING commit due to COMPILE ERROR."
exit 2
fi
@sergigp
Copy link

sergigp commented Jan 17, 2016

Hi, just curious but what is your "format" task ? Scalastyle ?

@JavierCane
Copy link

Hi!

Since this is the first Google search result while searching for scala pre-commit, I'll leave here the script that we use (based on you implementation :D ) if it helps anyone :)

It checks the compilation, the scalastyle, and the test:scalastyle in 3 different steps in order to show which one has errors.

#!/bin/bash

# Checks if locally staged changes are formatted properly ignoring non-staged changes.
# @see: https://gist.github.com/cvogt/2676ed6c6d1abafa3d6a

PATH=$PATH:/usr/local/bin:/usr/local/sbin

echo ""
echo "Doing some Checks…"

echo "* Moving to the project directory…"
_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
DIR=$( echo $_DIR | sed 's/\/.git\/hooks$//' )

echo "* Stashing non-staged changes so we don't check them"…
git diff --quiet
hadNoNonStagedChanges=$?

if ! [ $hadNoNonStagedChanges -eq 0 ]
then
    git stash --keep-index -u > /dev/null
fi

echo "* Compiling…"
sbt test:compile > /dev/null
compiles=$?

if [ $compiles -ne 0 ]
then
    echo "  [KO] Error compiling "
else
    echo "* Checking production code style…"

    sbt scalastyle > /dev/null
    productionScalastyle=$?

    if [ $productionScalastyle -ne 0 ]
    then
        echo "  [KO] Error checking production code style"
    else
        echo "* Checking test code style…"

        sbt test:scalastyle > /dev/null
        testScalastyle=$?

        if [ $testScalastyle -ne 0 ]
        then
            echo "  [KO] Error checking test code style"
        fi
    fi
fi

echo "* Applying the stash with the non-staged changes…"
if ! [ $hadNoNonStagedChanges -eq 0 ]
then
    sleep 1 && git stash pop --index > /dev/null & # sleep because otherwise commit fails when this leads to a merge conflict
fi

# Final result
echo ""

if [ $compiles -eq 0 ] && [ $productionScalastyle -eq 0 ] && [ $testScalastyle -eq 0 ]
then
    echo "[OK] Your code will be committed young padawan"
    exit 0
elif [ $compiles -ne 0 ]
then
    echo "[KO] Cancelling commit due to compile error (run 'sbt test:compile' for more information)"
    exit 1
elif [ $productionScalastyle -ne 0 ]
then
    echo "[KO] Cancelling commit due to production code style error (run 'sbt scalastyle' for more information)"
    exit 2
else
    echo "[KO] Cancelling commit due to test code style error (run 'sbt test:scalastyle' for more information)"
    exit 3
fi

@joan38
Copy link

joan38 commented Mar 13, 2020

I'm doing:
~/gitconfig/hooks/pre-commit:

#!/bin/sh
  
if grep -q 'addCommandAlias("style",' build.sbt; then
  exec sbt styleCheck
fi
exit 0

I ran once:

git config --global core.hooksPath ~/gitconfig/hooks

And in my projects build.sbt's I usually have:

addCommandAlias("style", "Compile/scalafix; Test/scalafix; Compile/scalafmt; Test/scalafmt; scalafmtSbt")
addCommandAlias("styleCheck", "Compile/scalafix --check; Test/scalafix --check; Compile/scalafmtCheck; Test/scalafmtCheck; scalafmtSbtCheck")

CI is also running:

sbt styleCheck

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