update: hand over cleanly from updates older than 2026-10-19
013acac's update (in use 2026-08-14 to 2026-10-19) copies the new update over itself with sudo cp while bash is still reading it, so bash reads on from byte 1484 of the new file: today, the middle of the logo, and the update dies with a syntax error. Put a line at exactly that byte that execs the new update, in a here-document a normal run skips. Found by 30-upgrade-from-baseline at ca658dc; the test replays 013acac's update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -166,3 +166,20 @@ ran() {
|
||||
[ "$status" -eq 1 ]
|
||||
[ ! -e "$RAN" ]
|
||||
}
|
||||
|
||||
@test "an update from before 2026-10-19 that copies this one over itself hands over to it" {
|
||||
# 013acac's update: sudo cp overwrites the file bash is still reading, and
|
||||
# bash reads on in the new one from where it was
|
||||
[ "$(/usr/bin/git -C "$REPO" rev-parse --is-shallow-repository)" = false ] \
|
||||
|| skip "needs update's history"
|
||||
/usr/bin/git -C "$REPO" show 013acac:update > "$HOME/.local/bin/update"
|
||||
chmod +x "$HOME/.local/bin/update"
|
||||
stub sudo '[ "$1" = cp ] && exec "$@"; exit 0'
|
||||
hook 10-a 'echo a >> "$RAN"'
|
||||
|
||||
run "$HOME/.local/bin/update"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" != *"command not found"* ]]
|
||||
[[ "$output" == *"Done."* ]]
|
||||
ran a
|
||||
}
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Updates from before 2026-10-19 (013acac's) copy this file over themselves
|
||||
# while bash is still reading them, then read on from byte 1484 of the new copy.
|
||||
# The exec line below starts at exactly that byte, so they run this update
|
||||
# afresh; the rest of the block pads it into place, and in a normal run the
|
||||
# block is a here-document nothing reads. Keep the exec line at byte 1484:
|
||||
# tests/update.bats checks it.
|
||||
: << 'FROM_OLD_UPDATE'
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
This block is padding for old updates. This block is padding for old updates.
|
||||
...................
|
||||
exec ~/.local/bin/update
|
||||
FROM_OLD_UPDATE
|
||||
|
||||
# The whole script is wrapped in { ...; exit; } so bash parses all of it before
|
||||
# running anything. That way, replacing this file mid-run (e.g. by git pull and
|
||||
# the copy below) can't make the running copy read a mix of old and new text.
|
||||
|
||||
Reference in New Issue
Block a user