Mostly make blame work with DocumentEngine
Summary: Ref T13105. This needs refinement but blame sort of works again, now. Test Plan: Viewed files in Diffusion and Files; saw blame in Diffusion when viewing in source mode. Reviewers: mydeveloperday Reviewed By: mydeveloperday Maniphest Tasks: T13105 Differential Revision: https://secure.phabricator.com/D19309
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
<?php
|
||||
|
||||
final class DiffusionBlameController extends DiffusionController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$response = $this->loadDiffusionContext();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
$drequest = $this->getDiffusionRequest();
|
||||
$repository = $drequest->getRepository();
|
||||
|
||||
$blame = $this->loadBlame();
|
||||
|
||||
$identifiers = array_fuse($blame);
|
||||
if ($identifiers) {
|
||||
$commits = id(new DiffusionCommitQuery())
|
||||
->setViewer($viewer)
|
||||
->withRepository($repository)
|
||||
->withIdentifiers($identifiers)
|
||||
->execute();
|
||||
$commits = mpull($commits, null, 'getCommitIdentifier');
|
||||
} else {
|
||||
$commits = array();
|
||||
}
|
||||
|
||||
$commit_map = mpull($commits, 'getCommitIdentifier', 'getPHID');
|
||||
|
||||
$revisions = array();
|
||||
$revision_map = array();
|
||||
if ($commits) {
|
||||
$revision_ids = id(new DifferentialRevision())
|
||||
->loadIDsByCommitPHIDs(array_keys($commit_map));
|
||||
if ($revision_ids) {
|
||||
$revisions = id(new DifferentialRevisionQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs($revision_ids)
|
||||
->execute();
|
||||
$revisions = mpull($revisions, null, 'getID');
|
||||
}
|
||||
|
||||
foreach ($revision_ids as $commit_phid => $revision_id) {
|
||||
// If the viewer can't actually see this revision, skip it.
|
||||
if (!isset($revisions[$revision_id])) {
|
||||
continue;
|
||||
}
|
||||
$revision_map[$commit_map[$commit_phid]] = $revision_id;
|
||||
}
|
||||
}
|
||||
|
||||
$base_href = (string)$drequest->generateURI(
|
||||
array(
|
||||
'action' => 'browse',
|
||||
'stable' => true,
|
||||
));
|
||||
|
||||
$skip_text = pht('Skip Past This Commit');
|
||||
$skip_icon = id(new PHUIIconView())
|
||||
->setIcon('fa-backward');
|
||||
|
||||
Javelin::initBehavior('phabricator-tooltips');
|
||||
|
||||
$handle_phids = array();
|
||||
foreach ($commits as $commit) {
|
||||
$author_phid = $commit->getAuthorPHID();
|
||||
if ($author_phid) {
|
||||
$handle_phids[] = $author_phid;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($revisions as $revision) {
|
||||
$handle_phids[] = $revision->getAuthorPHID();
|
||||
}
|
||||
|
||||
$handles = $viewer->loadHandles($handle_phids);
|
||||
|
||||
$map = array();
|
||||
foreach ($identifiers as $identifier) {
|
||||
$revision_id = idx($revision_map, $identifier);
|
||||
if ($revision_id) {
|
||||
$revision = idx($revisions, $revision_id);
|
||||
} else {
|
||||
$revision = null;
|
||||
}
|
||||
|
||||
$skip_href = $base_href.'?before='.$identifier;
|
||||
|
||||
$skip_link = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $skip_href,
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => $skip_text,
|
||||
'align' => 'E',
|
||||
'size' => 300,
|
||||
),
|
||||
),
|
||||
$skip_icon);
|
||||
|
||||
$commit = $commits[$identifier];
|
||||
|
||||
$author_phid = $commit->getAuthorPHID();
|
||||
if (!$author_phid && $revision) {
|
||||
$author_phid = $revision->getAuthorPHID();
|
||||
}
|
||||
|
||||
if (!$author_phid) {
|
||||
// This means we couldn't identify an author for the commit or the
|
||||
// revision. We just render a blank for alignment.
|
||||
$author_style = null;
|
||||
$author_href = null;
|
||||
$author_sigil = null;
|
||||
$author_meta = null;
|
||||
} else {
|
||||
$author_src = $handles[$author_phid]->getImageURI();
|
||||
$author_style = 'background-image: url('.$author_src.');';
|
||||
$author_href = $handles[$author_phid]->getURI();
|
||||
$author_sigil = 'has-tooltip';
|
||||
$author_meta = array(
|
||||
'tip' => $handles[$author_phid]->getName(),
|
||||
'align' => 'E',
|
||||
);
|
||||
}
|
||||
|
||||
$author_link = javelin_tag(
|
||||
$author_href ? 'a' : 'span',
|
||||
array(
|
||||
'class' => 'phabricator-source-blame-author',
|
||||
'style' => $author_style,
|
||||
'href' => $author_href,
|
||||
'sigil' => $author_sigil,
|
||||
'meta' => $author_meta,
|
||||
));
|
||||
|
||||
$commit_link = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $commit->getURI(),
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => $this->renderCommitTooltip($commit, $handles),
|
||||
'align' => 'E',
|
||||
'size' => 600,
|
||||
),
|
||||
),
|
||||
$commit->getLocalName());
|
||||
|
||||
$info = array(
|
||||
$author_link,
|
||||
$commit_link,
|
||||
);
|
||||
|
||||
if ($revision) {
|
||||
$revision_link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $revision->getURI(),
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => $this->renderRevisionTooltip($revision, $handles),
|
||||
'align' => 'E',
|
||||
'size' => 600,
|
||||
),
|
||||
),
|
||||
$revision->getMonogram());
|
||||
|
||||
|
||||
$info = array(
|
||||
$info,
|
||||
' / ',
|
||||
$revision_link,
|
||||
);
|
||||
}
|
||||
|
||||
$data = array(
|
||||
'skip' => $skip_link,
|
||||
'info' => hsprintf('%s', $info),
|
||||
);
|
||||
|
||||
$map[$identifier] = $data;
|
||||
}
|
||||
|
||||
return id(new AphrontAjaxResponse())->setContent(
|
||||
array(
|
||||
'blame' => $blame,
|
||||
'map' => $map,
|
||||
));
|
||||
}
|
||||
|
||||
private function loadBlame() {
|
||||
$drequest = $this->getDiffusionRequest();
|
||||
|
||||
$commit = $drequest->getCommit();
|
||||
$path = $drequest->getPath();
|
||||
|
||||
$blame_timeout = 15;
|
||||
|
||||
$blame = $this->callConduitWithDiffusionRequest(
|
||||
'diffusion.blame',
|
||||
array(
|
||||
'commit' => $commit,
|
||||
'paths' => array($path),
|
||||
'timeout' => $blame_timeout,
|
||||
));
|
||||
|
||||
return idx($blame, $path, array());
|
||||
}
|
||||
|
||||
private function renderRevisionTooltip(
|
||||
DifferentialRevision $revision,
|
||||
$handles) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$date = phabricator_date($revision->getDateModified(), $viewer);
|
||||
$monogram = $revision->getMonogram();
|
||||
$title = $revision->getTitle();
|
||||
$header = "{$monogram} {$title}";
|
||||
|
||||
$author = $handles[$revision->getAuthorPHID()]->getName();
|
||||
|
||||
return "{$header}\n{$date} \xC2\xB7 {$author}";
|
||||
}
|
||||
|
||||
private function renderCommitTooltip(
|
||||
PhabricatorRepositoryCommit $commit,
|
||||
$handles) {
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$date = phabricator_date($commit->getEpoch(), $viewer);
|
||||
$summary = trim($commit->getSummary());
|
||||
|
||||
$author_phid = $commit->getAuthorPHID();
|
||||
if ($author_phid && isset($handles[$author_phid])) {
|
||||
$author_name = $handles[$author_phid]->getName();
|
||||
} else {
|
||||
$author_name = null;
|
||||
}
|
||||
|
||||
if ($author_name) {
|
||||
return "{$summary}\n{$date} \xC2\xB7 {$author_name}";
|
||||
} else {
|
||||
return "{$summary}\n{$date}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -110,12 +110,6 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||
}
|
||||
|
||||
$path = $drequest->getPath();
|
||||
|
||||
// We need the blame information if 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 = $request->isAjax();
|
||||
|
||||
$params = array(
|
||||
'commit' => $drequest->getCommit(),
|
||||
'path' => $drequest->getPath(),
|
||||
@@ -184,11 +178,10 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||
$file->setName($basename);
|
||||
|
||||
return $file->getRedirectResponse();
|
||||
} else {
|
||||
$corpus = $this->buildGitLFSCorpus($lfs_ref);
|
||||
}
|
||||
|
||||
$corpus = $this->buildGitLFSCorpus($lfs_ref);
|
||||
} else {
|
||||
$this->loadLintMessages();
|
||||
$this->coverage = $drequest->loadCoverage();
|
||||
$show_editor = true;
|
||||
|
||||
@@ -205,12 +198,6 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->isAjax()) {
|
||||
return id(new AphrontAjaxResponse())->setContent($corpus);
|
||||
}
|
||||
|
||||
require_celerity_resource('diffusion-source-css');
|
||||
|
||||
$bar = $this->buildButtonBar($drequest, $show_editor);
|
||||
$header = $this->buildHeaderView($drequest);
|
||||
$header->setHeaderIcon('fa-file-code-o');
|
||||
@@ -480,35 +467,6 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||
return $view;
|
||||
}
|
||||
|
||||
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 buildButtonBar(
|
||||
DiffusionRequest $drequest,
|
||||
$show_editor) {
|
||||
@@ -550,33 +508,6 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||
->setColor(PHUIButtonView::GREY);
|
||||
}
|
||||
|
||||
$href = null;
|
||||
$show_lint = true;
|
||||
if ($this->getRequest()->getStr('lint') !== null) {
|
||||
$lint_text = pht('Hide Lint');
|
||||
$href = $base_uri->alter('lint', null);
|
||||
|
||||
} else if ($this->lintCommit === null) {
|
||||
$show_lint = false;
|
||||
} else {
|
||||
$lint_text = pht('Show Lint');
|
||||
$href = $this->getDiffusionRequest()->generateURI(array(
|
||||
'action' => 'browse',
|
||||
'commit' => $this->lintCommit,
|
||||
))->alter('lint', '');
|
||||
}
|
||||
|
||||
if ($show_lint) {
|
||||
$buttons[] =
|
||||
id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setText($lint_text)
|
||||
->setHref($href)
|
||||
->setIcon('fa-exclamation-triangle')
|
||||
->setDisabled(!$href)
|
||||
->setColor(PHUIButtonView::GREY);
|
||||
}
|
||||
|
||||
$bar = id(new PHUILeftRightView())
|
||||
->setLeft($buttons)
|
||||
->addClass('diffusion-action-bar full-mobile-buttons');
|
||||
@@ -705,40 +636,6 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||
->setColor(PHUIButtonView::GREY);
|
||||
}
|
||||
|
||||
private function renderInlines(
|
||||
array $inlines,
|
||||
$has_coverage,
|
||||
$engine) {
|
||||
|
||||
$rows = array();
|
||||
foreach ($inlines as $inline) {
|
||||
|
||||
// TODO: This should use modern scaffolding code.
|
||||
|
||||
$inline_view = id(new PHUIDiffInlineCommentDetailView())
|
||||
->setUser($this->getViewer())
|
||||
->setMarkupEngine($engine)
|
||||
->setInlineComment($inline)
|
||||
->render();
|
||||
|
||||
$row = array_fill(0, 3, phutil_tag('th'));
|
||||
|
||||
$row[] = phutil_tag('td', array(), $inline_view);
|
||||
|
||||
if ($has_coverage) {
|
||||
$row[] = phutil_tag(
|
||||
'td',
|
||||
array(
|
||||
'class' => 'cov cov-I',
|
||||
));
|
||||
}
|
||||
|
||||
$rows[] = phutil_tag('tr', array('class' => 'inline'), $row);
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
private function buildErrorCorpus($message) {
|
||||
$text = id(new PHUIBoxView())
|
||||
->addPadding(PHUI::PADDING_LARGE)
|
||||
@@ -898,33 +795,6 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||
return head($parents);
|
||||
}
|
||||
|
||||
private function renderRevisionTooltip(
|
||||
DifferentialRevision $revision,
|
||||
$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,
|
||||
$author) {
|
||||
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
|
||||
$date = phabricator_date($commit->getEpoch(), $viewer);
|
||||
$summary = trim($commit->getSummary());
|
||||
|
||||
return "{$summary}\n{$date} \xC2\xB7 {$author}";
|
||||
}
|
||||
|
||||
protected function markupText($text) {
|
||||
$engine = PhabricatorMarkupEngine::newDiffusionMarkupEngine();
|
||||
$engine->setConfig('viewer', $this->getRequest()->getUser());
|
||||
@@ -1108,127 +978,6 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||
return $view;
|
||||
}
|
||||
|
||||
private function loadBlame($path, $commit, $timeout) {
|
||||
$blame = $this->callConduitWithDiffusionRequest(
|
||||
'diffusion.blame',
|
||||
array(
|
||||
'commit' => $commit,
|
||||
'paths' => array($path),
|
||||
'timeout' => $timeout,
|
||||
));
|
||||
|
||||
$identifiers = idx($blame, $path, null);
|
||||
|
||||
if ($identifiers) {
|
||||
$viewer = $this->getViewer();
|
||||
$drequest = $this->getDiffusionRequest();
|
||||
$repository = $drequest->getRepository();
|
||||
|
||||
$commits = id(new DiffusionCommitQuery())
|
||||
->setViewer($viewer)
|
||||
->withRepository($repository)
|
||||
->withIdentifiers($identifiers)
|
||||
// TODO: We only fetch this to improve author display behavior, but
|
||||
// shouldn't really need to?
|
||||
->needCommitData(true)
|
||||
->execute();
|
||||
$commits = mpull($commits, null, 'getCommitIdentifier');
|
||||
} else {
|
||||
$commits = array();
|
||||
}
|
||||
|
||||
return array($identifiers, $commits);
|
||||
}
|
||||
|
||||
private function renderAuthorLinks(array $authors, $handles) {
|
||||
$links = array();
|
||||
|
||||
foreach ($authors as $phid) {
|
||||
if (!strlen($phid)) {
|
||||
// This means we couldn't identify an author for the commit or the
|
||||
// revision. We just render a blank for alignment.
|
||||
$style = null;
|
||||
$href = null;
|
||||
$sigil = null;
|
||||
$meta = null;
|
||||
} else {
|
||||
$src = $handles[$phid]->getImageURI();
|
||||
$style = 'background-image: url('.$src.');';
|
||||
$href = $handles[$phid]->getURI();
|
||||
$sigil = 'has-tooltip';
|
||||
$meta = array(
|
||||
'tip' => $handles[$phid]->getName(),
|
||||
'align' => 'E',
|
||||
);
|
||||
}
|
||||
|
||||
$links[$phid] = javelin_tag(
|
||||
$href ? 'a' : 'span',
|
||||
array(
|
||||
'class' => 'diffusion-author-link',
|
||||
'style' => $style,
|
||||
'href' => $href,
|
||||
'sigil' => $sigil,
|
||||
'meta' => $meta,
|
||||
));
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
private function renderCommitLinks(array $commits, $handles) {
|
||||
$links = array();
|
||||
foreach ($commits as $identifier => $commit) {
|
||||
$tooltip = $this->renderCommitTooltip(
|
||||
$commit,
|
||||
$commit->renderAuthorShortName($handles));
|
||||
|
||||
$commit_link = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $commit->getURI(),
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => $tooltip,
|
||||
'align' => 'E',
|
||||
'size' => 600,
|
||||
),
|
||||
),
|
||||
$commit->getLocalName());
|
||||
|
||||
$links[$identifier] = $commit_link;
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
private function renderRevisionLinks(array $revisions, $handles) {
|
||||
$links = array();
|
||||
|
||||
foreach ($revisions as $revision) {
|
||||
$revision_id = $revision->getID();
|
||||
|
||||
$tooltip = $this->renderRevisionTooltip($revision, $handles);
|
||||
|
||||
$revision_link = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/'.$revision->getMonogram(),
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => $tooltip,
|
||||
'align' => 'E',
|
||||
'size' => 600,
|
||||
),
|
||||
),
|
||||
$revision->getMonogram());
|
||||
|
||||
$links[$revision_id] = $revision_link;
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
private function getGitLFSRef(PhabricatorRepository $repository, $data) {
|
||||
if (!$repository->canUseGitLFS()) {
|
||||
return null;
|
||||
@@ -1375,13 +1124,4 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||
->setTable($history_table);
|
||||
}
|
||||
|
||||
private function getLineNumberBaseURI() {
|
||||
$drequest = $this->getDiffusionRequest();
|
||||
|
||||
return (string)$drequest->generateURI(
|
||||
array(
|
||||
'action' => 'browse',
|
||||
'stable' => true,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user