hghooks: validate backouts on vendored paths (bug 1366667) r?gps draft
authorbyron jones <glob@mozilla.com>
Wed, 24 May 2017 15:08:03 +0800
changeset 11170 a6be1e7333cd65dded8a4085c729340794efe6c0
parent 11169 80af4477f7860f4a94316285a86d0f3d2e127fe6
push id1698
push userbjones@mozilla.com
push dateTue, 06 Jun 2017 06:27:41 +0000
reviewersgps
bugs1366667
hghooks: validate backouts on vendored paths (bug 1366667) r?gps In order for backouts to servo to be automatically processed on servo's github repository, we need to ensure that backouts touching the servo directory are well formed, and contain the nodes being backed out. At this point validation is not required on non-vendored paths. MozReview-Commit-ID: 30N81ibz50I
hghooks/mozhghooks/commit-message.py
hghooks/tests/test-commit-messages.t
--- a/hghooks/mozhghooks/commit-message.py
+++ b/hghooks/mozhghooks/commit-message.py
@@ -11,17 +11,18 @@
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
 import re
-from mercurial.node import hex, short
+from mercurial.node import short
+from mozautomation import commitparser
 
 INVALID_REVIEW_FLAG_RE = re.compile(r'[\s.;]r\?(?:\w|$)')
 
 goodMessage = [re.compile(x, re.I) for x in [
     r'bug [0-9]+',
     r'no bug',
 
     r'^(back(ing|ed)?\s+out|backout).*(\s+|\:)[0-9a-f]{12}',
@@ -32,49 +33,59 @@ goodMessage = [re.compile(x, re.I) for x
 trySyntax = re.compile(r'\btry:')
 
 VENDORED_PATHS = (
     'servo/',
 )
 
 
 def is_vendor_ctx(ctx):
-    # This check isn't strictly necessary. But it does filter out
-    # most changesets without having to inspect the file list.
-    desc = ctx.description()
-    if 'Source-Revision: ' not in desc:
-        return False
-
     # Other hooks should ensure that only certain users can change
     # vendored paths.
     if not any(f.startswith(VENDORED_PATHS) for f in ctx.files()):
         return False
 
     return True
 
 
 def is_good_message(ui, c):
     def message(fmt):
         ui.write(
             '\n\n'
             '************************** ERROR ****************************\n'
             '%s\n%s\n%s\n'
             '*************************************************************\n'
             '\n\n'
-            % (fmt.format(rev=hex(c.node())[:12]), c.user(), c.description())
+            % (fmt.format(rev=c.hex()[:12]), c.user(), c.description())
         )
 
-    if is_vendor_ctx(c):
+    desc = c.description()
+    firstline = desc.splitlines()[0]
+
+    # Ensure backout commit descriptions are well formed.
+    if commitparser.is_backout(desc):
+        try:
+            if not commitparser.parse_backouts(desc, strict=True):
+                raise ValueError('Rev {rev} has malformed backout message.')
+            nodes, bugs = commitparser.parse_backouts(desc, strict=True)
+            if not nodes:
+                raise ValueError('Rev {rev} is missing backed out revisions.')
+        except ValueError as e:
+            # Reject invalid backout messages on vendored paths, warn otherwise.
+            if is_vendor_ctx(c):
+                message(str(e))
+                return False
+            ui.write('Warning: %s\n' % str(e).format(rev=c.hex()[:12]))
+
+    # Vendored merges must reference source revisions.
+    if 'Source-Revision: ' in desc and is_vendor_ctx(c):
         ui.write('(%s looks like a vendoring change; ignoring commit message '
                  'hook)\n' % short(c.node()))
         return True
 
-    desc = c.description()
-    firstline = desc.splitlines()[0]
-
     if c.user() in ["ffxbld", "seabld", "tbirdbld", "cltbld"]:
         return True
 
     if trySyntax.search(desc):
         message("Rev {rev} uses try syntax. (Did you mean to push to Try "
                 "instead?)")
         return False
 
--- a/hghooks/tests/test-commit-messages.t
+++ b/hghooks/tests/test-commit-messages.t
@@ -94,28 +94,29 @@ Backing out a single changeset
   $ hg push
   pushing to $TESTTMP/server
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
 
-Including the local numeric ID is silly, but allowed
+Including the local numeric ID is silly and deprecated, but allowed
 
   $ hg backout -r . -m 'backout 5:41f80b316d60'
   reverting foo
   changeset 6:8b918b1082f8 backs out changeset 5:41f80b316d60
   $ hg push
   pushing to $TESTTMP/server
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  Warning: Rev 8b918b1082f8 has malformed backout message.
 
 Checking "revert to" syntax
 
   $ hg backout -r . -m 'Revert to changeset 41f80b316d60 due to incomplete backout'
   reverting foo
   changeset 7:6b805c7a1ea0 backs out changeset 6:8b918b1082f8
   $ hg push
   pushing to $TESTTMP/server
@@ -340,16 +341,17 @@ Test some bad commit messages
   $ hg commit -m "Back out Dao's push because of build bustage"
   $ hg push
   pushing to $TESTTMP/server
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  Warning: Rev 0c2851fbf7ba has malformed backout message.
   
   
   ************************** ERROR ****************************
   Backout rev 0c2851fbf7ba needs a bug number or a rev id.
   test
   Back out Dao's push because of build bustage
   *************************************************************
   
@@ -598,20 +600,71 @@ Messages without "Source-Revision: " are
   $ hg push
   pushing to $TESTTMP/striptest/server-vendor
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
   (768c84b471a9 looks like a vendoring change; ignoring commit message hook)
-Change a random file and make sure someone isn't cheating the hook
+
+Malformed backout message in vendored path
+
+  $ touch servo/bar
+  $ hg -q commit -A -m 'backout bug 123456'
+  $ hg push
+  pushing to $TESTTMP/striptest/server-vendor
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  
+  
+  ************************** ERROR ****************************
+  Rev 169f75837913 has malformed backout message.
+  test
+  backout bug 123456
+  *************************************************************
+  
+  
+  transaction abort!
+  rollback completed
+  abort: pretxnchangegroup.commit_message hook failed
+  [255]
+
+Well formed backout message in vendored path
+
+  $ hg -q commit --amend -m 'Backout changeset 287b02e21fa2'
+  $ hg push
+  pushing to $TESTTMP/striptest/server-vendor
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+Malformed backout message outside of vendored path should be allowed but show
+a warning.
 
   $ mkdir not-vendored
   $ touch not-vendored/foo
+  $ hg -q commit -A -m 'backout bug 123456'
+  $ hg push
+  pushing to $TESTTMP/striptest/server-vendor
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  Warning: Rev 018e10233c06 has malformed backout message.
+
+Change a random file and make sure someone isn't cheating the hook
+
+  $ touch not-vendored/bar
   $ hg -q commit -A -l - << EOF
   > servo: Merge #42 - Not really servo
   > 
   > Not a real vendor since file not correct.
   > 
   > Source-Repo: https://github.com/servo/servo
   > Source-Revision: 287b02e21fa2c81d58b070be36add5e951512679
   > EOF
@@ -621,17 +674,17 @@ Change a random file and make sure someo
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
   
   
   ************************** ERROR ****************************
-  Rev 39998d39f844 needs "Bug N" or "No bug" in the commit message.
+  Rev b2f8699d705c needs "Bug N" or "No bug" in the commit message.
   test
   servo: Merge #42 - Not really servo
   
   Not a real vendor since file not correct.
   
   Source-Repo: https://github.com/servo/servo
   Source-Revision: 287b02e21fa2c81d58b070be36add5e951512679
   *************************************************************