##// END OF EJS Templates
events: expose refs data in commits event serialization data.
marcink -
r2338:03527bc5 default
parent child Browse files
Show More
@@ -1,282 +1,283 b''
1 # Copyright (C) 2016-2017 RhodeCode GmbH
1 # Copyright (C) 2016-2017 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
21
22 from rhodecode.translation import lazy_ugettext
22 from rhodecode.translation import lazy_ugettext
23 from rhodecode.model.db import User, Repository, Session
23 from rhodecode.model.db import User, Repository, Session
24 from rhodecode.events.base import RhodecodeEvent
24 from rhodecode.events.base import RhodecodeEvent
25 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
25 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
26
26
27 log = logging.getLogger(__name__)
27 log = logging.getLogger(__name__)
28
28
29
29
30 def _commits_as_dict(event, commit_ids, repos):
30 def _commits_as_dict(event, commit_ids, repos):
31 """
31 """
32 Helper function to serialize commit_ids
32 Helper function to serialize commit_ids
33
33
34 :param event: class calling this method
34 :param event: class calling this method
35 :param commit_ids: commits to get
35 :param commit_ids: commits to get
36 :param repos: list of repos to check
36 :param repos: list of repos to check
37 """
37 """
38 from rhodecode.lib.utils2 import extract_mentioned_users
38 from rhodecode.lib.utils2 import extract_mentioned_users
39 from rhodecode.lib.helpers import (
39 from rhodecode.lib.helpers import (
40 urlify_commit_message, process_patterns, chop_at_smart)
40 urlify_commit_message, process_patterns, chop_at_smart)
41 from rhodecode.model.repo import RepoModel
41 from rhodecode.model.repo import RepoModel
42
42
43 if not repos:
43 if not repos:
44 raise Exception('no repo defined')
44 raise Exception('no repo defined')
45
45
46 if not isinstance(repos, (tuple, list)):
46 if not isinstance(repos, (tuple, list)):
47 repos = [repos]
47 repos = [repos]
48
48
49 if not commit_ids:
49 if not commit_ids:
50 return []
50 return []
51
51
52 needed_commits = list(commit_ids)
52 needed_commits = list(commit_ids)
53
53
54 commits = []
54 commits = []
55 reviewers = []
55 reviewers = []
56 for repo in repos:
56 for repo in repos:
57 if not needed_commits:
57 if not needed_commits:
58 return commits # return early if we have the commits we need
58 return commits # return early if we have the commits we need
59
59
60 vcs_repo = repo.scm_instance(cache=False)
60 vcs_repo = repo.scm_instance(cache=False)
61 try:
61 try:
62 # use copy of needed_commits since we modify it while iterating
62 # use copy of needed_commits since we modify it while iterating
63 for commit_id in list(needed_commits):
63 for commit_id in list(needed_commits):
64 try:
64 try:
65 cs = vcs_repo.get_changeset(commit_id)
65 cs = vcs_repo.get_changeset(commit_id)
66 except CommitDoesNotExistError:
66 except CommitDoesNotExistError:
67 continue # maybe its in next repo
67 continue # maybe its in next repo
68
68
69 cs_data = cs.__json__()
69 cs_data = cs.__json__()
70 cs_data['refs'] = cs._get_refs()
70 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
71 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
71 cs_data['reviewers'] = reviewers
72 cs_data['reviewers'] = reviewers
72 cs_data['url'] = RepoModel().get_commit_url(
73 cs_data['url'] = RepoModel().get_commit_url(
73 repo, cs_data['raw_id'], request=event.request)
74 repo, cs_data['raw_id'], request=event.request)
74 cs_data['permalink_url'] = RepoModel().get_commit_url(
75 cs_data['permalink_url'] = RepoModel().get_commit_url(
75 repo, cs_data['raw_id'], request=event.request, permalink=True)
76 repo, cs_data['raw_id'], request=event.request, permalink=True)
76 urlified_message, issues_data = process_patterns(
77 urlified_message, issues_data = process_patterns(
77 cs_data['message'], repo.repo_name)
78 cs_data['message'], repo.repo_name)
78 cs_data['issues'] = issues_data
79 cs_data['issues'] = issues_data
79 cs_data['message_html'] = urlify_commit_message(
80 cs_data['message_html'] = urlify_commit_message(
80 cs_data['message'], repo.repo_name)
81 cs_data['message'], repo.repo_name)
81 cs_data['message_html_title'] = chop_at_smart(
82 cs_data['message_html_title'] = chop_at_smart(
82 cs_data['message'], '\n', suffix_if_chopped='...')
83 cs_data['message'], '\n', suffix_if_chopped='...')
83 commits.append(cs_data)
84 commits.append(cs_data)
84
85
85 needed_commits.remove(commit_id)
86 needed_commits.remove(commit_id)
86
87
87 except Exception as e:
88 except Exception as e:
88 log.exception(e)
89 log.exception(e)
89 # we don't send any commits when crash happens, only full list
90 # we don't send any commits when crash happens, only full list
90 # matters we short circuit then.
91 # matters we short circuit then.
91 return []
92 return []
92
93
93 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
94 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
94 if missing_commits:
95 if missing_commits:
95 log.error('missing commits: %s' % ', '.join(missing_commits))
96 log.error('missing commits: %s' % ', '.join(missing_commits))
96
97
97 return commits
98 return commits
98
99
99
100
100 def _issues_as_dict(commits):
101 def _issues_as_dict(commits):
101 """ Helper function to serialize issues from commits """
102 """ Helper function to serialize issues from commits """
102 issues = {}
103 issues = {}
103 for commit in commits:
104 for commit in commits:
104 for issue in commit['issues']:
105 for issue in commit['issues']:
105 issues[issue['id']] = issue
106 issues[issue['id']] = issue
106 return issues
107 return issues
107
108
108
109
109 class RepoEvent(RhodecodeEvent):
110 class RepoEvent(RhodecodeEvent):
110 """
111 """
111 Base class for events acting on a repository.
112 Base class for events acting on a repository.
112
113
113 :param repo: a :class:`Repository` instance
114 :param repo: a :class:`Repository` instance
114 """
115 """
115
116
116 def __init__(self, repo):
117 def __init__(self, repo):
117 super(RepoEvent, self).__init__()
118 super(RepoEvent, self).__init__()
118 self.repo = repo
119 self.repo = repo
119
120
120 def as_dict(self):
121 def as_dict(self):
121 from rhodecode.model.repo import RepoModel
122 from rhodecode.model.repo import RepoModel
122 data = super(RepoEvent, self).as_dict()
123 data = super(RepoEvent, self).as_dict()
123
124
124 extra_fields = collections.OrderedDict()
125 extra_fields = collections.OrderedDict()
125 for field in self.repo.extra_fields:
126 for field in self.repo.extra_fields:
126 extra_fields[field.field_key] = field.field_value
127 extra_fields[field.field_key] = field.field_value
127
128
128 data.update({
129 data.update({
129 'repo': {
130 'repo': {
130 'repo_id': self.repo.repo_id,
131 'repo_id': self.repo.repo_id,
131 'repo_name': self.repo.repo_name,
132 'repo_name': self.repo.repo_name,
132 'repo_type': self.repo.repo_type,
133 'repo_type': self.repo.repo_type,
133 'url': RepoModel().get_url(
134 'url': RepoModel().get_url(
134 self.repo, request=self.request),
135 self.repo, request=self.request),
135 'permalink_url': RepoModel().get_url(
136 'permalink_url': RepoModel().get_url(
136 self.repo, request=self.request, permalink=True),
137 self.repo, request=self.request, permalink=True),
137 'extra_fields': extra_fields
138 'extra_fields': extra_fields
138 }
139 }
139 })
140 })
140 return data
141 return data
141
142
142
143
143 class RepoPreCreateEvent(RepoEvent):
144 class RepoPreCreateEvent(RepoEvent):
144 """
145 """
145 An instance of this class is emitted as an :term:`event` before a repo is
146 An instance of this class is emitted as an :term:`event` before a repo is
146 created.
147 created.
147 """
148 """
148 name = 'repo-pre-create'
149 name = 'repo-pre-create'
149 display_name = lazy_ugettext('repository pre create')
150 display_name = lazy_ugettext('repository pre create')
150
151
151
152
152 class RepoCreateEvent(RepoEvent):
153 class RepoCreateEvent(RepoEvent):
153 """
154 """
154 An instance of this class is emitted as an :term:`event` whenever a repo is
155 An instance of this class is emitted as an :term:`event` whenever a repo is
155 created.
156 created.
156 """
157 """
157 name = 'repo-create'
158 name = 'repo-create'
158 display_name = lazy_ugettext('repository created')
159 display_name = lazy_ugettext('repository created')
159
160
160
161
161 class RepoPreDeleteEvent(RepoEvent):
162 class RepoPreDeleteEvent(RepoEvent):
162 """
163 """
163 An instance of this class is emitted as an :term:`event` whenever a repo is
164 An instance of this class is emitted as an :term:`event` whenever a repo is
164 created.
165 created.
165 """
166 """
166 name = 'repo-pre-delete'
167 name = 'repo-pre-delete'
167 display_name = lazy_ugettext('repository pre delete')
168 display_name = lazy_ugettext('repository pre delete')
168
169
169
170
170 class RepoDeleteEvent(RepoEvent):
171 class RepoDeleteEvent(RepoEvent):
171 """
172 """
172 An instance of this class is emitted as an :term:`event` whenever a repo is
173 An instance of this class is emitted as an :term:`event` whenever a repo is
173 created.
174 created.
174 """
175 """
175 name = 'repo-delete'
176 name = 'repo-delete'
176 display_name = lazy_ugettext('repository deleted')
177 display_name = lazy_ugettext('repository deleted')
177
178
178
179
179 class RepoVCSEvent(RepoEvent):
180 class RepoVCSEvent(RepoEvent):
180 """
181 """
181 Base class for events triggered by the VCS
182 Base class for events triggered by the VCS
182 """
183 """
183 def __init__(self, repo_name, extras):
184 def __init__(self, repo_name, extras):
184 self.repo = Repository.get_by_repo_name(repo_name)
185 self.repo = Repository.get_by_repo_name(repo_name)
185 if not self.repo:
186 if not self.repo:
186 raise Exception('repo by this name %s does not exist' % repo_name)
187 raise Exception('repo by this name %s does not exist' % repo_name)
187 self.extras = extras
188 self.extras = extras
188 super(RepoVCSEvent, self).__init__(self.repo)
189 super(RepoVCSEvent, self).__init__(self.repo)
189
190
190 @property
191 @property
191 def actor(self):
192 def actor(self):
192 if self.extras.get('username'):
193 if self.extras.get('username'):
193 return User.get_by_username(self.extras['username'])
194 return User.get_by_username(self.extras['username'])
194
195
195 @property
196 @property
196 def actor_ip(self):
197 def actor_ip(self):
197 if self.extras.get('ip'):
198 if self.extras.get('ip'):
198 return self.extras['ip']
199 return self.extras['ip']
199
200
200 @property
201 @property
201 def server_url(self):
202 def server_url(self):
202 if self.extras.get('server_url'):
203 if self.extras.get('server_url'):
203 return self.extras['server_url']
204 return self.extras['server_url']
204
205
205 @property
206 @property
206 def request(self):
207 def request(self):
207 return self.extras.get('request') or self.get_request()
208 return self.extras.get('request') or self.get_request()
208
209
209
210
210 class RepoPrePullEvent(RepoVCSEvent):
211 class RepoPrePullEvent(RepoVCSEvent):
211 """
212 """
212 An instance of this class is emitted as an :term:`event` before commits
213 An instance of this class is emitted as an :term:`event` before commits
213 are pulled from a repo.
214 are pulled from a repo.
214 """
215 """
215 name = 'repo-pre-pull'
216 name = 'repo-pre-pull'
216 display_name = lazy_ugettext('repository pre pull')
217 display_name = lazy_ugettext('repository pre pull')
217
218
218
219
219 class RepoPullEvent(RepoVCSEvent):
220 class RepoPullEvent(RepoVCSEvent):
220 """
221 """
221 An instance of this class is emitted as an :term:`event` after commits
222 An instance of this class is emitted as an :term:`event` after commits
222 are pulled from a repo.
223 are pulled from a repo.
223 """
224 """
224 name = 'repo-pull'
225 name = 'repo-pull'
225 display_name = lazy_ugettext('repository pull')
226 display_name = lazy_ugettext('repository pull')
226
227
227
228
228 class RepoPrePushEvent(RepoVCSEvent):
229 class RepoPrePushEvent(RepoVCSEvent):
229 """
230 """
230 An instance of this class is emitted as an :term:`event` before commits
231 An instance of this class is emitted as an :term:`event` before commits
231 are pushed to a repo.
232 are pushed to a repo.
232 """
233 """
233 name = 'repo-pre-push'
234 name = 'repo-pre-push'
234 display_name = lazy_ugettext('repository pre push')
235 display_name = lazy_ugettext('repository pre push')
235
236
236
237
237 class RepoPushEvent(RepoVCSEvent):
238 class RepoPushEvent(RepoVCSEvent):
238 """
239 """
239 An instance of this class is emitted as an :term:`event` after commits
240 An instance of this class is emitted as an :term:`event` after commits
240 are pushed to a repo.
241 are pushed to a repo.
241
242
242 :param extras: (optional) dict of data from proxied VCS actions
243 :param extras: (optional) dict of data from proxied VCS actions
243 """
244 """
244 name = 'repo-push'
245 name = 'repo-push'
245 display_name = lazy_ugettext('repository push')
246 display_name = lazy_ugettext('repository push')
246
247
247 def __init__(self, repo_name, pushed_commit_ids, extras):
248 def __init__(self, repo_name, pushed_commit_ids, extras):
248 super(RepoPushEvent, self).__init__(repo_name, extras)
249 super(RepoPushEvent, self).__init__(repo_name, extras)
249 self.pushed_commit_ids = pushed_commit_ids
250 self.pushed_commit_ids = pushed_commit_ids
250
251
251 def as_dict(self):
252 def as_dict(self):
252 data = super(RepoPushEvent, self).as_dict()
253 data = super(RepoPushEvent, self).as_dict()
253
254
254 def branch_url(branch_name):
255 def branch_url(branch_name):
255 return '{}/changelog?branch={}'.format(
256 return '{}/changelog?branch={}'.format(
256 data['repo']['url'], branch_name)
257 data['repo']['url'], branch_name)
257
258
258 commits = _commits_as_dict(
259 commits = _commits_as_dict(
259 self, commit_ids=self.pushed_commit_ids, repos=[self.repo])
260 self, commit_ids=self.pushed_commit_ids, repos=[self.repo])
260
261
261 last_branch = None
262 last_branch = None
262 for commit in reversed(commits):
263 for commit in reversed(commits):
263 commit['branch'] = commit['branch'] or last_branch
264 commit['branch'] = commit['branch'] or last_branch
264 last_branch = commit['branch']
265 last_branch = commit['branch']
265 issues = _issues_as_dict(commits)
266 issues = _issues_as_dict(commits)
266
267
267 branches = set(
268 branches = set(
268 commit['branch'] for commit in commits if commit['branch'])
269 commit['branch'] for commit in commits if commit['branch'])
269 branches = [
270 branches = [
270 {
271 {
271 'name': branch,
272 'name': branch,
272 'url': branch_url(branch)
273 'url': branch_url(branch)
273 }
274 }
274 for branch in branches
275 for branch in branches
275 ]
276 ]
276
277
277 data['push'] = {
278 data['push'] = {
278 'commits': commits,
279 'commits': commits,
279 'issues': issues,
280 'issues': issues,
280 'branches': branches,
281 'branches': branches,
281 }
282 }
282 return data
283 return data
General Comments 0
You need to be logged in to leave comments. Login now