@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Detect tasks referenced in commit messages and either link or update the mentioned tasks. Refs T945

Summary: This takes the place of D2721 which I am going to abandon.

Test Plan:
* Make a commit with "Closes T###" in the summary field. See that the mentioned task gets closed.
* Make a commit with "refs T###" in the summary. See that it gets added as a related commit via edges.

Reviewers: 20after4

Reviewed By: epriestley

CC: aran, Korvin, champo

Maniphest Tasks: T945

Differential Revision: https://secure.phabricator.com/D3466

+144 -4
+4 -2
src/__phutil_library_map__.php
··· 254 254 'DifferentialFieldSpecification' => 'applications/differential/field/specification/DifferentialFieldSpecification.php', 255 255 'DifferentialFieldSpecificationIncompleteException' => 'applications/differential/field/exception/DifferentialFieldSpecificationIncompleteException.php', 256 256 'DifferentialFieldValidationException' => 'applications/differential/field/exception/DifferentialFieldValidationException.php', 257 + 'DifferentialFreeformFieldSpecification' => 'applications/differential/field/specification/DifferentialFreeformFieldSpecification.php', 257 258 'DifferentialGitSVNIDFieldSpecification' => 'applications/differential/field/specification/DifferentialGitSVNIDFieldSpecification.php', 258 259 'DifferentialHostFieldSpecification' => 'applications/differential/field/specification/DifferentialHostFieldSpecification.php', 259 260 'DifferentialHunk' => 'applications/differential/storage/DifferentialHunk.php', ··· 1435 1436 'DifferentialFieldParseException' => 'Exception', 1436 1437 'DifferentialFieldSpecificationIncompleteException' => 'Exception', 1437 1438 'DifferentialFieldValidationException' => 'Exception', 1439 + 'DifferentialFreeformFieldSpecification' => 'DifferentialFieldSpecification', 1438 1440 'DifferentialGitSVNIDFieldSpecification' => 'DifferentialFieldSpecification', 1439 1441 'DifferentialHostFieldSpecification' => 'DifferentialFieldSpecification', 1440 1442 'DifferentialHunk' => 'DifferentialDAO', ··· 1477 1479 'DifferentialRevisionUpdateHistoryView' => 'AphrontView', 1478 1480 'DifferentialRevisionViewController' => 'DifferentialController', 1479 1481 'DifferentialSubscribeController' => 'DifferentialController', 1480 - 'DifferentialSummaryFieldSpecification' => 'DifferentialFieldSpecification', 1482 + 'DifferentialSummaryFieldSpecification' => 'DifferentialFreeformFieldSpecification', 1481 1483 'DifferentialTestPlanFieldSpecification' => 'DifferentialFieldSpecification', 1482 - 'DifferentialTitleFieldSpecification' => 'DifferentialFieldSpecification', 1484 + 'DifferentialTitleFieldSpecification' => 'DifferentialFreeformFieldSpecification', 1483 1485 'DifferentialUnitFieldSpecification' => 'DifferentialFieldSpecification', 1484 1486 'DiffusionBranchTableController' => 'DiffusionController', 1485 1487 'DiffusionBranchTableView' => 'DiffusionView',
+138
src/applications/differential/field/specification/DifferentialFreeformFieldSpecification.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2012 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + abstract class DifferentialFreeformFieldSpecification 20 + extends DifferentialFieldSpecification { 21 + 22 + public function didParseCommit( 23 + PhabricatorRepository $repository, 24 + PhabricatorRepositoryCommit $commit, 25 + PhabricatorRepositoryCommitData $data) { 26 + 27 + $user = id(new PhabricatorUser())->loadOneWhere( 28 + 'phid = %s', 29 + $data->getCommitDetail('authorPHID')); 30 + if (!$user) { 31 + return; 32 + } 33 + 34 + $prefixes = array( 35 + 'resolves' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 36 + 'fixes' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 37 + 'wontfix' => ManiphestTaskStatus::STATUS_CLOSED_WONTFIX, 38 + 'wontfixes' => ManiphestTaskStatus::STATUS_CLOSED_WONTFIX, 39 + 'spite' => ManiphestTaskStatus::STATUS_CLOSED_SPITE, 40 + 'spites' => ManiphestTaskStatus::STATUS_CLOSED_SPITE, 41 + 'invalidate' => ManiphestTaskStatus::STATUS_CLOSED_INVALID, 42 + 'invaldiates' => ManiphestTaskStatus::STATUS_CLOSED_INVALID, 43 + 'close' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 44 + 'closes' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 45 + 'ref' => null, 46 + 'refs' => null, 47 + 'references' => null, 48 + 'cf.' => null, 49 + ); 50 + 51 + $suffixes = array( 52 + 'as resolved' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 53 + 'as fixed' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 54 + 'as wontfix' => ManiphestTaskStatus::STATUS_CLOSED_WONTFIX, 55 + 'as spite' => ManiphestTaskStatus::STATUS_CLOSED_SPITE, 56 + 'out of spite' => ManiphestTaskStatus::STATUS_CLOSED_SPITE, 57 + 'as invalid' => ManiphestTaskStatus::STATUS_CLOSED_INVALID, 58 + '' => null, 59 + ); 60 + 61 + $prefix_regex = array(); 62 + foreach ($prefixes as $prefix => $resolution) { 63 + $prefix_regex[] = preg_quote($prefix, '/'); 64 + } 65 + $prefix_regex = implode('|', $prefix_regex); 66 + 67 + $suffix_regex = array(); 68 + foreach ($suffixes as $suffix => $resolution) { 69 + $suffix_regex[] = preg_quote($suffix, '/'); 70 + } 71 + $suffix_regex = implode('|', $suffix_regex); 72 + 73 + $matches = null; 74 + $ok = preg_match_all( 75 + "/({$prefix_regex})\s+T(\d+)\s+({$suffix_regex})/i", 76 + $this->renderValueForCommitMessage($is_edit = false), 77 + $matches, 78 + PREG_SET_ORDER); 79 + 80 + if (!$ok) { 81 + return; 82 + } 83 + 84 + foreach ($matches as $set) { 85 + $prefix = strtolower($set[1]); 86 + $task_id = (int)$set[2]; 87 + $suffix = strtolower($set[3]); 88 + 89 + $status = idx($suffixes, $suffix); 90 + if (!$status) { 91 + $status = idx($prefixes, $prefix); 92 + } 93 + 94 + $tasks = id(new ManiphestTaskQuery()) 95 + ->withTaskIDs(array($task_id)) 96 + ->execute(); 97 + $task = idx($tasks, $task_id); 98 + 99 + if (!$task) { 100 + // Task doesn't exist, or the user can't see it. 101 + continue; 102 + } 103 + 104 + id(new PhabricatorEdgeEditor()) 105 + ->setUser($user) 106 + ->addEdge( 107 + $task->getPHID(), 108 + PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT, 109 + $commit->getPHID()) 110 + ->save(); 111 + 112 + if (!$status) { 113 + // Text like "Ref T123", don't change the task status. 114 + continue; 115 + } 116 + 117 + if ($task->getStatus() != ManiphestTaskStatus::STATUS_OPEN) { 118 + // Task is already closed. 119 + continue; 120 + } 121 + 122 + $commit_name = $repository->formatCommitName( 123 + $commit->getCommitIdentifier()); 124 + 125 + $call = new ConduitCall( 126 + 'maniphest.update', 127 + array( 128 + 'id' => $task->getID(), 129 + 'status' => $status, 130 + 'comments' => "Closed by commit {$commit_name}.", 131 + )); 132 + 133 + $call->setUser($user); 134 + $call->execute(); 135 + } 136 + } 137 + 138 + }
+1 -1
src/applications/differential/field/specification/DifferentialSummaryFieldSpecification.php
··· 17 17 */ 18 18 19 19 final class DifferentialSummaryFieldSpecification 20 - extends DifferentialFieldSpecification { 20 + extends DifferentialFreeformFieldSpecification { 21 21 22 22 private $summary = ''; 23 23
+1 -1
src/applications/differential/field/specification/DifferentialTitleFieldSpecification.php
··· 17 17 */ 18 18 19 19 final class DifferentialTitleFieldSpecification 20 - extends DifferentialFieldSpecification { 20 + extends DifferentialFreeformFieldSpecification { 21 21 22 22 private $title; 23 23 private $error = true;