##// END OF EJS Templates
git-lfs: settings for GIT repos to enable git-lfs and set store location...
marcink -
r1570:f2271c3d default
parent child Browse files
Show More
@@ -82,7 +82,7 b' class SettingsController(BaseController)'
82 rhodecode.CONFIG.get('labs_settings_active', 'true'))
82 rhodecode.CONFIG.get('labs_settings_active', 'true'))
83 c.navlist = navigation_list(request)
83 c.navlist = navigation_list(request)
84
84
85 def _get_hg_ui_settings(self):
85 def _get_ui_settings(self):
86 ret = RhodeCodeUi.query().all()
86 ret = RhodeCodeUi.query().all()
87
87
88 if not ret:
88 if not ret:
@@ -94,7 +94,7 b' class SettingsController(BaseController)'
94 if k == '/':
94 if k == '/':
95 k = 'root_path'
95 k = 'root_path'
96
96
97 if k in ['push_ssl', 'publish']:
97 if k in ['push_ssl', 'publish', 'enabled']:
98 v = str2bool(v)
98 v = str2bool(v)
99
99
100 if k.find('.') != -1:
100 if k.find('.') != -1:
@@ -165,6 +165,7 b' class SettingsController(BaseController)'
165
165
166 model.create_or_update_global_svn_settings(form_result)
166 model.create_or_update_global_svn_settings(form_result)
167 model.create_or_update_global_hg_settings(form_result)
167 model.create_or_update_global_hg_settings(form_result)
168 model.create_or_update_global_git_settings(form_result)
168 model.create_or_update_global_pr_settings(form_result)
169 model.create_or_update_global_pr_settings(form_result)
169 except Exception:
170 except Exception:
170 log.exception("Exception while updating settings")
171 log.exception("Exception while updating settings")
@@ -668,7 +669,8 b' class SettingsController(BaseController)'
668
669
669 def _form_defaults(self):
670 def _form_defaults(self):
670 defaults = SettingsModel().get_all_settings()
671 defaults = SettingsModel().get_all_settings()
671 defaults.update(self._get_hg_ui_settings())
672 defaults.update(self._get_ui_settings())
673
672 defaults.update({
674 defaults.update({
673 'new_svn_branch': '',
675 'new_svn_branch': '',
674 'new_svn_tag': '',
676 'new_svn_tag': '',
@@ -378,13 +378,19 b' class _BaseVcsSettingsForm(formencode.Sc'
378 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
378 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
379 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
379 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
380
380
381 # PR/Code-review
382 rhodecode_pr_merge_enabled = v.StringBoolean(if_missing=False)
383 rhodecode_use_outdated_comments = v.StringBoolean(if_missing=False)
384
385 # hg
381 extensions_largefiles = v.StringBoolean(if_missing=False)
386 extensions_largefiles = v.StringBoolean(if_missing=False)
382 phases_publish = v.StringBoolean(if_missing=False)
387 phases_publish = v.StringBoolean(if_missing=False)
383
384 rhodecode_pr_merge_enabled = v.StringBoolean(if_missing=False)
385 rhodecode_use_outdated_comments = v.StringBoolean(if_missing=False)
386 rhodecode_hg_use_rebase_for_merging = v.StringBoolean(if_missing=False)
388 rhodecode_hg_use_rebase_for_merging = v.StringBoolean(if_missing=False)
387
389
390 # git
391 vcs_git_lfs_enabled = v.StringBoolean(if_missing=False)
392
393 # svn
388 vcs_svn_proxy_http_requests_enabled = v.StringBoolean(if_missing=False)
394 vcs_svn_proxy_http_requests_enabled = v.StringBoolean(if_missing=False)
389 vcs_svn_proxy_http_server_url = v.UnicodeString(strip=True, if_missing=None)
395 vcs_svn_proxy_http_server_url = v.UnicodeString(strip=True, if_missing=None)
390
396
@@ -398,8 +404,10 b' def ApplicationUiSettingsForm():'
398 )
404 )
399 largefiles_usercache = All(
405 largefiles_usercache = All(
400 v.ValidPath(),
406 v.ValidPath(),
401 v.UnicodeString(strip=True, min=2, not_empty=True)
407 v.UnicodeString(strip=True, min=2, not_empty=True))
402 )
408 vcs_git_lfs_store_location = All(
409 v.ValidPath(),
410 v.UnicodeString(strip=True, min=2, not_empty=True))
403 extensions_hgsubversion = v.StringBoolean(if_missing=False)
411 extensions_hgsubversion = v.StringBoolean(if_missing=False)
404 extensions_hggit = v.StringBoolean(if_missing=False)
412 extensions_hggit = v.StringBoolean(if_missing=False)
405 new_svn_branch = v.ValidSvnPattern(section='vcs_svn_branch')
413 new_svn_branch = v.ValidSvnPattern(section='vcs_svn_branch')
@@ -410,15 +410,21 b' class VcsSettingsModel(object):'
410 HOOKS_SETTINGS = (
410 HOOKS_SETTINGS = (
411 ('hooks', 'changegroup.repo_size'),
411 ('hooks', 'changegroup.repo_size'),
412 ('hooks', 'changegroup.push_logger'),
412 ('hooks', 'changegroup.push_logger'),
413 ('hooks', 'outgoing.pull_logger'))
413 ('hooks', 'outgoing.pull_logger'),)
414 HG_SETTINGS = (
414 HG_SETTINGS = (
415 ('extensions', 'largefiles'),
415 ('extensions', 'largefiles'),
416 ('phases', 'publish'))
416 ('phases', 'publish'),)
417 GIT_SETTINGS = (
418 ('vcs_git_lfs', 'enabled'),)
419
417 GLOBAL_HG_SETTINGS = (
420 GLOBAL_HG_SETTINGS = (
418 ('extensions', 'largefiles'),
421 ('extensions', 'largefiles'),
419 ('largefiles', 'usercache'),
422 ('largefiles', 'usercache'),
420 ('phases', 'publish'),
423 ('phases', 'publish'),
421 ('extensions', 'hgsubversion'))
424 ('extensions', 'hgsubversion'))
425 GLOBAL_GIT_SETTINGS = (
426 ('vcs_git_lfs', 'enabled'),
427 ('vcs_git_lfs', 'store_location'))
422 GLOBAL_SVN_SETTINGS = (
428 GLOBAL_SVN_SETTINGS = (
423 ('vcs_svn_proxy', 'http_requests_enabled'),
429 ('vcs_svn_proxy', 'http_requests_enabled'),
424 ('vcs_svn_proxy', 'http_server_url'))
430 ('vcs_svn_proxy', 'http_server_url'))
@@ -431,7 +437,8 b' class VcsSettingsModel(object):'
431 def __init__(self, sa=None, repo=None):
437 def __init__(self, sa=None, repo=None):
432 self.global_settings = SettingsModel(sa=sa)
438 self.global_settings = SettingsModel(sa=sa)
433 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
439 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
434 self._ui_settings = self.HG_SETTINGS + self.HOOKS_SETTINGS
440 self._ui_settings = (
441 self.HG_SETTINGS + self.GIT_SETTINGS + self.HOOKS_SETTINGS)
435 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
442 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
436
443
437 @property
444 @property
@@ -485,6 +492,9 b' class VcsSettingsModel(object):'
485 if repo.repo_type == 'hg':
492 if repo.repo_type == 'hg':
486 self.create_or_update_repo_hg_settings(data)
493 self.create_or_update_repo_hg_settings(data)
487
494
495 if repo.repo_type == 'git':
496 self.create_or_update_repo_git_settings(data)
497
488 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
498 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
489
499
490 @assert_repo_settings
500 @assert_repo_settings
@@ -534,9 +544,11 b' class VcsSettingsModel(object):'
534
544
535 @assert_repo_settings
545 @assert_repo_settings
536 def create_or_update_repo_hg_settings(self, data):
546 def create_or_update_repo_hg_settings(self, data):
537 largefiles, phases = self.HG_SETTINGS
547 largefiles, phases = \
538 largefiles_key, phases_key = self._get_settings_keys(
548 self.HG_SETTINGS
539 self.HG_SETTINGS, data)
549 largefiles_key, phases_key = \
550 self._get_settings_keys(self.HG_SETTINGS, data)
551
540 self._create_or_update_ui(
552 self._create_or_update_ui(
541 self.repo_settings, *largefiles, value='',
553 self.repo_settings, *largefiles, value='',
542 active=data[largefiles_key])
554 active=data[largefiles_key])
@@ -548,7 +560,6 b' class VcsSettingsModel(object):'
548 = self.GLOBAL_HG_SETTINGS
560 = self.GLOBAL_HG_SETTINGS
549 largefiles_key, largefiles_store_key, phases_key, subversion_key \
561 largefiles_key, largefiles_store_key, phases_key, subversion_key \
550 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS, data)
562 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS, data)
551
552 self._create_or_update_ui(
563 self._create_or_update_ui(
553 self.global_settings, *largefiles, value='',
564 self.global_settings, *largefiles, value='',
554 active=data[largefiles_key])
565 active=data[largefiles_key])
@@ -560,6 +571,31 b' class VcsSettingsModel(object):'
560 self._create_or_update_ui(
571 self._create_or_update_ui(
561 self.global_settings, *hgsubversion, active=data[subversion_key])
572 self.global_settings, *hgsubversion, active=data[subversion_key])
562
573
574 def create_or_update_repo_git_settings(self, data):
575 # NOTE(marcink): # comma make unpack work properly
576 lfs_enabled, \
577 = self.GIT_SETTINGS
578
579 lfs_enabled_key, \
580 = self._get_settings_keys(self.GIT_SETTINGS, data)
581
582 self._create_or_update_ui(
583 self.repo_settings, *lfs_enabled, value=data[lfs_enabled_key],
584 active=data[lfs_enabled_key])
585
586 def create_or_update_global_git_settings(self, data):
587 lfs_enabled, lfs_store_location \
588 = self.GLOBAL_GIT_SETTINGS
589 lfs_enabled_key, lfs_store_location_key \
590 = self._get_settings_keys(self.GLOBAL_GIT_SETTINGS, data)
591
592 self._create_or_update_ui(
593 self.global_settings, *lfs_enabled, value=data[lfs_enabled_key],
594 active=data[lfs_enabled_key])
595 self._create_or_update_ui(
596 self.global_settings, *lfs_store_location,
597 value=data[lfs_store_location_key])
598
563 def create_or_update_global_svn_settings(self, data):
599 def create_or_update_global_svn_settings(self, data):
564 # branch/tags patterns
600 # branch/tags patterns
565 self._create_svn_settings(self.global_settings, data)
601 self._create_svn_settings(self.global_settings, data)
@@ -677,9 +713,12 b' class VcsSettingsModel(object):'
677 for section, key in self._ui_settings:
713 for section, key in self._ui_settings:
678 ui = settings.get_ui_by_section_and_key(section, key)
714 ui = settings.get_ui_by_section_and_key(section, key)
679 result_key = self._get_form_ui_key(section, key)
715 result_key = self._get_form_ui_key(section, key)
716
680 if ui:
717 if ui:
681 if section in ('hooks', 'extensions'):
718 if section in ('hooks', 'extensions'):
682 result[result_key] = ui.ui_active
719 result[result_key] = ui.ui_active
720 elif result_key in ['vcs_git_lfs_enabled']:
721 result[result_key] = ui.ui_active
683 else:
722 else:
684 result[result_key] = ui.ui_value
723 result[result_key] = ui.ui_value
685
724
@@ -154,6 +154,39 b''
154
154
155 % endif
155 % endif
156
156
157 % if display_globals or repo_type in ['git']:
158 <div class="panel panel-default">
159 <div class="panel-heading">
160 <h3 class="panel-title">${_('Git Settings')}</h3>
161 </div>
162 <div class="panel-body">
163 <div class="checkbox">
164 ${h.checkbox('vcs_git_lfs_enabled' + suffix, 'True', **kwargs)}
165 <label for="vcs_git_lfs_enabled${suffix}">${_('Enable lfs extension')}</label>
166 </div>
167 <div class="label">
168 % if display_globals:
169 <span class="help-block">${_('Enable lfs extensions for all repositories.')}</span>
170 % else:
171 <span class="help-block">${_('Enable lfs extensions for this repository.')}</span>
172 % endif
173 </div>
174
175 % if display_globals:
176 <div class="field">
177 <div class="input">
178 ${h.text('vcs_git_lfs_store_location' + suffix, size=59)}
179 </div>
180 </div>
181 <div class="label">
182 <span class="help-block">${_('Filesystem location where Git lfs objects should be stored.')}</span>
183 </div>
184 % endif
185 </div>
186 </div>
187 % endif
188
189
157 % if display_globals:
190 % if display_globals:
158 <div class="panel panel-default">
191 <div class="panel panel-default">
159 <div class="panel-heading">
192 <div class="panel-heading">
@@ -20,7 +20,10 b''
20
20
21 import pytest
21 import pytest
22 import urlparse
22 import urlparse
23 import mock
24 import simplejson as json
23
25
26 from rhodecode.lib.vcs.backends.base import Config
24 from rhodecode.tests.lib.middleware import mock_scm_app
27 from rhodecode.tests.lib.middleware import mock_scm_app
25 import rhodecode.lib.middleware.simplegit as simplegit
28 import rhodecode.lib.middleware.simplegit as simplegit
26
29
@@ -107,22 +110,24 b' def test_get_repository_name(url, expect'
107 get_environ(url, request_method))
110 get_environ(url, request_method))
108
111
109
112
110 def test_get_config(pylonsapp):
113 def test_get_config(pylonsapp, user_util):
114 repo = user_util.create_repo(repo_type='git')
111 app = simplegit.SimpleGit(application=None,
115 app = simplegit.SimpleGit(application=None,
112 config={'auth_ret_code': '', 'base_path': ''},
116 config={'auth_ret_code': '', 'base_path': ''},
113 registry=None)
117 registry=None)
114 extras = {'foo': 'FOO', 'bar': 'BAR'}
118 extras = {'foo': 'FOO', 'bar': 'BAR'}
115
119
116 # We copy the extras as the method below will change the contents.
120 # We copy the extras as the method below will change the contents.
117 config = app._create_config(dict(extras), repo_name='test-repo')
121 git_config = app._create_config(dict(extras), repo_name=repo.repo_name)
122
118 expected_config = dict(extras)
123 expected_config = dict(extras)
119 expected_config.update({
124 expected_config.update({
120 'git_update_server_info': False,
125 'git_update_server_info': False,
121 'git_lfs_enabled': True,
126 'git_lfs_enabled': False,
122 'git_lfs_store_path': simplegit.default_lfs_store()
127 'git_lfs_store_path': git_config['git_lfs_store_path']
123 })
128 })
124
129
125 assert config == expected_config
130 assert git_config == expected_config
126
131
127
132
128 def test_create_wsgi_app_uses_scm_app_from_simplevcs(pylonsapp):
133 def test_create_wsgi_app_uses_scm_app_from_simplevcs(pylonsapp):
@@ -78,30 +78,42 b' def test_get_repository_name(url, expect'
78 assert expected_repo_name == app._get_repository_name(get_environ(url))
78 assert expected_repo_name == app._get_repository_name(get_environ(url))
79
79
80
80
81 def test_get_config():
81 def test_get_config(pylonsapp, user_util):
82 repo = user_util.create_repo(repo_type='git')
82 app = simplehg.SimpleHg(application=None,
83 app = simplehg.SimpleHg(application=None,
83 config={'auth_ret_code': '', 'base_path': ''},
84 config={'auth_ret_code': '', 'base_path': ''},
84 registry=None)
85 registry=None)
85 extras = {'foo': 'FOO', 'bar': 'BAR'}
86 extras = {'foo': 'FOO', 'bar': 'BAR'}
86
87
87 mock_config = Config()
88 hg_config = app._create_config(extras, repo_name=repo.repo_name)
88 mock_config.set('a1', 'b1', 'c1')
89
89 mock_config.set('a2', 'b2', 'c2')
90 config = simplehg.utils.make_db_config(repo=repo.repo_name)
90 # We mock the call to make_db_config, otherwise we need to wait for the
91 config.set('rhodecode', 'RC_SCM_DATA', json.dumps(extras))
91 # pylonsaspp
92 hg_config_org = config
92 with mock.patch('rhodecode.lib.utils.make_db_config',
93 return_value=mock_config) as make_db_config_mock:
94 hg_config = app._create_config(extras, repo_name='test-repo')
95
93
96 make_db_config_mock.assert_called_once_with(repo='test-repo')
94 expected_config = [
97 assert isinstance(hg_config, list)
95 ('vcs_svn_tag', 'ff89f8c714d135d865f44b90e5413b88de19a55f', '/tags/*'),
98
96 ('web', 'push_ssl', 'False'),
99 # Remove the entries from the mock_config so to get only the extras
97 ('web', 'allow_push', '*'),
100 hg_config.remove(('a1', 'b1', 'c1'))
98 ('web', 'allow_archive', 'gz zip bz2'),
101 hg_config.remove(('a2', 'b2', 'c2'))
99 ('web', 'baseurl', '/'),
102
100 ('vcs_git_lfs', 'store_location', hg_config_org.get('vcs_git_lfs', 'store_location')),
103 assert hg_config[0][:2] == ('rhodecode', 'RC_SCM_DATA')
101 ('vcs_svn_branch', '9aac1a38c3b8a0cdc4ae0f960a5f83332bc4fa5e', '/branches/*'),
104 assert json.loads(hg_config[0][-1]) == extras
102 ('vcs_svn_branch', 'c7e6a611c87da06529fd0dd733308481d67c71a8', '/trunk'),
103 ('largefiles', 'usercache', hg_config_org.get('largefiles', 'usercache')),
104 ('hooks', 'preoutgoing.pre_pull', 'python:vcsserver.hooks.pre_pull'),
105 ('hooks', 'prechangegroup.pre_push', 'python:vcsserver.hooks.pre_push'),
106 ('hooks', 'outgoing.pull_logger', 'python:vcsserver.hooks.log_pull_action'),
107 ('hooks', 'pretxnchangegroup.pre_push', 'python:vcsserver.hooks.pre_push'),
108 ('hooks', 'changegroup.push_logger', 'python:vcsserver.hooks.log_push_action'),
109 ('hooks', 'changegroup.repo_size', 'python:vcsserver.hooks.repo_size'),
110 ('phases', 'publish', 'True'),
111 ('extensions', 'largefiles', ''),
112 ('paths', '/', hg_config_org.get('paths', '/')),
113 ('rhodecode', 'RC_SCM_DATA', '{"foo": "FOO", "bar": "BAR"}')
114 ]
115 for entry in expected_config:
116 assert entry in hg_config
105
117
106
118
107 def test_create_wsgi_app_uses_scm_app_from_simplevcs():
119 def test_create_wsgi_app_uses_scm_app_from_simplevcs():
@@ -176,7 +176,7 b' class TestVcsSettingsModel(object):'
176 settings_mock.get_setting_by_name.return_value = result_mock
176 settings_mock.get_setting_by_name.return_value = result_mock
177 result = model._collect_all_settings(global_=global_)
177 result = model._collect_all_settings(global_=global_)
178
178
179 ui_settings = model.HG_SETTINGS + model.HOOKS_SETTINGS
179 ui_settings = model.HG_SETTINGS + model.GIT_SETTINGS + model.HOOKS_SETTINGS
180 self._assert_get_settings_calls(
180 self._assert_get_settings_calls(
181 settings_mock, ui_settings, model.GENERAL_SETTINGS)
181 settings_mock, ui_settings, model.GENERAL_SETTINGS)
182 self._assert_collect_all_settings_result(
182 self._assert_collect_all_settings_result(
@@ -230,7 +230,13 b' class TestVcsSettingsModel(object):'
230 expected_result = {}
230 expected_result = {}
231 for section, key in ui_settings:
231 for section, key in ui_settings:
232 key = '{}_{}'.format(section, key.replace('.', '_'))
232 key = '{}_{}'.format(section, key.replace('.', '_'))
233 value = True if section in ('extensions', 'hooks') else 'ui_value'
233
234 if section in ('extensions', 'hooks'):
235 value = True
236 elif key in ['vcs_git_lfs_enabled']:
237 value = True
238 else:
239 value = 'ui_value'
234 expected_result[key] = value
240 expected_result[key] = value
235
241
236 for name in general_settings:
242 for name in general_settings:
@@ -599,6 +605,25 b' class TestCreateOrUpdateGlobalHgSettings'
599 assert exc_info.value.message == expected_message
605 assert exc_info.value.message == expected_message
600
606
601
607
608 class TestCreateOrUpdateGlobalGitSettings(object):
609 FORM_DATA = {
610 'vcs_git_lfs_enabled': False,
611 'vcs_git_lfs_store_location': '/example/lfs-store',
612 }
613
614 def test_creates_repo_hg_settings_when_data_is_correct(self):
615 model = VcsSettingsModel()
616 with mock.patch.object(model, '_create_or_update_ui') as create_mock:
617 model.create_or_update_global_git_settings(self.FORM_DATA)
618 expected_calls = [
619 mock.call(model.global_settings, 'vcs_git_lfs', 'enabled',
620 active=False, value=False),
621 mock.call(model.global_settings, 'vcs_git_lfs', 'store_location',
622 value='/example/lfs-store'),
623 ]
624 assert expected_calls == create_mock.call_args_list
625
626
602 class TestDeleteRepoSvnPattern(object):
627 class TestDeleteRepoSvnPattern(object):
603 def test_success_when_repo_is_set(self, backend_svn):
628 def test_success_when_repo_is_set(self, backend_svn):
604 repo_name = backend_svn.repo_name
629 repo_name = backend_svn.repo_name
@@ -933,6 +958,8 b' class TestCreateOrUpdateRepoSettings(obj'
933 'hooks_outgoing_pull_logger': False,
958 'hooks_outgoing_pull_logger': False,
934 'extensions_largefiles': False,
959 'extensions_largefiles': False,
935 'largefiles_usercache': '/example/largefiles-store',
960 'largefiles_usercache': '/example/largefiles-store',
961 'vcs_git_lfs_enabled': False,
962 'vcs_git_lfs_store_location': '/',
936 'phases_publish': 'False',
963 'phases_publish': 'False',
937 'rhodecode_pr_merge_enabled': False,
964 'rhodecode_pr_merge_enabled': False,
938 'rhodecode_use_outdated_comments': False,
965 'rhodecode_use_outdated_comments': False,
General Comments 0
You need to be logged in to leave comments. Login now