summaryrefslogtreecommitdiffstats
path: root/sbe/build/tools/hooks/verify-commit
diff options
context:
space:
mode:
Diffstat (limited to 'sbe/build/tools/hooks/verify-commit')
-rwxr-xr-xsbe/build/tools/hooks/verify-commit359
1 files changed, 359 insertions, 0 deletions
diff --git a/sbe/build/tools/hooks/verify-commit b/sbe/build/tools/hooks/verify-commit
new file mode 100755
index 00000000..c29ba9ac
--- /dev/null
+++ b/sbe/build/tools/hooks/verify-commit
@@ -0,0 +1,359 @@
+#!/usr/bin/perl
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: sbe/build/tools/hooks/verify-commit $
+#
+# OpenPOWER sbe Project
+#
+# Contributors Listed Below - COPYRIGHT 2016
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+use strict;
+
+my $issueFound = 0;
+my $errorFound = 0;
+
+my $projectName = $ENV{'PROJECT_NAME'};
+# Relative path of import tree from project root
+my $importPrefix = $ENV{'IMPORT_REL_PATH'}."/";
+
+verifyPatchSet(); # Verify the patch contents.
+verifyCommitMsg(); # Verify the commit message.
+
+# Finish out the divider.
+if ($issueFound)
+{
+ print "------------------------------------------------------------\n";
+}
+
+# Return a bad RC if we found an error. Let warnings pass.
+exit ($errorFound ? -1 : 0);
+
+
+########################### Subroutines ################################
+
+# @sub verifyPatchSet
+#
+# Extract the contents (lines changed) from the patch set and verify.
+#
+sub verifyPatchSet
+{
+ # git-diff options:
+ # * Diff against the previous commit (HEAD~1)
+ # * Filter only added and modified files (AM).
+ # * Show only the lines changed, with no context (U0).
+ # Grep only the lines marked with "+" (instead of "-") to find just the
+ # actions done by this patchset and not the content removed.
+ open PATCH_CONTENTS, "git diff HEAD~1 --diff-filter=AM -U0 | ".
+ "grep -e \"^+\" -e \"^@@.*+[0-9]\\+\" |";
+
+ my %fileContents = ();
+
+ my $lastFile = "";
+ my $fileLines = ();
+ my $lineCount = 0;
+ while (my $line = <PATCH_CONTENTS>)
+ {
+ chomp $line;
+
+ # Line starting with "+++ b/path/to/file" indicate a new file.
+ if ($line =~ m/^\+\+\+ b\/(.*)/)
+ {
+ # Save previous file into the map.
+ if ($lastFile ne "")
+ {
+ $fileContents{$lastFile} = $fileLines;
+ $fileLines = ();
+ $lineCount = 0;
+ }
+ $lastFile = $1;
+ }
+ # Lines starting with "@@" indicates a seek in the file, so update
+ # line numbers.
+ elsif ($line =~ m/^@@.*\+([0-9]+)/)
+ {
+ $lineCount = $1 - 1;
+ }
+ else
+ {
+ $line =~ s/^\+//; # filter off the leading + symbol.
+ $lineCount++;
+ push @{$fileLines}, [$line, $lineCount];
+ }
+ }
+ if ($lastFile ne "") # Save last file into the map.
+ {
+ $fileContents{$lastFile} = $fileLines;
+ $fileLines = ();
+ }
+
+ # Verify each line of each file.
+ foreach my $file (sort keys %fileContents)
+ {
+ foreach my $line (@{$fileContents{$file}})
+ {
+ verifyFileLine($file, @{$line}[0], @{$line}[1]);
+ }
+ }
+}
+
+# @sub verifyFileLine
+#
+# Checks a particular line of the file for the following issues:
+# * Warning: Lines longer than 80 characters, except in trace statement.
+# * Warning: Trailing whitespace.
+# * Warning: Tab characters outside of makefiles.
+# * Warning: TODO or FIXME type tag without a corresponding RTC number.
+# * Warning: NOMERGE tag found.
+#
+sub verifyFileLine
+{
+ my ($file,$line,$count) = @_;
+
+ # Check if file was mirrored
+ my $mirror = 0;
+ if ($file =~ m/^$importPrefix/)
+ {
+ $mirror = 1;
+ }
+
+ # Check line length.
+ if (length($line) > 80)
+ {
+ # Allow trace statements to slide.
+ if (($line =~ m/TRAC[DSFU]/) ||
+ ($line =~m/TS_FAIL/) ||
+ ($line =~m/printk/) ||
+ ($line =~m/displayf/) ||
+ ($line =~ m/FAPI_(INF|IMP|ERR|DBG|SCAN)/))
+ {
+ }
+ else
+ {
+ warning($file,$line,$count,
+ (sprintf "Length is more than 80 characters (%d).",
+ length($line))
+ );
+ }
+ }
+
+ # Check trailing whitespace.
+ if ($line =~ m/\s$/)
+ {
+ warning($file,$line,$count,
+ "Trailing whitespace found.");
+ }
+
+ # Check tabs.
+ if ($line =~ m/\t/)
+ {
+ # Makefiles are ok (require tabs).
+ if (not (($file =~ m/makefile/) || ($file =~ m/\.mk/)))
+ {
+ warning($file,$line,$count,
+ "Tab character found.");
+ }
+ }
+
+ # Check "TODO" or "FIXME" type comments.
+ if (($line =~ m/TODO/i) || ($line =~ m/FIXME/i))
+ {
+ if ( (not ($line =~ m/RTC[\s:]\s*[0-9]+/)) &&
+ (not ($line =~ m/CQ[\s:]\s*[A-Z][A-Z][0-9]+/)))
+ {
+ warning($file,$line,$count,
+ "TODO/FIXME tag without corresponding RTC or CQ number.");
+ }
+ }
+
+ # Check "NOMERGE" type comment.
+ if ($line =~ m/NOMERGE/i)
+ {
+ warning($file,$line,$count,
+ "NOMERGE tag found.");
+ }
+
+ # Check for "Confidential", unless it's a mirrored commit
+ if ($line =~ m/Confidential/i && $projectName =~ m/HostBoot/i && !$mirror)
+ {
+ unless (($file =~ m/verify-commit/) ||
+ ($file =~ m/addCopyright.pl/))
+ {
+ error($file,$line,$count,
+ "File contains 'Confidential'.");
+ }
+ }
+}
+
+# @sub verifyCommitMsg
+#
+# Looks at the commit message to verify the following items:
+# * Topic is exactly 1 line long.
+# * Lines are less than 80 characters.
+# * No trailing whitespace.
+# * Tags, such as 'RTC:', are only found in the footer.
+# * Untagged lines are not found in the footer.
+# * RTC tag is formatted correctly.
+# * Warning for lacking RTC tag.
+#
+sub verifyCommitMsg
+{
+ open COMMIT_CONTENTS, "git log -n1 --pretty=format:%B |";
+ my $lineCount = 0;
+ my $rtcTag = "";
+ my $cqTag = "";
+ my $taggedLine = "";
+ my $untaggedLine = "";
+
+ while (my $line = <COMMIT_CONTENTS>)
+ {
+ $lineCount++;
+ chomp $line;
+
+ # Check line length over 80 characters.
+ if (length($line) > 80)
+ {
+ error("Commit Message",$line,$lineCount,
+ (sprintf "Length is more than 80 characters (%d).",
+ length($line))
+ );
+ }
+
+ # Check trailing whitespace.
+ if ($line =~ m/[^\s]+\s$/)
+ {
+ error("Commit Message",$line,$lineCount,
+ "Trailing whitespace found.");
+ }
+
+ # Blank line indicates a new "section".
+ if ($line =~ m/^$/)
+ {
+ # Check for tags outside of the footer.
+ # (new section implies previous section was not a footer)
+ if ("" ne $taggedLine)
+ {
+ error("Commit Message",$taggedLine,$lineCount,
+ "Tagged line found outside commit-msg footer.");
+ }
+
+ $rtcTag = "";
+ $cqTag = "";
+ $untaggedLine = "";
+ $taggedLine = "";
+ }
+ else
+ {
+ # Check for multi-line topic.
+ if ($lineCount == 2)
+ {
+ error("Commit Message",$line,$lineCount,
+ "Topic must be only one line long.");
+ }
+ }
+
+ # Verify format of RTC message.
+ if ($line =~ m/^\s*RTC:\s*[0-9]+(.*)/)
+ {
+ if ("" ne $rtcTag)
+ {
+ error("Commit Message",$line,$lineCount,
+ "Duplicate RTC tag found.");
+ }
+
+ $rtcTag = $line;
+ if ("" ne $1)
+ {
+ error("Commit Message",$line,$lineCount,
+ (sprintf "RTC tag format incorrect (%s).", $1));
+ }
+ }
+
+ if ($line =~ m/^\s*CQ:\s*[A-Z][A-Z][0-9]+(.*)/)
+ {
+ if ("" ne $cqTag)
+ {
+ error("Commit Message",$line,$lineCount,
+ "Duplicate CQ tag found.");
+ }
+
+ $cqTag = $line;
+ if ("" ne $1)
+ {
+ error("Commit Message",$line,$lineCount,
+ (sprintf "CQ tag format incorrect (%s).", $1));
+ }
+ }
+
+ # Identify if this is a tagged line or a non-tagged line and store
+ # away.
+ if ($line =~ m/^\s*[A-Za-z0-9\-_]+:[^:]/)
+ {
+ # We allow lines that look like tags in the topic like...
+ # "FOO: Adding support for BAR."
+ if ($lineCount > 1)
+ {
+ $taggedLine = $line;
+ }
+ }
+ else
+ {
+ $untaggedLine = $line;
+ }
+ }
+
+ # Warn for missing RTC tag.
+ if (("" eq $rtcTag) && ("" eq $cqTag))
+ {
+ warning("Commit Message","<end-of-file>",$lineCount,
+ "Neither RTC nor CQ tag found.");
+ }
+
+ # Error for a mix of tag / untagged in the last section (ie. untagged
+ # lines in the footer).
+ if (("" ne $untaggedLine) && ("" ne $taggedLine))
+ {
+ error("Commit Message",$untaggedLine,$lineCount,
+ "Untagged line found in footer.");
+ }
+}
+
+sub warning
+{
+ my ($file, $line, $count, $statement) = @_;
+ print "------------------------------------------------------------\n";
+ print "WARNING: $statement\n";
+ print " $file:$count\n";
+ print " $line\n";
+
+ $issueFound = 1;
+}
+
+sub error
+{
+ my ($file, $line, $count, $statement) = @_;
+ print "------------------------------------------------------------\n";
+ print "ERROR: $statement\n";
+ print " $file:$count\n";
+ print " $line\n";
+
+ $issueFound = 1;
+ $errorFound = 1;
+}
+
OpenPOWER on IntegriCloud