diff mbox series

[b4] b4: add checkpatch via prep --check

Message ID 20230803-add-checkpatch-v1-1-2952aee9e2a8@google.com (mailing list archive)
State New
Headers show
Series [b4] b4: add checkpatch via prep --check | expand

Commit Message

Justin Stitt Aug. 3, 2023, 10:45 p.m. UTC
This patch adds support for the following incantation:

`$ b4 prep --check`

Which will invoke `./scripts/checkpatch.pl` on your entire series. Fails
gracefully if not in a Linux source tree.

I am using `subprocess.run` to invoke `checkpatch`. I'm letting the
stdout go straight to the user without piping or capturing.

Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Justin Stitt <justinstitt@google.com>
---
To: "Kernel.org Tools" <tools@linux.kernel.org>
To: Nick Desaulniers <ndesaulniers@google.com>
To: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
---
 b4/command.py |  6 ++++++
 b4/ez.py      | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 37 insertions(+), 1 deletion(-)


---
base-commit: 8382882b9fb6c50737b6e19198a259850527d2a6
change-id: 20230803-add-checkpatch-1bc3a54f3bb1

Best regards,
--
Justin Stitt <justinstitt@google.com>

Comments

Konstantin Ryabitsev Aug. 8, 2023, 4:18 p.m. UTC | #1
On Thu, Aug 03, 2023 at 10:45:53PM +0000, Justin Stitt wrote:
> This patch adds support for the following incantation:
> 
> `$ b4 prep --check`

Justin:

I see your patch, but I want to step back a bit and have a broader discussion
about various pre-send integration checks, especially when it comes to how we
report errors and warnings to the developer running the check.

I will send a follow-up topic to the tools and users lists. For now, let's sit
on this and adjust based on the feedback I receive.

-K
diff mbox series

Patch

diff --git a/b4/command.py b/b4/command.py
index 71c1abd..8aa84a2 100644
--- a/b4/command.py
+++ b/b4/command.py
@@ -283,6 +283,12 @@  def setup_parser() -> argparse.ArgumentParser:
                        help='Show series info in a format that can be passed to other commands.')
     spp_g.add_argument('--cleanup', metavar='BRANCHNAME', nargs='?', const='_show',
                        help='Archive and remove a prep-tracked branch and all its sent/ tags')
+    spp_g.add_argument(
+        "--check",
+        action="store_true",
+        default=False,
+        help="Run ./scripts/checkpatch.pl on your entire patch series",
+    )
 
     ag_prepn = sp_prep.add_argument_group('Create new branch', 'Create a new branch for working on patch series')
     ag_prepn.add_argument('-n', '--new', dest='new_series_name',
diff --git a/b4/ez.py b/b4/ez.py
index bbaa807..a9e0fc2 100644
--- a/b4/ez.py
+++ b/b4/ez.py
@@ -26,9 +26,10 @@  import gzip
 import io
 import tarfile
 
-from typing import Optional, Tuple, List, Union
 from email import utils
+from typing import Optional, Tuple, List, Union
 from string import Template
+from pathlib import Path
 
 try:
     import patatt
@@ -2157,6 +2158,30 @@  def set_prefixes(prefixes: list) -> None:
         logger.info('No changes to extra prefixes.')
 
 
+def checkpatch() -> int:
+    """
+    Invoke ./scripts/checkpatch.pl if it is available.
+    Only consider the current working directory.
+    Return True if patch is all good, False otherwise.
+    """
+    from subprocess import run
+
+    checkpath_pl_path = Path("./scripts/checkpatch.pl")
+    if not checkpath_pl_path.exists():
+        logger.critical(f'CRITICAL: no {checkpath_pl_path} found.')
+        logger.critical(f'          Navigate to Linux source tree.')
+        sys.exit(1)
+
+    start = get_series_start()
+    end = 'HEAD'
+    cover_commit = find_cover_commit()
+    patches = b4.git_range_to_patches(None, start, end, ignore_commits={cover_commit})
+    command = ['./scripts/checkpatch.pl', '--git'] + [x[0] for x in patches]
+
+    result = run(command)
+
+    return result.returncode
+
 def cmd_prep(cmdargs: argparse.Namespace) -> None:
     check_can_gfr()
     status = b4.git_get_repo_status()
@@ -2165,6 +2190,11 @@  def cmd_prep(cmdargs: argparse.Namespace) -> None:
         logger.critical('          Stash or commit them first.')
         sys.exit(1)
 
+    if cmdargs.check:
+        checkpatch_return_code = checkpatch()
+        logger.info(f"checkpatch return code: {checkpatch_return_code}")
+        return # nothing else needs to happen after a checkpatch call
+
     if cmdargs.reroll:
         msgid = cmdargs.reroll
         msgs = b4.get_pi_thread_by_msgid(msgid, onlymsgids={msgid}, nocache=True)