Mercurial > public > src > rhodecode
diff pylons_app/lib/middleware/simplehg.py @ 366:6484963056cd
implemented cache for repeated queries in simplehg mercurial requests
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Wed, 14 Jul 2010 12:31:11 +0200 |
parents | 1ef52a70f3b7 |
children | 664a5b8c551a |
line wrap: on
line diff
--- a/pylons_app/lib/middleware/simplehg.py Wed Jul 14 02:28:51 2010 +0200 +++ b/pylons_app/lib/middleware/simplehg.py Wed Jul 14 12:31:11 2010 +0200 @@ -2,7 +2,7 @@ # encoding: utf-8 # middleware to handle mercurial api calls # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com> - + # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; version 2 @@ -27,21 +27,23 @@ """ from datetime import datetime from itertools import chain +from mercurial.error import RepoError from mercurial.hgweb import hgweb from mercurial.hgweb.request import wsgiapplication -from mercurial.error import RepoError from paste.auth.basic import AuthBasicAuthenticator from paste.httpheaders import REMOTE_USER, AUTH_TYPE -from pylons_app.lib.auth import authfunc, HasPermissionAnyMiddleware +from pylons_app.lib.auth import authfunc, HasPermissionAnyMiddleware, \ + get_user_cached from pylons_app.lib.utils import is_mercurial, make_ui, invalidate_cache, \ check_repo_fast from pylons_app.model import meta from pylons_app.model.db import UserLog, User -import pylons_app.lib.helpers as h from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError import logging import os +import pylons_app.lib.helpers as h import traceback + log = logging.getLogger(__name__) class SimpleHg(object): @@ -56,86 +58,84 @@ def __call__(self, environ, start_response): if not is_mercurial(environ): return self.application(environ, start_response) - else: - #=================================================================== - # AUTHENTICATE THIS MERCURIAL REQUEST - #=================================================================== - username = REMOTE_USER(environ) - if not username: - result = self.authenticate(environ) - if isinstance(result, str): - AUTH_TYPE.update(environ, 'basic') - REMOTE_USER.update(environ, result) - else: - return result.wsgi_application(environ, start_response) - + + #=================================================================== + # AUTHENTICATE THIS MERCURIAL REQUEST + #=================================================================== + username = REMOTE_USER(environ) + if not username: + result = self.authenticate(environ) + if isinstance(result, str): + AUTH_TYPE.update(environ, 'basic') + REMOTE_USER.update(environ, result) + else: + return result.wsgi_application(environ, start_response) + + try: + repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:]) + except: + log.error(traceback.format_exc()) + return HTTPInternalServerError()(environ, start_response) + + #=================================================================== + # CHECK PERMISSIONS FOR THIS REQUEST + #=================================================================== + action = self.__get_action(environ) + if action: + username = self.__get_environ_user(environ) try: - repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:]) + user = self.__get_user(username) except: log.error(traceback.format_exc()) return HTTPInternalServerError()(environ, start_response) + #check permissions for this repository + if action == 'pull': + if not HasPermissionAnyMiddleware('repository.read', + 'repository.write', + 'repository.admin')\ + (user, repo_name): + return HTTPForbidden()(environ, start_response) + if action == 'push': + if not HasPermissionAnyMiddleware('repository.write', + 'repository.admin')\ + (user, repo_name): + return HTTPForbidden()(environ, start_response) - #=================================================================== - # CHECK PERMISSIONS FOR THIS REQUEST - #=================================================================== - action = self.__get_action(environ) - if action: - username = self.__get_environ_user(environ) - try: - sa = meta.Session - user = sa.query(User)\ - .filter(User.username == username).one() - except: - log.error(traceback.format_exc()) - return HTTPInternalServerError()(environ, start_response) - #check permissions for this repository - if action == 'pull': - if not HasPermissionAnyMiddleware('repository.read', - 'repository.write', - 'repository.admin')\ - (user, repo_name): - return HTTPForbidden()(environ, start_response) - if action == 'push': - if not HasPermissionAnyMiddleware('repository.write', - 'repository.admin')\ - (user, repo_name): - return HTTPForbidden()(environ, start_response) - - #log action - proxy_key = 'HTTP_X_REAL_IP' - def_key = 'REMOTE_ADDR' - ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0')) - self.__log_user_action(user, action, repo_name, ipaddr) - - #=================================================================== - # MERCURIAL REQUEST HANDLING - #=================================================================== - environ['PATH_INFO'] = '/'#since we wrap into hgweb, reset the path - self.baseui = make_ui('db') - self.basepath = self.config['base_path'] - self.repo_path = os.path.join(self.basepath, repo_name) + #log action + proxy_key = 'HTTP_X_REAL_IP' + def_key = 'REMOTE_ADDR' + ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0')) + self.__log_user_action(user, action, repo_name, ipaddr) + + #=================================================================== + # MERCURIAL REQUEST HANDLING + #=================================================================== + environ['PATH_INFO'] = '/'#since we wrap into hgweb, reset the path + self.baseui = make_ui('db') + self.basepath = self.config['base_path'] + self.repo_path = os.path.join(self.basepath, repo_name) - #quick check if that dir exists... - if check_repo_fast(repo_name, self.basepath): + #quick check if that dir exists... + if check_repo_fast(repo_name, self.basepath): + return HTTPNotFound()(environ, start_response) + try: + app = wsgiapplication(self.__make_app) + except RepoError as e: + if str(e).find('not found') != -1: return HTTPNotFound()(environ, start_response) - try: - app = wsgiapplication(self.__make_app) - except RepoError as e: - if str(e).find('not found') != -1: - return HTTPNotFound()(environ, start_response) - except Exception: - log.error(traceback.format_exc()) - return HTTPInternalServerError()(environ, start_response) - - #invalidate cache on push - if action == 'push': - self.__invalidate_cache(repo_name) - messages = [] - messages.append('thank you for using hg-app') - - return self.msg_wrapper(app, environ, start_response, messages) - else: - return app(environ, start_response) + except Exception: + log.error(traceback.format_exc()) + return HTTPInternalServerError()(environ, start_response) + + #invalidate cache on push + if action == 'push': + self.__invalidate_cache(repo_name) + messages = [] + messages.append('thank you for using hg-app') + + return self.msg_wrapper(app, environ, start_response, messages) + else: + return app(environ, start_response) def msg_wrapper(self, app, environ, start_response, messages=[]): @@ -160,6 +160,11 @@ def __get_environ_user(self, environ): return environ.get('REMOTE_USER') + def __get_user(self, username): + return get_user_cached(username) + + + def __get_size(self, repo_path, content_size): size = int(content_size) for path, dirs, files in os.walk(repo_path):