Changeset - 0441afb55a96
[Not reviewed]
default
0 2 0
Mads Kiilerich - 7 years ago 2019-01-23 03:47:46
mads@kiilerich.com
middleware: move VCS specific functionality to the VCS apps

For Git, inline _handle_githooks into a wrapper app so it is simple and
explicit and executed exactly when the request is processed.

For Mercurial, similarly, only set REPO_NAME when the request actually is
processed.
2 files changed with 31 insertions and 31 deletions:
0 comments (0 inline, 0 general)
kallithea/lib/middleware/simplegit.py
Show inline comments
 
@@ -14,54 +14,55 @@
 
"""
 
kallithea.lib.middleware.simplegit
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
SimpleGit middleware for handling Git protocol requests (push/clone etc.)
 
It's implemented with basic auth function
 

	
 
This file was forked by the Kallithea project in July 2014.
 
Original author and date, and relevant copyright and licensing information is below:
 
:created_on: Apr 28, 2010
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH, and others.
 
:license: GPLv3, see LICENSE.md for more details.
 

	
 
"""
 

	
 

	
 
import os
 
import re
 
import logging
 
import traceback
 

	
 
from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
 
    HTTPNotAcceptable, HTTPBadRequest
 
from kallithea.model.db import Ui
 

	
 
from kallithea.model.db import Ui, Repository
 
from kallithea.lib.utils2 import safe_str, safe_unicode, get_server_url, \
 
    _set_extras
 
from kallithea.lib.base import BaseVCSController
 
from kallithea.lib.utils import make_ui, is_valid_repo
 
from kallithea.lib.hooks import log_pull_action
 
from kallithea.lib.middleware.pygrack import make_wsgi_app
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
GIT_PROTO_PAT = re.compile(r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack)$')
 

	
 

	
 
cmd_mapping = {
 
    'git-receive-pack': 'push',
 
    'git-upload-pack': 'pull',
 
}
 

	
 

	
 
class SimpleGit(BaseVCSController):
 

	
 
    scm_alias = 'git'
 

	
 
    @classmethod
 
    def parse_request(cls, environ):
 
        path_info = environ.get('PATH_INFO', '')
 
        m = GIT_PROTO_PAT.match(path_info)
 
        if m is None:
 
            return None
 
@@ -98,59 +99,55 @@ class SimpleGit(BaseVCSController):
 
        # CHECK PERMISSIONS
 
        #======================================================================
 
        user, response_app = self._authorize(environ, start_response, parsed_request.action, parsed_request.repo_name, ip_addr)
 
        if response_app is not None:
 
            return response_app(environ, start_response)
 

	
 
        # extras are injected into Mercurial UI object and later available
 
        # in hooks executed by Kallithea
 
        from kallithea import CONFIG
 
        server_url = get_server_url(environ)
 
        extras = {
 
            'ip': ip_addr,
 
            'username': user.username,
 
            'action': parsed_request.action,
 
            'repository': parsed_request.repo_name,
 
            'scm': self.scm_alias,
 
            'config': CONFIG['__file__'],
 
            'server_url': server_url,
 
        }
 

	
 
        #===================================================================
 
        # GIT REQUEST HANDLING
 
        #===================================================================
 
        log.debug('HOOKS extras is %s', extras)
 
        baseui = make_ui()
 
        _set_extras(extras or {})
 

	
 
        try:
 
            self._handle_githooks(parsed_request.repo_name, parsed_request.action, baseui, environ)
 
            log.info('%s action on %s repo "%s" by "%s" from %s',
 
                     parsed_request.action, self.scm_alias, parsed_request.repo_name, safe_str(user.username), ip_addr)
 
            app = self.__make_app(parsed_request.repo_name)
 
            app = self._make_app(parsed_request)
 
            return app(environ, start_response)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise HTTPInternalServerError()
 

	
 
    def __make_app(self, repo_name):
 
    def _make_app(self, parsed_request):
 
        """
 
        Return a pygrack wsgi application.
 
        """
 
        return make_wsgi_app(repo_name, safe_str(self.basepath)) # FIXME: safe_str???
 

	
 
    def _handle_githooks(self, repo_name, action, baseui, environ):
 
        """
 
        Handles pull action, push is handled by post-receive hook
 
        """
 
        from kallithea.lib.hooks import log_pull_action
 
        service = environ['QUERY_STRING'].split('=')
 
        pygrack_app = make_wsgi_app(parsed_request.repo_name, self.basepath)
 

	
 
        if len(service) < 2:
 
            return
 
        def wrapper_app(environ, start_response):
 
            if (parsed_request.cmd == 'info/refs' and
 
                parsed_request.service == 'git-upload-pack'
 
                ):
 
                baseui = make_ui()
 
                repo = Repository.get_by_repo_name(parsed_request.repo_name)
 
                scm_repo = repo.scm_instance
 
                # Run hooks, like Mercurial outgoing.pull_logger does
 
                log_pull_action(ui=baseui, repo=scm_repo._repo)
 
            # Note: push hooks are handled by post-receive hook
 

	
 
        from kallithea.model.db import Repository
 
        _repo = Repository.get_by_repo_name(repo_name)
 
        _repo = _repo.scm_instance
 
            return pygrack_app(environ, start_response)
 

	
 
        if action == 'pull':
 
            log_pull_action(ui=baseui, repo=_repo._repo)
 
        return wrapper_app
kallithea/lib/middleware/simplehg.py
Show inline comments
 
@@ -151,47 +151,50 @@ class SimpleHg(BaseVCSController):
 

	
 
        #======================================================================
 
        # CHECK PERMISSIONS
 
        #======================================================================
 
        user, response_app = self._authorize(environ, start_response, parsed_request.action, parsed_request.repo_name, ip_addr)
 
        if response_app is not None:
 
            return response_app(environ, start_response)
 

	
 
        # extras are injected into Mercurial UI object and later available
 
        # in hooks executed by Kallithea
 
        from kallithea import CONFIG
 
        server_url = get_server_url(environ)
 
        extras = {
 
            'ip': ip_addr,
 
            'username': user.username,
 
            'action': parsed_request.action,
 
            'repository': parsed_request.repo_name,
 
            'scm': self.scm_alias,
 
            'config': CONFIG['__file__'],
 
            'server_url': server_url,
 
        }
 
        #======================================================================
 
        # MERCURIAL REQUEST HANDLING
 
        #======================================================================
 
        str_repo_name = safe_str(parsed_request.repo_name)
 
        repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
 
        log.debug('Repository path is %s', repo_path)
 

	
 
        log.debug('HOOKS extras is %s', extras)
 
        baseui = make_ui(repo_path=repo_path)
 
        _set_extras(extras or {})
 

	
 
        try:
 
            log.info('%s action on %s repo "%s" by "%s" from %s',
 
                     parsed_request.action, self.scm_alias, parsed_request.repo_name, safe_str(user.username), ip_addr)
 
            environ['REPO_NAME'] = str_repo_name # used by hgweb_mod.hgweb
 
            app = self.__make_app(repo_path, baseui)
 
            app = self._make_app(parsed_request)
 
            return app(environ, start_response)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise HTTPInternalServerError()
 

	
 
    def __make_app(self, repo_name, baseui):
 
    def _make_app(self, parsed_request):
 
        """
 
        Make an hgweb wsgi application.
 
        """
 
        Make an hgweb wsgi application using baseui.
 
        """
 
        return hgweb_mod.hgweb(repo_name, name=repo_name, baseui=baseui)
 
        str_repo_name = safe_str(parsed_request.repo_name)
 
        repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
 
        baseui = make_ui(repo_path=repo_path)
 
        hgweb_app = hgweb_mod.hgweb(repo_path, name=str_repo_name, baseui=baseui)
 

	
 
        def wrapper_app(environ, start_response):
 
            environ['REPO_NAME'] = str_repo_name # used by hgweb_mod.hgweb
 
            return hgweb_app(environ, start_response)
 

	
 
        return wrapper_app
0 comments (0 inline, 0 general)