@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Don't consider accepting on behalf of valid-but-accepted reviewers to be a validation error

Summary:
Fixes T12757. Here's a simple repro for this:

- Add a package you own as a reviewer to a revision you're reviewing.
- Open two windows, select "Accept", don't submit the form.
- Submit the form in window A.
- Submit the fomr in window B.

Previously, window B would show an error, because we considered accepting on behalf of the package invalid, as the package had already accepted.

Instead, let repeat-accepts through without complaint.

Some product stuff:

- We could roadblock users with a more narrow validation error message here instead, like "Package X has already been accepted.", but I think this would be more annoying than helpful.
- If your accept has no effect (i.e., everything you're accepting for has already accepted) we currently just let it through. I think this is fine -- and a bit tricky to tailor -- but the ideal/consistent beavior is to do a "no effect" warning like "All the reviewers you're accepting for have already accepted.". This is sufficiently finnicky/rare (and probably not terribly useful/desiable in this specific case)that I'm just punting.

Test Plan: Did the flow above, got an "Accept" instead of a validation error.

Reviewers: chad, lvital

Reviewed By: chad, lvital

Subscribers: lvital

Maniphest Tasks: T12757

Differential Revision: https://secure.phabricator.com/D18019

+25 -6
+15 -6
src/applications/differential/xaction/DifferentialRevisionAcceptTransaction.php
··· 50 50 51 51 protected function getActionOptions( 52 52 PhabricatorUser $viewer, 53 - DifferentialRevision $revision) { 53 + DifferentialRevision $revision, 54 + $include_accepted = false) { 54 55 55 56 $reviewers = $revision->getReviewers(); 56 57 ··· 98 99 } 99 100 } 100 101 101 - if ($reviewer->isAccepted($diff_phid)) { 102 - // If a reviewer is already in a full "accepted" state, don't 103 - // include that reviewer as an option. 104 - continue; 102 + if (!$include_accepted) { 103 + if ($reviewer->isAccepted($diff_phid)) { 104 + // If a reviewer is already in a full "accepted" state, don't 105 + // include that reviewer as an option unless we're listing all 106 + // reviwers, including reviewers who have already accepted. 107 + continue; 108 + } 105 109 } 106 110 107 111 $reviewer_phids[$reviewer_phid] = $reviewer_phid; ··· 185 189 'least one reviewer.')); 186 190 } 187 191 188 - list($options) = $this->getActionOptions($actor, $object); 192 + // NOTE: We're including reviewers who have already been accepted in this 193 + // check. Legitimate users may race one another to accept on behalf of 194 + // packages. If we get a form submission which includes a reviewer which 195 + // someone has already accepted, that's fine. See T12757. 196 + 197 + list($options) = $this->getActionOptions($actor, $object, true); 189 198 foreach ($value as $phid) { 190 199 if (!isset($options[$phid])) { 191 200 throw new Exception(
+10
src/applications/differential/xaction/DifferentialRevisionReviewTransaction.php
··· 17 17 $viewer = $this->getActor(); 18 18 list($options, $default) = $this->getActionOptions($viewer, $object); 19 19 20 + // Remove reviewers which aren't actionable. In the case of "Accept", we 21 + // may allow the transaction to proceed with some reviewers who have 22 + // already accepted, to avoid race conditions where two reviewers fill 23 + // out the form at the same time and accept on behalf of the same package. 24 + // It's okay for these reviewers to survive validation, but they should 25 + // not survive beyond this point. 26 + $value = array_fuse($value); 27 + $value = array_intersect($value, array_keys($options)); 28 + $value = array_values($value); 29 + 20 30 sort($default); 21 31 sort($value); 22 32