mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-26 07:20:57 +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:
parent
f981d50f5d
commit
637e3f38f3
9 changed files with 110 additions and 2 deletions
|
@ -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();
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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'));
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -17,6 +17,7 @@ final class PhabricatorRepositorySearchEngine
|
|||
|
||||
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
||||
$query = id(new PhabricatorRepositoryQuery())
|
||||
->needProjectPHIDs(true)
|
||||
->needCommitCounts(true)
|
||||
->needMostRecentCommits(true);
|
||||
|
||||
|
|
|
@ -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 )------------------------------------------- */
|
||||
|
||||
|
|
|
@ -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.';
|
||||
|
||||
|
|
Loading…
Reference in a new issue