#!/bin/bash
# Adapted from puppet script given at http://projects.puppetlabs.com/projects/1/wiki/Puppet_Version_Control

NOBOLD="\033[0m"
BOLD="\033[1m"
RED="\033[31m"
GREEN="\033[32m"
YELLOW="\033[33m"
BLUE="\033[34m"
MAGENTA="\033[35m"
CYAN="\033[36m"
WHITE="\033[37m"

NULL_SHA1="0000000000000000000000000000000000000000"

branch="$1"
if [[ "$2" != $NULL_SHA1 ]]; then
    branch=$(git rev-parse --symbolic --abbrev-ref $1)
fi

MAINBRANCH=$(git config --get mysociety.mainbranch)
if [[ "$branch" == "gh-pages" || "$branch" == "${MAINBRANCH:=master}" ]]; then
  log=$(mktemp /tmp/git.update.log.XXXXXX)
  if git log --oneline "$2".."$3" | grep -i '^[^ ]* \([^a-z]*WIP\|fixup\|squash\)' > $log; then
    echo
    echo -e "${RED}Bad commits found:${NOBOLD}" >&2
    echo -e "${CYAN}$(cat $log)${NOBOLD}" >&2
    echo
    rm -f $log
    exit 1
  fi
  rm -f $log
fi

if [[ "$branch" == *gh-pages* ]]
then
    exit 0
fi

# Branch being deleted
if [[ "$3" == $NULL_SHA1 ]]; then
    exit 0
fi

if [ -n "$(git branch -a --contains "$3")" ]
then
    echo "$3 is already pointed to by another branch, assuming it's already been checked"
    exit 0
fi

exit_status=0

# Check JSON files are valid JSON
syntax_check="/data/mysociety/bin/valid-json"
tmp=$(mktemp /tmp/git.update.XXXXXX)
log=$(mktemp /tmp/git.update.log.XXXXXX)
tree=$(mktemp /tmp/git.diff-tree.XXXXXX)

FROM="$2"
if [[ "$2" == $NULL_SHA1 ]]; then
    FROM=$(git rev-parse $(git rev-list --reverse "$3" --not --branches|head -1)^)
fi
git diff-tree -r "$FROM" "$3" > $tree

while read old_mode new_mode old_sha1 new_sha1 status name
do
  # skip lines showing parent commit
  test -z "$new_sha1" && continue
  # skip deletions
  [ "$new_sha1" = $NULL_SHA1 ] && continue
  # Only test .json files
  if [[ $name =~ [.]json$ ]]
  then
    git cat-file blob $new_sha1 > $tmp
    set -o pipefail
    if ! $syntax_check < $tmp; then
      echo
      echo -e "${RED}Invalid JSON${NOBOLD}" >&2
      echo -e "For more details run this: ${CYAN}git diff $old_sha1 $new_sha1 ${NOBOLD}" >&2
      echo
      exit_status=1
    fi
  fi
done < $tree

# JSlint if we've been asked to
if [[ "`git config --get mysociety.jslint`" != 'true' ]]; then
   rm -f $log $tmp $tree
   exit $exit_status
fi

syntax_check="/usr/bin/jshint"
# Need to read out .jshintrc and .jshintignore from git to use them!

while read old_mode new_mode old_sha1 new_sha1 status name
do
  # skip lines showing parent commit
  test -z "$new_sha1" && continue
  # skip deletions
  [ "$new_sha1" = $NULL_SHA1 ] && continue
  # skip anything vendored
  [[ $name =~ /vendor/ ]] && continue
  # Only test .js files
  if [[ $name =~ [.]js$ ]]
  then
    git cat-file blob $new_sha1 > $tmp
    set -o pipefail
    if ! $syntax_check $tmp > $log; then
      echo
      echo -e "$(sed 's|[^:]*:|'\\${RED}${name}\\${NOBOLD}'|' $log)" >&2
      echo -e "For more details run this: ${CYAN}git diff $old_sha1 $new_sha1 ${NOBOLD}" >&2 
      echo
      exit_status=1
    fi
  fi
done < $tree

rm -f $log $tmp $tree
exit $exit_status
