fix(luci): ensure Tachyon menu item reliably appears in LuCI

- Remove 'uci: { tachyon: true }' dependency from menu.d/luci-app-tachyon.json so LuCI does not hide the menu node if UCI config is uncommitted/reloading
- Add portable timeout normalization in install.sh ucode to handle Busybox timeout and systems without timeout applet
- Ensure luci_postinst is called directly in IPK postinst (build.sh) and after install in install.sh
- Restart uhttpd alongside rpcd and purge LuCI caches in post-install and uninstaller
- Fix uninstall.sh to remove packages individually with lock retry and omit non-existent luci-i18n-tachyon-en
- In install_ui_packages, verify that menu.d/luci-app-tachyon.json actually exists on disk before proceeding
This commit is contained in:
Dushnilin
2026-09-03 19:14:22 +03:00
parent 5c7aa58669
commit 1c48422511
6 changed files with 83 additions and 13 deletions
+1
View File
@@ -466,6 +466,7 @@ EOF
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0 [ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
. ${IPKG_INSTROOT}/lib/functions.sh . ${IPKG_INSTROOT}/lib/functions.sh
default_postinst $0 $@ default_postinst $0 $@
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/tachyon luci_postinst >/dev/null 2>&1 || true
EOF EOF
cat > "$control_dir/postinst-pkg" <<'EOF' cat > "$control_dir/postinst-pkg" <<'EOF'
+55 -4
View File
@@ -910,11 +910,48 @@ function normalize_status(status) {
return status > 255 ? int(status / 256) : status; return status > 255 ? int(status / 256) : status;
} }
let timeout_prefix_cache = null;
function timeout_prefix() {
if (timeout_prefix_cache != null)
return timeout_prefix_cache;
if (normalize_status(system("timeout 1 /bin/true >/dev/null 2>&1")) == 0)
timeout_prefix_cache = [ "timeout" ];
else if (normalize_status(system("timeout -t 1 /bin/true >/dev/null 2>&1")) == 0)
timeout_prefix_cache = [ "timeout", "-t" ];
else
timeout_prefix_cache = [];
return timeout_prefix_cache;
}
function normalize_timeout_args(args) {
if (length(args) > 1 && args[0] == "timeout") {
let prefix = timeout_prefix();
let secs = args[1];
let rest = [];
for (let i = 2; i < length(args); i++)
push(rest, args[i]);
if (length(prefix) == 0)
return rest;
let result = [];
for (let p in prefix)
push(result, p);
push(result, secs);
for (let r in rest)
push(result, r);
return result;
}
return args;
}
function run_args(args) { function run_args(args) {
args = normalize_timeout_args(args);
return normalize_status(system(command_from_args(args) + " >/dev/null 2>&1")) == 0; return normalize_status(system(command_from_args(args) + " >/dev/null 2>&1")) == 0;
} }
function command_output(args) { function command_output(args) {
args = normalize_timeout_args(args);
let pipe = fs.popen(command_from_args(args) + " 2>/dev/null", "r"); let pipe = fs.popen(command_from_args(args) + " 2>/dev/null", "r");
if (!pipe) if (!pipe)
return ""; return "";
@@ -1441,6 +1478,8 @@ function installer_post_install() {
run_args([ "timeout", "10", INSTALLER_RPCD_INIT, "restart" ]); run_args([ "timeout", "10", INSTALLER_RPCD_INIT, "restart" ]);
run_args([ "timeout", "10", "/etc/init.d/uhttpd", "restart" ]); run_args([ "timeout", "10", "/etc/init.d/uhttpd", "restart" ]);
} }
if (path_executable(INSTALLER_TACHYON_BIN))
run_args([ "timeout", "15", INSTALLER_TACHYON_BIN, "luci_postinst" ]);
if (env("TACHYON_WAS_ENABLED", "0") == "1" && path_executable(INSTALLER_TACHYON_INIT)) if (env("TACHYON_WAS_ENABLED", "0") == "1" && path_executable(INSTALLER_TACHYON_INIT))
run_args([ "timeout", "10", INSTALLER_TACHYON_INIT, "enable" ]); run_args([ "timeout", "10", INSTALLER_TACHYON_INIT, "enable" ]);
@@ -2068,7 +2107,7 @@ installer_text() {
summary_release) printf '%s\n' "Релиз" ;; summary_release) printf '%s\n' "Релиз" ;;
summary_legacy_removed) printf '%s\n' "Предыдущая версия перенесена и удалена." ;; summary_legacy_removed) printf '%s\n' "Предыдущая версия перенесена и удалена." ;;
summary_log) printf '%s\n' "Лог" ;; summary_log) printf '%s\n' "Лог" ;;
summary_luci_notice) printf '%s\n' "Откройте LuCI и проверьте правила перед включением Tachyon" ;; summary_luci_notice) printf '%s\n' "Откройте LuCI и проверьте правила перед включением Tachyon. Если меню не появилось сразу, обновите страницу (Ctrl+F5) или перезайдите в LuCI." ;;
*) printf '%s\n' "$key" ;; *) printf '%s\n' "$key" ;;
esac esac
return 0 return 0
@@ -2115,7 +2154,7 @@ installer_text() {
summary_release) printf '%s\n' "Release" ;; summary_release) printf '%s\n' "Release" ;;
summary_legacy_removed) printf '%s\n' "Legacy installation migrated and removed." ;; summary_legacy_removed) printf '%s\n' "Legacy installation migrated and removed." ;;
summary_log) printf '%s\n' "Log" ;; summary_log) printf '%s\n' "Log" ;;
summary_luci_notice) printf '%s\n' "Open LuCI and review your rules before enabling Tachyon" ;; summary_luci_notice) printf '%s\n' "Open LuCI and review your rules before enabling Tachyon. If the menu doesn't appear immediately, hard-refresh the page (Ctrl+F5) or re-login." ;;
*) printf '%s\n' "$key" ;; *) printf '%s\n' "$key" ;;
esac esac
} }
@@ -2607,13 +2646,17 @@ migrate_legacy_configuration() {
install_ui_packages() { install_ui_packages() {
if ! pkg_install_files "$TACHYON_APP_FILE"; then if ! pkg_install_files "$TACHYON_APP_FILE"; then
if pkg_is_installed "luci-app-tachyon"; then if pkg_is_installed "luci-app-tachyon" && [ -f "/usr/share/luci/menu.d/luci-app-tachyon.json" ]; then
warn "Package manager reported errors during luci-app-tachyon installation, but the package is installed — continuing" warn "Package manager reported non-critical errors during luci-app-tachyon installation, but files are verified"
else else
fail "luci-app-tachyon installation failed" fail "luci-app-tachyon installation failed"
fi fi
fi fi
if [ ! -f "/usr/share/luci/menu.d/luci-app-tachyon.json" ]; then
fail "luci-app-tachyon installation failed: menu.d/luci-app-tachyon.json missing"
fi
if [ -n "$TACHYON_I18N_FILE" ]; then if [ -n "$TACHYON_I18N_FILE" ]; then
if ! pkg_install_files "$TACHYON_I18N_FILE"; then if ! pkg_install_files "$TACHYON_I18N_FILE"; then
if pkg_is_installed "luci-i18n-tachyon-ru"; then if pkg_is_installed "luci-i18n-tachyon-ru"; then
@@ -2635,6 +2678,14 @@ post_install() {
TACHYON_WAS_INSTALLED="$TACHYON_WAS_INSTALLED" TACHYON_LEGACY_DETECTED="$TACHYON_LEGACY_DETECTED" \ TACHYON_WAS_INSTALLED="$TACHYON_WAS_INSTALLED" TACHYON_LEGACY_DETECTED="$TACHYON_LEGACY_DETECTED" \
install_json_ucode installer-post-install || install_json_ucode installer-post-install ||
fail "Failed to complete Tachyon post-install actions" fail "Failed to complete Tachyon post-install actions"
rm -f /var/luci-indexcache* /tmp/luci-indexcache* /var/luci-modulecache* /tmp/luci-modulecache* 2>/dev/null || true
if [ -x "/etc/init.d/rpcd" ]; then
/etc/init.d/rpcd restart >/dev/null 2>&1 || true
fi
if [ -x "/etc/init.d/uhttpd" ]; then
/etc/init.d/uhttpd restart >/dev/null 2>&1 || true
fi
} }
TOTAL_STEPS=10 TOTAL_STEPS=10
@@ -7,8 +7,7 @@
"path": "tachyon/tachyon" "path": "tachyon/tachyon"
}, },
"depends": { "depends": {
"acl": [ "luci-app-tachyon" ], "acl": [ "luci-app-tachyon" ]
"uci": { "tachyon": true } }
}
} }
} }
+2
View File
@@ -299,6 +299,8 @@ function luci_postinst() {
if (!PACKAGE_TEST_MODE) { if (!PACKAGE_TEST_MODE) {
if (path_exists("/etc/init.d/rpcd")) if (path_exists("/etc/init.d/rpcd"))
command_success_from_args([ "/etc/init.d/rpcd", "restart" ]); command_success_from_args([ "/etc/init.d/rpcd", "restart" ]);
if (path_exists("/etc/init.d/uhttpd"))
command_success_from_args([ "/etc/init.d/uhttpd", "restart" ]);
command_success_from_args([ "logger", "-t", "tachyon", "[info] Package defaults applied" ]); command_success_from_args([ "logger", "-t", "tachyon", "[info] Package defaults applied" ]);
} }
return true; return true;
@@ -66,9 +66,9 @@ function uninstall_tachyon(purge_config) {
log_step("Removing Tachyon packages..."); log_step("Removing Tachyon packages...");
if (fs.stat("/bin/opkg") != null || fs.stat("/usr/bin/opkg") != null) { if (fs.stat("/bin/opkg") != null || fs.stat("/usr/bin/opkg") != null) {
run_cmd(["opkg", "remove", "luci-app-tachyon", "tachyon"]); run_cmd(["opkg", "remove", "--force-depends", "--force-remove", "luci-i18n-tachyon-ru", "luci-app-tachyon", "tachyon"]);
} else if (fs.stat("/sbin/apk") != null) { } else if (fs.stat("/sbin/apk") != null) {
run_cmd(["apk", "del", "luci-app-tachyon", "tachyon"]); run_cmd(["apk", "del", "luci-i18n-tachyon-ru", "luci-app-tachyon", "tachyon"]);
} }
log_step("Tachyon has been successfully uninstalled."); log_step("Tachyon has been successfully uninstalled.");
+21 -4
View File
@@ -240,10 +240,24 @@ CURRENT_STEP=$((CURRENT_STEP + 1))
tui_step "$CURRENT_STEP" "$TOTAL_STEPS" "Удаление установленных пакетов Tachyon..." tui_step "$CURRENT_STEP" "$TOTAL_STEPS" "Удаление установленных пакетов Tachyon..."
if command -v apk >/dev/null 2>&1 && [ -d "/lib/apk/db" ]; then if command -v apk >/dev/null 2>&1 && [ -d "/lib/apk/db" ]; then
apk del luci-app-tachyon tachyon luci-i18n-tachyon-ru luci-i18n-tachyon-en >/dev/null 2>&1 || true for _pkg in luci-i18n-tachyon-ru luci-app-tachyon tachyon; do
if apk info -e "$_pkg" >/dev/null 2>&1; then
apk del "$_pkg" >/dev/null 2>&1 || true
fi
done
tui_ok "Пакеты удалены через apk-tools" tui_ok "Пакеты удалены через apk-tools"
elif command -v opkg >/dev/null 2>&1; then elif command -v opkg >/dev/null 2>&1; then
opkg remove --force-depends luci-app-tachyon tachyon luci-i18n-tachyon-ru luci-i18n-tachyon-en >/dev/null 2>&1 || true _wait=0
while [ -f /var/lock/opkg.lock ] || [ -f /var/run/opkg.lock ]; do
_wait=$((_wait + 1))
[ "$_wait" -ge 10 ] && break
sleep 1
done
for _pkg in luci-i18n-tachyon-ru luci-app-tachyon tachyon; do
if opkg list-installed "$_pkg" 2>/dev/null | grep -q "^$_pkg "; then
opkg remove --force-depends --force-remove "$_pkg" >/dev/null 2>&1 || true
fi
done
tui_ok "Пакеты удалены через opkg" tui_ok "Пакеты удалены через opkg"
fi fi
@@ -282,9 +296,12 @@ if [ "$OPT_PURGE" -eq 1 ]; then
tui_ok "Все конфигурации Tachyon удалены (--purge)" tui_ok "Все конфигурации Tachyon удалены (--purge)"
fi fi
# Reload rpcd to update LuCI menu # Restart rpcd and uhttpd to update LuCI menu
if [ -f "/etc/init.d/rpcd" ]; then if [ -f "/etc/init.d/rpcd" ]; then
/etc/init.d/rpcd reload >/dev/null 2>&1 || true /etc/init.d/rpcd restart >/dev/null 2>&1 || true
fi
if [ -f "/etc/init.d/uhttpd" ]; then
/etc/init.d/uhttpd restart >/dev/null 2>&1 || true
fi fi
# Check if parent Forkop / Podkop services exist and restore them # Check if parent Forkop / Podkop services exist and restore them