##// END OF EJS Templates
events: added more validation of repo type events
super-admin -
r5124:e0800033 default
parent child Browse files
Show More
@@ -1,436 +1,440 b''
1 # Copyright (C) 2016-2023 RhodeCode GmbH
1 # Copyright (C) 2016-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import collections
19 import collections
20 import logging
20 import logging
21 import datetime
21 import datetime
22
22
23 from rhodecode.translation import lazy_ugettext
23 from rhodecode.translation import lazy_ugettext
24 from rhodecode.model.db import User, Repository, Session
24 from rhodecode.model.db import User, Repository, Session
25 from rhodecode.events.base import RhodeCodeIntegrationEvent
25 from rhodecode.events.base import RhodeCodeIntegrationEvent
26 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
26 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
27
27
28 log = logging.getLogger(__name__)
28 log = logging.getLogger(__name__)
29
29
30
30
31 def _commits_as_dict(event, commit_ids, repos):
31 def _commits_as_dict(event, commit_ids, repos):
32 """
32 """
33 Helper function to serialize commit_ids
33 Helper function to serialize commit_ids
34
34
35 :param event: class calling this method
35 :param event: class calling this method
36 :param commit_ids: commits to get
36 :param commit_ids: commits to get
37 :param repos: list of repos to check
37 :param repos: list of repos to check
38 """
38 """
39 from rhodecode.lib.utils2 import extract_mentioned_users
39 from rhodecode.lib.utils2 import extract_mentioned_users
40 from rhodecode.lib.helpers import (
40 from rhodecode.lib.helpers import (
41 urlify_commit_message, process_patterns, chop_at_smart)
41 urlify_commit_message, process_patterns, chop_at_smart)
42 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.repo import RepoModel
43
43
44 if not repos:
44 if not repos:
45 raise Exception('no repo defined')
45 raise Exception('no repo defined')
46
46
47 if not isinstance(repos, (tuple, list)):
47 if not isinstance(repos, (tuple, list)):
48 repos = [repos]
48 repos = [repos]
49
49
50 if not commit_ids:
50 if not commit_ids:
51 return []
51 return []
52
52
53 needed_commits = list(commit_ids)
53 needed_commits = list(commit_ids)
54
54
55 commits = []
55 commits = []
56 reviewers = []
56 reviewers = []
57 for repo in repos:
57 for repo in repos:
58 if not needed_commits:
58 if not needed_commits:
59 return commits # return early if we have the commits we need
59 return commits # return early if we have the commits we need
60
60
61 vcs_repo = repo.scm_instance(cache=False)
61 vcs_repo = repo.scm_instance(cache=False)
62
62
63 try:
63 try:
64 # use copy of needed_commits since we modify it while iterating
64 # use copy of needed_commits since we modify it while iterating
65 for commit_id in list(needed_commits):
65 for commit_id in list(needed_commits):
66 if commit_id.startswith('tag=>'):
66 if commit_id.startswith('tag=>'):
67 raw_id = commit_id[5:]
67 raw_id = commit_id[5:]
68 cs_data = {
68 cs_data = {
69 'raw_id': commit_id, 'short_id': commit_id,
69 'raw_id': commit_id, 'short_id': commit_id,
70 'branch': None,
70 'branch': None,
71 'git_ref_change': 'tag_add',
71 'git_ref_change': 'tag_add',
72 'message': f'Added new tag {raw_id}',
72 'message': f'Added new tag {raw_id}',
73 'author': event.actor.full_contact,
73 'author': event.actor.full_contact,
74 'date': datetime.datetime.now(),
74 'date': datetime.datetime.now(),
75 'refs': {
75 'refs': {
76 'branches': [],
76 'branches': [],
77 'bookmarks': [],
77 'bookmarks': [],
78 'tags': []
78 'tags': []
79 }
79 }
80 }
80 }
81 commits.append(cs_data)
81 commits.append(cs_data)
82
82
83 elif commit_id.startswith('delete_branch=>'):
83 elif commit_id.startswith('delete_branch=>'):
84 raw_id = commit_id[15:]
84 raw_id = commit_id[15:]
85 cs_data = {
85 cs_data = {
86 'raw_id': commit_id, 'short_id': commit_id,
86 'raw_id': commit_id, 'short_id': commit_id,
87 'branch': None,
87 'branch': None,
88 'git_ref_change': 'branch_delete',
88 'git_ref_change': 'branch_delete',
89 'message': f'Deleted branch {raw_id}',
89 'message': f'Deleted branch {raw_id}',
90 'author': event.actor.full_contact,
90 'author': event.actor.full_contact,
91 'date': datetime.datetime.now(),
91 'date': datetime.datetime.now(),
92 'refs': {
92 'refs': {
93 'branches': [],
93 'branches': [],
94 'bookmarks': [],
94 'bookmarks': [],
95 'tags': []
95 'tags': []
96 }
96 }
97 }
97 }
98 commits.append(cs_data)
98 commits.append(cs_data)
99
99
100 else:
100 else:
101 try:
101 try:
102 cs = vcs_repo.get_commit(commit_id)
102 cs = vcs_repo.get_commit(commit_id)
103 except CommitDoesNotExistError:
103 except CommitDoesNotExistError:
104 continue # maybe its in next repo
104 continue # maybe its in next repo
105
105
106 cs_data = cs.__json__()
106 cs_data = cs.__json__()
107 cs_data['refs'] = cs._get_refs()
107 cs_data['refs'] = cs._get_refs()
108
108
109 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
109 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
110 cs_data['reviewers'] = reviewers
110 cs_data['reviewers'] = reviewers
111 cs_data['url'] = RepoModel().get_commit_url(
111 cs_data['url'] = RepoModel().get_commit_url(
112 repo, cs_data['raw_id'], request=event.request)
112 repo, cs_data['raw_id'], request=event.request)
113 cs_data['permalink_url'] = RepoModel().get_commit_url(
113 cs_data['permalink_url'] = RepoModel().get_commit_url(
114 repo, cs_data['raw_id'], request=event.request,
114 repo, cs_data['raw_id'], request=event.request,
115 permalink=True)
115 permalink=True)
116 urlified_message, issues_data, errors = process_patterns(
116 urlified_message, issues_data, errors = process_patterns(
117 cs_data['message'], repo.repo_name)
117 cs_data['message'], repo.repo_name)
118 cs_data['issues'] = issues_data
118 cs_data['issues'] = issues_data
119 cs_data['message_html'] = urlify_commit_message(
119 cs_data['message_html'] = urlify_commit_message(
120 cs_data['message'], repo.repo_name)
120 cs_data['message'], repo.repo_name)
121 cs_data['message_html_title'] = chop_at_smart(
121 cs_data['message_html_title'] = chop_at_smart(
122 cs_data['message'], '\n', suffix_if_chopped='...')
122 cs_data['message'], '\n', suffix_if_chopped='...')
123 commits.append(cs_data)
123 commits.append(cs_data)
124
124
125 needed_commits.remove(commit_id)
125 needed_commits.remove(commit_id)
126
126
127 except Exception:
127 except Exception:
128 log.exception('Failed to extract commits data')
128 log.exception('Failed to extract commits data')
129 # we don't send any commits when crash happens, only full list
129 # we don't send any commits when crash happens, only full list
130 # matters we short circuit then.
130 # matters we short circuit then.
131 return []
131 return []
132
132
133 # we failed to remove all needed_commits from all repositories
134 if needed_commits:
135 raise ValueError(f'Unexpectedly not found {needed_commits} in all available repos {repos}')
136
133 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
137 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
134 if missing_commits:
138 if missing_commits:
135 log.error('Inconsistent repository state. '
139 log.error('Inconsistent repository state. '
136 'Missing commits: %s', ', '.join(missing_commits))
140 'Missing commits: %s', ', '.join(missing_commits))
137
141
138 return commits
142 return commits
139
143
140
144
141 def _issues_as_dict(commits):
145 def _issues_as_dict(commits):
142 """ Helper function to serialize issues from commits """
146 """ Helper function to serialize issues from commits """
143 issues = {}
147 issues = {}
144 for commit in commits:
148 for commit in commits:
145 for issue in commit['issues']:
149 for issue in commit['issues']:
146 issues[issue['id']] = issue
150 issues[issue['id']] = issue
147 return issues
151 return issues
148
152
149
153
150 class RepoEvent(RhodeCodeIntegrationEvent):
154 class RepoEvent(RhodeCodeIntegrationEvent):
151 """
155 """
152 Base class for events acting on a repository.
156 Base class for events acting on a repository.
153
157
154 :param repo: a :class:`Repository` instance
158 :param repo: a :class:`Repository` instance
155 """
159 """
156
160
157 def __init__(self, repo):
161 def __init__(self, repo):
158 super().__init__()
162 super().__init__()
159 self.repo = repo
163 self.repo = repo
160
164
161 def as_dict(self):
165 def as_dict(self):
162 from rhodecode.model.repo import RepoModel
166 from rhodecode.model.repo import RepoModel
163 data = super().as_dict()
167 data = super().as_dict()
164
168
165 extra_fields = collections.OrderedDict()
169 extra_fields = collections.OrderedDict()
166 for field in self.repo.extra_fields:
170 for field in self.repo.extra_fields:
167 extra_fields[field.field_key] = field.field_value
171 extra_fields[field.field_key] = field.field_value
168
172
169 data.update({
173 data.update({
170 'repo': {
174 'repo': {
171 'repo_id': self.repo.repo_id,
175 'repo_id': self.repo.repo_id,
172 'repo_name': self.repo.repo_name,
176 'repo_name': self.repo.repo_name,
173 'repo_type': self.repo.repo_type,
177 'repo_type': self.repo.repo_type,
174 'url': RepoModel().get_url(
178 'url': RepoModel().get_url(
175 self.repo, request=self.request),
179 self.repo, request=self.request),
176 'permalink_url': RepoModel().get_url(
180 'permalink_url': RepoModel().get_url(
177 self.repo, request=self.request, permalink=True),
181 self.repo, request=self.request, permalink=True),
178 'extra_fields': extra_fields
182 'extra_fields': extra_fields
179 }
183 }
180 })
184 })
181 return data
185 return data
182
186
183
187
184 class RepoCommitCommentEvent(RepoEvent):
188 class RepoCommitCommentEvent(RepoEvent):
185 """
189 """
186 An instance of this class is emitted as an :term:`event` after a comment is made
190 An instance of this class is emitted as an :term:`event` after a comment is made
187 on repository commit.
191 on repository commit.
188 """
192 """
189
193
190 name = 'repo-commit-comment'
194 name = 'repo-commit-comment'
191 display_name = lazy_ugettext('repository commit comment')
195 display_name = lazy_ugettext('repository commit comment')
192 description = lazy_ugettext('Event triggered after a comment was made '
196 description = lazy_ugettext('Event triggered after a comment was made '
193 'on commit inside a repository')
197 'on commit inside a repository')
194
198
195 def __init__(self, repo, commit, comment):
199 def __init__(self, repo, commit, comment):
196 super().__init__(repo)
200 super().__init__(repo)
197 self.commit = commit
201 self.commit = commit
198 self.comment = comment
202 self.comment = comment
199
203
200 def as_dict(self):
204 def as_dict(self):
201 data = super().as_dict()
205 data = super().as_dict()
202 data['commit'] = {
206 data['commit'] = {
203 'commit_id': self.commit.raw_id,
207 'commit_id': self.commit.raw_id,
204 'commit_message': self.commit.message,
208 'commit_message': self.commit.message,
205 'commit_branch': self.commit.branch,
209 'commit_branch': self.commit.branch,
206 }
210 }
207
211
208 data['comment'] = {
212 data['comment'] = {
209 'comment_id': self.comment.comment_id,
213 'comment_id': self.comment.comment_id,
210 'comment_text': self.comment.text,
214 'comment_text': self.comment.text,
211 'comment_type': self.comment.comment_type,
215 'comment_type': self.comment.comment_type,
212 'comment_f_path': self.comment.f_path,
216 'comment_f_path': self.comment.f_path,
213 'comment_line_no': self.comment.line_no,
217 'comment_line_no': self.comment.line_no,
214 'comment_version': self.comment.last_version,
218 'comment_version': self.comment.last_version,
215 }
219 }
216 return data
220 return data
217
221
218
222
219 class RepoCommitCommentEditEvent(RepoEvent):
223 class RepoCommitCommentEditEvent(RepoEvent):
220 """
224 """
221 An instance of this class is emitted as an :term:`event` after a comment is edited
225 An instance of this class is emitted as an :term:`event` after a comment is edited
222 on repository commit.
226 on repository commit.
223 """
227 """
224
228
225 name = 'repo-commit-edit-comment'
229 name = 'repo-commit-edit-comment'
226 display_name = lazy_ugettext('repository commit edit comment')
230 display_name = lazy_ugettext('repository commit edit comment')
227 description = lazy_ugettext('Event triggered after a comment was edited '
231 description = lazy_ugettext('Event triggered after a comment was edited '
228 'on commit inside a repository')
232 'on commit inside a repository')
229
233
230 def __init__(self, repo, commit, comment):
234 def __init__(self, repo, commit, comment):
231 super().__init__(repo)
235 super().__init__(repo)
232 self.commit = commit
236 self.commit = commit
233 self.comment = comment
237 self.comment = comment
234
238
235 def as_dict(self):
239 def as_dict(self):
236 data = super().as_dict()
240 data = super().as_dict()
237 data['commit'] = {
241 data['commit'] = {
238 'commit_id': self.commit.raw_id,
242 'commit_id': self.commit.raw_id,
239 'commit_message': self.commit.message,
243 'commit_message': self.commit.message,
240 'commit_branch': self.commit.branch,
244 'commit_branch': self.commit.branch,
241 }
245 }
242
246
243 data['comment'] = {
247 data['comment'] = {
244 'comment_id': self.comment.comment_id,
248 'comment_id': self.comment.comment_id,
245 'comment_text': self.comment.text,
249 'comment_text': self.comment.text,
246 'comment_type': self.comment.comment_type,
250 'comment_type': self.comment.comment_type,
247 'comment_f_path': self.comment.f_path,
251 'comment_f_path': self.comment.f_path,
248 'comment_line_no': self.comment.line_no,
252 'comment_line_no': self.comment.line_no,
249 'comment_version': self.comment.last_version,
253 'comment_version': self.comment.last_version,
250 }
254 }
251 return data
255 return data
252
256
253
257
254 class RepoPreCreateEvent(RepoEvent):
258 class RepoPreCreateEvent(RepoEvent):
255 """
259 """
256 An instance of this class is emitted as an :term:`event` before a repo is
260 An instance of this class is emitted as an :term:`event` before a repo is
257 created.
261 created.
258 """
262 """
259 name = 'repo-pre-create'
263 name = 'repo-pre-create'
260 display_name = lazy_ugettext('repository pre create')
264 display_name = lazy_ugettext('repository pre create')
261 description = lazy_ugettext('Event triggered before repository is created')
265 description = lazy_ugettext('Event triggered before repository is created')
262
266
263
267
264 class RepoCreateEvent(RepoEvent):
268 class RepoCreateEvent(RepoEvent):
265 """
269 """
266 An instance of this class is emitted as an :term:`event` whenever a repo is
270 An instance of this class is emitted as an :term:`event` whenever a repo is
267 created.
271 created.
268 """
272 """
269 name = 'repo-create'
273 name = 'repo-create'
270 display_name = lazy_ugettext('repository created')
274 display_name = lazy_ugettext('repository created')
271 description = lazy_ugettext('Event triggered after repository was created')
275 description = lazy_ugettext('Event triggered after repository was created')
272
276
273
277
274 class RepoPreDeleteEvent(RepoEvent):
278 class RepoPreDeleteEvent(RepoEvent):
275 """
279 """
276 An instance of this class is emitted as an :term:`event` whenever a repo is
280 An instance of this class is emitted as an :term:`event` whenever a repo is
277 created.
281 created.
278 """
282 """
279 name = 'repo-pre-delete'
283 name = 'repo-pre-delete'
280 display_name = lazy_ugettext('repository pre delete')
284 display_name = lazy_ugettext('repository pre delete')
281 description = lazy_ugettext('Event triggered before a repository is deleted')
285 description = lazy_ugettext('Event triggered before a repository is deleted')
282
286
283
287
284 class RepoDeleteEvent(RepoEvent):
288 class RepoDeleteEvent(RepoEvent):
285 """
289 """
286 An instance of this class is emitted as an :term:`event` whenever a repo is
290 An instance of this class is emitted as an :term:`event` whenever a repo is
287 created.
291 created.
288 """
292 """
289 name = 'repo-delete'
293 name = 'repo-delete'
290 display_name = lazy_ugettext('repository deleted')
294 display_name = lazy_ugettext('repository deleted')
291 description = lazy_ugettext('Event triggered after repository was deleted')
295 description = lazy_ugettext('Event triggered after repository was deleted')
292
296
293
297
294 class RepoVCSEvent(RepoEvent):
298 class RepoVCSEvent(RepoEvent):
295 """
299 """
296 Base class for events triggered by the VCS
300 Base class for events triggered by the VCS
297 """
301 """
298 def __init__(self, repo_name, extras):
302 def __init__(self, repo_name, extras):
299 self.repo = Repository.get_by_repo_name(repo_name)
303 self.repo = Repository.get_by_repo_name(repo_name)
300 if not self.repo:
304 if not self.repo:
301 raise Exception('repo by this name %s does not exist' % repo_name)
305 raise Exception(f'repo by this name {repo_name} does not exist')
302 self.extras = extras
306 self.extras = extras
303 super().__init__(self.repo)
307 super().__init__(self.repo)
304
308
305 @property
309 @property
306 def actor(self):
310 def actor(self):
307 if self.extras.get('username'):
311 if self.extras.get('username'):
308 return User.get_by_username(self.extras['username'])
312 return User.get_by_username(self.extras['username'])
309
313
310 @property
314 @property
311 def actor_ip(self):
315 def actor_ip(self):
312 if self.extras.get('ip'):
316 if self.extras.get('ip'):
313 return self.extras['ip']
317 return self.extras['ip']
314
318
315 @property
319 @property
316 def server_url(self):
320 def server_url(self):
317 if self.extras.get('server_url'):
321 if self.extras.get('server_url'):
318 return self.extras['server_url']
322 return self.extras['server_url']
319
323
320 @property
324 @property
321 def request(self):
325 def request(self):
322 return self.extras.get('request') or self.get_request()
326 return self.extras.get('request') or self.get_request()
323
327
324
328
325 class RepoPrePullEvent(RepoVCSEvent):
329 class RepoPrePullEvent(RepoVCSEvent):
326 """
330 """
327 An instance of this class is emitted as an :term:`event` before commits
331 An instance of this class is emitted as an :term:`event` before commits
328 are pulled from a repo.
332 are pulled from a repo.
329 """
333 """
330 name = 'repo-pre-pull'
334 name = 'repo-pre-pull'
331 display_name = lazy_ugettext('repository pre pull')
335 display_name = lazy_ugettext('repository pre pull')
332 description = lazy_ugettext('Event triggered before repository code is pulled')
336 description = lazy_ugettext('Event triggered before repository code is pulled')
333
337
334
338
335 class RepoPullEvent(RepoVCSEvent):
339 class RepoPullEvent(RepoVCSEvent):
336 """
340 """
337 An instance of this class is emitted as an :term:`event` after commits
341 An instance of this class is emitted as an :term:`event` after commits
338 are pulled from a repo.
342 are pulled from a repo.
339 """
343 """
340 name = 'repo-pull'
344 name = 'repo-pull'
341 display_name = lazy_ugettext('repository pull')
345 display_name = lazy_ugettext('repository pull')
342 description = lazy_ugettext('Event triggered after repository code was pulled')
346 description = lazy_ugettext('Event triggered after repository code was pulled')
343
347
344
348
345 class RepoPrePushEvent(RepoVCSEvent):
349 class RepoPrePushEvent(RepoVCSEvent):
346 """
350 """
347 An instance of this class is emitted as an :term:`event` before commits
351 An instance of this class is emitted as an :term:`event` before commits
348 are pushed to a repo.
352 are pushed to a repo.
349 """
353 """
350 name = 'repo-pre-push'
354 name = 'repo-pre-push'
351 display_name = lazy_ugettext('repository pre push')
355 display_name = lazy_ugettext('repository pre push')
352 description = lazy_ugettext('Event triggered before the code is '
356 description = lazy_ugettext('Event triggered before the code is '
353 'pushed to a repository')
357 'pushed to a repository')
354
358
355
359
356 class RepoPushEvent(RepoVCSEvent):
360 class RepoPushEvent(RepoVCSEvent):
357 """
361 """
358 An instance of this class is emitted as an :term:`event` after commits
362 An instance of this class is emitted as an :term:`event` after commits
359 are pushed to a repo.
363 are pushed to a repo.
360
364
361 :param extras: (optional) dict of data from proxied VCS actions
365 :param extras: (optional) dict of data from proxied VCS actions
362 """
366 """
363 name = 'repo-push'
367 name = 'repo-push'
364 display_name = lazy_ugettext('repository push')
368 display_name = lazy_ugettext('repository push')
365 description = lazy_ugettext('Event triggered after the code was '
369 description = lazy_ugettext('Event triggered after the code was '
366 'pushed to a repository')
370 'pushed to a repository')
367
371
368 def __init__(self, repo_name, pushed_commit_ids, extras):
372 def __init__(self, repo_name, pushed_commit_ids, extras):
369 super().__init__(repo_name, extras)
373 super().__init__(repo_name, extras)
370 self.pushed_commit_ids = pushed_commit_ids
374 self.pushed_commit_ids = pushed_commit_ids
371 self.new_refs = extras.new_refs
375 self.new_refs = extras.new_refs
372
376
373 def as_dict(self):
377 def as_dict(self):
374 data = super().as_dict()
378 data = super().as_dict()
375
379
376 def branch_url(branch_name):
380 def branch_url(branch_name):
377 return '{}/changelog?branch={}'.format(
381 return '{}/changelog?branch={}'.format(
378 data['repo']['url'], branch_name)
382 data['repo']['url'], branch_name)
379
383
380 def tag_url(tag_name):
384 def tag_url(tag_name):
381 return '{}/files/{}/'.format(
385 return '{}/files/{}/'.format(
382 data['repo']['url'], tag_name)
386 data['repo']['url'], tag_name)
383
387
384 commits = _commits_as_dict(
388 commits = _commits_as_dict(
385 self, commit_ids=self.pushed_commit_ids, repos=[self.repo])
389 self, commit_ids=self.pushed_commit_ids, repos=[self.repo])
386
390
387 last_branch = None
391 last_branch = None
388 for commit in reversed(commits):
392 for commit in reversed(commits):
389 commit['branch'] = commit['branch'] or last_branch
393 commit['branch'] = commit['branch'] or last_branch
390 last_branch = commit['branch']
394 last_branch = commit['branch']
391 issues = _issues_as_dict(commits)
395 issues = _issues_as_dict(commits)
392
396
393 branches = set()
397 branches = set()
394 tags = set()
398 tags = set()
395 for commit in commits:
399 for commit in commits:
396 if commit['refs']['tags']:
400 if commit['refs']['tags']:
397 for tag in commit['refs']['tags']:
401 for tag in commit['refs']['tags']:
398 tags.add(tag)
402 tags.add(tag)
399 if commit['branch']:
403 if commit['branch']:
400 branches.add(commit['branch'])
404 branches.add(commit['branch'])
401
405
402 # maybe we have branches in new_refs ?
406 # maybe we have branches in new_refs ?
403 try:
407 try:
404 branches = branches.union(set(self.new_refs['branches']))
408 branches = branches.union(set(self.new_refs['branches']))
405 except Exception:
409 except Exception:
406 pass
410 pass
407
411
408 branches = [
412 branches = [
409 {
413 {
410 'name': branch,
414 'name': branch,
411 'url': branch_url(branch)
415 'url': branch_url(branch)
412 }
416 }
413 for branch in branches
417 for branch in branches
414 ]
418 ]
415
419
416 # maybe we have branches in new_refs ?
420 # maybe we have branches in new_refs ?
417 try:
421 try:
418 tags = tags.union(set(self.new_refs['tags']))
422 tags = tags.union(set(self.new_refs['tags']))
419 except Exception:
423 except Exception:
420 pass
424 pass
421
425
422 tags = [
426 tags = [
423 {
427 {
424 'name': tag,
428 'name': tag,
425 'url': tag_url(tag)
429 'url': tag_url(tag)
426 }
430 }
427 for tag in tags
431 for tag in tags
428 ]
432 ]
429
433
430 data['push'] = {
434 data['push'] = {
431 'commits': commits,
435 'commits': commits,
432 'issues': issues,
436 'issues': issues,
433 'branches': branches,
437 'branches': branches,
434 'tags': tags,
438 'tags': tags,
435 }
439 }
436 return data
440 return data
General Comments 0
You need to be logged in to leave comments. Login now