diff mbox series

[b4,2/2] ez: allow inserting a range-diff in the cover-letter

Message ID 20240225-ez-range-diff-cover-letter-v1-2-0df35b63bcf2@gmail.com (mailing list archive)
State Accepted
Headers show
Series ez: allow inserting a range-diff in the cover letter | expand

Commit Message

Philippe Blain Feb. 25, 2024, 10:12 p.m. UTC
Some projects recommend inserting in the cover letter a range-diff
against the previous version when sending subsequent versions of a
series.

Support this convention by recognizing the token '${range_diff}' in the
cover letter template, and automatically invoking 'git range-diff'
against the previous revision when creating the cover letter.

As such, adjust ez.py::compare to allow returning the range-diff output
instead of 'execvp'-ing the command.

Since the range-diff invocation might take some time, only perform it if
the corresponding token is found in the cover letter template.

Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com>
---
 docs/config.rst |  1 +
 src/b4/ez.py    | 32 ++++++++++++++++++++++++++++----
 2 files changed, 29 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/docs/config.rst b/docs/config.rst
index 8523107..77f70f2 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -406,6 +406,7 @@  Contributor-oriented settings
   * ``${cover}``: the content of the cover letter itself
   * ``${shortlog}``: the ``git shortlog`` output for the series
   * ``${diffstat}``: the ``git diff --stat`` output for the series
+  * ``${range_diff}``: the ``git range-diff`` output against the previous revision of the series
   * ``${base_commit}``: the base commit of the series
   * ``${change_id}``: the change-id of the series
   * ``${signature}``: your signature, either from ``~/.signature`` if found, or from your Git config
diff --git a/src/b4/ez.py b/src/b4/ez.py
index 3bf4e9c..11f4cb2 100644
--- a/src/b4/ez.py
+++ b/src/b4/ez.py
@@ -76,6 +76,11 @@  Changes in v${newrev}:
 
 """
 
+DEFAULT_RANGEDIFF_TEMPLATE = """
+Range-diff versus v${oldrev}:
+
+"""
+
 
 def get_auth_configs() -> Tuple[str, str, str, str, str, str]:
     config = b4.get_main_config()
@@ -1242,6 +1247,18 @@  def get_prep_branch_as_patches(movefrom: bool = True, thread: bool = True, addtr
         'base_commit': base_commit,
         'signature': b4.get_email_signature(),
     }
+    if cover_template.find('${range_diff}') >= 0:
+        if revision > 1:
+            oldrev = revision - 1
+            rangediff_template = DEFAULT_RANGEDIFF_TEMPLATE
+            rd_tptvals = {
+                'oldrev': oldrev,
+            }
+            range_diff = Template(rangediff_template.lstrip()).safe_substitute(rd_tptvals)
+            range_diff += compare(oldrev, execvp=False)
+            tptvals['range_diff'] = range_diff
+        else:
+            tptvals['range_diff'] = ""
     cover_letter = Template(cover_template.lstrip()).safe_substitute(tptvals)
     # Store tracking info in the header in a safe format, which should allow us to
     # fully restore our work from the already sent series.
@@ -2055,7 +2072,7 @@  def force_revision(forceto: int) -> None:
     store_cover(cover, tracking)
 
 
-def compare(compareto: str) -> None:
+def compare(compareto: str, execvp: bool = True) -> Union[List[str], None]:
     cover, tracking = load_cover()
     # Try the new format first
     tagname, revision = get_sent_tagname(tracking['series']['change-id'], SENT_TAG_PREFIX, compareto)
@@ -2085,10 +2102,17 @@  def compare(compareto: str) -> None:
     lines = b4.git_get_command_lines(None, gitargs)
     curr_end = lines[0]
     grdcmd = ['git', 'range-diff', '%.12s..%.12s' % (prev_start, prev_end), '%.12s..%.12s' % (curr_start, curr_end)]
-    # We exec range-diff and let it take over
     logger.debug('Running %s', ' '.join(grdcmd))
-    os.execvp(grdcmd[0], grdcmd)
-
+    if (execvp):
+        # We exec range-diff and let it take over
+        os.execvp(grdcmd[0], grdcmd)
+    else:
+        ecode, out = b4.git_run_command(None, grdcmd[1:])
+        if ecode:
+            logger.critical('CRITICAL: Could not execute range-diff')
+            sys.exit(1)
+        else:
+            return out
 
 def auto_to_cc() -> None:
     tocmdstr = None