# HG changeset patch # User Mads Kiilerich # Date 2015-08-20 17:29:55 # Node ID d9386a3924db536560a02776b8398c2edea1bc14 # Parent 22a3fa3c42548e2cc14bf1f618f0e14991b1dc17 vcs: invalidate repo caches _after_ a push finishes Caches were invalidated right after creating the result iterator, before actually applying the change. Caches would thus be refreshed too early and soon be outdated. This bug was especially seen causing errors with missing revisions when creating PRs right after pushing. diff --git a/kallithea/lib/base.py b/kallithea/lib/base.py --- a/kallithea/lib/base.py +++ b/kallithea/lib/base.py @@ -520,3 +520,20 @@ class BaseRepoController(BaseController) log.error(traceback.format_exc()) h.flash(safe_str(e), category='error') raise webob.exc.HTTPBadRequest() + + +class WSGIResultCloseCallback(object): + """Wrap a WSGI result and let close call close after calling the + close method on the result. + """ + def __init__(self, result, close): + self._result = result + self._close = close + + def __iter__(self): + return iter(self._result) + + def close(self): + if hasattr(self._result, 'close'): + self._result.close() + self._close() diff --git a/kallithea/lib/middleware/simplegit.py b/kallithea/lib/middleware/simplegit.py --- a/kallithea/lib/middleware/simplegit.py +++ b/kallithea/lib/middleware/simplegit.py @@ -40,7 +40,7 @@ from kallithea.model.db import User, Ui from kallithea.lib.utils2 import safe_str, fix_PATH, get_server_url,\ _set_extras -from kallithea.lib.base import BaseVCSController +from kallithea.lib.base import BaseVCSController, WSGIResultCloseCallback from kallithea.lib.utils import make_ui, is_valid_repo from kallithea.lib.exceptions import HTTPLockedRC from kallithea.lib.hooks import pre_pull @@ -203,7 +203,11 @@ class SimpleGit(BaseVCSController): log.info('%s action on Git repo "%s" by "%s" from %s', action, str_repo_name, safe_str(username), ip_addr) app = self.__make_app(repo_name, repo_path, extras) - return app(environ, start_response) + result = app(environ, start_response) + if action == 'push': + result = WSGIResultCloseCallback(result, + lambda: self._invalidate_cache(repo_name)) + return result except HTTPLockedRC as e: _code = CONFIG.get('lock_ret_code') log.debug('Repository LOCKED ret code %s!', _code) @@ -211,10 +215,6 @@ class SimpleGit(BaseVCSController): except Exception: log.error(traceback.format_exc()) return HTTPInternalServerError()(environ, start_response) - finally: - # invalidate cache on push - if action == 'push': - self._invalidate_cache(repo_name) def __make_app(self, repo_name, repo_path, extras): """ diff --git a/kallithea/lib/middleware/simplehg.py b/kallithea/lib/middleware/simplehg.py --- a/kallithea/lib/middleware/simplehg.py +++ b/kallithea/lib/middleware/simplehg.py @@ -39,7 +39,7 @@ from kallithea.model.db import User from kallithea.lib.utils2 import safe_str, fix_PATH, get_server_url,\ _set_extras -from kallithea.lib.base import BaseVCSController +from kallithea.lib.base import BaseVCSController, WSGIResultCloseCallback from kallithea.lib.utils import make_ui, is_valid_repo, ui_sections from kallithea.lib.vcs.utils.hgcompat import RepoError, hgweb_mod from kallithea.lib.exceptions import HTTPLockedRC @@ -205,7 +205,11 @@ class SimpleHg(BaseVCSController): log.info('%s action on Mercurial repo "%s" by "%s" from %s', action, str_repo_name, safe_str(username), ip_addr) app = self.__make_app(repo_path, baseui, extras) - return app(environ, start_response) + result = app(environ, start_response) + if action == 'push': + result = WSGIResultCloseCallback(result, + lambda: self._invalidate_cache(repo_name)) + return result except RepoError as e: if str(e).find('not found') != -1: return HTTPNotFound()(environ, start_response) @@ -216,10 +220,6 @@ class SimpleHg(BaseVCSController): except Exception: log.error(traceback.format_exc()) return HTTPInternalServerError()(environ, start_response) - finally: - # invalidate cache on push - if action == 'push': - self._invalidate_cache(repo_name) def __make_app(self, repo_name, baseui, extras): """