1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-29 10:12:41 +01:00

Allow repositories to be associated with projects

Summary: Ref T4264. Ref T2628. Ref T3102. Allows you to associate repositories with projects. In the future, you'll be able to write Herald object rules against projects, use Herald fields like "Repository's projects", and search by project.

Test Plan: See screenshots.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T3102, T4264, T2628

Differential Revision: https://secure.phabricator.com/D7881
This commit is contained in:
epriestley 2014-01-03 12:24:09 -08:00
parent f981d50f5d
commit 637e3f38f3
9 changed files with 110 additions and 2 deletions

View file

@ -165,6 +165,16 @@ final class DiffusionRepositoryController extends DiffusionController {
->setUser($user);
$view->addProperty(pht('Callsign'), $repository->getCallsign());
$project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$repository->getPHID(),
PhabricatorEdgeConfig::TYPE_OBJECT_HAS_PROJECT);
if ($project_phids) {
$this->loadHandles($project_phids);
$view->addProperty(
pht('Projects'),
$this->renderHandlesForPHIDs($project_phids));
}
if ($repository->isHosted()) {
$serve_off = PhabricatorRepository::SERVE_OFF;
$callsign = $repository->getCallsign();

View file

@ -16,6 +16,7 @@ final class DiffusionRepositoryEditBasicController
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->needProjectPHIDs(true)
->withIDs(array($repository->getID()))
->executeOne();
@ -33,6 +34,7 @@ final class DiffusionRepositoryEditBasicController
if ($request->isFormPost()) {
$v_name = $request->getStr('name');
$v_desc = $request->getStr('description');
$v_projects = $request->getArr('projectPHIDs');
if (!strlen($v_name)) {
$e_name = pht('Required');
@ -47,6 +49,7 @@ final class DiffusionRepositoryEditBasicController
$type_name = PhabricatorRepositoryTransaction::TYPE_NAME;
$type_desc = PhabricatorRepositoryTransaction::TYPE_DESCRIPTION;
$type_edge = PhabricatorTransactions::TYPE_EDGE;
$xactions[] = id(clone $template)
->setTransactionType($type_name)
@ -56,6 +59,16 @@ final class DiffusionRepositoryEditBasicController
->setTransactionType($type_desc)
->setNewValue($v_desc);
$xactions[] = id(clone $template)
->setTransactionType($type_edge)
->setMetadataValue(
'edge:type',
PhabricatorEdgeConfig::TYPE_OBJECT_HAS_PROJECT)
->setNewValue(
array(
'=' => array_fuse($v_projects),
));
id(new PhabricatorRepositoryEditor())
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
@ -78,6 +91,8 @@ final class DiffusionRepositoryEditBasicController
->setErrors($errors);
}
$project_handles = $this->loadViewerHandles($repository->getProjectPHIDs());
$form = id(new AphrontFormView())
->setUser($user)
->appendChild(
@ -91,6 +106,12 @@ final class DiffusionRepositoryEditBasicController
->setName('description')
->setLabel(pht('Description'))
->setValue($v_desc))
->appendChild(
id(new AphrontFormTokenizerControl())
->setDatasource('/typeahead/common/projects/')
->setName('projectPHIDs')
->setLabel(pht('Projects'))
->setValue($project_handles))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Save'))

View file

@ -253,6 +253,16 @@ final class DiffusionRepositoryEditMainController
$view->addProperty(pht('Type'), $type);
$view->addProperty(pht('Callsign'), $repository->getCallsign());
$project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$repository->getPHID(),
PhabricatorEdgeConfig::TYPE_OBJECT_HAS_PROJECT);
if ($project_phids) {
$this->loadHandles($project_phids);
$view->addProperty(
pht('Projects'),
$this->renderHandlesForPHIDs($project_phids));
}
$view->addProperty(
pht('Status'),
$this->buildRepositoryStatus($repository));

View file

@ -30,6 +30,11 @@ final class DiffusionRepositoryListController extends DiffusionController
$viewer = $this->getRequest()->getUser();
$project_phids = array_fuse(
array_mergev(
mpull($repositories, 'getProjectPHIDs')));
$project_handles = $this->loadViewerHandles($project_phids);
$list = new PHUIObjectItemListView();
foreach ($repositories as $repository) {
$id = $repository->getID();
@ -49,7 +54,8 @@ final class DiffusionRepositoryListController extends DiffusionController
$item->setEpoch($commit->getEpoch());
}
$item->addAttribute(
$item->addIcon(
'none',
PhabricatorRepositoryType::getNameForRepositoryType(
$repository->getVersionControlSystem()));
@ -72,6 +78,15 @@ final class DiffusionRepositoryListController extends DiffusionController
$item->addAttribute(pht('No Commits'));
}
$handles = array_select_keys(
$project_handles,
$repository->getProjectPHIDs());
if ($handles) {
$item->addAttribute(
id(new ManiphestTaskProjectsView())
->setHandles($handles));
}
if (!$repository->isTracked()) {
$item->setDisabled(true);
$item->addIcon('disable-grey', pht('Inactive'));

View file

@ -32,6 +32,7 @@ final class PhabricatorRepositoryEditor
$types[] = PhabricatorRepositoryTransaction::TYPE_CREDENTIAL;
$types[] = PhabricatorRepositoryTransaction::TYPE_DANGEROUS;
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;

View file

@ -23,6 +23,7 @@ final class PhabricatorRepositoryQuery
private $needMostRecentCommits;
private $needCommitCounts;
private $needProjectPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
@ -69,6 +70,11 @@ final class PhabricatorRepositoryQuery
return $this;
}
public function needProjectPHIDs($need_phids) {
$this->needProjectPHIDs = $need_phids;
return $this;
}
public function setOrder($order) {
$this->order = $order;
return $this;
@ -116,7 +122,6 @@ final class PhabricatorRepositoryQuery
}
}
return $repositories;
}
@ -148,6 +153,27 @@ final class PhabricatorRepositoryQuery
return $repositories;
}
public function didFilterPage(array $repositories) {
if ($this->needProjectPHIDs) {
$type_project = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_PROJECT;
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($repositories, 'getPHID'))
->withEdgeTypes(array($type_project));
$edge_query->execute();
foreach ($repositories as $repository) {
$project_phids = $edge_query->getDestinationPHIDs(
array(
$repository->getPHID(),
));
$repository->attachProjectPHIDs($project_phids);
}
}
return $repositories;
}
public function getReversePaging() {
switch ($this->order) {
case self::ORDER_CALLSIGN:

View file

@ -17,6 +17,7 @@ final class PhabricatorRepositorySearchEngine
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorRepositoryQuery())
->needProjectPHIDs(true)
->needCommitCounts(true)
->needMostRecentCommits(true);

View file

@ -43,6 +43,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
private $commitCount = self::ATTACHABLE;
private $mostRecentCommit = self::ATTACHABLE;
private $projectPHIDs = self::ATTACHABLE;
public static function initializeNewRepository(PhabricatorUser $actor) {
$app = id(new PhabricatorApplicationQuery())
@ -193,6 +194,15 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
return $uri;
}
public function attachProjectPHIDs(array $project_phids) {
$this->projectPHIDs = $project_phids;
return $this;
}
public function getProjectPHIDs() {
return $this->assertAttached($this->projectPHIDs);
}
/* -( Remote Command Execution )------------------------------------------- */

View file

@ -63,6 +63,9 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
const TYPE_OBJECT_USES_CREDENTIAL = 39;
const TYPE_CREDENTIAL_USED_BY_OBJECT = 40;
const TYPE_OBJECT_HAS_PROJECT = 41;
const TYPE_PROJECT_HAS_OBJECT = 42;
const TYPE_TEST_NO_CYCLE = 9000;
const TYPE_PHOB_HAS_ASANATASK = 80001;
@ -142,6 +145,9 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
self::TYPE_OBJECT_USES_CREDENTIAL => self::TYPE_CREDENTIAL_USED_BY_OBJECT,
self::TYPE_CREDENTIAL_USED_BY_OBJECT => self::TYPE_OBJECT_USES_CREDENTIAL,
self::TYPE_OBJECT_HAS_PROJECT => self::TYPE_PROJECT_HAS_OBJECT,
self::TYPE_PROJECT_HAS_OBJECT => self::TYPE_OBJECT_HAS_PROJECT,
);
return idx($map, $edge_type);
@ -213,6 +219,7 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
return '%s edited member(s), added %d: %s; removed %d: %s.';
case self::TYPE_MEMBER_OF_PROJ:
case self::TYPE_COMMIT_HAS_PROJECT:
case self::TYPE_OBJECT_HAS_PROJECT:
return '%s edited project(s), added %d: %s; removed %d: %s.';
case self::TYPE_QUESTION_HAS_VOTING_USER:
case self::TYPE_ANSWER_HAS_VOTING_USER:
@ -227,6 +234,7 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
case self::TYPE_UNSUBSCRIBED_FROM_OBJECT:
case self::TYPE_FILE_HAS_OBJECT:
case self::TYPE_CONTRIBUTED_TO_OBJECT:
case self::TYPE_PROJECT_HAS_OBJECT:
return '%s edited object(s), added %d: %s; removed %d: %s.';
case self::TYPE_OBJECT_HAS_UNSUBSCRIBER:
return '%s edited unsubcriber(s), added %d: %s; removed %d: %s.';
@ -287,6 +295,7 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
return '%s added %d member(s): %s.';
case self::TYPE_MEMBER_OF_PROJ:
case self::TYPE_COMMIT_HAS_PROJECT:
case self::TYPE_OBJECT_HAS_PROJECT:
return '%s added %d project(s): %s.';
case self::TYPE_QUESTION_HAS_VOTING_USER:
case self::TYPE_ANSWER_HAS_VOTING_USER:
@ -319,6 +328,7 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
case self::TYPE_UNSUBSCRIBED_FROM_OBJECT:
case self::TYPE_FILE_HAS_OBJECT:
case self::TYPE_CONTRIBUTED_TO_OBJECT:
case self::TYPE_PROJECT_HAS_OBJECT:
default:
return '%s added %d object(s): %s.';
@ -356,6 +366,7 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
return '%s removed %d member(s): %s.';
case self::TYPE_MEMBER_OF_PROJ:
case self::TYPE_COMMIT_HAS_PROJECT:
case self::TYPE_OBJECT_HAS_PROJECT:
return '%s removed %d project(s): %s.';
case self::TYPE_QUESTION_HAS_VOTING_USER:
case self::TYPE_ANSWER_HAS_VOTING_USER:
@ -388,6 +399,7 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
case self::TYPE_UNSUBSCRIBED_FROM_OBJECT:
case self::TYPE_FILE_HAS_OBJECT:
case self::TYPE_CONTRIBUTED_TO_OBJECT:
case self::TYPE_PROJECT_HAS_OBJECT:
default:
return '%s removed %d object(s): %s.';
@ -423,6 +435,7 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
return '%s updated members of %s.';
case self::TYPE_MEMBER_OF_PROJ:
case self::TYPE_COMMIT_HAS_PROJECT:
case self::TYPE_OBJECT_HAS_PROJECT:
return '%s updated projects of %s.';
case self::TYPE_QUESTION_HAS_VOTING_USER:
case self::TYPE_ANSWER_HAS_VOTING_USER:
@ -455,6 +468,7 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
case self::TYPE_UNSUBSCRIBED_FROM_OBJECT:
case self::TYPE_FILE_HAS_OBJECT:
case self::TYPE_CONTRIBUTED_TO_OBJECT:
case self::TYPE_PROJECT_HAS_OBJECT:
default:
return '%s updated objects of %s.';