# HG changeset patch # User Laurent Charignon # Date 1431463949 25200 # Node ID b8f880d4171d3e0ed10ce85976408681fa1f8b39 # Parent dffdd0dbe78062137761b8c5715db739fe7e9eb5 inhibit: direct access with and without warning on a per command basis We introduce a new filtername visibile-directaccess-nowarn to enable direct access with no warning on a per command basis. The motivation behing this change is to display warning when attempting direct access in destructive commands. diff -r dffdd0dbe780 -r b8f880d4171d hgext/inhibit.py --- a/hgext/inhibit.py Tue May 12 12:26:46 2015 -0700 +++ b/hgext/inhibit.py Tue May 12 13:52:29 2015 -0700 @@ -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 @@ 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 +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 @@ -208,8 +251,8 @@ obsolete.cachefuncs['obsolete'] = _computeobsoleteset # 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() if not ui.configbool('inhibit', 'onlydirectaccess', False): # drop divergence computation since it is incompatible with "light revive" obsolete.cachefuncs['divergent'] = lambda repo: set() @@ -251,8 +294,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: @@ -265,6 +312,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', [], '') @@ -272,12 +325,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 diff -r dffdd0dbe780 -r b8f880d4171d tests/test-inhibit.t --- a/tests/test-inhibit.t Tue May 12 12:26:46 2015 -0700 +++ b/tests/test-inhibit.t Tue May 12 13:52:29 2015 -0700 @@ -401,6 +401,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