Git Hook: Core Data Model Validation

Committing an unversioned changed to your Core Data model can be a major problem that frequently results in a crash. For this reason, I’ve created the following git commit hook which will validate model updates. Validation uses the following rules:

  • Don't allow modified Core Data models, just adding new ones.
  • If a new model is added, make sure the current model version number has changed. Note that it only checks to see if there was a change and does not attempt to match the version number. This is intended to allow initial commits which may contain many different model versions at once.
  • Attempt to compile the model to make sure there aren't any obvious errors like missing types, etc.

    #!/bin/sh
    
    MODIFIED_XCDATAMODELS=`git diff --staged --name-status|sed -E '/^M[[:space:]]+/!d;/\.xcdatamodel\/contents/!d;s/^M[[:space:]]+//'`
    
    # Modified Models
    if [ ! -z "$MODIFIED_XCDATAMODELS" ]; then
      echo A modified Core Data model was found: `basename $MODIFIED_XCDATAMODELS`
        echo Use model versioning instead of changing models directly.
        exit 1
    fi
    
    # Added Models
    git diff --staged --name-status|sed -E '/^A[[:space:]]+.*\.xcdatamodel\/contents/!d;s/^A[[:space:]]+//;s/\/contents//' | while read MODEL; do
        # Check for an accompanying change to ".xccurrentversion".
        VERSION_UPDATE=`git diff --staged --name-status "$MODEL/../.xccurrentversion"`
        MODEL_NAME=`basename "$MODEL"|sed -E 's/\.xcdatamodel$//'`
    
        if [ -z "$VERSION_UPDATE" ]; then
            echo Model added without a version update: $MODEL_NAME
            exit 1
        fi
    
        TEMP_DIR=`mktemp -d /tmp/momc.XXXXXX`
        TEMP_MOMD="$TEMP_DIR/$MODEL_NAME.momd"
    
        # Make sure it compiles without error.
        xcrun momc "$MODEL" "$TEMP_MOMD"
        MOMC_RESULT=$?
        rm "$TEMP_MOMD"
        rmdir "$TEMP_DIR"
    
        if [ "$MOMC_RESULT" -ne 0 ]; then
            echo Error compiling model: $MODEL_NAME
            exit 1
        fi
    done
    

You can install this hook in the normal way, which is to say you should copy it to.git/hooks/pre-commit and make it executable with chmod +x .git/hooks/pre-commit. Happy modeling!

Posted on Nov 29, 2014
Written by Emlyn Murphy