install_leechblock: deploy lib/ alongside the entry script
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run

The pacman-wrapper installer copied install_leechblock.sh to
/usr/local/share/digital_wellbeing/ along with three data files, but no
lib/. After the split in 1dceca66 the deployed entry script sources
every install phase from lib/ beside itself, so deploying it without
that directory leaves a copy that dies on its first `source`.

This is not hypothetical: the live deployed copy was found in exactly
that state at the start of this work -- the previous session's split
entry script, deployed and then left behind when the repo was reverted.
It failed on every invocation. It has been repaired and now carries the
libs.

The glob is leechblock_*.sh rather than *.sh because lib/ is shared with
unrelated music_* helpers that have no business in /usr/local. The copy
mirrors rather than merges, so a lib deleted upstream does not linger.

Verified against a fake root and then for real: the deployed copy runs,
its sha256 matches the repo, and inject_default_config resolves the
defaults JSON and the seeder from the deploy root rather than from lib/.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Krzysztof Rudnicki 2026-08-21 15:44:10 +02:00
parent fbec46567d
commit baeb1119d0
3 changed files with 68 additions and 0 deletions

View File

@ -0,0 +1,51 @@
{
"intent": "Teach the pacman-wrapper installer to deploy install_leechblock.sh's lib/ directory alongside the entry script, so the deployed copy at /usr/local/share/digital_wellbeing/ can actually run after the split.",
"scope": [
"linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/lib/protect_and_extras.sh: install_leechblock_payload also mirrors lib/",
"linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/install_pacman_wrapper.sh: two new path variables",
"Non-goal: any change to install_leechblock.sh or its libs -- they shipped in 1dceca66 and are untouched here"
],
"changes": [
"install_leechblock_payload now mirrors the four leechblock_*.sh libs into ${LEECHBLOCK_INSTALL_DIR}/lib and marks them executable. Before this, the deployer copied the entry script and three data files but no lib/, so after the split the deployed installer would die on its first `source`.",
"The copy is a mirror (rm -rf then recreate), not a merge, so a lib removed upstream does not linger in the deployed tree.",
"The glob is leechblock_*.sh, not *.sh, on purpose: lib/ is shared with unrelated music_detect.sh / music_monitor.sh / music_status.sh helpers that this payload has no business shipping to /usr/local.",
"A missing lib/ now emits an explicit warning that the deployed installer will not run, rather than silently deploying a broken entry script."
],
"verification": [
{
"command": "install_leechblock_payload against a fake root (/tmp/fakeroot) with the real sources",
"result": "pass",
"evidence": "Deployed tree contains exactly install_leechblock.sh, leechblock_defaults.json, seed_leechblock_storage.js and lib/{browsers,config,fetch,firefox}.sh -- the four leechblock libs and none of the three music_* helpers."
},
{
"command": "bash /tmp/fakeroot/digital_wellbeing/install_leechblock.sh --help",
"result": "pass",
"evidence": "Exit 0 with the normal usage text, proving the deployed entry script resolves its libs from the deployed lib/ rather than dying on `source`."
},
{
"command": "inject_default_config in the deployed layout with a node stub",
"result": "pass",
"evidence": "DEFAULTS_SRC and the seeder resolved to /tmp/fakeroot/digital_wellbeing/*, not to lib/. This is the specific silent failure the SCRIPT_DIR fix in 1dceca66 targets, now confirmed in the deployed layout as well as the repo tree."
},
{
"command": "Real deploy to /usr/local/share/digital_wellbeing/ + bash <deployed> --help + sha256sum comparison",
"result": "pass",
"evidence": "Live deployed copy runs (exit 0, usage text) and its sha256 is identical to the repo's install_leechblock.sh. The deployed lib/ holds the four libs, executable."
},
{
"command": "shellcheck + shfmt idempotence + bash -n on both changed files",
"result": "pass",
"evidence": "shellcheck rc=0, shfmt -w is a no-op on both, both parse. 70 and 130 lines, under the 250-line cap."
}
],
"risks": [
"This commit closes a window that the split itself opened: between 1dceca66 and this change, running the deployer would have overwritten a working deployed copy with a split entry script and no libs. The live copy was repaired by hand during this session and is now deployed correctly from the fixed path.",
"The deployer is reached via /etc/pacman.d/hooks/96-restore-pkg-wrappers.hook -> rewrap_pkg_managers.sh on pacman/pacman-git transactions, so the window was real but narrow.",
"npm install --prefix still runs against LEECHBLOCK_INSTALL_DIR when package.json is present; unchanged by this commit."
],
"rollback": [
"git revert this commit; install_leechblock_payload returns to copying the entry script without lib/.",
"After rollback the deployed installer would break again on its next deploy, so also either revert 1dceca66 or hand-restore the pre-split entry script to /usr/local/share/digital_wellbeing/.",
"Validate with: bash /usr/local/share/digital_wellbeing/install_leechblock.sh --help (expect exit 0)."
]
}

View File

@ -59,6 +59,8 @@ LEECHBLOCK_INSTALL_DIR="/usr/local/share/digital_wellbeing"
LEECHBLOCK_INSTALLER_DEST="${LEECHBLOCK_INSTALL_DIR}/install_leechblock.sh"
LEECHBLOCK_DEFAULTS_DEST="${LEECHBLOCK_INSTALL_DIR}/leechblock_defaults.json"
LEECHBLOCK_SEEDER_DEST="${LEECHBLOCK_INSTALL_DIR}/seed_leechblock_storage.js"
LEECHBLOCK_LIB_SOURCE="$(dirname "$0")/../lib"
LEECHBLOCK_LIB_DEST="${LEECHBLOCK_INSTALL_DIR}/lib"
VBOX_ENFORCE_SOURCE="$(dirname "$0")/../virtualbox/enforce_vbox_hosts.sh"
VBOX_INSTALL_DIR="/usr/local/share/digital_wellbeing/virtualbox"
VBOX_ENFORCE_DEST="${VBOX_INSTALL_DIR}/enforce_vbox_hosts.sh"

View File

@ -22,6 +22,21 @@ install_leechblock_payload() {
echo -e "${BLUE}Installing LeechBlock installer to ${LEECHBLOCK_INSTALLER_DEST}...${NC}"
cp "$LEECHBLOCK_INSTALLER_SOURCE" "$LEECHBLOCK_INSTALLER_DEST"
chmod +x "$LEECHBLOCK_INSTALLER_DEST"
# The installer sources every install phase from lib/ beside itself, so
# the directory has to travel with it. Deploying the entry script alone
# leaves a copy that dies on its first `source`. Mirror rather than
# merge, so a lib deleted upstream does not linger here.
if [ -d "$LEECHBLOCK_LIB_SOURCE" ]; then
rm -rf "$LEECHBLOCK_LIB_DEST"
mkdir -p "$LEECHBLOCK_LIB_DEST"
# Only the leechblock_* libs: lib/ is shared with unrelated scripts
# (the music_* helpers) that this payload has no business shipping.
cp "$LEECHBLOCK_LIB_SOURCE"/leechblock_*.sh "$LEECHBLOCK_LIB_DEST"/
chmod +x "$LEECHBLOCK_LIB_DEST"/leechblock_*.sh
echo -e "${GREEN}LeechBlock libs deployed to ${LEECHBLOCK_LIB_DEST}${NC}"
else
echo -e "${YELLOW}LeechBlock lib/ not found at ${LEECHBLOCK_LIB_SOURCE}; the deployed installer will not run${NC}"
fi
echo -e "${GREEN}LeechBlock installer deployed to ${LEECHBLOCK_INSTALLER_DEST}${NC}"
else
echo -e "${YELLOW}LeechBlock installer not found at ${LEECHBLOCK_INSTALLER_SOURCE}, skipping...${NC}"