changeset 2105:926f55b038bc beta

added initial rc-extension module - possible to store additional mappings for stats - possible to overwrite and add to whoosh index extensions issue #322 - post create repo hook callback - post push/pull hooks callback
author Marcin Kuzminski <marcin@python-works.com>
date Tue, 06 Mar 2012 23:03:10 +0200
parents f21f66abb4f7
children 95f1ed68cac1
files docs/changelog.rst docs/setup.rst docs/usage/general.rst rhodecode/__init__.py rhodecode/config/environment.py rhodecode/config/rcextensions/__init__.py rhodecode/config/rcextensions/make_rcextensions.py rhodecode/lib/__init__.py rhodecode/lib/auth.py rhodecode/lib/hooks.py rhodecode/lib/indexers/__init__.py setup.py
diffstat 12 files changed, 247 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/docs/changelog.rst	Mon Mar 05 16:58:55 2012 +0200
+++ b/docs/changelog.rst	Tue Mar 06 23:03:10 2012 +0200
@@ -17,6 +17,8 @@
 - Whoosh logging is now controlled by the .ini files logging setup
 - added clone-url into edit form on /settings page
 - added help text into repo add/edit forms
+- created rcextensions module with additional mappings (ref #322) and
+  post push/pull/create repo hooks callbacks
 
 fixes
 +++++
--- a/docs/setup.rst	Mon Mar 05 16:58:55 2012 +0200
+++ b/docs/setup.rst	Tue Mar 06 23:03:10 2012 +0200
@@ -20,9 +20,10 @@
 
 
 Next, you need to create the databases used by RhodeCode. I recommend that you
-use sqlite (default) or postgresql. If you choose a database other than the
+use postgresql or sqlite (default). If you choose a database other than the
 default ensure you properly adjust the db url in your production.ini
-configuration file to use this other database. Create the databases by running
+configuration file to use this other database. RhodeCode currently supports
+postgresql, sqlite and mysql databases. Create the database by running
 the following command::
 
     paster setup-app production.ini
@@ -57,15 +58,18 @@
 - In the admin panel you can toggle ldap, anonymous, permissions settings. As
   well as edit more advanced options on users and repositories
 
-Try copying your own mercurial repository into the "root" directory you are
-using, then from within the RhodeCode web application choose Admin >
-repositories. Then choose Add New Repository. Add the repository you copied 
-into the root. Test that you can browse your repository from within RhodeCode 
-and then try cloning your repository from RhodeCode with::
+Optionally users can create `rcextensions` package that extends RhodeCode
+functionality. To do this simply execute::
+
+    paster make-rcext production.ini
 
-    hg clone http://127.0.0.1:5000/<repository name>
+This will create `rcextensions` package in the same place that your `ini` file
+lives. With `rcextensions` it's possible to add additional mapping for whoosh, 
+stats and add additional code into the push/pull/create repo hooks. For example
+for sending signals to build-bots such as jenkins.
+Please see the `__init__.py` file inside `rcextensions` package 
+for more details.
 
-where *repository name* is replaced by the name of your repository.
 
 Using RhodeCode with SSH
 ------------------------
--- a/docs/usage/general.rst	Mon Mar 05 16:58:55 2012 +0200
+++ b/docs/usage/general.rst	Tue Mar 06 23:03:10 2012 +0200
@@ -71,6 +71,11 @@
 on errors the mails will have a detailed traceback of error.
 
 
+Mails are also sent for code comments. If someone comments on a changeset
+mail is sent to all participants, the person who commited the changeset 
+(if present in RhodeCode), and to all people mentioned with @mention system.
+
+
 Trending source files
 ---------------------
 
--- a/rhodecode/__init__.py	Mon Mar 05 16:58:55 2012 +0200
+++ b/rhodecode/__init__.py	Tue Mar 06 23:03:10 2012 +0200
@@ -90,3 +90,6 @@
 
 # link to config for pylons
 CONFIG = {}
+
+# Linked module for extensions
+EXTENSIONS = {}
--- a/rhodecode/config/environment.py	Mon Mar 05 16:58:55 2012 +0200
+++ b/rhodecode/config/environment.py	Tue Mar 06 23:03:10 2012 +0200
@@ -19,6 +19,7 @@
 from rhodecode.lib.utils import repo2db_mapper, make_ui, set_rhodecode_config
 from rhodecode.model import init_model
 from rhodecode.model.scm import ScmModel
+from rhodecode.lib.vcs.utils.fakemod import create_module
 
 log = logging.getLogger(__name__)
 
@@ -46,6 +47,11 @@
     config['pylons.app_globals'] = app_globals.Globals(config)
     config['pylons.h'] = rhodecode.lib.helpers
     rhodecode.CONFIG = config
+
+    path = os.path.join(config['here'], 'rcextensions', '__init__.py')
+    if os.path.isfile(path):
+        rcext = create_module('rc', path)
+        rhodecode.EXTENSIONS = rcext
     # Setup cache object as early as possible
     import pylons
     pylons.cache._push_object(config['pylons.app_globals'].cache)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/config/rcextensions/__init__.py	Tue Mar 06 23:03:10 2012 +0200
@@ -0,0 +1,84 @@
+# Additional mappings that are not present in the pygments lexers
+# used for building stats
+# format is {'ext':'Name'} eg. {'py':'Python'}
+# NOTE: that this will overide any mappings in LANGUAGES_EXTENSIONS_MAP
+# build by pygments
+EXTRA_MAPPINGS = {}
+
+#==============================================================================
+# WHOOSH INDEX EXTENSIONS
+#==============================================================================
+# if INDEX_EXTENSIONS is [] it'll use pygments lexers extensions by default.
+# To set your own just add to this list extensions to index with content
+INDEX_EXTENSIONS = []
+
+# additional extensions for indexing besides the default from pygments
+# those get's added to INDEX_EXTENSIONS
+EXTRA_INDEX_EXTENSIONS = []
+
+
+#==============================================================================
+# POST CREATE REPOSITORY HOOK
+#==============================================================================
+# this function will be executed after each repository is created
+def _crhook(*args, **kwargs):
+    """
+    Post create repository HOOK
+    kwargs available:
+     :param repo_name:
+     :param repo_type:
+     :param description:
+     :param private:
+     :param created_on:
+     :param enable_downloads:
+     :param repo_id:
+     :param user_id:
+     :param enable_statistics:
+     :param clone_uri:
+     :param fork_id:
+     :param group_id:
+     :param created_by:
+    """
+    return 0
+CREATE_REPO_HOOK = _crhook
+
+
+#==============================================================================
+# POST PUSH HOOK
+#==============================================================================
+
+# this function will be executed after each push it's runned after the build-in
+# hook that rhodecode uses for logging pushes
+def _pushhook(*args, **kwargs):
+    """
+    Post push hook
+    kwargs available:
+
+      :param username: name of user who pushed
+      :param ip: ip of who pushed
+      :param action: pull
+      :param repository: repository name
+      :param pushed_revs: generator of pushed revisions
+    """
+    return 0
+PUSH_HOOK = _pushhook
+
+
+#==============================================================================
+# POST PULL HOOK
+#==============================================================================
+
+# this function will be executed after each push it's runned after the build-in
+# hook that rhodecode uses for logging pushes
+def _pullhook(*args, **kwargs):
+    """
+    Post pull hook
+    kwargs available::
+
+      :param username: name of user who pulled
+      :param ip: ip of who pushed
+      :param action: pull
+      :param repository: repository name
+    """
+    return 0
+PULL_HOOK = _pullhook
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/config/rcextensions/make_rcextensions.py	Tue Mar 06 23:03:10 2012 +0200
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.config.rcextensions.make_rcextensions
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Whoosh indexing module for RhodeCode
+
+    :created_on: Mar 6, 2012
+    :author: marcink
+    :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
+# 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, see <http://www.gnu.org/licenses/>.
+import os
+import sys
+import pkg_resources
+import traceback
+import logging
+from os.path import dirname as dn, join as jn
+
+#to get the rhodecode import
+sys.path.append(dn(dn(dn(os.path.realpath(__file__)))))
+
+from rhodecode.lib.utils import BasePasterCommand, Command, ask_ok
+
+log = logging.getLogger(__name__)
+
+
+class MakeRcExt(BasePasterCommand):
+
+    max_args = 1
+    min_args = 1
+
+    usage = "CONFIG_FILE"
+    summary = "Creates additional extensions for rhodecode"
+    group_name = "RhodeCode"
+    takes_config_file = -1
+    parser = Command.standard_parser(verbose=True)
+
+    def command(self):
+        logging.config.fileConfig(self.path_to_ini_file)
+        from pylons import config
+
+        def _make_file(ext_file):
+            bdir = os.path.split(ext_file)[0]
+            if not os.path.isdir(bdir):
+                os.makedirs(bdir)
+            with open(ext_file, 'wb') as f:
+                f.write(tmpl)
+                log.info('Writen new extensions file to %s' % ext_file)
+
+        here = config['here']
+        tmpl = pkg_resources.resource_string(
+            'rhodecode', jn('config', 'rcextensions', '__init__.py')
+        )
+        ext_file = jn(here, 'rcextensions', '__init__.py')
+        if os.path.exists(ext_file):
+            msg = ('Extension file already exists, do you want '
+                   'to overwrite it ? [y/n]')
+            if ask_ok(msg):
+                _make_file(ext_file)
+            else:
+                log.info('nothing done...')
+        else:
+            _make_file(ext_file)
+
+    def update_parser(self):
+        pass
+
+
--- a/rhodecode/lib/__init__.py	Mon Mar 05 16:58:55 2012 +0200
+++ b/rhodecode/lib/__init__.py	Tue Mar 06 23:03:10 2012 +0200
@@ -25,6 +25,7 @@
 
 import os
 import re
+from rhodecode import EXTENSIONS
 from rhodecode.lib.vcs.utils.lazy import LazyProperty
 
 
@@ -64,10 +65,21 @@
 LANGUAGES_EXTENSIONS_MAP = __get_lem()
 
 # Additional mappings that are not present in the pygments lexers
-# NOTE: that this will overide any mappings in LANGUAGES_EXTENSIONS_MAP
-ADDITIONAL_MAPPINGS = {'xaml': 'XAML'}
+LANGUAGES_EXTENSIONS_MAP.update(getattr(EXTENSIONS, 'EXTRA_MAPPINGS', {}))
+
+#==============================================================================
+# WHOOSH INDEX EXTENSIONS
+#==============================================================================
+# EXTENSIONS WE WANT TO INDEX CONTENT OFF USING WHOOSH
+INDEX_EXTENSIONS = LANGUAGES_EXTENSIONS_MAP.keys()
 
-LANGUAGES_EXTENSIONS_MAP.update(ADDITIONAL_MAPPINGS)
+#OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
+
+if getattr(EXTENSIONS, 'INDEX_EXTENSIONS', []) != []:
+    INDEX_EXTENSIONS = getattr(EXTENSIONS, 'INDEX_EXTENSIONS', [])
+
+#ADDITIONAL MAPPINGS
+INDEX_EXTENSIONS.extend(getattr(EXTENSIONS, 'EXTRA_INDEX_EXTENSIONS', []))
 
 # list of readme files to search in file tree and display in summary
 # attached weights defines the search  order lower is first
--- a/rhodecode/lib/auth.py	Mon Mar 05 16:58:55 2012 +0200
+++ b/rhodecode/lib/auth.py	Tue Mar 06 23:03:10 2012 +0200
@@ -655,7 +655,7 @@
 
         for perm in perms:
             if perm not in available_perms:
-                raise Exception("'%s' permission in not defined" % perm)
+                raise Exception("'%s' permission is not defined" % perm)
         self.required_perms = set(perms)
         self.user_perms = None
         self.granted_for = ''
--- a/rhodecode/lib/hooks.py	Mon Mar 05 16:58:55 2012 +0200
+++ b/rhodecode/lib/hooks.py	Tue Mar 06 23:03:10 2012 +0200
@@ -27,9 +27,10 @@
 
 from mercurial.scmutil import revrange
 from mercurial.node import nullrev
-
+from rhodecode import EXTENSIONS
 from rhodecode.lib import helpers as h
 from rhodecode.lib.utils import action_logger
+from inspect import isfunction
 
 
 def repo_size(ui, repo, hooktype=None, **kwargs):
@@ -78,14 +79,19 @@
     :param repo:
     """
 
-    extra_params = dict(repo.ui.configitems('rhodecode_extras'))
-    username = extra_params['username']
-    repository = extra_params['repository']
+    extras = dict(repo.ui.configitems('rhodecode_extras'))
+    username = extras['username']
+    repository = extras['repository']
     action = 'pull'
 
-    action_logger(username, action, repository, extra_params['ip'],
-                  commit=True)
+    action_logger(username, action, repository, extras['ip'], commit=True)
+    # extension hook call
+    callback = getattr(EXTENSIONS, 'PULL_HOOK', None)
 
+    if isfunction(callback):
+        kw = {}
+        kw.update(extras)
+        callback(**kw)
     return 0
 
 
@@ -97,10 +103,10 @@
     :param repo:
     """
 
-    extra_params = dict(repo.ui.configitems('rhodecode_extras'))
-    username = extra_params['username']
-    repository = extra_params['repository']
-    action = extra_params['action'] + ':%s'
+    extras = dict(repo.ui.configitems('rhodecode_extras'))
+    username = extras['username']
+    repository = extras['repository']
+    action = extras['action'] + ':%s'
     node = kwargs['node']
 
     def get_revs(repo, rev_opt):
@@ -119,16 +125,22 @@
 
     action = action % ','.join(revs)
 
-    action_logger(username, action, repository, extra_params['ip'],
-                  commit=True)
+    action_logger(username, action, repository, extras['ip'], commit=True)
 
+    # extension hook call
+    callback = getattr(EXTENSIONS, 'PUSH_HOOK', None)
+    if isfunction(callback):
+        kw = {'pushed_revs': revs}
+        kw.update(extras)
+        callback(**kw)
     return 0
 
 
 def log_create_repository(repository_dict, created_by, **kwargs):
     """
     Post create repository Hook. This is a dummy function for admins to re-use
-    if needed
+    if needed. It's taken from rhodecode-extensions module and executed 
+    if present
 
     :param repository: dict dump of repository object
     :param created_by: username who created repository
@@ -151,5 +163,12 @@
 
     """
 
+    callback = getattr(EXTENSIONS, 'CREATE_REPO_HOOK', None)
+    if isfunction(callback):
+        kw = {}
+        kw.update(repository_dict)
+        kw.update({'created_by': created_by})
+        kw.update(kwargs)
+        return callback(**kw)
 
     return 0
--- a/rhodecode/lib/indexers/__init__.py	Mon Mar 05 16:58:55 2012 +0200
+++ b/rhodecode/lib/indexers/__init__.py	Tue Mar 06 23:03:10 2012 +0200
@@ -47,12 +47,10 @@
 from rhodecode.model.scm import ScmModel
 from rhodecode.model.repo import RepoModel
 from rhodecode.config.environment import load_environment
-from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP, LazyProperty
+from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP, INDEX_EXTENSIONS, \
+    LazyProperty
 from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
 
-# EXTENSIONS WE WANT TO INDEX CONTENT OFF
-INDEX_EXTENSIONS = LANGUAGES_EXTENSIONS_MAP.keys()
-
 # CUSTOM ANALYZER wordsplit + lowercase filter
 ANALYZER = RegexTokenizer(expression=r"\w+") | LowercaseFilter()
 
--- a/setup.py	Mon Mar 05 16:58:55 2012 +0200
+++ b/setup.py	Tue Mar 06 23:03:10 2012 +0200
@@ -94,8 +94,9 @@
     main = pylons.util:PylonsInstaller
 
     [paste.global_paster_command]
-    make-index = rhodecode.lib.indexers:MakeIndex
-    upgrade-db = rhodecode.lib.dbmigrate:UpgradeDb
+    make-index=rhodecode.lib.indexers:MakeIndex
+    make-rcext=rhodecode.config.rcextensions.make_rcextensions:MakeRcExt
+    upgrade-db=rhodecode.lib.dbmigrate:UpgradeDb
     celeryd=rhodecode.lib.celerypylons.commands:CeleryDaemonCommand
     """,
 )