Mercurial > evolve
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):