protected function getResult(ConduitAPIRequest $request) { $drequest = $this->getDiffusionRequest(); $path_dicts = $request->getValue('paths', array()); $paths = array(); foreach ($path_dicts as $dict) { $paths[] = DiffusionRepositoryPath::newFromDictionary($dict); } $best = -1; $readme = ''; $best_render_type = 'plain'; foreach ($paths as $result_path) { $file_type = $result_path->getFileType(); if ($file_type != ArcanistDiffChangeType::FILE_NORMAL && $file_type != ArcanistDiffChangeType::FILE_TEXT) { // Skip directories, etc. continue; } $path = strtolower($result_path->getPath()); if ($path === 'readme') { $path .= '.remarkup'; } if (strncmp($path, 'readme.', 7) !== 0) { continue; } $priority = 0; switch (substr($path, 7)) { case 'remarkup': $priority = 100; $render_type = 'remarkup'; break; case 'rainbow': $priority = 90; $render_type = 'rainbow'; break; case 'md': $priority = 50; $render_type = 'remarkup'; break; case 'txt': $priority = 10; $render_type = 'plain'; break; default: $priority = 0; $render_type = 'plain'; break; } if ($priority > $best) { $best = $priority; $readme = $result_path; $best_render_type = $render_type; } } if (!$readme) { return ''; } $readme_request = DiffusionRequest::newFromDictionary(array('user' => $request->getUser(), 'repository' => $drequest->getRepository(), 'commit' => $drequest->getStableCommit(), 'path' => $readme->getFullPath())); $file_content = DiffusionFileContent::newFromConduit(DiffusionQuery::callConduitWithDiffusionRequest($request->getUser(), $readme_request, 'diffusion.filecontentquery', array('commit' => $drequest->getStableCommit(), 'path' => $readme->getFullPath(), 'needsBlame' => false))); $readme_content = $file_content->getCorpus(); switch ($best_render_type) { case 'plain': $readme_content = phutil_escape_html_newlines($readme_content); $class = null; break; case 'rainbow': $highlighter = new PhutilRainbowSyntaxHighlighter(); $readme_content = $highlighter->getHighlightFuture($readme_content)->resolve(); $readme_content = phutil_escape_html_newlines($readme_content); require_celerity_resource('syntax-highlighting-css'); $class = 'remarkup-code'; break; case 'remarkup': // TODO: This is sketchy, but make sure we hit the markup cache. $markup_object = id(new PhabricatorMarkupOneOff())->setEngineRuleset('diffusion-readme')->setContent($readme_content); $markup_field = 'default'; $readme_content = id(new PhabricatorMarkupEngine())->setViewer($request->getUser())->addObject($markup_object, $markup_field)->process()->getOutput($markup_object, $markup_field); $engine = $markup_object->newMarkupEngine($markup_field); $toc = PhutilRemarkupHeaderBlockRule::renderTableOfContents($engine); if ($toc) { $toc = phutil_tag_div('phabricator-remarkup-toc', array(phutil_tag_div('phabricator-remarkup-toc-header', pht('Table of Contents')), $toc)); $readme_content = array($toc, $readme_content); } $class = 'phabricator-remarkup'; break; } $readme_content = phutil_tag('div', array('class' => $class), $readme_content); return $readme_content; }
protected function processDiffusionRequest(AphrontRequest $request) { $drequest = $this->getDiffusionRequest(); $viewer = $request->getUser(); $before = $request->getStr('before'); if ($before) { return $this->buildBeforeResponse($before); } $path = $drequest->getPath(); $preferences = $viewer->loadPreferences(); $show_blame = $request->getBool('blame', $preferences->getPreference(PhabricatorUserPreferences::PREFERENCE_DIFFUSION_BLAME, false)); $show_color = $request->getBool('color', $preferences->getPreference(PhabricatorUserPreferences::PREFERENCE_DIFFUSION_COLOR, true)); $view = $request->getStr('view'); if ($request->isFormPost() && $view != 'raw' && $viewer->isLoggedIn()) { $preferences->setPreference(PhabricatorUserPreferences::PREFERENCE_DIFFUSION_BLAME, $show_blame); $preferences->setPreference(PhabricatorUserPreferences::PREFERENCE_DIFFUSION_COLOR, $show_color); $preferences->save(); $uri = $request->getRequestURI()->alter('blame', null)->alter('color', null); return id(new AphrontRedirectResponse())->setURI($uri); } // We need the blame information if blame is on and we're building plain // text, or blame is on and this is an Ajax request. If blame is on and // this is a colorized request, we don't show blame at first (we ajax it // in afterward) so we don't need to query for it. $needs_blame = $show_blame && !$show_color || $show_blame && $request->isAjax(); $params = array('commit' => $drequest->getCommit(), 'path' => $drequest->getPath(), 'needsBlame' => $needs_blame); $byte_limit = null; if ($view !== 'raw') { $byte_limit = PhabricatorFileStorageEngine::getChunkThreshold(); $time_limit = 10; $params += array('timeout' => $time_limit, 'byteLimit' => $byte_limit); } $file_content = DiffusionFileContent::newFromConduit($this->callConduitWithDiffusionRequest('diffusion.filecontentquery', $params)); $data = $file_content->getCorpus(); if ($view === 'raw') { return $this->buildRawResponse($path, $data); } $this->loadLintMessages(); $this->coverage = $drequest->loadCoverage(); if ($byte_limit && strlen($data) == $byte_limit) { $corpus = $this->buildErrorCorpus(pht('This file is larger than %s byte(s), and too large to display ' . 'in the web UI.', $byte_limit)); } else { if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) { $file = $this->loadFileForData($path, $data); $file_uri = $file->getBestURI(); if ($file->isViewableImage()) { $corpus = $this->buildImageCorpus($file_uri); } else { $corpus = $this->buildBinaryCorpus($file_uri, $data); } } else { // Build the content of the file. $corpus = $this->buildCorpus($show_blame, $show_color, $file_content, $needs_blame, $drequest, $path, $data); } } if ($request->isAjax()) { return id(new AphrontAjaxResponse())->setContent($corpus); } require_celerity_resource('diffusion-source-css'); // Render the page. $view = $this->buildActionView($drequest); $action_list = $this->enrichActionView($view, $drequest, $show_blame, $show_color); $properties = $this->buildPropertyView($drequest, $action_list); $object_box = id(new PHUIObjectBoxView())->setHeader($this->buildHeaderView($drequest))->addPropertyList($properties); $content = array(); $content[] = $object_box; $follow = $request->getStr('follow'); if ($follow) { $notice = new PHUIInfoView(); $notice->setSeverity(PHUIInfoView::SEVERITY_WARNING); $notice->setTitle(pht('Unable to Continue')); switch ($follow) { case 'first': $notice->appendChild(pht('Unable to continue tracing the history of this file because ' . 'this commit is the first commit in the repository.')); break; case 'created': $notice->appendChild(pht('Unable to continue tracing the history of this file because ' . 'this commit created the file.')); break; } $content[] = $notice; } $renamed = $request->getStr('renamed'); if ($renamed) { $notice = new PHUIInfoView(); $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE); $notice->setTitle(pht('File Renamed')); $notice->appendChild(pht("File history passes through a rename from '%s' to '%s'.", $drequest->getPath(), $renamed)); $content[] = $notice; } $content[] = $corpus; $content[] = $this->buildOpenRevisions(); $crumbs = $this->buildCrumbs(array('branch' => true, 'path' => true, 'view' => 'browse')); $basename = basename($this->getDiffusionRequest()->getPath()); return $this->buildApplicationPage(array($crumbs, $content), array('title' => $basename)); }