public function renderValueForRevisionView() { $diff = $this->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[] = '<li>' . '<span class="lint-severity-' . phutil_escape_html($severity) . '">' . phutil_escape_html(ucwords($severity)) . '</span>' . ' ' . '(' . phutil_escape_html($code) . ') ' . phutil_escape_html($name) . ' at line ' . phutil_escape_html($line) . '<p>' . phutil_escape_html($description) . '</p>' . '</li>'; } $lint_messages[] = '<li class="lint-file-block">' . 'Lint for <strong>' . phutil_escape_html($path) . '</strong>' . '<ul>' . implode("\n", $message_markup) . '</ul>' . '</li>'; } $ltail = '<div class="differential-lint-block">' . '<ul>' . implode("\n", $lint_messages) . '</ul>' . '</div>'; } return $lstar . ' ' . $lmsg . $ltail; }
public function renderValueForRevisionView() { $diff = $this->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 = idx($test, 'name'); $result = idx($test, 'result'); if ($result != DifferentialUnitTestResult::RESULT_POSTPONED && $result != DifferentialUnitTestResult::RESULT_PASS) { $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine(); $userdata = phutil_utf8_shorten(idx($test, 'userdata'), 512); $userdata = $engine->markupText($userdata); $unit_messages[] = '<li>' . '<span class="unit-result-' . phutil_escape_html($result) . '">' . phutil_escape_html(ucwords($result)) . '</span>' . ' ' . phutil_escape_html($name) . '<p>' . $userdata . '</p>' . '</li>'; } else { if ($result == DifferentialUnitTestResult::RESULT_POSTPONED) { $postponed_count++; } } } $uexcuse = $this->getUnitExcuse(); if ($unit_messages) { $utail = '<div class="differential-unit-block">' . $uexcuse . '<ul>' . implode("\n", $unit_messages) . '</ul>' . '</div>'; } } if ($postponed_count > 0 && $diff->getUnitStatus() == DifferentialUnitStatus::UNIT_POSTPONED) { $umsg = $postponed_count . ' ' . $umsg; } return $ustar . ' ' . $umsg . $utail; }
public function renderValueForRevisionView() { $diff = $this->getDiff(); $path_changesets = mpull($diff->loadChangesets(), 'getId', 'getFilename'); $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'); $line_link = phutil_escape_html($line); if (isset($path_changesets[$path])) { // TODO: Create standalone links for large diffs. Logic is in // DifferentialDiffTableOfContentsView::renderChangesetLink(). $line_link = phutil_render_tag('a', array('href' => '#C' . $path_changesets[$path] . 'NL' . $line), $line_link); } $message_markup[] = hsprintf('<li>' . '<span class="lint-severity-%s">%s</span> (%s) %s ' . 'at line ' . $line_link . '<p>%s</p>' . '</li>', $severity, ucwords($severity), $code, $name, $description); } $lint_messages[] = '<li class="lint-file-block">' . 'Lint for <strong>' . phutil_escape_html($path) . '</strong>' . '<ul>' . implode("\n", $message_markup) . '</ul>' . '</li>'; } $lexcuse = $this->getLintExcuse(); $ltail = '<div class="differential-lint-block">' . $lexcuse . '<ul>' . implode("\n", $lint_messages) . '</ul>' . '</div>'; } return $lstar . ' ' . $lmsg . $ltail; }
public function renderValueForRevisionView() { $diff = $this->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", '<br />', $userdata); $unit_messages[] = '<tr>' . '<th>' . $name . '</th>' . '<th class="unit-test-result">' . '<div class="result-' . $result . '">' . strtoupper($result) . '</div>' . '</th>' . '<td>' . $userdata . '</td>' . '</tr>'; $utail = '<div class="differential-unit-block">' . '<table class="differential-unit-table">' . implode("\n", $unit_messages) . '</table>' . '</div>'; } 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; }
public function renderDiffPropertyViewValue(DifferentialDiff $diff) { $colors = array(DifferentialUnitStatus::UNIT_NONE => 'grey', DifferentialUnitStatus::UNIT_OKAY => 'green', DifferentialUnitStatus::UNIT_WARN => 'yellow', DifferentialUnitStatus::UNIT_FAIL => 'red', DifferentialUnitStatus::UNIT_SKIP => 'blue', DifferentialUnitStatus::UNIT_AUTO_SKIP => 'blue'); $icon_color = idx($colors, $diff->getUnitStatus(), 'grey'); $message = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff->getUnitStatus()); $status = id(new PHUIStatusListView())->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_STAR, $icon_color)->setTarget($message)); return $status; }
public function renderValueForRevisionView() { $diff = $this->getDiff(); $ustar = DifferentialRevisionUpdateHistoryView::renderDiffUnitStar($diff); $umsg = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff); $rows = array(); $rows[] = array('style' => 'star', 'name' => $ustar, 'value' => $umsg, 'show' => true); $excuse = $this->getUnitExcuse(); if ($excuse) { $rows[] = array('style' => 'excuse', 'name' => 'Excuse', 'value' => nl2br(phutil_escape_html($excuse)), 'show' => true); } $show_limit = 10; $hidden = array(); $udata = $this->getDiffProperty('arc:unit'); if ($udata) { $sort_map = array(ArcanistUnitTestResult::RESULT_BROKEN => 0, ArcanistUnitTestResult::RESULT_FAIL => 1, ArcanistUnitTestResult::RESULT_UNSOUND => 2, ArcanistUnitTestResult::RESULT_SKIP => 3, ArcanistUnitTestResult::RESULT_POSTPONED => 4, ArcanistUnitTestResult::RESULT_PASS => 5); foreach ($udata as $key => $test) { $udata[$key]['sort'] = idx($sort_map, idx($test, 'result')); } $udata = isort($udata, 'sort'); foreach ($udata as $test) { $result = idx($test, 'result'); $default_hide = false; switch ($result) { case ArcanistUnitTestResult::RESULT_POSTPONED: case ArcanistUnitTestResult::RESULT_PASS: $default_hide = true; break; } if ($show_limit && !$default_hide) { --$show_limit; $show = true; } else { $show = false; if (empty($hidden[$result])) { $hidden[$result] = 0; } $hidden[$result]++; } $rows[] = array('style' => $this->getResultStyle($result), 'name' => phutil_escape_html(ucwords($result)), 'value' => phutil_escape_html(idx($test, 'name')), 'show' => $show); $userdata = idx($test, 'userdata'); if ($userdata) { $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine(); $userdata = $engine->markupText($userdata); $rows[] = array('style' => 'details', 'value' => $userdata, 'show' => false); if (empty($hidden['details'])) { $hidden['details'] = 0; } $hidden['details']++; } } } $show_string = $this->renderShowString($hidden); $view = new DifferentialResultsTableView(); $view->setRows($rows); $view->setShowMoreString($show_string); return $view->render(); }
protected function renderHarbormasterStatus(DifferentialDiff $diff, array $messages) { $colors = array(DifferentialLintStatus::LINT_NONE => 'grey', DifferentialLintStatus::LINT_OKAY => 'green', DifferentialLintStatus::LINT_WARN => 'yellow', DifferentialLintStatus::LINT_FAIL => 'red', DifferentialLintStatus::LINT_SKIP => 'blue', DifferentialLintStatus::LINT_AUTO_SKIP => 'blue'); $icon_color = idx($colors, $diff->getLintStatus(), 'grey'); $message = DifferentialRevisionUpdateHistoryView::getDiffLintMessage($diff); $excuse = $diff->getProperty('arc:lint-excuse'); if (strlen($excuse)) { $excuse = array(phutil_tag('strong', array(), pht('Excuse:')), ' ', phutil_escape_html_newlines($excuse)); } $status = id(new PHUIStatusListView())->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_STAR, $icon_color)->setTarget($message)->setNote($excuse)); return $status; }
public function renderPropertyViewValue(array $handles) { $diff = $this->getObject()->getActiveDiff(); $path_changesets = mpull($diff->loadChangesets(), 'getID', 'getFilename'); $lstar = DifferentialRevisionUpdateHistoryView::renderDiffLintStar($diff); $lmsg = DifferentialRevisionUpdateHistoryView::getDiffLintMessage($diff); $ldata = $diff->getProperty('arc:lint'); $ltail = null; $rows = array(); $rows[] = array('style' => 'star', 'name' => $lstar, 'value' => $lmsg, 'show' => true); $excuse = $diff->getProperty('arc:lint-excuse'); if ($excuse) { $rows[] = array('style' => 'excuse', 'name' => 'Excuse', 'value' => phutil_escape_html_newlines($excuse), 'show' => true); } $show_limit = 10; $hidden = array(); if ($ldata) { $ldata = igroup($ldata, 'path'); foreach ($ldata as $path => $messages) { $rows[] = array('style' => 'section', 'name' => $path, 'show' => $show_limit); 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'); $line_link = 'line ' . intval($line); if (isset($path_changesets[$path])) { $href = '#C' . $path_changesets[$path] . 'NL' . max(1, $line); // TODO: We are always showing the active diff // if ($diff->getID() != $this->getDiff()->getID()) { // $href = '/D'.$diff->getRevisionID().'?id='.$diff->getID().$href; // } $line_link = phutil_tag('a', array('href' => $href), $line_link); } if ($show_limit) { --$show_limit; $show = true; } else { $show = false; if (empty($hidden[$severity])) { $hidden[$severity] = 0; } $hidden[$severity]++; } $rows[] = array('style' => $this->getSeverityStyle($severity), 'name' => ucwords($severity), 'value' => hsprintf('(%s) %s at %s', $code, $name, $line_link), 'show' => $show); if (!empty($message['locations'])) { $locations = array(); foreach ($message['locations'] as $location) { $other_line = idx($location, 'line'); $locations[] = idx($location, 'path', $path) . ($other_line ? ":{$other_line}" : ''); } $description .= "\nOther locations: " . implode(', ', $locations); } if (strlen($description)) { $rows[] = array('style' => 'details', 'value' => phutil_escape_html_newlines($description), 'show' => false); if (empty($hidden['details'])) { $hidden['details'] = 0; } $hidden['details']++; } } } } $postponed = $diff->getProperty('arc:lint-postponed'); if ($postponed) { foreach ($postponed as $linter) { $rows[] = array('style' => $this->getPostponedStyle(), 'name' => 'Postponed', 'value' => $linter, 'show' => false); if (empty($hidden['postponed'])) { $hidden['postponed'] = 0; } $hidden['postponed']++; } } $show_string = $this->renderShowString($hidden); $view = new DifferentialResultsTableView(); $view->setRows($rows); $view->setShowMoreString($show_string); return $view->render(); }
protected function renderHarbormasterStatus(DifferentialDiff $diff, array $messages) { $colors = array(DifferentialUnitStatus::UNIT_NONE => 'grey', DifferentialUnitStatus::UNIT_OKAY => 'green', DifferentialUnitStatus::UNIT_WARN => 'yellow', DifferentialUnitStatus::UNIT_FAIL => 'red', DifferentialUnitStatus::UNIT_SKIP => 'blue', DifferentialUnitStatus::UNIT_AUTO_SKIP => 'blue', DifferentialUnitStatus::UNIT_POSTPONED => 'blue'); $icon_color = idx($colors, $diff->getUnitStatus(), 'grey'); $message = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff); $note = array(); $groups = mgroup($messages, 'getResult'); $groups = array_select_keys($groups, array(ArcanistUnitTestResult::RESULT_FAIL, ArcanistUnitTestResult::RESULT_BROKEN, ArcanistUnitTestResult::RESULT_UNSOUND, ArcanistUnitTestResult::RESULT_SKIP, ArcanistUnitTestResult::RESULT_PASS)) + $groups; foreach ($groups as $result => $group) { $count = new PhutilNumber(count($group)); switch ($result) { case ArcanistUnitTestResult::RESULT_PASS: $note[] = pht('%s Passed Test(s)', $count); break; case ArcanistUnitTestResult::RESULT_FAIL: $note[] = pht('%s Failed Test(s)', $count); break; case ArcanistUnitTestResult::RESULT_SKIP: $note[] = pht('%s Skipped Test(s)', $count); break; case ArcanistUnitTestResult::RESULT_BROKEN: $note[] = pht('%s Broken Test(s)', $count); break; case ArcanistUnitTestResult::RESULT_UNSOUND: $note[] = pht('%s Unsound Test(s)', $count); break; default: $note[] = pht('%s Other Test(s)', $count); break; } } $buildable = $diff->getBuildable(); if ($buildable) { $full_results = '/harbormaster/unit/' . $buildable->getID() . '/'; $note[] = phutil_tag('a', array('href' => $full_results), pht('View Full Results')); } $excuse = $diff->getProperty('arc:unit-excuse'); if (strlen($excuse)) { $excuse = array(phutil_tag('strong', array(), pht('Excuse:')), ' ', phutil_escape_html_newlines($excuse)); $note[] = $excuse; } $note = phutil_implode_html(" · ", $note); $status = id(new PHUIStatusListView())->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_STAR, $icon_color)->setTarget($message)->setNote($note)); return $status; }
public function renderPropertyViewValue(array $handles) { $diff = $this->getObject()->getActiveDiff(); $ustar = DifferentialRevisionUpdateHistoryView::renderDiffUnitStar($diff); $umsg = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff); $rows = array(); $rows[] = array('style' => 'star', 'name' => $ustar, 'value' => $umsg, 'show' => true); $excuse = $diff->getProperty('arc:unit-excuse'); if ($excuse) { $rows[] = array('style' => 'excuse', 'name' => 'Excuse', 'value' => phutil_escape_html_newlines($excuse), 'show' => true); } $show_limit = 10; $hidden = array(); $udata = $diff->getProperty('arc:unit'); if ($udata) { $sort_map = array(ArcanistUnitTestResult::RESULT_BROKEN => 0, ArcanistUnitTestResult::RESULT_FAIL => 1, ArcanistUnitTestResult::RESULT_UNSOUND => 2, ArcanistUnitTestResult::RESULT_SKIP => 3, ArcanistUnitTestResult::RESULT_POSTPONED => 4, ArcanistUnitTestResult::RESULT_PASS => 5); foreach ($udata as $key => $test) { $udata[$key]['sort'] = idx($sort_map, idx($test, 'result')); } $udata = isort($udata, 'sort'); $engine = new PhabricatorMarkupEngine(); $engine->setViewer($this->getViewer()); $markup_objects = array(); foreach ($udata as $key => $test) { $userdata = idx($test, 'userdata'); if ($userdata) { if ($userdata !== false) { $userdata = str_replace("", '', $userdata); } $markup_object = id(new PhabricatorMarkupOneOff())->setContent($userdata)->setPreserveLinebreaks(true); $engine->addObject($markup_object, 'default'); $markup_objects[$key] = $markup_object; } } $engine->process(); foreach ($udata as $key => $test) { $result = idx($test, 'result'); $default_hide = false; switch ($result) { case ArcanistUnitTestResult::RESULT_POSTPONED: case ArcanistUnitTestResult::RESULT_PASS: $default_hide = true; break; } if ($show_limit && !$default_hide) { --$show_limit; $show = true; } else { $show = false; if (empty($hidden[$result])) { $hidden[$result] = 0; } $hidden[$result]++; } $value = idx($test, 'name'); if (!empty($test['link'])) { $value = phutil_tag('a', array('href' => $test['link'], 'target' => '_blank'), $value); } $rows[] = array('style' => $this->getResultStyle($result), 'name' => ucwords($result), 'value' => $value, 'show' => $show); if (isset($markup_objects[$key])) { $rows[] = array('style' => 'details', 'value' => $engine->getOutput($markup_objects[$key], 'default'), 'show' => false); if (empty($hidden['details'])) { $hidden['details'] = 0; } $hidden['details']++; } } } $show_string = $this->renderShowString($hidden); $view = new DifferentialResultsTableView(); $view->setRows($rows); $view->setShowMoreString($show_string); return $view->render(); }
public function renderValueForRevisionView() { $diff = $this->getDiff(); $path_changesets = mpull($diff->loadChangesets(), 'getID', 'getFilename'); $lstar = DifferentialRevisionUpdateHistoryView::renderDiffLintStar($diff); $lmsg = DifferentialRevisionUpdateHistoryView::getDiffLintMessage($diff); $ldata = $this->getDiffProperty('arc:lint'); $ltail = null; $rows = array(); $rows[] = array('style' => 'star', 'name' => $lstar, 'value' => $lmsg, 'show' => true); $excuse = $this->getLintExcuse(); if ($excuse) { $rows[] = array('style' => 'excuse', 'name' => 'Excuse', 'value' => nl2br(phutil_escape_html($excuse)), 'show' => true); } $show_limit = 10; $hidden = array(); if ($ldata) { $ldata = igroup($ldata, 'path'); foreach ($ldata as $path => $messages) { $rows[] = array('style' => 'section', 'name' => phutil_escape_html($path), 'show' => $show_limit); 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'); $line_link = 'line ' . intval($line); if (isset($path_changesets[$path])) { $line_link = phutil_render_tag('a', array('href' => '#C' . $path_changesets[$path] . 'NL' . max(1, $line)), $line_link); } if ($show_limit) { --$show_limit; $show = true; } else { $show = false; if (empty($hidden[$severity])) { $hidden[$severity] = 0; } $hidden[$severity]++; } $rows[] = array('style' => $this->getSeverityStyle($severity), 'name' => phutil_escape_html(ucwords($severity)), 'value' => hsprintf("(%s) %s at {$line_link}", $code, $name), 'show' => $show); if (strlen($description)) { $rows[] = array('style' => 'details', 'value' => nl2br(phutil_escape_html($description)), 'show' => false); if (empty($hidden['details'])) { $hidden['details'] = 0; } $hidden['details']++; } } } } $postponed = $this->getPostponedLinters(); if ($postponed) { foreach ($postponed as $linter) { $rows[] = array('style' => $this->getPostponedStyle(), 'name' => 'Postponed', 'value' => phutil_escape_html($linter), 'show' => false); if (empty($hidden['postponed'])) { $hidden['postponed'] = 0; } $hidden['postponed']++; } } $show_string = $this->renderShowString($hidden); $view = new DifferentialResultsTableView(); $view->setRows($rows); $view->setShowMoreString($show_string); return $view->render(); }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $viewer_is_anonymous = !$user->isLoggedIn(); $revision = id(new DifferentialRevision())->load($this->revisionID); if (!$revision) { return new Aphront404Response(); } $revision->loadRelationships(); $diffs = $revision->loadDiffs(); if (!$diffs) { throw new Exception("This revision has no diffs. Something has gone quite wrong."); } $diff_vs = $request->getInt('vs'); $target_id = $request->getInt('id'); $target = idx($diffs, $target_id, end($diffs)); $target_manual = $target; if (!$target_id) { foreach ($diffs as $diff) { if ($diff->getCreationMethod() != 'commit') { $target_manual = $diff; } } } if (empty($diffs[$diff_vs])) { $diff_vs = null; } $arc_project = $target->loadArcanistProject(); $repository = $arc_project ? $arc_project->loadRepository() : null; list($changesets, $vs_map, $vs_changesets, $rendering_references) = $this->loadChangesetsAndVsMap($target, idx($diffs, $diff_vs), $repository); if ($request->getExists('download')) { return $this->buildRawDiffResponse($changesets, $vs_changesets, $vs_map, $repository); } list($aux_fields, $props) = $this->loadAuxiliaryFieldsAndProperties($revision, $target_manual, array('local:commits', 'arc:lint', 'arc:unit')); $comments = $revision->loadComments(); $comments = array_merge($this->getImplicitComments($revision, reset($diffs)), $comments); $all_changesets = $changesets; $inlines = $this->loadInlineComments($comments, $all_changesets); $object_phids = array_merge($revision->getReviewers(), $revision->getCCPHIDs(), $revision->loadCommitPHIDs(), array($revision->getAuthorPHID(), $user->getPHID()), mpull($comments, 'getAuthorPHID')); foreach ($comments as $comment) { $metadata = $comment->getMetadata(); $added_reviewers = idx($metadata, DifferentialComment::METADATA_ADDED_REVIEWERS); if ($added_reviewers) { foreach ($added_reviewers as $phid) { $object_phids[] = $phid; } } $added_ccs = idx($metadata, DifferentialComment::METADATA_ADDED_CCS); if ($added_ccs) { foreach ($added_ccs as $phid) { $object_phids[] = $phid; } } } foreach ($revision->getAttached() as $type => $phids) { foreach ($phids as $phid => $info) { $object_phids[] = $phid; } } $aux_phids = array(); foreach ($aux_fields as $key => $aux_field) { $aux_phids[$key] = $aux_field->getRequiredHandlePHIDsForRevisionView(); } $object_phids = array_merge($object_phids, array_mergev($aux_phids)); $object_phids = array_unique($object_phids); $handles = id(new PhabricatorObjectHandleData($object_phids))->loadHandles(); foreach ($aux_fields as $key => $aux_field) { // Make sure each field only has access to handles it specifically // requested, not all handles. Otherwise you can get a field which works // only in the presence of other fields. $aux_field->setHandles(array_select_keys($handles, $aux_phids[$key])); } $reviewer_warning = null; $has_live_reviewer = false; foreach ($revision->getReviewers() as $reviewer) { if (!$handles[$reviewer]->isDisabled()) { $has_live_reviewer = true; } } if (!$has_live_reviewer) { $reviewer_warning = new AphrontErrorView(); $reviewer_warning->setSeverity(AphrontErrorView::SEVERITY_WARNING); $reviewer_warning->setTitle('No Active Reviewers'); if ($revision->getReviewers()) { $reviewer_warning->appendChild('<p>All specified reviewers are disabled. You may want to add ' . 'some new reviewers.</p>'); } else { $reviewer_warning->appendChild('<p>This revision has no specified reviewers. You may want to ' . 'add some.</p>'); } } $request_uri = $request->getRequestURI(); $limit = 100; $large = $request->getStr('large'); if (count($changesets) > $limit && !$large) { $count = number_format(count($changesets)); $warning = new AphrontErrorView(); $warning->setTitle('Very Large Diff'); $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING); $warning->setWidth(AphrontErrorView::WIDTH_WIDE); $warning->appendChild("<p>This diff is very large and affects {$count} files. Load " . "each file individually. " . "<strong>" . phutil_render_tag('a', array('href' => $request_uri->alter('large', 'true')->setFragment('toc')), 'Show All Files Inline') . "</strong>"); $warning = $warning->render(); $my_inlines = id(new DifferentialInlineComment())->loadAllWhere('revisionID = %d AND commentID IS NULL AND authorPHID = %s AND ' . 'changesetID IN (%Ld)', $this->revisionID, $user->getPHID(), mpull($changesets, 'getID')); $visible_changesets = array(); foreach ($inlines + $my_inlines as $inline) { $changeset_id = $inline->getChangesetID(); if (isset($changesets[$changeset_id])) { $visible_changesets[$changeset_id] = $changesets[$changeset_id]; } } if (!empty($props['arc:lint'])) { $changeset_paths = mpull($changesets, null, 'getFilename'); foreach ($props['arc:lint'] as $lint) { $changeset = idx($changeset_paths, $lint['path']); if ($changeset) { $visible_changesets[$changeset->getID()] = $changeset; } } } } else { $warning = null; $visible_changesets = $changesets; } $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: build a better version of the action links and deprecate the // whole DifferentialRevisionDetailRenderer class. $custom_renderer = newv($custom_renderer_class, array()); $custom_renderer->setDiff($target); if ($diff_vs) { $custom_renderer->setVSDiff($diffs[$diff_vs]); } $actions = array_merge($actions, $custom_renderer->generateActionLinks($revision, $target_manual)); } $whitespace = $request->getStr('whitespace', DifferentialChangesetParser::WHITESPACE_IGNORE_ALL); if ($arc_project) { list($symbol_indexes, $project_phids) = $this->buildSymbolIndexes($arc_project, $visible_changesets); } else { $symbol_indexes = array(); $project_phids = null; } $revision_detail->setActions($actions); $revision_detail->setUser($user); $comment_view = new DifferentialRevisionCommentListView(); $comment_view->setComments($comments); $comment_view->setHandles($handles); $comment_view->setInlineComments($inlines); $comment_view->setChangesets($all_changesets); $comment_view->setUser($user); $comment_view->setTargetDiff($target); $comment_view->setVersusDiffID($diff_vs); if ($arc_project) { Javelin::initBehavior('repository-crossreference', array('section' => $comment_view->getID(), 'projects' => $project_phids)); } $changeset_view = new DifferentialChangesetListView(); $changeset_view->setChangesets($changesets); $changeset_view->setVisibleChangesets($visible_changesets); if (!$viewer_is_anonymous) { $changeset_view->setInlineCommentControllerURI('/differential/comment/inline/edit/' . $revision->getID() . '/'); } $changeset_view->setStandaloneURI('/differential/changeset/'); $changeset_view->setRawFileURIs('/differential/changeset/?view=old', '/differential/changeset/?view=new'); $changeset_view->setUser($user); $changeset_view->setDiff($target); $changeset_view->setRenderingReferences($rendering_references); $changeset_view->setVsMap($vs_map); $changeset_view->setWhitespace($whitespace); if ($repository) { $changeset_view->setRepository($repository); } $changeset_view->setSymbolIndexes($symbol_indexes); $diff_history = new DifferentialRevisionUpdateHistoryView(); $diff_history->setDiffs($diffs); $diff_history->setSelectedVersusDiffID($diff_vs); $diff_history->setSelectedDiffID($target->getID()); $diff_history->setSelectedWhitespace($whitespace); $diff_history->setUser($user); $local_view = new DifferentialLocalCommitsView(); $local_view->setUser($user); $local_view->setLocalCommits(idx($props, 'local:commits')); if ($repository) { $other_revisions = $this->loadOtherRevisions($changesets, $target, $repository); } else { $other_revisions = array(); } $other_view = null; if ($other_revisions) { $other_view = $this->renderOtherRevisions($other_revisions); } $toc_view = new DifferentialDiffTableOfContentsView(); $toc_view->setChangesets($changesets); $toc_view->setVisibleChangesets($visible_changesets); $toc_view->setRenderingReferences($rendering_references); $toc_view->setUnitTestData(idx($props, 'arc:unit', array())); if ($repository) { $toc_view->setRepository($repository); } $toc_view->setDiff($target); $toc_view->setUser($user); $toc_view->setRevisionID($revision->getID()); $toc_view->setWhitespace($whitespace); $comment_form = null; if (!$viewer_is_anonymous) { $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), 'differential-comment-' . $revision->getID()); if ($draft) { $draft = $draft->getDraft(); } else { $draft = null; } $comment_form = new DifferentialAddCommentView(); $comment_form->setRevision($revision); $comment_form->setAuxFields($aux_fields); $comment_form->setActions($this->getRevisionCommentActions($revision)); $comment_form->setActionURI('/differential/comment/save/'); $comment_form->setUser($user); $comment_form->setDraft($draft); } $pane_id = celerity_generate_unique_node_id(); Javelin::initBehavior('differential-keyboard-navigation', array('haunt' => $pane_id)); Javelin::initBehavior('differential-user-select'); $page_pane = id(new DifferentialPrimaryPaneView())->setLineWidthFromChangesets($changesets)->setID($pane_id)->appendChild($comment_view->render() . $diff_history->render() . $warning . $local_view->render() . $toc_view->render() . $other_view . $changeset_view->render()); if ($comment_form) { $page_pane->appendChild($comment_form->render()); } PhabricatorFeedStoryNotification::updateObjectNotificationViews($user, $revision->getPHID()); $top_anchor = id(new PhabricatorAnchorView())->setAnchorName('top')->setNavigationMarker(true); $nav = $this->buildSideNavView($revision, $changesets); $nav->selectFilter(''); $nav->appendChild(array($reviewer_warning, $top_anchor, $revision_detail, $page_pane)); return $this->buildApplicationPage($nav, array('title' => 'D' . $revision->getID() . ' ' . $revision->getTitle())); }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $viewer_is_anonymous = !$user->isLoggedIn(); $revision = id(new DifferentialRevision())->load($this->revisionID); if (!$revision) { return new Aphront404Response(); } $revision->loadRelationships(); $diffs = $revision->loadDiffs(); if (!$diffs) { throw new Exception("This revision has no diffs. Something has gone quite wrong."); } $diff_vs = $request->getInt('vs'); $target = end($diffs); $target_id = $request->getInt('id'); if ($target_id) { if (isset($diffs[$target_id])) { $target = $diffs[$target_id]; } } $diffs = mpull($diffs, null, 'getID'); if (empty($diffs[$diff_vs])) { $diff_vs = null; } list($aux_fields, $props) = $this->loadAuxiliaryFieldsAndProperties($revision, $target, array('local:commits')); list($changesets, $vs_map, $rendering_references) = $this->loadChangesetsAndVsMap($diffs, $diff_vs, $target); $comments = $revision->loadComments(); $comments = array_merge($this->getImplicitComments($revision), $comments); $all_changesets = $changesets; $inlines = $this->loadInlineComments($comments, $all_changesets); $object_phids = array_merge($revision->getReviewers(), $revision->getCCPHIDs(), $revision->loadCommitPHIDs(), array($revision->getAuthorPHID(), $user->getPHID()), mpull($comments, 'getAuthorPHID')); foreach ($comments as $comment) { $metadata = $comment->getMetadata(); $added_reviewers = idx($metadata, DifferentialComment::METADATA_ADDED_REVIEWERS); if ($added_reviewers) { foreach ($added_reviewers as $phid) { $object_phids[] = $phid; } } $added_ccs = idx($metadata, DifferentialComment::METADATA_ADDED_CCS); if ($added_ccs) { foreach ($added_ccs as $phid) { $object_phids[] = $phid; } } } foreach ($revision->getAttached() as $type => $phids) { foreach ($phids as $phid => $info) { $object_phids[] = $phid; } } $aux_phids = array(); foreach ($aux_fields as $key => $aux_field) { $aux_phids[$key] = $aux_field->getRequiredHandlePHIDsForRevisionView(); } $object_phids = array_merge($object_phids, array_mergev($aux_phids)); $object_phids = array_unique($object_phids); $handles = id(new PhabricatorObjectHandleData($object_phids))->loadHandles(); foreach ($aux_fields as $key => $aux_field) { // Make sure each field only has access to handles it specifically // requested, not all handles. Otherwise you can get a field which works // only in the presence of other fields. $aux_field->setHandles(array_select_keys($handles, $aux_phids[$key])); } $request_uri = $request->getRequestURI(); $limit = 100; $large = $request->getStr('large'); if (count($changesets) > $limit && !$large) { $count = number_format(count($changesets)); $warning = new AphrontErrorView(); $warning->setTitle('Very Large Diff'); $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING); $warning->setWidth(AphrontErrorView::WIDTH_WIDE); $warning->appendChild("<p>This diff is very large and affects {$count} files. Use " . "Table of Contents to open files in a standalone view. " . "<strong>" . phutil_render_tag('a', array('href' => $request_uri->alter('large', 'true')), 'Show All Files Inline') . "</strong>"); $warning = $warning->render(); $visible_changesets = array(); } else { $warning = null; $visible_changesets = $changesets; } $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: build a better version of the action links and deprecate the // whole DifferentialRevisionDetailRenderer class. PhutilSymbolLoader::loadClass($custom_renderer_class); $custom_renderer = newv($custom_renderer_class, array()); $actions = array_merge($actions, $custom_renderer->generateActionLinks($revision, $target)); } $whitespace = $request->getStr('whitespace', DifferentialChangesetParser::WHITESPACE_IGNORE_ALL); $arc_project = $target->loadArcanistProject(); if ($arc_project) { $symbol_indexes = $this->buildSymbolIndexes($target, $arc_project, $visible_changesets); $repository = $arc_project->loadRepository(); } else { $symbol_indexes = array(); $repository = null; } $revision_detail->setActions($actions); $revision_detail->setUser($user); $comment_view = new DifferentialRevisionCommentListView(); $comment_view->setComments($comments); $comment_view->setHandles($handles); $comment_view->setInlineComments($inlines); $comment_view->setChangesets($all_changesets); $comment_view->setUser($user); $comment_view->setTargetDiff($target); $comment_view->setVersusDiffID($diff_vs); $changeset_view = new DifferentialChangesetListView(); $changeset_view->setChangesets($visible_changesets); $changeset_view->setEditable(!$viewer_is_anonymous); $changeset_view->setStandaloneViews(true); $changeset_view->setRevision($revision); $changeset_view->setDiff($target); $changeset_view->setRenderingReferences($rendering_references); $changeset_view->setWhitespace($whitespace); if ($repository) { $changeset_view->setRepository($repository, $target); } $changeset_view->setSymbolIndexes($symbol_indexes); $diff_history = new DifferentialRevisionUpdateHistoryView(); $diff_history->setDiffs($diffs); $diff_history->setSelectedVersusDiffID($diff_vs); $diff_history->setSelectedDiffID($target->getID()); $diff_history->setSelectedWhitespace($whitespace); $diff_history->setUser($user); $local_view = new DifferentialLocalCommitsView(); $local_view->setUser($user); $local_view->setLocalCommits(idx($props, 'local:commits')); $toc_view = new DifferentialDiffTableOfContentsView(); $toc_view->setChangesets($changesets); $toc_view->setStandaloneViewLink(empty($visible_changesets)); $toc_view->setVsMap($vs_map); $toc_view->setRevisionID($revision->getID()); $toc_view->setWhitespace($whitespace); if (!$viewer_is_anonymous) { $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), 'differential-comment-' . $revision->getID()); if ($draft) { $draft = $draft->getDraft(); } else { $draft = null; } $comment_form = new DifferentialAddCommentView(); $comment_form->setRevision($revision); $comment_form->setActions($this->getRevisionCommentActions($revision)); $comment_form->setActionURI('/differential/comment/save/'); $comment_form->setUser($user); $comment_form->setDraft($draft); } $pane_id = celerity_generate_unique_node_id(); Javelin::initBehavior('differential-keyboard-navigation', array('haunt' => $pane_id)); $page_pane = id(new DifferentialPrimaryPaneView())->setLineWidthFromChangesets($changesets)->setID($pane_id)->appendChild($revision_detail->render() . $comment_view->render() . $diff_history->render() . $warning . $local_view->render() . $toc_view->render() . $changeset_view->render()); if ($comment_form) { $page_pane->appendChild($comment_form->render()); } return $this->buildStandardPageResponse($page_pane, array('title' => 'D' . $revision->getID() . ' ' . $revision->getTitle())); }
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: <tt>' . phutil_escape_html($next_step) . '</tt>'; } } $status = DifferentialRevisionStatus::getNameForRevisionStatus($status); $properties['Revision Status'] = '<strong>' . $status . '</strong>' . $next_step; $author = $handles[$revision->getAuthorPHID()]; $properties['Author'] = $author->renderLink(); $properties['Reviewers'] = $this->renderHandleLinkList(array_select_keys($handles, $revision->getReviewers())); $properties['CCs'] = $this->renderHandleLinkList(array_select_keys($handles, $revision->getCCPHIDs())); $host = $diff->getSourceMachine(); if ($host) { $properties['Host'] = phutil_escape_html($host); } $path = $diff->getSourcePath(); if ($path) { $branch = $diff->getBranch() ? ' (' . $diff->getBranch() . ')' : ''; $properties['Path'] = phutil_escape_html("{$path} {$branch}"); } $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[] = '<li>' . '<span class="lint-severity-' . phutil_escape_html($severity) . '">' . phutil_escape_html(ucwords($severity)) . '</span>' . ' ' . '(' . phutil_escape_html($code) . ') ' . phutil_escape_html($name) . ' at line ' . phutil_escape_html($line) . '<p>' . phutil_escape_html($description) . '</p>' . '</li>'; } $lint_messages[] = '<li class="lint-file-block">' . 'Lint for <strong>' . phutil_escape_html($path) . '</strong>' . '<ul>' . implode("\n", $message_markup) . '</ul>' . '</li>'; } $ltail = '<div class="differential-lint-block">' . '<ul>' . implode("\n", $lint_messages) . '</ul>' . '</div>'; } $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", '<br />', $userdata); $unit_messages[] = '<tr>' . '<th>' . $name . '</th>' . '<th class="unit-test-result">' . '<div class="result-' . $result . '">' . strtoupper($result) . '</div>' . '</th>' . '<td>' . $userdata . '</td>' . '</tr>'; $utail = '<div class="differential-unit-block">' . '<table class="differential-unit-table">' . implode("\n", $unit_messages) . '</table>' . '</div>'; } 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; if (PhabricatorEnv::getEnvConfig('maniphest.enabled')) { $tasks = $revision->getAttachedPHIDs(PhabricatorPHIDConstants::PHID_TYPE_TASK); if ($tasks) { $links = array(); foreach ($tasks as $task_phid) { $links[] = $handles[$task_phid]->renderLink(); } $properties['Maniphest Tasks'] = implode('<br />', $links); } } $commit_phids = $revision->getCommitPHIDs(); if ($commit_phids) { $links = array(); foreach ($commit_phids as $commit_phid) { $links[] = $handles[$commit_phid]->renderLink(); } $properties['Commits'] = implode('<br />', $links); } $properties['Lines'] = number_format($diff->getLineCount()); $arcanist_phid = $diff->getArcanistProjectPHID(); if ($arcanist_phid) { $properties['Arcanist Project'] = phutil_escape_html($handles[$arcanist_phid]->getName()); } $properties['Apply Patch'] = '<tt>arc patch D' . $revision->getID() . '</tt>'; $properties['Export Patch'] = '<tt>arc export --revision ' . $revision->getID() . '</tt>'; return $properties; }