The _hermes-python prologue compared uv.lock / pyproject.toml / pm/lock.json against facts.json with `-nt`. facts.json is only rewritten on a real sync, so a checkout that rewrites an input without changing it left the input newer forever: every run from an activated shell re-sourced activate (~370ms instead of ~13ms). pm now records, after every successful full-closure install (no-op syncs included), a stamp per input under installs/<key>/inputs carrying the exact mtime the install was verified against, snapshotted before installing so an input edited mid-install still reads as stale. The prologue re-activates when any input's mtime differs from its stamp in either direction (branch switches can move it backwards), when an input is missing, or when there are no stamps. It globs the stamp dir, so pm owns the only input list. Also read pyvenv.cfg as utf-8-sig (footgun lane, same file).
59 lines
2.2 KiB
Bash
Executable File
59 lines
2.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Run a repo Python script under the activated Hermes environment.
|
|
#
|
|
# Shebang target for POSIX scripts:
|
|
# #!/usr/bin/env -S bash -c 'exec "$BASH" "$(dirname "$0")/_hermes-python" "$0" "$@"'
|
|
#
|
|
# The kernel appends the invoking script, so `$1` is the Python file to run
|
|
# and `$@` its arguments. Activates when there is no environment to inherit, or
|
|
# when the inherited one predates its inputs; then execs the interpreter on the
|
|
# same file, so tracebacks and __file__ point at the real script.
|
|
set -u
|
|
|
|
target=${1:-}
|
|
if [ -z "$target" ]; then
|
|
printf 'usage: %s <script.py> [args...]\n' "$0" >&2
|
|
exit 2
|
|
fi
|
|
shift
|
|
|
|
_here="$(cd "$(dirname "$target")" && pwd)"
|
|
while [ "$_here" != / ] && [ ! -f "$_here/activate" ]; do _here="$(dirname "$_here")"; done
|
|
if [ ! -f "$_here/activate" ]; then
|
|
printf '%s: no activate script above %s\n' "$0" "$target" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# pm records, beside the installed-state file named by __HERMES_ACTIVATED, one
|
|
# stamp per dependency input carrying the exact mtime that input had when the
|
|
# install was last verified against it (pm.environments.record_activation_inputs).
|
|
# Any input whose mtime DIFFERS from its stamp — newer or older, since a branch
|
|
# switch can move it either way — means the inherited environment may not match
|
|
# its inputs. `-nt`/`-ot` are bash builtins, so this costs no process spawn, and
|
|
# every successful activation re-records, so one re-activation settles it. No
|
|
# stamps (an install from before stamps existed), a missing input, a dangling
|
|
# sentinel or a legacy literal "1" all activate.
|
|
_needs_activation=1
|
|
if [ -n "${__HERMES_ACTIVATED:-}" ] && [ -e "${__HERMES_ACTIVATED}" ]; then
|
|
_stamps="${__HERMES_ACTIVATED%/*}/inputs"
|
|
_needs_activation=0
|
|
_stamped=0
|
|
for _stamp in "$_stamps"/* "$_stamps"/*/*; do
|
|
[ -f "$_stamp" ] || continue
|
|
_stamped=1
|
|
_input="$_here/${_stamp#"$_stamps"/}"
|
|
if [ ! -e "$_input" ] || [ "$_input" -nt "$_stamp" ] || [ "$_input" -ot "$_stamp" ]; then
|
|
_needs_activation=1
|
|
break
|
|
fi
|
|
done
|
|
[ "$_stamped" = 1 ] || _needs_activation=1
|
|
fi
|
|
|
|
if [ "$_needs_activation" = 1 ]; then
|
|
# shellcheck source=/dev/null
|
|
. "$_here/activate" || exit 1
|
|
fi
|
|
|
|
exec python3 "$target" "$@"
|