]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Scripts/PatchCheck.py
BaseTools/Scripts/PatchCheck.py: Do not use mailmap
[mirror_edk2.git] / BaseTools / Scripts / PatchCheck.py
index 3b6d77081e7e08ae852d6e5a1d2d09bf7ca28dda..13da6967785d45e0ab5186054f14d53682000379 100755 (executable)
@@ -1,7 +1,7 @@
 ## @file\r
 #  Check a patch for various format issues\r
 #\r
-#  Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>\r
 #  Copyright (C) 2020, Red Hat, Inc.<BR>\r
 #\r
 #  SPDX-License-Identifier: BSD-2-Clause-Patent\r
@@ -26,18 +26,22 @@ class Verbose:
 class EmailAddressCheck:\r
     """Checks an email address."""\r
 \r
-    def __init__(self, email):\r
+    def __init__(self, email, description):\r
         self.ok = True\r
 \r
         if email is None:\r
             self.error('Email address is missing!')\r
             return\r
+        if description is None:\r
+            self.error('Email description is missing!')\r
+            return\r
 \r
+        self.description = "'" + description + "'"\r
         self.check_email_address(email)\r
 \r
     def error(self, *err):\r
         if self.ok and Verbose.level > Verbose.ONELINE:\r
-            print('The email address is not valid:')\r
+            print('The ' + self.description + ' email address is not valid:')\r
         self.ok = False\r
         if Verbose.level < Verbose.NORMAL:\r
             return\r
@@ -75,6 +79,10 @@ class EmailAddressCheck:
             self.error("The email address cannot contain a space: " +\r
                        mo.group(3))\r
 \r
+        if ' via Groups.Io' in name and mo.group(3).endswith('@groups.io'):\r
+            self.error("Email rewritten by lists DMARC / DKIM / SPF: " +\r
+                       email)\r
+\r
 class CommitMessageCheck:\r
     """Checks the contents of a git commit message."""\r
 \r
@@ -88,6 +96,8 @@ class CommitMessageCheck:
         self.subject = subject\r
         self.msg = message\r
 \r
+        print (subject)\r
+\r
         self.check_contributed_under()\r
         self.check_signed_off_by()\r
         self.check_misc_signatures()\r
@@ -174,7 +184,7 @@ class CommitMessageCheck:
             if s[2] != ' ':\r
                 self.error("There should be a space after '" + sig + ":'")\r
 \r
-            EmailAddressCheck(s[3])\r
+            EmailAddressCheck(s[3], sig)\r
 \r
         return sigs\r
 \r
@@ -204,6 +214,8 @@ class CommitMessageCheck:
         for sig in self.sig_types:\r
             self.find_signatures(sig)\r
 \r
+    cve_re = re.compile('CVE-[0-9]{4}-[0-9]{5}[^0-9]')\r
+\r
     def check_overall_format(self):\r
         lines = self.msg.splitlines()\r
 \r
@@ -221,9 +233,26 @@ class CommitMessageCheck:
             self.error('Empty commit message!')\r
             return\r
 \r
-        if count >= 1 and len(lines[0].rstrip()) >= 72:\r
-            self.error('First line of commit message (subject line) ' +\r
-                       'is too long.')\r
+        if count >= 1 and re.search(self.cve_re, lines[0]):\r
+            #\r
+            # If CVE-xxxx-xxxxx is present in subject line, then limit length of\r
+            # subject line to 92 characters\r
+            #\r
+            if len(lines[0].rstrip()) >= 93:\r
+                self.error(\r
+                    'First line of commit message (subject line) is too long (%d >= 93).' %\r
+                    (len(lines[0].rstrip()))\r
+                    )\r
+        else:\r
+            #\r
+            # If CVE-xxxx-xxxxx is not present in subject line, then limit\r
+            # length of subject line to 75 characters\r
+            #\r
+            if len(lines[0].rstrip()) >= 76:\r
+                self.error(\r
+                    'First line of commit message (subject line) is too long (%d >= 76).' %\r
+                    (len(lines[0].rstrip()))\r
+                    )\r
 \r
         if count >= 1 and len(lines[0].strip()) == 0:\r
             self.error('First line of commit message (subject line) ' +\r
@@ -237,7 +266,14 @@ class CommitMessageCheck:
             if (len(lines[i]) >= 76 and\r
                 len(lines[i].split()) > 1 and\r
                 not lines[i].startswith('git-svn-id:')):\r
-                self.error('Line %d of commit message is too long.' % (i + 1))\r
+                #\r
+                # Print a warning if body line is longer than 75 characters\r
+                #\r
+                print(\r
+                    'WARNING - Line %d of commit message is too long (%d >= 76).' %\r
+                    (i + 1, len(lines[i]))\r
+                    )\r
+                print(lines[i])\r
 \r
         last_sig_line = None\r
         for i in range(count - 1, 0, -1):\r
@@ -309,7 +345,21 @@ class GitDiffCheck:
                 self.state = PRE_PATCH\r
                 self.filename = line[13:].split(' ', 1)[0]\r
                 self.is_newfile = False\r
-                self.force_crlf = not self.filename.endswith('.sh')\r
+                self.force_crlf = True\r
+                self.force_notabs = True\r
+                if self.filename.endswith('.sh'):\r
+                    #\r
+                    # Do not enforce CR/LF line endings for linux shell scripts.\r
+                    #\r
+                    self.force_crlf = False\r
+                if self.filename == '.gitmodules':\r
+                    #\r
+                    # .gitmodules is updated by git and uses tabs and LF line\r
+                    # endings.  Do not enforce no tabs and do not enforce\r
+                    # CR/LF line endings.\r
+                    #\r
+                    self.force_crlf = False\r
+                    self.force_notabs = False\r
             elif len(line.rstrip()) != 0:\r
                 self.format_error("didn't find diff command")\r
             self.line_num += 1\r
@@ -323,6 +373,11 @@ class GitDiffCheck:
                 self.binary = True\r
                 if self.is_newfile:\r
                     self.new_bin.append(self.filename)\r
+            elif line.startswith('new file mode 160000'):\r
+                #\r
+                # New submodule.  Do not enforce CR/LF line endings\r
+                #\r
+                self.force_crlf = False\r
             else:\r
                 ok = False\r
                 self.is_newfile = self.newfile_prefix_re.match(line)\r
@@ -397,7 +452,7 @@ class GitDiffCheck:
         if self.force_crlf and eol != '\r\n':\r
             self.added_line_error('Line ending (%s) is not CRLF' % repr(eol),\r
                                   line)\r
-        if '\t' in line:\r
+        if self.force_notabs and '\t' in line:\r
             self.added_line_error('Tab character used', line)\r
         if len(stripped) < len(line):\r
             self.added_line_error('Trailing whitespace found', line)\r
@@ -447,6 +502,9 @@ class CheckOnePatch:
         self.patch = patch\r
         self.find_patch_pieces()\r
 \r
+        email_check = EmailAddressCheck(self.author_email, 'Author')\r
+        email_ok = email_check.ok\r
+\r
         msg_check = CommitMessageCheck(self.commit_subject, self.commit_msg)\r
         msg_ok = msg_check.ok\r
 \r
@@ -455,7 +513,7 @@ class CheckOnePatch:
             diff_check = GitDiffCheck(self.diff)\r
             diff_ok = diff_check.ok\r
 \r
-        self.ok = msg_ok and diff_ok\r
+        self.ok = email_ok and msg_ok and diff_ok\r
 \r
         if Verbose.level == Verbose.ONELINE:\r
             if self.ok:\r
@@ -528,11 +586,30 @@ class CheckOnePatch:
         else:\r
             self.stat = mo.group('stat')\r
             self.commit_msg = mo.group('commit_message')\r
+        #\r
+        # Parse subject line from email header.  The subject line may be\r
+        # composed of multiple parts with different encodings.  Decode and\r
+        # combine all the parts to produce a single string with the contents of\r
+        # the decoded subject line.\r
+        #\r
+        parts = email.header.decode_header(pmail.get('subject'))\r
+        subject = ''\r
+        for (part, encoding) in parts:\r
+            if encoding:\r
+                part = part.decode(encoding)\r
+            else:\r
+                try:\r
+                    part = part.decode()\r
+                except:\r
+                    pass\r
+            subject = subject + part\r
 \r
-        self.commit_subject = pmail['subject'].replace('\r\n', '')\r
+        self.commit_subject = subject.replace('\r\n', '')\r
         self.commit_subject = self.commit_subject.replace('\n', '')\r
         self.commit_subject = self.subject_prefix_re.sub('', self.commit_subject, 1)\r
 \r
+        self.author_email = pmail['from']\r
+\r
 class CheckGitCommits:\r
     """Reads patches from git based on the specified git revision range.\r
 \r
@@ -552,6 +629,8 @@ class CheckGitCommits:
                 else:\r
                     blank_line = True\r
                 print('Checking git commit:', commit)\r
+            email = self.read_committer_email_address_from_git(commit)\r
+            self.ok &= EmailAddressCheck(email, 'Committer').ok\r
             patch = self.read_patch_from_git(commit)\r
             self.ok &= CheckOnePatch(commit, patch).ok\r
         if not commits:\r
@@ -568,7 +647,13 @@ class CheckGitCommits:
 \r
     def read_patch_from_git(self, commit):\r
         # Run git to get the commit patch\r
-        return self.run_git('show', '--pretty=email', '--no-textconv', commit)\r
+        return self.run_git('show', '--pretty=email', '--no-textconv',\r
+                            '--no-use-mailmap', commit)\r
+\r
+    def read_committer_email_address_from_git(self, commit):\r
+        # Run git to get the committer email\r
+        return self.run_git('show', '--pretty=%cn <%ce>', '--no-patch',\r
+                            '--no-use-mailmap', commit)\r
 \r
     def run_git(self, *args):\r
         cmd = [ 'git' ]\r