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:
+49
-29
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user