mercurial/upgrade_utils/auto_upgrade.py
changeset 49192 2ab79873786e
child 49194 e4b31016e194
equal deleted inserted replaced
49191:4450faeb52bb 49192:2ab79873786e
       
     1 # upgrade.py - functions for automatic upgrade of Mercurial repository
       
     2 #
       
     3 # Copyright (c) 2022-present, Pierre-Yves David
       
     4 #
       
     5 # This software may be used and distributed according to the terms of the
       
     6 # GNU General Public License version 2 or any later version.
       
     7 from ..i18n import _
       
     8 
       
     9 from .. import (
       
    10     error,
       
    11     requirements as requirementsmod,
       
    12     scmutil,
       
    13 )
       
    14 
       
    15 
       
    16 def get_share_safe_action(repo):
       
    17     """return an automatic-upgrade action for `share-safe` if applicable
       
    18 
       
    19     If no action is needed, return None, otherwise return a callback to upgrade
       
    20     or downgrade the repository according the configuration and repository
       
    21     format.
       
    22     """
       
    23     ui = repo.ui
       
    24     requirements = repo.requirements
       
    25     auto_upgrade_share_source = ui.configbool(
       
    26         b'format',
       
    27         b'use-share-safe.automatic-upgrade-of-mismatching-repositories',
       
    28     )
       
    29 
       
    30     action = None
       
    31 
       
    32     if (
       
    33         auto_upgrade_share_source
       
    34         and requirementsmod.SHARED_REQUIREMENT not in requirements
       
    35     ):
       
    36         sf_config = ui.configbool(b'format', b'use-share-safe')
       
    37         sf_local = requirementsmod.SHARESAFE_REQUIREMENT in requirements
       
    38         if sf_config and not sf_local:
       
    39             msg = _(
       
    40                 b"automatically upgrading repository to the `share-safe`"
       
    41                 b" feature\n"
       
    42             )
       
    43             hint = b"(see `hg help config.format.use-share-safe` for details)\n"
       
    44 
       
    45             def action():
       
    46                 if not ui.quiet:
       
    47                     ui.write_err(msg)
       
    48                     ui.write_err(hint)
       
    49                 requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
       
    50                 scmutil.writereporequirements(repo, requirements)
       
    51 
       
    52         elif sf_local and not sf_config:
       
    53             msg = _(
       
    54                 b"automatically downgrading repository from the `share-safe`"
       
    55                 b" feature\n"
       
    56             )
       
    57             hint = b"(see `hg help config.format.use-share-safe` for details)\n"
       
    58 
       
    59             def action():
       
    60                 if not ui.quiet:
       
    61                     ui.write_err(msg)
       
    62                     ui.write_err(hint)
       
    63                 requirements.discard(requirementsmod.SHARESAFE_REQUIREMENT)
       
    64                 scmutil.writereporequirements(repo, requirements)
       
    65 
       
    66     return action
       
    67 
       
    68 
       
    69 AUTO_UPGRADE_ACTIONS = [
       
    70     get_share_safe_action,
       
    71 ]
       
    72 
       
    73 
       
    74 def may_auto_upgrade(repo, maker_func):
       
    75     """potentially perform auto-upgrade and return the final repository to use
       
    76 
       
    77     Auto-upgrade are "quick" repository upgrade that might automatically be run
       
    78     by "any" repository access. See `hg help config.format` for automatic
       
    79     upgrade documentation.
       
    80 
       
    81     note: each relevant upgrades are done one after the other for simplicity.
       
    82     This avoid having repository is partially inconsistent state while
       
    83     upgrading.
       
    84 
       
    85     repo: the current repository instance
       
    86     maker_func: a factory function that can recreate a repository after an upgrade
       
    87     """
       
    88     clear = False
       
    89 
       
    90     loop = 0
       
    91 
       
    92     while not clear:
       
    93         loop += 1
       
    94         if loop > 100:
       
    95             # XXX basic protection against infinite loop, make it better.
       
    96             raise error.ProgrammingError("Too many auto upgrade loops")
       
    97         clear = True
       
    98         for get_action in AUTO_UPGRADE_ACTIONS:
       
    99             action = get_action(repo)
       
   100             if action is not None:
       
   101                 clear = False
       
   102                 with repo.wlock(wait=False), repo.lock(wait=False):
       
   103                     action = get_action(repo)
       
   104                     if action is not None:
       
   105                         action()
       
   106                     repo = maker_func()
       
   107     return repo