Changeset - a4a4bcc09ac5
[Not reviewed]
default
0 1 0
Mads Kiilerich - 7 years ago 2019-01-07 02:08:35
mads@kiilerich.com
Grafted from: b2c1950dd6a7
middleware: remove access fallback to reuse previous access - drop _git_stored_op

Before, the previous action was kept in the global controller instance. That
was conceptually wrong. The previous request might be entirely unrelated,
coming from another user.

It was mainly used for 'info/refs' commands ... but even more, that will be the
first command that is sent, giving nothing relevant to reuse.

Fortunately, with handling of 'info/refs', we no longer seem to need it.

The fallback for unknown commands with unknown 'action' is now to return a HTTP
failure, like we do for Mercurial.
1 file changed with 15 insertions and 14 deletions:
0 comments (0 inline, 0 general)
kallithea/lib/middleware/simplegit.py
Show inline comments
 
@@ -25,25 +25,25 @@ Original author and date, and relevant c
 
: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
 
    HTTPNotAcceptable, HTTPBadRequest
 
from kallithea.model.db import Ui
 

	
 
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.middleware.pygrack import make_wsgi_app
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
GIT_PROTO_PAT = re.compile(r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack)')
 
@@ -51,26 +51,24 @@ GIT_PROTO_PAT = re.compile(r'^/(.+)/(inf
 

	
 
def is_git(environ):
 
    path_info = environ['PATH_INFO']
 
    isgit_path = GIT_PROTO_PAT.match(path_info)
 
    log.debug('pathinfo: %s detected as Git %s',
 
        path_info, isgit_path is not None
 
    )
 
    return isgit_path
 

	
 

	
 
class SimpleGit(BaseVCSController):
 

	
 
    _git_stored_op = 'pull' # most recent kind of command
 

	
 
    def _handle_request(self, environ, start_response):
 
        if not is_git(environ):
 
            return self.application(environ, start_response)
 

	
 
        ip_addr = self._get_ip_addr(environ)
 
        # skip passing error to error controller
 
        environ['pylons.status_code_redirect'] = True
 

	
 
        #======================================================================
 
        # EXTRACT REPOSITORY NAME FROM ENV
 
        #======================================================================
 
        try:
 
@@ -140,43 +138,46 @@ class SimpleGit(BaseVCSController):
 

	
 
        :param environ: environ where PATH_INFO is stored
 
        """
 
        try:
 
            return GIT_PROTO_PAT.match(environ['PATH_INFO']).group(1)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def __get_action(self, environ):
 
        """
 
        Maps Git request commands into 'pull' or 'push'.
 

	
 
        Raises HTTPBadRequest if the request environment doesn't look like a git client.
 
        """
 
        mapping = {
 
            'git-receive-pack': 'push',
 
            'git-upload-pack': 'pull',
 
        }
 
        path_info = environ.get('PATH_INFO', '')
 
        m = GIT_PROTO_PAT.match(path_info)
 
        if m is not None:
 
        if m is None:
 
            action = None
 
        else:
 
            cmd = m.group(2)
 
            if cmd == 'info/refs':
 
                service = environ['QUERY_STRING'].split('=')
 
                cmd = service[1] if len(service) > 1 else None
 
                if cmd in mapping:
 
                    self._git_stored_op = mapping[cmd]
 
            elif cmd in mapping:
 
                self._git_stored_op = mapping[cmd]
 
        # fallback to stored variable as we don't know if the last
 
        # operation is pull/push
 
        return self._git_stored_op
 
            query_string = environ['QUERY_STRING']
 
            if cmd == 'info/refs' and query_string.startswith('service='):
 
                service = query_string.split('=', 1)[1]
 
                action = mapping.get(service)
 
            else:
 
                action = mapping.get(cmd)
 
        if action is None:
 
            raise HTTPBadRequest('Unable to detect pull/push action for %r! Are you using a nonstandard command or client?' % path_info)
 
        return action
 

	
 
    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('=')
 

	
 
        if len(service) < 2:
 
            return
 

	
 
        from kallithea.model.db import Repository
0 comments (0 inline, 0 general)