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