diff 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
line wrap: on
line diff
--- a/rhodecode/lib/middleware/simplegit.py	Tue Aug 21 19:36:21 2012 +0200
+++ b/rhodecode/lib/middleware/simplegit.py	Wed Aug 22 00:30:02 2012 +0200
@@ -31,6 +31,8 @@
 
 from dulwich import server as dulserver
 from dulwich.web import LimitedInputFilter, GunzipFilter
+from rhodecode.lib.exceptions import HTTPLockedRC
+from rhodecode.lib.hooks import pre_pull
 
 
 class SimpleGitUploadPackHandler(dulserver.UploadPackHandler):
@@ -102,11 +104,11 @@
 class SimpleGit(BaseVCSController):
 
     def _handle_request(self, environ, start_response):
-
         if not is_git(environ):
             return self.application(environ, start_response)
         if not self._check_ssl(environ, start_response):
             return HTTPNotAcceptable('SSL REQUIRED !')(environ, start_response)
+
         ipaddr = self._get_ip_addr(environ)
         username = None
         self._git_first_op = False
@@ -184,21 +186,39 @@
                 if perm is not True:
                     return HTTPForbidden()(environ, start_response)
 
+        # extras are injected into UI object and later available
+        # in hooks executed by rhodecode
         extras = {
             'ip': ipaddr,
             'username': username,
             'action': action,
             'repository': repo_name,
             'scm': 'git',
+            'make_lock': None,
+            'locked_by': [None, None]
         }
-        # set the environ variables for this request
-        os.environ['RC_SCM_DATA'] = json.dumps(extras)
+
         #===================================================================
         # GIT REQUEST HANDLING
         #===================================================================
         repo_path = os.path.join(safe_str(self.basepath), safe_str(repo_name))
         log.debug('Repository path is %s' % repo_path)
 
+        # CHECK LOCKING only if it's not ANONYMOUS USER
+        if username != User.DEFAULT_USER:
+            log.debug('Checking locking on repository')
+            (make_lock,
+             locked,
+             locked_by) = self._check_locking_state(
+                            environ=environ, action=action,
+                            repo=repo_name, user_id=user.user_id
+                       )
+            # store the make_lock for later evaluation in hooks
+            extras.update({'make_lock': make_lock,
+                           'locked_by': locked_by})
+        # set the environ variables for this request
+        os.environ['RC_SCM_DATA'] = json.dumps(extras)
+        log.debug('HOOKS extras is %s' % extras)
         baseui = make_ui('db')
         self.__inject_extras(repo_path, baseui, extras)
 
@@ -209,13 +229,16 @@
             self._handle_githooks(repo_name, action, baseui, environ)
 
             log.info('%s action on GIT repo "%s"' % (action, repo_name))
-            app = self.__make_app(repo_name, repo_path, username)
+            app = self.__make_app(repo_name, repo_path, extras)
             return app(environ, start_response)
+        except HTTPLockedRC, e:
+            log.debug('Repositry LOCKED ret code 423!')
+            return e(environ, start_response)
         except Exception:
             log.error(traceback.format_exc())
             return HTTPInternalServerError()(environ, start_response)
 
-    def __make_app(self, repo_name, repo_path, username):
+    def __make_app(self, repo_name, repo_path, extras):
         """
         Make an wsgi application using dulserver
 
@@ -227,7 +250,7 @@
         app = make_wsgi_app(
             repo_root=safe_str(self.basepath),
             repo_name=repo_name,
-            username=username,
+            extras=extras,
         )
         app = GunzipFilter(LimitedInputFilter(app))
         return app
@@ -279,6 +302,7 @@
         """
         from rhodecode.lib.hooks import log_pull_action
         service = environ['QUERY_STRING'].split('=')
+
         if len(service) < 2:
             return
 
@@ -288,6 +312,9 @@
         _repo._repo.ui = baseui
 
         _hooks = dict(baseui.configitems('hooks')) or {}
+        if action == 'pull':
+            # stupid git, emulate pre-pull hook !
+            pre_pull(ui=baseui, repo=_repo._repo)
         if action == 'pull' and _hooks.get(RhodeCodeUi.HOOK_PULL):
             log_pull_action(ui=baseui, repo=_repo._repo)