changeset 51268:622f00b350be

censor: add a command flag to skip the head checks In some case we spend hours of time checking the heads to censors a simple file is not a good behavior. Especially when censors is used to removed corrupted content.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Fri, 01 Dec 2023 22:44:33 +0100
parents 195ab99cf791
children db121ddd171e
files hgext/censor.py tests/test-censor.t
diffstat 2 files changed, 37 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/censor.py	Fri Dec 01 22:33:35 2023 +0100
+++ b/hgext/censor.py	Fri Dec 01 22:44:33 2023 +0100
@@ -60,17 +60,31 @@
             _(b'censor file from specified revision'),
             _(b'REV'),
         ),
+        (
+            b'',
+            b'check-heads',
+            True,
+            _(b'check that repository heads are not affected'),
+        ),
         (b't', b'tombstone', b'', _(b'replacement tombstone data'), _(b'TEXT')),
     ],
     _(b'-r REV [-t TEXT] [FILE]'),
     helpcategory=command.CATEGORY_MAINTENANCE,
 )
-def censor(ui, repo, path, rev=b'', tombstone=b'', **opts):
+def censor(ui, repo, path, rev=b'', tombstone=b'', check_heads=True, **opts):
     with repo.wlock(), repo.lock():
-        return _docensor(ui, repo, path, rev, tombstone, **opts)
+        return _docensor(
+            ui,
+            repo,
+            path,
+            rev,
+            tombstone,
+            check_heads=check_heads,
+            **opts,
+        )
 
 
-def _docensor(ui, repo, path, rev=b'', tombstone=b'', **opts):
+def _docensor(ui, repo, path, rev=b'', tombstone=b'', check_heads=True, **opts):
     if not path:
         raise error.Abort(_(b'must specify file path to censor'))
     if not rev:
@@ -98,20 +112,22 @@
         raise error.Abort(_(b'file does not exist at revision %s') % rev)
 
     fnode = fctx.filenode()
-    heads = []
-    repo_heads = repo.heads()
-    msg = b'checking for the censored content in %d heads\n' % len(repo_heads)
-    ui.status(msg)
-    for headnode in repo_heads:
-        hc = repo[headnode]
-        if path in hc and hc.filenode(path) == fnode:
-            heads.append(hc)
-    if heads:
-        headlist = b', '.join([short(c.node()) for c in heads])
-        raise error.Abort(
-            _(b'cannot censor file in heads (%s)') % headlist,
-            hint=_(b'clean/delete and commit first'),
-        )
+    if check_heads:
+        heads = []
+        repo_heads = repo.heads()
+        msg = b'checking for the censored content in %d heads\n'
+        msg %= len(repo_heads)
+        ui.status(msg)
+        for headnode in repo_heads:
+            hc = repo[headnode]
+            if path in hc and hc.filenode(path) == fnode:
+                heads.append(hc)
+        if heads:
+            headlist = b', '.join([short(c.node()) for c in heads])
+            raise error.Abort(
+                _(b'cannot censor file in heads (%s)') % headlist,
+                hint=_(b'clean/delete and commit first'),
+            )
 
     wp = wctx.parents()
     if ctx.node() in [p.node() for p in wp]:
--- a/tests/test-censor.t	Fri Dec 01 22:33:35 2023 +0100
+++ b/tests/test-censor.t	Fri Dec 01 22:44:33 2023 +0100
@@ -511,6 +511,10 @@
   (run 'hg update' to get a working copy)
   $ hg cat -r 0 target | head -n 10
 
+Can skip the head checking steps
+
+  $ hg --config extensions.censor= censor -r 0  --no-check-heads target
+
 #if revlogv2
 
 Testing feature that does not work in revlog v1