[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/releeph/conduit/work/ -> ReleephWorkNextRequestConduitAPIMethod.php (source)

   1  <?php
   2  
   3  final class ReleephWorkNextRequestConduitAPIMethod
   4    extends ReleephConduitAPIMethod {
   5  
   6    private $project;
   7    private $branch;
   8  
   9    public function getAPIMethodName() {
  10      return 'releephwork.nextrequest';
  11    }
  12  
  13    public function getMethodStatus() {
  14      return self::METHOD_STATUS_UNSTABLE;
  15    }
  16  
  17    public function getMethodDescription() {
  18      return
  19        'Return info required to cut a branch, '.
  20        'and pick and revert ReleephRequests';
  21    }
  22  
  23    public function defineParamTypes() {
  24      return array(
  25        'branchPHID'  => 'required phid',
  26        'seen'        => 'required map<string, bool>',
  27      );
  28    }
  29  
  30    public function defineReturnType() {
  31      return '';
  32    }
  33  
  34    public function defineErrorTypes() {
  35      return array(
  36        'ERR-NOT-PUSHER' =>
  37          'You are not listed as a pusher for thie Releeph project!',
  38      );
  39    }
  40  
  41    protected function execute(ConduitAPIRequest $request) {
  42      $viewer = $request->getUser();
  43      $seen = $request->getValue('seen');
  44  
  45      $branch = id(new ReleephBranchQuery())
  46        ->setViewer($viewer)
  47        ->withPHIDs(array($request->getValue('branchPHID')))
  48        ->executeOne();
  49  
  50      $project = $branch->getProduct();
  51  
  52      $needs_pick = array();
  53      $needs_revert = array();
  54  
  55      // Load every request ever made for this branch...?!!!
  56      $releeph_requests = id(new ReleephRequestQuery())
  57        ->setViewer($viewer)
  58        ->withBranchIDs(array($branch->getID()))
  59        ->execute();
  60  
  61      foreach ($releeph_requests as $candidate) {
  62        $phid = $candidate->getPHID();
  63        if (idx($seen, $phid)) {
  64          continue;
  65        }
  66  
  67        $should = $candidate->shouldBeInBranch();
  68        $in = $candidate->getInBranch();
  69        if ($should && !$in) {
  70          $needs_pick[] = $candidate;
  71        }
  72        if (!$should && $in) {
  73          $needs_revert[] = $candidate;
  74        }
  75      }
  76  
  77      /**
  78       * Sort both needs_pick and needs_revert in ascending commit order, as
  79       * discovered by Phabricator (using the `id` column to perform that
  80       * ordering).
  81       *
  82       * This is easy for $needs_pick as the ordinal is stored. It is hard for
  83       * reverts, as we have to look that information up.
  84       */
  85      $needs_pick = $this->sortPicks($needs_pick);
  86      $needs_revert = $this->sortReverts($needs_revert);
  87  
  88      /**
  89       * Do reverts first in reverse order, then the picks in original-commit
  90       * order.
  91       *
  92       * This seems like the correct thing to do, but there may be a better
  93       * algorithm for the releephwork.nextrequest Conduit call that orders
  94       * things better.
  95       *
  96       * We could also button-mash our way through everything that failed (at the
  97       * end of the run) to try failed things again.
  98       */
  99      $releeph_request = null;
 100      $action = null;
 101      if ($needs_revert) {
 102        $releeph_request = last($needs_revert);
 103        $action = 'revert';
 104        $commit_id = $releeph_request->getCommitIdentifier();
 105        $commit_phid = $releeph_request->getCommitPHID();
 106      } else if ($needs_pick) {
 107        $releeph_request = head($needs_pick);
 108        $action = 'pick';
 109        $commit = $releeph_request->loadPhabricatorRepositoryCommit();
 110        $commit_id = $commit->getCommitIdentifier();
 111        $commit_phid = $commit->getPHID();
 112      } else {
 113        // Return early if there's nothing to do!
 114        return array();
 115      }
 116  
 117      // Build the response
 118      $phids = array();
 119      $phids[] = $commit_phid;
 120  
 121      $diff_phid = null;
 122      $diff_rev_id = null;
 123  
 124      $requested_object = $releeph_request->getRequestedObject();
 125      if ($requested_object instanceof DifferentialRevision) {
 126        $diff_rev = $requested_object;
 127      } else {
 128        $diff_rev = null;
 129      }
 130  
 131      if ($diff_rev) {
 132        $diff_phid = $diff_rev->getPHID();
 133        $phids[] = $diff_phid;
 134        $diff_rev_id = $diff_rev->getID();
 135      }
 136  
 137      $phids[] = $releeph_request->getPHID();
 138      $handles = id(new PhabricatorHandleQuery())
 139        ->setViewer($request->getUser())
 140        ->withPHIDs($phids)
 141        ->execute();
 142  
 143      $diff_name = null;
 144      if ($diff_rev) {
 145        $diff_name = $handles[$diff_phid]->getName();
 146      }
 147  
 148      $new_author_phid = null;
 149      if ($diff_rev) {
 150        $new_author_phid = $diff_rev->getAuthorPHID();
 151      } else {
 152        $pr_commit = $releeph_request->loadPhabricatorRepositoryCommit();
 153        if ($pr_commit) {
 154          $new_author_phid = $pr_commit->getAuthorPHID();
 155        }
 156      }
 157  
 158      return array(
 159        'requestID'         => $releeph_request->getID(),
 160        'requestPHID'       => $releeph_request->getPHID(),
 161        'requestName'       => $handles[$releeph_request->getPHID()]->getName(),
 162        'requestorPHID'     => $releeph_request->getRequestUserPHID(),
 163        'action'            => $action,
 164        'diffRevID'         => $diff_rev_id,
 165        'diffName'          => $diff_name,
 166        'commitIdentifier'  => $commit_id,
 167        'commitPHID'        => $commit_phid,
 168        'commitName'        => $handles[$commit_phid]->getName(),
 169        'needsRevert'       => mpull($needs_revert, 'getID'),
 170        'needsPick'         => mpull($needs_pick, 'getID'),
 171        'newAuthorPHID'     => $new_author_phid,
 172      );
 173    }
 174  
 175    private function sortPicks(array $releeph_requests) {
 176      $surrogate = array();
 177      foreach ($releeph_requests as $rq) {
 178        // TODO: it's likely that relying on the `id` column to provide
 179        // trunk-commit-order is thoroughly broken.
 180        $ordinal = (int) $rq->loadPhabricatorRepositoryCommit()->getID();
 181        $surrogate[$ordinal] = $rq;
 182      }
 183      ksort($surrogate);
 184      return $surrogate;
 185    }
 186  
 187    /**
 188     * Sort an array of ReleephRequests, that have been picked into a branch, in
 189     * the order in which they were picked to the branch.
 190     */
 191    private function sortReverts(array $releeph_requests) {
 192      if (!$releeph_requests) {
 193        return array();
 194      }
 195  
 196      // ReleephRequests, keyed by <branch-commit-id>
 197      $releeph_requests = mpull($releeph_requests, null, 'getCommitIdentifier');
 198  
 199      $commits = id(new PhabricatorRepositoryCommit())
 200        ->loadAllWhere(
 201          'commitIdentifier IN (%Ls)',
 202          mpull($releeph_requests, 'getCommitIdentifier'));
 203  
 204      // A map of <branch-commit-id> => <branch-commit-ordinal>
 205      $surrogate = mpull($commits, 'getID', 'getCommitIdentifier');
 206  
 207      $unparsed = array();
 208      $result = array();
 209  
 210      foreach ($releeph_requests as $commit_id => $releeph_request) {
 211        $ordinal = idx($surrogate, $commit_id);
 212        if ($ordinal) {
 213          $result[$ordinal] = $releeph_request;
 214        } else {
 215          $unparsed[] = $releeph_request;
 216        }
 217      }
 218  
 219      // Sort $result in ascending order
 220      ksort($result);
 221  
 222      // Unparsed commits we'll just have to guess, based on time
 223      $unparsed = msort($unparsed, 'getDateModified');
 224  
 225      return array_merge($result, $unparsed);
 226    }
 227  
 228  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1