--- a/hgext/inhibit.py Wed Apr 01 14:26:10 2015 -0700
+++ b/hgext/inhibit.py Fri Mar 27 10:58:04 2015 -0700
@@ -13,12 +13,21 @@
obsolescence markers. Obsolete revision can be cheaply brought back to life
that way. However as the inhibitor are not fitting in an append only model,
this is incompatible with sharing mutable history.
+
+The second feature is called direct access. It is the ability to refer and
+access hidden sha in commands provided that you know their value.
+For example hg log -r XXX where XXX is a commit has should work whether XXX is
+hidden or not as we assume that the user knows what he is doing when referring
+to XXX.
"""
from mercurial import localrepo
from mercurial import obsolete
from mercurial import extensions
from mercurial import cmdutil
from mercurial import scmutil
+from mercurial import repoview
+from mercurial import revset
+from mercurial import error
cmdtable = {}
command = cmdutil.command(cmdtable)
@@ -37,6 +46,7 @@
return obsinhibit
repo.__class__ = obsinhibitedrepo
+ repo._explicitaccess = set()
# obsolescence inhibitor
########################
@@ -125,9 +135,58 @@
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)
+
+def gethashsymbols(tree):
+ # Returns the list of symbols of the tree that look like hashes
+ # for example for the revset 3::abe3ff it will return ('abe3ff')
+ if not tree:
+ return []
+
+ if len(tree) == 2 and tree[0] == "symbol":
+ try:
+ int(tree[1])
+ return []
+ except ValueError as e:
+ return [tree[1]]
+ elif len(tree) == 3:
+ return gethashsymbols(tree[1]) + gethashsymbols(tree[2])
+ else:
+ return []
+
+def _posttreebuilthook(orig, tree, repo):
+ # This is use to enabled direct hash access
+ # We extract the symbols that look like hashes and add them to the
+ # explicitaccess set
+ orig(tree, repo)
+ if repo and repo.filtername == 'visible':
+ prelength = len(repo._explicitaccess)
+ repo.symbols = gethashsymbols(tree)
+ cl = repo.unfiltered().changelog
+ for node in repo.symbols:
+ try:
+ node = cl._partialmatch(node)
+ except error.LookupError:
+ node = None
+ if node is not None:
+ rev = cl.rev(node)
+ if rev not in repo.changelog:
+ repo._explicitaccess.add(rev)
+ if prelength != len(repo._explicitaccess):
+ repo.invalidatevolatilesets()
@command('debugobsinhibit', [], '')
def cmddebugobsinhibit(ui, repo, *revs):
"""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