Mercurial > kallithea
comparison rhodecode/lib/middleware/simplegit.py @ 1496:f4fed0b32103 beta
Rewrote git middleware with the same pattern as recent fix for #176
- additionally fixed dulwich server bug, that used old deprecated method. This fix caused huge improvement of speed for fetching git repos
- moved simplehg and simplegit middleware into begining of pylons callstack. This low level middleware
don't need to run any of the middlewares except each other.
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Thu, 29 Sep 2011 23:34:47 +0300 |
parents | b7563ad4e7ee |
children | 71738535ed78 |
comparison
equal
deleted
inserted
replaced
1495:5bd42279930c | 1496:f4fed0b32103 |
---|---|
42 objects_iter = self.repo.fetch_objects( | 42 objects_iter = self.repo.fetch_objects( |
43 graph_walker.determine_wants, graph_walker, self.progress, | 43 graph_walker.determine_wants, graph_walker, self.progress, |
44 get_tagged=self.get_tagged) | 44 get_tagged=self.get_tagged) |
45 | 45 |
46 # Do they want any objects? | 46 # Do they want any objects? |
47 if len(objects_iter) == 0: | 47 if objects_iter is None or len(objects_iter) == 0: |
48 return | 48 return |
49 | 49 |
50 self.progress("counting objects: %d, done.\n" % len(objects_iter)) | 50 self.progress("counting objects: %d, done.\n" % len(objects_iter)) |
51 dulserver.write_pack_data(dulserver.ProtocolFile(None, write), | 51 dulserver.write_pack_objects(dulserver.ProtocolFile(None, write), |
52 objects_iter, len(objects_iter)) | 52 objects_iter, len(objects_iter)) |
53 messages = [] | 53 messages = [] |
54 messages.append('thank you for using rhodecode') | 54 messages.append('thank you for using rhodecode') |
55 | 55 |
56 for msg in messages: | 56 for msg in messages: |
94 class SimpleGit(object): | 94 class SimpleGit(object): |
95 | 95 |
96 def __init__(self, application, config): | 96 def __init__(self, application, config): |
97 self.application = application | 97 self.application = application |
98 self.config = config | 98 self.config = config |
99 #authenticate this git request using | 99 # base path of repo locations |
100 self.basepath = self.config['base_path'] | |
101 #authenticate this mercurial request using authfunc | |
100 self.authenticate = AuthBasicAuthenticator('', authfunc) | 102 self.authenticate = AuthBasicAuthenticator('', authfunc) |
101 self.ipaddr = '0.0.0.0' | |
102 self.repo_name = None | |
103 self.username = None | |
104 self.action = None | |
105 | 103 |
106 def __call__(self, environ, start_response): | 104 def __call__(self, environ, start_response): |
107 if not is_git(environ): | 105 if not is_git(environ): |
108 return self.application(environ, start_response) | 106 return self.application(environ, start_response) |
109 | 107 |
110 proxy_key = 'HTTP_X_REAL_IP' | 108 proxy_key = 'HTTP_X_REAL_IP' |
111 def_key = 'REMOTE_ADDR' | 109 def_key = 'REMOTE_ADDR' |
112 self.ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0')) | 110 ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0')) |
111 username = None | |
113 # skip passing error to error controller | 112 # skip passing error to error controller |
114 environ['pylons.status_code_redirect'] = True | 113 environ['pylons.status_code_redirect'] = True |
115 | 114 |
116 #====================================================================== | 115 #====================================================================== |
117 # GET ACTION PULL or PUSH | 116 # EXTRACT REPOSITORY NAME FROM ENV |
118 #====================================================================== | 117 #====================================================================== |
119 self.action = self.__get_action(environ) | |
120 try: | 118 try: |
121 #================================================================== | 119 repo_name = self.__get_repository(environ) |
122 # GET REPOSITORY NAME | 120 log.debug('Extracted repo name is %s' % repo_name) |
123 #================================================================== | |
124 self.repo_name = self.__get_repository(environ) | |
125 except: | 121 except: |
126 return HTTPInternalServerError()(environ, start_response) | 122 return HTTPInternalServerError()(environ, start_response) |
127 | 123 |
128 #====================================================================== | 124 #====================================================================== |
125 # GET ACTION PULL or PUSH | |
126 #====================================================================== | |
127 action = self.__get_action(environ) | |
128 | |
129 #====================================================================== | |
129 # CHECK ANONYMOUS PERMISSION | 130 # CHECK ANONYMOUS PERMISSION |
130 #====================================================================== | 131 #====================================================================== |
131 if self.action in ['pull', 'push']: | 132 if action in ['pull', 'push']: |
132 anonymous_user = self.__get_user('default') | 133 anonymous_user = self.__get_user('default') |
133 self.username = anonymous_user.username | 134 username = anonymous_user.username |
134 anonymous_perm = self.__check_permission(self.action, | 135 anonymous_perm = self.__check_permission(action, |
135 anonymous_user, | 136 anonymous_user, |
136 self.repo_name) | 137 repo_name) |
137 | 138 |
138 if anonymous_perm is not True or anonymous_user.active is False: | 139 if anonymous_perm is not True or anonymous_user.active is False: |
139 if anonymous_perm is not True: | 140 if anonymous_perm is not True: |
140 log.debug('Not enough credentials to access this ' | 141 log.debug('Not enough credentials to access this ' |
141 'repository as anonymous user') | 142 'repository as anonymous user') |
160 #============================================================== | 161 #============================================================== |
161 # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME FROM | 162 # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME FROM |
162 # BASIC AUTH | 163 # BASIC AUTH |
163 #============================================================== | 164 #============================================================== |
164 | 165 |
165 if self.action in ['pull', 'push']: | 166 if action in ['pull', 'push']: |
166 username = REMOTE_USER(environ) | 167 username = REMOTE_USER(environ) |
167 try: | 168 try: |
168 user = self.__get_user(username) | 169 user = self.__get_user(username) |
169 self.username = user.username | 170 username = user.username |
170 except: | 171 except: |
171 log.error(traceback.format_exc()) | 172 log.error(traceback.format_exc()) |
172 return HTTPInternalServerError()(environ, | 173 return HTTPInternalServerError()(environ, |
173 start_response) | 174 start_response) |
174 | 175 |
175 #check permissions for this repository | 176 #check permissions for this repository |
176 perm = self.__check_permission(self.action, user, | 177 perm = self.__check_permission(action, user, |
177 self.repo_name) | 178 repo_name) |
178 if perm is not True: | 179 if perm is not True: |
179 return HTTPForbidden()(environ, start_response) | 180 return HTTPForbidden()(environ, start_response) |
180 | 181 |
181 self.extras = {'ip': self.ipaddr, | 182 extras = {'ip': ipaddr, |
182 'username': self.username, | 183 'username': username, |
183 'action': self.action, | 184 'action': action, |
184 'repository': self.repo_name} | 185 'repository': repo_name} |
185 | 186 |
186 #=================================================================== | 187 #=================================================================== |
187 # GIT REQUEST HANDLING | 188 # GIT REQUEST HANDLING |
188 #=================================================================== | 189 #=================================================================== |
189 self.basepath = self.config['base_path'] | 190 |
190 self.repo_path = os.path.join(self.basepath, self.repo_name) | 191 repo_path = safe_str(os.path.join(self.basepath, repo_name)) |
191 #quick check if that dir exists... | 192 log.debug('Repository path is %s' % repo_path) |
192 if check_repo_fast(self.repo_name, self.basepath): | 193 |
194 # quick check if that dir exists... | |
195 if check_repo_fast(repo_name, self.basepath): | |
193 return HTTPNotFound()(environ, start_response) | 196 return HTTPNotFound()(environ, start_response) |
197 | |
194 try: | 198 try: |
195 app = self.__make_app() | 199 #invalidate cache on push |
196 except: | 200 if action == 'push': |
201 self.__invalidate_cache(repo_name) | |
202 | |
203 app = self.__make_app(repo_name, repo_path) | |
204 return app(environ, start_response) | |
205 except Exception: | |
197 log.error(traceback.format_exc()) | 206 log.error(traceback.format_exc()) |
198 return HTTPInternalServerError()(environ, start_response) | 207 return HTTPInternalServerError()(environ, start_response) |
199 | 208 |
200 #invalidate cache on push | 209 def __make_app(self, repo_name, repo_path): |
201 if self.action == 'push': | 210 """ |
202 self.__invalidate_cache(self.repo_name) | 211 Make an wsgi application using dulserver |
203 | 212 |
204 return app(environ, start_response) | 213 :param repo_name: name of the repository |
205 | 214 :param repo_path: full path to the repository |
206 def __make_app(self): | 215 """ |
207 _d = {'/' + self.repo_name: Repo(self.repo_path)} | 216 |
217 _d = {'/' + repo_name: Repo(repo_path)} | |
208 backend = dulserver.DictBackend(_d) | 218 backend = dulserver.DictBackend(_d) |
209 gitserve = HTTPGitApplication(backend) | 219 gitserve = HTTPGitApplication(backend) |
210 | 220 |
211 return gitserve | 221 return gitserve |
212 | 222 |
213 def __check_permission(self, action, user, repo_name): | 223 def __check_permission(self, action, user, repo_name): |
214 """Checks permissions using action (push/pull) user and repository | 224 """ |
225 Checks permissions using action (push/pull) user and repository | |
215 name | 226 name |
216 | 227 |
217 :param action: push or pull action | 228 :param action: push or pull action |
218 :param user: user instance | 229 :param user: user instance |
219 :param repo_name: repository name | 230 :param repo_name: repository name |
233 return False | 244 return False |
234 | 245 |
235 return True | 246 return True |
236 | 247 |
237 def __get_repository(self, environ): | 248 def __get_repository(self, environ): |
238 """Get's repository name out of PATH_INFO header | 249 """ |
250 Get's repository name out of PATH_INFO header | |
239 | 251 |
240 :param environ: environ where PATH_INFO is stored | 252 :param environ: environ where PATH_INFO is stored |
241 """ | 253 """ |
242 try: | 254 try: |
243 repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:]) | 255 repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:]) |
272 def __invalidate_cache(self, repo_name): | 284 def __invalidate_cache(self, repo_name): |
273 """we know that some change was made to repositories and we should | 285 """we know that some change was made to repositories and we should |
274 invalidate the cache to see the changes right away but only for | 286 invalidate the cache to see the changes right away but only for |
275 push requests""" | 287 push requests""" |
276 invalidate_cache('get_repo_cached_%s' % repo_name) | 288 invalidate_cache('get_repo_cached_%s' % repo_name) |
289 |