##// END OF EJS Templates
cli: only config_file_initialize_app should set global CONFIG; needs_config_file will be passed the config object
Mads Kiilerich -
r8609:e9521559 default
parent child Browse files
Show More
@@ -1,62 +1,62 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
5 # (at your option) any later version.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU General Public License
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 """
14 """
15 kallithea
15 kallithea
16 ~~~~~~~~~
16 ~~~~~~~~~
17
17
18 Kallithea, a web based repository management system.
18 Kallithea, a web based repository management system.
19
19
20 Versioning implementation: http://www.python.org/dev/peps/pep-0386/
20 Versioning implementation: http://www.python.org/dev/peps/pep-0386/
21
21
22 This file was forked by the Kallithea project in July 2014.
22 This file was forked by the Kallithea project in July 2014.
23 Original author and date, and relevant copyright and licensing information is below:
23 Original author and date, and relevant copyright and licensing information is below:
24 :created_on: Apr 9, 2010
24 :created_on: Apr 9, 2010
25 :author: marcink
25 :author: marcink
26 :copyright: (c) 2013 RhodeCode GmbH, (C) 2014 Bradley M. Kuhn, and others.
26 :copyright: (c) 2013 RhodeCode GmbH, (C) 2014 Bradley M. Kuhn, and others.
27 :license: GPLv3, see LICENSE.md for more details.
27 :license: GPLv3, see LICENSE.md for more details.
28 """
28 """
29
29
30 import platform
30 import platform
31 import sys
31 import sys
32
32
33
33
34 if sys.version_info < (3, 6):
34 if sys.version_info < (3, 6):
35 raise Exception('Kallithea requires python 3.6 or later')
35 raise Exception('Kallithea requires python 3.6 or later')
36
36
37 VERSION = (0, 6, 99)
37 VERSION = (0, 6, 99)
38 BACKENDS = {
38 BACKENDS = {
39 'hg': 'Mercurial repository',
39 'hg': 'Mercurial repository',
40 'git': 'Git repository',
40 'git': 'Git repository',
41 }
41 }
42
42
43 CELERY_APP = None # set to Celery app instance if using Celery
43 CELERY_APP = None # set to Celery app instance if using Celery
44
44
45 CONFIG = {}
45 CONFIG = {} # set to tg.config when TG app is initialized and calls app_cfg
46
46
47 # URL prefix for non repository related links - must start with `/`
47 # URL prefix for non repository related links - must start with `/`
48 ADMIN_PREFIX = '/_admin'
48 ADMIN_PREFIX = '/_admin'
49 URL_SEP = '/'
49 URL_SEP = '/'
50
50
51 # Linked module for extensions
51 # Linked module for extensions
52 EXTENSIONS = {}
52 EXTENSIONS = {}
53
53
54 __version__ = '.'.join(str(each) for each in VERSION)
54 __version__ = '.'.join(str(each) for each in VERSION)
55 __platform__ = platform.system()
55 __platform__ = platform.system()
56 __license__ = 'GPLv3'
56 __license__ = 'GPLv3'
57 __py_version__ = sys.version_info
57 __py_version__ = sys.version_info
58 __author__ = "Various Authors"
58 __author__ = "Various Authors"
59 __url__ = 'https://kallithea-scm.org/'
59 __url__ = 'https://kallithea-scm.org/'
60
60
61 is_windows = __platform__ in ['Windows']
61 is_windows = __platform__ in ['Windows']
62 is_unix = not is_windows
62 is_unix = not is_windows
@@ -1,88 +1,86 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
5 # (at your option) any later version.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU General Public License
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
14
15 import configparser
15 import configparser
16 import functools
16 import functools
17 import logging.config
17 import logging.config
18 import os
18 import os
19 import re
19 import re
20 import sys
20 import sys
21
21
22 import click
22 import click
23 import paste.deploy
23 import paste.deploy
24
24
25 import kallithea
25 import kallithea
26 import kallithea.config.application
26 import kallithea.config.application
27
27
28
28
29 # kallithea_cli is usually invoked through the 'kallithea-cli' wrapper script
29 # kallithea_cli is usually invoked through the 'kallithea-cli' wrapper script
30 # that is installed by setuptools, as specified in setup.py console_scripts
30 # that is installed by setuptools, as specified in setup.py console_scripts
31 # entry_points. The script will be using the right virtualenv (if any), and for
31 # entry_points. The script will be using the right virtualenv (if any), and for
32 # Unix, it will contain #! pointing at the right python executable. The script
32 # Unix, it will contain #! pointing at the right python executable. The script
33 # also makes sure sys.argv[0] points back at the script path, and that is what
33 # also makes sure sys.argv[0] points back at the script path, and that is what
34 # can be used to invoke 'kallithea-cli' later.
34 # can be used to invoke 'kallithea-cli' later.
35 kallithea_cli_path = sys.argv[0]
35 kallithea_cli_path = sys.argv[0]
36
36
37
37
38 def read_config(ini_file_name, strip_section_prefix):
38 def read_config(ini_file_name, strip_section_prefix):
39 """Read ini_file_name content, and for all sections like '[X:Y]' where X is
39 """Read ini_file_name content, and for all sections like '[X:Y]' where X is
40 strip_section_prefix, replace the section name with '[Y]'."""
40 strip_section_prefix, replace the section name with '[Y]'."""
41
41
42 def repl(m):
42 def repl(m):
43 if m.group(1) == strip_section_prefix:
43 if m.group(1) == strip_section_prefix:
44 return '[%s]' % m.group(2)
44 return '[%s]' % m.group(2)
45 return m.group(0)
45 return m.group(0)
46
46
47 with open(ini_file_name) as f:
47 with open(ini_file_name) as f:
48 return re.sub(r'^\[([^:]+):(.*)]', repl, f.read(), flags=re.MULTILINE)
48 return re.sub(r'^\[([^:]+):(.*)]', repl, f.read(), flags=re.MULTILINE)
49
49
50
50
51 # This placeholder is the main entry point for the kallithea-cli command
51 # This placeholder is the main entry point for the kallithea-cli command
52 @click.group(context_settings=dict(help_option_names=['-h', '--help']))
52 @click.group(context_settings=dict(help_option_names=['-h', '--help']))
53 def cli():
53 def cli():
54 """Various commands to manage a Kallithea instance."""
54 """Various commands to manage a Kallithea instance."""
55
55
56 def register_command(needs_config_file=False, config_file_initialize_app=False, hidden=False):
56 def register_command(needs_config_file=False, config_file_initialize_app=False, hidden=False):
57 """Register a kallithea-cli subcommand.
57 """Register a kallithea-cli subcommand.
58
58
59 If one of the needs_config_file flags are true, a config file must be specified
59 If one of the needs_config_file flags are true, a config file must be specified
60 with -c and it is read and logging is configured. The configuration is
60 with -c and it is read and logging is configured. The configuration is
61 available in the kallithea.CONFIG dict.
61 available in the kallithea.CONFIG dict.
62
62
63 If config_file_initialize_app is true, Kallithea, TurboGears global state
63 If config_file_initialize_app is true, Kallithea, TurboGears global state
64 (including tg.config), and database access will also be fully initialized.
64 (including tg.config), and database access will also be fully initialized.
65 """
65 """
66 cli_command = cli.command(hidden=hidden)
66 cli_command = cli.command(hidden=hidden)
67 if needs_config_file or config_file_initialize_app:
67 if needs_config_file or config_file_initialize_app:
68 def annotator(annotated):
68 def annotator(annotated):
69 @click.option('--config_file', '-c', help="Path to .ini file with app configuration.",
69 @click.option('--config_file', '-c', help="Path to .ini file with app configuration.",
70 type=click.Path(dir_okay=False, exists=True, readable=True), required=True)
70 type=click.Path(dir_okay=False, exists=True, readable=True), required=True)
71 @functools.wraps(annotated) # reuse meta data from the wrapped function so click can see other options
71 @functools.wraps(annotated) # reuse meta data from the wrapped function so click can see other options
72 def runtime_wrapper(config_file, *args, **kwargs):
72 def runtime_wrapper(config_file, *args, **kwargs):
73 path_to_ini_file = os.path.realpath(config_file)
73 path_to_ini_file = os.path.realpath(config_file)
74 config = paste.deploy.appconfig('config:' + path_to_ini_file)
74 config = paste.deploy.appconfig('config:' + path_to_ini_file)
75 cp = configparser.ConfigParser(strict=False)
75 cp = configparser.ConfigParser(strict=False)
76 cp.read_string(read_config(path_to_ini_file, strip_section_prefix=annotated.__name__))
76 cp.read_string(read_config(path_to_ini_file, strip_section_prefix=annotated.__name__))
77 logging.config.fileConfig(cp,
77 logging.config.fileConfig(cp,
78 {'__file__': path_to_ini_file, 'here': os.path.dirname(path_to_ini_file)})
78 {'__file__': path_to_ini_file, 'here': os.path.dirname(path_to_ini_file)})
79 if config_file_initialize_app:
79 if needs_config_file:
80 if needs_config_file: # special case for db creation: also call annotated function (with config parameter) *before* app initialization
81 annotated(*args, config=config, **kwargs)
80 annotated(*args, config=config, **kwargs)
81 if config_file_initialize_app:
82 kallithea.config.application.make_app(config.global_conf, **config.local_conf)
82 kallithea.config.application.make_app(config.global_conf, **config.local_conf)
83 else:
84 kallithea.CONFIG = dict(config) # config is a dict subclass
85 annotated(*args, **kwargs)
83 annotated(*args, **kwargs)
86 return cli_command(runtime_wrapper)
84 return cli_command(runtime_wrapper)
87 return annotator
85 return annotator
88 return cli_command
86 return cli_command
@@ -1,57 +1,56 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
5 # (at your option) any later version.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU General Public License
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 """
14 """
15 This file was forked by the Kallithea project in July 2014 and later moved.
15 This file was forked by the Kallithea project in July 2014 and later moved.
16 Original author and date, and relevant copyright and licensing information is below:
16 Original author and date, and relevant copyright and licensing information is below:
17 :created_on: Mar 6, 2012
17 :created_on: Mar 6, 2012
18 :author: marcink
18 :author: marcink
19 :copyright: (c) 2013 RhodeCode GmbH, and others.
19 :copyright: (c) 2013 RhodeCode GmbH, and others.
20 :license: GPLv3, see LICENSE.md for more details.
20 :license: GPLv3, see LICENSE.md for more details.
21 """
21 """
22 import os
22 import os
23
23
24 import click
24 import click
25 import pkg_resources
25 import pkg_resources
26
26
27 import kallithea
28 import kallithea.bin.kallithea_cli_base as cli_base
27 import kallithea.bin.kallithea_cli_base as cli_base
29 from kallithea.lib.utils2 import ask_ok
28 from kallithea.lib.utils2 import ask_ok
30
29
31
30
32 @cli_base.register_command(needs_config_file=True)
31 @cli_base.register_command(needs_config_file=True)
33 def extensions_create():
32 def extensions_create(config):
34 """Write template file for extending Kallithea in Python.
33 """Write template file for extending Kallithea in Python.
35
34
36 Create a template `extensions.py` file next to the ini file. Local
35 Create a template `extensions.py` file next to the ini file. Local
37 customizations in that file will survive upgrades. The file contains
36 customizations in that file will survive upgrades. The file contains
38 instructions on how it can be customized.
37 instructions on how it can be customized.
39 """
38 """
40 here = kallithea.CONFIG['here']
39 here = config['here']
41 content = pkg_resources.resource_string(
40 content = pkg_resources.resource_string(
42 'kallithea', os.path.join('templates', 'py', 'extensions.py')
41 'kallithea', os.path.join('templates', 'py', 'extensions.py')
43 )
42 )
44 ext_file = os.path.join(here, 'extensions.py')
43 ext_file = os.path.join(here, 'extensions.py')
45 if os.path.exists(ext_file):
44 if os.path.exists(ext_file):
46 msg = ('Extension file %s already exists, do you want '
45 msg = ('Extension file %s already exists, do you want '
47 'to overwrite it ? [y/n] ') % ext_file
46 'to overwrite it ? [y/n] ') % ext_file
48 if not ask_ok(msg):
47 if not ask_ok(msg):
49 click.echo('Nothing done, exiting...')
48 click.echo('Nothing done, exiting...')
50 return
49 return
51
50
52 dirname = os.path.dirname(ext_file)
51 dirname = os.path.dirname(ext_file)
53 if not os.path.isdir(dirname):
52 if not os.path.isdir(dirname):
54 os.makedirs(dirname)
53 os.makedirs(dirname)
55 with open(ext_file, 'wb') as f:
54 with open(ext_file, 'wb') as f:
56 f.write(content)
55 f.write(content)
57 click.echo('Wrote new extensions file to %s' % ext_file)
56 click.echo('Wrote new extensions file to %s' % ext_file)
@@ -1,86 +1,85 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
5 # (at your option) any later version.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU General Public License
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 import os
14 import os
15 import sys
15 import sys
16
16
17 import click
17 import click
18
18
19 import kallithea
20 import kallithea.bin.kallithea_cli_base as cli_base
19 import kallithea.bin.kallithea_cli_base as cli_base
21
20
22
21
23 dispath_py_template = '''\
22 dispath_py_template = '''\
24 # Created by Kallithea 'kallithea-cli iis-install'
23 # Created by Kallithea 'kallithea-cli iis-install'
25 import sys
24 import sys
26
25
27 if hasattr(sys, "isapidllhandle"):
26 if hasattr(sys, "isapidllhandle"):
28 import win32traceutil
27 import win32traceutil
29
28
30 import isapi_wsgi
29 import isapi_wsgi
31 import os
30 import os
32
31
33 def __ExtensionFactory__():
32 def __ExtensionFactory__():
34 from paste.deploy import loadapp
33 from paste.deploy import loadapp
35 from logging.config import fileConfig
34 from logging.config import fileConfig
36 fileConfig('%(inifile)s', {'__file__': '%(inifile)s', 'here': '%(inifiledir)s'})
35 fileConfig('%(inifile)s', {'__file__': '%(inifile)s', 'here': '%(inifiledir)s'})
37
36
38 application = loadapp('config:%(inifile)s')
37 application = loadapp('config:%(inifile)s')
39
38
40 def app(environ, start_response):
39 def app(environ, start_response):
41 user = environ.get('REMOTE_USER', None)
40 user = environ.get('REMOTE_USER', None)
42 if user is not None:
41 if user is not None:
43 os.environ['REMOTE_USER'] = user
42 os.environ['REMOTE_USER'] = user
44 return application(environ, start_response)
43 return application(environ, start_response)
45
44
46 return isapi_wsgi.ISAPIThreadPoolHandler(app)
45 return isapi_wsgi.ISAPIThreadPoolHandler(app)
47
46
48 if __name__=='__main__':
47 if __name__=='__main__':
49 from isapi.install import *
48 from isapi.install import *
50 params = ISAPIParameters()
49 params = ISAPIParameters()
51 sm = [ScriptMapParams(Extension="*", Flags=0)]
50 sm = [ScriptMapParams(Extension="*", Flags=0)]
52 vd = VirtualDirParameters(Name="%(virtualdir)s",
51 vd = VirtualDirParameters(Name="%(virtualdir)s",
53 Description = "Kallithea",
52 Description = "Kallithea",
54 ScriptMaps = sm,
53 ScriptMaps = sm,
55 ScriptMapUpdate = "replace")
54 ScriptMapUpdate = "replace")
56 params.VirtualDirs = [vd]
55 params.VirtualDirs = [vd]
57 HandleCommandLine(params)
56 HandleCommandLine(params)
58 '''
57 '''
59
58
60 @cli_base.register_command(needs_config_file=True)
59 @cli_base.register_command(needs_config_file=True)
61 @click.option('--virtualdir', default='/',
60 @click.option('--virtualdir', default='/',
62 help='The virtual folder to install into on IIS.')
61 help='The virtual folder to install into on IIS.')
63 def iis_install(virtualdir):
62 def iis_install(virtualdir, config):
64 """Install into IIS using isapi-wsgi."""
63 """Install into IIS using isapi-wsgi."""
65
64
66 config_file_abs = kallithea.CONFIG['__file__']
65 config_file_abs = config['__file__']
67
66
68 try:
67 try:
69 import isapi_wsgi
68 import isapi_wsgi
70 assert isapi_wsgi
69 assert isapi_wsgi
71 except ImportError:
70 except ImportError:
72 sys.stderr.write('missing requirement: isapi-wsgi not installed\n')
71 sys.stderr.write('missing requirement: isapi-wsgi not installed\n')
73 sys.exit(1)
72 sys.exit(1)
74
73
75 dispatchfile = os.path.join(os.getcwd(), 'dispatch.py')
74 dispatchfile = os.path.join(os.getcwd(), 'dispatch.py')
76 click.echo('Writing %s' % dispatchfile)
75 click.echo('Writing %s' % dispatchfile)
77 with open(dispatchfile, 'w') as f:
76 with open(dispatchfile, 'w') as f:
78 f.write(dispath_py_template % {
77 f.write(dispath_py_template % {
79 'inifile': config_file_abs.replace('\\', '\\\\'),
78 'inifile': config_file_abs.replace('\\', '\\\\'),
80 'inifiledir': os.path.dirname(config_file_abs).replace('\\', '\\\\'),
79 'inifiledir': os.path.dirname(config_file_abs).replace('\\', '\\\\'),
81 'virtualdir': virtualdir,
80 'virtualdir': virtualdir,
82 })
81 })
83
82
84 click.echo('Run \'python "%s" install\' with administrative privileges '
83 click.echo('Run \'python "%s" install\' with administrative privileges '
85 'to generate the _dispatch.dll file and install it into the '
84 'to generate the _dispatch.dll file and install it into the '
86 'default web site' % dispatchfile)
85 'default web site' % dispatchfile)
General Comments 0
You need to be logged in to leave comments. Login now