##// END OF EJS Templates
release: Finish preparation for 4.19.1
release: Finish preparation for 4.19.1

File last commit:

r850:cbc05af2 default
r858:3a815eeb v4.19.1 stable
Show More
http_main.py
688 lines | 23.2 KiB | text/x-python | PythonLexer
initial commit
r0 # RhodeCode VCSServer provides access to different vcs backends via network.
code: update copyrights to 2020
r850 # Copyright (C) 2014-2020 RhodeCode GmbH
initial commit
r0 #
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
http: status will return PID to help check stuck workers.
r372 import os
exceptions: allow error tracking and exception storage on vcsserver.
r491 import sys
initial commit
r0 import base64
import locale
import logging
import uuid
import wsgiref.util
http-mode: expose tracebacks back to the client.
r146 import traceback
exc_store: allow to specify a custom path for exception store.
r519 import tempfile
initial commit
r0 from itertools import chain
dan
vcsserver: added streaming interface for streaming remote attributes
r768 from cStringIO import StringIO
initial commit
r0
http: set REMOTE_USER and REMOTE_HOST http variables....
r269 import simplejson as json
initial commit
r0 import msgpack
from pyramid.config import Configurator
caches: replaced beaker with dogpile cache.
r483 from pyramid.settings import asbool, aslist
initial commit
r0 from pyramid.wsgi import wsgiapp
compat: use py3 compatible configparser
r405 from pyramid.compat import configparser
dan
vcsserver: added streaming interface for streaming remote attributes
r768 from pyramid.response import Response
initial commit
r0
dan
vcsserver: added streaming interface for streaming remote attributes
r768 from vcsserver.utils import safe_int
locale: use a hacky way to catch the locale set error. We rather "cleanup" the env ourselfs...
r507
log = logging.getLogger(__name__)
# due to Mercurial/glibc2.27 problems we need to detect if locale settings are
# causing problems and "fix" it in case they do and fallback to LC_ALL = C
try:
locale.setlocale(locale.LC_ALL, '')
except locale.Error as e:
log.error(
'LOCALE ERROR: failed to set LC_ALL, fallback to LC_ALL=C, org error: %s', e)
os.environ['LC_ALL'] = 'C'
exc_store: allow to specify a custom path for exception store.
r519 import vcsserver
Martin Bornhold
hg: Include mercurial patching when using the http app.
r35 from vcsserver import remote_wsgi, scm_app, settings, hgpatches
git-lfs: added vcsserver handling of git-lfs objects....
r180 from vcsserver.git_lfs.app import GIT_LFS_CONTENT_TYPE, GIT_LFS_PROTO_PAT
initial commit
r0 from vcsserver.echo_stub import remote_wsgi as remote_wsgi_stub
from vcsserver.echo_stub.echo_app import EchoApp
hooks: adjust to handle protected branch cases, and force push.
r509 from vcsserver.exceptions import HTTPRepoLocked, HTTPRepoBranchProtected
exceptions: allow error tracking and exception storage on vcsserver.
r491 from vcsserver.lib.exc_tracking import store_exception
initial commit
r0 from vcsserver.server import VcsServer
try:
from vcsserver.git import GitFactory, GitRemote
except ImportError:
GitFactory = None
GitRemote = None
git-lfs: added vcsserver handling of git-lfs objects....
r180
initial commit
r0 try:
from vcsserver.hg import MercurialFactory, HgRemote
except ImportError:
MercurialFactory = None
HgRemote = None
git-lfs: added vcsserver handling of git-lfs objects....
r180
initial commit
r0 try:
from vcsserver.svn import SubversionFactory, SvnRemote
except ImportError:
SubversionFactory = None
SvnRemote = None
locale: use a hacky way to catch the locale set error. We rather "cleanup" the env ourselfs...
r507
stream: use wsgi.input_terminated because of webob changes of handling chunked encoding
r332 def _is_request_chunked(environ):
stream = environ.get('HTTP_TRANSFER_ENCODING', '') == 'chunked'
return stream
caches: replaced beaker with dogpile cache.
r483 def _int_setting(settings, name, default):
settings[name] = int(settings.get(name, default))
exc_store: allow to specify a custom path for exception store.
r519 return settings[name]
caches: replaced beaker with dogpile cache.
r483
def _bool_setting(settings, name, default):
input_val = settings.get(name, default)
if isinstance(input_val, unicode):
input_val = input_val.encode('utf8')
settings[name] = asbool(input_val)
exc_store: allow to specify a custom path for exception store.
r519 return settings[name]
caches: replaced beaker with dogpile cache.
r483
def _list_setting(settings, name, default):
raw_value = settings.get(name, default)
# Otherwise we assume it uses pyramids space/newline separation.
settings[name] = aslist(raw_value)
exc_store: allow to specify a custom path for exception store.
r519 return settings[name]
caches: replaced beaker with dogpile cache.
r483
exc_store: allow to specify a custom path for exception store.
r519 def _string_setting(settings, name, default, lower=True, default_when_empty=False):
caches: replaced beaker with dogpile cache.
r483 value = settings.get(name, default)
exc_store: allow to specify a custom path for exception store.
r519
if default_when_empty and not value:
# use default value when value is empty
value = default
caches: replaced beaker with dogpile cache.
r483 if lower:
value = value.lower()
settings[name] = value
exc_store: allow to specify a custom path for exception store.
r519 return settings[name]
caches: replaced beaker with dogpile cache.
r483
initial commit
r0 class VCS(object):
dan
vcsserver: added streaming interface for streaming remote attributes
r768 def __init__(self, locale_conf=None, cache_config=None):
self.locale = locale_conf
initial commit
r0 self.cache_config = cache_config
self._configure_locale()
if GitFactory and GitRemote:
caches: replaced beaker with dogpile cache.
r483 git_factory = GitFactory()
initial commit
r0 self._git_remote = GitRemote(git_factory)
else:
log.info("Git client import failed")
if MercurialFactory and HgRemote:
caches: replaced beaker with dogpile cache.
r483 hg_factory = MercurialFactory()
initial commit
r0 self._hg_remote = HgRemote(hg_factory)
else:
log.info("Mercurial client import failed")
if SubversionFactory and SvnRemote:
caches: replaced beaker with dogpile cache.
r483 svn_factory = SubversionFactory()
svn: added support for hooks management of git and subversion....
r407 # hg factory is used for svn url validation
caches: replaced beaker with dogpile cache.
r483 hg_factory = MercurialFactory()
initial commit
r0 self._svn_remote = SvnRemote(svn_factory, hg_factory=hg_factory)
else:
log.info("Subversion client import failed")
self._vcsserver = VcsServer()
def _configure_locale(self):
if self.locale:
logging: use lazy formatting of log entries
r541 log.info('Settings locale: `LC_ALL` to %s', self.locale)
initial commit
r0 else:
log.info(
'Configuring locale subsystem based on environment variables')
try:
# If self.locale is the empty string, then the locale
# module will use the environment variables. See the
# documentation of the package `locale`.
locale.setlocale(locale.LC_ALL, self.locale)
language_code, encoding = locale.getlocale()
log.info(
'Locale set to language code "%s" with encoding "%s".',
language_code, encoding)
except locale.Error:
log.exception(
'Cannot set locale, not configuring the locale system')
class WsgiProxy(object):
def __init__(self, wsgi):
self.wsgi = wsgi
def __call__(self, environ, start_response):
input_data = environ['wsgi.input'].read()
input_data = msgpack.unpackb(input_data)
error = None
try:
data, status, headers = self.wsgi.handle(
input_data['environment'], input_data['input_data'],
*input_data['args'], **input_data['kwargs'])
except Exception as e:
data, status, headers = [], None, None
error = {
'message': str(e),
'_vcs_kind': getattr(e, '_vcs_kind', None)
}
start_response(200, {})
return self._iterator(error, status, headers, data)
def _iterator(self, error, status, headers, data):
initial_data = [
error,
status,
headers,
]
for d in chain(initial_data, data):
yield msgpack.packb(d)
pyramid: don't use deprecated custom_predicates in view config
r583 def not_found(request):
return {'status': '404 NOT FOUND'}
class VCSViewPredicate(object):
def __init__(self, val, config):
self.remotes = val
def text(self):
return 'vcs view method = %s' % (self.remotes.keys(),)
phash = text
def __call__(self, context, request):
"""
View predicate that returns true if given backend is supported by
defined remotes.
"""
backend = request.matchdict.get('backend')
return backend in self.remotes
initial commit
r0 class HTTPApplication(object):
ALLOWED_EXCEPTIONS = ('KeyError', 'URLError')
remote_wsgi = remote_wsgi
_use_echo_app = False
service-endpoint: expose additional data of vcsserver via service-data endpoint....
r173 def __init__(self, settings=None, global_config=None):
caches: replaced beaker with dogpile cache.
r483 self._sanitize_settings_and_apply_defaults(settings)
initial commit
r0 self.config = Configurator(settings=settings)
service-endpoint: expose additional data of vcsserver via service-data endpoint....
r173 self.global_config = global_config
caches: replaced beaker with dogpile cache.
r483 self.config.include('vcsserver.lib.rc_cache')
service-endpoint: expose additional data of vcsserver via service-data endpoint....
r173
app: small code cleanups
r743 settings_locale = settings.get('locale', '') or 'en_US.UTF-8'
dan
vcsserver: added streaming interface for streaming remote attributes
r768 vcs = VCS(locale_conf=settings_locale, cache_config=settings)
initial commit
r0 self._remotes = {
'hg': vcs._hg_remote,
'git': vcs._git_remote,
'svn': vcs._svn_remote,
'server': vcs._vcsserver,
}
if settings.get('dev.use_echo_app', 'false').lower() == 'true':
self._use_echo_app = True
log.warning("Using EchoApp for VCS operations.")
self.remote_wsgi = remote_wsgi_stub
exc_store: allow to specify a custom path for exception store.
r519
self._configure_settings(global_config, settings)
initial commit
r0 self._configure()
exc_store: allow to specify a custom path for exception store.
r519 def _configure_settings(self, global_config, app_settings):
initial commit
r0 """
Configure the settings module.
"""
exc_store: allow to specify a custom path for exception store.
r519 settings_merged = global_config.copy()
settings_merged.update(app_settings)
initial commit
r0 git_path = app_settings.get('git_path', None)
if git_path:
settings.GIT_EXECUTABLE = git_path
svn: added support for hooks management of git and subversion....
r407 binary_dir = app_settings.get('core.binary_dir', None)
if binary_dir:
settings.BINARY_DIR = binary_dir
initial commit
r0
exc_store: allow to specify a custom path for exception store.
r519 # Store the settings to make them available to other modules.
vcsserver.PYRAMID_SETTINGS = settings_merged
vcsserver.CONFIG = settings_merged
caches: replaced beaker with dogpile cache.
r483 def _sanitize_settings_and_apply_defaults(self, settings):
exc_store: default value should be constant accross all types of instances for shared exception store
r524 temp_store = tempfile.gettempdir()
default_cache_dir = os.path.join(temp_store, 'rc_cache')
exc_store: allow to specify a custom path for exception store.
r519
# save default, cache dir, and use it for all backends later.
default_cache_dir = _string_setting(
settings,
'cache_dir',
default_cache_dir, lower=False, default_when_empty=True)
# ensure we have our dir created
if not os.path.isdir(default_cache_dir):
code: fix deprecated octal usage for py3 compatability.
r590 os.makedirs(default_cache_dir, mode=0o755)
exc_store: allow to specify a custom path for exception store.
r519
# exception store cache
_string_setting(
settings,
exception_store: rename .ini option for future
r520 'exception_tracker.store_path',
exc_store: default value should be constant accross all types of instances for shared exception store
r524 temp_store, lower=False, default_when_empty=True)
exc_store: allow to specify a custom path for exception store.
r519
caches: replaced beaker with dogpile cache.
r483 # repo_object cache
_string_setting(
settings,
'rc_cache.repo_object.backend',
caches: set file based cache as default for vcsserver
r776 'dogpile.cache.rc.file_namespace', lower=False)
caches: replaced beaker with dogpile cache.
r483 _int_setting(
settings,
'rc_cache.repo_object.expiration_time',
caches: set file based cache as default for vcsserver
r776 30 * 24 * 60 * 60)
_string_setting(
caches: replaced beaker with dogpile cache.
r483 settings,
caches: set file based cache as default for vcsserver
r776 'rc_cache.repo_object.arguments.filename',
os.path.join(default_cache_dir, 'vcsserver_cache_1'), lower=False)
caches: replaced beaker with dogpile cache.
r483
initial commit
r0 def _configure(self):
pyramid: don't use deprecated custom_predicates in view config
r583 self.config.add_renderer(name='msgpack', factory=self._msgpack_renderer_factory)
initial commit
r0
http: added service backend for testing communication, and extracting vcsserver version...
r102 self.config.add_route('service', '/_service')
initial commit
r0 self.config.add_route('status', '/status')
self.config.add_route('hg_proxy', '/proxy/hg')
self.config.add_route('git_proxy', '/proxy/git')
dan
vcsserver: added streaming interface for streaming remote attributes
r768
# rpc methods
initial commit
r0 self.config.add_route('vcs', '/{backend}')
dan
vcsserver: added streaming interface for streaming remote attributes
r768
# streaming rpc remote methods
self.config.add_route('vcs_stream', '/{backend}/stream')
# vcs operations clone/push as streaming
initial commit
r0 self.config.add_route('stream_git', '/stream/git/*repo_name')
self.config.add_route('stream_hg', '/stream/hg/*repo_name')
pyramid: don't use deprecated custom_predicates in view config
r583 self.config.add_view(self.status_view, route_name='status', renderer='json')
self.config.add_view(self.service_view, route_name='service', renderer='msgpack')
http: added service backend for testing communication, and extracting vcsserver version...
r102
initial commit
r0 self.config.add_view(self.hg_proxy(), route_name='hg_proxy')
self.config.add_view(self.git_proxy(), route_name='git_proxy')
pyramid: don't use deprecated custom_predicates in view config
r583 self.config.add_view(self.vcs_view, route_name='vcs', renderer='msgpack',
vcs_view=self._remotes)
dan
vcsserver: added streaming interface for streaming remote attributes
r768 self.config.add_view(self.vcs_stream_view, route_name='vcs_stream',
vcs_view=self._remotes)
initial commit
r0
self.config.add_view(self.hg_stream(), route_name='stream_hg')
self.config.add_view(self.git_stream(), route_name='stream_git')
http-app: added default not_found view.
r151
pyramid: don't use deprecated custom_predicates in view config
r583 self.config.add_view_predicate('vcs_view', VCSViewPredicate)
self.config.add_notfound_view(not_found, renderer='json')
http-app: added default not_found view.
r151
exceptions: use only one exception handler to track errors with nicer...
r178 self.config.add_view(self.handle_vcs_exception, context=Exception)
http: added catch-all exception handler to show errors in logs.
r150
vcsserver: http main added time measuring tween for debugging.
r154 self.config.add_tween(
request-wrapper: set custom module for better logging.
r744 'vcsserver.tweens.request_wrapper.RequestWrapperTween',
vcsserver: http main added time measuring tween for debugging.
r154 )
request-wrapper: add request counter.
r756 self.config.add_request_method(
'vcsserver.lib.request_counter.get_request_counter',
'request_count')
vcsserver: http main added time measuring tween for debugging.
r154
initial commit
r0 def wsgi_app(self):
return self.config.make_wsgi_app()
dan
vcsserver: added streaming interface for streaming remote attributes
r768 def _vcs_view_params(self, request):
initial commit
r0 remote = self._remotes[request.matchdict['backend']]
payload = msgpack.unpackb(request.body, use_list=True)
method = payload.get('method')
dan
vcsserver: added streaming interface for streaming remote attributes
r768 params = payload['params']
initial commit
r0 wire = params.get('wire')
args = params.get('args')
kwargs = params.get('kwargs')
caches: replaced beaker with dogpile cache.
r483 context_uid = None
initial commit
r0 if wire:
try:
caches: replaced beaker with dogpile cache.
r483 wire['context'] = context_uid = uuid.UUID(wire['context'])
initial commit
r0 except KeyError:
pass
args.insert(0, wire)
dan
vcsserver: added streaming interface for streaming remote attributes
r768 repo_state_uid = wire.get('repo_state_uid') if wire else None
initial commit
r0
logging: skip large attribute expansion on archive_repo. We don't need arguments there
r742 # NOTE(marcink): trading complexity for slight performance
if log.isEnabledFor(logging.DEBUG):
no_args_methods = [
'archive_repo'
]
if method in no_args_methods:
call_args = ''
else:
call_args = args[1:]
http-proto: added some more logging.
r745
dan
vcsserver: added streaming interface for streaming remote attributes
r768 log.debug('method requested:%s with args:%s kwargs:%s context_uid: %s, repo_state_uid:%s',
http-proto: added some more logging.
r745 method, call_args, kwargs, context_uid, repo_state_uid)
git: switched most git operations to libgit2
r725
dan
vcsserver: added streaming interface for streaming remote attributes
r768 return payload, remote, method, args, kwargs
def vcs_view(self, request):
payload, remote, method, args, kwargs = self._vcs_view_params(request)
payload_id = payload.get('id')
initial commit
r0 try:
resp = getattr(remote, method)(*args, **kwargs)
except Exception as e:
exceptions: allow error tracking and exception storage on vcsserver.
r491 exc_info = list(sys.exc_info())
exc_type, exc_value, exc_traceback = exc_info
org_exc = getattr(e, '_org_exc', None)
org_exc_name = None
exception: store orginal tb and exc inside the new exception passed to rhodecode from vcsserver.
r621 org_exc_tb = ''
exceptions: allow error tracking and exception storage on vcsserver.
r491 if org_exc:
org_exc_name = org_exc.__class__.__name__
exception: store orginal tb and exc inside the new exception passed to rhodecode from vcsserver.
r621 org_exc_tb = getattr(e, '_org_exc_tb', '')
exceptions: allow error tracking and exception storage on vcsserver.
r491 # replace our "faked" exception with our org
exc_info[0] = org_exc.__class__
exc_info[1] = org_exc
exceptions: don't report lookup errors as exceptions stored in the exception store....
r843 should_store_exc = True
if org_exc:
def get_exc_fqn(_exc_obj):
module_name = getattr(org_exc.__class__, '__module__', 'UNKNOWN')
return module_name + '.' + org_exc_name
exc_fqn = get_exc_fqn(org_exc)
if exc_fqn in ['mercurial.error.RepoLookupError',
'vcsserver.exceptions.RefNotFoundException']:
should_store_exc = False
if should_store_exc:
store_exception(id(exc_info), exc_info)
exceptions: allow error tracking and exception storage on vcsserver.
r491
tb_info = ''.join(
traceback.format_exception(exc_type, exc_value, exc_traceback))
http-mode: expose tracebacks back to the client.
r146
initial commit
r0 type_ = e.__class__.__name__
if type_ not in self.ALLOWED_EXCEPTIONS:
type_ = None
resp = {
dan
vcsserver: added streaming interface for streaming remote attributes
r768 'id': payload_id,
initial commit
r0 'error': {
'message': e.message,
http-mode: expose tracebacks back to the client.
r146 'traceback': tb_info,
exceptions: allow error tracking and exception storage on vcsserver.
r491 'org_exc': org_exc_name,
exception: store orginal tb and exc inside the new exception passed to rhodecode from vcsserver.
r621 'org_exc_tb': org_exc_tb,
initial commit
r0 'type': type_
}
}
try:
caches: replaced beaker with dogpile cache.
r483 resp['error']['_vcs_kind'] = getattr(e, '_vcs_kind', None)
initial commit
r0 except AttributeError:
pass
else:
resp = {
dan
vcsserver: added streaming interface for streaming remote attributes
r768 'id': payload_id,
initial commit
r0 'result': resp
}
return resp
dan
vcsserver: added streaming interface for streaming remote attributes
r768 def vcs_stream_view(self, request):
payload, remote, method, args, kwargs = self._vcs_view_params(request)
# this method has a stream: marker we remove it here
method = method.split('stream:')[-1]
chunk_size = safe_int(payload.get('chunk_size')) or 4096
try:
resp = getattr(remote, method)(*args, **kwargs)
except Exception as e:
raise
def get_chunked_data(method_resp):
stream = StringIO(method_resp)
while 1:
chunk = stream.read(chunk_size)
if not chunk:
break
yield chunk
response = Response(app_iter=get_chunked_data(resp))
response.content_type = 'application/octet-stream'
return response
initial commit
r0 def status_view(self, request):
vcsserver-status: report version for easier debugging.
r250 import vcsserver
http: status will return PID to help check stuck workers.
r372 return {'status': 'OK', 'vcsserver_version': vcsserver.__version__,
'pid': os.getpid()}
initial commit
r0
http: added service backend for testing communication, and extracting vcsserver version...
r102 def service_view(self, request):
import vcsserver
service-endpoint: expose additional data of vcsserver via service-data endpoint....
r173
http: added service backend for testing communication, and extracting vcsserver version...
r102 payload = msgpack.unpackb(request.body, use_list=True)
service: expose config so enterprise can read it.
r784 server_config, app_config = {}, {}
service-endpoint: expose additional data of vcsserver via service-data endpoint....
r173
try:
path = self.global_config['__file__']
service: expose config so enterprise can read it.
r784 config = configparser.RawConfigParser()
service-endpoint: expose additional data of vcsserver via service-data endpoint....
r173 config.read(path)
service: expose config so enterprise can read it.
r784
if config.has_section('server:main'):
server_config = dict(config.items('server:main'))
if config.has_section('app:main'):
app_config = dict(config.items('app:main'))
service-endpoint: expose additional data of vcsserver via service-data endpoint....
r173 except Exception:
log.exception('Failed to read .ini file for display')
service: expose config so enterprise can read it.
r784
environ = os.environ.items()
service-endpoint: expose additional data of vcsserver via service-data endpoint....
r173
http: added service backend for testing communication, and extracting vcsserver version...
r102 resp = {
'id': payload.get('id'),
'result': dict(
version=vcsserver.__version__,
service: expose config so enterprise can read it.
r784 config=server_config,
app_config=app_config,
environ=environ,
http: added service backend for testing communication, and extracting vcsserver version...
r102 payload=payload,
)
}
return resp
initial commit
r0 def _msgpack_renderer_factory(self, info):
def _render(value, system):
request = system.get('request')
if request is not None:
response = request.response
ct = response.content_type
if ct == response.default_content_type:
response.content_type = 'application/x-msgpack'
app: small code cleanups
r743 return msgpack.packb(value)
initial commit
r0 return _render
http: set REMOTE_USER and REMOTE_HOST http variables....
r269 def set_env_from_config(self, environ, config):
dict_conf = {}
try:
for elem in config:
if elem[0] == 'rhodecode':
dict_conf = json.loads(elem[2])
break
except Exception:
log.exception('Failed to fetch SCM CONFIG')
return
username = dict_conf.get('username')
if username:
environ['REMOTE_USER'] = username
mercurial: expose HGUSER into environ becuase some extensions explicitly rely on this....
r353 # mercurial specific, some extension api rely on this
environ['HGUSER'] = username
http: set REMOTE_USER and REMOTE_HOST http variables....
r269
ip = dict_conf.get('ip')
if ip:
environ['REMOTE_HOST'] = ip
stream: use wsgi.input_terminated because of webob changes of handling chunked encoding
r332 if _is_request_chunked(environ):
# set the compatibility flag for webob
environ['wsgi.input_terminated'] = True
initial commit
r0 def hg_proxy(self):
@wsgiapp
def _hg_proxy(environ, start_response):
app = WsgiProxy(self.remote_wsgi.HgRemoteWsgi())
return app(environ, start_response)
return _hg_proxy
def git_proxy(self):
@wsgiapp
def _git_proxy(environ, start_response):
app = WsgiProxy(self.remote_wsgi.GitRemoteWsgi())
return app(environ, start_response)
return _git_proxy
def hg_stream(self):
if self._use_echo_app:
@wsgiapp
def _hg_stream(environ, start_response):
app = EchoApp('fake_path', 'fake_name', None)
return app(environ, start_response)
return _hg_stream
else:
@wsgiapp
def _hg_stream(environ, start_response):
logs: added some added logging for stream hg/git.
r247 log.debug('http-app: handling hg stream')
initial commit
r0 repo_path = environ['HTTP_X_RC_REPO_PATH']
repo_name = environ['HTTP_X_RC_REPO_NAME']
packed_config = base64.b64decode(
environ['HTTP_X_RC_REPO_CONFIG'])
config = msgpack.unpackb(packed_config)
app = scm_app.create_hg_wsgi_app(
repo_path, repo_name, config)
http: set REMOTE_USER and REMOTE_HOST http variables....
r269 # Consistent path information for hgweb
initial commit
r0 environ['PATH_INFO'] = environ['HTTP_X_RC_PATH_INFO']
environ['REPO_NAME'] = repo_name
http: set REMOTE_USER and REMOTE_HOST http variables....
r269 self.set_env_from_config(environ, config)
logs: added some added logging for stream hg/git.
r247 log.debug('http-app: starting app handler '
'with %s and process request', app)
initial commit
r0 return app(environ, ResponseFilter(start_response))
return _hg_stream
def git_stream(self):
if self._use_echo_app:
@wsgiapp
def _git_stream(environ, start_response):
app = EchoApp('fake_path', 'fake_name', None)
return app(environ, start_response)
return _git_stream
else:
@wsgiapp
def _git_stream(environ, start_response):
logs: added some added logging for stream hg/git.
r247 log.debug('http-app: handling git stream')
initial commit
r0 repo_path = environ['HTTP_X_RC_REPO_PATH']
repo_name = environ['HTTP_X_RC_REPO_NAME']
packed_config = base64.b64decode(
environ['HTTP_X_RC_REPO_CONFIG'])
config = msgpack.unpackb(packed_config)
environ['PATH_INFO'] = environ['HTTP_X_RC_PATH_INFO']
http: set REMOTE_USER and REMOTE_HOST http variables....
r269 self.set_env_from_config(environ, config)
git-lfs: added vcsserver handling of git-lfs objects....
r180 content_type = environ.get('CONTENT_TYPE', '')
path = environ['PATH_INFO']
is_lfs_request = GIT_LFS_CONTENT_TYPE in content_type
log.debug(
'LFS: Detecting if request `%s` is LFS server path based '
'on content type:`%s`, is_lfs:%s',
path, content_type, is_lfs_request)
if not is_lfs_request:
# fallback detection by path
if GIT_LFS_PROTO_PAT.match(path):
is_lfs_request = True
log.debug(
'LFS: fallback detection by path of: `%s`, is_lfs:%s',
path, is_lfs_request)
if is_lfs_request:
app = scm_app.create_git_lfs_wsgi_app(
repo_path, repo_name, config)
else:
app = scm_app.create_git_wsgi_app(
repo_path, repo_name, config)
logs: added some added logging for stream hg/git.
r247
log.debug('http-app: starting app handler '
'with %s and process request', app)
stream: use wsgi.input_terminated because of webob changes of handling chunked encoding
r332
initial commit
r0 return app(environ, start_response)
git-lfs: added vcsserver handling of git-lfs objects....
r180
initial commit
r0 return _git_stream
Martin Bornhold
http: Add error handling for the repo-locked exception. Part of #4237...
r85 def handle_vcs_exception(self, exception, request):
exceptions: use only one exception handler to track errors with nicer...
r178 _vcs_kind = getattr(exception, '_vcs_kind', '')
if _vcs_kind == 'repo_locked':
Martin Bornhold
http: Add error handling for the repo-locked exception. Part of #4237...
r85 # Get custom repo-locked status code if present.
status_code = request.headers.get('X-RC-Locked-Status-Code')
return HTTPRepoLocked(
title=exception.message, status_code=status_code)
exceptions: allow error tracking and exception storage on vcsserver.
r491
hooks: adjust to handle protected branch cases, and force push.
r509 elif _vcs_kind == 'repo_branch_protected':
# Get custom repo-branch-protected status code if present.
return HTTPRepoBranchProtected(title=exception.message)
exceptions: allow error tracking and exception storage on vcsserver.
r491 exc_info = request.exc_info
store_exception(id(exc_info), exc_info)
errors: use a better interface to track exceptions and tracebacks.
r478 traceback_info = 'unavailable'
if request.exc_info:
exceptions: allow error tracking and exception storage on vcsserver.
r491 exc_type, exc_value, exc_tb = request.exc_info
traceback_info = ''.join(traceback.format_exception(exc_type, exc_value, exc_tb))
Martin Bornhold
http: Add error handling for the repo-locked exception. Part of #4237...
r85
errors: use a better interface to track exceptions and tracebacks.
r478 log.error(
'error occurred handling this request for path: %s, \n tb: %s',
request.path, traceback_info)
http: added catch-all exception handler to show errors in logs.
r150 raise exception
initial commit
r0
class ResponseFilter(object):
def __init__(self, start_response):
self._start_response = start_response
def __call__(self, status, response_headers, exc_info=None):
headers = tuple(
(h, v) for h, v in response_headers
if not wsgiref.util.is_hop_by_hop(h))
return self._start_response(status, headers, exc_info)
def main(global_config, **settings):
Martin Bornhold
hg: Include mercurial patching when using the http app.
r35 if MercurialFactory:
hgpatches.patch_largefiles_capabilities()
Martin Bornhold
subrepo: Apply mercurial sub repository patch.
r100 hgpatches.patch_subrepo_type_mapping()
caches: replaced beaker with dogpile cache.
r483
service-endpoint: expose additional data of vcsserver via service-data endpoint....
r173 app = HTTPApplication(settings=settings, global_config=global_config)
initial commit
r0 return app.wsgi_app()