Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15418705
D19443.id46541.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.id46541.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
@@ -815,8 +815,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',
@@ -4092,6 +4096,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',
@@ -6166,8 +6171,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',
@@ -10000,6 +10009,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,16 @@
->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);
+ }
+ }
}
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']) {
+ $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,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(),
+ );
+ }
+
+}
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,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.'));
+ }
+
+}
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,12 @@
$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;
}
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/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,8 +75,14 @@
$this->phids);
}
- if ($this->hasEffectivePHID !== null) {
+ if ($this->assigneePHIDs !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'repository_identity.currentEffectiveUserPHID IN (%Ls)',
+ $this->assigneePHIDs);
+ }
+ if ($this->hasEffectivePHID !== null) {
if ($this->hasEffectivePHID) {
$where[] = qsprintf(
$conn,
@@ -82,6 +106,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
@@ -21,23 +21,33 @@
return pht(
'%s assigned this identity to %s.',
$this->renderAuthor(),
- $this->renderHandle($new));
+ $this->renderIdentityHandle($new));
} else if (!$new) {
return pht(
'%s removed %s as the assignee of this identity.',
$this->renderAuthor(),
- $this->renderHandle($old));
+ $this->renderIdentityHandle($old));
} else {
return pht(
'%s changed the assigned user for this identity from %s to %s.',
$this->renderAuthor(),
- $this->renderHandle($old),
- $this->renderHandle($new));
+ $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();
@@ -50,6 +60,10 @@
continue;
}
+ if ($new === $unassigned_token) {
+ continue;
+ }
+
$assignee_list = id(new PhabricatorPeopleQuery())
->setViewer($this->getActor())
->withPHIDs(array($new))
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 22, 12:58 AM (12 h, 26 m ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7224600
Default Alt Text
D19443.id46541.diff (20 KB)
Attached To
Mode
D19443: Assign RepositoryIdentity objects to commits
Attached
Detach File
Event Timeline
Log In to Comment