##// END OF EJS Templates
mercurial: allow editing largefile store from web interface.
marcink -
r1563:d4c84e02 default
parent child Browse files
Show More
@@ -1,32 +1,14 b''
1 .. _hg-lrg-loc:
1 .. _hg-lrg-loc:
2
2
3 Change the |hg| Large Files Location
3 Change the |hg| Large Files Location
4 ------------------------------------
4 ------------------------------------
5
5
6 |RCE| manages |hg| larges files from the following default location
6 |RCE| manages |hg| larges files from the following default location
7 :file:`/home/{user}/repos/.cache/largefiles`. If you wish to change this, use
7 :file:`/home/{user}/repos/.cache/largefiles`. If you wish to change this, use
8 the following steps:
8 the following steps:
9
9
10 1. Open ishell from the terminal and use it to log into the |RCE| database by
10 1. Open :menuselection:`Admin --> Settings --> VCS` as super-admin.
11 specifying the instance :file:`rhodecode.ini` file.
12
13 .. code-block:: bash
14
15 # Open iShell from the terminal and set ini file
16 $ rccontrol ishell enterprise-1
17
18 2. Run the following commands, and ensure that |RCE| has write access to the
19 new directory:
20
11
21 .. code-block:: bash
12 In section called `Mercurial Settings` you can change where the largefiles
13 objects should be stored.
22
14
23 # Once logged into the database, use SQL to redirect
24 # the large files location
25 In [1]: from rhodecode.model.settings import SettingsModel
26 In [2]: SettingsModel().get_ui_by_key('usercache')
27 Out[2]: <RhodeCodeUi[largefiles]usercache=>/mnt/hgfs/shared/workspace/xxxx/.cache/largefiles]>
28
29 In [3]: largefiles_cache = SettingsModel().get_ui_by_key('usercache')
30 In [4]: largefiles_cache.ui_value = '/new/path’
31 In [5]: Session().add(largefiles_cache);Session().commit()
32
@@ -1,80 +1,84 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 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 shlex
22 import shlex
23 import platform
23 import platform
24
24
25 from rhodecode.model import init_model
25 from rhodecode.model import init_model
26
26
27
27
28
28
29 def configure_vcs(config):
29 def configure_vcs(config):
30 """
30 """
31 Patch VCS config with some RhodeCode specific stuff
31 Patch VCS config with some RhodeCode specific stuff
32 """
32 """
33 from rhodecode.lib.vcs import conf
33 from rhodecode.lib.vcs import conf
34 conf.settings.BACKENDS = {
34 conf.settings.BACKENDS = {
35 'hg': 'rhodecode.lib.vcs.backends.hg.MercurialRepository',
35 'hg': 'rhodecode.lib.vcs.backends.hg.MercurialRepository',
36 'git': 'rhodecode.lib.vcs.backends.git.GitRepository',
36 'git': 'rhodecode.lib.vcs.backends.git.GitRepository',
37 'svn': 'rhodecode.lib.vcs.backends.svn.SubversionRepository',
37 'svn': 'rhodecode.lib.vcs.backends.svn.SubversionRepository',
38 }
38 }
39
39
40 conf.settings.HOOKS_PROTOCOL = config['vcs.hooks.protocol']
40 conf.settings.HOOKS_PROTOCOL = config['vcs.hooks.protocol']
41 conf.settings.HOOKS_DIRECT_CALLS = config['vcs.hooks.direct_calls']
41 conf.settings.HOOKS_DIRECT_CALLS = config['vcs.hooks.direct_calls']
42 conf.settings.GIT_REV_FILTER = shlex.split(config['git_rev_filter'])
42 conf.settings.GIT_REV_FILTER = shlex.split(config['git_rev_filter'])
43 conf.settings.DEFAULT_ENCODINGS = config['default_encoding']
43 conf.settings.DEFAULT_ENCODINGS = config['default_encoding']
44 conf.settings.ALIASES[:] = config['vcs.backends']
44 conf.settings.ALIASES[:] = config['vcs.backends']
45 conf.settings.SVN_COMPATIBLE_VERSION = config['vcs.svn.compatible_version']
45 conf.settings.SVN_COMPATIBLE_VERSION = config['vcs.svn.compatible_version']
46
46
47
47
48 def initialize_database(config):
48 def initialize_database(config):
49 from rhodecode.lib.utils2 import engine_from_config, get_encryption_key
49 from rhodecode.lib.utils2 import engine_from_config, get_encryption_key
50 engine = engine_from_config(config, 'sqlalchemy.db1.')
50 engine = engine_from_config(config, 'sqlalchemy.db1.')
51 init_model(engine, encryption_key=get_encryption_key(config))
51 init_model(engine, encryption_key=get_encryption_key(config))
52
52
53
53
54 def initialize_test_environment(settings, test_env=None):
54 def initialize_test_environment(settings, test_env=None):
55 if test_env is None:
55 if test_env is None:
56 test_env = not int(os.environ.get('RC_NO_TMP_PATH', 0))
56 test_env = not int(os.environ.get('RC_NO_TMP_PATH', 0))
57
57
58 from rhodecode.lib.utils import (
58 from rhodecode.lib.utils import (
59 create_test_directory, create_test_database, create_test_repositories,
59 create_test_directory, create_test_database, create_test_repositories,
60 create_test_index)
60 create_test_index)
61 from rhodecode.tests import TESTS_TMP_PATH
61 from rhodecode.tests import TESTS_TMP_PATH
62 from rhodecode.lib.vcs.backends.hg import largefiles_store
62 # test repos
63 # test repos
63 if test_env:
64 if test_env:
64 create_test_directory(TESTS_TMP_PATH)
65 create_test_directory(TESTS_TMP_PATH)
66 # large object stores
67 create_test_directory(largefiles_store(TESTS_TMP_PATH))
68
65 create_test_database(TESTS_TMP_PATH, settings)
69 create_test_database(TESTS_TMP_PATH, settings)
66 create_test_repositories(TESTS_TMP_PATH, settings)
70 create_test_repositories(TESTS_TMP_PATH, settings)
67 create_test_index(TESTS_TMP_PATH, settings)
71 create_test_index(TESTS_TMP_PATH, settings)
68
72
69
73
70 def get_vcs_server_protocol(config):
74 def get_vcs_server_protocol(config):
71 return config['vcs.server.protocol']
75 return config['vcs.server.protocol']
72
76
73
77
74 def set_instance_id(config):
78 def set_instance_id(config):
75 """ Sets a dynamic generated config['instance_id'] if missing or '*' """
79 """ Sets a dynamic generated config['instance_id'] if missing or '*' """
76
80
77 config['instance_id'] = config.get('instance_id') or ''
81 config['instance_id'] = config.get('instance_id') or ''
78 if config['instance_id'] == '*' or not config['instance_id']:
82 if config['instance_id'] == '*' or not config['instance_id']:
79 _platform_id = platform.uname()[1] or 'instance'
83 _platform_id = platform.uname()[1] or 'instance'
80 config['instance_id'] = '%s-%s' % (_platform_id, os.getpid())
84 config['instance_id'] = '%s-%s' % (_platform_id, os.getpid())
@@ -1,549 +1,553 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 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 """
21 """
22 this is forms validation classes
22 this is forms validation classes
23 http://formencode.org/module-formencode.validators.html
23 http://formencode.org/module-formencode.validators.html
24 for list off all availible validators
24 for list off all availible validators
25
25
26 we can create our own validators
26 we can create our own validators
27
27
28 The table below outlines the options which can be used in a schema in addition to the validators themselves
28 The table below outlines the options which can be used in a schema in addition to the validators themselves
29 pre_validators [] These validators will be applied before the schema
29 pre_validators [] These validators will be applied before the schema
30 chained_validators [] These validators will be applied after the schema
30 chained_validators [] These validators will be applied after the schema
31 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
31 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
32 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
32 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
33 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
33 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
34 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
34 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
35
35
36
36
37 <name> = formencode.validators.<name of validator>
37 <name> = formencode.validators.<name of validator>
38 <name> must equal form name
38 <name> must equal form name
39 list=[1,2,3,4,5]
39 list=[1,2,3,4,5]
40 for SELECT use formencode.All(OneOf(list), Int())
40 for SELECT use formencode.All(OneOf(list), Int())
41
41
42 """
42 """
43
43
44 import deform
44 import deform
45 import logging
45 import logging
46 import formencode
46 import formencode
47
47
48 from pkg_resources import resource_filename
48 from pkg_resources import resource_filename
49 from formencode import All, Pipe
49 from formencode import All, Pipe
50
50
51 from pylons.i18n.translation import _
51 from pylons.i18n.translation import _
52
52
53 from rhodecode import BACKENDS
53 from rhodecode import BACKENDS
54 from rhodecode.lib import helpers
54 from rhodecode.lib import helpers
55 from rhodecode.model import validators as v
55 from rhodecode.model import validators as v
56
56
57 log = logging.getLogger(__name__)
57 log = logging.getLogger(__name__)
58
58
59
59
60 deform_templates = resource_filename('deform', 'templates')
60 deform_templates = resource_filename('deform', 'templates')
61 rhodecode_templates = resource_filename('rhodecode', 'templates/forms')
61 rhodecode_templates = resource_filename('rhodecode', 'templates/forms')
62 search_path = (rhodecode_templates, deform_templates)
62 search_path = (rhodecode_templates, deform_templates)
63
63
64
64
65 class RhodecodeFormZPTRendererFactory(deform.ZPTRendererFactory):
65 class RhodecodeFormZPTRendererFactory(deform.ZPTRendererFactory):
66 """ Subclass of ZPTRendererFactory to add rhodecode context variables """
66 """ Subclass of ZPTRendererFactory to add rhodecode context variables """
67 def __call__(self, template_name, **kw):
67 def __call__(self, template_name, **kw):
68 kw['h'] = helpers
68 kw['h'] = helpers
69 return self.load(template_name)(**kw)
69 return self.load(template_name)(**kw)
70
70
71
71
72 form_renderer = RhodecodeFormZPTRendererFactory(search_path)
72 form_renderer = RhodecodeFormZPTRendererFactory(search_path)
73 deform.Form.set_default_renderer(form_renderer)
73 deform.Form.set_default_renderer(form_renderer)
74
74
75
75
76 def LoginForm():
76 def LoginForm():
77 class _LoginForm(formencode.Schema):
77 class _LoginForm(formencode.Schema):
78 allow_extra_fields = True
78 allow_extra_fields = True
79 filter_extra_fields = True
79 filter_extra_fields = True
80 username = v.UnicodeString(
80 username = v.UnicodeString(
81 strip=True,
81 strip=True,
82 min=1,
82 min=1,
83 not_empty=True,
83 not_empty=True,
84 messages={
84 messages={
85 'empty': _(u'Please enter a login'),
85 'empty': _(u'Please enter a login'),
86 'tooShort': _(u'Enter a value %(min)i characters long or more')
86 'tooShort': _(u'Enter a value %(min)i characters long or more')
87 }
87 }
88 )
88 )
89
89
90 password = v.UnicodeString(
90 password = v.UnicodeString(
91 strip=False,
91 strip=False,
92 min=3,
92 min=3,
93 not_empty=True,
93 not_empty=True,
94 messages={
94 messages={
95 'empty': _(u'Please enter a password'),
95 'empty': _(u'Please enter a password'),
96 'tooShort': _(u'Enter %(min)i characters or more')}
96 'tooShort': _(u'Enter %(min)i characters or more')}
97 )
97 )
98
98
99 remember = v.StringBoolean(if_missing=False)
99 remember = v.StringBoolean(if_missing=False)
100
100
101 chained_validators = [v.ValidAuth()]
101 chained_validators = [v.ValidAuth()]
102 return _LoginForm
102 return _LoginForm
103
103
104
104
105 def UserForm(edit=False, available_languages=[], old_data={}):
105 def UserForm(edit=False, available_languages=[], old_data={}):
106 class _UserForm(formencode.Schema):
106 class _UserForm(formencode.Schema):
107 allow_extra_fields = True
107 allow_extra_fields = True
108 filter_extra_fields = True
108 filter_extra_fields = True
109 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
109 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
110 v.ValidUsername(edit, old_data))
110 v.ValidUsername(edit, old_data))
111 if edit:
111 if edit:
112 new_password = All(
112 new_password = All(
113 v.ValidPassword(),
113 v.ValidPassword(),
114 v.UnicodeString(strip=False, min=6, not_empty=False)
114 v.UnicodeString(strip=False, min=6, not_empty=False)
115 )
115 )
116 password_confirmation = All(
116 password_confirmation = All(
117 v.ValidPassword(),
117 v.ValidPassword(),
118 v.UnicodeString(strip=False, min=6, not_empty=False),
118 v.UnicodeString(strip=False, min=6, not_empty=False),
119 )
119 )
120 admin = v.StringBoolean(if_missing=False)
120 admin = v.StringBoolean(if_missing=False)
121 else:
121 else:
122 password = All(
122 password = All(
123 v.ValidPassword(),
123 v.ValidPassword(),
124 v.UnicodeString(strip=False, min=6, not_empty=True)
124 v.UnicodeString(strip=False, min=6, not_empty=True)
125 )
125 )
126 password_confirmation = All(
126 password_confirmation = All(
127 v.ValidPassword(),
127 v.ValidPassword(),
128 v.UnicodeString(strip=False, min=6, not_empty=False)
128 v.UnicodeString(strip=False, min=6, not_empty=False)
129 )
129 )
130
130
131 password_change = v.StringBoolean(if_missing=False)
131 password_change = v.StringBoolean(if_missing=False)
132 create_repo_group = v.StringBoolean(if_missing=False)
132 create_repo_group = v.StringBoolean(if_missing=False)
133
133
134 active = v.StringBoolean(if_missing=False)
134 active = v.StringBoolean(if_missing=False)
135 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
135 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
136 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
136 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
137 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
137 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
138 extern_name = v.UnicodeString(strip=True)
138 extern_name = v.UnicodeString(strip=True)
139 extern_type = v.UnicodeString(strip=True)
139 extern_type = v.UnicodeString(strip=True)
140 language = v.OneOf(available_languages, hideList=False,
140 language = v.OneOf(available_languages, hideList=False,
141 testValueList=True, if_missing=None)
141 testValueList=True, if_missing=None)
142 chained_validators = [v.ValidPasswordsMatch()]
142 chained_validators = [v.ValidPasswordsMatch()]
143 return _UserForm
143 return _UserForm
144
144
145
145
146 def UserGroupForm(edit=False, old_data=None, allow_disabled=False):
146 def UserGroupForm(edit=False, old_data=None, allow_disabled=False):
147 old_data = old_data or {}
147 old_data = old_data or {}
148
148
149 class _UserGroupForm(formencode.Schema):
149 class _UserGroupForm(formencode.Schema):
150 allow_extra_fields = True
150 allow_extra_fields = True
151 filter_extra_fields = True
151 filter_extra_fields = True
152
152
153 users_group_name = All(
153 users_group_name = All(
154 v.UnicodeString(strip=True, min=1, not_empty=True),
154 v.UnicodeString(strip=True, min=1, not_empty=True),
155 v.ValidUserGroup(edit, old_data)
155 v.ValidUserGroup(edit, old_data)
156 )
156 )
157 user_group_description = v.UnicodeString(strip=True, min=1,
157 user_group_description = v.UnicodeString(strip=True, min=1,
158 not_empty=False)
158 not_empty=False)
159
159
160 users_group_active = v.StringBoolean(if_missing=False)
160 users_group_active = v.StringBoolean(if_missing=False)
161
161
162 if edit:
162 if edit:
163 # this is user group owner
163 # this is user group owner
164 user = All(
164 user = All(
165 v.UnicodeString(not_empty=True),
165 v.UnicodeString(not_empty=True),
166 v.ValidRepoUser(allow_disabled))
166 v.ValidRepoUser(allow_disabled))
167 return _UserGroupForm
167 return _UserGroupForm
168
168
169
169
170 def RepoGroupForm(edit=False, old_data=None, available_groups=None,
170 def RepoGroupForm(edit=False, old_data=None, available_groups=None,
171 can_create_in_root=False, allow_disabled=False):
171 can_create_in_root=False, allow_disabled=False):
172 old_data = old_data or {}
172 old_data = old_data or {}
173 available_groups = available_groups or []
173 available_groups = available_groups or []
174
174
175 class _RepoGroupForm(formencode.Schema):
175 class _RepoGroupForm(formencode.Schema):
176 allow_extra_fields = True
176 allow_extra_fields = True
177 filter_extra_fields = False
177 filter_extra_fields = False
178
178
179 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
179 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
180 v.SlugifyName(),)
180 v.SlugifyName(),)
181 group_description = v.UnicodeString(strip=True, min=1,
181 group_description = v.UnicodeString(strip=True, min=1,
182 not_empty=False)
182 not_empty=False)
183 group_copy_permissions = v.StringBoolean(if_missing=False)
183 group_copy_permissions = v.StringBoolean(if_missing=False)
184
184
185 group_parent_id = v.OneOf(available_groups, hideList=False,
185 group_parent_id = v.OneOf(available_groups, hideList=False,
186 testValueList=True, not_empty=True)
186 testValueList=True, not_empty=True)
187 enable_locking = v.StringBoolean(if_missing=False)
187 enable_locking = v.StringBoolean(if_missing=False)
188 chained_validators = [
188 chained_validators = [
189 v.ValidRepoGroup(edit, old_data, can_create_in_root)]
189 v.ValidRepoGroup(edit, old_data, can_create_in_root)]
190
190
191 if edit:
191 if edit:
192 # this is repo group owner
192 # this is repo group owner
193 user = All(
193 user = All(
194 v.UnicodeString(not_empty=True),
194 v.UnicodeString(not_empty=True),
195 v.ValidRepoUser(allow_disabled))
195 v.ValidRepoUser(allow_disabled))
196
196
197 return _RepoGroupForm
197 return _RepoGroupForm
198
198
199
199
200 def RegisterForm(edit=False, old_data={}):
200 def RegisterForm(edit=False, old_data={}):
201 class _RegisterForm(formencode.Schema):
201 class _RegisterForm(formencode.Schema):
202 allow_extra_fields = True
202 allow_extra_fields = True
203 filter_extra_fields = True
203 filter_extra_fields = True
204 username = All(
204 username = All(
205 v.ValidUsername(edit, old_data),
205 v.ValidUsername(edit, old_data),
206 v.UnicodeString(strip=True, min=1, not_empty=True)
206 v.UnicodeString(strip=True, min=1, not_empty=True)
207 )
207 )
208 password = All(
208 password = All(
209 v.ValidPassword(),
209 v.ValidPassword(),
210 v.UnicodeString(strip=False, min=6, not_empty=True)
210 v.UnicodeString(strip=False, min=6, not_empty=True)
211 )
211 )
212 password_confirmation = All(
212 password_confirmation = All(
213 v.ValidPassword(),
213 v.ValidPassword(),
214 v.UnicodeString(strip=False, min=6, not_empty=True)
214 v.UnicodeString(strip=False, min=6, not_empty=True)
215 )
215 )
216 active = v.StringBoolean(if_missing=False)
216 active = v.StringBoolean(if_missing=False)
217 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
217 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
218 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
218 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
219 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
219 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
220
220
221 chained_validators = [v.ValidPasswordsMatch()]
221 chained_validators = [v.ValidPasswordsMatch()]
222
222
223 return _RegisterForm
223 return _RegisterForm
224
224
225
225
226 def PasswordResetForm():
226 def PasswordResetForm():
227 class _PasswordResetForm(formencode.Schema):
227 class _PasswordResetForm(formencode.Schema):
228 allow_extra_fields = True
228 allow_extra_fields = True
229 filter_extra_fields = True
229 filter_extra_fields = True
230 email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
230 email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
231 return _PasswordResetForm
231 return _PasswordResetForm
232
232
233
233
234 def RepoForm(edit=False, old_data=None, repo_groups=None, landing_revs=None,
234 def RepoForm(edit=False, old_data=None, repo_groups=None, landing_revs=None,
235 allow_disabled=False):
235 allow_disabled=False):
236 old_data = old_data or {}
236 old_data = old_data or {}
237 repo_groups = repo_groups or []
237 repo_groups = repo_groups or []
238 landing_revs = landing_revs or []
238 landing_revs = landing_revs or []
239 supported_backends = BACKENDS.keys()
239 supported_backends = BACKENDS.keys()
240
240
241 class _RepoForm(formencode.Schema):
241 class _RepoForm(formencode.Schema):
242 allow_extra_fields = True
242 allow_extra_fields = True
243 filter_extra_fields = False
243 filter_extra_fields = False
244 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
244 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
245 v.SlugifyName())
245 v.SlugifyName())
246 repo_group = All(v.CanWriteGroup(old_data),
246 repo_group = All(v.CanWriteGroup(old_data),
247 v.OneOf(repo_groups, hideList=True))
247 v.OneOf(repo_groups, hideList=True))
248 repo_type = v.OneOf(supported_backends, required=False,
248 repo_type = v.OneOf(supported_backends, required=False,
249 if_missing=old_data.get('repo_type'))
249 if_missing=old_data.get('repo_type'))
250 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
250 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
251 repo_private = v.StringBoolean(if_missing=False)
251 repo_private = v.StringBoolean(if_missing=False)
252 repo_landing_rev = v.OneOf(landing_revs, hideList=True)
252 repo_landing_rev = v.OneOf(landing_revs, hideList=True)
253 repo_copy_permissions = v.StringBoolean(if_missing=False)
253 repo_copy_permissions = v.StringBoolean(if_missing=False)
254 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
254 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
255
255
256 repo_enable_statistics = v.StringBoolean(if_missing=False)
256 repo_enable_statistics = v.StringBoolean(if_missing=False)
257 repo_enable_downloads = v.StringBoolean(if_missing=False)
257 repo_enable_downloads = v.StringBoolean(if_missing=False)
258 repo_enable_locking = v.StringBoolean(if_missing=False)
258 repo_enable_locking = v.StringBoolean(if_missing=False)
259
259
260 if edit:
260 if edit:
261 # this is repo owner
261 # this is repo owner
262 user = All(
262 user = All(
263 v.UnicodeString(not_empty=True),
263 v.UnicodeString(not_empty=True),
264 v.ValidRepoUser(allow_disabled))
264 v.ValidRepoUser(allow_disabled))
265 clone_uri_change = v.UnicodeString(
265 clone_uri_change = v.UnicodeString(
266 not_empty=False, if_missing=v.Missing)
266 not_empty=False, if_missing=v.Missing)
267
267
268 chained_validators = [v.ValidCloneUri(),
268 chained_validators = [v.ValidCloneUri(),
269 v.ValidRepoName(edit, old_data)]
269 v.ValidRepoName(edit, old_data)]
270 return _RepoForm
270 return _RepoForm
271
271
272
272
273 def RepoPermsForm():
273 def RepoPermsForm():
274 class _RepoPermsForm(formencode.Schema):
274 class _RepoPermsForm(formencode.Schema):
275 allow_extra_fields = True
275 allow_extra_fields = True
276 filter_extra_fields = False
276 filter_extra_fields = False
277 chained_validators = [v.ValidPerms(type_='repo')]
277 chained_validators = [v.ValidPerms(type_='repo')]
278 return _RepoPermsForm
278 return _RepoPermsForm
279
279
280
280
281 def RepoGroupPermsForm(valid_recursive_choices):
281 def RepoGroupPermsForm(valid_recursive_choices):
282 class _RepoGroupPermsForm(formencode.Schema):
282 class _RepoGroupPermsForm(formencode.Schema):
283 allow_extra_fields = True
283 allow_extra_fields = True
284 filter_extra_fields = False
284 filter_extra_fields = False
285 recursive = v.OneOf(valid_recursive_choices)
285 recursive = v.OneOf(valid_recursive_choices)
286 chained_validators = [v.ValidPerms(type_='repo_group')]
286 chained_validators = [v.ValidPerms(type_='repo_group')]
287 return _RepoGroupPermsForm
287 return _RepoGroupPermsForm
288
288
289
289
290 def UserGroupPermsForm():
290 def UserGroupPermsForm():
291 class _UserPermsForm(formencode.Schema):
291 class _UserPermsForm(formencode.Schema):
292 allow_extra_fields = True
292 allow_extra_fields = True
293 filter_extra_fields = False
293 filter_extra_fields = False
294 chained_validators = [v.ValidPerms(type_='user_group')]
294 chained_validators = [v.ValidPerms(type_='user_group')]
295 return _UserPermsForm
295 return _UserPermsForm
296
296
297
297
298 def RepoFieldForm():
298 def RepoFieldForm():
299 class _RepoFieldForm(formencode.Schema):
299 class _RepoFieldForm(formencode.Schema):
300 filter_extra_fields = True
300 filter_extra_fields = True
301 allow_extra_fields = True
301 allow_extra_fields = True
302
302
303 new_field_key = All(v.FieldKey(),
303 new_field_key = All(v.FieldKey(),
304 v.UnicodeString(strip=True, min=3, not_empty=True))
304 v.UnicodeString(strip=True, min=3, not_empty=True))
305 new_field_value = v.UnicodeString(not_empty=False, if_missing=u'')
305 new_field_value = v.UnicodeString(not_empty=False, if_missing=u'')
306 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
306 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
307 if_missing='str')
307 if_missing='str')
308 new_field_label = v.UnicodeString(not_empty=False)
308 new_field_label = v.UnicodeString(not_empty=False)
309 new_field_desc = v.UnicodeString(not_empty=False)
309 new_field_desc = v.UnicodeString(not_empty=False)
310
310
311 return _RepoFieldForm
311 return _RepoFieldForm
312
312
313
313
314 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
314 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
315 repo_groups=[], landing_revs=[]):
315 repo_groups=[], landing_revs=[]):
316 class _RepoForkForm(formencode.Schema):
316 class _RepoForkForm(formencode.Schema):
317 allow_extra_fields = True
317 allow_extra_fields = True
318 filter_extra_fields = False
318 filter_extra_fields = False
319 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
319 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
320 v.SlugifyName())
320 v.SlugifyName())
321 repo_group = All(v.CanWriteGroup(),
321 repo_group = All(v.CanWriteGroup(),
322 v.OneOf(repo_groups, hideList=True))
322 v.OneOf(repo_groups, hideList=True))
323 repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
323 repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
324 description = v.UnicodeString(strip=True, min=1, not_empty=True)
324 description = v.UnicodeString(strip=True, min=1, not_empty=True)
325 private = v.StringBoolean(if_missing=False)
325 private = v.StringBoolean(if_missing=False)
326 copy_permissions = v.StringBoolean(if_missing=False)
326 copy_permissions = v.StringBoolean(if_missing=False)
327 fork_parent_id = v.UnicodeString()
327 fork_parent_id = v.UnicodeString()
328 chained_validators = [v.ValidForkName(edit, old_data)]
328 chained_validators = [v.ValidForkName(edit, old_data)]
329 landing_rev = v.OneOf(landing_revs, hideList=True)
329 landing_rev = v.OneOf(landing_revs, hideList=True)
330
330
331 return _RepoForkForm
331 return _RepoForkForm
332
332
333
333
334 def ApplicationSettingsForm():
334 def ApplicationSettingsForm():
335 class _ApplicationSettingsForm(formencode.Schema):
335 class _ApplicationSettingsForm(formencode.Schema):
336 allow_extra_fields = True
336 allow_extra_fields = True
337 filter_extra_fields = False
337 filter_extra_fields = False
338 rhodecode_title = v.UnicodeString(strip=True, max=40, not_empty=False)
338 rhodecode_title = v.UnicodeString(strip=True, max=40, not_empty=False)
339 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
339 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
340 rhodecode_pre_code = v.UnicodeString(strip=True, min=1, not_empty=False)
340 rhodecode_pre_code = v.UnicodeString(strip=True, min=1, not_empty=False)
341 rhodecode_post_code = v.UnicodeString(strip=True, min=1, not_empty=False)
341 rhodecode_post_code = v.UnicodeString(strip=True, min=1, not_empty=False)
342 rhodecode_captcha_public_key = v.UnicodeString(strip=True, min=1, not_empty=False)
342 rhodecode_captcha_public_key = v.UnicodeString(strip=True, min=1, not_empty=False)
343 rhodecode_captcha_private_key = v.UnicodeString(strip=True, min=1, not_empty=False)
343 rhodecode_captcha_private_key = v.UnicodeString(strip=True, min=1, not_empty=False)
344 rhodecode_create_personal_repo_group = v.StringBoolean(if_missing=False)
344 rhodecode_create_personal_repo_group = v.StringBoolean(if_missing=False)
345 rhodecode_personal_repo_group_pattern = v.UnicodeString(strip=True, min=1, not_empty=False)
345 rhodecode_personal_repo_group_pattern = v.UnicodeString(strip=True, min=1, not_empty=False)
346
346
347 return _ApplicationSettingsForm
347 return _ApplicationSettingsForm
348
348
349
349
350 def ApplicationVisualisationForm():
350 def ApplicationVisualisationForm():
351 class _ApplicationVisualisationForm(formencode.Schema):
351 class _ApplicationVisualisationForm(formencode.Schema):
352 allow_extra_fields = True
352 allow_extra_fields = True
353 filter_extra_fields = False
353 filter_extra_fields = False
354 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
354 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
355 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
355 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
356 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
356 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
357
357
358 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
358 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
359 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
359 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
360 rhodecode_dashboard_items = v.Int(min=5, not_empty=True)
360 rhodecode_dashboard_items = v.Int(min=5, not_empty=True)
361 rhodecode_admin_grid_items = v.Int(min=5, not_empty=True)
361 rhodecode_admin_grid_items = v.Int(min=5, not_empty=True)
362 rhodecode_show_version = v.StringBoolean(if_missing=False)
362 rhodecode_show_version = v.StringBoolean(if_missing=False)
363 rhodecode_use_gravatar = v.StringBoolean(if_missing=False)
363 rhodecode_use_gravatar = v.StringBoolean(if_missing=False)
364 rhodecode_markup_renderer = v.OneOf(['markdown', 'rst'])
364 rhodecode_markup_renderer = v.OneOf(['markdown', 'rst'])
365 rhodecode_gravatar_url = v.UnicodeString(min=3)
365 rhodecode_gravatar_url = v.UnicodeString(min=3)
366 rhodecode_clone_uri_tmpl = v.UnicodeString(min=3)
366 rhodecode_clone_uri_tmpl = v.UnicodeString(min=3)
367 rhodecode_support_url = v.UnicodeString()
367 rhodecode_support_url = v.UnicodeString()
368 rhodecode_show_revision_number = v.StringBoolean(if_missing=False)
368 rhodecode_show_revision_number = v.StringBoolean(if_missing=False)
369 rhodecode_show_sha_length = v.Int(min=4, not_empty=True)
369 rhodecode_show_sha_length = v.Int(min=4, not_empty=True)
370
370
371 return _ApplicationVisualisationForm
371 return _ApplicationVisualisationForm
372
372
373
373
374 class _BaseVcsSettingsForm(formencode.Schema):
374 class _BaseVcsSettingsForm(formencode.Schema):
375 allow_extra_fields = True
375 allow_extra_fields = True
376 filter_extra_fields = False
376 filter_extra_fields = False
377 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
377 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
378 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
378 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
379 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
379 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
380
380
381 extensions_largefiles = v.StringBoolean(if_missing=False)
381 extensions_largefiles = v.StringBoolean(if_missing=False)
382 phases_publish = v.StringBoolean(if_missing=False)
382 phases_publish = v.StringBoolean(if_missing=False)
383
383
384 rhodecode_pr_merge_enabled = v.StringBoolean(if_missing=False)
384 rhodecode_pr_merge_enabled = v.StringBoolean(if_missing=False)
385 rhodecode_use_outdated_comments = v.StringBoolean(if_missing=False)
385 rhodecode_use_outdated_comments = v.StringBoolean(if_missing=False)
386 rhodecode_hg_use_rebase_for_merging = v.StringBoolean(if_missing=False)
386 rhodecode_hg_use_rebase_for_merging = v.StringBoolean(if_missing=False)
387
387
388 vcs_svn_proxy_http_requests_enabled = v.StringBoolean(if_missing=False)
388 vcs_svn_proxy_http_requests_enabled = v.StringBoolean(if_missing=False)
389 vcs_svn_proxy_http_server_url = v.UnicodeString(strip=True, if_missing=None)
389 vcs_svn_proxy_http_server_url = v.UnicodeString(strip=True, if_missing=None)
390
390
391
391
392 def ApplicationUiSettingsForm():
392 def ApplicationUiSettingsForm():
393 class _ApplicationUiSettingsForm(_BaseVcsSettingsForm):
393 class _ApplicationUiSettingsForm(_BaseVcsSettingsForm):
394 web_push_ssl = v.StringBoolean(if_missing=False)
394 web_push_ssl = v.StringBoolean(if_missing=False)
395 paths_root_path = All(
395 paths_root_path = All(
396 v.ValidPath(),
396 v.ValidPath(),
397 v.UnicodeString(strip=True, min=1, not_empty=True)
397 v.UnicodeString(strip=True, min=1, not_empty=True)
398 )
398 )
399 largefiles_usercache = All(
400 v.ValidPath(),
401 v.UnicodeString(strip=True, min=2, not_empty=True)
402 )
399 extensions_hgsubversion = v.StringBoolean(if_missing=False)
403 extensions_hgsubversion = v.StringBoolean(if_missing=False)
400 extensions_hggit = v.StringBoolean(if_missing=False)
404 extensions_hggit = v.StringBoolean(if_missing=False)
401 new_svn_branch = v.ValidSvnPattern(section='vcs_svn_branch')
405 new_svn_branch = v.ValidSvnPattern(section='vcs_svn_branch')
402 new_svn_tag = v.ValidSvnPattern(section='vcs_svn_tag')
406 new_svn_tag = v.ValidSvnPattern(section='vcs_svn_tag')
403
407
404 return _ApplicationUiSettingsForm
408 return _ApplicationUiSettingsForm
405
409
406
410
407 def RepoVcsSettingsForm(repo_name):
411 def RepoVcsSettingsForm(repo_name):
408 class _RepoVcsSettingsForm(_BaseVcsSettingsForm):
412 class _RepoVcsSettingsForm(_BaseVcsSettingsForm):
409 inherit_global_settings = v.StringBoolean(if_missing=False)
413 inherit_global_settings = v.StringBoolean(if_missing=False)
410 new_svn_branch = v.ValidSvnPattern(
414 new_svn_branch = v.ValidSvnPattern(
411 section='vcs_svn_branch', repo_name=repo_name)
415 section='vcs_svn_branch', repo_name=repo_name)
412 new_svn_tag = v.ValidSvnPattern(
416 new_svn_tag = v.ValidSvnPattern(
413 section='vcs_svn_tag', repo_name=repo_name)
417 section='vcs_svn_tag', repo_name=repo_name)
414
418
415 return _RepoVcsSettingsForm
419 return _RepoVcsSettingsForm
416
420
417
421
418 def LabsSettingsForm():
422 def LabsSettingsForm():
419 class _LabSettingsForm(formencode.Schema):
423 class _LabSettingsForm(formencode.Schema):
420 allow_extra_fields = True
424 allow_extra_fields = True
421 filter_extra_fields = False
425 filter_extra_fields = False
422
426
423 return _LabSettingsForm
427 return _LabSettingsForm
424
428
425
429
426 def ApplicationPermissionsForm(
430 def ApplicationPermissionsForm(
427 register_choices, password_reset_choices, extern_activate_choices):
431 register_choices, password_reset_choices, extern_activate_choices):
428 class _DefaultPermissionsForm(formencode.Schema):
432 class _DefaultPermissionsForm(formencode.Schema):
429 allow_extra_fields = True
433 allow_extra_fields = True
430 filter_extra_fields = True
434 filter_extra_fields = True
431
435
432 anonymous = v.StringBoolean(if_missing=False)
436 anonymous = v.StringBoolean(if_missing=False)
433 default_register = v.OneOf(register_choices)
437 default_register = v.OneOf(register_choices)
434 default_register_message = v.UnicodeString()
438 default_register_message = v.UnicodeString()
435 default_password_reset = v.OneOf(password_reset_choices)
439 default_password_reset = v.OneOf(password_reset_choices)
436 default_extern_activate = v.OneOf(extern_activate_choices)
440 default_extern_activate = v.OneOf(extern_activate_choices)
437
441
438 return _DefaultPermissionsForm
442 return _DefaultPermissionsForm
439
443
440
444
441 def ObjectPermissionsForm(repo_perms_choices, group_perms_choices,
445 def ObjectPermissionsForm(repo_perms_choices, group_perms_choices,
442 user_group_perms_choices):
446 user_group_perms_choices):
443 class _ObjectPermissionsForm(formencode.Schema):
447 class _ObjectPermissionsForm(formencode.Schema):
444 allow_extra_fields = True
448 allow_extra_fields = True
445 filter_extra_fields = True
449 filter_extra_fields = True
446 overwrite_default_repo = v.StringBoolean(if_missing=False)
450 overwrite_default_repo = v.StringBoolean(if_missing=False)
447 overwrite_default_group = v.StringBoolean(if_missing=False)
451 overwrite_default_group = v.StringBoolean(if_missing=False)
448 overwrite_default_user_group = v.StringBoolean(if_missing=False)
452 overwrite_default_user_group = v.StringBoolean(if_missing=False)
449 default_repo_perm = v.OneOf(repo_perms_choices)
453 default_repo_perm = v.OneOf(repo_perms_choices)
450 default_group_perm = v.OneOf(group_perms_choices)
454 default_group_perm = v.OneOf(group_perms_choices)
451 default_user_group_perm = v.OneOf(user_group_perms_choices)
455 default_user_group_perm = v.OneOf(user_group_perms_choices)
452
456
453 return _ObjectPermissionsForm
457 return _ObjectPermissionsForm
454
458
455
459
456 def UserPermissionsForm(create_choices, create_on_write_choices,
460 def UserPermissionsForm(create_choices, create_on_write_choices,
457 repo_group_create_choices, user_group_create_choices,
461 repo_group_create_choices, user_group_create_choices,
458 fork_choices, inherit_default_permissions_choices):
462 fork_choices, inherit_default_permissions_choices):
459 class _DefaultPermissionsForm(formencode.Schema):
463 class _DefaultPermissionsForm(formencode.Schema):
460 allow_extra_fields = True
464 allow_extra_fields = True
461 filter_extra_fields = True
465 filter_extra_fields = True
462
466
463 anonymous = v.StringBoolean(if_missing=False)
467 anonymous = v.StringBoolean(if_missing=False)
464
468
465 default_repo_create = v.OneOf(create_choices)
469 default_repo_create = v.OneOf(create_choices)
466 default_repo_create_on_write = v.OneOf(create_on_write_choices)
470 default_repo_create_on_write = v.OneOf(create_on_write_choices)
467 default_user_group_create = v.OneOf(user_group_create_choices)
471 default_user_group_create = v.OneOf(user_group_create_choices)
468 default_repo_group_create = v.OneOf(repo_group_create_choices)
472 default_repo_group_create = v.OneOf(repo_group_create_choices)
469 default_fork_create = v.OneOf(fork_choices)
473 default_fork_create = v.OneOf(fork_choices)
470 default_inherit_default_permissions = v.OneOf(inherit_default_permissions_choices)
474 default_inherit_default_permissions = v.OneOf(inherit_default_permissions_choices)
471
475
472 return _DefaultPermissionsForm
476 return _DefaultPermissionsForm
473
477
474
478
475 def UserIndividualPermissionsForm():
479 def UserIndividualPermissionsForm():
476 class _DefaultPermissionsForm(formencode.Schema):
480 class _DefaultPermissionsForm(formencode.Schema):
477 allow_extra_fields = True
481 allow_extra_fields = True
478 filter_extra_fields = True
482 filter_extra_fields = True
479
483
480 inherit_default_permissions = v.StringBoolean(if_missing=False)
484 inherit_default_permissions = v.StringBoolean(if_missing=False)
481
485
482 return _DefaultPermissionsForm
486 return _DefaultPermissionsForm
483
487
484
488
485 def DefaultsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
489 def DefaultsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
486 class _DefaultsForm(formencode.Schema):
490 class _DefaultsForm(formencode.Schema):
487 allow_extra_fields = True
491 allow_extra_fields = True
488 filter_extra_fields = True
492 filter_extra_fields = True
489 default_repo_type = v.OneOf(supported_backends)
493 default_repo_type = v.OneOf(supported_backends)
490 default_repo_private = v.StringBoolean(if_missing=False)
494 default_repo_private = v.StringBoolean(if_missing=False)
491 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
495 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
492 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
496 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
493 default_repo_enable_locking = v.StringBoolean(if_missing=False)
497 default_repo_enable_locking = v.StringBoolean(if_missing=False)
494
498
495 return _DefaultsForm
499 return _DefaultsForm
496
500
497
501
498 def AuthSettingsForm():
502 def AuthSettingsForm():
499 class _AuthSettingsForm(formencode.Schema):
503 class _AuthSettingsForm(formencode.Schema):
500 allow_extra_fields = True
504 allow_extra_fields = True
501 filter_extra_fields = True
505 filter_extra_fields = True
502 auth_plugins = All(v.ValidAuthPlugins(),
506 auth_plugins = All(v.ValidAuthPlugins(),
503 v.UniqueListFromString()(not_empty=True))
507 v.UniqueListFromString()(not_empty=True))
504
508
505 return _AuthSettingsForm
509 return _AuthSettingsForm
506
510
507
511
508 def UserExtraEmailForm():
512 def UserExtraEmailForm():
509 class _UserExtraEmailForm(formencode.Schema):
513 class _UserExtraEmailForm(formencode.Schema):
510 email = All(v.UniqSystemEmail(), v.Email(not_empty=True))
514 email = All(v.UniqSystemEmail(), v.Email(not_empty=True))
511 return _UserExtraEmailForm
515 return _UserExtraEmailForm
512
516
513
517
514 def UserExtraIpForm():
518 def UserExtraIpForm():
515 class _UserExtraIpForm(formencode.Schema):
519 class _UserExtraIpForm(formencode.Schema):
516 ip = v.ValidIp()(not_empty=True)
520 ip = v.ValidIp()(not_empty=True)
517 return _UserExtraIpForm
521 return _UserExtraIpForm
518
522
519
523
520
524
521 def PullRequestForm(repo_id):
525 def PullRequestForm(repo_id):
522 class ReviewerForm(formencode.Schema):
526 class ReviewerForm(formencode.Schema):
523 user_id = v.Int(not_empty=True)
527 user_id = v.Int(not_empty=True)
524 reasons = All()
528 reasons = All()
525
529
526 class _PullRequestForm(formencode.Schema):
530 class _PullRequestForm(formencode.Schema):
527 allow_extra_fields = True
531 allow_extra_fields = True
528 filter_extra_fields = True
532 filter_extra_fields = True
529
533
530 user = v.UnicodeString(strip=True, required=True)
534 user = v.UnicodeString(strip=True, required=True)
531 source_repo = v.UnicodeString(strip=True, required=True)
535 source_repo = v.UnicodeString(strip=True, required=True)
532 source_ref = v.UnicodeString(strip=True, required=True)
536 source_ref = v.UnicodeString(strip=True, required=True)
533 target_repo = v.UnicodeString(strip=True, required=True)
537 target_repo = v.UnicodeString(strip=True, required=True)
534 target_ref = v.UnicodeString(strip=True, required=True)
538 target_ref = v.UnicodeString(strip=True, required=True)
535 revisions = All(#v.NotReviewedRevisions(repo_id)(),
539 revisions = All(#v.NotReviewedRevisions(repo_id)(),
536 v.UniqueList()(not_empty=True))
540 v.UniqueList()(not_empty=True))
537 review_members = formencode.ForEach(ReviewerForm())
541 review_members = formencode.ForEach(ReviewerForm())
538 pullrequest_title = v.UnicodeString(strip=True, required=True)
542 pullrequest_title = v.UnicodeString(strip=True, required=True)
539 pullrequest_desc = v.UnicodeString(strip=True, required=False)
543 pullrequest_desc = v.UnicodeString(strip=True, required=False)
540
544
541 return _PullRequestForm
545 return _PullRequestForm
542
546
543
547
544 def IssueTrackerPatternsForm():
548 def IssueTrackerPatternsForm():
545 class _IssueTrackerPatternsForm(formencode.Schema):
549 class _IssueTrackerPatternsForm(formencode.Schema):
546 allow_extra_fields = True
550 allow_extra_fields = True
547 filter_extra_fields = False
551 filter_extra_fields = False
548 chained_validators = [v.ValidPattern()]
552 chained_validators = [v.ValidPattern()]
549 return _IssueTrackerPatternsForm
553 return _IssueTrackerPatternsForm
@@ -1,731 +1,737 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 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 hashlib
21 import hashlib
22 import logging
22 import logging
23 from collections import namedtuple
23 from collections import namedtuple
24 from functools import wraps
24 from functools import wraps
25
25
26 from rhodecode.lib import caches
26 from rhodecode.lib import caches
27 from rhodecode.lib.utils2 import (
27 from rhodecode.lib.utils2 import (
28 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
28 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
29 from rhodecode.lib.vcs.backends import base
29 from rhodecode.lib.vcs.backends import base
30 from rhodecode.model import BaseModel
30 from rhodecode.model import BaseModel
31 from rhodecode.model.db import (
31 from rhodecode.model.db import (
32 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting)
32 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting)
33 from rhodecode.model.meta import Session
33 from rhodecode.model.meta import Session
34
34
35
35
36 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
37
37
38
38
39 UiSetting = namedtuple(
39 UiSetting = namedtuple(
40 'UiSetting', ['section', 'key', 'value', 'active'])
40 'UiSetting', ['section', 'key', 'value', 'active'])
41
41
42 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
42 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
43
43
44
44
45 class SettingNotFound(Exception):
45 class SettingNotFound(Exception):
46 def __init__(self):
46 def __init__(self):
47 super(SettingNotFound, self).__init__('Setting is not found')
47 super(SettingNotFound, self).__init__('Setting is not found')
48
48
49
49
50 class SettingsModel(BaseModel):
50 class SettingsModel(BaseModel):
51 BUILTIN_HOOKS = (
51 BUILTIN_HOOKS = (
52 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
52 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
53 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
53 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
54 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL)
54 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL)
55 HOOKS_SECTION = 'hooks'
55 HOOKS_SECTION = 'hooks'
56
56
57 def __init__(self, sa=None, repo=None):
57 def __init__(self, sa=None, repo=None):
58 self.repo = repo
58 self.repo = repo
59 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
59 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
60 self.SettingsDbModel = (
60 self.SettingsDbModel = (
61 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
61 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
62 super(SettingsModel, self).__init__(sa)
62 super(SettingsModel, self).__init__(sa)
63
63
64 def get_ui_by_key(self, key):
64 def get_ui_by_key(self, key):
65 q = self.UiDbModel.query()
65 q = self.UiDbModel.query()
66 q = q.filter(self.UiDbModel.ui_key == key)
66 q = q.filter(self.UiDbModel.ui_key == key)
67 q = self._filter_by_repo(RepoRhodeCodeUi, q)
67 q = self._filter_by_repo(RepoRhodeCodeUi, q)
68 return q.scalar()
68 return q.scalar()
69
69
70 def get_ui_by_section(self, section):
70 def get_ui_by_section(self, section):
71 q = self.UiDbModel.query()
71 q = self.UiDbModel.query()
72 q = q.filter(self.UiDbModel.ui_section == section)
72 q = q.filter(self.UiDbModel.ui_section == section)
73 q = self._filter_by_repo(RepoRhodeCodeUi, q)
73 q = self._filter_by_repo(RepoRhodeCodeUi, q)
74 return q.all()
74 return q.all()
75
75
76 def get_ui_by_section_and_key(self, section, key):
76 def get_ui_by_section_and_key(self, section, key):
77 q = self.UiDbModel.query()
77 q = self.UiDbModel.query()
78 q = q.filter(self.UiDbModel.ui_section == section)
78 q = q.filter(self.UiDbModel.ui_section == section)
79 q = q.filter(self.UiDbModel.ui_key == key)
79 q = q.filter(self.UiDbModel.ui_key == key)
80 q = self._filter_by_repo(RepoRhodeCodeUi, q)
80 q = self._filter_by_repo(RepoRhodeCodeUi, q)
81 return q.scalar()
81 return q.scalar()
82
82
83 def get_ui(self, section=None, key=None):
83 def get_ui(self, section=None, key=None):
84 q = self.UiDbModel.query()
84 q = self.UiDbModel.query()
85 q = self._filter_by_repo(RepoRhodeCodeUi, q)
85 q = self._filter_by_repo(RepoRhodeCodeUi, q)
86
86
87 if section:
87 if section:
88 q = q.filter(self.UiDbModel.ui_section == section)
88 q = q.filter(self.UiDbModel.ui_section == section)
89 if key:
89 if key:
90 q = q.filter(self.UiDbModel.ui_key == key)
90 q = q.filter(self.UiDbModel.ui_key == key)
91
91
92 # TODO: mikhail: add caching
92 # TODO: mikhail: add caching
93 result = [
93 result = [
94 UiSetting(
94 UiSetting(
95 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
95 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
96 value=safe_str(r.ui_value), active=r.ui_active
96 value=safe_str(r.ui_value), active=r.ui_active
97 )
97 )
98 for r in q.all()
98 for r in q.all()
99 ]
99 ]
100 return result
100 return result
101
101
102 def get_builtin_hooks(self):
102 def get_builtin_hooks(self):
103 q = self.UiDbModel.query()
103 q = self.UiDbModel.query()
104 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
104 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
105 return self._get_hooks(q)
105 return self._get_hooks(q)
106
106
107 def get_custom_hooks(self):
107 def get_custom_hooks(self):
108 q = self.UiDbModel.query()
108 q = self.UiDbModel.query()
109 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
109 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
110 return self._get_hooks(q)
110 return self._get_hooks(q)
111
111
112 def create_ui_section_value(self, section, val, key=None, active=True):
112 def create_ui_section_value(self, section, val, key=None, active=True):
113 new_ui = self.UiDbModel()
113 new_ui = self.UiDbModel()
114 new_ui.ui_section = section
114 new_ui.ui_section = section
115 new_ui.ui_value = val
115 new_ui.ui_value = val
116 new_ui.ui_active = active
116 new_ui.ui_active = active
117
117
118 if self.repo:
118 if self.repo:
119 repo = self._get_repo(self.repo)
119 repo = self._get_repo(self.repo)
120 repository_id = repo.repo_id
120 repository_id = repo.repo_id
121 new_ui.repository_id = repository_id
121 new_ui.repository_id = repository_id
122
122
123 if not key:
123 if not key:
124 # keys are unique so they need appended info
124 # keys are unique so they need appended info
125 if self.repo:
125 if self.repo:
126 key = hashlib.sha1(
126 key = hashlib.sha1(
127 '{}{}{}'.format(section, val, repository_id)).hexdigest()
127 '{}{}{}'.format(section, val, repository_id)).hexdigest()
128 else:
128 else:
129 key = hashlib.sha1('{}{}'.format(section, val)).hexdigest()
129 key = hashlib.sha1('{}{}'.format(section, val)).hexdigest()
130
130
131 new_ui.ui_key = key
131 new_ui.ui_key = key
132
132
133 Session().add(new_ui)
133 Session().add(new_ui)
134 return new_ui
134 return new_ui
135
135
136 def create_or_update_hook(self, key, value):
136 def create_or_update_hook(self, key, value):
137 ui = (
137 ui = (
138 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
138 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
139 self.UiDbModel())
139 self.UiDbModel())
140 ui.ui_section = self.HOOKS_SECTION
140 ui.ui_section = self.HOOKS_SECTION
141 ui.ui_active = True
141 ui.ui_active = True
142 ui.ui_key = key
142 ui.ui_key = key
143 ui.ui_value = value
143 ui.ui_value = value
144
144
145 if self.repo:
145 if self.repo:
146 repo = self._get_repo(self.repo)
146 repo = self._get_repo(self.repo)
147 repository_id = repo.repo_id
147 repository_id = repo.repo_id
148 ui.repository_id = repository_id
148 ui.repository_id = repository_id
149
149
150 Session().add(ui)
150 Session().add(ui)
151 return ui
151 return ui
152
152
153 def delete_ui(self, id_):
153 def delete_ui(self, id_):
154 ui = self.UiDbModel.get(id_)
154 ui = self.UiDbModel.get(id_)
155 if not ui:
155 if not ui:
156 raise SettingNotFound()
156 raise SettingNotFound()
157 Session().delete(ui)
157 Session().delete(ui)
158
158
159 def get_setting_by_name(self, name):
159 def get_setting_by_name(self, name):
160 q = self._get_settings_query()
160 q = self._get_settings_query()
161 q = q.filter(self.SettingsDbModel.app_settings_name == name)
161 q = q.filter(self.SettingsDbModel.app_settings_name == name)
162 return q.scalar()
162 return q.scalar()
163
163
164 def create_or_update_setting(
164 def create_or_update_setting(
165 self, name, val=Optional(''), type_=Optional('unicode')):
165 self, name, val=Optional(''), type_=Optional('unicode')):
166 """
166 """
167 Creates or updates RhodeCode setting. If updates is triggered it will
167 Creates or updates RhodeCode setting. If updates is triggered it will
168 only update parameters that are explicityl set Optional instance will
168 only update parameters that are explicityl set Optional instance will
169 be skipped
169 be skipped
170
170
171 :param name:
171 :param name:
172 :param val:
172 :param val:
173 :param type_:
173 :param type_:
174 :return:
174 :return:
175 """
175 """
176
176
177 res = self.get_setting_by_name(name)
177 res = self.get_setting_by_name(name)
178 repo = self._get_repo(self.repo) if self.repo else None
178 repo = self._get_repo(self.repo) if self.repo else None
179
179
180 if not res:
180 if not res:
181 val = Optional.extract(val)
181 val = Optional.extract(val)
182 type_ = Optional.extract(type_)
182 type_ = Optional.extract(type_)
183
183
184 args = (
184 args = (
185 (repo.repo_id, name, val, type_)
185 (repo.repo_id, name, val, type_)
186 if repo else (name, val, type_))
186 if repo else (name, val, type_))
187 res = self.SettingsDbModel(*args)
187 res = self.SettingsDbModel(*args)
188
188
189 else:
189 else:
190 if self.repo:
190 if self.repo:
191 res.repository_id = repo.repo_id
191 res.repository_id = repo.repo_id
192
192
193 res.app_settings_name = name
193 res.app_settings_name = name
194 if not isinstance(type_, Optional):
194 if not isinstance(type_, Optional):
195 # update if set
195 # update if set
196 res.app_settings_type = type_
196 res.app_settings_type = type_
197 if not isinstance(val, Optional):
197 if not isinstance(val, Optional):
198 # update if set
198 # update if set
199 res.app_settings_value = val
199 res.app_settings_value = val
200
200
201 Session().add(res)
201 Session().add(res)
202 return res
202 return res
203
203
204 def invalidate_settings_cache(self):
204 def invalidate_settings_cache(self):
205 namespace = 'rhodecode_settings'
205 namespace = 'rhodecode_settings'
206 cache_manager = caches.get_cache_manager('sql_cache_short', namespace)
206 cache_manager = caches.get_cache_manager('sql_cache_short', namespace)
207 caches.clear_cache_manager(cache_manager)
207 caches.clear_cache_manager(cache_manager)
208
208
209 def get_all_settings(self, cache=False):
209 def get_all_settings(self, cache=False):
210 def _compute():
210 def _compute():
211 q = self._get_settings_query()
211 q = self._get_settings_query()
212 if not q:
212 if not q:
213 raise Exception('Could not get application settings !')
213 raise Exception('Could not get application settings !')
214
214
215 settings = {
215 settings = {
216 'rhodecode_' + result.app_settings_name: result.app_settings_value
216 'rhodecode_' + result.app_settings_name: result.app_settings_value
217 for result in q
217 for result in q
218 }
218 }
219 return settings
219 return settings
220
220
221 if cache:
221 if cache:
222 log.debug('Fetching app settings using cache')
222 log.debug('Fetching app settings using cache')
223 repo = self._get_repo(self.repo) if self.repo else None
223 repo = self._get_repo(self.repo) if self.repo else None
224 namespace = 'rhodecode_settings'
224 namespace = 'rhodecode_settings'
225 cache_manager = caches.get_cache_manager(
225 cache_manager = caches.get_cache_manager(
226 'sql_cache_short', namespace)
226 'sql_cache_short', namespace)
227 _cache_key = (
227 _cache_key = (
228 "get_repo_{}_settings".format(repo.repo_id)
228 "get_repo_{}_settings".format(repo.repo_id)
229 if repo else "get_app_settings")
229 if repo else "get_app_settings")
230
230
231 return cache_manager.get(_cache_key, createfunc=_compute)
231 return cache_manager.get(_cache_key, createfunc=_compute)
232
232
233 else:
233 else:
234 return _compute()
234 return _compute()
235
235
236 def get_auth_settings(self):
236 def get_auth_settings(self):
237 q = self._get_settings_query()
237 q = self._get_settings_query()
238 q = q.filter(
238 q = q.filter(
239 self.SettingsDbModel.app_settings_name.startswith('auth_'))
239 self.SettingsDbModel.app_settings_name.startswith('auth_'))
240 rows = q.all()
240 rows = q.all()
241 auth_settings = {
241 auth_settings = {
242 row.app_settings_name: row.app_settings_value for row in rows}
242 row.app_settings_name: row.app_settings_value for row in rows}
243 return auth_settings
243 return auth_settings
244
244
245 def get_auth_plugins(self):
245 def get_auth_plugins(self):
246 auth_plugins = self.get_setting_by_name("auth_plugins")
246 auth_plugins = self.get_setting_by_name("auth_plugins")
247 return auth_plugins.app_settings_value
247 return auth_plugins.app_settings_value
248
248
249 def get_default_repo_settings(self, strip_prefix=False):
249 def get_default_repo_settings(self, strip_prefix=False):
250 q = self._get_settings_query()
250 q = self._get_settings_query()
251 q = q.filter(
251 q = q.filter(
252 self.SettingsDbModel.app_settings_name.startswith('default_'))
252 self.SettingsDbModel.app_settings_name.startswith('default_'))
253 rows = q.all()
253 rows = q.all()
254
254
255 result = {}
255 result = {}
256 for row in rows:
256 for row in rows:
257 key = row.app_settings_name
257 key = row.app_settings_name
258 if strip_prefix:
258 if strip_prefix:
259 key = remove_prefix(key, prefix='default_')
259 key = remove_prefix(key, prefix='default_')
260 result.update({key: row.app_settings_value})
260 result.update({key: row.app_settings_value})
261 return result
261 return result
262
262
263 def get_repo(self):
263 def get_repo(self):
264 repo = self._get_repo(self.repo)
264 repo = self._get_repo(self.repo)
265 if not repo:
265 if not repo:
266 raise Exception(
266 raise Exception(
267 'Repository `{}` cannot be found inside the database'.format(
267 'Repository `{}` cannot be found inside the database'.format(
268 self.repo))
268 self.repo))
269 return repo
269 return repo
270
270
271 def _filter_by_repo(self, model, query):
271 def _filter_by_repo(self, model, query):
272 if self.repo:
272 if self.repo:
273 repo = self.get_repo()
273 repo = self.get_repo()
274 query = query.filter(model.repository_id == repo.repo_id)
274 query = query.filter(model.repository_id == repo.repo_id)
275 return query
275 return query
276
276
277 def _get_hooks(self, query):
277 def _get_hooks(self, query):
278 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
278 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
279 query = self._filter_by_repo(RepoRhodeCodeUi, query)
279 query = self._filter_by_repo(RepoRhodeCodeUi, query)
280 return query.all()
280 return query.all()
281
281
282 def _get_settings_query(self):
282 def _get_settings_query(self):
283 q = self.SettingsDbModel.query()
283 q = self.SettingsDbModel.query()
284 return self._filter_by_repo(RepoRhodeCodeSetting, q)
284 return self._filter_by_repo(RepoRhodeCodeSetting, q)
285
285
286 def list_enabled_social_plugins(self, settings):
286 def list_enabled_social_plugins(self, settings):
287 enabled = []
287 enabled = []
288 for plug in SOCIAL_PLUGINS_LIST:
288 for plug in SOCIAL_PLUGINS_LIST:
289 if str2bool(settings.get('rhodecode_auth_{}_enabled'.format(plug)
289 if str2bool(settings.get('rhodecode_auth_{}_enabled'.format(plug)
290 )):
290 )):
291 enabled.append(plug)
291 enabled.append(plug)
292 return enabled
292 return enabled
293
293
294
294
295 def assert_repo_settings(func):
295 def assert_repo_settings(func):
296 @wraps(func)
296 @wraps(func)
297 def _wrapper(self, *args, **kwargs):
297 def _wrapper(self, *args, **kwargs):
298 if not self.repo_settings:
298 if not self.repo_settings:
299 raise Exception('Repository is not specified')
299 raise Exception('Repository is not specified')
300 return func(self, *args, **kwargs)
300 return func(self, *args, **kwargs)
301 return _wrapper
301 return _wrapper
302
302
303
303
304 class IssueTrackerSettingsModel(object):
304 class IssueTrackerSettingsModel(object):
305 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
305 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
306 SETTINGS_PREFIX = 'issuetracker_'
306 SETTINGS_PREFIX = 'issuetracker_'
307
307
308 def __init__(self, sa=None, repo=None):
308 def __init__(self, sa=None, repo=None):
309 self.global_settings = SettingsModel(sa=sa)
309 self.global_settings = SettingsModel(sa=sa)
310 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
310 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
311
311
312 @property
312 @property
313 def inherit_global_settings(self):
313 def inherit_global_settings(self):
314 if not self.repo_settings:
314 if not self.repo_settings:
315 return True
315 return True
316 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
316 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
317 return setting.app_settings_value if setting else True
317 return setting.app_settings_value if setting else True
318
318
319 @inherit_global_settings.setter
319 @inherit_global_settings.setter
320 def inherit_global_settings(self, value):
320 def inherit_global_settings(self, value):
321 if self.repo_settings:
321 if self.repo_settings:
322 settings = self.repo_settings.create_or_update_setting(
322 settings = self.repo_settings.create_or_update_setting(
323 self.INHERIT_SETTINGS, value, type_='bool')
323 self.INHERIT_SETTINGS, value, type_='bool')
324 Session().add(settings)
324 Session().add(settings)
325
325
326 def _get_keyname(self, key, uid, prefix=''):
326 def _get_keyname(self, key, uid, prefix=''):
327 return '{0}{1}{2}_{3}'.format(
327 return '{0}{1}{2}_{3}'.format(
328 prefix, self.SETTINGS_PREFIX, key, uid)
328 prefix, self.SETTINGS_PREFIX, key, uid)
329
329
330 def _make_dict_for_settings(self, qs):
330 def _make_dict_for_settings(self, qs):
331 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
331 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
332
332
333 issuetracker_entries = {}
333 issuetracker_entries = {}
334 # create keys
334 # create keys
335 for k, v in qs.items():
335 for k, v in qs.items():
336 if k.startswith(prefix_match):
336 if k.startswith(prefix_match):
337 uid = k[len(prefix_match):]
337 uid = k[len(prefix_match):]
338 issuetracker_entries[uid] = None
338 issuetracker_entries[uid] = None
339
339
340 # populate
340 # populate
341 for uid in issuetracker_entries:
341 for uid in issuetracker_entries:
342 issuetracker_entries[uid] = AttributeDict({
342 issuetracker_entries[uid] = AttributeDict({
343 'pat': qs.get(self._get_keyname('pat', uid, 'rhodecode_')),
343 'pat': qs.get(self._get_keyname('pat', uid, 'rhodecode_')),
344 'url': qs.get(self._get_keyname('url', uid, 'rhodecode_')),
344 'url': qs.get(self._get_keyname('url', uid, 'rhodecode_')),
345 'pref': qs.get(self._get_keyname('pref', uid, 'rhodecode_')),
345 'pref': qs.get(self._get_keyname('pref', uid, 'rhodecode_')),
346 'desc': qs.get(self._get_keyname('desc', uid, 'rhodecode_')),
346 'desc': qs.get(self._get_keyname('desc', uid, 'rhodecode_')),
347 })
347 })
348 return issuetracker_entries
348 return issuetracker_entries
349
349
350 def get_global_settings(self, cache=False):
350 def get_global_settings(self, cache=False):
351 """
351 """
352 Returns list of global issue tracker settings
352 Returns list of global issue tracker settings
353 """
353 """
354 defaults = self.global_settings.get_all_settings(cache=cache)
354 defaults = self.global_settings.get_all_settings(cache=cache)
355 settings = self._make_dict_for_settings(defaults)
355 settings = self._make_dict_for_settings(defaults)
356 return settings
356 return settings
357
357
358 def get_repo_settings(self, cache=False):
358 def get_repo_settings(self, cache=False):
359 """
359 """
360 Returns list of issue tracker settings per repository
360 Returns list of issue tracker settings per repository
361 """
361 """
362 if not self.repo_settings:
362 if not self.repo_settings:
363 raise Exception('Repository is not specified')
363 raise Exception('Repository is not specified')
364 all_settings = self.repo_settings.get_all_settings(cache=cache)
364 all_settings = self.repo_settings.get_all_settings(cache=cache)
365 settings = self._make_dict_for_settings(all_settings)
365 settings = self._make_dict_for_settings(all_settings)
366 return settings
366 return settings
367
367
368 def get_settings(self, cache=False):
368 def get_settings(self, cache=False):
369 if self.inherit_global_settings:
369 if self.inherit_global_settings:
370 return self.get_global_settings(cache=cache)
370 return self.get_global_settings(cache=cache)
371 else:
371 else:
372 return self.get_repo_settings(cache=cache)
372 return self.get_repo_settings(cache=cache)
373
373
374 def delete_entries(self, uid):
374 def delete_entries(self, uid):
375 if self.repo_settings:
375 if self.repo_settings:
376 all_patterns = self.get_repo_settings()
376 all_patterns = self.get_repo_settings()
377 settings_model = self.repo_settings
377 settings_model = self.repo_settings
378 else:
378 else:
379 all_patterns = self.get_global_settings()
379 all_patterns = self.get_global_settings()
380 settings_model = self.global_settings
380 settings_model = self.global_settings
381 entries = all_patterns.get(uid)
381 entries = all_patterns.get(uid)
382
382
383 for del_key in entries:
383 for del_key in entries:
384 setting_name = self._get_keyname(del_key, uid)
384 setting_name = self._get_keyname(del_key, uid)
385 entry = settings_model.get_setting_by_name(setting_name)
385 entry = settings_model.get_setting_by_name(setting_name)
386 if entry:
386 if entry:
387 Session().delete(entry)
387 Session().delete(entry)
388
388
389 Session().commit()
389 Session().commit()
390
390
391 def create_or_update_setting(
391 def create_or_update_setting(
392 self, name, val=Optional(''), type_=Optional('unicode')):
392 self, name, val=Optional(''), type_=Optional('unicode')):
393 if self.repo_settings:
393 if self.repo_settings:
394 setting = self.repo_settings.create_or_update_setting(
394 setting = self.repo_settings.create_or_update_setting(
395 name, val, type_)
395 name, val, type_)
396 else:
396 else:
397 setting = self.global_settings.create_or_update_setting(
397 setting = self.global_settings.create_or_update_setting(
398 name, val, type_)
398 name, val, type_)
399 return setting
399 return setting
400
400
401
401
402 class VcsSettingsModel(object):
402 class VcsSettingsModel(object):
403
403
404 INHERIT_SETTINGS = 'inherit_vcs_settings'
404 INHERIT_SETTINGS = 'inherit_vcs_settings'
405 GENERAL_SETTINGS = (
405 GENERAL_SETTINGS = (
406 'use_outdated_comments',
406 'use_outdated_comments',
407 'pr_merge_enabled',
407 'pr_merge_enabled',
408 'hg_use_rebase_for_merging')
408 'hg_use_rebase_for_merging')
409
409
410 HOOKS_SETTINGS = (
410 HOOKS_SETTINGS = (
411 ('hooks', 'changegroup.repo_size'),
411 ('hooks', 'changegroup.repo_size'),
412 ('hooks', 'changegroup.push_logger'),
412 ('hooks', 'changegroup.push_logger'),
413 ('hooks', 'outgoing.pull_logger'))
413 ('hooks', 'outgoing.pull_logger'))
414 HG_SETTINGS = (
414 HG_SETTINGS = (
415 ('extensions', 'largefiles'),
415 ('extensions', 'largefiles'),
416 ('phases', 'publish'))
416 ('phases', 'publish'))
417 GLOBAL_HG_SETTINGS = (
417 GLOBAL_HG_SETTINGS = (
418 ('extensions', 'largefiles'),
418 ('extensions', 'largefiles'),
419 ('largefiles', 'usercache'),
419 ('phases', 'publish'),
420 ('phases', 'publish'),
420 ('extensions', 'hgsubversion'))
421 ('extensions', 'hgsubversion'))
421 GLOBAL_SVN_SETTINGS = (
422 GLOBAL_SVN_SETTINGS = (
422 ('vcs_svn_proxy', 'http_requests_enabled'),
423 ('vcs_svn_proxy', 'http_requests_enabled'),
423 ('vcs_svn_proxy', 'http_server_url'))
424 ('vcs_svn_proxy', 'http_server_url'))
424
425
425 SVN_BRANCH_SECTION = 'vcs_svn_branch'
426 SVN_BRANCH_SECTION = 'vcs_svn_branch'
426 SVN_TAG_SECTION = 'vcs_svn_tag'
427 SVN_TAG_SECTION = 'vcs_svn_tag'
427 SSL_SETTING = ('web', 'push_ssl')
428 SSL_SETTING = ('web', 'push_ssl')
428 PATH_SETTING = ('paths', '/')
429 PATH_SETTING = ('paths', '/')
429
430
430 def __init__(self, sa=None, repo=None):
431 def __init__(self, sa=None, repo=None):
431 self.global_settings = SettingsModel(sa=sa)
432 self.global_settings = SettingsModel(sa=sa)
432 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
433 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
433 self._ui_settings = self.HG_SETTINGS + self.HOOKS_SETTINGS
434 self._ui_settings = self.HG_SETTINGS + self.HOOKS_SETTINGS
434 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
435 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
435
436
436 @property
437 @property
437 @assert_repo_settings
438 @assert_repo_settings
438 def inherit_global_settings(self):
439 def inherit_global_settings(self):
439 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
440 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
440 return setting.app_settings_value if setting else True
441 return setting.app_settings_value if setting else True
441
442
442 @inherit_global_settings.setter
443 @inherit_global_settings.setter
443 @assert_repo_settings
444 @assert_repo_settings
444 def inherit_global_settings(self, value):
445 def inherit_global_settings(self, value):
445 self.repo_settings.create_or_update_setting(
446 self.repo_settings.create_or_update_setting(
446 self.INHERIT_SETTINGS, value, type_='bool')
447 self.INHERIT_SETTINGS, value, type_='bool')
447
448
448 def get_global_svn_branch_patterns(self):
449 def get_global_svn_branch_patterns(self):
449 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
450 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
450
451
451 @assert_repo_settings
452 @assert_repo_settings
452 def get_repo_svn_branch_patterns(self):
453 def get_repo_svn_branch_patterns(self):
453 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
454 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
454
455
455 def get_global_svn_tag_patterns(self):
456 def get_global_svn_tag_patterns(self):
456 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
457 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
457
458
458 @assert_repo_settings
459 @assert_repo_settings
459 def get_repo_svn_tag_patterns(self):
460 def get_repo_svn_tag_patterns(self):
460 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
461 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
461
462
462 def get_global_settings(self):
463 def get_global_settings(self):
463 return self._collect_all_settings(global_=True)
464 return self._collect_all_settings(global_=True)
464
465
465 @assert_repo_settings
466 @assert_repo_settings
466 def get_repo_settings(self):
467 def get_repo_settings(self):
467 return self._collect_all_settings(global_=False)
468 return self._collect_all_settings(global_=False)
468
469
469 @assert_repo_settings
470 @assert_repo_settings
470 def create_or_update_repo_settings(
471 def create_or_update_repo_settings(
471 self, data, inherit_global_settings=False):
472 self, data, inherit_global_settings=False):
472 from rhodecode.model.scm import ScmModel
473 from rhodecode.model.scm import ScmModel
473
474
474 self.inherit_global_settings = inherit_global_settings
475 self.inherit_global_settings = inherit_global_settings
475
476
476 repo = self.repo_settings.get_repo()
477 repo = self.repo_settings.get_repo()
477 if not inherit_global_settings:
478 if not inherit_global_settings:
478 if repo.repo_type == 'svn':
479 if repo.repo_type == 'svn':
479 self.create_repo_svn_settings(data)
480 self.create_repo_svn_settings(data)
480 else:
481 else:
481 self.create_or_update_repo_hook_settings(data)
482 self.create_or_update_repo_hook_settings(data)
482 self.create_or_update_repo_pr_settings(data)
483 self.create_or_update_repo_pr_settings(data)
483
484
484 if repo.repo_type == 'hg':
485 if repo.repo_type == 'hg':
485 self.create_or_update_repo_hg_settings(data)
486 self.create_or_update_repo_hg_settings(data)
486
487
487 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
488 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
488
489
489 @assert_repo_settings
490 @assert_repo_settings
490 def create_or_update_repo_hook_settings(self, data):
491 def create_or_update_repo_hook_settings(self, data):
491 for section, key in self.HOOKS_SETTINGS:
492 for section, key in self.HOOKS_SETTINGS:
492 data_key = self._get_form_ui_key(section, key)
493 data_key = self._get_form_ui_key(section, key)
493 if data_key not in data:
494 if data_key not in data:
494 raise ValueError(
495 raise ValueError(
495 'The given data does not contain {} key'.format(data_key))
496 'The given data does not contain {} key'.format(data_key))
496
497
497 active = data.get(data_key)
498 active = data.get(data_key)
498 repo_setting = self.repo_settings.get_ui_by_section_and_key(
499 repo_setting = self.repo_settings.get_ui_by_section_and_key(
499 section, key)
500 section, key)
500 if not repo_setting:
501 if not repo_setting:
501 global_setting = self.global_settings.\
502 global_setting = self.global_settings.\
502 get_ui_by_section_and_key(section, key)
503 get_ui_by_section_and_key(section, key)
503 self.repo_settings.create_ui_section_value(
504 self.repo_settings.create_ui_section_value(
504 section, global_setting.ui_value, key=key, active=active)
505 section, global_setting.ui_value, key=key, active=active)
505 else:
506 else:
506 repo_setting.ui_active = active
507 repo_setting.ui_active = active
507 Session().add(repo_setting)
508 Session().add(repo_setting)
508
509
509 def update_global_hook_settings(self, data):
510 def update_global_hook_settings(self, data):
510 for section, key in self.HOOKS_SETTINGS:
511 for section, key in self.HOOKS_SETTINGS:
511 data_key = self._get_form_ui_key(section, key)
512 data_key = self._get_form_ui_key(section, key)
512 if data_key not in data:
513 if data_key not in data:
513 raise ValueError(
514 raise ValueError(
514 'The given data does not contain {} key'.format(data_key))
515 'The given data does not contain {} key'.format(data_key))
515 active = data.get(data_key)
516 active = data.get(data_key)
516 repo_setting = self.global_settings.get_ui_by_section_and_key(
517 repo_setting = self.global_settings.get_ui_by_section_and_key(
517 section, key)
518 section, key)
518 repo_setting.ui_active = active
519 repo_setting.ui_active = active
519 Session().add(repo_setting)
520 Session().add(repo_setting)
520
521
521 @assert_repo_settings
522 @assert_repo_settings
522 def create_or_update_repo_pr_settings(self, data):
523 def create_or_update_repo_pr_settings(self, data):
523 return self._create_or_update_general_settings(
524 return self._create_or_update_general_settings(
524 self.repo_settings, data)
525 self.repo_settings, data)
525
526
526 def create_or_update_global_pr_settings(self, data):
527 def create_or_update_global_pr_settings(self, data):
527 return self._create_or_update_general_settings(
528 return self._create_or_update_general_settings(
528 self.global_settings, data)
529 self.global_settings, data)
529
530
530 @assert_repo_settings
531 @assert_repo_settings
531 def create_repo_svn_settings(self, data):
532 def create_repo_svn_settings(self, data):
532 return self._create_svn_settings(self.repo_settings, data)
533 return self._create_svn_settings(self.repo_settings, data)
533
534
534 @assert_repo_settings
535 @assert_repo_settings
535 def create_or_update_repo_hg_settings(self, data):
536 def create_or_update_repo_hg_settings(self, data):
536 largefiles, phases = self.HG_SETTINGS
537 largefiles, phases = self.HG_SETTINGS
537 largefiles_key, phases_key = self._get_settings_keys(
538 largefiles_key, phases_key = self._get_settings_keys(
538 self.HG_SETTINGS, data)
539 self.HG_SETTINGS, data)
539 self._create_or_update_ui(
540 self._create_or_update_ui(
540 self.repo_settings, *largefiles, value='',
541 self.repo_settings, *largefiles, value='',
541 active=data[largefiles_key])
542 active=data[largefiles_key])
542 self._create_or_update_ui(
543 self._create_or_update_ui(
543 self.repo_settings, *phases, value=safe_str(data[phases_key]))
544 self.repo_settings, *phases, value=safe_str(data[phases_key]))
544
545
545 def create_or_update_global_hg_settings(self, data):
546 def create_or_update_global_hg_settings(self, data):
546 largefiles, phases, hgsubversion = self.GLOBAL_HG_SETTINGS
547 largefiles, largefiles_store, phases, hgsubversion \
547 largefiles_key, phases_key, subversion_key = self._get_settings_keys(
548 = self.GLOBAL_HG_SETTINGS
548 self.GLOBAL_HG_SETTINGS, data)
549 largefiles_key, largefiles_store_key, phases_key, subversion_key \
550 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS, data)
551
549 self._create_or_update_ui(
552 self._create_or_update_ui(
550 self.global_settings, *largefiles, value='',
553 self.global_settings, *largefiles, value='',
551 active=data[largefiles_key])
554 active=data[largefiles_key])
552 self._create_or_update_ui(
555 self._create_or_update_ui(
556 self.global_settings, *largefiles_store,
557 value=data[largefiles_store_key])
558 self._create_or_update_ui(
553 self.global_settings, *phases, value=safe_str(data[phases_key]))
559 self.global_settings, *phases, value=safe_str(data[phases_key]))
554 self._create_or_update_ui(
560 self._create_or_update_ui(
555 self.global_settings, *hgsubversion, active=data[subversion_key])
561 self.global_settings, *hgsubversion, active=data[subversion_key])
556
562
557 def create_or_update_global_svn_settings(self, data):
563 def create_or_update_global_svn_settings(self, data):
558 # branch/tags patterns
564 # branch/tags patterns
559 self._create_svn_settings(self.global_settings, data)
565 self._create_svn_settings(self.global_settings, data)
560
566
561 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
567 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
562 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
568 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
563 self.GLOBAL_SVN_SETTINGS, data)
569 self.GLOBAL_SVN_SETTINGS, data)
564
570
565 self._create_or_update_ui(
571 self._create_or_update_ui(
566 self.global_settings, *http_requests_enabled,
572 self.global_settings, *http_requests_enabled,
567 value=safe_str(data[http_requests_enabled_key]))
573 value=safe_str(data[http_requests_enabled_key]))
568 self._create_or_update_ui(
574 self._create_or_update_ui(
569 self.global_settings, *http_server_url,
575 self.global_settings, *http_server_url,
570 value=data[http_server_url_key])
576 value=data[http_server_url_key])
571
577
572 def update_global_ssl_setting(self, value):
578 def update_global_ssl_setting(self, value):
573 self._create_or_update_ui(
579 self._create_or_update_ui(
574 self.global_settings, *self.SSL_SETTING, value=value)
580 self.global_settings, *self.SSL_SETTING, value=value)
575
581
576 def update_global_path_setting(self, value):
582 def update_global_path_setting(self, value):
577 self._create_or_update_ui(
583 self._create_or_update_ui(
578 self.global_settings, *self.PATH_SETTING, value=value)
584 self.global_settings, *self.PATH_SETTING, value=value)
579
585
580 @assert_repo_settings
586 @assert_repo_settings
581 def delete_repo_svn_pattern(self, id_):
587 def delete_repo_svn_pattern(self, id_):
582 self.repo_settings.delete_ui(id_)
588 self.repo_settings.delete_ui(id_)
583
589
584 def delete_global_svn_pattern(self, id_):
590 def delete_global_svn_pattern(self, id_):
585 self.global_settings.delete_ui(id_)
591 self.global_settings.delete_ui(id_)
586
592
587 @assert_repo_settings
593 @assert_repo_settings
588 def get_repo_ui_settings(self, section=None, key=None):
594 def get_repo_ui_settings(self, section=None, key=None):
589 global_uis = self.global_settings.get_ui(section, key)
595 global_uis = self.global_settings.get_ui(section, key)
590 repo_uis = self.repo_settings.get_ui(section, key)
596 repo_uis = self.repo_settings.get_ui(section, key)
591 filtered_repo_uis = self._filter_ui_settings(repo_uis)
597 filtered_repo_uis = self._filter_ui_settings(repo_uis)
592 filtered_repo_uis_keys = [
598 filtered_repo_uis_keys = [
593 (s.section, s.key) for s in filtered_repo_uis]
599 (s.section, s.key) for s in filtered_repo_uis]
594
600
595 def _is_global_ui_filtered(ui):
601 def _is_global_ui_filtered(ui):
596 return (
602 return (
597 (ui.section, ui.key) in filtered_repo_uis_keys
603 (ui.section, ui.key) in filtered_repo_uis_keys
598 or ui.section in self._svn_sections)
604 or ui.section in self._svn_sections)
599
605
600 filtered_global_uis = [
606 filtered_global_uis = [
601 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
607 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
602
608
603 return filtered_global_uis + filtered_repo_uis
609 return filtered_global_uis + filtered_repo_uis
604
610
605 def get_global_ui_settings(self, section=None, key=None):
611 def get_global_ui_settings(self, section=None, key=None):
606 return self.global_settings.get_ui(section, key)
612 return self.global_settings.get_ui(section, key)
607
613
608 def get_ui_settings_as_config_obj(self, section=None, key=None):
614 def get_ui_settings_as_config_obj(self, section=None, key=None):
609 config = base.Config()
615 config = base.Config()
610
616
611 ui_settings = self.get_ui_settings(section=section, key=key)
617 ui_settings = self.get_ui_settings(section=section, key=key)
612
618
613 for entry in ui_settings:
619 for entry in ui_settings:
614 config.set(entry.section, entry.key, entry.value)
620 config.set(entry.section, entry.key, entry.value)
615
621
616 return config
622 return config
617
623
618 def get_ui_settings(self, section=None, key=None):
624 def get_ui_settings(self, section=None, key=None):
619 if not self.repo_settings or self.inherit_global_settings:
625 if not self.repo_settings or self.inherit_global_settings:
620 return self.get_global_ui_settings(section, key)
626 return self.get_global_ui_settings(section, key)
621 else:
627 else:
622 return self.get_repo_ui_settings(section, key)
628 return self.get_repo_ui_settings(section, key)
623
629
624 def get_svn_patterns(self, section=None):
630 def get_svn_patterns(self, section=None):
625 if not self.repo_settings:
631 if not self.repo_settings:
626 return self.get_global_ui_settings(section)
632 return self.get_global_ui_settings(section)
627 else:
633 else:
628 return self.get_repo_ui_settings(section)
634 return self.get_repo_ui_settings(section)
629
635
630 @assert_repo_settings
636 @assert_repo_settings
631 def get_repo_general_settings(self):
637 def get_repo_general_settings(self):
632 global_settings = self.global_settings.get_all_settings()
638 global_settings = self.global_settings.get_all_settings()
633 repo_settings = self.repo_settings.get_all_settings()
639 repo_settings = self.repo_settings.get_all_settings()
634 filtered_repo_settings = self._filter_general_settings(repo_settings)
640 filtered_repo_settings = self._filter_general_settings(repo_settings)
635 global_settings.update(filtered_repo_settings)
641 global_settings.update(filtered_repo_settings)
636 return global_settings
642 return global_settings
637
643
638 def get_global_general_settings(self):
644 def get_global_general_settings(self):
639 return self.global_settings.get_all_settings()
645 return self.global_settings.get_all_settings()
640
646
641 def get_general_settings(self):
647 def get_general_settings(self):
642 if not self.repo_settings or self.inherit_global_settings:
648 if not self.repo_settings or self.inherit_global_settings:
643 return self.get_global_general_settings()
649 return self.get_global_general_settings()
644 else:
650 else:
645 return self.get_repo_general_settings()
651 return self.get_repo_general_settings()
646
652
647 def get_repos_location(self):
653 def get_repos_location(self):
648 return self.global_settings.get_ui_by_key('/').ui_value
654 return self.global_settings.get_ui_by_key('/').ui_value
649
655
650 def _filter_ui_settings(self, settings):
656 def _filter_ui_settings(self, settings):
651 filtered_settings = [
657 filtered_settings = [
652 s for s in settings if self._should_keep_setting(s)]
658 s for s in settings if self._should_keep_setting(s)]
653 return filtered_settings
659 return filtered_settings
654
660
655 def _should_keep_setting(self, setting):
661 def _should_keep_setting(self, setting):
656 keep = (
662 keep = (
657 (setting.section, setting.key) in self._ui_settings or
663 (setting.section, setting.key) in self._ui_settings or
658 setting.section in self._svn_sections)
664 setting.section in self._svn_sections)
659 return keep
665 return keep
660
666
661 def _filter_general_settings(self, settings):
667 def _filter_general_settings(self, settings):
662 keys = ['rhodecode_{}'.format(key) for key in self.GENERAL_SETTINGS]
668 keys = ['rhodecode_{}'.format(key) for key in self.GENERAL_SETTINGS]
663 return {
669 return {
664 k: settings[k]
670 k: settings[k]
665 for k in settings if k in keys}
671 for k in settings if k in keys}
666
672
667 def _collect_all_settings(self, global_=False):
673 def _collect_all_settings(self, global_=False):
668 settings = self.global_settings if global_ else self.repo_settings
674 settings = self.global_settings if global_ else self.repo_settings
669 result = {}
675 result = {}
670
676
671 for section, key in self._ui_settings:
677 for section, key in self._ui_settings:
672 ui = settings.get_ui_by_section_and_key(section, key)
678 ui = settings.get_ui_by_section_and_key(section, key)
673 result_key = self._get_form_ui_key(section, key)
679 result_key = self._get_form_ui_key(section, key)
674 if ui:
680 if ui:
675 if section in ('hooks', 'extensions'):
681 if section in ('hooks', 'extensions'):
676 result[result_key] = ui.ui_active
682 result[result_key] = ui.ui_active
677 else:
683 else:
678 result[result_key] = ui.ui_value
684 result[result_key] = ui.ui_value
679
685
680 for name in self.GENERAL_SETTINGS:
686 for name in self.GENERAL_SETTINGS:
681 setting = settings.get_setting_by_name(name)
687 setting = settings.get_setting_by_name(name)
682 if setting:
688 if setting:
683 result_key = 'rhodecode_{}'.format(name)
689 result_key = 'rhodecode_{}'.format(name)
684 result[result_key] = setting.app_settings_value
690 result[result_key] = setting.app_settings_value
685
691
686 return result
692 return result
687
693
688 def _get_form_ui_key(self, section, key):
694 def _get_form_ui_key(self, section, key):
689 return '{section}_{key}'.format(
695 return '{section}_{key}'.format(
690 section=section, key=key.replace('.', '_'))
696 section=section, key=key.replace('.', '_'))
691
697
692 def _create_or_update_ui(
698 def _create_or_update_ui(
693 self, settings, section, key, value=None, active=None):
699 self, settings, section, key, value=None, active=None):
694 ui = settings.get_ui_by_section_and_key(section, key)
700 ui = settings.get_ui_by_section_and_key(section, key)
695 if not ui:
701 if not ui:
696 active = True if active is None else active
702 active = True if active is None else active
697 settings.create_ui_section_value(
703 settings.create_ui_section_value(
698 section, value, key=key, active=active)
704 section, value, key=key, active=active)
699 else:
705 else:
700 if active is not None:
706 if active is not None:
701 ui.ui_active = active
707 ui.ui_active = active
702 if value is not None:
708 if value is not None:
703 ui.ui_value = value
709 ui.ui_value = value
704 Session().add(ui)
710 Session().add(ui)
705
711
706 def _create_svn_settings(self, settings, data):
712 def _create_svn_settings(self, settings, data):
707 svn_settings = {
713 svn_settings = {
708 'new_svn_branch': self.SVN_BRANCH_SECTION,
714 'new_svn_branch': self.SVN_BRANCH_SECTION,
709 'new_svn_tag': self.SVN_TAG_SECTION
715 'new_svn_tag': self.SVN_TAG_SECTION
710 }
716 }
711 for key in svn_settings:
717 for key in svn_settings:
712 if data.get(key):
718 if data.get(key):
713 settings.create_ui_section_value(svn_settings[key], data[key])
719 settings.create_ui_section_value(svn_settings[key], data[key])
714
720
715 def _create_or_update_general_settings(self, settings, data):
721 def _create_or_update_general_settings(self, settings, data):
716 for name in self.GENERAL_SETTINGS:
722 for name in self.GENERAL_SETTINGS:
717 data_key = 'rhodecode_{}'.format(name)
723 data_key = 'rhodecode_{}'.format(name)
718 if data_key not in data:
724 if data_key not in data:
719 raise ValueError(
725 raise ValueError(
720 'The given data does not contain {} key'.format(data_key))
726 'The given data does not contain {} key'.format(data_key))
721 setting = settings.create_or_update_setting(
727 setting = settings.create_or_update_setting(
722 name, data[data_key], 'bool')
728 name, data[data_key], 'bool')
723 Session().add(setting)
729 Session().add(setting)
724
730
725 def _get_settings_keys(self, settings, data):
731 def _get_settings_keys(self, settings, data):
726 data_keys = [self._get_form_ui_key(*s) for s in settings]
732 data_keys = [self._get_form_ui_key(*s) for s in settings]
727 for data_key in data_keys:
733 for data_key in data_keys:
728 if data_key not in data:
734 if data_key not in data:
729 raise ValueError(
735 raise ValueError(
730 'The given data does not contain {} key'.format(data_key))
736 'The given data does not contain {} key'.format(data_key))
731 return data_keys
737 return data_keys
@@ -1,275 +1,291 b''
1 ## snippet for displaying vcs settings
1 ## snippet for displaying vcs settings
2 ## usage:
2 ## usage:
3 ## <%namespace name="vcss" file="/base/vcssettings.mako"/>
3 ## <%namespace name="vcss" file="/base/vcssettings.mako"/>
4 ## ${vcss.vcs_settings_fields()}
4 ## ${vcss.vcs_settings_fields()}
5
5
6 <%def name="vcs_settings_fields(suffix='', svn_branch_patterns=None, svn_tag_patterns=None, repo_type=None, display_globals=False, allow_repo_location_change=False, **kwargs)">
6 <%def name="vcs_settings_fields(suffix='', svn_branch_patterns=None, svn_tag_patterns=None, repo_type=None, display_globals=False, allow_repo_location_change=False, **kwargs)">
7 % if display_globals:
7 % if display_globals:
8 <div class="panel panel-default">
8 <div class="panel panel-default">
9 <div class="panel-heading" id="general">
9 <div class="panel-heading" id="general">
10 <h3 class="panel-title">${_('General')}</h3>
10 <h3 class="panel-title">${_('General')}</h3>
11 </div>
11 </div>
12 <div class="panel-body">
12 <div class="panel-body">
13 <div class="field">
13 <div class="field">
14 <div class="checkbox">
14 <div class="checkbox">
15 ${h.checkbox('web_push_ssl' + suffix, 'True')}
15 ${h.checkbox('web_push_ssl' + suffix, 'True')}
16 <label for="web_push_ssl${suffix}">${_('Require SSL for vcs operations')}</label>
16 <label for="web_push_ssl${suffix}">${_('Require SSL for vcs operations')}</label>
17 </div>
17 </div>
18 <div class="label">
18 <div class="label">
19 <span class="help-block">${_('Activate to set RhodeCode to require SSL for pushing or pulling. If SSL certificate is missing it will return a HTTP Error 406: Not Acceptable.')}</span>
19 <span class="help-block">${_('Activate to set RhodeCode to require SSL for pushing or pulling. If SSL certificate is missing it will return a HTTP Error 406: Not Acceptable.')}</span>
20 </div>
20 </div>
21 </div>
21 </div>
22 </div>
22 </div>
23 </div>
23 </div>
24 % endif
24 % endif
25
25
26 % if display_globals:
26 % if display_globals:
27 <div class="panel panel-default">
27 <div class="panel panel-default">
28 <div class="panel-heading">
28 <div class="panel-heading">
29 <h3 class="panel-title">${_('Main Storage Location')}</h3>
29 <h3 class="panel-title">${_('Main Storage Location')}</h3>
30 </div>
30 </div>
31 <div class="panel-body">
31 <div class="panel-body">
32 <div class="field">
32 <div class="field">
33 <div class="inputx locked_input">
33 <div class="inputx locked_input">
34 %if allow_repo_location_change:
34 %if allow_repo_location_change:
35 ${h.text('paths_root_path',size=59,readonly="readonly", class_="disabled")}
35 ${h.text('paths_root_path',size=59,readonly="readonly", class_="disabled")}
36 <span id="path_unlock" class="tooltip"
36 <span id="path_unlock" class="tooltip"
37 title="${h.tooltip(_('Click to unlock. You must restart RhodeCode in order to make this setting take effect.'))}">
37 title="${h.tooltip(_('Click to unlock. You must restart RhodeCode in order to make this setting take effect.'))}">
38 <div class="btn btn-default lock_input_button"><i id="path_unlock_icon" class="icon-lock"></i></div>
38 <div class="btn btn-default lock_input_button"><i id="path_unlock_icon" class="icon-lock"></i></div>
39 </span>
39 </span>
40 %else:
40 %else:
41 ${_('Repository location change is disabled. You can enable this by changing the `allow_repo_location_change` inside .ini file.')}
41 ${_('Repository location change is disabled. You can enable this by changing the `allow_repo_location_change` inside .ini file.')}
42 ## form still requires this but we cannot internally change it anyway
42 ## form still requires this but we cannot internally change it anyway
43 ${h.hidden('paths_root_path',size=30,readonly="readonly", class_="disabled")}
43 ${h.hidden('paths_root_path',size=30,readonly="readonly", class_="disabled")}
44 %endif
44 %endif
45 </div>
45 </div>
46 </div>
46 </div>
47 <div class="label">
47 <div class="label">
48 <span class="help-block">${_('Filesystem location where repositories should be stored. After changing this value a restart and rescan of the repository folder are required.')}</span>
48 <span class="help-block">${_('Filesystem location where repositories should be stored. After changing this value a restart and rescan of the repository folder are required.')}</span>
49 </div>
49 </div>
50 </div>
50 </div>
51 </div>
51 </div>
52 % endif
52 % endif
53
53
54 % if display_globals or repo_type in ['git', 'hg']:
54 % if display_globals or repo_type in ['git', 'hg']:
55 <div class="panel panel-default">
55 <div class="panel panel-default">
56 <div class="panel-heading" id="general">
56 <div class="panel-heading" id="general">
57 <h3 class="panel-title">${_('Internal Hooks')}</h3>
57 <h3 class="panel-title">${_('Internal Hooks')}</h3>
58 </div>
58 </div>
59 <div class="panel-body">
59 <div class="panel-body">
60 <div class="field">
60 <div class="field">
61 <div class="checkbox">
61 <div class="checkbox">
62 ${h.checkbox('hooks_changegroup_repo_size' + suffix, 'True', **kwargs)}
62 ${h.checkbox('hooks_changegroup_repo_size' + suffix, 'True', **kwargs)}
63 <label for="hooks_changegroup_repo_size${suffix}">${_('Show repository size after push')}</label>
63 <label for="hooks_changegroup_repo_size${suffix}">${_('Show repository size after push')}</label>
64 </div>
64 </div>
65
65
66 <div class="label">
66 <div class="label">
67 <span class="help-block">${_('Trigger a hook that calculates repository size after each push.')}</span>
67 <span class="help-block">${_('Trigger a hook that calculates repository size after each push.')}</span>
68 </div>
68 </div>
69 <div class="checkbox">
69 <div class="checkbox">
70 ${h.checkbox('hooks_changegroup_push_logger' + suffix, 'True', **kwargs)}
70 ${h.checkbox('hooks_changegroup_push_logger' + suffix, 'True', **kwargs)}
71 <label for="hooks_changegroup_push_logger${suffix}">${_('Execute pre/post push hooks')}</label>
71 <label for="hooks_changegroup_push_logger${suffix}">${_('Execute pre/post push hooks')}</label>
72 </div>
72 </div>
73 <div class="label">
73 <div class="label">
74 <span class="help-block">${_('Execute Built in pre/post push hooks. This also executes rcextensions hooks.')}</span>
74 <span class="help-block">${_('Execute Built in pre/post push hooks. This also executes rcextensions hooks.')}</span>
75 </div>
75 </div>
76 <div class="checkbox">
76 <div class="checkbox">
77 ${h.checkbox('hooks_outgoing_pull_logger' + suffix, 'True', **kwargs)}
77 ${h.checkbox('hooks_outgoing_pull_logger' + suffix, 'True', **kwargs)}
78 <label for="hooks_outgoing_pull_logger${suffix}">${_('Execute pre/post pull hooks')}</label>
78 <label for="hooks_outgoing_pull_logger${suffix}">${_('Execute pre/post pull hooks')}</label>
79 </div>
79 </div>
80 <div class="label">
80 <div class="label">
81 <span class="help-block">${_('Execute Built in pre/post pull hooks. This also executes rcextensions hooks.')}</span>
81 <span class="help-block">${_('Execute Built in pre/post pull hooks. This also executes rcextensions hooks.')}</span>
82 </div>
82 </div>
83 </div>
83 </div>
84 </div>
84 </div>
85 </div>
85 </div>
86 % endif
86 % endif
87
87
88 % if display_globals or repo_type in ['hg']:
88 % if display_globals or repo_type in ['hg']:
89 <div class="panel panel-default">
89 <div class="panel panel-default">
90 <div class="panel-heading">
90 <div class="panel-heading">
91 <h3 class="panel-title">${_('Mercurial Settings')}</h3>
91 <h3 class="panel-title">${_('Mercurial Settings')}</h3>
92 </div>
92 </div>
93 <div class="panel-body">
93 <div class="panel-body">
94 <div class="checkbox">
94 <div class="checkbox">
95 ${h.checkbox('extensions_largefiles' + suffix, 'True', **kwargs)}
95 ${h.checkbox('extensions_largefiles' + suffix, 'True', **kwargs)}
96 <label for="extensions_largefiles${suffix}">${_('Enable largefiles extension')}</label>
96 <label for="extensions_largefiles${suffix}">${_('Enable largefiles extension')}</label>
97 </div>
97 </div>
98 <div class="label">
98 <div class="label">
99 <span class="help-block">${_('Enable Largefiles extensions for all repositories.')}</span>
99 % if display_globals:
100 <span class="help-block">${_('Enable Largefiles extensions for all repositories.')}</span>
101 % else:
102 <span class="help-block">${_('Enable Largefiles extensions for this repository.')}</span>
103 % endif
100 </div>
104 </div>
105
106 % if display_globals:
107 <div class="field">
108 <div class="input">
109 ${h.text('largefiles_usercache' + suffix, size=59)}
110 </div>
111 </div>
112 <div class="label">
113 <span class="help-block">${_('Filesystem location where Mercurial largefile objects should be stored.')}</span>
114 </div>
115 % endif
116
101 <div class="checkbox">
117 <div class="checkbox">
102 ${h.checkbox('phases_publish' + suffix, 'True', **kwargs)}
118 ${h.checkbox('phases_publish' + suffix, 'True', **kwargs)}
103 <label for="phases_publish${suffix}">${_('Set repositories as publishing') if display_globals else _('Set repository as publishing')}</label>
119 <label for="phases_publish${suffix}">${_('Set repositories as publishing') if display_globals else _('Set repository as publishing')}</label>
104 </div>
120 </div>
105 <div class="label">
121 <div class="label">
106 <span class="help-block">${_('When this is enabled all commits in the repository are seen as public commits by clients.')}</span>
122 <span class="help-block">${_('When this is enabled all commits in the repository are seen as public commits by clients.')}</span>
107 </div>
123 </div>
108 % if display_globals:
124 % if display_globals:
109 <div class="checkbox">
125 <div class="checkbox">
110 ${h.checkbox('extensions_hgsubversion' + suffix,'True')}
126 ${h.checkbox('extensions_hgsubversion' + suffix,'True')}
111 <label for="extensions_hgsubversion${suffix}">${_('Enable hgsubversion extension')}</label>
127 <label for="extensions_hgsubversion${suffix}">${_('Enable hgsubversion extension')}</label>
112 </div>
128 </div>
113 <div class="label">
129 <div class="label">
114 <span class="help-block">${_('Requires hgsubversion library to be installed. Allows cloning remote SVN repositories and migrates them to Mercurial type.')}</span>
130 <span class="help-block">${_('Requires hgsubversion library to be installed. Allows cloning remote SVN repositories and migrates them to Mercurial type.')}</span>
115 </div>
131 </div>
116 % endif
132 % endif
117 </div>
133 </div>
118 </div>
134 </div>
119 ## LABS for HG
135 ## LABS for HG
120 % if c.labs_active:
136 % if c.labs_active:
121 <div class="panel panel-danger">
137 <div class="panel panel-danger">
122 <div class="panel-heading">
138 <div class="panel-heading">
123 <h3 class="panel-title">${_('Mercurial Labs Settings')} (${_('These features are considered experimental and may not work as expected.')})</h3>
139 <h3 class="panel-title">${_('Mercurial Labs Settings')} (${_('These features are considered experimental and may not work as expected.')})</h3>
124 </div>
140 </div>
125 <div class="panel-body">
141 <div class="panel-body">
126
142
127 <div class="checkbox">
143 <div class="checkbox">
128 ${h.checkbox('rhodecode_hg_use_rebase_for_merging' + suffix, 'True', **kwargs)}
144 ${h.checkbox('rhodecode_hg_use_rebase_for_merging' + suffix, 'True', **kwargs)}
129 <label for="rhodecode_hg_use_rebase_for_merging${suffix}">${_('Use rebase as merge strategy')}</label>
145 <label for="rhodecode_hg_use_rebase_for_merging${suffix}">${_('Use rebase as merge strategy')}</label>
130 </div>
146 </div>
131 <div class="label">
147 <div class="label">
132 <span class="help-block">${_('Use rebase instead of creating a merge commit when merging via web interface.')}</span>
148 <span class="help-block">${_('Use rebase instead of creating a merge commit when merging via web interface.')}</span>
133 </div>
149 </div>
134
150
135 </div>
151 </div>
136 </div>
152 </div>
137 % endif
153 % endif
138
154
139 % endif
155 % endif
140
156
141 % if display_globals:
157 % if display_globals:
142 <div class="panel panel-default">
158 <div class="panel panel-default">
143 <div class="panel-heading">
159 <div class="panel-heading">
144 <h3 class="panel-title">${_('Global Subversion Settings')}</h3>
160 <h3 class="panel-title">${_('Global Subversion Settings')}</h3>
145 </div>
161 </div>
146 <div class="panel-body">
162 <div class="panel-body">
147 <div class="field">
163 <div class="field">
148 <div class="checkbox">
164 <div class="checkbox">
149 ${h.checkbox('vcs_svn_proxy_http_requests_enabled' + suffix, 'True', **kwargs)}
165 ${h.checkbox('vcs_svn_proxy_http_requests_enabled' + suffix, 'True', **kwargs)}
150 <label for="vcs_svn_proxy_http_requests_enabled${suffix}">${_('Proxy subversion HTTP requests')}</label>
166 <label for="vcs_svn_proxy_http_requests_enabled${suffix}">${_('Proxy subversion HTTP requests')}</label>
151 </div>
167 </div>
152 <div class="label">
168 <div class="label">
153 <span class="help-block">
169 <span class="help-block">
154 ${_('Subversion HTTP Support. Enables communication with SVN over HTTP protocol.')}
170 ${_('Subversion HTTP Support. Enables communication with SVN over HTTP protocol.')}
155 <a href="${h.url('enterprise_svn_setup')}" target="_blank">${_('SVN Protocol setup Documentation')}</a>.
171 <a href="${h.url('enterprise_svn_setup')}" target="_blank">${_('SVN Protocol setup Documentation')}</a>.
156 </span>
172 </span>
157 </div>
173 </div>
158 </div>
174 </div>
159 <div class="field">
175 <div class="field">
160 <div class="label">
176 <div class="label">
161 <label for="vcs_svn_proxy_http_server_url">${_('Subversion HTTP Server URL')}</label><br/>
177 <label for="vcs_svn_proxy_http_server_url">${_('Subversion HTTP Server URL')}</label><br/>
162 </div>
178 </div>
163 <div class="input">
179 <div class="input">
164 ${h.text('vcs_svn_proxy_http_server_url',size=59)}
180 ${h.text('vcs_svn_proxy_http_server_url',size=59)}
165 % if c.svn_proxy_generate_config:
181 % if c.svn_proxy_generate_config:
166 <span class="buttons">
182 <span class="buttons">
167 <button class="btn btn-primary" id="vcs_svn_generate_cfg">${_('Generate Apache Config')}</button>
183 <button class="btn btn-primary" id="vcs_svn_generate_cfg">${_('Generate Apache Config')}</button>
168 </span>
184 </span>
169 % endif
185 % endif
170 </div>
186 </div>
171 </div>
187 </div>
172 </div>
188 </div>
173 </div>
189 </div>
174 % endif
190 % endif
175
191
176 % if display_globals or repo_type in ['svn']:
192 % if display_globals or repo_type in ['svn']:
177 <div class="panel panel-default">
193 <div class="panel panel-default">
178 <div class="panel-heading">
194 <div class="panel-heading">
179 <h3 class="panel-title">${_('Subversion Settings')}</h3>
195 <h3 class="panel-title">${_('Subversion Settings')}</h3>
180 </div>
196 </div>
181 <div class="panel-body">
197 <div class="panel-body">
182 <div class="field">
198 <div class="field">
183 <div class="content" >
199 <div class="content" >
184 <label>${_('Repository patterns')}</label><br/>
200 <label>${_('Repository patterns')}</label><br/>
185 </div>
201 </div>
186 </div>
202 </div>
187 <div class="label">
203 <div class="label">
188 <span class="help-block">${_('Patterns for identifying SVN branches and tags. For recursive search, use "*". Eg.: "/branches/*"')}</span>
204 <span class="help-block">${_('Patterns for identifying SVN branches and tags. For recursive search, use "*". Eg.: "/branches/*"')}</span>
189 </div>
205 </div>
190
206
191 <div class="field branch_patterns">
207 <div class="field branch_patterns">
192 <div class="input" >
208 <div class="input" >
193 <label>${_('Branches')}:</label><br/>
209 <label>${_('Branches')}:</label><br/>
194 </div>
210 </div>
195 % if svn_branch_patterns:
211 % if svn_branch_patterns:
196 % for branch in svn_branch_patterns:
212 % for branch in svn_branch_patterns:
197 <div class="input adjacent" id="${'id%s' % branch.ui_id}">
213 <div class="input adjacent" id="${'id%s' % branch.ui_id}">
198 ${h.hidden('branch_ui_key' + suffix, branch.ui_key)}
214 ${h.hidden('branch_ui_key' + suffix, branch.ui_key)}
199 ${h.text('branch_value_%d' % branch.ui_id + suffix, branch.ui_value, size=59, readonly="readonly", class_='disabled')}
215 ${h.text('branch_value_%d' % branch.ui_id + suffix, branch.ui_value, size=59, readonly="readonly", class_='disabled')}
200 % if kwargs.get('disabled') != 'disabled':
216 % if kwargs.get('disabled') != 'disabled':
201 <span class="btn btn-x" onclick="ajaxDeletePattern(${branch.ui_id},'${'id%s' % branch.ui_id}')">
217 <span class="btn btn-x" onclick="ajaxDeletePattern(${branch.ui_id},'${'id%s' % branch.ui_id}')">
202 ${_('Delete')}
218 ${_('Delete')}
203 </span>
219 </span>
204 % endif
220 % endif
205 </div>
221 </div>
206 % endfor
222 % endfor
207 %endif
223 %endif
208 </div>
224 </div>
209 % if kwargs.get('disabled') != 'disabled':
225 % if kwargs.get('disabled') != 'disabled':
210 <div class="field branch_patterns">
226 <div class="field branch_patterns">
211 <div class="input" >
227 <div class="input" >
212 ${h.text('new_svn_branch',size=59,placeholder='New branch pattern')}
228 ${h.text('new_svn_branch',size=59,placeholder='New branch pattern')}
213 </div>
229 </div>
214 </div>
230 </div>
215 % endif
231 % endif
216 <div class="field tag_patterns">
232 <div class="field tag_patterns">
217 <div class="input" >
233 <div class="input" >
218 <label>${_('Tags')}:</label><br/>
234 <label>${_('Tags')}:</label><br/>
219 </div>
235 </div>
220 % if svn_tag_patterns:
236 % if svn_tag_patterns:
221 % for tag in svn_tag_patterns:
237 % for tag in svn_tag_patterns:
222 <div class="input" id="${'id%s' % tag.ui_id + suffix}">
238 <div class="input" id="${'id%s' % tag.ui_id + suffix}">
223 ${h.hidden('tag_ui_key' + suffix, tag.ui_key)}
239 ${h.hidden('tag_ui_key' + suffix, tag.ui_key)}
224 ${h.text('tag_ui_value_new_%d' % tag.ui_id + suffix, tag.ui_value, size=59, readonly="readonly", class_='disabled tag_input')}
240 ${h.text('tag_ui_value_new_%d' % tag.ui_id + suffix, tag.ui_value, size=59, readonly="readonly", class_='disabled tag_input')}
225 % if kwargs.get('disabled') != 'disabled':
241 % if kwargs.get('disabled') != 'disabled':
226 <span class="btn btn-x" onclick="ajaxDeletePattern(${tag.ui_id},'${'id%s' % tag.ui_id}')">
242 <span class="btn btn-x" onclick="ajaxDeletePattern(${tag.ui_id},'${'id%s' % tag.ui_id}')">
227 ${_('Delete')}
243 ${_('Delete')}
228 </span>
244 </span>
229 %endif
245 %endif
230 </div>
246 </div>
231 % endfor
247 % endfor
232 % endif
248 % endif
233 </div>
249 </div>
234 % if kwargs.get('disabled') != 'disabled':
250 % if kwargs.get('disabled') != 'disabled':
235 <div class="field tag_patterns">
251 <div class="field tag_patterns">
236 <div class="input" >
252 <div class="input" >
237 ${h.text('new_svn_tag' + suffix, size=59, placeholder='New tag pattern')}
253 ${h.text('new_svn_tag' + suffix, size=59, placeholder='New tag pattern')}
238 </div>
254 </div>
239 </div>
255 </div>
240 %endif
256 %endif
241 </div>
257 </div>
242 </div>
258 </div>
243 % else:
259 % else:
244 ${h.hidden('new_svn_branch' + suffix, '')}
260 ${h.hidden('new_svn_branch' + suffix, '')}
245 ${h.hidden('new_svn_tag' + suffix, '')}
261 ${h.hidden('new_svn_tag' + suffix, '')}
246 % endif
262 % endif
247
263
248
264
249
265
250
266
251 % if display_globals or repo_type in ['hg', 'git']:
267 % if display_globals or repo_type in ['hg', 'git']:
252 <div class="panel panel-default">
268 <div class="panel panel-default">
253 <div class="panel-heading">
269 <div class="panel-heading">
254 <h3 class="panel-title">${_('Pull Request Settings')}</h3>
270 <h3 class="panel-title">${_('Pull Request Settings')}</h3>
255 </div>
271 </div>
256 <div class="panel-body">
272 <div class="panel-body">
257 <div class="checkbox">
273 <div class="checkbox">
258 ${h.checkbox('rhodecode_pr_merge_enabled' + suffix, 'True', **kwargs)}
274 ${h.checkbox('rhodecode_pr_merge_enabled' + suffix, 'True', **kwargs)}
259 <label for="rhodecode_pr_merge_enabled${suffix}">${_('Enable server-side merge for pull requests')}</label>
275 <label for="rhodecode_pr_merge_enabled${suffix}">${_('Enable server-side merge for pull requests')}</label>
260 </div>
276 </div>
261 <div class="label">
277 <div class="label">
262 <span class="help-block">${_('Note: when this feature is enabled, it only runs hooks defined in the rcextension package. Custom hooks added on the Admin -> Settings -> Hooks page will not be run when pull requests are automatically merged from the web interface.')}</span>
278 <span class="help-block">${_('Note: when this feature is enabled, it only runs hooks defined in the rcextension package. Custom hooks added on the Admin -> Settings -> Hooks page will not be run when pull requests are automatically merged from the web interface.')}</span>
263 </div>
279 </div>
264 <div class="checkbox">
280 <div class="checkbox">
265 ${h.checkbox('rhodecode_use_outdated_comments' + suffix, 'True', **kwargs)}
281 ${h.checkbox('rhodecode_use_outdated_comments' + suffix, 'True', **kwargs)}
266 <label for="rhodecode_use_outdated_comments${suffix}">${_('Invalidate and relocate inline comments during update')}</label>
282 <label for="rhodecode_use_outdated_comments${suffix}">${_('Invalidate and relocate inline comments during update')}</label>
267 </div>
283 </div>
268 <div class="label">
284 <div class="label">
269 <span class="help-block">${_('During the update of a pull request, the position of inline comments will be updated and outdated inline comments will be hidden.')}</span>
285 <span class="help-block">${_('During the update of a pull request, the position of inline comments will be updated and outdated inline comments will be hidden.')}</span>
270 </div>
286 </div>
271 </div>
287 </div>
272 </div>
288 </div>
273 % endif
289 % endif
274
290
275 </%def>
291 </%def>
@@ -1,1029 +1,1034 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 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 mock
21 import mock
22 import pytest
22 import pytest
23
23
24 from rhodecode.lib.utils2 import str2bool
24 from rhodecode.lib.utils2 import str2bool
25 from rhodecode.model.meta import Session
25 from rhodecode.model.meta import Session
26 from rhodecode.model.settings import VcsSettingsModel, UiSetting
26 from rhodecode.model.settings import VcsSettingsModel, UiSetting
27
27
28
28
29 HOOKS_FORM_DATA = {
29 HOOKS_FORM_DATA = {
30 'hooks_changegroup_repo_size': True,
30 'hooks_changegroup_repo_size': True,
31 'hooks_changegroup_push_logger': True,
31 'hooks_changegroup_push_logger': True,
32 'hooks_outgoing_pull_logger': True
32 'hooks_outgoing_pull_logger': True
33 }
33 }
34
34
35 SVN_FORM_DATA = {
35 SVN_FORM_DATA = {
36 'new_svn_branch': 'test-branch',
36 'new_svn_branch': 'test-branch',
37 'new_svn_tag': 'test-tag'
37 'new_svn_tag': 'test-tag'
38 }
38 }
39
39
40 GENERAL_FORM_DATA = {
40 GENERAL_FORM_DATA = {
41 'rhodecode_pr_merge_enabled': True,
41 'rhodecode_pr_merge_enabled': True,
42 'rhodecode_use_outdated_comments': True,
42 'rhodecode_use_outdated_comments': True,
43 'rhodecode_hg_use_rebase_for_merging': True,
43 'rhodecode_hg_use_rebase_for_merging': True,
44 }
44 }
45
45
46
46
47 class TestInheritGlobalSettingsProperty(object):
47 class TestInheritGlobalSettingsProperty(object):
48 def test_get_raises_exception_when_repository_not_specified(self):
48 def test_get_raises_exception_when_repository_not_specified(self):
49 model = VcsSettingsModel()
49 model = VcsSettingsModel()
50 with pytest.raises(Exception) as exc_info:
50 with pytest.raises(Exception) as exc_info:
51 model.inherit_global_settings
51 model.inherit_global_settings
52 assert exc_info.value.message == 'Repository is not specified'
52 assert exc_info.value.message == 'Repository is not specified'
53
53
54 def test_true_is_returned_when_value_is_not_found(self, repo_stub):
54 def test_true_is_returned_when_value_is_not_found(self, repo_stub):
55 model = VcsSettingsModel(repo=repo_stub.repo_name)
55 model = VcsSettingsModel(repo=repo_stub.repo_name)
56 assert model.inherit_global_settings is True
56 assert model.inherit_global_settings is True
57
57
58 def test_value_is_returned(self, repo_stub, settings_util):
58 def test_value_is_returned(self, repo_stub, settings_util):
59 model = VcsSettingsModel(repo=repo_stub.repo_name)
59 model = VcsSettingsModel(repo=repo_stub.repo_name)
60 settings_util.create_repo_rhodecode_setting(
60 settings_util.create_repo_rhodecode_setting(
61 repo_stub, VcsSettingsModel.INHERIT_SETTINGS, False, 'bool')
61 repo_stub, VcsSettingsModel.INHERIT_SETTINGS, False, 'bool')
62 assert model.inherit_global_settings is False
62 assert model.inherit_global_settings is False
63
63
64 def test_value_is_set(self, repo_stub):
64 def test_value_is_set(self, repo_stub):
65 model = VcsSettingsModel(repo=repo_stub.repo_name)
65 model = VcsSettingsModel(repo=repo_stub.repo_name)
66 model.inherit_global_settings = False
66 model.inherit_global_settings = False
67 setting = model.repo_settings.get_setting_by_name(
67 setting = model.repo_settings.get_setting_by_name(
68 VcsSettingsModel.INHERIT_SETTINGS)
68 VcsSettingsModel.INHERIT_SETTINGS)
69 try:
69 try:
70 assert setting.app_settings_type == 'bool'
70 assert setting.app_settings_type == 'bool'
71 assert setting.app_settings_value is False
71 assert setting.app_settings_value is False
72 finally:
72 finally:
73 Session().delete(setting)
73 Session().delete(setting)
74 Session().commit()
74 Session().commit()
75
75
76 def test_set_raises_exception_when_repository_not_specified(self):
76 def test_set_raises_exception_when_repository_not_specified(self):
77 model = VcsSettingsModel()
77 model = VcsSettingsModel()
78 with pytest.raises(Exception) as exc_info:
78 with pytest.raises(Exception) as exc_info:
79 model.inherit_global_settings = False
79 model.inherit_global_settings = False
80 assert exc_info.value.message == 'Repository is not specified'
80 assert exc_info.value.message == 'Repository is not specified'
81
81
82
82
83 class TestVcsSettingsModel(object):
83 class TestVcsSettingsModel(object):
84 def test_global_svn_branch_patterns(self):
84 def test_global_svn_branch_patterns(self):
85 model = VcsSettingsModel()
85 model = VcsSettingsModel()
86 expected_result = {'test': 'test'}
86 expected_result = {'test': 'test'}
87 with mock.patch.object(model, 'global_settings') as settings_mock:
87 with mock.patch.object(model, 'global_settings') as settings_mock:
88 get_settings = settings_mock.get_ui_by_section
88 get_settings = settings_mock.get_ui_by_section
89 get_settings.return_value = expected_result
89 get_settings.return_value = expected_result
90 settings_mock.return_value = expected_result
90 settings_mock.return_value = expected_result
91 result = model.get_global_svn_branch_patterns()
91 result = model.get_global_svn_branch_patterns()
92
92
93 get_settings.assert_called_once_with(model.SVN_BRANCH_SECTION)
93 get_settings.assert_called_once_with(model.SVN_BRANCH_SECTION)
94 assert expected_result == result
94 assert expected_result == result
95
95
96 def test_repo_svn_branch_patterns(self):
96 def test_repo_svn_branch_patterns(self):
97 model = VcsSettingsModel()
97 model = VcsSettingsModel()
98 expected_result = {'test': 'test'}
98 expected_result = {'test': 'test'}
99 with mock.patch.object(model, 'repo_settings') as settings_mock:
99 with mock.patch.object(model, 'repo_settings') as settings_mock:
100 get_settings = settings_mock.get_ui_by_section
100 get_settings = settings_mock.get_ui_by_section
101 get_settings.return_value = expected_result
101 get_settings.return_value = expected_result
102 settings_mock.return_value = expected_result
102 settings_mock.return_value = expected_result
103 result = model.get_repo_svn_branch_patterns()
103 result = model.get_repo_svn_branch_patterns()
104
104
105 get_settings.assert_called_once_with(model.SVN_BRANCH_SECTION)
105 get_settings.assert_called_once_with(model.SVN_BRANCH_SECTION)
106 assert expected_result == result
106 assert expected_result == result
107
107
108 def test_repo_svn_branch_patterns_raises_exception_when_repo_is_not_set(
108 def test_repo_svn_branch_patterns_raises_exception_when_repo_is_not_set(
109 self):
109 self):
110 model = VcsSettingsModel()
110 model = VcsSettingsModel()
111 with pytest.raises(Exception) as exc_info:
111 with pytest.raises(Exception) as exc_info:
112 model.get_repo_svn_branch_patterns()
112 model.get_repo_svn_branch_patterns()
113 assert exc_info.value.message == 'Repository is not specified'
113 assert exc_info.value.message == 'Repository is not specified'
114
114
115 def test_global_svn_tag_patterns(self):
115 def test_global_svn_tag_patterns(self):
116 model = VcsSettingsModel()
116 model = VcsSettingsModel()
117 expected_result = {'test': 'test'}
117 expected_result = {'test': 'test'}
118 with mock.patch.object(model, 'global_settings') as settings_mock:
118 with mock.patch.object(model, 'global_settings') as settings_mock:
119 get_settings = settings_mock.get_ui_by_section
119 get_settings = settings_mock.get_ui_by_section
120 get_settings.return_value = expected_result
120 get_settings.return_value = expected_result
121 settings_mock.return_value = expected_result
121 settings_mock.return_value = expected_result
122 result = model.get_global_svn_tag_patterns()
122 result = model.get_global_svn_tag_patterns()
123
123
124 get_settings.assert_called_once_with(model.SVN_TAG_SECTION)
124 get_settings.assert_called_once_with(model.SVN_TAG_SECTION)
125 assert expected_result == result
125 assert expected_result == result
126
126
127 def test_repo_svn_tag_patterns(self):
127 def test_repo_svn_tag_patterns(self):
128 model = VcsSettingsModel()
128 model = VcsSettingsModel()
129 expected_result = {'test': 'test'}
129 expected_result = {'test': 'test'}
130 with mock.patch.object(model, 'repo_settings') as settings_mock:
130 with mock.patch.object(model, 'repo_settings') as settings_mock:
131 get_settings = settings_mock.get_ui_by_section
131 get_settings = settings_mock.get_ui_by_section
132 get_settings.return_value = expected_result
132 get_settings.return_value = expected_result
133 settings_mock.return_value = expected_result
133 settings_mock.return_value = expected_result
134 result = model.get_repo_svn_tag_patterns()
134 result = model.get_repo_svn_tag_patterns()
135
135
136 get_settings.assert_called_once_with(model.SVN_TAG_SECTION)
136 get_settings.assert_called_once_with(model.SVN_TAG_SECTION)
137 assert expected_result == result
137 assert expected_result == result
138
138
139 def test_repo_svn_tag_patterns_raises_exception_when_repo_is_not_set(self):
139 def test_repo_svn_tag_patterns_raises_exception_when_repo_is_not_set(self):
140 model = VcsSettingsModel()
140 model = VcsSettingsModel()
141 with pytest.raises(Exception) as exc_info:
141 with pytest.raises(Exception) as exc_info:
142 model.get_repo_svn_tag_patterns()
142 model.get_repo_svn_tag_patterns()
143 assert exc_info.value.message == 'Repository is not specified'
143 assert exc_info.value.message == 'Repository is not specified'
144
144
145 def test_get_global_settings(self):
145 def test_get_global_settings(self):
146 expected_result = {'test': 'test'}
146 expected_result = {'test': 'test'}
147 model = VcsSettingsModel()
147 model = VcsSettingsModel()
148 with mock.patch.object(model, '_collect_all_settings') as collect_mock:
148 with mock.patch.object(model, '_collect_all_settings') as collect_mock:
149 collect_mock.return_value = expected_result
149 collect_mock.return_value = expected_result
150 result = model.get_global_settings()
150 result = model.get_global_settings()
151
151
152 collect_mock.assert_called_once_with(global_=True)
152 collect_mock.assert_called_once_with(global_=True)
153 assert result == expected_result
153 assert result == expected_result
154
154
155 def test_get_repo_settings(self, repo_stub):
155 def test_get_repo_settings(self, repo_stub):
156 model = VcsSettingsModel(repo=repo_stub.repo_name)
156 model = VcsSettingsModel(repo=repo_stub.repo_name)
157 expected_result = {'test': 'test'}
157 expected_result = {'test': 'test'}
158 with mock.patch.object(model, '_collect_all_settings') as collect_mock:
158 with mock.patch.object(model, '_collect_all_settings') as collect_mock:
159 collect_mock.return_value = expected_result
159 collect_mock.return_value = expected_result
160 result = model.get_repo_settings()
160 result = model.get_repo_settings()
161
161
162 collect_mock.assert_called_once_with(global_=False)
162 collect_mock.assert_called_once_with(global_=False)
163 assert result == expected_result
163 assert result == expected_result
164
164
165 @pytest.mark.parametrize('settings, global_', [
165 @pytest.mark.parametrize('settings, global_', [
166 ('global_settings', True),
166 ('global_settings', True),
167 ('repo_settings', False)
167 ('repo_settings', False)
168 ])
168 ])
169 def test_collect_all_settings(self, settings, global_):
169 def test_collect_all_settings(self, settings, global_):
170 model = VcsSettingsModel()
170 model = VcsSettingsModel()
171 result_mock = self._mock_result()
171 result_mock = self._mock_result()
172
172
173 settings_patch = mock.patch.object(model, settings)
173 settings_patch = mock.patch.object(model, settings)
174 with settings_patch as settings_mock:
174 with settings_patch as settings_mock:
175 settings_mock.get_ui_by_section_and_key.return_value = result_mock
175 settings_mock.get_ui_by_section_and_key.return_value = result_mock
176 settings_mock.get_setting_by_name.return_value = result_mock
176 settings_mock.get_setting_by_name.return_value = result_mock
177 result = model._collect_all_settings(global_=global_)
177 result = model._collect_all_settings(global_=global_)
178
178
179 ui_settings = model.HG_SETTINGS + model.HOOKS_SETTINGS
179 ui_settings = model.HG_SETTINGS + model.HOOKS_SETTINGS
180 self._assert_get_settings_calls(
180 self._assert_get_settings_calls(
181 settings_mock, ui_settings, model.GENERAL_SETTINGS)
181 settings_mock, ui_settings, model.GENERAL_SETTINGS)
182 self._assert_collect_all_settings_result(
182 self._assert_collect_all_settings_result(
183 ui_settings, model.GENERAL_SETTINGS, result)
183 ui_settings, model.GENERAL_SETTINGS, result)
184
184
185 @pytest.mark.parametrize('settings, global_', [
185 @pytest.mark.parametrize('settings, global_', [
186 ('global_settings', True),
186 ('global_settings', True),
187 ('repo_settings', False)
187 ('repo_settings', False)
188 ])
188 ])
189 def test_collect_all_settings_without_empty_value(self, settings, global_):
189 def test_collect_all_settings_without_empty_value(self, settings, global_):
190 model = VcsSettingsModel()
190 model = VcsSettingsModel()
191
191
192 settings_patch = mock.patch.object(model, settings)
192 settings_patch = mock.patch.object(model, settings)
193 with settings_patch as settings_mock:
193 with settings_patch as settings_mock:
194 settings_mock.get_ui_by_section_and_key.return_value = None
194 settings_mock.get_ui_by_section_and_key.return_value = None
195 settings_mock.get_setting_by_name.return_value = None
195 settings_mock.get_setting_by_name.return_value = None
196 result = model._collect_all_settings(global_=global_)
196 result = model._collect_all_settings(global_=global_)
197
197
198 assert result == {}
198 assert result == {}
199
199
200 def _mock_result(self):
200 def _mock_result(self):
201 result_mock = mock.Mock()
201 result_mock = mock.Mock()
202 result_mock.ui_value = 'ui_value'
202 result_mock.ui_value = 'ui_value'
203 result_mock.ui_active = True
203 result_mock.ui_active = True
204 result_mock.app_settings_value = 'setting_value'
204 result_mock.app_settings_value = 'setting_value'
205 return result_mock
205 return result_mock
206
206
207 def _assert_get_settings_calls(
207 def _assert_get_settings_calls(
208 self, settings_mock, ui_settings, general_settings):
208 self, settings_mock, ui_settings, general_settings):
209 assert (
209 assert (
210 settings_mock.get_ui_by_section_and_key.call_count ==
210 settings_mock.get_ui_by_section_and_key.call_count ==
211 len(ui_settings))
211 len(ui_settings))
212 assert (
212 assert (
213 settings_mock.get_setting_by_name.call_count ==
213 settings_mock.get_setting_by_name.call_count ==
214 len(general_settings))
214 len(general_settings))
215
215
216 for section, key in ui_settings:
216 for section, key in ui_settings:
217 expected_call = mock.call(section, key)
217 expected_call = mock.call(section, key)
218 assert (
218 assert (
219 expected_call in
219 expected_call in
220 settings_mock.get_ui_by_section_and_key.call_args_list)
220 settings_mock.get_ui_by_section_and_key.call_args_list)
221
221
222 for name in general_settings:
222 for name in general_settings:
223 expected_call = mock.call(name)
223 expected_call = mock.call(name)
224 assert (
224 assert (
225 expected_call in
225 expected_call in
226 settings_mock.get_setting_by_name.call_args_list)
226 settings_mock.get_setting_by_name.call_args_list)
227
227
228 def _assert_collect_all_settings_result(
228 def _assert_collect_all_settings_result(
229 self, ui_settings, general_settings, result):
229 self, ui_settings, general_settings, result):
230 expected_result = {}
230 expected_result = {}
231 for section, key in ui_settings:
231 for section, key in ui_settings:
232 key = '{}_{}'.format(section, key.replace('.', '_'))
232 key = '{}_{}'.format(section, key.replace('.', '_'))
233 value = True if section in ('extensions', 'hooks') else 'ui_value'
233 value = True if section in ('extensions', 'hooks') else 'ui_value'
234 expected_result[key] = value
234 expected_result[key] = value
235
235
236 for name in general_settings:
236 for name in general_settings:
237 key = 'rhodecode_' + name
237 key = 'rhodecode_' + name
238 expected_result[key] = 'setting_value'
238 expected_result[key] = 'setting_value'
239
239
240 assert expected_result == result
240 assert expected_result == result
241
241
242
242
243 class TestCreateOrUpdateRepoHookSettings(object):
243 class TestCreateOrUpdateRepoHookSettings(object):
244 def test_create_when_no_repo_object_found(self, repo_stub):
244 def test_create_when_no_repo_object_found(self, repo_stub):
245 model = VcsSettingsModel(repo=repo_stub.repo_name)
245 model = VcsSettingsModel(repo=repo_stub.repo_name)
246
246
247 self._create_settings(model, HOOKS_FORM_DATA)
247 self._create_settings(model, HOOKS_FORM_DATA)
248
248
249 cleanup = []
249 cleanup = []
250 try:
250 try:
251 for section, key in model.HOOKS_SETTINGS:
251 for section, key in model.HOOKS_SETTINGS:
252 ui = model.repo_settings.get_ui_by_section_and_key(
252 ui = model.repo_settings.get_ui_by_section_and_key(
253 section, key)
253 section, key)
254 assert ui.ui_active is True
254 assert ui.ui_active is True
255 cleanup.append(ui)
255 cleanup.append(ui)
256 finally:
256 finally:
257 for ui in cleanup:
257 for ui in cleanup:
258 Session().delete(ui)
258 Session().delete(ui)
259 Session().commit()
259 Session().commit()
260
260
261 def test_create_raises_exception_when_data_incomplete(self, repo_stub):
261 def test_create_raises_exception_when_data_incomplete(self, repo_stub):
262 model = VcsSettingsModel(repo=repo_stub.repo_name)
262 model = VcsSettingsModel(repo=repo_stub.repo_name)
263
263
264 deleted_key = 'hooks_changegroup_repo_size'
264 deleted_key = 'hooks_changegroup_repo_size'
265 data = HOOKS_FORM_DATA.copy()
265 data = HOOKS_FORM_DATA.copy()
266 data.pop(deleted_key)
266 data.pop(deleted_key)
267
267
268 with pytest.raises(ValueError) as exc_info:
268 with pytest.raises(ValueError) as exc_info:
269 model.create_or_update_repo_hook_settings(data)
269 model.create_or_update_repo_hook_settings(data)
270 assert (
270 assert (
271 exc_info.value.message ==
271 exc_info.value.message ==
272 'The given data does not contain {} key'.format(deleted_key))
272 'The given data does not contain {} key'.format(deleted_key))
273
273
274 def test_update_when_repo_object_found(self, repo_stub, settings_util):
274 def test_update_when_repo_object_found(self, repo_stub, settings_util):
275 model = VcsSettingsModel(repo=repo_stub.repo_name)
275 model = VcsSettingsModel(repo=repo_stub.repo_name)
276 for section, key in model.HOOKS_SETTINGS:
276 for section, key in model.HOOKS_SETTINGS:
277 settings_util.create_repo_rhodecode_ui(
277 settings_util.create_repo_rhodecode_ui(
278 repo_stub, section, None, key=key, active=False)
278 repo_stub, section, None, key=key, active=False)
279 model.create_or_update_repo_hook_settings(HOOKS_FORM_DATA)
279 model.create_or_update_repo_hook_settings(HOOKS_FORM_DATA)
280 for section, key in model.HOOKS_SETTINGS:
280 for section, key in model.HOOKS_SETTINGS:
281 ui = model.repo_settings.get_ui_by_section_and_key(section, key)
281 ui = model.repo_settings.get_ui_by_section_and_key(section, key)
282 assert ui.ui_active is True
282 assert ui.ui_active is True
283
283
284 def _create_settings(self, model, data):
284 def _create_settings(self, model, data):
285 global_patch = mock.patch.object(model, 'global_settings')
285 global_patch = mock.patch.object(model, 'global_settings')
286 global_setting = mock.Mock()
286 global_setting = mock.Mock()
287 global_setting.ui_value = 'Test value'
287 global_setting.ui_value = 'Test value'
288 with global_patch as global_mock:
288 with global_patch as global_mock:
289 global_mock.get_ui_by_section_and_key.return_value = global_setting
289 global_mock.get_ui_by_section_and_key.return_value = global_setting
290 model.create_or_update_repo_hook_settings(HOOKS_FORM_DATA)
290 model.create_or_update_repo_hook_settings(HOOKS_FORM_DATA)
291
291
292
292
293 class TestUpdateGlobalHookSettings(object):
293 class TestUpdateGlobalHookSettings(object):
294 def test_update_raises_exception_when_data_incomplete(self):
294 def test_update_raises_exception_when_data_incomplete(self):
295 model = VcsSettingsModel()
295 model = VcsSettingsModel()
296
296
297 deleted_key = 'hooks_changegroup_repo_size'
297 deleted_key = 'hooks_changegroup_repo_size'
298 data = HOOKS_FORM_DATA.copy()
298 data = HOOKS_FORM_DATA.copy()
299 data.pop(deleted_key)
299 data.pop(deleted_key)
300
300
301 with pytest.raises(ValueError) as exc_info:
301 with pytest.raises(ValueError) as exc_info:
302 model.update_global_hook_settings(data)
302 model.update_global_hook_settings(data)
303 assert (
303 assert (
304 exc_info.value.message ==
304 exc_info.value.message ==
305 'The given data does not contain {} key'.format(deleted_key))
305 'The given data does not contain {} key'.format(deleted_key))
306
306
307 def test_update_global_hook_settings(self, settings_util):
307 def test_update_global_hook_settings(self, settings_util):
308 model = VcsSettingsModel()
308 model = VcsSettingsModel()
309 setting_mock = mock.MagicMock()
309 setting_mock = mock.MagicMock()
310 setting_mock.ui_active = False
310 setting_mock.ui_active = False
311 get_settings_patcher = mock.patch.object(
311 get_settings_patcher = mock.patch.object(
312 model.global_settings, 'get_ui_by_section_and_key',
312 model.global_settings, 'get_ui_by_section_and_key',
313 return_value=setting_mock)
313 return_value=setting_mock)
314 session_patcher = mock.patch('rhodecode.model.settings.Session')
314 session_patcher = mock.patch('rhodecode.model.settings.Session')
315 with get_settings_patcher as get_settings_mock, session_patcher:
315 with get_settings_patcher as get_settings_mock, session_patcher:
316 model.update_global_hook_settings(HOOKS_FORM_DATA)
316 model.update_global_hook_settings(HOOKS_FORM_DATA)
317 assert setting_mock.ui_active is True
317 assert setting_mock.ui_active is True
318 assert get_settings_mock.call_count == 3
318 assert get_settings_mock.call_count == 3
319
319
320
320
321 class TestCreateOrUpdateRepoGeneralSettings(object):
321 class TestCreateOrUpdateRepoGeneralSettings(object):
322 def test_calls_create_or_update_general_settings(self, repo_stub):
322 def test_calls_create_or_update_general_settings(self, repo_stub):
323 model = VcsSettingsModel(repo=repo_stub.repo_name)
323 model = VcsSettingsModel(repo=repo_stub.repo_name)
324 create_patch = mock.patch.object(
324 create_patch = mock.patch.object(
325 model, '_create_or_update_general_settings')
325 model, '_create_or_update_general_settings')
326 with create_patch as create_mock:
326 with create_patch as create_mock:
327 model.create_or_update_repo_pr_settings(GENERAL_FORM_DATA)
327 model.create_or_update_repo_pr_settings(GENERAL_FORM_DATA)
328 create_mock.assert_called_once_with(
328 create_mock.assert_called_once_with(
329 model.repo_settings, GENERAL_FORM_DATA)
329 model.repo_settings, GENERAL_FORM_DATA)
330
330
331 def test_raises_exception_when_repository_is_not_specified(self):
331 def test_raises_exception_when_repository_is_not_specified(self):
332 model = VcsSettingsModel()
332 model = VcsSettingsModel()
333 with pytest.raises(Exception) as exc_info:
333 with pytest.raises(Exception) as exc_info:
334 model.create_or_update_repo_pr_settings(GENERAL_FORM_DATA)
334 model.create_or_update_repo_pr_settings(GENERAL_FORM_DATA)
335 assert exc_info.value.message == 'Repository is not specified'
335 assert exc_info.value.message == 'Repository is not specified'
336
336
337
337
338 class TestCreateOrUpdatGlobalGeneralSettings(object):
338 class TestCreateOrUpdatGlobalGeneralSettings(object):
339 def test_calls_create_or_update_general_settings(self):
339 def test_calls_create_or_update_general_settings(self):
340 model = VcsSettingsModel()
340 model = VcsSettingsModel()
341 create_patch = mock.patch.object(
341 create_patch = mock.patch.object(
342 model, '_create_or_update_general_settings')
342 model, '_create_or_update_general_settings')
343 with create_patch as create_mock:
343 with create_patch as create_mock:
344 model.create_or_update_global_pr_settings(GENERAL_FORM_DATA)
344 model.create_or_update_global_pr_settings(GENERAL_FORM_DATA)
345 create_mock.assert_called_once_with(
345 create_mock.assert_called_once_with(
346 model.global_settings, GENERAL_FORM_DATA)
346 model.global_settings, GENERAL_FORM_DATA)
347
347
348
348
349 class TestCreateOrUpdateGeneralSettings(object):
349 class TestCreateOrUpdateGeneralSettings(object):
350 def test_create_when_no_repo_settings_found(self, repo_stub):
350 def test_create_when_no_repo_settings_found(self, repo_stub):
351 model = VcsSettingsModel(repo=repo_stub.repo_name)
351 model = VcsSettingsModel(repo=repo_stub.repo_name)
352 model._create_or_update_general_settings(
352 model._create_or_update_general_settings(
353 model.repo_settings, GENERAL_FORM_DATA)
353 model.repo_settings, GENERAL_FORM_DATA)
354
354
355 cleanup = []
355 cleanup = []
356 try:
356 try:
357 for name in model.GENERAL_SETTINGS:
357 for name in model.GENERAL_SETTINGS:
358 setting = model.repo_settings.get_setting_by_name(name)
358 setting = model.repo_settings.get_setting_by_name(name)
359 assert setting.app_settings_value is True
359 assert setting.app_settings_value is True
360 cleanup.append(setting)
360 cleanup.append(setting)
361 finally:
361 finally:
362 for setting in cleanup:
362 for setting in cleanup:
363 Session().delete(setting)
363 Session().delete(setting)
364 Session().commit()
364 Session().commit()
365
365
366 def test_create_raises_exception_when_data_incomplete(self, repo_stub):
366 def test_create_raises_exception_when_data_incomplete(self, repo_stub):
367 model = VcsSettingsModel(repo=repo_stub.repo_name)
367 model = VcsSettingsModel(repo=repo_stub.repo_name)
368
368
369 deleted_key = 'rhodecode_pr_merge_enabled'
369 deleted_key = 'rhodecode_pr_merge_enabled'
370 data = GENERAL_FORM_DATA.copy()
370 data = GENERAL_FORM_DATA.copy()
371 data.pop(deleted_key)
371 data.pop(deleted_key)
372
372
373 with pytest.raises(ValueError) as exc_info:
373 with pytest.raises(ValueError) as exc_info:
374 model._create_or_update_general_settings(model.repo_settings, data)
374 model._create_or_update_general_settings(model.repo_settings, data)
375 assert (
375 assert (
376 exc_info.value.message ==
376 exc_info.value.message ==
377 'The given data does not contain {} key'.format(deleted_key))
377 'The given data does not contain {} key'.format(deleted_key))
378
378
379 def test_update_when_repo_setting_found(self, repo_stub, settings_util):
379 def test_update_when_repo_setting_found(self, repo_stub, settings_util):
380 model = VcsSettingsModel(repo=repo_stub.repo_name)
380 model = VcsSettingsModel(repo=repo_stub.repo_name)
381 for name in model.GENERAL_SETTINGS:
381 for name in model.GENERAL_SETTINGS:
382 settings_util.create_repo_rhodecode_setting(
382 settings_util.create_repo_rhodecode_setting(
383 repo_stub, name, False, 'bool')
383 repo_stub, name, False, 'bool')
384
384
385 model._create_or_update_general_settings(
385 model._create_or_update_general_settings(
386 model.repo_settings, GENERAL_FORM_DATA)
386 model.repo_settings, GENERAL_FORM_DATA)
387
387
388 for name in model.GENERAL_SETTINGS:
388 for name in model.GENERAL_SETTINGS:
389 setting = model.repo_settings.get_setting_by_name(name)
389 setting = model.repo_settings.get_setting_by_name(name)
390 assert setting.app_settings_value is True
390 assert setting.app_settings_value is True
391
391
392
392
393 class TestCreateRepoSvnSettings(object):
393 class TestCreateRepoSvnSettings(object):
394 def test_calls_create_svn_settings(self, repo_stub):
394 def test_calls_create_svn_settings(self, repo_stub):
395 model = VcsSettingsModel(repo=repo_stub.repo_name)
395 model = VcsSettingsModel(repo=repo_stub.repo_name)
396 with mock.patch.object(model, '_create_svn_settings') as create_mock:
396 with mock.patch.object(model, '_create_svn_settings') as create_mock:
397 model.create_repo_svn_settings(SVN_FORM_DATA)
397 model.create_repo_svn_settings(SVN_FORM_DATA)
398 create_mock.assert_called_once_with(model.repo_settings, SVN_FORM_DATA)
398 create_mock.assert_called_once_with(model.repo_settings, SVN_FORM_DATA)
399
399
400 def test_raises_exception_when_repository_is_not_specified(self):
400 def test_raises_exception_when_repository_is_not_specified(self):
401 model = VcsSettingsModel()
401 model = VcsSettingsModel()
402 with pytest.raises(Exception) as exc_info:
402 with pytest.raises(Exception) as exc_info:
403 model.create_repo_svn_settings(SVN_FORM_DATA)
403 model.create_repo_svn_settings(SVN_FORM_DATA)
404 assert exc_info.value.message == 'Repository is not specified'
404 assert exc_info.value.message == 'Repository is not specified'
405
405
406
406
407 class TestCreateSvnSettings(object):
407 class TestCreateSvnSettings(object):
408 def test_create(self, repo_stub):
408 def test_create(self, repo_stub):
409 model = VcsSettingsModel(repo=repo_stub.repo_name)
409 model = VcsSettingsModel(repo=repo_stub.repo_name)
410 model._create_svn_settings(model.repo_settings, SVN_FORM_DATA)
410 model._create_svn_settings(model.repo_settings, SVN_FORM_DATA)
411 Session().commit()
411 Session().commit()
412
412
413 branch_ui = model.repo_settings.get_ui_by_section(
413 branch_ui = model.repo_settings.get_ui_by_section(
414 model.SVN_BRANCH_SECTION)
414 model.SVN_BRANCH_SECTION)
415 tag_ui = model.repo_settings.get_ui_by_section(
415 tag_ui = model.repo_settings.get_ui_by_section(
416 model.SVN_TAG_SECTION)
416 model.SVN_TAG_SECTION)
417
417
418 try:
418 try:
419 assert len(branch_ui) == 1
419 assert len(branch_ui) == 1
420 assert len(tag_ui) == 1
420 assert len(tag_ui) == 1
421 finally:
421 finally:
422 Session().delete(branch_ui[0])
422 Session().delete(branch_ui[0])
423 Session().delete(tag_ui[0])
423 Session().delete(tag_ui[0])
424 Session().commit()
424 Session().commit()
425
425
426 def test_create_tag(self, repo_stub):
426 def test_create_tag(self, repo_stub):
427 model = VcsSettingsModel(repo=repo_stub.repo_name)
427 model = VcsSettingsModel(repo=repo_stub.repo_name)
428 data = SVN_FORM_DATA.copy()
428 data = SVN_FORM_DATA.copy()
429 data.pop('new_svn_branch')
429 data.pop('new_svn_branch')
430 model._create_svn_settings(model.repo_settings, data)
430 model._create_svn_settings(model.repo_settings, data)
431 Session().commit()
431 Session().commit()
432
432
433 branch_ui = model.repo_settings.get_ui_by_section(
433 branch_ui = model.repo_settings.get_ui_by_section(
434 model.SVN_BRANCH_SECTION)
434 model.SVN_BRANCH_SECTION)
435 tag_ui = model.repo_settings.get_ui_by_section(
435 tag_ui = model.repo_settings.get_ui_by_section(
436 model.SVN_TAG_SECTION)
436 model.SVN_TAG_SECTION)
437
437
438 try:
438 try:
439 assert len(branch_ui) == 0
439 assert len(branch_ui) == 0
440 assert len(tag_ui) == 1
440 assert len(tag_ui) == 1
441 finally:
441 finally:
442 Session().delete(tag_ui[0])
442 Session().delete(tag_ui[0])
443 Session().commit()
443 Session().commit()
444
444
445 def test_create_nothing_when_no_svn_settings_specified(self, repo_stub):
445 def test_create_nothing_when_no_svn_settings_specified(self, repo_stub):
446 model = VcsSettingsModel(repo=repo_stub.repo_name)
446 model = VcsSettingsModel(repo=repo_stub.repo_name)
447 model._create_svn_settings(model.repo_settings, {})
447 model._create_svn_settings(model.repo_settings, {})
448 Session().commit()
448 Session().commit()
449
449
450 branch_ui = model.repo_settings.get_ui_by_section(
450 branch_ui = model.repo_settings.get_ui_by_section(
451 model.SVN_BRANCH_SECTION)
451 model.SVN_BRANCH_SECTION)
452 tag_ui = model.repo_settings.get_ui_by_section(
452 tag_ui = model.repo_settings.get_ui_by_section(
453 model.SVN_TAG_SECTION)
453 model.SVN_TAG_SECTION)
454
454
455 assert len(branch_ui) == 0
455 assert len(branch_ui) == 0
456 assert len(tag_ui) == 0
456 assert len(tag_ui) == 0
457
457
458 def test_create_nothing_when_empty_settings_specified(self, repo_stub):
458 def test_create_nothing_when_empty_settings_specified(self, repo_stub):
459 model = VcsSettingsModel(repo=repo_stub.repo_name)
459 model = VcsSettingsModel(repo=repo_stub.repo_name)
460 data = {
460 data = {
461 'new_svn_branch': '',
461 'new_svn_branch': '',
462 'new_svn_tag': ''
462 'new_svn_tag': ''
463 }
463 }
464 model._create_svn_settings(model.repo_settings, data)
464 model._create_svn_settings(model.repo_settings, data)
465 Session().commit()
465 Session().commit()
466
466
467 branch_ui = model.repo_settings.get_ui_by_section(
467 branch_ui = model.repo_settings.get_ui_by_section(
468 model.SVN_BRANCH_SECTION)
468 model.SVN_BRANCH_SECTION)
469 tag_ui = model.repo_settings.get_ui_by_section(
469 tag_ui = model.repo_settings.get_ui_by_section(
470 model.SVN_TAG_SECTION)
470 model.SVN_TAG_SECTION)
471
471
472 assert len(branch_ui) == 0
472 assert len(branch_ui) == 0
473 assert len(tag_ui) == 0
473 assert len(tag_ui) == 0
474
474
475
475
476 class TestCreateOrUpdateUi(object):
476 class TestCreateOrUpdateUi(object):
477 def test_create(self, repo_stub):
477 def test_create(self, repo_stub):
478 model = VcsSettingsModel(repo=repo_stub.repo_name)
478 model = VcsSettingsModel(repo=repo_stub.repo_name)
479 model._create_or_update_ui(
479 model._create_or_update_ui(
480 model.repo_settings, 'test-section', 'test-key', active=False,
480 model.repo_settings, 'test-section', 'test-key', active=False,
481 value='False')
481 value='False')
482 Session().commit()
482 Session().commit()
483
483
484 created_ui = model.repo_settings.get_ui_by_section_and_key(
484 created_ui = model.repo_settings.get_ui_by_section_and_key(
485 'test-section', 'test-key')
485 'test-section', 'test-key')
486
486
487 try:
487 try:
488 assert created_ui.ui_active is False
488 assert created_ui.ui_active is False
489 assert str2bool(created_ui.ui_value) is False
489 assert str2bool(created_ui.ui_value) is False
490 finally:
490 finally:
491 Session().delete(created_ui)
491 Session().delete(created_ui)
492 Session().commit()
492 Session().commit()
493
493
494 def test_update(self, repo_stub, settings_util):
494 def test_update(self, repo_stub, settings_util):
495 model = VcsSettingsModel(repo=repo_stub.repo_name)
495 model = VcsSettingsModel(repo=repo_stub.repo_name)
496
496
497 largefiles, phases = model.HG_SETTINGS
497 largefiles, phases = model.HG_SETTINGS
498 section = 'test-section'
498 section = 'test-section'
499 key = 'test-key'
499 key = 'test-key'
500 settings_util.create_repo_rhodecode_ui(
500 settings_util.create_repo_rhodecode_ui(
501 repo_stub, section, 'True', key=key, active=True)
501 repo_stub, section, 'True', key=key, active=True)
502
502
503 model._create_or_update_ui(
503 model._create_or_update_ui(
504 model.repo_settings, section, key, active=False, value='False')
504 model.repo_settings, section, key, active=False, value='False')
505 Session().commit()
505 Session().commit()
506
506
507 created_ui = model.repo_settings.get_ui_by_section_and_key(
507 created_ui = model.repo_settings.get_ui_by_section_and_key(
508 section, key)
508 section, key)
509 assert created_ui.ui_active is False
509 assert created_ui.ui_active is False
510 assert str2bool(created_ui.ui_value) is False
510 assert str2bool(created_ui.ui_value) is False
511
511
512
512
513 class TestCreateOrUpdateRepoHgSettings(object):
513 class TestCreateOrUpdateRepoHgSettings(object):
514 FORM_DATA = {
514 FORM_DATA = {
515 'extensions_largefiles': False,
515 'extensions_largefiles': False,
516 'phases_publish': False
516 'phases_publish': False
517 }
517 }
518
518
519 def test_creates_repo_hg_settings_when_data_is_correct(self, repo_stub):
519 def test_creates_repo_hg_settings_when_data_is_correct(self, repo_stub):
520 model = VcsSettingsModel(repo=repo_stub.repo_name)
520 model = VcsSettingsModel(repo=repo_stub.repo_name)
521 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
521 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
522 model.create_or_update_repo_hg_settings(self.FORM_DATA)
522 model.create_or_update_repo_hg_settings(self.FORM_DATA)
523 expected_calls = [
523 expected_calls = [
524 mock.call(model.repo_settings, 'extensions', 'largefiles',
524 mock.call(model.repo_settings, 'extensions', 'largefiles',
525 active=False, value=''),
525 active=False, value=''),
526 mock.call(model.repo_settings, 'phases', 'publish', value='False'),
526 mock.call(model.repo_settings, 'phases', 'publish', value='False'),
527 ]
527 ]
528 assert expected_calls == create_mock.call_args_list
528 assert expected_calls == create_mock.call_args_list
529
529
530 @pytest.mark.parametrize('field_to_remove', FORM_DATA.keys())
530 @pytest.mark.parametrize('field_to_remove', FORM_DATA.keys())
531 def test_key_is_not_found(self, repo_stub, field_to_remove):
531 def test_key_is_not_found(self, repo_stub, field_to_remove):
532 model = VcsSettingsModel(repo=repo_stub.repo_name)
532 model = VcsSettingsModel(repo=repo_stub.repo_name)
533 data = self.FORM_DATA.copy()
533 data = self.FORM_DATA.copy()
534 data.pop(field_to_remove)
534 data.pop(field_to_remove)
535 with pytest.raises(ValueError) as exc_info:
535 with pytest.raises(ValueError) as exc_info:
536 model.create_or_update_repo_hg_settings(data)
536 model.create_or_update_repo_hg_settings(data)
537 expected_message = 'The given data does not contain {} key'.format(
537 expected_message = 'The given data does not contain {} key'.format(
538 field_to_remove)
538 field_to_remove)
539 assert exc_info.value.message == expected_message
539 assert exc_info.value.message == expected_message
540
540
541 def test_create_raises_exception_when_repository_not_specified(self):
541 def test_create_raises_exception_when_repository_not_specified(self):
542 model = VcsSettingsModel()
542 model = VcsSettingsModel()
543 with pytest.raises(Exception) as exc_info:
543 with pytest.raises(Exception) as exc_info:
544 model.create_or_update_repo_hg_settings(self.FORM_DATA)
544 model.create_or_update_repo_hg_settings(self.FORM_DATA)
545 assert exc_info.value.message == 'Repository is not specified'
545 assert exc_info.value.message == 'Repository is not specified'
546
546
547
547
548 class TestUpdateGlobalSslSetting(object):
548 class TestUpdateGlobalSslSetting(object):
549 def test_updates_global_hg_settings(self):
549 def test_updates_global_hg_settings(self):
550 model = VcsSettingsModel()
550 model = VcsSettingsModel()
551 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
551 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
552 model.update_global_ssl_setting('False')
552 model.update_global_ssl_setting('False')
553 create_mock.assert_called_once_with(
553 create_mock.assert_called_once_with(
554 model.global_settings, 'web', 'push_ssl', value='False')
554 model.global_settings, 'web', 'push_ssl', value='False')
555
555
556
556
557 class TestUpdateGlobalPathSetting(object):
557 class TestUpdateGlobalPathSetting(object):
558 def test_updates_global_path_settings(self):
558 def test_updates_global_path_settings(self):
559 model = VcsSettingsModel()
559 model = VcsSettingsModel()
560 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
560 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
561 model.update_global_path_setting('False')
561 model.update_global_path_setting('False')
562 create_mock.assert_called_once_with(
562 create_mock.assert_called_once_with(
563 model.global_settings, 'paths', '/', value='False')
563 model.global_settings, 'paths', '/', value='False')
564
564
565
565
566 class TestCreateOrUpdateGlobalHgSettings(object):
566 class TestCreateOrUpdateGlobalHgSettings(object):
567 FORM_DATA = {
567 FORM_DATA = {
568 'extensions_largefiles': False,
568 'extensions_largefiles': False,
569 'largefiles_usercache': '/example/largefiles-store',
569 'phases_publish': False,
570 'phases_publish': False,
570 'extensions_hgsubversion': False
571 'extensions_hgsubversion': False
571 }
572 }
572
573
573 def test_creates_repo_hg_settings_when_data_is_correct(self):
574 def test_creates_repo_hg_settings_when_data_is_correct(self):
574 model = VcsSettingsModel()
575 model = VcsSettingsModel()
575 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
576 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
576 model.create_or_update_global_hg_settings(self.FORM_DATA)
577 model.create_or_update_global_hg_settings(self.FORM_DATA)
577 expected_calls = [
578 expected_calls = [
578 mock.call(model.global_settings, 'extensions', 'largefiles',
579 mock.call(model.global_settings, 'extensions', 'largefiles',
579 active=False, value=''),
580 active=False, value=''),
581 mock.call(model.global_settings, 'largefiles', 'usercache',
582 value='/example/largefiles-store'),
580 mock.call(model.global_settings, 'phases', 'publish',
583 mock.call(model.global_settings, 'phases', 'publish',
581 value='False'),
584 value='False'),
582 mock.call(model.global_settings, 'extensions', 'hgsubversion',
585 mock.call(model.global_settings, 'extensions', 'hgsubversion',
583 active=False)
586 active=False)
584 ]
587 ]
585 assert expected_calls == create_mock.call_args_list
588 assert expected_calls == create_mock.call_args_list
586
589
587 @pytest.mark.parametrize('field_to_remove', FORM_DATA.keys())
590 @pytest.mark.parametrize('field_to_remove', FORM_DATA.keys())
588 def test_key_is_not_found(self, repo_stub, field_to_remove):
591 def test_key_is_not_found(self, repo_stub, field_to_remove):
589 model = VcsSettingsModel(repo=repo_stub.repo_name)
592 model = VcsSettingsModel(repo=repo_stub.repo_name)
590 data = self.FORM_DATA.copy()
593 data = self.FORM_DATA.copy()
591 data.pop(field_to_remove)
594 data.pop(field_to_remove)
592 with pytest.raises(Exception) as exc_info:
595 with pytest.raises(Exception) as exc_info:
593 model.create_or_update_global_hg_settings(data)
596 model.create_or_update_global_hg_settings(data)
594 expected_message = 'The given data does not contain {} key'.format(
597 expected_message = 'The given data does not contain {} key'.format(
595 field_to_remove)
598 field_to_remove)
596 assert exc_info.value.message == expected_message
599 assert exc_info.value.message == expected_message
597
600
598
601
599 class TestDeleteRepoSvnPattern(object):
602 class TestDeleteRepoSvnPattern(object):
600 def test_success_when_repo_is_set(self, backend_svn):
603 def test_success_when_repo_is_set(self, backend_svn):
601 repo_name = backend_svn.repo_name
604 repo_name = backend_svn.repo_name
602 model = VcsSettingsModel(repo=repo_name)
605 model = VcsSettingsModel(repo=repo_name)
603 delete_ui_patch = mock.patch.object(model.repo_settings, 'delete_ui')
606 delete_ui_patch = mock.patch.object(model.repo_settings, 'delete_ui')
604 with delete_ui_patch as delete_ui_mock:
607 with delete_ui_patch as delete_ui_mock:
605 model.delete_repo_svn_pattern(123)
608 model.delete_repo_svn_pattern(123)
606 delete_ui_mock.assert_called_once_with(123)
609 delete_ui_mock.assert_called_once_with(123)
607
610
608 def test_raises_exception_when_repository_is_not_specified(self):
611 def test_raises_exception_when_repository_is_not_specified(self):
609 model = VcsSettingsModel()
612 model = VcsSettingsModel()
610 with pytest.raises(Exception) as exc_info:
613 with pytest.raises(Exception) as exc_info:
611 model.delete_repo_svn_pattern(123)
614 model.delete_repo_svn_pattern(123)
612 assert exc_info.value.message == 'Repository is not specified'
615 assert exc_info.value.message == 'Repository is not specified'
613
616
614
617
615 class TestDeleteGlobalSvnPattern(object):
618 class TestDeleteGlobalSvnPattern(object):
616 def test_delete_global_svn_pattern_calls_delete_ui(self):
619 def test_delete_global_svn_pattern_calls_delete_ui(self):
617 model = VcsSettingsModel()
620 model = VcsSettingsModel()
618 delete_ui_patch = mock.patch.object(model.global_settings, 'delete_ui')
621 delete_ui_patch = mock.patch.object(model.global_settings, 'delete_ui')
619 with delete_ui_patch as delete_ui_mock:
622 with delete_ui_patch as delete_ui_mock:
620 model.delete_global_svn_pattern(123)
623 model.delete_global_svn_pattern(123)
621 delete_ui_mock.assert_called_once_with(123)
624 delete_ui_mock.assert_called_once_with(123)
622
625
623
626
624 class TestFilterUiSettings(object):
627 class TestFilterUiSettings(object):
625 def test_settings_are_filtered(self):
628 def test_settings_are_filtered(self):
626 model = VcsSettingsModel()
629 model = VcsSettingsModel()
627 repo_settings = [
630 repo_settings = [
628 UiSetting('extensions', 'largefiles', '', True),
631 UiSetting('extensions', 'largefiles', '', True),
629 UiSetting('phases', 'publish', 'True', True),
632 UiSetting('phases', 'publish', 'True', True),
630 UiSetting('hooks', 'changegroup.repo_size', 'hook', True),
633 UiSetting('hooks', 'changegroup.repo_size', 'hook', True),
631 UiSetting('hooks', 'changegroup.push_logger', 'hook', True),
634 UiSetting('hooks', 'changegroup.push_logger', 'hook', True),
632 UiSetting('hooks', 'outgoing.pull_logger', 'hook', True),
635 UiSetting('hooks', 'outgoing.pull_logger', 'hook', True),
633 UiSetting(
636 UiSetting(
634 'vcs_svn_branch', '84223c972204fa545ca1b22dac7bef5b68d7442d',
637 'vcs_svn_branch', '84223c972204fa545ca1b22dac7bef5b68d7442d',
635 'test_branch', True),
638 'test_branch', True),
636 UiSetting(
639 UiSetting(
637 'vcs_svn_tag', '84229c972204fa545ca1b22dac7bef5b68d7442d',
640 'vcs_svn_tag', '84229c972204fa545ca1b22dac7bef5b68d7442d',
638 'test_tag', True),
641 'test_tag', True),
639 ]
642 ]
640 non_repo_settings = [
643 non_repo_settings = [
644 UiSetting('largefiles', 'usercache', '/example/largefiles-store', True),
641 UiSetting('test', 'outgoing.pull_logger', 'hook', True),
645 UiSetting('test', 'outgoing.pull_logger', 'hook', True),
642 UiSetting('hooks', 'test2', 'hook', True),
646 UiSetting('hooks', 'test2', 'hook', True),
643 UiSetting(
647 UiSetting(
644 'vcs_svn_repo', '84229c972204fa545ca1b22dac7bef5b68d7442d',
648 'vcs_svn_repo', '84229c972204fa545ca1b22dac7bef5b68d7442d',
645 'test_tag', True),
649 'test_tag', True),
646 ]
650 ]
647 settings = repo_settings + non_repo_settings
651 settings = repo_settings + non_repo_settings
648 filtered_settings = model._filter_ui_settings(settings)
652 filtered_settings = model._filter_ui_settings(settings)
649 assert sorted(filtered_settings) == sorted(repo_settings)
653 assert sorted(filtered_settings) == sorted(repo_settings)
650
654
651
655
652 class TestFilterGeneralSettings(object):
656 class TestFilterGeneralSettings(object):
653 def test_settings_are_filtered(self):
657 def test_settings_are_filtered(self):
654 model = VcsSettingsModel()
658 model = VcsSettingsModel()
655 settings = {
659 settings = {
656 'rhodecode_abcde': 'value1',
660 'rhodecode_abcde': 'value1',
657 'rhodecode_vwxyz': 'value2',
661 'rhodecode_vwxyz': 'value2',
658 }
662 }
659 general_settings = {
663 general_settings = {
660 'rhodecode_{}'.format(key): 'value'
664 'rhodecode_{}'.format(key): 'value'
661 for key in VcsSettingsModel.GENERAL_SETTINGS
665 for key in VcsSettingsModel.GENERAL_SETTINGS
662 }
666 }
663 settings.update(general_settings)
667 settings.update(general_settings)
664
668
665 filtered_settings = model._filter_general_settings(general_settings)
669 filtered_settings = model._filter_general_settings(general_settings)
666 assert sorted(filtered_settings) == sorted(general_settings)
670 assert sorted(filtered_settings) == sorted(general_settings)
667
671
668
672
669 class TestGetRepoUiSettings(object):
673 class TestGetRepoUiSettings(object):
670 def test_global_uis_are_returned_when_no_repo_uis_found(
674 def test_global_uis_are_returned_when_no_repo_uis_found(
671 self, repo_stub):
675 self, repo_stub):
672 model = VcsSettingsModel(repo=repo_stub.repo_name)
676 model = VcsSettingsModel(repo=repo_stub.repo_name)
673 result = model.get_repo_ui_settings()
677 result = model.get_repo_ui_settings()
674 svn_sections = (
678 svn_sections = (
675 VcsSettingsModel.SVN_TAG_SECTION,
679 VcsSettingsModel.SVN_TAG_SECTION,
676 VcsSettingsModel.SVN_BRANCH_SECTION)
680 VcsSettingsModel.SVN_BRANCH_SECTION)
677 expected_result = [
681 expected_result = [
678 s for s in model.global_settings.get_ui()
682 s for s in model.global_settings.get_ui()
679 if s.section not in svn_sections]
683 if s.section not in svn_sections]
680 assert sorted(result) == sorted(expected_result)
684 assert sorted(result) == sorted(expected_result)
681
685
682 def test_repo_uis_are_overriding_global_uis(
686 def test_repo_uis_are_overriding_global_uis(
683 self, repo_stub, settings_util):
687 self, repo_stub, settings_util):
684 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
688 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
685 settings_util.create_repo_rhodecode_ui(
689 settings_util.create_repo_rhodecode_ui(
686 repo_stub, section, 'repo', key=key, active=False)
690 repo_stub, section, 'repo', key=key, active=False)
687 model = VcsSettingsModel(repo=repo_stub.repo_name)
691 model = VcsSettingsModel(repo=repo_stub.repo_name)
688 result = model.get_repo_ui_settings()
692 result = model.get_repo_ui_settings()
689 for setting in result:
693 for setting in result:
690 locator = (setting.section, setting.key)
694 locator = (setting.section, setting.key)
691 if locator in VcsSettingsModel.HOOKS_SETTINGS:
695 if locator in VcsSettingsModel.HOOKS_SETTINGS:
692 assert setting.value == 'repo'
696 assert setting.value == 'repo'
693
697
694 assert setting.active is False
698 assert setting.active is False
695
699
696 def test_global_svn_patterns_are_not_in_list(
700 def test_global_svn_patterns_are_not_in_list(
697 self, repo_stub, settings_util):
701 self, repo_stub, settings_util):
698 svn_sections = (
702 svn_sections = (
699 VcsSettingsModel.SVN_TAG_SECTION,
703 VcsSettingsModel.SVN_TAG_SECTION,
700 VcsSettingsModel.SVN_BRANCH_SECTION)
704 VcsSettingsModel.SVN_BRANCH_SECTION)
701 for section in svn_sections:
705 for section in svn_sections:
702 settings_util.create_rhodecode_ui(
706 settings_util.create_rhodecode_ui(
703 section, 'repo', key='deadbeef' + section, active=False)
707 section, 'repo', key='deadbeef' + section, active=False)
704 model = VcsSettingsModel(repo=repo_stub.repo_name)
708 model = VcsSettingsModel(repo=repo_stub.repo_name)
705 result = model.get_repo_ui_settings()
709 result = model.get_repo_ui_settings()
706 for setting in result:
710 for setting in result:
707 assert setting.section not in svn_sections
711 assert setting.section not in svn_sections
708
712
709 def test_repo_uis_filtered_by_section_are_returned(
713 def test_repo_uis_filtered_by_section_are_returned(
710 self, repo_stub, settings_util):
714 self, repo_stub, settings_util):
711 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
715 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
712 settings_util.create_repo_rhodecode_ui(
716 settings_util.create_repo_rhodecode_ui(
713 repo_stub, section, 'repo', key=key, active=False)
717 repo_stub, section, 'repo', key=key, active=False)
714 model = VcsSettingsModel(repo=repo_stub.repo_name)
718 model = VcsSettingsModel(repo=repo_stub.repo_name)
715 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
719 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
716 result = model.get_repo_ui_settings(section=section)
720 result = model.get_repo_ui_settings(section=section)
717 for setting in result:
721 for setting in result:
718 assert setting.section == section
722 assert setting.section == section
719
723
720 def test_repo_uis_filtered_by_key_are_returned(
724 def test_repo_uis_filtered_by_key_are_returned(
721 self, repo_stub, settings_util):
725 self, repo_stub, settings_util):
722 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
726 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
723 settings_util.create_repo_rhodecode_ui(
727 settings_util.create_repo_rhodecode_ui(
724 repo_stub, section, 'repo', key=key, active=False)
728 repo_stub, section, 'repo', key=key, active=False)
725 model = VcsSettingsModel(repo=repo_stub.repo_name)
729 model = VcsSettingsModel(repo=repo_stub.repo_name)
726 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
730 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
727 result = model.get_repo_ui_settings(key=key)
731 result = model.get_repo_ui_settings(key=key)
728 for setting in result:
732 for setting in result:
729 assert setting.key == key
733 assert setting.key == key
730
734
731 def test_raises_exception_when_repository_is_not_specified(self):
735 def test_raises_exception_when_repository_is_not_specified(self):
732 model = VcsSettingsModel()
736 model = VcsSettingsModel()
733 with pytest.raises(Exception) as exc_info:
737 with pytest.raises(Exception) as exc_info:
734 model.get_repo_ui_settings()
738 model.get_repo_ui_settings()
735 assert exc_info.value.message == 'Repository is not specified'
739 assert exc_info.value.message == 'Repository is not specified'
736
740
737
741
738 class TestGetRepoGeneralSettings(object):
742 class TestGetRepoGeneralSettings(object):
739 def test_global_settings_are_returned_when_no_repo_settings_found(
743 def test_global_settings_are_returned_when_no_repo_settings_found(
740 self, repo_stub):
744 self, repo_stub):
741 model = VcsSettingsModel(repo=repo_stub.repo_name)
745 model = VcsSettingsModel(repo=repo_stub.repo_name)
742 result = model.get_repo_general_settings()
746 result = model.get_repo_general_settings()
743 expected_result = model.global_settings.get_all_settings()
747 expected_result = model.global_settings.get_all_settings()
744 assert sorted(result) == sorted(expected_result)
748 assert sorted(result) == sorted(expected_result)
745
749
746 def test_repo_uis_are_overriding_global_uis(
750 def test_repo_uis_are_overriding_global_uis(
747 self, repo_stub, settings_util):
751 self, repo_stub, settings_util):
748 for key in VcsSettingsModel.GENERAL_SETTINGS:
752 for key in VcsSettingsModel.GENERAL_SETTINGS:
749 settings_util.create_repo_rhodecode_setting(
753 settings_util.create_repo_rhodecode_setting(
750 repo_stub, key, 'abcde', type_='unicode')
754 repo_stub, key, 'abcde', type_='unicode')
751 model = VcsSettingsModel(repo=repo_stub.repo_name)
755 model = VcsSettingsModel(repo=repo_stub.repo_name)
752 result = model.get_repo_ui_settings()
756 result = model.get_repo_ui_settings()
753 for key in result:
757 for key in result:
754 if key in VcsSettingsModel.GENERAL_SETTINGS:
758 if key in VcsSettingsModel.GENERAL_SETTINGS:
755 assert result[key] == 'abcde'
759 assert result[key] == 'abcde'
756
760
757 def test_raises_exception_when_repository_is_not_specified(self):
761 def test_raises_exception_when_repository_is_not_specified(self):
758 model = VcsSettingsModel()
762 model = VcsSettingsModel()
759 with pytest.raises(Exception) as exc_info:
763 with pytest.raises(Exception) as exc_info:
760 model.get_repo_general_settings()
764 model.get_repo_general_settings()
761 assert exc_info.value.message == 'Repository is not specified'
765 assert exc_info.value.message == 'Repository is not specified'
762
766
763
767
764 class TestGetGlobalGeneralSettings(object):
768 class TestGetGlobalGeneralSettings(object):
765 def test_global_settings_are_returned(self, repo_stub):
769 def test_global_settings_are_returned(self, repo_stub):
766 model = VcsSettingsModel()
770 model = VcsSettingsModel()
767 result = model.get_global_general_settings()
771 result = model.get_global_general_settings()
768 expected_result = model.global_settings.get_all_settings()
772 expected_result = model.global_settings.get_all_settings()
769 assert sorted(result) == sorted(expected_result)
773 assert sorted(result) == sorted(expected_result)
770
774
771 def test_repo_uis_are_not_overriding_global_uis(
775 def test_repo_uis_are_not_overriding_global_uis(
772 self, repo_stub, settings_util):
776 self, repo_stub, settings_util):
773 for key in VcsSettingsModel.GENERAL_SETTINGS:
777 for key in VcsSettingsModel.GENERAL_SETTINGS:
774 settings_util.create_repo_rhodecode_setting(
778 settings_util.create_repo_rhodecode_setting(
775 repo_stub, key, 'abcde', type_='unicode')
779 repo_stub, key, 'abcde', type_='unicode')
776 model = VcsSettingsModel(repo=repo_stub.repo_name)
780 model = VcsSettingsModel(repo=repo_stub.repo_name)
777 result = model.get_global_general_settings()
781 result = model.get_global_general_settings()
778 expected_result = model.global_settings.get_all_settings()
782 expected_result = model.global_settings.get_all_settings()
779 assert sorted(result) == sorted(expected_result)
783 assert sorted(result) == sorted(expected_result)
780
784
781
785
782 class TestGetGlobalUiSettings(object):
786 class TestGetGlobalUiSettings(object):
783 def test_global_uis_are_returned(self, repo_stub):
787 def test_global_uis_are_returned(self, repo_stub):
784 model = VcsSettingsModel()
788 model = VcsSettingsModel()
785 result = model.get_global_ui_settings()
789 result = model.get_global_ui_settings()
786 expected_result = model.global_settings.get_ui()
790 expected_result = model.global_settings.get_ui()
787 assert sorted(result) == sorted(expected_result)
791 assert sorted(result) == sorted(expected_result)
788
792
789 def test_repo_uis_are_not_overriding_global_uis(
793 def test_repo_uis_are_not_overriding_global_uis(
790 self, repo_stub, settings_util):
794 self, repo_stub, settings_util):
791 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
795 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
792 settings_util.create_repo_rhodecode_ui(
796 settings_util.create_repo_rhodecode_ui(
793 repo_stub, section, 'repo', key=key, active=False)
797 repo_stub, section, 'repo', key=key, active=False)
794 model = VcsSettingsModel(repo=repo_stub.repo_name)
798 model = VcsSettingsModel(repo=repo_stub.repo_name)
795 result = model.get_global_ui_settings()
799 result = model.get_global_ui_settings()
796 expected_result = model.global_settings.get_ui()
800 expected_result = model.global_settings.get_ui()
797 assert sorted(result) == sorted(expected_result)
801 assert sorted(result) == sorted(expected_result)
798
802
799 def test_ui_settings_filtered_by_section(
803 def test_ui_settings_filtered_by_section(
800 self, repo_stub, settings_util):
804 self, repo_stub, settings_util):
801 model = VcsSettingsModel(repo=repo_stub.repo_name)
805 model = VcsSettingsModel(repo=repo_stub.repo_name)
802 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
806 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
803 result = model.get_global_ui_settings(section=section)
807 result = model.get_global_ui_settings(section=section)
804 expected_result = model.global_settings.get_ui(section=section)
808 expected_result = model.global_settings.get_ui(section=section)
805 assert sorted(result) == sorted(expected_result)
809 assert sorted(result) == sorted(expected_result)
806
810
807 def test_ui_settings_filtered_by_key(
811 def test_ui_settings_filtered_by_key(
808 self, repo_stub, settings_util):
812 self, repo_stub, settings_util):
809 model = VcsSettingsModel(repo=repo_stub.repo_name)
813 model = VcsSettingsModel(repo=repo_stub.repo_name)
810 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
814 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
811 result = model.get_global_ui_settings(key=key)
815 result = model.get_global_ui_settings(key=key)
812 expected_result = model.global_settings.get_ui(key=key)
816 expected_result = model.global_settings.get_ui(key=key)
813 assert sorted(result) == sorted(expected_result)
817 assert sorted(result) == sorted(expected_result)
814
818
815
819
816 class TestGetGeneralSettings(object):
820 class TestGetGeneralSettings(object):
817 def test_global_settings_are_returned_when_inherited_is_true(
821 def test_global_settings_are_returned_when_inherited_is_true(
818 self, repo_stub, settings_util):
822 self, repo_stub, settings_util):
819 model = VcsSettingsModel(repo=repo_stub.repo_name)
823 model = VcsSettingsModel(repo=repo_stub.repo_name)
820 model.inherit_global_settings = True
824 model.inherit_global_settings = True
821 for key in VcsSettingsModel.GENERAL_SETTINGS:
825 for key in VcsSettingsModel.GENERAL_SETTINGS:
822 settings_util.create_repo_rhodecode_setting(
826 settings_util.create_repo_rhodecode_setting(
823 repo_stub, key, 'abcde', type_='unicode')
827 repo_stub, key, 'abcde', type_='unicode')
824 result = model.get_general_settings()
828 result = model.get_general_settings()
825 expected_result = model.get_global_general_settings()
829 expected_result = model.get_global_general_settings()
826 assert sorted(result) == sorted(expected_result)
830 assert sorted(result) == sorted(expected_result)
827
831
828 def test_repo_settings_are_returned_when_inherited_is_false(
832 def test_repo_settings_are_returned_when_inherited_is_false(
829 self, repo_stub, settings_util):
833 self, repo_stub, settings_util):
830 model = VcsSettingsModel(repo=repo_stub.repo_name)
834 model = VcsSettingsModel(repo=repo_stub.repo_name)
831 model.inherit_global_settings = False
835 model.inherit_global_settings = False
832 for key in VcsSettingsModel.GENERAL_SETTINGS:
836 for key in VcsSettingsModel.GENERAL_SETTINGS:
833 settings_util.create_repo_rhodecode_setting(
837 settings_util.create_repo_rhodecode_setting(
834 repo_stub, key, 'abcde', type_='unicode')
838 repo_stub, key, 'abcde', type_='unicode')
835 result = model.get_general_settings()
839 result = model.get_general_settings()
836 expected_result = model.get_repo_general_settings()
840 expected_result = model.get_repo_general_settings()
837 assert sorted(result) == sorted(expected_result)
841 assert sorted(result) == sorted(expected_result)
838
842
839 def test_global_settings_are_returned_when_no_repository_specified(self):
843 def test_global_settings_are_returned_when_no_repository_specified(self):
840 model = VcsSettingsModel()
844 model = VcsSettingsModel()
841 result = model.get_general_settings()
845 result = model.get_general_settings()
842 expected_result = model.get_global_general_settings()
846 expected_result = model.get_global_general_settings()
843 assert sorted(result) == sorted(expected_result)
847 assert sorted(result) == sorted(expected_result)
844
848
845
849
846 class TestGetUiSettings(object):
850 class TestGetUiSettings(object):
847 def test_global_settings_are_returned_when_inherited_is_true(
851 def test_global_settings_are_returned_when_inherited_is_true(
848 self, repo_stub, settings_util):
852 self, repo_stub, settings_util):
849 model = VcsSettingsModel(repo=repo_stub.repo_name)
853 model = VcsSettingsModel(repo=repo_stub.repo_name)
850 model.inherit_global_settings = True
854 model.inherit_global_settings = True
851 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
855 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
852 settings_util.create_repo_rhodecode_ui(
856 settings_util.create_repo_rhodecode_ui(
853 repo_stub, section, 'repo', key=key, active=True)
857 repo_stub, section, 'repo', key=key, active=True)
854 result = model.get_ui_settings()
858 result = model.get_ui_settings()
855 expected_result = model.get_global_ui_settings()
859 expected_result = model.get_global_ui_settings()
856 assert sorted(result) == sorted(expected_result)
860 assert sorted(result) == sorted(expected_result)
857
861
858 def test_repo_settings_are_returned_when_inherited_is_false(
862 def test_repo_settings_are_returned_when_inherited_is_false(
859 self, repo_stub, settings_util):
863 self, repo_stub, settings_util):
860 model = VcsSettingsModel(repo=repo_stub.repo_name)
864 model = VcsSettingsModel(repo=repo_stub.repo_name)
861 model.inherit_global_settings = False
865 model.inherit_global_settings = False
862 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
866 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
863 settings_util.create_repo_rhodecode_ui(
867 settings_util.create_repo_rhodecode_ui(
864 repo_stub, section, 'repo', key=key, active=True)
868 repo_stub, section, 'repo', key=key, active=True)
865 result = model.get_ui_settings()
869 result = model.get_ui_settings()
866 expected_result = model.get_repo_ui_settings()
870 expected_result = model.get_repo_ui_settings()
867 assert sorted(result) == sorted(expected_result)
871 assert sorted(result) == sorted(expected_result)
868
872
869 def test_repo_settings_filtered_by_section_and_key(self, repo_stub):
873 def test_repo_settings_filtered_by_section_and_key(self, repo_stub):
870 model = VcsSettingsModel(repo=repo_stub.repo_name)
874 model = VcsSettingsModel(repo=repo_stub.repo_name)
871 model.inherit_global_settings = False
875 model.inherit_global_settings = False
872 args = ('section', 'key')
876 args = ('section', 'key')
873 with mock.patch.object(model, 'get_repo_ui_settings') as settings_mock:
877 with mock.patch.object(model, 'get_repo_ui_settings') as settings_mock:
874 model.get_ui_settings(*args)
878 model.get_ui_settings(*args)
875 settings_mock.assert_called_once_with(*args)
879 settings_mock.assert_called_once_with(*args)
876
880
877 def test_global_settings_filtered_by_section_and_key(self):
881 def test_global_settings_filtered_by_section_and_key(self):
878 model = VcsSettingsModel()
882 model = VcsSettingsModel()
879 args = ('section', 'key')
883 args = ('section', 'key')
880 with mock.patch.object(model, 'get_global_ui_settings') as (
884 with mock.patch.object(model, 'get_global_ui_settings') as (
881 settings_mock):
885 settings_mock):
882 model.get_ui_settings(*args)
886 model.get_ui_settings(*args)
883 settings_mock.assert_called_once_with(*args)
887 settings_mock.assert_called_once_with(*args)
884
888
885 def test_global_settings_are_returned_when_no_repository_specified(self):
889 def test_global_settings_are_returned_when_no_repository_specified(self):
886 model = VcsSettingsModel()
890 model = VcsSettingsModel()
887 result = model.get_ui_settings()
891 result = model.get_ui_settings()
888 expected_result = model.get_global_ui_settings()
892 expected_result = model.get_global_ui_settings()
889 assert sorted(result) == sorted(expected_result)
893 assert sorted(result) == sorted(expected_result)
890
894
891
895
892 class TestGetSvnPatterns(object):
896 class TestGetSvnPatterns(object):
893 def test_repo_settings_filtered_by_section_and_key(self, repo_stub):
897 def test_repo_settings_filtered_by_section_and_key(self, repo_stub):
894 model = VcsSettingsModel(repo=repo_stub.repo_name)
898 model = VcsSettingsModel(repo=repo_stub.repo_name)
895 args = ('section', )
899 args = ('section', )
896 with mock.patch.object(model, 'get_repo_ui_settings') as settings_mock:
900 with mock.patch.object(model, 'get_repo_ui_settings') as settings_mock:
897 model.get_svn_patterns(*args)
901 model.get_svn_patterns(*args)
898 settings_mock.assert_called_once_with(*args)
902 settings_mock.assert_called_once_with(*args)
899
903
900 def test_global_settings_filtered_by_section_and_key(self):
904 def test_global_settings_filtered_by_section_and_key(self):
901 model = VcsSettingsModel()
905 model = VcsSettingsModel()
902 args = ('section', )
906 args = ('section', )
903 with mock.patch.object(model, 'get_global_ui_settings') as (
907 with mock.patch.object(model, 'get_global_ui_settings') as (
904 settings_mock):
908 settings_mock):
905 model.get_svn_patterns(*args)
909 model.get_svn_patterns(*args)
906 settings_mock.assert_called_once_with(*args)
910 settings_mock.assert_called_once_with(*args)
907
911
908
912
909 class TestGetReposLocation(object):
913 class TestGetReposLocation(object):
910 def test_returns_repos_location(self, repo_stub):
914 def test_returns_repos_location(self, repo_stub):
911 model = VcsSettingsModel()
915 model = VcsSettingsModel()
912
916
913 result_mock = mock.Mock()
917 result_mock = mock.Mock()
914 result_mock.ui_value = '/tmp'
918 result_mock.ui_value = '/tmp'
915
919
916 with mock.patch.object(model, 'global_settings') as settings_mock:
920 with mock.patch.object(model, 'global_settings') as settings_mock:
917 settings_mock.get_ui_by_key.return_value = result_mock
921 settings_mock.get_ui_by_key.return_value = result_mock
918 result = model.get_repos_location()
922 result = model.get_repos_location()
919
923
920 settings_mock.get_ui_by_key.assert_called_once_with('/')
924 settings_mock.get_ui_by_key.assert_called_once_with('/')
921 assert result == '/tmp'
925 assert result == '/tmp'
922
926
923
927
924 class TestCreateOrUpdateRepoSettings(object):
928 class TestCreateOrUpdateRepoSettings(object):
925 FORM_DATA = {
929 FORM_DATA = {
926 'inherit_global_settings': False,
930 'inherit_global_settings': False,
927 'hooks_changegroup_repo_size': False,
931 'hooks_changegroup_repo_size': False,
928 'hooks_changegroup_push_logger': False,
932 'hooks_changegroup_push_logger': False,
929 'hooks_outgoing_pull_logger': False,
933 'hooks_outgoing_pull_logger': False,
930 'extensions_largefiles': False,
934 'extensions_largefiles': False,
935 'largefiles_usercache': '/example/largefiles-store',
931 'phases_publish': 'false',
936 'phases_publish': 'false',
932 'rhodecode_pr_merge_enabled': False,
937 'rhodecode_pr_merge_enabled': False,
933 'rhodecode_use_outdated_comments': False,
938 'rhodecode_use_outdated_comments': False,
934 'new_svn_branch': '',
939 'new_svn_branch': '',
935 'new_svn_tag': ''
940 'new_svn_tag': ''
936 }
941 }
937
942
938 def test_get_raises_exception_when_repository_not_specified(self):
943 def test_get_raises_exception_when_repository_not_specified(self):
939 model = VcsSettingsModel()
944 model = VcsSettingsModel()
940 with pytest.raises(Exception) as exc_info:
945 with pytest.raises(Exception) as exc_info:
941 model.create_or_update_repo_settings(data=self.FORM_DATA)
946 model.create_or_update_repo_settings(data=self.FORM_DATA)
942 assert exc_info.value.message == 'Repository is not specified'
947 assert exc_info.value.message == 'Repository is not specified'
943
948
944 def test_only_svn_settings_are_updated_when_type_is_svn(self, backend_svn):
949 def test_only_svn_settings_are_updated_when_type_is_svn(self, backend_svn):
945 repo = backend_svn.create_repo()
950 repo = backend_svn.create_repo()
946 model = VcsSettingsModel(repo=repo)
951 model = VcsSettingsModel(repo=repo)
947 with self._patch_model(model) as mocks:
952 with self._patch_model(model) as mocks:
948 model.create_or_update_repo_settings(
953 model.create_or_update_repo_settings(
949 data=self.FORM_DATA, inherit_global_settings=False)
954 data=self.FORM_DATA, inherit_global_settings=False)
950 mocks['create_repo_svn_settings'].assert_called_once_with(
955 mocks['create_repo_svn_settings'].assert_called_once_with(
951 self.FORM_DATA)
956 self.FORM_DATA)
952 non_called_methods = (
957 non_called_methods = (
953 'create_or_update_repo_hook_settings',
958 'create_or_update_repo_hook_settings',
954 'create_or_update_repo_pr_settings',
959 'create_or_update_repo_pr_settings',
955 'create_or_update_repo_hg_settings')
960 'create_or_update_repo_hg_settings')
956 for method in non_called_methods:
961 for method in non_called_methods:
957 assert mocks[method].call_count == 0
962 assert mocks[method].call_count == 0
958
963
959 def test_non_svn_settings_are_updated_when_type_is_hg(self, backend_hg):
964 def test_non_svn_settings_are_updated_when_type_is_hg(self, backend_hg):
960 repo = backend_hg.create_repo()
965 repo = backend_hg.create_repo()
961 model = VcsSettingsModel(repo=repo)
966 model = VcsSettingsModel(repo=repo)
962 with self._patch_model(model) as mocks:
967 with self._patch_model(model) as mocks:
963 model.create_or_update_repo_settings(
968 model.create_or_update_repo_settings(
964 data=self.FORM_DATA, inherit_global_settings=False)
969 data=self.FORM_DATA, inherit_global_settings=False)
965
970
966 assert mocks['create_repo_svn_settings'].call_count == 0
971 assert mocks['create_repo_svn_settings'].call_count == 0
967 called_methods = (
972 called_methods = (
968 'create_or_update_repo_hook_settings',
973 'create_or_update_repo_hook_settings',
969 'create_or_update_repo_pr_settings',
974 'create_or_update_repo_pr_settings',
970 'create_or_update_repo_hg_settings')
975 'create_or_update_repo_hg_settings')
971 for method in called_methods:
976 for method in called_methods:
972 mocks[method].assert_called_once_with(self.FORM_DATA)
977 mocks[method].assert_called_once_with(self.FORM_DATA)
973
978
974 def test_non_svn_and_hg_settings_are_updated_when_type_is_git(
979 def test_non_svn_and_hg_settings_are_updated_when_type_is_git(
975 self, backend_git):
980 self, backend_git):
976 repo = backend_git.create_repo()
981 repo = backend_git.create_repo()
977 model = VcsSettingsModel(repo=repo)
982 model = VcsSettingsModel(repo=repo)
978 with self._patch_model(model) as mocks:
983 with self._patch_model(model) as mocks:
979 model.create_or_update_repo_settings(
984 model.create_or_update_repo_settings(
980 data=self.FORM_DATA, inherit_global_settings=False)
985 data=self.FORM_DATA, inherit_global_settings=False)
981
986
982 assert mocks['create_repo_svn_settings'].call_count == 0
987 assert mocks['create_repo_svn_settings'].call_count == 0
983 called_methods = (
988 called_methods = (
984 'create_or_update_repo_hook_settings',
989 'create_or_update_repo_hook_settings',
985 'create_or_update_repo_pr_settings')
990 'create_or_update_repo_pr_settings')
986 non_called_methods = (
991 non_called_methods = (
987 'create_repo_svn_settings',
992 'create_repo_svn_settings',
988 'create_or_update_repo_hg_settings'
993 'create_or_update_repo_hg_settings'
989 )
994 )
990 for method in called_methods:
995 for method in called_methods:
991 mocks[method].assert_called_once_with(self.FORM_DATA)
996 mocks[method].assert_called_once_with(self.FORM_DATA)
992 for method in non_called_methods:
997 for method in non_called_methods:
993 assert mocks[method].call_count == 0
998 assert mocks[method].call_count == 0
994
999
995 def test_no_methods_are_called_when_settings_are_inherited(
1000 def test_no_methods_are_called_when_settings_are_inherited(
996 self, backend):
1001 self, backend):
997 repo = backend.create_repo()
1002 repo = backend.create_repo()
998 model = VcsSettingsModel(repo=repo)
1003 model = VcsSettingsModel(repo=repo)
999 with self._patch_model(model) as mocks:
1004 with self._patch_model(model) as mocks:
1000 model.create_or_update_repo_settings(
1005 model.create_or_update_repo_settings(
1001 data=self.FORM_DATA, inherit_global_settings=True)
1006 data=self.FORM_DATA, inherit_global_settings=True)
1002 for method_name in mocks:
1007 for method_name in mocks:
1003 assert mocks[method_name].call_count == 0
1008 assert mocks[method_name].call_count == 0
1004
1009
1005 def test_cache_is_marked_for_invalidation(self, repo_stub):
1010 def test_cache_is_marked_for_invalidation(self, repo_stub):
1006 model = VcsSettingsModel(repo=repo_stub)
1011 model = VcsSettingsModel(repo=repo_stub)
1007 invalidation_patcher = mock.patch(
1012 invalidation_patcher = mock.patch(
1008 'rhodecode.controllers.admin.repos.ScmModel.mark_for_invalidation')
1013 'rhodecode.controllers.admin.repos.ScmModel.mark_for_invalidation')
1009 with invalidation_patcher as invalidation_mock:
1014 with invalidation_patcher as invalidation_mock:
1010 model.create_or_update_repo_settings(
1015 model.create_or_update_repo_settings(
1011 data=self.FORM_DATA, inherit_global_settings=True)
1016 data=self.FORM_DATA, inherit_global_settings=True)
1012 invalidation_mock.assert_called_once_with(
1017 invalidation_mock.assert_called_once_with(
1013 repo_stub.repo_name, delete=True)
1018 repo_stub.repo_name, delete=True)
1014
1019
1015 def test_inherit_flag_is_saved(self, repo_stub):
1020 def test_inherit_flag_is_saved(self, repo_stub):
1016 model = VcsSettingsModel(repo=repo_stub)
1021 model = VcsSettingsModel(repo=repo_stub)
1017 model.inherit_global_settings = True
1022 model.inherit_global_settings = True
1018 with self._patch_model(model):
1023 with self._patch_model(model):
1019 model.create_or_update_repo_settings(
1024 model.create_or_update_repo_settings(
1020 data=self.FORM_DATA, inherit_global_settings=False)
1025 data=self.FORM_DATA, inherit_global_settings=False)
1021 assert model.inherit_global_settings is False
1026 assert model.inherit_global_settings is False
1022
1027
1023 def _patch_model(self, model):
1028 def _patch_model(self, model):
1024 return mock.patch.multiple(
1029 return mock.patch.multiple(
1025 model,
1030 model,
1026 create_repo_svn_settings=mock.DEFAULT,
1031 create_repo_svn_settings=mock.DEFAULT,
1027 create_or_update_repo_hook_settings=mock.DEFAULT,
1032 create_or_update_repo_hook_settings=mock.DEFAULT,
1028 create_or_update_repo_pr_settings=mock.DEFAULT,
1033 create_or_update_repo_pr_settings=mock.DEFAULT,
1029 create_or_update_repo_hg_settings=mock.DEFAULT)
1034 create_or_update_repo_hg_settings=mock.DEFAULT)
General Comments 0
You need to be logged in to leave comments. Login now