##// END OF EJS Templates
repo-settings: ensure deletion on repo settings model validate...
ergo -
r2180:d1b66400 default
parent child Browse files
Show More
@@ -1,814 +1,821 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 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 24 from collections import namedtuple
25 25 from functools import wraps
26 26
27 27 from rhodecode.lib import caches
28 28 from rhodecode.lib.utils2 import (
29 29 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
30 30 from rhodecode.lib.vcs.backends import base
31 31 from rhodecode.model import BaseModel
32 32 from rhodecode.model.db import (
33 33 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting)
34 34 from rhodecode.model.meta import Session
35 35
36 36
37 37 log = logging.getLogger(__name__)
38 38
39 39
40 40 UiSetting = namedtuple(
41 41 'UiSetting', ['section', 'key', 'value', 'active'])
42 42
43 43 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
44 44
45 45
46 46 class SettingNotFound(Exception):
47 def __init__(self):
48 super(SettingNotFound, self).__init__('Setting is not found')
47 def __init__(self, setting_id):
48 msg = 'Setting `{}` is not found'.format(setting_id)
49 super(SettingNotFound, self).__init__(msg)
49 50
50 51
51 52 class SettingsModel(BaseModel):
52 53 BUILTIN_HOOKS = (
53 54 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
54 55 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
55 56 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL,
56 57 RhodeCodeUi.HOOK_PUSH_KEY,)
57 58 HOOKS_SECTION = 'hooks'
58 59
59 60 def __init__(self, sa=None, repo=None):
60 61 self.repo = repo
61 62 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
62 63 self.SettingsDbModel = (
63 64 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
64 65 super(SettingsModel, self).__init__(sa)
65 66
66 67 def get_ui_by_key(self, key):
67 68 q = self.UiDbModel.query()
68 69 q = q.filter(self.UiDbModel.ui_key == key)
69 70 q = self._filter_by_repo(RepoRhodeCodeUi, q)
70 71 return q.scalar()
71 72
72 73 def get_ui_by_section(self, section):
73 74 q = self.UiDbModel.query()
74 75 q = q.filter(self.UiDbModel.ui_section == section)
75 76 q = self._filter_by_repo(RepoRhodeCodeUi, q)
76 77 return q.all()
77 78
78 79 def get_ui_by_section_and_key(self, section, key):
79 80 q = self.UiDbModel.query()
80 81 q = q.filter(self.UiDbModel.ui_section == section)
81 82 q = q.filter(self.UiDbModel.ui_key == key)
82 83 q = self._filter_by_repo(RepoRhodeCodeUi, q)
83 84 return q.scalar()
84 85
85 86 def get_ui(self, section=None, key=None):
86 87 q = self.UiDbModel.query()
87 88 q = self._filter_by_repo(RepoRhodeCodeUi, q)
88 89
89 90 if section:
90 91 q = q.filter(self.UiDbModel.ui_section == section)
91 92 if key:
92 93 q = q.filter(self.UiDbModel.ui_key == key)
93 94
94 95 # TODO: mikhail: add caching
95 96 result = [
96 97 UiSetting(
97 98 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
98 99 value=safe_str(r.ui_value), active=r.ui_active
99 100 )
100 101 for r in q.all()
101 102 ]
102 103 return result
103 104
104 105 def get_builtin_hooks(self):
105 106 q = self.UiDbModel.query()
106 107 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
107 108 return self._get_hooks(q)
108 109
109 110 def get_custom_hooks(self):
110 111 q = self.UiDbModel.query()
111 112 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
112 113 return self._get_hooks(q)
113 114
114 115 def create_ui_section_value(self, section, val, key=None, active=True):
115 116 new_ui = self.UiDbModel()
116 117 new_ui.ui_section = section
117 118 new_ui.ui_value = val
118 119 new_ui.ui_active = active
119 120
120 121 if self.repo:
121 122 repo = self._get_repo(self.repo)
122 123 repository_id = repo.repo_id
123 124 new_ui.repository_id = repository_id
124 125
125 126 if not key:
126 127 # keys are unique so they need appended info
127 128 if self.repo:
128 129 key = hashlib.sha1(
129 130 '{}{}{}'.format(section, val, repository_id)).hexdigest()
130 131 else:
131 132 key = hashlib.sha1('{}{}'.format(section, val)).hexdigest()
132 133
133 134 new_ui.ui_key = key
134 135
135 136 Session().add(new_ui)
136 137 return new_ui
137 138
138 139 def create_or_update_hook(self, key, value):
139 140 ui = (
140 141 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
141 142 self.UiDbModel())
142 143 ui.ui_section = self.HOOKS_SECTION
143 144 ui.ui_active = True
144 145 ui.ui_key = key
145 146 ui.ui_value = value
146 147
147 148 if self.repo:
148 149 repo = self._get_repo(self.repo)
149 150 repository_id = repo.repo_id
150 151 ui.repository_id = repository_id
151 152
152 153 Session().add(ui)
153 154 return ui
154 155
155 156 def delete_ui(self, id_):
156 157 ui = self.UiDbModel.get(id_)
157 158 if not ui:
158 raise SettingNotFound()
159 raise SettingNotFound(id_)
159 160 Session().delete(ui)
160 161
161 162 def get_setting_by_name(self, name):
162 163 q = self._get_settings_query()
163 164 q = q.filter(self.SettingsDbModel.app_settings_name == name)
164 165 return q.scalar()
165 166
166 167 def create_or_update_setting(
167 168 self, name, val=Optional(''), type_=Optional('unicode')):
168 169 """
169 170 Creates or updates RhodeCode setting. If updates is triggered it will
170 171 only update parameters that are explicityl set Optional instance will
171 172 be skipped
172 173
173 174 :param name:
174 175 :param val:
175 176 :param type_:
176 177 :return:
177 178 """
178 179
179 180 res = self.get_setting_by_name(name)
180 181 repo = self._get_repo(self.repo) if self.repo else None
181 182
182 183 if not res:
183 184 val = Optional.extract(val)
184 185 type_ = Optional.extract(type_)
185 186
186 187 args = (
187 188 (repo.repo_id, name, val, type_)
188 189 if repo else (name, val, type_))
189 190 res = self.SettingsDbModel(*args)
190 191
191 192 else:
192 193 if self.repo:
193 194 res.repository_id = repo.repo_id
194 195
195 196 res.app_settings_name = name
196 197 if not isinstance(type_, Optional):
197 198 # update if set
198 199 res.app_settings_type = type_
199 200 if not isinstance(val, Optional):
200 201 # update if set
201 202 res.app_settings_value = val
202 203
203 204 Session().add(res)
204 205 return res
205 206
206 207 def invalidate_settings_cache(self):
207 208 namespace = 'rhodecode_settings'
208 209 cache_manager = caches.get_cache_manager('sql_cache_short', namespace)
209 210 caches.clear_cache_manager(cache_manager)
210 211
211 212 def get_all_settings(self, cache=False):
212 213
213 214 def _compute():
214 215 q = self._get_settings_query()
215 216 if not q:
216 217 raise Exception('Could not get application settings !')
217 218
218 219 settings = {
219 220 'rhodecode_' + result.app_settings_name: result.app_settings_value
220 221 for result in q
221 222 }
222 223 return settings
223 224
224 225 if cache:
225 226 log.debug('Fetching app settings using cache')
226 227 repo = self._get_repo(self.repo) if self.repo else None
227 228 namespace = 'rhodecode_settings'
228 229 cache_manager = caches.get_cache_manager(
229 230 'sql_cache_short', namespace)
230 231 _cache_key = (
231 232 "get_repo_{}_settings".format(repo.repo_id)
232 233 if repo else "get_app_settings")
233 234
234 235 return cache_manager.get(_cache_key, createfunc=_compute)
235 236
236 237 else:
237 238 return _compute()
238 239
239 240 def get_auth_settings(self):
240 241 q = self._get_settings_query()
241 242 q = q.filter(
242 243 self.SettingsDbModel.app_settings_name.startswith('auth_'))
243 244 rows = q.all()
244 245 auth_settings = {
245 246 row.app_settings_name: row.app_settings_value for row in rows}
246 247 return auth_settings
247 248
248 249 def get_auth_plugins(self):
249 250 auth_plugins = self.get_setting_by_name("auth_plugins")
250 251 return auth_plugins.app_settings_value
251 252
252 253 def get_default_repo_settings(self, strip_prefix=False):
253 254 q = self._get_settings_query()
254 255 q = q.filter(
255 256 self.SettingsDbModel.app_settings_name.startswith('default_'))
256 257 rows = q.all()
257 258
258 259 result = {}
259 260 for row in rows:
260 261 key = row.app_settings_name
261 262 if strip_prefix:
262 263 key = remove_prefix(key, prefix='default_')
263 264 result.update({key: row.app_settings_value})
264 265 return result
265 266
266 267 def get_repo(self):
267 268 repo = self._get_repo(self.repo)
268 269 if not repo:
269 270 raise Exception(
270 271 'Repository `{}` cannot be found inside the database'.format(
271 272 self.repo))
272 273 return repo
273 274
274 275 def _filter_by_repo(self, model, query):
275 276 if self.repo:
276 277 repo = self.get_repo()
277 278 query = query.filter(model.repository_id == repo.repo_id)
278 279 return query
279 280
280 281 def _get_hooks(self, query):
281 282 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
282 283 query = self._filter_by_repo(RepoRhodeCodeUi, query)
283 284 return query.all()
284 285
285 286 def _get_settings_query(self):
286 287 q = self.SettingsDbModel.query()
287 288 return self._filter_by_repo(RepoRhodeCodeSetting, q)
288 289
289 290 def list_enabled_social_plugins(self, settings):
290 291 enabled = []
291 292 for plug in SOCIAL_PLUGINS_LIST:
292 293 if str2bool(settings.get('rhodecode_auth_{}_enabled'.format(plug)
293 294 )):
294 295 enabled.append(plug)
295 296 return enabled
296 297
297 298
298 299 def assert_repo_settings(func):
299 300 @wraps(func)
300 301 def _wrapper(self, *args, **kwargs):
301 302 if not self.repo_settings:
302 303 raise Exception('Repository is not specified')
303 304 return func(self, *args, **kwargs)
304 305 return _wrapper
305 306
306 307
307 308 class IssueTrackerSettingsModel(object):
308 309 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
309 310 SETTINGS_PREFIX = 'issuetracker_'
310 311
311 312 def __init__(self, sa=None, repo=None):
312 313 self.global_settings = SettingsModel(sa=sa)
313 314 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
314 315
315 316 @property
316 317 def inherit_global_settings(self):
317 318 if not self.repo_settings:
318 319 return True
319 320 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
320 321 return setting.app_settings_value if setting else True
321 322
322 323 @inherit_global_settings.setter
323 324 def inherit_global_settings(self, value):
324 325 if self.repo_settings:
325 326 settings = self.repo_settings.create_or_update_setting(
326 327 self.INHERIT_SETTINGS, value, type_='bool')
327 328 Session().add(settings)
328 329
329 330 def _get_keyname(self, key, uid, prefix=''):
330 331 return '{0}{1}{2}_{3}'.format(
331 332 prefix, self.SETTINGS_PREFIX, key, uid)
332 333
333 334 def _make_dict_for_settings(self, qs):
334 335 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
335 336
336 337 issuetracker_entries = {}
337 338 # create keys
338 339 for k, v in qs.items():
339 340 if k.startswith(prefix_match):
340 341 uid = k[len(prefix_match):]
341 342 issuetracker_entries[uid] = None
342 343
343 344 # populate
344 345 for uid in issuetracker_entries:
345 346 issuetracker_entries[uid] = AttributeDict({
346 347 'pat': qs.get(self._get_keyname('pat', uid, 'rhodecode_')),
347 348 'url': qs.get(self._get_keyname('url', uid, 'rhodecode_')),
348 349 'pref': qs.get(self._get_keyname('pref', uid, 'rhodecode_')),
349 350 'desc': qs.get(self._get_keyname('desc', uid, 'rhodecode_')),
350 351 })
351 352 return issuetracker_entries
352 353
353 354 def get_global_settings(self, cache=False):
354 355 """
355 356 Returns list of global issue tracker settings
356 357 """
357 358 defaults = self.global_settings.get_all_settings(cache=cache)
358 359 settings = self._make_dict_for_settings(defaults)
359 360 return settings
360 361
361 362 def get_repo_settings(self, cache=False):
362 363 """
363 364 Returns list of issue tracker settings per repository
364 365 """
365 366 if not self.repo_settings:
366 367 raise Exception('Repository is not specified')
367 368 all_settings = self.repo_settings.get_all_settings(cache=cache)
368 369 settings = self._make_dict_for_settings(all_settings)
369 370 return settings
370 371
371 372 def get_settings(self, cache=False):
372 373 if self.inherit_global_settings:
373 374 return self.get_global_settings(cache=cache)
374 375 else:
375 376 return self.get_repo_settings(cache=cache)
376 377
377 378 def delete_entries(self, uid):
378 379 if self.repo_settings:
379 380 all_patterns = self.get_repo_settings()
380 381 settings_model = self.repo_settings
381 382 else:
382 383 all_patterns = self.get_global_settings()
383 384 settings_model = self.global_settings
384 385 entries = all_patterns.get(uid)
385 386
386 387 for del_key in entries:
387 388 setting_name = self._get_keyname(del_key, uid)
388 389 entry = settings_model.get_setting_by_name(setting_name)
389 390 if entry:
390 391 Session().delete(entry)
391 392
392 393 Session().commit()
393 394
394 395 def create_or_update_setting(
395 396 self, name, val=Optional(''), type_=Optional('unicode')):
396 397 if self.repo_settings:
397 398 setting = self.repo_settings.create_or_update_setting(
398 399 name, val, type_)
399 400 else:
400 401 setting = self.global_settings.create_or_update_setting(
401 402 name, val, type_)
402 403 return setting
403 404
404 405
405 406 class VcsSettingsModel(object):
406 407
407 408 INHERIT_SETTINGS = 'inherit_vcs_settings'
408 409 GENERAL_SETTINGS = (
409 410 'use_outdated_comments',
410 411 'pr_merge_enabled',
411 412 'hg_use_rebase_for_merging',
412 413 'hg_close_branch_before_merging',
413 414 'git_use_rebase_for_merging',
414 415 'git_close_branch_before_merging')
415 416
416 417 HOOKS_SETTINGS = (
417 418 ('hooks', 'changegroup.repo_size'),
418 419 ('hooks', 'changegroup.push_logger'),
419 420 ('hooks', 'outgoing.pull_logger'),)
420 421 HG_SETTINGS = (
421 422 ('extensions', 'largefiles'),
422 423 ('phases', 'publish'),
423 424 ('extensions', 'evolve'),)
424 425 GIT_SETTINGS = (
425 426 ('vcs_git_lfs', 'enabled'),)
426 427 GLOBAL_HG_SETTINGS = (
427 428 ('extensions', 'largefiles'),
428 429 ('largefiles', 'usercache'),
429 430 ('phases', 'publish'),
430 431 ('extensions', 'hgsubversion'),
431 432 ('extensions', 'evolve'),)
432 433 GLOBAL_GIT_SETTINGS = (
433 434 ('vcs_git_lfs', 'enabled'),
434 435 ('vcs_git_lfs', 'store_location'))
435 436 GLOBAL_SVN_SETTINGS = (
436 437 ('vcs_svn_proxy', 'http_requests_enabled'),
437 438 ('vcs_svn_proxy', 'http_server_url'))
438 439
439 440 SVN_BRANCH_SECTION = 'vcs_svn_branch'
440 441 SVN_TAG_SECTION = 'vcs_svn_tag'
441 442 SSL_SETTING = ('web', 'push_ssl')
442 443 PATH_SETTING = ('paths', '/')
443 444
444 445 def __init__(self, sa=None, repo=None):
445 446 self.global_settings = SettingsModel(sa=sa)
446 447 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
447 448 self._ui_settings = (
448 449 self.HG_SETTINGS + self.GIT_SETTINGS + self.HOOKS_SETTINGS)
449 450 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
450 451
451 452 @property
452 453 @assert_repo_settings
453 454 def inherit_global_settings(self):
454 455 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
455 456 return setting.app_settings_value if setting else True
456 457
457 458 @inherit_global_settings.setter
458 459 @assert_repo_settings
459 460 def inherit_global_settings(self, value):
460 461 self.repo_settings.create_or_update_setting(
461 462 self.INHERIT_SETTINGS, value, type_='bool')
462 463
463 464 def get_global_svn_branch_patterns(self):
464 465 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
465 466
466 467 @assert_repo_settings
467 468 def get_repo_svn_branch_patterns(self):
468 469 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
469 470
470 471 def get_global_svn_tag_patterns(self):
471 472 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
472 473
473 474 @assert_repo_settings
474 475 def get_repo_svn_tag_patterns(self):
475 476 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
476 477
477 478 def get_global_settings(self):
478 479 return self._collect_all_settings(global_=True)
479 480
480 481 @assert_repo_settings
481 482 def get_repo_settings(self):
482 483 return self._collect_all_settings(global_=False)
483 484
484 485 @assert_repo_settings
485 486 def create_or_update_repo_settings(
486 487 self, data, inherit_global_settings=False):
487 488 from rhodecode.model.scm import ScmModel
488 489
489 490 self.inherit_global_settings = inherit_global_settings
490 491
491 492 repo = self.repo_settings.get_repo()
492 493 if not inherit_global_settings:
493 494 if repo.repo_type == 'svn':
494 495 self.create_repo_svn_settings(data)
495 496 else:
496 497 self.create_or_update_repo_hook_settings(data)
497 498 self.create_or_update_repo_pr_settings(data)
498 499
499 500 if repo.repo_type == 'hg':
500 501 self.create_or_update_repo_hg_settings(data)
501 502
502 503 if repo.repo_type == 'git':
503 504 self.create_or_update_repo_git_settings(data)
504 505
505 506 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
506 507
507 508 @assert_repo_settings
508 509 def create_or_update_repo_hook_settings(self, data):
509 510 for section, key in self.HOOKS_SETTINGS:
510 511 data_key = self._get_form_ui_key(section, key)
511 512 if data_key not in data:
512 513 raise ValueError(
513 514 'The given data does not contain {} key'.format(data_key))
514 515
515 516 active = data.get(data_key)
516 517 repo_setting = self.repo_settings.get_ui_by_section_and_key(
517 518 section, key)
518 519 if not repo_setting:
519 520 global_setting = self.global_settings.\
520 521 get_ui_by_section_and_key(section, key)
521 522 self.repo_settings.create_ui_section_value(
522 523 section, global_setting.ui_value, key=key, active=active)
523 524 else:
524 525 repo_setting.ui_active = active
525 526 Session().add(repo_setting)
526 527
527 528 def update_global_hook_settings(self, data):
528 529 for section, key in self.HOOKS_SETTINGS:
529 530 data_key = self._get_form_ui_key(section, key)
530 531 if data_key not in data:
531 532 raise ValueError(
532 533 'The given data does not contain {} key'.format(data_key))
533 534 active = data.get(data_key)
534 535 repo_setting = self.global_settings.get_ui_by_section_and_key(
535 536 section, key)
536 537 repo_setting.ui_active = active
537 538 Session().add(repo_setting)
538 539
539 540 @assert_repo_settings
540 541 def create_or_update_repo_pr_settings(self, data):
541 542 return self._create_or_update_general_settings(
542 543 self.repo_settings, data)
543 544
544 545 def create_or_update_global_pr_settings(self, data):
545 546 return self._create_or_update_general_settings(
546 547 self.global_settings, data)
547 548
548 549 @assert_repo_settings
549 550 def create_repo_svn_settings(self, data):
550 551 return self._create_svn_settings(self.repo_settings, data)
551 552
552 553 @assert_repo_settings
553 554 def create_or_update_repo_hg_settings(self, data):
554 555 largefiles, phases, evolve = \
555 556 self.HG_SETTINGS
556 557 largefiles_key, phases_key, evolve_key = \
557 558 self._get_settings_keys(self.HG_SETTINGS, data)
558 559
559 560 self._create_or_update_ui(
560 561 self.repo_settings, *largefiles, value='',
561 562 active=data[largefiles_key])
562 563 self._create_or_update_ui(
563 564 self.repo_settings, *evolve, value='',
564 565 active=data[evolve_key])
565 566 self._create_or_update_ui(
566 567 self.repo_settings, *phases, value=safe_str(data[phases_key]))
567 568
568 569 def create_or_update_global_hg_settings(self, data):
569 570 largefiles, largefiles_store, phases, hgsubversion, evolve \
570 571 = self.GLOBAL_HG_SETTINGS
571 572 largefiles_key, largefiles_store_key, phases_key, subversion_key, evolve_key \
572 573 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS, data)
573 574
574 575 self._create_or_update_ui(
575 576 self.global_settings, *largefiles, value='',
576 577 active=data[largefiles_key])
577 578 self._create_or_update_ui(
578 579 self.global_settings, *largefiles_store,
579 580 value=data[largefiles_store_key])
580 581 self._create_or_update_ui(
581 582 self.global_settings, *phases, value=safe_str(data[phases_key]))
582 583 self._create_or_update_ui(
583 584 self.global_settings, *hgsubversion, active=data[subversion_key])
584 585 self._create_or_update_ui(
585 586 self.global_settings, *evolve, value='',
586 587 active=data[evolve_key])
587 588
588 589 def create_or_update_repo_git_settings(self, data):
589 590 # NOTE(marcink): # comma make unpack work properly
590 591 lfs_enabled, \
591 592 = self.GIT_SETTINGS
592 593
593 594 lfs_enabled_key, \
594 595 = self._get_settings_keys(self.GIT_SETTINGS, data)
595 596
596 597 self._create_or_update_ui(
597 598 self.repo_settings, *lfs_enabled, value=data[lfs_enabled_key],
598 599 active=data[lfs_enabled_key])
599 600
600 601 def create_or_update_global_git_settings(self, data):
601 602 lfs_enabled, lfs_store_location \
602 603 = self.GLOBAL_GIT_SETTINGS
603 604 lfs_enabled_key, lfs_store_location_key \
604 605 = self._get_settings_keys(self.GLOBAL_GIT_SETTINGS, data)
605 606
606 607 self._create_or_update_ui(
607 608 self.global_settings, *lfs_enabled, value=data[lfs_enabled_key],
608 609 active=data[lfs_enabled_key])
609 610 self._create_or_update_ui(
610 611 self.global_settings, *lfs_store_location,
611 612 value=data[lfs_store_location_key])
612 613
613 614 def create_or_update_global_svn_settings(self, data):
614 615 # branch/tags patterns
615 616 self._create_svn_settings(self.global_settings, data)
616 617
617 618 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
618 619 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
619 620 self.GLOBAL_SVN_SETTINGS, data)
620 621
621 622 self._create_or_update_ui(
622 623 self.global_settings, *http_requests_enabled,
623 624 value=safe_str(data[http_requests_enabled_key]))
624 625 self._create_or_update_ui(
625 626 self.global_settings, *http_server_url,
626 627 value=data[http_server_url_key])
627 628
628 629 def update_global_ssl_setting(self, value):
629 630 self._create_or_update_ui(
630 631 self.global_settings, *self.SSL_SETTING, value=value)
631 632
632 633 def update_global_path_setting(self, value):
633 634 self._create_or_update_ui(
634 635 self.global_settings, *self.PATH_SETTING, value=value)
635 636
636 637 @assert_repo_settings
637 638 def delete_repo_svn_pattern(self, id_):
639 ui = self.repo_settings.UiDbModel.get(id_)
640 if ui and ui.repository.repo_name == self.repo_settings.repo:
641 # only delete if it's the same repo as initialized settings
638 642 self.repo_settings.delete_ui(id_)
643 else:
644 # raise error as if we wouldn't find this option
645 self.repo_settings.delete_ui(-1)
639 646
640 647 def delete_global_svn_pattern(self, id_):
641 648 self.global_settings.delete_ui(id_)
642 649
643 650 @assert_repo_settings
644 651 def get_repo_ui_settings(self, section=None, key=None):
645 652 global_uis = self.global_settings.get_ui(section, key)
646 653 repo_uis = self.repo_settings.get_ui(section, key)
647 654 filtered_repo_uis = self._filter_ui_settings(repo_uis)
648 655 filtered_repo_uis_keys = [
649 656 (s.section, s.key) for s in filtered_repo_uis]
650 657
651 658 def _is_global_ui_filtered(ui):
652 659 return (
653 660 (ui.section, ui.key) in filtered_repo_uis_keys
654 661 or ui.section in self._svn_sections)
655 662
656 663 filtered_global_uis = [
657 664 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
658 665
659 666 return filtered_global_uis + filtered_repo_uis
660 667
661 668 def get_global_ui_settings(self, section=None, key=None):
662 669 return self.global_settings.get_ui(section, key)
663 670
664 671 def get_ui_settings_as_config_obj(self, section=None, key=None):
665 672 config = base.Config()
666 673
667 674 ui_settings = self.get_ui_settings(section=section, key=key)
668 675
669 676 for entry in ui_settings:
670 677 config.set(entry.section, entry.key, entry.value)
671 678
672 679 return config
673 680
674 681 def get_ui_settings(self, section=None, key=None):
675 682 if not self.repo_settings or self.inherit_global_settings:
676 683 return self.get_global_ui_settings(section, key)
677 684 else:
678 685 return self.get_repo_ui_settings(section, key)
679 686
680 687 def get_svn_patterns(self, section=None):
681 688 if not self.repo_settings:
682 689 return self.get_global_ui_settings(section)
683 690 else:
684 691 return self.get_repo_ui_settings(section)
685 692
686 693 @assert_repo_settings
687 694 def get_repo_general_settings(self):
688 695 global_settings = self.global_settings.get_all_settings()
689 696 repo_settings = self.repo_settings.get_all_settings()
690 697 filtered_repo_settings = self._filter_general_settings(repo_settings)
691 698 global_settings.update(filtered_repo_settings)
692 699 return global_settings
693 700
694 701 def get_global_general_settings(self):
695 702 return self.global_settings.get_all_settings()
696 703
697 704 def get_general_settings(self):
698 705 if not self.repo_settings or self.inherit_global_settings:
699 706 return self.get_global_general_settings()
700 707 else:
701 708 return self.get_repo_general_settings()
702 709
703 710 def get_repos_location(self):
704 711 return self.global_settings.get_ui_by_key('/').ui_value
705 712
706 713 def _filter_ui_settings(self, settings):
707 714 filtered_settings = [
708 715 s for s in settings if self._should_keep_setting(s)]
709 716 return filtered_settings
710 717
711 718 def _should_keep_setting(self, setting):
712 719 keep = (
713 720 (setting.section, setting.key) in self._ui_settings or
714 721 setting.section in self._svn_sections)
715 722 return keep
716 723
717 724 def _filter_general_settings(self, settings):
718 725 keys = ['rhodecode_{}'.format(key) for key in self.GENERAL_SETTINGS]
719 726 return {
720 727 k: settings[k]
721 728 for k in settings if k in keys}
722 729
723 730 def _collect_all_settings(self, global_=False):
724 731 settings = self.global_settings if global_ else self.repo_settings
725 732 result = {}
726 733
727 734 for section, key in self._ui_settings:
728 735 ui = settings.get_ui_by_section_and_key(section, key)
729 736 result_key = self._get_form_ui_key(section, key)
730 737
731 738 if ui:
732 739 if section in ('hooks', 'extensions'):
733 740 result[result_key] = ui.ui_active
734 741 elif result_key in ['vcs_git_lfs_enabled']:
735 742 result[result_key] = ui.ui_active
736 743 else:
737 744 result[result_key] = ui.ui_value
738 745
739 746 for name in self.GENERAL_SETTINGS:
740 747 setting = settings.get_setting_by_name(name)
741 748 if setting:
742 749 result_key = 'rhodecode_{}'.format(name)
743 750 result[result_key] = setting.app_settings_value
744 751
745 752 return result
746 753
747 754 def _get_form_ui_key(self, section, key):
748 755 return '{section}_{key}'.format(
749 756 section=section, key=key.replace('.', '_'))
750 757
751 758 def _create_or_update_ui(
752 759 self, settings, section, key, value=None, active=None):
753 760 ui = settings.get_ui_by_section_and_key(section, key)
754 761 if not ui:
755 762 active = True if active is None else active
756 763 settings.create_ui_section_value(
757 764 section, value, key=key, active=active)
758 765 else:
759 766 if active is not None:
760 767 ui.ui_active = active
761 768 if value is not None:
762 769 ui.ui_value = value
763 770 Session().add(ui)
764 771
765 772 def _create_svn_settings(self, settings, data):
766 773 svn_settings = {
767 774 'new_svn_branch': self.SVN_BRANCH_SECTION,
768 775 'new_svn_tag': self.SVN_TAG_SECTION
769 776 }
770 777 for key in svn_settings:
771 778 if data.get(key):
772 779 settings.create_ui_section_value(svn_settings[key], data[key])
773 780
774 781 def _create_or_update_general_settings(self, settings, data):
775 782 for name in self.GENERAL_SETTINGS:
776 783 data_key = 'rhodecode_{}'.format(name)
777 784 if data_key not in data:
778 785 raise ValueError(
779 786 'The given data does not contain {} key'.format(data_key))
780 787 setting = settings.create_or_update_setting(
781 788 name, data[data_key], 'bool')
782 789 Session().add(setting)
783 790
784 791 def _get_settings_keys(self, settings, data):
785 792 data_keys = [self._get_form_ui_key(*s) for s in settings]
786 793 for data_key in data_keys:
787 794 if data_key not in data:
788 795 raise ValueError(
789 796 'The given data does not contain {} key'.format(data_key))
790 797 return data_keys
791 798
792 799 def create_largeobjects_dirs_if_needed(self, repo_store_path):
793 800 """
794 801 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
795 802 does a repository scan if enabled in the settings.
796 803 """
797 804
798 805 from rhodecode.lib.vcs.backends.hg import largefiles_store
799 806 from rhodecode.lib.vcs.backends.git import lfs_store
800 807
801 808 paths = [
802 809 largefiles_store(repo_store_path),
803 810 lfs_store(repo_store_path)]
804 811
805 812 for path in paths:
806 813 if os.path.isdir(path):
807 814 continue
808 815 if os.path.isfile(path):
809 816 continue
810 817 # not a file nor dir, we try to create it
811 818 try:
812 819 os.makedirs(path)
813 820 except Exception:
814 821 log.warning('Failed to create largefiles dir:%s', path)
@@ -1,807 +1,807 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 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 mock
22 22 import pytest
23 23
24 24 from rhodecode.lib.utils2 import safe_str
25 25 from rhodecode.model.db import (
26 26 RhodeCodeUi, RepoRhodeCodeUi, RhodeCodeSetting, RepoRhodeCodeSetting)
27 27 from rhodecode.model.meta import Session
28 28 from rhodecode.model.settings import SettingsModel, SettingNotFound, UiSetting
29 29
30 30
31 31 class TestRepoGetUiByKey(object):
32 32 def test_ui_settings_are_returned_when_key_is_found(
33 33 self, repo_stub, settings_util):
34 34 section = 'test section'
35 35 value = 'test value'
36 36
37 37 settings_util.create_repo_rhodecode_ui(
38 38 repo_stub, 'wrong section', 'wrong value')
39 39 setting = settings_util.create_repo_rhodecode_ui(
40 40 repo_stub, section, value)
41 41 key = setting.ui_key
42 42
43 43 model = SettingsModel(repo=repo_stub.repo_name)
44 44 result = model.get_ui_by_key(key)
45 45 assert result.ui_value == value
46 46 assert result.ui_section == section
47 47 assert result.ui_active is True
48 48
49 49 def test_none_is_returned_when_key_is_not_found(
50 50 self, repo_stub, settings_util):
51 51 settings_util.create_repo_rhodecode_ui(
52 52 repo_stub, 'wrong section', 'wrong value')
53 53
54 54 model = SettingsModel(repo=repo_stub.repo_name)
55 55 result = model.get_ui_by_key('abcde')
56 56 assert result is None
57 57
58 58
59 59 class TestGlobalGetUiByKey(object):
60 60 def test_ui_settings_are_returned_when_key_is_found(self, settings_util):
61 61 section = 'test section'
62 62 value = 'test value'
63 63
64 64 settings_util.create_rhodecode_ui('wrong section', 'wrong value')
65 65 setting = settings_util.create_rhodecode_ui(section, value)
66 66 key = setting.ui_key
67 67
68 68 model = SettingsModel()
69 69 result = model.get_ui_by_key(key)
70 70 assert result.ui_value == value
71 71 assert result.ui_section == section
72 72 assert result.ui_active is True
73 73
74 74 def test_none_is_returned_when_key_is_not_found(self, settings_util):
75 75 settings_util.create_rhodecode_ui('wrong section', 'wrong value')
76 76 model = SettingsModel()
77 77 result = model.get_ui_by_key('abcde')
78 78 assert result is None
79 79
80 80
81 81 class TestRepoGetUiBySection(object):
82 82 def test_ui_settings_are_returned_when_section_is_found(
83 83 self, repo_stub, settings_util):
84 84 section = 'test section'
85 85 values = ['test value 1', 'test value 2']
86 86
87 87 expected_pairs = []
88 88 for value in values:
89 89 setting = settings_util.create_repo_rhodecode_ui(
90 90 repo_stub, section, value)
91 91 expected_pairs.append((setting.ui_key, value))
92 92
93 93 model = SettingsModel(repo=repo_stub.repo_name)
94 94 result = model.get_ui_by_section(section)
95 95 result_pairs = [(r.ui_key, r.ui_value) for r in result]
96 96 assert sorted(result_pairs) == sorted(expected_pairs)
97 97
98 98 def test_empty_list_is_returned_when_section_is_not_found(
99 99 self, repo_stub, settings_util):
100 100 settings_util.create_repo_rhodecode_ui(
101 101 repo_stub, 'wrong section', 'wrong value')
102 102
103 103 model = SettingsModel(repo=repo_stub.repo_name)
104 104 result = model.get_ui_by_section('correct section')
105 105 assert result == []
106 106
107 107
108 108 class TestGlobalGetUiBySection(object):
109 109 def test_ui_settings_are_returned_when_section_is_found(
110 110 self, settings_util):
111 111 section = 'test section'
112 112 values = ['test value 1', 'test value 2']
113 113
114 114 expected_pairs = []
115 115 for value in values:
116 116 setting = settings_util.create_rhodecode_ui(section, value)
117 117 expected_pairs.append((setting.ui_key, value))
118 118
119 119 model = SettingsModel()
120 120 result = model.get_ui_by_section(section)
121 121 result_pairs = [(r.ui_key, r.ui_value) for r in result]
122 122 assert sorted(result_pairs) == sorted(expected_pairs)
123 123
124 124 def test_empty_list_is_returned_when_section_is_not_found(
125 125 self, settings_util):
126 126 settings_util.create_rhodecode_ui('wrong section', 'wrong value')
127 127
128 128 model = SettingsModel()
129 129 result = model.get_ui_by_section('correct section')
130 130 assert result == []
131 131
132 132
133 133 class TestRepoGetUiBySectionAndKey(object):
134 134 def test_ui_settings_are_returned_when_section_and_key_are_found(
135 135 self, repo_stub, settings_util):
136 136 section = 'test section'
137 137 value = 'test value'
138 138 key = 'test key'
139 139
140 140 settings_util.create_rhodecode_ui(
141 141 'wrong section', 'wrong value', key='wrong key')
142 142 setting = settings_util.create_repo_rhodecode_ui(
143 143 repo_stub, section, value, key=key)
144 144 key = setting.ui_key
145 145
146 146 model = SettingsModel(repo=repo_stub.repo_name)
147 147 result = model.get_ui_by_section_and_key(section, key)
148 148 assert result.ui_value == value
149 149 assert result.ui_section == section
150 150 assert result.ui_active is True
151 151
152 152 def test_none_is_returned_when_key_section_pair_is_not_found(
153 153 self, repo_stub, settings_util):
154 154 settings_util.create_repo_rhodecode_ui(
155 155 repo_stub, 'section', 'wrong value', key='wrong key')
156 156
157 157 model = SettingsModel(repo=repo_stub.repo_name)
158 158 result = model.get_ui_by_section_and_key('section', 'test key')
159 159 assert result is None
160 160
161 161
162 162 class TestGlobalGetUiBySectionAndKey(object):
163 163 def test_ui_settings_are_returned_when_section_and_key_are_found(
164 164 self, settings_util):
165 165 section = 'test section'
166 166 value = 'test value'
167 167 key = 'test key'
168 168
169 169 settings_util.create_rhodecode_ui(
170 170 'wrong section', 'wrong value', key='wrong key')
171 171 setting = settings_util.create_rhodecode_ui(section, value, key=key)
172 172 key = setting.ui_key
173 173
174 174 model = SettingsModel()
175 175 result = model.get_ui_by_section_and_key(section, key)
176 176 assert result.ui_value == value
177 177 assert result.ui_section == section
178 178 assert result.ui_active is True
179 179
180 180 def test_none_is_returned_when_key_section_pair_is_not_found(
181 181 self, settings_util):
182 182 settings_util.create_rhodecode_ui(
183 183 'section', 'wrong value', key='wrong key')
184 184 model = SettingsModel()
185 185 result = model.get_ui_by_section_and_key('section', 'test key')
186 186 assert result is None
187 187
188 188
189 189 class TestRepoGetUi(object):
190 190 def test_non_empty_list_is_returned_when_ui_settings_found(
191 191 self, repo_stub, settings_util, fake_ui_values):
192 192 for ui in fake_ui_values:
193 193 settings_util.create_repo_rhodecode_ui(
194 194 repo_stub, ui.section, ui.value, key=ui.key)
195 195 # Create few global settings to check that only repo ones are
196 196 # displayed
197 197 settings_util.create_rhodecode_ui(ui.section, ui.value, key=ui.key)
198 198
199 199 model = SettingsModel(repo=repo_stub.repo_name)
200 200 result = model.get_ui()
201 201 assert sorted(result) == sorted(fake_ui_values)
202 202
203 203 def test_settings_filtered_by_section(
204 204 self, repo_stub, settings_util, fake_ui_values):
205 205 for ui in fake_ui_values:
206 206 settings_util.create_repo_rhodecode_ui(
207 207 repo_stub, ui.section, ui.value, key=ui.key)
208 208
209 209 model = SettingsModel(repo=repo_stub.repo_name)
210 210 result = model.get_ui(section=fake_ui_values[0].section)
211 211 expected_result = [
212 212 s for s in fake_ui_values
213 213 if s.section == fake_ui_values[0].section]
214 214 assert sorted(result) == sorted(expected_result)
215 215
216 216 def test_settings_filtered_by_key(
217 217 self, repo_stub, settings_util, fake_ui_values):
218 218 for ui in fake_ui_values:
219 219 settings_util.create_repo_rhodecode_ui(
220 220 repo_stub, ui.section, ui.value, key=ui.key)
221 221
222 222 model = SettingsModel(repo=repo_stub.repo_name)
223 223 result = model.get_ui(key=fake_ui_values[0].key)
224 224 expected_result = [
225 225 s for s in fake_ui_values if s.key == fake_ui_values[0].key]
226 226 assert sorted(result) == sorted(expected_result)
227 227
228 228 def test_empty_list_is_returned_when_ui_settings_are_not_found(
229 229 self, repo_stub, settings_util):
230 230 for i in range(10):
231 231 settings_util.create_rhodecode_ui(
232 232 'section{}'.format(i), 'value{}'.format(i),
233 233 key='key{}'.format(i), active=True)
234 234
235 235 model = SettingsModel(repo=repo_stub.repo_name)
236 236 result = model.get_ui()
237 237 assert result == []
238 238
239 239
240 240 class TestGlobalGetUi(object):
241 241 def test_non_empty_list_is_returned_when_ui_settings_found(
242 242 self, backend_stub, settings_util, fake_ui_values):
243 243 repo = backend_stub.create_repo()
244 244 for ui in fake_ui_values:
245 245 settings_util.create_rhodecode_ui(ui.section, ui.value, key=ui.key)
246 246 # Create few repo settings to check that only global ones are
247 247 # displayed
248 248 settings_util.create_repo_rhodecode_ui(
249 249 repo, ui.section, ui.value, key=ui.key)
250 250
251 251 model = SettingsModel()
252 252 result = model.get_ui()
253 253 for ui in fake_ui_values:
254 254 assert ui in result
255 255
256 256 def test_settings_filtered_by_key(self, settings_util, fake_ui_values):
257 257 for ui in fake_ui_values:
258 258 settings_util.create_rhodecode_ui(ui.section, ui.value, key=ui.key)
259 259 expected_result = [
260 260 s for s in fake_ui_values if s.key == fake_ui_values[0].key]
261 261
262 262 model = SettingsModel()
263 263 result = model.get_ui(key=fake_ui_values[0].key)
264 264 assert sorted(result) == sorted(expected_result)
265 265
266 266 def test_settings_filtered_by_section(self, settings_util, fake_ui_values):
267 267 for ui in fake_ui_values:
268 268 settings_util.create_rhodecode_ui(ui.section, ui.value, key=ui.key)
269 269 expected_result = [
270 270 s for s in fake_ui_values
271 271 if s.section == fake_ui_values[0].section]
272 272
273 273 model = SettingsModel()
274 274 result = model.get_ui(section=fake_ui_values[0].section)
275 275 assert sorted(result) == sorted(expected_result)
276 276
277 277 def test_repo_settings_are_not_displayed(
278 278 self, backend_stub, settings_util, fake_ui_values):
279 279 repo = backend_stub.create_repo()
280 280 for ui in fake_ui_values:
281 281 settings_util.create_repo_rhodecode_ui(
282 282 repo, ui.section, ui.value, key=ui.key, active=ui.active)
283 283
284 284 model = SettingsModel()
285 285 result = model.get_ui()
286 286 for ui in fake_ui_values:
287 287 assert ui not in result
288 288
289 289
290 290 class TestRepoGetBuiltInHooks(object):
291 291 def test_only_builtin_hooks_are_returned(self, repo_stub, settings_util):
292 292 section = 'hooks'
293 293 valid_keys = SettingsModel.BUILTIN_HOOKS
294 294 invalid_keys = ('fake_hook', )
295 295 keys = valid_keys + invalid_keys
296 296
297 297 for key in keys:
298 298 settings_util.create_repo_rhodecode_ui(
299 299 repo_stub, section, 'test value', key=key)
300 300
301 301 model = SettingsModel(repo=repo_stub.repo_name)
302 302 result = model.get_builtin_hooks()
303 303
304 304 assert len(result) == len(valid_keys)
305 305 for entry in result:
306 306 assert entry.ui_key in valid_keys
307 307
308 308
309 309 class TestGlobalGetBuiltInHooks(object):
310 310 def test_only_builtin_hooks_are_returned(self, settings_util):
311 311 section = 'hooks'
312 312 valid_keys = ('valid_key1', 'valid_key2')
313 313 invalid_keys = ('fake_hook', )
314 314 keys = valid_keys + invalid_keys
315 315
316 316 for key in keys:
317 317 settings_util.create_rhodecode_ui(section, 'test value', key=key)
318 318
319 319 model = SettingsModel()
320 320 with mock.patch.object(model, 'BUILTIN_HOOKS', valid_keys):
321 321 result = model.get_builtin_hooks()
322 322
323 323 assert len(result) == len(valid_keys)
324 324 for entry in result:
325 325 assert entry.ui_key in valid_keys
326 326
327 327
328 328 class TestRepoGetCustomHooks(object):
329 329 def test_only_custom_hooks_are_returned(self, repo_stub, settings_util):
330 330 section = 'hooks'
331 331 valid_keys = ('custom', )
332 332 invalid_keys = SettingsModel.BUILTIN_HOOKS
333 333 keys = valid_keys + invalid_keys
334 334
335 335 for key in keys:
336 336 settings_util.create_repo_rhodecode_ui(
337 337 repo_stub, section, 'test value', key=key)
338 338
339 339 model = SettingsModel(repo=repo_stub.repo_name)
340 340 result = model.get_custom_hooks()
341 341
342 342 assert len(result) == len(valid_keys)
343 343 for entry in result:
344 344 assert entry.ui_key in valid_keys
345 345
346 346
347 347 class TestGlobalGetCustomHooks(object):
348 348 def test_only_custom_hooks_are_returned(self, settings_util):
349 349 section = 'hooks'
350 350 valid_keys = ('valid_key1', 'valid_key2')
351 351 invalid_keys = ('fake_hook', )
352 352 keys = valid_keys + invalid_keys
353 353
354 354 for key in keys:
355 355 settings_util.create_rhodecode_ui(section, 'test value', key=key)
356 356
357 357 model = SettingsModel()
358 358 with mock.patch.object(model, 'BUILTIN_HOOKS', invalid_keys):
359 359 result = model.get_custom_hooks()
360 360 for entry in result:
361 361 assert entry.ui_key not in invalid_keys
362 362
363 363
364 364 class TestRepoCreateUiSectionValue(object):
365 365 @pytest.mark.parametrize("additional_kwargs", [
366 366 {'key': 'abcde'},
367 367 {'active': False},
368 368 {}
369 369 ])
370 370 def test_ui_section_value_is_created(
371 371 self, repo_stub, additional_kwargs):
372 372 model = SettingsModel(repo=repo_stub.repo_name)
373 373 section = 'test section'
374 374 value = 'test value'
375 375 result = model.create_ui_section_value(section, value)
376 376 key = result.ui_key
377 377 Session().commit()
378 378
379 379 setting = model.get_ui_by_key(key)
380 380 try:
381 381 assert setting == result
382 382 assert isinstance(setting, RepoRhodeCodeUi)
383 383 finally:
384 384 Session().delete(result)
385 385 Session().commit()
386 386
387 387
388 388 class TestGlobalCreateUiSectionValue(object):
389 389 @pytest.mark.parametrize("additional_kwargs", [
390 390 {'key': 'abcde'},
391 391 {'active': False},
392 392 {}
393 393 ])
394 394 def test_ui_section_value_is_created_with_autogenerated_key(
395 395 self, backend_stub, additional_kwargs):
396 396 model = SettingsModel()
397 397 section = 'test section'
398 398 value = 'test value'
399 399 result = model.create_ui_section_value(
400 400 section, value, **additional_kwargs)
401 401 key = result.ui_key
402 402 Session().commit()
403 403
404 404 setting = model.get_ui_by_key(key)
405 405 try:
406 406 assert setting == result
407 407 assert isinstance(setting, RhodeCodeUi)
408 408 finally:
409 409 Session().delete(result)
410 410 Session().commit()
411 411
412 412
413 413 class TestRepoCreateOrUpdateHook(object):
414 414 def test_hook_created(self, repo_stub):
415 415 model = SettingsModel(repo=repo_stub.repo_name)
416 416 key = 'test_key'
417 417 value = 'test value'
418 418 result = model.create_or_update_hook(key, value)
419 419 Session().commit()
420 420
421 421 setting = model.get_ui_by_section_and_key('hooks', key)
422 422 try:
423 423 assert setting == result
424 424 assert isinstance(setting, RepoRhodeCodeUi)
425 425 finally:
426 426 Session().delete(result)
427 427 Session().commit()
428 428
429 429 def test_hook_updated(self, repo_stub, settings_util):
430 430 section = 'hooks'
431 431 key = 'test_key'
432 432
433 433 settings_util.create_repo_rhodecode_ui(
434 434 repo_stub, section, 'old value', key=key)
435 435
436 436 model = SettingsModel(repo=repo_stub.repo_name)
437 437 value = 'test value'
438 438 model.create_or_update_hook(key, value)
439 439 Session().commit()
440 440
441 441 setting = model.get_ui_by_section_and_key('hooks', key)
442 442 assert setting.ui_value == value
443 443
444 444
445 445 class TestGlobalCreateOrUpdateHook(object):
446 446 def test_hook_created(self):
447 447 model = SettingsModel()
448 448 key = 'test_key'
449 449 value = 'test value'
450 450 result = model.create_or_update_hook(key, value)
451 451 Session().commit()
452 452
453 453 setting = model.get_ui_by_section_and_key('hooks', key)
454 454 try:
455 455 assert setting == result
456 456 assert isinstance(setting, RhodeCodeUi)
457 457 finally:
458 458 Session().delete(result)
459 459 Session().commit()
460 460
461 461 def test_hook_updated(self, settings_util):
462 462 section = 'hooks'
463 463 key = 'test_key'
464 464
465 465 settings_util.create_rhodecode_ui(section, 'old value', key=key)
466 466
467 467 model = SettingsModel()
468 468 value = 'test value'
469 469 model.create_or_update_hook(key, value)
470 470 Session().commit()
471 471
472 472 setting = model.get_ui_by_section_and_key('hooks', key)
473 473 assert setting.ui_value == value
474 474
475 475
476 476 class TestDeleteUiValue(object):
477 477 def test_delete_ui_when_repo_is_set(self, repo_stub, settings_util):
478 478 model = SettingsModel(repo=repo_stub.repo_name)
479 479 result = settings_util.create_repo_rhodecode_ui(
480 480 repo_stub, 'section', None, cleanup=False)
481 481
482 482 key = result.ui_key
483 483 model.delete_ui(result.ui_id)
484 484 Session().commit()
485 485
486 486 setting = model.get_ui_by_key(key)
487 487 assert setting is None
488 488
489 489 @pytest.mark.parametrize('id_', (None, 123))
490 490 def test_raises_exception_when_id_is_not_specified(self, id_):
491 491 model = SettingsModel()
492 492 with pytest.raises(SettingNotFound) as exc_info:
493 493 model.delete_ui(id_)
494 assert exc_info.value.message == 'Setting is not found'
494 assert exc_info.value.message == 'Setting `{}` is not found'.format(id_)
495 495
496 496 def test_delete_ui_when_repo_is_not_set(self, settings_util):
497 497 model = SettingsModel()
498 498 result = settings_util.create_rhodecode_ui(
499 499 'section', None, cleanup=False)
500 500
501 501 key = result.ui_key
502 502 model.delete_ui(result.ui_id)
503 503 Session().commit()
504 504
505 505 setting = model.get_ui_by_key(key)
506 506 assert setting is None
507 507
508 508
509 509 class TestRepoGetSettingByName(object):
510 510 @pytest.mark.parametrize("name, value, type_, expected_value", [
511 511 ('test_unicode', 'Straße', 'unicode', 'Straße'),
512 512 ('test_int', '1234', 'int', 1234),
513 513 ('test_bool', 'True', 'bool', True),
514 514 ('test_list', 'a,b,c', 'list', ['a', 'b', 'c'])
515 515 ])
516 516 def test_setting_is_returned_when_name_is_found(
517 517 self, repo_stub, settings_util, name, value, type_,
518 518 expected_value):
519 519 settings_util.create_repo_rhodecode_setting(
520 520 repo_stub, name, value, type_)
521 521
522 522 model = SettingsModel(repo=repo_stub.repo_name)
523 523 setting = model.get_setting_by_name(name)
524 524 assert setting.app_settings_type == type_
525 525 actual_value = setting.app_settings_value
526 526 if type_ == 'unicode':
527 527 actual_value = safe_str(actual_value)
528 528 assert actual_value == expected_value
529 529
530 530 def test_returns_none_if_the_setting_does_not_exist(self, repo_stub):
531 531 model = SettingsModel(repo=repo_stub.repo_name)
532 532 setting = model.get_setting_by_name('abcde')
533 533 assert setting is None
534 534
535 535
536 536 class TestGlobalGetSettingByName(object):
537 537 @pytest.mark.parametrize("name, value, type_, expected_value", [
538 538 ('test_unicode', 'Straße', 'unicode', 'Straße'),
539 539 ('test_int', '1234', 'int', 1234),
540 540 ('test_bool', 'True', 'bool', True),
541 541 ('test_list', 'a,b,c', 'list', ['a', 'b', 'c'])
542 542 ])
543 543 def test_setting_is_returned_when_name_is_found(
544 544 self, settings_util, name, value, type_, expected_value):
545 545 settings_util.create_rhodecode_setting(name, value, type_)
546 546
547 547 model = SettingsModel()
548 548 setting = model.get_setting_by_name(name)
549 549 assert setting.app_settings_type == type_
550 550 actual_value = setting.app_settings_value
551 551 if type_ == 'unicode':
552 552 actual_value = safe_str(actual_value)
553 553 assert actual_value == expected_value
554 554
555 555 def test_returns_none_if_the_setting_does_not_exist(self):
556 556 model = SettingsModel()
557 557 setting = model.get_setting_by_name('abcde')
558 558 assert setting is None
559 559
560 560
561 561 class TestRepoGetAllSettings(object):
562 562 def test_settings_are_found(self, repo_stub, settings_util):
563 563 initial_settings = {
564 564 'test_setting_{}'.format(i): 'value' for i in range(10)}
565 565 settings = [
566 566 settings_util.create_repo_rhodecode_setting(
567 567 repo_stub, name, initial_settings[name], 'unicode')
568 568 for name in initial_settings
569 569 ]
570 570 model = SettingsModel(repo=repo_stub.repo_name)
571 571
572 572 settings = model.get_all_settings()
573 573 expected_settings = {
574 574 'rhodecode_' + name: initial_settings[name]
575 575 for name in initial_settings
576 576 }
577 577
578 578 assert len(settings) == 10
579 579 assert expected_settings == settings
580 580
581 581 def test_settings_are_not_found(self, repo_stub):
582 582 model = SettingsModel(repo=repo_stub.repo_name)
583 583 setting = model.get_all_settings()
584 584 assert setting == {}
585 585
586 586
587 587 class TestGlobalGetAllSettings(object):
588 588 def test_settings_are_found(self, settings_util):
589 589 initial_settings = {
590 590 'test_setting_{}'.format(i): 'value' for i in range(10)}
591 591 settings = [
592 592 settings_util.create_rhodecode_setting(
593 593 name, initial_settings[name], 'unicode')
594 594 for name in initial_settings
595 595 ]
596 596 model = SettingsModel()
597 597
598 598 settings = model.get_all_settings()
599 599 expected_settings = {
600 600 'rhodecode_' + name: initial_settings[name]
601 601 for name in initial_settings
602 602 }
603 603
604 604 filtered_settings = {
605 605 name: settings[name]
606 606 for name in settings if name.startswith('rhodecode_test_setting')
607 607 }
608 608 assert len(filtered_settings) == 10
609 609 assert expected_settings == filtered_settings
610 610
611 611 def test_settings_are_not_found(self, repo_stub):
612 612 model = SettingsModel(repo=repo_stub.repo_name)
613 613 setting = model.get_all_settings()
614 614 assert setting == {}
615 615
616 616
617 617 class TestRepoCreateOrUpdateSetting(object):
618 618 def test_setting_is_created(self, repo_stub):
619 619 model = SettingsModel(repo=repo_stub.repo_name)
620 620 name = 'test_setting'
621 621 value = 'test_value'
622 622 model.create_or_update_setting(name, val=value)
623 623
624 624 setting = model.get_setting_by_name(name)
625 625 try:
626 626 assert setting.app_settings_name == name
627 627 assert setting.app_settings_value == value
628 628 assert setting.app_settings_type == 'unicode'
629 629 assert isinstance(setting, RepoRhodeCodeSetting)
630 630 finally:
631 631 Session().delete(setting)
632 632 Session().commit()
633 633
634 634 def test_setting_is_updated(self, repo_stub, settings_util):
635 635 model = SettingsModel(repo=repo_stub.repo_name)
636 636 name = 'test_setting'
637 637 value = 'test_value'
638 638 settings_util.create_repo_rhodecode_setting(
639 639 repo_stub, name, value, 'unicode', cleanup=False)
640 640
641 641 updated_value = 'test_value_2'
642 642 model.create_or_update_setting(name, val=updated_value)
643 643
644 644 setting = model.get_setting_by_name(name)
645 645 try:
646 646 assert setting.app_settings_name == name
647 647 assert setting.app_settings_value == updated_value
648 648 assert setting.app_settings_type == 'unicode'
649 649 assert isinstance(setting, RepoRhodeCodeSetting)
650 650 finally:
651 651 Session().delete(setting)
652 652 Session().commit()
653 653
654 654
655 655 class TestGlobalCreateOrUpdateSetting(object):
656 656 def test_setting_is_created(self):
657 657 model = SettingsModel()
658 658 name = 'test_setting'
659 659 value = 'test_value'
660 660 model.create_or_update_setting(name, val=value)
661 661
662 662 setting = model.get_setting_by_name(name)
663 663 try:
664 664 assert setting.app_settings_name == name
665 665 assert setting.app_settings_value == value
666 666 assert setting.app_settings_type == 'unicode'
667 667 assert isinstance(setting, RhodeCodeSetting)
668 668 finally:
669 669 Session().delete(setting)
670 670 Session().commit()
671 671
672 672 def test_setting_is_updated(self, settings_util):
673 673 model = SettingsModel()
674 674 name = 'test_setting'
675 675 value = 'test_value'
676 676 settings_util.create_rhodecode_setting(
677 677 name, value, 'unicode', cleanup=False)
678 678
679 679 updated_value = 'test_value_2'
680 680 model.create_or_update_setting(name, val=updated_value)
681 681
682 682 setting = model.get_setting_by_name(name)
683 683 try:
684 684 assert setting.app_settings_name == name
685 685 assert setting.app_settings_value == updated_value
686 686 assert setting.app_settings_type == 'unicode'
687 687 assert isinstance(setting, RhodeCodeSetting)
688 688 finally:
689 689 Session().delete(setting)
690 690 Session().commit()
691 691
692 692
693 693 class TestRepoGetAuthSettings(object):
694 694 def test_settings_prefixed_with_auth_are_retured(
695 695 self, repo_stub, settings_util):
696 696 model = SettingsModel(repo=repo_stub.repo_name)
697 697 valid_settings = ('auth_test1', 'auth_test2')
698 698 invalid_settings = ('test1', 'test2')
699 699 fake_value = 'test_value'
700 700
701 701 for name in valid_settings + invalid_settings:
702 702 settings_util.create_repo_rhodecode_setting(
703 703 repo_stub, name, fake_value, 'unicode')
704 704
705 705 auth_settings = model.get_auth_settings()
706 706 assert auth_settings == {name: fake_value for name in valid_settings}
707 707
708 708
709 709 class TestGlobalGetAuthSettings(object):
710 710 def test_settings_prefixed_with_auth_are_retured(self, settings_util):
711 711 model = SettingsModel()
712 712 valid_settings = ('auth_test1', 'auth_test2')
713 713 invalid_settings = ('test1', 'test2')
714 714 fake_value = 'test_value'
715 715
716 716 for name in valid_settings + invalid_settings:
717 717 settings_util.create_rhodecode_setting(name, fake_value, 'unicode')
718 718
719 719 auth_settings = model.get_auth_settings()
720 720 for name in auth_settings:
721 721 assert name not in invalid_settings
722 722 if name in valid_settings:
723 723 assert auth_settings[name] == fake_value
724 724
725 725
726 726 class TestGetAuthPlugins(object):
727 727 def test_get_setting_by_name_is_called(self):
728 728 model = SettingsModel()
729 729
730 730 fake_value = 'some value'
731 731 result_mock = mock.Mock()
732 732 result_mock.app_settings_value = fake_value
733 733
734 734 get_setting_patch = mock.patch.object(
735 735 model, 'get_setting_by_name', return_value=result_mock)
736 736
737 737 with get_setting_patch as get_setting_mock:
738 738 result = model.get_auth_plugins()
739 739
740 740 get_setting_mock.assert_called_once_with('auth_plugins')
741 741 assert result == fake_value
742 742
743 743
744 744 class TestDefaultRepoSettings(object):
745 745 DEFAULT_SETTINGS_NAMES = ['default_a{}'.format(i) for i in range(10)]
746 746 CUSTOM_SETTINGS_NAMES = ['setting_b_{}'.format(i) for i in range(10)]
747 747
748 748 def test_returns_global_settings_prefixed_with_default(
749 749 self, settings_util):
750 750 self._create_values(settings_util)
751 751 model = SettingsModel()
752 752 result = model.get_default_repo_settings()
753 753 self._assert_prefixed_settings(result)
754 754
755 755 def test_returns_global_settings_without_default_prefix(
756 756 self, settings_util):
757 757 self._create_values(settings_util)
758 758 model = SettingsModel()
759 759 result = model.get_default_repo_settings(strip_prefix=True)
760 760 self._assert_non_prefixed_settings(result)
761 761
762 762 def test_returns_per_repo_settings_prefixed_with_default(
763 763 self, repo_stub, settings_util):
764 764 model = SettingsModel(repo=repo_stub)
765 765 self._create_values(settings_util, repo=repo_stub)
766 766 result = model.get_default_repo_settings()
767 767 self._assert_prefixed_settings(result)
768 768
769 769 def test_returns_per_repo_settings_without_default_prefix(
770 770 self, repo_stub, settings_util):
771 771 model = SettingsModel(repo=repo_stub)
772 772 self._create_values(settings_util, repo=repo_stub)
773 773 result = model.get_default_repo_settings(strip_prefix=True)
774 774 self._assert_non_prefixed_settings(result)
775 775
776 776 def _create_values(self, settings_util, repo=None):
777 777 for name in self.DEFAULT_SETTINGS_NAMES + self.CUSTOM_SETTINGS_NAMES:
778 778 if not repo:
779 779 settings_util.create_rhodecode_setting(
780 780 name, 'value', 'unicode')
781 781 else:
782 782 settings_util.create_repo_rhodecode_setting(
783 783 repo, name, 'value', 'unicode')
784 784
785 785 def _assert_prefixed_settings(self, result):
786 786 for setting in self.DEFAULT_SETTINGS_NAMES:
787 787 assert setting in result
788 788 assert result[setting] == 'value'
789 789
790 790 for setting in self.CUSTOM_SETTINGS_NAMES:
791 791 assert setting not in result
792 792
793 793 def _assert_non_prefixed_settings(self, result):
794 794 for setting in self.DEFAULT_SETTINGS_NAMES:
795 795 setting = setting.replace('default_', '')
796 796 assert setting in result
797 797 assert result[setting] == 'value'
798 798
799 799
800 800 @pytest.fixture
801 801 def fake_ui_values():
802 802 return [
803 803 UiSetting(
804 804 'section{}'.format(i % 2), 'key{}'.format(i),
805 805 'value{}'.format(i), True)
806 806 for i in range(10)
807 807 ]
@@ -1,1072 +1,1083 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 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 mock
22 22 import pytest
23 23
24 24 from rhodecode.lib.utils2 import str2bool
25 25 from rhodecode.model.meta import Session
26 26 from rhodecode.model.settings import VcsSettingsModel, UiSetting
27 27
28 28
29 29 HOOKS_FORM_DATA = {
30 30 'hooks_changegroup_repo_size': True,
31 31 'hooks_changegroup_push_logger': True,
32 32 'hooks_outgoing_pull_logger': True
33 33 }
34 34
35 35 SVN_FORM_DATA = {
36 36 'new_svn_branch': 'test-branch',
37 37 'new_svn_tag': 'test-tag'
38 38 }
39 39
40 40 GENERAL_FORM_DATA = {
41 41 'rhodecode_pr_merge_enabled': True,
42 42 'rhodecode_use_outdated_comments': True,
43 43 'rhodecode_hg_use_rebase_for_merging': True,
44 44 'rhodecode_hg_close_branch_before_merging': True,
45 45 'rhodecode_git_use_rebase_for_merging': True,
46 46 'rhodecode_git_close_branch_before_merging': True,
47 47 }
48 48
49 49
50 50 class TestInheritGlobalSettingsProperty(object):
51 51 def test_get_raises_exception_when_repository_not_specified(self):
52 52 model = VcsSettingsModel()
53 53 with pytest.raises(Exception) as exc_info:
54 54 model.inherit_global_settings
55 55 assert exc_info.value.message == 'Repository is not specified'
56 56
57 57 def test_true_is_returned_when_value_is_not_found(self, repo_stub):
58 58 model = VcsSettingsModel(repo=repo_stub.repo_name)
59 59 assert model.inherit_global_settings is True
60 60
61 61 def test_value_is_returned(self, repo_stub, settings_util):
62 62 model = VcsSettingsModel(repo=repo_stub.repo_name)
63 63 settings_util.create_repo_rhodecode_setting(
64 64 repo_stub, VcsSettingsModel.INHERIT_SETTINGS, False, 'bool')
65 65 assert model.inherit_global_settings is False
66 66
67 67 def test_value_is_set(self, repo_stub):
68 68 model = VcsSettingsModel(repo=repo_stub.repo_name)
69 69 model.inherit_global_settings = False
70 70 setting = model.repo_settings.get_setting_by_name(
71 71 VcsSettingsModel.INHERIT_SETTINGS)
72 72 try:
73 73 assert setting.app_settings_type == 'bool'
74 74 assert setting.app_settings_value is False
75 75 finally:
76 76 Session().delete(setting)
77 77 Session().commit()
78 78
79 79 def test_set_raises_exception_when_repository_not_specified(self):
80 80 model = VcsSettingsModel()
81 81 with pytest.raises(Exception) as exc_info:
82 82 model.inherit_global_settings = False
83 83 assert exc_info.value.message == 'Repository is not specified'
84 84
85 85
86 86 class TestVcsSettingsModel(object):
87 87 def test_global_svn_branch_patterns(self):
88 88 model = VcsSettingsModel()
89 89 expected_result = {'test': 'test'}
90 90 with mock.patch.object(model, 'global_settings') as settings_mock:
91 91 get_settings = settings_mock.get_ui_by_section
92 92 get_settings.return_value = expected_result
93 93 settings_mock.return_value = expected_result
94 94 result = model.get_global_svn_branch_patterns()
95 95
96 96 get_settings.assert_called_once_with(model.SVN_BRANCH_SECTION)
97 97 assert expected_result == result
98 98
99 99 def test_repo_svn_branch_patterns(self):
100 100 model = VcsSettingsModel()
101 101 expected_result = {'test': 'test'}
102 102 with mock.patch.object(model, 'repo_settings') as settings_mock:
103 103 get_settings = settings_mock.get_ui_by_section
104 104 get_settings.return_value = expected_result
105 105 settings_mock.return_value = expected_result
106 106 result = model.get_repo_svn_branch_patterns()
107 107
108 108 get_settings.assert_called_once_with(model.SVN_BRANCH_SECTION)
109 109 assert expected_result == result
110 110
111 111 def test_repo_svn_branch_patterns_raises_exception_when_repo_is_not_set(
112 112 self):
113 113 model = VcsSettingsModel()
114 114 with pytest.raises(Exception) as exc_info:
115 115 model.get_repo_svn_branch_patterns()
116 116 assert exc_info.value.message == 'Repository is not specified'
117 117
118 118 def test_global_svn_tag_patterns(self):
119 119 model = VcsSettingsModel()
120 120 expected_result = {'test': 'test'}
121 121 with mock.patch.object(model, 'global_settings') as settings_mock:
122 122 get_settings = settings_mock.get_ui_by_section
123 123 get_settings.return_value = expected_result
124 124 settings_mock.return_value = expected_result
125 125 result = model.get_global_svn_tag_patterns()
126 126
127 127 get_settings.assert_called_once_with(model.SVN_TAG_SECTION)
128 128 assert expected_result == result
129 129
130 130 def test_repo_svn_tag_patterns(self):
131 131 model = VcsSettingsModel()
132 132 expected_result = {'test': 'test'}
133 133 with mock.patch.object(model, 'repo_settings') as settings_mock:
134 134 get_settings = settings_mock.get_ui_by_section
135 135 get_settings.return_value = expected_result
136 136 settings_mock.return_value = expected_result
137 137 result = model.get_repo_svn_tag_patterns()
138 138
139 139 get_settings.assert_called_once_with(model.SVN_TAG_SECTION)
140 140 assert expected_result == result
141 141
142 142 def test_repo_svn_tag_patterns_raises_exception_when_repo_is_not_set(self):
143 143 model = VcsSettingsModel()
144 144 with pytest.raises(Exception) as exc_info:
145 145 model.get_repo_svn_tag_patterns()
146 146 assert exc_info.value.message == 'Repository is not specified'
147 147
148 148 def test_get_global_settings(self):
149 149 expected_result = {'test': 'test'}
150 150 model = VcsSettingsModel()
151 151 with mock.patch.object(model, '_collect_all_settings') as collect_mock:
152 152 collect_mock.return_value = expected_result
153 153 result = model.get_global_settings()
154 154
155 155 collect_mock.assert_called_once_with(global_=True)
156 156 assert result == expected_result
157 157
158 158 def test_get_repo_settings(self, repo_stub):
159 159 model = VcsSettingsModel(repo=repo_stub.repo_name)
160 160 expected_result = {'test': 'test'}
161 161 with mock.patch.object(model, '_collect_all_settings') as collect_mock:
162 162 collect_mock.return_value = expected_result
163 163 result = model.get_repo_settings()
164 164
165 165 collect_mock.assert_called_once_with(global_=False)
166 166 assert result == expected_result
167 167
168 168 @pytest.mark.parametrize('settings, global_', [
169 169 ('global_settings', True),
170 170 ('repo_settings', False)
171 171 ])
172 172 def test_collect_all_settings(self, settings, global_):
173 173 model = VcsSettingsModel()
174 174 result_mock = self._mock_result()
175 175
176 176 settings_patch = mock.patch.object(model, settings)
177 177 with settings_patch as settings_mock:
178 178 settings_mock.get_ui_by_section_and_key.return_value = result_mock
179 179 settings_mock.get_setting_by_name.return_value = result_mock
180 180 result = model._collect_all_settings(global_=global_)
181 181
182 182 ui_settings = model.HG_SETTINGS + model.GIT_SETTINGS + model.HOOKS_SETTINGS
183 183 self._assert_get_settings_calls(
184 184 settings_mock, ui_settings, model.GENERAL_SETTINGS)
185 185 self._assert_collect_all_settings_result(
186 186 ui_settings, model.GENERAL_SETTINGS, result)
187 187
188 188 @pytest.mark.parametrize('settings, global_', [
189 189 ('global_settings', True),
190 190 ('repo_settings', False)
191 191 ])
192 192 def test_collect_all_settings_without_empty_value(self, settings, global_):
193 193 model = VcsSettingsModel()
194 194
195 195 settings_patch = mock.patch.object(model, settings)
196 196 with settings_patch as settings_mock:
197 197 settings_mock.get_ui_by_section_and_key.return_value = None
198 198 settings_mock.get_setting_by_name.return_value = None
199 199 result = model._collect_all_settings(global_=global_)
200 200
201 201 assert result == {}
202 202
203 203 def _mock_result(self):
204 204 result_mock = mock.Mock()
205 205 result_mock.ui_value = 'ui_value'
206 206 result_mock.ui_active = True
207 207 result_mock.app_settings_value = 'setting_value'
208 208 return result_mock
209 209
210 210 def _assert_get_settings_calls(
211 211 self, settings_mock, ui_settings, general_settings):
212 212 assert (
213 213 settings_mock.get_ui_by_section_and_key.call_count ==
214 214 len(ui_settings))
215 215 assert (
216 216 settings_mock.get_setting_by_name.call_count ==
217 217 len(general_settings))
218 218
219 219 for section, key in ui_settings:
220 220 expected_call = mock.call(section, key)
221 221 assert (
222 222 expected_call in
223 223 settings_mock.get_ui_by_section_and_key.call_args_list)
224 224
225 225 for name in general_settings:
226 226 expected_call = mock.call(name)
227 227 assert (
228 228 expected_call in
229 229 settings_mock.get_setting_by_name.call_args_list)
230 230
231 231 def _assert_collect_all_settings_result(
232 232 self, ui_settings, general_settings, result):
233 233 expected_result = {}
234 234 for section, key in ui_settings:
235 235 key = '{}_{}'.format(section, key.replace('.', '_'))
236 236
237 237 if section in ('extensions', 'hooks'):
238 238 value = True
239 239 elif key in ['vcs_git_lfs_enabled']:
240 240 value = True
241 241 else:
242 242 value = 'ui_value'
243 243 expected_result[key] = value
244 244
245 245 for name in general_settings:
246 246 key = 'rhodecode_' + name
247 247 expected_result[key] = 'setting_value'
248 248
249 249 assert expected_result == result
250 250
251 251
252 252 class TestCreateOrUpdateRepoHookSettings(object):
253 253 def test_create_when_no_repo_object_found(self, repo_stub):
254 254 model = VcsSettingsModel(repo=repo_stub.repo_name)
255 255
256 256 self._create_settings(model, HOOKS_FORM_DATA)
257 257
258 258 cleanup = []
259 259 try:
260 260 for section, key in model.HOOKS_SETTINGS:
261 261 ui = model.repo_settings.get_ui_by_section_and_key(
262 262 section, key)
263 263 assert ui.ui_active is True
264 264 cleanup.append(ui)
265 265 finally:
266 266 for ui in cleanup:
267 267 Session().delete(ui)
268 268 Session().commit()
269 269
270 270 def test_create_raises_exception_when_data_incomplete(self, repo_stub):
271 271 model = VcsSettingsModel(repo=repo_stub.repo_name)
272 272
273 273 deleted_key = 'hooks_changegroup_repo_size'
274 274 data = HOOKS_FORM_DATA.copy()
275 275 data.pop(deleted_key)
276 276
277 277 with pytest.raises(ValueError) as exc_info:
278 278 model.create_or_update_repo_hook_settings(data)
279 279 assert (
280 280 exc_info.value.message ==
281 281 'The given data does not contain {} key'.format(deleted_key))
282 282
283 283 def test_update_when_repo_object_found(self, repo_stub, settings_util):
284 284 model = VcsSettingsModel(repo=repo_stub.repo_name)
285 285 for section, key in model.HOOKS_SETTINGS:
286 286 settings_util.create_repo_rhodecode_ui(
287 287 repo_stub, section, None, key=key, active=False)
288 288 model.create_or_update_repo_hook_settings(HOOKS_FORM_DATA)
289 289 for section, key in model.HOOKS_SETTINGS:
290 290 ui = model.repo_settings.get_ui_by_section_and_key(section, key)
291 291 assert ui.ui_active is True
292 292
293 293 def _create_settings(self, model, data):
294 294 global_patch = mock.patch.object(model, 'global_settings')
295 295 global_setting = mock.Mock()
296 296 global_setting.ui_value = 'Test value'
297 297 with global_patch as global_mock:
298 298 global_mock.get_ui_by_section_and_key.return_value = global_setting
299 299 model.create_or_update_repo_hook_settings(HOOKS_FORM_DATA)
300 300
301 301
302 302 class TestUpdateGlobalHookSettings(object):
303 303 def test_update_raises_exception_when_data_incomplete(self):
304 304 model = VcsSettingsModel()
305 305
306 306 deleted_key = 'hooks_changegroup_repo_size'
307 307 data = HOOKS_FORM_DATA.copy()
308 308 data.pop(deleted_key)
309 309
310 310 with pytest.raises(ValueError) as exc_info:
311 311 model.update_global_hook_settings(data)
312 312 assert (
313 313 exc_info.value.message ==
314 314 'The given data does not contain {} key'.format(deleted_key))
315 315
316 316 def test_update_global_hook_settings(self, settings_util):
317 317 model = VcsSettingsModel()
318 318 setting_mock = mock.MagicMock()
319 319 setting_mock.ui_active = False
320 320 get_settings_patcher = mock.patch.object(
321 321 model.global_settings, 'get_ui_by_section_and_key',
322 322 return_value=setting_mock)
323 323 session_patcher = mock.patch('rhodecode.model.settings.Session')
324 324 with get_settings_patcher as get_settings_mock, session_patcher:
325 325 model.update_global_hook_settings(HOOKS_FORM_DATA)
326 326 assert setting_mock.ui_active is True
327 327 assert get_settings_mock.call_count == 3
328 328
329 329
330 330 class TestCreateOrUpdateRepoGeneralSettings(object):
331 331 def test_calls_create_or_update_general_settings(self, repo_stub):
332 332 model = VcsSettingsModel(repo=repo_stub.repo_name)
333 333 create_patch = mock.patch.object(
334 334 model, '_create_or_update_general_settings')
335 335 with create_patch as create_mock:
336 336 model.create_or_update_repo_pr_settings(GENERAL_FORM_DATA)
337 337 create_mock.assert_called_once_with(
338 338 model.repo_settings, GENERAL_FORM_DATA)
339 339
340 340 def test_raises_exception_when_repository_is_not_specified(self):
341 341 model = VcsSettingsModel()
342 342 with pytest.raises(Exception) as exc_info:
343 343 model.create_or_update_repo_pr_settings(GENERAL_FORM_DATA)
344 344 assert exc_info.value.message == 'Repository is not specified'
345 345
346 346
347 347 class TestCreateOrUpdatGlobalGeneralSettings(object):
348 348 def test_calls_create_or_update_general_settings(self):
349 349 model = VcsSettingsModel()
350 350 create_patch = mock.patch.object(
351 351 model, '_create_or_update_general_settings')
352 352 with create_patch as create_mock:
353 353 model.create_or_update_global_pr_settings(GENERAL_FORM_DATA)
354 354 create_mock.assert_called_once_with(
355 355 model.global_settings, GENERAL_FORM_DATA)
356 356
357 357
358 358 class TestCreateOrUpdateGeneralSettings(object):
359 359 def test_create_when_no_repo_settings_found(self, repo_stub):
360 360 model = VcsSettingsModel(repo=repo_stub.repo_name)
361 361 model._create_or_update_general_settings(
362 362 model.repo_settings, GENERAL_FORM_DATA)
363 363
364 364 cleanup = []
365 365 try:
366 366 for name in model.GENERAL_SETTINGS:
367 367 setting = model.repo_settings.get_setting_by_name(name)
368 368 assert setting.app_settings_value is True
369 369 cleanup.append(setting)
370 370 finally:
371 371 for setting in cleanup:
372 372 Session().delete(setting)
373 373 Session().commit()
374 374
375 375 def test_create_raises_exception_when_data_incomplete(self, repo_stub):
376 376 model = VcsSettingsModel(repo=repo_stub.repo_name)
377 377
378 378 deleted_key = 'rhodecode_pr_merge_enabled'
379 379 data = GENERAL_FORM_DATA.copy()
380 380 data.pop(deleted_key)
381 381
382 382 with pytest.raises(ValueError) as exc_info:
383 383 model._create_or_update_general_settings(model.repo_settings, data)
384 384 assert (
385 385 exc_info.value.message ==
386 386 'The given data does not contain {} key'.format(deleted_key))
387 387
388 388 def test_update_when_repo_setting_found(self, repo_stub, settings_util):
389 389 model = VcsSettingsModel(repo=repo_stub.repo_name)
390 390 for name in model.GENERAL_SETTINGS:
391 391 settings_util.create_repo_rhodecode_setting(
392 392 repo_stub, name, False, 'bool')
393 393
394 394 model._create_or_update_general_settings(
395 395 model.repo_settings, GENERAL_FORM_DATA)
396 396
397 397 for name in model.GENERAL_SETTINGS:
398 398 setting = model.repo_settings.get_setting_by_name(name)
399 399 assert setting.app_settings_value is True
400 400
401 401
402 402 class TestCreateRepoSvnSettings(object):
403 403 def test_calls_create_svn_settings(self, repo_stub):
404 404 model = VcsSettingsModel(repo=repo_stub.repo_name)
405 405 with mock.patch.object(model, '_create_svn_settings') as create_mock:
406 406 model.create_repo_svn_settings(SVN_FORM_DATA)
407 407 create_mock.assert_called_once_with(model.repo_settings, SVN_FORM_DATA)
408 408
409 409 def test_raises_exception_when_repository_is_not_specified(self):
410 410 model = VcsSettingsModel()
411 411 with pytest.raises(Exception) as exc_info:
412 412 model.create_repo_svn_settings(SVN_FORM_DATA)
413 413 assert exc_info.value.message == 'Repository is not specified'
414 414
415 415
416 416 class TestCreateSvnSettings(object):
417 417 def test_create(self, repo_stub):
418 418 model = VcsSettingsModel(repo=repo_stub.repo_name)
419 419 model._create_svn_settings(model.repo_settings, SVN_FORM_DATA)
420 420 Session().commit()
421 421
422 422 branch_ui = model.repo_settings.get_ui_by_section(
423 423 model.SVN_BRANCH_SECTION)
424 424 tag_ui = model.repo_settings.get_ui_by_section(
425 425 model.SVN_TAG_SECTION)
426 426
427 427 try:
428 428 assert len(branch_ui) == 1
429 429 assert len(tag_ui) == 1
430 430 finally:
431 431 Session().delete(branch_ui[0])
432 432 Session().delete(tag_ui[0])
433 433 Session().commit()
434 434
435 435 def test_create_tag(self, repo_stub):
436 436 model = VcsSettingsModel(repo=repo_stub.repo_name)
437 437 data = SVN_FORM_DATA.copy()
438 438 data.pop('new_svn_branch')
439 439 model._create_svn_settings(model.repo_settings, data)
440 440 Session().commit()
441 441
442 442 branch_ui = model.repo_settings.get_ui_by_section(
443 443 model.SVN_BRANCH_SECTION)
444 444 tag_ui = model.repo_settings.get_ui_by_section(
445 445 model.SVN_TAG_SECTION)
446 446
447 447 try:
448 448 assert len(branch_ui) == 0
449 449 assert len(tag_ui) == 1
450 450 finally:
451 451 Session().delete(tag_ui[0])
452 452 Session().commit()
453 453
454 454 def test_create_nothing_when_no_svn_settings_specified(self, repo_stub):
455 455 model = VcsSettingsModel(repo=repo_stub.repo_name)
456 456 model._create_svn_settings(model.repo_settings, {})
457 457 Session().commit()
458 458
459 459 branch_ui = model.repo_settings.get_ui_by_section(
460 460 model.SVN_BRANCH_SECTION)
461 461 tag_ui = model.repo_settings.get_ui_by_section(
462 462 model.SVN_TAG_SECTION)
463 463
464 464 assert len(branch_ui) == 0
465 465 assert len(tag_ui) == 0
466 466
467 467 def test_create_nothing_when_empty_settings_specified(self, repo_stub):
468 468 model = VcsSettingsModel(repo=repo_stub.repo_name)
469 469 data = {
470 470 'new_svn_branch': '',
471 471 'new_svn_tag': ''
472 472 }
473 473 model._create_svn_settings(model.repo_settings, data)
474 474 Session().commit()
475 475
476 476 branch_ui = model.repo_settings.get_ui_by_section(
477 477 model.SVN_BRANCH_SECTION)
478 478 tag_ui = model.repo_settings.get_ui_by_section(
479 479 model.SVN_TAG_SECTION)
480 480
481 481 assert len(branch_ui) == 0
482 482 assert len(tag_ui) == 0
483 483
484 484
485 485 class TestCreateOrUpdateUi(object):
486 486 def test_create(self, repo_stub):
487 487 model = VcsSettingsModel(repo=repo_stub.repo_name)
488 488 model._create_or_update_ui(
489 489 model.repo_settings, 'test-section', 'test-key', active=False,
490 490 value='False')
491 491 Session().commit()
492 492
493 493 created_ui = model.repo_settings.get_ui_by_section_and_key(
494 494 'test-section', 'test-key')
495 495
496 496 try:
497 497 assert created_ui.ui_active is False
498 498 assert str2bool(created_ui.ui_value) is False
499 499 finally:
500 500 Session().delete(created_ui)
501 501 Session().commit()
502 502
503 503 def test_update(self, repo_stub, settings_util):
504 504 model = VcsSettingsModel(repo=repo_stub.repo_name)
505 505
506 506 largefiles, phases, evolve = model.HG_SETTINGS
507 507
508 508 section = 'test-section'
509 509 key = 'test-key'
510 510 settings_util.create_repo_rhodecode_ui(
511 511 repo_stub, section, 'True', key=key, active=True)
512 512
513 513 model._create_or_update_ui(
514 514 model.repo_settings, section, key, active=False, value='False')
515 515 Session().commit()
516 516
517 517 created_ui = model.repo_settings.get_ui_by_section_and_key(
518 518 section, key)
519 519 assert created_ui.ui_active is False
520 520 assert str2bool(created_ui.ui_value) is False
521 521
522 522
523 523 class TestCreateOrUpdateRepoHgSettings(object):
524 524 FORM_DATA = {
525 525 'extensions_largefiles': False,
526 526 'extensions_evolve': False,
527 527 'phases_publish': False
528 528 }
529 529
530 530 def test_creates_repo_hg_settings_when_data_is_correct(self, repo_stub):
531 531 model = VcsSettingsModel(repo=repo_stub.repo_name)
532 532 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
533 533 model.create_or_update_repo_hg_settings(self.FORM_DATA)
534 534 expected_calls = [
535 535 mock.call(model.repo_settings, 'extensions', 'largefiles',
536 536 active=False, value=''),
537 537 mock.call(model.repo_settings, 'extensions', 'evolve',
538 538 active=False, value=''),
539 539 mock.call(model.repo_settings, 'phases', 'publish', value='False'),
540 540 ]
541 541 assert expected_calls == create_mock.call_args_list
542 542
543 543 @pytest.mark.parametrize('field_to_remove', FORM_DATA.keys())
544 544 def test_key_is_not_found(self, repo_stub, field_to_remove):
545 545 model = VcsSettingsModel(repo=repo_stub.repo_name)
546 546 data = self.FORM_DATA.copy()
547 547 data.pop(field_to_remove)
548 548 with pytest.raises(ValueError) as exc_info:
549 549 model.create_or_update_repo_hg_settings(data)
550 550 expected_message = 'The given data does not contain {} key'.format(
551 551 field_to_remove)
552 552 assert exc_info.value.message == expected_message
553 553
554 554 def test_create_raises_exception_when_repository_not_specified(self):
555 555 model = VcsSettingsModel()
556 556 with pytest.raises(Exception) as exc_info:
557 557 model.create_or_update_repo_hg_settings(self.FORM_DATA)
558 558 assert exc_info.value.message == 'Repository is not specified'
559 559
560 560
561 561 class TestUpdateGlobalSslSetting(object):
562 562 def test_updates_global_hg_settings(self):
563 563 model = VcsSettingsModel()
564 564 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
565 565 model.update_global_ssl_setting('False')
566 566 create_mock.assert_called_once_with(
567 567 model.global_settings, 'web', 'push_ssl', value='False')
568 568
569 569
570 570 class TestUpdateGlobalPathSetting(object):
571 571 def test_updates_global_path_settings(self):
572 572 model = VcsSettingsModel()
573 573 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
574 574 model.update_global_path_setting('False')
575 575 create_mock.assert_called_once_with(
576 576 model.global_settings, 'paths', '/', value='False')
577 577
578 578
579 579 class TestCreateOrUpdateGlobalHgSettings(object):
580 580 FORM_DATA = {
581 581 'extensions_largefiles': False,
582 582 'largefiles_usercache': '/example/largefiles-store',
583 583 'phases_publish': False,
584 584 'extensions_hgsubversion': False,
585 585 'extensions_evolve': False
586 586 }
587 587
588 588 def test_creates_repo_hg_settings_when_data_is_correct(self):
589 589 model = VcsSettingsModel()
590 590 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
591 591 model.create_or_update_global_hg_settings(self.FORM_DATA)
592 592 expected_calls = [
593 593 mock.call(model.global_settings, 'extensions', 'largefiles',
594 594 active=False, value=''),
595 595 mock.call(model.global_settings, 'largefiles', 'usercache',
596 596 value='/example/largefiles-store'),
597 597 mock.call(model.global_settings, 'phases', 'publish',
598 598 value='False'),
599 599 mock.call(model.global_settings, 'extensions', 'hgsubversion',
600 600 active=False),
601 601 mock.call(model.global_settings, 'extensions', 'evolve',
602 602 active=False, value='')
603 603 ]
604 604 assert expected_calls == create_mock.call_args_list
605 605
606 606 @pytest.mark.parametrize('field_to_remove', FORM_DATA.keys())
607 607 def test_key_is_not_found(self, repo_stub, field_to_remove):
608 608 model = VcsSettingsModel(repo=repo_stub.repo_name)
609 609 data = self.FORM_DATA.copy()
610 610 data.pop(field_to_remove)
611 611 with pytest.raises(Exception) as exc_info:
612 612 model.create_or_update_global_hg_settings(data)
613 613 expected_message = 'The given data does not contain {} key'.format(
614 614 field_to_remove)
615 615 assert exc_info.value.message == expected_message
616 616
617 617
618 618 class TestCreateOrUpdateGlobalGitSettings(object):
619 619 FORM_DATA = {
620 620 'vcs_git_lfs_enabled': False,
621 621 'vcs_git_lfs_store_location': '/example/lfs-store',
622 622 }
623 623
624 624 def test_creates_repo_hg_settings_when_data_is_correct(self):
625 625 model = VcsSettingsModel()
626 626 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
627 627 model.create_or_update_global_git_settings(self.FORM_DATA)
628 628 expected_calls = [
629 629 mock.call(model.global_settings, 'vcs_git_lfs', 'enabled',
630 630 active=False, value=False),
631 631 mock.call(model.global_settings, 'vcs_git_lfs', 'store_location',
632 632 value='/example/lfs-store'),
633 633 ]
634 634 assert expected_calls == create_mock.call_args_list
635 635
636 636
637 637 class TestDeleteRepoSvnPattern(object):
638 def test_success_when_repo_is_set(self, backend_svn):
638 def test_success_when_repo_is_set(self, backend_svn, settings_util):
639 repo = backend_svn.create_repo()
640 repo_name = repo.repo_name
641
642 model = VcsSettingsModel(repo=repo_name)
643 entry = settings_util.create_repo_rhodecode_ui(
644 repo, VcsSettingsModel.SVN_BRANCH_SECTION, 'svn-branch')
645 Session().commit()
646
647 model.delete_repo_svn_pattern(entry.ui_id)
648
649 def test_fail_when_delete_id_from_other_repo(self, backend_svn):
639 650 repo_name = backend_svn.repo_name
640 651 model = VcsSettingsModel(repo=repo_name)
641 652 delete_ui_patch = mock.patch.object(model.repo_settings, 'delete_ui')
642 653 with delete_ui_patch as delete_ui_mock:
643 654 model.delete_repo_svn_pattern(123)
644 delete_ui_mock.assert_called_once_with(123)
655 delete_ui_mock.assert_called_once_with(-1)
645 656
646 657 def test_raises_exception_when_repository_is_not_specified(self):
647 658 model = VcsSettingsModel()
648 659 with pytest.raises(Exception) as exc_info:
649 660 model.delete_repo_svn_pattern(123)
650 661 assert exc_info.value.message == 'Repository is not specified'
651 662
652 663
653 664 class TestDeleteGlobalSvnPattern(object):
654 665 def test_delete_global_svn_pattern_calls_delete_ui(self):
655 666 model = VcsSettingsModel()
656 667 delete_ui_patch = mock.patch.object(model.global_settings, 'delete_ui')
657 668 with delete_ui_patch as delete_ui_mock:
658 669 model.delete_global_svn_pattern(123)
659 670 delete_ui_mock.assert_called_once_with(123)
660 671
661 672
662 673 class TestFilterUiSettings(object):
663 674 def test_settings_are_filtered(self):
664 675 model = VcsSettingsModel()
665 676 repo_settings = [
666 677 UiSetting('extensions', 'largefiles', '', True),
667 678 UiSetting('phases', 'publish', 'True', True),
668 679 UiSetting('hooks', 'changegroup.repo_size', 'hook', True),
669 680 UiSetting('hooks', 'changegroup.push_logger', 'hook', True),
670 681 UiSetting('hooks', 'outgoing.pull_logger', 'hook', True),
671 682 UiSetting(
672 683 'vcs_svn_branch', '84223c972204fa545ca1b22dac7bef5b68d7442d',
673 684 'test_branch', True),
674 685 UiSetting(
675 686 'vcs_svn_tag', '84229c972204fa545ca1b22dac7bef5b68d7442d',
676 687 'test_tag', True),
677 688 ]
678 689 non_repo_settings = [
679 690 UiSetting('largefiles', 'usercache', '/example/largefiles-store', True),
680 691 UiSetting('test', 'outgoing.pull_logger', 'hook', True),
681 692 UiSetting('hooks', 'test2', 'hook', True),
682 693 UiSetting(
683 694 'vcs_svn_repo', '84229c972204fa545ca1b22dac7bef5b68d7442d',
684 695 'test_tag', True),
685 696 ]
686 697 settings = repo_settings + non_repo_settings
687 698 filtered_settings = model._filter_ui_settings(settings)
688 699 assert sorted(filtered_settings) == sorted(repo_settings)
689 700
690 701
691 702 class TestFilterGeneralSettings(object):
692 703 def test_settings_are_filtered(self):
693 704 model = VcsSettingsModel()
694 705 settings = {
695 706 'rhodecode_abcde': 'value1',
696 707 'rhodecode_vwxyz': 'value2',
697 708 }
698 709 general_settings = {
699 710 'rhodecode_{}'.format(key): 'value'
700 711 for key in VcsSettingsModel.GENERAL_SETTINGS
701 712 }
702 713 settings.update(general_settings)
703 714
704 715 filtered_settings = model._filter_general_settings(general_settings)
705 716 assert sorted(filtered_settings) == sorted(general_settings)
706 717
707 718
708 719 class TestGetRepoUiSettings(object):
709 720 def test_global_uis_are_returned_when_no_repo_uis_found(
710 721 self, repo_stub):
711 722 model = VcsSettingsModel(repo=repo_stub.repo_name)
712 723 result = model.get_repo_ui_settings()
713 724 svn_sections = (
714 725 VcsSettingsModel.SVN_TAG_SECTION,
715 726 VcsSettingsModel.SVN_BRANCH_SECTION)
716 727 expected_result = [
717 728 s for s in model.global_settings.get_ui()
718 729 if s.section not in svn_sections]
719 730 assert sorted(result) == sorted(expected_result)
720 731
721 732 def test_repo_uis_are_overriding_global_uis(
722 733 self, repo_stub, settings_util):
723 734 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
724 735 settings_util.create_repo_rhodecode_ui(
725 736 repo_stub, section, 'repo', key=key, active=False)
726 737 model = VcsSettingsModel(repo=repo_stub.repo_name)
727 738 result = model.get_repo_ui_settings()
728 739 for setting in result:
729 740 locator = (setting.section, setting.key)
730 741 if locator in VcsSettingsModel.HOOKS_SETTINGS:
731 742 assert setting.value == 'repo'
732 743
733 744 assert setting.active is False
734 745
735 746 def test_global_svn_patterns_are_not_in_list(
736 747 self, repo_stub, settings_util):
737 748 svn_sections = (
738 749 VcsSettingsModel.SVN_TAG_SECTION,
739 750 VcsSettingsModel.SVN_BRANCH_SECTION)
740 751 for section in svn_sections:
741 752 settings_util.create_rhodecode_ui(
742 753 section, 'repo', key='deadbeef' + section, active=False)
743 754 model = VcsSettingsModel(repo=repo_stub.repo_name)
744 755 result = model.get_repo_ui_settings()
745 756 for setting in result:
746 757 assert setting.section not in svn_sections
747 758
748 759 def test_repo_uis_filtered_by_section_are_returned(
749 760 self, repo_stub, settings_util):
750 761 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
751 762 settings_util.create_repo_rhodecode_ui(
752 763 repo_stub, section, 'repo', key=key, active=False)
753 764 model = VcsSettingsModel(repo=repo_stub.repo_name)
754 765 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
755 766 result = model.get_repo_ui_settings(section=section)
756 767 for setting in result:
757 768 assert setting.section == section
758 769
759 770 def test_repo_uis_filtered_by_key_are_returned(
760 771 self, repo_stub, settings_util):
761 772 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
762 773 settings_util.create_repo_rhodecode_ui(
763 774 repo_stub, section, 'repo', key=key, active=False)
764 775 model = VcsSettingsModel(repo=repo_stub.repo_name)
765 776 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
766 777 result = model.get_repo_ui_settings(key=key)
767 778 for setting in result:
768 779 assert setting.key == key
769 780
770 781 def test_raises_exception_when_repository_is_not_specified(self):
771 782 model = VcsSettingsModel()
772 783 with pytest.raises(Exception) as exc_info:
773 784 model.get_repo_ui_settings()
774 785 assert exc_info.value.message == 'Repository is not specified'
775 786
776 787
777 788 class TestGetRepoGeneralSettings(object):
778 789 def test_global_settings_are_returned_when_no_repo_settings_found(
779 790 self, repo_stub):
780 791 model = VcsSettingsModel(repo=repo_stub.repo_name)
781 792 result = model.get_repo_general_settings()
782 793 expected_result = model.global_settings.get_all_settings()
783 794 assert sorted(result) == sorted(expected_result)
784 795
785 796 def test_repo_uis_are_overriding_global_uis(
786 797 self, repo_stub, settings_util):
787 798 for key in VcsSettingsModel.GENERAL_SETTINGS:
788 799 settings_util.create_repo_rhodecode_setting(
789 800 repo_stub, key, 'abcde', type_='unicode')
790 801 model = VcsSettingsModel(repo=repo_stub.repo_name)
791 802 result = model.get_repo_ui_settings()
792 803 for key in result:
793 804 if key in VcsSettingsModel.GENERAL_SETTINGS:
794 805 assert result[key] == 'abcde'
795 806
796 807 def test_raises_exception_when_repository_is_not_specified(self):
797 808 model = VcsSettingsModel()
798 809 with pytest.raises(Exception) as exc_info:
799 810 model.get_repo_general_settings()
800 811 assert exc_info.value.message == 'Repository is not specified'
801 812
802 813
803 814 class TestGetGlobalGeneralSettings(object):
804 815 def test_global_settings_are_returned(self, repo_stub):
805 816 model = VcsSettingsModel()
806 817 result = model.get_global_general_settings()
807 818 expected_result = model.global_settings.get_all_settings()
808 819 assert sorted(result) == sorted(expected_result)
809 820
810 821 def test_repo_uis_are_not_overriding_global_uis(
811 822 self, repo_stub, settings_util):
812 823 for key in VcsSettingsModel.GENERAL_SETTINGS:
813 824 settings_util.create_repo_rhodecode_setting(
814 825 repo_stub, key, 'abcde', type_='unicode')
815 826 model = VcsSettingsModel(repo=repo_stub.repo_name)
816 827 result = model.get_global_general_settings()
817 828 expected_result = model.global_settings.get_all_settings()
818 829 assert sorted(result) == sorted(expected_result)
819 830
820 831
821 832 class TestGetGlobalUiSettings(object):
822 833 def test_global_uis_are_returned(self, repo_stub):
823 834 model = VcsSettingsModel()
824 835 result = model.get_global_ui_settings()
825 836 expected_result = model.global_settings.get_ui()
826 837 assert sorted(result) == sorted(expected_result)
827 838
828 839 def test_repo_uis_are_not_overriding_global_uis(
829 840 self, repo_stub, settings_util):
830 841 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
831 842 settings_util.create_repo_rhodecode_ui(
832 843 repo_stub, section, 'repo', key=key, active=False)
833 844 model = VcsSettingsModel(repo=repo_stub.repo_name)
834 845 result = model.get_global_ui_settings()
835 846 expected_result = model.global_settings.get_ui()
836 847 assert sorted(result) == sorted(expected_result)
837 848
838 849 def test_ui_settings_filtered_by_section(
839 850 self, repo_stub, settings_util):
840 851 model = VcsSettingsModel(repo=repo_stub.repo_name)
841 852 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
842 853 result = model.get_global_ui_settings(section=section)
843 854 expected_result = model.global_settings.get_ui(section=section)
844 855 assert sorted(result) == sorted(expected_result)
845 856
846 857 def test_ui_settings_filtered_by_key(
847 858 self, repo_stub, settings_util):
848 859 model = VcsSettingsModel(repo=repo_stub.repo_name)
849 860 section, key = VcsSettingsModel.HOOKS_SETTINGS[0]
850 861 result = model.get_global_ui_settings(key=key)
851 862 expected_result = model.global_settings.get_ui(key=key)
852 863 assert sorted(result) == sorted(expected_result)
853 864
854 865
855 866 class TestGetGeneralSettings(object):
856 867 def test_global_settings_are_returned_when_inherited_is_true(
857 868 self, repo_stub, settings_util):
858 869 model = VcsSettingsModel(repo=repo_stub.repo_name)
859 870 model.inherit_global_settings = True
860 871 for key in VcsSettingsModel.GENERAL_SETTINGS:
861 872 settings_util.create_repo_rhodecode_setting(
862 873 repo_stub, key, 'abcde', type_='unicode')
863 874 result = model.get_general_settings()
864 875 expected_result = model.get_global_general_settings()
865 876 assert sorted(result) == sorted(expected_result)
866 877
867 878 def test_repo_settings_are_returned_when_inherited_is_false(
868 879 self, repo_stub, settings_util):
869 880 model = VcsSettingsModel(repo=repo_stub.repo_name)
870 881 model.inherit_global_settings = False
871 882 for key in VcsSettingsModel.GENERAL_SETTINGS:
872 883 settings_util.create_repo_rhodecode_setting(
873 884 repo_stub, key, 'abcde', type_='unicode')
874 885 result = model.get_general_settings()
875 886 expected_result = model.get_repo_general_settings()
876 887 assert sorted(result) == sorted(expected_result)
877 888
878 889 def test_global_settings_are_returned_when_no_repository_specified(self):
879 890 model = VcsSettingsModel()
880 891 result = model.get_general_settings()
881 892 expected_result = model.get_global_general_settings()
882 893 assert sorted(result) == sorted(expected_result)
883 894
884 895
885 896 class TestGetUiSettings(object):
886 897 def test_global_settings_are_returned_when_inherited_is_true(
887 898 self, repo_stub, settings_util):
888 899 model = VcsSettingsModel(repo=repo_stub.repo_name)
889 900 model.inherit_global_settings = True
890 901 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
891 902 settings_util.create_repo_rhodecode_ui(
892 903 repo_stub, section, 'repo', key=key, active=True)
893 904 result = model.get_ui_settings()
894 905 expected_result = model.get_global_ui_settings()
895 906 assert sorted(result) == sorted(expected_result)
896 907
897 908 def test_repo_settings_are_returned_when_inherited_is_false(
898 909 self, repo_stub, settings_util):
899 910 model = VcsSettingsModel(repo=repo_stub.repo_name)
900 911 model.inherit_global_settings = False
901 912 for section, key in VcsSettingsModel.HOOKS_SETTINGS:
902 913 settings_util.create_repo_rhodecode_ui(
903 914 repo_stub, section, 'repo', key=key, active=True)
904 915 result = model.get_ui_settings()
905 916 expected_result = model.get_repo_ui_settings()
906 917 assert sorted(result) == sorted(expected_result)
907 918
908 919 def test_repo_settings_filtered_by_section_and_key(self, repo_stub):
909 920 model = VcsSettingsModel(repo=repo_stub.repo_name)
910 921 model.inherit_global_settings = False
911 922 args = ('section', 'key')
912 923 with mock.patch.object(model, 'get_repo_ui_settings') as settings_mock:
913 924 model.get_ui_settings(*args)
914 925 settings_mock.assert_called_once_with(*args)
915 926
916 927 def test_global_settings_filtered_by_section_and_key(self):
917 928 model = VcsSettingsModel()
918 929 args = ('section', 'key')
919 930 with mock.patch.object(model, 'get_global_ui_settings') as (
920 931 settings_mock):
921 932 model.get_ui_settings(*args)
922 933 settings_mock.assert_called_once_with(*args)
923 934
924 935 def test_global_settings_are_returned_when_no_repository_specified(self):
925 936 model = VcsSettingsModel()
926 937 result = model.get_ui_settings()
927 938 expected_result = model.get_global_ui_settings()
928 939 assert sorted(result) == sorted(expected_result)
929 940
930 941
931 942 class TestGetSvnPatterns(object):
932 943 def test_repo_settings_filtered_by_section_and_key(self, repo_stub):
933 944 model = VcsSettingsModel(repo=repo_stub.repo_name)
934 945 args = ('section', )
935 946 with mock.patch.object(model, 'get_repo_ui_settings') as settings_mock:
936 947 model.get_svn_patterns(*args)
937 948 settings_mock.assert_called_once_with(*args)
938 949
939 950 def test_global_settings_filtered_by_section_and_key(self):
940 951 model = VcsSettingsModel()
941 952 args = ('section', )
942 953 with mock.patch.object(model, 'get_global_ui_settings') as (
943 954 settings_mock):
944 955 model.get_svn_patterns(*args)
945 956 settings_mock.assert_called_once_with(*args)
946 957
947 958
948 959 class TestGetReposLocation(object):
949 960 def test_returns_repos_location(self, repo_stub):
950 961 model = VcsSettingsModel()
951 962
952 963 result_mock = mock.Mock()
953 964 result_mock.ui_value = '/tmp'
954 965
955 966 with mock.patch.object(model, 'global_settings') as settings_mock:
956 967 settings_mock.get_ui_by_key.return_value = result_mock
957 968 result = model.get_repos_location()
958 969
959 970 settings_mock.get_ui_by_key.assert_called_once_with('/')
960 971 assert result == '/tmp'
961 972
962 973
963 974 class TestCreateOrUpdateRepoSettings(object):
964 975 FORM_DATA = {
965 976 'inherit_global_settings': False,
966 977 'hooks_changegroup_repo_size': False,
967 978 'hooks_changegroup_push_logger': False,
968 979 'hooks_outgoing_pull_logger': False,
969 980 'extensions_largefiles': False,
970 981 'extensions_evolve': False,
971 982 'largefiles_usercache': '/example/largefiles-store',
972 983 'vcs_git_lfs_enabled': False,
973 984 'vcs_git_lfs_store_location': '/',
974 985 'phases_publish': 'False',
975 986 'rhodecode_pr_merge_enabled': False,
976 987 'rhodecode_use_outdated_comments': False,
977 988 'new_svn_branch': '',
978 989 'new_svn_tag': ''
979 990 }
980 991
981 992 def test_get_raises_exception_when_repository_not_specified(self):
982 993 model = VcsSettingsModel()
983 994 with pytest.raises(Exception) as exc_info:
984 995 model.create_or_update_repo_settings(data=self.FORM_DATA)
985 996 assert exc_info.value.message == 'Repository is not specified'
986 997
987 998 def test_only_svn_settings_are_updated_when_type_is_svn(self, backend_svn):
988 999 repo = backend_svn.create_repo()
989 1000 model = VcsSettingsModel(repo=repo)
990 1001 with self._patch_model(model) as mocks:
991 1002 model.create_or_update_repo_settings(
992 1003 data=self.FORM_DATA, inherit_global_settings=False)
993 1004 mocks['create_repo_svn_settings'].assert_called_once_with(
994 1005 self.FORM_DATA)
995 1006 non_called_methods = (
996 1007 'create_or_update_repo_hook_settings',
997 1008 'create_or_update_repo_pr_settings',
998 1009 'create_or_update_repo_hg_settings')
999 1010 for method in non_called_methods:
1000 1011 assert mocks[method].call_count == 0
1001 1012
1002 1013 def test_non_svn_settings_are_updated_when_type_is_hg(self, backend_hg):
1003 1014 repo = backend_hg.create_repo()
1004 1015 model = VcsSettingsModel(repo=repo)
1005 1016 with self._patch_model(model) as mocks:
1006 1017 model.create_or_update_repo_settings(
1007 1018 data=self.FORM_DATA, inherit_global_settings=False)
1008 1019
1009 1020 assert mocks['create_repo_svn_settings'].call_count == 0
1010 1021 called_methods = (
1011 1022 'create_or_update_repo_hook_settings',
1012 1023 'create_or_update_repo_pr_settings',
1013 1024 'create_or_update_repo_hg_settings')
1014 1025 for method in called_methods:
1015 1026 mocks[method].assert_called_once_with(self.FORM_DATA)
1016 1027
1017 1028 def test_non_svn_and_hg_settings_are_updated_when_type_is_git(
1018 1029 self, backend_git):
1019 1030 repo = backend_git.create_repo()
1020 1031 model = VcsSettingsModel(repo=repo)
1021 1032 with self._patch_model(model) as mocks:
1022 1033 model.create_or_update_repo_settings(
1023 1034 data=self.FORM_DATA, inherit_global_settings=False)
1024 1035
1025 1036 assert mocks['create_repo_svn_settings'].call_count == 0
1026 1037 called_methods = (
1027 1038 'create_or_update_repo_hook_settings',
1028 1039 'create_or_update_repo_pr_settings')
1029 1040 non_called_methods = (
1030 1041 'create_repo_svn_settings',
1031 1042 'create_or_update_repo_hg_settings'
1032 1043 )
1033 1044 for method in called_methods:
1034 1045 mocks[method].assert_called_once_with(self.FORM_DATA)
1035 1046 for method in non_called_methods:
1036 1047 assert mocks[method].call_count == 0
1037 1048
1038 1049 def test_no_methods_are_called_when_settings_are_inherited(
1039 1050 self, backend):
1040 1051 repo = backend.create_repo()
1041 1052 model = VcsSettingsModel(repo=repo)
1042 1053 with self._patch_model(model) as mocks:
1043 1054 model.create_or_update_repo_settings(
1044 1055 data=self.FORM_DATA, inherit_global_settings=True)
1045 1056 for method_name in mocks:
1046 1057 assert mocks[method_name].call_count == 0
1047 1058
1048 1059 def test_cache_is_marked_for_invalidation(self, repo_stub):
1049 1060 model = VcsSettingsModel(repo=repo_stub)
1050 1061 invalidation_patcher = mock.patch(
1051 1062 'rhodecode.model.scm.ScmModel.mark_for_invalidation')
1052 1063 with invalidation_patcher as invalidation_mock:
1053 1064 model.create_or_update_repo_settings(
1054 1065 data=self.FORM_DATA, inherit_global_settings=True)
1055 1066 invalidation_mock.assert_called_once_with(
1056 1067 repo_stub.repo_name, delete=True)
1057 1068
1058 1069 def test_inherit_flag_is_saved(self, repo_stub):
1059 1070 model = VcsSettingsModel(repo=repo_stub)
1060 1071 model.inherit_global_settings = True
1061 1072 with self._patch_model(model):
1062 1073 model.create_or_update_repo_settings(
1063 1074 data=self.FORM_DATA, inherit_global_settings=False)
1064 1075 assert model.inherit_global_settings is False
1065 1076
1066 1077 def _patch_model(self, model):
1067 1078 return mock.patch.multiple(
1068 1079 model,
1069 1080 create_repo_svn_settings=mock.DEFAULT,
1070 1081 create_or_update_repo_hook_settings=mock.DEFAULT,
1071 1082 create_or_update_repo_pr_settings=mock.DEFAULT,
1072 1083 create_or_update_repo_hg_settings=mock.DEFAULT)
General Comments 0
You need to be logged in to leave comments. Login now