Patchwork [1,of,2,V2] grep: warn on censored revisions instead of erroring out

login
register
mail settings
Submitter Jordi Gutiérrez Hermoso
Date Oct. 22, 2019, 2:02 p.m.
Message ID <386e0a956ae57a95d623.1571752962@chloe>
Download mbox | patch
Permalink /patch/42529/
State Accepted
Headers show

Comments

Jordi Gutiérrez Hermoso - Oct. 22, 2019, 2:02 p.m.
# HG changeset patch
# User Jordi Gutiérrez Hermoso <jordigh@octave.org>
# Date 1571752600 14400
#      Tue Oct 22 09:56:40 2019 -0400
# Node ID 386e0a956ae57a95d62330c95497d7460761f3fd
# Parent  d782cce137fd1d50cccfecf8ccb17a623fde8800
grep: warn on censored revisions instead of erroring out

We need most of the grep logic to go through in case we encounter a
censored revision, so we just return a None body for a censored node,
and we stop just short of trying to record matches with the contents
of that censored body. The other parts such as recording that the
censored file has been considered at this revision needs to go into
the proper dicts.

I have also gotten weary of all the abbreviations, so while I did a
small refactor to move the file-data-getting operation into a common
function, I also expanded the abbreviations of the relevant variables
within this little function. Hopefully some day this helps someone
figure out what all the abbreviations mean.

Although the censoring docs currently state that some commands error
out or are ignored depending on the `censor.policy` config, I cannot
see a benefit for grep to ever stop dead in its tracks when a censored
revision is encountered. I will also amend the docs to indicate that
some commands, such as grep, unconditionally ignore censored
revisions.
Yuya Nishihara - Oct. 23, 2019, 12:46 p.m.
On Tue, 22 Oct 2019 10:02:42 -0400, Jordi Gutiérrez Hermoso wrote:
> # HG changeset patch
> # User Jordi Gutiérrez Hermoso <jordigh@octave.org>
> # Date 1571752600 14400
> #      Tue Oct 22 09:56:40 2019 -0400
> # Node ID 386e0a956ae57a95d62330c95497d7460761f3fd
> # Parent  d782cce137fd1d50cccfecf8ccb17a623fde8800
> grep: warn on censored revisions instead of erroring out

Queued, thanks.

> +            ui.warn(
> +                _(b'cannot search in censored file: %(filename)s:%(revnum)s\n')
> +                % {
> +                    'filename': filename,
> +                    'revnum': pycompat.bytestr(revision),

Added missing b''s for py3 compatibility.

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3440,6 +3440,9 @@  def grep(ui, repo, pattern, *pats, **opt
     def grepbody(fn, rev, body):
         matches[rev].setdefault(fn, [])
         m = matches[rev][fn]
+        if body is None:
+            return
+
         for lnum, cstart, cend, line in matchlines(body):
             s = linestate(line, lnum, cstart, cend)
             m.append(s)
@@ -3575,6 +3578,22 @@  def grep(ui, repo, pattern, *pats, **opt
 
     getrenamed = scmutil.getrenamedfn(repo)
 
+    def get_file_content(filename, filelog, filenode, context, revision):
+        try:
+            content = filelog.read(filenode)
+        except error.WdirUnsupported:
+            content = context[filename].data()
+        except error.CensoredNodeError:
+            content = None
+            ui.warn(
+                _(b'cannot search in censored file: %(filename)s:%(revnum)s\n')
+                % {
+                    'filename': filename,
+                    'revnum': pycompat.bytestr(revision),
+                }
+            )
+        return content
+
     def prep(ctx, fns):
         rev = ctx.rev()
         pctx = ctx.p1()
@@ -3601,17 +3620,15 @@  def grep(ui, repo, pattern, *pats, **opt
             files.append(fn)
 
             if fn not in matches[rev]:
-                try:
-                    content = flog.read(fnode)
-                except error.WdirUnsupported:
-                    content = ctx[fn].data()
+                content = get_file_content(fn, flog, fnode, ctx, rev)
                 grepbody(fn, rev, content)
 
             pfn = copy or fn
             if pfn not in matches[parent]:
                 try:
-                    fnode = pctx.filenode(pfn)
-                    grepbody(pfn, parent, flog.read(fnode))
+                    pfnode = pctx.filenode(pfn)
+                    pcontent = get_file_content(pfn, flog, pfnode, pctx, parent)
+                    grepbody(pfn, parent, pcontent)
                 except error.LookupError:
                     pass
 
diff --git a/tests/test-censor.t b/tests/test-censor.t
--- a/tests/test-censor.t
+++ b/tests/test-censor.t
@@ -442,6 +442,33 @@  Censored nodes can be bundled up and unb
   checking files
   checked 14 changesets with 15 changes to 2 files
 
+Grepping only warns, doesn't error out
+
+  $ cd ../rpull
+  $ hg grep 'Normal file'
+  bystander:Normal file v2
+  $ hg grep nothing
+  target:Re-sanitized; nothing to see here
+  $ hg grep --diff 'Normal file'
+  cannot search in censored file: target:7
+  cannot search in censored file: target:10
+  cannot search in censored file: target:12
+  bystander:6:-:Normal file v2
+  cannot search in censored file: target:1
+  cannot search in censored file: target:2
+  cannot search in censored file: target:3
+  bystander:2:-:Normal file here
+  bystander:2:+:Normal file v2
+  bystander:0:+:Normal file here
+  $ hg grep --diff nothing
+  cannot search in censored file: target:7
+  cannot search in censored file: target:10
+  cannot search in censored file: target:12
+  target:13:+:Re-sanitized; nothing to see here
+  cannot search in censored file: target:1
+  cannot search in censored file: target:2
+  cannot search in censored file: target:3
+
 Censored nodes can be imported on top of censored nodes, consecutively
 
   $ hg init ../rimport