--- a/hgext/censor.py Wed Oct 10 12:25:28 2018 -0400
+++ b/hgext/censor.py Mon Oct 22 14:46:06 2018 -0400
@@ -33,9 +33,7 @@
from mercurial import (
error,
registrar,
- revlog,
scmutil,
- util,
)
cmdtable = {}
@@ -49,7 +47,8 @@
@command('censor',
[('r', 'rev', '', _('censor file from specified revision'), _('REV')),
('t', 'tombstone', '', _('replacement tombstone data'), _('TEXT'))],
- _('-r REV [-t TEXT] [FILE]'))
+ _('-r REV [-t TEXT] [FILE]'),
+ helpcategory=command.CATEGORY_MAINTENANCE)
def censor(ui, repo, path, rev='', tombstone='', **opts):
with repo.wlock(), repo.lock():
return _docensor(ui, repo, path, rev, tombstone, **opts)
@@ -82,8 +81,11 @@
raise error.Abort(_('file does not exist at revision %s') % rev)
fnode = fctx.filenode()
- headctxs = [repo[c] for c in repo.heads()]
- heads = [c for c in headctxs if path in c and c.filenode(path) == fnode]
+ heads = []
+ for headnode in repo.heads():
+ hc = repo[headnode]
+ if path in hc and hc.filenode(path) == fnode:
+ heads.append(hc)
if heads:
headlist = ', '.join([short(c.node()) for c in heads])
raise error.Abort(_('cannot censor file in heads (%s)') % headlist,
@@ -94,90 +96,5 @@
raise error.Abort(_('cannot censor working directory'),
hint=_('clean/delete/update first'))
- flogv = flog.version & 0xFFFF
- if flogv != revlog.REVLOGV1:
- raise error.Abort(
- _('censor does not support revlog version %d') % (flogv,))
-
- tombstone = revlog.packmeta({"censored": tombstone}, "")
-
- crev = fctx.filerev()
-
- if len(tombstone) > flog.rawsize(crev):
- raise error.Abort(_(
- 'censor tombstone must be no longer than censored data'))
-
- # Using two files instead of one makes it easy to rewrite entry-by-entry
- idxread = repo.svfs(flog.indexfile, 'r')
- idxwrite = repo.svfs(flog.indexfile, 'wb', atomictemp=True)
- if flog.version & revlog.FLAG_INLINE_DATA:
- dataread, datawrite = idxread, idxwrite
- else:
- dataread = repo.svfs(flog.datafile, 'r')
- datawrite = repo.svfs(flog.datafile, 'wb', atomictemp=True)
-
- # Copy all revlog data up to the entry to be censored.
- rio = revlog.revlogio()
- offset = flog.start(crev)
-
- for chunk in util.filechunkiter(idxread, limit=crev * rio.size):
- idxwrite.write(chunk)
- for chunk in util.filechunkiter(dataread, limit=offset):
- datawrite.write(chunk)
-
- def rewriteindex(r, newoffs, newdata=None):
- """Rewrite the index entry with a new data offset and optional new data.
-
- The newdata argument, if given, is a tuple of three positive integers:
- (new compressed, new uncompressed, added flag bits).
- """
- offlags, comp, uncomp, base, link, p1, p2, nodeid = flog.index[r]
- flags = revlog.gettype(offlags)
- if newdata:
- comp, uncomp, nflags = newdata
- flags |= nflags
- offlags = revlog.offset_type(newoffs, flags)
- e = (offlags, comp, uncomp, r, link, p1, p2, nodeid)
- idxwrite.write(rio.packentry(e, None, flog.version, r))
- idxread.seek(rio.size, 1)
-
- def rewrite(r, offs, data, nflags=revlog.REVIDX_DEFAULT_FLAGS):
- """Write the given full text to the filelog with the given data offset.
-
- Returns:
- The integer number of data bytes written, for tracking data offsets.
- """
- flag, compdata = flog.compress(data)
- newcomp = len(flag) + len(compdata)
- rewriteindex(r, offs, (newcomp, len(data), nflags))
- datawrite.write(flag)
- datawrite.write(compdata)
- dataread.seek(flog.length(r), 1)
- return newcomp
-
- # Rewrite censored revlog entry with (padded) tombstone data.
- pad = ' ' * (flog.rawsize(crev) - len(tombstone))
- offset += rewrite(crev, offset, tombstone + pad, revlog.REVIDX_ISCENSORED)
-
- # Rewrite all following filelog revisions fixing up offsets and deltas.
- for srev in xrange(crev + 1, len(flog)):
- if crev in flog.parentrevs(srev):
- # Immediate children of censored node must be re-added as fulltext.
- try:
- revdata = flog.revision(srev)
- except error.CensoredNodeError as e:
- revdata = e.tombstone
- dlen = rewrite(srev, offset, revdata)
- else:
- # Copy any other revision data verbatim after fixing up the offset.
- rewriteindex(srev, offset)
- dlen = flog.length(srev)
- for chunk in util.filechunkiter(dataread, limit=dlen):
- datawrite.write(chunk)
- offset += dlen
-
- idxread.close()
- idxwrite.close()
- if dataread is not idxread:
- dataread.close()
- datawrite.close()
+ with repo.transaction(b'censor') as tr:
+ flog.censorrevision(tr, fnode, tombstone=tombstone)