[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/diffusion/query/lowlevel/ -> DiffusionLowLevelCommitFieldsQuery.php (source)

   1  <?php
   2  
   3  final class DiffusionLowLevelCommitFieldsQuery
   4    extends DiffusionLowLevelQuery {
   5  
   6    private $ref;
   7    private $revisionMatchData = array(
   8      'usedURI' => null,
   9      'foundURI' => null,
  10      'validDomain' => null,
  11      'matchHashType' => null,
  12      'matchHashValue' => null,
  13    );
  14  
  15    public function withCommitRef(DiffusionCommitRef $ref) {
  16      $this->ref = $ref;
  17      return $this;
  18    }
  19  
  20    public function getRevisionMatchData() {
  21      return $this->revisionMatchData;
  22    }
  23  
  24    private function setRevisionMatchData($key, $value) {
  25      $this->revisionMatchData[$key] = $value;
  26      return $this;
  27    }
  28  
  29    public function executeQuery() {
  30      $ref = $this->ref;
  31      $message = $ref->getMessage();
  32      $hashes = $ref->getHashes();
  33  
  34      $params = array(
  35        'corpus' => $message,
  36        'partial' => true,
  37      );
  38  
  39      $result = id(new ConduitCall('differential.parsecommitmessage', $params))
  40        ->setUser(PhabricatorUser::getOmnipotentUser())
  41        ->execute();
  42      $fields = $result['fields'];
  43  
  44      $revision_id = idx($fields, 'revisionID');
  45      if ($revision_id) {
  46        $this->setRevisionMatchData('usedURI', true);
  47      } else {
  48        $this->setRevisionMatchData('usedURI', false);
  49      }
  50      $revision_id_info = $result['revisionIDFieldInfo'];
  51      $this->setRevisionMatchData('foundURI', $revision_id_info['value']);
  52      $this->setRevisionMatchData(
  53        'validDomain',
  54        $revision_id_info['validDomain']);
  55  
  56      // If there is no "Differential Revision:" field in the message, try to
  57      // identify the revision by doing a hash lookup.
  58  
  59      if (!$revision_id && $hashes) {
  60        $hash_list = array();
  61        foreach ($hashes as $hash) {
  62          $hash_list[] = array($hash->getHashType(), $hash->getHashValue());
  63        }
  64        $revisions = id(new DifferentialRevisionQuery())
  65          ->setViewer(PhabricatorUser::getOmnipotentUser())
  66          ->needHashes(true)
  67          ->withCommitHashes($hash_list)
  68          ->execute();
  69  
  70        if (!empty($revisions)) {
  71          $revision = $this->pickBestRevision($revisions);
  72          $fields['revisionID'] = $revision->getID();
  73          $revision_hashes = $revision->getHashes();
  74          $revision_hashes = DiffusionCommitHash::convertArrayToObjects(
  75            $revision_hashes);
  76          $revision_hashes = mpull($revision_hashes, 'getHashType');
  77          // sort the hashes in the order the mighty
  78          // @{class:ArcanstDifferentialRevisionHash} does; probably unnecessary
  79          // but should future proof things nicely.
  80          $revision_hashes = array_select_keys(
  81            $revision_hashes,
  82            ArcanistDifferentialRevisionHash::getTypes());
  83          foreach ($hashes as $hash) {
  84            $revision_hash = idx($revision_hashes, $hash->getHashType());
  85            if (!$revision_hash) {
  86              continue;
  87            }
  88            if ($revision_hash->getHashValue() == $hash->getHashValue()) {
  89              $this->setRevisionMatchData(
  90                'matchHashType',
  91                $hash->getHashType());
  92              $this->setRevisionMatchData(
  93                'matchHashValue',
  94                $hash->getHashValue());
  95              break;
  96            }
  97          }
  98        }
  99      }
 100  
 101      return $fields;
 102    }
 103  
 104  
 105    /**
 106     * When querying for revisions by hash, more than one revision may be found.
 107     * This function identifies the "best" revision from such a set. Typically,
 108     * there is only one revision found. Otherwise, we try to pick an accepted
 109     * revision first, followed by an open revision, and otherwise we go with a
 110     * closed or abandoned revision as a last resort.
 111     */
 112    private function pickBestRevision(array $revisions) {
 113      assert_instances_of($revisions, 'DifferentialRevision');
 114  
 115      // If we have more than one revision of a given status, choose the most
 116      // recently updated one.
 117      $revisions = msort($revisions, 'getDateModified');
 118      $revisions = array_reverse($revisions);
 119  
 120      // Try to find an accepted revision first.
 121      $status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED;
 122      foreach ($revisions as $revision) {
 123        if ($revision->getStatus() == $status_accepted) {
 124          return $revision;
 125        }
 126      }
 127  
 128      // Try to find an open revision.
 129      foreach ($revisions as $revision) {
 130        if (!$revision->isClosed()) {
 131          return $revision;
 132        }
 133      }
 134  
 135      // Settle for whatever's left.
 136      return head($revisions);
 137    }
 138  
 139  }


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