##// END OF EJS Templates
integrations: add recursive repo group scope to allow integrations...
dan -
r793:fc8d2069 default
parent child Browse files
Show More
@@ -40,7 +40,7 b' from rhodecode.admin.navigation import n'
40 40 from rhodecode.translation import _
41 41 from rhodecode.integrations import integration_type_registry
42 42 from rhodecode.model.validation_schema.schemas.integration_schema import (
43 make_integration_schema)
43 make_integration_schema, IntegrationScopeType)
44 44
45 45 log = logging.getLogger(__name__)
46 46
@@ -151,7 +151,11 b' class IntegrationSettingsViewBase(object'
151 151 defaults['options'] = {
152 152 'name': self.integration.name,
153 153 'enabled': self.integration.enabled,
154 'scope': self.integration.scope,
154 'scope': {
155 'repo': self.integration.repo,
156 'repo_group': self.integration.repo_group,
157 'child_repos_only': self.integration.child_repos_only,
158 },
155 159 }
156 160 else:
157 161 if self.repo:
@@ -168,10 +172,10 b' class IntegrationSettingsViewBase(object'
168 172 'name': _('{name} integration').format(
169 173 name=self.IntegrationType.display_name),
170 174 }
171 if self.repo:
172 defaults['options']['scope'] = self.repo
173 elif self.repo_group:
174 defaults['options']['scope'] = self.repo_group
175 defaults['options']['scope'] = {
176 'repo': self.repo,
177 'repo_group': self.repo_group,
178 }
175 179
176 180 return defaults
177 181
@@ -250,11 +254,10 b' class IntegrationSettingsViewBase(object'
250 254 # scope is read only field in these cases, and has to be added
251 255 options = pstruct.setdefault('options', {})
252 256 if 'scope' not in options:
253 if self.repo:
254 options['scope'] = 'repo:{}'.format(self.repo.repo_name)
255 elif self.repo_group:
256 options['scope'] = 'repogroup:{}'.format(
257 self.repo_group.group_name)
257 options['scope'] = IntegrationScopeType().serialize(None, {
258 'repo': self.repo,
259 'repo_group': self.repo_group,
260 })
258 261
259 262 try:
260 263 valid_data = form.validate_pstruct(pstruct)
@@ -276,7 +279,11 b' class IntegrationSettingsViewBase(object'
276 279 name=valid_data['options']['name'],
277 280 enabled=valid_data['options']['enabled'],
278 281 settings=valid_data['settings'],
279 scope=scope)
282 repo=scope['repo'],
283 repo_group=scope['repo_group'],
284 child_repos_only=scope['child_repos_only'],
285 )
286
280 287
281 288 self.integration.settings = valid_data['settings']
282 289 Session().commit()
@@ -291,16 +298,16 b' class IntegrationSettingsViewBase(object'
291 298 # keeping in mind if the original view was for /repo/ or /_admin/
292 299 admin_view = not (self.repo or self.repo_group)
293 300
294 if isinstance(self.integration.scope, Repository) and not admin_view:
301 if self.integration.repo and not admin_view:
295 302 redirect_to = self.request.route_path(
296 303 'repo_integrations_edit',
297 repo_name=self.integration.scope.repo_name,
304 repo_name=self.integration.repo.repo_name,
298 305 integration=self.integration.integration_type,
299 306 integration_id=self.integration.integration_id)
300 elif isinstance(self.integration.scope, RepoGroup) and not admin_view:
307 elif self.integration.repo_group and not admin_view:
301 308 redirect_to = self.request.route_path(
302 309 'repo_group_integrations_edit',
303 repo_group_name=self.integration.scope.group_name,
310 repo_group_name=self.integration.repo_group.group_name,
304 311 integration=self.integration.integration_type,
305 312 integration_id=self.integration.integration_id)
306 313 else:
@@ -3499,36 +3499,18 b' class Integration(Base, BaseModel):'
3499 3499 nullable=True, unique=None, default=None)
3500 3500 repo_group = relationship('RepoGroup', lazy='joined')
3501 3501
3502 @hybrid_property
3502 @property
3503 3503 def scope(self):
3504 3504 if self.repo:
3505 return self.repo
3505 return repr(self.repo)
3506 3506 if self.repo_group:
3507 return self.repo_group
3507 if self.child_repos_only:
3508 return repr(self.repo_group) + ' (child repos only)'
3509 else:
3510 return repr(self.repo_group) + ' (recursive)'
3508 3511 if self.child_repos_only:
3509 3512 return 'root_repos'
3510 3513 return 'global'
3511 3514
3512 @scope.setter
3513 def scope(self, value):
3514 self.repo = None
3515 self.repo_id = None
3516 self.repo_group_id = None
3517 self.repo_group = None
3518 self.child_repos_only = False
3519 if isinstance(value, Repository):
3520 self.repo_id = value.repo_id
3521 self.repo = value
3522 elif isinstance(value, RepoGroup):
3523 self.repo_group_id = value.group_id
3524 self.repo_group = value
3525 elif value == 'root_repos':
3526 self.child_repos_only = True
3527 elif value == 'global':
3528 pass
3529 else:
3530 raise Exception("invalid scope: %s, must be one of "
3531 "['global', 'root_repos', <RepoGroup>. <Repository>]" % value)
3532
3533 3515 def __repr__(self):
3534 3516 return '<Integration(%r, %r)>' % (self.integration_type, self.scope)
@@ -61,23 +61,24 b' class IntegrationModel(BaseModel):'
61 61 raise Exception('integration must be int, long or Instance'
62 62 ' of Integration got %s' % type(integration))
63 63
64 def create(self, IntegrationType, name, enabled, scope, settings):
64 def create(self, IntegrationType, name, enabled, repo, repo_group,
65 child_repos_only, settings):
65 66 """ Create an IntegrationType integration """
66 67 integration = Integration()
67 68 integration.integration_type = IntegrationType.key
68 69 self.sa.add(integration)
69 self.update_integration(integration, name, enabled, scope, settings)
70 self.update_integration(integration, name, enabled, repo, repo_group,
71 child_repos_only, settings)
70 72 self.sa.commit()
71 73 return integration
72 74
73 def update_integration(self, integration, name, enabled, scope, settings):
74 """
75 :param scope: one of ['global', 'root_repos', <RepoGroup>. <Repository>]
76 """
77
75 def update_integration(self, integration, name, enabled, repo, repo_group,
76 child_repos_only, settings):
78 77 integration = self.__get_integration(integration)
79 78
80 integration.scope = scope
79 integration.repo = repo
80 integration.repo_group = repo_group
81 integration.child_repos_only = child_repos_only
81 82 integration.name = name
82 83 integration.enabled = enabled
83 84 integration.settings = settings
@@ -127,7 +128,7 b' class IntegrationModel(BaseModel):'
127 128 query = self.sa.query(Integration).filter(
128 129 and_(Integration.repo_id==None, Integration.repo_group_id==None)
129 130 )
130 elif scope == 'root_repos':
131 elif scope == 'root-repos':
131 132 query = self.sa.query(Integration).filter(
132 133 and_(Integration.repo_id==None,
133 134 Integration.repo_group_id==None,
@@ -185,13 +186,21 b' class IntegrationModel(BaseModel):'
185 186
186 187 if event.repo.group:
187 188 clauses.append(
188 Integration.repo_group_id == event.repo.group.group_id
189 and_(
190 Integration.repo_group_id==event.repo.group.group_id,
191 Integration.child_repos_only==True
192 )
189 193 )
190 # repo group cascade to kids (maybe implement this sometime?)
191 # clauses.append(Integration.repo_group_id.in_(
192 # [group.group_id for group in
193 # event.repo.groups_with_parents]
194 # ))
194 # repo group cascade to kids
195 clauses.append(
196 and_(
197 Integration.repo_group_id.in_(
198 [group.group_id for group in
199 event.repo.groups_with_parents]
200 ),
201 Integration.child_repos_only==False
202 )
203 )
195 204
196 205
197 206 if not event.repo.group: # root repo
@@ -37,7 +37,7 b' def integration_scope_choices(permission'
37 37 if 'hg.admin' in permissions['global']:
38 38 result.extend([
39 39 ('global', _('Global (all repositories)')),
40 ('root_repos', _('Top level repositories only')),
40 ('root-repos', _('Top level repositories only')),
41 41 ])
42 42
43 43 repo_choices = [
@@ -47,13 +47,19 b' def integration_scope_choices(permission'
47 47 if repo_perm == 'repository.admin'
48 48 ]
49 49 repogroup_choices = [
50 ('repogroup:%s' % repo_group_name, '/' + repo_group_name + ' (group)')
50 ('repogroup:%s' % repo_group_name, '/' + repo_group_name + '/ (child repos only)')
51 for repo_group_name, repo_group_perm
52 in permissions['repositories_groups'].items()
53 if repo_group_perm == 'group.admin'
54 ]
55 repogroup_recursive_choices = [
56 ('repogroup-recursive:%s' % repo_group_name, '/' + repo_group_name + '/ (recursive)')
51 57 for repo_group_name, repo_group_perm
52 58 in permissions['repositories_groups'].items()
53 59 if repo_group_perm == 'group.admin'
54 60 ]
55 61 result.extend(
56 sorted(repogroup_choices + repo_choices,
62 sorted(repogroup_recursive_choices + repogroup_choices + repo_choices,
57 63 key=lambda (choice, label): choice.split(':', 1)[1]
58 64 )
59 65 )
@@ -66,27 +72,24 b' def deferred_integration_scopes_validato'
66 72 def _scope_validator(_node, scope):
67 73 is_super_admin = 'hg.admin' in perms['global']
68 74
69 if scope in ('global', 'root_repos'):
75 if scope.get('repo'):
76 if (is_super_admin or perms['repositories'].get(
77 scope['repo'].repo_name) == 'repository.admin'):
78 return True
79 msg = _('Only repo admins can create integrations')
80 raise colander.Invalid(_node, msg)
81 elif scope.get('repo_group'):
82 if (is_super_admin or perms['repositories_groups'].get(
83 scope['repo_group'].group_name) == 'group.admin'):
84 return True
85
86 msg = _('Only repogroup admins can create integrations')
87 raise colander.Invalid(_node, msg)
88 else:
70 89 if is_super_admin:
71 90 return True
72 91 msg = _('Only superadmins can create global integrations')
73 92 raise colander.Invalid(_node, msg)
74 elif isinstance(scope, Repository):
75 if (is_super_admin or perms['repositories'].get(
76 scope.repo_name) == 'repository.admin'):
77 return True
78 msg = _('Only repo admins can create integrations')
79 raise colander.Invalid(_node, msg)
80 elif isinstance(scope, RepoGroup):
81 if (is_super_admin or perms['repositories_groups'].get(
82 scope.group_name) == 'group.admin'):
83 return True
84
85 msg = _('Only repogroup admins can create integrations')
86 raise colander.Invalid(_node, msg)
87
88 msg = _('Invalid integration scope: %s' % scope)
89 raise colander.Invalid(node, msg)
90 93
91 94 return _scope_validator
92 95
@@ -100,17 +103,26 b' def deferred_integration_scopes_widget(n'
100 103 widget = deform.widget.Select2Widget(values=choices)
101 104 return widget
102 105
103 class IntegrationScope(colander.SchemaType):
106
107 class IntegrationScopeType(colander.SchemaType):
104 108 def serialize(self, node, appstruct):
105 109 if appstruct is colander.null:
106 110 return colander.null
107 111
108 if isinstance(appstruct, Repository):
109 return 'repo:%s' % appstruct.repo_name
110 elif isinstance(appstruct, RepoGroup):
111 return 'repogroup:%s' % appstruct.group_name
112 elif appstruct in ('global', 'root_repos'):
113 return appstruct
112 if appstruct.get('repo'):
113 return 'repo:%s' % appstruct['repo'].repo_name
114 elif appstruct.get('repo_group'):
115 if appstruct.get('child_repos_only'):
116 return 'repogroup:%s' % appstruct['repo_group'].group_name
117 else:
118 return 'repogroup-recursive:%s' % (
119 appstruct['repo_group'].group_name)
120 else:
121 if appstruct.get('child_repos_only'):
122 return 'root-repos'
123 else:
124 return 'global'
125
114 126 raise colander.Invalid(node, '%r is not a valid scope' % appstruct)
115 127
116 128 def deserialize(self, node, cstruct):
@@ -120,16 +132,43 b' class IntegrationScope(colander.SchemaTy'
120 132 if cstruct.startswith('repo:'):
121 133 repo = Repository.get_by_repo_name(cstruct.split(':')[1])
122 134 if repo:
123 return repo
135 return {
136 'repo': repo,
137 'repo_group': None,
138 'child_repos_only': None,
139 }
140 elif cstruct.startswith('repogroup-recursive:'):
141 repo_group = RepoGroup.get_by_group_name(cstruct.split(':')[1])
142 if repo_group:
143 return {
144 'repo': None,
145 'repo_group': repo_group,
146 'child_repos_only': False
147 }
124 148 elif cstruct.startswith('repogroup:'):
125 149 repo_group = RepoGroup.get_by_group_name(cstruct.split(':')[1])
126 150 if repo_group:
127 return repo_group
128 elif cstruct in ('global', 'root_repos'):
129 return cstruct
151 return {
152 'repo': None,
153 'repo_group': repo_group,
154 'child_repos_only': True
155 }
156 elif cstruct == 'global':
157 return {
158 'repo': None,
159 'repo_group': None,
160 'child_repos_only': False
161 }
162 elif cstruct == 'root-repos':
163 return {
164 'repo': None,
165 'repo_group': None,
166 'child_repos_only': True
167 }
130 168
131 169 raise colander.Invalid(node, '%r is not a valid scope' % cstruct)
132 170
171
133 172 class IntegrationOptionsSchemaBase(colander.MappingSchema):
134 173
135 174 name = colander.SchemaNode(
@@ -140,10 +179,10 b' class IntegrationOptionsSchemaBase(colan'
140 179 )
141 180
142 181 scope = colander.SchemaNode(
143 IntegrationScope(),
182 IntegrationScopeType(),
144 183 description=_(
145 'Scope of the integration. Group scope means the integration '
146 ' runs on all child repos of that group.'),
184 'Scope of the integration. Recursive means the integration '
185 ' runs on all repos of that group and children recursively.'),
147 186 title=_('Integration scope'),
148 187 validator=deferred_integration_scopes_validator,
149 188 widget=deferred_integration_scopes_widget,
@@ -166,14 +166,17 b''
166 166 %elif integration.repo_group:
167 167 <a href="${h.url('repo_group_home', group_name=integration.repo_group.group_name)}">
168 168 ${_('repogroup')}:${integration.repo_group.group_name}
169 %if integration.child_repos_only:
170 ${_('child repos only')}
171 %else:
172 ${_('cascade to all')}
173 %endif
169 174 </a>
170 175 %else:
171 %if integration.scope == 'root_repos':
176 %if integration.child_repos_only:
172 177 ${_('top level repos only')}
173 %elif integration.scope == 'global':
178 %else:
174 179 ${_('global')}
175 %else:
176 ${_('unknown scope')}: ${integration.scope}
177 180 %endif
178 181 </td>
179 182 %endif
@@ -222,12 +222,14 b' def _post_integration_test_helper(app, u'
222 222 scopes_destinations = [
223 223 ('global',
224 224 ADMIN_PREFIX + '/integrations'),
225 ('root_repos',
225 ('root-repos',
226 226 ADMIN_PREFIX + '/integrations'),
227 227 ('repo:%s' % repo.repo_name,
228 228 '/%s/settings/integrations' % repo.repo_name),
229 229 ('repogroup:%s' % repo_group.group_name,
230 230 '/%s/settings/integrations' % repo_group.group_name),
231 ('repogroup-recursive:%s' % repo_group.group_name,
232 '/%s/settings/integrations' % repo_group.group_name),
231 233 ]
232 234
233 235 for scope, destination in scopes_destinations:
@@ -51,75 +51,84 b' class TestDeleteScopesDeletesIntegration'
51 51 def integration_repos(request, StubIntegrationType, stub_integration_settings):
52 52 """
53 53 Create repositories and integrations for testing, and destroy them after
54
55 Structure:
56 root_repo
57 parent_group/
58 parent_repo
59 child_group/
60 child_repo
61 other_group/
62 other_repo
54 63 """
55 64 fixture = Fixture()
56 65
57 repo_group_1_id = 'int_test_repo_group_1_%s' % time.time()
58 repo_group_1 = fixture.create_repo_group(repo_group_1_id)
59 repo_group_2_id = 'int_test_repo_group_2_%s' % time.time()
60 repo_group_2 = fixture.create_repo_group(repo_group_2_id)
66
67 parent_group_id = 'int_test_parent_group_%s' % time.time()
68 parent_group = fixture.create_repo_group(parent_group_id)
69
70 other_group_id = 'int_test_other_group_%s' % time.time()
71 other_group = fixture.create_repo_group(other_group_id)
61 72
62 repo_1_id = 'int_test_repo_1_%s' % time.time()
63 repo_1 = fixture.create_repo(repo_1_id, repo_group=repo_group_1)
64 repo_2_id = 'int_test_repo_2_%s' % time.time()
65 repo_2 = fixture.create_repo(repo_2_id, repo_group=repo_group_2)
73 child_group_id = (
74 parent_group_id + '/' + 'int_test_child_group_%s' % time.time())
75 child_group = fixture.create_repo_group(child_group_id)
76
77 parent_repo_id = 'int_test_parent_repo_%s' % time.time()
78 parent_repo = fixture.create_repo(parent_repo_id, repo_group=parent_group)
79
80 child_repo_id = 'int_test_child_repo_%s' % time.time()
81 child_repo = fixture.create_repo(child_repo_id, repo_group=child_group)
82
83 other_repo_id = 'int_test_other_repo_%s' % time.time()
84 other_repo = fixture.create_repo(other_repo_id, repo_group=other_group)
66 85
67 86 root_repo_id = 'int_test_repo_root_%s' % time.time()
68 87 root_repo = fixture.create_repo(root_repo_id)
69 88
70 integration_global = IntegrationModel().create(
71 StubIntegrationType, settings=stub_integration_settings,
72 enabled=True, name='test global integration', scope='global')
73 integration_root_repos = IntegrationModel().create(
74 StubIntegrationType, settings=stub_integration_settings,
75 enabled=True, name='test root repos integration', scope='root_repos')
76 integration_repo_1 = IntegrationModel().create(
77 StubIntegrationType, settings=stub_integration_settings,
78 enabled=True, name='test repo 1 integration', scope=repo_1)
79 integration_repo_group_1 = IntegrationModel().create(
80 StubIntegrationType, settings=stub_integration_settings,
81 enabled=True, name='test repo group 1 integration', scope=repo_group_1)
82 integration_repo_2 = IntegrationModel().create(
83 StubIntegrationType, settings=stub_integration_settings,
84 enabled=True, name='test repo 2 integration', scope=repo_2)
85 integration_repo_group_2 = IntegrationModel().create(
86 StubIntegrationType, settings=stub_integration_settings,
87 enabled=True, name='test repo group 2 integration', scope=repo_group_2)
89 integrations = {}
90 for name, repo, repo_group, child_repos_only in [
91 ('global', None, None, None),
92 ('root_repos', None, None, True),
93 ('parent_repo', parent_repo, None, None),
94 ('child_repo', child_repo, None, None),
95 ('other_repo', other_repo, None, None),
96 ('root_repo', root_repo, None, None),
97 ('parent_group', None, parent_group, True),
98 ('parent_group_recursive', None, parent_group, False),
99 ('child_group', None, child_group, True),
100 ('child_group_recursive', None, child_group, False),
101 ('other_group', None, other_group, True),
102 ('other_group_recursive', None, other_group, False),
103 ]:
104 integrations[name] = IntegrationModel().create(
105 StubIntegrationType, settings=stub_integration_settings,
106 enabled=True, name='test %s integration' % name,
107 repo=repo, repo_group=repo_group, child_repos_only=child_repos_only)
88 108
89 109 Session().commit()
90 110
91 111 def _cleanup():
92 Session().delete(integration_global)
93 Session().delete(integration_root_repos)
94 Session().delete(integration_repo_1)
95 Session().delete(integration_repo_group_1)
96 Session().delete(integration_repo_2)
97 Session().delete(integration_repo_group_2)
112 for integration in integrations.values():
113 Session.delete(integration)
114
98 115 fixture.destroy_repo(root_repo)
99 fixture.destroy_repo(repo_1)
100 fixture.destroy_repo(repo_2)
101 fixture.destroy_repo_group(repo_group_1)
102 fixture.destroy_repo_group(repo_group_2)
116 fixture.destroy_repo(child_repo)
117 fixture.destroy_repo(parent_repo)
118 fixture.destroy_repo(other_repo)
119 fixture.destroy_repo_group(child_group)
120 fixture.destroy_repo_group(parent_group)
121 fixture.destroy_repo_group(other_group)
103 122
104 123 request.addfinalizer(_cleanup)
105 124
106 125 return {
126 'integrations': integrations,
107 127 'repos': {
108 'repo_1': repo_1,
109 'repo_2': repo_2,
110 128 'root_repo': root_repo,
111 },
112 'repo_groups': {
113 'repo_group_1': repo_group_1,
114 'repo_group_2': repo_group_2,
115 },
116 'integrations': {
117 'global': integration_global,
118 'root_repos': integration_root_repos,
119 'repo_1': integration_repo_1,
120 'repo_2': integration_repo_2,
121 'repo_group_1': integration_repo_group_1,
122 'repo_group_2': integration_repo_group_2,
129 'other_repo': other_repo,
130 'parent_repo': parent_repo,
131 'child_repo': child_repo,
123 132 }
124 133 }
125 134
@@ -133,27 +142,41 b' def test_enabled_integration_repo_scopes'
133 142
134 143 assert triggered_integrations == [
135 144 integrations['global'],
136 integrations['root_repos']
145 integrations['root_repos'],
146 integrations['root_repo'],
147 ]
148
149
150 triggered_integrations = IntegrationModel().get_for_event(
151 events.RepoEvent(repos['other_repo']))
152
153 assert triggered_integrations == [
154 integrations['global'],
155 integrations['other_repo'],
156 integrations['other_group'],
157 integrations['other_group_recursive'],
137 158 ]
138 159
139 160
140 161 triggered_integrations = IntegrationModel().get_for_event(
141 events.RepoEvent(repos['repo_1']))
162 events.RepoEvent(repos['parent_repo']))
142 163
143 164 assert triggered_integrations == [
144 165 integrations['global'],
145 integrations['repo_1'],
146 integrations['repo_group_1']
166 integrations['parent_repo'],
167 integrations['parent_group'],
168 integrations['parent_group_recursive'],
147 169 ]
148 170
149
150 171 triggered_integrations = IntegrationModel().get_for_event(
151 events.RepoEvent(repos['repo_2']))
172 events.RepoEvent(repos['child_repo']))
152 173
153 174 assert triggered_integrations == [
154 175 integrations['global'],
155 integrations['repo_2'],
156 integrations['repo_group_2'],
176 integrations['child_repo'],
177 integrations['parent_group_recursive'],
178 integrations['child_group'],
179 integrations['child_group_recursive'],
157 180 ]
158 181
159 182
@@ -172,17 +195,24 b' def test_disabled_integration_repo_scope'
172 195
173 196
174 197 triggered_integrations = IntegrationModel().get_for_event(
175 events.RepoEvent(repos['repo_1']))
198 events.RepoEvent(repos['parent_repo']))
176 199
177 200 assert triggered_integrations == []
178 201
179 202
180 203 triggered_integrations = IntegrationModel().get_for_event(
181 events.RepoEvent(repos['repo_2']))
204 events.RepoEvent(repos['child_repo']))
182 205
183 206 assert triggered_integrations == []
184 207
185 208
209 triggered_integrations = IntegrationModel().get_for_event(
210 events.RepoEvent(repos['other_repo']))
211
212 assert triggered_integrations == []
213
214
215
186 216 def test_enabled_non_repo_integrations(integration_repos):
187 217 integrations = integration_repos['integrations']
188 218
@@ -47,42 +47,93 b' class TestIntegrationSchema(object):'
47 47 'repositories_groups': {},
48 48 }
49 49
50 perms_tests = {
51 ('repo:%s' % repo.repo_name, repo): [
52 ({}, False),
53 ({'global': ['hg.admin']}, True),
54 ({'global': []}, False),
55 ({'repositories': {repo.repo_name: 'repository.admin'}}, True),
56 ({'repositories': {repo.repo_name: 'repository.read'}}, False),
57 ({'repositories': {repo.repo_name: 'repository.write'}}, False),
58 ({'repositories': {repo.repo_name: 'repository.none'}}, False),
59 ],
60 ('repogroup:%s' % repo_group.group_name, repo_group): [
61 ({}, False),
62 ({'global': ['hg.admin']}, True),
63 ({'global': []}, False),
64 ({'repositories_groups':
65 {repo_group.group_name: 'group.admin'}}, True),
66 ({'repositories_groups':
67 {repo_group.group_name: 'group.read'}}, False),
68 ({'repositories_groups':
69 {repo_group.group_name: 'group.write'}}, False),
70 ({'repositories_groups':
71 {repo_group.group_name: 'group.none'}}, False),
72 ],
73 ('global', 'global'): [
74 ({}, False),
75 ({'global': ['hg.admin']}, True),
76 ({'global': []}, False),
77 ],
78 ('root_repos', 'root_repos'): [
79 ({}, False),
80 ({'global': ['hg.admin']}, True),
81 ({'global': []}, False),
82 ],
83 }
50 perms_tests = [
51 (
52 'repo:%s' % repo.repo_name,
53 {
54 'child_repos_only': None,
55 'repo_group': None,
56 'repo': repo,
57 },
58 [
59 ({}, False),
60 ({'global': ['hg.admin']}, True),
61 ({'global': []}, False),
62 ({'repositories': {repo.repo_name: 'repository.admin'}}, True),
63 ({'repositories': {repo.repo_name: 'repository.read'}}, False),
64 ({'repositories': {repo.repo_name: 'repository.write'}}, False),
65 ({'repositories': {repo.repo_name: 'repository.none'}}, False),
66 ]
67 ),
68 (
69 'repogroup:%s' % repo_group.group_name,
70 {
71 'repo': None,
72 'repo_group': repo_group,
73 'child_repos_only': True,
74 },
75 [
76 ({}, False),
77 ({'global': ['hg.admin']}, True),
78 ({'global': []}, False),
79 ({'repositories_groups':
80 {repo_group.group_name: 'group.admin'}}, True),
81 ({'repositories_groups':
82 {repo_group.group_name: 'group.read'}}, False),
83 ({'repositories_groups':
84 {repo_group.group_name: 'group.write'}}, False),
85 ({'repositories_groups':
86 {repo_group.group_name: 'group.none'}}, False),
87 ]
88 ),
89 (
90 'repogroup-recursive:%s' % repo_group.group_name,
91 {
92 'repo': None,
93 'repo_group': repo_group,
94 'child_repos_only': False,
95 },
96 [
97 ({}, False),
98 ({'global': ['hg.admin']}, True),
99 ({'global': []}, False),
100 ({'repositories_groups':
101 {repo_group.group_name: 'group.admin'}}, True),
102 ({'repositories_groups':
103 {repo_group.group_name: 'group.read'}}, False),
104 ({'repositories_groups':
105 {repo_group.group_name: 'group.write'}}, False),
106 ({'repositories_groups':
107 {repo_group.group_name: 'group.none'}}, False),
108 ]
109 ),
110 (
111 'global',
112 {
113 'repo': None,
114 'repo_group': None,
115 'child_repos_only': False,
116 }, [
117 ({}, False),
118 ({'global': ['hg.admin']}, True),
119 ({'global': []}, False),
120 ]
121 ),
122 (
123 'root-repos',
124 {
125 'repo': None,
126 'repo_group': None,
127 'child_repos_only': True,
128 }, [
129 ({}, False),
130 ({'global': ['hg.admin']}, True),
131 ({'global': []}, False),
132 ]
133 ),
134 ]
84 135
85 for (scope_input, scope_output), perms_allowed in perms_tests.items():
136 for scope_input, scope_output, perms_allowed in perms_tests:
86 137 for perms_update, allowed in perms_allowed:
87 138 perms = dict(empty_perms_dict, **perms_update)
88 139
@@ -1709,7 +1709,8 b' def repo_integration_stub(request, repo_'
1709 1709 stub_integration_settings):
1710 1710 integration = IntegrationModel().create(
1711 1711 StubIntegrationType, settings=stub_integration_settings, enabled=True,
1712 name='test repo integration', scope=repo_stub)
1712 name='test repo integration',
1713 repo=repo_stub, repo_group=None, child_repos_only=None)
1713 1714
1714 1715 @request.addfinalizer
1715 1716 def cleanup():
@@ -1723,7 +1724,23 b' def repogroup_integration_stub(request, '
1723 1724 stub_integration_settings):
1724 1725 integration = IntegrationModel().create(
1725 1726 StubIntegrationType, settings=stub_integration_settings, enabled=True,
1726 name='test repogroup integration', scope=test_repo_group)
1727 name='test repogroup integration',
1728 repo=None, repo_group=test_repo_group, child_repos_only=True)
1729
1730 @request.addfinalizer
1731 def cleanup():
1732 IntegrationModel().delete(integration)
1733
1734 return integration
1735
1736
1737 @pytest.fixture
1738 def repogroup_recursive_integration_stub(request, test_repo_group,
1739 StubIntegrationType, stub_integration_settings):
1740 integration = IntegrationModel().create(
1741 StubIntegrationType, settings=stub_integration_settings, enabled=True,
1742 name='test recursive repogroup integration',
1743 repo=None, repo_group=test_repo_group, child_repos_only=False)
1727 1744
1728 1745 @request.addfinalizer
1729 1746 def cleanup():
@@ -1737,7 +1754,8 b' def global_integration_stub(request, Stu'
1737 1754 stub_integration_settings):
1738 1755 integration = IntegrationModel().create(
1739 1756 StubIntegrationType, settings=stub_integration_settings, enabled=True,
1740 name='test global integration', scope='global')
1757 name='test global integration',
1758 repo=None, repo_group=None, child_repos_only=None)
1741 1759
1742 1760 @request.addfinalizer
1743 1761 def cleanup():
@@ -1751,7 +1769,8 b' def root_repos_integration_stub(request,'
1751 1769 stub_integration_settings):
1752 1770 integration = IntegrationModel().create(
1753 1771 StubIntegrationType, settings=stub_integration_settings, enabled=True,
1754 name='test global integration', scope='root_repos')
1772 name='test global integration',
1773 repo=None, repo_group=None, child_repos_only=True)
1755 1774
1756 1775 @request.addfinalizer
1757 1776 def cleanup():
General Comments 0
You need to be logged in to leave comments. Login now