[PATCH b4 v2] ez: avoid duplicate signatures on resend

Cássio Gabriel <[email protected]> Sat, 13 Jun 2026 02:30:03 -0300
Newsgroups org.kernel.linux.tools
Message-ID <[email protected]>
'b4 send --resend' rebuilds messages from the historical sent tag and
appends the current email signature to the cover text. If the stored
cover already ends in a canonical signature block, the regenerated
message carries two footer blocks.

Strip an existing trailing canonical signature before adding the current
one. Reuse the helper when preparing sent tags so reroll and resend handle
the delimiter consistently.

Link: https://lore.kernel.org/all/20260511-alsa-hda-cs35l41-fw-work-teardown-v1-1-1184e9bc4f25@gmail.com/
Signed-off-by: Cássio Gabriel <[email protected]>
---
Changes in v2:
- Only recognize the canonical email signature delimiter '-- '.
- Preserve bare '--' lines in cover letter content.
- Add a no-signature regression test.
- Link to v1: https://patch.msgid.link/[email protected]
---
base-commit: 474350a3035537184556061872e9e905b47774ca
---
 src/b4/ez.py         | 15 +++++++++++----
 src/tests/test_ez.py | 26 ++++++++++++++++++++++++++
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/src/b4/ez.py b/src/b4/ez.py
index fa904b1..2378c93 100644
--- a/src/b4/ez.py
+++ b/src/b4/ez.py
@@ -1735,6 +1735,15 @@ def get_cover_subject_body(cover: str) -> Tuple[b4.LoreSubject, str]:
     return lsubject, cbody
 
 
+def strip_cover_signature(cbody: str) -> str:
+    body = cbody.replace('\r', '').rstrip('\n')
+    sigpos = body.rfind('\n-- \n')
+    if sigpos >= 0:
+        return body[:sigpos].rstrip('\n')
+
+    return body
+
+
 def rethread(patches: List[Tuple[str, EmailMessage]]) -> None:
     refto = patches[0][1].get('message-id')
     if refto is not None:
@@ -1993,7 +2002,7 @@ def get_sent_tag_as_patches(
     cover, base_commit, change_id = get_base_changeid_from_tag(tagname)
 
     csubject, cbody = get_cover_subject_body(cover)
-    cbody = cbody.strip() + '\n-- \n' + b4.get_email_signature()
+    cbody = strip_cover_signature(cbody) + '\n-- \n' + b4.get_email_signature()
     prefixes = ['RESEND'] + csubject.get_extra_prefixes(exclude=['RESEND'])
     msgid_tpt = make_msgid_tpt(change_id, revision)
     seriests = int(time.time())
@@ -2661,9 +2670,7 @@ def reroll(
     mybranch: str, tag_msg: str, msgid: str, tagprefix: str = SENT_TAG_PREFIX
 ) -> None:
     # Remove signature
-    chunks = tag_msg.rsplit('\n-- \n')
-    if len(chunks) > 1:
-        tag_msg = chunks[0] + '\n'
+    tag_msg = strip_cover_signature(tag_msg) + '\n'
 
     cover, tracking = load_cover(strip_comments=True)
     revision = tracking['series']['revision']
diff --git a/src/tests/test_ez.py b/src/tests/test_ez.py
index 3d05ef9..9be2064 100644
--- a/src/tests/test_ez.py
+++ b/src/tests/test_ez.py
@@ -408,3 +408,29 @@ def test_store_cover_preserves_series_notes(prepdir_commit: str) -> None:
     ecode, backup_oid = b4.git_run_command(None, ['rev-parse', f'refs/original/{cb}'])
     assert ecode == 0
     assert backup_oid.strip() == pre_head
+
+
+def test_strip_cover_signature() -> None:
+    cbody = (
+        'Cover text.\n\n'
+        '---\n'
+        'base-commit: abc123\n'
+        'change-id: 20260101-test-change-id\n\n'
+        'Best regards,\n'
+        '-- \n'
+        'Test User <[email protected]>\n'
+    )
+
+    assert b4.ez.strip_cover_signature(cbody) == (
+        'Cover text.\n\n'
+        '---\n'
+        'base-commit: abc123\n'
+        'change-id: 20260101-test-change-id\n\n'
+        'Best regards,'
+    )
+
+
+def test_strip_cover_signature_without_signature() -> None:
+    cbody = 'Cover text.\n\n--\n\nMore cover text.\n'
+
+    assert b4.ez.strip_cover_signature(cbody) == cbody.rstrip('\n')