##// END OF EJS Templates
revlog: test possible read race condition with splitting...
revlog: test possible read race condition with splitting This is currently working fine, but could break with another approach (for example, with the one we are about to use in the next changesets…) So we make sure the case is covered.

File last commit:

r50237:67b210bb default
r51239:b0cdd0be stable
Show More
auto_upgrade.py
254 lines | 8.5 KiB | text/x-python | PythonLexer
auto-upgrade: introduce a way to auto-upgrade to/from share-safe...
r50087 # upgrade.py - functions for automatic upgrade of Mercurial repository
#
# Copyright (c) 2022-present, Pierre-Yves David
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from ..i18n import _
from .. import (
error,
requirements as requirementsmod,
scmutil,
)
auto-upgrade: introduce a way to auto-upgrade to/from tracked-hint...
r50089 from . import (
actions,
engine,
)
class AutoUpgradeOperation(actions.BaseOperation):
"""A limited Upgrade Operation used to run simple auto upgrade task
(Expand it as needed in the future)
"""
def __init__(self, req):
super().__init__(
new_requirements=req,
backup_store=False,
)
auto-upgrade: introduce a way to auto-upgrade to/from share-safe...
r50087
def get_share_safe_action(repo):
"""return an automatic-upgrade action for `share-safe` if applicable
If no action is needed, return None, otherwise return a callback to upgrade
or downgrade the repository according the configuration and repository
format.
"""
ui = repo.ui
requirements = repo.requirements
auto_upgrade_share_source = ui.configbool(
b'format',
b'use-share-safe.automatic-upgrade-of-mismatching-repositories',
)
auto-upgrade: add an option to silence the share-safe message...
r50234 auto_upgrade_quiet = ui.configbool(
b'format',
b'use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet',
)
auto-upgrade: introduce a way to auto-upgrade to/from share-safe...
r50087
action = None
if (
auto_upgrade_share_source
and requirementsmod.SHARED_REQUIREMENT not in requirements
):
sf_config = ui.configbool(b'format', b'use-share-safe')
sf_local = requirementsmod.SHARESAFE_REQUIREMENT in requirements
if sf_config and not sf_local:
msg = _(
b"automatically upgrading repository to the `share-safe`"
b" feature\n"
)
hint = b"(see `hg help config.format.use-share-safe` for details)\n"
def action():
auto-upgrade: add an option to silence the share-safe message...
r50234 if not (ui.quiet or auto_upgrade_quiet):
auto-upgrade: introduce a way to auto-upgrade to/from share-safe...
r50087 ui.write_err(msg)
ui.write_err(hint)
requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
scmutil.writereporequirements(repo, requirements)
elif sf_local and not sf_config:
msg = _(
b"automatically downgrading repository from the `share-safe`"
b" feature\n"
)
hint = b"(see `hg help config.format.use-share-safe` for details)\n"
def action():
auto-upgrade: add an option to silence the share-safe message...
r50234 if not (ui.quiet or auto_upgrade_quiet):
auto-upgrade: introduce a way to auto-upgrade to/from share-safe...
r50087 ui.write_err(msg)
ui.write_err(hint)
requirements.discard(requirementsmod.SHARESAFE_REQUIREMENT)
scmutil.writereporequirements(repo, requirements)
return action
auto-upgrade: introduce a way to auto-upgrade to/from tracked-hint...
r50089 def get_tracked_hint_action(repo):
"""return an automatic-upgrade action for `tracked-hint` if applicable
If no action is needed, return None, otherwise return a callback to upgrade
or downgrade the repository according the configuration and repository
format.
"""
ui = repo.ui
requirements = set(repo.requirements)
auto_upgrade_tracked_hint = ui.configbool(
b'format',
b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories',
)
auto-upgrade: add an option to silence the tracked-hint message...
r50237 auto_upgrade_quiet = ui.configbool(
b'format',
b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet',
)
auto-upgrade: introduce a way to auto-upgrade to/from tracked-hint...
r50089
action = None
if auto_upgrade_tracked_hint:
th_config = ui.configbool(b'format', b'use-dirstate-tracked-hint')
th_local = requirementsmod.DIRSTATE_TRACKED_HINT_V1 in requirements
if th_config and not th_local:
msg = _(
b"automatically upgrading repository to the `tracked-hint`"
b" feature\n"
)
hint = b"(see `hg help config.format.use-dirstate-tracked-hint` for details)\n"
def action():
auto-upgrade: add an option to silence the tracked-hint message...
r50237 if not (ui.quiet or auto_upgrade_quiet):
auto-upgrade: introduce a way to auto-upgrade to/from tracked-hint...
r50089 ui.write_err(msg)
ui.write_err(hint)
requirements.add(requirementsmod.DIRSTATE_TRACKED_HINT_V1)
op = AutoUpgradeOperation(requirements)
engine.upgrade_tracked_hint(ui, repo, op, add=True)
elif th_local and not th_config:
msg = _(
b"automatically downgrading repository from the `tracked-hint`"
b" feature\n"
)
hint = b"(see `hg help config.format.use-dirstate-tracked-hint` for details)\n"
def action():
auto-upgrade: add an option to silence the tracked-hint message...
r50237 if not (ui.quiet or auto_upgrade_quiet):
auto-upgrade: introduce a way to auto-upgrade to/from tracked-hint...
r50089 ui.write_err(msg)
ui.write_err(hint)
requirements.discard(requirementsmod.DIRSTATE_TRACKED_HINT_V1)
op = AutoUpgradeOperation(requirements)
engine.upgrade_tracked_hint(ui, repo, op, add=False)
return action
auto-upgrade: introduce a way to auto-upgrade to/from dirstate-v2...
r50090 def get_dirstate_v2_action(repo):
"""return an automatic-upgrade action for `dirstate-v2` if applicable
If no action is needed, return None, otherwise return a callback to upgrade
or downgrade the repository according the configuration and repository
format.
"""
ui = repo.ui
requirements = set(repo.requirements)
auto-upgrade: rename a variable to match the actual content...
r50235 auto_upgrade_dv2 = ui.configbool(
auto-upgrade: introduce a way to auto-upgrade to/from dirstate-v2...
r50090 b'format',
b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories',
)
auto-upgrade: add an option to silence the dirstate-v2 message...
r50236 auto_upgrade_dv2_quiet = ui.configbool(
b'format',
b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet',
)
auto-upgrade: introduce a way to auto-upgrade to/from dirstate-v2...
r50090
action = None
auto-upgrade: rename a variable to match the actual content...
r50235 if auto_upgrade_dv2:
auto-upgrade: introduce a way to auto-upgrade to/from dirstate-v2...
r50090 d2_config = ui.configbool(b'format', b'use-dirstate-v2')
d2_local = requirementsmod.DIRSTATE_V2_REQUIREMENT in requirements
if d2_config and not d2_local:
msg = _(
b"automatically upgrading repository to the `dirstate-v2`"
b" feature\n"
)
hint = (
b"(see `hg help config.format.use-dirstate-v2` for details)\n"
)
def action():
auto-upgrade: add an option to silence the dirstate-v2 message...
r50236 if not (ui.quiet or auto_upgrade_dv2_quiet):
auto-upgrade: introduce a way to auto-upgrade to/from dirstate-v2...
r50090 ui.write_err(msg)
ui.write_err(hint)
requirements.add(requirementsmod.DIRSTATE_V2_REQUIREMENT)
fake_op = AutoUpgradeOperation(requirements)
engine.upgrade_dirstate(repo.ui, repo, fake_op, b'v1', b'v2')
elif d2_local and not d2_config:
msg = _(
b"automatically downgrading repository from the `dirstate-v2`"
b" feature\n"
)
hint = (
b"(see `hg help config.format.use-dirstate-v2` for details)\n"
)
def action():
auto-upgrade: add an option to silence the dirstate-v2 message...
r50236 if not (ui.quiet or auto_upgrade_dv2_quiet):
auto-upgrade: introduce a way to auto-upgrade to/from dirstate-v2...
r50090 ui.write_err(msg)
ui.write_err(hint)
requirements.discard(requirementsmod.DIRSTATE_V2_REQUIREMENT)
fake_op = AutoUpgradeOperation(requirements)
engine.upgrade_dirstate(repo.ui, repo, fake_op, b'v2', b'v1')
return action
auto-upgrade: introduce a way to auto-upgrade to/from share-safe...
r50087 AUTO_UPGRADE_ACTIONS = [
auto-upgrade: introduce a way to auto-upgrade to/from dirstate-v2...
r50090 get_dirstate_v2_action,
auto-upgrade: introduce a way to auto-upgrade to/from share-safe...
r50087 get_share_safe_action,
auto-upgrade: introduce a way to auto-upgrade to/from tracked-hint...
r50089 get_tracked_hint_action,
auto-upgrade: introduce a way to auto-upgrade to/from share-safe...
r50087 ]
def may_auto_upgrade(repo, maker_func):
"""potentially perform auto-upgrade and return the final repository to use
Auto-upgrade are "quick" repository upgrade that might automatically be run
by "any" repository access. See `hg help config.format` for automatic
upgrade documentation.
note: each relevant upgrades are done one after the other for simplicity.
This avoid having repository is partially inconsistent state while
upgrading.
repo: the current repository instance
maker_func: a factory function that can recreate a repository after an upgrade
"""
clear = False
loop = 0
auto-upgrade: skip the operation if the repository cannot be locked...
r50095 try:
while not clear:
loop += 1
if loop > 100:
# XXX basic protection against infinite loop, make it better.
raise error.ProgrammingError("Too many auto upgrade loops")
clear = True
for get_action in AUTO_UPGRADE_ACTIONS:
action = get_action(repo)
if action is not None:
clear = False
with repo.wlock(wait=False), repo.lock(wait=False):
action = get_action(repo)
if action is not None:
action()
repo = maker_func()
except error.LockError:
# if we cannot get the lock, ignore the auto-upgrade attemps and
# proceed. We might want to make this behavior configurable in the
# future.
pass
auto-upgrade: introduce a way to auto-upgrade to/from share-safe...
r50087 return repo