check-commit: try to fix multiline handling
authortimeless <timeless@mozdev.org>
Tue, 12 Jan 2016 08:50:15 +0000
changeset 27782 7291c8165e33
parent 27781 2af351bd289c
child 27783 1d095371de47
check-commit: try to fix multiline handling The old code did not understand the difference between the first line of the summary, and a random line in the summary that happened to include a #, or a random line in the changes that happened to include it. 965788d9ae09 is an example where it fails
contrib/check-commit
tests/test-contrib-check-commit.t
--- a/contrib/check-commit	Thu Jan 07 01:28:59 2016 +0000
+++ b/contrib/check-commit	Tue Jan 12 08:50:15 2016 +0000
@@ -17,39 +17,56 @@
 
 import re, sys, os
 
+commitheader = r"^(?:# [^\n]*\n)*"
+afterheader = commitheader + r"(?!#)"
+beforepatch = afterheader + r"(?!\n(?!@@))"
+
 errors = [
-    (r"[(]bc[)]", "(BC) needs to be uppercase"),
-    (r"[(]issue \d\d\d", "no space allowed between issue and number"),
-    (r"[(]bug(\d|\s)", "use (issueDDDD) instead of bug"),
-    (r"^# User [^@\n]+$", "username is not an email address"),
-    (r"^# .*\n(?!merge with )[^#]\S+[^:] ",
+    (beforepatch + r".*[(]bc[)]", "(BC) needs to be uppercase"),
+    (beforepatch + r".*[(]issue \d\d\d", "no space allowed between issue and number"),
+    (beforepatch + r".*[(]bug(\d|\s)", "use (issueDDDD) instead of bug"),
+    (commitheader + r"# User [^@\n]+\n", "username is not an email address"),
+    (commitheader + r"(?!merge with )[^#]\S+[^:] ",
      "summary line doesn't start with 'topic: '"),
-    (r"^# .*\n[A-Z][a-z]\S+", "don't capitalize summary lines"),
-    (r"^# .*\n[^\n]*: *[A-Z][a-z]\S+", "don't capitalize summary lines"),
-    (r"^# [^\n]*\n\S*[^A-Za-z0-9-]\S*: ",
+    (afterheader + r"[A-Z][a-z]\S+", "don't capitalize summary lines"),
+    (afterheader + r"[^\n]*: *[A-Z][a-z]\S+", "don't capitalize summary lines"),
+    (afterheader + r"\S*[^A-Za-z0-9-]\S*: ",
      "summary keyword should be most user-relevant one-word command or topic"),
-    (r"^# .*\n.*\.\s+$", "don't add trailing period on summary line"),
-    (r"^# .*\n[^#].{78,}", "summary line too long (limit is 78)"),
-    (r"^\+\n \n", "adds double empty line"),
-    (r"^ \n\+\n", "adds double empty line"),
-    (r"^\+[ \t]+def [a-z]+_[a-z]", "adds a function with foo_bar naming"),
+    (afterheader + r".*\.\s*\n", "don't add trailing period on summary line"),
+    (afterheader + r".{79,}", "summary line too long (limit is 78)"),
+    (r"\n\+\n \n", "adds double empty line"),
+    (r"\n \n\+\n", "adds double empty line"),
+    (r"\n\+[ \t]+def [a-z]+_[a-z]", "adds a function with foo_bar naming"),
 ]
 
+word = re.compile('\S')
+def nonempty(first, second):
+    if word.search(first):
+        return first
+    return second
+
 def checkcommit(commit, node = None):
     exitcode = 0
     printed = node is None
     for exp, msg in errors:
-        m = re.search(exp, commit, re.MULTILINE)
+        m = re.search(exp, commit)
         if m:
             pos = 0
+            end = m.end()
+            trailing = re.search(r'(\\n)+$', exp)
+            if trailing:
+                end -= len(trailing.group()) / 2
+            last = ''
             for n, l in enumerate(commit.splitlines(True)):
                 pos += len(l)
-                if pos >= m.end():
+                if pos < end:
+                    last = nonempty(l, last)
+                else:
                     if not printed:
                         printed = True
                         print "node: %s" % node
                     print "%d: %s" % (n, msg)
-                    print " %s" % l[:-1]
+                    print " %s" % nonempty(l, last)[:-1]
                     if "BYPASS" not in os.environ:
                         exitcode = 1
                     break
--- a/tests/test-contrib-check-commit.t	Thu Jan 07 01:28:59 2016 +0000
+++ b/tests/test-contrib-check-commit.t	Tue Jan 12 08:50:15 2016 +0000
@@ -103,7 +103,7 @@
   7: don't add trailing period on summary line
    This has no topic and ends with a period.
   19: adds double empty line
-    
+   +
   15: adds double empty line
    +
   16: adds a function with foo_bar naming