##// END OF EJS Templates
lock: pass "success" boolean to _afterlock callbacks...
lock: pass "success" boolean to _afterlock callbacks This lets the callback decide if it should actually run or not. I suspect that most callbacks (and hooks) *should not* run in this scenario, but I'm trying to not break any existing behavior. `persistmanifestcache`, however, seems actively dangerous to run: we just encountered an exception and the repo is in an unknown state (hopefully a consistent one due to transactions, but this is not 100% guaranteed), and the data we cache may be based on this unknown state. This was observed by our users since we wrap some of the functions that persistmanifestcache calls and it expects that the repo object is in a certain state that we'd set up earlier. If the user hits ctrl-c before we establish that state, we end up crashing there. I'm going to make that extension resilient to this issue, but figured it might be a common issue and should be handled here as well instead of just working around the issue. Differential Revision: https://phab.mercurial-scm.org/D7459

File last commit:

r43623:bec73401 default
r44167:4b065b01 default
Show More
censor.py
119 lines | 3.9 KiB | text/x-python | PythonLexer
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347 # Copyright (C) 2015 - Mike Edgar <adgar@google.com>
#
# This extension enables removal of file content at a given revision,
# rewriting the data/metadata of successive revisions to preserve revision log
# integrity.
"""erase file content at a given revision
The censor command instructs Mercurial to erase all content of a file at a given
revision *without updating the changeset hash.* This allows existing history to
remain valid while preventing future clones/pulls from receiving the erased
data.
Typical uses for censor are due to security or legal requirements, including::
Mads Kiilerich
spelling: trivial spell checking
r26781 * Passwords, private keys, cryptographic material
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347 * Licensed data/code/libraries for which the license has expired
* Personally Identifiable Information or other private data
Censored nodes can interrupt mercurial's typical operation whenever the excised
data needs to be materialized. Some commands, like ``hg cat``/``hg revert``,
simply fail when asked to produce censored data. Others, like ``hg verify`` and
``hg update``, must be capable of tolerating censored data to continue to
function in a meaningful way. Such commands only tolerate censored file
FUJIWARA Katsunori
censor: fix incorrect configuration name for ignoring error at censored file...
r24890 revisions if they are allowed by the "censor.policy=ignore" config option.
Jordi GutiƩrrez Hermoso
censor: document that some commands simply ignore censored data...
r43623
A few informative commands such as ``hg grep`` will unconditionally
ignore censored data and merely report that it was encountered.
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347 """
Gregory Szorc
censor: use absolute_import
r28092 from __future__ import absolute_import
from mercurial.i18n import _
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347 from mercurial.node import short
Gregory Szorc
censor: use absolute_import
r28092
from mercurial import (
error,
Yuya Nishihara
registrar: move cmdutil.command to registrar module (API)...
r32337 registrar,
Gregory Szorc
censor: use absolute_import
r28092 scmutil,
)
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347
cmdtable = {}
Yuya Nishihara
registrar: move cmdutil.command to registrar module (API)...
r32337 command = registrar.command(cmdtable)
Augie Fackler
extensions: change magic "shipped with hg" string...
r29841 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
Augie Fackler
extensions: document that `testedwith = 'internal'` is special...
r25186 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
# be specifying the version(s) of Mercurial they are tested with, or
# leave the attribute unspecified.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 testedwith = b'ships-with-hg-core'
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347
Augie Fackler
formatting: blacken the codebase...
r43346
@command(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'censor',
Augie Fackler
formatting: blacken the codebase...
r43346 [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (
b'r',
b'rev',
b'',
_(b'censor file from specified revision'),
_(b'REV'),
),
(b't', b'tombstone', b'', _(b'replacement tombstone data'), _(b'TEXT')),
Augie Fackler
formatting: blacken the codebase...
r43346 ],
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'-r REV [-t TEXT] [FILE]'),
Augie Fackler
formatting: blacken the codebase...
r43346 helpcategory=command.CATEGORY_MAINTENANCE,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def censor(ui, repo, path, rev=b'', tombstone=b'', **opts):
Matt Harbison
censor: use context manager for lock management
r38460 with repo.wlock(), repo.lock():
FUJIWARA Katsunori
censor: make censor acquire locks before processing...
r27290 return _docensor(ui, repo, path, rev, tombstone, **opts)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def _docensor(ui, repo, path, rev=b'', tombstone=b'', **opts):
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347 if not path:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'must specify file path to censor'))
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347 if not rev:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'must specify revision to censor'))
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347
FUJIWARA Katsunori
censor: make various path forms available like other Mercurial commands...
r25806 wctx = repo[None]
m = scmutil.match(wctx, (path,))
if m.anypats() or len(m.files()) != 1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'can only specify an explicit filename'))
FUJIWARA Katsunori
censor: make various path forms available like other Mercurial commands...
r25806 path = m.files()[0]
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347 flog = repo.file(path)
if not len(flog):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'cannot censor file with no history'))
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347
rev = scmutil.revsingle(repo, rev, rev).rev()
try:
ctx = repo[rev]
except KeyError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'invalid revision identifier %s') % rev)
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347
try:
fctx = ctx.filectx(path)
except error.LookupError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'file does not exist at revision %s') % rev)
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347
fnode = fctx.filenode()
Valentin Gatien-Baron
censor: use a reasonable amount of memory...
r39651 heads = []
for headnode in repo.heads():
Yuya Nishihara
censor: rename loop variable to silence pyflakes warning...
r39697 hc = repo[headnode]
if path in hc and hc.filenode(path) == fnode:
heads.append(hc)
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347 if heads:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 headlist = b', '.join([short(c.node()) for c in heads])
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'cannot censor file in heads (%s)') % headlist,
hint=_(b'clean/delete and commit first'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347
wp = wctx.parents()
if ctx.node() in [p.node() for p in wp]:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'cannot censor working directory'),
hint=_(b'clean/delete/update first'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Mike Edgar
censor: add censor command to hgext with basic client-side tests...
r24347
Gregory Szorc
revlog: move censor logic out of censor extension...
r39814 with repo.transaction(b'censor') as tr:
flog.censorrevision(tr, fnode, tombstone=tombstone)