Checkpatch sometimes has false positives. This makes it less useful for
automatic usage: tools like b4 [0] can run checkpatch on all of your
patches and give you a quick overview. When iterating on a branch, it's
tiresome to manually re-check that any errors are known false positives.

This patch adds a mechanism to record alongside the patch that it might
produce certain checkpatch errors, and that these are expected false
positives. There are two aspects to this mechanism:

1. If a block like:

   Notes (checkpatch-ignore):
     FOO,BAR
     BAZ

   Is found before the diff in the patch content, FOO, BAR and BAZ error
   types are ignored while processing this file.

   Its expected that users put this in the "graveyard" i.e. the region
   between the --- and the beginning of the diff.

2. --notes=checkpatch-ignore is added to the `git format-patch`
   command that checkpatch.pl uses in --git mode, so that if the commit
   being inspected has a note [1] under the checkpatch-ignore ref, it
   will be formatted into a block like the one above.

To avoid significant reworks to the Perl code, this is implemented by
mutating a global variable while processing each patch. (The variable
name refers to a patch as a "file" for consistency with other code).

Because the main loop in process() begins to emit errors before it has
necessarily processed the checkpatch-ignore block, this parsing is done
separately in its own loop.

[0] b4 - see "--check" arg
    https://b4.docs.kernel.org/en/latest/contributor/prep.html

[1] https://git-scm.com/docs/git-notes

Signed-off-by: Brendan Jackman <jackm...@google.com>
---

Notes (checkpatch-ignore):
    EMAIL_SUBJECT

 scripts/checkpatch.pl | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 
9eed3683ad76caffbbb2418e5dbea7551d374406..ce6914a845ec3f936ad656fa123f58aa85ce4b2f
 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -53,7 +53,10 @@ my %debug;
 my %camelcase = ();
 my %use_type = ();
 my @use = ();
+# Error types to ignore during the whole invocation.
 my %ignore_type = ();
+# Error types to be ignored in the present "file" (i.e. patch).
+my %file_ignore_type = ();
 my @ignore = ();
 my $help = 0;
 my $configuration_file = ".checkpatch.conf";
@@ -1306,7 +1309,7 @@ for my $filename (@ARGV) {
        my $oldfile = $file;
        $file = 1 if ($is_git_file);
        if ($git) {
-               open($FILE, '-|', "git format-patch -M --stdout -1 $filename") 
||
+               open($FILE, '-|', "git format-patch --notes=checkpatch-ignore 
-M --stdout -1 $filename") ||
                        die "$P: $filename: git format-patch failed - $!\n";
        } elsif ($file) {
                open($FILE, '-|', "diff -u /dev/null $filename") ||
@@ -2329,7 +2332,7 @@ sub show_type {
 
        return defined $use_type{$type} if (scalar keys %use_type > 0);
 
-       return !defined $ignore_type{$type};
+       return !defined $ignore_type{$type} && !defined 
$file_ignore_type{$type};
 }
 
 sub report {
@@ -2624,6 +2627,29 @@ sub exclude_global_initialisers {
                $realfile =~ m@/bpf/.*\.bpf\.c$@;
 }
 
+# Parse the "Notes (checkpatch-ignore):" block in the region before the diff,
+# and set file_ignore_type accordingly.
+sub parse_checkpatch_ignore {
+       my $linesRef = shift;
+       my $in_checkpatch_ignore = 0;
+
+       foreach my $line (@$linesRef) {
+               # have we reached the actual diff?
+               if ($line =~ /^diff --git.*?(\s+)$/ || $line =~ 
/^\+\+\+\s+(\s+)/) {
+                       last;
+               }
+
+               if ($in_checkpatch_ignore) {
+                       if ($line =~ /^\s*$/) {
+                               last;
+                       }
+                       hash_save_array_words(\%file_ignore_type, [$line]);
+               } elsif ($line =~ /^Notes \(checkpatch-ignore\):\s*/) {
+                       $in_checkpatch_ignore = 1;
+               }
+       }
+}
+
 sub process {
        my $filename = shift;
 
@@ -2701,6 +2727,8 @@ sub process {
 
        my $checklicenseline = 1;
 
+       %file_ignore_type = ();
+
        sanitise_line_reset();
        my $line;
        foreach my $rawline (@rawlines) {
@@ -2780,6 +2808,8 @@ sub process {
                }
        }
 
+       parse_checkpatch_ignore(\@lines);
+
        $prefix = '';
 
        $realcnt = 0;

-- 
2.48.0.rc2.279.g1de40edade-goog


Reply via email to