vcs: register repo_name as specialized middleware variables instead

of relying on env variables.

- use order of defined vcs.backends to detect middleware for handling requests
This commit is contained in:
Marcin Kuzminski 2016-09-06 19:49:28 +02:00
parent d9ca3e74c2
commit df353f19ea
4 changed files with 63 additions and 50 deletions

View file

@ -50,7 +50,6 @@ from rhodecode.lib.vcs.backends import base
from rhodecode.model import meta
from rhodecode.model.db import User, Repository
from rhodecode.model.scm import ScmModel
from rhodecode.model.settings import SettingsModel
log = logging.getLogger(__name__)
@ -88,8 +87,10 @@ class SimpleVCS(object):
self.registry = registry
self.application = application
self.config = config
# re-populated by specialized middlewares
# re-populated by specialized middleware
self.repo_name = None
self.repo_vcs_config = base.Config()
# base path of repo locations
self.basepath = get_rhodecode_base_path()
# authenticate this VCS request using authfunc
@ -115,9 +116,7 @@ class SimpleVCS(object):
def _get_by_id(self, repo_name):
"""
Gets a special pattern _<ID> from clone url and tries to replace it
with a repository_name for support of _<ID> non changable urls
:param repo_name:
with a repository_name for support of _<ID> non changeable urls
"""
data = repo_name.split('/')
@ -234,23 +233,18 @@ class SimpleVCS(object):
log.debug('User not allowed to proceed, %s', reason)
return HTTPNotAcceptable(reason)(environ, start_response)
if not self.repo_name:
log.warning('Repository name is empty: %s', self.repo_name)
# failed to get repo name, we fail now
return HTTPNotFound()(environ, start_response)
log.debug('Extracted repo name is %s', self.repo_name)
ip_addr = get_ip_addr(environ)
username = None
# skip passing error to error controller
environ['pylons.status_code_redirect'] = True
# ======================================================================
# EXTRACT REPOSITORY NAME FROM ENV SET IN `class VCSMiddleware`
# ======================================================================
repo_name = environ['REPO_NAME']
log.debug('Extracted repo name is %s', repo_name)
# check for type, presence in database and on filesystem
if not self.is_valid_and_existing_repo(
repo_name, self.basepath, self.SCM):
return HTTPNotFound()(environ, start_response)
# ======================================================================
# GET ACTION PULL or PUSH
# ======================================================================
@ -265,7 +259,7 @@ class SimpleVCS(object):
if anonymous_user.active:
# ONLY check permissions if the user is activated
anonymous_perm = self._check_permission(
action, anonymous_user, repo_name, ip_addr)
action, anonymous_user, self.repo_name, ip_addr)
else:
anonymous_perm = False
@ -329,7 +323,8 @@ class SimpleVCS(object):
return HTTPNotAcceptable(reason)(environ, start_response)
# check permissions for this repository
perm = self._check_permission(action, user, repo_name, ip_addr)
perm = self._check_permission(
action, user, self.repo_name, ip_addr)
if not perm:
return HTTPForbidden()(environ, start_response)
@ -337,14 +332,14 @@ class SimpleVCS(object):
# in hooks executed by rhodecode
check_locking = _should_check_locking(environ.get('QUERY_STRING'))
extras = vcs_operation_context(
environ, repo_name=repo_name, username=username,
environ, repo_name=self.repo_name, username=username,
action=action, scm=self.SCM,
check_locking=check_locking)
# ======================================================================
# REQUEST HANDLING
# ======================================================================
str_repo_name = safe_str(repo_name)
str_repo_name = safe_str(self.repo_name)
repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
log.debug('Repository path is %s', repo_path)
@ -355,7 +350,7 @@ class SimpleVCS(object):
action, self.SCM, str_repo_name, safe_str(username), ip_addr)
return self._generate_vcs_response(
environ, start_response, repo_path, repo_name, extras, action)
environ, start_response, repo_path, self.repo_name, extras, action)
@initialize_generator
def _generate_vcs_response(

View file

@ -24,12 +24,13 @@ import logging
import tempfile
import urlparse
from webob.exc import HTTPNotFound
import rhodecode
from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
from rhodecode.lib.middleware.simplegit import SimpleGit, GIT_PROTO_PAT
from rhodecode.lib.middleware.simplehg import SimpleHg
from rhodecode.lib.middleware.simplesvn import SimpleSvn
from rhodecode.lib.vcs.backends import base
from rhodecode.model.settings import VcsSettingsModel
log = logging.getLogger(__name__)
@ -132,8 +133,14 @@ class VCSMiddleware(object):
self.config = config
self.appenlight_client = appenlight_client
self.registry = registry
self.repo_vcs_config = base.Config()
self.use_gzip = True
# order in which we check the middlewares, based on vcs.backends config
self.check_middlewares = config['vcs.backends']
self.checks = {
'hg': (is_hg, SimpleHg),
'git': (is_git, SimpleGit),
'svn': (is_svn, SimpleSvn),
}
def vcs_config(self, repo_name=None):
"""
@ -141,43 +148,50 @@ class VCSMiddleware(object):
"""
return VcsSettingsModel(repo=repo_name).get_ui_settings_as_config_obj()
def wrap_in_gzip_if_enabled(self, app):
def wrap_in_gzip_if_enabled(self, app, config):
if self.use_gzip:
app = GunzipMiddleware(app)
return app
def _get_handler_app(self, environ):
app = None
if is_hg(environ):
app = SimpleHg(self.application, self.config, self.registry)
if is_git(environ):
app = SimpleGit(self.application, self.config, self.registry)
if is_svn(environ):
app = SimpleSvn(self.application, self.config, self.registry)
if app:
# translate the _REPO_ID into real repo NAME for usage
# in midddleware
environ['PATH_INFO'] = app._get_by_id(environ['PATH_INFO'])
repo_name = app._get_repository_name(environ)
environ['REPO_NAME'] = repo_name
self.repo_vcs_config = self.vcs_config(repo_name)
app.repo_vcs_config = self.repo_vcs_config
app = self.wrap_in_gzip_if_enabled(app)
app, _ = wrap_in_appenlight_if_enabled(
app, self.config, self.appenlight_client)
log.debug('Checking vcs types in order: %r', self.check_middlewares)
for vcs_type in self.check_middlewares:
vcs_check, handler = self.checks[vcs_type]
if vcs_check(environ):
log.debug(
'Found VCS Middleware to handle the request %s', handler)
app = handler(self.application, self.config, self.registry)
break
return app
def __call__(self, environ, start_response):
# check if we handle one of interesting protocols ?
# check if we handle one of interesting protocols, optionally extract
# specific vcsSettings and allow changes of how things are wrapped
vcs_handler = self._get_handler_app(environ)
if vcs_handler:
# translate the _REPO_ID into real repo NAME for usage
# in middleware
environ['PATH_INFO'] = vcs_handler._get_by_id(environ['PATH_INFO'])
repo_name = vcs_handler._get_repository_name(environ)
# check for type, presence in database and on filesystem
if not vcs_handler.is_valid_and_existing_repo(
repo_name, vcs_handler.basepath, vcs_handler.SCM):
return HTTPNotFound()(environ, start_response)
# TODO(marcink): this is probably not needed anymore
environ['REPO_NAME'] = repo_name
# register repo_name and it's config back to the handler
vcs_handler.repo_name = repo_name
vcs_handler.repo_vcs_config = self.vcs_config(repo_name)
vcs_handler = self.wrap_in_gzip_if_enabled(
vcs_handler, self.config)
vcs_handler, _ = wrap_in_appenlight_if_enabled(
vcs_handler, self.config, self.appenlight_client)
return vcs_handler(environ, start_response)
return self.application(environ, start_response)

View file

@ -42,6 +42,10 @@ class StubVCSController(simplevcs.SimpleVCS):
SCM = 'hg'
stub_response_body = tuple()
def __init__(self, *args, **kwargs):
super(StubVCSController, self).__init__(*args, **kwargs)
self.repo_name = HG_REPO
def _get_repository_name(self, environ):
return HG_REPO

View file

@ -105,7 +105,7 @@ class TestVCSMiddleware(object):
'HTTP_DAV': 'http://subversion.tigris.org/xmlns/dav/svn/log'
}
application = Mock()
config = {'appenlight': False}
config = {'appenlight': False, 'vcs.backends': ['svn']}
registry = Mock()
middleware = vcs.VCSMiddleware(
application, config=config,
@ -125,7 +125,7 @@ class TestVCSMiddleware(object):
'HTTP_DAV': 'http://subversion.tigris.org/xmlns/dav/svn/log'
}
application = Mock()
config = {'appenlight': False}
config = {'appenlight': False, 'vcs.backends': ['svn']}
registry = Mock()
middleware = vcs.VCSMiddleware(
application, config=config,