diff mbox series

[b4] ez: Add support for a from field detection mechanism to overwrite authorship

Message ID 20240614150419.1124423-1-kory.maincent@bootlin.com (mailing list archive)
State New
Headers show
Series [b4] ez: Add support for a from field detection mechanism to overwrite authorship | expand

Commit Message

Kory Maincent June 14, 2024, 3:04 p.m. UTC
Implement management of the From tag in the cover letter. If present,
all patches will have their commit messages prepended with it.

One use case is to include info of a company funding or sponsoring a
development, as requested by Jakub Kicinski:
https://lore.kernel.org/all/20240215105846.6dd48886@kernel.org/

Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
---
 src/b4/ez.py | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/src/b4/ez.py b/src/b4/ez.py
index 53e8f0a..2244045 100644
--- a/src/b4/ez.py
+++ b/src/b4/ez.py
@@ -1319,6 +1319,7 @@  def get_cover_dests(cbody: str) -> Tuple[List, List, str]:
     htrs, cmsg, mtrs, basement, sig = b4.LoreMessage.get_body_parts(cbody)
     tos = list()
     ccs = list()
+    fromaddr = set()
     for mtr in list(mtrs):
         if mtr.lname == 'to':
             tos.append(mtr.addr)
@@ -1326,8 +1327,14 @@  def get_cover_dests(cbody: str) -> Tuple[List, List, str]:
         elif mtr.lname == 'cc':
             ccs.append(mtr.addr)
             mtrs.remove(mtr)
+        elif mtr.lname == 'from':
+            if fromaddr:
+                logger.critical("CRITICAL: We can't have two authors for this series")
+                sys.exit(1)
+            fromaddr = mtr.value
+            mtrs.remove(mtr)
     cbody = b4.LoreMessage.rebuild_message(htrs, cmsg, mtrs, basement, sig)
-    return tos, ccs, cbody
+    return tos, ccs, fromaddr, cbody
 
 
 def add_cover(csubject: b4.LoreSubject, msgid_tpt: str, patches: List[Tuple[str, email.message.Message]],
@@ -1579,7 +1586,7 @@  def get_prep_branch_as_patches(movefrom: bool = True, thread: bool = True, addtr
     wrapped = textwrap.wrap('X-B4-Tracking: v=1; b=' + b64tracking, subsequent_indent=' ', width=75)
     thdata = ''.join(wrapped).replace('X-B4-Tracking: ', '')
 
-    alltos, allccs, cbody = get_cover_dests(cover_letter)
+    alltos, allccs, allfrom, cbody = get_cover_dests(cover_letter)
     if len(patches) == 1:
         mixin_cover(cbody, patches)
     else:
@@ -1603,7 +1610,7 @@  def get_prep_branch_as_patches(movefrom: bool = True, thread: bool = True, addtr
     if prefixes:
         header = '[' + ', '.join(prefixes) + f'] {header}'
     tag_msg = f'{header}\n\n{cover_letter}'
-    return alltos, allccs, tag_msg, patches
+    return alltos, allccs, allfrom, tag_msg, patches
 
 
 def get_sent_tag_as_patches(tagname: str, revision: int) -> Tuple[List, List, List[Tuple[str, email.message.Message]]]:
@@ -1623,18 +1630,18 @@  def get_sent_tag_as_patches(tagname: str, revision: int) -> Tuple[List, List, Li
                                       seriests=seriests,
                                       mailfrom=mailfrom)
 
-    alltos, allccs, cbody = get_cover_dests(cbody)
+    alltos, allccs, allfrom, cbody = get_cover_dests(cbody)
     if len(patches) == 1:
         mixin_cover(cbody, patches)
     else:
         add_cover(csubject, msgid_tpt, patches, cbody, seriests)
 
-    return alltos, allccs, patches
+    return alltos, allccs, allfrom, patches
 
 
 def format_patch(output_dir: str) -> None:
     try:
-        tos, ccs, tstr, patches = get_prep_branch_as_patches(thread=False, movefrom=False, addtracking=False)
+        tos, ccs, fromsrc, tstr, patches = get_prep_branch_as_patches(thread=False, movefrom=False, addtracking=False)
     except RuntimeError as ex:
         logger.critical('CRITICAL: Failed to convert range to patches: %s', ex)
         sys.exit(1)
@@ -1764,7 +1771,7 @@  def cmd_send(cmdargs: argparse.Namespace) -> None:
             tagname, revision = get_sent_tagname(mybranch, SENT_TAG_PREFIX, revstr)
 
         try:
-            todests, ccdests, patches = get_sent_tag_as_patches(tagname, revision=revision)
+            todests, ccdests, fromsrc, patches = get_sent_tag_as_patches(tagname, revision=revision)
         except RuntimeError as ex:
             logger.critical('CRITICAL: Failed to convert tag to patches: %s', ex)
             sys.exit(1)
@@ -1784,7 +1791,7 @@  def cmd_send(cmdargs: argparse.Namespace) -> None:
             prefixes = None
 
         try:
-            todests, ccdests, tag_msg, patches = get_prep_branch_as_patches(prefixes=prefixes)
+            todests, ccdests, fromsrc, tag_msg, patches = get_prep_branch_as_patches(prefixes=prefixes)
         except RuntimeError as ex:
             logger.critical('CRITICAL: Failed to convert range to patches: %s', ex)
             sys.exit(1)
@@ -2067,6 +2074,9 @@  def cmd_send(cmdargs: argparse.Namespace) -> None:
                 msg.replace_header('Cc', b4.format_addrs(pcc))
             else:
                 msg.add_header('Cc', b4.format_addrs(pcc))
+        if fromsrc:
+            payload = "From: " + fromsrc + "\n\n" + msg.get_payload()
+            msg.set_payload(payload, charset='utf-8')
 
         send_msgs.append(msg)
 
@@ -2631,7 +2641,7 @@  def auto_to_cc() -> None:
             extras.append(ltr)
 
     try:
-        tos, ccs, tag_msg, patches = get_prep_branch_as_patches()
+        tos, ccs, fromsrc, tag_msg, patches = get_prep_branch_as_patches()
     except RuntimeError:
         logger.info('No commits in branch')
         return