Something went wrong. Try again.
@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
Something went wrong. Try again.
29 kB · 1020 lines
PHP
at commit dcd7a316
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021<?php
final class DiffusionBrowseFileController extends DiffusionBrowseController {
private $lintCommit; private $lintMessages;
public function processRequest() { $request = $this->getRequest(); $drequest = $this->getDiffusionRequest();
$before = $request->getStr('before'); if ($before) { return $this->buildBeforeResponse($before); }
$path = $drequest->getPath();
$preferences = $request->getUser()->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') { $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());
$file_content = DiffusionFileContent::newFromConduit( $this->callConduitWithDiffusionRequest( 'diffusion.filecontentquery', array( 'commit' => $drequest->getCommit(), 'path' => $drequest->getPath(), 'needsBlame' => $needs_blame, ))); $data = $file_content->getCorpus();
if ($view === 'raw') { return $this->buildRawResponse($path, $data); }
$this->loadLintMessages();
$binary_uri = null; 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); $binary_uri = $file_uri; } } 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, $binary_uri);
$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 AphrontErrorView(); $notice->setSeverity(AphrontErrorView::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 AphrontErrorView(); $notice->setSeverity(AphrontErrorView::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, )); }
private function loadLintMessages() { $drequest = $this->getDiffusionRequest(); $branch = $drequest->loadBranch();
if (!$branch || !$branch->getLintCommit()) { return; }
$this->lintCommit = $branch->getLintCommit();
$conn = id(new PhabricatorRepository())->establishConnection('r');
$where = ''; if ($drequest->getLint()) { $where = qsprintf( $conn, 'AND code = %s', $drequest->getLint()); }
$this->lintMessages = queryfx_all( $conn, 'SELECT * FROM %T WHERE branchID = %d %Q AND path = %s', PhabricatorRepository::TABLE_LINTMESSAGE, $branch->getID(), $where, '/'.$drequest->getPath()); }
private function buildCorpus( $show_blame, $show_color, DiffusionFileContent $file_content, $needs_blame, DiffusionRequest $drequest, $path, $data) {
if (!$show_color) { $style = "margin: 1em 2em; width: 90%; height: 80em; font-family: monospace"; if (!$show_blame) { $corpus = phutil_tag( 'textarea', array( 'style' => $style, ), $file_content->getCorpus()); } else { $text_list = $file_content->getTextList(); $rev_list = $file_content->getRevList(); $blame_dict = $file_content->getBlameDict();
$rows = array(); foreach ($text_list as $k => $line) { $rev = $rev_list[$k]; $author = $blame_dict[$rev]['author']; $rows[] = sprintf("%-10s %-20s %s", substr($rev, 0, 7), $author, $line); }
$corpus = phutil_tag( 'textarea', array( 'style' => $style, ), implode("\n", $rows)); } } else { require_celerity_resource('syntax-highlighting-css'); $text_list = $file_content->getTextList(); $rev_list = $file_content->getRevList(); $blame_dict = $file_content->getBlameDict();
$text_list = implode("\n", $text_list); $text_list = PhabricatorSyntaxHighlighter::highlightWithFilename( $path, $text_list); $text_list = explode("\n", $text_list);
$rows = $this->buildDisplayRows($text_list, $rev_list, $blame_dict, $needs_blame, $drequest, $show_blame, $show_color);
$corpus_table = javelin_tag( 'table', array( 'class' => "diffusion-source remarkup-code PhabricatorMonospaced", 'sigil' => 'phabricator-source', ), $rows);
if ($this->getRequest()->isAjax()) { return $corpus_table; }
$id = celerity_generate_unique_node_id();
$projects = $drequest->loadArcanistProjects(); $langs = array(); foreach ($projects as $project) { $ls = $project->getSymbolIndexLanguages(); if (!$ls) { continue; } $dep_projects = $project->getSymbolIndexProjects(); $dep_projects[] = $project->getPHID(); foreach ($ls as $lang) { if (!isset($langs[$lang])) { $langs[$lang] = array(); } $langs[$lang] += $dep_projects + array($project); } }
$lang = last(explode('.', $drequest->getPath()));
if (isset($langs[$lang])) { Javelin::initBehavior( 'repository-crossreference', array( 'container' => $id, 'lang' => $lang, 'projects' => $langs[$lang], )); }
$corpus = phutil_tag( 'div', array( 'id' => $id, ), $corpus_table);
$corpus = id(new PHUIObjectBoxView()) ->setHeaderText('File Contents') ->appendChild($corpus);
Javelin::initBehavior('load-blame', array('id' => $id)); }
return $corpus; }
private function enrichActionView( PhabricatorActionListView $view, DiffusionRequest $drequest, $show_blame, $show_color, $binary_uri) {
$viewer = $this->getRequest()->getUser(); $base_uri = $this->getRequest()->getRequestURI();
$view->addAction( id(new PhabricatorActionView()) ->setName(pht('Show Last Change')) ->setHref( $drequest->generateURI( array( 'action' => 'change', ))) ->setIcon('new'));
if ($show_blame) { $blame_text = pht('Disable Blame'); $blame_icon = 'blame-grey'; $blame_value = 0; } else { $blame_text = pht('Enable Blame'); $blame_icon = 'blame'; $blame_value = 1; }
$view->addAction( id(new PhabricatorActionView()) ->setName($blame_text) ->setHref($base_uri->alter('blame', $blame_value)) ->setIcon($blame_icon) ->setUser($viewer) ->setRenderAsForm(true));
if ($show_color) { $highlight_text = pht('Disable Highlighting'); $highlight_icon = 'highlight-grey'; $highlight_value = 0; } else { $highlight_text = pht('Enable Highlighting'); $highlight_icon = 'highlight'; $highlight_value = 1; }
$view->addAction( id(new PhabricatorActionView()) ->setName($highlight_text) ->setHref($base_uri->alter('color', $highlight_value)) ->setIcon($highlight_icon) ->setUser($viewer) ->setRenderAsForm(true));
$href = null; if ($this->getRequest()->getStr('lint') !== null) { $lint_text = pht('Hide %d Lint Message(s)', count($this->lintMessages)); $href = $base_uri->alter('lint', null);
} else if ($this->lintCommit === null) { $lint_text = pht('Lint not Available'); } else { $lint_text = pht( 'Show %d Lint Message(s)', count($this->lintMessages)); $href = $this->getDiffusionRequest()->generateURI(array( 'action' => 'browse', 'commit' => $this->lintCommit, ))->alter('lint', ''); }
$view->addAction( id(new PhabricatorActionView()) ->setName($lint_text) ->setHref($href) ->setIcon('warning') ->setDisabled(!$href));
if ($binary_uri) { $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Download Raw File')) ->setHref($binary_uri) ->setIcon('download')); } else { $view->addAction( id(new PhabricatorActionView()) ->setName(pht('View Raw File')) ->setHref($base_uri->alter('view', 'raw')) ->setIcon('file')); }
$view->addAction($this->createEditAction());
return $view; }
private function createEditAction() { $request = $this->getRequest(); $user = $request->getUser();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository(); $path = $drequest->getPath(); $line = nonempty((int)$drequest->getLine(), 1);
$callsign = $repository->getCallsign(); $editor_link = $user->loadEditorLink($path, $line, $callsign);
$action = id(new PhabricatorActionView()) ->setName(pht('Open in Editor')) ->setIcon('edit');
$action->setHref($editor_link); $action->setDisabled(!$editor_link);
return $action; }
private function buildDisplayRows( array $text_list, array $rev_list, array $blame_dict, $needs_blame, DiffusionRequest $drequest, $show_blame, $show_color) {
$handles = array(); if ($blame_dict) { $epoch_list = ipull(ifilter($blame_dict, 'epoch'), 'epoch'); $epoch_min = min($epoch_list); $epoch_max = max($epoch_list); $epoch_range = ($epoch_max - $epoch_min) + 1;
$author_phids = ipull(ifilter($blame_dict, 'authorPHID'), 'authorPHID'); $handles = $this->loadViewerHandles($author_phids); }
$line_arr = array(); $line_str = $drequest->getLine(); $ranges = explode(',', $line_str); foreach ($ranges as $range) { if (strpos($range, '-') !== false) { list($min, $max) = explode('-', $range, 2); $line_arr[] = array( 'min' => min($min, $max), 'max' => max($min, $max), ); } else if (strlen($range)) { $line_arr[] = array( 'min' => $range, 'max' => $range, ); } }
$display = array();
$line_number = 1; $last_rev = null; $color = null; foreach ($text_list as $k => $line) { $display_line = array( 'epoch' => null, 'commit' => null, 'author' => null, 'target' => null, 'highlighted' => null, 'line' => $line_number, 'data' => $line, );
if ($show_blame) { // If the line's rev is same as the line above, show empty content // with same color; otherwise generate blame info. The newer a change // is, the more saturated the color.
$rev = idx($rev_list, $k, $last_rev);
if ($last_rev == $rev) { $display_line['color'] = $color; } else { $blame = $blame_dict[$rev];
if (!isset($blame['epoch'])) { $color = '#ffd'; // Render as warning. } else { $color_ratio = ($blame['epoch'] - $epoch_min) / $epoch_range; $color_value = 0xE6 * (1.0 - $color_ratio); $color = sprintf( '#%02x%02x%02x', $color_value, 0xF6, $color_value); }
$display_line['epoch'] = idx($blame, 'epoch'); $display_line['color'] = $color; $display_line['commit'] = $rev;
$author_phid = idx($blame, 'authorPHID'); if ($author_phid && $handles[$author_phid]) { $author_link = $handles[$author_phid]->renderLink(); } else { $author_link = phutil_tag( 'span', array( ), $blame['author']); } $display_line['author'] = $author_link;
$last_rev = $rev; } }
if ($line_arr) { if ($line_number == $line_arr[0]['min']) { $display_line['target'] = true; } foreach ($line_arr as $range) { if ($line_number >= $range['min'] && $line_number <= $range['max']) { $display_line['highlighted'] = true; } } }
$display[] = $display_line; ++$line_number; }
$request = $this->getRequest(); $viewer = $request->getUser();
$commits = array_filter(ipull($display, 'commit')); if ($commits) { $commits = id(new DiffusionCommitQuery()) ->setViewer($viewer) ->withRepository($drequest->getRepository()) ->withIdentifiers($commits) ->execute(); $commits = mpull($commits, null, 'getCommitIdentifier'); }
$revision_ids = id(new DifferentialRevision()) ->loadIDsByCommitPHIDs(mpull($commits, 'getPHID')); $revisions = array(); if ($revision_ids) { $revisions = id(new DifferentialRevisionQuery()) ->setViewer($viewer) ->withIDs($revision_ids) ->execute(); }
$phids = array(); foreach ($commits as $commit) { if ($commit->getAuthorPHID()) { $phids[] = $commit->getAuthorPHID(); } } foreach ($revisions as $revision) { if ($revision->getAuthorPHID()) { $phids[] = $revision->getAuthorPHID(); } } $handles = $this->loadViewerHandles($phids);
Javelin::initBehavior('phabricator-oncopy', array());
$engine = null; $inlines = array(); if ($this->getRequest()->getStr('lint') !== null && $this->lintMessages) { $engine = new PhabricatorMarkupEngine(); $engine->setViewer($viewer);
foreach ($this->lintMessages as $message) { $inline = id(new PhabricatorAuditInlineComment()) ->setID($message['id']) ->setSyntheticAuthor( ArcanistLintSeverity::getStringForSeverity($message['severity']). ' '.$message['code'].' ('.$message['name'].')') ->setLineNumber($message['line']) ->setContent($message['description']); $inlines[$message['line']][] = $inline;
$engine->addObject( $inline, PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY); }
$engine->process(); require_celerity_resource('differential-changeset-view-css'); }
$rows = $this->renderInlines( idx($inlines, 0, array()), ($show_blame), $engine);
foreach ($display as $line) {
$line_href = $drequest->generateURI( array( 'action' => 'browse', 'line' => $line['line'], 'stable' => true, ));
$blame = array(); $style = null; if (array_key_exists('color', $line)) { if ($line['color']) { $style = 'background: '.$line['color'].';'; }
$before_link = null; $commit_link = null; $revision_link = null; if (idx($line, 'commit')) { $commit = $line['commit'];
if (idx($commits, $commit)) { $tooltip = $this->renderCommitTooltip( $commits[$commit], $handles, $line['author']); } else { $tooltip = null; }
Javelin::initBehavior('phabricator-tooltips', array()); require_celerity_resource('aphront-tooltip-css');
$commit_link = javelin_tag( 'a', array( 'href' => $drequest->generateURI( array( 'action' => 'commit', 'commit' => $line['commit'], )), 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => $tooltip, 'align' => 'E', 'size' => 600, ), ), phutil_utf8_shorten($line['commit'], 9, ''));
$revision_id = null; if (idx($commits, $commit)) { $revision_id = idx($revision_ids, $commits[$commit]->getPHID()); }
if ($revision_id) { $revision = idx($revisions, $revision_id); if ($revision) { $tooltip = $this->renderRevisionTooltip($revision, $handles); $revision_link = javelin_tag( 'a', array( 'href' => '/D'.$revision->getID(), 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => $tooltip, 'align' => 'E', 'size' => 600, ), ), 'D'.$revision->getID()); } }
$uri = $line_href->alter('before', $commit); $before_link = javelin_tag( 'a', array( 'href' => $uri->setQueryParam('view', 'blame'), 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => pht('Skip Past This Commit'), 'align' => 'E', 'size' => 300, ), ), "\xC2\xAB"); }
$blame[] = phutil_tag( 'th', array( 'class' => 'diffusion-blame-link', ), $before_link);
$object_links = array(); $object_links[] = $commit_link; if ($revision_link) { $object_links[] = phutil_tag('span', array(), '/'); $object_links[] = $revision_link; }
$blame[] = phutil_tag( 'th', array( 'class' => 'diffusion-rev-link', ), $object_links); }
$line_link = phutil_tag( 'a', array( 'href' => $line_href, 'style' => $style, ), $line['line']);
$blame[] = javelin_tag( 'th', array( 'class' => 'diffusion-line-link', 'sigil' => 'phabricator-source-line', 'style' => $style, ), $line_link);
Javelin::initBehavior('phabricator-line-linker');
if ($line['target']) { Javelin::initBehavior( 'diffusion-jump-to', array( 'target' => 'scroll_target', )); $anchor_text = phutil_tag( 'a', array( 'id' => 'scroll_target', ), ''); } else { $anchor_text = null; }
$blame[] = phutil_tag( 'td', array( ), array( $anchor_text,
// NOTE: See phabricator-oncopy behavior. "\xE2\x80\x8B",
// TODO: [HTML] Not ideal. phutil_safe_html(str_replace("\t", ' ', $line['data'])), ));
$rows[] = phutil_tag( 'tr', array( 'class' => ($line['highlighted'] ? 'phabricator-source-highlight' : null), ), $blame);
$rows = array_merge($rows, $this->renderInlines( idx($inlines, $line['line'], array()), ($show_blame), $engine)); }
return $rows; }
private function renderInlines(array $inlines, $needs_blame, $engine) { $rows = array(); foreach ($inlines as $inline) { $inline_view = id(new DifferentialInlineCommentView()) ->setMarkupEngine($engine) ->setInlineComment($inline) ->render(); $row = array_fill(0, ($needs_blame ? 5 : 1), phutil_tag('th')); $row[] = phutil_tag('td', array(), $inline_view); $rows[] = phutil_tag('tr', array('class' => 'inline'), $row); } return $rows; }
private function loadFileForData($path, $data) { $file = PhabricatorFile::buildFromFileDataOrHash( $data, array( 'name' => basename($path), 'ttl' => time() + 60 * 60 * 24, 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE, ));
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); $file->attachToObject( $this->getRequest()->getUser(), $this->getDiffusionRequest()->getRepository()->getPHID()); unset($unguarded);
return $file; }
private function buildRawResponse($path, $data) { $file = $this->loadFileForData($path, $data); return id(new AphrontRedirectResponse())->setURI($file->getBestURI()); }
private function buildImageCorpus($file_uri) { $properties = new PHUIPropertyListView();
$properties->addImageContent( phutil_tag( 'img', array( 'src' => $file_uri, )));
return id(new PHUIObjectBoxView()) ->setHeaderText(pht('Image')) ->addPropertyList($properties); }
private function buildBinaryCorpus($file_uri, $data) { $properties = new PHUIPropertyListView();
$size = strlen($data); $properties->addTextContent( pht( 'This is a binary file. It is %s byte(s) in length.', new PhutilNumber($size)));
return $properties; }
private function buildBeforeResponse($before) { $request = $this->getRequest(); $drequest = $this->getDiffusionRequest();
// NOTE: We need to get the grandparent so we can capture filename changes // in the parent.
$parent = $this->loadParentCommitOf($before); $old_filename = null; $was_created = false; if ($parent) { $grandparent = $this->loadParentCommitOf($parent);
if ($grandparent) { $rename_query = new DiffusionRenameHistoryQuery(); $rename_query->setRequest($drequest); $rename_query->setOldCommit($grandparent); $rename_query->setViewer($request->getUser()); $old_filename = $rename_query->loadOldFilename(); $was_created = $rename_query->getWasCreated(); } }
$follow = null; if ($was_created) { // If the file was created in history, that means older commits won't // have it. Since we know it existed at 'before', it must have been // created then; jump there. $target_commit = $before; $follow = 'created'; } else if ($parent) { // If we found a parent, jump to it. This is the normal case. $target_commit = $parent; } else { // If there's no parent, this was probably created in the initial commit? // And the "was_created" check will fail because we can't identify the // grandparent. Keep the user at 'before'. $target_commit = $before; $follow = 'first'; }
$path = $drequest->getPath(); $renamed = null; if ($old_filename !== null && $old_filename !== '/'.$path) { $renamed = $path; $path = $old_filename; }
$line = null; // If there's a follow error, drop the line so the user sees the message. if (!$follow) { $line = $this->getBeforeLineNumber($target_commit); }
$before_uri = $drequest->generateURI( array( 'action' => 'browse', 'commit' => $target_commit, 'line' => $line, 'path' => $path, ));
$before_uri->setQueryParams($request->getRequestURI()->getQueryParams()); $before_uri = $before_uri->alter('before', null); $before_uri = $before_uri->alter('renamed', $renamed); $before_uri = $before_uri->alter('follow', $follow);
return id(new AphrontRedirectResponse())->setURI($before_uri); }
private function getBeforeLineNumber($target_commit) { $drequest = $this->getDiffusionRequest();
$line = $drequest->getLine(); if (!$line) { return null; }
$raw_diff = $this->callConduitWithDiffusionRequest( 'diffusion.rawdiffquery', array( 'commit' => $drequest->getCommit(), 'path' => $drequest->getPath(), 'againstCommit' => $target_commit)); $old_line = 0; $new_line = 0;
foreach (explode("\n", $raw_diff) as $text) { if ($text[0] == '-' || $text[0] == ' ') { $old_line++; } if ($text[0] == '+' || $text[0] == ' ') { $new_line++; } if ($new_line == $line) { return $old_line; } }
// We didn't find the target line. return $line; }
private function loadParentCommitOf($commit) { $drequest = $this->getDiffusionRequest(); $user = $this->getRequest()->getUser();
$before_req = DiffusionRequest::newFromDictionary( array( 'user' => $user, 'repository' => $drequest->getRepository(), 'commit' => $commit, ));
$parents = DiffusionQuery::callConduitWithDiffusionRequest( $user, $before_req, 'diffusion.commitparentsquery', array( 'commit' => $commit, ));
return head($parents); }
private function renderRevisionTooltip( DifferentialRevision $revision, array $handles) { $viewer = $this->getRequest()->getUser();
$date = phabricator_date($revision->getDateModified(), $viewer); $id = $revision->getID(); $title = $revision->getTitle(); $header = "D{$id} {$title}";
$author = $handles[$revision->getAuthorPHID()]->getName();
return "{$header}\n{$date} \xC2\xB7 {$author}"; }
private function renderCommitTooltip( PhabricatorRepositoryCommit $commit, array $handles, $author) {
$viewer = $this->getRequest()->getUser();
$date = phabricator_date($commit->getEpoch(), $viewer); $summary = trim($commit->getSummary());
if ($commit->getAuthorPHID()) { $author = $handles[$commit->getAuthorPHID()]->getName(); }
return "{$summary}\n{$date} \xC2\xB7 {$author}"; }
}