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:
parent
d9ca3e74c2
commit
df353f19ea
4 changed files with 63 additions and 50 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue