diff --git a/kallithea/controllers/pullrequests.py b/kallithea/controllers/pullrequests.py --- a/kallithea/controllers/pullrequests.py +++ b/kallithea/controllers/pullrequests.py @@ -483,25 +483,6 @@ class PullrequestsController(BaseRepoCon c.allowed_to_change_status = self._get_is_allowed_change_status(c.pull_request) cc_model = ChangesetCommentsModel() cs_model = ChangesetStatusModel() - _cs_statuses = cs_model.get_statuses(c.pull_request.org_repo, - pull_request=c.pull_request, - with_revisions=True) - - cs_statuses = defaultdict(list) - for st in _cs_statuses: - cs_statuses[st.author.username] += [st] - - c.pull_request_reviewers = [] - c.pull_request_pending_reviewers = [] - for o in c.pull_request.reviewers: - st = cs_statuses.get(o.user.username, None) - if st: - sorter = lambda k: k.version - st = [(x, list(y)[0]) - for x, y in (groupby(sorted(st, key=sorter), sorter))] - else: - c.pull_request_pending_reviewers.append(o.user) - c.pull_request_reviewers.append([o.user, st]) # pull_requests repo_name we opened it against # ie. other_repo must match @@ -526,9 +507,10 @@ class PullrequestsController(BaseRepoCon pull_request=pull_request_id) # (badly named) pull-request status calculation based on reviewer votes - c.current_changeset_status = cs_model.calculate_status( - c.pull_request_reviewers, - ) + (c.pull_request_reviewers, + c.pull_request_pending_reviewers, + c.current_voting_result, + ) = cs_model.calculate_pull_request_result(c.pull_request) c.changeset_statuses = ChangesetStatus.STATUSES c.as_form = False diff --git a/kallithea/model/changeset_status.py b/kallithea/model/changeset_status.py --- a/kallithea/model/changeset_status.py +++ b/kallithea/model/changeset_status.py @@ -65,26 +65,39 @@ class ChangesetStatusModel(BaseModel): q = q.order_by(ChangesetStatus.version.asc()) return q - def calculate_status(self, statuses_by_reviewers): + def calculate_pull_request_result(self, pull_request): """ - approved if consensus - (old description: leading one wins, if number of occurrences are equal than weaker wins) - - :param statuses_by_reviewers: + Policy: approve if consensus. Only approve and reject counts as valid votes. """ - votes = defaultdict(int) - reviewers_number = len(statuses_by_reviewers) - for user, statuses in statuses_by_reviewers: - if statuses: - ver, latest = statuses[0] - votes[latest.status] += 1 - else: - votes[ChangesetStatus.DEFAULT] += 1 - if votes.get(ChangesetStatus.STATUS_APPROVED) == reviewers_number: - return ChangesetStatus.STATUS_APPROVED - else: - return ChangesetStatus.STATUS_UNDER_REVIEW + # collect latest votes from all voters + cs_statuses = dict() + for st in reversed(self.get_statuses(pull_request.org_repo, + pull_request=pull_request, + with_revisions=True)): + cs_statuses[st.author.username] = st + # collect votes from official reviewers + pull_request_reviewers = [] + pull_request_pending_reviewers = [] + approved_votes = 0 + for r in pull_request.reviewers: + st = cs_statuses.get(r.user.username) + if st and st.status == ChangesetStatus.STATUS_APPROVED: + approved_votes += 1 + if not st or st.status in (ChangesetStatus.STATUS_NOT_REVIEWED, + ChangesetStatus.STATUS_UNDER_REVIEW): + st = None + pull_request_pending_reviewers.append(r.user) + pull_request_reviewers.append((r.user, st)) + + # calculate result + result = ChangesetStatus.STATUS_UNDER_REVIEW + if approved_votes and approved_votes == len(pull_request.reviewers): + result = ChangesetStatus.STATUS_APPROVED + + return (pull_request_reviewers, + pull_request_pending_reviewers, + result) def get_statuses(self, repo, revision=None, pull_request=None, with_revisions=False): @@ -156,6 +169,7 @@ class ChangesetStatusModel(BaseModel): def _create_status(user, repo, status, comment, revision, pull_request): new_status = ChangesetStatus() + new_status.version = 0 # default new_status.author = self._get_user(user) new_status.repo = self._get_repo(repo) new_status.status = status diff --git a/kallithea/templates/pullrequests/pullrequest_show.html b/kallithea/templates/pullrequests/pullrequest_show.html --- a/kallithea/templates/pullrequests/pullrequest_show.html +++ b/kallithea/templates/pullrequests/pullrequest_show.html @@ -78,18 +78,18 @@ ${self.repo_context_bar('showpullrequest
- +
- %if c.current_changeset_status: + %if c.current_voting_result:
-
+
%if c.pull_request.is_closed(): ${_('Closed')}, %endif - ${h.changeset_status_lbl(c.current_changeset_status)} + ${h.changeset_status_lbl(c.current_voting_result)}
%endif @@ -103,8 +103,10 @@ ${self.repo_context_bar('showpullrequest
% if len(c.pull_request_pending_reviewers) > 0:
${ungettext('%d reviewer', '%d reviewers',len(c.pull_request_pending_reviewers)) % len(c.pull_request_pending_reviewers)}
+ % elif len(c.pull_request_reviewers) > 0: +
${_('Pull request was reviewed by all reviewers')}
%else: -
${_('Pull request was reviewed by all reviewers')}
+
${_('There are no reviewers')}
%endif
@@ -182,8 +184,8 @@ ${self.repo_context_bar('showpullrequest %for member,status in c.pull_request_reviewers:
  • -
    - +
    +
    gravatar
    ${member.full_name} (${_('owner') if c.pull_request.user_id == member.user_id else _('reviewer')})
    @@ -293,7 +295,7 @@ ${self.repo_context_bar('showpullrequest ## main comment form and it status ${comment.comments(h.url('pullrequest_comment', repo_name=c.repo_name, pull_request_id=c.pull_request.pull_request_id), - c.current_changeset_status, + c.current_voting_result, is_pr=True, change_status=c.allowed_to_change_status)} %endif