##// END OF EJS Templates
really check if last status is from pull request
marcink -
r2771:9640c1c6 beta
parent child Browse files
Show More
@@ -1,188 +1,189 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.changeset_status
3 rhodecode.model.changeset_status
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6
6
7 :created_on: Apr 30, 2012
7 :created_on: Apr 30, 2012
8 :author: marcink
8 :author: marcink
9 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
9 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
10 :license: GPLv3, see COPYING for more details.
10 :license: GPLv3, see COPYING for more details.
11 """
11 """
12 # This program is free software: you can redistribute it and/or modify
12 # This program is free software: you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation, either version 3 of the License, or
14 # the Free Software Foundation, either version 3 of the License, or
15 # (at your option) any later version.
15 # (at your option) any later version.
16 #
16 #
17 # This program is distributed in the hope that it will be useful,
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
20 # GNU General Public License for more details.
21 #
21 #
22 # You should have received a copy of the GNU General Public License
22 # You should have received a copy of the GNU General Public License
23 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24
24
25
25
26 import logging
26 import logging
27 from collections import defaultdict
27 from collections import defaultdict
28
28
29 from rhodecode.model import BaseModel
29 from rhodecode.model import BaseModel
30 from rhodecode.model.db import ChangesetStatus, PullRequest
30 from rhodecode.model.db import ChangesetStatus, PullRequest
31 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
31 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
32
32
33 log = logging.getLogger(__name__)
33 log = logging.getLogger(__name__)
34
34
35
35
36 class ChangesetStatusModel(BaseModel):
36 class ChangesetStatusModel(BaseModel):
37
37
38 cls = ChangesetStatus
38 cls = ChangesetStatus
39
39
40 def __get_changeset_status(self, changeset_status):
40 def __get_changeset_status(self, changeset_status):
41 return self._get_instance(ChangesetStatus, changeset_status)
41 return self._get_instance(ChangesetStatus, changeset_status)
42
42
43 def __get_pull_request(self, pull_request):
43 def __get_pull_request(self, pull_request):
44 return self._get_instance(PullRequest, pull_request)
44 return self._get_instance(PullRequest, pull_request)
45
45
46 def _get_status_query(self, repo, revision, pull_request,
46 def _get_status_query(self, repo, revision, pull_request,
47 with_revisions=False):
47 with_revisions=False):
48 repo = self._get_repo(repo)
48 repo = self._get_repo(repo)
49
49
50 q = ChangesetStatus.query()\
50 q = ChangesetStatus.query()\
51 .filter(ChangesetStatus.repo == repo)
51 .filter(ChangesetStatus.repo == repo)
52 if not with_revisions:
52 if not with_revisions:
53 q = q.filter(ChangesetStatus.version == 0)
53 q = q.filter(ChangesetStatus.version == 0)
54
54
55 if revision:
55 if revision:
56 q = q.filter(ChangesetStatus.revision == revision)
56 q = q.filter(ChangesetStatus.revision == revision)
57 elif pull_request:
57 elif pull_request:
58 pull_request = self.__get_pull_request(pull_request)
58 pull_request = self.__get_pull_request(pull_request)
59 q = q.filter(ChangesetStatus.pull_request == pull_request)
59 q = q.filter(ChangesetStatus.pull_request == pull_request)
60 else:
60 else:
61 raise Exception('Please specify revision or pull_request')
61 raise Exception('Please specify revision or pull_request')
62 q.order_by(ChangesetStatus.version.asc())
62 q.order_by(ChangesetStatus.version.asc())
63 return q
63 return q
64
64
65 def calculate_status(self, statuses_by_reviewers):
65 def calculate_status(self, statuses_by_reviewers):
66 """
66 """
67 leading one wins, if number of occurences are equal than weaker wins
67 leading one wins, if number of occurences are equal than weaker wins
68
68
69 :param statuses_by_reviewers:
69 :param statuses_by_reviewers:
70 """
70 """
71 status = None
71 status = None
72 votes = defaultdict(int)
72 votes = defaultdict(int)
73 reviewers_number = len(statuses_by_reviewers)
73 reviewers_number = len(statuses_by_reviewers)
74 for user, statuses in statuses_by_reviewers:
74 for user, statuses in statuses_by_reviewers:
75 if statuses:
75 if statuses:
76 ver, latest = statuses[0]
76 ver, latest = statuses[0]
77 votes[latest.status] += 1
77 votes[latest.status] += 1
78 else:
78 else:
79 votes[ChangesetStatus.DEFAULT] += 1
79 votes[ChangesetStatus.DEFAULT] += 1
80
80
81 if votes.get(ChangesetStatus.STATUS_APPROVED) == reviewers_number:
81 if votes.get(ChangesetStatus.STATUS_APPROVED) == reviewers_number:
82 return ChangesetStatus.STATUS_APPROVED
82 return ChangesetStatus.STATUS_APPROVED
83 else:
83 else:
84 return ChangesetStatus.STATUS_UNDER_REVIEW
84 return ChangesetStatus.STATUS_UNDER_REVIEW
85
85
86 def get_statuses(self, repo, revision=None, pull_request=None,
86 def get_statuses(self, repo, revision=None, pull_request=None,
87 with_revisions=False):
87 with_revisions=False):
88 q = self._get_status_query(repo, revision, pull_request,
88 q = self._get_status_query(repo, revision, pull_request,
89 with_revisions)
89 with_revisions)
90 return q.all()
90 return q.all()
91
91
92 def get_status(self, repo, revision=None, pull_request=None):
92 def get_status(self, repo, revision=None, pull_request=None):
93 """
93 """
94 Returns latest status of changeset for given revision or for given
94 Returns latest status of changeset for given revision or for given
95 pull request. Statuses are versioned inside a table itself and
95 pull request. Statuses are versioned inside a table itself and
96 version == 0 is always the current one
96 version == 0 is always the current one
97
97
98 :param repo:
98 :param repo:
99 :type repo:
99 :type repo:
100 :param revision: 40char hash or None
100 :param revision: 40char hash or None
101 :type revision: str
101 :type revision: str
102 :param pull_request: pull_request reference
102 :param pull_request: pull_request reference
103 :type:
103 :type:
104 """
104 """
105 q = self._get_status_query(repo, revision, pull_request)
105 q = self._get_status_query(repo, revision, pull_request)
106
106
107 # need to use first here since there can be multiple statuses
107 # need to use first here since there can be multiple statuses
108 # returned from pull_request
108 # returned from pull_request
109 status = q.first()
109 status = q.first()
110 status = status.status if status else status
110 status = status.status if status else status
111 st = status or ChangesetStatus.DEFAULT
111 st = status or ChangesetStatus.DEFAULT
112 return str(st)
112 return str(st)
113
113
114 def set_status(self, repo, status, user, comment, revision=None,
114 def set_status(self, repo, status, user, comment, revision=None,
115 pull_request=None, dont_allow_on_closed_pull_request=False):
115 pull_request=None, dont_allow_on_closed_pull_request=False):
116 """
116 """
117 Creates new status for changeset or updates the old ones bumping their
117 Creates new status for changeset or updates the old ones bumping their
118 version, leaving the current status at
118 version, leaving the current status at
119
119
120 :param repo:
120 :param repo:
121 :type repo:
121 :type repo:
122 :param revision:
122 :param revision:
123 :type revision:
123 :type revision:
124 :param status:
124 :param status:
125 :type status:
125 :type status:
126 :param user:
126 :param user:
127 :type user:
127 :type user:
128 :param comment:
128 :param comment:
129 :type comment:
129 :type comment:
130 :param dont_allow_on_closed_pull_request: don't allow a status change
130 :param dont_allow_on_closed_pull_request: don't allow a status change
131 if last status was for pull request and it's closed. We shouldn't
131 if last status was for pull request and it's closed. We shouldn't
132 mess around this manually
132 mess around this manually
133 """
133 """
134 repo = self._get_repo(repo)
134 repo = self._get_repo(repo)
135
135
136 q = ChangesetStatus.query()
136 q = ChangesetStatus.query()
137
137
138 if revision:
138 if revision:
139 q = q.filter(ChangesetStatus.repo == repo)
139 q = q.filter(ChangesetStatus.repo == repo)
140 q = q.filter(ChangesetStatus.revision == revision)
140 q = q.filter(ChangesetStatus.revision == revision)
141 elif pull_request:
141 elif pull_request:
142 pull_request = self.__get_pull_request(pull_request)
142 pull_request = self.__get_pull_request(pull_request)
143 q = q.filter(ChangesetStatus.repo == pull_request.org_repo)
143 q = q.filter(ChangesetStatus.repo == pull_request.org_repo)
144 q = q.filter(ChangesetStatus.pull_request == pull_request)
144 q = q.filter(ChangesetStatus.pull_request == pull_request)
145 cur_statuses = q.all()
145 cur_statuses = q.all()
146
146
147 #if statuses exists and last is associated with a closed pull request
147 #if statuses exists and last is associated with a closed pull request
148 # we need to check if we can allow this status change
148 # we need to check if we can allow this status change
149 if (dont_allow_on_closed_pull_request and cur_statuses
149 if (dont_allow_on_closed_pull_request and cur_statuses
150 and cur_statuses[0].pull_request.status == PullRequest.STATUS_CLOSED):
150 and getattr(cur_statuses[0].pull_request, 'status', '')
151 == PullRequest.STATUS_CLOSED):
151 raise StatusChangeOnClosedPullRequestError(
152 raise StatusChangeOnClosedPullRequestError(
152 'Changing status on closed pull request is not allowed'
153 'Changing status on closed pull request is not allowed'
153 )
154 )
154
155
155 if cur_statuses:
156 if cur_statuses:
156 for st in cur_statuses:
157 for st in cur_statuses:
157 st.version += 1
158 st.version += 1
158 self.sa.add(st)
159 self.sa.add(st)
159
160
160 def _create_status(user, repo, status, comment, revision, pull_request):
161 def _create_status(user, repo, status, comment, revision, pull_request):
161 new_status = ChangesetStatus()
162 new_status = ChangesetStatus()
162 new_status.author = self._get_user(user)
163 new_status.author = self._get_user(user)
163 new_status.repo = self._get_repo(repo)
164 new_status.repo = self._get_repo(repo)
164 new_status.status = status
165 new_status.status = status
165 new_status.comment = comment
166 new_status.comment = comment
166 new_status.revision = revision
167 new_status.revision = revision
167 new_status.pull_request = pull_request
168 new_status.pull_request = pull_request
168 return new_status
169 return new_status
169
170
170 if revision:
171 if revision:
171 new_status = _create_status(user=user, repo=repo, status=status,
172 new_status = _create_status(user=user, repo=repo, status=status,
172 comment=comment, revision=revision,
173 comment=comment, revision=revision,
173 pull_request=None)
174 pull_request=None)
174 self.sa.add(new_status)
175 self.sa.add(new_status)
175 return new_status
176 return new_status
176 elif pull_request:
177 elif pull_request:
177 #pull request can have more than one revision associated to it
178 #pull request can have more than one revision associated to it
178 #we need to create new version for each one
179 #we need to create new version for each one
179 new_statuses = []
180 new_statuses = []
180 repo = pull_request.org_repo
181 repo = pull_request.org_repo
181 for rev in pull_request.revisions:
182 for rev in pull_request.revisions:
182 new_status = _create_status(user=user, repo=repo,
183 new_status = _create_status(user=user, repo=repo,
183 status=status, comment=comment,
184 status=status, comment=comment,
184 revision=rev,
185 revision=rev,
185 pull_request=pull_request)
186 pull_request=pull_request)
186 new_statuses.append(new_status)
187 new_statuses.append(new_status)
187 self.sa.add(new_status)
188 self.sa.add(new_status)
188 return new_statuses
189 return new_statuses
General Comments 0
You need to be logged in to leave comments. Login now