@@ -26,6 +26,7 @@
from mercurial import cmdutil
from mercurial import scmutil
from mercurial import repoview
+from mercurial import branchmap
from mercurial import revset
from mercurial import error
from mercurial import commands
@@ -37,6 +38,15 @@
cmdtable = {}
command = cmdutil.command(cmdtable)
+# List of commands where no warning is shown for direct access
+directaccesslevel = [
+ # warning or not, extension (None if core), command name
+ (False, None, 'update'),
+ (False, None, 'export'),
+ (True, 'rebase', 'rebase'),
+ (False, 'evolve', 'prune'),
+]
+
def reposetup(ui, repo):
class obsinhibitedrepo(repo.__class__):
@@ -62,7 +72,30 @@
repo.__class__ = obsinhibitedrepo
repo._explicitaccess = set()
+def computehidden(repo):
+ hidden = repoview.computehidden(repo)
+ cl = repo.changelog
+ dynamic = hidden & repo._explicitaccess
+ if dynamic:
+ blocked = cl.ancestors(dynamic, inclusive=True)
+ hidden = frozenset(r for r in hidden if r not in blocked)
+ return hidden
+def setupdirectaccess():
+ """ Add two new filtername that behave like visible to provide direct access
+ and direct access with warning. Wraps the commands to setup direct access """
+ repoview.filtertable.update({'visible-directaccess-nowarn': computehidden})
+ repoview.filtertable.update({'visible-directaccess-warn': computehidden})
+ branchmap.subsettable['visible-directaccess-nowarn'] = 'visible'
+ branchmap.subsettable['visible-directaccess-warn'] = 'visible'
+
+ for warn, ext, cmd in directaccesslevel:
+ cmdtable = extensions.find(ext).cmdtable if ext else commands.table
+ wrapper = wrapwithwarning if warn else wrapwithoutwarning
+ try:
+ extensions.wrapcommand(cmdtable, cmd, wrapper)
+ except error.UnknownCommand:
+ pass
def _update(orig, ui, repo, *args, **kwargs):
"""
When moving to a commit we want to inhibit any obsolete commit affecting
@@ -192,6 +225,16 @@
transaction.addpostclose('inhibitposttransaction', inhibitposttransaction)
return transaction
+def wrapwithoutwarning(orig, ui, repo, *args, **kwargs):
+ if repo and repo.filtername == 'visible':
+ repo = repo.filtered("visible-directaccess-nowarn")
+ return orig(ui, repo, *args, **kwargs)
+
+def wrapwithwarning(orig, ui, repo, *args, **kwargs):
+ if repo and repo.filtername == 'visible':
+ repo = repo.filtered("visible-directaccess-warn")
+ return orig(ui, repo, *args, **kwargs)
+
def extsetup(ui):
# lets wrap the computation of the obsolete set
# We apply inhibition there
@@ -212,8 +255,8 @@
obsolete.cachefuncs['bumped'] = lambda repo: set()
# wrap create marker to make it able to lift the inhibition
extensions.wrapfunction(obsolete, 'createmarkers', _createmarkers)
- extensions.wrapfunction(repoview, '_getdynamicblockers', _accessvisible)
extensions.wrapfunction(revset, 'posttreebuilthook', _posttreebuilthook)
+ setupdirectaccess()
# wrap update to make sure that no obsolete commit is visible after an
# update
extensions.wrapcommand(commands.table, 'update', _update)
@@ -250,8 +293,12 @@
# We extract the symbols that look like hashes and add them to the
# explicitaccess set
orig(tree, repo)
- if repo is not None and repo.filtername == 'visible':
+ filternm = ""
+ if repo is not None:
+ filternm = repo.filtername
+ if filternm is not None and filternm.startswith('visible-directaccess'):
prelength = len(repo._explicitaccess)
+ accessbefore = set(repo._explicitaccess)
repo.symbols = gethashsymbols(tree)
cl = repo.unfiltered().changelog
for node in repo.symbols:
@@ -264,6 +311,12 @@
if rev not in repo.changelog:
repo._explicitaccess.add(rev)
if prelength != len(repo._explicitaccess):
+ if repo.filtername != 'visible-directaccess-nowarn':
+ unhiddencommits = repo._explicitaccess - accessbefore
+ repo.ui.warn( _("Warning: accessing hidden changesets %s "
+ "for write operation\n") %
+ (",".join([str(repo.unfiltered()[l])
+ for l in unhiddencommits])))
repo.invalidatevolatilesets()
@command('debugobsinhibit', [], '')
@@ -271,12 +324,3 @@
"""inhibit obsolescence markers effect on a set of revs"""
nodes = (repo[r].node() for r in scmutil.revrange(repo, revs))
_inhibitmarkers(repo, nodes)
-
-# ensure revision accessed by hash are visible
-###############################################
-
-def _accessvisible(orig, repo):
- """ensure accessed revs stay visible"""
- blockers = orig(repo)
- blockers.update(getattr(repo, '_explicitaccess', ()))
- return blockers
@@ -397,6 +397,9 @@
(use --hidden to access hidden revisions)
[255]
$ hg rebase -r ad78ff7d621f -r 53a94305e133 -d 2db36d8066ff
+ Warning: accessing hidden changesets 2db36d8066ff for write operation
+ Warning: accessing hidden changesets ad78ff7d621f for write operation
+ Warning: accessing hidden changesets 53a94305e133 for write operation
rebasing 10:ad78ff7d621f "add cK"
rebasing 11:53a94305e133 "add cL"
$ hg log -G