diff --git a/rhodecode/events/base.py b/rhodecode/events/base.py --- a/rhodecode/events/base.py +++ b/rhodecode/events/base.py @@ -16,9 +16,11 @@ # RhodeCode Enterprise Edition, including its added features, Support services, # and proprietary license terms, please see https://rhodecode.com/licenses/ import logging +import datetime -from datetime import datetime +from zope.cachedescriptors.property import Lazy as LazyProperty from pyramid.threadlocal import get_current_request + from rhodecode.lib.utils2 import AttributeDict @@ -36,10 +38,20 @@ class RhodecodeEvent(object): Base event class for all RhodeCode events """ name = "RhodeCodeEvent" + no_url_set = '' def __init__(self, request=None): - self.request = request or get_current_request() - self.utc_timestamp = datetime.utcnow() + self._request = request + self.utc_timestamp = datetime.datetime.utcnow() + + def get_request(self): + if self._request: + return self._request + return get_current_request() + + @LazyProperty + def request(self): + return self.get_request() @property def auth_user(self): @@ -57,7 +69,6 @@ class RhodecodeEvent(object): @property def actor(self): auth_user = self.auth_user - if auth_user: instance = auth_user.get_instance() if not instance: @@ -78,15 +89,14 @@ class RhodecodeEvent(object): @property def server_url(self): - default = '' if self.request: try: return self.request.route_url('home') except Exception: log.exception('Failed to fetch URL for server') - return default + return self.no_url_set - return default + return self.no_url_set def as_dict(self): data = { diff --git a/rhodecode/events/pullrequest.py b/rhodecode/events/pullrequest.py --- a/rhodecode/events/pullrequest.py +++ b/rhodecode/events/pullrequest.py @@ -52,9 +52,10 @@ class PullRequestEvent(RepoEvent): 'title': self.pullrequest.title, 'issues': issues, 'pull_request_id': self.pullrequest.pull_request_id, - 'url': PullRequestModel().get_url(self.pullrequest), + 'url': PullRequestModel().get_url( + self.pullrequest, request=self.request), 'permalink_url': PullRequestModel().get_url( - self.pullrequest, permalink=True), + self.pullrequest, request=self.request, permalink=True), 'status': self.pullrequest.calculated_review_status(), 'commits': commits, } @@ -134,9 +135,10 @@ class PullRequestCommentEvent(PullReques 'type': self.comment.comment_type, 'file': self.comment.f_path, 'line': self.comment.line_no, - 'url': CommentsModel().get_url(self.comment), + 'url': CommentsModel().get_url( + self.comment, request=self.request), 'permalink_url': CommentsModel().get_url( - self.comment, permalink=True), + self.comment, request=self.request, permalink=True), } }) return data diff --git a/rhodecode/events/repo.py b/rhodecode/events/repo.py --- a/rhodecode/events/repo.py +++ b/rhodecode/events/repo.py @@ -120,6 +120,7 @@ class RepoEvent(RhodecodeEvent): def as_dict(self): from rhodecode.model.repo import RepoModel data = super(RepoEvent, self).as_dict() + extra_fields = collections.OrderedDict() for field in self.repo.extra_fields: extra_fields[field.field_key] = field.field_value @@ -201,6 +202,10 @@ class RepoVCSEvent(RepoEvent): if self.extras.get('server_url'): return self.extras['server_url'] + @property + def request(self): + return self.extras.get('request') or self.get_request() + class RepoPrePullEvent(RepoVCSEvent): """ diff --git a/rhodecode/lib/base.py b/rhodecode/lib/base.py --- a/rhodecode/lib/base.py +++ b/rhodecode/lib/base.py @@ -582,6 +582,36 @@ def h_filter(s): return markupsafe.escape(s) +def add_events_routes(config): + """ + Adds routing that can be used in events. Because some events are triggered + outside of pyramid context, we need to bootstrap request with some + routing registered + """ + config.add_route(name='home', pattern='/') + + config.add_route(name='repo_summary', pattern='/{repo_name}') + config.add_route(name='repo_summary_explicit', pattern='/{repo_name}/summary') + config.add_route(name='repo_group_home', pattern='/{repo_group_name}') + + config.add_route(name='pullrequest_show', + pattern='/{repo_name}/pull-request/{pull_request_id}') + config.add_route(name='pull_requests_global', + pattern='/pull-request/{pull_request_id}') + + config.add_route(name='repo_commit', + pattern='/{repo_name}/changeset/{commit_id}') + config.add_route(name='repo_files', + pattern='/{repo_name}/files/{commit_id}/{f_path}') + + +def bootstrap_request(): + import pyramid.testing + request = pyramid.testing.DummyRequest() + config = pyramid.testing.setUp(request=request) + add_events_routes(config) + + class BaseRepoController(BaseController): """ Base class for controllers responsible for loading all needed data for diff --git a/rhodecode/lib/hooks_daemon.py b/rhodecode/lib/hooks_daemon.py --- a/rhodecode/lib/hooks_daemon.py +++ b/rhodecode/lib/hooks_daemon.py @@ -25,13 +25,11 @@ import threading from BaseHTTPServer import BaseHTTPRequestHandler from SocketServer import TCPServer -import pylons import rhodecode - from rhodecode.model import meta +from rhodecode.lib.base import bootstrap_request from rhodecode.lib import hooks_base -from rhodecode.lib.utils2 import ( - AttributeDict, safe_str, get_routes_generator_for_server_url) +from rhodecode.lib.utils2 import AttributeDict log = logging.getLogger(__name__) @@ -188,29 +186,28 @@ class Hooks(object): """ def repo_size(self, extras): - log.debug("Called repo_size of Hooks object") + log.debug("Called repo_size of %s object", self) return self._call_hook(hooks_base.repo_size, extras) def pre_pull(self, extras): - log.debug("Called pre_pull of Hooks object") + log.debug("Called pre_pull of %s object", self) return self._call_hook(hooks_base.pre_pull, extras) def post_pull(self, extras): - log.debug("Called post_pull of Hooks object") + log.debug("Called post_pull of %s object", self) return self._call_hook(hooks_base.post_pull, extras) def pre_push(self, extras): - log.debug("Called pre_push of Hooks object") + log.debug("Called pre_push of %s object", self) return self._call_hook(hooks_base.pre_push, extras) def post_push(self, extras): - log.debug("Called post_push of Hooks object") + log.debug("Called post_push of %s object", self) return self._call_hook(hooks_base.post_push, extras) def _call_hook(self, hook, extras): extras = AttributeDict(extras) - pylons_router = get_routes_generator_for_server_url(extras.server_url) - pylons.url._push_object(pylons_router) + extras.request = bootstrap_request() try: result = hook(extras) @@ -226,7 +223,6 @@ class Hooks(object): 'exception_args': error_args, } finally: - pylons.url._pop_object() meta.Session.remove() return {