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
. ${IPKG_INSTROOT}/lib/functions.sh
default_postinst $0 $@
[ -n "${IPKG_INSTROOT}" ] || /usr/bin/tachyon luci_postinst >/dev/null 2>&1 || true
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;
}
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) {
args = normalize_timeout_args(args);
return normalize_status(system(command_from_args(args) + " >/dev/null 2>&1")) == 0;
}
function command_output(args) {
args = normalize_timeout_args(args);
let pipe = fs.popen(command_from_args(args) + " 2>/dev/null", "r");
if (!pipe)
return "";
@@ -1441,6 +1478,8 @@ function installer_post_install() {
run_args([ "timeout", "10", INSTALLER_RPCD_INIT, "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))
run_args([ "timeout", "10", INSTALLER_TACHYON_INIT, "enable" ]);
@@ -2068,7 +2107,7 @@ installer_text() {
summary_release) printf '%s\n' "Релиз" ;;
summary_legacy_removed) 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" ;;
esac
return 0
@@ -2115,7 +2154,7 @@ installer_text() {
summary_release) printf '%s\n' "Release" ;;
summary_legacy_removed) printf '%s\n' "Legacy installation migrated and removed." ;;
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" ;;
esac
}
@@ -2607,13 +2646,17 @@ migrate_legacy_configuration() {
install_ui_packages() {
if ! pkg_install_files "$TACHYON_APP_FILE"; then
if pkg_is_installed "luci-app-tachyon"; then
warn "Package manager reported errors during luci-app-tachyon installation, but the package is installed — continuing"
if pkg_is_installed "luci-app-tachyon" && [ -f "/usr/share/luci/menu.d/luci-app-tachyon.json" ]; then
warn "Package manager reported non-critical errors during luci-app-tachyon installation, but files are verified"
else
fail "luci-app-tachyon installation failed"
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 ! pkg_install_files "$TACHYON_I18N_FILE"; 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" \
install_json_ucode installer-post-install ||
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
@@ -7,8 +7,7 @@
"path": "tachyon/tachyon"
},
"depends": {
"acl": [ "luci-app-tachyon" ],
"uci": { "tachyon": true }
}
"acl": [ "luci-app-tachyon" ]
}
}
}
+2
View File
@@ -299,6 +299,8 @@ function luci_postinst() {
if (!PACKAGE_TEST_MODE) {
if (path_exists("/etc/init.d/rpcd"))
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" ]);
}
return true;
@@ -66,9 +66,9 @@ function uninstall_tachyon(purge_config) {
log_step("Removing Tachyon packages...");
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) {
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.");
+21 -4
View File
@@ -240,10 +240,24 @@ CURRENT_STEP=$((CURRENT_STEP + 1))
tui_step "$CURRENT_STEP" "$TOTAL_STEPS" "Удаление установленных пакетов Tachyon..."
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"
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"
fi
@@ -282,9 +296,12 @@ if [ "$OPT_PURGE" -eq 1 ]; then
tui_ok "Все конфигурации Tachyon удалены (--purge)"
fi
# Reload rpcd to update LuCI menu
# Restart rpcd and uhttpd to update LuCI menu
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
# Check if parent Forkop / Podkop services exist and restore them