diff --git a/src/applications/diffusion/data/DiffusionCommitHash.php b/src/applications/diffusion/data/DiffusionCommitHash.php index 8605a99a34..7fbf23a2bf 100644 --- a/src/applications/diffusion/data/DiffusionCommitHash.php +++ b/src/applications/diffusion/data/DiffusionCommitHash.php @@ -1,26 +1,37 @@ hashValue = $hash_value; return $this; } public function getHashValue() { return $this->hashValue; } public function setHashType($hash_type) { $this->hashType = $hash_type; return $this; } public function getHashType() { return $this->hashType; } + public static function convertArrayToObjects(array $hashes) { + $hash_objects = array(); + foreach ($hashes as $hash) { + $type = $hash[0]; + $hash = $hash[1]; + $hash_objects[] = id(new DiffusionCommitHash()) + ->setHashType($type) + ->setHashValue($hash); + } + return $hash_objects; + } } diff --git a/src/applications/diffusion/query/lowlevel/DiffusionLowLevelCommitFieldsQuery.php b/src/applications/diffusion/query/lowlevel/DiffusionLowLevelCommitFieldsQuery.php index 64ad12e096..a288d6a70b 100644 --- a/src/applications/diffusion/query/lowlevel/DiffusionLowLevelCommitFieldsQuery.php +++ b/src/applications/diffusion/query/lowlevel/DiffusionLowLevelCommitFieldsQuery.php @@ -1,134 +1,139 @@ null, 'foundURI' => null, 'validDomain' => null, 'matchHashType' => null, 'matchHashValue' => null, ); public function withCommitRef(DiffusionCommitRef $ref) { $this->ref = $ref; return $this; } public function getRevisionMatchData() { return $this->revisionMatchData; } private function setRevisionMatchData($key, $value) { $this->revisionMatchData[$key] = $value; return $this; } public function executeQuery() { $ref = $this->ref; $message = $ref->getMessage(); $hashes = $ref->getHashes(); $params = array( 'corpus' => $message, 'partial' => true, ); $result = id(new ConduitCall('differential.parsecommitmessage', $params)) ->setUser(PhabricatorUser::getOmnipotentUser()) ->execute(); $fields = $result['fields']; $revision_id = idx($fields, 'revisionID'); if ($revision_id) { $this->setRevisionMatchData('usedURI', true); } else { $this->setRevisionMatchData('usedURI', false); } $revision_id_info = $result['revisionIDFieldInfo']; $this->setRevisionMatchData('foundURI', $revision_id_info['value']); $this->setRevisionMatchData( 'validDomain', $revision_id_info['validDomain']); // If there is no "Differential Revision:" field in the message, try to // identify the revision by doing a hash lookup. if (!$revision_id && $hashes) { $hash_list = array(); foreach ($hashes as $hash) { $hash_list[] = array($hash->getHashType(), $hash->getHashValue()); } $revisions = id(new DifferentialRevisionQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->needHashes(true) ->withCommitHashes($hash_list) ->execute(); if (!empty($revisions)) { $revision = $this->pickBestRevision($revisions); $fields['revisionID'] = $revision->getID(); $revision_hashes = $revision->getHashes(); + $revision_hashes = DiffusionCommitHash::convertArrayToObjects( + $revision_hashes); $revision_hashes = mpull($revision_hashes, 'getHashType'); // sort the hashes in the order the mighty // @{class:ArcanstDifferentialRevisionHash} does; probably unnecessary // but should future proof things nicely. $revision_hashes = array_select_keys( $revision_hashes, ArcanistDifferentialRevisionHash::getTypes()); foreach ($hashes as $hash) { - $revision_hash = $revision_hashes[$hash->getHashType()]; + $revision_hash = idx($revision_hashes, $hash->getHashType()); + if (!$revision_hash) { + continue; + } if ($revision_hash->getHashValue() == $hash->getHashValue()) { $this->setRevisionMatchData( 'matchHashType', $hash->getHashType()); $this->setRevisionMatchData( 'matchHashValue', $hash->getHashValue()); break; } } } } return $fields; } /** * When querying for revisions by hash, more than one revision may be found. * This function identifies the "best" revision from such a set. Typically, * there is only one revision found. Otherwise, we try to pick an accepted * revision first, followed by an open revision, and otherwise we go with a * closed or abandoned revision as a last resort. */ private function pickBestRevision(array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); // If we have more than one revision of a given status, choose the most // recently updated one. $revisions = msort($revisions, 'getDateModified'); $revisions = array_reverse($revisions); // Try to find an accepted revision first. $status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED; foreach ($revisions as $revision) { if ($revision->getStatus() == $status_accepted) { return $revision; } } // Try to find an open revision. foreach ($revisions as $revision) { if (!$revision->isClosed()) { return $revision; } } // Settle for whatever's left. return head($revisions); } }