[PATCH 4 of 4] check-commit: try to fix multiline handling

timeless timeless at mozdev.org
Thu Jan 7 16:13:20 CST 2016


# HG changeset patch
# User timeless <timeless at mozdev.org>
# Date 1452203449 0
#      Thu Jan 07 21:50:49 2016 +0000
# Node ID 039e0747daf69dcf454b34459a0d997a85d7f511
# Parent  666391b22d67439f2dee4761fa42775fc3c4e2ef
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

diff --git a/contrib/check-commit b/contrib/check-commit
--- a/contrib/check-commit
+++ b/contrib/check-commit
@@ -17,37 +17,53 @@
 
 import re, sys, os
 
+patchheader = r"^(?:# [^\n]*\n)*"
+afterheader = patchheader + r"(?!#)"
+patchfooter = None
 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+[^:] ",
+    (patchheader + r"# User [^@\n]+\n", "username is not an email address"),
+    (patchheader + 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.*\.\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"[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*\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


More information about the Mercurial-devel mailing list