Preparing the pre-commit and formatter
This section explains how to work with Arria's pre-commit hook for Git.
Create a file named
pre-commit(no extension!) inside the hidden directory.githooksof your repository, and save the contents of Script 1 (below) in it.Create a file named
format.pyin the root of your repository, and save the contents of Script 2 (below) in it.
Script 1
#!/bin/sh
## CONFIG
FORMAT_PATH="format.py"
PYTHON_PATH=python
## ENABLE_NAME_CLEANUP - optional param
## when set it will do Studio file name cleanup: remove version and replace spaces with underscores
## comment out to disable
ENABLE_NAME_CLEANUP=yes
## FUNCTIONS
checkJQ () {
echo "- checking if JQ is installed"
if ! $JQ --version > /dev/null 2> /dev/null
then
return 1
fi
return 0
}
checkLocalJQ () {
echo "- checking if local JQ is installed"
JQ=./jq
if ! $JQ --version > /dev/null 2> /dev/null
then
return 1
fi
return 0
}
downloadJQ () {
echo "- downloading JQ into project dir"
if [[ "$OSTYPE" == "linux-gnu" ]]; then
curl -o "jq" -L "https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64"
elif [[ "$OSTYPE" == "darwin"* ]]; then
curl -o "jq" -L "https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64"
elif [[ "$OSTYPE" == "cygwin" || "$OSTYPE" == "msys" || "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
curl -o "jq.exe" -L "https://github.com/stedolan/jq/releases/download/jq-1.6/jq-win64.exe"
else
echo "FAILED: JQ could not be downloaded. Unknown OS: $OSTYPE"
return 1
fi
export PATH=.:$PATH
echo "jq" >> .git/info/exclude
echo "jq.exe" >> .git/info/exclude
chmod +x jq 2> /dev/null
chmod +x jq.exe 2> /dev/null
}
isStudioFile () {
if [ ! -s "$1" ]
then
# empty file
return 1
fi
if ! cat "$1" | $JQ -ce ".templates[].value" > /dev/null 2> /dev/null
then
echo "- non-Studio file: $staged"
return 1
fi
return 0
}
isDeletedFile () {
if [ -r "$1" ]
then
return 1
fi
return 0
}
formatStudio () {
path=$1
temppath=$1.tmp
echo "- remove .sampleOutput, .version, .collaborators, .activeUser fields and format Studio file"
cat "$path" | $JQ "del(.sampleOutput, .version, .collaborators, .activeUser, .activeApiKey, .allowPublication, .published, .settingsNotNull)" > "$temppath" || ( echo "OPTIONAL: remove step failed for $path . Most probably the step was not applicable."; cp "$path" "$temppath" )
echo "- apply common formatting"
cat "$temppath" | $JQ -c . > "$path" || return 1
rm "$temppath"
return 0
}
setupJQ() {
# exit if no JQ
if ! checkJQ && ! checkLocalJQ
then
downloadJQ
if ! checkLocalJQ
then
echo "FAILED: no JQ installed. Pre-commit could not install JQ in the local repo. Please, install it manually, set PATH and verify 'jq --version'"
return 1
fi
fi
}
extractScripts () {
chmod +x "$FORMAT_PATH"
"$PYTHON_PATH" "$FORMAT_PATH" "$1" || return 1
return 0
}
## MAIN
echo "-------------------------------"
echo "- pre-commit hook started..."
setupJQ || exit $?
OLDIFS=$IFS
IFS=$'\n'
for staged in `git diff --name-only --cached`
do
# skip deleted file
if isDeletedFile "$staged"
then
continue
fi
# skip non-Studio files
if ! isStudioFile "$staged"
then
continue
fi
echo "- staged studio file: $staged"
# optional: normalize name - remove version and replace spaces with underscores
if [ -n $ENABLE_NAME_CLEANUP ]
then
filename=`basename "$staged"`
dir=`dirname "$staged"`
normalized_name=`echo "$filename" | tr '[A-Z ]' '[a-z_]' | sed -E 's/_\([0-9]+\)//g' | sed -E 's/_v[0-9]+\.json$/.json/g' | sed -E 's/^\[.+\]//g'`
if [ "$filename" != "$normalized_name" ]
then
echo "- name normalization: $filename -> $normalized_name"
git mv -f "$staged" "$dir/$normalized_name"
staged="$dir/$normalized_name"
fi
fi
# format Studio file
echo "- formatting staged Studio file with JQ"
if ! formatStudio "$staged"
then
echo "FAILED: formatting failed. Check if the staged file is a valid Studio project. Try to re-import from Studio."
exit 1
fi
# create peer review files
echo "- creating peer review files"
if ! extractScripts "$staged"
then
echo "FAILED: could not create peer review files from Studio project. Check if the staged file is a valid Studio project. Try to re-import from Studio."
exit 1
fi
# re-stage edited file
echo "- re-staging processed files"
if ! git add "$staged"
then
echo "FAILED: re-stage processed files: $staged"
exit 1
fi
if ! git add "${staged%\.json}_peer_review"
then
echo "FAILED: re-stage processed files: ${staged%\.json}_peer_review"
exit 1
fi
done
IFS=$OLDIFS
echo ""
echo "- pre-commit hook finished."
echo "-------------------------------"
Script 2
'''
This script generates .atl files from Studio projects, in order to make peer review easier. It creates 1 file for each script (template) in the project, pretty-printing some HTML tags in the process.
'''
import os
import sys
import json
file = sys.argv[1]
# set constants
SCRIPTS_KEY = 'templates'
OUTPUT_DIR = file[:-5] + '_peer_review'
# create output directory
if not os.path.exists(OUTPUT_DIR):
os.makedirs(OUTPUT_DIR)
# create script files
with open(file) as inFile:
data = json.load(inFile)
newFiles = []
for script in data[SCRIPTS_KEY]:
name = script['id']
code = script['value']
code = code.replace("<p>", "\n")
code = code.replace("</p>", "\n")
code = code.replace("<br>", "\n")
code = code.replace("<br/>", "\n")
code = code.replace(">", ">")
code = code.replace("<", "<")
code = code.replace("&", "&")
atlFileName = name + '.atl'
newFiles.append(atlFileName)
atlFile = open(OUTPUT_DIR + '/' + atlFileName, 'w')
code = code.encode('ascii', 'ignore').decode('ascii')
atlFile.write(code)
# deleted obsolete script files
for (dirpath, dirnames, filenames) in os.walk(OUTPUT_DIR):
for filename in filenames:
if filename.endswith('.atl') and filename not in newFiles:
os.remove(OUTPUT_DIR + '/' + filename)