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
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]