mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 08:42:41 +01:00
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
This commit is contained in:
parent
5b8028e254
commit
8a4c08b01d
10 changed files with 203 additions and 45 deletions
|
@ -1376,19 +1376,6 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/maniphest/behavior-task-preview.js',
|
||||
),
|
||||
'javelin-behavior-maniphest-project-create' =>
|
||||
array(
|
||||
'uri' => '/res/85a0eaf9/rsrc/js/application/maniphest/behavior-project-create.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-dom',
|
||||
2 => 'javelin-stratcom',
|
||||
3 => 'javelin-workflow',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/maniphest/behavior-project-create.js',
|
||||
),
|
||||
'javelin-behavior-maniphest-subpriority-editor' =>
|
||||
array(
|
||||
'uri' => '/res/5e02f19a/rsrc/js/application/maniphest/behavior-subpriorityeditor.js',
|
||||
|
@ -1621,6 +1608,19 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/phriction/phriction-document-preview.js',
|
||||
),
|
||||
'javelin-behavior-project-create' =>
|
||||
array(
|
||||
'uri' => '/res/e91f3f8f/rsrc/js/application/projects/behavior-project-create.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-dom',
|
||||
2 => 'javelin-stratcom',
|
||||
3 => 'javelin-workflow',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/projects/behavior-project-create.js',
|
||||
),
|
||||
'javelin-behavior-refresh-csrf' =>
|
||||
array(
|
||||
'uri' => '/res/88beba4c/rsrc/js/application/core/behavior-refresh-csrf.js',
|
||||
|
@ -2423,7 +2423,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'phabricator-object-list-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/4e060838/rsrc/css/application/projects/phabricator-object-list-view.css',
|
||||
'uri' => '/res/4f183668/rsrc/css/application/projects/phabricator-object-list-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
|
|
|
@ -318,6 +318,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionCommitBranchesController' => 'applications/diffusion/controller/DiffusionCommitBranchesController.php',
|
||||
'DiffusionCommitChangeTableView' => 'applications/diffusion/view/DiffusionCommitChangeTableView.php',
|
||||
'DiffusionCommitController' => 'applications/diffusion/controller/DiffusionCommitController.php',
|
||||
'DiffusionCommitEditController' => 'applications/diffusion/controller/DiffusionCommitEditController.php',
|
||||
'DiffusionCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionCommitParentsQuery.php',
|
||||
'DiffusionCommitTagsController' => 'applications/diffusion/controller/DiffusionCommitTagsController.php',
|
||||
'DiffusionCommitTagsQuery' => 'applications/diffusion/query/committags/DiffusionCommitTagsQuery.php',
|
||||
|
@ -1429,6 +1430,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionCommitBranchesController' => 'DiffusionController',
|
||||
'DiffusionCommitChangeTableView' => 'DiffusionView',
|
||||
'DiffusionCommitController' => 'DiffusionController',
|
||||
'DiffusionCommitEditController' => 'DiffusionController',
|
||||
'DiffusionCommitParentsQuery' => 'DiffusionQuery',
|
||||
'DiffusionCommitTagsController' => 'DiffusionController',
|
||||
'DiffusionCommitTagsQuery' => 'DiffusionQuery',
|
||||
|
|
|
@ -52,6 +52,8 @@ final class PhabricatorApplicationDiffusion extends PhabricatorApplication {
|
|||
=> 'DiffusionCommitBranchesController',
|
||||
'commit/(?P<commit>[a-z0-9]+)/tags/'
|
||||
=> 'DiffusionCommitTagsController',
|
||||
'commit/(?P<commit>[a-z0-9]+)/edit/'
|
||||
=> 'DiffusionCommitEditController',
|
||||
),
|
||||
'inline/' => array(
|
||||
'edit/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController',
|
||||
|
|
|
@ -50,8 +50,15 @@ final class DiffusionCommitController extends DiffusionController {
|
|||
$commit = $drequest->loadCommit();
|
||||
|
||||
if (!$commit) {
|
||||
// TODO: Make more user-friendly.
|
||||
throw new Exception('This commit has not parsed yet.');
|
||||
// TODO -- T1624 -- detect if this has actually not been parsed yet
|
||||
// and show this UI if so, else 404
|
||||
return $this->buildStandardPageResponse(
|
||||
id(new AphrontErrorView())
|
||||
->setTitle('Error displaying commit.')
|
||||
->appendChild('Failed to load the commit. The commit has not been '.
|
||||
'parsed yet.'),
|
||||
array('title' => 'Commit Still Parsing')
|
||||
);
|
||||
}
|
||||
|
||||
$commit_data = $drequest->loadCommitData();
|
||||
|
@ -83,7 +90,7 @@ final class DiffusionCommitController extends DiffusionController {
|
|||
$headsup_panel = new AphrontHeadsupView();
|
||||
$headsup_panel->setHeader('Commit Detail');
|
||||
$headsup_panel->setActionList(
|
||||
$this->renderHeadsupActionList($commit));
|
||||
$this->renderHeadsupActionList($commit, $repository));
|
||||
$headsup_panel->setProperties(
|
||||
$this->getCommitProperties(
|
||||
$commit,
|
||||
|
@ -310,14 +317,27 @@ final class DiffusionCommitController extends DiffusionController {
|
|||
PhabricatorRepositoryCommit $commit,
|
||||
PhabricatorRepositoryCommitData $data,
|
||||
array $parents) {
|
||||
|
||||
assert_instances_of($parents, 'PhabricatorRepositoryCommit');
|
||||
$user = $this->getRequest()->getUser();
|
||||
$commit_phid = $commit->getPHID();
|
||||
|
||||
$task_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
|
||||
$commit->getPHID(),
|
||||
PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK);
|
||||
$edges = id(new PhabricatorEdgeQuery())
|
||||
->withSourcePHIDs(array($commit_phid))
|
||||
->withEdgeTypes(array(
|
||||
PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK,
|
||||
PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT
|
||||
))
|
||||
->execute();
|
||||
|
||||
$phids = $task_phids;
|
||||
$task_phids = array_keys(
|
||||
$edges[$commit_phid][PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK]
|
||||
);
|
||||
$proj_phids = array_keys(
|
||||
$edges[$commit_phid][PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT]
|
||||
);
|
||||
|
||||
$phids = array_merge($task_phids, $proj_phids);
|
||||
if ($data->getCommitDetail('authorPHID')) {
|
||||
$phids[] = $data->getCommitDetail('authorPHID');
|
||||
}
|
||||
|
@ -380,7 +400,6 @@ final class DiffusionCommitController extends DiffusionController {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
$revision_phid = $data->getCommitDetail('differential.revisionPHID');
|
||||
if ($revision_phid) {
|
||||
$props['Differential Revision'] = $handles[$revision_phid]->renderLink();
|
||||
|
@ -394,7 +413,6 @@ final class DiffusionCommitController extends DiffusionController {
|
|||
$props['Parents'] = implode(' · ', $parent_links);
|
||||
}
|
||||
|
||||
|
||||
$request = $this->getDiffusionRequest();
|
||||
|
||||
$props['Branches'] = '<span id="commit-branches">Unknown</span>';
|
||||
|
@ -423,6 +441,15 @@ final class DiffusionCommitController extends DiffusionController {
|
|||
$props['Tasks'] = $task_list;
|
||||
}
|
||||
|
||||
if ($proj_phids) {
|
||||
$proj_list = array();
|
||||
foreach ($proj_phids as $phid) {
|
||||
$proj_list[] = $handles[$phid]->renderLink();
|
||||
}
|
||||
$proj_list = implode('<br />', $proj_list);
|
||||
$props['Projects'] = $proj_list;
|
||||
}
|
||||
|
||||
return $props;
|
||||
}
|
||||
|
||||
|
@ -739,13 +766,24 @@ final class DiffusionCommitController extends DiffusionController {
|
|||
}
|
||||
|
||||
private function renderHeadsupActionList(
|
||||
PhabricatorRepositoryCommit $commit) {
|
||||
PhabricatorRepositoryCommit $commit,
|
||||
PhabricatorRepository $repository) {
|
||||
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$actions = array();
|
||||
|
||||
// TODO -- integrate permissions into whether or not this action is shown
|
||||
$uri = '/diffusion/'.$repository->getCallSign().'/commit/'.
|
||||
$commit->getCommitIdentifier().'/edit/';
|
||||
$action = new AphrontHeadsupActionView();
|
||||
$action->setClass('action-edit');
|
||||
$action->setURI($uri);
|
||||
$action->setName('Edit Commit');
|
||||
$action->setWorkflow(false);
|
||||
$actions[] = $action;
|
||||
|
||||
require_celerity_resource('phabricator-flag-css');
|
||||
$flag = PhabricatorFlagQuery::loadUserFlag($user, $commit->getPHID());
|
||||
if ($flag) {
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class DiffusionCommitEditController extends DiffusionController {
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->diffusionRequest = DiffusionRequest::newFromDictionary($data);
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$drequest = $this->getDiffusionRequest();
|
||||
$callsign = $drequest->getRepository()->getCallsign();
|
||||
$repository = $drequest->getRepository();
|
||||
$commit = $drequest->loadCommit();
|
||||
$page_title = 'Edit Diffusion Commit';
|
||||
|
||||
if (!$commit) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$commit_phid = $commit->getPHID();
|
||||
$edge_type = PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT;
|
||||
$current_proj_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
|
||||
$commit_phid,
|
||||
$edge_type
|
||||
);
|
||||
$handles = id(new PhabricatorObjectHandleData($current_proj_phids))
|
||||
->loadHandles();
|
||||
$proj_t_values = mpull($handles, 'getFullName', 'getPHID');
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$proj_phids = $request->getArr('projects');
|
||||
$new_proj_phids = array_values($proj_phids);
|
||||
$rem_proj_phids = array_diff($current_proj_phids,
|
||||
$new_proj_phids);
|
||||
$editor = id(new PhabricatorEdgeEditor());
|
||||
$editor->setUser($user);
|
||||
foreach ($rem_proj_phids as $phid) {
|
||||
$editor->removeEdge($commit_phid, $edge_type, $phid);
|
||||
}
|
||||
foreach ($new_proj_phids as $phid) {
|
||||
$editor->addEdge($commit_phid, $edge_type, $phid);
|
||||
}
|
||||
$editor->save();
|
||||
|
||||
PhabricatorSearchCommitIndexer::indexCommit($commit);
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI('/r'.$callsign.$commit->getCommitIdentifier());
|
||||
}
|
||||
|
||||
$tokenizer_id = celerity_generate_unique_node_id();
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->setAction($request->getRequestURI()->getPath())
|
||||
->appendChild(
|
||||
id(new AphrontFormTokenizerControl())
|
||||
->setLabel('Projects')
|
||||
->setName('projects')
|
||||
->setValue($proj_t_values)
|
||||
->setID($tokenizer_id)
|
||||
->setCaption(
|
||||
javelin_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/project/create/',
|
||||
'mustcapture' => true,
|
||||
'sigil' => 'project-create',
|
||||
),
|
||||
'Create New Project'))
|
||||
->setDatasource('/typeahead/common/projects/'));;
|
||||
|
||||
Javelin::initBehavior('project-create', array(
|
||||
'tokenizerID' => $tokenizer_id,
|
||||
));
|
||||
|
||||
$submit = id(new AphrontFormSubmitControl())
|
||||
->setValue('Save')
|
||||
->addCancelButton('/r'.$callsign.$commit->getCommitIdentifier());
|
||||
$form->appendChild($submit);
|
||||
|
||||
$panel = id(new AphrontPanelView())
|
||||
->setHeader('Edit Diffusion Commit')
|
||||
->appendChild($form)
|
||||
->setWidth(AphrontPanelView::WIDTH_FORM);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$panel,
|
||||
array(
|
||||
'title' => $page_title,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
|
@ -466,7 +466,7 @@ final class ManiphestTaskEditController extends ManiphestController {
|
|||
|
||||
require_celerity_resource('aphront-error-view-css');
|
||||
|
||||
Javelin::initBehavior('maniphest-project-create', array(
|
||||
Javelin::initBehavior('project-create', array(
|
||||
'tokenizerID' => $project_tokenizer_id,
|
||||
));
|
||||
|
||||
|
|
|
@ -252,23 +252,6 @@ final class PhabricatorSearchEngineMySQL extends PhabricatorSearchEngine {
|
|||
'repository',
|
||||
PhabricatorSearchRelationship::RELATIONSHIP_REPOSITORY);
|
||||
|
||||
/*
|
||||
$join[] = $this->joinRelationship(
|
||||
$conn_r,
|
||||
$query,
|
||||
'reviewer',
|
||||
AdjutantRelationship::RELATIONSHIP_REVIEWER);
|
||||
$join[] = $this->joinRelationship(
|
||||
$conn_r,
|
||||
$query,
|
||||
'subscriber',
|
||||
AdjutantRelationship::RELATIONSHIP_SUBSCRIBER);
|
||||
$join[] = $this->joinRelationship(
|
||||
$conn_r,
|
||||
$query,
|
||||
'repository',
|
||||
AdjutantRelationship::RELATIONSHIP_REPOSITORY);
|
||||
*/
|
||||
$join = array_filter($join);
|
||||
|
||||
foreach ($join as $key => $clause) {
|
||||
|
@ -288,7 +271,7 @@ final class PhabricatorSearchEngineMySQL extends PhabricatorSearchEngine {
|
|||
$hits = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT
|
||||
document.phid
|
||||
document.phid
|
||||
FROM %T document
|
||||
%Q
|
||||
%Q
|
||||
|
|
|
@ -60,6 +60,20 @@ final class PhabricatorSearchCommitIndexer
|
|||
$date_created);
|
||||
}
|
||||
|
||||
$project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
|
||||
$commit->getPHID(),
|
||||
PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT
|
||||
);
|
||||
if ($project_phids) {
|
||||
foreach ($project_phids as $project_phid) {
|
||||
$doc->addRelationship(
|
||||
PhabricatorSearchRelationship::RELATIONSHIP_PROJECT,
|
||||
$project_phid,
|
||||
PhabricatorPHIDConstants::PHID_TYPE_PROJ,
|
||||
$date_created);
|
||||
}
|
||||
}
|
||||
|
||||
$doc->addRelationship(
|
||||
PhabricatorSearchRelationship::RELATIONSHIP_REPOSITORY,
|
||||
$repository->getPHID(),
|
||||
|
|
|
@ -41,6 +41,9 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
|
|||
const TYPE_PROJ_MEMBER = 13;
|
||||
const TYPE_MEMBER_OF_PROJ = 14;
|
||||
|
||||
const TYPE_COMMIT_HAS_PROJECT = 15;
|
||||
const TYPE_PROJECT_HAS_COMMIT = 16;
|
||||
|
||||
const TYPE_TEST_NO_CYCLE = 9000;
|
||||
|
||||
public static function getInverse($edge_type) {
|
||||
|
@ -64,6 +67,10 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
|
|||
|
||||
self::TYPE_PROJ_MEMBER => self::TYPE_MEMBER_OF_PROJ,
|
||||
self::TYPE_MEMBER_OF_PROJ => self::TYPE_PROJ_MEMBER,
|
||||
|
||||
self::TYPE_COMMIT_HAS_PROJECT => self::TYPE_PROJECT_HAS_COMMIT,
|
||||
self::TYPE_PROJECT_HAS_COMMIT => self::TYPE_COMMIT_HAS_PROJECT,
|
||||
|
||||
);
|
||||
|
||||
return idx($map, $edge_type);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/**
|
||||
* @provides javelin-behavior-maniphest-project-create
|
||||
* @provides javelin-behavior-project-create
|
||||
* @requires javelin-behavior
|
||||
* javelin-dom
|
||||
* javelin-stratcom
|
||||
* javelin-workflow
|
||||
*/
|
||||
|
||||
JX.behavior('maniphest-project-create', function(config) {
|
||||
JX.behavior('project-create', function(config) {
|
||||
|
||||
JX.Stratcom.listen(
|
||||
'click',
|
Loading…
Reference in a new issue