@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.

Parse VCS revert langauge in commit messages

Summary:
Ref T1751. When commit messages include language like "reverts X", parse it. This change doesn't do anything with the commits yet.

I attempted to cover all "natural" VCS messages and all reasonable human variations of these messages.

Test Plan: Added unit tests. Added `var_dump()` and used `scripts/repository/reparse.php --message X` to reparse some commit messages, with expected results.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T1751

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

+86 -1
+4
src/__phutil_library_map__.php
··· 334 334 'DifferentialFieldSpecificationIncompleteException' => 'applications/differential/field/exception/DifferentialFieldSpecificationIncompleteException.php', 335 335 'DifferentialFieldValidationException' => 'applications/differential/field/exception/DifferentialFieldValidationException.php', 336 336 'DifferentialFreeformFieldSpecification' => 'applications/differential/field/specification/DifferentialFreeformFieldSpecification.php', 337 + 'DifferentialFreeformFieldTestCase' => 'applications/differential/field/specification/__tests__/DifferentialFreeformFieldTestCase.php', 337 338 'DifferentialGitSVNIDFieldSpecification' => 'applications/differential/field/specification/DifferentialGitSVNIDFieldSpecification.php', 338 339 'DifferentialHostFieldSpecification' => 'applications/differential/field/specification/DifferentialHostFieldSpecification.php', 339 340 'DifferentialHovercardEventListener' => 'applications/differential/events/DifferentialHovercardEventListener.php', ··· 1221 1222 'PhabricatorPhabricatorOAuthConfigOptions' => 'applications/config/option/PhabricatorPhabricatorOAuthConfigOptions.php', 1222 1223 'PhabricatorPhameConfigOptions' => 'applications/phame/config/PhabricatorPhameConfigOptions.php', 1223 1224 'PhabricatorPholioConfigOptions' => 'applications/pholio/config/PhabricatorPholioConfigOptions.php', 1225 + 'PhabricatorPholioMockTestDataGenerator' => 'applications/pholio/lipsum/PhabricatorPholioMockTestDataGenerator.php', 1224 1226 'PhabricatorPhortuneConfigOptions' => 'applications/phortune/option/PhabricatorPhortuneConfigOptions.php', 1225 1227 'PhabricatorPhrequentConfigOptions' => 'applications/phrequent/config/PhabricatorPhrequentConfigOptions.php', 1226 1228 'PhabricatorPhrictionConfigOptions' => 'applications/phriction/config/PhabricatorPhrictionConfigOptions.php', ··· 2099 2101 'DifferentialFieldSpecificationIncompleteException' => 'Exception', 2100 2102 'DifferentialFieldValidationException' => 'Exception', 2101 2103 'DifferentialFreeformFieldSpecification' => 'DifferentialFieldSpecification', 2104 + 'DifferentialFreeformFieldTestCase' => 'PhabricatorTestCase', 2102 2105 'DifferentialGitSVNIDFieldSpecification' => 'DifferentialFieldSpecification', 2103 2106 'DifferentialHostFieldSpecification' => 'DifferentialFieldSpecification', 2104 2107 'DifferentialHovercardEventListener' => 'PhutilEventListener', ··· 2935 2938 'PhabricatorPhabricatorOAuthConfigOptions' => 'PhabricatorApplicationConfigOptions', 2936 2939 'PhabricatorPhameConfigOptions' => 'PhabricatorApplicationConfigOptions', 2937 2940 'PhabricatorPholioConfigOptions' => 'PhabricatorApplicationConfigOptions', 2941 + 'PhabricatorPholioMockTestDataGenerator' => 'PhabricatorTestDataGenerator', 2938 2942 'PhabricatorPhortuneConfigOptions' => 'PhabricatorApplicationConfigOptions', 2939 2943 'PhabricatorPhrequentConfigOptions' => 'PhabricatorApplicationConfigOptions', 2940 2944 'PhabricatorPhrictionConfigOptions' => 'PhabricatorApplicationConfigOptions',
+51 -1
src/applications/differential/field/specification/DifferentialFreeformFieldSpecification.php
··· 98 98 return $dependents; 99 99 } 100 100 101 + public static function findRevertedCommits($message) { 102 + $reverts = array(); 103 + $matches = null; 104 + 105 + // NOTE: Git language is "This reverts commit X." 106 + // NOTE: Mercurial language is "Backed out changeset Y". 107 + 108 + $prefixes = array( 109 + 'revert' => true, 110 + 'reverts' => true, 111 + 'back\s*out' => true, 112 + 'backs\s*out' => true, 113 + 'backed\s*out' => true, 114 + 'undo' => true, 115 + 'undoes' => true, 116 + ); 117 + 118 + $optional = array( 119 + 'commit' => true, 120 + 'changeset' => true, 121 + 'rev' => true, 122 + 'revision' => true, 123 + 'change' => true, 124 + 'diff' => true, 125 + ); 126 + 127 + $pre_re = implode('|', array_keys($prefixes)); 128 + $opt_re = implode('|', array_keys($optional)); 129 + 130 + $matches = null; 131 + preg_match_all( 132 + '/\b(?i:'.$pre_re.')(?:\s+(?i:'.$opt_re.'))?([rA-Z0-9a-f,\s]+)\b/', 133 + $message, 134 + $matches); 135 + 136 + $result = array(); 137 + foreach ($matches[1] as $commits) { 138 + $commits = preg_split('/[,\s]+/', $commits); 139 + $commits = array_filter($commits); 140 + foreach ($commits as $commit) { 141 + $result[$commit] = $commit; 142 + } 143 + } 144 + 145 + return $result; 146 + } 147 + 101 148 public function didWriteRevision(DifferentialRevisionEditor $editor) { 102 149 $message = $this->renderValueForCommitMessage(false); 103 150 ··· 151 198 PhabricatorRepositoryCommit $commit, 152 199 PhabricatorRepositoryCommitData $data) { 153 200 201 + $message = $this->renderValueForCommitMessage($is_edit = false); 202 + 203 + $commits = self::findRevertedCommits($message); 204 + 154 205 $user = id(new PhabricatorUser())->loadOneWhere( 155 206 'phid = %s', 156 207 $data->getCommitDetail('authorPHID')); ··· 158 209 return; 159 210 } 160 211 161 - $message = $this->renderValueForCommitMessage($is_edit = false); 162 212 $tasks_statuses = $this->findMentionedTasks($message); 163 213 if (!$tasks_statuses) { 164 214 return;
+31
src/applications/differential/field/specification/__tests__/DifferentialFreeformFieldTestCase.php
··· 1 + <?php 2 + 3 + final class DifferentialFreeformFieldTestCase extends PhabricatorTestCase { 4 + 5 + public function testRevertedCommitParser() { 6 + $map = array( 7 + "Reverts 123" => array('123'), 8 + "Reverts r123" => array('r123'), 9 + "Reverts ac382f2" => array('ac382f2'), 10 + "Reverts r22, r23" => array('r22', 'r23'), 11 + "Reverts D99" => array('D99'), 12 + "Backs out commit\n99\n100" => array('99', '100'), 13 + "undo change f9f9f8f8" => array('f9f9f8f8'), 14 + "Backedout Changeset rX1234" => array('rX1234'), 15 + "This doesn't revert anything" => array(), 16 + 'nonrevert of r11' => array(), 17 + "fixed a bug" => array(), 18 + ); 19 + 20 + foreach ($map as $input => $expect) { 21 + $actual = array_values( 22 + DifferentialFreeformFieldSpecification::findRevertedCommits($input)); 23 + 24 + $this->assertEqual( 25 + $expect, 26 + $actual, 27 + "Reverted commits in: {$input}"); 28 + } 29 + } 30 + 31 + }