blob: da0f887285c6ffea5930651f491a2baa3214d03e [file] [log] [blame]
#! /bin/bash
set -e
set -x
function notifyIfPossible() {
if which osascript > /dev/null; then
osascript -e 'display notification "Background build finished." with title "Buck"'
elif which notify-send > /dev/null; then
notify-send "Buck" "Background build finished."
fi
}
function getScript() {
local bash_source="${BASH_SOURCE[0]}"
local source_dir="$( dirname "${bash_source}" )"
while [ -h "${source_dir}" ]
do
bash_source="$(readlink "$SOURCE")"
[[ "${bash_source}" != /* ]] && bash_source="${source_dir}/${bash_source}"
source_dir="$( cd -P "$( dirname "${bash_source}" )" && pwd )"
done
echo "$( cd -P "$( dirname "${bash_source}" )" && pwd )/$( basename "${BASH_SOURCE[0]}" )"
}
function syncDirectory() {
local sourceDirectory=$(printf %q "$1")
local destinationDirectory=$(printf %q "$2")
echo >&2 "=== Syncing master and slave directories ==="
(
# Save the state of source directory
cd ${sourceDirectory}
local currentSourceHash=$(git rev-parse HEAD)
local currentSourceBranch=$(git rev-parse --abbrev-ref HEAD)
local patchFile=$(mktemp -t patch.XXXXX)
git diff > ${patchFile}
if [ ! -d ${destinationDirectory} ]; then
(
echo >&2 "=== Creating slave directory ==="
mkdir -p ${destinationDirectory}
cd ${destinationDirectory}
git init .
)
fi
# Move to and clean the destination directory
cd ${destinationDirectory}
git clean -fd
if ! git rev-parse --quiet --verify ${currentSourceHash}^{commit} > /dev/null; then
echo >&2 "=== Fetching from master to slave ==="
git fetch --depth=1 file://${sourceDirectory} ${currentSourceBranch}
fi
git reset --hard ${currentSourceHash}
if [ -s ${patchFile} ]; then
git apply ${patchFile}
fi
# Cleanup
rm ${patchFile}
)
}
function onChange() {
local sourceDirectory=$(printf %q "$1")
local destinationDirectory=$(printf %q "$2")
local target=$(printf %q "$3")
syncDirectory ${sourceDirectory} ${destinationDirectory}
(
cd ${destinationDirectory}
cat << EOF > .buckconfig.local
[cache]
dir = ${sourceDirectory}/buck-cache
dir_mode = readwrite
EOF
echo >&2 "=== Building ${target} ==="
mkdir -p ${sourceDirectory}/.buckd
BUCK_EXTRA_JAVA_ARGS=-Dbuck.autobuild=1 nice buck build ${target} &
local buckd_pid=$!
echo ${buckd_pid} > ${sourceDirectory}/.buckd/autobuild.pid
wait ${buckd_pid}
notifyIfPossible
rm -rf ${sourceDirectory}/.buckd/autobuild.pid
)
}
function createTrigger() {
local sourceDirectory=$(printf %q "$1")
local destinationDirectory=$(printf %q "$2")
local target=$(printf %q "$3")
echo >&2 "=== Creating Watchman Trigger ==="
if [ ! -d ${sourceDirectory}/.git ]; then
echo >&2 "Sorry, autobuilds only work in git repos for now!"
fi
onChange ${sourceDirectory} ${destinationDirectory} ${target}
watchman trigger-del ${sourceDirectory} buck_speculate
echo $(getScript)
watchman -j <<-EOT
["trigger", "${sourceDirectory}", {
"name": "buck_speculate",
"expression": ["allof", ["type", "f"], ["not", ["pcre", "(^.git|pyc\$|swp\$|swo\$)", "wholename"]]],
"command": ["$(getScript)", "change", "${sourceDirectory}", "${destinationDirectory}", "${target}"]
}]
EOT
}
function usage() {
cat <<- EOF
usage: buck_autobuild.sh watch <Source Directory> <Workspace Directory> <Target to Build>
Script is used to build a buck target on save in a safe manner.
The workspace directory will be a mirror of the source directory.
EOF
}
function main() {
if [ $# -lt 4 ]; then
usage
exit 1
fi
local command=$(printf %q "$1"); shift
local sourceDirectory=$(printf %q "$1"); shift
local destinationDirectory=$(printf %q "$1"); shift
local target=$(printf %q "$1"); shift
case ${command} in
change)
set -x
onChange ${sourceDirectory} ${destinationDirectory} ${target}
;;
watch)
createTrigger ${sourceDirectory} ${destinationDirectory} ${target}
;;
esac
echo "Finished Speculative Build!"
}
main $@