##// END OF EJS Templates
config: abort early if the environment doesn't allow Python to pass Unicode strings to the file system layer...
Mads Kiilerich -
r7299:0e33880b default
parent child Browse files
Show More
@@ -1,198 +1,214 b''
1 1 # -*- coding: utf-8 -*-
2 2 # This program is free software: you can redistribute it and/or modify
3 3 # it under the terms of the GNU General Public License as published by
4 4 # the Free Software Foundation, either version 3 of the License, or
5 5 # (at your option) any later version.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 """
15 15 Global configuration file for TurboGears2 specific settings in Kallithea.
16 16
17 17 This file complements the .ini file.
18 18 """
19 19
20 20 import platform
21 21 import os, sys, logging
22 22
23 23 import tg
24 24 from tg import hooks
25 25 from tg.configuration import AppConfig
26 26 from tg.support.converters import asbool
27 27 import alembic.config
28 28 from alembic.script.base import ScriptDirectory
29 29 from alembic.migration import MigrationContext
30 30 from sqlalchemy import create_engine
31 31 import mercurial
32 32
33 33 from kallithea.lib.middleware.https_fixup import HttpsFixup
34 34 from kallithea.lib.middleware.simplegit import SimpleGit
35 35 from kallithea.lib.middleware.simplehg import SimpleHg
36 36 from kallithea.lib.auth import set_available_permissions
37 37 from kallithea.lib.utils import load_rcextensions, make_ui, set_app_settings, set_vcs_config, \
38 38 set_indexer_config, check_git_version, repo2db_mapper
39 39 from kallithea.lib.utils2 import str2bool
40 40 import kallithea.model.base
41 41 from kallithea.model.scm import ScmModel
42 42
43 43 import formencode
44 44
45 45 log = logging.getLogger(__name__)
46 46
47 47
48 48 class KallitheaAppConfig(AppConfig):
49 49 # Note: AppConfig has a misleading name, as it's not the application
50 50 # configuration, but the application configurator. The AppConfig values are
51 51 # used as a template to create the actual configuration, which might
52 52 # overwrite or extend the one provided by the configurator template.
53 53
54 54 # To make it clear, AppConfig creates the config and sets into it the same
55 55 # values that AppConfig itself has. Then the values from the config file and
56 56 # gearbox options are loaded and merged into the configuration. Then an
57 57 # after_init_config(conf) method of AppConfig is called for any change that
58 58 # might depend on options provided by configuration files.
59 59
60 60 def __init__(self):
61 61 super(KallitheaAppConfig, self).__init__()
62 62
63 63 self['package'] = kallithea
64 64
65 65 self['prefer_toscawidgets2'] = False
66 66 self['use_toscawidgets'] = False
67 67
68 68 self['renderers'] = []
69 69
70 70 # Enable json in expose
71 71 self['renderers'].append('json')
72 72
73 73 # Configure template rendering
74 74 self['renderers'].append('mako')
75 75 self['default_renderer'] = 'mako'
76 76 self['use_dotted_templatenames'] = False
77 77
78 78 # Configure Sessions, store data as JSON to avoid pickle security issues
79 79 self['session.enabled'] = True
80 80 self['session.data_serializer'] = 'json'
81 81
82 82 # Configure the base SQLALchemy Setup
83 83 self['use_sqlalchemy'] = True
84 84 self['model'] = kallithea.model.base
85 85 self['DBSession'] = kallithea.model.meta.Session
86 86
87 87 # Configure App without an authentication backend.
88 88 self['auth_backend'] = None
89 89
90 90 # Use custom error page for these errors. By default, Turbogears2 does not add
91 91 # 400 in this list.
92 92 # Explicitly listing all is considered more robust than appending to defaults,
93 93 # in light of possible future framework changes.
94 94 self['errorpage.status_codes'] = [400, 401, 403, 404]
95 95
96 96 # Disable transaction manager -- currently Kallithea takes care of transactions itself
97 97 self['tm.enabled'] = False
98 98
99 99
100 100 base_config = KallitheaAppConfig()
101 101
102 102 # TODO still needed as long as we use pylonslib
103 103 sys.modules['pylons'] = tg
104 104
105 105 # DebugBar, a debug toolbar for TurboGears2.
106 106 # (https://github.com/TurboGears/tgext.debugbar)
107 107 # To enable it, install 'tgext.debugbar' and 'kajiki', and run Kallithea with
108 108 # 'debug = true' (not in production!)
109 109 # See the Kallithea documentation for more information.
110 110 try:
111 111 from tgext.debugbar import enable_debugbar
112 112 import kajiki # only to check its existence
113 113 except ImportError:
114 114 pass
115 115 else:
116 116 base_config['renderers'].append('kajiki')
117 117 enable_debugbar(base_config)
118 118
119 119
120 120 def setup_configuration(app):
121 121 config = app.config
122 122
123 # Verify that things work when Dulwich passes unicode paths to the file system layer.
124 # Note: UTF-8 is preferred, but for example ISO-8859-1 or mbcs should also work under the right cirumstances.
125 try:
126 u'\xe9'.encode(sys.getfilesystemencoding()) # Test using Γ© (&eacute;)
127 except UnicodeEncodeError:
128 log.error("Cannot encode Unicode paths to file system encoding %r", sys.getfilesystemencoding())
129 for var in ['LC_CTYPE', 'LC_ALL', 'LANG']:
130 if var in os.environ:
131 val = os.environ[var]
132 log.error("Note: Environment variable %s is %r - perhaps change it to some other value from 'locale -a', like 'C.UTF-8' or 'en_US.UTF-8'", var, val)
133 break
134 else:
135 log.error("Note: No locale setting found in environment variables - perhaps set LC_CTYPE to some value from 'locale -a', like 'C.UTF-8' or 'en_US.UTF-8'")
136 log.error("Terminating ...")
137 sys.exit(1)
138
123 139 # Mercurial sets encoding at module import time, so we have to monkey patch it
124 140 hgencoding = config.get('hgencoding')
125 141 if hgencoding:
126 142 mercurial.encoding.encoding = hgencoding
127 143
128 144 if config.get('ignore_alembic_revision', False):
129 145 log.warn('database alembic revision checking is disabled')
130 146 else:
131 147 dbconf = config['sqlalchemy.url']
132 148 alembic_cfg = alembic.config.Config()
133 149 alembic_cfg.set_main_option('script_location', 'kallithea:alembic')
134 150 alembic_cfg.set_main_option('sqlalchemy.url', dbconf)
135 151 script_dir = ScriptDirectory.from_config(alembic_cfg)
136 152 available_heads = sorted(script_dir.get_heads())
137 153
138 154 engine = create_engine(dbconf)
139 155 with engine.connect() as conn:
140 156 context = MigrationContext.configure(conn)
141 157 current_heads = sorted(str(s) for s in context.get_current_heads())
142 158 if current_heads != available_heads:
143 159 log.error('Failed to run Kallithea:\n\n'
144 160 'The database version does not match the Kallithea version.\n'
145 161 'Please read the documentation on how to upgrade or downgrade the database.\n'
146 162 'Current database version id(s): %s\n'
147 163 'Expected database version id(s): %s\n'
148 164 'If you are a developer and you know what you are doing, you can add `ignore_alembic_revision = True` '
149 165 'to your .ini file to skip the check.\n' % (' '.join(current_heads), ' '.join(available_heads)))
150 166 sys.exit(1)
151 167
152 168 # store some globals into kallithea
153 169 kallithea.CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
154 170 kallithea.CELERY_EAGER = str2bool(config['app_conf'].get('celery.always.eager'))
155 171 kallithea.CONFIG = config
156 172
157 173 load_rcextensions(root_path=config['here'])
158 174
159 175 set_available_permissions(config)
160 176 repos_path = make_ui('db').configitems('paths')[0][1]
161 177 config['base_path'] = repos_path
162 178 set_app_settings(config)
163 179
164 180 instance_id = kallithea.CONFIG.get('instance_id', '*')
165 181 if instance_id == '*':
166 182 instance_id = '%s-%s' % (platform.uname()[1], os.getpid())
167 183 kallithea.CONFIG['instance_id'] = instance_id
168 184
169 185 # update kallithea.CONFIG with the meanwhile changed 'config'
170 186 kallithea.CONFIG.update(config)
171 187
172 188 # configure vcs and indexer libraries (they are supposed to be independent
173 189 # as much as possible and thus avoid importing tg.config or
174 190 # kallithea.CONFIG).
175 191 set_vcs_config(kallithea.CONFIG)
176 192 set_indexer_config(kallithea.CONFIG)
177 193
178 194 check_git_version()
179 195
180 196
181 197 hooks.register('configure_new_app', setup_configuration)
182 198
183 199
184 200 def setup_application(app):
185 201 config = app.config
186 202
187 203 # we want our low level middleware to get to the request ASAP. We don't
188 204 # need any stack middleware in them - especially no StatusCodeRedirect buffering
189 205 app = SimpleHg(app, config)
190 206 app = SimpleGit(app, config)
191 207
192 208 # Enable https redirects based on HTTP_X_URL_SCHEME set by proxy
193 209 if any(asbool(config.get(x)) for x in ['https_fixup', 'force_https', 'use_htsts']):
194 210 app = HttpsFixup(app, config)
195 211 return app
196 212
197 213
198 214 hooks.register('before_config', setup_application)
General Comments 0
You need to be logged in to leave comments. Login now