changeset 341:1ef52a70f3b7

Made config file free configuration based on database and capable of beeing manage via application settings + some code cleanups
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 14 Jul 2010 02:28:32 +0200
parents 71f25781079d
children c71dc6ef36e6
files pylons_app/config/environment.py pylons_app/config/middleware.py pylons_app/config/repositories.config_tmpl pylons_app/controllers/settings.py pylons_app/lib/app_globals.py pylons_app/lib/db_manage.py pylons_app/lib/middleware/simplehg.py pylons_app/lib/utils.py pylons_app/model/db.py pylons_app/websetup.py
diffstat 10 files changed, 141 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/pylons_app/config/environment.py	Fri Jul 09 02:38:17 2010 +0200
+++ b/pylons_app/config/environment.py	Wed Jul 14 02:28:32 2010 +0200
@@ -4,7 +4,7 @@
 from pylons.error import handle_mako_error
 from pylons_app.config.routing import make_map
 from pylons_app.lib.auth import set_available_permissions, set_base_path
-from pylons_app.lib.utils import repo2db_mapper
+from pylons_app.lib.utils import repo2db_mapper, make_ui, set_hg_app_config
 from pylons_app.model import init_model
 from pylons_app.model.hg_model import _get_repos_cached_initial
 from sqlalchemy import engine_from_config
@@ -61,9 +61,12 @@
         sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.')
 
     init_model(sa_engine_db1)
+    config['pylons.app_globals'].baseui = make_ui('db')
+    
     repo2db_mapper(_get_repos_cached_initial(config['pylons.app_globals']))
     set_available_permissions(config)
     set_base_path(config)
+    set_hg_app_config(config)
     # CONFIGURATION OPTIONS HERE (note: all config options will override
     # any Pylons config options)
     
--- a/pylons_app/config/middleware.py	Fri Jul 09 02:38:17 2010 +0200
+++ b/pylons_app/config/middleware.py	Wed Jul 14 02:28:32 2010 +0200
@@ -41,7 +41,6 @@
     app = SessionMiddleware(app, config)
     
     # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
-    #set the https based on HTTP_X_URL_SCHEME
     
     app = SimpleHg(app, config)
     
--- a/pylons_app/config/repositories.config_tmpl	Fri Jul 09 02:38:17 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-[hooks]
-#to do push with autoupdate
-changegroup = hg update >&2
-
-[web]
-#for http requests push ssl to false
-push_ssl = false
-allow_archive = gz zip bz2
-allow_push = *
-baseurl = /
-
-[paths]
-#this path should point to mercurial repositories remeber about '*' at the end
-/ = %(repo_location)s
--- a/pylons_app/controllers/settings.py	Fri Jul 09 02:38:17 2010 +0200
+++ b/pylons_app/controllers/settings.py	Wed Jul 14 02:28:32 2010 +0200
@@ -70,8 +70,6 @@
         )  
 
     def update(self, repo_name):
-        print request.POST
-        print 'x' * 110
         repo_model = RepoModel()
         _form = RepoSettingsForm(edit=True)()
         try:
--- a/pylons_app/lib/app_globals.py	Fri Jul 09 02:38:17 2010 +0200
+++ b/pylons_app/lib/app_globals.py	Wed Jul 14 02:28:32 2010 +0200
@@ -2,10 +2,9 @@
 
 from beaker.cache import CacheManager
 from beaker.util import parse_cache_config_options
-from pylons_app.lib.utils import make_ui
+from vcs.utils.lazy import LazyProperty
 
 class Globals(object):
-
     """Globals acts as a container for objects available throughout the
     life of the application
 
@@ -18,8 +17,17 @@
 
         """
         self.cache = CacheManager(**parse_cache_config_options(config))
-        self.baseui = make_ui(config['hg_app_repo_conf'])
-        self.paths = self.baseui.configitems('paths')
-        self.base_path = self.paths[0][1].replace('*', '')
         self.changeset_annotation_colors = {}
-        self.available_permissions = None # propagated after init_model
+        self.available_permissions = None   # propagated after init_model
+        self.app_title = None               # propagated after init_model
+        self.baseui = None                  # propagated after init_model        
+        
+    @LazyProperty
+    def paths(self):
+        if self.baseui:
+            return self.baseui.configitems('paths')
+    
+    @LazyProperty
+    def base_path(self):
+        if self.baseui:
+            return self.paths[0][1].replace('*', '')            
--- a/pylons_app/lib/db_manage.py	Fri Jul 09 02:38:17 2010 +0200
+++ b/pylons_app/lib/db_manage.py	Wed Jul 14 02:28:32 2010 +0200
@@ -33,7 +33,7 @@
 
 from pylons_app.lib.auth import get_crypt_password
 from pylons_app.model import init_model
-from pylons_app.model.db import User, Permission
+from pylons_app.model.db import User, Permission, HgAppUi
 from pylons_app.model.meta import Session, Base
 from sqlalchemy.engine import create_engine
 import logging
@@ -79,7 +79,62 @@
         username = raw_input('Specify admin username:')
         password = getpass.getpass('Specify admin password:')
         self.create_user(username, password, True)
+    
+    def config_prompt(self):
+        log.info('Seting up repositories.config')
         
+        
+        path = raw_input('Specify valid full path to your repositories'
+                        ' you can change this later application settings:')
+        
+        if not os.path.isdir(path):
+            log.error('You entered wrong path')
+            sys.exit()
+        
+        hooks = HgAppUi()
+        hooks.ui_section = 'hooks'
+        hooks.ui_key = 'changegroup'
+        hooks.ui_value = 'hg update >&2'
+        
+        web1 = HgAppUi()
+        web1.ui_section = 'web'
+        web1.ui_key = 'push_ssl'
+        web1.ui_value = 'false'
+                
+        web2 = HgAppUi()
+        web2.ui_section = 'web'
+        web2.ui_key = 'allow_archive'
+        web2.ui_value = 'gz zip bz2'
+                
+        web3 = HgAppUi()
+        web3.ui_section = 'web'
+        web3.ui_key = 'allow_push'
+        web3.ui_value = '*'
+        
+        web4 = HgAppUi()
+        web4.ui_section = 'web'
+        web4.ui_key = 'baseurl'
+        web4.ui_value = '/'                        
+        
+        paths = HgAppUi()
+        paths.ui_section = 'paths'
+        paths.ui_key = '/'
+        paths.ui_value = os.path.join(path, '*')
+        
+        
+        try:
+            self.sa.add(hooks)
+            self.sa.add(web1)
+            self.sa.add(web2)
+            self.sa.add(web3)
+            self.sa.add(web4)
+            self.sa.add(paths)
+            self.sa.commit()
+        except:
+            self.sa.rollback()
+            raise        
+        log.info('created ui config')
+                    
     def create_user(self, username, password, admin=False):
         
         log.info('creating default user')
@@ -93,8 +148,6 @@
         def_user.admin = False
         def_user.active = False
         
-        self.sa.add(def_user)
-        
         log.info('creating administrator user %s', username)
         new_user = User()
         new_user.username = username
@@ -106,6 +159,7 @@
         new_user.active = True
         
         try:
+            self.sa.add(def_user)
             self.sa.add(new_user)
             self.sa.commit()
         except:
--- a/pylons_app/lib/middleware/simplehg.py	Fri Jul 09 02:38:17 2010 +0200
+++ b/pylons_app/lib/middleware/simplehg.py	Wed Jul 14 02:28:32 2010 +0200
@@ -50,7 +50,7 @@
         self.application = application
         self.config = config
         #authenticate this mercurial request using 
-        realm = '%s %s' % (self.config['hg_app_name'], 'mercurial repository')
+        realm = self.config['hg_app_auth_realm']
         self.authenticate = AuthBasicAuthenticator(realm, authfunc)
         
     def __call__(self, environ, start_response):
@@ -111,14 +111,13 @@
             # MERCURIAL REQUEST HANDLING
             #===================================================================
             environ['PATH_INFO'] = '/'#since we wrap into hgweb, reset the path
-            self.baseui = make_ui(self.config['hg_app_repo_conf'])
+            self.baseui = make_ui('db')
             self.basepath = self.config['base_path']
             self.repo_path = os.path.join(self.basepath, repo_name)
 
             #quick check if that dir exists...
             if check_repo_fast(repo_name, self.basepath):
                 return HTTPNotFound()(environ, start_response)
-            
             try:
                 app = wsgiapplication(self.__make_app)
             except RepoError as e:
@@ -155,7 +154,7 @@
         return chain(org_response, custom_messages(messages))
 
     def __make_app(self):
-        hgserve = hgweb(self.repo_path)
+        hgserve = hgweb(str(self.repo_path), baseui=self.baseui)
         return  self.__load_web_settings(hgserve)
     
     def __get_environ_user(self, environ):
@@ -214,10 +213,12 @@
            
                    
     def __load_web_settings(self, hgserve):
-        repoui = make_ui(os.path.join(self.repo_path, '.hg', 'hgrc'), False)
         #set the global ui for hgserve
         hgserve.repo.ui = self.baseui
         
+        hgrc = os.path.join(self.repo_path, '.hg', 'hgrc')
+        repoui = make_ui('file', hgrc, False)
+        
         if repoui:
             #set the repository based config
             hgserve.repo.ui = repoui
--- a/pylons_app/lib/utils.py	Fri Jul 09 02:38:17 2010 +0200
+++ b/pylons_app/lib/utils.py	Wed Jul 14 02:28:32 2010 +0200
@@ -27,7 +27,7 @@
 import logging
 from mercurial import ui, config, hg
 from mercurial.error import RepoError
-from pylons_app.model.db import Repository, User
+from pylons_app.model.db import Repository, User, HgAppUi
 log = logging.getLogger(__name__)
 
 
@@ -75,53 +75,58 @@
         log.info('%s repo is free for creation', repo_name)
         return True
 
-def make_ui(path=None, checkpaths=True):        
+def make_ui(read_from='file', path=None, checkpaths=True):        
     """
-    A funcion that will read python rc files and make an ui from read options
+    A function that will read python rc files or database
+    and make an mercurial ui object from read options
     
     @param path: path to mercurial config file
+    @param checkpaths: check the path
+    @param read_from: read from 'file' or 'db'
     """
-    if not path:
-        log.error('repos config path is empty !')
-    
-    if not os.path.isfile(path):
-        log.warning('Unable to read config file %s' % path)
-        return False
     #propagated from mercurial documentation
-    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',
-                ]
+    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', ]
+    baseui = ui.ui()
 
-    baseui = ui.ui()
-    cfg = config.config()
-    cfg.read(path)
-    if checkpaths:check_repo_dir(cfg.items('paths'))
-
-    for section in sections:
-        for k, v in cfg.items(section):
-            baseui.setconfig(section, k, v)
+                
+    if read_from == 'file':
+        if not os.path.isfile(path):
+            log.warning('Unable to read config file %s' % path)
+            return False
+        
+        cfg = config.config()
+        cfg.read(path)
+        for section in sections:
+            for k, v in cfg.items(section):
+                baseui.setconfig(section, k, v)
+        if checkpaths:check_repo_dir(cfg.items('paths'))                
+              
+        
+    elif read_from == 'db':
+        from pylons_app.model.meta import Session
+        sa = Session()
+            
+        hg_ui = sa.query(HgAppUi).all()
+        for ui_ in hg_ui:
+            baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
+        
     
     return baseui
 
+
+def set_hg_app_config(config):
+    config['hg_app_auth_realm'] = 'realm'
+    config['hg_app_name'] = 'app name'
+
 def invalidate_cache(name, *args):
     """Invalidates given name cache"""
     
--- a/pylons_app/model/db.py	Fri Jul 09 02:38:17 2010 +0200
+++ b/pylons_app/model/db.py	Wed Jul 14 02:28:32 2010 +0200
@@ -3,6 +3,21 @@
 from sqlalchemy import *
 from vcs.utils.lazy import LazyProperty
 
+class HgAppSettings(Base):
+    __tablename__ = 'hg_app_settings'
+    __table_args__ = {'useexisting':True}
+    app_settings_id = Column("app_settings_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
+    app_title = Column("app_title", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+    app_auth_realm = Column("auth_realm", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+
+class HgAppUi(Base):
+    __tablename__ = 'hg_app_ui'
+    __table_args__ = {'useexisting':True}
+    ui_id = Column("ui_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
+    ui_section = Column("ui_section", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+    ui_key = Column("ui_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+    ui_value = Column("ui_value", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+
 class User(Base): 
     __tablename__ = 'users'
     __table_args__ = {'useexisting':True}
--- a/pylons_app/websetup.py	Fri Jul 09 02:38:17 2010 +0200
+++ b/pylons_app/websetup.py	Wed Jul 14 02:28:32 2010 +0200
@@ -12,37 +12,11 @@
 ROOT = dn(dn(os.path.realpath(__file__)))
 sys.path.append(ROOT)
 
-
-def setup_repository():
-    log.info('Seting up repositories.config')
-    fname = 'repositories.config'
-    
-    try:
-        tmpl = open(jn(ROOT, 'pylons_app', 'config', 'repositories.config_tmpl')).read()
-    except IOError:
-        raise
-    
-    path = raw_input('Specify valid full path to your repositories'
-                    ' you can change this later in repositories.config file:')
-    
-    if not os.path.isdir(path):
-        log.error('You entered wrong path')
-        sys.exit()
-    
-    
-    path = jn(path, '*') 
-    dest_path = jn(ROOT, fname)
-    f = open(dest_path, 'wb')
-    f.write(tmpl % {'repo_location':path})
-    f.close()
-    log.info('created repositories.config in %s', dest_path)
-        
-
 def setup_app(command, conf, vars):
     """Place any commands to setup pylons_app here"""
-    setup_repository()
     dbmanage = DbManage(log_sql=True)
     dbmanage.create_tables(override=True)
+    dbmanage.config_prompt()
     dbmanage.admin_prompt()
     dbmanage.create_permissions()
     load_environment(conf.global_conf, conf.local_conf)