ksummit.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: Dan Williams <dan.j.williams@intel.com>
To: konstantin@linuxfoundation.org
Cc: ksummit@lists.linux.dev, workflows@vger.kernel.org
Subject: [PATCH 3/3] mbox: Add a --add-link-note option to shazam
Date: Tue, 14 Oct 2025 00:15:30 -0700	[thread overview]
Message-ID: <20251014071530.3665691-4-dan.j.williams@intel.com> (raw)
In-Reply-To: <20251014071530.3665691-1-dan.j.williams@intel.com>

While the Link: tag is disruptive to some top-level maintainer workflows
[1], it is also useful to a significant number of developers and subsystem
maintainers.

It is also the case that dynamic patch-id lookup [2] is an incomplete
replacement for having the submission Link: trailer readily available.
Specifically, navigating to a patch on gitweb or displaying the patch in
the local developer tree it is convenient to have the metadata inline.

A method to have that metadata available without polluting upstream is to
keep git notes locally.

Add a new option to shazam that annotates newly applied commits with the
Link: trailer of the submission. Honor the b4.linkmask option to use the
preferred namespace (patch.msgid.link) for these links.

Note: Claude Sonnet 4 was used to help early drafts of this patch, but all
submitted lines are authored by me or copied from other parts of b4.

Link: http://lore.kernel.org/CAHk-=whP2zoFm+-EmgQ69-00cxM5jgoEGWyAYVQ8bQYFbb2j=Q@mail.gmail.com [1]
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 src/b4/command.py |  2 ++
 src/b4/mbox.py    | 58 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/src/b4/command.py b/src/b4/command.py
index 455124d9726a..678b0b53d6b9 100644
--- a/src/b4/command.py
+++ b/src/b4/command.py
@@ -211,6 +211,8 @@ def setup_parser() -> argparse.ArgumentParser:
     sp_sh = subparsers.add_parser('shazam', help='Like b4 am, but applies the series to your tree')
     cmd_retrieval_common_opts(sp_sh)
     cmd_am_common_opts(sp_sh)
+    sp_sh.add_argument('-L', '--add-link-note', dest='addlinknote', action='store_true', default=False,
+                       help='Add a git note with Link: trailer for every created commit')
     sh_g = sp_sh.add_mutually_exclusive_group()
     sh_g.add_argument('-H', '--make-fetch-head', dest='makefetchhead', action='store_true', default=False,
                       help='Attempt to treat series as a pull request and fetch it into FETCH_HEAD')
diff --git a/src/b4/mbox.py b/src/b4/mbox.py
index 8810ddd71b21..9479b8995019 100644
--- a/src/b4/mbox.py
+++ b/src/b4/mbox.py
@@ -354,6 +354,8 @@ def make_am(msgs: List[EmailMessage], cmdargs: argparse.Namespace, msgid: str) -
             logger.info(out.strip())
             if ecode == 0:
                 thanks_record_am(lser, cherrypick=cherrypick)
+                if cmdargs.addlinknote:
+                    shazam_notes(topdir, lser, 'HEAD')
             sys.exit(ecode)
 
         base_commit = get_base_commit(topdir, first_body, lser, cmdargs)
@@ -448,6 +450,9 @@ def make_am(msgs: List[EmailMessage], cmdargs: argparse.Namespace, msgid: str) -
             # We exec git-merge and let it take over
             os.execvp(mergecmd[0], mergecmd)
 
+        if cmdargs.addlinknote:
+            shazam_notes(topdir, lser, 'FETCH_HEAD')
+
         logger.info('You can now merge or checkout FETCH_HEAD')
         logger.info('  e.g.: %s', ' '.join(mergecmd))
         sys.exit(0)
@@ -547,6 +552,59 @@ def thanks_record_am(lser: b4.LoreSeries, cherrypick: Optional[List[int]]) -> No
         b4.patchwork_set_state(msgids, pwstate)
 
 
+def commits_by_patchid(gitdir: Optional[str], branch: str, num_patches: int) -> b4.Dict[str, str]:
+    """Create a patch-id to commit lookup for the top N commits"""
+
+    commits = dict()
+
+    args = ['log', '--no-abbrev', '--no-decorate', '--oneline', f'-{num_patches}', branch]
+    lines = b4.git_get_command_lines(gitdir, args)
+    if not lines:
+        return commits
+
+    for line in lines:
+        commit_id, subject = line.split(maxsplit=1)
+
+        ecode, diff_out = b4.git_get_rev_diff(gitdir, commit_id)
+        if ecode != 0 or not diff_out.strip():
+            continue
+
+        patch_id = b4.LoreMessage.get_patch_id(diff_out)
+        if patch_id:
+            commits[patch_id] = commit_id
+
+    return commits
+
+
+def shazam_notes(gitdir: Optional[str], lser: 'b4.LoreSeries', branch: str) -> None:
+    """Match commits to LoreMessages using git patch-id and emit debug info for later git notes processing."""
+    if not lser or not lser.patches:
+        return
+
+    lmsgs = [lmsg for lmsg in lser.patches if lmsg is not None and lmsg.has_diff]
+    if not lmsgs:
+        return
+
+    # Cache recently applied commits by patch-id (account for a merge commit)
+    commits = commits_by_patchid(gitdir, branch, len(lmsgs) + 1)
+    if not commits:
+        return
+
+    # Add link trailer notes
+    for lmsg in lmsgs:
+        patch_id = lmsg.git_patch_id
+        if not patch_id:
+            continue
+
+        if patch_id not in commits:
+            continue
+
+        commit_id = commits[patch_id]
+        linktrailer = lmsg.linktrailer
+        note_message = f"{linktrailer.name}: {linktrailer.value}"
+
+        b4.git_run_command(gitdir, ['notes', 'append', '-m', note_message, commit_id])
+
 def save_as_quilt(am_msgs: List[EmailMessage], q_dirname: str) -> None:
     if os.path.exists(q_dirname):
         logger.critical('ERROR: Directory %s exists, not saving quilt patches', q_dirname)
-- 
2.51.0


  parent reply	other threads:[~2025-10-14  7:15 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-14  7:15 [PATCH 0/3] b4: Add git notes for submission link trailers Dan Williams
2025-10-14  7:15 ` [PATCH 1/3] b4: Move linktrailer to a LoreMessage property Dan Williams
2025-10-14  7:15 ` [PATCH 2/3] b4, ty: Move git_get_rev_diff to __init__ for reuse in post processing shazam Dan Williams
2025-10-14  7:15 ` Dan Williams [this message]
2025-10-14 18:28   ` [PATCH 3/3] mbox: Add a --add-link-note option to shazam dan.j.williams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251014071530.3665691-4-dan.j.williams@intel.com \
    --to=dan.j.williams@intel.com \
    --cc=konstantin@linuxfoundation.org \
    --cc=ksummit@lists.linux.dev \
    --cc=workflows@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox