comparison pylons_app/lib/middleware/simplehg.py @ 355:6c23e72437e3

mercurial middleware now returns 500's instead of 404 on errors and 404 when repo not found, added tracebacks
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 04 Jul 2010 00:52:47 +0200
parents a9a6c74ad2a6
children 71f25781079d
comparison
equal deleted inserted replaced
354:f5f290d68646 355:6c23e72437e3
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # encoding: utf-8 2 # encoding: utf-8
3 # middleware to handle mercurial api calls 3 # middleware to handle mercurial api calls
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com> 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 from mercurial.error import RepoError
5 6
6 # This program is free software; you can redistribute it and/or 7 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License 8 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2 9 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license. 10 # of the License or (at your opinion) any later version of the license.
30 from mercurial.hgweb import hgweb 31 from mercurial.hgweb import hgweb
31 from mercurial.hgweb.request import wsgiapplication 32 from mercurial.hgweb.request import wsgiapplication
32 from paste.auth.basic import AuthBasicAuthenticator 33 from paste.auth.basic import AuthBasicAuthenticator
33 from paste.httpheaders import REMOTE_USER, AUTH_TYPE 34 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
34 from pylons_app.lib.auth import authfunc, HasPermissionAnyMiddleware 35 from pylons_app.lib.auth import authfunc, HasPermissionAnyMiddleware
35 from pylons_app.lib.utils import is_mercurial, make_ui, invalidate_cache 36 from pylons_app.lib.utils import is_mercurial, make_ui, invalidate_cache, \
37 check_repo_fast
36 from pylons_app.model import meta 38 from pylons_app.model import meta
37 from pylons_app.model.db import UserLog, User 39 from pylons_app.model.db import UserLog, User
38 from webob.exc import HTTPNotFound, HTTPForbidden 40 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
39 import logging 41 import logging
40 import os 42 import os
41 import traceback 43 import traceback
42 log = logging.getLogger(__name__) 44 log = logging.getLogger(__name__)
43 45
66 else: 68 else:
67 return result.wsgi_application(environ, start_response) 69 return result.wsgi_application(environ, start_response)
68 70
69 try: 71 try:
70 repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:]) 72 repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
71 except Exception as e: 73 except:
72 log.error(traceback.format_exc()) 74 log.error(traceback.format_exc())
73 return HTTPNotFound()(environ, start_response) 75 return HTTPInternalServerError()(environ, start_response)
74 76
75 #=================================================================== 77 #===================================================================
76 # CHECK PERMISSIONS FOR THIS REQUEST 78 # CHECK PERMISSIONS FOR THIS REQUEST
77 #=================================================================== 79 #===================================================================
78 action = self.__get_action(environ) 80 action = self.__get_action(environ)
81 try: 83 try:
82 sa = meta.Session 84 sa = meta.Session
83 user = sa.query(User)\ 85 user = sa.query(User)\
84 .filter(User.username == username).one() 86 .filter(User.username == username).one()
85 except: 87 except:
86 return HTTPNotFound()(environ, start_response) 88 log.error(traceback.format_exc())
89 return HTTPInternalServerError()(environ, start_response)
87 #check permissions for this repository 90 #check permissions for this repository
88 if action == 'pull': 91 if action == 'pull':
89 if not HasPermissionAnyMiddleware('repository.read', 92 if not HasPermissionAnyMiddleware('repository.read',
90 'repository.write', 93 'repository.write',
91 'repository.admin')\ 94 'repository.admin')\
108 #=================================================================== 111 #===================================================================
109 environ['PATH_INFO'] = '/'#since we wrap into hgweb, reset the path 112 environ['PATH_INFO'] = '/'#since we wrap into hgweb, reset the path
110 self.baseui = make_ui(self.config['hg_app_repo_conf']) 113 self.baseui = make_ui(self.config['hg_app_repo_conf'])
111 self.basepath = self.config['base_path'] 114 self.basepath = self.config['base_path']
112 self.repo_path = os.path.join(self.basepath, repo_name) 115 self.repo_path = os.path.join(self.basepath, repo_name)
116
117 #quick check if that dir exists...
118 if check_repo_fast(repo_name, self.basepath):
119 return HTTPNotFound()(environ, start_response)
120
113 try: 121 try:
114 app = wsgiapplication(self.__make_app) 122 app = wsgiapplication(self.__make_app)
123 except RepoError as e:
124 if str(e).find('not found') != -1:
125 return HTTPNotFound()(environ, start_response)
115 except Exception: 126 except Exception:
116 log.error(traceback.format_exc()) 127 log.error(traceback.format_exc())
117 return HTTPNotFound()(environ, start_response) 128 return HTTPInternalServerError()(environ, start_response)
118 129
119 130
120 #invalidate cache on push 131 #invalidate cache on push
121 if action == 'push': 132 if action == 'push':
122 self.__invalidate_cache(repo_name) 133 self.__invalidate_cache(repo_name)