# HG changeset patch # User Marcin Kuzminski # Date 2013-03-24 02:07:04 # Node ID 238486bb71abf296b3588e82bccd03cb3226e4cf # Parent c177f304eb401cce9c7df118fa6abebefa257e1e Switched handling of RhodeCode extra params in consistent way - use only os.environ for both hg and git - hacking ui objects was bad - os.environ allows easier to call rhodecode hooks externally diff --git a/rhodecode/lib/hooks.py b/rhodecode/lib/hooks.py --- a/rhodecode/lib/hooks.py +++ b/rhodecode/lib/hooks.py @@ -26,6 +26,7 @@ import os import sys import time import binascii +import traceback from inspect import isfunction from mercurial.scmutil import revrange @@ -36,7 +37,7 @@ from rhodecode.lib.utils import action_l from rhodecode.lib.vcs.backends.base import EmptyChangeset from rhodecode.lib.compat import json from rhodecode.lib.exceptions import HTTPLockedRC -from rhodecode.lib.utils2 import safe_str +from rhodecode.lib.utils2 import safe_str, _extract_extras from rhodecode.model.db import Repository, User @@ -91,31 +92,14 @@ def repo_size(ui, repo, hooktype=None, * def pre_push(ui, repo, **kwargs): # pre push function, currently used to ban pushing when # repository is locked - try: - rc_extras = json.loads(os.environ.get('RC_SCM_DATA', "{}")) - except: - rc_extras = {} - extras = dict(repo.ui.configitems('rhodecode_extras')) + ex = _extract_extras() - if 'username' in extras: - username = extras['username'] - repository = extras['repository'] - scm = extras['scm'] - locked_by = extras['locked_by'] - elif 'username' in rc_extras: - username = rc_extras['username'] - repository = rc_extras['repository'] - scm = rc_extras['scm'] - locked_by = rc_extras['locked_by'] - else: - raise Exception('Missing data in repo.ui and os.environ') - - usr = User.get_by_username(username) - if locked_by[0] and usr.user_id != int(locked_by[0]): - locked_by = User.get(locked_by[0]).username + usr = User.get_by_username(ex.username) + if ex.locked_by[0] and usr.user_id != int(ex.locked_by[0]): + locked_by = User.get(ex.locked_by[0]).username # this exception is interpreted in git/hg middlewares and based # on that proper return code is server to client - _http_ret = HTTPLockedRC(repository, locked_by) + _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions sys.stdout.write(_http_ret.title) @@ -126,29 +110,12 @@ def pre_push(ui, repo, **kwargs): def pre_pull(ui, repo, **kwargs): # pre push function, currently used to ban pushing when # repository is locked - try: - rc_extras = json.loads(os.environ.get('RC_SCM_DATA', "{}")) - except: - rc_extras = {} - extras = dict(repo.ui.configitems('rhodecode_extras')) - if 'username' in extras: - username = extras['username'] - repository = extras['repository'] - scm = extras['scm'] - locked_by = extras['locked_by'] - elif 'username' in rc_extras: - username = rc_extras['username'] - repository = rc_extras['repository'] - scm = rc_extras['scm'] - locked_by = rc_extras['locked_by'] - else: - raise Exception('Missing data in repo.ui and os.environ') - - if locked_by[0]: - locked_by = User.get(locked_by[0]).username + ex = _extract_extras() + if ex.locked_by[0]: + locked_by = User.get(ex.locked_by[0]).username # this exception is interpreted in git/hg middlewares and based # on that proper return code is server to client - _http_ret = HTTPLockedRC(repository, locked_by) + _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions sys.stdout.write(_http_ret.title) @@ -163,47 +130,27 @@ def log_pull_action(ui, repo, **kwargs): :param ui: :param repo: """ - try: - rc_extras = json.loads(os.environ.get('RC_SCM_DATA', "{}")) - except: - rc_extras = {} - extras = dict(repo.ui.configitems('rhodecode_extras')) - if 'username' in extras: - username = extras['username'] - repository = extras['repository'] - scm = extras['scm'] - make_lock = extras['make_lock'] - locked_by = extras['locked_by'] - ip = extras['ip'] - elif 'username' in rc_extras: - username = rc_extras['username'] - repository = rc_extras['repository'] - scm = rc_extras['scm'] - make_lock = rc_extras['make_lock'] - locked_by = rc_extras['locked_by'] - ip = rc_extras['ip'] - else: - raise Exception('Missing data in repo.ui and os.environ') - user = User.get_by_username(username) + ex = _extract_extras() + + user = User.get_by_username(ex.username) action = 'pull' - action_logger(user, action, repository, ip, commit=True) + action_logger(user, action, ex.repository, ex.ip, commit=True) # extension hook call from rhodecode import EXTENSIONS callback = getattr(EXTENSIONS, 'PULL_HOOK', None) - if isfunction(callback): kw = {} - kw.update(extras) + kw.update(ex) callback(**kw) - if make_lock is True: - Repository.lock(Repository.get_by_repo_name(repository), user.user_id) + if ex.make_lock is True: + Repository.lock(Repository.get_by_repo_name(ex.repository), user.user_id) #msg = 'Made lock on repo `%s`' % repository #sys.stdout.write(msg) - if locked_by[0]: - locked_by = User.get(locked_by[0]).username - _http_ret = HTTPLockedRC(repository, locked_by) + if ex.locked_by[0]: + locked_by = User.get(ex.locked_by[0]).username + _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions sys.stdout.write(_http_ret.title) @@ -218,32 +165,11 @@ def log_push_action(ui, repo, **kwargs): :param repo: repo object containing the `ui` object """ - try: - rc_extras = json.loads(os.environ.get('RC_SCM_DATA', "{}")) - except: - rc_extras = {} + ex = _extract_extras() - extras = dict(repo.ui.configitems('rhodecode_extras')) - if 'username' in extras: - username = extras['username'] - repository = extras['repository'] - scm = extras['scm'] - make_lock = extras['make_lock'] - locked_by = extras['locked_by'] - action = extras['action'] - elif 'username' in rc_extras: - username = rc_extras['username'] - repository = rc_extras['repository'] - scm = rc_extras['scm'] - make_lock = rc_extras['make_lock'] - locked_by = rc_extras['locked_by'] - action = extras['action'] - else: - raise Exception('Missing data in repo.ui and os.environ') + action = ex.action + ':%s' - action = action + ':%s' - - if scm == 'hg': + if ex.scm == 'hg': node = kwargs['node'] def get_revs(repo, rev_opt): @@ -259,31 +185,31 @@ def log_push_action(ui, repo, **kwargs): stop, start = get_revs(repo, [node + ':']) h = binascii.hexlify revs = [h(repo[r].node()) for r in xrange(start, stop + 1)] - elif scm == 'git': + elif ex.scm == 'git': revs = kwargs.get('_git_revs', []) if '_git_revs' in kwargs: kwargs.pop('_git_revs') action = action % ','.join(revs) - action_logger(username, action, repository, extras['ip'], commit=True) + action_logger(ex.username, action, ex.repository, ex.ip, commit=True) # extension hook call from rhodecode import EXTENSIONS callback = getattr(EXTENSIONS, 'PUSH_HOOK', None) if isfunction(callback): kw = {'pushed_revs': revs} - kw.update(extras) + kw.update(ex) callback(**kw) - if make_lock is False: - Repository.unlock(Repository.get_by_repo_name(repository)) - msg = 'Released lock on repo `%s`\n' % repository + if ex.make_lock is False: + Repository.unlock(Repository.get_by_repo_name(ex.repository)) + msg = 'Released lock on repo `%s`\n' % ex.repository sys.stdout.write(msg) - if locked_by[0]: - locked_by = User.get(locked_by[0]).username - _http_ret = HTTPLockedRC(repository, locked_by) + if ex.locked_by[0]: + locked_by = User.get(ex.locked_by[0]).username + _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions sys.stdout.write(_http_ret.title) diff --git a/rhodecode/lib/middleware/pygrack.py b/rhodecode/lib/middleware/pygrack.py --- a/rhodecode/lib/middleware/pygrack.py +++ b/rhodecode/lib/middleware/pygrack.py @@ -121,8 +121,6 @@ class GitRepository(object): try: gitenv = os.environ - from rhodecode.lib.compat import json - gitenv['RHODECODE_EXTRAS'] = json.dumps(self.extras) # forget all configs gitenv['GIT_CONFIG_NOGLOBAL'] = '1' opts = dict( diff --git a/rhodecode/lib/middleware/simplegit.py b/rhodecode/lib/middleware/simplegit.py --- a/rhodecode/lib/middleware/simplegit.py +++ b/rhodecode/lib/middleware/simplegit.py @@ -79,7 +79,8 @@ from paste.httpheaders import REMOTE_USE from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \ HTTPBadRequest, HTTPNotAcceptable -from rhodecode.lib.utils2 import safe_str, fix_PATH, get_server_url +from rhodecode.lib.utils2 import safe_str, fix_PATH, get_server_url,\ + _set_extras from rhodecode.lib.base import BaseVCSController from rhodecode.lib.auth import get_container_username from rhodecode.lib.utils import is_valid_repo, make_ui @@ -333,10 +334,4 @@ class SimpleGit(BaseVCSController): :param extras: dict with extra params to put into baseui """ - # make our hgweb quiet so it doesn't print output - baseui.setconfig('ui', 'quiet', 'true') - - #inject some additional parameters that will be available in ui - #for hooks - for k, v in extras.items(): - baseui.setconfig('rhodecode_extras', k, v) + _set_extras(extras) diff --git a/rhodecode/lib/middleware/simplehg.py b/rhodecode/lib/middleware/simplehg.py --- a/rhodecode/lib/middleware/simplehg.py +++ b/rhodecode/lib/middleware/simplehg.py @@ -35,7 +35,8 @@ from paste.httpheaders import REMOTE_USE from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \ HTTPBadRequest, HTTPNotAcceptable -from rhodecode.lib.utils2 import safe_str, fix_PATH, get_server_url +from rhodecode.lib.utils2 import safe_str, fix_PATH, get_server_url,\ + _set_extras from rhodecode.lib.base import BaseVCSController from rhodecode.lib.auth import get_container_username from rhodecode.lib.utils import make_ui, is_valid_repo, ui_sections @@ -276,11 +277,6 @@ class SimpleHg(BaseVCSController): # make our hgweb quiet so it doesn't print output baseui.setconfig('ui', 'quiet', 'true') - #inject some additional parameters that will be available in ui - #for hooks - for k, v in extras.items(): - baseui.setconfig('rhodecode_extras', k, v) - repoui = make_ui('file', hgrc, False) if repoui: @@ -288,3 +284,4 @@ class SimpleHg(BaseVCSController): for section in ui_sections: for k, v in repoui.configitems(section): baseui.setconfig(section, k, v) + _set_extras(extras) diff --git a/rhodecode/lib/utils2.py b/rhodecode/lib/utils2.py --- a/rhodecode/lib/utils2.py +++ b/rhodecode/lib/utils2.py @@ -23,13 +23,17 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import os import re +import sys import time import datetime +import traceback import webob from pylons.i18n.translation import _, ungettext from rhodecode.lib.vcs.utils.lazy import LazyProperty +from rhodecode.lib.compat import json def __get_lem(): @@ -552,7 +556,6 @@ def fix_PATH(os_=None): Get current active python path, and append it to PATH variable to fix issues of subprocess calls and different python versions """ - import sys if os_ is None: import os else: @@ -578,3 +581,29 @@ def obfuscate_url_pw(engine): def get_server_url(environ): req = webob.Request(environ) return req.host_url + req.script_name + + +def _extract_extras(): + """ + Extracts the rc extras data from os.environ, and wraps it into named + AttributeDict object + """ + try: + rc_extras = json.loads(os.environ['RC_SCM_DATA']) + except: + print os.environ + print >> sys.stderr, traceback.format_exc() + rc_extras = {} + + try: + for k in ['username', 'repository', 'locked_by', 'scm', 'make_lock', + 'action', 'ip']: + rc_extras[k] + except KeyError, e: + raise Exception('Missing key %s in os.environ %s' % (e, rc_extras)) + + return AttributeDict(rc_extras) + + +def _set_extras(extras): + os.environ['RC_SCM_DATA'] = json.dumps(extras) diff --git a/rhodecode/lib/vcs/backends/base.py b/rhodecode/lib/vcs/backends/base.py --- a/rhodecode/lib/vcs/backends/base.py +++ b/rhodecode/lib/vcs/backends/base.py @@ -311,27 +311,6 @@ class BaseRepository(object): """ raise NotImplementedError - def inject_ui(self, **extras): - """ - Injects extra parameters into UI object of this repo - """ - required_extras = [ - 'ip', - 'username', - 'action', - 'repository', - 'scm', - 'config', - 'server_url', - 'make_lock', - 'locked_by', - ] - for req in required_extras: - if req not in extras: - raise AttributeError('Missing attribute %s in extras' % (req)) - for k, v in extras.items(): - self._repo.ui.setconfig('rhodecode_extras', k, v) - class BaseChangeset(object): """ diff --git a/rhodecode/lib/vcs/backends/git/repository.py b/rhodecode/lib/vcs/backends/git/repository.py --- a/rhodecode/lib/vcs/backends/git/repository.py +++ b/rhodecode/lib/vcs/backends/git/repository.py @@ -66,14 +66,7 @@ class GitRepository(BaseRepository): @ThreadLocalLazyProperty def _repo(self): - repo = Repo(self.path) - # patch the instance of GitRepo with an "FAKE" ui object to add - # compatibility layer with Mercurial - if not hasattr(repo, 'ui'): - from mercurial.ui import ui - baseui = ui() - setattr(repo, 'ui', baseui) - return repo + return Repo(self.path) @property def head(self): diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -47,7 +47,7 @@ from rhodecode.lib.vcs.utils.lazy import from rhodecode.lib.vcs.backends.base import EmptyChangeset from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ - safe_unicode, remove_suffix, remove_prefix, time_to_datetime + safe_unicode, remove_suffix, remove_prefix, time_to_datetime, _set_extras from rhodecode.lib.compat import json from rhodecode.lib.caching_query import FromCache @@ -937,10 +937,6 @@ class Repository(Base, BaseModel): return make_ui('db', clear_session=False) @classmethod - def inject_ui(cls, repo, extras={}): - repo.inject_ui(extras) - - @classmethod def is_valid(cls, repo_name): """ returns True if given repo name is a valid filesystem repository diff --git a/rhodecode/model/scm.py b/rhodecode/model/scm.py --- a/rhodecode/model/scm.py +++ b/rhodecode/model/scm.py @@ -44,7 +44,8 @@ from rhodecode.lib.vcs.backends.base imp from rhodecode import BACKENDS from rhodecode.lib import helpers as h -from rhodecode.lib.utils2 import safe_str, safe_unicode, get_server_url +from rhodecode.lib.utils2 import safe_str, safe_unicode, get_server_url,\ + _set_extras from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny from rhodecode.lib.utils import get_filesystem_repos, make_ui, \ action_logger, REMOVED_REPO_PAT @@ -437,7 +438,7 @@ class ScmModel(BaseModel): 'locked_by': [None, None] } _scm_repo = repo._repo - repo.inject_ui(**extras) + _set_extras(extras) if repo.alias == 'hg': log_push_action(_scm_repo.ui, _scm_repo, node=revisions[0]) elif repo.alias == 'git':