mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-09-10 18:34:18 +08:00
150 lines
9.3 KiB
Bash
Executable File
150 lines
9.3 KiB
Bash
Executable File
#!/bin/sh
|
|
# Push the footstrap theme to a HARDWARE router over ssh (containers use owlab).
|
|
# ONE theme, one luci.themes entry; layout (top/sidebar) is a client axis on the Footstrap tab of
|
|
# System -> System, not a theme entry. This registers the theme; it does NOT activate it.
|
|
set -e
|
|
|
|
R="${1:-router2512}"
|
|
N=footstrap
|
|
D="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
# cascade.css is generated from styles/ and is not in git. --dev keeps the comments so the
|
|
# file on the router still reads like the source.
|
|
"$D"/build-css.sh "$D/htdocs/luci-static/$N/cascade.css" --dev
|
|
|
|
ssh "$R" "mkdir -p /usr/share/ucode/luci/template/themes/$N \
|
|
/www/luci-static/$N \
|
|
"
|
|
|
|
# the ONE template (+ partials/). Sidebar and top bar are the same markup, morphed by
|
|
# :root[data-layout] — there is no second theme dir to copy.
|
|
scp -q "$D"/ucode/template/themes/$N/*.ut "$R":/usr/share/ucode/luci/template/themes/$N/
|
|
ssh "$R" "mkdir -p /usr/share/ucode/luci/template/themes/$N/partials"
|
|
scp -q "$D"/ucode/template/themes/$N/partials/*.ut "$R":/usr/share/ucode/luci/template/themes/$N/partials/
|
|
|
|
# shared static: cascade.css and the two logo files, which is all this directory holds. No
|
|
# wallpapers — the doodles this theme once downloaded from GitHub are gone, and nothing in the
|
|
# package fetches anything at run time; the Background axis paints an SVG the admin uploads.
|
|
scp -qr "$D"/htdocs/luci-static/$N/* "$R":/www/luci-static/$N/
|
|
|
|
# EVERY resource JS, by GLOB — never by name. This used to list the four files
|
|
# individually, so a FIFTH would be shipped by the package (luci.mk copies htdocs/
|
|
# wholesale) yet silently never reach the dev router — first tested after a release.
|
|
#
|
|
# A TAR OF THE TREE, not `scp *.js`: the flat glob does not descend, so anything a subdirectory
|
|
# holds shipped in the package (luci.mk copies htdocs/ wholesale) and reached the dev router never —
|
|
# the same class of miss the glob above was written to end, one directory level down. Every path
|
|
# under resources/ is ours to place.
|
|
tar -C "$D/htdocs/luci-static/resources" -cf - . | ssh "$R" "mkdir -p /www/luci-static/resources && tar -C /www/luci-static/resources -xf -"
|
|
|
|
# stamp the git-derived version into the deployed fs-version.js (the package does the same in
|
|
# Build/Prepare) so the Footstrap tab shows a real version instead of "(dev)". The FILE NAME is part
|
|
# of the contract: FS_VERSION lives in fs-version.js and moving it means changing every sed.
|
|
FS_V="$(git -C "$D" describe --tags --always 2>/dev/null | sed 's/^v//')"
|
|
# if-form, not `[ -n ] && ssh`: under `set -e` a bare `&&`-list whose LAST command fails is what
|
|
# aborts, so `[ -n "$FS_V" ] && ssh …` would take the sync down whenever git describe yielded
|
|
# nothing (a copied tree without .git). An `&&` guarding an ASSIGNMENT is a different shape and is
|
|
# safe. expr refuses a tag with sed- or shell-special characters rather than interpolating it.
|
|
if [ -n "$FS_V" ] && expr "$FS_V" : '[0-9A-Za-z._-]*$' >/dev/null; then
|
|
ssh "$R" "sed -i \"s#const FS_VERSION *= *'[^']*'#const FS_VERSION = '$FS_V'#\" /www/luci-static/resources/fs-version.js"
|
|
fi
|
|
|
|
# The catalogue. Nothing in Build/Prepare compiles it, and the release does not come from luci.mk
|
|
# either — owfeed bundles the catalogues inside the theme package — so a dev router gets them from
|
|
# nowhere unless this sync makes them. po2lmo is a luci-base host tool, absent from a dev machine
|
|
# by default, so this is best-effort: without it the strings stay English and the sync still
|
|
# succeeds. (Build it once from the pinned luci checkout: make -C modules/luci-base/src po2lmo —
|
|
# plural_formula.c is GENERATED by contrib/lemon, so a bare cc over the .c files cannot work.)
|
|
#
|
|
# The basename is `footstrap-theme`, matching owfeed.yml and NOT the po file's own name:
|
|
# lmo_load_catalog globs *.<lang>.lmo so any basename loads, and a v0.8.4 router still owns
|
|
# footstrap.ru.lmo through the old luci-i18n package, where the same path is a file conflict.
|
|
if command -v po2lmo >/dev/null 2>&1; then
|
|
ssh "$R" "mkdir -p /usr/lib/lua/luci/i18n"
|
|
for po in "$D"/po/*/*.po; do
|
|
[ -e "$po" ] || continue
|
|
lang="$(basename "$(dirname "$po")")"
|
|
po2lmo "$po" "/tmp/footstrap-theme.$lang.lmo"
|
|
scp -q "/tmp/footstrap-theme.$lang.lmo" "$R":/usr/lib/lua/luci/i18n/
|
|
rm -f "/tmp/footstrap-theme.$lang.lmo"
|
|
done
|
|
else
|
|
echo " (po2lmo not found — skipping the translation catalogue; strings stay English)"
|
|
fi
|
|
|
|
# root/ -> / as a TREE, never as a list of names. luci.mk installs root/ wholesale, so a file named
|
|
# here one-by-one is a file that ships in the package and silently never reaches the dev router —
|
|
# first noticed after a release. The top-level dirs come from a GLOB for the same reason: this used
|
|
# to tar `usr` literally, which is a hand-written list of one, and root/etc/ was the counterexample
|
|
# already sitting in the tree — root/etc/config/footstrap shipped in the package and never reached
|
|
# the router. tar, not `scp -r`, because scp's merge semantics on an existing /usr are ambiguous.
|
|
#
|
|
# Two subtrees have semantics a blind tar would break, so each is excluded and handled explicitly
|
|
# below. Both exclusions are about BEHAVIOUR, not about naming files: a new file under either dir
|
|
# still arrives for free.
|
|
# - etc/uci-defaults: deliberately run from /tmp (see below). Landing it in /etc/uci-defaults
|
|
# would make the router's next boot execute it and then DELETE it.
|
|
# - etc/config: conffiles. The package manager does not overwrite them on upgrade (Makefile's
|
|
# conffiles define) and neither may dev-sync — the live file holds the admin's "Save as
|
|
# default", and clobbering it here would be the very wipe that define exists to prevent.
|
|
set --
|
|
for _d in "$D"/root/*/; do set -- "$@" "$(basename "$_d")"; done
|
|
tar -C "$D/root" --exclude=etc/uci-defaults --exclude=etc/config -cf - "$@" | ssh "$R" "tar -C / -xf -"
|
|
|
|
# conffiles: install only when ABSENT, which is exactly what the package manager does with them.
|
|
for _f in "$D"/root/etc/config/*; do
|
|
[ -f "$_f" ] || continue
|
|
_b=$(basename "$_f")
|
|
scp -q "$_f" "$R":"/tmp/.fs-conf-$_b"
|
|
ssh "$R" "[ -f /etc/config/$_b ] || { mv /tmp/.fs-conf-$_b /etc/config/$_b; echo ' installed /etc/config/$_b (was absent)'; }; rm -f /tmp/.fs-conf-$_b"
|
|
done
|
|
# There is no self-update backend to deploy any more: the theme upgrades through the package feed
|
|
# the installer adds, which is what a package manager is for.
|
|
#
|
|
# No rpcd reload here either — same race as the Makefile's postinst note (Package/luci-theme-
|
|
# footstrap/postinst): this copies files onto a router where the theme registers no rpcd object,
|
|
# rpcd re-reads acl.d/*.json at LOGIN (not only on reload), and a developer's root session already
|
|
# carries read='*' write='*', so the theme's ACL group is irrelevant to it regardless.
|
|
ssh "$R" "rm -f /tmp/luci-indexcache*"
|
|
|
|
ssh "$R" "
|
|
# Sweep every pre-consolidation name, including $N-top: the top bar is not a theme any more, so a
|
|
# stale mediaurlbase pointing at its media dir would still render a theme LuCI no longer lists.
|
|
#
|
|
# rm -rf, not rm -f: these are DIRECTORIES (and $N-top a symlink to one, which rm -rf removes as the
|
|
# link rather than its target). \`rm -f\` refuses a directory, 2>/dev/null swallows the error, and
|
|
# this block runs without set -e — so the sweep silently does nothing. Every path is a literal built
|
|
# from \$N: no glob, no user input.
|
|
cd /www/luci-static
|
|
rm -rf $N/$N $N-top $N-dark $N-light $N-top-dark $N-top-light
|
|
cd /usr/share/ucode/luci/template/themes
|
|
rm -rf $N/$N $N-top $N-dark $N-light $N-top-dark $N-top-light
|
|
# The overview layout must not be left in luci-mod-status's global include dir, where LuCI loads
|
|
# every *.js under any theme: it is a chrome module now. A package upgrade drops the old file, but
|
|
# dev-sync copies rather than installs, so it has to be swept by name — otherwise the dev router
|
|
# runs both copies and the grid is arranged twice.
|
|
rm -f /www/luci-static/resources/view/status/include/05_footstrap_overview_layout.js
|
|
for db in /lib/apk/db/installed /usr/lib/opkg/status; do [ -f \"\$db\" ] && touch \"\$db\"; done
|
|
rm -f /tmp/luci-indexcache*"
|
|
|
|
# Register by running the package's own uci-defaults script — the single source of truth
|
|
# (ONE entry, luci.themes.Footstrap; layout, mode and palette are client-side toggles).
|
|
# PKG_UPGRADE=1 forces its upgrade branch, so the dev router's active theme is left alone.
|
|
scp -q "$D"/root/etc/uci-defaults/30_luci-theme-footstrap "$R":/tmp/30_luci-theme-footstrap
|
|
ssh "$R" "PKG_UPGRADE=1 sh /tmp/30_luci-theme-footstrap; rm -f /tmp/30_luci-theme-footstrap /tmp/luci-indexcache*"
|
|
|
|
|
|
# ---- bust the browser cache, or a dev deploy is invisible to the device you are testing on ----
|
|
#
|
|
# head.ut versions every asset with `?v={{ pkgs_update_time }}`, and luci-base derives that from the
|
|
# mtime of the PACKAGE DATABASE. Installing a package moves it; scp'ing files over an existing
|
|
# install does not — so a dev deploy leaves the URL identical while the bytes change, and a browser
|
|
# is entitled to keep serving what it has. On a phone that is not a theory: an afternoon of "still
|
|
# shakes" reports were taken against a stylesheet several deploys old.
|
|
#
|
|
# Touching the database file is what an install would have done to it, so the next page carries a
|
|
# new `?v=` for every asset. Router-only, dev-only: nothing in the package does this.
|
|
ssh "$R" 'touch /lib/apk/db/installed 2>/dev/null || touch /usr/lib/opkg/status 2>/dev/null || true'
|
|
|
|
echo "synced to $R (single Footstrap theme registered, active theme unchanged)"
|