# HG changeset patch # User Marcin Kuzminski # Date 1279067312 -7200 # Node ID 1ef52a70f3b77af35d0e656e100e2a5e1b5618e1 # Parent 71f25781079dfa780eb5eaf8364af95b76cf7618 Made config file free configuration based on database and capable of beeing manage via application settings + some code cleanups diff -r 71f25781079d -r 1ef52a70f3b7 pylons_app/config/environment.py --- 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) diff -r 71f25781079d -r 1ef52a70f3b7 pylons_app/config/middleware.py --- 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) diff -r 71f25781079d -r 1ef52a70f3b7 pylons_app/config/repositories.config_tmpl --- 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 diff -r 71f25781079d -r 1ef52a70f3b7 pylons_app/controllers/settings.py --- 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: diff -r 71f25781079d -r 1ef52a70f3b7 pylons_app/lib/app_globals.py --- 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('*', '') diff -r 71f25781079d -r 1ef52a70f3b7 pylons_app/lib/db_manage.py --- 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: diff -r 71f25781079d -r 1ef52a70f3b7 pylons_app/lib/middleware/simplehg.py --- 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 diff -r 71f25781079d -r 1ef52a70f3b7 pylons_app/lib/utils.py --- 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""" diff -r 71f25781079d -r 1ef52a70f3b7 pylons_app/model/db.py --- 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} diff -r 71f25781079d -r 1ef52a70f3b7 pylons_app/websetup.py --- 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)