* [PATCH b4] ez: avoid duplicate signatures on resend
@ 2026-05-25 4:14 Cássio Gabriel
2026-06-10 2:20 ` Konstantin Ryabitsev
0 siblings, 1 reply; 3+ messages in thread
From: Cássio Gabriel @ 2026-05-25 4:14 UTC (permalink / raw)
To: Kernel.org Tools; +Cc: Konstantin Ryabitsev, Cássio Gabriel
'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 signature block, the regenerated resend can carry
two footer blocks, as we can see here[1].
Strip an existing trailing cover signature before adding the current one.
Recognize both the standard "-- " delimiter and the bare "--" delimiter
observed in archived mail.
[1] https://lore.kernel.org/all/20260511-alsa-hda-cs35l41-fw-work-teardown-v1-1-1184e9bc4f25@gmail.com/
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
---
src/b4/ez.py | 15 +++++++++++----
src/tests/test_ez.py | 21 +++++++++++++++++++++
2 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/src/b4/ez.py b/src/b4/ez.py
index 3e81138..4f55f0f 100644
--- a/src/b4/ez.py
+++ b/src/b4/ez.py
@@ -1734,6 +1734,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 = max(body.rfind('\n-- \n'), 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:
@@ -1992,7 +2001,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())
@@ -2659,9 +2668,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..5abfea2 100644
--- a/src/tests/test_ez.py
+++ b/src/tests/test_ez.py
@@ -408,3 +408,24 @@ 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
+
+
+@pytest.mark.parametrize('sigmarker', ['-- ', '--'])
+def test_strip_cover_signature(sigmarker: str) -> None:
+ cbody = (
+ 'Cover text.\n\n'
+ '---\n'
+ 'base-commit: abc123\n'
+ 'change-id: 20260101-test-change-id\n\n'
+ 'Best regards,\n'
+ f'{sigmarker}\n'
+ 'Test User <test@example.com>\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,'
+ )
---
base-commit: d5d981426ead3f490713ef5d2fd1aa3d0f13b005
change-id: 20260525-resend-signature-fix-9ef453adc559
Best regards,
--
Cássio Gabriel <cassiogabrielcontato@gmail.com>
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH b4] ez: avoid duplicate signatures on resend
2026-05-25 4:14 [PATCH b4] ez: avoid duplicate signatures on resend Cássio Gabriel
@ 2026-06-10 2:20 ` Konstantin Ryabitsev
2026-06-13 2:30 ` Cássio Gabriel
0 siblings, 1 reply; 3+ messages in thread
From: Konstantin Ryabitsev @ 2026-06-10 2:20 UTC (permalink / raw)
To: Cássio Gabriel; +Cc: Kernel.org Tools, Konstantin Ryabitsev
On Mon, 25 May 2026 01:14:23 -0300, Cássio Gabriel <cassiogabrielcontato@gmail.com> wrote:
> diff --git a/src/b4/ez.py b/src/b4/ez.py
> index 3e81138..4f55f0f 100644
> --- a/src/b4/ez.py
> +++ b/src/b4/ez.py
> @@ -1734,6 +1734,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 = max(body.rfind('\n-- \n'), body.rfind('\n--\n'))
> + if sigpos >= 0:
> + return body[:sigpos].rstrip('\n')
> +
> + return body
No, you should drop the '\n--\n' (bare, no trailing space) case from
the sigpos search. The canonical email signature delimiter is '\n-- \n'
— that trailing space is load-bearing and intentional and we
deliberately only recognise the canonical form, and for good reason:
bare '--' appears legitimately in cover letter prose — markdown
horizontal rules, CLI flag documentation, SQL comments, and various
other contexts. Matching it here can silently truncate the cover body
in ways the author would never expect, and the conservative posture of
the existing code is the right one. If someone's cover carries '\n--\n'
from a non-conformant mailer, a doubled footer on resend is a far
smaller problem than silently eating half the cover text.
With the bare '--' case removed the sigpos line simplifies to:
sigpos = body.rfind('\n-- \n')
and the '--' parametrize case in the test should be removed too.
This is the right fix for the resend path. The previous cbody.strip()
also stripped leading whitespace, which this helper does not -- a minor
behaviour change worth looking out for in case it wasn't intentional.
>
> diff --git a/src/tests/test_ez.py b/src/tests/test_ez.py
> index 3d05ef9..5abfea2 100644
> --- a/src/tests/test_ez.py
> +++ b/src/tests/test_ez.py
> @@ -408,3 +408,24 @@ def test_store_cover_preserves_series_notes(prepdir_commit: str) -> None:
> [ ... skip 18 lines ... ]
> + 'Cover text.\n\n'
> + '---\n'
> + 'base-commit: abc123\n'
> + 'change-id: 20260101-test-change-id\n\n'
> + 'Best regards,'
> + )
The '-- ' parametrize case is correct and should be kept. The '--' case
should be removed along with the bare-delimiter matching in the helper itself.
Optionally, adding a no-signature case would lock in that the function returns
the body unchanged (modulo trailing-newline normalization) when no delimiter
is present.
--
Konstantin Ryabitsev <konstantin@linuxfoundation.org>
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH b4] ez: avoid duplicate signatures on resend
2026-06-10 2:20 ` Konstantin Ryabitsev
@ 2026-06-13 2:30 ` Cássio Gabriel
0 siblings, 0 replies; 3+ messages in thread
From: Cássio Gabriel @ 2026-06-13 2:30 UTC (permalink / raw)
To: Konstantin Ryabitsev; +Cc: Kernel.org Tools
[-- Attachment #1.1: Type: text/plain, Size: 2783 bytes --]
Hi!
On 6/9/26 23:20, Konstantin Ryabitsev wrote:
> On Mon, 25 May 2026 01:14:23 -0300, Cássio Gabriel <cassiogabrielcontato@gmail.com> wrote:
>> diff --git a/src/b4/ez.py b/src/b4/ez.py
>> index 3e81138..4f55f0f 100644
>> --- a/src/b4/ez.py
>> +++ b/src/b4/ez.py
>> @@ -1734,6 +1734,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 = max(body.rfind('\n-- \n'), body.rfind('\n--\n'))
>> + if sigpos >= 0:
>> + return body[:sigpos].rstrip('\n')
>> +
>> + return body
>
> No, you should drop the '\n--\n' (bare, no trailing space) case from
> the sigpos search. The canonical email signature delimiter is '\n-- \n'
> — that trailing space is load-bearing and intentional and we
> deliberately only recognise the canonical form, and for good reason:
> bare '--' appears legitimately in cover letter prose — markdown
> horizontal rules, CLI flag documentation, SQL comments, and various
> other contexts. Matching it here can silently truncate the cover body
> in ways the author would never expect, and the conservative posture of
> the existing code is the right one. If someone's cover carries '\n--\n'
> from a non-conformant mailer, a doubled footer on resend is a far
> smaller problem than silently eating half the cover text.
>
> With the bare '--' case removed the sigpos line simplifies to:
>
> sigpos = body.rfind('\n-- \n')
>
> and the '--' parametrize case in the test should be removed too.
>
> This is the right fix for the resend path. The previous cbody.strip()
> also stripped leading whitespace, which this helper does not -- a minor
> behaviour change worth looking out for in case it wasn't intentional.
>
>>
>> diff --git a/src/tests/test_ez.py b/src/tests/test_ez.py
>> index 3d05ef9..5abfea2 100644
>> --- a/src/tests/test_ez.py
>> +++ b/src/tests/test_ez.py
>> @@ -408,3 +408,24 @@ def test_store_cover_preserves_series_notes(prepdir_commit: str) -> None:
>> [ ... skip 18 lines ... ]
>> + 'Cover text.\n\n'
>> + '---\n'
>> + 'base-commit: abc123\n'
>> + 'change-id: 20260101-test-change-id\n\n'
>> + 'Best regards,'
>> + )
>
> The '-- ' parametrize case is correct and should be kept. The '--' case
> should be removed along with the bare-delimiter matching in the helper itself.
> Optionally, adding a no-signature case would lock in that the function returns
> the body unchanged (modulo trailing-newline normalization) when no delimiter
> is present.
Thanks for the review.
I'll respin these suggestions in v2.
--
Thanks,
Cássio
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 236 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-06-13 2:30 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-25 4:14 [PATCH b4] ez: avoid duplicate signatures on resend Cássio Gabriel
2026-06-10 2:20 ` Konstantin Ryabitsev
2026-06-13 2:30 ` Cássio Gabriel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.