diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -1074,6 +1074,11 @@ ) coreconfigitem( b'experimental', + b'sharesafe-auto-downgrade-shares', + default=False, +) +coreconfigitem( + b'experimental', b'sharesafe-auto-upgrade-shares', default=False, ) diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -574,11 +574,26 @@ and requirementsmod.SHARESAFE_REQUIREMENT not in _readrequires(sharedvfs, True) ): - raise error.Abort( - _(b"share source does not support exp-sharesafe requirement") - ) - - requirements |= _readrequires(storevfs, False) + if ui.configbool( + b'experimental', b'sharesafe-auto-downgrade-shares' + ): + # prevent cyclic import localrepo -> upgrade -> localrepo + from . import upgrade + + upgrade.downgrade_share_to_non_safe( + ui, + hgvfs, + sharedvfs, + requirements, + ) + else: + raise error.Abort( + _( + b"share source does not support exp-sharesafe requirement" + ) + ) + else: + requirements |= _readrequires(storevfs, False) elif shared: sourcerequires = _readrequires(sharedvfs, False) if requirementsmod.SHARESAFE_REQUIREMENT in sourcerequires: diff --git a/mercurial/upgrade.py b/mercurial/upgrade.py --- a/mercurial/upgrade.py +++ b/mercurial/upgrade.py @@ -264,3 +264,34 @@ finally: if wlock: wlock.release() + + +def downgrade_share_to_non_safe( + ui, + hgvfs, + sharedvfs, + current_requirements, +): + """Downgrades a share which use share-safe to not use it""" + wlock = None + try: + wlock = lockmod.trylock(ui, hgvfs, b'wlock', 0, 0) + source_requirements = localrepo._readrequires(sharedvfs, True) + # we cannot be 100% sure on which requirements were present in store when + # the source supported share-safe. However, we do know that working + # directory requirements were not there. Hence we remove them + source_requirements -= requirementsmod.WORKING_DIR_REQUIREMENTS + current_requirements |= source_requirements + current_requirements.remove(requirementsmod.SHARESAFE_REQUIREMENT) + scmutil.writerequires(hgvfs, current_requirements) + ui.warn(_(b'repository downgraded to not use share-safe mode\n')) + except error.LockError as e: + # raise error right away because if downgrade failed, we cannot load + # the repository because it does not have complete set of requirements + raise error.Abort( + _(b'failed to downgrade share, got error: %s') + % stringutil.forcebytestr(e.strerror) + ) + finally: + if wlock: + wlock.release() diff --git a/tests/test-share-safe.t b/tests/test-share-safe.t --- a/tests/test-share-safe.t +++ b/tests/test-share-safe.t @@ -484,6 +484,27 @@ abort: share source does not support exp-sharesafe requirement [255] +Testing automatic downgrade of shares when config is set + + $ touch ../ss-share/.hg/wlock + $ hg log -GT "{node}: {desc}\n" -R ../ss-share --config experimental.sharesafe-auto-downgrade-shares=true + abort: failed to downgrade share, got error: Lock held + [255] + $ rm ../ss-share/.hg/wlock + + $ hg log -GT "{node}: {desc}\n" -R ../ss-share --config experimental.sharesafe-auto-downgrade-shares=true + repository downgraded to not use share-safe mode + @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar + | + o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo + + + $ hg log -GT "{node}: {desc}\n" -R ../ss-share + @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar + | + o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo + + Testing automatic upgrade of shares when config is set