diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 61100f848f..d40b8c6805 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -139,6 +139,7 @@ phutil_register_library_map(array( 'DifferentialAuxiliaryField' => 'applications/differential/storage/auxiliaryfield', 'DifferentialBlameRevisionFieldSpecification' => 'applications/differential/field/specification/blamerev', 'DifferentialCCWelcomeMail' => 'applications/differential/mail/ccwelcome', + 'DifferentialCCsFieldSpecification' => 'applications/differential/field/specification/ccs', 'DifferentialChangeType' => 'applications/differential/constants/changetype', 'DifferentialChangeset' => 'applications/differential/storage/changeset', 'DifferentialChangesetDetailView' => 'applications/differential/view/changesetdetailview', @@ -180,6 +181,7 @@ phutil_register_library_map(array( 'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/inlinecommentpreview', 'DifferentialInlineCommentView' => 'applications/differential/view/inlinecomment', 'DifferentialLinesFieldSpecification' => 'applications/differential/field/specification/lines', + 'DifferentialLintFieldSpecification' => 'applications/differential/field/specification/lint', 'DifferentialLintStatus' => 'applications/differential/constants/lintstatus', 'DifferentialMail' => 'applications/differential/mail/base', 'DifferentialManiphestTasksFieldSpecification' => 'applications/differential/field/specification/maniphesttasks', @@ -189,6 +191,7 @@ phutil_register_library_map(array( 'DifferentialReplyHandler' => 'applications/differential/replyhandler', 'DifferentialRevertPlanFieldSpecification' => 'applications/differential/field/specification/revertplan', 'DifferentialReviewRequestMail' => 'applications/differential/mail/reviewrequest', + 'DifferentialReviewersFieldSpecification' => 'applications/differential/field/specification/reviewers', 'DifferentialRevision' => 'applications/differential/storage/revision', 'DifferentialRevisionCommentListView' => 'applications/differential/view/revisioncommentlist', 'DifferentialRevisionCommentView' => 'applications/differential/view/revisioncomment', @@ -200,10 +203,12 @@ phutil_register_library_map(array( 'DifferentialRevisionListController' => 'applications/differential/controller/revisionlist', 'DifferentialRevisionListData' => 'applications/differential/data/revisionlist', 'DifferentialRevisionStatus' => 'applications/differential/constants/revisionstatus', + 'DifferentialRevisionStatusFieldSpecification' => 'applications/differential/field/specification/revisionstatus', 'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/revisionupdatehistory', 'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview', 'DifferentialSubscribeController' => 'applications/differential/controller/subscribe', 'DifferentialTasksAttacher' => 'applications/differential/tasks', + 'DifferentialUnitFieldSpecification' => 'applications/differential/field/specification/unit', 'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus', 'DifferentialUnitTestResult' => 'applications/differential/constants/unittestresult', 'DifferentialViewTime' => 'applications/differential/storage/viewtime', @@ -792,6 +797,7 @@ phutil_register_library_map(array( 'DifferentialAuxiliaryField' => 'DifferentialDAO', 'DifferentialBlameRevisionFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialCCWelcomeMail' => 'DifferentialReviewRequestMail', + 'DifferentialCCsFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialChangeset' => 'DifferentialDAO', 'DifferentialChangesetDetailView' => 'AphrontView', 'DifferentialChangesetListView' => 'AphrontView', @@ -820,6 +826,7 @@ phutil_register_library_map(array( 'DifferentialInlineCommentPreviewController' => 'DifferentialController', 'DifferentialInlineCommentView' => 'AphrontView', 'DifferentialLinesFieldSpecification' => 'DifferentialFieldSpecification', + 'DifferentialLintFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialManiphestTasksFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail', 'DifferentialPathFieldSpecification' => 'DifferentialFieldSpecification', @@ -827,15 +834,18 @@ phutil_register_library_map(array( 'DifferentialReplyHandler' => 'PhabricatorMailReplyHandler', 'DifferentialRevertPlanFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialReviewRequestMail' => 'DifferentialMail', + 'DifferentialReviewersFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialRevision' => 'DifferentialDAO', 'DifferentialRevisionCommentListView' => 'AphrontView', 'DifferentialRevisionCommentView' => 'AphrontView', 'DifferentialRevisionDetailView' => 'AphrontView', 'DifferentialRevisionEditController' => 'DifferentialController', 'DifferentialRevisionListController' => 'DifferentialController', + 'DifferentialRevisionStatusFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialRevisionUpdateHistoryView' => 'AphrontView', 'DifferentialRevisionViewController' => 'DifferentialController', 'DifferentialSubscribeController' => 'DifferentialController', + 'DifferentialUnitFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialViewTime' => 'DifferentialDAO', 'DiffusionBranchTableView' => 'DiffusionView', 'DiffusionBrowseController' => 'DiffusionController', diff --git a/src/applications/differential/controller/revisionview/DifferentialRevisionViewController.php b/src/applications/differential/controller/revisionview/DifferentialRevisionViewController.php index accf29754a..a9dc09b4a7 100644 --- a/src/applications/differential/controller/revisionview/DifferentialRevisionViewController.php +++ b/src/applications/differential/controller/revisionview/DifferentialRevisionViewController.php @@ -58,10 +58,7 @@ class DifferentialRevisionViewController extends DifferentialController { $diff_vs = null; } - $aux_fields = $this->loadAuxiliaryFields($revision); - foreach ($aux_fields as $aux_field) { - $aux_field->setDiff($target); - } + $aux_fields = $this->loadAuxiliaryFields($revision, $target); list($changesets, $vs_map, $rendering_references) = $this->loadChangesetsAndVsMap($diffs, $diff_vs, $target); @@ -156,47 +153,31 @@ class DifferentialRevisionViewController extends DifferentialController { $visible_changesets = $changesets; } - $diff_properties = id(new DifferentialDiffProperty())->loadAllWhere( - 'diffID = %d AND name IN (%Ls)', - $target->getID(), - array( - 'arc:lint', - 'arc:unit', - )); - $diff_properties = mpull($diff_properties, 'getData', 'getName'); - $revision_detail = new DifferentialRevisionDetailView(); $revision_detail->setRevision($revision); $revision_detail->setAuxiliaryFields($aux_fields); + $actions = $this->getRevisionActions($revision); + $custom_renderer_class = PhabricatorEnv::getEnvConfig( 'differential.revision-custom-detail-renderer'); if ($custom_renderer_class) { + + // TODO: Either deprecate generateProperties() or build a better version + // of the action links and deprecate the whole class. Custom fields + // now provide a much more powerful version of generateProperties(). + PhutilSymbolLoader::loadClass($custom_renderer_class); $custom_renderer = newv($custom_renderer_class, array()); - } else { - $custom_renderer = null; - } + $properties = $custom_renderer->generateProperties($revision, $target); + $revision_detail->setProperties($properties); - $properties = $this->getRevisionProperties( - $revision, - $target, - $handles, - $diff_properties); - if ($custom_renderer) { - $properties = array_merge( - $properties, - $custom_renderer->generateProperties($revision, $target)); - } - - $revision_detail->setProperties($properties); - - $actions = $this->getRevisionActions($revision); - if ($custom_renderer) { $actions = array_merge( $actions, $custom_renderer->generateActionLinks($revision, $target)); + } else { + $revision_detail->setProperties(array()); } $whitespace = $request->getStr( @@ -307,143 +288,6 @@ class DifferentialRevisionViewController extends DifferentialController { return $comments; } - private function getRevisionProperties( - DifferentialRevision $revision, - DifferentialDiff $diff, - array $handles, - array $diff_properties) { - - $properties = array(); - - $status = $revision->getStatus(); - $next_step = null; - if ($status == DifferentialRevisionStatus::ACCEPTED) { - switch ($diff->getSourceControlSystem()) { - case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: - $next_step = 'arc amend --revision '.$revision->getID(); - break; - case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: - $next_step = 'arc commit --revision '.$revision->getID(); - break; - } - if ($next_step) { - $next_step = - ' · '. - 'Next step: '.phutil_escape_html($next_step).''; - } - } - $status = DifferentialRevisionStatus::getNameForRevisionStatus($status); - $properties['Revision Status'] = ''.$status.''.$next_step; - - $properties['Reviewers'] = $this->renderHandleLinkList( - array_select_keys( - $handles, - $revision->getReviewers())); - - $properties['CCs'] = $this->renderHandleLinkList( - array_select_keys( - $handles, - $revision->getCCPHIDs())); - - $lstar = DifferentialRevisionUpdateHistoryView::renderDiffLintStar($diff); - $lmsg = DifferentialRevisionUpdateHistoryView::getDiffLintMessage($diff); - $ldata = idx($diff_properties, 'arc:lint'); - $ltail = null; - if ($ldata) { - $ldata = igroup($ldata, 'path'); - $lint_messages = array(); - foreach ($ldata as $path => $messages) { - $message_markup = array(); - foreach ($messages as $message) { - $path = idx($message, 'path'); - $line = idx($message, 'line'); - - $code = idx($message, 'code'); - $severity = idx($message, 'severity'); - - $name = idx($message, 'name'); - $description = idx($message, 'description'); - - $message_markup[] = - '
  • '. - ''. - phutil_escape_html(ucwords($severity)). - ''. - ' '. - '('.phutil_escape_html($code).') '. - phutil_escape_html($name). - ' at line '.phutil_escape_html($line). - '

    '.phutil_escape_html($description).'

    '. - '
  • '; - } - $lint_messages[] = - '
  • '. - 'Lint for '.phutil_escape_html($path).''. - ''. - '
  • '; - } - $ltail = - '
    '. - ''. - '
    '; - } - - $properties['Lint'] = $lstar.' '.$lmsg.$ltail; - - $ustar = DifferentialRevisionUpdateHistoryView::renderDiffUnitStar($diff); - $umsg = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff); - - $postponed_count = 0; - $udata = idx($diff_properties, 'arc:unit'); - $utail = null; - if ($udata) { - $unit_messages = array(); - foreach ($udata as $test) { - $name = phutil_escape_html(idx($test, 'name')); - $result = phutil_escape_html(idx($test, 'result')); - - if ($result != DifferentialUnitTestResult::RESULT_POSTPONED && - $result != DifferentialUnitTestResult::RESULT_PASS) { - $userdata = phutil_escape_html(idx($test, 'userdata')); - if (strlen($userdata) > 256) { - $userdata = substr($userdata, 0, 256).'...'; - } - $userdata = str_replace("\n", '
    ', $userdata); - $unit_messages[] = - ''. - ''.$name.''. - ''. - '
    '. - strtoupper($result). - '
    '. - ''. - ''.$userdata.''. - ''; - - $utail = - '
    '. - ''. - implode("\n", $unit_messages). - '
    '. - '
    '; - } else if ($result == DifferentialUnitTestResult::RESULT_POSTPONED) { - $postponed_count++; - } - } - } - - if ($postponed_count > 0 && - $diff->getUnitStatus() == DifferentialUnitStatus::UNIT_POSTPONED) { - $umsg = $postponed_count.' '.$umsg; - } - - $properties['Unit'] = $ustar.' '.$umsg.$utail; - - return $properties; - } - private function getRevisionActions(DifferentialRevision $revision) { $viewer_phid = $this->getRequest()->getUser()->getPHID(); $viewer_is_owner = ($revision->getAuthorPHID() == $viewer_phid); @@ -512,14 +356,6 @@ class DifferentialRevisionViewController extends DifferentialController { return $links; } - - private function renderHandleLinkList(array $list) { - if (empty($list)) { - return 'None'; - } - return implode(', ', mpull($list, 'renderLink')); - } - private function getRevisionCommentActions(DifferentialRevision $revision) { $actions = array( @@ -674,7 +510,9 @@ class DifferentialRevisionViewController extends DifferentialController { ->replace(); } - private function loadAuxiliaryFields(DifferentialRevision $revision) { + private function loadAuxiliaryFields( + DifferentialRevision $revision, + DifferentialDiff $diff) { $aux_fields = DifferentialFieldSelector::newSelector() ->getFieldSpecifications(); foreach ($aux_fields as $key => $aux_field) { @@ -683,9 +521,42 @@ class DifferentialRevisionViewController extends DifferentialController { } } - return DifferentialAuxiliaryField::loadFromStorage( + $aux_fields = DifferentialAuxiliaryField::loadFromStorage( $revision, $aux_fields); + + $aux_props = array(); + foreach ($aux_fields as $key => $aux_field) { + $aux_field->setDiff($diff); + $aux_props[$key] = $aux_field->getRequiredDiffProperties(); + } + + $required_properties = array_mergev($aux_props); + $property_map = array(); + if ($required_properties) { + $properties = id(new DifferentialDiffProperty())->loadAllWhere( + 'diffID = %d AND name IN (%Ls)', + $diff->getID(), + $required_properties); + $property_map = mpull($properties, 'getData', 'getName'); + } + + foreach ($aux_fields as $key => $aux_field) { + // Give each field only the properties it specifically required, and + // set 'null' for each requested key which we didn't actually load a + // value for (otherwise, getDiffProperty() will throw). + if ($aux_props[$key]) { + $props = array_select_keys($property_map, $aux_props[$key]) + + array_fill_keys($aux_props[$key], null); + } else { + $props = array(); + } + + $aux_field->setDiffProperties($props); + } + + return $aux_fields; } + } diff --git a/src/applications/differential/controller/revisionview/__init__.php b/src/applications/differential/controller/revisionview/__init__.php index 042008c08e..a7809f0195 100644 --- a/src/applications/differential/controller/revisionview/__init__.php +++ b/src/applications/differential/controller/revisionview/__init__.php @@ -9,8 +9,6 @@ phutil_require_module('phabricator', 'aphront/response/404'); phutil_require_module('phabricator', 'applications/differential/constants/action'); phutil_require_module('phabricator', 'applications/differential/constants/revisionstatus'); -phutil_require_module('phabricator', 'applications/differential/constants/unitstatus'); -phutil_require_module('phabricator', 'applications/differential/constants/unittestresult'); phutil_require_module('phabricator', 'applications/differential/controller/base'); phutil_require_module('phabricator', 'applications/differential/field/selector/base'); phutil_require_module('phabricator', 'applications/differential/parser/changeset'); @@ -30,7 +28,6 @@ phutil_require_module('phabricator', 'applications/differential/view/revisiondet phutil_require_module('phabricator', 'applications/differential/view/revisionupdatehistory'); phutil_require_module('phabricator', 'applications/draft/storage/draft'); phutil_require_module('phabricator', 'applications/phid/handle/data'); -phutil_require_module('phabricator', 'applications/repository/constants/repositorytype'); phutil_require_module('phabricator', 'infrastructure/celerity/api'); phutil_require_module('phabricator', 'infrastructure/env'); phutil_require_module('phabricator', 'infrastructure/javelin/api'); diff --git a/src/applications/differential/editor/revision/DifferentialRevisionEditor.php b/src/applications/differential/editor/revision/DifferentialRevisionEditor.php index 3f56616304..6611492e51 100644 --- a/src/applications/differential/editor/revision/DifferentialRevisionEditor.php +++ b/src/applications/differential/editor/revision/DifferentialRevisionEditor.php @@ -165,12 +165,25 @@ class DifferentialRevisionEditor { if ($revision->getAuthorPHID() === null) { $revision->setAuthorPHID($this->getActorPHID()); } - + if ($revision->getRevertPlan() === null) { + $revision->setRevertPlan(''); + } + if ($revision->getBlameRevision() === null) { + $revision->setBlameRevision(''); + } + if ($revision->getSummary() === null) { + $revision->setSummary(''); + } + if ($revision->getTestPlan() === null) { + $revision->setTestPlan(''); + } $revision->save(); } $revision->loadRelationships(); + $this->willWriteRevision(); + if ($this->reviewers === null) { $this->reviewers = $revision->getReviewers(); } @@ -368,6 +381,8 @@ class DifferentialRevisionEditor { $revision->save(); + $this->didWriteRevision(); + $event_data = array( 'revision_id' => $revision->getID(), 'revision_phid' => $revision->getPHID(), @@ -689,6 +704,17 @@ class DifferentialRevisionEditor { } } + private function willWriteRevision() { + foreach ($this->auxiliaryFields as $aux_field) { + $aux_field->willWriteRevision($this); + } + } + + private function didWriteRevision() { + foreach ($this->auxiliaryFields as $aux_field) { + $aux_field->didWriteRevision($this); + } + } } diff --git a/src/applications/differential/field/selector/default/DifferentialDefaultFieldSelector.php b/src/applications/differential/field/selector/default/DifferentialDefaultFieldSelector.php index 5c31d0fb02..0c9380c8ac 100644 --- a/src/applications/differential/field/selector/default/DifferentialDefaultFieldSelector.php +++ b/src/applications/differential/field/selector/default/DifferentialDefaultFieldSelector.php @@ -21,10 +21,15 @@ final class DifferentialDefaultFieldSelector public function getFieldSpecifications() { return array( + new DifferentialRevisionStatusFieldSpecification(), new DifferentialAuthorFieldSpecification(), + new DifferentialReviewersFieldSpecification(), + new DifferentialCCsFieldSpecification(), + new DifferentialUnitFieldSpecification(), + new DifferentialLintFieldSpecification(), + new DifferentialCommitsFieldSpecification(), new DifferentialDependenciesFieldSpecification(), new DifferentialManiphestTasksFieldSpecification(), - new DifferentialCommitsFieldSpecification(), new DifferentialHostFieldSpecification(), new DifferentialPathFieldSpecification(), new DifferentialLinesFieldSpecification(), diff --git a/src/applications/differential/field/selector/default/__init__.php b/src/applications/differential/field/selector/default/__init__.php index b8cd112fb7..85864635b0 100644 --- a/src/applications/differential/field/selector/default/__init__.php +++ b/src/applications/differential/field/selector/default/__init__.php @@ -10,13 +10,18 @@ phutil_require_module('phabricator', 'applications/differential/field/selector/b phutil_require_module('phabricator', 'applications/differential/field/specification/applypatch'); phutil_require_module('phabricator', 'applications/differential/field/specification/arcanistproject'); phutil_require_module('phabricator', 'applications/differential/field/specification/author'); +phutil_require_module('phabricator', 'applications/differential/field/specification/ccs'); phutil_require_module('phabricator', 'applications/differential/field/specification/commits'); phutil_require_module('phabricator', 'applications/differential/field/specification/dependencies'); phutil_require_module('phabricator', 'applications/differential/field/specification/exportpatch'); phutil_require_module('phabricator', 'applications/differential/field/specification/host'); phutil_require_module('phabricator', 'applications/differential/field/specification/lines'); +phutil_require_module('phabricator', 'applications/differential/field/specification/lint'); phutil_require_module('phabricator', 'applications/differential/field/specification/maniphesttasks'); phutil_require_module('phabricator', 'applications/differential/field/specification/path'); +phutil_require_module('phabricator', 'applications/differential/field/specification/reviewers'); +phutil_require_module('phabricator', 'applications/differential/field/specification/revisionstatus'); +phutil_require_module('phabricator', 'applications/differential/field/specification/unit'); phutil_require_source('DifferentialDefaultFieldSelector.php'); diff --git a/src/applications/differential/field/specification/base/DifferentialFieldSpecification.php b/src/applications/differential/field/specification/base/DifferentialFieldSpecification.php index 4e87173a1e..ae036cfeb4 100644 --- a/src/applications/differential/field/specification/base/DifferentialFieldSpecification.php +++ b/src/applications/differential/field/specification/base/DifferentialFieldSpecification.php @@ -28,7 +28,7 @@ * @task edit Extending the Revision Edit Interface * @task view Extending the Revision View Interface * @task conduit Extending the Conduit View Interface - * @task handles Loading Handles + * @task load Loading Additional Data * @task context Contextual Data */ abstract class DifferentialFieldSpecification { @@ -36,6 +36,7 @@ abstract class DifferentialFieldSpecification { private $revision; private $diff; private $handles; + private $diffProperties; /* -( Storage )------------------------------------------------------------ */ @@ -174,11 +175,34 @@ abstract class DifferentialFieldSpecification { return; } + /** + * @task edit + */ + public function willWriteRevision(DifferentialRevisionEditor $editor) { + return; + } + + /** + * @task edit + */ + public function didWriteRevision(DifferentialRevisionEditor $editor) { + return; + } + /* -( Extending the Revision View Interface )------------------------------ */ /** + * Determine if this field should appear on the revision detail view + * interface. One use of this interface is to add purely informational + * fields to the revision view, without any sort of backing storage. + * + * If you return true from this method, you must implement the methods + * @{method:renderLabelForRevisionView} and + * @{method:renderValueForRevisionView}. + * + * @return bool True if this field should appear when viewing a revision. * @task view */ public function shouldAppearOnRevisionView() { @@ -187,6 +211,13 @@ abstract class DifferentialFieldSpecification { /** + * Return a string field label which will appear in the revision detail + * table. + * + * You must implement this method if you return true from + * @{method:shouldAppearOnRevisionView}. + * + * @return string Label for field in revision detail view. * @task view */ public function renderLabelForRevisionView() { @@ -195,6 +226,16 @@ abstract class DifferentialFieldSpecification { /** + * Return a markup block representing the field for the revision detail + * view. Note that you can return null to suppress display (for instance, + * if the field shows related objects of some type and the revision doesn't + * have any related objects). + * + * You must implement this method if you return true from + * @{method:shouldAppearOnRevisionView}. + * + * @return string|null Display markup for field value, or null to suppress + * field rendering. * @task view */ public function renderValueForRevisionView() { @@ -231,7 +272,7 @@ abstract class DifferentialFieldSpecification { } -/* -( Loading Handles )---------------------------------------------------- */ +/* -( Loading Additional Data )-------------------------------------------- */ /** @@ -248,7 +289,7 @@ abstract class DifferentialFieldSpecification { * You can later retrieve these handles by calling @{method:getHandle}. * * @return list List of PHIDs to load handles for. - * @task handles + * @task load */ protected function getRequiredHandlePHIDs() { return array(); @@ -263,7 +304,7 @@ abstract class DifferentialFieldSpecification { * need. * * @return list List of PHIDs to load handles for. - * @task handles + * @task load */ public function getRequiredHandlePHIDsForRevisionView() { return $this->getRequiredHandlePHIDs(); @@ -278,13 +319,24 @@ abstract class DifferentialFieldSpecification { * need. * * @return list List of PHIDs to load handles for. - * @task handles + * @task load */ public function getRequiredHandlePHIDsForEdit() { return $this->getRequiredHandlePHIDs(); } + /** + * Specify which diff properties this field needs to load. + * + * @return list List of diff property keys this field requires. + * @task load + */ + public function getRequiredDiffProperties() { + return array(); + } + + /* -( Contextual Data )---------------------------------------------------- */ @@ -312,6 +364,14 @@ abstract class DifferentialFieldSpecification { return $this; } + /** + * @task context + */ + final public function setDiffProperties(array $diff_properties) { + $this->diffProperties = $diff_properties; + return $this; + } + /** * @task context */ @@ -341,6 +401,9 @@ abstract class DifferentialFieldSpecification { * @task context */ final protected function getHandle($phid) { + if ($this->handles === null) { + throw new DifferentialFieldDataNotAvailableException($this); + } if (empty($this->handles[$phid])) { $class = get_class($this); throw new Exception( @@ -351,4 +414,30 @@ abstract class DifferentialFieldSpecification { return $this->handles[$phid]; } + /** + * Get a diff property which this field previously requested by returning + * the key from @{method:getRequiredDiffProperties}. + * + * @param string Diff property key. + * @return string|null Diff property, or null if the property does not have + * a value. + * @task context + */ + final public function getDiffProperty($key) { + if ($this->diffProperties === null) { + // This will be set to some (possibly empty) array if we've loaded + // properties, so null means diff properties aren't available in this + // context. + throw new DifferentialFieldDataNotAvailableException($this); + } + if (!array_key_exists($key, $this->diffProperties)) { + $class = get_class($this); + throw new Exception( + "A differential field (of class '{$class}') is attempting to retrieve ". + "a diff property ('{$key}') which it did not request. Return all ". + "diff property keys you need from getRequiredDiffProperties()."); + } + return $this->diffProperties[$key]; + } + } diff --git a/src/applications/differential/field/specification/ccs/DifferentialCCsFieldSpecification.php b/src/applications/differential/field/specification/ccs/DifferentialCCsFieldSpecification.php new file mode 100644 index 0000000000..ed57ab83fc --- /dev/null +++ b/src/applications/differential/field/specification/ccs/DifferentialCCsFieldSpecification.php @@ -0,0 +1,53 @@ +getCCPHIDs(); + } + + public function renderLabelForRevisionView() { + return 'CCs:'; + } + + public function renderValueForRevisionView() { + $cc_phids = $this->getCCPHIDs(); + if (!$cc_phids) { + return 'None'; + } + + $links = array(); + foreach ($cc_phids as $cc_phid) { + $links[] = $this->getHandle($cc_phid)->renderLink(); + } + + return implode(', ', $links); + } + + private function getCCPHIDs() { + $revision = $this->getRevision(); + return $revision->getCCPHIDs(); + } + +} diff --git a/src/applications/differential/field/specification/ccs/__init__.php b/src/applications/differential/field/specification/ccs/__init__.php new file mode 100644 index 0000000000..f7e1685565 --- /dev/null +++ b/src/applications/differential/field/specification/ccs/__init__.php @@ -0,0 +1,12 @@ +getDiff(); + + $lstar = DifferentialRevisionUpdateHistoryView::renderDiffLintStar($diff); + $lmsg = DifferentialRevisionUpdateHistoryView::getDiffLintMessage($diff); + $ldata = $this->getDiffProperty('arc:lint'); + $ltail = null; + if ($ldata) { + $ldata = igroup($ldata, 'path'); + $lint_messages = array(); + foreach ($ldata as $path => $messages) { + $message_markup = array(); + foreach ($messages as $message) { + $path = idx($message, 'path'); + $line = idx($message, 'line'); + + $code = idx($message, 'code'); + $severity = idx($message, 'severity'); + + $name = idx($message, 'name'); + $description = idx($message, 'description'); + + $message_markup[] = + '
  • '. + ''. + phutil_escape_html(ucwords($severity)). + ''. + ' '. + '('.phutil_escape_html($code).') '. + phutil_escape_html($name). + ' at line '.phutil_escape_html($line). + '

    '.phutil_escape_html($description).'

    '. + '
  • '; + } + $lint_messages[] = + '
  • '. + 'Lint for '.phutil_escape_html($path).''. + ''. + '
  • '; + } + $ltail = + '
    '. + ''. + '
    '; + } + + return $lstar.' '.$lmsg.$ltail; + } +} diff --git a/src/applications/differential/field/specification/lint/__init__.php b/src/applications/differential/field/specification/lint/__init__.php new file mode 100644 index 0000000000..0041dfe5f7 --- /dev/null +++ b/src/applications/differential/field/specification/lint/__init__.php @@ -0,0 +1,16 @@ +getReviewerPHIDs(); + } + + public function renderLabelForRevisionView() { + return 'Reviewers:'; + } + + public function renderValueForRevisionView() { + $reviewer_phids = $this->getReviewerPHIDs(); + if (!$reviewer_phids) { + return 'None'; + } + + $links = array(); + foreach ($reviewer_phids as $reviewer_phid) { + $links[] = $this->getHandle($reviewer_phid)->renderLink(); + } + + return implode(', ', $links); + } + + private function getReviewerPHIDs() { + $revision = $this->getRevision(); + return $revision->getReviewers(); + } + +} diff --git a/src/applications/differential/field/specification/reviewers/__init__.php b/src/applications/differential/field/specification/reviewers/__init__.php new file mode 100644 index 0000000000..fb1adf0a61 --- /dev/null +++ b/src/applications/differential/field/specification/reviewers/__init__.php @@ -0,0 +1,12 @@ +getRevision(); + $diff = $this->getDiff(); + + $status = $revision->getStatus(); + $next_step = null; + if ($status == DifferentialRevisionStatus::ACCEPTED) { + switch ($diff->getSourceControlSystem()) { + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: + $next_step = 'arc amend --revision '.$revision->getID(); + break; + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: + $next_step = 'arc commit --revision '.$revision->getID(); + break; + } + if ($next_step) { + $next_step = + ' · '. + 'Next step: '.phutil_escape_html($next_step).''; + } + } + $status = DifferentialRevisionStatus::getNameForRevisionStatus($status); + return ''.$status.''.$next_step; + } + +} diff --git a/src/applications/differential/field/specification/revisionstatus/__init__.php b/src/applications/differential/field/specification/revisionstatus/__init__.php new file mode 100644 index 0000000000..c8649c3340 --- /dev/null +++ b/src/applications/differential/field/specification/revisionstatus/__init__.php @@ -0,0 +1,16 @@ +getDiff(); + + $ustar = DifferentialRevisionUpdateHistoryView::renderDiffUnitStar($diff); + $umsg = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff); + + $postponed_count = 0; + $udata = $this->getDiffProperty('arc:unit'); + $utail = null; + + if ($udata) { + $unit_messages = array(); + foreach ($udata as $test) { + $name = phutil_escape_html(idx($test, 'name')); + $result = phutil_escape_html(idx($test, 'result')); + + if ($result != DifferentialUnitTestResult::RESULT_POSTPONED && + $result != DifferentialUnitTestResult::RESULT_PASS) { + $userdata = phutil_escape_html(idx($test, 'userdata')); + if (strlen($userdata) > 256) { + $userdata = substr($userdata, 0, 256).'...'; + } + $userdata = str_replace("\n", '
    ', $userdata); + $unit_messages[] = + ''. + ''.$name.''. + ''. + '
    '. + strtoupper($result). + '
    '. + ''. + ''.$userdata.''. + ''; + + $utail = + '
    '. + ''. + implode("\n", $unit_messages). + '
    '. + '
    '; + } else if ($result == DifferentialUnitTestResult::RESULT_POSTPONED) { + $postponed_count++; + } + } + } + + if ($postponed_count > 0 && + $diff->getUnitStatus() == DifferentialUnitStatus::UNIT_POSTPONED) { + $umsg = $postponed_count.' '.$umsg; + } + + return $ustar.' '.$umsg.$utail; + } + +} diff --git a/src/applications/differential/field/specification/unit/__init__.php b/src/applications/differential/field/specification/unit/__init__.php new file mode 100644 index 0000000000..73b0a4571c --- /dev/null +++ b/src/applications/differential/field/specification/unit/__init__.php @@ -0,0 +1,18 @@ +