public function render() { $old = $this->oldText; $new = $this->newText; // TODO: On mobile, or perhaps by default, we should switch to 1-up once // that is built. if (strlen($old)) { $old = phutil_utf8_hard_wrap($old, 80); $old = implode("\n", $old) . "\n"; } if (strlen($new)) { $new = phutil_utf8_hard_wrap($new, 80); $new = implode("\n", $new) . "\n"; } try { $engine = new PhabricatorDifferenceEngine(); $changeset = $engine->generateChangesetFromFileContent($old, $new); $whitespace_mode = DifferentialChangesetParser::WHITESPACE_SHOW_ALL; $markup_engine = new PhabricatorMarkupEngine(); $markup_engine->setViewer($this->getUser()); $parser = new DifferentialChangesetParser(); $parser->setChangeset($changeset); $parser->setMarkupEngine($markup_engine); $parser->setWhitespaceMode($whitespace_mode); return $parser->render(0, PHP_INT_MAX, array()); } catch (Exception $ex) { return $ex->getMessage(); } }
private function buildChangesetParsers($type, $data, $file) { $parser = new ArcanistDiffParser(); $changes = $parser->parseDiff($data); $diff = DifferentialDiff::newFromRawChanges(PhabricatorUser::getOmnipotentUser(), $changes); $changesets = $diff->getChangesets(); $engine = new PhabricatorMarkupEngine(); $engine->setViewer(new PhabricatorUser()); $parsers = array(); foreach ($changesets as $changeset) { $cparser = new DifferentialChangesetParser(); $cparser->setUser(new PhabricatorUser()); $cparser->setDisableCache(true); $cparser->setChangeset($changeset); $cparser->setMarkupEngine($engine); if ($type == 'one') { $cparser->setRenderer(new DifferentialChangesetOneUpTestRenderer()); } else { if ($type == 'two') { $cparser->setRenderer(new DifferentialChangesetTwoUpTestRenderer()); } else { throw new Exception(pht('Unknown renderer type "%s"!', $type)); } } $parsers[] = $cparser; } return $parsers; }
public function processRequest() { $drequest = $this->getDiffusionRequest(); $request = $this->getRequest(); $user = $request->getUser(); if (!$request->isAjax()) { // This request came out of the dropdown menu, either "View Standalone" // or "View Raw File". $view = $request->getStr('view'); if ($view == 'r') { $uri = $drequest->generateURI(array('action' => 'browse', 'params' => array('view' => 'raw'))); } else { $uri = $drequest->generateURI(array('action' => 'change')); } return id(new AphrontRedirectResponse())->setURI($uri); } $diff_query = DiffusionDiffQuery::newFromDiffusionRequest($drequest); $changeset = $diff_query->loadChangeset(); if (!$changeset) { return new Aphront404Response(); } $parser = new DifferentialChangesetParser(); $parser->setChangeset($changeset); $parser->setRenderingReference($diff_query->getRenderingReference()); $parser->setMarkupEngine(PhabricatorMarkupEngine::newDiffusionMarkupEngine()); $pquery = new DiffusionPathIDQuery(array($changeset->getFilename())); $ids = $pquery->loadPathIDs(); $path_id = $ids[$changeset->getFilename()]; $parser->setLeftSideCommentMapping($path_id, false); $parser->setRightSideCommentMapping($path_id, true); $parser->setWhitespaceMode(DifferentialChangesetParser::WHITESPACE_SHOW_ALL); $inlines = id(new PhabricatorAuditInlineComment())->loadAllWhere('commitPHID = %s AND pathID = %d AND (authorPHID = %s OR auditCommentID IS NOT NULL)', $drequest->loadCommit()->getPHID(), $path_id, $user->getPHID()); if ($inlines) { foreach ($inlines as $inline) { $parser->parseInlineComment($inline); } $phids = mpull($inlines, 'getAuthorPHID'); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $parser->setHandles($handles); } $spec = $request->getStr('range'); list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec); $output = $parser->render($range_s, $range_e, $mask); return id(new PhabricatorChangesetResponse())->setRenderedChangeset($output); }
private function buildChangesetParser($type, $data, $file) { $parser = new ArcanistDiffParser(); $changes = $parser->parseDiff($data); $diff = DifferentialDiff::newFromRawChanges($changes); if (count($diff->getChangesets()) !== 1) { throw new Exception("Expected one changeset: {$file}"); } $changeset = head($diff->getChangesets()); $engine = new PhabricatorMarkupEngine(); $engine->setViewer(new PhabricatorUser()); $cparser = new DifferentialChangesetParser(); $cparser->setDisableCache(true); $cparser->setChangeset($changeset); $cparser->setMarkupEngine($engine); if ($type == 'one') { $cparser->setRenderer(new DifferentialChangesetOneUpTestRenderer()); } else { if ($type == 'two') { $cparser->setRenderer(new DifferentialChangesetTwoUpTestRenderer()); } else { throw new Exception("Unknown renderer type '{$type}'!"); } } return $cparser; }
public function processRequest() { $drequest = $this->getDiffusionRequest(); $request = $this->getRequest(); $diff_query = DiffusionDiffQuery::newFromDiffusionRequest($drequest); $changeset = $diff_query->loadChangeset(); if (!$changeset) { return new Aphront404Response(); } $parser = new DifferentialChangesetParser(); $parser->setChangeset($changeset); $parser->setRenderingReference($diff_query->getRenderingReference()); $parser->setWhitespaceMode(DifferentialChangesetParser::WHITESPACE_SHOW_ALL); $spec = $request->getStr('range'); list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec); $output = $parser->render($range_s, $range_e, $mask); return id(new AphrontAjaxResponse())->setContent($output); }
public function testDiffChangesets() { $hunk = new DifferentialHunkModern(); $hunk->setChanges("+a\n b\n-c"); $hunk->setNewOffset(1); $hunk->setNewLen(2); $left = new DifferentialChangeset(); $left->attachHunks(array($hunk)); $tests = array("+a\n b\n-c" => array(array(), array()), "+a\n x\n-c" => array(array(), array()), "+aa\n b\n-c" => array(array(1), array(11)), " b\n-c" => array(array(1), array()), "+a\n b\n c" => array(array(), array(13)), "+a\n x\n c" => array(array(), array(13))); foreach ($tests as $changes => $expected) { $hunk = new DifferentialHunkModern(); $hunk->setChanges($changes); $hunk->setNewOffset(11); $hunk->setNewLen(3); $right = new DifferentialChangeset(); $right->attachHunks(array($hunk)); $parser = new DifferentialChangesetParser(); $parser->setOriginals($left, $right); $this->assertEqual($expected, $parser->diffOriginals(), $changes); } }
private static function buildChangesetsFromRawChanges(DifferentialDiff $diff, array $changes) { // There may not be any changes; initialize the changesets list so that // we don't throw later when accessing it. $diff->attachChangesets(array()); $lines = 0; foreach ($changes as $change) { if ($change->getType() == ArcanistDiffChangeType::TYPE_MESSAGE) { // If a user pastes a diff into Differential which includes a commit // message (e.g., they ran `git show` to generate it), discard that // change when constructing a DifferentialDiff. continue; } $changeset = new DifferentialChangeset(); $add_lines = 0; $del_lines = 0; $first_line = PHP_INT_MAX; $hunks = $change->getHunks(); if ($hunks) { foreach ($hunks as $hunk) { $dhunk = new DifferentialModernHunk(); $dhunk->setOldOffset($hunk->getOldOffset()); $dhunk->setOldLen($hunk->getOldLength()); $dhunk->setNewOffset($hunk->getNewOffset()); $dhunk->setNewLen($hunk->getNewLength()); $dhunk->setChanges($hunk->getCorpus()); $changeset->addUnsavedHunk($dhunk); $add_lines += $hunk->getAddLines(); $del_lines += $hunk->getDelLines(); $added_lines = $hunk->getChangedLines('new'); if ($added_lines) { $first_line = min($first_line, head_key($added_lines)); } } $lines += $add_lines + $del_lines; } else { // This happens when you add empty files. $changeset->attachHunks(array()); } $metadata = $change->getAllMetadata(); if ($first_line != PHP_INT_MAX) { $metadata['line:first'] = $first_line; } $changeset->setOldFile($change->getOldPath()); $changeset->setFilename($change->getCurrentPath()); $changeset->setChangeType($change->getType()); $changeset->setFileType($change->getFileType()); $changeset->setMetadata($metadata); $changeset->setOldProperties($change->getOldProperties()); $changeset->setNewProperties($change->getNewProperties()); $changeset->setAwayPaths($change->getAwayPaths()); $changeset->setAddLines($add_lines); $changeset->setDelLines($del_lines); $diff->addUnsavedChangeset($changeset); } $diff->setLineCount($lines); $parser = new DifferentialChangesetParser(); $changesets = $parser->detectCopiedCode($diff->getChangesets(), $min_width = 30, $min_lines = 3); $diff->attachChangesets($changesets); return $diff; }
public function processRequest() { $request = $this->getRequest(); $author_phid = $request->getUser()->getPHID(); $rendering_reference = $request->getStr('ref'); $parts = explode('/', $rendering_reference); if (count($parts) == 2) { list($id, $vs) = $parts; } else { $id = $parts[0]; $vs = 0; } $id = (int) $id; $vs = (int) $vs; $changeset = id(new DifferentialChangeset())->load($id); if (!$changeset) { return new Aphront404Response(); } $view = $request->getStr('view'); if ($view) { $changeset->attachHunks($changeset->loadHunks()); switch ($view) { case 'new': return $this->buildRawFileResponse($changeset->makeNewFile()); case 'old': return $this->buildRawFileResponse($changeset->makeOldFile()); default: return new Aphront400Response(); } } if ($vs && $vs != -1) { $vs_changeset = id(new DifferentialChangeset())->load($vs); if (!$vs_changeset) { return new Aphront404Response(); } } if (!$vs) { $right = $changeset; $left = null; $right_source = $right->getID(); $right_new = true; $left_source = $right->getID(); $left_new = false; $render_cache_key = $right->getID(); } else { if ($vs == -1) { $right = null; $left = $changeset; $right_source = $left->getID(); $right_new = false; $left_source = $left->getID(); $left_new = true; $render_cache_key = null; } else { $right = $changeset; $left = $vs_changeset; $right_source = $right->getID(); $right_new = true; $left_source = $left->getID(); $left_new = true; $render_cache_key = null; } } if ($left) { $left->attachHunks($left->loadHunks()); } if ($right) { $right->attachHunks($right->loadHunks()); } if ($left) { $left_data = $left->makeNewFile(); if ($right) { $right_data = $right->makeNewFile(); } else { $right_data = $left->makeOldFile(); } $engine = new PhabricatorDifferenceEngine(); $synthetic = $engine->generateChangesetFromFileContent($left_data, $right_data); $choice = nonempty($left, $right); $choice->attachHunks($synthetic->getHunks()); $changeset = $choice; $changeset->setID(null); } $spec = $request->getStr('range'); list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec); $parser = new DifferentialChangesetParser(); $parser->setChangeset($changeset); $parser->setRenderingReference($rendering_reference); $parser->setRenderCacheKey($render_cache_key); $parser->setRightSideCommentMapping($right_source, $right_new); $parser->setLeftSideCommentMapping($left_source, $left_new); $parser->setWhitespaceMode($request->getStr('whitespace')); // Load both left-side and right-side inline comments. $inlines = $this->loadInlineComments(array($left_source, $right_source), $author_phid); $phids = array(); foreach ($inlines as $inline) { $parser->parseInlineComment($inline); $phids[$inline->getAuthorPHID()] = true; } $phids = array_keys($phids); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $parser->setHandles($handles); $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine(); $parser->setMarkupEngine($engine); if ($request->isAjax()) { // TODO: This is sort of lazy, the effect is just to not render "Edit" // links on the "standalone view". $parser->setUser($request->getUser()); } $output = $parser->render($range_s, $range_e, $mask); if ($request->isAjax()) { return id(new AphrontAjaxResponse())->setContent($output); } Javelin::initBehavior('differential-show-more', array('uri' => '/differential/changeset/', 'whitespace' => $request->getStr('whitespace'))); Javelin::initBehavior('differential-comment-jump', array()); $detail = new DifferentialChangesetDetailView(); $detail->setChangeset($changeset); $detail->appendChild($output); if (!$vs) { $detail->addButton(phutil_render_tag('a', array('href' => $request->getRequestURI()->alter('view', 'old'), 'class' => 'grey button small'), 'View Raw File (Old Version)')); $detail->addButton(phutil_render_tag('a', array('href' => $request->getRequestURI()->alter('view', 'new'), 'class' => 'grey button small'), 'View Raw File (New Version)')); } $detail->setRevisionID($request->getInt('revision_id')); $output = id(new DifferentialPrimaryPaneView())->setLineWidthFromChangesets(array($changeset))->appendChild('<div class="differential-review-stage" ' . 'id="differential-review-stage">' . $detail->render() . '</div>'); return $this->buildStandardPageResponse(array($output), array('title' => 'Changeset View')); }
private function renderFullSummary($transaction) { switch ($transaction->getTransactionType()) { case ManiphestTransactionType::TYPE_DESCRIPTION: $id = $transaction->getID(); $old_text = wordwrap($transaction->getOldValue(), 80); $new_text = wordwrap($transaction->getNewValue(), 80); $engine = new PhabricatorDifferenceEngine(); $changeset = $engine->generateChangesetFromFileContent($old_text, $new_text); $whitespace_mode = DifferentialChangesetParser::WHITESPACE_SHOW_ALL; $parser = new DifferentialChangesetParser(); $parser->setChangeset($changeset); $parser->setRenderingReference($id); $parser->setWhitespaceMode($whitespace_mode); $spec = $this->getRangeSpecification(); list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec); $output = $parser->render($range_s, $range_e, $mask); return $output; } return null; }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $document = id(new PhrictionDocument())->load($this->id); if (!$document) { return new Aphront404Response(); } $current = id(new PhrictionContent())->load($document->getContentID()); $l = $request->getInt('l'); $r = $request->getInt('r'); $ref = $request->getStr('ref'); if ($ref) { list($l, $r) = explode(',', $ref); } $content = id(new PhrictionContent())->loadAllWhere('documentID = %d AND version IN (%Ld)', $document->getID(), array($l, $r)); $content = mpull($content, null, 'getVersion'); $content_l = idx($content, $l, null); $content_r = idx($content, $r, null); if (!$content_l || !$content_r) { return new Aphront404Response(); } $text_l = $content_l->getContent(); $text_r = $content_r->getContent(); $text_l = wordwrap($text_l, 80); $text_r = wordwrap($text_r, 80); $engine = new PhabricatorDifferenceEngine(); $changeset = $engine->generateChangesetFromFileContent($text_l, $text_r); $changeset->setOldProperties(array('Title' => $content_l->getTitle())); $changeset->setNewProperties(array('Title' => $content_r->getTitle())); $whitespace_mode = DifferentialChangesetParser::WHITESPACE_SHOW_ALL; $parser = new DifferentialChangesetParser(); $parser->setChangeset($changeset); $parser->setRenderingReference("{$l},{$r}"); $parser->setWhitespaceMode($whitespace_mode); $spec = $request->getStr('range'); list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec); $output = $parser->render($range_s, $range_e, $mask); if ($request->isAjax()) { return id(new PhabricatorChangesetResponse())->setRenderedChangeset($output); } require_celerity_resource('differential-changeset-view-css'); require_celerity_resource('syntax-highlighting-css'); require_celerity_resource('phriction-document-css'); Javelin::initBehavior('differential-show-more', array('uri' => '/phriction/diff/' . $document->getID() . '/', 'whitespace' => $whitespace_mode)); $slug = $document->getSlug(); $revert_l = $this->renderRevertButton($content_l, $current); $revert_r = $this->renderRevertButton($content_r, $current); $crumbs = new AphrontCrumbsView(); $crumbs->setCrumbs(array('Phriction', phutil_render_tag('a', array('href' => PhrictionDocument::getSlugURI($slug)), phutil_escape_html($current->getTitle())), phutil_render_tag('a', array('href' => '/phriction/history/' . $document->getSlug() . '/'), 'History'), phutil_escape_html("Changes Between Version {$l} and Version {$r}"))); $comparison_table = $this->renderComparisonTable(array($content_r, $content_l)); $navigation_table = null; if ($l + 1 == $r) { $nav_l = $l > 1; $nav_r = $r != $current->getVersion(); $uri = $request->getRequestURI(); if ($nav_l) { $link_l = phutil_render_tag('a', array('href' => $uri->alter('l', $l - 1)->alter('r', $r - 1)), "« Previous Change"); } else { $link_l = 'Original Change'; } $link_r = null; if ($nav_r) { $link_r = phutil_render_tag('a', array('href' => $uri->alter('l', $l + 1)->alter('r', $r + 1)), "Next Change »"); } else { $link_r = 'Most Recent Change'; } $navigation_table = '<table class="phriction-history-nav-table"> <tr> <td class="nav-prev">' . $link_l . '</td> <td class="nav-next">' . $link_r . '</td> </tr> </table>'; } $output = '<div class="phriction-document-history-diff">' . $comparison_table->render() . '<br />' . '<br />' . $navigation_table . '<table class="phriction-revert-table">' . '<tr><td>' . $revert_l . '</td><td>' . $revert_r . '</td>' . '</table>' . $output . '</div>'; return $this->buildStandardPageResponse(array($crumbs, $output), array('title' => 'Document History')); }
public function render() { $this->requireResource('differential-changeset-view-css'); $changesets = $this->changesets; Javelin::initBehavior('differential-toggle-files', array('pht' => array('undo' => pht('Undo'), 'collapsed' => pht('This file content has been collapsed.')))); Javelin::initBehavior('differential-dropdown-menus', array('pht' => array('Open in Editor' => pht('Open in Editor'), 'Show All Context' => pht('Show All Context'), 'All Context Shown' => pht('All Context Shown'), "Can't Toggle Unloaded File" => pht("Can't Toggle Unloaded File"), 'Expand File' => pht('Expand File'), 'Collapse File' => pht('Collapse File'), 'Browse in Diffusion' => pht('Browse in Diffusion'), 'View Standalone' => pht('View Standalone'), 'Show Raw File (Left)' => pht('Show Raw File (Left)'), 'Show Raw File (Right)' => pht('Show Raw File (Right)'), 'Configure Editor' => pht('Configure Editor'), 'Load Changes' => pht('Load Changes'), 'View Side-by-Side' => pht('View Side-by-Side'), 'View Unified' => pht('View Unified'), 'Change Text Encoding...' => pht('Change Text Encoding...'), 'Highlight As...' => pht('Highlight As...')))); $renderer = DifferentialChangesetParser::getDefaultRendererForViewer($this->getUser()); $output = array(); $ids = array(); foreach ($changesets as $key => $changeset) { $file = $changeset->getFilename(); $class = 'differential-changeset'; if (!$this->inlineURI) { $class .= ' differential-changeset-noneditable'; } $ref = $this->references[$key]; $detail = id(new DifferentialChangesetDetailView())->setUser($this->getUser()); $uniq_id = 'diff-' . $changeset->getAnchorName(); $detail->setID($uniq_id); $view_options = $this->renderViewOptionsDropdown($detail, $ref, $changeset); $detail->setChangeset($changeset); $detail->addButton($view_options); $detail->setSymbolIndex(idx($this->symbolIndexes, $key)); $detail->setVsChangesetID(idx($this->vsMap, $changeset->getID())); $detail->setEditable(true); $detail->setRenderingRef($ref); $detail->setRenderURI($this->renderURI); $detail->setWhitespace($this->whitespace); $detail->setRenderer($renderer); if ($this->getParser()) { $detail->appendChild($this->getParser()->renderChangeset()); $detail->setLoaded(true); } else { $detail->setAutoload(isset($this->visibleChangesets[$key])); if (isset($this->visibleChangesets[$key])) { $load = pht('Loading...'); } else { $load = javelin_tag('a', array('class' => 'button grey', 'href' => '#' . $uniq_id, 'sigil' => 'differential-load', 'meta' => array('id' => $detail->getID(), 'kill' => true), 'mustcapture' => true), pht('Load File')); } $detail->appendChild(phutil_tag('div', array('id' => $uniq_id), phutil_tag('div', array('class' => 'differential-loading'), $load))); } $output[] = $detail->render(); $ids[] = $detail->getID(); } $this->requireResource('aphront-tooltip-css'); $this->initBehavior('differential-populate', array('changesetViewIDs' => $ids)); $this->initBehavior('differential-comment-jump', array()); if ($this->inlineURI) { Javelin::initBehavior('differential-edit-inline-comments', array('uri' => $this->inlineURI, 'stage' => 'differential-review-stage', 'revealIcon' => hsprintf('%s', new PHUIDiffRevealIconView()))); } $header = id(new PHUIHeaderView())->setHeader($this->getTitle()); $content = phutil_tag('div', array('class' => 'differential-review-stage', 'id' => 'differential-review-stage'), $output); $object_box = id(new PHUIObjectBoxView())->setHeader($header)->setCollapsed(true)->appendChild($content); return $object_box; }
public function processRequest() { $request = $this->getRequest(); $author_phid = $request->getUser()->getPHID(); $rendering_reference = $request->getStr('ref'); $parts = explode('/', $rendering_reference); if (count($parts) == 2) { list($id, $vs) = $parts; } else { $id = $parts[0]; $vs = 0; } $id = (int) $id; $vs = (int) $vs; $changeset = id(new DifferentialChangeset())->load($id); if (!$changeset) { return new Aphront404Response(); } $view = $request->getStr('view'); if ($view) { $changeset->attachHunks($changeset->loadHunks()); $phid = idx($changeset->getMetadata(), "{$view}:binary-phid"); if ($phid) { return id(new AphrontRedirectResponse())->setURI("/file/info/{$phid}/"); } switch ($view) { case 'new': return $this->buildRawFileResponse($changeset, $is_new = true); case 'old': if ($vs && $vs != -1) { $vs_changeset = id(new DifferentialChangeset())->load($vs); if ($vs_changeset) { $vs_changeset->attachHunks($vs_changeset->loadHunks()); return $this->buildRawFileResponse($vs_changeset, $is_new = true); } } return $this->buildRawFileResponse($changeset, $is_new = false); default: return new Aphront400Response(); } } if ($vs && $vs != -1) { $vs_changeset = id(new DifferentialChangeset())->load($vs); if (!$vs_changeset) { return new Aphront404Response(); } } if (!$vs) { $right = $changeset; $left = null; $right_source = $right->getID(); $right_new = true; $left_source = $right->getID(); $left_new = false; $render_cache_key = $right->getID(); } else { if ($vs == -1) { $right = null; $left = $changeset; $right_source = $left->getID(); $right_new = false; $left_source = $left->getID(); $left_new = true; $render_cache_key = null; } else { $right = $changeset; $left = $vs_changeset; $right_source = $right->getID(); $right_new = true; $left_source = $left->getID(); $left_new = true; $render_cache_key = null; } } if ($left) { $left->attachHunks($left->loadHunks()); } if ($right) { $right->attachHunks($right->loadHunks()); } if ($left) { $left_data = $left->makeNewFile(); if ($right) { $right_data = $right->makeNewFile(); } else { $right_data = $left->makeOldFile(); } $engine = new PhabricatorDifferenceEngine(); $synthetic = $engine->generateChangesetFromFileContent($left_data, $right_data); $choice = clone nonempty($left, $right); $choice->attachHunks($synthetic->getHunks()); $changeset = $choice; } $coverage = null; if ($right && $right->getDiffID()) { $unit = id(new DifferentialDiffProperty())->loadOneWhere('diffID = %d AND name = %s', $right->getDiffID(), 'arc:unit'); if ($unit) { $coverage = array(); foreach ($unit->getData() as $result) { $result_coverage = idx($result, 'coverage'); if (!$result_coverage) { continue; } $file_coverage = idx($result_coverage, $right->getFileName()); if (!$file_coverage) { continue; } $coverage[] = $file_coverage; } $coverage = ArcanistUnitTestResult::mergeCoverage($coverage); } } $spec = $request->getStr('range'); list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec); $parser = new DifferentialChangesetParser(); $parser->setCoverage($coverage); $parser->setChangeset($changeset); $parser->setRenderingReference($rendering_reference); $parser->setRenderCacheKey($render_cache_key); $parser->setRightSideCommentMapping($right_source, $right_new); $parser->setLeftSideCommentMapping($left_source, $left_new); $parser->setWhitespaceMode($request->getStr('whitespace')); if ($left && $right) { $parser->setOriginals($left, $right); } // Load both left-side and right-side inline comments. $inlines = $this->loadInlineComments(array($left_source, $right_source), $author_phid); if ($left_new) { $inlines = array_merge($inlines, $this->buildLintInlineComments($left)); } if ($right_new) { $inlines = array_merge($inlines, $this->buildLintInlineComments($right)); } $phids = array(); foreach ($inlines as $inline) { $parser->parseInlineComment($inline); if ($inline->getAuthorPHID()) { $phids[$inline->getAuthorPHID()] = true; } } $phids = array_keys($phids); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $parser->setHandles($handles); $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine(); $parser->setMarkupEngine($engine); if ($request->isAjax()) { // TODO: This is sort of lazy, the effect is just to not render "Edit" // and "Reply" links on the "standalone view". $parser->setUser($request->getUser()); } $output = $parser->render($range_s, $range_e, $mask); $mcov = $parser->renderModifiedCoverage(); if ($request->isAjax()) { $coverage = array('differential-mcoverage-' . md5($changeset->getFilename()) => $mcov); return id(new PhabricatorChangesetResponse())->setRenderedChangeset($output)->setCoverage($coverage); } Javelin::initBehavior('differential-show-more', array('uri' => '/differential/changeset/', 'whitespace' => $request->getStr('whitespace'))); Javelin::initBehavior('differential-comment-jump', array()); $detail = new DifferentialChangesetDetailView(); $detail->setChangeset($changeset); $detail->appendChild($output); $detail->setVsChangesetID($left_source); $output = id(new DifferentialPrimaryPaneView())->setLineWidthFromChangesets(array($changeset))->appendChild('<div class="differential-review-stage" ' . 'id="differential-review-stage">' . $detail->render() . '</div>'); return $this->buildStandardPageResponse(array($output), array('title' => 'Changeset View')); }
private function tryCacheStuff() { $whitespace_mode = $this->whitespaceMode; switch ($whitespace_mode) { case self::WHITESPACE_SHOW_ALL: case self::WHITESPACE_IGNORE_TRAILING: break; default: $whitespace_mode = self::WHITESPACE_IGNORE_ALL; break; } $skip_cache = $whitespace_mode != self::WHITESPACE_IGNORE_ALL; $this->whitespaceMode = $whitespace_mode; $changeset = $this->changeset; if ($changeset->getFileType() == DifferentialChangeType::FILE_TEXT || $changeset->getFileType() == DifferentialChangeType::FILE_SYMLINK) { if ($skip_cache || !$this->loadCache()) { $ignore_all = $this->whitespaceMode == self::WHITESPACE_IGNORE_ALL; if ($ignore_all && $changeset->getWhitespaceMatters()) { $ignore_all = false; } // The "ignore all whitespace" algorithm depends on rediffing the // files, and we currently need complete representations of both // files to do anything reasonable. If we only have parts of the files, // don't use the "ignore all" algorithm. if ($ignore_all) { $hunks = $changeset->getHunks(); if (count($hunks) !== 1) { $ignore_all = false; } else { $first_hunk = reset($hunks); if ($first_hunk->getOldOffset() != 1 || $first_hunk->getNewOffset() != 1) { $ignore_all = false; } } } if ($ignore_all) { $old_file = $changeset->makeOldFile(); $new_file = $changeset->makeNewFile(); if ($old_file == $new_file) { // If the old and new files are exactly identical, the synthetic // diff below will give us nonsense and whitespace modes are // irrelevant anyway. This occurs when you, e.g., copy a file onto // itself in Subversion (see T271). $ignore_all = false; } } if ($ignore_all) { // Huge mess. Generate a "-bw" (ignore all whitespace changes) diff, // parse it out, and then play a shell game with the parsed format // in process() so we highlight only changed lines but render // whitespace differences. If we don't do this, we either fail to // render whitespace changes (which is incredibly confusing, // especially for python) or often produce a much larger set of // differences than necessary. $engine = new PhabricatorDifferenceEngine(); $engine->setIgnoreWhitespace(true); $no_whitespace_changeset = $engine->generateChangesetFromFileContent($old_file, $new_file); // subparser takes over the current non-whitespace-ignoring changeset $subparser = new DifferentialChangesetParser(); $subparser->isSubparser = true; $subparser->setChangeset($changeset); foreach ($changeset->getHunks() as $hunk) { $subparser->parseHunk($hunk); } // We need to call process() so that the subparser's values for // metadata (like 'unchanged') is correct. $subparser->process(); $this->subparser = $subparser; // While we aren't updating $this->changeset (since it has a bunch // of metadata we need to preserve, so that headers like "this file // was moved" render correctly), we're overwriting the local // $changeset so that the block below will choose the synthetic // hunks we've built instead of the original hunks. $changeset = $no_whitespace_changeset; } // This either uses the real hunks, or synthetic hunks we built above. foreach ($changeset->getHunks() as $hunk) { $this->parseHunk($hunk); } $this->process(); if (!$skip_cache) { $this->saveCache(); } } } }
public function handleRequest(AphrontRequest $request) { $response = $this->loadDiffusionContext(); if ($response) { return $response; } $viewer = $this->getViewer(); $drequest = $this->getDiffusionRequest(); if (!$request->isAjax()) { // This request came out of the dropdown menu, either "View Standalone" // or "View Raw File". $view = $request->getStr('view'); if ($view == 'r') { $uri = $drequest->generateURI(array('action' => 'browse', 'params' => array('view' => 'raw'))); } else { $uri = $drequest->generateURI(array('action' => 'change')); } return id(new AphrontRedirectResponse())->setURI($uri); } $data = $this->callConduitWithDiffusionRequest('diffusion.diffquery', array('commit' => $drequest->getCommit(), 'path' => $drequest->getPath())); $drequest->updateSymbolicCommit($data['effectiveCommit']); $raw_changes = ArcanistDiffChange::newFromConduit($data['changes']); $diff = DifferentialDiff::newEphemeralFromRawChanges($raw_changes); $changesets = $diff->getChangesets(); $changeset = reset($changesets); if (!$changeset) { return new Aphront404Response(); } $parser = new DifferentialChangesetParser(); $parser->setUser($viewer); $parser->setChangeset($changeset); $parser->setRenderingReference($drequest->generateURI(array('action' => 'rendering-ref'))); $parser->readParametersFromRequest($request); $coverage = $drequest->loadCoverage(); if ($coverage) { $parser->setCoverage($coverage); } $commit = $drequest->loadCommit(); $pquery = new DiffusionPathIDQuery(array($changeset->getFilename())); $ids = $pquery->loadPathIDs(); $path_id = $ids[$changeset->getFilename()]; $parser->setLeftSideCommentMapping($path_id, false); $parser->setRightSideCommentMapping($path_id, true); $parser->setCanMarkDone($commit->getAuthorPHID() && $viewer->getPHID() == $commit->getAuthorPHID()); $parser->setObjectOwnerPHID($commit->getAuthorPHID()); $parser->setWhitespaceMode(DifferentialChangesetParser::WHITESPACE_SHOW_ALL); $inlines = PhabricatorAuditInlineComment::loadDraftAndPublishedComments($viewer, $commit->getPHID(), $path_id); if ($inlines) { foreach ($inlines as $inline) { $parser->parseInlineComment($inline); } $phids = mpull($inlines, 'getAuthorPHID'); $handles = $this->loadViewerHandles($phids); $parser->setHandles($handles); } $engine = new PhabricatorMarkupEngine(); $engine->setViewer($viewer); foreach ($inlines as $inline) { $engine->addObject($inline, PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY); } $engine->process(); $parser->setMarkupEngine($engine); $spec = $request->getStr('range'); list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec); $parser->setRange($range_s, $range_e); $parser->setMask($mask); return id(new PhabricatorChangesetResponse())->setRenderedChangeset($parser->renderChangeset())->setUndoTemplates($parser->getRenderer()->renderUndoTemplates()); }
public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); $rendering_reference = $request->getStr('ref'); $parts = explode('/', $rendering_reference); if (count($parts) == 2) { list($id, $vs) = $parts; } else { $id = $parts[0]; $vs = 0; } $id = (int) $id; $vs = (int) $vs; $load_ids = array($id); if ($vs && $vs != -1) { $load_ids[] = $vs; } $changesets = id(new DifferentialChangesetQuery())->setViewer($viewer)->withIDs($load_ids)->needHunks(true)->execute(); $changesets = mpull($changesets, null, 'getID'); $changeset = idx($changesets, $id); if (!$changeset) { return new Aphront404Response(); } $vs_changeset = null; if ($vs && $vs != -1) { $vs_changeset = idx($changesets, $vs); if (!$vs_changeset) { return new Aphront404Response(); } } $view = $request->getStr('view'); if ($view) { $phid = idx($changeset->getMetadata(), "{$view}:binary-phid"); if ($phid) { return id(new AphrontRedirectResponse())->setURI("/file/info/{$phid}/"); } switch ($view) { case 'new': return $this->buildRawFileResponse($changeset, $is_new = true); case 'old': if ($vs_changeset) { return $this->buildRawFileResponse($vs_changeset, $is_new = true); } return $this->buildRawFileResponse($changeset, $is_new = false); default: return new Aphront400Response(); } } $old = array(); $new = array(); if (!$vs) { $right = $changeset; $left = null; $right_source = $right->getID(); $right_new = true; $left_source = $right->getID(); $left_new = false; $render_cache_key = $right->getID(); $old[] = $changeset; $new[] = $changeset; } else { if ($vs == -1) { $right = null; $left = $changeset; $right_source = $left->getID(); $right_new = false; $left_source = $left->getID(); $left_new = true; $render_cache_key = null; $old[] = $changeset; $new[] = $changeset; } else { $right = $changeset; $left = $vs_changeset; $right_source = $right->getID(); $right_new = true; $left_source = $left->getID(); $left_new = true; $render_cache_key = null; $new[] = $left; $new[] = $right; } } if ($left) { $left_data = $left->makeNewFile(); if ($right) { $right_data = $right->makeNewFile(); } else { $right_data = $left->makeOldFile(); } $engine = new PhabricatorDifferenceEngine(); $synthetic = $engine->generateChangesetFromFileContent($left_data, $right_data); $choice = clone nonempty($left, $right); $choice->attachHunks($synthetic->getHunks()); $changeset = $choice; } if ($left_new || $right_new) { $diff_map = array(); if ($left) { $diff_map[] = $left->getDiff(); } if ($right) { $diff_map[] = $right->getDiff(); } $diff_map = mpull($diff_map, null, 'getPHID'); $buildables = id(new HarbormasterBuildableQuery())->setViewer($viewer)->withBuildablePHIDs(array_keys($diff_map))->withManualBuildables(false)->needBuilds(true)->needTargets(true)->execute(); $buildables = mpull($buildables, null, 'getBuildablePHID'); foreach ($diff_map as $diff_phid => $changeset_diff) { $changeset_diff->attachBuildable(idx($buildables, $diff_phid)); } } $coverage = null; if ($right_new) { $coverage = $this->loadCoverage($right); } $spec = $request->getStr('range'); list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec); $parser = id(new DifferentialChangesetParser())->setCoverage($coverage)->setChangeset($changeset)->setRenderingReference($rendering_reference)->setRenderCacheKey($render_cache_key)->setRightSideCommentMapping($right_source, $right_new)->setLeftSideCommentMapping($left_source, $left_new); $parser->readParametersFromRequest($request); if ($left && $right) { $parser->setOriginals($left, $right); } $diff = $changeset->getDiff(); $revision_id = $diff->getRevisionID(); $can_mark = false; $object_owner_phid = null; $revision = null; if ($revision_id) { $revision = id(new DifferentialRevisionQuery())->setViewer($viewer)->withIDs(array($revision_id))->executeOne(); if ($revision) { $can_mark = $revision->getAuthorPHID() == $viewer->getPHID(); $object_owner_phid = $revision->getAuthorPHID(); } } // Load both left-side and right-side inline comments. if ($revision) { $query = id(new DifferentialInlineCommentQuery())->setViewer($viewer)->needHidden(true)->withRevisionPHIDs(array($revision->getPHID())); $inlines = $query->execute(); $inlines = $query->adjustInlinesForChangesets($inlines, $old, $new, $revision); } else { $inlines = array(); } if ($left_new) { $inlines = array_merge($inlines, $this->buildLintInlineComments($left)); } if ($right_new) { $inlines = array_merge($inlines, $this->buildLintInlineComments($right)); } $phids = array(); foreach ($inlines as $inline) { $parser->parseInlineComment($inline); if ($inline->getAuthorPHID()) { $phids[$inline->getAuthorPHID()] = true; } } $phids = array_keys($phids); $handles = $this->loadViewerHandles($phids); $parser->setHandles($handles); $engine = new PhabricatorMarkupEngine(); $engine->setViewer($viewer); foreach ($inlines as $inline) { $engine->addObject($inline, PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY); } $engine->process(); $parser->setUser($viewer)->setMarkupEngine($engine)->setShowEditAndReplyLinks(true)->setCanMarkDone($can_mark)->setObjectOwnerPHID($object_owner_phid)->setRange($range_s, $range_e)->setMask($mask); if ($request->isAjax()) { // NOTE: We must render the changeset before we render coverage // information, since it builds some caches. $rendered_changeset = $parser->renderChangeset(); $mcov = $parser->renderModifiedCoverage(); $coverage_data = array('differential-mcoverage-' . md5($changeset->getFilename()) => $mcov); return id(new PhabricatorChangesetResponse())->setRenderedChangeset($rendered_changeset)->setCoverage($coverage_data)->setUndoTemplates($parser->getRenderer()->renderUndoTemplates()); } $detail = id(new DifferentialChangesetListView())->setUser($this->getViewer())->setChangesets(array($changeset))->setVisibleChangesets(array($changeset))->setRenderingReferences(array($rendering_reference))->setRenderURI('/differential/changeset/')->setDiff($diff)->setTitle(pht('Standalone View'))->setParser($parser); if ($revision_id) { $detail->setInlineCommentControllerURI('/differential/comment/inline/edit/' . $revision_id . '/'); } $crumbs = $this->buildApplicationCrumbs(); if ($revision_id) { $crumbs->addTextCrumb('D' . $revision_id, '/D' . $revision_id); } $diff_id = $diff->getID(); if ($diff_id) { $crumbs->addTextCrumb(pht('Diff %d', $diff_id), $this->getApplicationURI('diff/' . $diff_id)); } $crumbs->addTextCrumb($changeset->getDisplayFilename()); return $this->buildApplicationPage(array($crumbs, $detail), array('title' => pht('Changeset View'), 'device' => false)); }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $document = id(new PhrictionDocumentQuery())->setViewer($user)->withIDs(array($this->id))->needContent(true)->executeOne(); if (!$document) { return new Aphront404Response(); } $current = $document->getContent(); $l = $request->getInt('l'); $r = $request->getInt('r'); $ref = $request->getStr('ref'); if ($ref) { list($l, $r) = explode(',', $ref); } $content = id(new PhrictionContent())->loadAllWhere('documentID = %d AND version IN (%Ld)', $document->getID(), array($l, $r)); $content = mpull($content, null, 'getVersion'); $content_l = idx($content, $l, null); $content_r = idx($content, $r, null); if (!$content_l || !$content_r) { return new Aphront404Response(); } $text_l = $content_l->getContent(); $text_r = $content_r->getContent(); $text_l = phutil_utf8_hard_wrap($text_l, 80); $text_l = implode("\n", $text_l); $text_r = phutil_utf8_hard_wrap($text_r, 80); $text_r = implode("\n", $text_r); $engine = new PhabricatorDifferenceEngine(); $changeset = $engine->generateChangesetFromFileContent($text_l, $text_r); $changeset->setOldProperties(array('Title' => $content_l->getTitle())); $changeset->setNewProperties(array('Title' => $content_r->getTitle())); $whitespace_mode = DifferentialChangesetParser::WHITESPACE_SHOW_ALL; $parser = new DifferentialChangesetParser(); $parser->setChangeset($changeset); $parser->setRenderingReference("{$l},{$r}"); $parser->setWhitespaceMode($whitespace_mode); $engine = new PhabricatorMarkupEngine(); $engine->setViewer($user); $engine->process(); $parser->setMarkupEngine($engine); $spec = $request->getStr('range'); list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec); $output = $parser->render($range_s, $range_e, $mask); if ($request->isAjax()) { return id(new PhabricatorChangesetResponse())->setRenderedChangeset($output); } require_celerity_resource('differential-changeset-view-css'); require_celerity_resource('syntax-highlighting-css'); require_celerity_resource('phriction-document-css'); Javelin::initBehavior('differential-show-more', array('uri' => '/phriction/diff/' . $document->getID() . '/', 'whitespace' => $whitespace_mode)); $slug = $document->getSlug(); $revert_l = $this->renderRevertButton($content_l, $current); $revert_r = $this->renderRevertButton($content_r, $current); $crumbs = $this->buildApplicationCrumbs(); $crumb_views = $this->renderBreadcrumbs($slug); foreach ($crumb_views as $view) { $crumbs->addCrumb($view); } $crumbs->addTextCrumb(pht('History'), PhrictionDocument::getSlugURI($slug, 'history')); $title = pht('Version %s vs %s', $l, $r); $header = id(new PHUIHeaderView())->setHeader($title); $crumbs->addTextCrumb($title, $request->getRequestURI()); $comparison_table = $this->renderComparisonTable(array($content_r, $content_l)); $navigation_table = null; if ($l + 1 == $r) { $nav_l = $l > 1; $nav_r = $r != $current->getVersion(); $uri = $request->getRequestURI(); if ($nav_l) { $link_l = phutil_tag('a', array('href' => $uri->alter('l', $l - 1)->alter('r', $r - 1), 'class' => 'button'), pht("« Previous Change")); } else { $link_l = phutil_tag('a', array('href' => '#', 'class' => 'button grey disabled'), pht('Original Change')); } $link_r = null; if ($nav_r) { $link_r = phutil_tag('a', array('href' => $uri->alter('l', $l + 1)->alter('r', $r + 1), 'class' => 'button'), pht("Next Change »")); } else { $link_r = phutil_tag('a', array('href' => '#', 'class' => 'button grey disabled'), pht('Most Recent Change')); } $navigation_table = phutil_tag('table', array('class' => 'phriction-history-nav-table'), phutil_tag('tr', array(), array(phutil_tag('td', array('class' => 'nav-prev'), $link_l), phutil_tag('td', array('class' => 'nav-next'), $link_r)))); } $output = hsprintf('<div class="phriction-document-history-diff">' . '%s%s' . '<table class="phriction-revert-table">' . '<tr><td>%s</td><td>%s</td>' . '</table>' . '%s' . '</div>', $comparison_table->render(), $navigation_table, $revert_l, $revert_r, $output); $object_box = id(new PHUIObjectBoxView())->setHeader($header)->appendChild($output); return $this->buildApplicationPage(array($crumbs, $object_box), array('title' => pht('Document History'))); }
public function processRequest() { $request = $this->getRequest(); $author_phid = $request->getUser()->getPHID(); $rendering_reference = $request->getStr('ref'); $parts = explode('/', $rendering_reference); if (count($parts) == 2) { list($id, $vs) = $parts; } else { $id = $parts[0]; $vs = 0; } $id = (int) $id; $vs = (int) $vs; $load_ids = array($id); if ($vs && $vs != -1) { $load_ids[] = $vs; } $changesets = id(new DifferentialChangesetQuery())->setViewer($request->getUser())->withIDs($load_ids)->needHunks(true)->execute(); $changesets = mpull($changesets, null, 'getID'); $changeset = idx($changesets, $id); if (!$changeset) { return new Aphront404Response(); } $vs_changeset = null; if ($vs && $vs != -1) { $vs_changeset = idx($changesets, $vs); if (!$vs_changeset) { return new Aphront404Response(); } } $view = $request->getStr('view'); if ($view) { $phid = idx($changeset->getMetadata(), "{$view}:binary-phid"); if ($phid) { return id(new AphrontRedirectResponse())->setURI("/file/info/{$phid}/"); } switch ($view) { case 'new': return $this->buildRawFileResponse($changeset, $is_new = true); case 'old': if ($vs_changeset) { return $this->buildRawFileResponse($vs_changeset, $is_new = true); } return $this->buildRawFileResponse($changeset, $is_new = false); default: return new Aphront400Response(); } } if (!$vs) { $right = $changeset; $left = null; $right_source = $right->getID(); $right_new = true; $left_source = $right->getID(); $left_new = false; $render_cache_key = $right->getID(); } else { if ($vs == -1) { $right = null; $left = $changeset; $right_source = $left->getID(); $right_new = false; $left_source = $left->getID(); $left_new = true; $render_cache_key = null; } else { $right = $changeset; $left = $vs_changeset; $right_source = $right->getID(); $right_new = true; $left_source = $left->getID(); $left_new = true; $render_cache_key = null; } } if ($left) { $left_data = $left->makeNewFile(); if ($right) { $right_data = $right->makeNewFile(); } else { $right_data = $left->makeOldFile(); } $engine = new PhabricatorDifferenceEngine(); $synthetic = $engine->generateChangesetFromFileContent($left_data, $right_data); $choice = clone nonempty($left, $right); $choice->attachHunks($synthetic->getHunks()); $changeset = $choice; } $coverage = null; if ($right && $right->getDiffID()) { $unit = id(new DifferentialDiffProperty())->loadOneWhere('diffID = %d AND name = %s', $right->getDiffID(), 'arc:unit'); if ($unit) { $coverage = array(); foreach ($unit->getData() as $result) { $result_coverage = idx($result, 'coverage'); if (!$result_coverage) { continue; } $file_coverage = idx($result_coverage, $right->getFileName()); if (!$file_coverage) { continue; } $coverage[] = $file_coverage; } $coverage = ArcanistUnitTestResult::mergeCoverage($coverage); } } $spec = $request->getStr('range'); list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec); $parser = new DifferentialChangesetParser(); $parser->setCoverage($coverage); $parser->setChangeset($changeset); $parser->setRenderingReference($rendering_reference); $parser->setRenderCacheKey($render_cache_key); $parser->setRightSideCommentMapping($right_source, $right_new); $parser->setLeftSideCommentMapping($left_source, $left_new); $parser->setWhitespaceMode($request->getStr('whitespace')); $parser->setCharacterEncoding($request->getStr('encoding')); $parser->setHighlightAs($request->getStr('highlight')); if ($request->getStr('renderer') == '1up') { $parser->setRenderer(new DifferentialChangesetOneUpRenderer()); } if ($left && $right) { $parser->setOriginals($left, $right); } // Load both left-side and right-side inline comments. $inlines = $this->loadInlineComments(array($left_source, $right_source), $author_phid); if ($left_new) { $inlines = array_merge($inlines, $this->buildLintInlineComments($left)); } if ($right_new) { $inlines = array_merge($inlines, $this->buildLintInlineComments($right)); } $phids = array(); foreach ($inlines as $inline) { $parser->parseInlineComment($inline); if ($inline->getAuthorPHID()) { $phids[$inline->getAuthorPHID()] = true; } } $phids = array_keys($phids); $handles = $this->loadViewerHandles($phids); $parser->setHandles($handles); $engine = new PhabricatorMarkupEngine(); $engine->setViewer($request->getUser()); foreach ($inlines as $inline) { $engine->addObject($inline, PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY); } $engine->process(); $parser->setMarkupEngine($engine); if ($request->isAjax()) { // TODO: This is sort of lazy, the effect is just to not render "Edit" // and "Reply" links on the "standalone view". $parser->setUser($request->getUser()); } $output = $parser->render($range_s, $range_e, $mask); $mcov = $parser->renderModifiedCoverage(); if ($request->isAjax()) { $coverage = array('differential-mcoverage-' . md5($changeset->getFilename()) => $mcov); return id(new PhabricatorChangesetResponse())->setRenderedChangeset($output)->setCoverage($coverage); } Javelin::initBehavior('differential-show-more', array('uri' => '/differential/changeset/', 'whitespace' => $request->getStr('whitespace'))); Javelin::initBehavior('differential-comment-jump', array()); // TODO: [HTML] Clean up DifferentialChangesetParser output, but it's // undergoing like six kinds of refactoring anyway. $output = phutil_safe_html($output); $detail = new DifferentialChangesetDetailView(); $detail->setChangeset($changeset); $detail->appendChild($output); $detail->setVsChangesetID($left_source); $panel = new DifferentialPrimaryPaneView(); $panel->appendChild(phutil_tag('div', array('class' => 'differential-review-stage', 'id' => 'differential-review-stage'), $detail->render())); $crumbs = $this->buildApplicationCrumbs(); $revision_id = $changeset->getDiff()->getRevisionID(); if ($revision_id) { $crumbs->addTextCrumb('D' . $revision_id, '/D' . $revision_id); } $diff_id = $changeset->getDiff()->getID(); if ($diff_id) { $crumbs->addTextCrumb(pht('Diff %d', $diff_id), $this->getApplicationURI('diff/' . $diff_id)); } $crumbs->addTextCrumb($changeset->getDisplayFilename()); $box = id(new PHUIObjectBoxView())->setHeaderText(pht('Standalone View'))->appendChild($panel); return $this->buildApplicationPage(array($crumbs, $box), array('title' => pht('Changeset View'), 'device' => false)); }