apply.sh: fix b2.py patch guard and make patching self-correcting

Two bugs:
1. hasattr(B2RcloneRemote, "get_restic_config") returned True because the base
   class defines the method (it just raises NotImplementedError). The method was
   never added to B2RcloneRemote. Fixed: use __dict__ check instead.

2. "skip if TRUECLOUD_PATCH marker present" prevented a corrected patch block
   from replacing a previously-written buggy one without clearing the overlay.
   Fixed: always strip any existing TRUECLOUD_PATCH block and rewrite it fresh
   using a Python heredoc. Each apply.sh run now self-corrects to the latest
   version of the patch.
This commit is contained in:
2026-06-16 15:36:36 +00:00
parent f556746310
commit c8a0c42762
+49 -29
View File
@@ -177,10 +177,10 @@ with open(d + '/patch/sitecustomize.py', encoding='utf-8') as fh:
fi fi
# ── Direct file patching ────────────────────────────────────────────────── # ── Direct file patching ──────────────────────────────────────────────────
# Append a marker block to b2.py and restic.py in the overlay (primary # Patch b2.py and restic.py directly in the overlay (primary approach).
# approach). This is simpler than the sitecustomize.py import hook and # Each run strips any existing TRUECLOUD_PATCH block and rewrites it fresh,
# works regardless of how Python's site initialisation is configured. # so a bugfix in the block takes effect immediately on the next apply.sh run
# apply.sh re-patches on every boot; the overlay is volatile (tmpfs). # without needing to manually clear the overlay.
if [ -n "$_MW_DIR" ] && [ "$_can_install" = true ]; then if [ -n "$_MW_DIR" ] && [ "$_can_install" = true ]; then
_B2_PY="$_MW_DIR/rclone/remote/b2.py" _B2_PY="$_MW_DIR/rclone/remote/b2.py"
@@ -188,27 +188,37 @@ with open(d + '/patch/sitecustomize.py', encoding='utf-8') as fh:
# ── b2.py ───────────────────────────────────────────────────────────── # ── b2.py ─────────────────────────────────────────────────────────────
if [ -f "$_B2_PY" ]; then if [ -f "$_B2_PY" ]; then
if grep -q "TRUECLOUD_PATCH" "$_B2_PY" 2>/dev/null; then if "$PYTHON" - "$_B2_PY" << 'PYEOF'
echo "OK: b2.py already patched" import sys
_b2_ok=1
else
cat >> "$_B2_PY" << 'B2_PATCH'
BLOCK = """
# TRUECLOUD_PATCH — added by truenas-truecloud-patch/patch/apply.sh # TRUECLOUD_PATCH — added by truenas-truecloud-patch/patch/apply.sh
def _tc_get_restic_config(task): def _tc_get_restic_config(task):
p = task["credentials"]["provider"] p = task["credentials"]["provider"]
return "", {"B2_ACCOUNT_ID": p["account"], "B2_ACCOUNT_KEY": p["key"]} return "", {"B2_ACCOUNT_ID": p["account"], "B2_ACCOUNT_KEY": p["key"]}
if not hasattr(B2RcloneRemote, "get_restic_config"): if "get_restic_config" not in B2RcloneRemote.__dict__:
B2RcloneRemote.get_restic_config = staticmethod(_tc_get_restic_config) B2RcloneRemote.get_restic_config = staticmethod(_tc_get_restic_config)
B2RcloneRemote.restic = True B2RcloneRemote.restic = True
B2_PATCH """
if [ $? -eq 0 ]; then
echo "OK: Patched b2.py → $_B2_PY" path = sys.argv[1]
_b2_ok=1 with open(path, encoding="utf-8") as fh:
else content = fh.read()
echo "WARNING: Failed to write to b2.py (overlay not writable?)"
fi marker = "\n# TRUECLOUD_PATCH"
idx = content.find(marker)
base = content[:idx] if idx != -1 else content
patched = base.rstrip("\n") + "\n" + BLOCK
with open(path, "w", encoding="utf-8") as fh:
fh.write(patched)
PYEOF
then
echo "OK: Patched b2.py → $_B2_PY"
_b2_ok=1
else
echo "WARNING: Failed to patch b2.py"
fi fi
else else
echo "WARNING: b2.py not found at $_B2_PY" echo "WARNING: b2.py not found at $_B2_PY"
@@ -216,12 +226,10 @@ B2_PATCH
# ── restic.py ───────────────────────────────────────────────────────── # ── restic.py ─────────────────────────────────────────────────────────
if [ -f "$_RESTIC_PY" ]; then if [ -f "$_RESTIC_PY" ]; then
if grep -q "TRUECLOUD_PATCH" "$_RESTIC_PY" 2>/dev/null; then if "$PYTHON" - "$_RESTIC_PY" << 'PYEOF'
echo "OK: restic.py already patched" import sys
_restic_ok=1
else
cat >> "$_RESTIC_PY" << 'RESTIC_PATCH'
BLOCK = """
# TRUECLOUD_PATCH — added by truenas-truecloud-patch/patch/apply.sh # TRUECLOUD_PATCH — added by truenas-truecloud-patch/patch/apply.sh
_tc_orig_get_restic_config = get_restic_config _tc_orig_get_restic_config = get_restic_config
@@ -253,13 +261,25 @@ def get_restic_config(cloud_backup):
return result return result
get_restic_config._truecloud_patched = True get_restic_config._truecloud_patched = True
RESTIC_PATCH """
if [ $? -eq 0 ]; then
echo "OK: Patched restic.py → $_RESTIC_PY" path = sys.argv[1]
_restic_ok=1 with open(path, encoding="utf-8") as fh:
else content = fh.read()
echo "WARNING: Failed to write to restic.py (overlay not writable?)"
fi marker = "\n# TRUECLOUD_PATCH"
idx = content.find(marker)
base = content[:idx] if idx != -1 else content
patched = base.rstrip("\n") + "\n" + BLOCK
with open(path, "w", encoding="utf-8") as fh:
fh.write(patched)
PYEOF
then
echo "OK: Patched restic.py → $_RESTIC_PY"
_restic_ok=1
else
echo "WARNING: Failed to patch restic.py"
fi fi
else else
echo "WARNING: restic.py not found at $_RESTIC_PY" echo "WARNING: restic.py not found at $_RESTIC_PY"