mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-30 08:28:20 +01:00
Separate all commit message field parsing out of Differential custom fields
Summary: Ref T11114. See that task for some discussion. Overall, Differential custom fields ended up with too many responsibilities. Later work in EditEngine provides a more promising model for achieving modularity with smaller, more consistent components. In particular, we have some custom fields like `DifferentialGitSVNIDField` and `DifferentialConflictsField` which serve //only// to support the field parser. This starts pulling commit message responsibilities out of the core list of custom fields and into simpler dedicated parsers. Test Plan: Created and edited revisions from the CLI. Added a bit of test coverage. Reviewers: chad Reviewed By: chad Maniphest Tasks: T11114 Differential Revision: https://secure.phabricator.com/D17058
This commit is contained in:
parent
552c546689
commit
8476ad1a28
19 changed files with 632 additions and 40 deletions
|
@ -353,8 +353,10 @@ phutil_register_library_map(array(
|
|||
'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php',
|
||||
'DifferentialApplyPatchField' => 'applications/differential/customfield/DifferentialApplyPatchField.php',
|
||||
'DifferentialAsanaRepresentationField' => 'applications/differential/customfield/DifferentialAsanaRepresentationField.php',
|
||||
'DifferentialAuditorsCommitMessageField' => 'applications/differential/field/DifferentialAuditorsCommitMessageField.php',
|
||||
'DifferentialAuditorsField' => 'applications/differential/customfield/DifferentialAuditorsField.php',
|
||||
'DifferentialAuthorField' => 'applications/differential/customfield/DifferentialAuthorField.php',
|
||||
'DifferentialBlameRevisionCommitMessageField' => 'applications/differential/field/DifferentialBlameRevisionCommitMessageField.php',
|
||||
'DifferentialBlameRevisionField' => 'applications/differential/customfield/DifferentialBlameRevisionField.php',
|
||||
'DifferentialBlockHeraldAction' => 'applications/differential/herald/DifferentialBlockHeraldAction.php',
|
||||
'DifferentialBlockingReviewerDatasource' => 'applications/differential/typeahead/DifferentialBlockingReviewerDatasource.php',
|
||||
|
@ -383,10 +385,12 @@ phutil_register_library_map(array(
|
|||
'DifferentialCloseConduitAPIMethod' => 'applications/differential/conduit/DifferentialCloseConduitAPIMethod.php',
|
||||
'DifferentialCommentPreviewController' => 'applications/differential/controller/DifferentialCommentPreviewController.php',
|
||||
'DifferentialCommentSaveController' => 'applications/differential/controller/DifferentialCommentSaveController.php',
|
||||
'DifferentialCommitMessageField' => 'applications/differential/field/DifferentialCommitMessageField.php',
|
||||
'DifferentialCommitMessageParser' => 'applications/differential/parser/DifferentialCommitMessageParser.php',
|
||||
'DifferentialCommitMessageParserTestCase' => 'applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php',
|
||||
'DifferentialCommitsField' => 'applications/differential/customfield/DifferentialCommitsField.php',
|
||||
'DifferentialConduitAPIMethod' => 'applications/differential/conduit/DifferentialConduitAPIMethod.php',
|
||||
'DifferentialConflictsCommitMessageField' => 'applications/differential/field/DifferentialConflictsCommitMessageField.php',
|
||||
'DifferentialConflictsField' => 'applications/differential/customfield/DifferentialConflictsField.php',
|
||||
'DifferentialController' => 'applications/differential/controller/DifferentialController.php',
|
||||
'DifferentialCoreCustomField' => 'applications/differential/customfield/DifferentialCoreCustomField.php',
|
||||
|
@ -444,6 +448,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialGetRevisionConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetRevisionConduitAPIMethod.php',
|
||||
'DifferentialGetWorkingCopy' => 'applications/differential/DifferentialGetWorkingCopy.php',
|
||||
'DifferentialGitHubLandingStrategy' => 'applications/differential/landing/DifferentialGitHubLandingStrategy.php',
|
||||
'DifferentialGitSVNIDCommitMessageField' => 'applications/differential/field/DifferentialGitSVNIDCommitMessageField.php',
|
||||
'DifferentialGitSVNIDField' => 'applications/differential/customfield/DifferentialGitSVNIDField.php',
|
||||
'DifferentialHarbormasterField' => 'applications/differential/customfield/DifferentialHarbormasterField.php',
|
||||
'DifferentialHiddenComment' => 'applications/differential/storage/DifferentialHiddenComment.php',
|
||||
|
@ -461,6 +466,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialInlineCommentMailView' => 'applications/differential/mail/DifferentialInlineCommentMailView.php',
|
||||
'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/DifferentialInlineCommentPreviewController.php',
|
||||
'DifferentialInlineCommentQuery' => 'applications/differential/query/DifferentialInlineCommentQuery.php',
|
||||
'DifferentialJIRAIssuesCommitMessageField' => 'applications/differential/field/DifferentialJIRAIssuesCommitMessageField.php',
|
||||
'DifferentialJIRAIssuesField' => 'applications/differential/customfield/DifferentialJIRAIssuesField.php',
|
||||
'DifferentialLandingActionMenuEventListener' => 'applications/differential/landing/DifferentialLandingActionMenuEventListener.php',
|
||||
'DifferentialLandingStrategy' => 'applications/differential/landing/DifferentialLandingStrategy.php',
|
||||
|
@ -493,7 +499,9 @@ phutil_register_library_map(array(
|
|||
'DifferentialResponsibleDatasource' => 'applications/differential/typeahead/DifferentialResponsibleDatasource.php',
|
||||
'DifferentialResponsibleUserDatasource' => 'applications/differential/typeahead/DifferentialResponsibleUserDatasource.php',
|
||||
'DifferentialResponsibleViewerFunctionDatasource' => 'applications/differential/typeahead/DifferentialResponsibleViewerFunctionDatasource.php',
|
||||
'DifferentialRevertPlanCommitMessageField' => 'applications/differential/field/DifferentialRevertPlanCommitMessageField.php',
|
||||
'DifferentialRevertPlanField' => 'applications/differential/customfield/DifferentialRevertPlanField.php',
|
||||
'DifferentialReviewedByCommitMessageField' => 'applications/differential/field/DifferentialReviewedByCommitMessageField.php',
|
||||
'DifferentialReviewedByField' => 'applications/differential/customfield/DifferentialReviewedByField.php',
|
||||
'DifferentialReviewerDatasource' => 'applications/differential/typeahead/DifferentialReviewerDatasource.php',
|
||||
'DifferentialReviewerForRevisionEdgeType' => 'applications/differential/edge/DifferentialReviewerForRevisionEdgeType.php',
|
||||
|
@ -503,6 +511,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialReviewersAddBlockingSelfHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddBlockingSelfHeraldAction.php',
|
||||
'DifferentialReviewersAddReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddReviewersHeraldAction.php',
|
||||
'DifferentialReviewersAddSelfHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddSelfHeraldAction.php',
|
||||
'DifferentialReviewersCommitMessageField' => 'applications/differential/field/DifferentialReviewersCommitMessageField.php',
|
||||
'DifferentialReviewersField' => 'applications/differential/customfield/DifferentialReviewersField.php',
|
||||
'DifferentialReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersHeraldAction.php',
|
||||
'DifferentialReviewersView' => 'applications/differential/view/DifferentialReviewersView.php',
|
||||
|
@ -530,6 +539,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialRevisionHasTaskRelationship' => 'applications/differential/relationships/DifferentialRevisionHasTaskRelationship.php',
|
||||
'DifferentialRevisionHeraldField' => 'applications/differential/herald/DifferentialRevisionHeraldField.php',
|
||||
'DifferentialRevisionHeraldFieldGroup' => 'applications/differential/herald/DifferentialRevisionHeraldFieldGroup.php',
|
||||
'DifferentialRevisionIDCommitMessageField' => 'applications/differential/field/DifferentialRevisionIDCommitMessageField.php',
|
||||
'DifferentialRevisionIDField' => 'applications/differential/customfield/DifferentialRevisionIDField.php',
|
||||
'DifferentialRevisionLandController' => 'applications/differential/controller/DifferentialRevisionLandController.php',
|
||||
'DifferentialRevisionListController' => 'applications/differential/controller/DifferentialRevisionListController.php',
|
||||
|
@ -563,9 +573,15 @@ phutil_register_library_map(array(
|
|||
'DifferentialSchemaSpec' => 'applications/differential/storage/DifferentialSchemaSpec.php',
|
||||
'DifferentialSetDiffPropertyConduitAPIMethod' => 'applications/differential/conduit/DifferentialSetDiffPropertyConduitAPIMethod.php',
|
||||
'DifferentialStoredCustomField' => 'applications/differential/customfield/DifferentialStoredCustomField.php',
|
||||
'DifferentialSubscribersCommitMessageField' => 'applications/differential/field/DifferentialSubscribersCommitMessageField.php',
|
||||
'DifferentialSubscribersField' => 'applications/differential/customfield/DifferentialSubscribersField.php',
|
||||
'DifferentialSummaryCommitMessageField' => 'applications/differential/field/DifferentialSummaryCommitMessageField.php',
|
||||
'DifferentialSummaryField' => 'applications/differential/customfield/DifferentialSummaryField.php',
|
||||
'DifferentialTagsCommitMessageField' => 'applications/differential/field/DifferentialTagsCommitMessageField.php',
|
||||
'DifferentialTasksCommitMessageField' => 'applications/differential/field/DifferentialTasksCommitMessageField.php',
|
||||
'DifferentialTestPlanCommitMessageField' => 'applications/differential/field/DifferentialTestPlanCommitMessageField.php',
|
||||
'DifferentialTestPlanField' => 'applications/differential/customfield/DifferentialTestPlanField.php',
|
||||
'DifferentialTitleCommitMessageField' => 'applications/differential/field/DifferentialTitleCommitMessageField.php',
|
||||
'DifferentialTitleField' => 'applications/differential/customfield/DifferentialTitleField.php',
|
||||
'DifferentialTransaction' => 'applications/differential/storage/DifferentialTransaction.php',
|
||||
'DifferentialTransactionComment' => 'applications/differential/storage/DifferentialTransactionComment.php',
|
||||
|
@ -4976,8 +4992,10 @@ phutil_register_library_map(array(
|
|||
'DifferentialAffectedPath' => 'DifferentialDAO',
|
||||
'DifferentialApplyPatchField' => 'DifferentialCustomField',
|
||||
'DifferentialAsanaRepresentationField' => 'DifferentialCustomField',
|
||||
'DifferentialAuditorsCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialAuditorsField' => 'DifferentialStoredCustomField',
|
||||
'DifferentialAuthorField' => 'DifferentialCustomField',
|
||||
'DifferentialBlameRevisionCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialBlameRevisionField' => 'DifferentialStoredCustomField',
|
||||
'DifferentialBlockHeraldAction' => 'HeraldAction',
|
||||
'DifferentialBlockingReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
|
@ -5009,10 +5027,12 @@ phutil_register_library_map(array(
|
|||
'DifferentialCloseConduitAPIMethod' => 'DifferentialConduitAPIMethod',
|
||||
'DifferentialCommentPreviewController' => 'DifferentialController',
|
||||
'DifferentialCommentSaveController' => 'DifferentialController',
|
||||
'DifferentialCommitMessageField' => 'Phobject',
|
||||
'DifferentialCommitMessageParser' => 'Phobject',
|
||||
'DifferentialCommitMessageParserTestCase' => 'PhabricatorTestCase',
|
||||
'DifferentialCommitsField' => 'DifferentialCustomField',
|
||||
'DifferentialConduitAPIMethod' => 'ConduitAPIMethod',
|
||||
'DifferentialConflictsCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialConflictsField' => 'DifferentialCustomField',
|
||||
'DifferentialController' => 'PhabricatorController',
|
||||
'DifferentialCoreCustomField' => 'DifferentialCustomField',
|
||||
|
@ -5077,6 +5097,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialGetRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod',
|
||||
'DifferentialGetWorkingCopy' => 'Phobject',
|
||||
'DifferentialGitHubLandingStrategy' => 'DifferentialLandingStrategy',
|
||||
'DifferentialGitSVNIDCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialGitSVNIDField' => 'DifferentialCustomField',
|
||||
'DifferentialHarbormasterField' => 'DifferentialCustomField',
|
||||
'DifferentialHiddenComment' => 'DifferentialDAO',
|
||||
|
@ -5100,6 +5121,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialInlineCommentMailView' => 'DifferentialMailView',
|
||||
'DifferentialInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController',
|
||||
'DifferentialInlineCommentQuery' => 'PhabricatorOffsetPagedQuery',
|
||||
'DifferentialJIRAIssuesCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialJIRAIssuesField' => 'DifferentialStoredCustomField',
|
||||
'DifferentialLandingActionMenuEventListener' => 'PhabricatorEventListener',
|
||||
'DifferentialLandingStrategy' => 'Phobject',
|
||||
|
@ -5132,7 +5154,9 @@ phutil_register_library_map(array(
|
|||
'DifferentialResponsibleDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'DifferentialResponsibleUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'DifferentialResponsibleViewerFunctionDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'DifferentialRevertPlanCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialRevertPlanField' => 'DifferentialStoredCustomField',
|
||||
'DifferentialReviewedByCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialReviewedByField' => 'DifferentialCoreCustomField',
|
||||
'DifferentialReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'DifferentialReviewerForRevisionEdgeType' => 'PhabricatorEdgeType',
|
||||
|
@ -5142,6 +5166,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialReviewersAddBlockingSelfHeraldAction' => 'DifferentialReviewersHeraldAction',
|
||||
'DifferentialReviewersAddReviewersHeraldAction' => 'DifferentialReviewersHeraldAction',
|
||||
'DifferentialReviewersAddSelfHeraldAction' => 'DifferentialReviewersHeraldAction',
|
||||
'DifferentialReviewersCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialReviewersField' => 'DifferentialCoreCustomField',
|
||||
'DifferentialReviewersHeraldAction' => 'HeraldAction',
|
||||
'DifferentialReviewersView' => 'AphrontView',
|
||||
|
@ -5185,6 +5210,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialRevisionHasTaskRelationship' => 'DifferentialRevisionRelationship',
|
||||
'DifferentialRevisionHeraldField' => 'HeraldField',
|
||||
'DifferentialRevisionHeraldFieldGroup' => 'HeraldFieldGroup',
|
||||
'DifferentialRevisionIDCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialRevisionIDField' => 'DifferentialCustomField',
|
||||
'DifferentialRevisionLandController' => 'DifferentialController',
|
||||
'DifferentialRevisionListController' => 'DifferentialController',
|
||||
|
@ -5218,9 +5244,15 @@ phutil_register_library_map(array(
|
|||
'DifferentialSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||
'DifferentialSetDiffPropertyConduitAPIMethod' => 'DifferentialConduitAPIMethod',
|
||||
'DifferentialStoredCustomField' => 'DifferentialCustomField',
|
||||
'DifferentialSubscribersCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialSubscribersField' => 'DifferentialCoreCustomField',
|
||||
'DifferentialSummaryCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialSummaryField' => 'DifferentialCoreCustomField',
|
||||
'DifferentialTagsCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialTasksCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialTestPlanCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialTestPlanField' => 'DifferentialCoreCustomField',
|
||||
'DifferentialTitleCommitMessageField' => 'DifferentialCommitMessageField',
|
||||
'DifferentialTitleField' => 'DifferentialCoreCustomField',
|
||||
'DifferentialTransaction' => 'PhabricatorModularTransaction',
|
||||
'DifferentialTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialAuditorsCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'phabricator:auditors';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Auditors');
|
||||
}
|
||||
|
||||
public function parseFieldValue($value) {
|
||||
return $this->parseObjectList(
|
||||
$value,
|
||||
array(
|
||||
PhabricatorPeopleUserPHIDType::TYPECONST,
|
||||
PhabricatorProjectProjectPHIDType::TYPECONST,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialBlameRevisionCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'blameRevision';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Blame Revision');
|
||||
}
|
||||
|
||||
public function getFieldAliases() {
|
||||
return array(
|
||||
'Blame Rev',
|
||||
);
|
||||
}
|
||||
|
||||
public function isFieldEnabled() {
|
||||
return $this->isCustomFieldEnabled('phabricator:blame-revision');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
abstract class DifferentialCommitMessageField
|
||||
extends Phobject {
|
||||
|
||||
private $viewer;
|
||||
|
||||
final public function setViewer(PhabricatorUser $viewer) {
|
||||
$this->viewer = $viewer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getViewer() {
|
||||
return $this->viewer;
|
||||
}
|
||||
|
||||
abstract public function getFieldName();
|
||||
|
||||
public function isFieldEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFieldAliases() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function validateFieldValue($value) {
|
||||
return;
|
||||
}
|
||||
|
||||
public function parseFieldValue($value) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
final public function getCommitMessageFieldKey() {
|
||||
return $this->getPhobjectClassConstant('FIELDKEY', 64);
|
||||
}
|
||||
|
||||
final public static function newEnabledFields(PhabricatorUser $viewer) {
|
||||
$fields = self::getAllFields();
|
||||
|
||||
$results = array();
|
||||
foreach ($fields as $key => $field) {
|
||||
$field = clone $field;
|
||||
$field->setViewer($viewer);
|
||||
if ($field->isFieldEnabled()) {
|
||||
$results[$key] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
final public static function getAllFields() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->setUniqueMethod('getCommitMessageFieldKey')
|
||||
->execute();
|
||||
}
|
||||
|
||||
protected function raiseParseException($message) {
|
||||
throw new DifferentialFieldParseException($message);
|
||||
}
|
||||
|
||||
protected function raiseValidationException($message) {
|
||||
throw new DifferentialFieldValidationException($message);
|
||||
}
|
||||
|
||||
protected function parseObjectList(
|
||||
$value,
|
||||
array $types,
|
||||
$allow_partial = false,
|
||||
array $suffixes = array()) {
|
||||
return id(new PhabricatorObjectListQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->setAllowedTypes($types)
|
||||
->setObjectList($value)
|
||||
->setAllowPartialResults($allow_partial)
|
||||
->setSuffixes($suffixes)
|
||||
->execute();
|
||||
}
|
||||
|
||||
protected function isCustomFieldEnabled($key) {
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
new DifferentialRevision(),
|
||||
PhabricatorCustomField::ROLE_VIEW);
|
||||
|
||||
$fields = $field_list->getFields();
|
||||
return isset($fields[$key]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialConflictsCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'conflicts';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Conflicts');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialGitSVNIDCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'gitSVNID';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('git-svn-id');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialJIRAIssuesCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'jira.issues';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('JIRA Issues');
|
||||
}
|
||||
|
||||
public function getFieldAliases() {
|
||||
return array(
|
||||
'JIRA',
|
||||
'JIRA Issue',
|
||||
);
|
||||
}
|
||||
|
||||
public function parseFieldValue($value) {
|
||||
return preg_split('/[\s,]+/', $value, $limit = -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
||||
public function isFieldEnabled() {
|
||||
return (bool)PhabricatorJIRAAuthProvider::getJIRAProvider();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialRevertPlanCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'revertPlan';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Revert Plan');
|
||||
}
|
||||
|
||||
public function isFieldEnabled() {
|
||||
return $this->isCustomFieldEnabled('phabricator:revert-plan');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialReviewedByCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'reviewedByPHIDs';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Reviewed By');
|
||||
}
|
||||
|
||||
public function parseFieldValue($value) {
|
||||
return $this->parseObjectList(
|
||||
$value,
|
||||
array(
|
||||
PhabricatorPeopleUserPHIDType::TYPECONST,
|
||||
PhabricatorProjectProjectPHIDType::TYPECONST,
|
||||
),
|
||||
$allow_partial = true);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialReviewersCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'reviewerPHIDs';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Reviewers');
|
||||
}
|
||||
|
||||
public function getFieldAliases() {
|
||||
return array(
|
||||
'Reviewer',
|
||||
);
|
||||
}
|
||||
|
||||
public function parseFieldValue($value) {
|
||||
$results = $this->parseObjectList(
|
||||
$value,
|
||||
array(
|
||||
PhabricatorPeopleUserPHIDType::TYPECONST,
|
||||
PhabricatorProjectProjectPHIDType::TYPECONST,
|
||||
PhabricatorOwnersPackagePHIDType::TYPECONST,
|
||||
),
|
||||
false,
|
||||
array('!'));
|
||||
|
||||
return $this->flattenReviewers($results);
|
||||
}
|
||||
|
||||
private function flattenReviewers(array $values) {
|
||||
// NOTE: For now, `arc` relies on this field returning only scalars, so we
|
||||
// need to reduce the results into scalars. See T10981.
|
||||
$result = array();
|
||||
|
||||
foreach ($values as $value) {
|
||||
$result[] = $value['phid'].implode('', array_keys($value['suffixes']));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function inflateReviewers(array $values) {
|
||||
$result = array();
|
||||
|
||||
foreach ($values as $value) {
|
||||
if (substr($value, -1) == '!') {
|
||||
$value = substr($value, 0, -1);
|
||||
$suffixes = array('!' => '!');
|
||||
} else {
|
||||
$suffixes = array();
|
||||
}
|
||||
|
||||
$result[] = array(
|
||||
'phid' => $value,
|
||||
'suffixes' => $suffixes,
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialRevisionIDCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'revisionID';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Differential Revision');
|
||||
}
|
||||
|
||||
public function parseFieldValue($value) {
|
||||
// If the value is just "D123" or similar, parse the ID from it directly.
|
||||
$value = trim($value);
|
||||
$matches = null;
|
||||
if (preg_match('/^[dD]([1-9]\d*)\z/', $value, $matches)) {
|
||||
return (int)$matches[1];
|
||||
}
|
||||
|
||||
// Otherwise, try to extract a URI value.
|
||||
return self::parseRevisionIDFromURI($value);
|
||||
}
|
||||
|
||||
private static function parseRevisionIDFromURI($uri_string) {
|
||||
$uri = new PhutilURI($uri_string);
|
||||
$path = $uri->getPath();
|
||||
|
||||
$matches = null;
|
||||
if (preg_match('#^/D(\d+)$#', $path, $matches)) {
|
||||
$id = (int)$matches[1];
|
||||
|
||||
$prod_uri = new PhutilURI(PhabricatorEnv::getProductionURI('/D'.$id));
|
||||
|
||||
// Make sure the URI is the same as our URI. Basically, we want to ignore
|
||||
// commits from other Phabricator installs.
|
||||
if ($uri->getDomain() == $prod_uri->getDomain()) {
|
||||
return $id;
|
||||
}
|
||||
|
||||
$allowed_uris = PhabricatorEnv::getAllowedURIs('/D'.$id);
|
||||
|
||||
foreach ($allowed_uris as $allowed_uri) {
|
||||
if ($uri_string == $allowed_uri) {
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialSubscribersCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'ccPHIDs';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Subscribers');
|
||||
}
|
||||
|
||||
public function getFieldAliases() {
|
||||
return array(
|
||||
'CC',
|
||||
'CCs',
|
||||
'Subscriber',
|
||||
);
|
||||
}
|
||||
|
||||
public function parseFieldValue($value) {
|
||||
return $this->parseObjectList(
|
||||
$value,
|
||||
array(
|
||||
PhabricatorPeopleUserPHIDType::TYPECONST,
|
||||
PhabricatorProjectProjectPHIDType::TYPECONST,
|
||||
PhabricatorOwnersPackagePHIDType::TYPECONST,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialSummaryCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'summary';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Summary');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialTagsCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'phabricator:projects';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Tags');
|
||||
}
|
||||
|
||||
public function getFieldAliases() {
|
||||
return array(
|
||||
'Tag',
|
||||
'Project',
|
||||
'Projects',
|
||||
);
|
||||
}
|
||||
|
||||
public function parseFieldValue($value) {
|
||||
return $this->parseObjectList(
|
||||
$value,
|
||||
array(
|
||||
PhabricatorProjectProjectPHIDType::TYPECONST,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialTasksCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'maniphestTaskPHIDs';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Maniphest Tasks');
|
||||
}
|
||||
|
||||
public function getFieldAliases() {
|
||||
return array(
|
||||
'Task',
|
||||
'Tasks',
|
||||
'Maniphest Task',
|
||||
);
|
||||
}
|
||||
|
||||
public function parseFieldValue($value) {
|
||||
return $this->parseObjectList(
|
||||
$value,
|
||||
array(
|
||||
ManiphestTaskPHIDType::TYPECONST,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialTestPlanCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'testPlan';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Test Plan');
|
||||
}
|
||||
|
||||
public function getFieldAliases() {
|
||||
return array(
|
||||
'Testplan',
|
||||
'Tested',
|
||||
'Tests',
|
||||
);
|
||||
}
|
||||
|
||||
public function isFieldEnabled() {
|
||||
return $this->isCustomFieldEnabled('differential:test-plan');
|
||||
}
|
||||
|
||||
public function validateFieldValue($value) {
|
||||
$is_required = PhabricatorEnv::getEnvConfig(
|
||||
'differential.require-test-plan-field');
|
||||
|
||||
if ($is_required && !strlen($value)) {
|
||||
$this->raiseValidationException(
|
||||
pht(
|
||||
'You must provide a test plan. Describe the actions you performed '.
|
||||
'to verify the behavior of this change.'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialTitleCommitMessageField
|
||||
extends DifferentialCommitMessageField {
|
||||
|
||||
const FIELDKEY = 'title';
|
||||
|
||||
public function getFieldName() {
|
||||
return pht('Title');
|
||||
}
|
||||
|
||||
public static function getDefaultTitle() {
|
||||
return pht('<<Replace this line with your revision title>');
|
||||
}
|
||||
|
||||
public function parseFieldValue($value) {
|
||||
if ($value === self::getDefaultTitle()) {
|
||||
$this->raiseParseException(
|
||||
pht(
|
||||
'Replace the default title line with a human-readable revision '.
|
||||
'title which describes the changes you are making.'));
|
||||
}
|
||||
|
||||
return parent::parseFieldValue($value);
|
||||
}
|
||||
|
||||
public function validateFieldValue($value) {
|
||||
if (!strlen($value)) {
|
||||
$this->raiseValidationException(
|
||||
pht(
|
||||
'You must provide a revision title in the first line '.
|
||||
'of your commit message.'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -26,43 +26,18 @@ final class DifferentialCommitMessageParser extends Phobject {
|
|||
private $titleKey;
|
||||
private $summaryKey;
|
||||
private $errors;
|
||||
private $commitMessageFields;
|
||||
private $raiseMissingFieldErrors = true;
|
||||
|
||||
public static function newStandardParser(PhabricatorUser $viewer) {
|
||||
$key_title = DifferentialTitleCommitMessageField::FIELDKEY;
|
||||
$key_summary = DifferentialSummaryCommitMessageField::FIELDKEY;
|
||||
|
||||
$key_title = id(new DifferentialTitleField())->getFieldKeyForConduit();
|
||||
$key_summary = id(new DifferentialSummaryField())->getFieldKeyForConduit();
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
new DifferentialRevision(),
|
||||
DifferentialCustomField::ROLE_COMMITMESSAGE);
|
||||
$field_list->setViewer($viewer);
|
||||
|
||||
$label_map = array();
|
||||
|
||||
foreach ($field_list->getFields() as $field) {
|
||||
$labels = $field->getCommitMessageLabels();
|
||||
$key = $field->getFieldKeyForConduit();
|
||||
|
||||
foreach ($labels as $label) {
|
||||
$normal_label = self::normalizeFieldLabel(
|
||||
$label);
|
||||
if (!empty($label_map[$normal_label])) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Field label "%s" is parsed by two custom fields: "%s" and '.
|
||||
'"%s". Each label must be parsed by only one field.',
|
||||
$label,
|
||||
$key,
|
||||
$label_map[$normal_label]));
|
||||
}
|
||||
$label_map[$normal_label] = $key;
|
||||
}
|
||||
}
|
||||
$field_list = DifferentialCommitMessageField::newEnabledFields($viewer);
|
||||
|
||||
return id(new self())
|
||||
->setViewer($viewer)
|
||||
->setLabelMap($label_map)
|
||||
->setCommitMessageFields($field_list)
|
||||
->setTitleKey($key_title)
|
||||
->setSummaryKey($key_summary);
|
||||
}
|
||||
|
@ -88,6 +63,25 @@ final class DifferentialCommitMessageParser extends Phobject {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task config
|
||||
*/
|
||||
public function setCommitMessageFields($fields) {
|
||||
assert_instances_of($fields, 'DifferentialCommitMessageField');
|
||||
$fields = mpull($fields, null, 'getCommitMessageFieldKey');
|
||||
$this->commitMessageFields = $fields;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task config
|
||||
*/
|
||||
public function getCommitMessageFields() {
|
||||
return $this->commitMessageFields;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task config
|
||||
*/
|
||||
|
@ -141,7 +135,7 @@ final class DifferentialCommitMessageParser extends Phobject {
|
|||
public function parseCorpus($corpus) {
|
||||
$this->errors = array();
|
||||
|
||||
$label_map = $this->labelMap;
|
||||
$label_map = $this->getLabelMap();
|
||||
$key_title = $this->titleKey;
|
||||
$key_summary = $this->summaryKey;
|
||||
|
||||
|
@ -258,13 +252,7 @@ final class DifferentialCommitMessageParser extends Phobject {
|
|||
$viewer = $this->getViewer();
|
||||
$text_map = $this->parseCorpus($corpus);
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
new DifferentialRevision(),
|
||||
DifferentialCustomField::ROLE_COMMITMESSAGE);
|
||||
$field_list->setViewer($viewer);
|
||||
|
||||
$field_map = $field_list->getFields();
|
||||
$field_map = mpull($field_map, null, 'getFieldKeyForConduit');
|
||||
$field_map = $this->getCommitMessageFields();
|
||||
|
||||
$result_map = array();
|
||||
foreach ($text_map as $field_key => $text_value) {
|
||||
|
@ -281,7 +269,7 @@ final class DifferentialCommitMessageParser extends Phobject {
|
|||
}
|
||||
|
||||
try {
|
||||
$result = $field->parseValueFromCommitMessage($text_value);
|
||||
$result = $field->parseFieldValue($text_value);
|
||||
$result_map[$field_key] = $result;
|
||||
} catch (DifferentialFieldParseException $ex) {
|
||||
$this->errors[] = pht(
|
||||
|
@ -294,7 +282,7 @@ final class DifferentialCommitMessageParser extends Phobject {
|
|||
if ($this->getRaiseMissingFieldErrors()) {
|
||||
foreach ($field_map as $key => $field) {
|
||||
try {
|
||||
$field->validateCommitMessageValue(idx($result_map, $key));
|
||||
$field->validateFieldValue(idx($result_map, $key));
|
||||
} catch (DifferentialFieldValidationException $ex) {
|
||||
$this->errors[] = pht(
|
||||
'Invalid or missing field "%s": %s',
|
||||
|
@ -330,6 +318,38 @@ final class DifferentialCommitMessageParser extends Phobject {
|
|||
/* -( Internals )---------------------------------------------------------- */
|
||||
|
||||
|
||||
private function getLabelMap() {
|
||||
if ($this->labelMap === null) {
|
||||
$field_list = $this->getCommitMessageFields();
|
||||
|
||||
$label_map = array();
|
||||
foreach ($field_list as $field_key => $field) {
|
||||
$labels = $field->getFieldAliases();
|
||||
$labels[] = $field->getFieldName();
|
||||
|
||||
foreach ($labels as $label) {
|
||||
$normal_label = self::normalizeFieldLabel($label);
|
||||
if (!empty($label_map[$normal_label])) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Field label "%s" is parsed by two custom fields: "%s" and '.
|
||||
'"%s". Each label must be parsed by only one field.',
|
||||
$label,
|
||||
$field_key,
|
||||
$label_map[$normal_label]));
|
||||
}
|
||||
|
||||
$label_map[$normal_label] = $field_key;
|
||||
}
|
||||
}
|
||||
|
||||
$this->labelMap = $label_map;
|
||||
}
|
||||
|
||||
return $this->labelMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task internal
|
||||
*/
|
||||
|
|
|
@ -41,6 +41,36 @@ final class DifferentialCommitMessageParserTestCase
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public function testDifferentialCommitMessageFieldParser() {
|
||||
$message = <<<EOMESSAGE
|
||||
This is the title.
|
||||
|
||||
Summary: This is the summary.
|
||||
EOMESSAGE;
|
||||
|
||||
$fields = array(
|
||||
new DifferentialTitleCommitMessageField(),
|
||||
new DifferentialSummaryCommitMessageField(),
|
||||
);
|
||||
|
||||
$expect = array(
|
||||
DifferentialTitleCommitMessageField::FIELDKEY =>
|
||||
'This is the title.',
|
||||
DifferentialSummaryCommitMessageField::FIELDKEY =>
|
||||
'This is the summary.',
|
||||
);
|
||||
|
||||
$parser = id(new DifferentialCommitMessageParser())
|
||||
->setCommitMessageFields($fields)
|
||||
->setTitleKey(DifferentialTitleCommitMessageField::FIELDKEY)
|
||||
->setSummaryKey(DifferentialSummaryCommitMessageField::FIELDKEY);
|
||||
|
||||
$actual = $parser->parseFields($message);
|
||||
|
||||
$this->assertEqual($expect, $actual);
|
||||
}
|
||||
|
||||
public function testDifferentialCommitMessageParserNormalization() {
|
||||
$map = array(
|
||||
'Test Plan' => 'test plan',
|
||||
|
|
Loading…
Add table
Reference in a new issue