Pin exact sing-box package on APK
This commit is contained in:
@@ -371,7 +371,7 @@ function opkg_package_version_from_list(package_name, output) {
|
||||
function available_package_version(package_name) {
|
||||
package_name = as_string(package_name);
|
||||
if (is_apk())
|
||||
return trim(helper_output_input(command_output_from_args([ "apk", "policy", package_name ]), "updates-apk-policy-version", []));
|
||||
return trim(module_output([ LIB_DIR + "/core/packages.uc", "apk-available-version", package_name ]));
|
||||
return opkg_package_version_from_list(package_name, command_output_from_args([ "opkg", "list", package_name ]));
|
||||
}
|
||||
|
||||
@@ -384,12 +384,16 @@ function pkg_install_name_command(package_name) {
|
||||
command_from_args([ "opkg", "install", package_name ]) + " </dev/null";
|
||||
}
|
||||
|
||||
function pkg_install_name_downgrade(package_name) {
|
||||
function pkg_install_name_downgrade(package_name, package_version) {
|
||||
package_name = as_string(package_name);
|
||||
if (is_apk()) {
|
||||
package_version = as_string(package_version);
|
||||
if (package_version == "")
|
||||
return false;
|
||||
let package_spec = package_name + "=" + package_version;
|
||||
if (pkg_is_installed(package_name))
|
||||
return command_success(command_from_args([ "apk", "fix", "--reinstall", "--upgrade", package_name ]) + " </dev/null");
|
||||
return command_success(command_from_args([ "apk", "add", package_name ]) + " </dev/null");
|
||||
return command_success(command_from_args([ "apk", "fix", "--reinstall", "--upgrade", package_spec ]) + " </dev/null");
|
||||
return command_success(command_from_args([ "apk", "add", package_spec ]) + " </dev/null");
|
||||
}
|
||||
|
||||
return command_success(command_from_args([ "opkg", "install", "--force-overwrite", "--force-reinstall", "--force-downgrade", package_name ]) + " </dev/null") ||
|
||||
@@ -1150,7 +1154,8 @@ function restore_file_backup(target_path, backup_path) {
|
||||
}
|
||||
|
||||
function restore_sing_box_service_from_marker(marker) {
|
||||
if (as_string(marker) == "extended-compressed")
|
||||
if (as_string(marker) == "extended-compressed" ||
|
||||
(!file_exists("/etc/init.d/sing-box") && file_nonempty("/usr/bin/sing-box")))
|
||||
return install_managed_sing_box_service_script();
|
||||
remove_managed_sing_box_service_script();
|
||||
return true;
|
||||
@@ -1265,24 +1270,24 @@ function restore_sing_box_extended_package_variant() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function replace_sing_box_package_variant(target_package, conflict_package) {
|
||||
function replace_sing_box_package_variant(target_package, conflict_package, target_version) {
|
||||
prepare_sing_box_package_service_install();
|
||||
if ((as_string(conflict_package) == "" || !pkg_is_installed(conflict_package)) &&
|
||||
(target_package == "sing-box-extended" || !pkg_is_installed("sing-box-extended")))
|
||||
return pkg_install_name_downgrade(target_package);
|
||||
return pkg_install_name_downgrade(target_package, target_version);
|
||||
|
||||
if (target_package != "sing-box-extended" && !pkg_remove_sing_box_conflict("sing-box-extended"))
|
||||
return false;
|
||||
if (as_string(conflict_package) != "" && !pkg_remove_sing_box_conflict(conflict_package))
|
||||
return false;
|
||||
return pkg_install_name_downgrade(target_package);
|
||||
return pkg_install_name_downgrade(target_package, target_version);
|
||||
}
|
||||
|
||||
function restore_sing_box_package_variant(previous_variant) {
|
||||
if (previous_variant == "tiny")
|
||||
return replace_sing_box_package_variant("sing-box-tiny", "sing-box");
|
||||
return replace_sing_box_package_variant("sing-box-tiny", "sing-box", available_package_version("sing-box-tiny"));
|
||||
if (previous_variant == "stable")
|
||||
return replace_sing_box_package_variant("sing-box", "sing-box-tiny");
|
||||
return replace_sing_box_package_variant("sing-box", "sing-box-tiny", available_package_version("sing-box"));
|
||||
if (previous_variant == "extended")
|
||||
return restore_sing_box_extended_package_variant();
|
||||
if (previous_variant == "not-installed") {
|
||||
@@ -1304,8 +1309,10 @@ function restore_sing_box_install_backup(previous_variant, backup_binary) {
|
||||
if (sing_box_variant_is_package_managed(previous_variant)) {
|
||||
if (restore_sing_box_package_variant(previous_variant))
|
||||
return true;
|
||||
if (as_string(backup_binary) != "")
|
||||
restore_sing_box_backup(backup_binary);
|
||||
if (as_string(backup_binary) != "" && restore_sing_box_backup(backup_binary)) {
|
||||
updates_log("Package rollback failed; restored the previous sing-box binary backup", "warn");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1708,7 +1715,7 @@ function install_package_sing_box(action, tiny) {
|
||||
}
|
||||
|
||||
if (!run_logged("Installing " + label + " package", "sh -c " + shell_quote("exit 0")) ||
|
||||
!replace_sing_box_package_variant(package_name, conflict))
|
||||
!replace_sing_box_package_variant(package_name, conflict, latest_version))
|
||||
fail_package_sing_box_install(action, tiny, "package installation failed", current_version, latest_version,
|
||||
package_name, previous_variant, backup_binary, backup_cronet, previous_marker, previous_version_state, cronet_touched);
|
||||
|
||||
|
||||
@@ -102,6 +102,16 @@ function apk_version(package_name) {
|
||||
return apk_info_version(package_name, command_output([ "apk", "info", "-v", package_name ]));
|
||||
}
|
||||
|
||||
function apk_available_version(package_name) {
|
||||
package_name = as_string(package_name);
|
||||
if (!command_exists("apk"))
|
||||
return "";
|
||||
return apk_manifest_version(
|
||||
package_name,
|
||||
command_output([ "apk", "list", "--available", "--manifest", package_name ])
|
||||
);
|
||||
}
|
||||
|
||||
function opkg_version(package_name) {
|
||||
package_name = as_string(package_name);
|
||||
if (!command_exists("opkg"))
|
||||
@@ -133,9 +143,11 @@ else if (mode == "version")
|
||||
print(version(ARGV[1]), "\n");
|
||||
else if (mode == "apk-version")
|
||||
print(apk_version(ARGV[1]), "\n");
|
||||
else if (mode == "apk-available-version")
|
||||
print(apk_available_version(ARGV[1]), "\n");
|
||||
else if (mode == "opkg-version")
|
||||
print(opkg_version(ARGV[1]), "\n");
|
||||
else {
|
||||
warn("Usage: core/packages.uc <installed|apk-installed|opkg-installed|version|apk-version|opkg-version> <package>\n");
|
||||
warn("Usage: core/packages.uc <installed|apk-installed|opkg-installed|version|apk-version|apk-available-version|opkg-version> <package>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -101,6 +101,12 @@ grep -Fq 'forkop_status_running_with_timeout()' "$ACTION_UC" ||
|
||||
fail "components/action.uc must use bounded Forkop status checks for component actions"
|
||||
grep -Fq 'restore_sing_box_after_failed_package_install' "$ACTION_UC" ||
|
||||
fail "stable and tiny sing-box package installs must restore the previous variant after validation failures"
|
||||
grep -Fq 'let package_spec = package_name + "=" + package_version;' "$ACTION_UC" ||
|
||||
fail "APK sing-box installs must pin the concrete package version instead of selecting a provider"
|
||||
grep -Fq 'Package rollback failed; restored the previous sing-box binary backup' "$ACTION_UC" ||
|
||||
fail "package rollback must accept a successfully restored binary backup"
|
||||
grep -Fq '!file_exists("/etc/init.d/sing-box") && file_nonempty("/usr/bin/sing-box")' "$ACTION_UC" ||
|
||||
fail "binary rollback must restore a managed sing-box service when the package script is missing"
|
||||
grep -Fq 'fail_package_sing_box_install(action, tiny, "package was installed, but sing-box binary is not available"' "$ACTION_UC" ||
|
||||
fail "stable and tiny sing-box binary validation failures must use transactional rollback"
|
||||
grep -Fq 'fail_package_sing_box_install(action, tiny, "was installed, but Forkop did not start cleanly"' "$ACTION_UC" ||
|
||||
@@ -184,6 +190,12 @@ if (mode == "opkg-version")
|
||||
exit(0);
|
||||
if (mode == "opkg-installed")
|
||||
exit(1);
|
||||
if (mode == "apk-available-version") {
|
||||
print("1.2.3-r1\n");
|
||||
exit(0);
|
||||
}
|
||||
if (mode == "apk-version")
|
||||
exit(0);
|
||||
exit(1);
|
||||
UCODE
|
||||
cat >"$package_runtime_lib/singbox/runtime.uc" <<'UCODE'
|
||||
@@ -253,6 +265,38 @@ if (secondList <= update) fail('stable sing-box version must be resolved again a
|
||||
if (install <= secondList) fail('stable sing-box install must happen after post-update version resolve');
|
||||
NODE
|
||||
|
||||
cat >"$package_runtime_bin/apk" <<'SH'
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
printf 'apk %s\n' "$*" >>"${FAKE_APK_LOG:?}"
|
||||
case "${1:-}" in
|
||||
info)
|
||||
exit 1
|
||||
;;
|
||||
update|add|fix|del)
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
SH
|
||||
chmod +x "$package_runtime_bin/apk"
|
||||
set +e
|
||||
PATH="$package_runtime_bin:$PATH" \
|
||||
FORKOP_LIB="$package_runtime_lib" \
|
||||
FORKOP_RUNTIME_STATE_DIR="$WORK_DIR/apk-package-runtime" \
|
||||
FORKOP_BIN="$WORK_DIR/missing-forkop" \
|
||||
FORKOP_SERVICE_INIT="$WORK_DIR/missing-init" \
|
||||
FAKE_APK_LOG="$WORK_DIR/apk.log" \
|
||||
ucode -L "$package_runtime_lib" "$ACTION_UC" component-action sing_box install_stable >/dev/null
|
||||
set -e
|
||||
grep -Fxq 'apk add sing-box=1.2.3-r1' "$WORK_DIR/apk.log" ||
|
||||
fail "APK stable action must request the exact sing-box package version"
|
||||
if grep -Fxq 'apk add sing-box' "$WORK_DIR/apk.log"; then
|
||||
fail "APK stable action must not use the provider-selecting unversioned package name"
|
||||
fi
|
||||
|
||||
release_json="$(cat <<'JSON'
|
||||
{
|
||||
"tag_name": "1.2.3",
|
||||
|
||||
@@ -94,6 +94,24 @@ if ucode -L "$FORKOP_LIB" "$PACKAGES_UC" installed forkop-definitely-missing >/d
|
||||
fail "missing package must not be reported installed"
|
||||
fi
|
||||
|
||||
mkdir -p "$WORK_DIR/apk-bin"
|
||||
cat >"$WORK_DIR/apk-bin/apk" <<'SH'
|
||||
#!/usr/bin/env sh
|
||||
if [ "$1 $2 $3 $4" = "list --available --manifest sing-box" ]; then
|
||||
printf '%s\n' \
|
||||
'P:sing-box-extended' \
|
||||
'V:9.9.9-r1' \
|
||||
'p:sing-box' \
|
||||
'P:sing-box' \
|
||||
'V:1.2.3-r1'
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
SH
|
||||
chmod +x "$WORK_DIR/apk-bin/apk"
|
||||
[ "$(PATH="$WORK_DIR/apk-bin:$PATH" ucode -L "$FORKOP_LIB" "$PACKAGES_UC" apk-available-version sing-box)" = "1.2.3-r1" ] ||
|
||||
fail "APK available version lookup must select the exact package name, not a higher-priority provider"
|
||||
|
||||
mark_hex="$(ucode -L "$FORKOP_LIB" "$RULES_UC" mark-hex 0x01000000 2)"
|
||||
[ "$mark_hex" = "0x01000002" ] ||
|
||||
fail "providers/rules.uc mark math changed"
|
||||
|
||||
Reference in New Issue
Block a user