mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-25 14:08:19 +01:00
(stable) Promote 2018 Week 22
This commit is contained in:
commit
236253df8c
34 changed files with 1242 additions and 15 deletions
|
@ -9,8 +9,8 @@ return array(
|
|||
'names' => array(
|
||||
'conpherence.pkg.css' => 'e68cf1fa',
|
||||
'conpherence.pkg.js' => '15191c65',
|
||||
'core.pkg.css' => '8be474cc',
|
||||
'core.pkg.js' => 'e452721e',
|
||||
'core.pkg.css' => '8e3d1fb7',
|
||||
'core.pkg.js' => '2058ec09',
|
||||
'differential.pkg.css' => '06dc617c',
|
||||
'differential.pkg.js' => 'c2ca903a',
|
||||
'diffusion.pkg.css' => 'a2d17c7d',
|
||||
|
@ -167,7 +167,7 @@ return array(
|
|||
'rsrc/css/phui/phui-object-box.css' => '9cff003c',
|
||||
'rsrc/css/phui/phui-pager.css' => 'edcbc226',
|
||||
'rsrc/css/phui/phui-pinboard-view.css' => '2495140e',
|
||||
'rsrc/css/phui/phui-property-list-view.css' => 'de4754d8',
|
||||
'rsrc/css/phui/phui-property-list-view.css' => '546a04ae',
|
||||
'rsrc/css/phui/phui-remarkup-preview.css' => '54a34863',
|
||||
'rsrc/css/phui/phui-segment-bar-view.css' => 'b1d1b892',
|
||||
'rsrc/css/phui/phui-spacing.css' => '042804d6',
|
||||
|
@ -259,7 +259,7 @@ return array(
|
|||
'rsrc/externals/javelin/lib/__tests__/URI.js' => '1e45fda9',
|
||||
'rsrc/externals/javelin/lib/__tests__/behavior.js' => '1ea62783',
|
||||
'rsrc/externals/javelin/lib/behavior.js' => '61cbc29a',
|
||||
'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => 'dfaf006b',
|
||||
'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => 'bb6e5c16',
|
||||
'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => '70baed2f',
|
||||
'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => '185bbd53',
|
||||
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '503e17fd',
|
||||
|
@ -710,7 +710,7 @@ return array(
|
|||
'javelin-scrollbar' => '9065f639',
|
||||
'javelin-sound' => '949c0fe5',
|
||||
'javelin-stratcom' => '327f418a',
|
||||
'javelin-tokenizer' => 'dfaf006b',
|
||||
'javelin-tokenizer' => 'bb6e5c16',
|
||||
'javelin-typeahead' => '70baed2f',
|
||||
'javelin-typeahead-composite-source' => '503e17fd',
|
||||
'javelin-typeahead-normalizer' => '185bbd53',
|
||||
|
@ -842,7 +842,7 @@ return array(
|
|||
'phui-oi-simple-ui-css' => 'a8beebea',
|
||||
'phui-pager-css' => 'edcbc226',
|
||||
'phui-pinboard-view-css' => '2495140e',
|
||||
'phui-property-list-view-css' => 'de4754d8',
|
||||
'phui-property-list-view-css' => '546a04ae',
|
||||
'phui-remarkup-preview-css' => '54a34863',
|
||||
'phui-segment-bar-view-css' => 'b1d1b892',
|
||||
'phui-spacing-css' => '042804d6',
|
||||
|
@ -1842,6 +1842,12 @@ return array(
|
|||
'javelin-uri',
|
||||
'phabricator-notification',
|
||||
),
|
||||
'bb6e5c16' => array(
|
||||
'javelin-dom',
|
||||
'javelin-util',
|
||||
'javelin-stratcom',
|
||||
'javelin-install',
|
||||
),
|
||||
'bcaccd64' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-behavior-device',
|
||||
|
@ -2019,12 +2025,6 @@ return array(
|
|||
'phuix-icon-view',
|
||||
'phabricator-prefab',
|
||||
),
|
||||
'dfaf006b' => array(
|
||||
'javelin-dom',
|
||||
'javelin-util',
|
||||
'javelin-stratcom',
|
||||
'javelin-install',
|
||||
),
|
||||
'e1d25dfb' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-stratcom',
|
||||
|
|
14
resources/sql/autopatches/20180430.repo_identity.sql
Normal file
14
resources/sql/autopatches/20180430.repo_identity.sql
Normal file
|
@ -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};
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_repository.repository_identity
|
||||
ADD COLUMN authorPHID VARBINARY(64) NOT NULL;
|
19
resources/sql/autopatches/20180504.repo_identity.xaction.sql
Normal file
19
resources/sql/autopatches/20180504.repo_identity.xaction.sql
Normal file
|
@ -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};
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE {$NAMESPACE}_repository.repository_commit
|
||||
ADD COLUMN authorIdentityPHID VARBINARY(64) DEFAULT NULL,
|
||||
ADD COLUMN committerIdentityPHID VARBINARY(64) DEFAULT NULL;
|
|
@ -815,6 +815,13 @@ phutil_register_library_map(array(
|
|||
'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php',
|
||||
'DiffusionHistoryView' => 'applications/diffusion/view/DiffusionHistoryView.php',
|
||||
'DiffusionHovercardEngineExtension' => 'applications/diffusion/engineextension/DiffusionHovercardEngineExtension.php',
|
||||
'DiffusionIdentityAssigneeDatasource' => 'applications/diffusion/typeahead/DiffusionIdentityAssigneeDatasource.php',
|
||||
'DiffusionIdentityAssigneeEditField' => 'applications/diffusion/editfield/DiffusionIdentityAssigneeEditField.php',
|
||||
'DiffusionIdentityAssigneeSearchField' => 'applications/diffusion/searchfield/DiffusionIdentityAssigneeSearchField.php',
|
||||
'DiffusionIdentityEditController' => 'applications/diffusion/controller/DiffusionIdentityEditController.php',
|
||||
'DiffusionIdentityListController' => 'applications/diffusion/controller/DiffusionIdentityListController.php',
|
||||
'DiffusionIdentityUnassignedDatasource' => 'applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php',
|
||||
'DiffusionIdentityViewController' => 'applications/diffusion/controller/DiffusionIdentityViewController.php',
|
||||
'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php',
|
||||
'DiffusionInlineCommentPreviewController' => 'applications/diffusion/controller/DiffusionInlineCommentPreviewController.php',
|
||||
'DiffusionInternalAncestorsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionInternalAncestorsConduitAPIMethod.php',
|
||||
|
@ -937,6 +944,8 @@ phutil_register_library_map(array(
|
|||
'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',
|
||||
|
@ -4085,6 +4094,16 @@ phutil_register_library_map(array(
|
|||
'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',
|
||||
'PhabricatorRepositoryIdentityChangeWorker' => 'applications/repository/worker/PhabricatorRepositoryIdentityChangeWorker.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',
|
||||
|
@ -4099,6 +4118,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryManagementMovePathsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMovePathsWorkflow.php',
|
||||
'PhabricatorRepositoryManagementParentsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementParentsWorkflow.php',
|
||||
'PhabricatorRepositoryManagementPullWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementPullWorkflow.php',
|
||||
'PhabricatorRepositoryManagementRebuildIdentitiesWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementRebuildIdentitiesWorkflow.php',
|
||||
'PhabricatorRepositoryManagementRefsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementRefsWorkflow.php',
|
||||
'PhabricatorRepositoryManagementReparseWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php',
|
||||
'PhabricatorRepositoryManagementThawWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php',
|
||||
|
@ -6152,6 +6172,13 @@ phutil_register_library_map(array(
|
|||
'DiffusionHistoryTableView' => 'DiffusionHistoryView',
|
||||
'DiffusionHistoryView' => 'DiffusionView',
|
||||
'DiffusionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension',
|
||||
'DiffusionIdentityAssigneeDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'DiffusionIdentityAssigneeEditField' => 'PhabricatorTokenizerEditField',
|
||||
'DiffusionIdentityAssigneeSearchField' => 'PhabricatorSearchTokenizerField',
|
||||
'DiffusionIdentityEditController' => 'DiffusionController',
|
||||
'DiffusionIdentityListController' => 'DiffusionController',
|
||||
'DiffusionIdentityUnassignedDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'DiffusionIdentityViewController' => 'DiffusionController',
|
||||
'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController',
|
||||
'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController',
|
||||
'DiffusionInternalAncestorsConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
|
||||
|
@ -6273,6 +6300,8 @@ phutil_register_library_map(array(
|
|||
'DiffusionRepositoryEditUpdateController' => 'DiffusionRepositoryManageController',
|
||||
'DiffusionRepositoryFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'DiffusionRepositoryHistoryManagementPanel' => 'DiffusionRepositoryManagementPanel',
|
||||
'DiffusionRepositoryIdentityEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'DiffusionRepositoryIdentitySearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'DiffusionRepositoryListController' => 'DiffusionController',
|
||||
'DiffusionRepositoryManageController' => 'DiffusionController',
|
||||
'DiffusionRepositoryManagePanelsController' => 'DiffusionRepositoryManageController',
|
||||
|
@ -9975,6 +10004,20 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryGitLFSRefQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorRepositoryGraphCache' => 'Phobject',
|
||||
'PhabricatorRepositoryGraphStream' => 'Phobject',
|
||||
'PhabricatorRepositoryIdentity' => array(
|
||||
'PhabricatorRepositoryDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
),
|
||||
'PhabricatorRepositoryIdentityAssignTransaction' => 'PhabricatorRepositoryIdentityTransactionType',
|
||||
'PhabricatorRepositoryIdentityChangeWorker' => 'PhabricatorWorker',
|
||||
'PhabricatorRepositoryIdentityEditEngine' => 'PhabricatorEditEngine',
|
||||
'PhabricatorRepositoryIdentityFerretEngine' => 'PhabricatorFerretEngine',
|
||||
'PhabricatorRepositoryIdentityPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhabricatorRepositoryIdentityQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorRepositoryIdentityTransaction' => 'PhabricatorModularTransaction',
|
||||
'PhabricatorRepositoryIdentityTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'PhabricatorRepositoryIdentityTransactionType' => 'PhabricatorModularTransactionType',
|
||||
'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
|
@ -9989,6 +10032,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryManagementMovePathsWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementParentsWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementPullWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementRebuildIdentitiesWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementRefsWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementReparseWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementThawWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
|
|
|
@ -124,6 +124,15 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
|
|||
'(?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>[^/]+)/'
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionIdentityEditController
|
||||
extends DiffusionController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
return id(new PhabricatorRepositoryIdentityEditEngine())
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
<?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'),
|
||||
$this->buildPropertyValue($effective_phid));
|
||||
$properties->addProperty(
|
||||
pht('Automatically Detected User'),
|
||||
$this->buildPropertyValue($automatic_phid));
|
||||
$properties->addProperty(
|
||||
pht('Manually Set User'),
|
||||
$this->buildPropertyValue($manual_phid));
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(array(pht('Identity Assignments'), $tag));
|
||||
|
||||
return id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->addPropertyList($properties);
|
||||
}
|
||||
|
||||
private function buildPropertyValue($value) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
if ($value == DiffusionIdentityUnassignedDatasource::FUNCTION_TOKEN) {
|
||||
return phutil_tag('em', array(), pht('Explicitly Unassigned'));
|
||||
} else if (!$value) {
|
||||
return null;
|
||||
} else {
|
||||
return $viewer->renderHandle($value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionIdentityAssigneeEditField
|
||||
extends PhabricatorTokenizerEditField {
|
||||
|
||||
protected function newDatasource() {
|
||||
return new DiffusionIdentityAssigneeDatasource();
|
||||
}
|
||||
|
||||
protected function newHTTPParameterType() {
|
||||
return new AphrontUserListHTTPParameterType();
|
||||
}
|
||||
|
||||
protected function newConduitParameterType() {
|
||||
if ($this->getIsSingleValue()) {
|
||||
return new ConduitUserParameterType();
|
||||
} else {
|
||||
return new ConduitUserListParameterType();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
<?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 DiffusionIdentityAssigneeSearchField())
|
||||
->setLabel(pht('Assigned To'))
|
||||
->setKey('assignee')
|
||||
->setDescription(pht('Search for identities by assignee.')),
|
||||
id(new PhabricatorSearchTextField())
|
||||
->setLabel(pht('Identity Contains'))
|
||||
->setKey('match')
|
||||
->setDescription(pht('Search for identities by substring.')),
|
||||
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']);
|
||||
}
|
||||
|
||||
if ($map['match'] !== null) {
|
||||
$query->withIdentityNameLike($map['match']);
|
||||
}
|
||||
|
||||
if ($map['assignee']) {
|
||||
$query->withAssigneePHIDs($map['assignee']);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionIdentityAssigneeSearchField
|
||||
extends PhabricatorSearchTokenizerField {
|
||||
|
||||
protected function getDefaultValue() {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function getValueFromRequest(AphrontRequest $request, $key) {
|
||||
return $this->getUsersFromRequest($request, $key);
|
||||
}
|
||||
|
||||
protected function newDatasource() {
|
||||
return new DiffusionIdentityAssigneeDatasource();
|
||||
}
|
||||
|
||||
protected function newConduitParameterType() {
|
||||
return new ConduitUserListParameterType();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionIdentityAssigneeDatasource
|
||||
extends PhabricatorTypeaheadCompositeDatasource {
|
||||
|
||||
public function getBrowseTitle() {
|
||||
return pht('Browse Assignee');
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type a username or function...');
|
||||
}
|
||||
|
||||
public function getComponentDatasources() {
|
||||
return array(
|
||||
new PhabricatorPeopleDatasource(),
|
||||
new DiffusionIdentityUnassignedDatasource(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionIdentityUnassignedDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
const FUNCTION_TOKEN = 'unassigned()';
|
||||
|
||||
public function getBrowseTitle() {
|
||||
return pht('Browse Explicitly Unassigned');
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type "unassigned"...');
|
||||
}
|
||||
|
||||
public function getDatasourceApplicationClass() {
|
||||
return 'PhabricatorDiffusionApplication';
|
||||
}
|
||||
|
||||
public function getDatasourceFunctions() {
|
||||
return array(
|
||||
'unassigned' => array(
|
||||
'name' => pht('Explicitly Unassigned'),
|
||||
'summary' => pht('Find results which are not assigned.'),
|
||||
'description' => pht(
|
||||
"This function includes results which have been explicitly ".
|
||||
"unassigned. Use a query like this to find explicitly ".
|
||||
"unassigned results:\n\n%s\n\n".
|
||||
"If you combine this function with other functions, the query will ".
|
||||
"return results which match the other selectors //or// have no ".
|
||||
"assignee. For example, this query will find results which are ".
|
||||
"assigned to `alincoln`, and will also find results which have been ".
|
||||
"unassigned:\n\n%s",
|
||||
'> unassigned()',
|
||||
'> alincoln, unassigned()'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function loadResults() {
|
||||
$results = array(
|
||||
$this->buildUnassignedResult(),
|
||||
);
|
||||
return $this->filterResultsAgainstTokens($results);
|
||||
}
|
||||
|
||||
protected function evaluateFunction($function, array $argv_list) {
|
||||
$results = array();
|
||||
|
||||
foreach ($argv_list as $argv) {
|
||||
$results[] = self::FUNCTION_TOKEN;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function renderFunctionTokens($function, array $argv_list) {
|
||||
$results = array();
|
||||
foreach ($argv_list as $argv) {
|
||||
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
|
||||
$this->buildUnassignedResult());
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
private function buildUnassignedResult() {
|
||||
$name = pht('Unassigned');
|
||||
return $this->newFunctionResult()
|
||||
->setName($name.' unassigned')
|
||||
->setDisplayName($name)
|
||||
->setIcon('fa-ban')
|
||||
->setPHID('unassigned()')
|
||||
->setUnique(true)
|
||||
->addAttribute(pht('Select results with no owner.'));
|
||||
}
|
||||
|
||||
}
|
|
@ -420,6 +420,12 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
$user->endWriteLocking();
|
||||
$user->saveTransaction();
|
||||
|
||||
// Try and match this new address against unclaimed `RepositoryIdentity`s
|
||||
PhabricatorWorker::scheduleTask(
|
||||
'PhabricatorRepositoryIdentityChangeWorker',
|
||||
array('userPHID' => $user->getPHID()),
|
||||
array('objectPHID' => $user->getPHID()));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,11 @@ final class PhortunePaymentMethod extends PhortuneDAO
|
|||
|
||||
public function getDescription() {
|
||||
$provider = $this->buildPaymentProvider();
|
||||
return $provider->getPaymentMethodProviderDescription();
|
||||
|
||||
$expires = $this->getDisplayExpires();
|
||||
$description = $provider->getPaymentMethodProviderDescription();
|
||||
|
||||
return pht("Expires %s \xC2\xB7 %s", $expires, $description);
|
||||
}
|
||||
|
||||
public function getMetadataValue($key, $default = null) {
|
||||
|
|
|
@ -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 DiffusionIdentityAssigneeEditField())
|
||||
->setKey('manuallySetUserPHID')
|
||||
->setLabel(pht('Assigned To'))
|
||||
->setDescription(pht('Override this identity\'s assignment.'))
|
||||
->setTransactionType(
|
||||
PhabricatorRepositoryIdentityAssignTransaction::TRANSACTIONTYPE)
|
||||
->setIsCopyable(true)
|
||||
->setIsNullable(true)
|
||||
->setSingleValue($object->getManuallySetUserPHID()),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRepositoryManagementRebuildIdentitiesWorkflow
|
||||
extends PhabricatorRepositoryManagementWorkflow {
|
||||
|
||||
protected function didConstruct() {
|
||||
$this
|
||||
->setName('rebuild-identities')
|
||||
->setExamples(
|
||||
'**rebuild-identities** [__options__] __repository__')
|
||||
->setSynopsis(pht('Rebuild repository identities from commits.'))
|
||||
->setArguments(
|
||||
array(
|
||||
array(
|
||||
'name' => 'repositories',
|
||||
'wildcard' => true,
|
||||
),
|
||||
array(
|
||||
'name' => 'all',
|
||||
'help' => pht('Rebuild identities across all repositories.'),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
public function execute(PhutilArgumentParser $args) {
|
||||
$console = PhutilConsole::getConsole();
|
||||
|
||||
$all = $args->getArg('all');
|
||||
$repositories = $args->getArg('repositories');
|
||||
|
||||
if ($all xor empty($repositories)) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht('Specify --all or a list of repositories, but not both.'));
|
||||
}
|
||||
|
||||
$query = id(new DiffusionCommitQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->needCommitData(true);
|
||||
|
||||
if ($repositories) {
|
||||
$repos = $this->loadRepositories($args, 'repositories');
|
||||
$query->withRepositoryIDs(mpull($repos, 'getID'));
|
||||
}
|
||||
|
||||
$iterator = new PhabricatorQueryIterator($query);
|
||||
foreach ($iterator as $commit) {
|
||||
$data = $commit->getCommitData();
|
||||
$author_name = $data->getAuthorName();
|
||||
$author_identity = $this->getIdentityForCommit(
|
||||
$commit, $author_name);
|
||||
|
||||
$commit->setAuthorIdentityPHID($author_identity->getPHID());
|
||||
$data->setCommitDetail(
|
||||
'authorIdentityPHID', $author_identity->getPHID());
|
||||
|
||||
$committer_name = $data->getCommitDetail('committer', null);
|
||||
if ($committer_name) {
|
||||
$committer_identity = $this->getIdentityForCommit(
|
||||
$commit, $committer_name);
|
||||
|
||||
$commit->setCommitterIdentityPHID($committer_identity->getPHID());
|
||||
$data->setCommitDetail(
|
||||
'committerIdentityPHID', $committer_identity->getPHID());
|
||||
}
|
||||
|
||||
$commit->save();
|
||||
$data->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function getIdentityForCommit(
|
||||
PhabricatorRepositoryCommit $commit, $identity_name) {
|
||||
|
||||
static $seen = array();
|
||||
$identity_key = PhabricatorHash::digestForIndex($identity_name);
|
||||
if (empty($seen[$identity_key])) {
|
||||
try {
|
||||
$user_phid = id(new DiffusionResolveUserQuery())
|
||||
->withCommit($commit)
|
||||
->withName($identity_name)
|
||||
->execute();
|
||||
|
||||
$identity = id(new PhabricatorRepositoryIdentity())
|
||||
->setAuthorPHID($commit->getPHID())
|
||||
->setIdentityName($identity_name)
|
||||
->setAutomaticGuessedUserPHID($user_phid)
|
||||
->save();
|
||||
} catch (AphrontDuplicateKeyQueryException $ex) {
|
||||
// Somehow this identity already exists?
|
||||
$identity = id(new PhabricatorRepositoryIdentityQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withIdentityNames(array($identity_name))
|
||||
->executeOne();
|
||||
}
|
||||
$seen[$identity_key] = $identity;
|
||||
}
|
||||
|
||||
return $seen[$identity_key];
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ final class PhabricatorRepositoryManagementReparseWorkflow
|
|||
protected function didConstruct() {
|
||||
$this
|
||||
->setName('reparse')
|
||||
->setExamples('**reparse** [options] __repository__')
|
||||
->setExamples('**reparse** [options] __commit__')
|
||||
->setSynopsis(
|
||||
pht(
|
||||
'**reparse** __what__ __which_parts__ [--trace] [--force]'."\n\n".
|
||||
|
|
|
@ -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) {}
|
||||
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRepositoryIdentityQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
private $ids;
|
||||
private $phids;
|
||||
private $identityNames;
|
||||
private $emailAddress;
|
||||
private $assigneePHIDs;
|
||||
private $identityNameLike;
|
||||
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 withIdentityNameLike($name_like) {
|
||||
$this->identityNameLike = $name_like;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withEmailAddress($address) {
|
||||
$this->emailAddress = $address;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withAssigneePHIDs(array $assignees) {
|
||||
$this->assigneePHIDs = $assignees;
|
||||
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->assigneePHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'repository_identity.currentEffectiveUserPHID IN (%Ls)',
|
||||
$this->assigneePHIDs);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if ($this->emailAddress !== null) {
|
||||
$identity_style = "<{$this->emailAddress}>";
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'repository_identity.identityNameRaw LIKE %<',
|
||||
$identity_style);
|
||||
}
|
||||
|
||||
if ($this->identityNameLike != null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'repository_identity.identityNameRaw LIKE %~',
|
||||
$this->identityNameLike);
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
return 'PhabricatorDiffusionApplication';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRepositoryIdentityTransactionQuery
|
||||
extends PhabricatorApplicationTransactionQuery {
|
||||
|
||||
public function getTemplateApplicationTransaction() {
|
||||
return new PhabricatorRepositoryIdentityTransaction();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,8 @@ final class PhabricatorRepositoryCommit
|
|||
|
||||
protected $repositoryID;
|
||||
protected $phid;
|
||||
protected $authorIdentityPHID;
|
||||
protected $committerIdentityPHID;
|
||||
protected $commitIdentifier;
|
||||
protected $epoch;
|
||||
protected $mailKey;
|
||||
|
@ -113,6 +115,8 @@ final class PhabricatorRepositoryCommit
|
|||
'commitIdentifier' => 'text40',
|
||||
'mailKey' => 'bytes20',
|
||||
'authorPHID' => 'phid?',
|
||||
'authorIdentityPHID' => 'phid?',
|
||||
'committerIdentityPHID' => 'phid?',
|
||||
'auditStatus' => 'uint32',
|
||||
'summary' => 'text255',
|
||||
'importStatus' => 'uint32',
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
<?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,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRepositoryIdentityChangeWorker
|
||||
extends PhabricatorWorker {
|
||||
|
||||
protected function doWork() {
|
||||
$viewer = PhabricatorUser::getOmnipotentUser();
|
||||
|
||||
$task_data = $this->getTaskData();
|
||||
$user_phid = idx($task_data, 'userPHID');
|
||||
|
||||
$user = id(new PhabricatorPeopleQuery())
|
||||
->withPHIDs(array($user_phid))
|
||||
->setViewer($viewer)
|
||||
->executeOne();
|
||||
|
||||
$emails = id(new PhabricatorUserEmail())->loadAllWhere(
|
||||
'userPHID = %s ORDER BY address',
|
||||
$user->getPHID());
|
||||
|
||||
foreach ($emails as $email) {
|
||||
$identities = id(new PhabricatorRepositoryIdentityQuery())
|
||||
->setViewer($viewer)
|
||||
->withEmailAddress($email->getAddress())
|
||||
->execute();
|
||||
|
||||
foreach ($identities as $identity) {
|
||||
$identity->setAutomaticGuessedUserPHID($user->getPHID())
|
||||
->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -66,6 +66,34 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker
|
|||
$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());
|
||||
|
@ -81,6 +109,8 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker
|
|||
$data->setCommitDetail('authorName', $ref->getAuthorName());
|
||||
$data->setCommitDetail('authorEmail', $ref->getAuthorEmail());
|
||||
|
||||
$data->setCommitDetail(
|
||||
'authorIdentityPHID', $author_identity->getPHID());
|
||||
$data->setCommitDetail(
|
||||
'authorPHID',
|
||||
$this->resolveUserPHID($commit, $author));
|
||||
|
@ -96,6 +126,8 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker
|
|||
$data->setCommitDetail(
|
||||
'committerPHID',
|
||||
$this->resolveUserPHID($commit, $committer));
|
||||
$data->setCommitDetail(
|
||||
'committerIdentityPHID', $committer_identity->getPHID());
|
||||
}
|
||||
|
||||
$repository = $this->repository;
|
||||
|
@ -133,6 +165,9 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker
|
|||
$commit->setAuthorPHID($author_phid);
|
||||
}
|
||||
|
||||
$commit->setAuthorIdentityPHID($author_identity->getPHID());
|
||||
$commit->setCommitterIdentityPHID($committer_identity->getPHID());
|
||||
|
||||
$commit->setSummary($data->getSummary());
|
||||
$commit->save();
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?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->renderIdentityHandle($new));
|
||||
} else if (!$new) {
|
||||
return pht(
|
||||
'%s removed %s as the assignee of this identity.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderIdentityHandle($old));
|
||||
} else {
|
||||
return pht(
|
||||
'%s changed the assigned user for this identity from %s to %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderIdentityHandle($old),
|
||||
$this->renderIdentityHandle($new));
|
||||
}
|
||||
}
|
||||
|
||||
private function renderIdentityHandle($handle) {
|
||||
$unassigned_token = DiffusionIdentityUnassignedDatasource::FUNCTION_TOKEN;
|
||||
if ($handle === $unassigned_token) {
|
||||
return phutil_tag('em', array(), pht('Explicitly Unassigned'));
|
||||
} else {
|
||||
return $this->renderHandle($handle);
|
||||
}
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
$unassigned_token = DiffusionIdentityUnassignedDatasource::FUNCTION_TOKEN;
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
$old = $xaction->getOldValue();
|
||||
$new = $xaction->getNewValue();
|
||||
if (!strlen($new)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($new === $old) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($new === $unassigned_token) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorRepositoryIdentityTransactionType
|
||||
extends PhabricatorModularTransactionType {}
|
|
@ -207,6 +207,7 @@ div.phui-property-list-stacked .phui-property-list-properties
|
|||
.document-engine-image img {
|
||||
margin: 20px auto;
|
||||
background: url('/rsrc/image/checker_light.png');
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.device-desktop .document-engine-image img:hover {
|
||||
|
|
|
@ -400,7 +400,8 @@ JX.install('Tokenizer', {
|
|||
// this unusual token.
|
||||
|
||||
var tok;
|
||||
while ((tok = this._tokens.pop()) !== null) {
|
||||
while (this._tokens.length) {
|
||||
tok = this._tokens.pop();
|
||||
if (this._remove(tok, true)) {
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue