mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-20 05:42:40 +01:00
Move commit message/metadata field query to a separate class
Summary: Ref T4195. I need to query commit metadata to figure out which revision a commit is associated with. Move this out of the MessageParser so the code can be called from the HookEngine. Test Plan: Used `reparse.php` to reparse a variety of SVN, Mercurial and Git commits. Used `var_dump()` to verify sensible fields were returned. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T4195 Differential Revision: https://secure.phabricator.com/D7805
This commit is contained in:
parent
23332241b2
commit
d7c4edab28
3 changed files with 94 additions and 89 deletions
|
@ -508,6 +508,7 @@ phutil_register_library_map(array(
|
||||||
'DiffusionLintController' => 'applications/diffusion/controller/DiffusionLintController.php',
|
'DiffusionLintController' => 'applications/diffusion/controller/DiffusionLintController.php',
|
||||||
'DiffusionLintDetailsController' => 'applications/diffusion/controller/DiffusionLintDetailsController.php',
|
'DiffusionLintDetailsController' => 'applications/diffusion/controller/DiffusionLintDetailsController.php',
|
||||||
'DiffusionLintSaveRunner' => 'applications/diffusion/DiffusionLintSaveRunner.php',
|
'DiffusionLintSaveRunner' => 'applications/diffusion/DiffusionLintSaveRunner.php',
|
||||||
|
'DiffusionLowLevelCommitFieldsQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelCommitFieldsQuery.php',
|
||||||
'DiffusionLowLevelCommitQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelCommitQuery.php',
|
'DiffusionLowLevelCommitQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelCommitQuery.php',
|
||||||
'DiffusionLowLevelGitRefQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelGitRefQuery.php',
|
'DiffusionLowLevelGitRefQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelGitRefQuery.php',
|
||||||
'DiffusionLowLevelMercurialBranchesQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelMercurialBranchesQuery.php',
|
'DiffusionLowLevelMercurialBranchesQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelMercurialBranchesQuery.php',
|
||||||
|
@ -2894,6 +2895,7 @@ phutil_register_library_map(array(
|
||||||
'DiffusionLastModifiedController' => 'DiffusionController',
|
'DiffusionLastModifiedController' => 'DiffusionController',
|
||||||
'DiffusionLintController' => 'DiffusionController',
|
'DiffusionLintController' => 'DiffusionController',
|
||||||
'DiffusionLintDetailsController' => 'DiffusionController',
|
'DiffusionLintDetailsController' => 'DiffusionController',
|
||||||
|
'DiffusionLowLevelCommitFieldsQuery' => 'DiffusionLowLevelQuery',
|
||||||
'DiffusionLowLevelCommitQuery' => 'DiffusionLowLevelQuery',
|
'DiffusionLowLevelCommitQuery' => 'DiffusionLowLevelQuery',
|
||||||
'DiffusionLowLevelGitRefQuery' => 'DiffusionLowLevelQuery',
|
'DiffusionLowLevelGitRefQuery' => 'DiffusionLowLevelQuery',
|
||||||
'DiffusionLowLevelMercurialBranchesQuery' => 'DiffusionLowLevelQuery',
|
'DiffusionLowLevelMercurialBranchesQuery' => 'DiffusionLowLevelQuery',
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DiffusionLowLevelCommitFieldsQuery
|
||||||
|
extends DiffusionLowLevelQuery {
|
||||||
|
|
||||||
|
private $ref;
|
||||||
|
|
||||||
|
public function withCommitRef(DiffusionCommitRef $ref) {
|
||||||
|
$this->ref = $ref;
|
||||||
|
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'];
|
||||||
|
|
||||||
|
// If there is no "Differential Revision:" field in the message, try to
|
||||||
|
// identify the revision by doing a hash lookup.
|
||||||
|
|
||||||
|
$revision_id = idx($fields, 'revisionID');
|
||||||
|
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())
|
||||||
|
->withCommitHashes($hash_list)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
if (!empty($revisions)) {
|
||||||
|
$revision = $this->pickBestRevision($revisions);
|
||||||
|
$fields['revisionID'] = $revision->getID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -43,16 +43,11 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker
|
||||||
$author_phid);
|
$author_phid);
|
||||||
}
|
}
|
||||||
|
|
||||||
$call = new ConduitCall(
|
$field_values = id(new DiffusionLowLevelCommitFieldsQuery())
|
||||||
'differential.parsecommitmessage',
|
->setRepository($repository)
|
||||||
array(
|
->withCommitRef($ref)
|
||||||
'corpus' => $message,
|
->execute();
|
||||||
'partial' => true,
|
$revision_id = idx($field_values, 'revisionID');
|
||||||
));
|
|
||||||
$call->setUser(PhabricatorUser::getOmnipotentUser());
|
|
||||||
$result = $call->execute();
|
|
||||||
|
|
||||||
$field_values = $result['fields'];
|
|
||||||
|
|
||||||
if (!empty($field_values['reviewedByPHIDs'])) {
|
if (!empty($field_values['reviewedByPHIDs'])) {
|
||||||
$data->setCommitDetail(
|
$data->setCommitDetail(
|
||||||
|
@ -60,26 +55,7 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker
|
||||||
reset($field_values['reviewedByPHIDs']));
|
reset($field_values['reviewedByPHIDs']));
|
||||||
}
|
}
|
||||||
|
|
||||||
$revision_id = idx($field_values, 'revisionID');
|
$data->setCommitDetail('differential.revisionID', $revision_id);
|
||||||
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())
|
|
||||||
->withCommitHashes($hash_list)
|
|
||||||
->execute();
|
|
||||||
|
|
||||||
if (!empty($revisions)) {
|
|
||||||
$revision = $this->identifyBestRevision($revisions);
|
|
||||||
$revision_id = $revision->getID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->setCommitDetail(
|
|
||||||
'differential.revisionID',
|
|
||||||
$revision_id);
|
|
||||||
|
|
||||||
if ($author_phid != $commit->getAuthorPHID()) {
|
if ($author_phid != $commit->getAuthorPHID()) {
|
||||||
$commit->setAuthorPHID($author_phid);
|
$commit->setAuthorPHID($author_phid);
|
||||||
|
@ -386,65 +362,6 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 identifyBestRevision(array $revisions) {
|
|
||||||
assert_instances_of($revisions, 'DifferentialRevision');
|
|
||||||
// get the simplest, common case out of the way
|
|
||||||
if (count($revisions) == 1) {
|
|
||||||
return reset($revisions);
|
|
||||||
}
|
|
||||||
|
|
||||||
$first_choice = array();
|
|
||||||
$second_choice = array();
|
|
||||||
$third_choice = array();
|
|
||||||
foreach ($revisions as $revision) {
|
|
||||||
switch ($revision->getStatus()) {
|
|
||||||
// "Accepted" revisions -- ostensibly what we're looking for!
|
|
||||||
case ArcanistDifferentialRevisionStatus::ACCEPTED:
|
|
||||||
$first_choice[] = $revision;
|
|
||||||
break;
|
|
||||||
// "Open" revisions
|
|
||||||
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
|
|
||||||
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
|
|
||||||
$second_choice[] = $revision;
|
|
||||||
break;
|
|
||||||
// default is a wtf? here
|
|
||||||
default:
|
|
||||||
case ArcanistDifferentialRevisionStatus::ABANDONED:
|
|
||||||
case ArcanistDifferentialRevisionStatus::CLOSED:
|
|
||||||
$third_choice[] = $revision;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// go down the ladder like a bro at last call
|
|
||||||
if (!empty($first_choice)) {
|
|
||||||
return $this->identifyMostRecentRevision($first_choice);
|
|
||||||
}
|
|
||||||
if (!empty($second_choice)) {
|
|
||||||
return $this->identifyMostRecentRevision($second_choice);
|
|
||||||
}
|
|
||||||
if (!empty($third_choice)) {
|
|
||||||
return $this->identifyMostRecentRevision($third_choice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a set of revisions, returns the revision with the latest
|
|
||||||
* updated time. This is ostensibly the most recent revision.
|
|
||||||
*/
|
|
||||||
private function identifyMostRecentRevision(array $revisions) {
|
|
||||||
assert_instances_of($revisions, 'DifferentialRevision');
|
|
||||||
$revisions = msort($revisions, 'getDateModified');
|
|
||||||
return end($revisions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function resolveUserPHID(
|
private function resolveUserPHID(
|
||||||
PhabricatorRepositoryCommit $commit,
|
PhabricatorRepositoryCommit $commit,
|
||||||
$user_name) {
|
$user_name) {
|
||||||
|
|
Loading…
Reference in a new issue