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.
--- a/mercurial/commands.py Tue Oct 15 22:44:55 2019 +0900
+++ b/mercurial/commands.py Tue Oct 22 09:56:40 2019 -0400
@@ -3440,6 +3440,9 @@
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,19 @@
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')
+ % {b'filename': filename, b'revnum': pycompat.bytestr(revision)}
+ )
+ return content
+
def prep(ctx, fns):
rev = ctx.rev()
pctx = ctx.p1()
@@ -3601,17 +3617,15 @@
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
--- a/tests/test-censor.t Tue Oct 15 22:44:55 2019 +0900
+++ b/tests/test-censor.t Tue Oct 22 09:56:40 2019 -0400
@@ -442,6 +442,33 @@
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