Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15283506
D19429.id46505.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
33 KB
Referenced Files
None
Subscribers
None
D19429.id46505.diff
View Options
diff --git a/resources/sql/autopatches/20180430.repo_identity.sql b/resources/sql/autopatches/20180430.repo_identity.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180430.repo_identity.sql
@@ -0,0 +1,14 @@
+CREATE TABLE {$NAMESPACE}_repository.repository_identity (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ automaticGuessedUserPHID VARBINARY(64) DEFAULT NULL,
+ manuallySetUserPHID VARBINARY(64) DEFAULT NULL,
+ currentEffectiveUserPHID VARBINARY(64) DEFAULT NULL,
+ identityNameHash BINARY(12) NOT NULL,
+ identityNameRaw LONGBLOB NOT NULL,
+ identityNameEncoding VARCHAR(16) DEFAULT NULL COLLATE {$COLLATE_TEXT},
+ UNIQUE KEY `key_phid` (phid),
+ UNIQUE KEY `key_identity` (identityNameHash)
+) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20180504.repo_identity.author.sql b/resources/sql/autopatches/20180504.repo_identity.author.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180504.repo_identity.author.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_repository.repository_identity
+ ADD COLUMN authorPHID VARBINARY(64) NOT NULL;
diff --git a/resources/sql/autopatches/20180504.repo_identity.xaction.sql b/resources/sql/autopatches/20180504.repo_identity.xaction.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180504.repo_identity.xaction.sql
@@ -0,0 +1,19 @@
+CREATE TABLE {$NAMESPACE}_repository.repository_identitytransaction (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ authorPHID VARBINARY(64) NOT NULL,
+ objectPHID VARBINARY(64) NOT NULL,
+ viewPolicy VARBINARY(64) NOT NULL,
+ editPolicy VARBINARY(64) NOT NULL,
+ commentPHID VARBINARY(64) DEFAULT NULL,
+ commentVersion INT UNSIGNED NOT NULL,
+ transactionType VARCHAR(32) NOT NULL,
+ oldValue LONGTEXT NOT NULL,
+ newValue LONGTEXT NOT NULL,
+ contentSource LONGTEXT NOT NULL,
+ metadata LONGTEXT NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ UNIQUE KEY `key_phid` (`phid`),
+ KEY `key_object` (`objectPHID`)
+) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE {$COLLATE_TEXT};
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -814,6 +814,9 @@
'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php',
'DiffusionHistoryView' => 'applications/diffusion/view/DiffusionHistoryView.php',
'DiffusionHovercardEngineExtension' => 'applications/diffusion/engineextension/DiffusionHovercardEngineExtension.php',
+ 'DiffusionIdentityEditController' => 'applications/diffusion/controller/DiffusionIdentityEditController.php',
+ 'DiffusionIdentityListController' => 'applications/diffusion/controller/DiffusionIdentityListController.php',
+ 'DiffusionIdentityViewController' => 'applications/diffusion/controller/DiffusionIdentityViewController.php',
'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php',
'DiffusionInlineCommentPreviewController' => 'applications/diffusion/controller/DiffusionInlineCommentPreviewController.php',
'DiffusionInternalGitRawDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionInternalGitRawDiffQueryConduitAPIMethod.php',
@@ -935,6 +938,8 @@
'DiffusionRepositoryEditUpdateController' => 'applications/diffusion/controller/DiffusionRepositoryEditUpdateController.php',
'DiffusionRepositoryFunctionDatasource' => 'applications/diffusion/typeahead/DiffusionRepositoryFunctionDatasource.php',
'DiffusionRepositoryHistoryManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php',
+ 'DiffusionRepositoryIdentityEditor' => 'applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php',
+ 'DiffusionRepositoryIdentitySearchEngine' => 'applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php',
'DiffusionRepositoryListController' => 'applications/diffusion/controller/DiffusionRepositoryListController.php',
'DiffusionRepositoryManageController' => 'applications/diffusion/controller/DiffusionRepositoryManageController.php',
'DiffusionRepositoryManagePanelsController' => 'applications/diffusion/controller/DiffusionRepositoryManagePanelsController.php',
@@ -4078,6 +4083,15 @@
'PhabricatorRepositoryGitLFSRefQuery' => 'applications/repository/query/PhabricatorRepositoryGitLFSRefQuery.php',
'PhabricatorRepositoryGraphCache' => 'applications/repository/graphcache/PhabricatorRepositoryGraphCache.php',
'PhabricatorRepositoryGraphStream' => 'applications/repository/daemon/PhabricatorRepositoryGraphStream.php',
+ 'PhabricatorRepositoryIdentity' => 'applications/repository/storage/PhabricatorRepositoryIdentity.php',
+ 'PhabricatorRepositoryIdentityAssignTransaction' => 'applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php',
+ 'PhabricatorRepositoryIdentityEditEngine' => 'applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php',
+ 'PhabricatorRepositoryIdentityFerretEngine' => 'applications/repository/search/PhabricatorRepositoryIdentityFerretEngine.php',
+ 'PhabricatorRepositoryIdentityPHIDType' => 'applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php',
+ 'PhabricatorRepositoryIdentityQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityQuery.php',
+ 'PhabricatorRepositoryIdentityTransaction' => 'applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php',
+ 'PhabricatorRepositoryIdentityTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php',
+ 'PhabricatorRepositoryIdentityTransactionType' => 'applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php',
'PhabricatorRepositoryManagementCacheWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementCacheWorkflow.php',
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementClusterizeWorkflow.php',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php',
@@ -6144,6 +6158,9 @@
'DiffusionHistoryTableView' => 'DiffusionHistoryView',
'DiffusionHistoryView' => 'DiffusionView',
'DiffusionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension',
+ 'DiffusionIdentityEditController' => 'DiffusionController',
+ 'DiffusionIdentityListController' => 'DiffusionController',
+ 'DiffusionIdentityViewController' => 'DiffusionController',
'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController',
'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController',
'DiffusionInternalGitRawDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
@@ -6264,6 +6281,8 @@
'DiffusionRepositoryEditUpdateController' => 'DiffusionRepositoryManageController',
'DiffusionRepositoryFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'DiffusionRepositoryHistoryManagementPanel' => 'DiffusionRepositoryManagementPanel',
+ 'DiffusionRepositoryIdentityEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'DiffusionRepositoryIdentitySearchEngine' => 'PhabricatorApplicationSearchEngine',
'DiffusionRepositoryListController' => 'DiffusionController',
'DiffusionRepositoryManageController' => 'DiffusionController',
'DiffusionRepositoryManagePanelsController' => 'DiffusionRepositoryManageController',
@@ -9961,6 +9980,19 @@
'PhabricatorRepositoryGitLFSRefQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorRepositoryGraphCache' => 'Phobject',
'PhabricatorRepositoryGraphStream' => 'Phobject',
+ 'PhabricatorRepositoryIdentity' => array(
+ 'PhabricatorRepositoryDAO',
+ 'PhabricatorPolicyInterface',
+ 'PhabricatorApplicationTransactionInterface',
+ ),
+ 'PhabricatorRepositoryIdentityAssignTransaction' => 'PhabricatorRepositoryIdentityTransactionType',
+ 'PhabricatorRepositoryIdentityEditEngine' => 'PhabricatorEditEngine',
+ 'PhabricatorRepositoryIdentityFerretEngine' => 'PhabricatorFerretEngine',
+ 'PhabricatorRepositoryIdentityPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorRepositoryIdentityQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhabricatorRepositoryIdentityTransaction' => 'PhabricatorModularTransaction',
+ 'PhabricatorRepositoryIdentityTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
+ 'PhabricatorRepositoryIdentityTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
diff --git a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php
--- a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php
+++ b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php
@@ -124,6 +124,15 @@
'(?P<repositoryCallsign>[A-Z]+)' => $repository_routes,
'(?P<repositoryID>[1-9]\d*)' => $repository_routes,
+ 'identity/' => array(
+ $this->getQueryRoutePattern() =>
+ 'DiffusionIdentityListController',
+ $this->getEditRoutePattern('edit/') =>
+ 'DiffusionIdentityEditController',
+ 'view/(?P<id>[^/]+)/' =>
+ 'DiffusionIdentityViewController',
+ ),
+
'inline/' => array(
'edit/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController',
'preview/(?P<phid>[^/]+)/'
diff --git a/src/applications/diffusion/controller/DiffusionIdentityEditController.php b/src/applications/diffusion/controller/DiffusionIdentityEditController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/controller/DiffusionIdentityEditController.php
@@ -0,0 +1,12 @@
+<?php
+
+final class DiffusionIdentityEditController
+ extends DiffusionController {
+
+ public function handleRequest(AphrontRequest $request) {
+ return id(new PhabricatorRepositoryIdentityEditEngine())
+ ->setController($this)
+ ->buildResponse();
+ }
+
+}
diff --git a/src/applications/diffusion/controller/DiffusionIdentityListController.php b/src/applications/diffusion/controller/DiffusionIdentityListController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/controller/DiffusionIdentityListController.php
@@ -0,0 +1,22 @@
+<?php
+
+final class DiffusionIdentityListController
+ extends DiffusionController {
+
+ public function handleRequest(AphrontRequest $request) {
+ return id(new DiffusionRepositoryIdentitySearchEngine())
+ ->setController($this)
+ ->buildResponse();
+ }
+
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ id(new PhabricatorRepositoryIdentityEditEngine())
+ ->setViewer($this->getViewer())
+ ->addActionToCrumbs($crumbs);
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/applications/diffusion/controller/DiffusionIdentityViewController.php b/src/applications/diffusion/controller/DiffusionIdentityViewController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/controller/DiffusionIdentityViewController.php
@@ -0,0 +1,123 @@
+<?php
+
+final class DiffusionIdentityViewController
+ extends DiffusionController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+
+ $id = $request->getURIData('id');
+ $identity = id(new PhabricatorRepositoryIdentityQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($id))
+ ->executeOne();
+ if (!$identity) {
+ return new Aphront404Response();
+ }
+
+ $title = pht('Identity %d', $identity->getID());
+
+ $curtain = $this->buildCurtain($identity);
+
+ $header = id(new PHUIHeaderView())
+ ->setUser($viewer)
+ ->setHeader($identity->getIdentityShortName())
+ ->setHeaderIcon('fa-globe')
+ ->setPolicyObject($identity);
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb($identity->getID());
+ $crumbs->setBorder(true);
+
+ $timeline = $this->buildTransactionTimeline(
+ $identity,
+ new PhabricatorRepositoryIdentityTransactionQuery());
+ $timeline->setShouldTerminate(true);
+
+ $properties = $this->buildPropertyList($identity);
+
+ $view = id(new PHUITwoColumnView())
+ ->setHeader($header)
+ ->setCurtain($curtain)
+ ->setMainColumn(array(
+ $properties,
+ $timeline,
+ ));
+
+ return $this->newPage()
+ ->setTitle($title)
+ ->setCrumbs($crumbs)
+ ->appendChild(
+ array(
+ $view,
+ ));
+ }
+
+ private function buildCurtain(PhabricatorRepositoryIdentity $identity) {
+ $viewer = $this->getViewer();
+
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $identity,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
+ $id = $identity->getID();
+ $edit_uri = $this->getApplicationURI("identity/edit/{$id}/");
+
+ $curtain = $this->newCurtainView($identity);
+
+ $curtain->addAction(
+ id(new PhabricatorActionView())
+ ->setIcon('fa-pencil')
+ ->setName(pht('Edit Identity'))
+ ->setHref($edit_uri)
+ ->setWorkflow(!$can_edit)
+ ->setDisabled(!$can_edit));
+
+ return $curtain;
+ }
+
+ private function buildPropertyList(
+ PhabricatorRepositoryIdentity $identity) {
+
+ $viewer = $this->getViewer();
+
+ $properties = id(new PHUIPropertyListView())
+ ->setUser($viewer);
+
+ $effective_phid = $identity->getCurrentEffectiveUserPHID();
+ $automatic_phid = $identity->getAutomaticGuessedUserPHID();
+ $manual_phid = $identity->getManuallySetUserPHID();
+
+ if ($effective_phid) {
+ $tag = id(new PHUITagView())
+ ->setType(PHUITagView::TYPE_SHADE)
+ ->setColor('green')
+ ->setIcon('fa-check')
+ ->setName('Assigned');
+ } else {
+ $tag = id(new PHUITagView())
+ ->setType(PHUITagView::TYPE_SHADE)
+ ->setColor('indigo')
+ ->setIcon('fa-bomb')
+ ->setName('Unassigned');
+ }
+ $properties->addProperty(
+ pht('Effective User'),
+ $viewer->renderHandle($effective_phid));
+ $properties->addProperty(
+ pht('Automatically Detected User'),
+ $viewer->renderHandle($automatic_phid));
+ $properties->addProperty(
+ pht('Manually Set User'),
+ $viewer->renderHandle($manual_phid));
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader(array(pht('Identity Assignments'), $tag));
+
+ return id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
+ ->addPropertyList($properties);
+ }
+}
diff --git a/src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php b/src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php
@@ -0,0 +1,26 @@
+<?php
+
+final class DiffusionRepositoryIdentityEditor
+ extends PhabricatorApplicationTransactionEditor {
+
+ public function getEditorObjectsDescription() {
+ return pht('Repository Identity');
+ }
+
+ public function getCreateObjectTitle($author, $object) {
+ return pht('%s created this identity.', $author);
+ }
+
+ public function getCreateObjectTitleForFeed($author, $object) {
+ return pht('%s created %s.', $author, $object);
+ }
+
+ protected function supportsSearch() {
+ return true;
+ }
+
+ public function getEditorApplicationClass() {
+ return 'PhabricatorDiffusionApplication';
+ }
+
+}
diff --git a/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php b/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php
@@ -0,0 +1,92 @@
+<?php
+
+final class DiffusionRepositoryIdentitySearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ public function getResultTypeDescription() {
+ return pht('Repository Identities');
+ }
+
+ public function getApplicationClassName() {
+ return 'PhabricatorDiffusionApplication';
+ }
+
+ public function newQuery() {
+ return new PhabricatorRepositoryIdentityQuery();
+ }
+
+ protected function buildCustomSearchFields() {
+ return array(
+ id(new PhabricatorSearchThreeStateField())
+ ->setLabel(pht('Is Assigned'))
+ ->setKey('hasEffectivePHID')
+ ->setOptions(
+ pht('(Show All)'),
+ pht('Show Only Assigned Identities'),
+ pht('Show Only Unassigned Identities')),
+ );
+ }
+
+ protected function buildQueryFromParameters(array $map) {
+ $query = $this->newQuery();
+
+ if ($map['hasEffectivePHID'] !== null) {
+ $query->withHasEffectivePHID($map['hasEffectivePHID']);
+ }
+
+ return $query;
+ }
+
+ protected function getURI($path) {
+ return '/diffusion/identity/'.$path;
+ }
+
+ protected function getBuiltinQueryNames() {
+ $names = array(
+ 'all' => pht('All Identities'),
+ );
+
+ return $names;
+ }
+
+ public function buildSavedQueryFromBuiltin($query_key) {
+
+ $query = $this->newSavedQuery();
+ $query->setQueryKey($query_key);
+
+ switch ($query_key) {
+ case 'all':
+ return $query;
+ }
+
+ return parent::buildSavedQueryFromBuiltin($query_key);
+ }
+
+ protected function renderResultList(
+ array $identities,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+ assert_instances_of($identities, 'PhabricatorRepositoryIdentity');
+
+ $viewer = $this->requireViewer();
+
+ $list = new PHUIObjectItemListView();
+ $list->setUser($viewer);
+ foreach ($identities as $identity) {
+ $item = id(new PHUIObjectItemView())
+ ->setObjectName(pht('Identity %d', $identity->getID()))
+ ->setHeader($identity->getIdentityShortName())
+ ->setHref($identity->getURI())
+ ->setObject($identity);
+
+ $list->addItem($item);
+ }
+
+ $result = new PhabricatorApplicationSearchResultView();
+ $result->setObjectList($list);
+ $result->setNoDataString(pht('No Identities found.'));
+
+ return $result;
+ }
+
+}
diff --git a/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php b/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php
@@ -0,0 +1,91 @@
+<?php
+
+final class PhabricatorRepositoryIdentityEditEngine
+ extends PhabricatorEditEngine {
+
+ const ENGINECONST = 'repository.identity';
+
+ public function isEngineConfigurable() {
+ return false;
+ }
+
+ public function getEngineName() {
+ return pht('Repository Identities');
+ }
+
+ public function getSummaryHeader() {
+ return pht('Edit Repository Identity Configurations');
+ }
+
+ public function getSummaryText() {
+ return pht('This engine is used to edit Repository identities.');
+ }
+
+ public function getEngineApplicationClass() {
+ return 'PhabricatorDiffusionApplication';
+ }
+
+ protected function newEditableObject() {
+ return new PhabricatorRepositoryIdentity();
+ }
+
+ protected function newObjectQuery() {
+ return new PhabricatorRepositoryIdentityQuery();
+ }
+
+ protected function getObjectCreateTitleText($object) {
+ return pht('Create Identity');
+ }
+
+ protected function getObjectCreateButtonText($object) {
+ return pht('Create Identity');
+ }
+
+ protected function getObjectEditTitleText($object) {
+ return pht('Edit Identity: %s', $object->getIdentityShortName());
+ }
+
+ protected function getObjectEditShortText($object) {
+ return pht('Edit Identity');
+ }
+
+ protected function getObjectCreateShortText() {
+ return pht('Create Identity');
+ }
+
+ protected function getObjectName() {
+ return pht('Identity');
+ }
+
+ protected function getEditorURI() {
+ return '/diffusion/identity/edit/';
+ }
+
+ protected function getObjectCreateCancelURI($object) {
+ return '/diffusion/identity/';
+ }
+
+ protected function getObjectViewURI($object) {
+ return $object->getURI();
+ }
+
+ protected function getCreateNewObjectPolicy() {
+ return PhabricatorPolicies::POLICY_USER;
+ }
+
+ protected function buildCustomEditFields($object) {
+ return array(
+ id(new PhabricatorUsersEditField())
+ ->setKey('manuallySetUserPHID')
+ ->setLabel(pht('Assigned To'))
+ ->setDescription(pht('Override this identity\'s assignment.'))
+ ->setTransactionType(
+ PhabricatorRepositoryIdentityAssignTransaction::TRANSACTIONTYPE)
+ ->setIsCopyable(true)
+ ->setIsNullable(true)
+ ->setSingleValue($object->getManuallySetUserPHID()),
+
+ );
+ }
+
+}
diff --git a/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php
@@ -0,0 +1,33 @@
+<?php
+
+final class PhabricatorRepositoryIdentityPHIDType
+ extends PhabricatorPHIDType {
+
+ const TYPECONST = 'RIDT';
+
+ public function getTypeName() {
+ return pht('Repository Identity');
+ }
+
+ public function newObject() {
+ return new PhabricatorRepositoryIdentity();
+ }
+
+ public function getPHIDTypeApplicationClass() {
+ return 'PhabricatorDiffusionApplication';
+ }
+
+ protected function buildQueryForObjects(
+ PhabricatorObjectQuery $query,
+ array $phids) {
+
+ return id(new PhabricatorRepositoryIdentityQuery())
+ ->withPHIDs($phids);
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {}
+
+}
diff --git a/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php b/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
@@ -0,0 +1,92 @@
+<?php
+
+final class PhabricatorRepositoryIdentityQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+ private $identityNames;
+ private $hasEffectivePHID;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withIdentityNames(array $names) {
+ $this->identityNames = $names;
+ return $this;
+ }
+
+ public function withHasEffectivePHID($has_effective_phid) {
+ $this->hasEffectivePHID = $has_effective_phid;
+ return $this;
+ }
+
+ public function newResultObject() {
+ return new PhabricatorRepositoryIdentity();
+ }
+
+ protected function getPrimaryTableAlias() {
+ return 'repository_identity';
+ }
+
+ protected function loadPage() {
+ return $this->loadStandardPage($this->newResultObject());
+ }
+
+ protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
+ $where = parent::buildWhereClauseParts($conn);
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'repository_identity.id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'repository_identity.phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->hasEffectivePHID !== null) {
+
+ if ($this->hasEffectivePHID) {
+ $where[] = qsprintf(
+ $conn,
+ 'repository_identity.currentEffectiveUserPHID IS NOT NULL');
+ } else {
+ $where[] = qsprintf(
+ $conn,
+ 'repository_identity.currentEffectiveUserPHID IS NULL');
+ }
+ }
+
+ if ($this->identityNames !== null) {
+ $name_hashes = array();
+ foreach ($this->identityNames as $name) {
+ $name_hashes[] = PhabricatorHash::digestForIndex($name);
+ }
+
+ $where[] = qsprintf(
+ $conn,
+ 'repository_identity.identityNameHash IN (%Ls)',
+ $name_hashes);
+ }
+
+ return $where;
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorDiffusionApplication';
+ }
+
+}
diff --git a/src/applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php b/src/applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorRepositoryIdentityTransactionQuery
+ extends PhabricatorApplicationTransactionQuery {
+
+ public function getTemplateApplicationTransaction() {
+ return new PhabricatorRepositoryIdentityTransaction();
+ }
+
+}
diff --git a/src/applications/repository/search/PhabricatorRepositoryIdentityFerretEngine.php b/src/applications/repository/search/PhabricatorRepositoryIdentityFerretEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/search/PhabricatorRepositoryIdentityFerretEngine.php
@@ -0,0 +1,18 @@
+<?php
+
+final class PhabricatorRepositoryIdentityFerretEngine
+ extends PhabricatorFerretEngine {
+
+ public function getApplicationName() {
+ return 'repository';
+ }
+
+ public function getScopeName() {
+ return 'identity';
+ }
+
+ public function newSearchEngine() {
+ return new DiffusionRepositoryIdentitySearchEngine();
+ }
+
+}
diff --git a/src/applications/repository/storage/PhabricatorRepositoryIdentity.php b/src/applications/repository/storage/PhabricatorRepositoryIdentity.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/storage/PhabricatorRepositoryIdentity.php
@@ -0,0 +1,118 @@
+<?php
+
+final class PhabricatorRepositoryIdentity
+ extends PhabricatorRepositoryDAO
+ implements
+ PhabricatorPolicyInterface,
+ PhabricatorApplicationTransactionInterface {
+
+ protected $authorPHID;
+ protected $identityNameHash;
+ protected $identityNameRaw;
+ protected $identityNameEncoding;
+ protected $automaticGuessedUserPHID;
+ protected $manuallySetUserPHID;
+ protected $currentEffectiveUserPHID;
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => true,
+ self::CONFIG_BINARY => array(
+ 'identityNameRaw' => true,
+ ),
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'identityNameHash' => 'bytes12',
+ 'identityNameEncoding' => 'text16?',
+ 'automaticGuessedUserPHID' => 'phid?',
+ 'manuallySetUserPHID' => 'phid?',
+ 'currentEffectiveUserPHID' => 'phid?',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_identity' => array(
+ 'columns' => array('identityNameHash'),
+ 'unique' => true,
+ ),
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function getPHIDType() {
+ return PhabricatorRepositoryIdentityPHIDType::TYPECONST;
+ }
+
+ public function setIdentityName($name_raw) {
+ $this->setIdentityNameRaw($name_raw);
+ $this->setIdentityNameHash(PhabricatorHash::digestForIndex($name_raw));
+ $this->setIdentityNameEncoding($this->detectEncodingForStorage($name_raw));
+
+ return $this;
+ }
+
+ public function getIdentityName() {
+ return $this->getUTF8StringFromStorage(
+ $this->getIdentityNameRaw(),
+ $this->getIdentityNameEncoding());
+ }
+
+ public function getIdentityShortName() {
+ // TODO
+ return $this->getIdentityName();
+ }
+
+ public function getURI() {
+ return '/diffusion/identity/view/'.$this->getID().'/';
+ }
+
+ public function save() {
+ if ($this->manuallySetUserPHID) {
+ $this->currentEffectiveUserPHID = $this->manuallySetUserPHID;
+ } else {
+ $this->currentEffectiveUserPHID = $this->automaticGuessedUserPHID;
+ }
+
+ return parent::save();
+ }
+
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ );
+ }
+
+ public function getPolicy($capability) {
+ return PhabricatorPolicies::getMostOpenPolicy();
+ }
+
+ public function hasAutomaticCapability(
+ $capability, PhabricatorUser $viewer) {
+ return false;
+ }
+
+
+/* -( PhabricatorApplicationTransactionInterface )------------------------- */
+
+
+ public function getApplicationTransactionEditor() {
+ return new DiffusionRepositoryIdentityEditor();
+ }
+
+ public function getApplicationTransactionObject() {
+ return $this;
+ }
+
+ public function getApplicationTransactionTemplate() {
+ return new PhabricatorRepositoryIdentityTransaction();
+ }
+
+ public function willRenderTimeline(
+ PhabricatorApplicationTransactionView $timeline,
+ AphrontRequest $request) {
+
+ return $timeline;
+ }
+
+}
diff --git a/src/applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php b/src/applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php
@@ -0,0 +1,18 @@
+<?php
+
+final class PhabricatorRepositoryIdentityTransaction
+ extends PhabricatorModularTransaction {
+
+ public function getApplicationTransactionType() {
+ return PhabricatorRepositoryIdentityPHIDType::TYPECONST;
+ }
+
+ public function getBaseTransactionClass() {
+ return 'PhabricatorRepositoryIdentityTransactionType';
+ }
+
+ public function getApplicationName() {
+ return 'repository';
+ }
+
+}
diff --git a/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php b/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
--- a/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
+++ b/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
@@ -66,6 +66,34 @@
$committer = $ref->getCommitter();
$hashes = $ref->getHashes();
+ $author_identity = id(new PhabricatorRepositoryIdentityQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withIdentityNames(array($author))
+ ->executeOne();
+
+ if (!$author_identity) {
+ $author_identity = id(new PhabricatorRepositoryIdentity())
+ ->setAuthorPHID($commit->getPHID())
+ ->setIdentityName($author)
+ ->setAutomaticGuessedUserPHID(
+ $this->resolveUserPHID($commit, $author))
+ ->save();
+ }
+
+ $committer_identity = id(new PhabricatorRepositoryIdentityQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withIdentityNames(array($committer))
+ ->executeOne();
+
+ if (!$committer_identity) {
+ $committer_identity = id(new PhabricatorRepositoryIdentity())
+ ->setAuthorPHID($commit->getPHID())
+ ->setIdentityName($committer)
+ ->setAutomaticGuessedUserPHID(
+ $this->resolveUserPHID($commit, $committer))
+ ->save();
+ }
+
$data = id(new PhabricatorRepositoryCommitData())->loadOneWhere(
'commitID = %d',
$commit->getID());
diff --git a/src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php b/src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php
@@ -0,0 +1,67 @@
+<?php
+
+final class PhabricatorRepositoryIdentityAssignTransaction
+ extends PhabricatorRepositoryIdentityTransactionType {
+
+ const TRANSACTIONTYPE = 'repository:identity:assign';
+
+ public function generateOldValue($object) {
+ return nonempty($object->getManuallySetUserPHID(), null);
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setManuallySetUserPHID($value);
+ }
+
+ public function getTitle() {
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ if (!$old) {
+ return pht(
+ '%s assigned this identity to %s.',
+ $this->renderAuthor(),
+ $this->renderHandle($new));
+ } else if (!$new) {
+ return pht(
+ '%s removed %s as the assignee of this identity.',
+ $this->renderAuthor(),
+ $this->renderHandle($old));
+ } else {
+ return pht(
+ '%s changed the assigned user for this identity from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderHandle($old),
+ $this->renderHandle($new));
+ }
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ foreach ($xactions as $xaction) {
+ $old = $xaction->getOldValue();
+ $new = $xaction->getNewValue();
+ if (!strlen($new)) {
+ continue;
+ }
+
+ if ($new === $old) {
+ continue;
+ }
+
+ $assignee_list = id(new PhabricatorPeopleQuery())
+ ->setViewer($this->getActor())
+ ->withPHIDs(array($new))
+ ->execute();
+
+ if (!$assignee_list) {
+ $errors[] = $this->newInvalidError(
+ pht('User "%s" is not a valid user.',
+ $new));
+ }
+ }
+ return $errors;
+ }
+
+}
diff --git a/src/applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php b/src/applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php
@@ -0,0 +1,4 @@
+<?php
+
+abstract class PhabricatorRepositoryIdentityTransactionType
+ extends PhabricatorModularTransactionType {}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Mar 5, 7:38 AM (2 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7223975
Default Alt Text
D19429.id46505.diff (33 KB)
Attached To
Mode
D19429: Add controllers/search/edit engine functionality to RepositoryIdentity
Attached
Detach File
Event Timeline
Log In to Comment