##// END OF EJS Templates
auth-plugins: remove the in-object cache that cauused invalidation failures....
super-admin -
r4885:2768c2d4 default
parent child Browse files
Show More
@@ -1,107 +1,121 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2020 RhodeCode GmbH
3 # Copyright (C) 2012-2020 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 time
21 import logging
22 import logging
22
23
23 from pyramid.exceptions import ConfigurationError
24 from pyramid.exceptions import ConfigurationError
24 from zope.interface import implementer
25 from zope.interface import implementer
25
26
26 from rhodecode.authentication.interface import IAuthnPluginRegistry
27 from rhodecode.authentication.interface import IAuthnPluginRegistry
28 from rhodecode.model.settings import SettingsModel
27 from rhodecode.lib.utils2 import safe_str
29 from rhodecode.lib.utils2 import safe_str
28 from rhodecode.model.settings import SettingsModel
30 from rhodecode.lib.statsd_client import StatsdClient
31 from rhodecode.lib import rc_cache
29
32
30 log = logging.getLogger(__name__)
33 log = logging.getLogger(__name__)
31
34
32
35
33 @implementer(IAuthnPluginRegistry)
36 @implementer(IAuthnPluginRegistry)
34 class AuthenticationPluginRegistry(object):
37 class AuthenticationPluginRegistry(object):
35
38
36 # INI settings key to set a fallback authentication plugin.
39 # INI settings key to set a fallback authentication plugin.
37 fallback_plugin_key = 'rhodecode.auth_plugin_fallback'
40 fallback_plugin_key = 'rhodecode.auth_plugin_fallback'
38
41
39 def __init__(self, settings):
42 def __init__(self, settings):
40 self._plugins = {}
43 self._plugins = {}
41 self._plugins_for_auth = None
42 self._fallback_plugin = settings.get(self.fallback_plugin_key, None)
44 self._fallback_plugin = settings.get(self.fallback_plugin_key, None)
43
45
44 def add_authn_plugin(self, config, plugin):
46 def add_authn_plugin(self, config, plugin):
45 plugin_id = plugin.get_id()
47 plugin_id = plugin.get_id()
46 if plugin_id in self._plugins.keys():
48 if plugin_id in self._plugins.keys():
47 raise ConfigurationError(
49 raise ConfigurationError(
48 'Cannot register authentication plugin twice: "%s"', plugin_id)
50 'Cannot register authentication plugin twice: "%s"', plugin_id)
49 else:
51 else:
50 log.debug('Register authentication plugin: "%s"', plugin_id)
52 log.debug('Register authentication plugin: "%s"', plugin_id)
51 self._plugins[plugin_id] = plugin
53 self._plugins[plugin_id] = plugin
52
54
53 def get_plugins(self):
55 def get_plugins(self):
54 def sort_key(plugin):
56 def sort_key(plugin):
55 return str.lower(safe_str(plugin.get_display_name()))
57 return str.lower(safe_str(plugin.get_display_name()))
56
58
57 return sorted(self._plugins.values(), key=sort_key)
59 return sorted(self._plugins.values(), key=sort_key)
58
60
59 def get_plugin(self, plugin_id):
61 def get_plugin(self, plugin_id):
60 return self._plugins.get(plugin_id, None)
62 return self._plugins.get(plugin_id, None)
61
63
62 def get_plugin_by_uid(self, plugin_uid):
64 def get_plugin_by_uid(self, plugin_uid):
63 for plugin in self._plugins.values():
65 for plugin in self._plugins.values():
64 if plugin.uid == plugin_uid:
66 if plugin.uid == plugin_uid:
65 return plugin
67 return plugin
66
68
67 def invalidate_plugins_for_auth(self):
69 def get_plugins_for_authentication(self, cache=True):
68 log.debug('Invalidating cached plugins for authentication')
69 self._plugins_for_auth = None
70
71 def get_plugins_for_authentication(self):
72 """
70 """
73 Returns a list of plugins which should be consulted when authenticating
71 Returns a list of plugins which should be consulted when authenticating
74 a user. It only returns plugins which are enabled and active.
72 a user. It only returns plugins which are enabled and active.
75 Additionally it includes the fallback plugin from the INI file, if
73 Additionally it includes the fallback plugin from the INI file, if
76 `rhodecode.auth_plugin_fallback` is set to a plugin ID.
74 `rhodecode.auth_plugin_fallback` is set to a plugin ID.
77 """
75 """
78 if self._plugins_for_auth is not None:
76
79 return self._plugins_for_auth
77 cache_namespace_uid = 'cache_auth_plugins'
78 region = rc_cache.get_or_create_region('cache_general', cache_namespace_uid)
80
79
81 plugins = []
80 @region.conditional_cache_on_arguments(condition=cache)
81 def _get_auth_plugins(name, key, fallback_plugin):
82 plugins = []
82
83
83 # Add all enabled and active plugins to the list. We iterate over the
84 # Add all enabled and active plugins to the list. We iterate over the
84 # auth_plugins setting from DB because it also represents the ordering.
85 # auth_plugins setting from DB because it also represents the ordering.
85 enabled_plugins = SettingsModel().get_auth_plugins()
86 enabled_plugins = SettingsModel().get_auth_plugins()
86 raw_settings = SettingsModel().get_all_settings(cache=True)
87 raw_settings = SettingsModel().get_all_settings(cache=False)
87 for plugin_id in enabled_plugins:
88 for plugin_id in enabled_plugins:
88 plugin = self.get_plugin(plugin_id)
89 plugin = self.get_plugin(plugin_id)
89 if plugin is not None and plugin.is_active(
90 if plugin is not None and plugin.is_active(
90 plugin_cached_settings=raw_settings):
91 plugin_cached_settings=raw_settings):
92
93 # inject settings into plugin, we can re-use the DB fetched settings here
94 plugin._settings = plugin._propagate_settings(raw_settings)
95 plugins.append(plugin)
91
96
92 # inject settings into plugin, we can re-use the DB fetched settings here
97 # Add the fallback plugin from ini file.
93 plugin._settings = plugin._propagate_settings(raw_settings)
98 if fallback_plugin:
94 plugins.append(plugin)
99 log.warn(
100 'Using fallback authentication plugin from INI file: "%s"',
101 fallback_plugin)
102 plugin = self.get_plugin(fallback_plugin)
103 if plugin is not None and plugin not in plugins:
104 plugin._settings = plugin._propagate_settings(raw_settings)
105 plugins.append(plugin)
106 return plugins
95
107
96 # Add the fallback plugin from ini file.
108 start = time.time()
97 if self._fallback_plugin:
109 plugins = _get_auth_plugins('rhodecode_auth_plugins', 'v1', self._fallback_plugin)
98 log.warn(
110
99 'Using fallback authentication plugin from INI file: "%s"',
111 compute_time = time.time() - start
100 self._fallback_plugin)
112 log.debug('cached method:%s took %.4fs', _get_auth_plugins.func_name, compute_time)
101 plugin = self.get_plugin(self._fallback_plugin)
102 if plugin is not None and plugin not in plugins:
103 plugin._settings = plugin._propagate_settings(raw_settings)
104 plugins.append(plugin)
105
113
106 self._plugins_for_auth = plugins
114 statsd = StatsdClient.statsd
107 return self._plugins_for_auth
115 if statsd:
116 elapsed_time_ms = round(1000.0 * compute_time) # use ms only
117 statsd.timing("rhodecode_auth_plugins_timing.histogram", elapsed_time_ms,
118 use_decimals=False)
119
120 return plugins
121
@@ -1,924 +1,918 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 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 re
22 import re
23 import hashlib
23 import hashlib
24 import logging
24 import logging
25 import time
25 import time
26 from collections import namedtuple
26 from collections import namedtuple
27 from functools import wraps
27 from functools import wraps
28 import bleach
28 import bleach
29 from pyramid.threadlocal import get_current_request, get_current_registry
29 from pyramid.threadlocal import get_current_request, get_current_registry
30
30
31 from rhodecode.lib import rc_cache
31 from rhodecode.lib import rc_cache
32 from rhodecode.lib.utils2 import (
32 from rhodecode.lib.utils2 import (
33 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
33 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
34 from rhodecode.lib.vcs.backends import base
34 from rhodecode.lib.vcs.backends import base
35 from rhodecode.lib.statsd_client import StatsdClient
35 from rhodecode.lib.statsd_client import StatsdClient
36 from rhodecode.model import BaseModel
36 from rhodecode.model import BaseModel
37 from rhodecode.model.db import (
37 from rhodecode.model.db import (
38 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting)
38 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting)
39 from rhodecode.model.meta import Session
39 from rhodecode.model.meta import Session
40
40
41
41
42 log = logging.getLogger(__name__)
42 log = logging.getLogger(__name__)
43
43
44
44
45 UiSetting = namedtuple(
45 UiSetting = namedtuple(
46 'UiSetting', ['section', 'key', 'value', 'active'])
46 'UiSetting', ['section', 'key', 'value', 'active'])
47
47
48 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
48 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
49
49
50
50
51 class SettingNotFound(Exception):
51 class SettingNotFound(Exception):
52 def __init__(self, setting_id):
52 def __init__(self, setting_id):
53 msg = 'Setting `{}` is not found'.format(setting_id)
53 msg = 'Setting `{}` is not found'.format(setting_id)
54 super(SettingNotFound, self).__init__(msg)
54 super(SettingNotFound, self).__init__(msg)
55
55
56
56
57 class SettingsModel(BaseModel):
57 class SettingsModel(BaseModel):
58 BUILTIN_HOOKS = (
58 BUILTIN_HOOKS = (
59 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
59 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
60 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
60 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
61 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL,
61 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL,
62 RhodeCodeUi.HOOK_PUSH_KEY,)
62 RhodeCodeUi.HOOK_PUSH_KEY,)
63 HOOKS_SECTION = 'hooks'
63 HOOKS_SECTION = 'hooks'
64
64
65 def __init__(self, sa=None, repo=None):
65 def __init__(self, sa=None, repo=None):
66 self.repo = repo
66 self.repo = repo
67 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
67 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
68 self.SettingsDbModel = (
68 self.SettingsDbModel = (
69 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
69 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
70 super(SettingsModel, self).__init__(sa)
70 super(SettingsModel, self).__init__(sa)
71
71
72 def get_ui_by_key(self, key):
72 def get_ui_by_key(self, key):
73 q = self.UiDbModel.query()
73 q = self.UiDbModel.query()
74 q = q.filter(self.UiDbModel.ui_key == key)
74 q = q.filter(self.UiDbModel.ui_key == key)
75 q = self._filter_by_repo(RepoRhodeCodeUi, q)
75 q = self._filter_by_repo(RepoRhodeCodeUi, q)
76 return q.scalar()
76 return q.scalar()
77
77
78 def get_ui_by_section(self, section):
78 def get_ui_by_section(self, section):
79 q = self.UiDbModel.query()
79 q = self.UiDbModel.query()
80 q = q.filter(self.UiDbModel.ui_section == section)
80 q = q.filter(self.UiDbModel.ui_section == section)
81 q = self._filter_by_repo(RepoRhodeCodeUi, q)
81 q = self._filter_by_repo(RepoRhodeCodeUi, q)
82 return q.all()
82 return q.all()
83
83
84 def get_ui_by_section_and_key(self, section, key):
84 def get_ui_by_section_and_key(self, section, key):
85 q = self.UiDbModel.query()
85 q = self.UiDbModel.query()
86 q = q.filter(self.UiDbModel.ui_section == section)
86 q = q.filter(self.UiDbModel.ui_section == section)
87 q = q.filter(self.UiDbModel.ui_key == key)
87 q = q.filter(self.UiDbModel.ui_key == key)
88 q = self._filter_by_repo(RepoRhodeCodeUi, q)
88 q = self._filter_by_repo(RepoRhodeCodeUi, q)
89 return q.scalar()
89 return q.scalar()
90
90
91 def get_ui(self, section=None, key=None):
91 def get_ui(self, section=None, key=None):
92 q = self.UiDbModel.query()
92 q = self.UiDbModel.query()
93 q = self._filter_by_repo(RepoRhodeCodeUi, q)
93 q = self._filter_by_repo(RepoRhodeCodeUi, q)
94
94
95 if section:
95 if section:
96 q = q.filter(self.UiDbModel.ui_section == section)
96 q = q.filter(self.UiDbModel.ui_section == section)
97 if key:
97 if key:
98 q = q.filter(self.UiDbModel.ui_key == key)
98 q = q.filter(self.UiDbModel.ui_key == key)
99
99
100 # TODO: mikhail: add caching
100 # TODO: mikhail: add caching
101 result = [
101 result = [
102 UiSetting(
102 UiSetting(
103 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
103 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
104 value=safe_str(r.ui_value), active=r.ui_active
104 value=safe_str(r.ui_value), active=r.ui_active
105 )
105 )
106 for r in q.all()
106 for r in q.all()
107 ]
107 ]
108 return result
108 return result
109
109
110 def get_builtin_hooks(self):
110 def get_builtin_hooks(self):
111 q = self.UiDbModel.query()
111 q = self.UiDbModel.query()
112 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
112 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
113 return self._get_hooks(q)
113 return self._get_hooks(q)
114
114
115 def get_custom_hooks(self):
115 def get_custom_hooks(self):
116 q = self.UiDbModel.query()
116 q = self.UiDbModel.query()
117 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
117 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
118 return self._get_hooks(q)
118 return self._get_hooks(q)
119
119
120 def create_ui_section_value(self, section, val, key=None, active=True):
120 def create_ui_section_value(self, section, val, key=None, active=True):
121 new_ui = self.UiDbModel()
121 new_ui = self.UiDbModel()
122 new_ui.ui_section = section
122 new_ui.ui_section = section
123 new_ui.ui_value = val
123 new_ui.ui_value = val
124 new_ui.ui_active = active
124 new_ui.ui_active = active
125
125
126 repository_id = ''
126 repository_id = ''
127 if self.repo:
127 if self.repo:
128 repo = self._get_repo(self.repo)
128 repo = self._get_repo(self.repo)
129 repository_id = repo.repo_id
129 repository_id = repo.repo_id
130 new_ui.repository_id = repository_id
130 new_ui.repository_id = repository_id
131
131
132 if not key:
132 if not key:
133 # keys are unique so they need appended info
133 # keys are unique so they need appended info
134 if self.repo:
134 if self.repo:
135 key = hashlib.sha1(
135 key = hashlib.sha1(
136 '{}{}{}'.format(section, val, repository_id)).hexdigest()
136 '{}{}{}'.format(section, val, repository_id)).hexdigest()
137 else:
137 else:
138 key = hashlib.sha1('{}{}'.format(section, val)).hexdigest()
138 key = hashlib.sha1('{}{}'.format(section, val)).hexdigest()
139
139
140 new_ui.ui_key = key
140 new_ui.ui_key = key
141
141
142 Session().add(new_ui)
142 Session().add(new_ui)
143 return new_ui
143 return new_ui
144
144
145 def create_or_update_hook(self, key, value):
145 def create_or_update_hook(self, key, value):
146 ui = (
146 ui = (
147 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
147 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
148 self.UiDbModel())
148 self.UiDbModel())
149 ui.ui_section = self.HOOKS_SECTION
149 ui.ui_section = self.HOOKS_SECTION
150 ui.ui_active = True
150 ui.ui_active = True
151 ui.ui_key = key
151 ui.ui_key = key
152 ui.ui_value = value
152 ui.ui_value = value
153
153
154 if self.repo:
154 if self.repo:
155 repo = self._get_repo(self.repo)
155 repo = self._get_repo(self.repo)
156 repository_id = repo.repo_id
156 repository_id = repo.repo_id
157 ui.repository_id = repository_id
157 ui.repository_id = repository_id
158
158
159 Session().add(ui)
159 Session().add(ui)
160 return ui
160 return ui
161
161
162 def delete_ui(self, id_):
162 def delete_ui(self, id_):
163 ui = self.UiDbModel.get(id_)
163 ui = self.UiDbModel.get(id_)
164 if not ui:
164 if not ui:
165 raise SettingNotFound(id_)
165 raise SettingNotFound(id_)
166 Session().delete(ui)
166 Session().delete(ui)
167
167
168 def get_setting_by_name(self, name):
168 def get_setting_by_name(self, name):
169 q = self._get_settings_query()
169 q = self._get_settings_query()
170 q = q.filter(self.SettingsDbModel.app_settings_name == name)
170 q = q.filter(self.SettingsDbModel.app_settings_name == name)
171 return q.scalar()
171 return q.scalar()
172
172
173 def create_or_update_setting(
173 def create_or_update_setting(
174 self, name, val=Optional(''), type_=Optional('unicode')):
174 self, name, val=Optional(''), type_=Optional('unicode')):
175 """
175 """
176 Creates or updates RhodeCode setting. If updates is triggered it will
176 Creates or updates RhodeCode setting. If updates is triggered it will
177 only update parameters that are explicitly set Optional instance will
177 only update parameters that are explicitly set Optional instance will
178 be skipped
178 be skipped
179
179
180 :param name:
180 :param name:
181 :param val:
181 :param val:
182 :param type_:
182 :param type_:
183 :return:
183 :return:
184 """
184 """
185
185
186 res = self.get_setting_by_name(name)
186 res = self.get_setting_by_name(name)
187 repo = self._get_repo(self.repo) if self.repo else None
187 repo = self._get_repo(self.repo) if self.repo else None
188
188
189 if not res:
189 if not res:
190 val = Optional.extract(val)
190 val = Optional.extract(val)
191 type_ = Optional.extract(type_)
191 type_ = Optional.extract(type_)
192
192
193 args = (
193 args = (
194 (repo.repo_id, name, val, type_)
194 (repo.repo_id, name, val, type_)
195 if repo else (name, val, type_))
195 if repo else (name, val, type_))
196 res = self.SettingsDbModel(*args)
196 res = self.SettingsDbModel(*args)
197
197
198 else:
198 else:
199 if self.repo:
199 if self.repo:
200 res.repository_id = repo.repo_id
200 res.repository_id = repo.repo_id
201
201
202 res.app_settings_name = name
202 res.app_settings_name = name
203 if not isinstance(type_, Optional):
203 if not isinstance(type_, Optional):
204 # update if set
204 # update if set
205 res.app_settings_type = type_
205 res.app_settings_type = type_
206 if not isinstance(val, Optional):
206 if not isinstance(val, Optional):
207 # update if set
207 # update if set
208 res.app_settings_value = val
208 res.app_settings_value = val
209
209
210 Session().add(res)
210 Session().add(res)
211 return res
211 return res
212
212
213 def get_cache_region(self):
213 def get_cache_region(self):
214 repo = self._get_repo(self.repo) if self.repo else None
214 repo = self._get_repo(self.repo) if self.repo else None
215 cache_key = "repo.{}".format(repo.repo_id) if repo else "general_settings"
215 cache_key = "repo.{}".format(repo.repo_id) if repo else "general_settings"
216 cache_namespace_uid = 'cache_settings.{}'.format(cache_key)
216 cache_namespace_uid = 'cache_settings.{}'.format(cache_key)
217 region = rc_cache.get_or_create_region('cache_general', cache_namespace_uid)
217 region = rc_cache.get_or_create_region('cache_general', cache_namespace_uid)
218 return region, cache_key
218 return region, cache_key
219
219
220 def invalidate_settings_cache(self):
220 def invalidate_settings_cache(self):
221 from rhodecode.authentication.base import get_authn_registry
222
223 region, cache_key = self.get_cache_region()
221 region, cache_key = self.get_cache_region()
224 log.debug('Invalidation cache region %s for cache_key: %s', region, cache_key)
222 log.debug('Invalidation cache region %s for cache_key: %s', region, cache_key)
225 region.invalidate()
223 region.invalidate()
226 registry = get_current_registry()
227 if registry:
228 authn_registry = get_authn_registry(registry)
229 if authn_registry:
230 authn_registry.invalidate_plugins_for_auth()
231
224
232 def get_all_settings(self, cache=False, from_request=True):
225 def get_all_settings(self, cache=False, from_request=True):
233 # defines if we use GLOBAL, or PER_REPO
226 # defines if we use GLOBAL, or PER_REPO
234 repo = self._get_repo(self.repo) if self.repo else None
227 repo = self._get_repo(self.repo) if self.repo else None
235
228
236 # initially try the requests context, this is the fastest
229 # initially try the requests context, this is the fastest
237 # we only fetch global config
230 # we only fetch global config
238 if from_request:
231 if from_request:
239 request = get_current_request()
232 request = get_current_request()
240
233
241 if request and not repo and hasattr(request, 'call_context') and hasattr(request.call_context, 'rc_config'):
234 if request and not repo and hasattr(request, 'call_context') and hasattr(request.call_context, 'rc_config'):
242 rc_config = request.call_context.rc_config
235 rc_config = request.call_context.rc_config
243 if rc_config:
236 if rc_config:
244 return rc_config
237 return rc_config
245
238
246 region, cache_key = self.get_cache_region()
239 region, cache_key = self.get_cache_region()
247
240
248 @region.conditional_cache_on_arguments(condition=cache)
241 @region.conditional_cache_on_arguments(condition=cache)
249 def _get_all_settings(name, key):
242 def _get_all_settings(name, key):
250 q = self._get_settings_query()
243 q = self._get_settings_query()
251 if not q:
244 if not q:
252 raise Exception('Could not get application settings !')
245 raise Exception('Could not get application settings !')
253
246
254 settings = {
247 settings = {
255 'rhodecode_' + res.app_settings_name: res.app_settings_value
248 'rhodecode_' + res.app_settings_name: res.app_settings_value
256 for res in q
249 for res in q
257 }
250 }
258 return settings
251 return settings
259
252
260 start = time.time()
253 start = time.time()
261 result = _get_all_settings('rhodecode_settings', cache_key)
254 result = _get_all_settings('rhodecode_settings', cache_key)
262 compute_time = time.time() - start
255 compute_time = time.time() - start
256 log.debug('cached method:%s took %.4fs', _get_all_settings.func_name, compute_time)
263
257
264 statsd = StatsdClient.statsd
258 statsd = StatsdClient.statsd
265 if statsd:
259 if statsd:
266 elapsed_time_ms = round(1000.0 * compute_time) # use ms only
260 elapsed_time_ms = round(1000.0 * compute_time) # use ms only
267 statsd.timing("rhodecode_settings_timing.histogram", elapsed_time_ms,
261 statsd.timing("rhodecode_settings_timing.histogram", elapsed_time_ms,
268 use_decimals=False)
262 use_decimals=False)
269
263
270 log.debug('Fetching app settings for key: %s took: %.4fs: cache: %s', cache_key, compute_time, cache)
264 log.debug('Fetching app settings for key: %s took: %.4fs: cache: %s', cache_key, compute_time, cache)
271
265
272 return result
266 return result
273
267
274 def get_auth_settings(self):
268 def get_auth_settings(self):
275 q = self._get_settings_query()
269 q = self._get_settings_query()
276 q = q.filter(
270 q = q.filter(
277 self.SettingsDbModel.app_settings_name.startswith('auth_'))
271 self.SettingsDbModel.app_settings_name.startswith('auth_'))
278 rows = q.all()
272 rows = q.all()
279 auth_settings = {
273 auth_settings = {
280 row.app_settings_name: row.app_settings_value for row in rows}
274 row.app_settings_name: row.app_settings_value for row in rows}
281 return auth_settings
275 return auth_settings
282
276
283 def get_auth_plugins(self):
277 def get_auth_plugins(self):
284 auth_plugins = self.get_setting_by_name("auth_plugins")
278 auth_plugins = self.get_setting_by_name("auth_plugins")
285 return auth_plugins.app_settings_value
279 return auth_plugins.app_settings_value
286
280
287 def get_default_repo_settings(self, strip_prefix=False):
281 def get_default_repo_settings(self, strip_prefix=False):
288 q = self._get_settings_query()
282 q = self._get_settings_query()
289 q = q.filter(
283 q = q.filter(
290 self.SettingsDbModel.app_settings_name.startswith('default_'))
284 self.SettingsDbModel.app_settings_name.startswith('default_'))
291 rows = q.all()
285 rows = q.all()
292
286
293 result = {}
287 result = {}
294 for row in rows:
288 for row in rows:
295 key = row.app_settings_name
289 key = row.app_settings_name
296 if strip_prefix:
290 if strip_prefix:
297 key = remove_prefix(key, prefix='default_')
291 key = remove_prefix(key, prefix='default_')
298 result.update({key: row.app_settings_value})
292 result.update({key: row.app_settings_value})
299 return result
293 return result
300
294
301 def get_repo(self):
295 def get_repo(self):
302 repo = self._get_repo(self.repo)
296 repo = self._get_repo(self.repo)
303 if not repo:
297 if not repo:
304 raise Exception(
298 raise Exception(
305 'Repository `{}` cannot be found inside the database'.format(
299 'Repository `{}` cannot be found inside the database'.format(
306 self.repo))
300 self.repo))
307 return repo
301 return repo
308
302
309 def _filter_by_repo(self, model, query):
303 def _filter_by_repo(self, model, query):
310 if self.repo:
304 if self.repo:
311 repo = self.get_repo()
305 repo = self.get_repo()
312 query = query.filter(model.repository_id == repo.repo_id)
306 query = query.filter(model.repository_id == repo.repo_id)
313 return query
307 return query
314
308
315 def _get_hooks(self, query):
309 def _get_hooks(self, query):
316 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
310 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
317 query = self._filter_by_repo(RepoRhodeCodeUi, query)
311 query = self._filter_by_repo(RepoRhodeCodeUi, query)
318 return query.all()
312 return query.all()
319
313
320 def _get_settings_query(self):
314 def _get_settings_query(self):
321 q = self.SettingsDbModel.query()
315 q = self.SettingsDbModel.query()
322 return self._filter_by_repo(RepoRhodeCodeSetting, q)
316 return self._filter_by_repo(RepoRhodeCodeSetting, q)
323
317
324 def list_enabled_social_plugins(self, settings):
318 def list_enabled_social_plugins(self, settings):
325 enabled = []
319 enabled = []
326 for plug in SOCIAL_PLUGINS_LIST:
320 for plug in SOCIAL_PLUGINS_LIST:
327 if str2bool(settings.get('rhodecode_auth_{}_enabled'.format(plug)
321 if str2bool(settings.get('rhodecode_auth_{}_enabled'.format(plug)
328 )):
322 )):
329 enabled.append(plug)
323 enabled.append(plug)
330 return enabled
324 return enabled
331
325
332
326
333 def assert_repo_settings(func):
327 def assert_repo_settings(func):
334 @wraps(func)
328 @wraps(func)
335 def _wrapper(self, *args, **kwargs):
329 def _wrapper(self, *args, **kwargs):
336 if not self.repo_settings:
330 if not self.repo_settings:
337 raise Exception('Repository is not specified')
331 raise Exception('Repository is not specified')
338 return func(self, *args, **kwargs)
332 return func(self, *args, **kwargs)
339 return _wrapper
333 return _wrapper
340
334
341
335
342 class IssueTrackerSettingsModel(object):
336 class IssueTrackerSettingsModel(object):
343 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
337 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
344 SETTINGS_PREFIX = 'issuetracker_'
338 SETTINGS_PREFIX = 'issuetracker_'
345
339
346 def __init__(self, sa=None, repo=None):
340 def __init__(self, sa=None, repo=None):
347 self.global_settings = SettingsModel(sa=sa)
341 self.global_settings = SettingsModel(sa=sa)
348 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
342 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
349
343
350 @property
344 @property
351 def inherit_global_settings(self):
345 def inherit_global_settings(self):
352 if not self.repo_settings:
346 if not self.repo_settings:
353 return True
347 return True
354 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
348 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
355 return setting.app_settings_value if setting else True
349 return setting.app_settings_value if setting else True
356
350
357 @inherit_global_settings.setter
351 @inherit_global_settings.setter
358 def inherit_global_settings(self, value):
352 def inherit_global_settings(self, value):
359 if self.repo_settings:
353 if self.repo_settings:
360 settings = self.repo_settings.create_or_update_setting(
354 settings = self.repo_settings.create_or_update_setting(
361 self.INHERIT_SETTINGS, value, type_='bool')
355 self.INHERIT_SETTINGS, value, type_='bool')
362 Session().add(settings)
356 Session().add(settings)
363
357
364 def _get_keyname(self, key, uid, prefix=''):
358 def _get_keyname(self, key, uid, prefix=''):
365 return '{0}{1}{2}_{3}'.format(
359 return '{0}{1}{2}_{3}'.format(
366 prefix, self.SETTINGS_PREFIX, key, uid)
360 prefix, self.SETTINGS_PREFIX, key, uid)
367
361
368 def _make_dict_for_settings(self, qs):
362 def _make_dict_for_settings(self, qs):
369 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
363 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
370
364
371 issuetracker_entries = {}
365 issuetracker_entries = {}
372 # create keys
366 # create keys
373 for k, v in qs.items():
367 for k, v in qs.items():
374 if k.startswith(prefix_match):
368 if k.startswith(prefix_match):
375 uid = k[len(prefix_match):]
369 uid = k[len(prefix_match):]
376 issuetracker_entries[uid] = None
370 issuetracker_entries[uid] = None
377
371
378 def url_cleaner(input_str):
372 def url_cleaner(input_str):
379 input_str = input_str.replace('"', '').replace("'", '')
373 input_str = input_str.replace('"', '').replace("'", '')
380 input_str = bleach.clean(input_str, strip=True)
374 input_str = bleach.clean(input_str, strip=True)
381 return input_str
375 return input_str
382
376
383 # populate
377 # populate
384 for uid in issuetracker_entries:
378 for uid in issuetracker_entries:
385 url_data = qs.get(self._get_keyname('url', uid, 'rhodecode_'))
379 url_data = qs.get(self._get_keyname('url', uid, 'rhodecode_'))
386
380
387 pat = qs.get(self._get_keyname('pat', uid, 'rhodecode_'))
381 pat = qs.get(self._get_keyname('pat', uid, 'rhodecode_'))
388 try:
382 try:
389 pat_compiled = re.compile(r'%s' % pat)
383 pat_compiled = re.compile(r'%s' % pat)
390 except re.error:
384 except re.error:
391 pat_compiled = None
385 pat_compiled = None
392
386
393 issuetracker_entries[uid] = AttributeDict({
387 issuetracker_entries[uid] = AttributeDict({
394 'pat': pat,
388 'pat': pat,
395 'pat_compiled': pat_compiled,
389 'pat_compiled': pat_compiled,
396 'url': url_cleaner(
390 'url': url_cleaner(
397 qs.get(self._get_keyname('url', uid, 'rhodecode_')) or ''),
391 qs.get(self._get_keyname('url', uid, 'rhodecode_')) or ''),
398 'pref': bleach.clean(
392 'pref': bleach.clean(
399 qs.get(self._get_keyname('pref', uid, 'rhodecode_')) or ''),
393 qs.get(self._get_keyname('pref', uid, 'rhodecode_')) or ''),
400 'desc': qs.get(
394 'desc': qs.get(
401 self._get_keyname('desc', uid, 'rhodecode_')),
395 self._get_keyname('desc', uid, 'rhodecode_')),
402 })
396 })
403
397
404 return issuetracker_entries
398 return issuetracker_entries
405
399
406 def get_global_settings(self, cache=False):
400 def get_global_settings(self, cache=False):
407 """
401 """
408 Returns list of global issue tracker settings
402 Returns list of global issue tracker settings
409 """
403 """
410 defaults = self.global_settings.get_all_settings(cache=cache)
404 defaults = self.global_settings.get_all_settings(cache=cache)
411 settings = self._make_dict_for_settings(defaults)
405 settings = self._make_dict_for_settings(defaults)
412 return settings
406 return settings
413
407
414 def get_repo_settings(self, cache=False):
408 def get_repo_settings(self, cache=False):
415 """
409 """
416 Returns list of issue tracker settings per repository
410 Returns list of issue tracker settings per repository
417 """
411 """
418 if not self.repo_settings:
412 if not self.repo_settings:
419 raise Exception('Repository is not specified')
413 raise Exception('Repository is not specified')
420 all_settings = self.repo_settings.get_all_settings(cache=cache)
414 all_settings = self.repo_settings.get_all_settings(cache=cache)
421 settings = self._make_dict_for_settings(all_settings)
415 settings = self._make_dict_for_settings(all_settings)
422 return settings
416 return settings
423
417
424 def get_settings(self, cache=False):
418 def get_settings(self, cache=False):
425 if self.inherit_global_settings:
419 if self.inherit_global_settings:
426 return self.get_global_settings(cache=cache)
420 return self.get_global_settings(cache=cache)
427 else:
421 else:
428 return self.get_repo_settings(cache=cache)
422 return self.get_repo_settings(cache=cache)
429
423
430 def delete_entries(self, uid):
424 def delete_entries(self, uid):
431 if self.repo_settings:
425 if self.repo_settings:
432 all_patterns = self.get_repo_settings()
426 all_patterns = self.get_repo_settings()
433 settings_model = self.repo_settings
427 settings_model = self.repo_settings
434 else:
428 else:
435 all_patterns = self.get_global_settings()
429 all_patterns = self.get_global_settings()
436 settings_model = self.global_settings
430 settings_model = self.global_settings
437 entries = all_patterns.get(uid, [])
431 entries = all_patterns.get(uid, [])
438
432
439 for del_key in entries:
433 for del_key in entries:
440 setting_name = self._get_keyname(del_key, uid)
434 setting_name = self._get_keyname(del_key, uid)
441 entry = settings_model.get_setting_by_name(setting_name)
435 entry = settings_model.get_setting_by_name(setting_name)
442 if entry:
436 if entry:
443 Session().delete(entry)
437 Session().delete(entry)
444
438
445 Session().commit()
439 Session().commit()
446
440
447 def create_or_update_setting(
441 def create_or_update_setting(
448 self, name, val=Optional(''), type_=Optional('unicode')):
442 self, name, val=Optional(''), type_=Optional('unicode')):
449 if self.repo_settings:
443 if self.repo_settings:
450 setting = self.repo_settings.create_or_update_setting(
444 setting = self.repo_settings.create_or_update_setting(
451 name, val, type_)
445 name, val, type_)
452 else:
446 else:
453 setting = self.global_settings.create_or_update_setting(
447 setting = self.global_settings.create_or_update_setting(
454 name, val, type_)
448 name, val, type_)
455 return setting
449 return setting
456
450
457
451
458 class VcsSettingsModel(object):
452 class VcsSettingsModel(object):
459
453
460 INHERIT_SETTINGS = 'inherit_vcs_settings'
454 INHERIT_SETTINGS = 'inherit_vcs_settings'
461 GENERAL_SETTINGS = (
455 GENERAL_SETTINGS = (
462 'use_outdated_comments',
456 'use_outdated_comments',
463 'pr_merge_enabled',
457 'pr_merge_enabled',
464 'hg_use_rebase_for_merging',
458 'hg_use_rebase_for_merging',
465 'hg_close_branch_before_merging',
459 'hg_close_branch_before_merging',
466 'git_use_rebase_for_merging',
460 'git_use_rebase_for_merging',
467 'git_close_branch_before_merging',
461 'git_close_branch_before_merging',
468 'diff_cache',
462 'diff_cache',
469 )
463 )
470
464
471 HOOKS_SETTINGS = (
465 HOOKS_SETTINGS = (
472 ('hooks', 'changegroup.repo_size'),
466 ('hooks', 'changegroup.repo_size'),
473 ('hooks', 'changegroup.push_logger'),
467 ('hooks', 'changegroup.push_logger'),
474 ('hooks', 'outgoing.pull_logger'),
468 ('hooks', 'outgoing.pull_logger'),
475 )
469 )
476 HG_SETTINGS = (
470 HG_SETTINGS = (
477 ('extensions', 'largefiles'),
471 ('extensions', 'largefiles'),
478 ('phases', 'publish'),
472 ('phases', 'publish'),
479 ('extensions', 'evolve'),
473 ('extensions', 'evolve'),
480 ('extensions', 'topic'),
474 ('extensions', 'topic'),
481 ('experimental', 'evolution'),
475 ('experimental', 'evolution'),
482 ('experimental', 'evolution.exchange'),
476 ('experimental', 'evolution.exchange'),
483 )
477 )
484 GIT_SETTINGS = (
478 GIT_SETTINGS = (
485 ('vcs_git_lfs', 'enabled'),
479 ('vcs_git_lfs', 'enabled'),
486 )
480 )
487 GLOBAL_HG_SETTINGS = (
481 GLOBAL_HG_SETTINGS = (
488 ('extensions', 'largefiles'),
482 ('extensions', 'largefiles'),
489 ('largefiles', 'usercache'),
483 ('largefiles', 'usercache'),
490 ('phases', 'publish'),
484 ('phases', 'publish'),
491 ('extensions', 'hgsubversion'),
485 ('extensions', 'hgsubversion'),
492 ('extensions', 'evolve'),
486 ('extensions', 'evolve'),
493 ('extensions', 'topic'),
487 ('extensions', 'topic'),
494 ('experimental', 'evolution'),
488 ('experimental', 'evolution'),
495 ('experimental', 'evolution.exchange'),
489 ('experimental', 'evolution.exchange'),
496 )
490 )
497
491
498 GLOBAL_GIT_SETTINGS = (
492 GLOBAL_GIT_SETTINGS = (
499 ('vcs_git_lfs', 'enabled'),
493 ('vcs_git_lfs', 'enabled'),
500 ('vcs_git_lfs', 'store_location')
494 ('vcs_git_lfs', 'store_location')
501 )
495 )
502
496
503 GLOBAL_SVN_SETTINGS = (
497 GLOBAL_SVN_SETTINGS = (
504 ('vcs_svn_proxy', 'http_requests_enabled'),
498 ('vcs_svn_proxy', 'http_requests_enabled'),
505 ('vcs_svn_proxy', 'http_server_url')
499 ('vcs_svn_proxy', 'http_server_url')
506 )
500 )
507
501
508 SVN_BRANCH_SECTION = 'vcs_svn_branch'
502 SVN_BRANCH_SECTION = 'vcs_svn_branch'
509 SVN_TAG_SECTION = 'vcs_svn_tag'
503 SVN_TAG_SECTION = 'vcs_svn_tag'
510 SSL_SETTING = ('web', 'push_ssl')
504 SSL_SETTING = ('web', 'push_ssl')
511 PATH_SETTING = ('paths', '/')
505 PATH_SETTING = ('paths', '/')
512
506
513 def __init__(self, sa=None, repo=None):
507 def __init__(self, sa=None, repo=None):
514 self.global_settings = SettingsModel(sa=sa)
508 self.global_settings = SettingsModel(sa=sa)
515 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
509 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
516 self._ui_settings = (
510 self._ui_settings = (
517 self.HG_SETTINGS + self.GIT_SETTINGS + self.HOOKS_SETTINGS)
511 self.HG_SETTINGS + self.GIT_SETTINGS + self.HOOKS_SETTINGS)
518 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
512 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
519
513
520 @property
514 @property
521 @assert_repo_settings
515 @assert_repo_settings
522 def inherit_global_settings(self):
516 def inherit_global_settings(self):
523 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
517 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
524 return setting.app_settings_value if setting else True
518 return setting.app_settings_value if setting else True
525
519
526 @inherit_global_settings.setter
520 @inherit_global_settings.setter
527 @assert_repo_settings
521 @assert_repo_settings
528 def inherit_global_settings(self, value):
522 def inherit_global_settings(self, value):
529 self.repo_settings.create_or_update_setting(
523 self.repo_settings.create_or_update_setting(
530 self.INHERIT_SETTINGS, value, type_='bool')
524 self.INHERIT_SETTINGS, value, type_='bool')
531
525
532 def get_global_svn_branch_patterns(self):
526 def get_global_svn_branch_patterns(self):
533 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
527 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
534
528
535 @assert_repo_settings
529 @assert_repo_settings
536 def get_repo_svn_branch_patterns(self):
530 def get_repo_svn_branch_patterns(self):
537 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
531 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
538
532
539 def get_global_svn_tag_patterns(self):
533 def get_global_svn_tag_patterns(self):
540 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
534 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
541
535
542 @assert_repo_settings
536 @assert_repo_settings
543 def get_repo_svn_tag_patterns(self):
537 def get_repo_svn_tag_patterns(self):
544 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
538 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
545
539
546 def get_global_settings(self):
540 def get_global_settings(self):
547 return self._collect_all_settings(global_=True)
541 return self._collect_all_settings(global_=True)
548
542
549 @assert_repo_settings
543 @assert_repo_settings
550 def get_repo_settings(self):
544 def get_repo_settings(self):
551 return self._collect_all_settings(global_=False)
545 return self._collect_all_settings(global_=False)
552
546
553 @assert_repo_settings
547 @assert_repo_settings
554 def get_repo_settings_inherited(self):
548 def get_repo_settings_inherited(self):
555 global_settings = self.get_global_settings()
549 global_settings = self.get_global_settings()
556 global_settings.update(self.get_repo_settings())
550 global_settings.update(self.get_repo_settings())
557 return global_settings
551 return global_settings
558
552
559 @assert_repo_settings
553 @assert_repo_settings
560 def create_or_update_repo_settings(
554 def create_or_update_repo_settings(
561 self, data, inherit_global_settings=False):
555 self, data, inherit_global_settings=False):
562 from rhodecode.model.scm import ScmModel
556 from rhodecode.model.scm import ScmModel
563
557
564 self.inherit_global_settings = inherit_global_settings
558 self.inherit_global_settings = inherit_global_settings
565
559
566 repo = self.repo_settings.get_repo()
560 repo = self.repo_settings.get_repo()
567 if not inherit_global_settings:
561 if not inherit_global_settings:
568 if repo.repo_type == 'svn':
562 if repo.repo_type == 'svn':
569 self.create_repo_svn_settings(data)
563 self.create_repo_svn_settings(data)
570 else:
564 else:
571 self.create_or_update_repo_hook_settings(data)
565 self.create_or_update_repo_hook_settings(data)
572 self.create_or_update_repo_pr_settings(data)
566 self.create_or_update_repo_pr_settings(data)
573
567
574 if repo.repo_type == 'hg':
568 if repo.repo_type == 'hg':
575 self.create_or_update_repo_hg_settings(data)
569 self.create_or_update_repo_hg_settings(data)
576
570
577 if repo.repo_type == 'git':
571 if repo.repo_type == 'git':
578 self.create_or_update_repo_git_settings(data)
572 self.create_or_update_repo_git_settings(data)
579
573
580 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
574 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
581
575
582 @assert_repo_settings
576 @assert_repo_settings
583 def create_or_update_repo_hook_settings(self, data):
577 def create_or_update_repo_hook_settings(self, data):
584 for section, key in self.HOOKS_SETTINGS:
578 for section, key in self.HOOKS_SETTINGS:
585 data_key = self._get_form_ui_key(section, key)
579 data_key = self._get_form_ui_key(section, key)
586 if data_key not in data:
580 if data_key not in data:
587 raise ValueError(
581 raise ValueError(
588 'The given data does not contain {} key'.format(data_key))
582 'The given data does not contain {} key'.format(data_key))
589
583
590 active = data.get(data_key)
584 active = data.get(data_key)
591 repo_setting = self.repo_settings.get_ui_by_section_and_key(
585 repo_setting = self.repo_settings.get_ui_by_section_and_key(
592 section, key)
586 section, key)
593 if not repo_setting:
587 if not repo_setting:
594 global_setting = self.global_settings.\
588 global_setting = self.global_settings.\
595 get_ui_by_section_and_key(section, key)
589 get_ui_by_section_and_key(section, key)
596 self.repo_settings.create_ui_section_value(
590 self.repo_settings.create_ui_section_value(
597 section, global_setting.ui_value, key=key, active=active)
591 section, global_setting.ui_value, key=key, active=active)
598 else:
592 else:
599 repo_setting.ui_active = active
593 repo_setting.ui_active = active
600 Session().add(repo_setting)
594 Session().add(repo_setting)
601
595
602 def update_global_hook_settings(self, data):
596 def update_global_hook_settings(self, data):
603 for section, key in self.HOOKS_SETTINGS:
597 for section, key in self.HOOKS_SETTINGS:
604 data_key = self._get_form_ui_key(section, key)
598 data_key = self._get_form_ui_key(section, key)
605 if data_key not in data:
599 if data_key not in data:
606 raise ValueError(
600 raise ValueError(
607 'The given data does not contain {} key'.format(data_key))
601 'The given data does not contain {} key'.format(data_key))
608 active = data.get(data_key)
602 active = data.get(data_key)
609 repo_setting = self.global_settings.get_ui_by_section_and_key(
603 repo_setting = self.global_settings.get_ui_by_section_and_key(
610 section, key)
604 section, key)
611 repo_setting.ui_active = active
605 repo_setting.ui_active = active
612 Session().add(repo_setting)
606 Session().add(repo_setting)
613
607
614 @assert_repo_settings
608 @assert_repo_settings
615 def create_or_update_repo_pr_settings(self, data):
609 def create_or_update_repo_pr_settings(self, data):
616 return self._create_or_update_general_settings(
610 return self._create_or_update_general_settings(
617 self.repo_settings, data)
611 self.repo_settings, data)
618
612
619 def create_or_update_global_pr_settings(self, data):
613 def create_or_update_global_pr_settings(self, data):
620 return self._create_or_update_general_settings(
614 return self._create_or_update_general_settings(
621 self.global_settings, data)
615 self.global_settings, data)
622
616
623 @assert_repo_settings
617 @assert_repo_settings
624 def create_repo_svn_settings(self, data):
618 def create_repo_svn_settings(self, data):
625 return self._create_svn_settings(self.repo_settings, data)
619 return self._create_svn_settings(self.repo_settings, data)
626
620
627 def _set_evolution(self, settings, is_enabled):
621 def _set_evolution(self, settings, is_enabled):
628 if is_enabled:
622 if is_enabled:
629 # if evolve is active set evolution=all
623 # if evolve is active set evolution=all
630
624
631 self._create_or_update_ui(
625 self._create_or_update_ui(
632 settings, *('experimental', 'evolution'), value='all',
626 settings, *('experimental', 'evolution'), value='all',
633 active=True)
627 active=True)
634 self._create_or_update_ui(
628 self._create_or_update_ui(
635 settings, *('experimental', 'evolution.exchange'), value='yes',
629 settings, *('experimental', 'evolution.exchange'), value='yes',
636 active=True)
630 active=True)
637 # if evolve is active set topics server support
631 # if evolve is active set topics server support
638 self._create_or_update_ui(
632 self._create_or_update_ui(
639 settings, *('extensions', 'topic'), value='',
633 settings, *('extensions', 'topic'), value='',
640 active=True)
634 active=True)
641
635
642 else:
636 else:
643 self._create_or_update_ui(
637 self._create_or_update_ui(
644 settings, *('experimental', 'evolution'), value='',
638 settings, *('experimental', 'evolution'), value='',
645 active=False)
639 active=False)
646 self._create_or_update_ui(
640 self._create_or_update_ui(
647 settings, *('experimental', 'evolution.exchange'), value='no',
641 settings, *('experimental', 'evolution.exchange'), value='no',
648 active=False)
642 active=False)
649 self._create_or_update_ui(
643 self._create_or_update_ui(
650 settings, *('extensions', 'topic'), value='',
644 settings, *('extensions', 'topic'), value='',
651 active=False)
645 active=False)
652
646
653 @assert_repo_settings
647 @assert_repo_settings
654 def create_or_update_repo_hg_settings(self, data):
648 def create_or_update_repo_hg_settings(self, data):
655 largefiles, phases, evolve = \
649 largefiles, phases, evolve = \
656 self.HG_SETTINGS[:3]
650 self.HG_SETTINGS[:3]
657 largefiles_key, phases_key, evolve_key = \
651 largefiles_key, phases_key, evolve_key = \
658 self._get_settings_keys(self.HG_SETTINGS[:3], data)
652 self._get_settings_keys(self.HG_SETTINGS[:3], data)
659
653
660 self._create_or_update_ui(
654 self._create_or_update_ui(
661 self.repo_settings, *largefiles, value='',
655 self.repo_settings, *largefiles, value='',
662 active=data[largefiles_key])
656 active=data[largefiles_key])
663 self._create_or_update_ui(
657 self._create_or_update_ui(
664 self.repo_settings, *evolve, value='',
658 self.repo_settings, *evolve, value='',
665 active=data[evolve_key])
659 active=data[evolve_key])
666 self._set_evolution(self.repo_settings, is_enabled=data[evolve_key])
660 self._set_evolution(self.repo_settings, is_enabled=data[evolve_key])
667
661
668 self._create_or_update_ui(
662 self._create_or_update_ui(
669 self.repo_settings, *phases, value=safe_str(data[phases_key]))
663 self.repo_settings, *phases, value=safe_str(data[phases_key]))
670
664
671 def create_or_update_global_hg_settings(self, data):
665 def create_or_update_global_hg_settings(self, data):
672 largefiles, largefiles_store, phases, hgsubversion, evolve \
666 largefiles, largefiles_store, phases, hgsubversion, evolve \
673 = self.GLOBAL_HG_SETTINGS[:5]
667 = self.GLOBAL_HG_SETTINGS[:5]
674 largefiles_key, largefiles_store_key, phases_key, subversion_key, evolve_key \
668 largefiles_key, largefiles_store_key, phases_key, subversion_key, evolve_key \
675 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS[:5], data)
669 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS[:5], data)
676
670
677 self._create_or_update_ui(
671 self._create_or_update_ui(
678 self.global_settings, *largefiles, value='',
672 self.global_settings, *largefiles, value='',
679 active=data[largefiles_key])
673 active=data[largefiles_key])
680 self._create_or_update_ui(
674 self._create_or_update_ui(
681 self.global_settings, *largefiles_store, value=data[largefiles_store_key])
675 self.global_settings, *largefiles_store, value=data[largefiles_store_key])
682 self._create_or_update_ui(
676 self._create_or_update_ui(
683 self.global_settings, *phases, value=safe_str(data[phases_key]))
677 self.global_settings, *phases, value=safe_str(data[phases_key]))
684 self._create_or_update_ui(
678 self._create_or_update_ui(
685 self.global_settings, *hgsubversion, active=data[subversion_key])
679 self.global_settings, *hgsubversion, active=data[subversion_key])
686 self._create_or_update_ui(
680 self._create_or_update_ui(
687 self.global_settings, *evolve, value='',
681 self.global_settings, *evolve, value='',
688 active=data[evolve_key])
682 active=data[evolve_key])
689 self._set_evolution(self.global_settings, is_enabled=data[evolve_key])
683 self._set_evolution(self.global_settings, is_enabled=data[evolve_key])
690
684
691 def create_or_update_repo_git_settings(self, data):
685 def create_or_update_repo_git_settings(self, data):
692 # NOTE(marcink): # comma makes unpack work properly
686 # NOTE(marcink): # comma makes unpack work properly
693 lfs_enabled, \
687 lfs_enabled, \
694 = self.GIT_SETTINGS
688 = self.GIT_SETTINGS
695
689
696 lfs_enabled_key, \
690 lfs_enabled_key, \
697 = self._get_settings_keys(self.GIT_SETTINGS, data)
691 = self._get_settings_keys(self.GIT_SETTINGS, data)
698
692
699 self._create_or_update_ui(
693 self._create_or_update_ui(
700 self.repo_settings, *lfs_enabled, value=data[lfs_enabled_key],
694 self.repo_settings, *lfs_enabled, value=data[lfs_enabled_key],
701 active=data[lfs_enabled_key])
695 active=data[lfs_enabled_key])
702
696
703 def create_or_update_global_git_settings(self, data):
697 def create_or_update_global_git_settings(self, data):
704 lfs_enabled, lfs_store_location \
698 lfs_enabled, lfs_store_location \
705 = self.GLOBAL_GIT_SETTINGS
699 = self.GLOBAL_GIT_SETTINGS
706 lfs_enabled_key, lfs_store_location_key \
700 lfs_enabled_key, lfs_store_location_key \
707 = self._get_settings_keys(self.GLOBAL_GIT_SETTINGS, data)
701 = self._get_settings_keys(self.GLOBAL_GIT_SETTINGS, data)
708
702
709 self._create_or_update_ui(
703 self._create_or_update_ui(
710 self.global_settings, *lfs_enabled, value=data[lfs_enabled_key],
704 self.global_settings, *lfs_enabled, value=data[lfs_enabled_key],
711 active=data[lfs_enabled_key])
705 active=data[lfs_enabled_key])
712 self._create_or_update_ui(
706 self._create_or_update_ui(
713 self.global_settings, *lfs_store_location,
707 self.global_settings, *lfs_store_location,
714 value=data[lfs_store_location_key])
708 value=data[lfs_store_location_key])
715
709
716 def create_or_update_global_svn_settings(self, data):
710 def create_or_update_global_svn_settings(self, data):
717 # branch/tags patterns
711 # branch/tags patterns
718 self._create_svn_settings(self.global_settings, data)
712 self._create_svn_settings(self.global_settings, data)
719
713
720 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
714 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
721 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
715 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
722 self.GLOBAL_SVN_SETTINGS, data)
716 self.GLOBAL_SVN_SETTINGS, data)
723
717
724 self._create_or_update_ui(
718 self._create_or_update_ui(
725 self.global_settings, *http_requests_enabled,
719 self.global_settings, *http_requests_enabled,
726 value=safe_str(data[http_requests_enabled_key]))
720 value=safe_str(data[http_requests_enabled_key]))
727 self._create_or_update_ui(
721 self._create_or_update_ui(
728 self.global_settings, *http_server_url,
722 self.global_settings, *http_server_url,
729 value=data[http_server_url_key])
723 value=data[http_server_url_key])
730
724
731 def update_global_ssl_setting(self, value):
725 def update_global_ssl_setting(self, value):
732 self._create_or_update_ui(
726 self._create_or_update_ui(
733 self.global_settings, *self.SSL_SETTING, value=value)
727 self.global_settings, *self.SSL_SETTING, value=value)
734
728
735 def update_global_path_setting(self, value):
729 def update_global_path_setting(self, value):
736 self._create_or_update_ui(
730 self._create_or_update_ui(
737 self.global_settings, *self.PATH_SETTING, value=value)
731 self.global_settings, *self.PATH_SETTING, value=value)
738
732
739 @assert_repo_settings
733 @assert_repo_settings
740 def delete_repo_svn_pattern(self, id_):
734 def delete_repo_svn_pattern(self, id_):
741 ui = self.repo_settings.UiDbModel.get(id_)
735 ui = self.repo_settings.UiDbModel.get(id_)
742 if ui and ui.repository.repo_name == self.repo_settings.repo:
736 if ui and ui.repository.repo_name == self.repo_settings.repo:
743 # only delete if it's the same repo as initialized settings
737 # only delete if it's the same repo as initialized settings
744 self.repo_settings.delete_ui(id_)
738 self.repo_settings.delete_ui(id_)
745 else:
739 else:
746 # raise error as if we wouldn't find this option
740 # raise error as if we wouldn't find this option
747 self.repo_settings.delete_ui(-1)
741 self.repo_settings.delete_ui(-1)
748
742
749 def delete_global_svn_pattern(self, id_):
743 def delete_global_svn_pattern(self, id_):
750 self.global_settings.delete_ui(id_)
744 self.global_settings.delete_ui(id_)
751
745
752 @assert_repo_settings
746 @assert_repo_settings
753 def get_repo_ui_settings(self, section=None, key=None):
747 def get_repo_ui_settings(self, section=None, key=None):
754 global_uis = self.global_settings.get_ui(section, key)
748 global_uis = self.global_settings.get_ui(section, key)
755 repo_uis = self.repo_settings.get_ui(section, key)
749 repo_uis = self.repo_settings.get_ui(section, key)
756
750
757 filtered_repo_uis = self._filter_ui_settings(repo_uis)
751 filtered_repo_uis = self._filter_ui_settings(repo_uis)
758 filtered_repo_uis_keys = [
752 filtered_repo_uis_keys = [
759 (s.section, s.key) for s in filtered_repo_uis]
753 (s.section, s.key) for s in filtered_repo_uis]
760
754
761 def _is_global_ui_filtered(ui):
755 def _is_global_ui_filtered(ui):
762 return (
756 return (
763 (ui.section, ui.key) in filtered_repo_uis_keys
757 (ui.section, ui.key) in filtered_repo_uis_keys
764 or ui.section in self._svn_sections)
758 or ui.section in self._svn_sections)
765
759
766 filtered_global_uis = [
760 filtered_global_uis = [
767 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
761 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
768
762
769 return filtered_global_uis + filtered_repo_uis
763 return filtered_global_uis + filtered_repo_uis
770
764
771 def get_global_ui_settings(self, section=None, key=None):
765 def get_global_ui_settings(self, section=None, key=None):
772 return self.global_settings.get_ui(section, key)
766 return self.global_settings.get_ui(section, key)
773
767
774 def get_ui_settings_as_config_obj(self, section=None, key=None):
768 def get_ui_settings_as_config_obj(self, section=None, key=None):
775 config = base.Config()
769 config = base.Config()
776
770
777 ui_settings = self.get_ui_settings(section=section, key=key)
771 ui_settings = self.get_ui_settings(section=section, key=key)
778
772
779 for entry in ui_settings:
773 for entry in ui_settings:
780 config.set(entry.section, entry.key, entry.value)
774 config.set(entry.section, entry.key, entry.value)
781
775
782 return config
776 return config
783
777
784 def get_ui_settings(self, section=None, key=None):
778 def get_ui_settings(self, section=None, key=None):
785 if not self.repo_settings or self.inherit_global_settings:
779 if not self.repo_settings or self.inherit_global_settings:
786 return self.get_global_ui_settings(section, key)
780 return self.get_global_ui_settings(section, key)
787 else:
781 else:
788 return self.get_repo_ui_settings(section, key)
782 return self.get_repo_ui_settings(section, key)
789
783
790 def get_svn_patterns(self, section=None):
784 def get_svn_patterns(self, section=None):
791 if not self.repo_settings:
785 if not self.repo_settings:
792 return self.get_global_ui_settings(section)
786 return self.get_global_ui_settings(section)
793 else:
787 else:
794 return self.get_repo_ui_settings(section)
788 return self.get_repo_ui_settings(section)
795
789
796 @assert_repo_settings
790 @assert_repo_settings
797 def get_repo_general_settings(self):
791 def get_repo_general_settings(self):
798 global_settings = self.global_settings.get_all_settings()
792 global_settings = self.global_settings.get_all_settings()
799 repo_settings = self.repo_settings.get_all_settings()
793 repo_settings = self.repo_settings.get_all_settings()
800 filtered_repo_settings = self._filter_general_settings(repo_settings)
794 filtered_repo_settings = self._filter_general_settings(repo_settings)
801 global_settings.update(filtered_repo_settings)
795 global_settings.update(filtered_repo_settings)
802 return global_settings
796 return global_settings
803
797
804 def get_global_general_settings(self):
798 def get_global_general_settings(self):
805 return self.global_settings.get_all_settings()
799 return self.global_settings.get_all_settings()
806
800
807 def get_general_settings(self):
801 def get_general_settings(self):
808 if not self.repo_settings or self.inherit_global_settings:
802 if not self.repo_settings or self.inherit_global_settings:
809 return self.get_global_general_settings()
803 return self.get_global_general_settings()
810 else:
804 else:
811 return self.get_repo_general_settings()
805 return self.get_repo_general_settings()
812
806
813 def get_repos_location(self):
807 def get_repos_location(self):
814 return self.global_settings.get_ui_by_key('/').ui_value
808 return self.global_settings.get_ui_by_key('/').ui_value
815
809
816 def _filter_ui_settings(self, settings):
810 def _filter_ui_settings(self, settings):
817 filtered_settings = [
811 filtered_settings = [
818 s for s in settings if self._should_keep_setting(s)]
812 s for s in settings if self._should_keep_setting(s)]
819 return filtered_settings
813 return filtered_settings
820
814
821 def _should_keep_setting(self, setting):
815 def _should_keep_setting(self, setting):
822 keep = (
816 keep = (
823 (setting.section, setting.key) in self._ui_settings or
817 (setting.section, setting.key) in self._ui_settings or
824 setting.section in self._svn_sections)
818 setting.section in self._svn_sections)
825 return keep
819 return keep
826
820
827 def _filter_general_settings(self, settings):
821 def _filter_general_settings(self, settings):
828 keys = ['rhodecode_{}'.format(key) for key in self.GENERAL_SETTINGS]
822 keys = ['rhodecode_{}'.format(key) for key in self.GENERAL_SETTINGS]
829 return {
823 return {
830 k: settings[k]
824 k: settings[k]
831 for k in settings if k in keys}
825 for k in settings if k in keys}
832
826
833 def _collect_all_settings(self, global_=False):
827 def _collect_all_settings(self, global_=False):
834 settings = self.global_settings if global_ else self.repo_settings
828 settings = self.global_settings if global_ else self.repo_settings
835 result = {}
829 result = {}
836
830
837 for section, key in self._ui_settings:
831 for section, key in self._ui_settings:
838 ui = settings.get_ui_by_section_and_key(section, key)
832 ui = settings.get_ui_by_section_and_key(section, key)
839 result_key = self._get_form_ui_key(section, key)
833 result_key = self._get_form_ui_key(section, key)
840
834
841 if ui:
835 if ui:
842 if section in ('hooks', 'extensions'):
836 if section in ('hooks', 'extensions'):
843 result[result_key] = ui.ui_active
837 result[result_key] = ui.ui_active
844 elif result_key in ['vcs_git_lfs_enabled']:
838 elif result_key in ['vcs_git_lfs_enabled']:
845 result[result_key] = ui.ui_active
839 result[result_key] = ui.ui_active
846 else:
840 else:
847 result[result_key] = ui.ui_value
841 result[result_key] = ui.ui_value
848
842
849 for name in self.GENERAL_SETTINGS:
843 for name in self.GENERAL_SETTINGS:
850 setting = settings.get_setting_by_name(name)
844 setting = settings.get_setting_by_name(name)
851 if setting:
845 if setting:
852 result_key = 'rhodecode_{}'.format(name)
846 result_key = 'rhodecode_{}'.format(name)
853 result[result_key] = setting.app_settings_value
847 result[result_key] = setting.app_settings_value
854
848
855 return result
849 return result
856
850
857 def _get_form_ui_key(self, section, key):
851 def _get_form_ui_key(self, section, key):
858 return '{section}_{key}'.format(
852 return '{section}_{key}'.format(
859 section=section, key=key.replace('.', '_'))
853 section=section, key=key.replace('.', '_'))
860
854
861 def _create_or_update_ui(
855 def _create_or_update_ui(
862 self, settings, section, key, value=None, active=None):
856 self, settings, section, key, value=None, active=None):
863 ui = settings.get_ui_by_section_and_key(section, key)
857 ui = settings.get_ui_by_section_and_key(section, key)
864 if not ui:
858 if not ui:
865 active = True if active is None else active
859 active = True if active is None else active
866 settings.create_ui_section_value(
860 settings.create_ui_section_value(
867 section, value, key=key, active=active)
861 section, value, key=key, active=active)
868 else:
862 else:
869 if active is not None:
863 if active is not None:
870 ui.ui_active = active
864 ui.ui_active = active
871 if value is not None:
865 if value is not None:
872 ui.ui_value = value
866 ui.ui_value = value
873 Session().add(ui)
867 Session().add(ui)
874
868
875 def _create_svn_settings(self, settings, data):
869 def _create_svn_settings(self, settings, data):
876 svn_settings = {
870 svn_settings = {
877 'new_svn_branch': self.SVN_BRANCH_SECTION,
871 'new_svn_branch': self.SVN_BRANCH_SECTION,
878 'new_svn_tag': self.SVN_TAG_SECTION
872 'new_svn_tag': self.SVN_TAG_SECTION
879 }
873 }
880 for key in svn_settings:
874 for key in svn_settings:
881 if data.get(key):
875 if data.get(key):
882 settings.create_ui_section_value(svn_settings[key], data[key])
876 settings.create_ui_section_value(svn_settings[key], data[key])
883
877
884 def _create_or_update_general_settings(self, settings, data):
878 def _create_or_update_general_settings(self, settings, data):
885 for name in self.GENERAL_SETTINGS:
879 for name in self.GENERAL_SETTINGS:
886 data_key = 'rhodecode_{}'.format(name)
880 data_key = 'rhodecode_{}'.format(name)
887 if data_key not in data:
881 if data_key not in data:
888 raise ValueError(
882 raise ValueError(
889 'The given data does not contain {} key'.format(data_key))
883 'The given data does not contain {} key'.format(data_key))
890 setting = settings.create_or_update_setting(
884 setting = settings.create_or_update_setting(
891 name, data[data_key], 'bool')
885 name, data[data_key], 'bool')
892 Session().add(setting)
886 Session().add(setting)
893
887
894 def _get_settings_keys(self, settings, data):
888 def _get_settings_keys(self, settings, data):
895 data_keys = [self._get_form_ui_key(*s) for s in settings]
889 data_keys = [self._get_form_ui_key(*s) for s in settings]
896 for data_key in data_keys:
890 for data_key in data_keys:
897 if data_key not in data:
891 if data_key not in data:
898 raise ValueError(
892 raise ValueError(
899 'The given data does not contain {} key'.format(data_key))
893 'The given data does not contain {} key'.format(data_key))
900 return data_keys
894 return data_keys
901
895
902 def create_largeobjects_dirs_if_needed(self, repo_store_path):
896 def create_largeobjects_dirs_if_needed(self, repo_store_path):
903 """
897 """
904 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
898 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
905 does a repository scan if enabled in the settings.
899 does a repository scan if enabled in the settings.
906 """
900 """
907
901
908 from rhodecode.lib.vcs.backends.hg import largefiles_store
902 from rhodecode.lib.vcs.backends.hg import largefiles_store
909 from rhodecode.lib.vcs.backends.git import lfs_store
903 from rhodecode.lib.vcs.backends.git import lfs_store
910
904
911 paths = [
905 paths = [
912 largefiles_store(repo_store_path),
906 largefiles_store(repo_store_path),
913 lfs_store(repo_store_path)]
907 lfs_store(repo_store_path)]
914
908
915 for path in paths:
909 for path in paths:
916 if os.path.isdir(path):
910 if os.path.isdir(path):
917 continue
911 continue
918 if os.path.isfile(path):
912 if os.path.isfile(path):
919 continue
913 continue
920 # not a file nor dir, we try to create it
914 # not a file nor dir, we try to create it
921 try:
915 try:
922 os.makedirs(path)
916 os.makedirs(path)
923 except Exception:
917 except Exception:
924 log.warning('Failed to create largefiles dir:%s', path)
918 log.warning('Failed to create largefiles dir:%s', path)
General Comments 0
You need to be logged in to leave comments. Login now