##// END OF EJS Templates
exception-handling: nicer error catching on repository creation.
marcink -
r1203:5a5d1405 stable
parent child Browse files
Show More
@@ -1,284 +1,283 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2012-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 RhodeCode task modules, containing all task that suppose to be run
23 23 by celery daemon
24 24 """
25 25
26 26
27 27 import os
28 28 import logging
29 29
30 30 from celery.task import task
31 31 from pylons import config
32 32
33 33 import rhodecode
34 34 from rhodecode.lib.celerylib import (
35 35 run_task, dbsession, __get_lockkey, LockHeld, DaemonLock,
36 36 get_session, vcsconnection, RhodecodeCeleryTask)
37 37 from rhodecode.lib.hooks_base import log_create_repository
38 38 from rhodecode.lib.rcmail.smtp_mailer import SmtpMailer
39 39 from rhodecode.lib.utils import add_cache, action_logger
40 40 from rhodecode.lib.utils2 import safe_int, str2bool
41 41 from rhodecode.model.db import Repository, User
42 42
43 43
44 44 add_cache(config) # pragma: no cover
45 45
46 46
47 47 def get_logger(cls):
48 48 if rhodecode.CELERY_ENABLED:
49 49 try:
50 50 log = cls.get_logger()
51 51 except Exception:
52 52 log = logging.getLogger(__name__)
53 53 else:
54 54 log = logging.getLogger(__name__)
55 55
56 56 return log
57 57
58 58
59 59 @task(ignore_result=True, base=RhodecodeCeleryTask)
60 60 @dbsession
61 61 def send_email(recipients, subject, body='', html_body='', email_config=None):
62 62 """
63 63 Sends an email with defined parameters from the .ini files.
64 64
65 65 :param recipients: list of recipients, it this is empty the defined email
66 66 address from field 'email_to' is used instead
67 67 :param subject: subject of the mail
68 68 :param body: body of the mail
69 69 :param html_body: html version of body
70 70 """
71 71 log = get_logger(send_email)
72 72
73 73 email_config = email_config or rhodecode.CONFIG
74 74 subject = "%s %s" % (email_config.get('email_prefix', ''), subject)
75 75 if not recipients:
76 76 # if recipients are not defined we send to email_config + all admins
77 77 admins = [
78 78 u.email for u in User.query().filter(User.admin == True).all()]
79 79 recipients = [email_config.get('email_to')] + admins
80 80
81 81 mail_server = email_config.get('smtp_server') or None
82 82 if mail_server is None:
83 83 log.error("SMTP server information missing. Sending email failed. "
84 84 "Make sure that `smtp_server` variable is configured "
85 85 "inside the .ini file")
86 86 return False
87 87
88 88 mail_from = email_config.get('app_email_from', 'RhodeCode')
89 89 user = email_config.get('smtp_username')
90 90 passwd = email_config.get('smtp_password')
91 91 mail_port = email_config.get('smtp_port')
92 92 tls = str2bool(email_config.get('smtp_use_tls'))
93 93 ssl = str2bool(email_config.get('smtp_use_ssl'))
94 94 debug = str2bool(email_config.get('debug'))
95 95 smtp_auth = email_config.get('smtp_auth')
96 96
97 97 try:
98 98 m = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth,
99 99 mail_port, ssl, tls, debug=debug)
100 100 m.send(recipients, subject, body, html_body)
101 101 except Exception:
102 102 log.exception('Mail sending failed')
103 103 return False
104 104 return True
105 105
106 106
107 107 @task(ignore_result=True, base=RhodecodeCeleryTask)
108 108 @dbsession
109 109 @vcsconnection
110 110 def create_repo(form_data, cur_user):
111 111 from rhodecode.model.repo import RepoModel
112 112 from rhodecode.model.user import UserModel
113 113 from rhodecode.model.settings import SettingsModel
114 114
115 115 log = get_logger(create_repo)
116 116 DBS = get_session()
117 117
118 118 cur_user = UserModel(DBS)._get_user(cur_user)
119 119 owner = cur_user
120 120
121 121 repo_name = form_data['repo_name']
122 122 repo_name_full = form_data['repo_name_full']
123 123 repo_type = form_data['repo_type']
124 124 description = form_data['repo_description']
125 125 private = form_data['repo_private']
126 126 clone_uri = form_data.get('clone_uri')
127 127 repo_group = safe_int(form_data['repo_group'])
128 128 landing_rev = form_data['repo_landing_rev']
129 129 copy_fork_permissions = form_data.get('copy_permissions')
130 130 copy_group_permissions = form_data.get('repo_copy_permissions')
131 131 fork_of = form_data.get('fork_parent_id')
132 132 state = form_data.get('repo_state', Repository.STATE_PENDING)
133 133
134 134 # repo creation defaults, private and repo_type are filled in form
135 135 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
136 136 enable_statistics = form_data.get(
137 137 'enable_statistics', defs.get('repo_enable_statistics'))
138 138 enable_locking = form_data.get(
139 139 'enable_locking', defs.get('repo_enable_locking'))
140 140 enable_downloads = form_data.get(
141 141 'enable_downloads', defs.get('repo_enable_downloads'))
142 142
143 143 try:
144 144 RepoModel(DBS)._create_repo(
145 145 repo_name=repo_name_full,
146 146 repo_type=repo_type,
147 147 description=description,
148 148 owner=owner,
149 149 private=private,
150 150 clone_uri=clone_uri,
151 151 repo_group=repo_group,
152 152 landing_rev=landing_rev,
153 153 fork_of=fork_of,
154 154 copy_fork_permissions=copy_fork_permissions,
155 155 copy_group_permissions=copy_group_permissions,
156 156 enable_statistics=enable_statistics,
157 157 enable_locking=enable_locking,
158 158 enable_downloads=enable_downloads,
159 159 state=state
160 160 )
161 161
162 action_logger(cur_user, 'user_created_repo',
163 repo_name_full, '', DBS)
162 action_logger(cur_user, 'user_created_repo', repo_name_full, '', DBS)
164 163 DBS.commit()
165 164
166 165 # now create this repo on Filesystem
167 166 RepoModel(DBS)._create_filesystem_repo(
168 167 repo_name=repo_name,
169 168 repo_type=repo_type,
170 169 repo_group=RepoModel(DBS)._get_repo_group(repo_group),
171 170 clone_uri=clone_uri,
172 171 )
173 172 repo = Repository.get_by_repo_name(repo_name_full)
174 173 log_create_repository(created_by=owner.username, **repo.get_dict())
175 174
176 175 # update repo commit caches initially
177 176 repo.update_commit_cache()
178 177
179 178 # set new created state
180 179 repo.set_state(Repository.STATE_CREATED)
181 180 DBS.commit()
182 except Exception as e:
183 log.warning('Exception %s occurred when creating repository, '
184 'doing cleanup...', e)
181 except Exception:
182 log.warning('Exception occurred when creating repository, '
183 'doing cleanup...', exc_info=True)
185 184 # rollback things manually !
186 185 repo = Repository.get_by_repo_name(repo_name_full)
187 186 if repo:
188 187 Repository.delete(repo.repo_id)
189 188 DBS.commit()
190 189 RepoModel(DBS)._delete_filesystem_repo(repo)
191 190 raise
192 191
193 192 # it's an odd fix to make celery fail task when exception occurs
194 193 def on_failure(self, *args, **kwargs):
195 194 pass
196 195
197 196 return True
198 197
199 198
200 199 @task(ignore_result=True, base=RhodecodeCeleryTask)
201 200 @dbsession
202 201 @vcsconnection
203 202 def create_repo_fork(form_data, cur_user):
204 203 """
205 204 Creates a fork of repository using internal VCS methods
206 205
207 206 :param form_data:
208 207 :param cur_user:
209 208 """
210 209 from rhodecode.model.repo import RepoModel
211 210 from rhodecode.model.user import UserModel
212 211
213 212 log = get_logger(create_repo_fork)
214 213 DBS = get_session()
215 214
216 215 cur_user = UserModel(DBS)._get_user(cur_user)
217 216 owner = cur_user
218 217
219 218 repo_name = form_data['repo_name'] # fork in this case
220 219 repo_name_full = form_data['repo_name_full']
221 220 repo_type = form_data['repo_type']
222 221 description = form_data['description']
223 222 private = form_data['private']
224 223 clone_uri = form_data.get('clone_uri')
225 224 repo_group = safe_int(form_data['repo_group'])
226 225 landing_rev = form_data['landing_rev']
227 226 copy_fork_permissions = form_data.get('copy_permissions')
228 227 fork_id = safe_int(form_data.get('fork_parent_id'))
229 228
230 229 try:
231 230 fork_of = RepoModel(DBS)._get_repo(fork_id)
232 231 RepoModel(DBS)._create_repo(
233 232 repo_name=repo_name_full,
234 233 repo_type=repo_type,
235 234 description=description,
236 235 owner=owner,
237 236 private=private,
238 237 clone_uri=clone_uri,
239 238 repo_group=repo_group,
240 239 landing_rev=landing_rev,
241 240 fork_of=fork_of,
242 241 copy_fork_permissions=copy_fork_permissions
243 242 )
244 243 action_logger(cur_user, 'user_forked_repo:%s' % repo_name_full,
245 244 fork_of.repo_name, '', DBS)
246 245 DBS.commit()
247 246
248 247 base_path = Repository.base_path()
249 248 source_repo_path = os.path.join(base_path, fork_of.repo_name)
250 249
251 250 # now create this repo on Filesystem
252 251 RepoModel(DBS)._create_filesystem_repo(
253 252 repo_name=repo_name,
254 253 repo_type=repo_type,
255 254 repo_group=RepoModel(DBS)._get_repo_group(repo_group),
256 255 clone_uri=source_repo_path,
257 256 )
258 257 repo = Repository.get_by_repo_name(repo_name_full)
259 258 log_create_repository(created_by=owner.username, **repo.get_dict())
260 259
261 260 # update repo commit caches initially
262 261 config = repo._config
263 262 config.set('extensions', 'largefiles', '')
264 263 repo.update_commit_cache(config=config)
265 264
266 265 # set new created state
267 266 repo.set_state(Repository.STATE_CREATED)
268 267 DBS.commit()
269 268 except Exception as e:
270 269 log.warning('Exception %s occurred when forking repository, '
271 270 'doing cleanup...', e)
272 271 # rollback things manually !
273 272 repo = Repository.get_by_repo_name(repo_name_full)
274 273 if repo:
275 274 Repository.delete(repo.repo_id)
276 275 DBS.commit()
277 276 RepoModel(DBS)._delete_filesystem_repo(repo)
278 277 raise
279 278
280 279 # it's an odd fix to make celery fail task when exception occurs
281 280 def on_failure(self, *args, **kwargs):
282 281 pass
283 282
284 283 return True
@@ -1,730 +1,731 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import hashlib
22 22 import logging
23 23 from collections import namedtuple
24 24 from functools import wraps
25 25
26 26 from rhodecode.lib import caches
27 27 from rhodecode.lib.utils2 import (
28 28 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
29 29 from rhodecode.lib.vcs.backends import base
30 30 from rhodecode.model import BaseModel
31 31 from rhodecode.model.db import (
32 32 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting)
33 33 from rhodecode.model.meta import Session
34 34
35 35
36 36 log = logging.getLogger(__name__)
37 37
38 38
39 39 UiSetting = namedtuple(
40 40 'UiSetting', ['section', 'key', 'value', 'active'])
41 41
42 42 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
43 43
44 44
45 45 class SettingNotFound(Exception):
46 46 def __init__(self):
47 47 super(SettingNotFound, self).__init__('Setting is not found')
48 48
49 49
50 50 class SettingsModel(BaseModel):
51 51 BUILTIN_HOOKS = (
52 52 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
53 53 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PULL,
54 54 RhodeCodeUi.HOOK_PRE_PULL)
55 55 HOOKS_SECTION = 'hooks'
56 56
57 57 def __init__(self, sa=None, repo=None):
58 58 self.repo = repo
59 59 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
60 60 self.SettingsDbModel = (
61 61 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
62 62 super(SettingsModel, self).__init__(sa)
63 63
64 64 def get_ui_by_key(self, key):
65 65 q = self.UiDbModel.query()
66 66 q = q.filter(self.UiDbModel.ui_key == key)
67 67 q = self._filter_by_repo(RepoRhodeCodeUi, q)
68 68 return q.scalar()
69 69
70 70 def get_ui_by_section(self, section):
71 71 q = self.UiDbModel.query()
72 72 q = q.filter(self.UiDbModel.ui_section == section)
73 73 q = self._filter_by_repo(RepoRhodeCodeUi, q)
74 74 return q.all()
75 75
76 76 def get_ui_by_section_and_key(self, section, key):
77 77 q = self.UiDbModel.query()
78 78 q = q.filter(self.UiDbModel.ui_section == section)
79 79 q = q.filter(self.UiDbModel.ui_key == key)
80 80 q = self._filter_by_repo(RepoRhodeCodeUi, q)
81 81 return q.scalar()
82 82
83 83 def get_ui(self, section=None, key=None):
84 84 q = self.UiDbModel.query()
85 85 q = self._filter_by_repo(RepoRhodeCodeUi, q)
86 86
87 87 if section:
88 88 q = q.filter(self.UiDbModel.ui_section == section)
89 89 if key:
90 90 q = q.filter(self.UiDbModel.ui_key == key)
91 91
92 92 # TODO: mikhail: add caching
93 93 result = [
94 94 UiSetting(
95 95 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
96 96 value=safe_str(r.ui_value), active=r.ui_active
97 97 )
98 98 for r in q.all()
99 99 ]
100 100 return result
101 101
102 102 def get_builtin_hooks(self):
103 103 q = self.UiDbModel.query()
104 104 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
105 105 return self._get_hooks(q)
106 106
107 107 def get_custom_hooks(self):
108 108 q = self.UiDbModel.query()
109 109 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
110 110 return self._get_hooks(q)
111 111
112 112 def create_ui_section_value(self, section, val, key=None, active=True):
113 113 new_ui = self.UiDbModel()
114 114 new_ui.ui_section = section
115 115 new_ui.ui_value = val
116 116 new_ui.ui_active = active
117 117
118 118 if self.repo:
119 119 repo = self._get_repo(self.repo)
120 120 repository_id = repo.repo_id
121 121 new_ui.repository_id = repository_id
122 122
123 123 if not key:
124 124 # keys are unique so they need appended info
125 125 if self.repo:
126 126 key = hashlib.sha1(
127 127 '{}{}{}'.format(section, val, repository_id)).hexdigest()
128 128 else:
129 129 key = hashlib.sha1('{}{}'.format(section, val)).hexdigest()
130 130
131 131 new_ui.ui_key = key
132 132
133 133 Session().add(new_ui)
134 134 return new_ui
135 135
136 136 def create_or_update_hook(self, key, value):
137 137 ui = (
138 138 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
139 139 self.UiDbModel())
140 140 ui.ui_section = self.HOOKS_SECTION
141 141 ui.ui_active = True
142 142 ui.ui_key = key
143 143 ui.ui_value = value
144 144
145 145 if self.repo:
146 146 repo = self._get_repo(self.repo)
147 147 repository_id = repo.repo_id
148 148 ui.repository_id = repository_id
149 149
150 150 Session().add(ui)
151 151 return ui
152 152
153 153 def delete_ui(self, id_):
154 154 ui = self.UiDbModel.get(id_)
155 155 if not ui:
156 156 raise SettingNotFound()
157 157 Session().delete(ui)
158 158
159 159 def get_setting_by_name(self, name):
160 160 q = self._get_settings_query()
161 161 q = q.filter(self.SettingsDbModel.app_settings_name == name)
162 162 return q.scalar()
163 163
164 164 def create_or_update_setting(
165 165 self, name, val=Optional(''), type_=Optional('unicode')):
166 166 """
167 167 Creates or updates RhodeCode setting. If updates is triggered it will
168 168 only update parameters that are explicityl set Optional instance will
169 169 be skipped
170 170
171 171 :param name:
172 172 :param val:
173 173 :param type_:
174 174 :return:
175 175 """
176 176
177 177 res = self.get_setting_by_name(name)
178 178 repo = self._get_repo(self.repo) if self.repo else None
179 179
180 180 if not res:
181 181 val = Optional.extract(val)
182 182 type_ = Optional.extract(type_)
183 183
184 184 args = (
185 185 (repo.repo_id, name, val, type_)
186 186 if repo else (name, val, type_))
187 187 res = self.SettingsDbModel(*args)
188 188
189 189 else:
190 190 if self.repo:
191 191 res.repository_id = repo.repo_id
192 192
193 193 res.app_settings_name = name
194 194 if not isinstance(type_, Optional):
195 195 # update if set
196 196 res.app_settings_type = type_
197 197 if not isinstance(val, Optional):
198 198 # update if set
199 199 res.app_settings_value = val
200 200
201 201 Session().add(res)
202 202 return res
203 203
204 204 def invalidate_settings_cache(self):
205 205 namespace = 'rhodecode_settings'
206 206 cache_manager = caches.get_cache_manager('sql_cache_short', namespace)
207 207 caches.clear_cache_manager(cache_manager)
208 208
209 209 def get_all_settings(self, cache=False):
210 210 def _compute():
211 211 q = self._get_settings_query()
212 212 if not q:
213 213 raise Exception('Could not get application settings !')
214 214
215 215 settings = {
216 216 'rhodecode_' + result.app_settings_name: result.app_settings_value
217 217 for result in q
218 218 }
219 219 return settings
220 220
221 221 if cache:
222 222 log.debug('Fetching app settings using cache')
223 223 repo = self._get_repo(self.repo) if self.repo else None
224 224 namespace = 'rhodecode_settings'
225 225 cache_manager = caches.get_cache_manager(
226 226 'sql_cache_short', namespace)
227 227 _cache_key = (
228 228 "get_repo_{}_settings".format(repo.repo_id)
229 229 if repo else "get_app_settings")
230 230
231 231 return cache_manager.get(_cache_key, createfunc=_compute)
232 232
233 233 else:
234 234 return _compute()
235 235
236 236 def get_auth_settings(self):
237 237 q = self._get_settings_query()
238 238 q = q.filter(
239 239 self.SettingsDbModel.app_settings_name.startswith('auth_'))
240 240 rows = q.all()
241 241 auth_settings = {
242 242 row.app_settings_name: row.app_settings_value for row in rows}
243 243 return auth_settings
244 244
245 245 def get_auth_plugins(self):
246 246 auth_plugins = self.get_setting_by_name("auth_plugins")
247 247 return auth_plugins.app_settings_value
248 248
249 249 def get_default_repo_settings(self, strip_prefix=False):
250 250 q = self._get_settings_query()
251 251 q = q.filter(
252 252 self.SettingsDbModel.app_settings_name.startswith('default_'))
253 253 rows = q.all()
254 254
255 255 result = {}
256 256 for row in rows:
257 257 key = row.app_settings_name
258 258 if strip_prefix:
259 259 key = remove_prefix(key, prefix='default_')
260 260 result.update({key: row.app_settings_value})
261 261 return result
262 262
263 263 def get_repo(self):
264 264 repo = self._get_repo(self.repo)
265 265 if not repo:
266 266 raise Exception(
267 'Repository {} cannot be found'.format(self.repo))
267 'Repository `{}` cannot be found inside the database'.format(
268 self.repo))
268 269 return repo
269 270
270 271 def _filter_by_repo(self, model, query):
271 272 if self.repo:
272 273 repo = self.get_repo()
273 274 query = query.filter(model.repository_id == repo.repo_id)
274 275 return query
275 276
276 277 def _get_hooks(self, query):
277 278 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
278 279 query = self._filter_by_repo(RepoRhodeCodeUi, query)
279 280 return query.all()
280 281
281 282 def _get_settings_query(self):
282 283 q = self.SettingsDbModel.query()
283 284 return self._filter_by_repo(RepoRhodeCodeSetting, q)
284 285
285 286 def list_enabled_social_plugins(self, settings):
286 287 enabled = []
287 288 for plug in SOCIAL_PLUGINS_LIST:
288 289 if str2bool(settings.get('rhodecode_auth_{}_enabled'.format(plug)
289 290 )):
290 291 enabled.append(plug)
291 292 return enabled
292 293
293 294
294 295 def assert_repo_settings(func):
295 296 @wraps(func)
296 297 def _wrapper(self, *args, **kwargs):
297 298 if not self.repo_settings:
298 299 raise Exception('Repository is not specified')
299 300 return func(self, *args, **kwargs)
300 301 return _wrapper
301 302
302 303
303 304 class IssueTrackerSettingsModel(object):
304 305 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
305 306 SETTINGS_PREFIX = 'issuetracker_'
306 307
307 308 def __init__(self, sa=None, repo=None):
308 309 self.global_settings = SettingsModel(sa=sa)
309 310 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
310 311
311 312 @property
312 313 def inherit_global_settings(self):
313 314 if not self.repo_settings:
314 315 return True
315 316 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
316 317 return setting.app_settings_value if setting else True
317 318
318 319 @inherit_global_settings.setter
319 320 def inherit_global_settings(self, value):
320 321 if self.repo_settings:
321 322 settings = self.repo_settings.create_or_update_setting(
322 323 self.INHERIT_SETTINGS, value, type_='bool')
323 324 Session().add(settings)
324 325
325 326 def _get_keyname(self, key, uid, prefix=''):
326 327 return '{0}{1}{2}_{3}'.format(
327 328 prefix, self.SETTINGS_PREFIX, key, uid)
328 329
329 330 def _make_dict_for_settings(self, qs):
330 331 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
331 332
332 333 issuetracker_entries = {}
333 334 # create keys
334 335 for k, v in qs.items():
335 336 if k.startswith(prefix_match):
336 337 uid = k[len(prefix_match):]
337 338 issuetracker_entries[uid] = None
338 339
339 340 # populate
340 341 for uid in issuetracker_entries:
341 342 issuetracker_entries[uid] = AttributeDict({
342 343 'pat': qs.get(self._get_keyname('pat', uid, 'rhodecode_')),
343 344 'url': qs.get(self._get_keyname('url', uid, 'rhodecode_')),
344 345 'pref': qs.get(self._get_keyname('pref', uid, 'rhodecode_')),
345 346 'desc': qs.get(self._get_keyname('desc', uid, 'rhodecode_')),
346 347 })
347 348 return issuetracker_entries
348 349
349 350 def get_global_settings(self, cache=False):
350 351 """
351 352 Returns list of global issue tracker settings
352 353 """
353 354 defaults = self.global_settings.get_all_settings(cache=cache)
354 355 settings = self._make_dict_for_settings(defaults)
355 356 return settings
356 357
357 358 def get_repo_settings(self, cache=False):
358 359 """
359 360 Returns list of issue tracker settings per repository
360 361 """
361 362 if not self.repo_settings:
362 363 raise Exception('Repository is not specified')
363 364 all_settings = self.repo_settings.get_all_settings(cache=cache)
364 365 settings = self._make_dict_for_settings(all_settings)
365 366 return settings
366 367
367 368 def get_settings(self, cache=False):
368 369 if self.inherit_global_settings:
369 370 return self.get_global_settings(cache=cache)
370 371 else:
371 372 return self.get_repo_settings(cache=cache)
372 373
373 374 def delete_entries(self, uid):
374 375 if self.repo_settings:
375 376 all_patterns = self.get_repo_settings()
376 377 settings_model = self.repo_settings
377 378 else:
378 379 all_patterns = self.get_global_settings()
379 380 settings_model = self.global_settings
380 381 entries = all_patterns.get(uid)
381 382
382 383 for del_key in entries:
383 384 setting_name = self._get_keyname(del_key, uid)
384 385 entry = settings_model.get_setting_by_name(setting_name)
385 386 if entry:
386 387 Session().delete(entry)
387 388
388 389 Session().commit()
389 390
390 391 def create_or_update_setting(
391 392 self, name, val=Optional(''), type_=Optional('unicode')):
392 393 if self.repo_settings:
393 394 setting = self.repo_settings.create_or_update_setting(
394 395 name, val, type_)
395 396 else:
396 397 setting = self.global_settings.create_or_update_setting(
397 398 name, val, type_)
398 399 return setting
399 400
400 401
401 402 class VcsSettingsModel(object):
402 403
403 404 INHERIT_SETTINGS = 'inherit_vcs_settings'
404 405 GENERAL_SETTINGS = (
405 406 'use_outdated_comments',
406 407 'pr_merge_enabled',
407 408 'hg_use_rebase_for_merging')
408 409
409 410 HOOKS_SETTINGS = (
410 411 ('hooks', 'changegroup.repo_size'),
411 412 ('hooks', 'changegroup.push_logger'),
412 413 ('hooks', 'outgoing.pull_logger'))
413 414 HG_SETTINGS = (
414 415 ('extensions', 'largefiles'),
415 416 ('phases', 'publish'))
416 417 GLOBAL_HG_SETTINGS = (
417 418 ('extensions', 'largefiles'),
418 419 ('phases', 'publish'),
419 420 ('extensions', 'hgsubversion'))
420 421 GLOBAL_SVN_SETTINGS = (
421 422 ('vcs_svn_proxy', 'http_requests_enabled'),
422 423 ('vcs_svn_proxy', 'http_server_url'))
423 424
424 425 SVN_BRANCH_SECTION = 'vcs_svn_branch'
425 426 SVN_TAG_SECTION = 'vcs_svn_tag'
426 427 SSL_SETTING = ('web', 'push_ssl')
427 428 PATH_SETTING = ('paths', '/')
428 429
429 430 def __init__(self, sa=None, repo=None):
430 431 self.global_settings = SettingsModel(sa=sa)
431 432 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
432 433 self._ui_settings = self.HG_SETTINGS + self.HOOKS_SETTINGS
433 434 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
434 435
435 436 @property
436 437 @assert_repo_settings
437 438 def inherit_global_settings(self):
438 439 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
439 440 return setting.app_settings_value if setting else True
440 441
441 442 @inherit_global_settings.setter
442 443 @assert_repo_settings
443 444 def inherit_global_settings(self, value):
444 445 self.repo_settings.create_or_update_setting(
445 446 self.INHERIT_SETTINGS, value, type_='bool')
446 447
447 448 def get_global_svn_branch_patterns(self):
448 449 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
449 450
450 451 @assert_repo_settings
451 452 def get_repo_svn_branch_patterns(self):
452 453 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
453 454
454 455 def get_global_svn_tag_patterns(self):
455 456 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
456 457
457 458 @assert_repo_settings
458 459 def get_repo_svn_tag_patterns(self):
459 460 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
460 461
461 462 def get_global_settings(self):
462 463 return self._collect_all_settings(global_=True)
463 464
464 465 @assert_repo_settings
465 466 def get_repo_settings(self):
466 467 return self._collect_all_settings(global_=False)
467 468
468 469 @assert_repo_settings
469 470 def create_or_update_repo_settings(
470 471 self, data, inherit_global_settings=False):
471 472 from rhodecode.model.scm import ScmModel
472 473
473 474 self.inherit_global_settings = inherit_global_settings
474 475
475 476 repo = self.repo_settings.get_repo()
476 477 if not inherit_global_settings:
477 478 if repo.repo_type == 'svn':
478 479 self.create_repo_svn_settings(data)
479 480 else:
480 481 self.create_or_update_repo_hook_settings(data)
481 482 self.create_or_update_repo_pr_settings(data)
482 483
483 484 if repo.repo_type == 'hg':
484 485 self.create_or_update_repo_hg_settings(data)
485 486
486 487 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
487 488
488 489 @assert_repo_settings
489 490 def create_or_update_repo_hook_settings(self, data):
490 491 for section, key in self.HOOKS_SETTINGS:
491 492 data_key = self._get_form_ui_key(section, key)
492 493 if data_key not in data:
493 494 raise ValueError(
494 495 'The given data does not contain {} key'.format(data_key))
495 496
496 497 active = data.get(data_key)
497 498 repo_setting = self.repo_settings.get_ui_by_section_and_key(
498 499 section, key)
499 500 if not repo_setting:
500 501 global_setting = self.global_settings.\
501 502 get_ui_by_section_and_key(section, key)
502 503 self.repo_settings.create_ui_section_value(
503 504 section, global_setting.ui_value, key=key, active=active)
504 505 else:
505 506 repo_setting.ui_active = active
506 507 Session().add(repo_setting)
507 508
508 509 def update_global_hook_settings(self, data):
509 510 for section, key in self.HOOKS_SETTINGS:
510 511 data_key = self._get_form_ui_key(section, key)
511 512 if data_key not in data:
512 513 raise ValueError(
513 514 'The given data does not contain {} key'.format(data_key))
514 515 active = data.get(data_key)
515 516 repo_setting = self.global_settings.get_ui_by_section_and_key(
516 517 section, key)
517 518 repo_setting.ui_active = active
518 519 Session().add(repo_setting)
519 520
520 521 @assert_repo_settings
521 522 def create_or_update_repo_pr_settings(self, data):
522 523 return self._create_or_update_general_settings(
523 524 self.repo_settings, data)
524 525
525 526 def create_or_update_global_pr_settings(self, data):
526 527 return self._create_or_update_general_settings(
527 528 self.global_settings, data)
528 529
529 530 @assert_repo_settings
530 531 def create_repo_svn_settings(self, data):
531 532 return self._create_svn_settings(self.repo_settings, data)
532 533
533 534 @assert_repo_settings
534 535 def create_or_update_repo_hg_settings(self, data):
535 536 largefiles, phases = self.HG_SETTINGS
536 537 largefiles_key, phases_key = self._get_settings_keys(
537 538 self.HG_SETTINGS, data)
538 539 self._create_or_update_ui(
539 540 self.repo_settings, *largefiles, value='',
540 541 active=data[largefiles_key])
541 542 self._create_or_update_ui(
542 543 self.repo_settings, *phases, value=safe_str(data[phases_key]))
543 544
544 545 def create_or_update_global_hg_settings(self, data):
545 546 largefiles, phases, hgsubversion = self.GLOBAL_HG_SETTINGS
546 547 largefiles_key, phases_key, subversion_key = self._get_settings_keys(
547 548 self.GLOBAL_HG_SETTINGS, data)
548 549 self._create_or_update_ui(
549 550 self.global_settings, *largefiles, value='',
550 551 active=data[largefiles_key])
551 552 self._create_or_update_ui(
552 553 self.global_settings, *phases, value=safe_str(data[phases_key]))
553 554 self._create_or_update_ui(
554 555 self.global_settings, *hgsubversion, active=data[subversion_key])
555 556
556 557 def create_or_update_global_svn_settings(self, data):
557 558 # branch/tags patterns
558 559 self._create_svn_settings(self.global_settings, data)
559 560
560 561 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
561 562 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
562 563 self.GLOBAL_SVN_SETTINGS, data)
563 564
564 565 self._create_or_update_ui(
565 566 self.global_settings, *http_requests_enabled,
566 567 value=safe_str(data[http_requests_enabled_key]))
567 568 self._create_or_update_ui(
568 569 self.global_settings, *http_server_url,
569 570 value=data[http_server_url_key])
570 571
571 572 def update_global_ssl_setting(self, value):
572 573 self._create_or_update_ui(
573 574 self.global_settings, *self.SSL_SETTING, value=value)
574 575
575 576 def update_global_path_setting(self, value):
576 577 self._create_or_update_ui(
577 578 self.global_settings, *self.PATH_SETTING, value=value)
578 579
579 580 @assert_repo_settings
580 581 def delete_repo_svn_pattern(self, id_):
581 582 self.repo_settings.delete_ui(id_)
582 583
583 584 def delete_global_svn_pattern(self, id_):
584 585 self.global_settings.delete_ui(id_)
585 586
586 587 @assert_repo_settings
587 588 def get_repo_ui_settings(self, section=None, key=None):
588 589 global_uis = self.global_settings.get_ui(section, key)
589 590 repo_uis = self.repo_settings.get_ui(section, key)
590 591 filtered_repo_uis = self._filter_ui_settings(repo_uis)
591 592 filtered_repo_uis_keys = [
592 593 (s.section, s.key) for s in filtered_repo_uis]
593 594
594 595 def _is_global_ui_filtered(ui):
595 596 return (
596 597 (ui.section, ui.key) in filtered_repo_uis_keys
597 598 or ui.section in self._svn_sections)
598 599
599 600 filtered_global_uis = [
600 601 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
601 602
602 603 return filtered_global_uis + filtered_repo_uis
603 604
604 605 def get_global_ui_settings(self, section=None, key=None):
605 606 return self.global_settings.get_ui(section, key)
606 607
607 608 def get_ui_settings_as_config_obj(self, section=None, key=None):
608 609 config = base.Config()
609 610
610 611 ui_settings = self.get_ui_settings(section=section, key=key)
611 612
612 613 for entry in ui_settings:
613 614 config.set(entry.section, entry.key, entry.value)
614 615
615 616 return config
616 617
617 618 def get_ui_settings(self, section=None, key=None):
618 619 if not self.repo_settings or self.inherit_global_settings:
619 620 return self.get_global_ui_settings(section, key)
620 621 else:
621 622 return self.get_repo_ui_settings(section, key)
622 623
623 624 def get_svn_patterns(self, section=None):
624 625 if not self.repo_settings:
625 626 return self.get_global_ui_settings(section)
626 627 else:
627 628 return self.get_repo_ui_settings(section)
628 629
629 630 @assert_repo_settings
630 631 def get_repo_general_settings(self):
631 632 global_settings = self.global_settings.get_all_settings()
632 633 repo_settings = self.repo_settings.get_all_settings()
633 634 filtered_repo_settings = self._filter_general_settings(repo_settings)
634 635 global_settings.update(filtered_repo_settings)
635 636 return global_settings
636 637
637 638 def get_global_general_settings(self):
638 639 return self.global_settings.get_all_settings()
639 640
640 641 def get_general_settings(self):
641 642 if not self.repo_settings or self.inherit_global_settings:
642 643 return self.get_global_general_settings()
643 644 else:
644 645 return self.get_repo_general_settings()
645 646
646 647 def get_repos_location(self):
647 648 return self.global_settings.get_ui_by_key('/').ui_value
648 649
649 650 def _filter_ui_settings(self, settings):
650 651 filtered_settings = [
651 652 s for s in settings if self._should_keep_setting(s)]
652 653 return filtered_settings
653 654
654 655 def _should_keep_setting(self, setting):
655 656 keep = (
656 657 (setting.section, setting.key) in self._ui_settings or
657 658 setting.section in self._svn_sections)
658 659 return keep
659 660
660 661 def _filter_general_settings(self, settings):
661 662 keys = ['rhodecode_{}'.format(key) for key in self.GENERAL_SETTINGS]
662 663 return {
663 664 k: settings[k]
664 665 for k in settings if k in keys}
665 666
666 667 def _collect_all_settings(self, global_=False):
667 668 settings = self.global_settings if global_ else self.repo_settings
668 669 result = {}
669 670
670 671 for section, key in self._ui_settings:
671 672 ui = settings.get_ui_by_section_and_key(section, key)
672 673 result_key = self._get_form_ui_key(section, key)
673 674 if ui:
674 675 if section in ('hooks', 'extensions'):
675 676 result[result_key] = ui.ui_active
676 677 else:
677 678 result[result_key] = ui.ui_value
678 679
679 680 for name in self.GENERAL_SETTINGS:
680 681 setting = settings.get_setting_by_name(name)
681 682 if setting:
682 683 result_key = 'rhodecode_{}'.format(name)
683 684 result[result_key] = setting.app_settings_value
684 685
685 686 return result
686 687
687 688 def _get_form_ui_key(self, section, key):
688 689 return '{section}_{key}'.format(
689 690 section=section, key=key.replace('.', '_'))
690 691
691 692 def _create_or_update_ui(
692 693 self, settings, section, key, value=None, active=None):
693 694 ui = settings.get_ui_by_section_and_key(section, key)
694 695 if not ui:
695 696 active = True if active is None else active
696 697 settings.create_ui_section_value(
697 698 section, value, key=key, active=active)
698 699 else:
699 700 if active is not None:
700 701 ui.ui_active = active
701 702 if value is not None:
702 703 ui.ui_value = value
703 704 Session().add(ui)
704 705
705 706 def _create_svn_settings(self, settings, data):
706 707 svn_settings = {
707 708 'new_svn_branch': self.SVN_BRANCH_SECTION,
708 709 'new_svn_tag': self.SVN_TAG_SECTION
709 710 }
710 711 for key in svn_settings:
711 712 if data.get(key):
712 713 settings.create_ui_section_value(svn_settings[key], data[key])
713 714
714 715 def _create_or_update_general_settings(self, settings, data):
715 716 for name in self.GENERAL_SETTINGS:
716 717 data_key = 'rhodecode_{}'.format(name)
717 718 if data_key not in data:
718 719 raise ValueError(
719 720 'The given data does not contain {} key'.format(data_key))
720 721 setting = settings.create_or_update_setting(
721 722 name, data[data_key], 'bool')
722 723 Session().add(setting)
723 724
724 725 def _get_settings_keys(self, settings, data):
725 726 data_keys = [self._get_form_ui_key(*s) for s in settings]
726 727 for data_key in data_keys:
727 728 if data_key not in data:
728 729 raise ValueError(
729 730 'The given data does not contain {} key'.format(data_key))
730 731 return data_keys
General Comments 0
You need to be logged in to leave comments. Login now