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

Allow commits to be associated with projects and associated goodies

Summary:
- Commit detail view
- List of projects
- "edit" action which takes the user to a simple form where they can only add / remove projects.
- Integrated the project relationship into the commit search indexer
- fixed a bug from D790; it seems you must select the column if you're going to join against it later. Without this change searching for author or projectfails 100% for me.

Test Plan: added and removed projects. verified appropriate projects showed up in detail and edit view. searched for commits by project and found the ones I was supposed to...!

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Korvin

Maniphest Tasks: T1614

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

+203 -45
+14 -14
src/__celerity_resource_map__.php
··· 1376 1376 ), 1377 1377 'disk' => '/rsrc/js/application/maniphest/behavior-task-preview.js', 1378 1378 ), 1379 - 'javelin-behavior-maniphest-project-create' => 1380 - array( 1381 - 'uri' => '/res/85a0eaf9/rsrc/js/application/maniphest/behavior-project-create.js', 1382 - 'type' => 'js', 1383 - 'requires' => 1384 - array( 1385 - 0 => 'javelin-behavior', 1386 - 1 => 'javelin-dom', 1387 - 2 => 'javelin-stratcom', 1388 - 3 => 'javelin-workflow', 1389 - ), 1390 - 'disk' => '/rsrc/js/application/maniphest/behavior-project-create.js', 1391 - ), 1392 1379 'javelin-behavior-maniphest-subpriority-editor' => 1393 1380 array( 1394 1381 'uri' => '/res/5e02f19a/rsrc/js/application/maniphest/behavior-subpriorityeditor.js', ··· 1620 1607 3 => 'phabricator-shaped-request', 1621 1608 ), 1622 1609 'disk' => '/rsrc/js/application/phriction/phriction-document-preview.js', 1610 + ), 1611 + 'javelin-behavior-project-create' => 1612 + array( 1613 + 'uri' => '/res/e91f3f8f/rsrc/js/application/projects/behavior-project-create.js', 1614 + 'type' => 'js', 1615 + 'requires' => 1616 + array( 1617 + 0 => 'javelin-behavior', 1618 + 1 => 'javelin-dom', 1619 + 2 => 'javelin-stratcom', 1620 + 3 => 'javelin-workflow', 1621 + ), 1622 + 'disk' => '/rsrc/js/application/projects/behavior-project-create.js', 1623 1623 ), 1624 1624 'javelin-behavior-refresh-csrf' => 1625 1625 array( ··· 2423 2423 ), 2424 2424 'phabricator-object-list-view-css' => 2425 2425 array( 2426 - 'uri' => '/res/4e060838/rsrc/css/application/projects/phabricator-object-list-view.css', 2426 + 'uri' => '/res/4f183668/rsrc/css/application/projects/phabricator-object-list-view.css', 2427 2427 'type' => 'css', 2428 2428 'requires' => 2429 2429 array(
+2
src/__phutil_library_map__.php
··· 318 318 'DiffusionCommitBranchesController' => 'applications/diffusion/controller/DiffusionCommitBranchesController.php', 319 319 'DiffusionCommitChangeTableView' => 'applications/diffusion/view/DiffusionCommitChangeTableView.php', 320 320 'DiffusionCommitController' => 'applications/diffusion/controller/DiffusionCommitController.php', 321 + 'DiffusionCommitEditController' => 'applications/diffusion/controller/DiffusionCommitEditController.php', 321 322 'DiffusionCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionCommitParentsQuery.php', 322 323 'DiffusionCommitTagsController' => 'applications/diffusion/controller/DiffusionCommitTagsController.php', 323 324 'DiffusionCommitTagsQuery' => 'applications/diffusion/query/committags/DiffusionCommitTagsQuery.php', ··· 1429 1430 'DiffusionCommitBranchesController' => 'DiffusionController', 1430 1431 'DiffusionCommitChangeTableView' => 'DiffusionView', 1431 1432 'DiffusionCommitController' => 'DiffusionController', 1433 + 'DiffusionCommitEditController' => 'DiffusionController', 1432 1434 'DiffusionCommitParentsQuery' => 'DiffusionQuery', 1433 1435 'DiffusionCommitTagsController' => 'DiffusionController', 1434 1436 'DiffusionCommitTagsQuery' => 'DiffusionQuery',
+2
src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
··· 52 52 => 'DiffusionCommitBranchesController', 53 53 'commit/(?P<commit>[a-z0-9]+)/tags/' 54 54 => 'DiffusionCommitTagsController', 55 + 'commit/(?P<commit>[a-z0-9]+)/edit/' 56 + => 'DiffusionCommitEditController', 55 57 ), 56 58 'inline/' => array( 57 59 'edit/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController',
+48 -10
src/applications/diffusion/controller/DiffusionCommitController.php
··· 50 50 $commit = $drequest->loadCommit(); 51 51 52 52 if (!$commit) { 53 - // TODO: Make more user-friendly. 54 - throw new Exception('This commit has not parsed yet.'); 53 + // TODO -- T1624 -- detect if this has actually not been parsed yet 54 + // and show this UI if so, else 404 55 + return $this->buildStandardPageResponse( 56 + id(new AphrontErrorView()) 57 + ->setTitle('Error displaying commit.') 58 + ->appendChild('Failed to load the commit. The commit has not been '. 59 + 'parsed yet.'), 60 + array('title' => 'Commit Still Parsing') 61 + ); 55 62 } 56 63 57 64 $commit_data = $drequest->loadCommitData(); ··· 83 90 $headsup_panel = new AphrontHeadsupView(); 84 91 $headsup_panel->setHeader('Commit Detail'); 85 92 $headsup_panel->setActionList( 86 - $this->renderHeadsupActionList($commit)); 93 + $this->renderHeadsupActionList($commit, $repository)); 87 94 $headsup_panel->setProperties( 88 95 $this->getCommitProperties( 89 96 $commit, ··· 310 317 PhabricatorRepositoryCommit $commit, 311 318 PhabricatorRepositoryCommitData $data, 312 319 array $parents) { 320 + 313 321 assert_instances_of($parents, 'PhabricatorRepositoryCommit'); 314 322 $user = $this->getRequest()->getUser(); 323 + $commit_phid = $commit->getPHID(); 315 324 316 - $task_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( 317 - $commit->getPHID(), 318 - PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK); 325 + $edges = id(new PhabricatorEdgeQuery()) 326 + ->withSourcePHIDs(array($commit_phid)) 327 + ->withEdgeTypes(array( 328 + PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK, 329 + PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT 330 + )) 331 + ->execute(); 319 332 320 - $phids = $task_phids; 333 + $task_phids = array_keys( 334 + $edges[$commit_phid][PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK] 335 + ); 336 + $proj_phids = array_keys( 337 + $edges[$commit_phid][PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT] 338 + ); 339 + 340 + $phids = array_merge($task_phids, $proj_phids); 321 341 if ($data->getCommitDetail('authorPHID')) { 322 342 $phids[] = $data->getCommitDetail('authorPHID'); 323 343 } ··· 380 400 } 381 401 } 382 402 383 - 384 403 $revision_phid = $data->getCommitDetail('differential.revisionPHID'); 385 404 if ($revision_phid) { 386 405 $props['Differential Revision'] = $handles[$revision_phid]->renderLink(); ··· 393 412 } 394 413 $props['Parents'] = implode(' &middot; ', $parent_links); 395 414 } 396 - 397 415 398 416 $request = $this->getDiffusionRequest(); 399 417 ··· 421 439 } 422 440 $task_list = implode('<br />', $task_list); 423 441 $props['Tasks'] = $task_list; 442 + } 443 + 444 + if ($proj_phids) { 445 + $proj_list = array(); 446 + foreach ($proj_phids as $phid) { 447 + $proj_list[] = $handles[$phid]->renderLink(); 448 + } 449 + $proj_list = implode('<br />', $proj_list); 450 + $props['Projects'] = $proj_list; 424 451 } 425 452 426 453 return $props; ··· 739 766 } 740 767 741 768 private function renderHeadsupActionList( 742 - PhabricatorRepositoryCommit $commit) { 769 + PhabricatorRepositoryCommit $commit, 770 + PhabricatorRepository $repository) { 743 771 744 772 $request = $this->getRequest(); 745 773 $user = $request->getUser(); 746 774 747 775 $actions = array(); 776 + 777 + // TODO -- integrate permissions into whether or not this action is shown 778 + $uri = '/diffusion/'.$repository->getCallSign().'/commit/'. 779 + $commit->getCommitIdentifier().'/edit/'; 780 + $action = new AphrontHeadsupActionView(); 781 + $action->setClass('action-edit'); 782 + $action->setURI($uri); 783 + $action->setName('Edit Commit'); 784 + $action->setWorkflow(false); 785 + $actions[] = $action; 748 786 749 787 require_celerity_resource('phabricator-flag-css'); 750 788 $flag = PhabricatorFlagQuery::loadUserFlag($user, $commit->getPHID());
+112
src/applications/diffusion/controller/DiffusionCommitEditController.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 + final class DiffusionCommitEditController extends DiffusionController { 20 + 21 + public function willProcessRequest(array $data) { 22 + $this->diffusionRequest = DiffusionRequest::newFromDictionary($data); 23 + } 24 + 25 + public function processRequest() { 26 + 27 + $request = $this->getRequest(); 28 + $user = $request->getUser(); 29 + $drequest = $this->getDiffusionRequest(); 30 + $callsign = $drequest->getRepository()->getCallsign(); 31 + $repository = $drequest->getRepository(); 32 + $commit = $drequest->loadCommit(); 33 + $page_title = 'Edit Diffusion Commit'; 34 + 35 + if (!$commit) { 36 + return new Aphront404Response(); 37 + } 38 + 39 + $commit_phid = $commit->getPHID(); 40 + $edge_type = PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT; 41 + $current_proj_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( 42 + $commit_phid, 43 + $edge_type 44 + ); 45 + $handles = id(new PhabricatorObjectHandleData($current_proj_phids)) 46 + ->loadHandles(); 47 + $proj_t_values = mpull($handles, 'getFullName', 'getPHID'); 48 + 49 + if ($request->isFormPost()) { 50 + $proj_phids = $request->getArr('projects'); 51 + $new_proj_phids = array_values($proj_phids); 52 + $rem_proj_phids = array_diff($current_proj_phids, 53 + $new_proj_phids); 54 + $editor = id(new PhabricatorEdgeEditor()); 55 + $editor->setUser($user); 56 + foreach ($rem_proj_phids as $phid) { 57 + $editor->removeEdge($commit_phid, $edge_type, $phid); 58 + } 59 + foreach ($new_proj_phids as $phid) { 60 + $editor->addEdge($commit_phid, $edge_type, $phid); 61 + } 62 + $editor->save(); 63 + 64 + PhabricatorSearchCommitIndexer::indexCommit($commit); 65 + 66 + return id(new AphrontRedirectResponse()) 67 + ->setURI('/r'.$callsign.$commit->getCommitIdentifier()); 68 + } 69 + 70 + $tokenizer_id = celerity_generate_unique_node_id(); 71 + $form = id(new AphrontFormView()) 72 + ->setUser($user) 73 + ->setAction($request->getRequestURI()->getPath()) 74 + ->appendChild( 75 + id(new AphrontFormTokenizerControl()) 76 + ->setLabel('Projects') 77 + ->setName('projects') 78 + ->setValue($proj_t_values) 79 + ->setID($tokenizer_id) 80 + ->setCaption( 81 + javelin_render_tag( 82 + 'a', 83 + array( 84 + 'href' => '/project/create/', 85 + 'mustcapture' => true, 86 + 'sigil' => 'project-create', 87 + ), 88 + 'Create New Project')) 89 + ->setDatasource('/typeahead/common/projects/'));; 90 + 91 + Javelin::initBehavior('project-create', array( 92 + 'tokenizerID' => $tokenizer_id, 93 + )); 94 + 95 + $submit = id(new AphrontFormSubmitControl()) 96 + ->setValue('Save') 97 + ->addCancelButton('/r'.$callsign.$commit->getCommitIdentifier()); 98 + $form->appendChild($submit); 99 + 100 + $panel = id(new AphrontPanelView()) 101 + ->setHeader('Edit Diffusion Commit') 102 + ->appendChild($form) 103 + ->setWidth(AphrontPanelView::WIDTH_FORM); 104 + 105 + return $this->buildStandardPageResponse( 106 + $panel, 107 + array( 108 + 'title' => $page_title, 109 + )); 110 + } 111 + 112 + }
+1 -1
src/applications/maniphest/controller/ManiphestTaskEditController.php
··· 466 466 467 467 require_celerity_resource('aphront-error-view-css'); 468 468 469 - Javelin::initBehavior('maniphest-project-create', array( 469 + Javelin::initBehavior('project-create', array( 470 470 'tokenizerID' => $project_tokenizer_id, 471 471 )); 472 472
+1 -18
src/applications/search/engine/PhabricatorSearchEngineMySQL.php
··· 252 252 'repository', 253 253 PhabricatorSearchRelationship::RELATIONSHIP_REPOSITORY); 254 254 255 - /* 256 - $join[] = $this->joinRelationship( 257 - $conn_r, 258 - $query, 259 - 'reviewer', 260 - AdjutantRelationship::RELATIONSHIP_REVIEWER); 261 - $join[] = $this->joinRelationship( 262 - $conn_r, 263 - $query, 264 - 'subscriber', 265 - AdjutantRelationship::RELATIONSHIP_SUBSCRIBER); 266 - $join[] = $this->joinRelationship( 267 - $conn_r, 268 - $query, 269 - 'repository', 270 - AdjutantRelationship::RELATIONSHIP_REPOSITORY); 271 - */ 272 255 $join = array_filter($join); 273 256 274 257 foreach ($join as $key => $clause) { ··· 288 271 $hits = queryfx_all( 289 272 $conn_r, 290 273 'SELECT 291 - document.phid 274 + document.phid 292 275 FROM %T document 293 276 %Q 294 277 %Q
+14
src/applications/search/index/indexer/PhabricatorSearchCommitIndexer.php
··· 60 60 $date_created); 61 61 } 62 62 63 + $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( 64 + $commit->getPHID(), 65 + PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT 66 + ); 67 + if ($project_phids) { 68 + foreach ($project_phids as $project_phid) { 69 + $doc->addRelationship( 70 + PhabricatorSearchRelationship::RELATIONSHIP_PROJECT, 71 + $project_phid, 72 + PhabricatorPHIDConstants::PHID_TYPE_PROJ, 73 + $date_created); 74 + } 75 + } 76 + 63 77 $doc->addRelationship( 64 78 PhabricatorSearchRelationship::RELATIONSHIP_REPOSITORY, 65 79 $repository->getPHID(),
+7
src/infrastructure/edges/constants/PhabricatorEdgeConfig.php
··· 41 41 const TYPE_PROJ_MEMBER = 13; 42 42 const TYPE_MEMBER_OF_PROJ = 14; 43 43 44 + const TYPE_COMMIT_HAS_PROJECT = 15; 45 + const TYPE_PROJECT_HAS_COMMIT = 16; 46 + 44 47 const TYPE_TEST_NO_CYCLE = 9000; 45 48 46 49 public static function getInverse($edge_type) { ··· 64 67 65 68 self::TYPE_PROJ_MEMBER => self::TYPE_MEMBER_OF_PROJ, 66 69 self::TYPE_MEMBER_OF_PROJ => self::TYPE_PROJ_MEMBER, 70 + 71 + self::TYPE_COMMIT_HAS_PROJECT => self::TYPE_PROJECT_HAS_COMMIT, 72 + self::TYPE_PROJECT_HAS_COMMIT => self::TYPE_COMMIT_HAS_PROJECT, 73 + 67 74 ); 68 75 69 76 return idx($map, $edge_type);
+2 -2
webroot/rsrc/js/application/maniphest/behavior-project-create.js webroot/rsrc/js/application/projects/behavior-project-create.js
··· 1 1 /** 2 - * @provides javelin-behavior-maniphest-project-create 2 + * @provides javelin-behavior-project-create 3 3 * @requires javelin-behavior 4 4 * javelin-dom 5 5 * javelin-stratcom 6 6 * javelin-workflow 7 7 */ 8 8 9 - JX.behavior('maniphest-project-create', function(config) { 9 + JX.behavior('project-create', function(config) { 10 10 11 11 JX.Stratcom.listen( 12 12 'click',