[util] Improve error messages for bad Signed-off-by lines
I was tracking down a CI failure for someone and had to add a print
statement to this script to figure out why the commit wasn't allowed.
This patch prints out the "I expected to see ..." message that I
needed. It also checks for malformed signoff lines.
Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/util/lint_commits.py b/util/lint_commits.py
index d3ef23a..437f13b 100755
--- a/util/lint_commits.py
+++ b/util/lint_commits.py
@@ -4,6 +4,7 @@
# SPDX-License-Identifier: Apache-2.0
import argparse
+import re
import sys
from git import Repo
@@ -79,17 +80,45 @@
"separates the summary from the long description.", commit)
success = False
- # Check that the commit message contains a Signed-off-by line which
- # matches the author name and email metadata.
- expected_signoff_line = "Signed-off-by: %s <%s>" % (commit.author.name,
- commit.author.email)
- if expected_signoff_line not in lines:
- error(
- 'The commit message must contain a Signed-off-by line that '
- 'matches the commit author name and email, indicating agreement '
- 'to the Contributor License Agreement. See CONTRIBUTING.md for '
- 'more details. "git commit -s" can be used to have git add this '
- 'line for you.')
+ # Check that the commit message contains at least one Signed-off-by line
+ # that matches the author name and email. There might be other signoffs (if
+ # there are multiple authors). We don't have any requirements about those
+ # at the moment and just pass them through.
+ signoff_lines = []
+ signoff_pfx = 'Signed-off-by: '
+ for idx, line in enumerate(lines):
+ if not line.startswith(signoff_pfx):
+ continue
+
+ signoff_body = line[len(signoff_pfx):]
+ match = re.match(r'[^<]+ <[^>]*>$', signoff_body)
+ if match is None:
+ error('Commit has Signed-off-by line {!r}, but the second part '
+ 'is not of the required form. It should be of the form '
+ '"Signed-off-by: NAME <EMAIL>".'
+ .format(line))
+ success = False
+
+ signoff_lines.append(line)
+
+ expected_signoff_line = ("Signed-off-by: {} <{}>"
+ .format(commit.author.name,
+ commit.author.email))
+ signoff_req_msg = ('The commit message must contain a Signed-off-by line '
+ 'that matches the commit author name and email, '
+ 'indicating agreement to the Contributor License '
+ 'Agreement. See CONTRIBUTING.md for more details. '
+ 'You can use "git commit -s" to ask git to add this '
+ 'line for you.')
+
+ if not signoff_lines:
+ error('Commit has no Signed-off-by line. ' + signoff_req_msg)
+ success = False
+ elif expected_signoff_line not in signoff_lines:
+ error(('Commit has one or more Signed-off-by lines, but not the one '
+ 'we expect. We expected to find "{}". '
+ .format(expected_signoff_line)) +
+ signoff_req_msg)
success = False
return success