Changeset - 01be209b9828
[Not reviewed]
beta
0 5 0
Marcin Kuzminski - 15 years ago 2010-11-25 01:57:37
marcin@python-works.com
project refactoring, cleaned up lib.utils from rarly used functions, and place them
in proper controllers
moves is_git is_hg functions to the middleware classes
5 files changed with 79 insertions and 103 deletions:
0 comments (0 inline, 0 general)
rhodecode/controllers/admin/settings.py
Show inline comments
 
@@ -24,25 +24,25 @@ settings controller for pylons
 
"""
 
from formencode import htmlfill
 
from pylons import request, session, tmpl_context as c, url, app_globals as g, \
 
    config
 
from pylons.controllers.util import abort, redirect
 
from pylons.i18n.translation import _
 
from rhodecode.lib import helpers as h
 
from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
 
    HasPermissionAnyDecorator
 
from rhodecode.lib.base import BaseController, render
 
from rhodecode.lib.celerylib import tasks, run_task
 
from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
 
    set_rhodecode_config, get_hg_settings, get_hg_ui_settings
 
    set_rhodecode_config
 
from rhodecode.model.db import RhodeCodeUi, Repository
 
from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
 
    ApplicationUiSettingsForm
 
from rhodecode.model.scm import ScmModel
 
from rhodecode.model.settings import SettingsModel
 
from rhodecode.model.user import UserModel
 
from sqlalchemy import func
 
import formencode
 
import logging
 
import traceback
 

	
 
log = logging.getLogger(__name__)
 
@@ -59,26 +59,26 @@ class SettingsController(BaseController)
 
    @LoginRequired()
 
    def __before__(self):
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        super(SettingsController, self).__before__()
 

	
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def index(self, format='html'):
 
        """GET /admin/settings: All items in the collection"""
 
        # url('admin_settings')
 

	
 
        defaults = get_hg_settings()
 
        defaults.update(get_hg_ui_settings())
 
        defaults = SettingsModel().get_app_settings()
 
        defaults.update(self.get_hg_ui_settings())
 
        return htmlfill.render(
 
            render('admin/settings/settings.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def create(self):
 
        """POST /admin/settings: Create a new item"""
 
        # url('admin_settings')
 

	
 
@@ -100,25 +100,25 @@ class SettingsController(BaseController)
 
            rm_obsolete = request.POST.get('destroy', False)
 
            log.debug('Rescanning directories with destroy=%s', rm_obsolete)
 

	
 
            initial = ScmModel().repo_scan(g.paths[0][1], g.baseui)
 
            for repo_name in initial.keys():
 
                invalidate_cache('get_repo_cached_%s' % repo_name)
 

	
 
            repo2db_mapper(initial, rm_obsolete)
 

	
 
            h.flash(_('Repositories successfully rescanned'), category='success')
 

	
 
        if setting_id == 'whoosh':
 
            repo_location = get_hg_ui_settings()['paths_root_path']
 
            repo_location = self.get_hg_ui_settings()['paths_root_path']
 
            full_index = request.POST.get('full_index', False)
 
            task = run_task(tasks.whoosh_index, repo_location, full_index)
 

	
 
            h.flash(_('Whoosh reindex task scheduled'), category='success')
 
        if setting_id == 'global':
 

	
 
            application_form = ApplicationSettingsForm()()
 
            try:
 
                form_result = application_form.to_python(dict(request.POST))
 
                settings_model = SettingsModel()
 
                try:
 
                    hgsettings1 = settings_model.get('title')
 
@@ -303,12 +303,33 @@ class SettingsController(BaseController)
 
                    % form_result.get('username'), category='error')
 

	
 
        return redirect(url('my_account'))
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
 
    def create_repository(self):
 
        """GET /_admin/create_repository: Form to create a new item"""
 
        new_repo = request.GET.get('repo', '')
 
        c.new_repo = h.repo_name_slug(new_repo)
 

	
 
        return render('admin/repos/repo_add_create_repository.html')
 

	
 
    def get_hg_ui_settings(self):
 
        ret = self.sa.query(RhodeCodeUi).all()
 

	
 
        if not ret:
 
            raise Exception('Could not get application ui settings !')
 
        settings = {}
 
        for each in ret:
 
            k = each.ui_key
 
            v = each.ui_value
 
            if k == '/':
 
                k = 'root_path'
 

	
 
            if k.find('.') != -1:
 
                k = k.replace('.', '_')
 

	
 
            if each.ui_section == 'hooks':
 
                v = each.ui_active
 

	
 
            settings[each.ui_section + '_' + k] = v
 

	
 
        return settings
rhodecode/lib/middleware/simplegit.py
Show inline comments
 
@@ -54,33 +54,45 @@ class SimpleGitUploadPackHandler(dulserv
 
        self.proto.write("0000")
 

	
 
dulserver.DEFAULT_HANDLERS = {
 
  'git-upload-pack': SimpleGitUploadPackHandler,
 
  'git-receive-pack': dulserver.ReceivePackHandler,
 
}
 

	
 
from dulwich.repo import Repo
 
from dulwich.web import HTTPGitApplication
 
from paste.auth.basic import AuthBasicAuthenticator
 
from paste.httpheaders import REMOTE_USER, AUTH_TYPE
 
from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware
 
from rhodecode.lib.utils import is_git, invalidate_cache, check_repo_fast
 
from rhodecode.lib.utils import invalidate_cache, check_repo_fast
 
from rhodecode.model.user import UserModel
 
from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
 
import logging
 
import os
 
import traceback
 

	
 
log = logging.getLogger(__name__)
 

	
 
def is_git(environ):
 
    """
 
    Returns True if request's target is git server. ``HTTP_USER_AGENT`` would
 
    then have git client version given.
 
    
 
    :param environ:
 
    """
 
    http_user_agent = environ.get('HTTP_USER_AGENT')
 
    if http_user_agent and http_user_agent.startswith('git'):
 
        return True
 
    return False
 

	
 
class SimpleGit(object):
 

	
 
    def __init__(self, application, config):
 
        self.application = application
 
        self.config = config
 
        #authenticate this git request using 
 
        self.authenticate = AuthBasicAuthenticator('', authfunc)
 
        self.ipaddr = '0.0.0.0'
 
        self.repository = None
 
        self.username = None
 
        self.action = None
 

	
rhodecode/lib/middleware/simplehg.py
Show inline comments
 
@@ -15,41 +15,50 @@
 
# 
 
# 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.
 
"""
 
Created on 2010-04-28
 

	
 
@author: marcink
 
SimpleHG middleware for handling mercurial protocol request (push/clone etc.)
 
It's implemented with basic auth function
 
"""
 
from itertools import chain
 
from mercurial.error import RepoError
 
from mercurial.hgweb import hgweb
 
from mercurial.hgweb.request import wsgiapplication
 
from paste.auth.basic import AuthBasicAuthenticator
 
from paste.httpheaders import REMOTE_USER, AUTH_TYPE
 
from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware
 
from rhodecode.lib.utils import is_mercurial, make_ui, invalidate_cache, \
 
from rhodecode.lib.utils import make_ui, invalidate_cache, \
 
    check_repo_fast, ui_sections
 
from rhodecode.model.user import UserModel
 
from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
 
import logging
 
import os
 
import traceback
 

	
 
log = logging.getLogger(__name__)
 

	
 
def is_mercurial(environ):
 
    """
 
    Returns True if request's target is mercurial server - header
 
    ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
 
    """
 
    http_accept = environ.get('HTTP_ACCEPT')
 
    if http_accept and http_accept.startswith('application/mercurial'):
 
        return True
 
    return False
 

	
 
class SimpleHg(object):
 

	
 
    def __init__(self, application, config):
 
        self.application = application
 
        self.config = config
 
        #authenticate this mercurial request using authfunc
 
        self.authenticate = AuthBasicAuthenticator('', authfunc)
 
        self.ipaddr = '0.0.0.0'
 
        self.repository = None
 
        self.username = None
 
        self.action = None
 

	
 
@@ -134,25 +143,25 @@ class SimpleHg(object):
 
        try:
 
            app = wsgiapplication(self.__make_app)
 
        except RepoError, e:
 
            if str(e).find('not found') != -1:
 
                return HTTPNotFound()(environ, start_response)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            return HTTPInternalServerError()(environ, start_response)
 

	
 
        #invalidate cache on push
 
        if self.action == 'push':
 
            self.__invalidate_cache(repo_name)
 
        
 

	
 
        return app(environ, start_response)
 

	
 

	
 
    def __make_app(self):
 
        hgserve = hgweb(str(self.repo_path), baseui=self.baseui)
 
        return  self.__load_web_settings(hgserve, self.extras)
 

	
 
    def __get_environ_user(self, environ):
 
        return environ.get('REMOTE_USER')
 

	
 
    def __get_user(self, username):
 
        return UserModel().get_by_username(username, cache=True)
rhodecode/lib/utils.py
Show inline comments
 
@@ -18,65 +18,43 @@
 
# MA  02110-1301, USA.
 
"""
 
Created on April 18, 2010
 
Utilities for RhodeCode
 
@author: marcink
 
"""
 

	
 
from UserDict import DictMixin
 
from mercurial import ui, config, hg
 
from mercurial.error import RepoError
 
from rhodecode.model import meta
 
from rhodecode.model.caching_query import FromCache
 
from rhodecode.model.db import Repository, User, RhodeCodeUi, RhodeCodeSettings, \
 
    UserLog
 
from rhodecode.model.db import Repository, User, RhodeCodeUi, UserLog
 
from rhodecode.model.repo import RepoModel
 
from rhodecode.model.user import UserModel
 

	
 
from vcs.backends.base import BaseChangeset
 
from paste.script import command
 
import ConfigParser
 
from vcs.utils.lazy import LazyProperty
 
import traceback
 
import datetime
 
import logging
 
import os
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def get_repo_slug(request):
 
    return request.environ['pylons.routes_dict'].get('repo_name')
 

	
 
def is_mercurial(environ):
 
    """
 
    Returns True if request's target is mercurial server - header
 
    ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
 
    """
 
    http_accept = environ.get('HTTP_ACCEPT')
 
    if http_accept and http_accept.startswith('application/mercurial'):
 
        return True
 
    return False
 

	
 
def is_git(environ):
 
    """
 
    Returns True if request's target is git server. ``HTTP_USER_AGENT`` would
 
    then have git client version given.
 
    
 
    :param environ:
 
    """
 
    http_user_agent = environ.get('HTTP_USER_AGENT')
 
    if http_user_agent and http_user_agent.startswith('git'):
 
        return True
 
    return False
 

	
 
def action_logger(user, action, repo, ipaddr='', sa=None):
 
    """
 
    Action logger for various actions made by users
 
    
 
    :param user: user that made this action, can be a unique username string or
 
        object containing user_id attribute
 
    :param action: action to log, should be on of predefined unique actions for
 
        easy translations
 
    :param repo: string name of repository or object containing repo_id,
 
        that action was made on
 
    :param ipaddr: optional ip address from what the action was made
 
    :param sa: optional sqlalchemy session
 
@@ -101,35 +79,34 @@ def action_logger(user, action, repo, ip
 
            repo_obj = rm.get(repo.repo_id, cache=False)
 
            repo_name = repo_obj.repo_name
 
        elif  isinstance(repo, basestring):
 
            repo_name = repo.lstrip('/')
 
            repo_obj = rm.get_by_repo_name(repo_name, cache=False)
 
        else:
 
            raise Exception('You have to provide repository to action logger')
 

	
 

	
 
        user_log = UserLog()
 
        user_log.user_id = user_obj.user_id
 
        user_log.action = action
 
        
 

	
 
        user_log.repository_id = repo_obj.repo_id
 
        user_log.repository_name = repo_name
 
        
 

	
 
        user_log.action_date = datetime.datetime.now()
 
        user_log.user_ip = ipaddr
 
        sa.add(user_log)
 
        sa.commit()
 

	
 
        log.info('Adding user %s, action %s on %s',
 
                                        user_obj.username, action, repo)
 
        log.info('Adding user %s, action %s on %s', user_obj, action, repo)
 
    except:
 
        log.error(traceback.format_exc())
 
        sa.rollback()
 

	
 
def get_repos(path, recursive=False, initial=False):
 
    """
 
    Scans given path for repos and return (name,(type,path)) tuple 
 
    :param prefix:
 
    :param path:
 
    :param recursive:
 
    :param initial:
 
    """
 
@@ -141,28 +118,24 @@ def get_repos(path, recursive=False, ini
 
    except:
 
        pass
 
    else:
 
        raise Exception('The given path %s should not be a repository got %s',
 
                        path, scm)
 

	
 
    for dirpath in os.listdir(path):
 
        try:
 
            yield dirpath, get_scm(os.path.join(path, dirpath))
 
        except VCSError:
 
            pass
 

	
 
if __name__ == '__main__':
 
    get_repos('', '/home/marcink/workspace-python')
 

	
 

	
 
def check_repo_fast(repo_name, base_path):
 
    if os.path.isdir(os.path.join(base_path, repo_name)):return False
 
    return True
 

	
 
def check_repo(repo_name, base_path, verify=True):
 

	
 
    repo_path = os.path.join(base_path, repo_name)
 

	
 
    try:
 
        if not check_repo_fast(repo_name, base_path):
 
            return False
 
        r = hg.repository(ui.ui(), repo_path)
 
@@ -176,84 +149,24 @@ def check_repo(repo_name, base_path, ver
 
        log.info('%s repo is free for creation', repo_name)
 
        return True
 

	
 
def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
 
    while True:
 
        ok = raw_input(prompt)
 
        if ok in ('y', 'ye', 'yes'): return True
 
        if ok in ('n', 'no', 'nop', 'nope'): return False
 
        retries = retries - 1
 
        if retries < 0: raise IOError
 
        print complaint
 

	
 
def get_hg_ui_cached():
 
    try:
 
        sa = meta.Session
 
        ret = sa.query(RhodeCodeUi)\
 
        .options(FromCache("sql_cache_short", "get_hg_ui_settings"))\
 
        .all()
 
    except:
 
        pass
 
    finally:
 
        meta.Session.remove()
 
    return ret
 

	
 

	
 
def get_hg_settings():
 
    try:
 
        sa = meta.Session()
 
        ret = sa.query(RhodeCodeSettings)\
 
        .options(FromCache("sql_cache_short", "get_hg_settings"))\
 
        .all()
 
    except:
 
        pass
 
    finally:
 
        meta.Session.remove()
 

	
 
    if not ret:
 
        raise Exception('Could not get application settings !')
 
    settings = {}
 
    for each in ret:
 
        settings['rhodecode_' + each.app_settings_name] = each.app_settings_value
 

	
 
    return settings
 

	
 
def get_hg_ui_settings():
 
    try:
 
        sa = meta.Session()
 
        ret = sa.query(RhodeCodeUi).all()
 
    except:
 
        pass
 
    finally:
 
        meta.Session.remove()
 

	
 
    if not ret:
 
        raise Exception('Could not get application ui settings !')
 
    settings = {}
 
    for each in ret:
 
        k = each.ui_key
 
        v = each.ui_value
 
        if k == '/':
 
            k = 'root_path'
 

	
 
        if k.find('.') != -1:
 
            k = k.replace('.', '_')
 

	
 
        if each.ui_section == 'hooks':
 
            v = each.ui_active
 

	
 
        settings[each.ui_section + '_' + k] = v
 

	
 
    return settings
 

	
 
#propagated from mercurial documentation
 
ui_sections = ['alias', 'auth',
 
                'decode/encode', 'defaults',
 
                'diff', 'email',
 
                'extensions', 'format',
 
                'merge-patterns', 'merge-tools',
 
                'hooks', 'http_proxy',
 
                'smtp', 'patch',
 
                'paths', 'profiling',
 
                'server', 'trusted',
 
                'ui', 'web', ]
 

	
 
@@ -279,34 +192,44 @@ def make_ui(read_from='file', path=None,
 
            log.warning('Unable to read config file %s' % path)
 
            return False
 
        log.debug('reading hgrc from %s', path)
 
        cfg = config.config()
 
        cfg.read(path)
 
        for section in ui_sections:
 
            for k, v in cfg.items(section):
 
                log.debug('settings ui from file[%s]%s:%s', section, k, v)
 
                baseui.setconfig(section, k, v)
 

	
 

	
 
    elif read_from == 'db':
 
        hg_ui = get_hg_ui_cached()
 
        sa = meta.Session()
 
        ret = sa.query(RhodeCodeUi)\
 
            .options(FromCache("sql_cache_short",
 
                               "get_hg_ui_settings")).all()
 
        meta.Session.remove()
 
        hg_ui = ret
 
        for ui_ in hg_ui:
 
            if ui_.ui_active:
 
                log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, ui_.ui_key, ui_.ui_value)
 
                baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
 
    return baseui
 

	
 

	
 
def set_rhodecode_config(config):
 
    hgsettings = get_hg_settings()
 
    """
 
    Updates pylons config with new settings from database
 
    :param config:
 
    """
 
    from rhodecode.model.settings import SettingsModel
 
    hgsettings = SettingsModel().get_app_settings()
 

	
 
    for k, v in hgsettings.items():
 
        config[k] = v
 

	
 
def invalidate_cache(cache_key, *args):
 
    """
 
    Puts cache invalidation task into db for 
 
    further global cache invalidation
 
    """
 
    from rhodecode.model.scm import ScmModel
 

	
 
    if cache_key.startswith('get_repo_cached_'):
rhodecode/model/settings.py
Show inline comments
 
@@ -19,42 +19,53 @@
 
# MA  02110-1301, USA.
 
"""
 
Created on Nov 17, 2010
 
Model for RhodeCode
 
:author: marcink
 
"""
 

	
 
from rhodecode.lib import helpers as h
 
from rhodecode.model import BaseModel
 
from rhodecode.model.caching_query import FromCache
 
from rhodecode.model.db import  RhodeCodeSettings
 
from sqlalchemy.orm import joinedload
 
from sqlalchemy.orm.session import make_transient
 
import logging
 

	
 
log = logging.getLogger(__name__)
 

	
 
class SettingsModel(BaseModel):
 
    """
 
    Settings model
 
    """
 

	
 
    def get(self, settings_key, cache=False):
 
        r = self.sa.query(RhodeCodeSettings)\
 
            .filter(RhodeCodeSettings.app_settings_name == settings_key).scalar()
 
        if cache:
 
            r = r.options(FromCache("sql_cache_short",
 
                                          "get_setting_%s" % settings_key))
 
        return r
 

	
 
    def get_app_settings(self):
 
        ret = self.sa.query(RhodeCodeSettings)\
 
            .options(FromCache("sql_cache_short",
 
                           "get_hg_settings")).all()
 

	
 
        if not ret:
 
            raise Exception('Could not get application settings !')
 
        settings = {}
 
        for each in ret:
 
            settings['rhodecode_' + each.app_settings_name] = each.app_settings_value
 

	
 
        return settings
 

	
 
    def get_ldap_settings(self):
 
        """
 
        Returns ldap settings from database
 
        :returns:
 
        ldap_active
 
        ldap_host
 
        ldap_port 
 
        ldap_ldaps
 
        ldap_dn_user 
 
        ldap_dn_pass 
 
        ldap_base_dn
0 comments (0 inline, 0 general)