hgext/censor.py
changeset 26587 56b2bcea2529
parent 25806 5e18f6e39006
child 26781 1aee2ab0f902
equal deleted inserted replaced
26586:d51c658d3f04 26587:56b2bcea2529
    41     [('r', 'rev', '', _('censor file from specified revision'), _('REV')),
    41     [('r', 'rev', '', _('censor file from specified revision'), _('REV')),
    42      ('t', 'tombstone', '', _('replacement tombstone data'), _('TEXT'))],
    42      ('t', 'tombstone', '', _('replacement tombstone data'), _('TEXT'))],
    43     _('-r REV [-t TEXT] [FILE]'))
    43     _('-r REV [-t TEXT] [FILE]'))
    44 def censor(ui, repo, path, rev='', tombstone='', **opts):
    44 def censor(ui, repo, path, rev='', tombstone='', **opts):
    45     if not path:
    45     if not path:
    46         raise util.Abort(_('must specify file path to censor'))
    46         raise error.Abort(_('must specify file path to censor'))
    47     if not rev:
    47     if not rev:
    48         raise util.Abort(_('must specify revision to censor'))
    48         raise error.Abort(_('must specify revision to censor'))
    49 
    49 
    50     wctx = repo[None]
    50     wctx = repo[None]
    51 
    51 
    52     m = scmutil.match(wctx, (path,))
    52     m = scmutil.match(wctx, (path,))
    53     if m.anypats() or len(m.files()) != 1:
    53     if m.anypats() or len(m.files()) != 1:
    54         raise util.Abort(_('can only specify an explicit filename'))
    54         raise error.Abort(_('can only specify an explicit filename'))
    55     path = m.files()[0]
    55     path = m.files()[0]
    56     flog = repo.file(path)
    56     flog = repo.file(path)
    57     if not len(flog):
    57     if not len(flog):
    58         raise util.Abort(_('cannot censor file with no history'))
    58         raise error.Abort(_('cannot censor file with no history'))
    59 
    59 
    60     rev = scmutil.revsingle(repo, rev, rev).rev()
    60     rev = scmutil.revsingle(repo, rev, rev).rev()
    61     try:
    61     try:
    62         ctx = repo[rev]
    62         ctx = repo[rev]
    63     except KeyError:
    63     except KeyError:
    64         raise util.Abort(_('invalid revision identifier %s') % rev)
    64         raise error.Abort(_('invalid revision identifier %s') % rev)
    65 
    65 
    66     try:
    66     try:
    67         fctx = ctx.filectx(path)
    67         fctx = ctx.filectx(path)
    68     except error.LookupError:
    68     except error.LookupError:
    69         raise util.Abort(_('file does not exist at revision %s') % rev)
    69         raise error.Abort(_('file does not exist at revision %s') % rev)
    70 
    70 
    71     fnode = fctx.filenode()
    71     fnode = fctx.filenode()
    72     headctxs = [repo[c] for c in repo.heads()]
    72     headctxs = [repo[c] for c in repo.heads()]
    73     heads = [c for c in headctxs if path in c and c.filenode(path) == fnode]
    73     heads = [c for c in headctxs if path in c and c.filenode(path) == fnode]
    74     if heads:
    74     if heads:
    75         headlist = ', '.join([short(c.node()) for c in heads])
    75         headlist = ', '.join([short(c.node()) for c in heads])
    76         raise util.Abort(_('cannot censor file in heads (%s)') % headlist,
    76         raise error.Abort(_('cannot censor file in heads (%s)') % headlist,
    77             hint=_('clean/delete and commit first'))
    77             hint=_('clean/delete and commit first'))
    78 
    78 
    79     wp = wctx.parents()
    79     wp = wctx.parents()
    80     if ctx.node() in [p.node() for p in wp]:
    80     if ctx.node() in [p.node() for p in wp]:
    81         raise util.Abort(_('cannot censor working directory'),
    81         raise error.Abort(_('cannot censor working directory'),
    82             hint=_('clean/delete/update first'))
    82             hint=_('clean/delete/update first'))
    83 
    83 
    84     flogv = flog.version & 0xFFFF
    84     flogv = flog.version & 0xFFFF
    85     if flogv != revlog.REVLOGNG:
    85     if flogv != revlog.REVLOGNG:
    86         raise util.Abort(
    86         raise error.Abort(
    87             _('censor does not support revlog version %d') % (flogv,))
    87             _('censor does not support revlog version %d') % (flogv,))
    88 
    88 
    89     tombstone = filelog.packmeta({"censored": tombstone}, "")
    89     tombstone = filelog.packmeta({"censored": tombstone}, "")
    90 
    90 
    91     crev = fctx.filerev()
    91     crev = fctx.filerev()
    92 
    92 
    93     if len(tombstone) > flog.rawsize(crev):
    93     if len(tombstone) > flog.rawsize(crev):
    94         raise util.Abort(_(
    94         raise error.Abort(_(
    95             'censor tombstone must be no longer than censored data'))
    95             'censor tombstone must be no longer than censored data'))
    96 
    96 
    97     # Using two files instead of one makes it easy to rewrite entry-by-entry
    97     # Using two files instead of one makes it easy to rewrite entry-by-entry
    98     idxread = repo.svfs(flog.indexfile, 'r')
    98     idxread = repo.svfs(flog.indexfile, 'r')
    99     idxwrite = repo.svfs(flog.indexfile, 'wb', atomictemp=True)
    99     idxwrite = repo.svfs(flog.indexfile, 'wb', atomictemp=True)