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.githooks
of your repository, and save the contents of Script 1 (below) in it.Create a file named
format.py
in 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)