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