Mercurial > kallithea
comparison rhodecode/lib/middleware/simplegit.py @ 2726:aa17c7a1b8a5 beta
Implemented basic locking functionality.
- Reimplemented how githooks behave
- emaulate pre-receive hook
- install missing git hooks if they aren't already in repo
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Wed, 22 Aug 2012 00:30:02 +0200 |
parents | 4c71667160e5 |
children | 63e58ef80ef1 dd2d5b65cae9 |
comparison
equal
deleted
inserted
replaced
2725:3853e37db97c | 2726:aa17c7a1b8a5 |
---|---|
29 import logging | 29 import logging |
30 import traceback | 30 import traceback |
31 | 31 |
32 from dulwich import server as dulserver | 32 from dulwich import server as dulserver |
33 from dulwich.web import LimitedInputFilter, GunzipFilter | 33 from dulwich.web import LimitedInputFilter, GunzipFilter |
34 from rhodecode.lib.exceptions import HTTPLockedRC | |
35 from rhodecode.lib.hooks import pre_pull | |
34 | 36 |
35 | 37 |
36 class SimpleGitUploadPackHandler(dulserver.UploadPackHandler): | 38 class SimpleGitUploadPackHandler(dulserver.UploadPackHandler): |
37 | 39 |
38 def handle(self): | 40 def handle(self): |
100 | 102 |
101 | 103 |
102 class SimpleGit(BaseVCSController): | 104 class SimpleGit(BaseVCSController): |
103 | 105 |
104 def _handle_request(self, environ, start_response): | 106 def _handle_request(self, environ, start_response): |
105 | |
106 if not is_git(environ): | 107 if not is_git(environ): |
107 return self.application(environ, start_response) | 108 return self.application(environ, start_response) |
108 if not self._check_ssl(environ, start_response): | 109 if not self._check_ssl(environ, start_response): |
109 return HTTPNotAcceptable('SSL REQUIRED !')(environ, start_response) | 110 return HTTPNotAcceptable('SSL REQUIRED !')(environ, start_response) |
111 | |
110 ipaddr = self._get_ip_addr(environ) | 112 ipaddr = self._get_ip_addr(environ) |
111 username = None | 113 username = None |
112 self._git_first_op = False | 114 self._git_first_op = False |
113 # skip passing error to error controller | 115 # skip passing error to error controller |
114 environ['pylons.status_code_redirect'] = True | 116 environ['pylons.status_code_redirect'] = True |
182 #check permissions for this repository | 184 #check permissions for this repository |
183 perm = self._check_permission(action, user, repo_name) | 185 perm = self._check_permission(action, user, repo_name) |
184 if perm is not True: | 186 if perm is not True: |
185 return HTTPForbidden()(environ, start_response) | 187 return HTTPForbidden()(environ, start_response) |
186 | 188 |
189 # extras are injected into UI object and later available | |
190 # in hooks executed by rhodecode | |
187 extras = { | 191 extras = { |
188 'ip': ipaddr, | 192 'ip': ipaddr, |
189 'username': username, | 193 'username': username, |
190 'action': action, | 194 'action': action, |
191 'repository': repo_name, | 195 'repository': repo_name, |
192 'scm': 'git', | 196 'scm': 'git', |
197 'make_lock': None, | |
198 'locked_by': [None, None] | |
193 } | 199 } |
194 # set the environ variables for this request | 200 |
195 os.environ['RC_SCM_DATA'] = json.dumps(extras) | |
196 #=================================================================== | 201 #=================================================================== |
197 # GIT REQUEST HANDLING | 202 # GIT REQUEST HANDLING |
198 #=================================================================== | 203 #=================================================================== |
199 repo_path = os.path.join(safe_str(self.basepath), safe_str(repo_name)) | 204 repo_path = os.path.join(safe_str(self.basepath), safe_str(repo_name)) |
200 log.debug('Repository path is %s' % repo_path) | 205 log.debug('Repository path is %s' % repo_path) |
201 | 206 |
207 # CHECK LOCKING only if it's not ANONYMOUS USER | |
208 if username != User.DEFAULT_USER: | |
209 log.debug('Checking locking on repository') | |
210 (make_lock, | |
211 locked, | |
212 locked_by) = self._check_locking_state( | |
213 environ=environ, action=action, | |
214 repo=repo_name, user_id=user.user_id | |
215 ) | |
216 # store the make_lock for later evaluation in hooks | |
217 extras.update({'make_lock': make_lock, | |
218 'locked_by': locked_by}) | |
219 # set the environ variables for this request | |
220 os.environ['RC_SCM_DATA'] = json.dumps(extras) | |
221 log.debug('HOOKS extras is %s' % extras) | |
202 baseui = make_ui('db') | 222 baseui = make_ui('db') |
203 self.__inject_extras(repo_path, baseui, extras) | 223 self.__inject_extras(repo_path, baseui, extras) |
204 | 224 |
205 try: | 225 try: |
206 # invalidate cache on push | 226 # invalidate cache on push |
207 if action == 'push': | 227 if action == 'push': |
208 self._invalidate_cache(repo_name) | 228 self._invalidate_cache(repo_name) |
209 self._handle_githooks(repo_name, action, baseui, environ) | 229 self._handle_githooks(repo_name, action, baseui, environ) |
210 | 230 |
211 log.info('%s action on GIT repo "%s"' % (action, repo_name)) | 231 log.info('%s action on GIT repo "%s"' % (action, repo_name)) |
212 app = self.__make_app(repo_name, repo_path, username) | 232 app = self.__make_app(repo_name, repo_path, extras) |
213 return app(environ, start_response) | 233 return app(environ, start_response) |
234 except HTTPLockedRC, e: | |
235 log.debug('Repositry LOCKED ret code 423!') | |
236 return e(environ, start_response) | |
214 except Exception: | 237 except Exception: |
215 log.error(traceback.format_exc()) | 238 log.error(traceback.format_exc()) |
216 return HTTPInternalServerError()(environ, start_response) | 239 return HTTPInternalServerError()(environ, start_response) |
217 | 240 |
218 def __make_app(self, repo_name, repo_path, username): | 241 def __make_app(self, repo_name, repo_path, extras): |
219 """ | 242 """ |
220 Make an wsgi application using dulserver | 243 Make an wsgi application using dulserver |
221 | 244 |
222 :param repo_name: name of the repository | 245 :param repo_name: name of the repository |
223 :param repo_path: full path to the repository | 246 :param repo_path: full path to the repository |
225 | 248 |
226 from rhodecode.lib.middleware.pygrack import make_wsgi_app | 249 from rhodecode.lib.middleware.pygrack import make_wsgi_app |
227 app = make_wsgi_app( | 250 app = make_wsgi_app( |
228 repo_root=safe_str(self.basepath), | 251 repo_root=safe_str(self.basepath), |
229 repo_name=repo_name, | 252 repo_name=repo_name, |
230 username=username, | 253 extras=extras, |
231 ) | 254 ) |
232 app = GunzipFilter(LimitedInputFilter(app)) | 255 app = GunzipFilter(LimitedInputFilter(app)) |
233 return app | 256 return app |
234 | 257 |
235 def __get_repository(self, environ): | 258 def __get_repository(self, environ): |
277 """ | 300 """ |
278 Handles pull action, push is handled by post-receive hook | 301 Handles pull action, push is handled by post-receive hook |
279 """ | 302 """ |
280 from rhodecode.lib.hooks import log_pull_action | 303 from rhodecode.lib.hooks import log_pull_action |
281 service = environ['QUERY_STRING'].split('=') | 304 service = environ['QUERY_STRING'].split('=') |
305 | |
282 if len(service) < 2: | 306 if len(service) < 2: |
283 return | 307 return |
284 | 308 |
285 from rhodecode.model.db import Repository | 309 from rhodecode.model.db import Repository |
286 _repo = Repository.get_by_repo_name(repo_name) | 310 _repo = Repository.get_by_repo_name(repo_name) |
287 _repo = _repo.scm_instance | 311 _repo = _repo.scm_instance |
288 _repo._repo.ui = baseui | 312 _repo._repo.ui = baseui |
289 | 313 |
290 _hooks = dict(baseui.configitems('hooks')) or {} | 314 _hooks = dict(baseui.configitems('hooks')) or {} |
315 if action == 'pull': | |
316 # stupid git, emulate pre-pull hook ! | |
317 pre_pull(ui=baseui, repo=_repo._repo) | |
291 if action == 'pull' and _hooks.get(RhodeCodeUi.HOOK_PULL): | 318 if action == 'pull' and _hooks.get(RhodeCodeUi.HOOK_PULL): |
292 log_pull_action(ui=baseui, repo=_repo._repo) | 319 log_pull_action(ui=baseui, repo=_repo._repo) |
293 | 320 |
294 def __inject_extras(self, repo_path, baseui, extras={}): | 321 def __inject_extras(self, repo_path, baseui, extras={}): |
295 """ | 322 """ |