# HG changeset patch # User domruf # Date 1465935279 -7200 # Node ID ada7b0495b9f61771d8baed3308de908a39f0fd8 # Parent b99e00fb6dd47d740f177799e880111af96d5a26 lock: fix for Mercurial 3.6+ - wrap hgweb to catch Locked exceptions from hooks With Mercurial 3.6, the handling of WSGI responses changed. The hook exceptions are no longer raised directly when app(environ, start_response) is called so the 'except HTTPLockedRC as e' block in _handle_request (a few lines above ) does not work anymore because the exception happens later. Therefore I created a wrapper class that can catch the exceptions. This makes locking work again and fixes lock related tests like TestVCSOperations.test_clone_after_repo_was_locked_hg which expect certain output of the hg client in case of an HTTPLockedRC exception. Depending on how https://bz.mercurial-scm.org/show_bug.cgi?id=5232 gets handled, this fix might become obsolete in the future. (Modified by Mads Kiilerich) diff -r b99e00fb6dd4 -r ada7b0495b9f kallithea/lib/middleware/simplehg.py --- a/kallithea/lib/middleware/simplehg.py Sat Jun 25 02:57:44 2016 +0200 +++ b/kallithea/lib/middleware/simplehg.py Tue Jun 14 22:14:39 2016 +0200 @@ -217,6 +217,7 @@ if str(e).find('not found') != -1: return HTTPNotFound()(environ, start_response) except HTTPLockedRC as e: + # Before Mercurial 3.6, lock exceptions were caught here log.debug('Locked, response %s: %s', e.code, e.title) return e(environ, start_response) except Exception: @@ -228,7 +229,18 @@ Make an wsgi application using hgweb, and inject generated baseui instance, additionally inject some extras into ui object """ - return hgweb_mod.hgweb(repo_name, name=repo_name, baseui=baseui) + class HgWebWrapper(hgweb_mod.hgweb): + # Work-around for Mercurial 3.6+ causing lock exceptions to be + # thrown late + def _runwsgi(self, req, repo): + try: + return super(HgWebWrapper, self)._runwsgi(req, repo) + except HTTPLockedRC as e: + log.debug('Locked, response %s: %s', e.code, e.title) + req.respond(e.status, 'text/plain') + return '' + + return HgWebWrapper(repo_name, name=repo_name, baseui=baseui) def __get_repository(self, environ): """