Add script for check patch header, including inclusion, commit,
category, bugzilla sections.
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
pr_checkformat.py | 166 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 166 insertions(+)
create mode 100644 pr_checkformat.py
diff --git a/pr_checkformat.py b/pr_checkformat.py
new file mode 100644
index 000000000000..9a799fe290d9
--- /dev/null
+++ b/pr_checkformat.py
@@ -0,0 +1,166 @@
+#!/usr/bin/python3
+
+import os
+import re
+import sys
+import subprocess
+import shlex
+
+def exec_shell(cmd, workdir = None):
+ p = subprocess.Popen(shlex.split(cmd), stdin = subprocess.PIPE, stdout = subprocess.PIPE,
+ stderr = subprocess.PIPE, cwd = workdir)
+ output, err = p.communicate(timeout = 180)
+ return p.returncode, str(output, 'utf-8'), str(err, 'utf-8')
+
+commit_format = {
+ "[Backport]":
+ [
+ [
+ [r'mainline inclusion\n' ,r''],
+ [r'from mainline(-v\d*\.\d*-rc\d*)?\n' ,r'miss "from mainline"'],
+ [r'commit [a-f0-9]{40}\n' ,r'miss commit or commit-id not 40char'],
+ [r'(category: .*\n)?' ,r''],
+ [r'bugzilla: .*\n' ,r'miss bugzilla'],
+ [r'(CVE: CVE-\d{4}-\d+\n)?' ,r''],
+ [r'\n' ,r'miss \n'],
+ [r'(Reference: .*\n)+' ,r'miss Reference'],
+ [r'\n' ,r'miss \n'],
+ [r'-{16,80}\n' ,r'miss parting line 16~80 "-"'],
+ [r'\n' ,r'miss \n'],
+ ],
+ [
+ [r'stable inclusion\n' ,r''],
+ [r'from stable-v\d*\.\d*\.\d*\n' ,r'miss "from stable"'],
+ [r'commit [a-f0-9]{40}\n' ,r'miss commit or commit-id not 40char'],
+ [r'(category: .*\n)?' ,r''],
+ [r'bugzilla: .*\n' ,r'miss bugzilla'],
+ [r'(CVE: CVE-\d{4}-\d+\n)?' ,r''],
+ [r'\n' ,r'miss \n'],
+ [r'(Reference: .*\n)+' ,r'miss Reference'],
+ [r'\n' ,r'miss \n'],
+ [r'-{16,80}\n' ,r'miss parting line 16~80 "-"'],
+ [r'\n' ,r'miss \n'],
+ ],
+ [
+ [r'.* inclusion\n' ,r'miss inclusion'],
+ [r'(category: .*\n)?' ,r''],
+ [r'bugzilla: .*\n' ,r'miss bugzilla'],
+ [r'(CVE: CVE-\d{4}-\d+\n)?' ,r''],
+ [r'\n' ,r'miss \n'],
+ [r'(Reference: .*\n)+' ,r'miss Reference'],
+ [r'\n' ,r'miss \n'],
+ [r'-{16,80}\n' ,r'miss parting line 16~80 "-"'],
+ [r'\n' ,r'miss \n'],
+ ],
+
+ ],
+ }
+
+def check_employee_id(body):
+ m = re.findall(r'Signed-off-by.*\n', body)
+ if len(m) == 0:
+ return False, "miss Signed-off-by\n"
+ else:
+ for sig in m:
+ __m = re.findall(r'Signed-off-by.*[a-zA-Z][0-9]{8}.*(a)huawei.com', sig)
+ if __m:
+ return False, "incorrect Signed-off-by: %s\n"%(__m);
+
+ m = re.findall(r'Reviewed-by.*\n', body)
+ for rew in m:
+ __m = re.findall(r'Reviewed-by.*[a-zA-Z][0-9]{8}.*(a)huawei.com', rew)
+ if __m:
+ return False, "incorrect Reviewed-by: %s\n"%(__m);
+
+ m = re.findall(r'Author:.*\n', body)
+ for author in m:
+ __m = re.findall(r'Author.*[a-zA-Z][0-9]{8}.*(a)huawei.com', author)
+ if __m:
+ return False, "incorrect author: %s\n"%(__m);
+
+ return True, ""
+
+def format_print(__format, line):
+ description = ""
+ for i in range(0, len(__format)):
+ __line = __format[i][0].replace("\\n","")
+ if i == line:
+ __line += "\t<------" + __format[i][1]
+ description += __line + "\n"
+ return description
+
+def match_format(__format, body):
+ regex = r''
+ match = False
+
+ for i in range(0, len(__format)):
+ regex = regex + __format[i][0]
+ m = re.match(regex, body)
+ if not m:
+ return match, format_print(__format, i)
+ match = True
+
+ return True, ""
+
+def error_description(description):
+ return description
+
+def do_checkformat(patch, workdir = None):
+ commit = patch.split(" ")[0]
+
+ description = ""
+
+ #check subject begin with hw
+ subject = exec_shell('git log --pretty=%s -n 1 %s'%('%s', commit), workdir)[1]
+ subject_type = subject.split(" ")[0]
+ if not subject_type in commit_format:
+ description = "subject should be begin with "
+ for __subject_type in commit_format:
+ description = description + __subject_type + ","
+ return False, error_description(description)
+
+ #check Sig/Review/Author has Job number
+ body = exec_shell('git log -n 1 %s'%(commit), workdir)[1]
+ ret, description = check_employee_id(body)
+ if ret == False:
+ return False, error_description(description)
+
+ #check commit message header
+ body = exec_shell('git log --pretty=%s -n 1 %s'%('%b', commit), workdir)[1]
+ for __format in commit_format[subject_type]:
+ match, description = match_format(__format, body)
+ if match == True:
+ if description == "":
+ return True, "checkformat success"
+ else:
+ return False, error_description(description)
+
+ #not match any template
+ description = "do not match any template!\n"
+ for __subject_type in commit_format:
+ description = description + __subject_type
+ for __format in commit_format[__subject_type]:
+ description += "^^^^^^^^^^\n"
+ description += format_print(__format, -1)
+ description = description + "^^^^^^^^^^\n"
+ return False, error_description(description)
+
+def main():
+ ForT = True
+ tag=sys.argv[1]
+ patches = os.popen("git log --oneline " + tag + "..HEAD").readlines()
+ for patch in patches:
+ ret, description = do_checkformat(patch)
+ if ret == False:
+ print("check " + patch + " failed")
+ print(description)
+ ForT = False
+ if ForT == False:
+ return False
+
+ print("check " + str(len(patches)) + " patch(es) success")
+ return True
+
+if __name__ == "__main__":
+ # execute only if run as a script
+ main()
--
2.20.1