changeset 3577:238486bb71ab beta

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
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 24 Mar 2013 03:07:04 +0100
parents c177f304eb40
children f3283898d431
files rhodecode/lib/hooks.py rhodecode/lib/middleware/pygrack.py rhodecode/lib/middleware/simplegit.py rhodecode/lib/middleware/simplehg.py rhodecode/lib/utils2.py rhodecode/lib/vcs/backends/base.py rhodecode/lib/vcs/backends/git/repository.py rhodecode/model/db.py rhodecode/model/scm.py
diffstat 9 files changed, 74 insertions(+), 160 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/lib/hooks.py	Thu Mar 21 11:26:58 2013 +0100
+++ b/rhodecode/lib/hooks.py	Sun Mar 24 03:07:04 2013 +0100
@@ -26,6 +26,7 @@
 import sys
 import time
 import binascii
+import traceback
 from inspect import isfunction
 
 from mercurial.scmutil import revrange
@@ -36,7 +37,7 @@
 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 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_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 @@
     :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 @@
     :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 @@
         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)
--- a/rhodecode/lib/middleware/pygrack.py	Thu Mar 21 11:26:58 2013 +0100
+++ b/rhodecode/lib/middleware/pygrack.py	Sun Mar 24 03:07:04 2013 +0100
@@ -121,8 +121,6 @@
 
         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(
--- a/rhodecode/lib/middleware/simplegit.py	Thu Mar 21 11:26:58 2013 +0100
+++ b/rhodecode/lib/middleware/simplegit.py	Sun Mar 24 03:07:04 2013 +0100
@@ -79,7 +79,8 @@
 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 @@
         :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)
--- a/rhodecode/lib/middleware/simplehg.py	Thu Mar 21 11:26:58 2013 +0100
+++ b/rhodecode/lib/middleware/simplehg.py	Sun Mar 24 03:07:04 2013 +0100
@@ -35,7 +35,8 @@
 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 @@
         # 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 @@
             for section in ui_sections:
                 for k, v in repoui.configitems(section):
                     baseui.setconfig(section, k, v)
+        _set_extras(extras)
--- a/rhodecode/lib/utils2.py	Thu Mar 21 11:26:58 2013 +0100
+++ b/rhodecode/lib/utils2.py	Sun Mar 24 03:07:04 2013 +0100
@@ -23,13 +23,17 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+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 @@
     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 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)
--- a/rhodecode/lib/vcs/backends/base.py	Thu Mar 21 11:26:58 2013 +0100
+++ b/rhodecode/lib/vcs/backends/base.py	Sun Mar 24 03:07:04 2013 +0100
@@ -311,27 +311,6 @@
         """
         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):
     """
--- a/rhodecode/lib/vcs/backends/git/repository.py	Thu Mar 21 11:26:58 2013 +0100
+++ b/rhodecode/lib/vcs/backends/git/repository.py	Sun Mar 24 03:07:04 2013 +0100
@@ -66,14 +66,7 @@
 
     @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):
--- a/rhodecode/model/db.py	Thu Mar 21 11:26:58 2013 +0100
+++ b/rhodecode/model/db.py	Sun Mar 24 03:07:04 2013 +0100
@@ -47,7 +47,7 @@
 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 @@
         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
--- a/rhodecode/model/scm.py	Thu Mar 21 11:26:58 2013 +0100
+++ b/rhodecode/model/scm.py	Sun Mar 24 03:07:04 2013 +0100
@@ -44,7 +44,8 @@
 
 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 @@
             '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':