1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-19 03:01:11 +01:00

Move Differential commit message rendering to dedicated classes

Summary:
Ref T11114. This probably still has some bugs, but survives basic sanity checks.

Continue pulling commit message logic out of CustomField so we can reduce the amount of responsibility/bloat in the classtree and send more code through EditEngine.

Test Plan:
  - Called `differential.getcommitmessage` via API console for various revisions/parameters (edit and create mode, with and without fields, with and without revisions).
  - Used `--create`, `--edit` and `--update` modes of `arc diff` from the CLI.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T11114

Differential Revision: https://secure.phabricator.com/D17066
This commit is contained in:
epriestley 2016-12-15 10:11:58 -08:00
parent 0387d62632
commit 24926f9453
20 changed files with 499 additions and 112 deletions

View file

@ -385,6 +385,7 @@ phutil_register_library_map(array(
'DifferentialCloseConduitAPIMethod' => 'applications/differential/conduit/DifferentialCloseConduitAPIMethod.php',
'DifferentialCommentPreviewController' => 'applications/differential/controller/DifferentialCommentPreviewController.php',
'DifferentialCommentSaveController' => 'applications/differential/controller/DifferentialCommentSaveController.php',
'DifferentialCommitMessageCustomField' => 'applications/differential/field/DifferentialCommitMessageCustomField.php',
'DifferentialCommitMessageField' => 'applications/differential/field/DifferentialCommitMessageField.php',
'DifferentialCommitMessageParser' => 'applications/differential/parser/DifferentialCommitMessageParser.php',
'DifferentialCommitMessageParserTestCase' => 'applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php',
@ -4996,10 +4997,10 @@ phutil_register_library_map(array(
'DifferentialAffectedPath' => 'DifferentialDAO',
'DifferentialApplyPatchField' => 'DifferentialCustomField',
'DifferentialAsanaRepresentationField' => 'DifferentialCustomField',
'DifferentialAuditorsCommitMessageField' => 'DifferentialCommitMessageField',
'DifferentialAuditorsCommitMessageField' => 'DifferentialCommitMessageCustomField',
'DifferentialAuditorsField' => 'DifferentialStoredCustomField',
'DifferentialAuthorField' => 'DifferentialCustomField',
'DifferentialBlameRevisionCommitMessageField' => 'DifferentialCommitMessageField',
'DifferentialBlameRevisionCommitMessageField' => 'DifferentialCommitMessageCustomField',
'DifferentialBlameRevisionField' => 'DifferentialStoredCustomField',
'DifferentialBlockHeraldAction' => 'HeraldAction',
'DifferentialBlockingReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
@ -5031,6 +5032,7 @@ phutil_register_library_map(array(
'DifferentialCloseConduitAPIMethod' => 'DifferentialConduitAPIMethod',
'DifferentialCommentPreviewController' => 'DifferentialController',
'DifferentialCommentSaveController' => 'DifferentialController',
'DifferentialCommitMessageCustomField' => 'DifferentialCommitMessageField',
'DifferentialCommitMessageField' => 'Phobject',
'DifferentialCommitMessageParser' => 'Phobject',
'DifferentialCommitMessageParserTestCase' => 'PhabricatorTestCase',
@ -5125,7 +5127,7 @@ phutil_register_library_map(array(
'DifferentialInlineCommentMailView' => 'DifferentialMailView',
'DifferentialInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController',
'DifferentialInlineCommentQuery' => 'PhabricatorOffsetPagedQuery',
'DifferentialJIRAIssuesCommitMessageField' => 'DifferentialCommitMessageField',
'DifferentialJIRAIssuesCommitMessageField' => 'DifferentialCommitMessageCustomField',
'DifferentialJIRAIssuesField' => 'DifferentialStoredCustomField',
'DifferentialLandingActionMenuEventListener' => 'PhabricatorEventListener',
'DifferentialLandingStrategy' => 'Phobject',
@ -5158,7 +5160,7 @@ phutil_register_library_map(array(
'DifferentialResponsibleDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'DifferentialResponsibleUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'DifferentialResponsibleViewerFunctionDatasource' => 'PhabricatorTypeaheadDatasource',
'DifferentialRevertPlanCommitMessageField' => 'DifferentialCommitMessageField',
'DifferentialRevertPlanCommitMessageField' => 'DifferentialCommitMessageCustomField',
'DifferentialRevertPlanField' => 'DifferentialStoredCustomField',
'DifferentialReviewedByCommitMessageField' => 'DifferentialCommitMessageField',
'DifferentialReviewedByField' => 'DifferentialCoreCustomField',

View file

@ -47,94 +47,71 @@ final class DifferentialGetCommitMessageConduitAPIMethod
}
} else {
$revision = DifferentialRevision::initializeNewRevision($viewer);
$revision->attachReviewerStatus(array());
$revision->attachActiveDiff(null);
}
$is_edit = $request->getValue('edit');
$is_create = ($is_edit == 'create');
$edit_mode = $request->getValue('edit');
$is_create = ($edit_mode == 'create');
$is_edit = ($edit_mode && !$is_create);
$field_list = PhabricatorCustomField::getObjectFields(
$revision,
($is_edit
? DifferentialCustomField::ROLE_COMMITMESSAGEEDIT
: DifferentialCustomField::ROLE_COMMITMESSAGE));
$field_list = DifferentialCommitMessageField::newEnabledFields($viewer);
$field_list
->setViewer($viewer)
->readFieldsFromStorage($revision);
$field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit');
$custom_storage = $this->loadCustomFieldStorage($viewer, $revision);
foreach ($field_list as $field) {
$field->setCustomFieldStorage($custom_storage);
}
// If we're editing the message, remove fields like "Conflicts" and
// "git-svn-id" which should not be presented to the user for editing.
if ($is_edit) {
$fields = $request->getValue('fields', array());
foreach ($fields as $field => $value) {
$custom_field = idx($field_map, $field);
if (!$custom_field) {
// Just ignore this, these workflows don't make strong distictions
// about field editability on the client side.
continue;
}
if ($is_create ||
$custom_field->shouldOverwriteWhenCommitMessageIsEdited()) {
$custom_field->readValueFromCommitMessage($value);
foreach ($field_list as $field_key => $field) {
if (!$field->isFieldEditable()) {
unset($field_list[$field_key]);
}
}
}
$phids = array();
foreach ($field_list->getFields() as $key => $field) {
$field_phids = $field->getRequiredHandlePHIDsForCommitMessage();
if (!is_array($field_phids)) {
throw new Exception(
pht(
'Custom field "%s" was expected to return an array of handle '.
'PHIDs required for commit message rendering, but returned "%s" '.
'instead.',
$field->getFieldKey(),
gettype($field_phids)));
$overrides = $request->getValue('fields', array());
$value_map = array();
foreach ($field_list as $field_key => $field) {
if (array_key_exists($field_key, $overrides)) {
$field_value = $overrides[$field_key];
} else {
$field_value = $field->readFieldValueFromObject($revision);
}
$phids[$key] = $field_phids;
// We're calling this method on the value no matter where we got it
// from, so we hit the same validation logic for values which came over
// the wire and which we generated.
$field_value = $field->readFieldValueFromConduit($field_value);
$value_map[$field_key] = $field_value;
}
$all_phids = array_mergev($phids);
if ($all_phids) {
$all_handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs($all_phids)
->execute();
} else {
$all_handles = array();
}
$key_title = id(new DifferentialTitleField())->getFieldKey();
$default_title = DifferentialTitleField::getDefaultTitle();
$key_title = DifferentialTitleCommitMessageField::FIELDKEY;
$commit_message = array();
foreach ($field_list->getFields() as $key => $field) {
$handles = array_select_keys($all_handles, $phids[$key]);
foreach ($field_list as $field_key => $field) {
$label = $field->getFieldName();
$wire_value = $value_map[$field_key];
$value = $field->renderFieldValue($wire_value);
$label = $field->renderCommitMessageLabel();
$value = $field->renderCommitMessageValue($handles);
$is_template = ($is_edit && $field->isTemplateField());
if (!is_string($value) && !is_null($value)) {
throw new Exception(
pht(
'Custom field "%s" was expected to render a string or null value, '.
'but rendered a "%s" instead.',
'Commit message field "%s" was expected to render a string or '.
'null value, but rendered a "%s" instead.',
$field->getFieldKey(),
gettype($value)));
}
$is_title = ($key == $key_title);
$is_title = ($field_key == $key_title);
if (!strlen($value)) {
if ($is_title) {
$commit_message[] = $default_title;
} else {
if ($is_edit && $field->shouldAppearInCommitMessageTemplate()) {
$commit_message[] = $label.': ';
}
if ($is_template) {
$commit_message[] = $label.': ';
}
} else {
if ($is_title) {
@ -153,46 +130,31 @@ final class DifferentialGetCommitMessageConduitAPIMethod
}
}
if ($is_edit) {
$tip = $this->getProTip($field_list);
if ($tip !== null) {
$commit_message[] = "\n".$tip;
return implode("\n\n", $commit_message);
}
private function loadCustomFieldStorage(
PhabricatorUser $viewer,
DifferentialRevision $revision) {
$custom_field_list = PhabricatorCustomField::getObjectFields(
$revision,
DifferentialCustomField::ROLE_COMMITMESSAGE);
$custom_field_list
->setViewer($viewer)
->readFieldsFromStorage($revision);
$custom_field_map = array();
foreach ($custom_field_list->getFields() as $custom_field) {
if (!$custom_field->shouldUseStorage()) {
continue;
}
$custom_field_key = $custom_field->getFieldKey();
$custom_field_value = $custom_field->getValueForStorage();
$custom_field_map[$custom_field_key] = $custom_field_value;
}
$commit_message = implode("\n\n", $commit_message);
return $commit_message;
return $custom_field_map;
}
private function getProTip() {
// Any field can provide tips, whether it normally appears on commit
// messages or not.
$field_list = PhabricatorCustomField::getObjectFields(
new DifferentialRevision(),
PhabricatorCustomField::ROLE_DEFAULT);
$tips = array();
foreach ($field_list->getFields() as $key => $field) {
$tips[] = $field->getProTips();
}
$tips = array_mergev($tips);
if (!$tips) {
return null;
}
shuffle($tips);
$tip = pht('Tip: %s', head($tips));
$tip = wordwrap($tip, 78, "\n", true);
$lines = explode("\n", $tip);
foreach ($lines as $key => $line) {
$lines[$key] = '# '.$line;
}
return implode("\n", $lines);
}
}

View file

@ -1,7 +1,7 @@
<?php
final class DifferentialAuditorsCommitMessageField
extends DifferentialCommitMessageField {
extends DifferentialCommitMessageCustomField {
const FIELDKEY = 'phabricator:auditors';
@ -18,4 +18,20 @@ final class DifferentialAuditorsCommitMessageField
));
}
public function getCustomFieldKey() {
return 'phabricator:auditors';
}
public function readFieldValueFromConduit($value) {
return $this->readStringListFieldValueFromConduit($value);
}
public function renderFieldValue($value) {
return $this->renderHandleList($value);
}
protected function readFieldValueFromCustomFieldStorage($value) {
return $this->readJSONFieldValueFromCustomFieldStorage($value, array());
}
}

View file

@ -1,7 +1,7 @@
<?php
final class DifferentialBlameRevisionCommitMessageField
extends DifferentialCommitMessageField {
extends DifferentialCommitMessageCustomField {
const FIELDKEY = 'blameRevision';
@ -15,8 +15,8 @@ final class DifferentialBlameRevisionCommitMessageField
);
}
public function isFieldEnabled() {
return $this->isCustomFieldEnabled('phabricator:blame-revision');
public function getCustomFieldKey() {
return 'phabricator:blame-revision';
}
}

View file

@ -0,0 +1,63 @@
<?php
abstract class DifferentialCommitMessageCustomField
extends DifferentialCommitMessageField {
abstract public function getCustomFieldKey();
public function getFieldOrder() {
$custom_key = $this->getCustomFieldKey();
return 100000 + $this->getCustomFieldOrder($custom_key);
}
public function isFieldEnabled() {
$custom_key = $this->getCustomFieldKey();
return $this->isCustomFieldEnabled($custom_key);
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
$custom_key = $this->getCustomFieldKey();
$value = $this->readCustomFieldValue($revision, $custom_key);
return $value;
}
protected function readFieldValueFromCustomFieldStorage($value) {
return $value;
}
protected function readJSONFieldValueFromCustomFieldStorage(
$value,
$default) {
try {
return phutil_json_decode($value);
} catch (PhutilJSONParserException $ex) {
return $default;
}
}
protected function readCustomFieldValue(
DifferentialRevision $revision,
$key) {
$value = idx($this->getCustomFieldStorage(), $key);
return $this->readFieldValueFromCustomFieldStorage($value);
}
protected function getCustomFieldOrder($key) {
$field_list = PhabricatorCustomField::getObjectFields(
new DifferentialRevision(),
DifferentialCustomField::ROLE_COMMITMESSAGE);
$fields = $field_list->getFields();
$idx = 0;
foreach ($fields as $field_key => $value) {
if ($key === $field_key) {
return $idx;
}
$idx++;
}
return $idx;
}
}

View file

@ -4,6 +4,7 @@ abstract class DifferentialCommitMessageField
extends Phobject {
private $viewer;
private $customFieldStorage;
final public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
@ -14,7 +15,17 @@ abstract class DifferentialCommitMessageField
return $this->viewer;
}
final public function setCustomFieldStorage(array $custom_field_storage) {
$this->customFieldStorage = $custom_field_storage;
return $this;
}
final public function getCustomFieldStorage() {
return $this->customFieldStorage;
}
abstract public function getFieldName();
abstract public function getFieldOrder();
public function isFieldEnabled() {
return true;
@ -32,6 +43,30 @@ abstract class DifferentialCommitMessageField
return $value;
}
public function isFieldEditable() {
return true;
}
public function isTemplateField() {
return true;
}
public function readFieldValueFromConduit($value) {
return $this->readStringFieldValueFromConduit($value);
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
return null;
}
public function renderFieldValue($value) {
if (!strlen($value)) {
return null;
}
return $value;
}
final public function getCommitMessageFieldKey() {
return $this->getPhobjectClassConstant('FIELDKEY', 64);
}
@ -55,6 +90,7 @@ abstract class DifferentialCommitMessageField
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getCommitMessageFieldKey')
->setSortMethod('getFieldOrder')
->execute();
}
@ -80,6 +116,62 @@ abstract class DifferentialCommitMessageField
->execute();
}
protected function renderHandleList(array $phids, array $suffixes = array()) {
if (!$phids) {
return null;
}
$handles = $this->getViewer()->loadHandles($phids);
$out = array();
foreach ($handles as $handle) {
$phid = $handle->getPHID();
if ($handle->getPolicyFiltered()) {
$token = $phid;
} else if ($handle->isComplete()) {
$token = $handle->getCommandLineObjectName();
}
$suffix = idx($suffixes, $phid);
$token = $token.$suffix;
$out[] = $token;
}
return implode(', ', $out);
}
protected function readStringFieldValueFromConduit($value) {
if ($value === null) {
return $value;
}
if (!is_string($value)) {
throw new Exception(
pht(
'Field "%s" expects a string value, but received a value of type '.
'"%s".',
$this->getCommitMessageFieldKey(),
gettype($value)));
}
return $value;
}
protected function readStringListFieldValueFromConduit($value) {
if (!is_array($value)) {
throw new Exception(
pht(
'Field "%s" expects a list of strings, but received a value of type '.
'"%s".',
$this->getCommitMessageFieldKey(),
gettype($value)));
}
return $value;
}
protected function isCustomFieldEnabled($key) {
$field_list = PhabricatorCustomField::getObjectFields(
new DifferentialRevision(),

View file

@ -9,4 +9,12 @@ final class DifferentialConflictsCommitMessageField
return pht('Conflicts');
}
public function getFieldOrder() {
return 900000;
}
public function isFieldEditable() {
return false;
}
}

View file

@ -9,4 +9,12 @@ final class DifferentialGitSVNIDCommitMessageField
return pht('git-svn-id');
}
public function getFieldOrder() {
return 900001;
}
public function isFieldEditable() {
return false;
}
}

View file

@ -1,7 +1,7 @@
<?php
final class DifferentialJIRAIssuesCommitMessageField
extends DifferentialCommitMessageField {
extends DifferentialCommitMessageCustomField {
const FIELDKEY = 'jira.issues';
@ -16,12 +16,28 @@ final class DifferentialJIRAIssuesCommitMessageField
);
}
public function getCustomFieldKey() {
return 'phabricator:jira-issues';
}
public function parseFieldValue($value) {
return preg_split('/[\s,]+/', $value, $limit = -1, PREG_SPLIT_NO_EMPTY);
}
public function isFieldEnabled() {
return (bool)PhabricatorJIRAAuthProvider::getJIRAProvider();
protected function readFieldValueFromCustomFieldStorage($value) {
return $this->readJSONFieldValueFromCustomFieldStorage($value, array());
}
public function readFieldValueFromConduit($value) {
return $this->readStringListFieldValueFromConduit($value);
}
public function renderFieldValue($value) {
if (!$value) {
return null;
}
return implode(', ', $value);
}
}

View file

@ -1,7 +1,7 @@
<?php
final class DifferentialRevertPlanCommitMessageField
extends DifferentialCommitMessageField {
extends DifferentialCommitMessageCustomField {
const FIELDKEY = 'revertPlan';
@ -9,8 +9,8 @@ final class DifferentialRevertPlanCommitMessageField
return pht('Revert Plan');
}
public function isFieldEnabled() {
return $this->isCustomFieldEnabled('phabricator:revert-plan');
public function getCustomFieldKey() {
return 'phabricator:revert-plan';
}
}

View file

@ -9,6 +9,10 @@ final class DifferentialReviewedByCommitMessageField
return pht('Reviewed By');
}
public function getFieldOrder() {
return 5000;
}
public function parseFieldValue($value) {
return $this->parseObjectList(
$value,
@ -19,4 +23,34 @@ final class DifferentialReviewedByCommitMessageField
$allow_partial = true);
}
public function isFieldEditable() {
return false;
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
if (!$revision->getPHID()) {
return array();
}
$phids = array();
foreach ($revision->getReviewerStatus() as $reviewer) {
switch ($reviewer->getStatus()) {
case DifferentialReviewerStatus::STATUS_ACCEPTED:
case DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER:
$phids[] = $reviewer->getReviewerPHID();
break;
}
}
return $phids;
}
public function readFieldValueFromConduit($value) {
return $this->readStringListFieldValueFromConduit($value);
}
public function renderFieldValue($value) {
return $this->renderHandleList($value);
}
}

View file

@ -9,6 +9,10 @@ final class DifferentialReviewersCommitMessageField
return pht('Reviewers');
}
public function getFieldOrder() {
return 4000;
}
public function getFieldAliases() {
return array(
'Reviewer',
@ -29,6 +33,50 @@ final class DifferentialReviewersCommitMessageField
return $this->flattenReviewers($results);
}
public function readFieldValueFromConduit($value) {
return $this->readStringListFieldValueFromConduit($value);
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
if (!$revision->getPHID()) {
return array();
}
$status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING;
$results = array();
foreach ($revision->getReviewerStatus() as $reviewer) {
if ($reviewer->getStatus() == $status_blocking) {
$suffixes = array('!' => '!');
} else {
$suffixes = array();
}
$results[] = array(
'phid' => $reviewer->getReviewerPHID(),
'suffixes' => $suffixes,
);
}
return $this->flattenReviewers($results);
}
public function renderFieldValue($value) {
$value = $this->inflateReviewers($value);
$phid_list = array();
$suffix_map = array();
foreach ($value as $reviewer) {
$phid = $reviewer['phid'];
$phid_list[] = $phid;
if (isset($reviewer['suffixes']['!'])) {
$suffix_map[$phid] = '!';
}
}
return $this->renderHandleList($phid_list, $suffix_map);
}
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.

View file

@ -9,6 +9,14 @@ final class DifferentialRevisionIDCommitMessageField
return pht('Differential Revision');
}
public function getFieldOrder() {
return 200000;
}
public function isTemplateField() {
return false;
}
public function parseFieldValue($value) {
// If the value is just "D123" or similar, parse the ID from it directly.
$value = trim($value);
@ -49,4 +57,23 @@ final class DifferentialRevisionIDCommitMessageField
return null;
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
return $revision->getID();
}
public function readFieldValueFromConduit($value) {
if (is_int($value)) {
$value = (string)$value;
}
return $this->readStringFieldValueFromConduit($value);
}
public function renderFieldValue($value) {
if (!strlen($value)) {
return null;
}
return PhabricatorEnv::getProductionURI('/D'.$value);
}
}

View file

@ -9,6 +9,10 @@ final class DifferentialSubscribersCommitMessageField
return pht('Subscribers');
}
public function getFieldOrder() {
return 6000;
}
public function getFieldAliases() {
return array(
'CC',
@ -27,4 +31,21 @@ final class DifferentialSubscribersCommitMessageField
));
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
if (!$revision->getPHID()) {
return array();
}
return PhabricatorSubscribersQuery::loadSubscribersForPHID(
$revision->getPHID());
}
public function readFieldValueFromConduit($value) {
return $this->readStringListFieldValueFromConduit($value);
}
public function renderFieldValue($value) {
return $this->renderHandleList($value);
}
}

View file

@ -9,4 +9,12 @@ final class DifferentialSummaryCommitMessageField
return pht('Summary');
}
public function getFieldOrder() {
return 2000;
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
return $revision->getSummary();
}
}

View file

@ -9,6 +9,10 @@ final class DifferentialTagsCommitMessageField
return pht('Tags');
}
public function getFieldOrder() {
return 7000;
}
public function getFieldAliases() {
return array(
'Tag',
@ -17,6 +21,10 @@ final class DifferentialTagsCommitMessageField
);
}
public function isTemplateField() {
return false;
}
public function parseFieldValue($value) {
return $this->parseObjectList(
$value,
@ -25,4 +33,26 @@ final class DifferentialTagsCommitMessageField
));
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
if (!$revision->getPHID()) {
return array();
}
$projects = PhabricatorEdgeQuery::loadDestinationPHIDs(
$revision->getPHID(),
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$projects = array_reverse($projects);
return $projects;
}
public function readFieldValueFromConduit($value) {
return $this->readStringListFieldValueFromConduit($value);
}
public function renderFieldValue($value) {
return $this->renderHandleList($value);
}
}

View file

@ -9,6 +9,10 @@ final class DifferentialTasksCommitMessageField
return pht('Maniphest Tasks');
}
public function getFieldOrder() {
return 8000;
}
public function getFieldAliases() {
return array(
'Task',
@ -17,6 +21,10 @@ final class DifferentialTasksCommitMessageField
);
}
public function isTemplateField() {
return false;
}
public function parseFieldValue($value) {
return $this->parseObjectList(
$value,
@ -25,4 +33,25 @@ final class DifferentialTasksCommitMessageField
));
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
if (!$revision->getPHID()) {
return array();
}
$projects = PhabricatorEdgeQuery::loadDestinationPHIDs(
$revision->getPHID(),
DifferentialRevisionHasTaskEdgeType::EDGECONST);
$projects = array_reverse($projects);
return $projects;
}
public function readFieldValueFromConduit($value) {
return $this->readStringListFieldValueFromConduit($value);
}
public function renderFieldValue($value) {
return $this->renderHandleList($value);
}
}

View file

@ -9,6 +9,10 @@ final class DifferentialTestPlanCommitMessageField
return pht('Test Plan');
}
public function getFieldOrder() {
return 3000;
}
public function getFieldAliases() {
return array(
'Testplan',
@ -33,4 +37,8 @@ final class DifferentialTestPlanCommitMessageField
}
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
return $revision->getTestPlan();
}
}

View file

@ -9,6 +9,10 @@ final class DifferentialTitleCommitMessageField
return pht('Title');
}
public function getFieldOrder() {
return 1000;
}
public static function getDefaultTitle() {
return pht('<<Replace this line with your revision title>');
}
@ -33,4 +37,14 @@ final class DifferentialTitleCommitMessageField
}
}
public function readFieldValueFromObject(DifferentialRevision $revision) {
$value = $revision->getTitle();
if (!strlen($value)) {
return self::getDefaultTitle();
}
return $value;
}
}

View file

@ -70,6 +70,7 @@ final class DifferentialRevision extends DifferentialDAO
->setAuthorPHID($actor->getPHID())
->attachRelationships(array())
->attachRepository(null)
->attachActiveDiff(null)
->attachReviewerStatus(array())
->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW);
}