diff hgext/inhibit.py @ 1339:0e2eb196923a

inhibit: create direct access extension Since we want to use direct access without necessarily using inhibit, this patch separates both extensions. Inhibit depends on direct access and we add a test to check that it complains if that is not the case.
author Laurent Charignon <lcharignon@fb.com>
date Thu, 14 May 2015 11:23:40 -0700
parents 77cbf9121e8a
children 9a1415f8b21b
line wrap: on
line diff
--- a/hgext/inhibit.py	Thu May 14 15:59:06 2015 -0700
+++ b/hgext/inhibit.py	Thu May 14 11:23:40 2015 -0700
@@ -1,52 +1,33 @@
-"""Reduce the changesets evolution feature scope for early and noob friendly UI
+"""reduce the changesets evolution feature scope for early and noob friendly ui
 
-The full scale changeset evolution have some massive bleeding edge and it is
+the full scale changeset evolution have some massive bleeding edge and it is
 very easy for people not very intimate with the concept to end up in intricate
-situation. In order to get some of the benefit sooner, this extension is
-disabling some of the less polished aspect of evolution. It should gradually
-get thinner and thinner as changeset evolution will get more polished. This
-extension is only recommended for large scale organisations. Individual user
-should probably stick on using Evolution in its current state, understand its
+situation. in order to get some of the benefit sooner, this extension is
+disabling some of the less polished aspect of evolution. it should gradually
+get thinner and thinner as changeset evolution will get more polished. this
+extension is only recommended for large scale organisations. individual user
+should probably stick on using evolution in its current state, understand its
 concept and provide feedback
 
-The first feature provided by this extension is the ability to "inhibit"
-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.
+This extension provides the ability to "inhibit" 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.
 """
 from mercurial import localrepo
 from mercurial import obsolete
 from mercurial import extensions
 from mercurial import cmdutil
+from mercurial import error
 from mercurial import scmutil
-from mercurial import repoview
-from mercurial import branchmap
-from mercurial import revset
-from mercurial import error
 from mercurial import commands
 from mercurial import lock as lockmod
 from mercurial import bookmarks
-from mercurial import lock as lockmod
 from mercurial.i18n import _
 
 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__):
@@ -66,36 +47,10 @@
             return newnode
 
     repo.__class__ = obsinhibitedrepo
-    repo._explicitaccess = set()
-    if not ui.configbool('inhibit', 'onlydirectaccess', False):
-        # Wrapping this to inhibit obsolete revs resulting from a transaction
-        extensions.wrapfunction(localrepo.localrepository,
-                                'transaction', transactioncallback)
-
-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
+    # Wrapping this to inhibit obsolete revs resulting from a transaction
+    extensions.wrapfunction(localrepo.localrepository,
+                            'transaction', transactioncallback)
 
-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
@@ -211,7 +166,6 @@
     finally:
         tr.release()
 
-
 def transactioncallback(orig, repo, *args, **kwargs):
     """ Wrap localrepo.transaction to inhibit new obsolete changes """
     def inhibitposttransaction(transaction):
@@ -226,16 +180,6 @@
     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
@@ -249,77 +193,29 @@
         for n in repo._obsinhibit:
             obs.discard(getrev(n))
         return obs
+    try:
+        extensions.find('directaccess')
+    except KeyError:
+        errormsg = _('Cannot use inhibit without the direct access extension')
+        raise error.Abort(errormsg)
     obsolete.cachefuncs['obsolete'] = _computeobsoleteset
     # wrap create marker to make it able to lift the inhibition
     extensions.wrapfunction(obsolete, 'createmarkers', _createmarkers)
-    extensions.wrapfunction(revset, 'posttreebuilthook', _posttreebuilthook)
-    setupdirectaccess()
-    if not ui.configbool('inhibit', 'onlydirectaccess', False):
-        # drop divergence computation since it is incompatible with "light revive"
-        obsolete.cachefuncs['divergent'] = lambda repo: set()
-        # drop bumped computation since it is incompatible with "light revive"
-        obsolete.cachefuncs['bumped'] = lambda repo: set()
-        # wrap update to make sure that no obsolete commit is visible after an
-        # update
-        extensions.wrapcommand(commands.table, 'update', _update)
-        # There are two ways to save bookmark changes during a transation, we
-        # wrap both to add inhibition markers.
-        extensions.wrapfunction(bookmarks.bmstore, 'recordchange', _bookmarkchanged)
-        extensions.wrapfunction(bookmarks.bmstore, 'write', _bookmarkchanged)
-        # Add bookmark -D option
-        entry = extensions.wrapcommand(commands.table, 'bookmark', _bookmark)
-        entry[1].append(('D','prune',None,
-                        _('delete the bookmark and prune the commits underneath')))
-
-
-
-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)
-    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:
-            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):
-            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()
+    # drop divergence computation since it is incompatible with "light revive"
+    obsolete.cachefuncs['divergent'] = lambda repo: set()
+    # drop bumped computation since it is incompatible with "light revive"
+    obsolete.cachefuncs['bumped'] = lambda repo: set()
+    # wrap update to make sure that no obsolete commit is visible after an
+    # update
+    extensions.wrapcommand(commands.table, 'update', _update)
+    # There are two ways to save bookmark changes during a transation, we
+    # wrap both to add inhibition markers.
+    extensions.wrapfunction(bookmarks.bmstore, 'recordchange', _bookmarkchanged)
+    extensions.wrapfunction(bookmarks.bmstore, 'write', _bookmarkchanged)
+    # Add bookmark -D option
+    entry = extensions.wrapcommand(commands.table, 'bookmark', _bookmark)
+    entry[1].append(('D','prune',None,
+                    _('delete the bookmark and prune the commits underneath')))
 
 @command('debugobsinhibit', [], '')
 def cmddebugobsinhibit(ui, repo, *revs):