thunderbird-patch-review

Easy-to-use patch review interface for Thunderbird

Contribute: ~marcc/thunderbird-review-plugin@lists.sr.ht

git clone git://mccd.space/thunderbird-patch-review

commit 97e85837b70f6030cdaaff46eff49420a69222a2
parent a56cd849f169464a1a47182decefb2841ecf54e4
Author: Pi Agent <agent@pi.local>
Date:   Sat, 18 Jul 2026 22:06:07 +0200

review: check the branch is still the one shown before Apply

Before running git am, re-resolve the repository and compare its current
branch with the one shown in the chip. If the branch moved between the
Browse pick and the Apply click (another checkout, rebase, ...), refresh
the chip to the new branch and ask the user to click Apply again to
confirm, rather than silently writing onto an unexpected branch. If the
repo is no longer reachable, refresh the chip into its error state and
report.

Diffstat:
Mextension/review/review.js | 24++++++++++++++++++++++++
1 file changed, 24 insertions(+), 0 deletions(-)
diff --git a/extension/review/review.js b/extension/review/review.js
@@ -614,6 +614,28 @@ async function applySeries(mode) {
   }
 
   showStatus("Applying series…");
+  const fresh = await bg({ type: "describe-repo", repo });
+  if (fresh.ok && state.repoBranch && fresh.branch && fresh.branch !== state.repoBranch) {
+    // The branch moved under us (another checkout, a rebase, etc.) between
+    // the Browse pick and the Apply click. Show the new branch and ask the
+    // user to confirm by re-applying, rather than silently writing onto
+    // an unexpected branch.
+    state.repoBranch = fresh.branch;
+    $("#repo-path").textContent = `${fresh.name} · ${fresh.branch}`;
+    showStatus(
+      `The repository's branch changed to "${fresh.branch}" since you chose it; ` +
+      "click Apply again to confirm.",
+      { error: true }
+    );
+    return;
+  }
+  if (!fresh.ok) {
+    // The repo disappeared between the Browse and the Apply.
+    refreshRepoDisplay(repo);
+    showStatus(fresh.error || "The repository is no longer readable.", { error: true });
+    return;
+  }
+
   const response = await bg({ type: "apply-series", messageIds, repo });
   const text = [response.ok ? "Series applied." : "Apply failed.", response.output || response.error]
     .filter(Boolean)
@@ -660,6 +682,8 @@ async function refreshRepoDisplay(path) {
     return;
   }
   state.repo = response.repo || path;
+  state.repoBranch = response.branch || null;
+  chip.classList.remove("error");
   chip.textContent = `${response.name} · ${response.branch}`;
 }