changeset 6537:80d5d4e587f7

topic: experimental config option and topic namespace checking in precheck()
author Anton Shestakov <av6@dwimlabs.net>
date Thu, 22 Jun 2023 21:51:37 -0300
parents d324fa553620
children d20e5eaba766
files hgext3rd/topic/__init__.py tests/test-namespaces-precheck.t
diffstat 2 files changed, 131 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/hgext3rd/topic/__init__.py	Mon Jul 17 16:20:16 2023 -0300
+++ b/hgext3rd/topic/__init__.py	Thu Jun 22 21:51:37 2023 -0300
@@ -186,6 +186,7 @@
     phases,
     pycompat,
     registrar,
+    rewriteutil,
     scmutil,
     smartset,
     templatefilters,
@@ -273,6 +274,11 @@
 configitem(b'devel', b'tns-report-transactions',
            default=lambda: [],
 )
+# used for allowing users to rewrite history only in their "own" topic
+# namespaces
+configitem(b'experimental', b'tns-allow-rewrite',
+           default=configitems.dynamicdefault,
+)
 configitem(b'experimental', b'topic-mode.server',
            default=configitems.dynamicdefault,
 )
@@ -568,6 +574,15 @@
         extensions.wrapfunction(histedit.histeditaction, 'applychange',
                                 applychangewrap)
 
+    # Wrapping precheck() both in core and in evolve to make sure all rewrite
+    # operations that could use precheck() are covered
+    extensions.wrapfunction(rewriteutil, 'precheck', wrapprecheck)
+    try:
+        evolve = extensions.find(b'evolve')
+        extensions.wrapfunction(evolve.rewriteutil, 'precheck', wrapprecheck)
+    except (KeyError, AttributeError):
+        pass
+
     server.setupserver(ui)
 
 def reposetup(ui, repo):
@@ -1704,6 +1719,26 @@
     if topic:
         _changecurrenttopic(repo, topic)
 
+def wrapprecheck(orig, repo, revs, action=b'rewrite', check_divergence=True):
+    # hg <= 6.1 (d4752aeb20f1)
+    args = pycompat.getargspec(orig).args
+    if r'check_divergence' in args:
+        orig(repo, revs, action, check_divergence=check_divergence)
+    else:
+        orig(repo, revs, action)
+
+    # TODO: at some point in future the default will change from '*' to the
+    # default topic namespace for the current user
+    allow = set(repo.ui.configlist(b'experimental', b'tns-allow-rewrite', [b'*']))
+    if b'*' not in allow:
+        namespaces = set(repo[rev].topic_namespace() for rev in revs)
+        disallowed = namespaces - allow
+        if disallowed:
+            msg = _(b"refusing to %s changesets with these topic namespaces: %s")
+            msg %= (action, b' '.join(disallowed))
+            hint = _(b"modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces")
+            raise compat.InputError(msg, hint=hint)
+
 def _changecurrenttns(repo, tns):
     if tns != b'none':
         with repo.wlock():
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-namespaces-precheck.t	Thu Jun 22 21:51:37 2023 -0300
@@ -0,0 +1,96 @@
+Checking affected topic namespaces before history rewrites
+==========================================================
+
+  $ . "$TESTDIR/testlib/common.sh"
+
+  $ cat >> $HGRCPATH << EOF
+  > [extensions]
+  > evolve =
+  > topic =
+  > rebase =
+  > histedit =
+  > [phases]
+  > publish = no
+  > [experimental]
+  > tns-allow-rewrite =
+  > EOF
+
+  $ hg init repo
+  $ cd repo
+
+Make sure general checks in precheck() happen before topic namespaces checks
+
+  $ hg prune null
+  abort: cannot prune the null revision
+  (no changeset checked out)
+  [10]
+
+  $ echo apple > a
+  $ hg ci -qAm apple
+
+  $ hg debug-topic-namespace foo
+  marked working directory as topic namespace: foo
+  $ hg topic bar
+  marked working directory as topic: bar
+  $ echo banana > b
+  $ hg ci -qAm 'banana'
+
+Allowing topic namespaces with --config works correctly
+
+  $ echo broccoli > b
+  $ hg amend -m 'broccoli'
+  abort: refusing to amend changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+  $ hg amend -m 'broccoli' --config experimental.tns-allow-rewrite=foo,something-unrelated
+
+  $ echo coconut > b
+  $ hg ci -qAm 'coconut'
+
+Testing history-rewriting commands from evolve extension
+
+  $ hg amend -m 'coconut'
+  abort: refusing to amend changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+  $ hg amend --patch -m 'coconut'
+  abort: refusing to amend changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+  $ hg uncommit
+  abort: refusing to uncommit changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+  $ hg prune -r .
+  abort: refusing to prune changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+  $ hg split -r .
+  abort: refusing to split changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+  $ hg touch -r .
+  abort: refusing to touch changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+
+Testing core history-rewriting commands
+
+  $ hg ci --amend
+  abort: refusing to amend changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+  $ hg branch different-branch --rev .
+  abort: refusing to change branch of changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+  $ hg rebase -r . -d null
+  abort: refusing to rebase changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+  $ hg histedit
+  abort: refusing to edit changesets with these topic namespaces: foo
+  (modify experimental.tns-allow-rewrite to allow rewriting changesets from these topic namespaces)
+  [10]
+
+  $ cd ..