##// END OF EJS Templates
caches: use process aware settings cache with proper invalidation.
marcink -
r2937:23a83d11 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

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