hooks: don't allow subrepositories on non-user repos (bug 1388559); r?glob draft
authorGregory Szorc <gps@mozilla.com>
Tue, 08 Aug 2017 16:50:51 -0700
changeset 11513 5a161c10d7738bb9da569c46d978ef9d28adbe0f
parent 11512 02675c286d0f50a755f60ff694b26063622b8b46
push id1755
push userbmo:gps@mozilla.com
push dateThu, 10 Aug 2017 18:16:22 +0000
reviewersglob
bugs1388559
hooks: don't allow subrepositories on non-user repos (bug 1388559); r?glob For the reasons stated in the added code. MozReview-Commit-ID: 59z53YmIN9O
hghooks/mozhghooks/check/prevent_subrepos.py
hghooks/mozhghooks/extension.py
hghooks/tests/test-prevent-subrepos.t
new file mode 100644
--- /dev/null
+++ b/hghooks/mozhghooks/check/prevent_subrepos.py
@@ -0,0 +1,77 @@
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from __future__ import absolute_import
+
+
+from ..checks import (
+    PreTxnChangegroupCheck,
+    print_banner,
+)
+
+
+SUBREPO_NOT_ALLOWED = """
+{node} contains subrepositories.
+
+Subrepositories are not allowed on this repository.
+
+Please remove .hgsub and/or .hgsubstate files from the repository and try your
+push again.
+"""
+
+
+SUBREPO_WARNING = """
+{node} contains subrepositories.
+
+Subrepositories are an advanced Mercurial feature. Subrepositories are not
+allowed by default on non-user repositories. Attempting to push this changeset
+to a non-user repository on this server will result in rejection.
+
+Please consider not using subrepositories.
+"""
+
+
+class PreventSubReposCheck(PreTxnChangegroupCheck):
+    """Prevents sub-repos from being committed.
+
+    Sub-repos are a power user feature. They make it difficult to convert repos
+    to and from Git. We also tend to prefer vendoring into a repo instead of
+    creating a "symlink" to another repo.
+
+    This check prevents the introduction of sub-repos on incoming changesets
+    for non-user repos. For user repos, it prints a non-fatal warning
+    discouraging their use.
+    """
+    @property
+    def name(self):
+        return 'prevent_subrepos'
+
+    def relevant(self):
+        return True
+
+    def pre(self):
+        self.fatal = not self.repo_metadata['user_repo']
+        self.done = False
+
+    def check(self, ctx):
+        # Since the check can be non-fatal and since it requires a manifest
+        # (which can be expensive to obtain), no-op if there is no work to do.
+        if self.done:
+            return True
+
+        if '.hgsub' not in ctx and '.hgsubstate' not in ctx:
+            return True
+
+        self.done = True
+
+        if self.fatal:
+            print_banner(self.ui, 'error', SUBREPO_NOT_ALLOWED.format(
+                node=ctx.hex()[0:12]))
+            return False
+        else:
+            print_banner(self.ui, 'warning', SUBREPO_WARNING.format(
+                node=ctx.hex()[0:12]))
+            return True
+
+    def post_check(self):
+        return True
--- a/hghooks/mozhghooks/extension.py
+++ b/hghooks/mozhghooks/extension.py
@@ -54,22 +54,24 @@ def get_checks(ui, repo, info, classes):
 
     return checks
 
 
 def pretxnchangegroup(ui, repo, node, source=None, **kwargs):
     # TODO come up with a mechanism for automatically discovering checks
     # so we don't have to enumerate them all.
     from mozhghooks.check import (
+        prevent_subrepos,
         prevent_symlinks,
         single_root,
         try_task_config_file,
     )
 
     CHECKS = (
+        prevent_subrepos.PreventSubReposCheck,
         prevent_symlinks.PreventSymlinksCheck,
         single_root.SingleRootCheck,
         try_task_config_file.TryConfigCheck,
     )
 
     # Never apply hooks at pull time or when re-applying from strips.
     if source in ('pull', 'strip'):
         return 0
new file mode 100644
--- /dev/null
+++ b/hghooks/tests/test-prevent-subrepos.t
@@ -0,0 +1,96 @@
+  $ . $TESTDIR/hghooks/tests/common.sh
+
+We can create subrepos on user repos (but a warning is printed)
+
+  $ mkdir -p users/someuser
+  $ hg init users/someuser/repo
+  $ hg init users/someuser/repo/subrepo
+  $ configurehooks users/someuser/repo
+
+  $ hg -q clone users/someuser/repo client
+  $ cd client
+
+  $ touch foo
+  $ hg -q commit -A -m initial
+  $ hg -q push
+
+  $ hg init subrepo
+  $ cd subrepo
+  $ echo subrepo > foo
+  $ hg -q commit -A -m 'initial subrepo'
+  $ cd ..
+
+  $ cat > .hgsub << EOF
+  > mysubrepo = subrepo
+  > EOF
+
+  $ hg add .hgsub
+  $ hg commit -m 'add subrepo'
+
+  $ hg files
+  .hgsub
+  .hgsubstate
+  foo
+
+  $ hg push
+  pushing to $TESTTMP/users/someuser/repo
+  pushing subrepo mysubrepo to $TESTTMP/users/someuser/repo/subrepo
+  no changes found
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 2 changes to 2 files
+  
+  ********************************** WARNING ***********************************
+  5e42dc5815d5 contains subrepositories.
+  
+  Subrepositories are an advanced Mercurial feature. Subrepositories are not
+  allowed by default on non-user repositories. Attempting to push this changeset
+  to a non-user repository on this server will result in rejection.
+  
+  Please consider not using subrepositories.
+  ******************************************************************************
+  
+  $ cd ..
+
+We cannot create subrepos on non-user repos
+
+  $ hg init server
+  $ configurehooks server
+We need this to exist so sub-repo push works
+  $ hg init server/subrepo
+  $ cd client
+
+  $ hg push -r 0 ../server
+  pushing to ../server
+  pushing subrepo mysubrepo to ../server/subrepo
+  no changes found
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+  $ hg push ../server
+  pushing to ../server
+  no changes made to subrepo mysubrepo since last push to ../server/subrepo
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 2 changes to 2 files
+  
+  *********************************** ERROR ************************************
+  5e42dc5815d5 contains subrepositories.
+  
+  Subrepositories are not allowed on this repository.
+  
+  Please remove .hgsub and/or .hgsubstate files from the repository and try your
+  push again.
+  ******************************************************************************
+  
+  transaction abort!
+  rollback completed
+  abort: pretxnchangegroup.mozhooks hook failed
+  [255]