scripts/source/files/generate_function_manifest.sh — scans every .sh in
scripts/ (skip-list matches generate_arrays.sh, plus excludes peer_shell.sh
which is a standalone forced-command target) and emits
scripts/source/files/arrays/function_manifest.sh:
declare -gA LP_FN_MAP=(
[acquireSingletonLock]="crontab/task/crontab_task_processor.sh"
[adoptDockerSubnet]="checks/requirements/check_docker_network.sh"
... # 698 entries
)
LP_EAGER_FILES=(
"backup/db/backup_db.sh"
"source/files/arrays/files_app.sh"
... # 32 entries (~7% of files)
)
The lazy loader (Phase 3) consumes LP_FN_MAP to install autoload stubs of
the form `name() { source "$LP_FN_MAP[name]"; name "$@"; }`. First call
sources the real file, which redefines the stub with the real body;
subsequent calls hit the real one. LP_EAGER_FILES enumerates files with
top-level side effects (variable assignments, source calls, bare commands
outside any function) — those MUST always source so the side effects fire.
Heuristic correctness, in order of importance:
- Function header detection requires EMPTY parens (`name()`), not just
`name(` — otherwise lines like `if (...)`, `for (...)`, `while (...)`
in embedded awk/perl get misread as bash function defs.
- Handles three function styles: `name() {` (same line), `name()\n{`
(LibrePortal convention), and one-liners `name() { body; }`.
- Tracks { } balance for inside-function depth, with the safe fallback that
ambiguous cases get marked eager (false positive = no behaviour change;
false negative would skip a needed source).
- Files containing embedded awk/perl with their own { } blocks (about 6 of
them: cli_debug_commands.sh, crontab_task_processor.sh, backup_db.sh,
backup_files.sh, etc.) get false-positive flagged eager — acceptable
because they just stay eager-loaded, matching today's behaviour.
- Collisions report to stderr (last-write wins, same as eager-load
semantics); no collisions found in the current tree.
Wiring:
- lpRegenArrays (`libreportal regen arrays`) now also runs the manifest
generator when the existing arrays need regen, keeping the two in sync.
- update.sh's quick-deploy regen step does the same after copying files
to the live install. Best-effort: failures don't abort because lazy
loading is opt-in (LP_LAZY=1) in Phase 3 and not the default yet.
Scanned: 454 files, indexed 698 function definitions, 32 eager (9 real,
23 auto-generated arrays + the manifest itself). 0 name collisions.
No behaviour change in this commit — the manifest is just data the loader
in Phase 3 will use. The default eager loading path is untouched.
Signed-off-by: librelad <librelad@digitalangels.vip>
90 lines
3.6 KiB
Bash
90 lines
3.6 KiB
Bash
#!/bin/bash
|
|
|
|
# Unified regeneration front door.
|
|
#
|
|
# One entry point that rebuilds the file-derived artifacts whose SOURCES changed,
|
|
# so callers (the CLI, the task-processor poll, a deploy) don't have to know which
|
|
# generator owns what. Runs as the manager and writes only into the data dirs — no
|
|
# privilege needed.
|
|
#
|
|
# lpRegen [scope] [--force]
|
|
# scope: all (default) | webui | arrays
|
|
#
|
|
# Self-heal: a stage runs only when a source file is newer than its artifact (or
|
|
# the artifact is missing), unless --force. The check is a cheap `find -newer`
|
|
# mtime compare — there is no watcher/daemon. The natural triggers (install,
|
|
# config change, deploy, the periodic task-processor poll) call this; it no-ops
|
|
# when nothing is stale, so it is safe to call often.
|
|
#
|
|
# webui — apps.json / apps-tools.json etc. from containers/<app>/{*.config,tools/*.tools.json}
|
|
# arrays — the static files_*.sh source arrays from scripts/** (a dev/build concern;
|
|
# a normal install never adds core scripts, so this is a no-op there)
|
|
|
|
# Is $artifact stale relative to the given find expression? Returns 0 (stale) when
|
|
# the artifact is missing or any matched source file is newer than it.
|
|
_lpRegenStale() {
|
|
local artifact="$1"; shift
|
|
[[ -f "$artifact" ]] || return 0
|
|
find "$@" -newer "$artifact" -print -quit 2>/dev/null | grep -q .
|
|
}
|
|
|
|
lpRegenWebui() {
|
|
local force="$1"
|
|
local gen="${containers_dir}libreportal/frontend/data/apps/generated"
|
|
local apps_json="$gen/apps.json"
|
|
local tools_json="$gen/apps-tools.json"
|
|
|
|
if [[ "$force" == "force" ]] \
|
|
|| _lpRegenStale "$apps_json" "$install_containers_dir" -maxdepth 2 -name '*.config' \
|
|
|| _lpRegenStale "$tools_json" "$install_containers_dir" -maxdepth 3 -path '*/tools/*.tools.json'; then
|
|
# Sources changed (e.g. an app folder was dropped in) — do the full,
|
|
# debounced refresh so the new app appears everywhere. Force past the
|
|
# updater's own debounce: we have already established there is real work.
|
|
WEBUI_UPDATER_FORCE=1 webuiLibrePortalUpdate
|
|
return $?
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
lpRegenArrays() {
|
|
local force="$1"
|
|
local arrays_dir="${install_scripts_dir}source/files/arrays"
|
|
local gen_script="${install_scripts_dir}source/files/generate_arrays.sh"
|
|
local manifest_script="${install_scripts_dir}source/files/generate_function_manifest.sh"
|
|
local newest_array
|
|
newest_array="$(ls -t "$arrays_dir"/files_*.sh 2>/dev/null | head -1)"
|
|
|
|
if [[ "$force" == "force" ]] || [[ -z "$newest_array" ]] \
|
|
|| find "$install_scripts_dir" -name '*.sh' -newer "$newest_array" -print -quit 2>/dev/null | grep -q .; then
|
|
local rc=0
|
|
[[ -f "$gen_script" ]] && "$gen_script" run || rc=$?
|
|
# Function manifest tracks the same source set — keep them in sync.
|
|
# Failures here don't abort: lazy-load is opt-in via LP_LAZY=1, so a
|
|
# stale manifest just means lazy mode might miss a recently-added
|
|
# function. Eager mode (the default) is unaffected.
|
|
[[ -f "$manifest_script" ]] && "$manifest_script" run >/dev/null 2>&1 || true
|
|
return $rc
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
lpRegen() {
|
|
local scope="all" force=""
|
|
local a
|
|
for a in "$@"; do
|
|
case "$a" in
|
|
--force|-f|force) force="force" ;;
|
|
all|webui|arrays) scope="$a" ;;
|
|
*) isNotice "Unknown regen argument: $a (use: all|webui|arrays [--force])" ;;
|
|
esac
|
|
done
|
|
|
|
local rc=0
|
|
case "$scope" in
|
|
arrays) lpRegenArrays "$force" || rc=$? ;;
|
|
webui) lpRegenWebui "$force" || rc=$? ;;
|
|
all) lpRegenArrays "$force" || rc=$?; lpRegenWebui "$force" || rc=$? ;;
|
|
esac
|
|
return $rc
|
|
}
|