hgext/inhibit.py
changeset 1334 b8f880d4171d
parent 1332 1ed337c7f061
child 1338 77cbf9121e8a
equal deleted inserted replaced
1333:dffdd0dbe780 1334:b8f880d4171d
    24 from mercurial import obsolete
    24 from mercurial import obsolete
    25 from mercurial import extensions
    25 from mercurial import extensions
    26 from mercurial import cmdutil
    26 from mercurial import cmdutil
    27 from mercurial import scmutil
    27 from mercurial import scmutil
    28 from mercurial import repoview
    28 from mercurial import repoview
       
    29 from mercurial import branchmap
    29 from mercurial import revset
    30 from mercurial import revset
    30 from mercurial import error
    31 from mercurial import error
    31 from mercurial import commands
    32 from mercurial import commands
    32 from mercurial import lock as lockmod
    33 from mercurial import lock as lockmod
    33 from mercurial import bookmarks
    34 from mercurial import bookmarks
    34 from mercurial import lock as lockmod
    35 from mercurial import lock as lockmod
    35 from mercurial.i18n import _
    36 from mercurial.i18n import _
    36 
    37 
    37 cmdtable = {}
    38 cmdtable = {}
    38 command = cmdutil.command(cmdtable)
    39 command = cmdutil.command(cmdtable)
       
    40 
       
    41 # List of commands where no warning is shown for direct access
       
    42 directaccesslevel = [
       
    43     # warning or not, extension (None if core), command name
       
    44     (False, None, 'update'), 
       
    45     (False, None, 'export'),
       
    46     (True,  'rebase', 'rebase'),
       
    47     (False,  'evolve', 'prune'),
       
    48 ]
    39 
    49 
    40 def reposetup(ui, repo):
    50 def reposetup(ui, repo):
    41 
    51 
    42     class obsinhibitedrepo(repo.__class__):
    52     class obsinhibitedrepo(repo.__class__):
    43 
    53 
    60     if not ui.configbool('inhibit', 'onlydirectaccess', False):
    70     if not ui.configbool('inhibit', 'onlydirectaccess', False):
    61         # Wrapping this to inhibit obsolete revs resulting from a transaction
    71         # Wrapping this to inhibit obsolete revs resulting from a transaction
    62         extensions.wrapfunction(localrepo.localrepository,
    72         extensions.wrapfunction(localrepo.localrepository,
    63                                 'transaction', transactioncallback)
    73                                 'transaction', transactioncallback)
    64 
    74 
    65 
    75 def _computehidden(repo):
       
    76     hidden = repoview.computehidden(repo)
       
    77     cl = repo.changelog
       
    78     dynamic = hidden & repo._explicitaccess
       
    79     if dynamic:
       
    80         blocked = cl.ancestors(dynamic, inclusive=True)
       
    81         hidden = frozenset(r for r in hidden if r not in blocked)
       
    82     return hidden
       
    83 
       
    84 def setupdirectaccess():
       
    85     """ Add two new filtername that behave like visible to provide direct access
       
    86     and direct access with warning. Wraps the commands to setup direct access """
       
    87     repoview.filtertable.update({'visible-directaccess-nowarn': _computehidden})
       
    88     repoview.filtertable.update({'visible-directaccess-warn': _computehidden})
       
    89     branchmap.subsettable['visible-directaccess-nowarn'] = 'visible'
       
    90     branchmap.subsettable['visible-directaccess-warn'] = 'visible'
       
    91 
       
    92     for warn, ext, cmd in directaccesslevel:
       
    93         cmdtable = extensions.find(ext).cmdtable if ext else commands.table
       
    94         wrapper = wrapwithwarning if warn else wrapwithoutwarning
       
    95         try:
       
    96             extensions.wrapcommand(cmdtable, cmd, wrapper)
       
    97         except error.UnknownCommand:
       
    98             pass
    66 def _update(orig, ui, repo, *args, **kwargs):
    99 def _update(orig, ui, repo, *args, **kwargs):
    67     """
   100     """
    68     When moving to a commit we want to inhibit any obsolete commit affecting
   101     When moving to a commit we want to inhibit any obsolete commit affecting
    69     the changeset we are updating to. In other words we don't want any visible
   102     the changeset we are updating to. In other words we don't want any visible
    70     commit to be obsolete.
   103     commit to be obsolete.
   190             _inhibitmarkers(repo, [repo[r].node() for r in visibleobsolete])
   223             _inhibitmarkers(repo, [repo[r].node() for r in visibleobsolete])
   191     transaction = orig(repo, *args, **kwargs)
   224     transaction = orig(repo, *args, **kwargs)
   192     transaction.addpostclose('inhibitposttransaction', inhibitposttransaction)
   225     transaction.addpostclose('inhibitposttransaction', inhibitposttransaction)
   193     return transaction
   226     return transaction
   194 
   227 
       
   228 def wrapwithoutwarning(orig, ui, repo, *args, **kwargs):
       
   229     if repo and repo.filtername == 'visible':
       
   230         repo = repo.filtered("visible-directaccess-nowarn")
       
   231     return orig(ui, repo, *args, **kwargs)
       
   232 
       
   233 def wrapwithwarning(orig, ui, repo, *args, **kwargs):
       
   234     if repo and repo.filtername == 'visible':
       
   235         repo = repo.filtered("visible-directaccess-warn")
       
   236     return orig(ui, repo, *args, **kwargs)
       
   237 
   195 def extsetup(ui):
   238 def extsetup(ui):
   196     # lets wrap the computation of the obsolete set
   239     # lets wrap the computation of the obsolete set
   197     # We apply inhibition there
   240     # We apply inhibition there
   198     obsfunc = obsolete.cachefuncs['obsolete']
   241     obsfunc = obsolete.cachefuncs['obsolete']
   199     def _computeobsoleteset(repo):
   242     def _computeobsoleteset(repo):
   206             obs.discard(getrev(n))
   249             obs.discard(getrev(n))
   207         return obs
   250         return obs
   208     obsolete.cachefuncs['obsolete'] = _computeobsoleteset
   251     obsolete.cachefuncs['obsolete'] = _computeobsoleteset
   209     # wrap create marker to make it able to lift the inhibition
   252     # wrap create marker to make it able to lift the inhibition
   210     extensions.wrapfunction(obsolete, 'createmarkers', _createmarkers)
   253     extensions.wrapfunction(obsolete, 'createmarkers', _createmarkers)
   211     extensions.wrapfunction(repoview, '_getdynamicblockers', _accessvisible)
       
   212     extensions.wrapfunction(revset, 'posttreebuilthook', _posttreebuilthook)
   254     extensions.wrapfunction(revset, 'posttreebuilthook', _posttreebuilthook)
       
   255     setupdirectaccess()
   213     if not ui.configbool('inhibit', 'onlydirectaccess', False):
   256     if not ui.configbool('inhibit', 'onlydirectaccess', False):
   214         # drop divergence computation since it is incompatible with "light revive"
   257         # drop divergence computation since it is incompatible with "light revive"
   215         obsolete.cachefuncs['divergent'] = lambda repo: set()
   258         obsolete.cachefuncs['divergent'] = lambda repo: set()
   216         # drop bumped computation since it is incompatible with "light revive"
   259         # drop bumped computation since it is incompatible with "light revive"
   217         obsolete.cachefuncs['bumped'] = lambda repo: set()
   260         obsolete.cachefuncs['bumped'] = lambda repo: set()
   249 def _posttreebuilthook(orig, tree, repo):
   292 def _posttreebuilthook(orig, tree, repo):
   250     # This is use to enabled direct hash access
   293     # This is use to enabled direct hash access
   251     # We extract the symbols that look like hashes and add them to the
   294     # We extract the symbols that look like hashes and add them to the
   252     # explicitaccess set
   295     # explicitaccess set
   253     orig(tree, repo)
   296     orig(tree, repo)
   254     if repo is not None and repo.filtername == 'visible':
   297     filternm = ""
       
   298     if repo is not None:
       
   299         filternm = repo.filtername
       
   300     if filternm is not None and filternm.startswith('visible-directaccess'):
   255         prelength = len(repo._explicitaccess)
   301         prelength = len(repo._explicitaccess)
       
   302         accessbefore = set(repo._explicitaccess)
   256         repo.symbols = gethashsymbols(tree)
   303         repo.symbols = gethashsymbols(tree)
   257         cl = repo.unfiltered().changelog
   304         cl = repo.unfiltered().changelog
   258         for node in repo.symbols:
   305         for node in repo.symbols:
   259             try:
   306             try:
   260                 node = cl._partialmatch(node)
   307                 node = cl._partialmatch(node)
   263             if node is not None:
   310             if node is not None:
   264                 rev = cl.rev(node)
   311                 rev = cl.rev(node)
   265                 if rev not in repo.changelog:
   312                 if rev not in repo.changelog:
   266                     repo._explicitaccess.add(rev)
   313                     repo._explicitaccess.add(rev)
   267         if prelength != len(repo._explicitaccess):
   314         if prelength != len(repo._explicitaccess):
       
   315             if repo.filtername != 'visible-directaccess-nowarn':
       
   316                 unhiddencommits = repo._explicitaccess - accessbefore
       
   317                 repo.ui.warn( _("Warning: accessing hidden changesets %s " 
       
   318                                 "for write operation\n") % 
       
   319                                 (",".join([str(repo.unfiltered()[l]) 
       
   320                                     for l in unhiddencommits])))
   268             repo.invalidatevolatilesets()
   321             repo.invalidatevolatilesets()
   269 
   322 
   270 @command('debugobsinhibit', [], '')
   323 @command('debugobsinhibit', [], '')
   271 def cmddebugobsinhibit(ui, repo, *revs):
   324 def cmddebugobsinhibit(ui, repo, *revs):
   272     """inhibit obsolescence markers effect on a set of revs"""
   325     """inhibit obsolescence markers effect on a set of revs"""
   273     nodes = (repo[r].node() for r in scmutil.revrange(repo, revs))
   326     nodes = (repo[r].node() for r in scmutil.revrange(repo, revs))
   274     _inhibitmarkers(repo, nodes)
   327     _inhibitmarkers(repo, nodes)
   275 
       
   276 # ensure revision accessed by hash are visible
       
   277 ###############################################
       
   278 
       
   279 def _accessvisible(orig, repo):
       
   280     """ensure accessed revs stay visible"""
       
   281     blockers = orig(repo)
       
   282     blockers.update(getattr(repo, '_explicitaccess', ()))
       
   283     return blockers