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