Show More
@@ -0,0 +1,164 b'' | |||||
|
1 | ## -*- coding: utf-8 -*- | |||
|
2 | <%inherit file="base.mako"/> | |||
|
3 | <%namespace name="base" file="base.mako"/> | |||
|
4 | ||||
|
5 | ## EMAIL SUBJECT | |||
|
6 | <%def name="subject()" filter="n,trim,whitespace_filter"> | |||
|
7 | <% | |||
|
8 | data = { | |||
|
9 | 'updating_user': '@'+h.person(updating_user), | |||
|
10 | 'pr_id': pull_request.pull_request_id, | |||
|
11 | 'pr_title': pull_request.title, | |||
|
12 | } | |||
|
13 | %> | |||
|
14 | ||||
|
15 | ${_('{updating_user} updated pull request. !{pr_id}: "{pr_title}"').format(**data) |n} | |||
|
16 | </%def> | |||
|
17 | ||||
|
18 | ## PLAINTEXT VERSION OF BODY | |||
|
19 | <%def name="body_plaintext()" filter="n,trim"> | |||
|
20 | <% | |||
|
21 | data = { | |||
|
22 | 'updating_user': h.person(updating_user), | |||
|
23 | 'pr_id': pull_request.pull_request_id, | |||
|
24 | 'pr_title': pull_request.title, | |||
|
25 | 'source_ref_type': pull_request.source_ref_parts.type, | |||
|
26 | 'source_ref_name': pull_request.source_ref_parts.name, | |||
|
27 | 'target_ref_type': pull_request.target_ref_parts.type, | |||
|
28 | 'target_ref_name': pull_request.target_ref_parts.name, | |||
|
29 | 'repo_url': pull_request_source_repo_url, | |||
|
30 | 'source_repo': pull_request_source_repo.repo_name, | |||
|
31 | 'target_repo': pull_request_target_repo.repo_name, | |||
|
32 | 'source_repo_url': pull_request_source_repo_url, | |||
|
33 | 'target_repo_url': pull_request_target_repo_url, | |||
|
34 | } | |||
|
35 | %> | |||
|
36 | ||||
|
37 | * ${_('Pull Request link')}: ${pull_request_url} | |||
|
38 | ||||
|
39 | * ${h.literal(_('Commit flow: {source_ref_type}:{source_ref_name} of {source_repo_url} into {target_ref_type}:{target_ref_name} of {target_repo_url}').format(**data))} | |||
|
40 | ||||
|
41 | * ${_('Title')}: ${pull_request.title} | |||
|
42 | ||||
|
43 | * ${_('Description')}: | |||
|
44 | ||||
|
45 | ${pull_request.description | trim} | |||
|
46 | ||||
|
47 | * Changed commits: | |||
|
48 | ||||
|
49 | - Added: ${len(added_commits)} | |||
|
50 | - Removed: ${len(removed_commits)} | |||
|
51 | ||||
|
52 | * Changed files: | |||
|
53 | ||||
|
54 | %if not changed_files: | |||
|
55 | No file changes found | |||
|
56 | %else: | |||
|
57 | %for file_name in added_files: | |||
|
58 | - A `${file_name}` | |||
|
59 | %endfor | |||
|
60 | %for file_name in modified_files: | |||
|
61 | - M `${file_name}` | |||
|
62 | %endfor | |||
|
63 | %for file_name in removed_files: | |||
|
64 | - R `${file_name}` | |||
|
65 | %endfor | |||
|
66 | %endif | |||
|
67 | ||||
|
68 | --- | |||
|
69 | ${self.plaintext_footer()} | |||
|
70 | </%def> | |||
|
71 | <% | |||
|
72 | data = { | |||
|
73 | 'updating_user': h.person(updating_user), | |||
|
74 | 'pr_id': pull_request.pull_request_id, | |||
|
75 | 'pr_title': pull_request.title, | |||
|
76 | 'source_ref_type': pull_request.source_ref_parts.type, | |||
|
77 | 'source_ref_name': pull_request.source_ref_parts.name, | |||
|
78 | 'target_ref_type': pull_request.target_ref_parts.type, | |||
|
79 | 'target_ref_name': pull_request.target_ref_parts.name, | |||
|
80 | 'repo_url': pull_request_source_repo_url, | |||
|
81 | 'source_repo': pull_request_source_repo.repo_name, | |||
|
82 | 'target_repo': pull_request_target_repo.repo_name, | |||
|
83 | 'source_repo_url': h.link_to(pull_request_source_repo.repo_name, pull_request_source_repo_url), | |||
|
84 | 'target_repo_url': h.link_to(pull_request_target_repo.repo_name, pull_request_target_repo_url), | |||
|
85 | } | |||
|
86 | %> | |||
|
87 | ||||
|
88 | <table style="text-align:left;vertical-align:middle;width: 100%"> | |||
|
89 | <tr> | |||
|
90 | <td style="width:100%;border-bottom:1px solid #dbd9da;"> | |||
|
91 | ||||
|
92 | <h4 style="margin: 0"> | |||
|
93 | <div style="margin-bottom: 4px"> | |||
|
94 | <span style="color:#7E7F7F">@${h.person(updating_user.username)}</span> | |||
|
95 | ${_('updated')} | |||
|
96 | <a href="${pull_request_url}" style="${base.link_css()}"> | |||
|
97 | ${_('pull request.').format(**data) } | |||
|
98 | </a> | |||
|
99 | </div> | |||
|
100 | <div style="margin-top: 10px"></div> | |||
|
101 | ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code> | |||
|
102 | </h4> | |||
|
103 | ||||
|
104 | </td> | |||
|
105 | </tr> | |||
|
106 | ||||
|
107 | </table> | |||
|
108 | ||||
|
109 | <table style="text-align:left;vertical-align:middle;width: 100%"> | |||
|
110 | ## spacing def | |||
|
111 | <tr> | |||
|
112 | <td style="width: 130px"></td> | |||
|
113 | <td></td> | |||
|
114 | </tr> | |||
|
115 | ||||
|
116 | <tr> | |||
|
117 | <td style="padding-right:20px;">${_('Pull request')}:</td> | |||
|
118 | <td> | |||
|
119 | <a href="${pull_request_url}" style="${base.link_css()}"> | |||
|
120 | !${pull_request.pull_request_id} | |||
|
121 | </a> | |||
|
122 | </td> | |||
|
123 | </tr> | |||
|
124 | ||||
|
125 | <tr> | |||
|
126 | <td style="padding-right:20px;line-height:20px;">${_('Commit Flow')}:</td> | |||
|
127 | <td style="line-height:20px;"> | |||
|
128 | <code>${'{}:{}'.format(data['source_ref_type'], pull_request.source_ref_parts.name)}</code> ${_('of')} ${data['source_repo_url']} | |||
|
129 | → | |||
|
130 | <code>${'{}:{}'.format(data['target_ref_type'], pull_request.target_ref_parts.name)}</code> ${_('of')} ${data['target_repo_url']} | |||
|
131 | </td> | |||
|
132 | </tr> | |||
|
133 | ||||
|
134 | <tr> | |||
|
135 | <td style="padding-right:20px;">${_('Description')}:</td> | |||
|
136 | <td style="white-space:pre-wrap"><code>${pull_request.description | trim}</code></td> | |||
|
137 | </tr> | |||
|
138 | <tr> | |||
|
139 | <td style="padding-right:20px;">${_('Changes')}:</td> | |||
|
140 | <td style="white-space:pre-line">\ | |||
|
141 | <strong>Changed commits:</strong> | |||
|
142 | ||||
|
143 | - Added: ${len(added_commits)} | |||
|
144 | - Removed: ${len(removed_commits)} | |||
|
145 | ||||
|
146 | <strong>Changed files:</strong> | |||
|
147 | ||||
|
148 | %if not changed_files: | |||
|
149 | No file changes found | |||
|
150 | %else: | |||
|
151 | %for file_name in added_files: | |||
|
152 | - A <a href="${pull_request_url + '#a_' + h.FID(ancestor_commit_id, file_name)}">${file_name}</a> | |||
|
153 | %endfor | |||
|
154 | %for file_name in modified_files: | |||
|
155 | - M <a href="${pull_request_url + '#a_' + h.FID(ancestor_commit_id, file_name)}">${file_name}</a> | |||
|
156 | %endfor | |||
|
157 | %for file_name in removed_files: | |||
|
158 | - R <a href="${pull_request_url + '#a_' + h.FID(ancestor_commit_id, file_name)}">${file_name}</a> | |||
|
159 | %endfor | |||
|
160 | %endif | |||
|
161 | </td> | |||
|
162 | </tr> | |||
|
163 | ||||
|
164 | </table> |
@@ -895,7 +895,9 b' def update_pull_request(' | |||||
895 |
|
895 | |||
896 | with pull_request.set_state(PullRequest.STATE_UPDATING): |
|
896 | with pull_request.set_state(PullRequest.STATE_UPDATING): | |
897 | if PullRequestModel().has_valid_update_type(pull_request): |
|
897 | if PullRequestModel().has_valid_update_type(pull_request): | |
898 | update_response = PullRequestModel().update_commits(pull_request) |
|
898 | db_user = apiuser.get_instance() | |
|
899 | update_response = PullRequestModel().update_commits( | |||
|
900 | pull_request, db_user) | |||
899 | commit_changes = update_response.changes or commit_changes |
|
901 | commit_changes = update_response.changes or commit_changes | |
900 | Session().commit() |
|
902 | Session().commit() | |
901 |
|
903 |
@@ -573,8 +573,7 b' class AdminSettingsView(BaseAppView):' | |||||
573 |
|
573 | |||
574 | email_kwargs = { |
|
574 | email_kwargs = { | |
575 | 'date': datetime.datetime.now(), |
|
575 | 'date': datetime.datetime.now(), | |
576 |
'user': c.rhodecode_user |
|
576 | 'user': c.rhodecode_user | |
577 | 'rhodecode_version': c.rhodecode_version |
|
|||
578 | } |
|
577 | } | |
579 |
|
578 | |||
580 | (subject, headers, email_body, |
|
579 | (subject, headers, email_body, |
@@ -78,7 +78,16 b' Check if we should use full-topic or min' | |||||
78 | target_repo = AttributeDict(repo_name='repo_group/target_repo') |
|
78 | target_repo = AttributeDict(repo_name='repo_group/target_repo') | |
79 | source_repo = AttributeDict(repo_name='repo_group/source_repo') |
|
79 | source_repo = AttributeDict(repo_name='repo_group/source_repo') | |
80 | user = User.get_by_username(self.request.GET.get('user')) or self._rhodecode_db_user |
|
80 | user = User.get_by_username(self.request.GET.get('user')) or self._rhodecode_db_user | |
81 |
|
81 | # file/commit changes for PR update | ||
|
82 | commit_changes = AttributeDict({ | |||
|
83 | 'added': ['aaaaaaabbbbb', 'cccccccddddddd'], | |||
|
84 | 'removed': ['eeeeeeeeeee'], | |||
|
85 | }) | |||
|
86 | file_changes = AttributeDict({ | |||
|
87 | 'added': ['a/file1.md', 'file2.py'], | |||
|
88 | 'modified': ['b/modified_file.rst'], | |||
|
89 | 'removed': ['.idea'], | |||
|
90 | }) | |||
82 | email_kwargs = { |
|
91 | email_kwargs = { | |
83 | 'test': {}, |
|
92 | 'test': {}, | |
84 | 'message': { |
|
93 | 'message': { | |
@@ -87,7 +96,6 b' Check if we should use full-topic or min' | |||||
87 | 'email_test': { |
|
96 | 'email_test': { | |
88 | 'user': user, |
|
97 | 'user': user, | |
89 | 'date': datetime.datetime.now(), |
|
98 | 'date': datetime.datetime.now(), | |
90 | 'rhodecode_version': c.rhodecode_version |
|
|||
91 | }, |
|
99 | }, | |
92 | 'password_reset': { |
|
100 | 'password_reset': { | |
93 | 'password_reset_url': 'http://example.com/reset-rhodecode-password/token', |
|
101 | 'password_reset_url': 'http://example.com/reset-rhodecode-password/token', | |
@@ -215,6 +223,35 b' This should work better !' | |||||
215 |
|
223 | |||
216 | }, |
|
224 | }, | |
217 |
|
225 | |||
|
226 | 'pull_request_update': { | |||
|
227 | 'updating_user': user, | |||
|
228 | ||||
|
229 | 'status_change': None, | |||
|
230 | 'status_change_type': None, | |||
|
231 | ||||
|
232 | 'pull_request': pr, | |||
|
233 | 'pull_request_commits': [], | |||
|
234 | ||||
|
235 | 'pull_request_target_repo': target_repo, | |||
|
236 | 'pull_request_target_repo_url': 'http://target-repo/url', | |||
|
237 | ||||
|
238 | 'pull_request_source_repo': source_repo, | |||
|
239 | 'pull_request_source_repo_url': 'http://source-repo/url', | |||
|
240 | ||||
|
241 | 'pull_request_url': 'http://localhost/pr1', | |||
|
242 | ||||
|
243 | # update comment links | |||
|
244 | 'pr_comment_url': 'http://comment-url', | |||
|
245 | 'pr_comment_reply_url': 'http://comment-url#reply', | |||
|
246 | 'ancestor_commit_id': 'f39bd443', | |||
|
247 | 'added_commits': commit_changes.added, | |||
|
248 | 'removed_commits': commit_changes.removed, | |||
|
249 | 'changed_files': (file_changes.added + file_changes.modified + file_changes.removed), | |||
|
250 | 'added_files': file_changes.added, | |||
|
251 | 'modified_files': file_changes.modified, | |||
|
252 | 'removed_files': file_changes.removed, | |||
|
253 | }, | |||
|
254 | ||||
218 | 'cs_comment': { |
|
255 | 'cs_comment': { | |
219 | 'user': user, |
|
256 | 'user': user, | |
220 | 'commit': AttributeDict(idx=123, raw_id='a'*40, message='Commit message'), |
|
257 | 'commit': AttributeDict(idx=123, raw_id='a'*40, message='Commit message'), | |
@@ -338,6 +375,8 b' users: description edit fixes' | |||||
338 |
|
375 | |||
339 | 'pull_request_comment+file': {}, |
|
376 | 'pull_request_comment+file': {}, | |
340 | 'pull_request_comment+status': {}, |
|
377 | 'pull_request_comment+status': {}, | |
|
378 | ||||
|
379 | 'pull_request_update': {}, | |||
341 | } |
|
380 | } | |
342 | c.email_types.update(EmailNotificationModel.email_types) |
|
381 | c.email_types.update(EmailNotificationModel.email_types) | |
343 |
|
382 |
@@ -1117,7 +1117,8 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1117 | _ = self.request.translate |
|
1117 | _ = self.request.translate | |
1118 |
|
1118 | |||
1119 | with pull_request.set_state(PullRequest.STATE_UPDATING): |
|
1119 | with pull_request.set_state(PullRequest.STATE_UPDATING): | |
1120 |
resp = PullRequestModel().update_commits( |
|
1120 | resp = PullRequestModel().update_commits( | |
|
1121 | pull_request, self._rhodecode_db_user) | |||
1121 |
|
1122 | |||
1122 | if resp.executed: |
|
1123 | if resp.executed: | |
1123 |
|
1124 |
@@ -821,7 +821,7 b' def is_svn_without_proxy(repository):' | |||||
821 |
|
821 | |||
822 | def discover_user(author): |
|
822 | def discover_user(author): | |
823 | """ |
|
823 | """ | |
824 | Tries to discover RhodeCode User based on the autho string. Author string |
|
824 | Tries to discover RhodeCode User based on the author string. Author string | |
825 | is typically `FirstName LastName <email@address.com>` |
|
825 | is typically `FirstName LastName <email@address.com>` | |
826 | """ |
|
826 | """ | |
827 |
|
827 | |||
@@ -1015,10 +1015,11 b' def bool2icon(value, show_at_false=True)' | |||||
1015 | #============================================================================== |
|
1015 | #============================================================================== | |
1016 | # PERMS |
|
1016 | # PERMS | |
1017 | #============================================================================== |
|
1017 | #============================================================================== | |
1018 |
from rhodecode.lib.auth import |
|
1018 | from rhodecode.lib.auth import ( | |
1019 |
Has |
|
1019 | HasPermissionAny, HasPermissionAll, | |
1020 |
HasRepo |
|
1020 | HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, | |
1021 | csrf_token_key |
|
1021 | HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token, | |
|
1022 | csrf_token_key, AuthUser) | |||
1022 |
|
1023 | |||
1023 |
|
1024 | |||
1024 | #============================================================================== |
|
1025 | #============================================================================== |
@@ -4401,6 +4401,7 b' class Notification(Base, BaseModel):' | |||||
4401 | TYPE_REGISTRATION = u'registration' |
|
4401 | TYPE_REGISTRATION = u'registration' | |
4402 | TYPE_PULL_REQUEST = u'pull_request' |
|
4402 | TYPE_PULL_REQUEST = u'pull_request' | |
4403 | TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment' |
|
4403 | TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment' | |
|
4404 | TYPE_PULL_REQUEST_UPDATE = u'pull_request_update' | |||
4404 |
|
4405 | |||
4405 | notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True) |
|
4406 | notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True) | |
4406 | subject = Column('subject', Unicode(512), nullable=True) |
|
4407 | subject = Column('subject', Unicode(512), nullable=True) |
@@ -293,6 +293,7 b' class EmailNotificationModel(BaseModel):' | |||||
293 | TYPE_REGISTRATION = Notification.TYPE_REGISTRATION |
|
293 | TYPE_REGISTRATION = Notification.TYPE_REGISTRATION | |
294 | TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST |
|
294 | TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST | |
295 | TYPE_PULL_REQUEST_COMMENT = Notification.TYPE_PULL_REQUEST_COMMENT |
|
295 | TYPE_PULL_REQUEST_COMMENT = Notification.TYPE_PULL_REQUEST_COMMENT | |
|
296 | TYPE_PULL_REQUEST_UPDATE = Notification.TYPE_PULL_REQUEST_UPDATE | |||
296 | TYPE_MAIN = Notification.TYPE_MESSAGE |
|
297 | TYPE_MAIN = Notification.TYPE_MESSAGE | |
297 |
|
298 | |||
298 | TYPE_PASSWORD_RESET = 'password_reset' |
|
299 | TYPE_PASSWORD_RESET = 'password_reset' | |
@@ -319,6 +320,8 b' class EmailNotificationModel(BaseModel):' | |||||
319 | 'rhodecode:templates/email_templates/pull_request_review.mako', |
|
320 | 'rhodecode:templates/email_templates/pull_request_review.mako', | |
320 | TYPE_PULL_REQUEST_COMMENT: |
|
321 | TYPE_PULL_REQUEST_COMMENT: | |
321 | 'rhodecode:templates/email_templates/pull_request_comment.mako', |
|
322 | 'rhodecode:templates/email_templates/pull_request_comment.mako', | |
|
323 | TYPE_PULL_REQUEST_UPDATE: | |||
|
324 | 'rhodecode:templates/email_templates/pull_request_update.mako', | |||
322 | } |
|
325 | } | |
323 |
|
326 | |||
324 | def __init__(self): |
|
327 | def __init__(self): | |
@@ -341,6 +344,7 b' class EmailNotificationModel(BaseModel):' | |||||
341 | """ |
|
344 | """ | |
342 |
|
345 | |||
343 | kwargs['rhodecode_instance_name'] = self.rhodecode_instance_name |
|
346 | kwargs['rhodecode_instance_name'] = self.rhodecode_instance_name | |
|
347 | kwargs['rhodecode_version'] = rhodecode.__version__ | |||
344 | instance_url = h.route_url('home') |
|
348 | instance_url = h.route_url('home') | |
345 | _kwargs = { |
|
349 | _kwargs = { | |
346 | 'instance_url': instance_url, |
|
350 | 'instance_url': instance_url, |
@@ -65,9 +65,19 b' log = logging.getLogger(__name__)' | |||||
65 |
|
65 | |||
66 | # Data structure to hold the response data when updating commits during a pull |
|
66 | # Data structure to hold the response data when updating commits during a pull | |
67 | # request update. |
|
67 | # request update. | |
68 | UpdateResponse = collections.namedtuple('UpdateResponse', [ |
|
68 | class UpdateResponse(object): | |
69 | 'executed', 'reason', 'new', 'old', 'changes', |
|
69 | ||
70 | 'source_changed', 'target_changed']) |
|
70 | def __init__(self, executed, reason, new, old, common_ancestor_id, | |
|
71 | commit_changes, source_changed, target_changed): | |||
|
72 | ||||
|
73 | self.executed = executed | |||
|
74 | self.reason = reason | |||
|
75 | self.new = new | |||
|
76 | self.old = old | |||
|
77 | self.common_ancestor_id = common_ancestor_id | |||
|
78 | self.changes = commit_changes | |||
|
79 | self.source_changed = source_changed | |||
|
80 | self.target_changed = target_changed | |||
71 |
|
81 | |||
72 |
|
82 | |||
73 | class PullRequestModel(BaseModel): |
|
83 | class PullRequestModel(BaseModel): | |
@@ -672,11 +682,13 b' class PullRequestModel(BaseModel):' | |||||
672 | source_ref_type = pull_request.source_ref_parts.type |
|
682 | source_ref_type = pull_request.source_ref_parts.type | |
673 | return source_ref_type in self.REF_TYPES |
|
683 | return source_ref_type in self.REF_TYPES | |
674 |
|
684 | |||
675 | def update_commits(self, pull_request): |
|
685 | def update_commits(self, pull_request, updating_user): | |
676 | """ |
|
686 | """ | |
677 | Get the updated list of commits for the pull request |
|
687 | Get the updated list of commits for the pull request | |
678 | and return the new pull request version and the list |
|
688 | and return the new pull request version and the list | |
679 | of commits processed by this update action |
|
689 | of commits processed by this update action | |
|
690 | ||||
|
691 | updating_user is the user_object who triggered the update | |||
680 | """ |
|
692 | """ | |
681 | pull_request = self.__get_pull_request(pull_request) |
|
693 | pull_request = self.__get_pull_request(pull_request) | |
682 | source_ref_type = pull_request.source_ref_parts.type |
|
694 | source_ref_type = pull_request.source_ref_parts.type | |
@@ -693,7 +705,7 b' class PullRequestModel(BaseModel):' | |||||
693 | return UpdateResponse( |
|
705 | return UpdateResponse( | |
694 | executed=False, |
|
706 | executed=False, | |
695 | reason=UpdateFailureReason.WRONG_REF_TYPE, |
|
707 | reason=UpdateFailureReason.WRONG_REF_TYPE, | |
696 | old=pull_request, new=None, changes=None, |
|
708 | old=pull_request, new=None, common_ancestor_id=None, commit_changes=None, | |
697 | source_changed=False, target_changed=False) |
|
709 | source_changed=False, target_changed=False) | |
698 |
|
710 | |||
699 | # source repo |
|
711 | # source repo | |
@@ -705,7 +717,7 b' class PullRequestModel(BaseModel):' | |||||
705 | return UpdateResponse( |
|
717 | return UpdateResponse( | |
706 | executed=False, |
|
718 | executed=False, | |
707 | reason=UpdateFailureReason.MISSING_SOURCE_REF, |
|
719 | reason=UpdateFailureReason.MISSING_SOURCE_REF, | |
708 | old=pull_request, new=None, changes=None, |
|
720 | old=pull_request, new=None, common_ancestor_id=None, commit_changes=None, | |
709 | source_changed=False, target_changed=False) |
|
721 | source_changed=False, target_changed=False) | |
710 |
|
722 | |||
711 | source_changed = source_ref_id != source_commit.raw_id |
|
723 | source_changed = source_ref_id != source_commit.raw_id | |
@@ -719,7 +731,7 b' class PullRequestModel(BaseModel):' | |||||
719 | return UpdateResponse( |
|
731 | return UpdateResponse( | |
720 | executed=False, |
|
732 | executed=False, | |
721 | reason=UpdateFailureReason.MISSING_TARGET_REF, |
|
733 | reason=UpdateFailureReason.MISSING_TARGET_REF, | |
722 | old=pull_request, new=None, changes=None, |
|
734 | old=pull_request, new=None, common_ancestor_id=None, commit_changes=None, | |
723 | source_changed=False, target_changed=False) |
|
735 | source_changed=False, target_changed=False) | |
724 | target_changed = target_ref_id != target_commit.raw_id |
|
736 | target_changed = target_ref_id != target_commit.raw_id | |
725 |
|
737 | |||
@@ -728,7 +740,7 b' class PullRequestModel(BaseModel):' | |||||
728 | return UpdateResponse( |
|
740 | return UpdateResponse( | |
729 | executed=False, |
|
741 | executed=False, | |
730 | reason=UpdateFailureReason.NO_CHANGE, |
|
742 | reason=UpdateFailureReason.NO_CHANGE, | |
731 | old=pull_request, new=None, changes=None, |
|
743 | old=pull_request, new=None, common_ancestor_id=None, commit_changes=None, | |
732 | source_changed=target_changed, target_changed=source_changed) |
|
744 | source_changed=target_changed, target_changed=source_changed) | |
733 |
|
745 | |||
734 | change_in_found = 'target repo' if target_changed else 'source repo' |
|
746 | change_in_found = 'target repo' if target_changed else 'source repo' | |
@@ -759,7 +771,7 b' class PullRequestModel(BaseModel):' | |||||
759 | return UpdateResponse( |
|
771 | return UpdateResponse( | |
760 | executed=False, |
|
772 | executed=False, | |
761 | reason=UpdateFailureReason.MISSING_TARGET_REF, |
|
773 | reason=UpdateFailureReason.MISSING_TARGET_REF, | |
762 | old=pull_request, new=None, changes=None, |
|
774 | old=pull_request, new=None, common_ancestor_id=None, commit_changes=None, | |
763 | source_changed=source_changed, target_changed=target_changed) |
|
775 | source_changed=source_changed, target_changed=target_changed) | |
764 |
|
776 | |||
765 | # re-compute commit ids |
|
777 | # re-compute commit ids | |
@@ -769,13 +781,13 b' class PullRequestModel(BaseModel):' | |||||
769 | target_commit.raw_id, source_commit.raw_id, source_repo, merge=True, |
|
781 | target_commit.raw_id, source_commit.raw_id, source_repo, merge=True, | |
770 | pre_load=pre_load) |
|
782 | pre_load=pre_load) | |
771 |
|
783 | |||
772 | ancestor = source_repo.get_common_ancestor( |
|
784 | ancestor_commit_id = source_repo.get_common_ancestor( | |
773 | source_commit.raw_id, target_commit.raw_id, target_repo) |
|
785 | source_commit.raw_id, target_commit.raw_id, target_repo) | |
774 |
|
786 | |||
775 | pull_request.source_ref = '%s:%s:%s' % ( |
|
787 | pull_request.source_ref = '%s:%s:%s' % ( | |
776 | source_ref_type, source_ref_name, source_commit.raw_id) |
|
788 | source_ref_type, source_ref_name, source_commit.raw_id) | |
777 | pull_request.target_ref = '%s:%s:%s' % ( |
|
789 | pull_request.target_ref = '%s:%s:%s' % ( | |
778 | target_ref_type, target_ref_name, ancestor) |
|
790 | target_ref_type, target_ref_name, ancestor_commit_id) | |
779 |
|
791 | |||
780 | pull_request.revisions = [ |
|
792 | pull_request.revisions = [ | |
781 | commit.raw_id for commit in reversed(commit_ranges)] |
|
793 | commit.raw_id for commit in reversed(commit_ranges)] | |
@@ -787,7 +799,7 b' class PullRequestModel(BaseModel):' | |||||
787 | pull_request, pull_request_version) |
|
799 | pull_request, pull_request_version) | |
788 |
|
800 | |||
789 | # calculate commit and file changes |
|
801 | # calculate commit and file changes | |
790 | changes = self._calculate_commit_id_changes( |
|
802 | commit_changes = self._calculate_commit_id_changes( | |
791 | old_commit_ids, new_commit_ids) |
|
803 | old_commit_ids, new_commit_ids) | |
792 | file_changes = self._calculate_file_changes( |
|
804 | file_changes = self._calculate_file_changes( | |
793 | old_diff_data, new_diff_data) |
|
805 | old_diff_data, new_diff_data) | |
@@ -797,23 +809,23 b' class PullRequestModel(BaseModel):' | |||||
797 | pull_request, old_diff_data=old_diff_data, |
|
809 | pull_request, old_diff_data=old_diff_data, | |
798 | new_diff_data=new_diff_data) |
|
810 | new_diff_data=new_diff_data) | |
799 |
|
811 | |||
800 | commit_changes = (changes.added or changes.removed) |
|
812 | valid_commit_changes = (commit_changes.added or commit_changes.removed) | |
801 | file_node_changes = ( |
|
813 | file_node_changes = ( | |
802 | file_changes.added or file_changes.modified or file_changes.removed) |
|
814 | file_changes.added or file_changes.modified or file_changes.removed) | |
803 | pr_has_changes = commit_changes or file_node_changes |
|
815 | pr_has_changes = valid_commit_changes or file_node_changes | |
804 |
|
816 | |||
805 | # Add an automatic comment to the pull request, in case |
|
817 | # Add an automatic comment to the pull request, in case | |
806 | # anything has changed |
|
818 | # anything has changed | |
807 | if pr_has_changes: |
|
819 | if pr_has_changes: | |
808 | update_comment = CommentsModel().create( |
|
820 | update_comment = CommentsModel().create( | |
809 | text=self._render_update_message(changes, file_changes), |
|
821 | text=self._render_update_message(ancestor_commit_id, commit_changes, file_changes), | |
810 | repo=pull_request.target_repo, |
|
822 | repo=pull_request.target_repo, | |
811 | user=pull_request.author, |
|
823 | user=pull_request.author, | |
812 | pull_request=pull_request, |
|
824 | pull_request=pull_request, | |
813 | send_email=False, renderer=DEFAULT_COMMENTS_RENDERER) |
|
825 | send_email=False, renderer=DEFAULT_COMMENTS_RENDERER) | |
814 |
|
826 | |||
815 | # Update status to "Under Review" for added commits |
|
827 | # Update status to "Under Review" for added commits | |
816 | for commit_id in changes.added: |
|
828 | for commit_id in commit_changes.added: | |
817 | ChangesetStatusModel().set_status( |
|
829 | ChangesetStatusModel().set_status( | |
818 | repo=pull_request.source_repo, |
|
830 | repo=pull_request.source_repo, | |
819 | status=ChangesetStatus.STATUS_UNDER_REVIEW, |
|
831 | status=ChangesetStatus.STATUS_UNDER_REVIEW, | |
@@ -822,10 +834,19 b' class PullRequestModel(BaseModel):' | |||||
822 | pull_request=pull_request, |
|
834 | pull_request=pull_request, | |
823 | revision=commit_id) |
|
835 | revision=commit_id) | |
824 |
|
836 | |||
|
837 | # send update email to users | |||
|
838 | try: | |||
|
839 | self.notify_users(pull_request=pull_request, updating_user=updating_user, | |||
|
840 | ancestor_commit_id=ancestor_commit_id, | |||
|
841 | commit_changes=commit_changes, | |||
|
842 | file_changes=file_changes) | |||
|
843 | except Exception: | |||
|
844 | log.exception('Failed to send email notification to users') | |||
|
845 | ||||
825 | log.debug( |
|
846 | log.debug( | |
826 | 'Updated pull request %s, added_ids: %s, common_ids: %s, ' |
|
847 | 'Updated pull request %s, added_ids: %s, common_ids: %s, ' | |
827 | 'removed_ids: %s', pull_request.pull_request_id, |
|
848 | 'removed_ids: %s', pull_request.pull_request_id, | |
828 | changes.added, changes.common, changes.removed) |
|
849 | commit_changes.added, commit_changes.common, commit_changes.removed) | |
829 | log.debug( |
|
850 | log.debug( | |
830 | 'Updated pull request with the following file changes: %s', |
|
851 | 'Updated pull request with the following file changes: %s', | |
831 | file_changes) |
|
852 | file_changes) | |
@@ -841,7 +862,8 b' class PullRequestModel(BaseModel):' | |||||
841 |
|
862 | |||
842 | return UpdateResponse( |
|
863 | return UpdateResponse( | |
843 | executed=True, reason=UpdateFailureReason.NONE, |
|
864 | executed=True, reason=UpdateFailureReason.NONE, | |
844 |
old=pull_request, new=pull_request_version, |
|
865 | old=pull_request, new=pull_request_version, | |
|
866 | common_ancestor_id=ancestor_commit_id, commit_changes=commit_changes, | |||
845 | source_changed=source_changed, target_changed=target_changed) |
|
867 | source_changed=source_changed, target_changed=target_changed) | |
846 |
|
868 | |||
847 | def _create_version_from_snapshot(self, pull_request): |
|
869 | def _create_version_from_snapshot(self, pull_request): | |
@@ -963,12 +985,13 b' class PullRequestModel(BaseModel):' | |||||
963 |
|
985 | |||
964 | return FileChangeTuple(added_files, modified_files, removed_files) |
|
986 | return FileChangeTuple(added_files, modified_files, removed_files) | |
965 |
|
987 | |||
966 | def _render_update_message(self, changes, file_changes): |
|
988 | def _render_update_message(self, ancestor_commit_id, changes, file_changes): | |
967 | """ |
|
989 | """ | |
968 | render the message using DEFAULT_COMMENTS_RENDERER (RST renderer), |
|
990 | render the message using DEFAULT_COMMENTS_RENDERER (RST renderer), | |
969 | so it's always looking the same disregarding on which default |
|
991 | so it's always looking the same disregarding on which default | |
970 | renderer system is using. |
|
992 | renderer system is using. | |
971 |
|
993 | |||
|
994 | :param ancestor_commit_id: ancestor raw_id | |||
972 | :param changes: changes named tuple |
|
995 | :param changes: changes named tuple | |
973 | :param file_changes: file changes named tuple |
|
996 | :param file_changes: file changes named tuple | |
974 |
|
997 | |||
@@ -987,6 +1010,7 b' class PullRequestModel(BaseModel):' | |||||
987 | 'added_files': file_changes.added, |
|
1010 | 'added_files': file_changes.added, | |
988 | 'modified_files': file_changes.modified, |
|
1011 | 'modified_files': file_changes.modified, | |
989 | 'removed_files': file_changes.removed, |
|
1012 | 'removed_files': file_changes.removed, | |
|
1013 | 'ancestor_commit_id': ancestor_commit_id | |||
990 | } |
|
1014 | } | |
991 | renderer = RstTemplateRenderer() |
|
1015 | renderer = RstTemplateRenderer() | |
992 | return renderer.render('pull_request_update.mako', **params) |
|
1016 | return renderer.render('pull_request_update.mako', **params) | |
@@ -1170,6 +1194,75 b' class PullRequestModel(BaseModel):' | |||||
1170 | email_kwargs=kwargs, |
|
1194 | email_kwargs=kwargs, | |
1171 | ) |
|
1195 | ) | |
1172 |
|
1196 | |||
|
1197 | def notify_users(self, pull_request, updating_user, ancestor_commit_id, | |||
|
1198 | commit_changes, file_changes): | |||
|
1199 | ||||
|
1200 | updating_user_id = updating_user.user_id | |||
|
1201 | reviewers = set([x.user.user_id for x in pull_request.reviewers]) | |||
|
1202 | # NOTE(marcink): send notification to all other users except to | |||
|
1203 | # person who updated the PR | |||
|
1204 | recipients = reviewers.difference(set([updating_user_id])) | |||
|
1205 | ||||
|
1206 | log.debug('Notify following recipients about pull-request update %s', recipients) | |||
|
1207 | ||||
|
1208 | pull_request_obj = pull_request | |||
|
1209 | ||||
|
1210 | # send email about the update | |||
|
1211 | changed_files = ( | |||
|
1212 | file_changes.added + file_changes.modified + file_changes.removed) | |||
|
1213 | ||||
|
1214 | pr_source_repo = pull_request_obj.source_repo | |||
|
1215 | pr_target_repo = pull_request_obj.target_repo | |||
|
1216 | ||||
|
1217 | pr_url = h.route_url('pullrequest_show', | |||
|
1218 | repo_name=pr_target_repo.repo_name, | |||
|
1219 | pull_request_id=pull_request_obj.pull_request_id,) | |||
|
1220 | ||||
|
1221 | # set some variables for email notification | |||
|
1222 | pr_target_repo_url = h.route_url( | |||
|
1223 | 'repo_summary', repo_name=pr_target_repo.repo_name) | |||
|
1224 | ||||
|
1225 | pr_source_repo_url = h.route_url( | |||
|
1226 | 'repo_summary', repo_name=pr_source_repo.repo_name) | |||
|
1227 | ||||
|
1228 | email_kwargs = { | |||
|
1229 | 'date': datetime.datetime.now(), | |||
|
1230 | 'updating_user': updating_user, | |||
|
1231 | ||||
|
1232 | 'pull_request': pull_request_obj, | |||
|
1233 | ||||
|
1234 | 'pull_request_target_repo': pr_target_repo, | |||
|
1235 | 'pull_request_target_repo_url': pr_target_repo_url, | |||
|
1236 | ||||
|
1237 | 'pull_request_source_repo': pr_source_repo, | |||
|
1238 | 'pull_request_source_repo_url': pr_source_repo_url, | |||
|
1239 | ||||
|
1240 | 'pull_request_url': pr_url, | |||
|
1241 | ||||
|
1242 | 'ancestor_commit_id': ancestor_commit_id, | |||
|
1243 | 'added_commits': commit_changes.added, | |||
|
1244 | 'removed_commits': commit_changes.removed, | |||
|
1245 | 'changed_files': changed_files, | |||
|
1246 | 'added_files': file_changes.added, | |||
|
1247 | 'modified_files': file_changes.modified, | |||
|
1248 | 'removed_files': file_changes.removed, | |||
|
1249 | } | |||
|
1250 | ||||
|
1251 | (subject, | |||
|
1252 | _h, _e, # we don't care about those | |||
|
1253 | body_plaintext) = EmailNotificationModel().render_email( | |||
|
1254 | EmailNotificationModel.TYPE_PULL_REQUEST_UPDATE, **email_kwargs) | |||
|
1255 | ||||
|
1256 | # create notification objects, and emails | |||
|
1257 | NotificationModel().create( | |||
|
1258 | created_by=updating_user, | |||
|
1259 | notification_subject=subject, | |||
|
1260 | notification_body=body_plaintext, | |||
|
1261 | notification_type=EmailNotificationModel.TYPE_PULL_REQUEST_UPDATE, | |||
|
1262 | recipients=recipients, | |||
|
1263 | email_kwargs=email_kwargs, | |||
|
1264 | ) | |||
|
1265 | ||||
1173 | def delete(self, pull_request, user): |
|
1266 | def delete(self, pull_request, user): | |
1174 | pull_request = self.__get_pull_request(pull_request) |
|
1267 | pull_request = self.__get_pull_request(pull_request) | |
1175 | old_data = pull_request.get_api_data(with_merge_state=False) |
|
1268 | old_data = pull_request.get_api_data(with_merge_state=False) |
@@ -115,17 +115,17 b' data = {' | |||||
115 | <td style="width:100%;border-bottom:1px solid #dbd9da;"> |
|
115 | <td style="width:100%;border-bottom:1px solid #dbd9da;"> | |
116 |
|
116 | |||
117 | <h4 style="margin: 0"> |
|
117 | <h4 style="margin: 0"> | |
118 |
<div style="margin-bottom: 4px |
|
118 | <div style="margin-bottom: 4px"> | |
119 | @${h.person(user.username)} |
|
119 | <span style="color:#7E7F7F">@${h.person(user.username)}</span> | |
|
120 | ${_('left a')} | |||
|
121 | <a href="${pr_comment_url}" style="${base.link_css()}"> | |||
|
122 | % if comment_file: | |||
|
123 | ${_('{comment_type} on file `{comment_file}` in pull request.').format(**data)} | |||
|
124 | % else: | |||
|
125 | ${_('{comment_type} on pull request.').format(**data) |n} | |||
|
126 | % endif | |||
|
127 | </a> | |||
120 | </div> |
|
128 | </div> | |
121 | ${_('left a')} |
|
|||
122 | <a href="${pr_comment_url}" style="${base.link_css()}"> |
|
|||
123 | % if comment_file: |
|
|||
124 | ${_('{comment_type} on file `{comment_file}` in pull request.').format(**data)} |
|
|||
125 | % else: |
|
|||
126 | ${_('{comment_type} on pull request.').format(**data) |n} |
|
|||
127 | % endif |
|
|||
128 | </a> |
|
|||
129 | <div style="margin-top: 10px"></div> |
|
129 | <div style="margin-top: 10px"></div> | |
130 | ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code> |
|
130 | ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code> | |
131 | </h4> |
|
131 | </h4> |
@@ -78,13 +78,13 b' data = {' | |||||
78 | <td style="width:100%;border-bottom:1px solid #dbd9da;"> |
|
78 | <td style="width:100%;border-bottom:1px solid #dbd9da;"> | |
79 |
|
79 | |||
80 | <h4 style="margin: 0"> |
|
80 | <h4 style="margin: 0"> | |
81 |
<div style="margin-bottom: 4px |
|
81 | <div style="margin-bottom: 4px"> | |
82 | @${h.person(user.username)} |
|
82 | <span style="color:#7E7F7F">@${h.person(user.username)}</span> | |
|
83 | ${_('requested a')} | |||
|
84 | <a href="${pull_request_url}" style="${base.link_css()}"> | |||
|
85 | ${_('pull request review.').format(**data) } | |||
|
86 | </a> | |||
83 | </div> |
|
87 | </div> | |
84 | ${_('requested a')} |
|
|||
85 | <a href="${pull_request_url}" style="${base.link_css()}"> |
|
|||
86 | ${_('pull request review.').format(**data) } |
|
|||
87 | </a> |
|
|||
88 | <div style="margin-top: 10px"></div> |
|
88 | <div style="margin-top: 10px"></div> | |
89 | ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code> |
|
89 | ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code> | |
90 | </h4> |
|
90 | </h4> |
@@ -14,13 +14,13 b' Pull request updated. Auto status change' | |||||
14 | %else: |
|
14 | %else: | |
15 | Changed files: |
|
15 | Changed files: | |
16 | %for file_name in added_files: |
|
16 | %for file_name in added_files: | |
17 |
* `A ${file_name} <#${'a_' + h.FID( |
|
17 | * `A ${file_name} <#${'a_' + h.FID(ancestor_commit_id, file_name)}>`_ | |
18 | %endfor |
|
18 | %endfor | |
19 | %for file_name in modified_files: |
|
19 | %for file_name in modified_files: | |
20 |
* `M ${file_name} <#${'a_' + h.FID( |
|
20 | * `M ${file_name} <#${'a_' + h.FID(ancestor_commit_id, file_name)}>`_ | |
21 | %endfor |
|
21 | %endfor | |
22 | %for file_name in removed_files: |
|
22 | %for file_name in removed_files: | |
23 | * R ${file_name} |
|
23 | * `R ${file_name}` | |
24 | %endfor |
|
24 | %endfor | |
25 | %endif |
|
25 | %endif | |
26 |
|
26 |
@@ -87,6 +87,59 b' def test_render_pr_email(app, user_admin' | |||||
87 | assert subject == '@test_admin (RhodeCode Admin) requested a pull request review. !200: "Example Pull Request"' |
|
87 | assert subject == '@test_admin (RhodeCode Admin) requested a pull request review. !200: "Example Pull Request"' | |
88 |
|
88 | |||
89 |
|
89 | |||
|
90 | def test_render_pr_update_email(app, user_admin): | |||
|
91 | ref = collections.namedtuple( | |||
|
92 | 'Ref', 'name, type')('fxies123', 'book') | |||
|
93 | ||||
|
94 | pr = collections.namedtuple('PullRequest', | |||
|
95 | 'pull_request_id, title, description, source_ref_parts, source_ref_name, target_ref_parts, target_ref_name')( | |||
|
96 | 200, 'Example Pull Request', 'Desc of PR', ref, 'bookmark', ref, 'Branch') | |||
|
97 | ||||
|
98 | source_repo = target_repo = collections.namedtuple( | |||
|
99 | 'Repo', 'type, repo_name')('hg', 'pull_request_1') | |||
|
100 | ||||
|
101 | commit_changes = AttributeDict({ | |||
|
102 | 'added': ['aaaaaaabbbbb', 'cccccccddddddd'], | |||
|
103 | 'removed': ['eeeeeeeeeee'], | |||
|
104 | }) | |||
|
105 | file_changes = AttributeDict({ | |||
|
106 | 'added': ['a/file1.md', 'file2.py'], | |||
|
107 | 'modified': ['b/modified_file.rst'], | |||
|
108 | 'removed': ['.idea'], | |||
|
109 | }) | |||
|
110 | ||||
|
111 | kwargs = { | |||
|
112 | 'updating_user': User.get_first_super_admin(), | |||
|
113 | ||||
|
114 | 'pull_request': pr, | |||
|
115 | 'pull_request_commits': [], | |||
|
116 | ||||
|
117 | 'pull_request_target_repo': target_repo, | |||
|
118 | 'pull_request_target_repo_url': 'x', | |||
|
119 | ||||
|
120 | 'pull_request_source_repo': source_repo, | |||
|
121 | 'pull_request_source_repo_url': 'x', | |||
|
122 | ||||
|
123 | 'pull_request_url': 'http://localhost/pr1', | |||
|
124 | ||||
|
125 | 'pr_comment_url': 'http://comment-url', | |||
|
126 | 'pr_comment_reply_url': 'http://comment-url#reply', | |||
|
127 | 'ancestor_commit_id': 'f39bd443', | |||
|
128 | 'added_commits': commit_changes.added, | |||
|
129 | 'removed_commits': commit_changes.removed, | |||
|
130 | 'changed_files': (file_changes.added + file_changes.modified + file_changes.removed), | |||
|
131 | 'added_files': file_changes.added, | |||
|
132 | 'modified_files': file_changes.modified, | |||
|
133 | 'removed_files': file_changes.removed, | |||
|
134 | } | |||
|
135 | ||||
|
136 | subject, headers, body, body_plaintext = EmailNotificationModel().render_email( | |||
|
137 | EmailNotificationModel.TYPE_PULL_REQUEST_UPDATE, **kwargs) | |||
|
138 | ||||
|
139 | # subject | |||
|
140 | assert subject == '@test_admin (RhodeCode Admin) updated pull request. !200: "Example Pull Request"' | |||
|
141 | ||||
|
142 | ||||
90 | @pytest.mark.parametrize('mention', [ |
|
143 | @pytest.mark.parametrize('mention', [ | |
91 | True, |
|
144 | True, | |
92 | False |
|
145 | False |
@@ -538,6 +538,7 b' Pull request updated. Auto status change' | |||||
538 | 'added_files': [], |
|
538 | 'added_files': [], | |
539 | 'modified_files': [], |
|
539 | 'modified_files': [], | |
540 | 'removed_files': [], |
|
540 | 'removed_files': [], | |
|
541 | 'ancestor_commit_id': 'aaabbbcccdddeee', | |||
541 | } |
|
542 | } | |
542 | renderer = RstTemplateRenderer() |
|
543 | renderer = RstTemplateRenderer() | |
543 | rendered = renderer.render('pull_request_update.mako', **params) |
|
544 | rendered = renderer.render('pull_request_update.mako', **params) | |
@@ -557,11 +558,11 b' Pull request updated. Auto status change' | |||||
557 | * :removed:`3 removed` |
|
558 | * :removed:`3 removed` | |
558 |
|
559 | |||
559 | Changed files: |
|
560 | Changed files: | |
560 | * `A /path/a.py <#a_c--68ed34923b68>`_ |
|
561 | * `A /path/a.py <#a_c-aaabbbcccddd-68ed34923b68>`_ | |
561 | * `A /path/b.js <#a_c--64f90608b607>`_ |
|
562 | * `A /path/b.js <#a_c-aaabbbcccddd-64f90608b607>`_ | |
562 | * `M /path/d.js <#a_c--85842bf30c6e>`_ |
|
563 | * `M /path/d.js <#a_c-aaabbbcccddd-85842bf30c6e>`_ | |
563 | * `M /path/ę.py <#a_c--d713adf009cd>`_ |
|
564 | * `M /path/ę.py <#a_c-aaabbbcccddd-d713adf009cd>`_ | |
564 | * R /path/ź.py |
|
565 | * `R /path/ź.py` | |
565 |
|
566 | |||
566 | .. |under_review| replace:: *"NEW STATUS"*''' |
|
567 | .. |under_review| replace:: *"NEW STATUS"*''' | |
567 |
|
568 | |||
@@ -577,6 +578,7 b' Pull request updated. Auto status change' | |||||
577 | 'added_files': added, |
|
578 | 'added_files': added, | |
578 | 'modified_files': modified, |
|
579 | 'modified_files': modified, | |
579 | 'removed_files': removed, |
|
580 | 'removed_files': removed, | |
|
581 | 'ancestor_commit_id': 'aaabbbcccdddeee', | |||
580 | } |
|
582 | } | |
581 | renderer = RstTemplateRenderer() |
|
583 | renderer = RstTemplateRenderer() | |
582 | rendered = renderer.render('pull_request_update.mako', **params) |
|
584 | rendered = renderer.render('pull_request_update.mako', **params) |
@@ -81,7 +81,7 b' def test_pull_request_stays_if_update_wi' | |||||
81 | voted_status, *pull_request.reviewers) |
|
81 | voted_status, *pull_request.reviewers) | |
82 |
|
82 | |||
83 | # Update, without change |
|
83 | # Update, without change | |
84 | PullRequestModel().update_commits(pull_request) |
|
84 | PullRequestModel().update_commits(pull_request, pull_request.author) | |
85 |
|
85 | |||
86 | # Expect that review status is the voted_status |
|
86 | # Expect that review status is the voted_status | |
87 | expected_review_status = voted_status |
|
87 | expected_review_status = voted_status | |
@@ -100,7 +100,7 b' def test_pull_request_under_review_if_up' | |||||
100 |
|
100 | |||
101 | # Update, with change |
|
101 | # Update, with change | |
102 | pr_util.update_source_repository() |
|
102 | pr_util.update_source_repository() | |
103 | PullRequestModel().update_commits(pull_request) |
|
103 | PullRequestModel().update_commits(pull_request, pull_request.author) | |
104 |
|
104 | |||
105 | # Expect that review status is the voted_status |
|
105 | # Expect that review status is the voted_status | |
106 | expected_review_status = db.ChangesetStatus.STATUS_UNDER_REVIEW |
|
106 | expected_review_status = db.ChangesetStatus.STATUS_UNDER_REVIEW | |
@@ -171,7 +171,7 b' def test_commit_keeps_status_if_unchange' | |||||
171 | commit_id = pull_request.revisions[-1] |
|
171 | commit_id = pull_request.revisions[-1] | |
172 | pr_util.create_status_votes(voted_status, pull_request.reviewers[0]) |
|
172 | pr_util.create_status_votes(voted_status, pull_request.reviewers[0]) | |
173 | pr_util.update_source_repository() |
|
173 | pr_util.update_source_repository() | |
174 | PullRequestModel().update_commits(pull_request) |
|
174 | PullRequestModel().update_commits(pull_request, pull_request.author) | |
175 | assert pull_request.revisions[-1] == commit_id |
|
175 | assert pull_request.revisions[-1] == commit_id | |
176 |
|
176 | |||
177 | status = ChangesetStatusModel().get_status( |
|
177 | status = ChangesetStatusModel().get_status( |
@@ -814,7 +814,7 b' def test_update_writes_snapshot_into_pul' | |||||
814 | pull_request = pr_util.create_pull_request() |
|
814 | pull_request = pr_util.create_pull_request() | |
815 | pr_util.update_source_repository() |
|
815 | pr_util.update_source_repository() | |
816 |
|
816 | |||
817 | model.update_commits(pull_request) |
|
817 | model.update_commits(pull_request, pull_request.author) | |
818 |
|
818 | |||
819 | # Expect that it has a version entry now |
|
819 | # Expect that it has a version entry now | |
820 | assert len(model.get_versions(pull_request)) == 1 |
|
820 | assert len(model.get_versions(pull_request)) == 1 | |
@@ -823,7 +823,7 b' def test_update_writes_snapshot_into_pul' | |||||
823 | def test_update_skips_new_version_if_unchanged(pr_util, config_stub): |
|
823 | def test_update_skips_new_version_if_unchanged(pr_util, config_stub): | |
824 | pull_request = pr_util.create_pull_request() |
|
824 | pull_request = pr_util.create_pull_request() | |
825 | model = PullRequestModel() |
|
825 | model = PullRequestModel() | |
826 | model.update_commits(pull_request) |
|
826 | model.update_commits(pull_request, pull_request.author) | |
827 |
|
827 | |||
828 | # Expect that it still has no versions |
|
828 | # Expect that it still has no versions | |
829 | assert len(model.get_versions(pull_request)) == 0 |
|
829 | assert len(model.get_versions(pull_request)) == 0 | |
@@ -835,7 +835,7 b' def test_update_assigns_comments_to_the_' | |||||
835 | comment = pr_util.create_comment() |
|
835 | comment = pr_util.create_comment() | |
836 | pr_util.update_source_repository() |
|
836 | pr_util.update_source_repository() | |
837 |
|
837 | |||
838 | model.update_commits(pull_request) |
|
838 | model.update_commits(pull_request, pull_request.author) | |
839 |
|
839 | |||
840 | # Expect that the comment is linked to the pr version now |
|
840 | # Expect that the comment is linked to the pr version now | |
841 | assert comment.pull_request_version == model.get_versions(pull_request)[0] |
|
841 | assert comment.pull_request_version == model.get_versions(pull_request)[0] | |
@@ -847,8 +847,9 b' def test_update_adds_a_comment_to_the_pu' | |||||
847 | pr_util.update_source_repository() |
|
847 | pr_util.update_source_repository() | |
848 | pr_util.update_source_repository() |
|
848 | pr_util.update_source_repository() | |
849 |
|
849 | |||
850 | model.update_commits(pull_request) |
|
850 | update_response = model.update_commits(pull_request, pull_request.author) | |
851 |
|
851 | |||
|
852 | commit_id = update_response.common_ancestor_id | |||
852 | # Expect to find a new comment about the change |
|
853 | # Expect to find a new comment about the change | |
853 | expected_message = textwrap.dedent( |
|
854 | expected_message = textwrap.dedent( | |
854 | """\ |
|
855 | """\ | |
@@ -863,10 +864,10 b' def test_update_adds_a_comment_to_the_pu' | |||||
863 | * :removed:`0 removed` |
|
864 | * :removed:`0 removed` | |
864 |
|
865 | |||
865 | Changed files: |
|
866 | Changed files: | |
866 | * `A file_2 <#a_c--92ed3b5f07b4>`_ |
|
867 | * `A file_2 <#a_c-{}-92ed3b5f07b4>`_ | |
867 |
|
868 | |||
868 | .. |under_review| replace:: *"Under Review"*""" |
|
869 | .. |under_review| replace:: *"Under Review"*""" | |
869 | ) |
|
870 | ).format(commit_id[:12]) | |
870 | pull_request_comments = sorted( |
|
871 | pull_request_comments = sorted( | |
871 | pull_request.comments, key=lambda c: c.modified_at) |
|
872 | pull_request.comments, key=lambda c: c.modified_at) | |
872 | update_comment = pull_request_comments[-1] |
|
873 | update_comment = pull_request_comments[-1] |
@@ -1047,7 +1047,7 b' class PRTestUtility(object):' | |||||
1047 | def add_one_commit(self, head=None): |
|
1047 | def add_one_commit(self, head=None): | |
1048 | self.update_source_repository(head=head) |
|
1048 | self.update_source_repository(head=head) | |
1049 | old_commit_ids = set(self.pull_request.revisions) |
|
1049 | old_commit_ids = set(self.pull_request.revisions) | |
1050 | PullRequestModel().update_commits(self.pull_request) |
|
1050 | PullRequestModel().update_commits(self.pull_request, self.pull_request.author) | |
1051 | commit_ids = set(self.pull_request.revisions) |
|
1051 | commit_ids = set(self.pull_request.revisions) | |
1052 | new_commit_ids = commit_ids - old_commit_ids |
|
1052 | new_commit_ids = commit_ids - old_commit_ids | |
1053 | assert len(new_commit_ids) == 1 |
|
1053 | assert len(new_commit_ids) == 1 | |
@@ -1066,7 +1066,7 b' class PRTestUtility(object):' | |||||
1066 | kwargs = {} |
|
1066 | kwargs = {} | |
1067 | source_vcs.strip(removed_commit_id, **kwargs) |
|
1067 | source_vcs.strip(removed_commit_id, **kwargs) | |
1068 |
|
1068 | |||
1069 | PullRequestModel().update_commits(self.pull_request) |
|
1069 | PullRequestModel().update_commits(self.pull_request, self.pull_request.author) | |
1070 | assert len(self.pull_request.revisions) == 1 |
|
1070 | assert len(self.pull_request.revisions) == 1 | |
1071 | return removed_commit_id |
|
1071 | return removed_commit_id | |
1072 |
|
1072 |
General Comments 0
You need to be logged in to leave comments.
Login now