diff --git a/src/applications/differential/field/specification/DifferentialFieldSpecification.php b/src/applications/differential/field/specification/DifferentialFieldSpecification.php index 77c108a585..8f99c85f96 100644 --- a/src/applications/differential/field/specification/DifferentialFieldSpecification.php +++ b/src/applications/differential/field/specification/DifferentialFieldSpecification.php @@ -578,25 +578,6 @@ abstract class DifferentialFieldSpecification { } - /** - * This method allows you to take action when a commit appears in a tracked - * branch (for example, by closing tasks associated with the commit). - * - * @param PhabricatorRepository The repository the commit appeared in. - * @param PhabricatorRepositoryCommit The commit itself. - * @param PhabricatorRepostioryCommitData Commit data. - * @return void - * - * @task commit - */ - public function didParseCommit( - PhabricatorRepository $repo, - PhabricatorRepositoryCommit $commit, - PhabricatorRepositoryCommitData $data) { - return; - } - - /* -( Loading Additional Data )-------------------------------------------- */ diff --git a/src/applications/differential/field/specification/DifferentialFreeformFieldSpecification.php b/src/applications/differential/field/specification/DifferentialFreeformFieldSpecification.php index 694fbf1b62..ce7d0633ea 100644 --- a/src/applications/differential/field/specification/DifferentialFreeformFieldSpecification.php +++ b/src/applications/differential/field/specification/DifferentialFreeformFieldSpecification.php @@ -3,162 +3,4 @@ abstract class DifferentialFreeformFieldSpecification extends DifferentialFieldSpecification { - private function findMentionedTasks($message) { - $maniphest = 'PhabricatorApplicationManiphest'; - if (!PhabricatorApplication::isClassInstalled($maniphest)) { - return array(); - } - - $prefixes = ManiphestTaskStatus::getStatusPrefixMap(); - $suffixes = ManiphestTaskStatus::getStatusSuffixMap(); - - $matches = id(new ManiphestCustomFieldStatusParser()) - ->parseCorpus($message); - - $task_statuses = array(); - foreach ($matches as $match) { - $prefix = phutil_utf8_strtolower($match['prefix']); - $suffix = phutil_utf8_strtolower($match['suffix']); - - $status = idx($suffixes, $suffix); - if (!$status) { - $status = idx($prefixes, $prefix); - } - - foreach ($match['monograms'] as $task_monogram) { - $task_id = (int)trim($task_monogram, 'tT'); - $task_statuses[$task_id] = $status; - } - } - - return $task_statuses; - } - - private function findDependentRevisions($message) { - $matches = id(new DifferentialCustomFieldDependsOnParser()) - ->parseCorpus($message); - - $dependents = array(); - foreach ($matches as $match) { - foreach ($match['monograms'] as $monogram) { - $id = (int)trim($monogram, 'dD'); - $dependents[$id] = $id; - } - } - - return $dependents; - } - - public static function findRevertedCommits($message) { - $matches = id(new DifferentialCustomFieldRevertsParser()) - ->parseCorpus($message); - - $result = array(); - foreach ($matches as $match) { - foreach ($match['monograms'] as $monogram) { - $result[$monogram] = $monogram; - } - } - - return $result; - } - - private function saveFieldEdges( - DifferentialRevision $revision, - $edge_type, - array $add_phids) { - - $revision_phid = $revision->getPHID(); - - $old_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( - $revision_phid, - $edge_type); - - $add_phids = array_diff($add_phids, $old_phids); - if (!$add_phids) { - return; - } - - $edge_editor = id(new PhabricatorEdgeEditor())->setActor($this->getUser()); - foreach ($add_phids as $phid) { - $edge_editor->addEdge($revision_phid, $edge_type, $phid); - } - // NOTE: Deletes only through the fields. - $edge_editor->save(); - } - - public function didParseCommit( - PhabricatorRepository $repository, - PhabricatorRepositoryCommit $commit, - PhabricatorRepositoryCommitData $data) { - - $message = $this->renderValueForCommitMessage($is_edit = false); - - $user = id(new PhabricatorUser())->loadOneWhere( - 'phid = %s', - $data->getCommitDetail('authorPHID')); - if (!$user) { - // TODO: Maybe after grey users, we should find a way to proceed even - // if we don't know who the author is. - return; - } - - $commit_names = self::findRevertedCommits($message); - if ($commit_names) { - $reverts = id(new DiffusionCommitQuery()) - ->setViewer($user) - ->withIdentifiers($commit_names) - ->withDefaultRepository($repository) - ->execute(); - foreach ($reverts as $revert) { - // TODO: Do interesting things here. - } - } - - $tasks_statuses = $this->findMentionedTasks($message); - if (!$tasks_statuses) { - return; - } - - $tasks = id(new ManiphestTaskQuery()) - ->setViewer($user) - ->withIDs(array_keys($tasks_statuses)) - ->execute(); - - foreach ($tasks as $task_id => $task) { - id(new PhabricatorEdgeEditor()) - ->setActor($user) - ->addEdge( - $task->getPHID(), - PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT, - $commit->getPHID()) - ->save(); - - $status = $tasks_statuses[$task_id]; - if (!$status) { - // Text like "Ref T123", don't change the task status. - continue; - } - - if ($task->getStatus() == $status) { - // Task is already in the specified status, so skip updating it. - continue; - } - - $commit_name = $repository->formatCommitName( - $commit->getCommitIdentifier()); - - $call = new ConduitCall( - 'maniphest.update', - array( - 'id' => $task->getID(), - 'status' => $status, - 'comments' => "Closed by commit {$commit_name}.", - )); - - $call->setUser($user); - $call->execute(); - } - } - } diff --git a/src/applications/releeph/differential/DifferentialReleephRequestFieldSpecification.php b/src/applications/releeph/differential/DifferentialReleephRequestFieldSpecification.php index 982c166a14..1ec037c3ef 100644 --- a/src/applications/releeph/differential/DifferentialReleephRequestFieldSpecification.php +++ b/src/applications/releeph/differential/DifferentialReleephRequestFieldSpecification.php @@ -243,6 +243,8 @@ final class DifferentialReleephRequestFieldSpecification PhabricatorRepositoryCommit $commit, PhabricatorRepositoryCommitData $data) { + // NOTE: This is currently dead code. See T2222. + $releeph_requests = $this->loadReleephRequests(); if (!$releeph_requests) { diff --git a/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php b/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php index fa7bb122e7..33fe94bc5a 100644 --- a/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php +++ b/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php @@ -85,10 +85,6 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker ->needReviewerStatus(true) ->needActiveDiffs(true); - // TODO: Remove this once we swap to new CustomFields. This is only - // required by the old FieldSpecifications, lower on in this worker. - $revision_query->needRelationships(true); - $revision = $revision_query->executeOne(); if ($revision) { @@ -200,21 +196,9 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker } if ($should_autoclose) { - // TODO: When this is moved to CustomFields, remove the additional - // call above in query construction. - $fields = DifferentialFieldSelector::newSelector() - ->getFieldSpecifications(); - foreach ($fields as $key => $field) { - if (!$field->shouldAppearOnCommitMessage()) { - continue; - } - $field->setUser($user); - $value = idx($field_values, $field->getCommitMessageKey()); - $field->setValueFromParsedCommitMessage($value); - if ($revision) { - $field->setRevision($revision); - } - $field->didParseCommit($repository, $commit, $data); + // TODO: This isn't as general as it could be. + if ($user->getPHID()) { + $this->closeTasks($user, $repository, $commit, $message); } } @@ -418,4 +402,109 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker ->execute(); } + private function closeTasks( + PhabricatorUser $actor, + PhabricatorRepository $repository, + PhabricatorRepositoryCommit $commit, + $message) { + + $maniphest = 'PhabricatorApplicationManiphest'; + if (!PhabricatorApplication::isClassInstalled($maniphest)) { + return; + } + + $prefixes = ManiphestTaskStatus::getStatusPrefixMap(); + $suffixes = ManiphestTaskStatus::getStatusSuffixMap(); + + $matches = id(new ManiphestCustomFieldStatusParser()) + ->parseCorpus($message); + + $task_statuses = array(); + foreach ($matches as $match) { + $prefix = phutil_utf8_strtolower($match['prefix']); + $suffix = phutil_utf8_strtolower($match['suffix']); + + $status = idx($suffixes, $suffix); + if (!$status) { + $status = idx($prefixes, $prefix); + } + + foreach ($match['monograms'] as $task_monogram) { + $task_id = (int)trim($task_monogram, 'tT'); + $task_statuses[$task_id] = $status; + } + } + + if (!$task_statuses) { + return; + } + + $tasks = id(new ManiphestTaskQuery()) + ->setViewer($actor) + ->withIDs(array_keys($task_statuses)) + ->execute(); + + foreach ($tasks as $task_id => $task) { + $xactions = array(); + + // TODO: Swap this for a real edge transaction once the weirdness in + // Maniphest edges is sorted out. Currently, Maniphest reacts to an edge + // edit on this edge. + id(new PhabricatorEdgeEditor()) + ->setActor($actor) + ->addEdge( + $task->getPHID(), + PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT, + $commit->getPHID()) + ->save(); + + /* TODO: Do this instead of the above. + + $xactions[] = id(new ManiphestTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue('edge:type', $edge_task_has_commit) + ->setNewValue( + array( + '+' => array( + $commit->getPHID() => $commit->getPHID(), + ), + )); + */ + + $status = $task_statuses[$task_id]; + if ($status) { + if ($task->getStatus() != $status) { + $xactions[] = id(new ManiphestTransaction()) + ->setTransactionType(ManiphestTransaction::TYPE_STATUS) + ->setNewValue($status); + + $commit_name = $repository->formatCommitName( + $commit->getCommitIdentifier()); + + $status_message = pht( + 'Closed by commit %s.', + $commit_name); + + $xactions[] = id(new ManiphestTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) + ->attachComment( + id(new ManiphestTransactionComment()) + ->setContent($status_message)); + } + } + + $content_source = PhabricatorContentSource::newForSource( + PhabricatorContentSource::SOURCE_DAEMON, + array()); + + $editor = id(new ManiphestTransactionEditor()) + ->setActor($actor) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true) + ->setContentSource($content_source); + + $editor->applyTransactions($task, $xactions); + } + } + }