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

Add basic detail-parser functionality.

+336 -12
+1
resources/sql/patches/016.userrealnameindex.sql
··· 1 + ALTER TABLE phabricator_user.user ADD key (realName);
+3
src/__phutil_library_map__.php
··· 342 342 'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/base', 343 343 'PhabricatorRepositoryCommitData' => 'applications/repository/storage/commitdata', 344 344 'PhabricatorRepositoryCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/base', 345 + 'PhabricatorRepositoryCommitMessageDetailParser' => 'applications/repository/parser/base', 345 346 'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/base', 346 347 'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/base', 347 348 'PhabricatorRepositoryCommitTaskDaemon' => 'applications/repository/daemon/committask', ··· 349 350 'PhabricatorRepositoryCreateController' => 'applications/repository/controller/create', 350 351 'PhabricatorRepositoryDAO' => 'applications/repository/storage/base', 351 352 'PhabricatorRepositoryDaemon' => 'applications/repository/daemon/base', 353 + 'PhabricatorRepositoryDefaultCommitMessageDetailParser' => 'applications/repository/parser/default', 352 354 'PhabricatorRepositoryEditController' => 'applications/repository/controller/edit', 353 355 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/git', 354 356 'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/git', ··· 690 692 'PhabricatorRepositoryCreateController' => 'PhabricatorRepositoryController', 691 693 'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO', 692 694 'PhabricatorRepositoryDaemon' => 'PhabricatorDaemon', 695 + 'PhabricatorRepositoryDefaultCommitMessageDetailParser' => 'PhabricatorRepositoryCommitMessageDetailParser', 693 696 'PhabricatorRepositoryEditController' => 'PhabricatorRepositoryController', 694 697 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 695 698 'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
+61 -6
src/applications/diffusion/controller/commit/DiffusionCommitController.php
··· 46 46 require_celerity_resource('diffusion-commit-view-css'); 47 47 require_celerity_resource('phabricator-remarkup-css'); 48 48 49 + $property_table = $this->renderPropertyTable($commit, $commit_data); 50 + 49 51 $detail_panel->appendChild( 50 52 '<div class="diffusion-commit-view">'. 51 53 '<div class="diffusion-commit-dateline">'. ··· 55 57 '</div>'. 56 58 '<h1>Revision Detail</h1>'. 57 59 '<div class="diffusion-commit-details">'. 58 - '<table class="diffusion-commit-properties">'. 59 - '<tr>'. 60 - '<th>Author:</th>'. 61 - '<td>'.phutil_escape_html($commit_data->getAuthorName()).'</td>'. 62 - '</tr>'. 63 - '</table>'. 60 + $property_table. 64 61 '<hr />'. 65 62 '<div class="diffusion-commit-message phabricator-remarkup">'. 66 63 $engine->markupText($commit_data->getCommitMessage()). ··· 166 163 array( 167 164 'title' => 'Diffusion', 168 165 )); 166 + } 167 + 168 + private function renderPropertyTable( 169 + PhabricatorRepositoryCommit $commit, 170 + PhabricatorRepositoryCommitData $data) { 171 + 172 + $phids = array(); 173 + if ($data->getCommitDetail('authorPHID')) { 174 + $phids[] = $data->getCommitDetail('authorPHID'); 175 + } 176 + if ($data->getCommitDetail('reviewerPHID')) { 177 + $phids[] = $data->getCommitDetail('reviewerPHID'); 178 + } 179 + if ($data->getCommitDetail('differential.revisionPHID')) { 180 + $phids[] = $data->getCommitDetail('differential.revisionPHID'); 181 + } 182 + 183 + $handles = array(); 184 + if ($phids) { 185 + $handles = id(new PhabricatorObjectHandleData($phids)) 186 + ->loadHandles(); 187 + } 188 + 189 + $props = array(); 190 + 191 + $author_phid = $data->getCommitDetail('authorPHID'); 192 + if ($data->getCommitDetail('authorPHID')) { 193 + $props['Author'] = $handles[$author_phid]->renderLink(); 194 + } else { 195 + $props['Author'] = phutil_escape_html($data->getAuthorName()); 196 + } 197 + 198 + $reviewer_phid = $data->getCommitDetail('reviewerPHID'); 199 + $reviewer_name = $data->getCommitDetail('reviewerName'); 200 + if ($reviewer_phid) { 201 + $props['Reviewer'] = $handles[$reviewer_phid]->renderLink(); 202 + } else if ($reviewer_name) { 203 + $props['Reviewer'] = phutil_escape_html($reviewer_name); 204 + } 205 + 206 + $revision_phid = $data->getCommitDetail('differential.revisionPHID'); 207 + if ($revision_phid) { 208 + $props['Differential Revision'] = $handles[$revision_phid]->renderLink(); 209 + } 210 + 211 + $rows = array(); 212 + foreach ($props as $key => $value) { 213 + $rows[] = 214 + '<tr>'. 215 + '<th>'.$key.':</th>'. 216 + '<td>'.$value.'</td>'. 217 + '</tr>'; 218 + } 219 + 220 + return 221 + '<table class="diffusion-commit-properties">'. 222 + implode("\n", $rows). 223 + '</table>'; 169 224 } 170 225 171 226 }
+3
src/applications/diffusion/controller/home/DiffusionHomeController.php
··· 105 105 'href' => '/diffusion/'.$repository->getCallsign().'/', 106 106 ), 107 107 phutil_escape_html($repository->getName())), 108 + phutil_escape_html($repository->getDetail('description')), 108 109 PhabricatorRepositoryType::getNameForRepositoryType( 109 110 $repository->getVersionControlSystem()), 110 111 $size ? number_format($size) : '-', ··· 122 123 $table->setHeaders( 123 124 array( 124 125 'Repository', 126 + 'Description', 125 127 'VCS', 126 128 'Size', 127 129 'Last', ··· 130 132 )); 131 133 $table->setColumnClasses( 132 134 array( 135 + 'pri', 133 136 'wide', 134 137 '', 135 138 'n',
+4
src/applications/diffusion/request/git/DiffusionGitRequest.php
··· 46 46 47 47 $branch = $this->getBranch(); 48 48 49 + // TODO: Here, particularly, we should give the user a specific error 50 + // message to indicate whether they've typed in some bogus branch and/or 51 + // followed a bad link, or misconfigured the default branch in the 52 + // Repository tool. 49 53 execx( 50 54 '(cd %s && git rev-parse --verify %s)', 51 55 $local_path,
+83 -6
src/applications/repository/controller/edit/PhabricatorRepositoryEditController.php
··· 115 115 $e_name = null; 116 116 } 117 117 118 + $repository->setDetail('description', $request->getStr('description')); 119 + 118 120 if (!$errors) { 119 121 $repository->save(); 120 122 return id(new AphrontRedirectResponse()) ··· 147 149 ->setError($e_name) 148 150 ->setCaption('Human-readable repository name.')) 149 151 ->appendChild( 152 + id(new AphrontFormTextAreaControl()) 153 + ->setLabel('Description') 154 + ->setName('description') 155 + ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT) 156 + ->setValue($repository->getDetail('description'))) 157 + ->appendChild( 150 158 id(new AphrontFormStaticControl()) 151 159 ->setLabel('Callsign') 152 160 ->setName('callsign') ··· 156 164 ->setLabel('Type') 157 165 ->setName('type') 158 166 ->setValue($repository->getVersionControlSystem())) 167 + ->appendChild( 168 + id(new AphrontFormStaticControl()) 169 + ->setLabel('ID') 170 + ->setValue($repository->getID())) 159 171 ->appendChild( 160 172 id(new AphrontFormStaticControl()) 161 173 ->setLabel('PHID') 162 - ->setName('phid') 163 174 ->setValue($repository->getPHID())) 164 175 ->appendChild( 165 176 id(new AphrontFormSubmitControl()) ··· 194 205 $e_uri = null; 195 206 $e_path = null; 196 207 208 + $is_git = false; 209 + $is_svn = false; 210 + 211 + switch ($repository->getVersionControlSystem()) { 212 + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 213 + $is_git = true; 214 + break; 215 + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 216 + $is_svn = true; 217 + break; 218 + default: 219 + throw new Exception("Unsupported VCS!"); 220 + } 221 + 197 222 if ($request->isFormPost()) { 198 223 $tracking = ($request->getStr('tracking') == 'enabled' ? true : false); 199 224 $repository->setDetail('tracking-enabled', $tracking); ··· 203 228 'pull-frequency', 204 229 max(1, $request->getInt('frequency'))); 205 230 231 + if ($is_git) { 232 + $repository->setDetail( 233 + 'default-branch', 234 + $request->getStr('default-branch')); 235 + } 236 + 237 + $repository->setDetail( 238 + 'detail-parser', 239 + $request->getStr( 240 + 'detail-parser', 241 + 'PhabricatorRepositoryDefaultCommitMessageDetailParser')); 242 + 206 243 if ($tracking) { 207 244 if (!$repository->getDetail('remote-uri')) { 208 245 $e_uri = 'Required'; ··· 237 274 238 275 $uri_caption = null; 239 276 $path_caption = null; 277 + 278 + 240 279 switch ($repository->getVersionControlSystem()) { 241 - case 'git': 280 + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 281 + $is_git = true; 242 282 $uri_caption = 243 283 'The user the tracking daemon runs as must have permission to '. 244 284 '<tt>git clone</tt> from this URI.'; ··· 247 287 'repository (or create one if it does not yet exist). The daemon '. 248 288 'will regularly pull remote changes into this working copy.'; 249 289 break; 250 - case 'svn': 290 + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 291 + $is_svn = true; 251 292 $uri_caption = 252 293 'The user the tracking daemon runs as must have permission to '. 253 294 '<tt>svn log</tt> from this URI.'; ··· 263 304 'repositories, importing commits as they happen and notifying '. 264 305 'Differential, Diffusion, Herald, and other services. To enable '. 265 306 'tracking for a repository, configure it here and then start (or '. 266 - 'restart) the PhabricatorRepositoryTrackingDaemon.</p>') 307 + 'restart) the daemons (TODO: explain this).</p>') 267 308 ->appendChild( 268 309 id(new AphrontFormStaticControl()) 269 310 ->setLabel('Repository') ··· 301 342 ->setValue($repository->getDetail('pull-frequency', 15)) 302 343 ->setCaption( 303 344 'Number of seconds daemon should sleep between requests. Larger '. 304 - 'numbers reduce load but also decrease responsiveness.')) 345 + 'numbers reduce load but also decrease responsiveness.')); 346 + 347 + if ($is_git) { 348 + $form 349 + ->appendChild( 350 + id(new AphrontFormTextControl()) 351 + ->setName('default-branch') 352 + ->setLabel('Default Branch') 353 + ->setValue( 354 + $repository->getDetail( 355 + 'default-branch', 356 + 'origin/master')) 357 + ->setCaption( 358 + 'Default <strong>remote</strong> branch to show in Diffusion.')); 359 + } 360 + 361 + $parsers = id(new PhutilSymbolLoader()) 362 + ->setAncestorClass('PhabricatorRepositoryCommitMessageDetailParser') 363 + ->selectSymbolsWithoutLoading(); 364 + $parsers = ipull($parsers, 'name', 'name'); 365 + 366 + $form 367 + ->appendChild( 368 + '<p class="aphront-form-instructions">If you extend the commit '. 369 + 'message format, you can provide a new parser which will extract '. 370 + 'extra information from it when commits are imported. This is an '. 371 + 'advanced feature, and using the default parser will be suitable '. 372 + 'in most cases.</p>') 373 + ->appendChild( 374 + id(new AphrontFormSelectControl()) 375 + ->setName('detail-parser') 376 + ->setLabel('Detail Parser') 377 + ->setOptions($parsers) 378 + ->setValue( 379 + $repository->getDetail( 380 + 'detail-parser', 381 + 'PhabricatorRepositoryDefaultCommitMessageDetailParser'))) 305 382 ->appendChild( 306 383 id(new AphrontFormSubmitControl()) 307 384 ->setValue('Save')); ··· 309 386 $panel = new AphrontPanelView(); 310 387 $panel->setHeader('Repository Tracking'); 311 388 $panel->appendChild($form); 312 - $panel->setWidth(AphrontPanelView::WIDTH_FORM); 389 + $panel->setWidth(AphrontPanelView::WIDTH_WIDE); 313 390 314 391 $nav = $this->sideNav; 315 392 $nav->appendChild($error_view);
+3
src/applications/repository/controller/edit/__init__.php
··· 9 9 phutil_require_module('phabricator', 'aphront/response/404'); 10 10 phutil_require_module('phabricator', 'aphront/response/redirect'); 11 11 phutil_require_module('phabricator', 'applications/differential/constants/revisioncontrolsystem'); 12 + phutil_require_module('phabricator', 'applications/repository/constants/repositorytype'); 12 13 phutil_require_module('phabricator', 'applications/repository/controller/base'); 13 14 phutil_require_module('phabricator', 'applications/repository/storage/githubnotification'); 14 15 phutil_require_module('phabricator', 'applications/repository/storage/repository'); ··· 16 17 phutil_require_module('phabricator', 'view/control/table'); 17 18 phutil_require_module('phabricator', 'view/form/base'); 18 19 phutil_require_module('phabricator', 'view/form/control/submit'); 20 + phutil_require_module('phabricator', 'view/form/control/text'); 19 21 phutil_require_module('phabricator', 'view/form/error'); 20 22 phutil_require_module('phabricator', 'view/layout/panel'); 21 23 phutil_require_module('phabricator', 'view/layout/sidenav'); ··· 23 25 24 26 phutil_require_module('phutil', 'filesystem'); 25 27 phutil_require_module('phutil', 'markup'); 28 + phutil_require_module('phutil', 'symbols'); 26 29 phutil_require_module('phutil', 'utils'); 27 30 28 31
+66
src/applications/repository/parser/base/PhabricatorRepositoryCommitMessageDetailParser.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 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 PhabricatorRepositoryCommitMessageDetailParser { 20 + 21 + private $commit; 22 + private $commitData; 23 + 24 + final public function __construct( 25 + PhabricatorRepositoryCommit $commit, 26 + PhabricatorRepositoryCommitData $data) { 27 + $this->commit = $commit; 28 + $this->commitData = $data; 29 + } 30 + 31 + final public function getCommit() { 32 + return $this->commit; 33 + } 34 + 35 + final public function getCommitData() { 36 + return $this->commitData; 37 + } 38 + 39 + public function resolveUserPHID($user_name) { 40 + if (!strlen($user_name)) { 41 + return null; 42 + } 43 + 44 + $by_username = id(new PhabricatorUser())->loadOneWhere( 45 + 'userName = %s', 46 + $user_name); 47 + if ($by_username) { 48 + return $by_username->getPHID(); 49 + } 50 + 51 + // Note, real names are not guaranteed unique, which is why we do it this 52 + // way. 53 + $by_realname = id(new PhabricatorUser())->loadAllWhere( 54 + 'realName = %s LIMIT 1', 55 + $user_name); 56 + if ($by_realname) { 57 + $by_realname = reset($by_realname); 58 + return $by_realname->getPHID(); 59 + } 60 + 61 + return null; 62 + } 63 + 64 + abstract public function parseCommitDetails(); 65 + 66 + }
+14
src/applications/repository/parser/base/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'applications/people/storage/user'); 10 + 11 + phutil_require_module('phutil', 'utils'); 12 + 13 + 14 + phutil_require_source('PhabricatorRepositoryCommitMessageDetailParser.php');
+67
src/applications/repository/parser/default/PhabricatorRepositoryDefaultCommitMessageDetailParser.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 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 + class PhabricatorRepositoryDefaultCommitMessageDetailParser 20 + extends PhabricatorRepositoryCommitMessageDetailParser { 21 + 22 + public function parseCommitDetails() { 23 + $commit = $this->getCommit(); 24 + $data = $this->getCommitData(); 25 + 26 + $details = nonempty($data->getCommitDetails(), array()); 27 + $message = $data->getCommitMessage(); 28 + $author_name = $data->getAuthorName(); 29 + 30 + $match = null; 31 + 32 + if (preg_match( 33 + '/^\s*Differential Revision:\s*(\S+)\s*$/mi', 34 + $message, 35 + $match)) { 36 + 37 + $id = (int)$match[1]; 38 + if ($id) { 39 + $details['differential.revisionID'] = (int)$match[1]; 40 + $revision = id(new DifferentialRevision())->load($id); 41 + if ($revision) { 42 + $details['differential.revisionPHID'] = $revision->getPHID(); 43 + } 44 + } 45 + } 46 + 47 + if (preg_match( 48 + '/^\s*Reviewed By:\s*(\S+)\s*$/mi', 49 + $message, 50 + $match)) { 51 + $details['reviewerName'] = $match[1]; 52 + 53 + $reviewer_phid = $this->resolveUserPHID($details['reviewerName']); 54 + if ($reviewer_phid) { 55 + $details['reviewerPHID'] = $reviewer_phid; 56 + } 57 + } 58 + 59 + $author_phid = $this->resolveUserPHID($author_name); 60 + if ($author_phid) { 61 + $details['authorPHID'] = $author_phid; 62 + } 63 + 64 + $data->setCommitDetails($details); 65 + } 66 + 67 + }
+14
src/applications/repository/parser/default/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'applications/repository/parser/base'); 10 + 11 + phutil_require_module('phutil', 'utils'); 12 + 13 + 14 + phutil_require_source('PhabricatorRepositoryDefaultCommitMessageDetailParser.php');
+4
src/applications/repository/storage/commitdata/PhabricatorRepositoryCommitData.php
··· 36 36 return substr($this->getCommitMessage(), 0, 80); 37 37 } 38 38 39 + public function getCommitDetail($key, $default = null) { 40 + return idx($this->commitDetails, $key, $default); 41 + } 42 + 39 43 }
+12
src/applications/repository/worker/commitmessageparser/base/PhabricatorRepositoryCommitMessageParserWorker.php
··· 31 31 $data->setCommitID($commit->getID()); 32 32 $data->setAuthorName($author); 33 33 $data->setCommitMessage($message); 34 + 35 + $repository = $this->repository; 36 + $detail_parser = $repository->getDetail( 37 + 'detail-parser', 38 + 'PhabricatorRepositoryDefaultCommitMessageDetailParser'); 39 + 40 + if ($detail_parser) { 41 + PhutilSymbolLoader::loadClass($detail_parser); 42 + $parser_obj = newv($detail_parser, array($commit, $data)); 43 + $parser_obj->parseCommitDetails(); 44 + } 45 + 34 46 $data->save(); 35 47 } 36 48
+1
src/applications/repository/worker/commitmessageparser/base/__init__.php
··· 9 9 phutil_require_module('phabricator', 'applications/repository/storage/commitdata'); 10 10 phutil_require_module('phabricator', 'applications/repository/worker/base'); 11 11 12 + phutil_require_module('phutil', 'symbols'); 12 13 phutil_require_module('phutil', 'utils'); 13 14 14 15