##// END OF EJS Templates
Mercurial: fix ssh-server support for UI objects...
marcink -
r3626:30cddb61 default
parent child Browse files
Show More
@@ -1,123 +1,137 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import sys
22 import sys
23 import shutil
24 import logging
23 import logging
25 import tempfile
24 import tempfile
26 import textwrap
25 import textwrap
27
26 import collections
28 from .base import VcsServer
27 from .base import VcsServer
28 from rhodecode.model.settings import VcsSettingsModel
29
29
30 log = logging.getLogger(__name__)
30 log = logging.getLogger(__name__)
31
31
32
32
33 class MercurialTunnelWrapper(object):
33 class MercurialTunnelWrapper(object):
34 process = None
34 process = None
35
35
36 def __init__(self, server):
36 def __init__(self, server):
37 self.server = server
37 self.server = server
38 self.stdin = sys.stdin
38 self.stdin = sys.stdin
39 self.stdout = sys.stdout
39 self.stdout = sys.stdout
40 self.svn_conf_fd, self.svn_conf_path = tempfile.mkstemp()
40 self.hooks_env_fd, self.hooks_env_path = tempfile.mkstemp(prefix='hgrc_rhodecode_')
41 self.hooks_env_fd, self.hooks_env_path = tempfile.mkstemp()
42
41
43 def create_hooks_env(self):
42 def create_hooks_env(self):
43 repo_name = self.server.repo_name
44 hg_flags = self.config_to_hgrc(repo_name)
44
45
45 content = textwrap.dedent(
46 content = textwrap.dedent(
46 '''
47 '''
47 # SSH hooks version=1.0.0
48 # SSH hooks version=2.0.0
48 [hooks]
49 [hooks]
49 pretxnchangegroup.ssh_auth=python:vcsserver.hooks.pre_push_ssh_auth
50 pretxnchangegroup.ssh_auth=python:vcsserver.hooks.pre_push_ssh_auth
50 pretxnchangegroup.ssh=python:vcsserver.hooks.pre_push_ssh
51 pretxnchangegroup.ssh=python:vcsserver.hooks.pre_push_ssh
51 changegroup.ssh=python:vcsserver.hooks.post_push_ssh
52 changegroup.ssh=python:vcsserver.hooks.post_push_ssh
52
53
53 preoutgoing.ssh=python:vcsserver.hooks.pre_pull_ssh
54 preoutgoing.ssh=python:vcsserver.hooks.pre_pull_ssh
54 outgoing.ssh=python:vcsserver.hooks.post_pull_ssh
55 outgoing.ssh=python:vcsserver.hooks.post_pull_ssh
55
56
57 # Custom Config version=2.0.0
58 {custom}
56 '''
59 '''
57 )
60 ).format(custom='\n'.join(hg_flags))
61
62 root = self.server.get_root_store()
63 hgrc_custom = os.path.join(root, repo_name, '.hg', 'hgrc_rhodecode')
64 hgrc_main = os.path.join(root, repo_name, '.hg', 'hgrc')
58
65
66 # cleanup custom hgrc file
67 if os.path.isfile(hgrc_custom):
68 with open(hgrc_custom, 'wb') as f:
69 f.write('')
70 log.debug('Cleanup custom hgrc file under %s', hgrc_custom)
71
72 # write temp
59 with os.fdopen(self.hooks_env_fd, 'w') as hooks_env_file:
73 with os.fdopen(self.hooks_env_fd, 'w') as hooks_env_file:
60 hooks_env_file.write(content)
74 hooks_env_file.write(content)
61 root = self.server.get_root_store()
62
75
63 hgrc_custom = os.path.join(
76 return self.hooks_env_path
64 root, self.server.repo_name, '.hg', 'hgrc_rhodecode')
65 log.debug('Wrote custom hgrc file under %s', hgrc_custom)
66 shutil.move(
67 self.hooks_env_path, hgrc_custom)
68
69 hgrc_main = os.path.join(
70 root, self.server.repo_name, '.hg', 'hgrc')
71 include_marker = '%include hgrc_rhodecode'
72
77
73 if not os.path.isfile(hgrc_main):
78 def remove_configs(self):
74 os.mknod(hgrc_main)
79 os.remove(self.hooks_env_path)
75
76 with open(hgrc_main, 'rb') as f:
77 data = f.read()
78 has_marker = include_marker in data
79
80
80 if not has_marker:
81 def command(self, hgrc_path):
81 log.debug('Adding include marker for hooks')
82 with open(hgrc_main, 'wa') as f:
83 f.write(textwrap.dedent('''
84 # added by RhodeCode
85 {}
86 '''.format(include_marker)))
87
88 def command(self):
89 root = self.server.get_root_store()
82 root = self.server.get_root_store()
90
83
91 command = (
84 command = (
92 "cd {root}; {hg_path} -R {root}{repo_name} "
85 "cd {root}; HGRCPATH={hgrc} {hg_path} -R {root}{repo_name} "
93 "serve --stdio".format(
86 "serve --stdio".format(
94 root=root, hg_path=self.server.hg_path,
87 root=root, hg_path=self.server.hg_path,
95 repo_name=self.server.repo_name))
88 repo_name=self.server.repo_name, hgrc=hgrc_path))
96 log.debug("Final CMD: %s", command)
89 log.debug("Final CMD: %s", command)
97 return command
90 return command
98
91
99 def run(self, extras):
92 def run(self, extras):
100 # at this point we cannot tell, we do further ACL checks
93 # at this point we cannot tell, we do further ACL checks
101 # inside the hooks
94 # inside the hooks
102 action = '?'
95 action = '?'
103 # permissions are check via `pre_push_ssh_auth` hook
96 # permissions are check via `pre_push_ssh_auth` hook
104 self.server.update_environment(action=action, extras=extras)
97 self.server.update_environment(action=action, extras=extras)
105 self.create_hooks_env()
98 custom_hgrc_file = self.create_hooks_env()
106 return os.system(self.command())
99
100 try:
101 return os.system(self.command(custom_hgrc_file))
102 finally:
103 self.remove_configs()
107
104
108
105
109 class MercurialServer(VcsServer):
106 class MercurialServer(VcsServer):
110 backend = 'hg'
107 backend = 'hg'
108 cli_flags = ['phases', 'largefiles', 'extensions', 'experimental']
111
109
112 def __init__(self, store, ini_path, repo_name,
110 def __init__(self, store, ini_path, repo_name, user, user_permissions, config, env):
113 user, user_permissions, config, env):
111 super(MercurialServer, self).__init__(user, user_permissions, config, env)
114 super(MercurialServer, self).\
115 __init__(user, user_permissions, config, env)
116
112
117 self.store = store
113 self.store = store
118 self.ini_path = ini_path
114 self.ini_path = ini_path
119 self.repo_name = repo_name
115 self.repo_name = repo_name
120 self._path = self.hg_path = config.get(
116 self._path = self.hg_path = config.get('app:main', 'ssh.executable.hg')
121 'app:main', 'ssh.executable.hg')
117 self.tunnel = MercurialTunnelWrapper(server=self)
118
119 def config_to_hgrc(self, repo_name):
120 ui_sections = collections.defaultdict(list)
121 ui = VcsSettingsModel(repo=repo_name).get_ui_settings(section=None, key=None)
122
122
123 self.tunnel = MercurialTunnelWrapper(server=self)
123 for entry in ui:
124 if not entry.active:
125 continue
126 sec = entry.section
127
128 if sec in self.cli_flags:
129 ui_sections[sec].append([entry.key, entry.value])
130
131 flags = []
132 for _sec, key_val in ui_sections.items():
133 flags.append(' ')
134 flags.append('[{}]'.format(_sec))
135 for key, val in key_val:
136 flags.append('{}= {}'.format(key, val))
137 return flags
@@ -1,116 +1,119 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import mock
22 import mock
22 import pytest
23 import pytest
23
24
24 from rhodecode.apps.ssh_support.lib.backends.hg import MercurialServer
25 from rhodecode.apps.ssh_support.lib.backends.hg import MercurialServer
25 from rhodecode.apps.ssh_support.tests.conftest import plain_dummy_env, plain_dummy_user
26 from rhodecode.apps.ssh_support.tests.conftest import plain_dummy_env, plain_dummy_user
26
27
27
28
28 class MercurialServerCreator(object):
29 class MercurialServerCreator(object):
29 root = '/tmp/repo/path/'
30 root = '/tmp/repo/path/'
30 hg_path = '/usr/local/bin/hg'
31 hg_path = '/usr/local/bin/hg'
31
32
32 config_data = {
33 config_data = {
33 'app:main': {
34 'app:main': {
34 'ssh.executable.hg': hg_path,
35 'ssh.executable.hg': hg_path,
35 'vcs.hooks.protocol': 'http',
36 'vcs.hooks.protocol': 'http',
36 }
37 }
37 }
38 }
38 repo_name = 'test_hg'
39 repo_name = 'test_hg'
39 user = plain_dummy_user()
40 user = plain_dummy_user()
40
41
41 def __init__(self):
42 def __init__(self):
42 def config_get(part, key):
43 def config_get(part, key):
43 return self.config_data.get(part, {}).get(key)
44 return self.config_data.get(part, {}).get(key)
44 self.config_mock = mock.Mock()
45 self.config_mock = mock.Mock()
45 self.config_mock.get = mock.Mock(side_effect=config_get)
46 self.config_mock.get = mock.Mock(side_effect=config_get)
46
47
47 def create(self, **kwargs):
48 def create(self, **kwargs):
48 parameters = {
49 parameters = {
49 'store': self.root,
50 'store': self.root,
50 'ini_path': '',
51 'ini_path': '',
51 'user': self.user,
52 'user': self.user,
52 'repo_name': self.repo_name,
53 'repo_name': self.repo_name,
53 'user_permissions': {
54 'user_permissions': {
54 'test_hg': 'repository.admin'
55 'test_hg': 'repository.admin'
55 },
56 },
56 'config': self.config_mock,
57 'config': self.config_mock,
57 'env': plain_dummy_env()
58 'env': plain_dummy_env()
58 }
59 }
59 parameters.update(kwargs)
60 parameters.update(kwargs)
60 server = MercurialServer(**parameters)
61 server = MercurialServer(**parameters)
61 return server
62 return server
62
63
63
64
64 @pytest.fixture
65 @pytest.fixture
65 def hg_server(app):
66 def hg_server(app):
66 return MercurialServerCreator()
67 return MercurialServerCreator()
67
68
68
69
69 class TestMercurialServer(object):
70 class TestMercurialServer(object):
70
71
71 def test_command(self, hg_server):
72 def test_command(self, hg_server, tmpdir):
72 server = hg_server.create()
73 server = hg_server.create()
74 custom_hgrc = os.path.join(str(tmpdir), 'hgrc')
73 expected_command = (
75 expected_command = (
74 'cd {root}; {hg_path} -R {root}{repo_name} serve --stdio'.format(
76 'cd {root}; HGRCPATH={custom_hgrc} {hg_path} -R {root}{repo_name} serve --stdio'.format(
75 root=hg_server.root, hg_path=hg_server.hg_path,
77 root=hg_server.root, custom_hgrc=custom_hgrc, hg_path=hg_server.hg_path,
76 repo_name=hg_server.repo_name)
78 repo_name=hg_server.repo_name)
77 )
79 )
78 assert expected_command == server.tunnel.command()
80 server_command = server.tunnel.command(custom_hgrc)
81 assert expected_command == server_command
79
82
80 @pytest.mark.parametrize('permissions, action, code', [
83 @pytest.mark.parametrize('permissions, action, code', [
81 ({}, 'pull', -2),
84 ({}, 'pull', -2),
82 ({'test_hg': 'repository.read'}, 'pull', 0),
85 ({'test_hg': 'repository.read'}, 'pull', 0),
83 ({'test_hg': 'repository.read'}, 'push', -2),
86 ({'test_hg': 'repository.read'}, 'push', -2),
84 ({'test_hg': 'repository.write'}, 'push', 0),
87 ({'test_hg': 'repository.write'}, 'push', 0),
85 ({'test_hg': 'repository.admin'}, 'push', 0),
88 ({'test_hg': 'repository.admin'}, 'push', 0),
86
89
87 ])
90 ])
88 def test_permission_checks(self, hg_server, permissions, action, code):
91 def test_permission_checks(self, hg_server, permissions, action, code):
89 server = hg_server.create(user_permissions=permissions)
92 server = hg_server.create(user_permissions=permissions)
90 result = server._check_permissions(action)
93 result = server._check_permissions(action)
91 assert result is code
94 assert result is code
92
95
93 @pytest.mark.parametrize('permissions, value', [
96 @pytest.mark.parametrize('permissions, value', [
94 ({}, False),
97 ({}, False),
95 ({'test_hg': 'repository.read'}, False),
98 ({'test_hg': 'repository.read'}, False),
96 ({'test_hg': 'repository.write'}, True),
99 ({'test_hg': 'repository.write'}, True),
97 ({'test_hg': 'repository.admin'}, True),
100 ({'test_hg': 'repository.admin'}, True),
98
101
99 ])
102 ])
100 def test_has_write_permissions(self, hg_server, permissions, value):
103 def test_has_write_permissions(self, hg_server, permissions, value):
101 server = hg_server.create(user_permissions=permissions)
104 server = hg_server.create(user_permissions=permissions)
102 result = server.has_write_perm()
105 result = server.has_write_perm()
103 assert result is value
106 assert result is value
104
107
105 def test_run_returns_executes_command(self, hg_server):
108 def test_run_returns_executes_command(self, hg_server):
106 server = hg_server.create()
109 server = hg_server.create()
107 from rhodecode.apps.ssh_support.lib.backends.hg import MercurialTunnelWrapper
110 from rhodecode.apps.ssh_support.lib.backends.hg import MercurialTunnelWrapper
108 with mock.patch.object(MercurialTunnelWrapper, 'create_hooks_env') as _patch:
111 with mock.patch.object(MercurialTunnelWrapper, 'create_hooks_env') as _patch:
109 _patch.return_value = 0
112 _patch.return_value = 0
110 with mock.patch.object(MercurialTunnelWrapper, 'command', return_value='date'):
113 with mock.patch.object(MercurialTunnelWrapper, 'command', return_value='date'):
111 exit_code = server.run()
114 exit_code = server.run()
112
115
113 assert exit_code == (0, False)
116 assert exit_code == (0, False)
114
117
115
118
116
119
@@ -1,886 +1,888 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import hashlib
22 import hashlib
23 import logging
23 import logging
24 from collections import namedtuple
24 from collections import namedtuple
25 from functools import wraps
25 from functools import wraps
26 import bleach
26 import bleach
27
27
28 from rhodecode.lib import rc_cache
28 from rhodecode.lib import rc_cache
29 from rhodecode.lib.utils2 import (
29 from rhodecode.lib.utils2 import (
30 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
30 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
31 from rhodecode.lib.vcs.backends import base
31 from rhodecode.lib.vcs.backends import base
32 from rhodecode.model import BaseModel
32 from rhodecode.model import BaseModel
33 from rhodecode.model.db import (
33 from rhodecode.model.db import (
34 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting, CacheKey)
34 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting, CacheKey)
35 from rhodecode.model.meta import Session
35 from rhodecode.model.meta import Session
36
36
37
37
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
40
40
41 UiSetting = namedtuple(
41 UiSetting = namedtuple(
42 'UiSetting', ['section', 'key', 'value', 'active'])
42 'UiSetting', ['section', 'key', 'value', 'active'])
43
43
44 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
44 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
45
45
46
46
47 class SettingNotFound(Exception):
47 class SettingNotFound(Exception):
48 def __init__(self, setting_id):
48 def __init__(self, setting_id):
49 msg = 'Setting `{}` is not found'.format(setting_id)
49 msg = 'Setting `{}` is not found'.format(setting_id)
50 super(SettingNotFound, self).__init__(msg)
50 super(SettingNotFound, self).__init__(msg)
51
51
52
52
53 class SettingsModel(BaseModel):
53 class SettingsModel(BaseModel):
54 BUILTIN_HOOKS = (
54 BUILTIN_HOOKS = (
55 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
55 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
56 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
56 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
57 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL,
57 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL,
58 RhodeCodeUi.HOOK_PUSH_KEY,)
58 RhodeCodeUi.HOOK_PUSH_KEY,)
59 HOOKS_SECTION = 'hooks'
59 HOOKS_SECTION = 'hooks'
60
60
61 def __init__(self, sa=None, repo=None):
61 def __init__(self, sa=None, repo=None):
62 self.repo = repo
62 self.repo = repo
63 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
63 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
64 self.SettingsDbModel = (
64 self.SettingsDbModel = (
65 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
65 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
66 super(SettingsModel, self).__init__(sa)
66 super(SettingsModel, self).__init__(sa)
67
67
68 def get_ui_by_key(self, key):
68 def get_ui_by_key(self, key):
69 q = self.UiDbModel.query()
69 q = self.UiDbModel.query()
70 q = q.filter(self.UiDbModel.ui_key == key)
70 q = q.filter(self.UiDbModel.ui_key == key)
71 q = self._filter_by_repo(RepoRhodeCodeUi, q)
71 q = self._filter_by_repo(RepoRhodeCodeUi, q)
72 return q.scalar()
72 return q.scalar()
73
73
74 def get_ui_by_section(self, section):
74 def get_ui_by_section(self, section):
75 q = self.UiDbModel.query()
75 q = self.UiDbModel.query()
76 q = q.filter(self.UiDbModel.ui_section == section)
76 q = q.filter(self.UiDbModel.ui_section == section)
77 q = self._filter_by_repo(RepoRhodeCodeUi, q)
77 q = self._filter_by_repo(RepoRhodeCodeUi, q)
78 return q.all()
78 return q.all()
79
79
80 def get_ui_by_section_and_key(self, section, key):
80 def get_ui_by_section_and_key(self, section, key):
81 q = self.UiDbModel.query()
81 q = self.UiDbModel.query()
82 q = q.filter(self.UiDbModel.ui_section == section)
82 q = q.filter(self.UiDbModel.ui_section == section)
83 q = q.filter(self.UiDbModel.ui_key == key)
83 q = q.filter(self.UiDbModel.ui_key == key)
84 q = self._filter_by_repo(RepoRhodeCodeUi, q)
84 q = self._filter_by_repo(RepoRhodeCodeUi, q)
85 return q.scalar()
85 return q.scalar()
86
86
87 def get_ui(self, section=None, key=None):
87 def get_ui(self, section=None, key=None):
88 q = self.UiDbModel.query()
88 q = self.UiDbModel.query()
89 q = self._filter_by_repo(RepoRhodeCodeUi, q)
89 q = self._filter_by_repo(RepoRhodeCodeUi, q)
90
90
91 if section:
91 if section:
92 q = q.filter(self.UiDbModel.ui_section == section)
92 q = q.filter(self.UiDbModel.ui_section == section)
93 if key:
93 if key:
94 q = q.filter(self.UiDbModel.ui_key == key)
94 q = q.filter(self.UiDbModel.ui_key == key)
95
95
96 # TODO: mikhail: add caching
96 # TODO: mikhail: add caching
97 result = [
97 result = [
98 UiSetting(
98 UiSetting(
99 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
99 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
100 value=safe_str(r.ui_value), active=r.ui_active
100 value=safe_str(r.ui_value), active=r.ui_active
101 )
101 )
102 for r in q.all()
102 for r in q.all()
103 ]
103 ]
104 return result
104 return result
105
105
106 def get_builtin_hooks(self):
106 def get_builtin_hooks(self):
107 q = self.UiDbModel.query()
107 q = self.UiDbModel.query()
108 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
108 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
109 return self._get_hooks(q)
109 return self._get_hooks(q)
110
110
111 def get_custom_hooks(self):
111 def get_custom_hooks(self):
112 q = self.UiDbModel.query()
112 q = self.UiDbModel.query()
113 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
113 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
114 return self._get_hooks(q)
114 return self._get_hooks(q)
115
115
116 def create_ui_section_value(self, section, val, key=None, active=True):
116 def create_ui_section_value(self, section, val, key=None, active=True):
117 new_ui = self.UiDbModel()
117 new_ui = self.UiDbModel()
118 new_ui.ui_section = section
118 new_ui.ui_section = section
119 new_ui.ui_value = val
119 new_ui.ui_value = val
120 new_ui.ui_active = active
120 new_ui.ui_active = active
121
121
122 repository_id = ''
122 repository_id = ''
123 if self.repo:
123 if self.repo:
124 repo = self._get_repo(self.repo)
124 repo = self._get_repo(self.repo)
125 repository_id = repo.repo_id
125 repository_id = repo.repo_id
126 new_ui.repository_id = repository_id
126 new_ui.repository_id = repository_id
127
127
128 if not key:
128 if not key:
129 # keys are unique so they need appended info
129 # keys are unique so they need appended info
130 if self.repo:
130 if self.repo:
131 key = hashlib.sha1(
131 key = hashlib.sha1(
132 '{}{}{}'.format(section, val, repository_id)).hexdigest()
132 '{}{}{}'.format(section, val, repository_id)).hexdigest()
133 else:
133 else:
134 key = hashlib.sha1('{}{}'.format(section, val)).hexdigest()
134 key = hashlib.sha1('{}{}'.format(section, val)).hexdigest()
135
135
136 new_ui.ui_key = key
136 new_ui.ui_key = key
137
137
138 Session().add(new_ui)
138 Session().add(new_ui)
139 return new_ui
139 return new_ui
140
140
141 def create_or_update_hook(self, key, value):
141 def create_or_update_hook(self, key, value):
142 ui = (
142 ui = (
143 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
143 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
144 self.UiDbModel())
144 self.UiDbModel())
145 ui.ui_section = self.HOOKS_SECTION
145 ui.ui_section = self.HOOKS_SECTION
146 ui.ui_active = True
146 ui.ui_active = True
147 ui.ui_key = key
147 ui.ui_key = key
148 ui.ui_value = value
148 ui.ui_value = value
149
149
150 if self.repo:
150 if self.repo:
151 repo = self._get_repo(self.repo)
151 repo = self._get_repo(self.repo)
152 repository_id = repo.repo_id
152 repository_id = repo.repo_id
153 ui.repository_id = repository_id
153 ui.repository_id = repository_id
154
154
155 Session().add(ui)
155 Session().add(ui)
156 return ui
156 return ui
157
157
158 def delete_ui(self, id_):
158 def delete_ui(self, id_):
159 ui = self.UiDbModel.get(id_)
159 ui = self.UiDbModel.get(id_)
160 if not ui:
160 if not ui:
161 raise SettingNotFound(id_)
161 raise SettingNotFound(id_)
162 Session().delete(ui)
162 Session().delete(ui)
163
163
164 def get_setting_by_name(self, name):
164 def get_setting_by_name(self, name):
165 q = self._get_settings_query()
165 q = self._get_settings_query()
166 q = q.filter(self.SettingsDbModel.app_settings_name == name)
166 q = q.filter(self.SettingsDbModel.app_settings_name == name)
167 return q.scalar()
167 return q.scalar()
168
168
169 def create_or_update_setting(
169 def create_or_update_setting(
170 self, name, val=Optional(''), type_=Optional('unicode')):
170 self, name, val=Optional(''), type_=Optional('unicode')):
171 """
171 """
172 Creates or updates RhodeCode setting. If updates is triggered it will
172 Creates or updates RhodeCode setting. If updates is triggered it will
173 only update parameters that are explicityl set Optional instance will
173 only update parameters that are explicityl set Optional instance will
174 be skipped
174 be skipped
175
175
176 :param name:
176 :param name:
177 :param val:
177 :param val:
178 :param type_:
178 :param type_:
179 :return:
179 :return:
180 """
180 """
181
181
182 res = self.get_setting_by_name(name)
182 res = self.get_setting_by_name(name)
183 repo = self._get_repo(self.repo) if self.repo else None
183 repo = self._get_repo(self.repo) if self.repo else None
184
184
185 if not res:
185 if not res:
186 val = Optional.extract(val)
186 val = Optional.extract(val)
187 type_ = Optional.extract(type_)
187 type_ = Optional.extract(type_)
188
188
189 args = (
189 args = (
190 (repo.repo_id, name, val, type_)
190 (repo.repo_id, name, val, type_)
191 if repo else (name, val, type_))
191 if repo else (name, val, type_))
192 res = self.SettingsDbModel(*args)
192 res = self.SettingsDbModel(*args)
193
193
194 else:
194 else:
195 if self.repo:
195 if self.repo:
196 res.repository_id = repo.repo_id
196 res.repository_id = repo.repo_id
197
197
198 res.app_settings_name = name
198 res.app_settings_name = name
199 if not isinstance(type_, Optional):
199 if not isinstance(type_, Optional):
200 # update if set
200 # update if set
201 res.app_settings_type = type_
201 res.app_settings_type = type_
202 if not isinstance(val, Optional):
202 if not isinstance(val, Optional):
203 # update if set
203 # update if set
204 res.app_settings_value = val
204 res.app_settings_value = val
205
205
206 Session().add(res)
206 Session().add(res)
207 return res
207 return res
208
208
209 def invalidate_settings_cache(self):
209 def invalidate_settings_cache(self):
210 invalidation_namespace = CacheKey.SETTINGS_INVALIDATION_NAMESPACE
210 invalidation_namespace = CacheKey.SETTINGS_INVALIDATION_NAMESPACE
211 CacheKey.set_invalidate(invalidation_namespace)
211 CacheKey.set_invalidate(invalidation_namespace)
212
212
213 def get_all_settings(self, cache=False):
213 def get_all_settings(self, cache=False):
214 region = rc_cache.get_or_create_region('sql_cache_short')
214 region = rc_cache.get_or_create_region('sql_cache_short')
215 invalidation_namespace = CacheKey.SETTINGS_INVALIDATION_NAMESPACE
215 invalidation_namespace = CacheKey.SETTINGS_INVALIDATION_NAMESPACE
216
216
217 @region.conditional_cache_on_arguments(condition=cache)
217 @region.conditional_cache_on_arguments(condition=cache)
218 def _get_all_settings(name, key):
218 def _get_all_settings(name, key):
219 q = self._get_settings_query()
219 q = self._get_settings_query()
220 if not q:
220 if not q:
221 raise Exception('Could not get application settings !')
221 raise Exception('Could not get application settings !')
222
222
223 settings = {
223 settings = {
224 'rhodecode_' + result.app_settings_name: result.app_settings_value
224 'rhodecode_' + result.app_settings_name: result.app_settings_value
225 for result in q
225 for result in q
226 }
226 }
227 return settings
227 return settings
228
228
229 repo = self._get_repo(self.repo) if self.repo else None
229 repo = self._get_repo(self.repo) if self.repo else None
230 key = "settings_repo.{}".format(repo.repo_id) if repo else "settings_app"
230 key = "settings_repo.{}".format(repo.repo_id) if repo else "settings_app"
231
231
232 inv_context_manager = rc_cache.InvalidationContext(
232 inv_context_manager = rc_cache.InvalidationContext(
233 uid='cache_settings', invalidation_namespace=invalidation_namespace)
233 uid='cache_settings', invalidation_namespace=invalidation_namespace)
234 with inv_context_manager as invalidation_context:
234 with inv_context_manager as invalidation_context:
235 # check for stored invalidation signal, and maybe purge the cache
235 # check for stored invalidation signal, and maybe purge the cache
236 # before computing it again
236 # before computing it again
237 if invalidation_context.should_invalidate():
237 if invalidation_context.should_invalidate():
238 # NOTE:(marcink) we flush the whole sql_cache_short region, because it
238 # NOTE:(marcink) we flush the whole sql_cache_short region, because it
239 # reads different settings etc. It's little too much but those caches
239 # reads different settings etc. It's little too much but those caches
240 # are anyway very short lived and it's a safest way.
240 # are anyway very short lived and it's a safest way.
241 region = rc_cache.get_or_create_region('sql_cache_short')
241 region = rc_cache.get_or_create_region('sql_cache_short')
242 region.invalidate()
242 region.invalidate()
243
243
244 result = _get_all_settings('rhodecode_settings', key)
244 result = _get_all_settings('rhodecode_settings', key)
245 log.debug('Fetching app settings for key: %s took: %.3fs', key,
245 log.debug('Fetching app settings for key: %s took: %.3fs', key,
246 inv_context_manager.compute_time)
246 inv_context_manager.compute_time)
247
247
248 return result
248 return result
249
249
250 def get_auth_settings(self):
250 def get_auth_settings(self):
251 q = self._get_settings_query()
251 q = self._get_settings_query()
252 q = q.filter(
252 q = q.filter(
253 self.SettingsDbModel.app_settings_name.startswith('auth_'))
253 self.SettingsDbModel.app_settings_name.startswith('auth_'))
254 rows = q.all()
254 rows = q.all()
255 auth_settings = {
255 auth_settings = {
256 row.app_settings_name: row.app_settings_value for row in rows}
256 row.app_settings_name: row.app_settings_value for row in rows}
257 return auth_settings
257 return auth_settings
258
258
259 def get_auth_plugins(self):
259 def get_auth_plugins(self):
260 auth_plugins = self.get_setting_by_name("auth_plugins")
260 auth_plugins = self.get_setting_by_name("auth_plugins")
261 return auth_plugins.app_settings_value
261 return auth_plugins.app_settings_value
262
262
263 def get_default_repo_settings(self, strip_prefix=False):
263 def get_default_repo_settings(self, strip_prefix=False):
264 q = self._get_settings_query()
264 q = self._get_settings_query()
265 q = q.filter(
265 q = q.filter(
266 self.SettingsDbModel.app_settings_name.startswith('default_'))
266 self.SettingsDbModel.app_settings_name.startswith('default_'))
267 rows = q.all()
267 rows = q.all()
268
268
269 result = {}
269 result = {}
270 for row in rows:
270 for row in rows:
271 key = row.app_settings_name
271 key = row.app_settings_name
272 if strip_prefix:
272 if strip_prefix:
273 key = remove_prefix(key, prefix='default_')
273 key = remove_prefix(key, prefix='default_')
274 result.update({key: row.app_settings_value})
274 result.update({key: row.app_settings_value})
275 return result
275 return result
276
276
277 def get_repo(self):
277 def get_repo(self):
278 repo = self._get_repo(self.repo)
278 repo = self._get_repo(self.repo)
279 if not repo:
279 if not repo:
280 raise Exception(
280 raise Exception(
281 'Repository `{}` cannot be found inside the database'.format(
281 'Repository `{}` cannot be found inside the database'.format(
282 self.repo))
282 self.repo))
283 return repo
283 return repo
284
284
285 def _filter_by_repo(self, model, query):
285 def _filter_by_repo(self, model, query):
286 if self.repo:
286 if self.repo:
287 repo = self.get_repo()
287 repo = self.get_repo()
288 query = query.filter(model.repository_id == repo.repo_id)
288 query = query.filter(model.repository_id == repo.repo_id)
289 return query
289 return query
290
290
291 def _get_hooks(self, query):
291 def _get_hooks(self, query):
292 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
292 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
293 query = self._filter_by_repo(RepoRhodeCodeUi, query)
293 query = self._filter_by_repo(RepoRhodeCodeUi, query)
294 return query.all()
294 return query.all()
295
295
296 def _get_settings_query(self):
296 def _get_settings_query(self):
297 q = self.SettingsDbModel.query()
297 q = self.SettingsDbModel.query()
298 return self._filter_by_repo(RepoRhodeCodeSetting, q)
298 return self._filter_by_repo(RepoRhodeCodeSetting, q)
299
299
300 def list_enabled_social_plugins(self, settings):
300 def list_enabled_social_plugins(self, settings):
301 enabled = []
301 enabled = []
302 for plug in SOCIAL_PLUGINS_LIST:
302 for plug in SOCIAL_PLUGINS_LIST:
303 if str2bool(settings.get('rhodecode_auth_{}_enabled'.format(plug)
303 if str2bool(settings.get('rhodecode_auth_{}_enabled'.format(plug)
304 )):
304 )):
305 enabled.append(plug)
305 enabled.append(plug)
306 return enabled
306 return enabled
307
307
308
308
309 def assert_repo_settings(func):
309 def assert_repo_settings(func):
310 @wraps(func)
310 @wraps(func)
311 def _wrapper(self, *args, **kwargs):
311 def _wrapper(self, *args, **kwargs):
312 if not self.repo_settings:
312 if not self.repo_settings:
313 raise Exception('Repository is not specified')
313 raise Exception('Repository is not specified')
314 return func(self, *args, **kwargs)
314 return func(self, *args, **kwargs)
315 return _wrapper
315 return _wrapper
316
316
317
317
318 class IssueTrackerSettingsModel(object):
318 class IssueTrackerSettingsModel(object):
319 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
319 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
320 SETTINGS_PREFIX = 'issuetracker_'
320 SETTINGS_PREFIX = 'issuetracker_'
321
321
322 def __init__(self, sa=None, repo=None):
322 def __init__(self, sa=None, repo=None):
323 self.global_settings = SettingsModel(sa=sa)
323 self.global_settings = SettingsModel(sa=sa)
324 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
324 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
325
325
326 @property
326 @property
327 def inherit_global_settings(self):
327 def inherit_global_settings(self):
328 if not self.repo_settings:
328 if not self.repo_settings:
329 return True
329 return True
330 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
330 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
331 return setting.app_settings_value if setting else True
331 return setting.app_settings_value if setting else True
332
332
333 @inherit_global_settings.setter
333 @inherit_global_settings.setter
334 def inherit_global_settings(self, value):
334 def inherit_global_settings(self, value):
335 if self.repo_settings:
335 if self.repo_settings:
336 settings = self.repo_settings.create_or_update_setting(
336 settings = self.repo_settings.create_or_update_setting(
337 self.INHERIT_SETTINGS, value, type_='bool')
337 self.INHERIT_SETTINGS, value, type_='bool')
338 Session().add(settings)
338 Session().add(settings)
339
339
340 def _get_keyname(self, key, uid, prefix=''):
340 def _get_keyname(self, key, uid, prefix=''):
341 return '{0}{1}{2}_{3}'.format(
341 return '{0}{1}{2}_{3}'.format(
342 prefix, self.SETTINGS_PREFIX, key, uid)
342 prefix, self.SETTINGS_PREFIX, key, uid)
343
343
344 def _make_dict_for_settings(self, qs):
344 def _make_dict_for_settings(self, qs):
345 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
345 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
346
346
347 issuetracker_entries = {}
347 issuetracker_entries = {}
348 # create keys
348 # create keys
349 for k, v in qs.items():
349 for k, v in qs.items():
350 if k.startswith(prefix_match):
350 if k.startswith(prefix_match):
351 uid = k[len(prefix_match):]
351 uid = k[len(prefix_match):]
352 issuetracker_entries[uid] = None
352 issuetracker_entries[uid] = None
353
353
354 def url_cleaner(input_str):
354 def url_cleaner(input_str):
355 input_str = input_str.replace('"', '').replace("'", '')
355 input_str = input_str.replace('"', '').replace("'", '')
356 input_str = bleach.clean(input_str, strip=True)
356 input_str = bleach.clean(input_str, strip=True)
357 return input_str
357 return input_str
358
358
359 # populate
359 # populate
360 for uid in issuetracker_entries:
360 for uid in issuetracker_entries:
361 url_data = qs.get(self._get_keyname('url', uid, 'rhodecode_'))
361 url_data = qs.get(self._get_keyname('url', uid, 'rhodecode_'))
362
362
363 issuetracker_entries[uid] = AttributeDict({
363 issuetracker_entries[uid] = AttributeDict({
364 'pat': qs.get(
364 'pat': qs.get(
365 self._get_keyname('pat', uid, 'rhodecode_')),
365 self._get_keyname('pat', uid, 'rhodecode_')),
366 'url': url_cleaner(
366 'url': url_cleaner(
367 qs.get(self._get_keyname('url', uid, 'rhodecode_')) or ''),
367 qs.get(self._get_keyname('url', uid, 'rhodecode_')) or ''),
368 'pref': bleach.clean(
368 'pref': bleach.clean(
369 qs.get(self._get_keyname('pref', uid, 'rhodecode_')) or ''),
369 qs.get(self._get_keyname('pref', uid, 'rhodecode_')) or ''),
370 'desc': qs.get(
370 'desc': qs.get(
371 self._get_keyname('desc', uid, 'rhodecode_')),
371 self._get_keyname('desc', uid, 'rhodecode_')),
372 })
372 })
373
373
374 return issuetracker_entries
374 return issuetracker_entries
375
375
376 def get_global_settings(self, cache=False):
376 def get_global_settings(self, cache=False):
377 """
377 """
378 Returns list of global issue tracker settings
378 Returns list of global issue tracker settings
379 """
379 """
380 defaults = self.global_settings.get_all_settings(cache=cache)
380 defaults = self.global_settings.get_all_settings(cache=cache)
381 settings = self._make_dict_for_settings(defaults)
381 settings = self._make_dict_for_settings(defaults)
382 return settings
382 return settings
383
383
384 def get_repo_settings(self, cache=False):
384 def get_repo_settings(self, cache=False):
385 """
385 """
386 Returns list of issue tracker settings per repository
386 Returns list of issue tracker settings per repository
387 """
387 """
388 if not self.repo_settings:
388 if not self.repo_settings:
389 raise Exception('Repository is not specified')
389 raise Exception('Repository is not specified')
390 all_settings = self.repo_settings.get_all_settings(cache=cache)
390 all_settings = self.repo_settings.get_all_settings(cache=cache)
391 settings = self._make_dict_for_settings(all_settings)
391 settings = self._make_dict_for_settings(all_settings)
392 return settings
392 return settings
393
393
394 def get_settings(self, cache=False):
394 def get_settings(self, cache=False):
395 if self.inherit_global_settings:
395 if self.inherit_global_settings:
396 return self.get_global_settings(cache=cache)
396 return self.get_global_settings(cache=cache)
397 else:
397 else:
398 return self.get_repo_settings(cache=cache)
398 return self.get_repo_settings(cache=cache)
399
399
400 def delete_entries(self, uid):
400 def delete_entries(self, uid):
401 if self.repo_settings:
401 if self.repo_settings:
402 all_patterns = self.get_repo_settings()
402 all_patterns = self.get_repo_settings()
403 settings_model = self.repo_settings
403 settings_model = self.repo_settings
404 else:
404 else:
405 all_patterns = self.get_global_settings()
405 all_patterns = self.get_global_settings()
406 settings_model = self.global_settings
406 settings_model = self.global_settings
407 entries = all_patterns.get(uid, [])
407 entries = all_patterns.get(uid, [])
408
408
409 for del_key in entries:
409 for del_key in entries:
410 setting_name = self._get_keyname(del_key, uid)
410 setting_name = self._get_keyname(del_key, uid)
411 entry = settings_model.get_setting_by_name(setting_name)
411 entry = settings_model.get_setting_by_name(setting_name)
412 if entry:
412 if entry:
413 Session().delete(entry)
413 Session().delete(entry)
414
414
415 Session().commit()
415 Session().commit()
416
416
417 def create_or_update_setting(
417 def create_or_update_setting(
418 self, name, val=Optional(''), type_=Optional('unicode')):
418 self, name, val=Optional(''), type_=Optional('unicode')):
419 if self.repo_settings:
419 if self.repo_settings:
420 setting = self.repo_settings.create_or_update_setting(
420 setting = self.repo_settings.create_or_update_setting(
421 name, val, type_)
421 name, val, type_)
422 else:
422 else:
423 setting = self.global_settings.create_or_update_setting(
423 setting = self.global_settings.create_or_update_setting(
424 name, val, type_)
424 name, val, type_)
425 return setting
425 return setting
426
426
427
427
428 class VcsSettingsModel(object):
428 class VcsSettingsModel(object):
429
429
430 INHERIT_SETTINGS = 'inherit_vcs_settings'
430 INHERIT_SETTINGS = 'inherit_vcs_settings'
431 GENERAL_SETTINGS = (
431 GENERAL_SETTINGS = (
432 'use_outdated_comments',
432 'use_outdated_comments',
433 'pr_merge_enabled',
433 'pr_merge_enabled',
434 'hg_use_rebase_for_merging',
434 'hg_use_rebase_for_merging',
435 'hg_close_branch_before_merging',
435 'hg_close_branch_before_merging',
436 'git_use_rebase_for_merging',
436 'git_use_rebase_for_merging',
437 'git_close_branch_before_merging',
437 'git_close_branch_before_merging',
438 'diff_cache',
438 'diff_cache',
439 )
439 )
440
440
441 HOOKS_SETTINGS = (
441 HOOKS_SETTINGS = (
442 ('hooks', 'changegroup.repo_size'),
442 ('hooks', 'changegroup.repo_size'),
443 ('hooks', 'changegroup.push_logger'),
443 ('hooks', 'changegroup.push_logger'),
444 ('hooks', 'outgoing.pull_logger'),
444 ('hooks', 'outgoing.pull_logger'),
445 )
445 )
446 HG_SETTINGS = (
446 HG_SETTINGS = (
447 ('extensions', 'largefiles'),
447 ('extensions', 'largefiles'),
448 ('phases', 'publish'),
448 ('phases', 'publish'),
449 ('extensions', 'evolve'),
449 ('extensions', 'evolve'),
450 ('extensions', 'topic'),
450 ('extensions', 'topic'),
451 ('experimental', 'evolution'),
451 ('experimental', 'evolution'),
452 ('experimental', 'evolution.exchange'),
452 )
453 )
453 GIT_SETTINGS = (
454 GIT_SETTINGS = (
454 ('vcs_git_lfs', 'enabled'),
455 ('vcs_git_lfs', 'enabled'),
455 )
456 )
456 GLOBAL_HG_SETTINGS = (
457 GLOBAL_HG_SETTINGS = (
457 ('extensions', 'largefiles'),
458 ('extensions', 'largefiles'),
458 ('largefiles', 'usercache'),
459 ('largefiles', 'usercache'),
459 ('phases', 'publish'),
460 ('phases', 'publish'),
460 ('extensions', 'hgsubversion'),
461 ('extensions', 'hgsubversion'),
461 ('extensions', 'evolve'),
462 ('extensions', 'evolve'),
462 ('extensions', 'topic'),
463 ('extensions', 'topic'),
463 ('experimental', 'evolution'),
464 ('experimental', 'evolution'),
465 ('experimental', 'evolution.exchange'),
464 )
466 )
465
467
466 GLOBAL_GIT_SETTINGS = (
468 GLOBAL_GIT_SETTINGS = (
467 ('vcs_git_lfs', 'enabled'),
469 ('vcs_git_lfs', 'enabled'),
468 ('vcs_git_lfs', 'store_location')
470 ('vcs_git_lfs', 'store_location')
469 )
471 )
470
472
471 GLOBAL_SVN_SETTINGS = (
473 GLOBAL_SVN_SETTINGS = (
472 ('vcs_svn_proxy', 'http_requests_enabled'),
474 ('vcs_svn_proxy', 'http_requests_enabled'),
473 ('vcs_svn_proxy', 'http_server_url')
475 ('vcs_svn_proxy', 'http_server_url')
474 )
476 )
475
477
476 SVN_BRANCH_SECTION = 'vcs_svn_branch'
478 SVN_BRANCH_SECTION = 'vcs_svn_branch'
477 SVN_TAG_SECTION = 'vcs_svn_tag'
479 SVN_TAG_SECTION = 'vcs_svn_tag'
478 SSL_SETTING = ('web', 'push_ssl')
480 SSL_SETTING = ('web', 'push_ssl')
479 PATH_SETTING = ('paths', '/')
481 PATH_SETTING = ('paths', '/')
480
482
481 def __init__(self, sa=None, repo=None):
483 def __init__(self, sa=None, repo=None):
482 self.global_settings = SettingsModel(sa=sa)
484 self.global_settings = SettingsModel(sa=sa)
483 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
485 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
484 self._ui_settings = (
486 self._ui_settings = (
485 self.HG_SETTINGS + self.GIT_SETTINGS + self.HOOKS_SETTINGS)
487 self.HG_SETTINGS + self.GIT_SETTINGS + self.HOOKS_SETTINGS)
486 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
488 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
487
489
488 @property
490 @property
489 @assert_repo_settings
491 @assert_repo_settings
490 def inherit_global_settings(self):
492 def inherit_global_settings(self):
491 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
493 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
492 return setting.app_settings_value if setting else True
494 return setting.app_settings_value if setting else True
493
495
494 @inherit_global_settings.setter
496 @inherit_global_settings.setter
495 @assert_repo_settings
497 @assert_repo_settings
496 def inherit_global_settings(self, value):
498 def inherit_global_settings(self, value):
497 self.repo_settings.create_or_update_setting(
499 self.repo_settings.create_or_update_setting(
498 self.INHERIT_SETTINGS, value, type_='bool')
500 self.INHERIT_SETTINGS, value, type_='bool')
499
501
500 def get_global_svn_branch_patterns(self):
502 def get_global_svn_branch_patterns(self):
501 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
503 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
502
504
503 @assert_repo_settings
505 @assert_repo_settings
504 def get_repo_svn_branch_patterns(self):
506 def get_repo_svn_branch_patterns(self):
505 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
507 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
506
508
507 def get_global_svn_tag_patterns(self):
509 def get_global_svn_tag_patterns(self):
508 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
510 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
509
511
510 @assert_repo_settings
512 @assert_repo_settings
511 def get_repo_svn_tag_patterns(self):
513 def get_repo_svn_tag_patterns(self):
512 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
514 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
513
515
514 def get_global_settings(self):
516 def get_global_settings(self):
515 return self._collect_all_settings(global_=True)
517 return self._collect_all_settings(global_=True)
516
518
517 @assert_repo_settings
519 @assert_repo_settings
518 def get_repo_settings(self):
520 def get_repo_settings(self):
519 return self._collect_all_settings(global_=False)
521 return self._collect_all_settings(global_=False)
520
522
521 @assert_repo_settings
523 @assert_repo_settings
522 def create_or_update_repo_settings(
524 def create_or_update_repo_settings(
523 self, data, inherit_global_settings=False):
525 self, data, inherit_global_settings=False):
524 from rhodecode.model.scm import ScmModel
526 from rhodecode.model.scm import ScmModel
525
527
526 self.inherit_global_settings = inherit_global_settings
528 self.inherit_global_settings = inherit_global_settings
527
529
528 repo = self.repo_settings.get_repo()
530 repo = self.repo_settings.get_repo()
529 if not inherit_global_settings:
531 if not inherit_global_settings:
530 if repo.repo_type == 'svn':
532 if repo.repo_type == 'svn':
531 self.create_repo_svn_settings(data)
533 self.create_repo_svn_settings(data)
532 else:
534 else:
533 self.create_or_update_repo_hook_settings(data)
535 self.create_or_update_repo_hook_settings(data)
534 self.create_or_update_repo_pr_settings(data)
536 self.create_or_update_repo_pr_settings(data)
535
537
536 if repo.repo_type == 'hg':
538 if repo.repo_type == 'hg':
537 self.create_or_update_repo_hg_settings(data)
539 self.create_or_update_repo_hg_settings(data)
538
540
539 if repo.repo_type == 'git':
541 if repo.repo_type == 'git':
540 self.create_or_update_repo_git_settings(data)
542 self.create_or_update_repo_git_settings(data)
541
543
542 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
544 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
543
545
544 @assert_repo_settings
546 @assert_repo_settings
545 def create_or_update_repo_hook_settings(self, data):
547 def create_or_update_repo_hook_settings(self, data):
546 for section, key in self.HOOKS_SETTINGS:
548 for section, key in self.HOOKS_SETTINGS:
547 data_key = self._get_form_ui_key(section, key)
549 data_key = self._get_form_ui_key(section, key)
548 if data_key not in data:
550 if data_key not in data:
549 raise ValueError(
551 raise ValueError(
550 'The given data does not contain {} key'.format(data_key))
552 'The given data does not contain {} key'.format(data_key))
551
553
552 active = data.get(data_key)
554 active = data.get(data_key)
553 repo_setting = self.repo_settings.get_ui_by_section_and_key(
555 repo_setting = self.repo_settings.get_ui_by_section_and_key(
554 section, key)
556 section, key)
555 if not repo_setting:
557 if not repo_setting:
556 global_setting = self.global_settings.\
558 global_setting = self.global_settings.\
557 get_ui_by_section_and_key(section, key)
559 get_ui_by_section_and_key(section, key)
558 self.repo_settings.create_ui_section_value(
560 self.repo_settings.create_ui_section_value(
559 section, global_setting.ui_value, key=key, active=active)
561 section, global_setting.ui_value, key=key, active=active)
560 else:
562 else:
561 repo_setting.ui_active = active
563 repo_setting.ui_active = active
562 Session().add(repo_setting)
564 Session().add(repo_setting)
563
565
564 def update_global_hook_settings(self, data):
566 def update_global_hook_settings(self, data):
565 for section, key in self.HOOKS_SETTINGS:
567 for section, key in self.HOOKS_SETTINGS:
566 data_key = self._get_form_ui_key(section, key)
568 data_key = self._get_form_ui_key(section, key)
567 if data_key not in data:
569 if data_key not in data:
568 raise ValueError(
570 raise ValueError(
569 'The given data does not contain {} key'.format(data_key))
571 'The given data does not contain {} key'.format(data_key))
570 active = data.get(data_key)
572 active = data.get(data_key)
571 repo_setting = self.global_settings.get_ui_by_section_and_key(
573 repo_setting = self.global_settings.get_ui_by_section_and_key(
572 section, key)
574 section, key)
573 repo_setting.ui_active = active
575 repo_setting.ui_active = active
574 Session().add(repo_setting)
576 Session().add(repo_setting)
575
577
576 @assert_repo_settings
578 @assert_repo_settings
577 def create_or_update_repo_pr_settings(self, data):
579 def create_or_update_repo_pr_settings(self, data):
578 return self._create_or_update_general_settings(
580 return self._create_or_update_general_settings(
579 self.repo_settings, data)
581 self.repo_settings, data)
580
582
581 def create_or_update_global_pr_settings(self, data):
583 def create_or_update_global_pr_settings(self, data):
582 return self._create_or_update_general_settings(
584 return self._create_or_update_general_settings(
583 self.global_settings, data)
585 self.global_settings, data)
584
586
585 @assert_repo_settings
587 @assert_repo_settings
586 def create_repo_svn_settings(self, data):
588 def create_repo_svn_settings(self, data):
587 return self._create_svn_settings(self.repo_settings, data)
589 return self._create_svn_settings(self.repo_settings, data)
588
590
589 def _set_evolution(self, settings, is_enabled):
591 def _set_evolution(self, settings, is_enabled):
590 if is_enabled:
592 if is_enabled:
591 # if evolve is active set evolution=all
593 # if evolve is active set evolution=all
592
594
593 self._create_or_update_ui(
595 self._create_or_update_ui(
594 settings, *('experimental', 'evolution'), value='all',
596 settings, *('experimental', 'evolution'), value='all',
595 active=True)
597 active=True)
596 self._create_or_update_ui(
598 self._create_or_update_ui(
597 settings, *('experimental', 'evolution.exchange'), value='yes',
599 settings, *('experimental', 'evolution.exchange'), value='yes',
598 active=True)
600 active=True)
599 # if evolve is active set topics server support
601 # if evolve is active set topics server support
600 self._create_or_update_ui(
602 self._create_or_update_ui(
601 settings, *('extensions', 'topic'), value='',
603 settings, *('extensions', 'topic'), value='',
602 active=True)
604 active=True)
603
605
604 else:
606 else:
605 self._create_or_update_ui(
607 self._create_or_update_ui(
606 settings, *('experimental', 'evolution'), value='',
608 settings, *('experimental', 'evolution'), value='',
607 active=False)
609 active=False)
608 self._create_or_update_ui(
610 self._create_or_update_ui(
609 settings, *('experimental', 'evolution.exchange'), value='no',
611 settings, *('experimental', 'evolution.exchange'), value='no',
610 active=False)
612 active=False)
611 self._create_or_update_ui(
613 self._create_or_update_ui(
612 settings, *('extensions', 'topic'), value='',
614 settings, *('extensions', 'topic'), value='',
613 active=False)
615 active=False)
614
616
615 @assert_repo_settings
617 @assert_repo_settings
616 def create_or_update_repo_hg_settings(self, data):
618 def create_or_update_repo_hg_settings(self, data):
617 largefiles, phases, evolve = \
619 largefiles, phases, evolve = \
618 self.HG_SETTINGS[:3]
620 self.HG_SETTINGS[:3]
619 largefiles_key, phases_key, evolve_key = \
621 largefiles_key, phases_key, evolve_key = \
620 self._get_settings_keys(self.HG_SETTINGS[:3], data)
622 self._get_settings_keys(self.HG_SETTINGS[:3], data)
621
623
622 self._create_or_update_ui(
624 self._create_or_update_ui(
623 self.repo_settings, *largefiles, value='',
625 self.repo_settings, *largefiles, value='',
624 active=data[largefiles_key])
626 active=data[largefiles_key])
625 self._create_or_update_ui(
627 self._create_or_update_ui(
626 self.repo_settings, *evolve, value='',
628 self.repo_settings, *evolve, value='',
627 active=data[evolve_key])
629 active=data[evolve_key])
628 self._set_evolution(self.repo_settings, is_enabled=data[evolve_key])
630 self._set_evolution(self.repo_settings, is_enabled=data[evolve_key])
629
631
630 self._create_or_update_ui(
632 self._create_or_update_ui(
631 self.repo_settings, *phases, value=safe_str(data[phases_key]))
633 self.repo_settings, *phases, value=safe_str(data[phases_key]))
632
634
633 def create_or_update_global_hg_settings(self, data):
635 def create_or_update_global_hg_settings(self, data):
634 largefiles, largefiles_store, phases, hgsubversion, evolve \
636 largefiles, largefiles_store, phases, hgsubversion, evolve \
635 = self.GLOBAL_HG_SETTINGS[:5]
637 = self.GLOBAL_HG_SETTINGS[:5]
636 largefiles_key, largefiles_store_key, phases_key, subversion_key, evolve_key \
638 largefiles_key, largefiles_store_key, phases_key, subversion_key, evolve_key \
637 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS[:5], data)
639 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS[:5], data)
638
640
639 self._create_or_update_ui(
641 self._create_or_update_ui(
640 self.global_settings, *largefiles, value='',
642 self.global_settings, *largefiles, value='',
641 active=data[largefiles_key])
643 active=data[largefiles_key])
642 self._create_or_update_ui(
644 self._create_or_update_ui(
643 self.global_settings, *largefiles_store, value=data[largefiles_store_key])
645 self.global_settings, *largefiles_store, value=data[largefiles_store_key])
644 self._create_or_update_ui(
646 self._create_or_update_ui(
645 self.global_settings, *phases, value=safe_str(data[phases_key]))
647 self.global_settings, *phases, value=safe_str(data[phases_key]))
646 self._create_or_update_ui(
648 self._create_or_update_ui(
647 self.global_settings, *hgsubversion, active=data[subversion_key])
649 self.global_settings, *hgsubversion, active=data[subversion_key])
648 self._create_or_update_ui(
650 self._create_or_update_ui(
649 self.global_settings, *evolve, value='',
651 self.global_settings, *evolve, value='',
650 active=data[evolve_key])
652 active=data[evolve_key])
651 self._set_evolution(self.global_settings, is_enabled=data[evolve_key])
653 self._set_evolution(self.global_settings, is_enabled=data[evolve_key])
652
654
653 def create_or_update_repo_git_settings(self, data):
655 def create_or_update_repo_git_settings(self, data):
654 # NOTE(marcink): # comma makes unpack work properly
656 # NOTE(marcink): # comma makes unpack work properly
655 lfs_enabled, \
657 lfs_enabled, \
656 = self.GIT_SETTINGS
658 = self.GIT_SETTINGS
657
659
658 lfs_enabled_key, \
660 lfs_enabled_key, \
659 = self._get_settings_keys(self.GIT_SETTINGS, data)
661 = self._get_settings_keys(self.GIT_SETTINGS, data)
660
662
661 self._create_or_update_ui(
663 self._create_or_update_ui(
662 self.repo_settings, *lfs_enabled, value=data[lfs_enabled_key],
664 self.repo_settings, *lfs_enabled, value=data[lfs_enabled_key],
663 active=data[lfs_enabled_key])
665 active=data[lfs_enabled_key])
664
666
665 def create_or_update_global_git_settings(self, data):
667 def create_or_update_global_git_settings(self, data):
666 lfs_enabled, lfs_store_location \
668 lfs_enabled, lfs_store_location \
667 = self.GLOBAL_GIT_SETTINGS
669 = self.GLOBAL_GIT_SETTINGS
668 lfs_enabled_key, lfs_store_location_key \
670 lfs_enabled_key, lfs_store_location_key \
669 = self._get_settings_keys(self.GLOBAL_GIT_SETTINGS, data)
671 = self._get_settings_keys(self.GLOBAL_GIT_SETTINGS, data)
670
672
671 self._create_or_update_ui(
673 self._create_or_update_ui(
672 self.global_settings, *lfs_enabled, value=data[lfs_enabled_key],
674 self.global_settings, *lfs_enabled, value=data[lfs_enabled_key],
673 active=data[lfs_enabled_key])
675 active=data[lfs_enabled_key])
674 self._create_or_update_ui(
676 self._create_or_update_ui(
675 self.global_settings, *lfs_store_location,
677 self.global_settings, *lfs_store_location,
676 value=data[lfs_store_location_key])
678 value=data[lfs_store_location_key])
677
679
678 def create_or_update_global_svn_settings(self, data):
680 def create_or_update_global_svn_settings(self, data):
679 # branch/tags patterns
681 # branch/tags patterns
680 self._create_svn_settings(self.global_settings, data)
682 self._create_svn_settings(self.global_settings, data)
681
683
682 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
684 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
683 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
685 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
684 self.GLOBAL_SVN_SETTINGS, data)
686 self.GLOBAL_SVN_SETTINGS, data)
685
687
686 self._create_or_update_ui(
688 self._create_or_update_ui(
687 self.global_settings, *http_requests_enabled,
689 self.global_settings, *http_requests_enabled,
688 value=safe_str(data[http_requests_enabled_key]))
690 value=safe_str(data[http_requests_enabled_key]))
689 self._create_or_update_ui(
691 self._create_or_update_ui(
690 self.global_settings, *http_server_url,
692 self.global_settings, *http_server_url,
691 value=data[http_server_url_key])
693 value=data[http_server_url_key])
692
694
693 def update_global_ssl_setting(self, value):
695 def update_global_ssl_setting(self, value):
694 self._create_or_update_ui(
696 self._create_or_update_ui(
695 self.global_settings, *self.SSL_SETTING, value=value)
697 self.global_settings, *self.SSL_SETTING, value=value)
696
698
697 def update_global_path_setting(self, value):
699 def update_global_path_setting(self, value):
698 self._create_or_update_ui(
700 self._create_or_update_ui(
699 self.global_settings, *self.PATH_SETTING, value=value)
701 self.global_settings, *self.PATH_SETTING, value=value)
700
702
701 @assert_repo_settings
703 @assert_repo_settings
702 def delete_repo_svn_pattern(self, id_):
704 def delete_repo_svn_pattern(self, id_):
703 ui = self.repo_settings.UiDbModel.get(id_)
705 ui = self.repo_settings.UiDbModel.get(id_)
704 if ui and ui.repository.repo_name == self.repo_settings.repo:
706 if ui and ui.repository.repo_name == self.repo_settings.repo:
705 # only delete if it's the same repo as initialized settings
707 # only delete if it's the same repo as initialized settings
706 self.repo_settings.delete_ui(id_)
708 self.repo_settings.delete_ui(id_)
707 else:
709 else:
708 # raise error as if we wouldn't find this option
710 # raise error as if we wouldn't find this option
709 self.repo_settings.delete_ui(-1)
711 self.repo_settings.delete_ui(-1)
710
712
711 def delete_global_svn_pattern(self, id_):
713 def delete_global_svn_pattern(self, id_):
712 self.global_settings.delete_ui(id_)
714 self.global_settings.delete_ui(id_)
713
715
714 @assert_repo_settings
716 @assert_repo_settings
715 def get_repo_ui_settings(self, section=None, key=None):
717 def get_repo_ui_settings(self, section=None, key=None):
716 global_uis = self.global_settings.get_ui(section, key)
718 global_uis = self.global_settings.get_ui(section, key)
717 repo_uis = self.repo_settings.get_ui(section, key)
719 repo_uis = self.repo_settings.get_ui(section, key)
718
720
719 filtered_repo_uis = self._filter_ui_settings(repo_uis)
721 filtered_repo_uis = self._filter_ui_settings(repo_uis)
720 filtered_repo_uis_keys = [
722 filtered_repo_uis_keys = [
721 (s.section, s.key) for s in filtered_repo_uis]
723 (s.section, s.key) for s in filtered_repo_uis]
722
724
723 def _is_global_ui_filtered(ui):
725 def _is_global_ui_filtered(ui):
724 return (
726 return (
725 (ui.section, ui.key) in filtered_repo_uis_keys
727 (ui.section, ui.key) in filtered_repo_uis_keys
726 or ui.section in self._svn_sections)
728 or ui.section in self._svn_sections)
727
729
728 filtered_global_uis = [
730 filtered_global_uis = [
729 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
731 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
730
732
731 return filtered_global_uis + filtered_repo_uis
733 return filtered_global_uis + filtered_repo_uis
732
734
733 def get_global_ui_settings(self, section=None, key=None):
735 def get_global_ui_settings(self, section=None, key=None):
734 return self.global_settings.get_ui(section, key)
736 return self.global_settings.get_ui(section, key)
735
737
736 def get_ui_settings_as_config_obj(self, section=None, key=None):
738 def get_ui_settings_as_config_obj(self, section=None, key=None):
737 config = base.Config()
739 config = base.Config()
738
740
739 ui_settings = self.get_ui_settings(section=section, key=key)
741 ui_settings = self.get_ui_settings(section=section, key=key)
740
742
741 for entry in ui_settings:
743 for entry in ui_settings:
742 config.set(entry.section, entry.key, entry.value)
744 config.set(entry.section, entry.key, entry.value)
743
745
744 return config
746 return config
745
747
746 def get_ui_settings(self, section=None, key=None):
748 def get_ui_settings(self, section=None, key=None):
747 if not self.repo_settings or self.inherit_global_settings:
749 if not self.repo_settings or self.inherit_global_settings:
748 return self.get_global_ui_settings(section, key)
750 return self.get_global_ui_settings(section, key)
749 else:
751 else:
750 return self.get_repo_ui_settings(section, key)
752 return self.get_repo_ui_settings(section, key)
751
753
752 def get_svn_patterns(self, section=None):
754 def get_svn_patterns(self, section=None):
753 if not self.repo_settings:
755 if not self.repo_settings:
754 return self.get_global_ui_settings(section)
756 return self.get_global_ui_settings(section)
755 else:
757 else:
756 return self.get_repo_ui_settings(section)
758 return self.get_repo_ui_settings(section)
757
759
758 @assert_repo_settings
760 @assert_repo_settings
759 def get_repo_general_settings(self):
761 def get_repo_general_settings(self):
760 global_settings = self.global_settings.get_all_settings()
762 global_settings = self.global_settings.get_all_settings()
761 repo_settings = self.repo_settings.get_all_settings()
763 repo_settings = self.repo_settings.get_all_settings()
762 filtered_repo_settings = self._filter_general_settings(repo_settings)
764 filtered_repo_settings = self._filter_general_settings(repo_settings)
763 global_settings.update(filtered_repo_settings)
765 global_settings.update(filtered_repo_settings)
764 return global_settings
766 return global_settings
765
767
766 def get_global_general_settings(self):
768 def get_global_general_settings(self):
767 return self.global_settings.get_all_settings()
769 return self.global_settings.get_all_settings()
768
770
769 def get_general_settings(self):
771 def get_general_settings(self):
770 if not self.repo_settings or self.inherit_global_settings:
772 if not self.repo_settings or self.inherit_global_settings:
771 return self.get_global_general_settings()
773 return self.get_global_general_settings()
772 else:
774 else:
773 return self.get_repo_general_settings()
775 return self.get_repo_general_settings()
774
776
775 def get_repos_location(self):
777 def get_repos_location(self):
776 return self.global_settings.get_ui_by_key('/').ui_value
778 return self.global_settings.get_ui_by_key('/').ui_value
777
779
778 def _filter_ui_settings(self, settings):
780 def _filter_ui_settings(self, settings):
779 filtered_settings = [
781 filtered_settings = [
780 s for s in settings if self._should_keep_setting(s)]
782 s for s in settings if self._should_keep_setting(s)]
781 return filtered_settings
783 return filtered_settings
782
784
783 def _should_keep_setting(self, setting):
785 def _should_keep_setting(self, setting):
784 keep = (
786 keep = (
785 (setting.section, setting.key) in self._ui_settings or
787 (setting.section, setting.key) in self._ui_settings or
786 setting.section in self._svn_sections)
788 setting.section in self._svn_sections)
787 return keep
789 return keep
788
790
789 def _filter_general_settings(self, settings):
791 def _filter_general_settings(self, settings):
790 keys = ['rhodecode_{}'.format(key) for key in self.GENERAL_SETTINGS]
792 keys = ['rhodecode_{}'.format(key) for key in self.GENERAL_SETTINGS]
791 return {
793 return {
792 k: settings[k]
794 k: settings[k]
793 for k in settings if k in keys}
795 for k in settings if k in keys}
794
796
795 def _collect_all_settings(self, global_=False):
797 def _collect_all_settings(self, global_=False):
796 settings = self.global_settings if global_ else self.repo_settings
798 settings = self.global_settings if global_ else self.repo_settings
797 result = {}
799 result = {}
798
800
799 for section, key in self._ui_settings:
801 for section, key in self._ui_settings:
800 ui = settings.get_ui_by_section_and_key(section, key)
802 ui = settings.get_ui_by_section_and_key(section, key)
801 result_key = self._get_form_ui_key(section, key)
803 result_key = self._get_form_ui_key(section, key)
802
804
803 if ui:
805 if ui:
804 if section in ('hooks', 'extensions'):
806 if section in ('hooks', 'extensions'):
805 result[result_key] = ui.ui_active
807 result[result_key] = ui.ui_active
806 elif result_key in ['vcs_git_lfs_enabled']:
808 elif result_key in ['vcs_git_lfs_enabled']:
807 result[result_key] = ui.ui_active
809 result[result_key] = ui.ui_active
808 else:
810 else:
809 result[result_key] = ui.ui_value
811 result[result_key] = ui.ui_value
810
812
811 for name in self.GENERAL_SETTINGS:
813 for name in self.GENERAL_SETTINGS:
812 setting = settings.get_setting_by_name(name)
814 setting = settings.get_setting_by_name(name)
813 if setting:
815 if setting:
814 result_key = 'rhodecode_{}'.format(name)
816 result_key = 'rhodecode_{}'.format(name)
815 result[result_key] = setting.app_settings_value
817 result[result_key] = setting.app_settings_value
816
818
817 return result
819 return result
818
820
819 def _get_form_ui_key(self, section, key):
821 def _get_form_ui_key(self, section, key):
820 return '{section}_{key}'.format(
822 return '{section}_{key}'.format(
821 section=section, key=key.replace('.', '_'))
823 section=section, key=key.replace('.', '_'))
822
824
823 def _create_or_update_ui(
825 def _create_or_update_ui(
824 self, settings, section, key, value=None, active=None):
826 self, settings, section, key, value=None, active=None):
825 ui = settings.get_ui_by_section_and_key(section, key)
827 ui = settings.get_ui_by_section_and_key(section, key)
826 if not ui:
828 if not ui:
827 active = True if active is None else active
829 active = True if active is None else active
828 settings.create_ui_section_value(
830 settings.create_ui_section_value(
829 section, value, key=key, active=active)
831 section, value, key=key, active=active)
830 else:
832 else:
831 if active is not None:
833 if active is not None:
832 ui.ui_active = active
834 ui.ui_active = active
833 if value is not None:
835 if value is not None:
834 ui.ui_value = value
836 ui.ui_value = value
835 Session().add(ui)
837 Session().add(ui)
836
838
837 def _create_svn_settings(self, settings, data):
839 def _create_svn_settings(self, settings, data):
838 svn_settings = {
840 svn_settings = {
839 'new_svn_branch': self.SVN_BRANCH_SECTION,
841 'new_svn_branch': self.SVN_BRANCH_SECTION,
840 'new_svn_tag': self.SVN_TAG_SECTION
842 'new_svn_tag': self.SVN_TAG_SECTION
841 }
843 }
842 for key in svn_settings:
844 for key in svn_settings:
843 if data.get(key):
845 if data.get(key):
844 settings.create_ui_section_value(svn_settings[key], data[key])
846 settings.create_ui_section_value(svn_settings[key], data[key])
845
847
846 def _create_or_update_general_settings(self, settings, data):
848 def _create_or_update_general_settings(self, settings, data):
847 for name in self.GENERAL_SETTINGS:
849 for name in self.GENERAL_SETTINGS:
848 data_key = 'rhodecode_{}'.format(name)
850 data_key = 'rhodecode_{}'.format(name)
849 if data_key not in data:
851 if data_key not in data:
850 raise ValueError(
852 raise ValueError(
851 'The given data does not contain {} key'.format(data_key))
853 'The given data does not contain {} key'.format(data_key))
852 setting = settings.create_or_update_setting(
854 setting = settings.create_or_update_setting(
853 name, data[data_key], 'bool')
855 name, data[data_key], 'bool')
854 Session().add(setting)
856 Session().add(setting)
855
857
856 def _get_settings_keys(self, settings, data):
858 def _get_settings_keys(self, settings, data):
857 data_keys = [self._get_form_ui_key(*s) for s in settings]
859 data_keys = [self._get_form_ui_key(*s) for s in settings]
858 for data_key in data_keys:
860 for data_key in data_keys:
859 if data_key not in data:
861 if data_key not in data:
860 raise ValueError(
862 raise ValueError(
861 'The given data does not contain {} key'.format(data_key))
863 'The given data does not contain {} key'.format(data_key))
862 return data_keys
864 return data_keys
863
865
864 def create_largeobjects_dirs_if_needed(self, repo_store_path):
866 def create_largeobjects_dirs_if_needed(self, repo_store_path):
865 """
867 """
866 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
868 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
867 does a repository scan if enabled in the settings.
869 does a repository scan if enabled in the settings.
868 """
870 """
869
871
870 from rhodecode.lib.vcs.backends.hg import largefiles_store
872 from rhodecode.lib.vcs.backends.hg import largefiles_store
871 from rhodecode.lib.vcs.backends.git import lfs_store
873 from rhodecode.lib.vcs.backends.git import lfs_store
872
874
873 paths = [
875 paths = [
874 largefiles_store(repo_store_path),
876 largefiles_store(repo_store_path),
875 lfs_store(repo_store_path)]
877 lfs_store(repo_store_path)]
876
878
877 for path in paths:
879 for path in paths:
878 if os.path.isdir(path):
880 if os.path.isdir(path):
879 continue
881 continue
880 if os.path.isfile(path):
882 if os.path.isfile(path):
881 continue
883 continue
882 # not a file nor dir, we try to create it
884 # not a file nor dir, we try to create it
883 try:
885 try:
884 os.makedirs(path)
886 os.makedirs(path)
885 except Exception:
887 except Exception:
886 log.warning('Failed to create largefiles dir:%s', path)
888 log.warning('Failed to create largefiles dir:%s', path)
General Comments 0
You need to be logged in to leave comments. Login now