From c4f7d7dcbd2bcd12ffa172d6f725267bd76db557 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 19 Jul 2026 08:55:50 +0000 Subject: [PATCH] [FIX] script todo: ~/.ssh/config entry wiped following blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _write_ssh_config_entry used a DOTALL (?ms) regex to remove an existing "Host " block; with DOTALL, ".*" crossed newlines and matched from the block to the end of the file, so re-adding an already-present host deleted every entry after it. Dropping DOTALL (keep MULTILINE, match indented lines with [^\n]*) removes only the target block and preserves the rest. Not a parallelism issue — the writes are sequential. Co-Authored-By: Claude Opus 4.8 (1M context) --- script/todo/todo.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/script/todo/todo.py b/script/todo/todo.py index 3c8f24f..c40f18a 100755 --- a/script/todo/todo.py +++ b/script/todo/todo.py @@ -1083,10 +1083,13 @@ class TODO: if os.path.exists(cfg): with open(cfg, encoding="utf-8") as fh: existing = fh.read() - # Retire un ancien bloc du même Host (jusqu'au prochain Host / EOF). + # Retire un ancien bloc du même Host (ses lignes indentées). Pas de + # drapeau DOTALL : « . » ne doit PAS traverser les sauts de ligne, + # sinon .* engloutirait tout jusqu'à la fin du fichier et effacerait + # les entrées suivantes. pattern = re.compile( - rf"(?ms)^[ \t]*Host[ \t]+{re.escape(host)}[ \t]*\n" - r"(?:[ \t]+.*\n?)*" + rf"(?m)^[ \t]*Host[ \t]+{re.escape(host)}[ \t]*\n" + r"(?:[ \t]+[^\n]*\n?)*" ) existing = pattern.sub("", existing).rstrip("\n") block = (