Page MenuHomePhabricator

D14963.diff
No OneTemporary

D14963.diff

diff --git a/src/applications/diffusion/controller/DiffusionBrowseController.php b/src/applications/diffusion/controller/DiffusionBrowseController.php
--- a/src/applications/diffusion/controller/DiffusionBrowseController.php
+++ b/src/applications/diffusion/controller/DiffusionBrowseController.php
@@ -592,15 +592,12 @@
$viewer = $this->getViewer();
- $blame_handles = array();
if ($needs_blame) {
$blame = $this->loadBlame($path, $drequest->getCommit());
- if ($blame) {
- $author_phids = mpull($blame, 'getAuthorPHID');
- $blame_handles = $viewer->loadHandles($author_phids);
- }
+ list($blame_list, $blame_commits) = $blame;
} else {
- $blame = array();
+ $blame_list = array();
+ $blame_commits = array();
}
$file_corpus = $file_content->getCorpus();
@@ -608,43 +605,11 @@
$can_highlight = (strlen($file_corpus) <= $highlight_limit);
if (!$show_color) {
- $lines = phutil_split_lines($file_corpus);
-
- $style =
- 'border: none; width: 100%; height: 80em; font-family: monospace';
- if (!$show_blame) {
- $corpus = phutil_tag(
- 'textarea',
- array(
- 'style' => $style,
- ),
- $file_corpus);
- } else {
- $rows = array();
- foreach ($lines as $line_number => $line) {
- $commit = idx($blame, $line_number);
- if ($commit) {
- $author = $commit->renderAuthorShortName($blame_handles);
- $commit_name = $commit->getShortName();
- } else {
- $author = null;
- $commit_name = null;
- }
-
- $rows[] = sprintf(
- '%-10s %-20s %s',
- $commit_name,
- $author,
- $line);
- }
-
- $corpus = phutil_tag(
- 'textarea',
- array(
- 'style' => $style,
- ),
- implode('', $rows));
- }
+ $corpus = $this->renderPlaintextCorpus(
+ $file_corpus,
+ $blame_list,
+ $blame_commits,
+ $show_blame);
} else {
if ($can_highlight) {
require_celerity_resource('syntax-highlighting-css');
@@ -659,7 +624,8 @@
$rows = $this->buildDisplayRows(
$lines,
- $blame,
+ $blame_list,
+ $blame_commits,
$show_blame,
$show_color);
@@ -883,25 +849,116 @@
private function buildDisplayRows(
array $lines,
- array $blame,
+ array $blame_list,
+ array $blame_commits,
$show_color,
$show_blame) {
+ $request = $this->getRequest();
+ $viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
- $handles = array();
- if ($blame) {
- $epoch_list = mpull($blame, 'getEpoch', 'getID');
- $epoch_list = array_filter($epoch_list);
+ $revision_map = array();
+ $revisions = array();
+ if ($blame_commits) {
+ $commit_map = mpull($blame_commits, 'getCommitIdentifier', 'getPHID');
+
+ $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) {
+ $revision_map[$commit_map[$commit_phid]] = $revision_id;
+ }
+ }
+
+ $phids = array();
+ foreach ($blame_commits as $commit) {
+ $author_phid = $commit->getAuthorPHID();
+ if ($author_phid === null) {
+ continue;
+ }
+ $phids[$author_phid] = $author_phid;
+ }
+
+ foreach ($revisions as $revision) {
+ $author_phid = $revision->getAuthorPHID();
+ if ($author_phid === null) {
+ continue;
+ }
+ $phids[$author_phid] = $author_phid;
+ }
+
+ $handles = $viewer->loadHandles($phids);
+
+ $colors = array();
+ if ($blame_commits) {
+ $epochs = array();
+
+ foreach ($blame_commits as $identifier => $commit) {
+ $epochs[$identifier] = $commit->getEpoch();
+ }
+
+ $epoch_list = array_filter($epochs);
$epoch_list = array_unique($epoch_list);
$epoch_list = array_values($epoch_list);
$epoch_min = min($epoch_list);
$epoch_max = max($epoch_list);
$epoch_range = ($epoch_max - $epoch_min) + 1;
+
+ foreach ($blame_commits as $identifier => $commit) {
+ $epoch = $epochs[$identifier];
+ if (!$epoch) {
+ $color = '#ffffdd'; // Warning color, missing data.
+ } else {
+ $color_ratio = ($epoch - $epoch_min) / $epoch_range;
+ $color_value = 0xE6 * (1.0 - $color_ratio);
+ $color = sprintf(
+ '#%02x%02x%02x',
+ $color_value,
+ 0xF6,
+ $color_value);
+ }
+
+ $colors[$identifier] = $color;
+ }
}
+ $display = array();
+ $last_identifier = null;
+ $last_color = null;
+ foreach ($lines as $line_index => $line) {
+ $color = '#f6f6f6';
+ $duplicate = false;
+ if (isset($blame_list[$line_index])) {
+ $identifier = $blame_list[$line_index];
+ if (isset($colors[$identifier])) {
+ $color = $colors[$identifier];
+ }
+
+ if ($identifier === $last_identifier) {
+ $duplicate = true;
+ } else {
+ $last_identifier = $identifier;
+ }
+ }
+
+ $display[$line_index] = array(
+ 'data' => $line,
+ 'target' => false,
+ 'highlighted' => false,
+ 'color' => $color,
+ 'duplicate' => $duplicate,
+ );
+ }
$line_arr = array();
$line_str = $drequest->getLine();
@@ -921,111 +978,22 @@
}
}
- $display = array();
-
- $line_number = 1;
- $last_commit = null;
- $color = null;
- foreach ($lines as $line_index => $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.
-
- $commit = idx($blame, $line_index, $last_commit);
-
- if ($commit && $last_commit &&
- ($last_commit->getID() == $commit->getID())) {
- $display_line['color'] = $color;
- } else {
- if ($commit) {
- $epoch = $commit->getEpoch();
- } else {
- $epoch = null;
- }
-
- if (!$epoch) {
- if (!$blame) {
- $color = '#f6f6f6';
- } else {
- $color = '#ffd'; // Render as warning.
- }
- } else {
- $color_ratio = ($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'] = $epoch;
- $display_line['color'] = $color;
-
- if ($commit) {
- $display_line['commit'] = $commit;
- } else {
- $display_line['commit'] = null;
- }
-
- $last_commit = $commit;
- }
+ // Mark the first highlighted line as the target line.
+ if ($line_arr) {
+ $target_line = $line_arr[0]['min'];
+ if (isset($display[$target_line - 1])) {
+ $display[$target_line - 1]['target'] = true;
}
-
- 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 = mpull($blame, 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 $blame_commit) {
- if ($blame_commit->getAuthorPHID()) {
- $phids[] = $blame_commit->getAuthorPHID();
- }
- }
- foreach ($revisions as $revision) {
- if ($revision->getAuthorPHID()) {
- $phids[] = $revision->getAuthorPHID();
+ // Mark all other highlighted lines as highlighted.
+ foreach ($line_arr as $range) {
+ for ($ii = $range['min']; $ii <= $range['max']; $ii++) {
+ if (isset($display[$ii - 1])) {
+ $display[$ii - 1]['highlighted'] = true;
+ }
}
}
- $handles = $this->loadViewerHandles($phids);
$engine = null;
$inlines = array();
@@ -1059,7 +1027,7 @@
// NOTE: We're doing this manually because rendering is otherwise
// dominated by URI generation for very large files.
- $line_base = (string)$repository->generateURI(
+ $line_base = (string)$drequest->generateURI(
array(
'action' => 'browse',
'stable' => true,
@@ -1070,122 +1038,87 @@
Javelin::initBehavior('phabricator-tooltips');
Javelin::initBehavior('phabricator-line-linker');
- foreach ($display as $line) {
- $line_href = $line_base.'$'.$line['line'];
+ // Render these once, since they tend to get repeated many times in large
+ // blame outputs.
+ $commit_links = $this->renderCommitLinks($blame_commits, $handles);
+ $revision_links = $this->renderRevisionLinks($revisions, $handles);
- $blame = array();
- $style = null;
- if (array_key_exists('color', $line)) {
- if ($line['color']) {
- $style = 'background: '.$line['color'].';';
- }
+ $skip_text = pht('Skip Past This Commit');
+ foreach ($display as $line_index => $line) {
+ $row = array();
- $before_link = null;
- $commit_link = null;
- $revision_link = null;
- if (idx($line, 'commit')) {
- $commit = $line['commit'];
-
- if ($commit) {
- $tooltip = $this->renderCommitTooltip(
- $commit,
- $handles,
- $commit->renderAuthorLink($handles));
- } else {
- $tooltip = null;
- }
+ $line_number = $line_index + 1;
+ $line_href = $line_base.'$'.$line_number;
- $commit_link = javelin_tag(
- 'a',
- array(
- 'href' => $drequest->generateURI(
- array(
- 'action' => 'commit',
- 'commit' => $commit->getCommitIdentifier(),
- )),
- 'sigil' => 'has-tooltip',
- 'meta' => array(
- 'tip' => $tooltip,
- 'align' => 'E',
- 'size' => 600,
- ),
- ),
- $commit->getShortName());
+ if (isset($blame_list[$line_index])) {
+ $identifier = $blame_list[$line_index];
+ } else {
+ $identifier = null;
+ }
- $revision_id = null;
- if ($commit) {
- $revision_id = idx($revision_ids, $commit->getPHID());
- }
+ $revision_link = null;
+ $commit_link = null;
+ $before_link = null;
+ $style = null;
+ if ($identifier && !$line['duplicate']) {
+ $style = 'background: '.$line['color'].';';
- 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());
- }
- }
+ if (isset($commit_links[$identifier])) {
+ $commit_link = $commit_links[$identifier];
+ }
- if ($commit) {
- $identifier = $commit->getCommitIdentifier();
- $skip_href = $line_href.'?before='.$identifier.'&view=blame';
-
- $before_link = javelin_tag(
- 'a',
- array(
- 'href' => $skip_href,
- 'sigil' => 'has-tooltip',
- 'meta' => array(
- 'tip' => pht('Skip Past This Commit'),
- 'align' => 'E',
- 'size' => 300,
- ),
- ),
- "\xC2\xAB");
+ if (isset($revision_map[$identifier])) {
+ $revision_id = $revision_map[$identifier];
+ if (isset($revision_links[$revision_id])) {
+ $revision_link = $revision_links[$revision_id];
}
}
- $blame[] = phutil_tag(
- 'th',
+ $skip_href = $line_href.'?before='.$identifier.'&view=blame';
+ $before_link = javelin_tag(
+ 'a',
array(
- 'class' => 'diffusion-blame-link',
+ 'href' => $skip_href,
+ 'sigil' => 'has-tooltip',
+ 'meta' => array(
+ 'tip' => $skip_text,
+ 'align' => 'E',
+ 'size' => 300,
+ ),
),
- $before_link);
+ "\xC2\xAB");
+ }
- $object_links = array();
- $object_links[] = $commit_link;
- if ($revision_link) {
- $object_links[] = phutil_tag('span', array(), '/');
- $object_links[] = $revision_link;
- }
+ $row[] = phutil_tag(
+ 'th',
+ array(
+ 'class' => 'diffusion-blame-link',
+ ),
+ $before_link);
- $blame[] = phutil_tag(
- 'th',
- array(
- 'class' => 'diffusion-rev-link',
- ),
- $object_links);
+ $object_links = array();
+ $object_links[] = $commit_link;
+ if ($revision_link) {
+ $object_links[] = phutil_tag('span', array(), '/');
+ $object_links[] = $revision_link;
}
+ $row[] = phutil_tag(
+ 'th',
+ array(
+ 'class' => 'diffusion-rev-link',
+ ),
+ $object_links);
+
$line_link = phutil_tag(
'a',
array(
'href' => $line_href,
'style' => $style,
),
- $line['line']);
+ $line_number);
- $blame[] = javelin_tag(
+ $row[] = javelin_tag(
'th',
array(
'class' => 'diffusion-line-link',
@@ -1210,7 +1143,7 @@
$anchor_text = null;
}
- $blame[] = phutil_tag(
+ $row[] = phutil_tag(
'td',
array(
),
@@ -1234,7 +1167,7 @@
$cov_class = 'N';
}
- $blame[] = phutil_tag(
+ $row[] = phutil_tag(
'td',
array(
'class' => 'cov cov-'.$cov_class,
@@ -1249,10 +1182,10 @@
'phabricator-source-highlight' :
null),
),
- $blame);
+ $row);
$cur_inlines = $this->renderInlines(
- idx($inlines, $line['line'], array()),
+ idx($inlines, $line_number, array()),
$show_blame,
$this->coverage,
$engine);
@@ -1520,7 +1453,6 @@
private function renderCommitTooltip(
PhabricatorRepositoryCommit $commit,
- array $handles,
$author) {
$viewer = $this->getRequest()->getUser();
@@ -1528,10 +1460,6 @@
$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}";
}
@@ -1809,16 +1737,133 @@
$commits = array();
}
- foreach ($identifiers as $key => $identifier) {
- $commit = idx($commits, $identifier);
- if ($commit) {
- $identifiers[$key] = $commit;
+ return array($identifiers, $commits);
+ }
+
+ 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->getShortName());
+
+ $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->getURI(),
+ 'sigil' => 'has-tooltip',
+ 'meta' => array(
+ 'tip' => $tooltip,
+ 'align' => 'E',
+ 'size' => 600,
+ ),
+ ),
+ $revision->getMonogram());
+
+ $links[$revision_id] = $revision_link;
+ }
+
+ return $links;
+ }
+
+ private function renderPlaintextCorpus(
+ $file_corpus,
+ array $blame_list,
+ array $blame_commits,
+ $show_blame) {
+
+ $viewer = $this->getViewer();
+
+ if (!$show_blame) {
+ $corpus = $file_corpus;
+ } else {
+ $author_phids = array();
+ foreach ($blame_commits as $commit) {
+ $author_phid = $commit->getAuthorPHID();
+ if ($author_phid === null) {
+ continue;
+ }
+ $author_phids[$author_phid] = $author_phid;
+ }
+
+ if ($author_phids) {
+ $handles = $viewer->loadHandles($author_phids);
} else {
- $identifiers[$key] = null;
+ $handles = array();
+ }
+
+ $authors = array();
+ $names = array();
+ foreach ($blame_commits as $identifier => $commit) {
+ $author = $commit->renderAuthorShortName($handles);
+ $name = $commit->getShortName();
+
+ $authors[$identifier] = $author;
+ $names[$identifier] = $name;
+ }
+
+ $lines = phutil_split_lines($file_corpus);
+
+ $rows = array();
+ foreach ($lines as $line_number => $line) {
+ $commit_name = null;
+ $author = null;
+
+ if (isset($blame_list[$line_number])) {
+ $identifier = $blame_list[$line_number];
+
+ if (isset($names[$identifier])) {
+ $commit_name = $names[$identifier];
+ }
+
+ if (isset($authors[$identifier])) {
+ $author = $authors[$identifier];
+ }
+ }
+
+ $rows[] = sprintf(
+ '%-10s %-20s %s',
+ $commit_name,
+ $author,
+ $line);
}
+ $corpus = implode('', $rows);
}
- return $identifiers;
+ return phutil_tag(
+ 'textarea',
+ array(
+ 'style' => 'border: none; width: 100%; height: 80em; '.
+ 'font-family: monospace',
+ ),
+ $corpus);
}
}

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 15, 8:04 PM (3 d, 10 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6739105
Default Alt Text
D14963.diff (19 KB)

Event Timeline