Skip to content

Instantly share code, notes, and snippets.

@timmc-edx
Created October 19, 2023 20:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timmc-edx/a0ba7aac8ab1ae4e5e54ea9695c569f3 to your computer and use it in GitHub Desktop.
Save timmc-edx/a0ba7aac8ab1ae4e5e54ea9695c569f3 to your computer and use it in GitHub Desktop.
Snapshot of make-requirements-if-needed.sh
#!/usr/bin/env bash
# Run `make requirements` if virtualenv or requirements dir has changed since
# last run.
set -eu -o pipefail
if [[ -z "${VIRTUAL_ENV:-}" ]]; then
echo >&2 "Not in a virtualenv"
exit 1
fi
if [[ ! -d "requirements" ]]; then
echo >&2 "./requirements/ missing from current dir"
exit 1
fi
# Bare filename to write at root of virtualenv.
hashfile_name="deps-venv.chk"
# Actual path
hashfile_path="$VIRTUAL_ENV/$hashfile_name"
function fingerprint_data_venv() {
# The virtualenv is large, so do a fingerprint that is fast. And
# it isn't directly affected by git checkouts, so we don't have to
# worry about spurious file modification time changes. Therefore,
# use file metadata rather than contents.
#
# For fingerprinting of these we include paths (sorted) with full
# metadata.
find "$VIRTUAL_ENV" -printf '%P %t %s %i %m %U %G\n' \
| grep -vP "^\\Q${hashfile_name}\\E " \
| sort
}
function fingerprint_data_reqs() {
# The requirements files are small, so we can use contents-based
# fingerprinting. These files also have their metadata changed by
# git branch switching, and we don't want the fingerprint to
# change just because we've switched branches and then switched
# back again. That's a reason to avoid using the metadata, even
# though it might be a little faster.
#
# All we need for fingerprinting are the file paths (in order)
# along with a hash of each file's contents.
find "./requirements/" -type f | sort | xargs -r sha256sum 2>/dev/null
}
function compute_fingerprint() {
# Combine the two fingerprint data sources and hash it all together
(fingerprint_data_venv && fingerprint_data_reqs) \
| sha256sum | head -c64
}
do_run=yes
if [[ -f "${hashfile_path}" ]]; then
prev_hash="$(cat -- "${hashfile_path}")"
cur_hash="$(compute_fingerprint)"
if [[ "$prev_hash" == "$cur_hash" ]]; then
echo >&2 "Dependency hashes match, skipping 'make requirements'"
do_run=no
else
echo >&2 "Dependency hashes do not match; running 'make requirements'"
echo >&2 "(prev=$prev_hash, cur=$cur_hash)"
fi
else
echo >&2 "Dependency hash file not found"
fi
if [[ "$do_run" == 'yes' ]]; then
make requirements
fi
compute_fingerprint > "${hashfile_path}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment