Skip to content

Instantly share code, notes, and snippets.

@GMNGeoffrey
Last active May 15, 2023 22:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GMNGeoffrey/3b664c4fd31dda298cbf84cfc29ec30a to your computer and use it in GitHub Desktop.
Save GMNGeoffrey/3b664c4fd31dda298cbf84cfc29ec30a to your computer and use it in GitHub Desktop.
Interactive Builds: git-watch, cool-bazel, ibazel

Some little scripts I've found useful for development. git-watch retriggers a command when your git repo changes, so can give interactive rebuilds like ibazel except I found that https://github.com/bazelbuild/bazel-watcher didn't work for me at all. This is also completely agnostic to the command, so can be used with CMake as well, for instance.

#!/bin/bash
# Copyright 2021 Google LLC.
# SPDX-License-Identifier: Apache-2.0
# https://c.tenor.com/w6fXtUDvwoYAAAAC/can-you-just-be-cool-just-once.gif
set -euo pipefail
COOL_BAZEL_RC_FILE="$(mktemp --tmpdir cool-bazel.XXXXX.bazelrc)"
function cleanup() {
rm "${COOL_BAZEL_RC_FILE}"
}
trap cleanup EXIT
COPTS=(
"-Wno-unused"
)
COPTS_STRING="$(IFS="," ; echo "${COPTS[*]}")"
readarray -t EDITED < <(git diff --name-only --diff-filter=AM --ignore-submodules | grep -i '.*\.h$\|.*\.c$\|.*\.cc$\|.*\.cpp$' | sed 's/\./\\\./g')
# Prefix with `^` anchor
EDITED=( "${EDITED[@]/#/^}" )
# Suffix with `$` anchor
EDITED=( "${EDITED[@]/%/$}" )
# Join on `,`
EDITED_STRING="$(IFS="," ; echo "${EDITED[*]}")"
if (( "${#EDITED[@]}" )); then
echo "build --per_file_copt=${EDITED_STRING}@${COPTS_STRING}" > "${COOL_BAZEL_RC_FILE}"
fi
bazel --bazelrc="${COOL_BAZEL_RC_FILE}" "$@"
# -*- sh -*-
# Copyright 2021 Google LLC.
# SPDX-License-Identifier: Apache-2.0
# Just copy Bazel autocompletion
complete -F _bazel__complete -o nospace cool-bazel
complete -F _bazel__complete -o nospace ibazel
#!/bin/bash
# Copyright 2021 Google LLC.
# SPDX-License-Identifier: Apache-2.0
set -u
function check_exists() {
if ! type "$1" > /dev/null 2>&1; then
echo "$1 command not found. Is it installed?"
exit 1
fi
}
check_exists git
check_exists inotifywait
GIT_ROOT="$(git rev-parse --show-toplevel)"
if (( "$?" != 0 )); then
echo "Failed to find git root. Are you in a git directory?"
exit 1
fi
echo "Running initial command before establishing watches."
bash -c "$@" &
PID="$!"
declare -a inotify_command=(
inotifywait
# inotifywait will output info about setting up watches, but we don't actually
# wait for it to finish set up before running our first command. I couldn't
# find a good way to do so and the command we run may stomp on the
# "Watches established" message, so we avoid outputtting the message at all.
--quiet
--event=modify,move,create,delete,attrib
--monitor
--recursive
# Output the full filepath, watched directory + filename
--format="%w%f"
# Watch everything under the git root
"${GIT_ROOT?}"
# Except the .git directory (this is not gitignored)
"@${GIT_ROOT?}/.git"
)
while read -r filepath; do
if ! git check-ignore -q "${filepath?}"; then
kill "${PID?}" > /dev/null 2>&1
# Wait for the process to actually exit.
# Technically this can hang forever if the process doesn't respond properly
# to SIGTERM. Hopefully the user will just Ctrl+C at that point. Suggestions
# for how to add a deadline to this welcome. `timeout wait` doesn't work
# since wait is a shell builtin.
wait "${PID?}"
printf "\n\nWatched file ${filepath} changed. Restarting\n\n"
bash -c "$@" &
PID="$!"
fi
done < <("${inotify_command[@]}")
#!/bin/bash
# Copyright 2021 Google LLC.
# SPDX-License-Identifier: Apache-2.0
# *Not* $@ which results in commands ending up like
# `bash -c 'cool-bazel test' //target/...`
# and building nothing
git watch "cool-bazel $*"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment