From 3aab169fbc3addc2ee5bd8ec0ca6d2b5d8c94e7d Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 20 Jun 2026 15:55:44 +0000 Subject: [PATCH] wolf: fix config.toml corruption when re-running on an existing install MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wolf rewrites config.toml on every start and reformats `mounts` as a multi-line TOML array. update_mounts() only replaced the single line starting with `mounts =`, leaving the remaining array elements and the closing `]` orphaned — producing invalid TOML ("Expected '=' after a key") that crashed Wolf on the next start. This bit any re-run of the installer (or `./manage.sh apps`) against a config Wolf had already reformatted. Replace the entire array (from `mounts =` to its closing `]`), and also clean up orphaned remnants left by a previously corrupted single-line rewrite so re-running the script repairs a broken config in place. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs --- services/wolf.sh | 50 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/services/wolf.sh b/services/wolf.sh index 72326e3..47a26a4 100644 --- a/services/wolf.sh +++ b/services/wolf.sh @@ -1160,11 +1160,30 @@ def make_app_block(app): ) def update_mounts(lines, wolf_name, new_mounts): + # Wolf rewrites config.toml and reformats `mounts` as a MULTI-LINE array, + # so we must replace the entire array (from `mounts =` to its closing `]`), + # not just the first line — otherwise the old elements are left orphaned and + # the file becomes invalid TOML. Always rewrite as a single line. for i, line in enumerate(lines): if f"name = '{wolf_name}'" in line: - for j in range(max(0, i-10), min(len(lines), i+15)): - if lines[j].strip().startswith('mounts ='): - lines[j] = f" mounts = {new_mounts}\n" + for j in range(max(0, i-20), min(len(lines), i+20)): + if lines[j].lstrip().startswith('mounts ='): + indent = lines[j][:len(lines[j]) - len(lines[j].lstrip())] + # End of the array = first line containing ']'. + k = j + while k < len(lines) and ']' not in lines[k]: + k += 1 + # Heal any orphaned array remnants left by a previously + # corrupted single-line rewrite (stray '…' elements / a lone + # ']' sitting below the mounts line). + m = k + 1 + while m < len(lines): + s = lines[m].lstrip() + if s.startswith("'") or s.startswith(']'): + m += 1 + else: + break + lines[j:m] = [f"{indent}mounts = {new_mounts}\n"] return True return False @@ -1658,11 +1677,30 @@ def make_app_block(app): ) def update_mounts(lines, wolf_name, new_mounts): + # Wolf rewrites config.toml and reformats `mounts` as a MULTI-LINE array, + # so we must replace the entire array (from `mounts =` to its closing `]`), + # not just the first line — otherwise the old elements are left orphaned and + # the file becomes invalid TOML. Always rewrite as a single line. for i, line in enumerate(lines): if f"name = '{wolf_name}'" in line: - for j in range(max(0, i-10), min(len(lines), i+15)): - if lines[j].strip().startswith('mounts ='): - lines[j] = f" mounts = {new_mounts}\n" + for j in range(max(0, i-20), min(len(lines), i+20)): + if lines[j].lstrip().startswith('mounts ='): + indent = lines[j][:len(lines[j]) - len(lines[j].lstrip())] + # End of the array = first line containing ']'. + k = j + while k < len(lines) and ']' not in lines[k]: + k += 1 + # Heal any orphaned array remnants left by a previously + # corrupted single-line rewrite (stray '…' elements / a lone + # ']' sitting below the mounts line). + m = k + 1 + while m < len(lines): + s = lines[m].lstrip() + if s.startswith("'") or s.startswith(']'): + m += 1 + else: + break + lines[j:m] = [f"{indent}mounts = {new_mounts}\n"] return True return False