Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15447813
D19443.id46507.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
20 KB
Referenced Files
None
Subscribers
None
D19443.id46507.diff
View Options
diff --git a/resources/sql/autopatches/20180509.repo_identity.commits.sql b/resources/sql/autopatches/20180509.repo_identity.commits.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180509.repo_identity.commits.sql
@@ -0,0 +1,3 @@
+ALTER TABLE {$NAMESPACE}_repository.repository_commit
+ ADD COLUMN authorIdentityPHID VARBINARY(64) DEFAULT NULL,
+ ADD COLUMN committerIdentityPHID VARBINARY(64) DEFAULT NULL;
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,8 +814,12 @@
'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',
@@ -4085,6 +4089,7 @@
'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',
@@ -6158,8 +6163,12 @@
'DiffusionHistoryTableView' => 'DiffusionHistoryView',
'DiffusionHistoryView' => 'DiffusionView',
'DiffusionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension',
+ 'DiffusionIdentityAssigneeDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
+ 'DiffusionIdentityAssigneeEditField' => 'PhabricatorTokenizerEditField',
+ 'DiffusionIdentityAssigneeSearchField' => 'PhabricatorSearchTokenizerField',
'DiffusionIdentityEditController' => 'DiffusionController',
'DiffusionIdentityListController' => 'DiffusionController',
+ 'DiffusionIdentityUnassignedDatasource' => 'PhabricatorTypeaheadDatasource',
'DiffusionIdentityViewController' => 'DiffusionController',
'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController',
'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController',
@@ -9986,6 +9995,7 @@
'PhabricatorApplicationTransactionInterface',
),
'PhabricatorRepositoryIdentityAssignTransaction' => 'PhabricatorRepositoryIdentityTransactionType',
+ 'PhabricatorRepositoryIdentityChangeWorker' => 'PhabricatorWorker',
'PhabricatorRepositoryIdentityEditEngine' => 'PhabricatorEditEngine',
'PhabricatorRepositoryIdentityFerretEngine' => 'PhabricatorFerretEngine',
'PhabricatorRepositoryIdentityPHIDType' => 'PhabricatorPHIDType',
diff --git a/src/applications/diffusion/controller/DiffusionIdentityViewController.php b/src/applications/diffusion/controller/DiffusionIdentityViewController.php
--- a/src/applications/diffusion/controller/DiffusionIdentityViewController.php
+++ b/src/applications/diffusion/controller/DiffusionIdentityViewController.php
@@ -104,13 +104,13 @@
}
$properties->addProperty(
pht('Effective User'),
- $viewer->renderHandle($effective_phid));
+ $this->buildPropertyValue($effective_phid));
$properties->addProperty(
pht('Automatically Detected User'),
- $viewer->renderHandle($automatic_phid));
+ $this->buildPropertyValue($automatic_phid));
$properties->addProperty(
pht('Manually Set User'),
- $viewer->renderHandle($manual_phid));
+ $this->buildPropertyValue($manual_phid));
$header = id(new PHUIHeaderView())
->setHeader(array(pht('Identity Assignments'), $tag));
@@ -120,4 +120,17 @@
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->addPropertyList($properties);
}
+
+ private function buildPropertyValue($value) {
+ $viewer = $this->getViewer();
+
+ // TODO: there must be a way to render the fancy "Unassigned" tag
+ if ($value == DiffusionIdentityUnassignedDatasource::FUNCTION_TOKEN) {
+ return pht('<Explicitly Unassigned>');
+ } else if (!$value) {
+ return null;
+ } else {
+ return $viewer->renderHandle($value);
+ }
+ }
}
diff --git a/src/applications/diffusion/editfield/DiffusionIdentityAssigneeEditField.php b/src/applications/diffusion/editfield/DiffusionIdentityAssigneeEditField.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/editfield/DiffusionIdentityAssigneeEditField.php
@@ -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();
+ }
+ }
+
+}
diff --git a/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php b/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php
--- a/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php
+++ b/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php
@@ -17,6 +17,14 @@
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')
@@ -34,6 +42,14 @@
$query->withHasEffectivePHID($map['hasEffectivePHID']);
}
+ if ($map['match'] !== null) {
+ $query->withIdentityNameLike($map['match']);
+ }
+
+ if ($map['assignee'] !== null) {
+ $query->withAssigneePHIDs($map['assignee']);
+ }
+
return $query;
}
diff --git a/src/applications/diffusion/searchfield/DiffusionIdentityAssigneeSearchField.php b/src/applications/diffusion/searchfield/DiffusionIdentityAssigneeSearchField.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/searchfield/DiffusionIdentityAssigneeSearchField.php
@@ -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();
+ }
+
+}
diff --git a/src/applications/diffusion/typeahead/DiffusionIdentityAssigneeDatasource.php b/src/applications/diffusion/typeahead/DiffusionIdentityAssigneeDatasource.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/typeahead/DiffusionIdentityAssigneeDatasource.php
@@ -0,0 +1,22 @@
+<?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 PhabricatorViewerDatasource(),
+ new PhabricatorPeopleDatasource(),
+ new DiffusionIdentityUnassignedDatasource(),
+ );
+ }
+
+}
diff --git a/src/applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php b/src/applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php
@@ -0,0 +1,76 @@
+<?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 no owner. Use a query ".
+ "like this to find 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 ".
+ "owner. For example, this query will find results which are owned ".
+ "by `alincoln`, and will also find results which have no owner:".
+ "\n\n%s",
+ '> none()',
+ '> alincoln, none()'),
+ ),
+ );
+ }
+
+ 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.'));
+ }
+
+}
diff --git a/src/applications/people/editor/PhabricatorUserEditor.php b/src/applications/people/editor/PhabricatorUserEditor.php
--- a/src/applications/people/editor/PhabricatorUserEditor.php
+++ b/src/applications/people/editor/PhabricatorUserEditor.php
@@ -420,6 +420,11 @@
$user->endWriteLocking();
$user->saveTransaction();
+ // Try and match this new address against unclaimed `RepositoryIdentity`s
+ PhabricatorWorker::scheduleTask(
+ 'PhabricatorRepositoryIdentityChangeWorker',
+ array('userPHID' => $user->getPHID()));
+
return $this;
}
diff --git a/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php b/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php
--- a/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php
+++ b/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php
@@ -75,7 +75,7 @@
protected function buildCustomEditFields($object) {
return array(
- id(new PhabricatorUsersEditField())
+ id(new DiffusionIdentityAssigneeEditField())
->setKey('manuallySetUserPHID')
->setLabel(pht('Assigned To'))
->setDescription(pht('Override this identity\'s assignment.'))
diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php
--- a/src/applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php
+++ b/src/applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php
@@ -102,6 +102,11 @@
public function execute(PhutilArgumentParser $args) {
$console = PhutilConsole::getConsole();
+ $data = array('userPHID' => 'PHID-USER-d7xt74lyk6dfoahqjpsl');
+ $worker = newv('PhabricatorRepositoryIdentityChangeWorker', array($data));
+ $worker->executeTask();
+ return;
+
$all_from_repo = $args->getArg('all');
$reparse_message = $args->getArg('message');
$reparse_change = $args->getArg('change');
diff --git a/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php b/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
--- a/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
@@ -6,6 +6,9 @@
private $ids;
private $phids;
private $identityNames;
+ private $emailAddress;
+ private $assigneePHIDs;
+ private $identityNameLike;
private $hasEffectivePHID;
public function withIDs(array $ids) {
@@ -23,6 +26,21 @@
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;
@@ -57,6 +75,13 @@
$this->phids);
}
+ if ($this->assigneePHIDs !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'repository_identity.currentEffectiveUserPHID IN (%Ls)',
+ $this->assigneePHIDs);
+ }
+
if ($this->hasEffectivePHID !== null) {
if ($this->hasEffectivePHID) {
@@ -82,6 +107,21 @@
$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;
}
diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommit.php b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
--- a/src/applications/repository/storage/PhabricatorRepositoryCommit.php
+++ b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
@@ -21,6 +21,8 @@
protected $repositoryID;
protected $phid;
+ protected $authorIdentityPHID;
+ protected $committerIdentityPHID;
protected $commitIdentifier;
protected $epoch;
protected $mailKey;
@@ -113,6 +115,8 @@
'commitIdentifier' => 'text40',
'mailKey' => 'bytes20',
'authorPHID' => 'phid?',
+ 'authorIdentityPHID' => 'phid?',
+ 'committerIdentityPHID' => 'phid?',
'auditStatus' => 'uint32',
'summary' => 'text255',
'importStatus' => 'uint32',
diff --git a/src/applications/repository/storage/PhabricatorRepositoryIdentity.php b/src/applications/repository/storage/PhabricatorRepositoryIdentity.php
--- a/src/applications/repository/storage/PhabricatorRepositoryIdentity.php
+++ b/src/applications/repository/storage/PhabricatorRepositoryIdentity.php
@@ -80,6 +80,7 @@
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
);
}
diff --git a/src/applications/repository/worker/PhabricatorRepositoryIdentityChangeWorker.php b/src/applications/repository/worker/PhabricatorRepositoryIdentityChangeWorker.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/worker/PhabricatorRepositoryIdentityChangeWorker.php
@@ -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();
+ }
+ }
+ }
+
+}
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
@@ -109,6 +109,8 @@
$data->setCommitDetail('authorName', $ref->getAuthorName());
$data->setCommitDetail('authorEmail', $ref->getAuthorEmail());
+ $data->setCommitDetail(
+ 'authorIdentityPHID', $author_identity->getPHID());
$data->setCommitDetail(
'authorPHID',
$this->resolveUserPHID($commit, $author));
@@ -124,6 +126,8 @@
$data->setCommitDetail(
'committerPHID',
$this->resolveUserPHID($commit, $committer));
+ $data->setCommitDetail(
+ 'committerIdentityPHID', $committer_identity->getPHID());
}
$repository = $this->repository;
@@ -161,6 +165,9 @@
$commit->setAuthorPHID($author_phid);
}
+ $commit->setAuthorIdentityPHID($author_identity->getPHID());
+ $commit->setCommitterIdentityPHID($committer_identity->getPHID());
+
$commit->setSummary($data->getSummary());
$commit->save();
diff --git a/src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php b/src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php
--- a/src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php
+++ b/src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php
@@ -55,11 +55,14 @@
->withPHIDs(array($new))
->execute();
- if (!$assignee_list) {
- $errors[] = $this->newInvalidError(
- pht('User "%s" is not a valid user.',
- $new));
- }
+ // TODO: turn this back on when I figure out how to check for
+ // 'unassigned()'
+
+ // if (!$assignee_list) {
+ // $errors[] = $this->newInvalidError(
+ // pht('User "%s" is not a valid user.',
+ // $new));
+ // }
}
return $errors;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 29, 1:42 AM (5 d, 18 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7725831
Default Alt Text
D19443.id46507.diff (20 KB)
Attached To
Mode
D19443: Assign RepositoryIdentity objects to commits
Attached
Detach File
Event Timeline
Log In to Comment