comparison rhodecode/model/comment.py @ 3430:bbe21df7ad48 beta

notifications changes - closing pull requests will give notification about it - more detailed notifications about commenting on changesets and pull requests
author Marcin Kuzminski <marcin@python-works.com>
date Sat, 02 Mar 2013 21:26:38 +0100
parents 32a283e5fd0d
children 1de8abd9a4e1
comparison
equal deleted inserted replaced
3429:fba8b977bed8 3430:bbe21df7ad48
33 from rhodecode.lib import helpers as h 33 from rhodecode.lib import helpers as h
34 from rhodecode.model import BaseModel 34 from rhodecode.model import BaseModel
35 from rhodecode.model.db import ChangesetComment, User, Repository, \ 35 from rhodecode.model.db import ChangesetComment, User, Repository, \
36 Notification, PullRequest 36 Notification, PullRequest
37 from rhodecode.model.notification import NotificationModel 37 from rhodecode.model.notification import NotificationModel
38 from rhodecode.model.meta import Session
38 39
39 log = logging.getLogger(__name__) 40 log = logging.getLogger(__name__)
40 41
41 42
42 class ChangesetCommentsModel(BaseModel): 43 class ChangesetCommentsModel(BaseModel):
55 user_obj = User.get_by_username(username, case_insensitive=True) 56 user_obj = User.get_by_username(username, case_insensitive=True)
56 if user_obj: 57 if user_obj:
57 user_objects.append(user_obj) 58 user_objects.append(user_obj)
58 return user_objects 59 return user_objects
59 60
60 def create(self, text, repo, user, revision=None, pull_request=None, 61 def _get_notification_data(self, repo, comment, user, comment_text,
61 f_path=None, line_no=None, status_change=None, send_email=True): 62 line_no=None, revision=None, pull_request=None,
62 """ 63 status_change=None, closing_pr=False):
63 Creates new comment for changeset or pull request. 64 """
64 IF status_change is not none this comment is associated with a 65 Get notification data
65 status change of changeset or changesets associated with pull request 66
66 67 :param comment_text:
67 :param text: 68 :param line:
68 :param repo: 69 :returns: tuple (subj,body,recipients,notification_type,email_kwargs)
69 :param user: 70 """
70 :param revision: 71 # make notification
71 :param pull_request: 72 body = comment_text # text of the comment
72 :param f_path: 73 line = ''
73 :param line_no: 74 if line_no:
74 :param status_change: 75 line = _('on line %s') % line_no
75 :param send_email: 76
76 """ 77 #changeset
77 if not text: 78 if revision:
78 return 79 notification_type = Notification.TYPE_CHANGESET_COMMENT
79
80 repo = self._get_repo(repo)
81 user = self._get_user(user)
82 comment = ChangesetComment()
83 comment.repo = repo
84 comment.author = user
85 comment.text = text
86 comment.f_path = f_path
87 comment.line_no = line_no
88
89 if revision:
90 cs = repo.scm_instance.get_changeset(revision) 80 cs = repo.scm_instance.get_changeset(revision)
91 desc = "%s - %s" % (cs.short_id, h.shorter(cs.message, 256)) 81 desc = "%s" % (cs.short_id)
92 comment.revision = revision 82
93 elif pull_request: 83 _url = h.url('changeset_home',
94 pull_request = self.__get_pull_request(pull_request) 84 repo_name=repo.repo_name,
95 comment.pull_request = pull_request 85 revision=revision,
96 else: 86 anchor='comment-%s' % comment.comment_id,
97 raise Exception('Please specify revision or pull_request_id') 87 qualified=True,
98 88 )
99 self.sa.add(comment)
100 self.sa.flush()
101
102 # make notification
103 line = ''
104 body = text
105
106 #changeset
107 if revision:
108 if line_no:
109 line = _('on line %s') % line_no
110 subj = safe_unicode( 89 subj = safe_unicode(
111 h.link_to('Re commit: %(desc)s %(line)s' % \ 90 h.link_to('Re changeset: %(desc)s %(line)s' % \
112 {'desc': desc, 'line': line}, 91 {'desc': desc, 'line': line},
113 h.url('changeset_home', repo_name=repo.repo_name, 92 _url)
114 revision=revision, 93 )
115 anchor='comment-%s' % comment.comment_id, 94 email_subject = 'User %s commented on changeset %s' % \
116 qualified=True, 95 (user.username, h.short_id(revision))
117 )
118 )
119 )
120 notification_type = Notification.TYPE_CHANGESET_COMMENT
121 # get the current participants of this changeset 96 # get the current participants of this changeset
122 recipients = ChangesetComment.get_users(revision=revision) 97 recipients = ChangesetComment.get_users(revision=revision)
123 # add changeset author if it's in rhodecode system 98 # add changeset author if it's in rhodecode system
124 cs_author = User.get_from_cs_author(cs.author) 99 cs_author = User.get_from_cs_author(cs.author)
125 if not cs_author: 100 if not cs_author:
126 #use repo owner if we cannot extract the author correctly 101 #use repo owner if we cannot extract the author correctly
127 cs_author = repo.user 102 cs_author = repo.user
128 recipients += [cs_author] 103 recipients += [cs_author]
129 email_kwargs = { 104 email_kwargs = {
130 'status_change': status_change, 105 'status_change': status_change,
106 'cs_comment_user': h.person(user.email),
107 'cs_target_repo': h.url('summary_home', repo_name=repo.repo_name,
108 qualified=True),
109 'cs_comment_url': _url,
110 'raw_id': revision,
111 'message': cs.message
131 } 112 }
132 #pull request 113 #pull request
133 elif pull_request: 114 elif pull_request:
115 notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
116 desc = comment.pull_request.title
134 _url = h.url('pullrequest_show', 117 _url = h.url('pullrequest_show',
135 repo_name=pull_request.other_repo.repo_name, 118 repo_name=pull_request.other_repo.repo_name,
136 pull_request_id=pull_request.pull_request_id, 119 pull_request_id=pull_request.pull_request_id,
137 anchor='comment-%s' % comment.comment_id, 120 anchor='comment-%s' % comment.comment_id,
138 qualified=True, 121 qualified=True,
139 ) 122 )
140 subj = safe_unicode( 123 subj = safe_unicode(
141 h.link_to('Re pull request #%(pr_id)s: %(desc)s %(line)s' % \ 124 h.link_to('Re pull request #%(pr_id)s: %(desc)s %(line)s' % \
142 {'desc': comment.pull_request.title, 125 {'desc': desc,
143 'pr_id': comment.pull_request.pull_request_id, 126 'pr_id': comment.pull_request.pull_request_id,
144 'line': line}, 127 'line': line},
145 _url) 128 _url)
146 ) 129 )
147 130 email_subject = 'User %s commented on pull request #%s' % \
148 notification_type = Notification.TYPE_PULL_REQUEST_COMMENT 131 (user.username, comment.pull_request.pull_request_id)
149 # get the current participants of this pull request 132 # get the current participants of this pull request
150 recipients = ChangesetComment.get_users(pull_request_id= 133 recipients = ChangesetComment.get_users(pull_request_id=
151 pull_request.pull_request_id) 134 pull_request.pull_request_id)
152 # add pull request author 135 # add pull request author
153 recipients += [pull_request.author] 136 recipients += [pull_request.author]
157 140
158 #set some variables for email notification 141 #set some variables for email notification
159 email_kwargs = { 142 email_kwargs = {
160 'pr_id': pull_request.pull_request_id, 143 'pr_id': pull_request.pull_request_id,
161 'status_change': status_change, 144 'status_change': status_change,
145 'closing_pr': closing_pr,
162 'pr_comment_url': _url, 146 'pr_comment_url': _url,
163 'pr_comment_user': h.person(user.email), 147 'pr_comment_user': h.person(user.email),
164 'pr_target_repo': h.url('summary_home', 148 'pr_target_repo': h.url('summary_home',
165 repo_name=pull_request.other_repo.repo_name, 149 repo_name=pull_request.other_repo.repo_name,
166 qualified=True) 150 qualified=True)
167 } 151 }
168 152
153 return subj, body, recipients, notification_type, email_kwargs, email_subject
154
155 def create(self, text, repo, user, revision=None, pull_request=None,
156 f_path=None, line_no=None, status_change=None, closing_pr=False,
157 send_email=True):
158 """
159 Creates new comment for changeset or pull request.
160 IF status_change is not none this comment is associated with a
161 status change of changeset or changesets associated with pull request
162
163 :param text:
164 :param repo:
165 :param user:
166 :param revision:
167 :param pull_request:
168 :param f_path:
169 :param line_no:
170 :param status_change:
171 :param closing_pr:
172 :param send_email:
173 """
174 if not text:
175 log.warning('Missing text for comment, skipping...')
176 return
177
178 repo = self._get_repo(repo)
179 user = self._get_user(user)
180 comment = ChangesetComment()
181 comment.repo = repo
182 comment.author = user
183 comment.text = text
184 comment.f_path = f_path
185 comment.line_no = line_no
186
187 if revision:
188 comment.revision = revision
189 elif pull_request:
190 pull_request = self.__get_pull_request(pull_request)
191 comment.pull_request = pull_request
192 else:
193 raise Exception('Please specify revision or pull_request_id')
194
195 Session().add(comment)
196 Session().flush()
197
169 if send_email: 198 if send_email:
199 (subj, body, recipients, notification_type,
200 email_kwargs, email_subject) = self._get_notification_data(
201 repo, comment, user,
202 comment_text=text,
203 line_no=line_no,
204 revision=revision,
205 pull_request=pull_request,
206 status_change=status_change,
207 closing_pr=closing_pr)
170 # create notification objects, and emails 208 # create notification objects, and emails
171 NotificationModel().create( 209 NotificationModel().create(
172 created_by=user, subject=subj, body=body, 210 created_by=user, subject=subj, body=body,
173 recipients=recipients, type_=notification_type, 211 recipients=recipients, type_=notification_type,
174 email_kwargs=email_kwargs 212 email_kwargs=email_kwargs, email_subject=email_subject
175 ) 213 )
176 214
177 mention_recipients = set(self._extract_mentions(body))\ 215 mention_recipients = set(self._extract_mentions(body))\
178 .difference(recipients) 216 .difference(recipients)
179 if mention_recipients: 217 if mention_recipients:
193 Deletes given comment 231 Deletes given comment
194 232
195 :param comment_id: 233 :param comment_id:
196 """ 234 """
197 comment = self.__get_changeset_comment(comment) 235 comment = self.__get_changeset_comment(comment)
198 self.sa.delete(comment) 236 Session().delete(comment)
199 237
200 return comment 238 return comment
201 239
202 def get_comments(self, repo_id, revision=None, pull_request=None): 240 def get_comments(self, repo_id, revision=None, pull_request=None):
203 """ 241 """
204 Get's main comments based on revision or pull_request_id 242 Get's main comments based on revision or pull_request_id
205 243
206 :param repo_id: 244 :param repo_id:
207 :type repo_id:
208 :param revision: 245 :param revision:
209 :type revision:
210 :param pull_request: 246 :param pull_request:
211 :type pull_request:
212 """ 247 """
213 248
214 q = ChangesetComment.query()\ 249 q = ChangesetComment.query()\
215 .filter(ChangesetComment.repo_id == repo_id)\ 250 .filter(ChangesetComment.repo_id == repo_id)\
216 .filter(ChangesetComment.line_no == None)\ 251 .filter(ChangesetComment.line_no == None)\
224 raise Exception('Please specify revision or pull_request') 259 raise Exception('Please specify revision or pull_request')
225 q = q.order_by(ChangesetComment.created_on) 260 q = q.order_by(ChangesetComment.created_on)
226 return q.all() 261 return q.all()
227 262
228 def get_inline_comments(self, repo_id, revision=None, pull_request=None): 263 def get_inline_comments(self, repo_id, revision=None, pull_request=None):
229 q = self.sa.query(ChangesetComment)\ 264 q = Session().query(ChangesetComment)\
230 .filter(ChangesetComment.repo_id == repo_id)\ 265 .filter(ChangesetComment.repo_id == repo_id)\
231 .filter(ChangesetComment.line_no != None)\ 266 .filter(ChangesetComment.line_no != None)\
232 .filter(ChangesetComment.f_path != None)\ 267 .filter(ChangesetComment.f_path != None)\
233 .order_by(ChangesetComment.comment_id.asc())\ 268 .order_by(ChangesetComment.comment_id.asc())\
234 269