Mercurial > hg-stable
changeset 51502:3b69324d9535 stable
exchange: fix locking to actually be scoped
The previous code was taking locks before entering with statements, so
exception before the with statement would not release the lock (except for
garbage collection).
We need to move to a try except here because the logic is more complicated.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 11 Jun 2024 11:14:13 +0200 |
parents | 429d57227e7f |
children | fcc149f3fdcb |
files | mercurial/exchange.py |
diffstat | 1 files changed, 40 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/exchange.py Tue Jun 11 11:13:36 2024 +0200 +++ b/mercurial/exchange.py Tue Jun 11 11:14:13 2024 +0200 @@ -466,42 +466,46 @@ # get lock as we might write phase data wlock = lock = None try: - # bundle2 push may receive a reply bundle touching bookmarks - # requiring the wlock. Take it now to ensure proper ordering. - maypushback = pushop.ui.configbool(b'experimental', b'bundle2.pushback') - if ( - (not _forcebundle1(pushop)) - and maypushback - and not bookmod.bookmarksinstore(repo) - ): - wlock = pushop.repo.wlock() - lock = pushop.repo.lock() - pushop.trmanager = transactionmanager( - pushop.repo, b'push-response', pushop.remote.url() - ) - except error.LockUnavailable as err: - # source repo cannot be locked. - # We do not abort the push, but just disable the local phase - # synchronisation. - msg = b'cannot lock source repository: %s\n' % stringutil.forcebytestr( - err - ) - pushop.ui.debug(msg) - - with wlock or util.nullcontextmanager(): - with lock or util.nullcontextmanager(): - with pushop.trmanager or util.nullcontextmanager(): - pushop.repo.checkpush(pushop) - _checkpublish(pushop) - _pushdiscovery(pushop) - if not pushop.force: - _checksubrepostate(pushop) - if not _forcebundle1(pushop): - _pushbundle2(pushop) - _pushchangeset(pushop) - _pushsyncphase(pushop) - _pushobsolete(pushop) - _pushbookmark(pushop) + try: + # bundle2 push may receive a reply bundle touching bookmarks + # requiring the wlock. Take it now to ensure proper ordering. + maypushback = pushop.ui.configbool( + b'experimental', + b'bundle2.pushback', + ) + if ( + (not _forcebundle1(pushop)) + and maypushback + and not bookmod.bookmarksinstore(repo) + ): + wlock = pushop.repo.wlock() + lock = pushop.repo.lock() + pushop.trmanager = transactionmanager( + pushop.repo, b'push-response', pushop.remote.url() + ) + except error.LockUnavailable as err: + # source repo cannot be locked. + # We do not abort the push, but just disable the local phase + # synchronisation. + msg = b'cannot lock source repository: %s\n' + msg %= stringutil.forcebytestr(err) + pushop.ui.debug(msg) + + pushop.repo.checkpush(pushop) + _checkpublish(pushop) + _pushdiscovery(pushop) + if not pushop.force: + _checksubrepostate(pushop) + if not _forcebundle1(pushop): + _pushbundle2(pushop) + _pushchangeset(pushop) + _pushsyncphase(pushop) + _pushobsolete(pushop) + _pushbookmark(pushop) + if pushop.trmanager is not None: + pushop.trmanager.close() + finally: + lockmod.release(pushop.trmanager, lock, wlock) if repo.ui.configbool(b'experimental', b'remotenames'): logexchange.pullremotenames(repo, remote)