#! /bin/bash

REPOSITORY="https://github.com/OoliteProject/oolite.git"
BRANCH="master"
CONFIGURATION="TestRelease"

VAR_DIR_NAME="var"
REPO_DIR_NAME="working_copy"

VAR="`pwd`/$VAR_DIR_NAME/"
LOG="$VAR/log/"
LOG_OLD="$VAR/log-old/"
LOG_SUCCESS="$VAR/log-success/"
COCOA_SRC_DIR="src/Cocoa/"
SNAPSHOT_MACRO_FILE="$COCOA_SRC_DIR/oolite-snapshot.xcconfig"
BUILD_DIR="build/$CONFIGURATION/"

LAST_REVISION_FILE="$VAR/revision"
SUCCESS_REVISION_FILE="$VAR/success_revision"
PREVIOUS_SUCCESS_REVISION_FILE="$VAR/previous_success_revision"
LATEST_NAME_FILE="$VAR/latest"
CHANGELOG_FILE="$LOG/change_log"
DIAGNOSTICS_FILE="$LOG/diagnostics"
STDERR_FILE="$LOG/xcb_stderr.txt"
STDOUT_FILE="$LOG/xcb_stdout.txt"
STATUS_FILE="$LOG/build_log.txt"
GIT_LOG_FILE="$LOG/git_log.txt"
LAST_UPDATED_FILE="$VAR/last_updated"

OOLITE_APP_PKG="$BUILD_DIR/Oolite.app"
DEBUG_OXP_PKG="DebugOXP/Debug.oxp"

FTP_URL_FILE="`pwd`/config/ftp_url"
FTP_CREDENTIALS_FILE="`pwd`/config/ftp_credentials"
FTP_INFO_SET=0

if [ ! "$GIT" ]
then
	GIT="git"
fi

if [ ! "$CURL" ]
then
	CURL="curl"
fi

if [ ! "$DITTO" ]
then
	DITTO="ditto"
fi


function report
{
	if [ `which growlnotify` ]
	then
		growlnotify -n "Oolite nightly build" -s "$1" -m "$2"
	fi
	echo $2
}


function fail
{
	if [ $FTP_INFO_SET -eq 1 ] && [ -e "$LAST_REVISION_FILE" ]
	then
		curl --silent $FTP_CREDENTIALS -T "$LAST_REVISION_FILE" "$FTP_URL/revision"
	fi
	report "Oolite nightly build failure" "$1"
	exit 1
}


# Ensure output directories exist.
if [ ! -e $VAR ]
then
	mkdir $VAR
fi


if [ -e $LOG ]
then
	if [ -e $LOG_OLD ]
	then
		rm -rf $LOG_OLD
	fi
	mv $LOG $LOG_OLD
fi

mkdir $LOG


# Clear git log so we can append to it freely
touch "$GIT_LOG_FILE"
echo "" > "$GIT_LOG_FILE"


if [ ! -e "$REPO_DIR_NAME" ]
then
	# Clone repo if necessary.
	CLEAN_CHECKOUT=1
	
	echo "Cloning Oolite..."
	"$GIT" clone --quiet "$REPOSITORY" "$REPO_DIR_NAME" >> "$GIT_LOG_FILE"
	if [ ! $? ]
	then
		fail "Failed to clone repository."
	fi

	STATUS=0

	cd "$REPO_DIR_NAME"
	"$GIT" checkout "$BRANCH"
else
	# Revert the file we manipulate for watermarking, then update repo.
	CLEAN_CHECKOUT=0
	cd "$REPO_DIR_NAME"

	echo "Updating..."
	"$GIT" checkout -- "$SNAPSHOT_MACRO_FILE" >> "$GIT_LOG_FILE"

	"$GIT" pull --quiet --ff-only >> "$GIT_LOG_FILE"
	STATUS=$?
fi

# Get $OOLITE_VERSION
source $COCOA_SRC_DIR/oolite-version.xcconfig


# Make sure we're on the right branch, and update submodules.
"$GIT" checkout "$BRANCH"
STATUS=$?

if [ $STATUS ]
then
	"$GIT" reset --hard "origin/$BRANCH"
	STATUS=$?
fi

if [ $STATUS ]
then
	"$GIT" submodule update --quiet --init --recursive >> "$GIT_LOG_FILE"
	STATUS=$?
fi

if [ ! $STATUS ]
then
	echo "Update failed: " > $DIAGNOSTICS_FILE
	cat $GIT_LOG_FILE >> $DIAGNOSTICS_FILE
	echo $STATUS
	fail "Code update failed."
fi


# Get last revision.
if [ ! -e $LAST_REVISION_FILE ]
then
	LAST_REVISION=0
else
	LAST_REVISION=`head -n 1 "$LAST_REVISION_FILE"`
fi


# Get current revision.
CURRENT_REVISION=`"$GIT" rev-parse --short HEAD`
if [ ! $? ]
then
	fail "Could not get revision hash."
fi

if [ $LAST_REVISION == $CURRENT_REVISION ]
then
	report "Oolite nightly unchanged" "No change, still at revision $LAST_REVISION."
	exit 0
fi

echo "Updated from revision $LAST_REVISION to $CURRENT_REVISION, building..."


# Delete existing build products so no old files are left lying around.
if [ -e $OOLITE_APP_PKG ]
then
	rm -rf $OOLITE_APP_PKG
fi


# Nastytacular: overwrite the oolite-snapshot.xcconfig file to generate the nightly watermark macros.
# The backslash jungle builds a string like -DOOLITE_SNAPSHOT_VERSION="\"1.77.1-130705\"".
DATESTAMP=`date "+%y%m%d"`
echo "SNAPSHOT_MACROS= -DSNAPSHOT_BUILD=1 -DOOLITE_SNAPSHOT_VERSION=\"\\\"$OOLITE_VERSION-$DATESTAMP\\\"\"" > src/Cocoa/oolite-snapshot.xcconfig

# Buildez la vache!
xcodebuild clean build -project Oolite.xcodeproj -target "Build All" -configuration $CONFIGURATION RUN_CLANG_STATIC_ANALYZER=NO >$STDOUT_FILE 2>$STDERR_FILE

# Generate status and diagnostics files.
grep "^[^\ ]" $STDOUT_FILE > $STATUS_FILE
grep -e "warning:" -e "error:" $STDOUT_FILE > $DIAGNOSTICS_FILE


# Set last revision regardless of success or failure, on the basis that a
# failed build isn't likely to suddenly work if you just retry it a day later.
echo $CURRENT_REVISION > $LAST_REVISION_FILE


# Check for failure.
grep -e "^\*\* BUILD FAILED \*\*$" $STDERR_FILE
if [ $? -ne 1 ]
then
	ERROR_COUNT=`grep "error:" $STDOUT_FILE | wc -l | tr -d " "`
	WARNING_COUNT=`grep "warning:" $STDOUT_FILE | wc -l | tr -d " "`
	fail "Build failed with $ERROR_COUNT errors and $WARNING_COUNT warnings."
fi


# Write changelog.
if [ $LAST_REVISION != 0 ]
then
	"$GIT" log --pretty=format:"%h %an %ad %s" --no-merges $LAST_REVISION..$CURRENT_REVISION > $CHANGELOG_FILE
else
	echo "Initial checkout." > $CHANGELOG_FILE
fi

mv $SUCCESS_REVISION_FILE $PREVIOUS_SUCCESS_REVISION_FILE
echo $CURRENT_REVISION > $SUCCESS_REVISION_FILE


# Keep logs of latest successful build.
if [ -e $LOG_SUCCESS ]
then
	rm -rf $LOG_SUCCESS
fi
cp -R $LOG $LOG_SUCCESS


# Pack up a zip file.
if ! echo "$OOLITE_VERSION" | grep "[0-9]*\.[0-9]*\.[0-9]*" > /dev/null
then
	OOLITE_VERSION="$OOLITE_VERSION.0"
fi

FULLVERSION=$OOLITE_VERSION.$DATESTAMP-dev
echo "Packaging nightly $FULLVERSION..."

PACKAGE_NAME=Oolite-nightly-$FULLVERSION
PACKAGE_DIR=$VAR/$PACKAGE_NAME/
ADDONS_DIR=$PACKAGE_DIR/AddOns/
ZIP_NAME=oolite-trunk-$FULLVERSION.mac.zip
echo $ZIP_NAME > "$LATEST_NAME_FILE"

mkdir $PACKAGE_DIR
cp -R $OOLITE_APP_PKG $PACKAGE_DIR
mkdir $ADDONS_DIR
cp -R $DEBUG_OXP_PKG $ADDONS_DIR

pushd $VAR > /dev/null
"$DITTO" -ck --noqtn --noacl --nocache --zlibCompressionLevel 9 "$PACKAGE_NAME" "$ZIP_NAME"
if [ ! $? ]
then
	fail "Could not create zip archive (ditto failed with exit code $?)."
fi
rm -rf $PACKAGE_NAME
popd > /dev/null


# ftp_url should contain a URL to an upload directory.
# ftp_credentials should contain command line arguments for curl authentication,
# such as -u user:password.
if [ -e $FTP_URL_FILE ] && [ -e $FTP_CREDENTIALS_FILE ]
then
	FTP_URL=`head -n 1 "$FTP_URL_FILE"`
	FTP_CREDENTIALS=`head -n 1 "$FTP_CREDENTIALS_FILE"`
	FTP_INFO_SET=1
else
	FTP_INFO_SET=0
fi


# Record date of this momentous event.
date > $LAST_UPDATED_FILE

if [ ! -e $VAR/$ZIP_NAME ]
then
	fail "Archive was not made for some reason."
fi

if [ $FTP_INFO_SET -eq 0 ]
then
	report "Oolite nightly success" "Build succeeded, but ftp_url and/or ftp_credentials are missing, so data cannot be uploaded."
	exit 0
fi


echo "Uploading $ZIP_NAME..."
"$CURL" "-#" $FTP_CREDENTIALS -T "$VAR/$ZIP_NAME" "$FTP_URL/$ZIP_NAME"
if [ ! $? ]
then
	echo ""
	fail "Upload failed ($?)."
fi

echo ""
echo "Uploading metadata..."
"$CURL" --silent $FTP_CREDENTIALS -T "$LAST_UPDATED_FILE" "$FTP_URL/last_updated"
"$CURL" --silent $FTP_CREDENTIALS -T "$CHANGELOG_FILE" "$FTP_URL/change_log"
"$CURL" --silent $FTP_CREDENTIALS -T "$DIAGNOSTICS_FILE" "$FTP_URL/diagnostics"
"$CURL" --silent $FTP_CREDENTIALS -T "$STATUS_FILE" "$FTP_URL/build_log"
"$CURL" --silent $FTP_CREDENTIALS -T "$LAST_REVISION_FILE" "$FTP_URL/revision"
"$CURL" --silent $FTP_CREDENTIALS -T "$PREVIOUS_SUCCESS_REVISION_FILE" "$FTP_URL/previous_successful"
"$CURL" --silent $FTP_CREDENTIALS -T "$LATEST_NAME_FILE" "$FTP_URL/latest"


rm $VAR/$ZIP_NAME
report $"Oolite nightly success" "Successfully built commit $CURRENT_REVISION and uploaded as $ZIP_NAME."
