2011-01-24 22:18:41 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class DifferentialDiffTableOfContentsView extends AphrontView {
|
|
|
|
|
|
|
|
private $changesets = array();
|
2012-03-15 18:45:35 +01:00
|
|
|
private $visibleChangesets = array();
|
2012-05-01 21:09:50 +02:00
|
|
|
private $references = array();
|
2012-03-01 08:16:45 +01:00
|
|
|
private $repository;
|
|
|
|
private $diff;
|
2011-04-15 23:25:23 +02:00
|
|
|
private $renderURI = '/differential/changeset/';
|
|
|
|
private $revisionID;
|
2011-04-28 06:16:35 +02:00
|
|
|
private $whitespace;
|
2012-03-13 01:06:55 +01:00
|
|
|
private $unitTestData;
|
2011-01-24 22:18:41 +01:00
|
|
|
|
|
|
|
public function setChangesets($changesets) {
|
|
|
|
$this->changesets = $changesets;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-03-15 18:45:35 +01:00
|
|
|
public function setVisibleChangesets($visible_changesets) {
|
|
|
|
$this->visibleChangesets = $visible_changesets;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-05-01 21:09:50 +02:00
|
|
|
public function setRenderingReferences(array $references) {
|
|
|
|
$this->references = $references;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-03-01 08:16:45 +01:00
|
|
|
public function setRepository(PhabricatorRepository $repository) {
|
|
|
|
$this->repository = $repository;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setDiff(DifferentialDiff $diff) {
|
|
|
|
$this->diff = $diff;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-03-13 01:06:55 +01:00
|
|
|
public function setUnitTestData($unit_test_data) {
|
|
|
|
$this->unitTestData = $unit_test_data;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2011-04-15 23:25:23 +02:00
|
|
|
public function setRevisionID($revision_id) {
|
|
|
|
$this->revisionID = $revision_id;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2011-04-28 06:16:35 +02:00
|
|
|
public function setWhitespace($whitespace) {
|
|
|
|
$this->whitespace = $whitespace;
|
|
|
|
return $this;
|
|
|
|
}
|
2011-04-15 23:25:23 +02:00
|
|
|
|
2011-01-24 22:18:41 +01:00
|
|
|
public function render() {
|
2011-01-27 23:55:52 +01:00
|
|
|
|
|
|
|
require_celerity_resource('differential-core-view-css');
|
2011-01-25 20:57:47 +01:00
|
|
|
require_celerity_resource('differential-table-of-contents-css');
|
2011-01-24 22:18:41 +01:00
|
|
|
|
|
|
|
$rows = array();
|
|
|
|
|
2012-03-13 01:06:55 +01:00
|
|
|
$coverage = array();
|
|
|
|
if ($this->unitTestData) {
|
|
|
|
$coverage_by_file = array();
|
|
|
|
foreach ($this->unitTestData as $result) {
|
|
|
|
$test_coverage = idx($result, 'coverage');
|
|
|
|
if (!$test_coverage) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foreach ($test_coverage as $file => $results) {
|
|
|
|
$coverage_by_file[$file][] = $results;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach ($coverage_by_file as $file => $coverages) {
|
|
|
|
$coverage[$file] = ArcanistUnitTestResult::mergeCoverage($coverages);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-24 22:18:41 +01:00
|
|
|
$changesets = $this->changesets;
|
2012-03-01 08:16:45 +01:00
|
|
|
$paths = array();
|
2012-03-15 18:45:35 +01:00
|
|
|
foreach ($changesets as $id => $changeset) {
|
2011-01-24 22:18:41 +01:00
|
|
|
$type = $changeset->getChangeType();
|
|
|
|
$ftype = $changeset->getFileType();
|
2012-05-01 21:09:50 +02:00
|
|
|
$ref = idx($this->references, $id);
|
2013-04-16 20:02:04 +02:00
|
|
|
$display_file = $changeset->getDisplayFilename();
|
2012-01-16 07:43:54 +01:00
|
|
|
|
2013-04-16 20:02:04 +02:00
|
|
|
$meta = null;
|
2011-01-24 22:18:41 +01:00
|
|
|
if (DifferentialChangeType::isOldLocationChangeType($type)) {
|
|
|
|
$away = $changeset->getAwayPaths();
|
|
|
|
if (count($away) > 1) {
|
|
|
|
$meta = array();
|
|
|
|
if ($type == DifferentialChangeType::TYPE_MULTICOPY) {
|
2013-01-24 22:18:44 +01:00
|
|
|
$meta[] = pht('Deleted after being copied to multiple locations:');
|
2011-01-24 22:18:41 +01:00
|
|
|
} else {
|
2013-01-24 22:18:44 +01:00
|
|
|
$meta[] = pht('Copied to multiple locations:');
|
2011-01-24 22:18:41 +01:00
|
|
|
}
|
|
|
|
foreach ($away as $path) {
|
2013-02-13 23:50:15 +01:00
|
|
|
$meta[] = $path;
|
2011-01-24 22:18:41 +01:00
|
|
|
}
|
2013-02-13 23:50:15 +01:00
|
|
|
$meta = phutil_implode_html(phutil_tag('br'), $meta);
|
2011-01-24 22:18:41 +01:00
|
|
|
} else {
|
|
|
|
if ($type == DifferentialChangeType::TYPE_MOVE_AWAY) {
|
2013-04-16 20:02:04 +02:00
|
|
|
$display_file = $this->renderRename(
|
|
|
|
$display_file,
|
|
|
|
reset($away),
|
|
|
|
"\xE2\x86\x92");
|
2011-01-24 22:18:41 +01:00
|
|
|
} else {
|
2013-02-13 23:50:15 +01:00
|
|
|
$meta = pht('Copied to %s', reset($away));
|
2011-01-24 22:18:41 +01:00
|
|
|
}
|
|
|
|
}
|
2012-01-16 07:43:54 +01:00
|
|
|
} else if ($type == DifferentialChangeType::TYPE_MOVE_HERE) {
|
2013-04-16 20:02:04 +02:00
|
|
|
$old_file = $changeset->getOldFile();
|
|
|
|
$display_file = $this->renderRename(
|
|
|
|
$display_file,
|
|
|
|
$old_file,
|
|
|
|
"\xE2\x86\x90");
|
2012-01-16 07:43:54 +01:00
|
|
|
} else if ($type == DifferentialChangeType::TYPE_COPY_HERE) {
|
2013-02-13 23:50:15 +01:00
|
|
|
$meta = pht('Copied from %s', $changeset->getOldFile());
|
2011-01-24 22:18:41 +01:00
|
|
|
}
|
|
|
|
|
2013-04-16 20:02:04 +02:00
|
|
|
$link = $this->renderChangesetLink($changeset, $ref, $display_file);
|
|
|
|
|
2011-01-24 22:18:41 +01:00
|
|
|
$line_count = $changeset->getAffectedLineCount();
|
|
|
|
if ($line_count == 0) {
|
|
|
|
$lines = null;
|
|
|
|
} else {
|
2012-06-14 22:43:09 +02:00
|
|
|
$lines = ' '.pht('(%d line(s))', $line_count);
|
2011-01-24 22:18:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
$char = DifferentialChangeType::getSummaryCharacterForChangeType($type);
|
|
|
|
$chartitle = DifferentialChangeType::getFullNameForChangeType($type);
|
|
|
|
$desc = DifferentialChangeType::getShortNameForFileType($ftype);
|
|
|
|
if ($desc) {
|
|
|
|
$desc = '('.$desc.')';
|
|
|
|
}
|
|
|
|
$pchar =
|
|
|
|
($changeset->getOldProperties() === $changeset->getNewProperties())
|
|
|
|
? null
|
2013-11-11 18:23:23 +01:00
|
|
|
: phutil_tag('span', array('title' => pht('Properties Changed')), 'M')
|
|
|
|
;
|
2011-01-24 22:18:41 +01:00
|
|
|
|
2012-03-13 01:06:55 +01:00
|
|
|
$fname = $changeset->getFilename();
|
|
|
|
$cov = $this->renderCoverage($coverage, $fname);
|
|
|
|
if ($cov === null) {
|
2013-02-13 23:50:15 +01:00
|
|
|
$mcov = $cov = phutil_tag('em', array(), '-');
|
2012-03-13 01:06:55 +01:00
|
|
|
} else {
|
2013-01-18 09:32:58 +01:00
|
|
|
$mcov = phutil_tag(
|
2012-03-13 01:06:55 +01:00
|
|
|
'div',
|
|
|
|
array(
|
|
|
|
'id' => 'differential-mcoverage-'.md5($fname),
|
|
|
|
'class' => 'differential-mcoverage-loading',
|
|
|
|
),
|
2012-03-15 18:45:35 +01:00
|
|
|
(isset($this->visibleChangesets[$id]) ? 'Loading...' : '?'));
|
2012-03-13 01:06:55 +01:00
|
|
|
}
|
|
|
|
|
2013-11-11 18:23:23 +01:00
|
|
|
$rows[] = phutil_tag('tr', array(), array(
|
|
|
|
phutil_tag(
|
|
|
|
'td',
|
|
|
|
array('class' => 'differential-toc-char', 'title' => $chartitle),
|
|
|
|
$char),
|
|
|
|
phutil_tag('td', array('class' => 'differential-toc-prop'), $pchar),
|
|
|
|
phutil_tag('td', array('class' => 'differential-toc-ftype'), $desc),
|
|
|
|
phutil_tag(
|
|
|
|
'td',
|
|
|
|
array('class' => 'differential-toc-file'),
|
|
|
|
array($link, $lines)),
|
|
|
|
phutil_tag('td', array('class' => 'differential-toc-cov'), $cov),
|
|
|
|
phutil_tag('td', array('class' => 'differential-toc-mcov'), $mcov),
|
|
|
|
));
|
2011-01-24 22:18:41 +01:00
|
|
|
if ($meta) {
|
2013-11-11 18:23:23 +01:00
|
|
|
$rows[] = phutil_tag('tr', array(), array(
|
|
|
|
phutil_tag('td', array('colspan' => 3)),
|
|
|
|
phutil_tag('td', array('class' => 'differential-toc-meta'), $meta),
|
|
|
|
));
|
2011-01-24 22:18:41 +01:00
|
|
|
}
|
2012-03-01 08:16:45 +01:00
|
|
|
if ($this->diff && $this->repository) {
|
|
|
|
$paths[] =
|
2012-04-10 08:42:12 +02:00
|
|
|
$changeset->getAbsoluteRepositoryPath($this->repository, $this->diff);
|
2012-03-01 08:16:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$editor_link = null;
|
|
|
|
if ($paths && $this->user) {
|
|
|
|
$editor_link = $this->user->loadEditorLink(
|
2012-12-04 00:51:18 +01:00
|
|
|
$paths,
|
2012-03-01 08:16:45 +01:00
|
|
|
1, // line number
|
2012-04-05 02:53:16 +02:00
|
|
|
$this->repository->getCallsign());
|
2012-03-01 08:16:45 +01:00
|
|
|
if ($editor_link) {
|
2012-12-13 06:00:35 +01:00
|
|
|
$editor_link =
|
2013-01-18 03:57:09 +01:00
|
|
|
phutil_tag(
|
2012-12-13 06:00:35 +01:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $editor_link,
|
|
|
|
'class' => 'button differential-toc-edit-all',
|
|
|
|
),
|
2013-01-24 22:18:44 +01:00
|
|
|
pht('Open All in Editor'));
|
2012-03-01 08:16:45 +01:00
|
|
|
}
|
2011-01-24 22:18:41 +01:00
|
|
|
}
|
|
|
|
|
2013-01-25 21:57:17 +01:00
|
|
|
$reveal_link = javelin_tag(
|
2012-12-13 06:00:35 +01:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'sigil' => 'differential-reveal-all',
|
|
|
|
'mustcapture' => true,
|
|
|
|
'class' => 'button differential-toc-reveal-all',
|
|
|
|
),
|
2013-01-25 21:57:17 +01:00
|
|
|
pht('Show All Context'));
|
2012-12-13 06:00:35 +01:00
|
|
|
|
2013-11-11 18:23:23 +01:00
|
|
|
$buttons = phutil_tag('tr', array(),
|
|
|
|
phutil_tag('td', array('colspan' => 7),
|
|
|
|
array($editor_link, $reveal_link)));
|
2012-05-30 03:20:11 +02:00
|
|
|
|
2013-09-29 00:55:38 +02:00
|
|
|
$content = hsprintf(
|
|
|
|
'%s'.
|
2012-08-22 00:01:20 +02:00
|
|
|
'<div class="differential-toc differential-panel">'.
|
2011-01-24 22:18:41 +01:00
|
|
|
'<table>'.
|
2012-03-13 01:06:55 +01:00
|
|
|
'<tr>'.
|
|
|
|
'<th></th>'.
|
|
|
|
'<th></th>'.
|
|
|
|
'<th></th>'.
|
|
|
|
'<th>Path</th>'.
|
2013-02-13 23:50:15 +01:00
|
|
|
'<th class="differential-toc-cov">%s</th>'.
|
|
|
|
'<th class="differential-toc-mcov">%s</th>'.
|
2012-03-13 01:06:55 +01:00
|
|
|
'</tr>'.
|
2013-02-13 23:50:15 +01:00
|
|
|
'%s%s'.
|
2011-01-24 22:18:41 +01:00
|
|
|
'</table>'.
|
2013-02-13 23:50:15 +01:00
|
|
|
'</div>',
|
|
|
|
id(new PhabricatorAnchorView())
|
|
|
|
->setAnchorName('toc')
|
|
|
|
->setNavigationMarker(true)
|
|
|
|
->render(),
|
|
|
|
pht('Coverage (All)'),
|
|
|
|
pht('Coverage (Touched)'),
|
|
|
|
phutil_implode_html("\n", $rows),
|
|
|
|
$buttons);
|
2013-09-29 00:55:38 +02:00
|
|
|
|
|
|
|
return id(new PHUIObjectBoxView())
|
|
|
|
->setHeaderText(pht('Table of Contents'))
|
Provide more structure to PHUIObjectBoxView
Summary:
Three changes here.
- Add `setActionList()`, and use that to set the action list.
- Add `setPropertyList()`, and use that to set the property list.
These will let us add some apropriate CSS so we can fix the border issue, and get rid of a bunch of goofy `.x + .y` selectors.
- Replace `addContent()` with `appendChild()`.
This is just a consistency thing; `AphrontView` already provides `appendChild()`, and `addContent()` did the same thing.
Test Plan:
- Viewed "All Config".
- Viewed a countdown.
- Viewed a revision (add comment, change list, table of contents, comment, local commits, open revisions affecting these files, update history).
- Viewed Diffusion (browse, change, history, repository, lint).
- Viewed Drydock (resource, lease).
- Viewed Files.
- Viewed Herald.
- Viewed Legalpad.
- Viewed macro (edit, edit audio, view).
- Viewed Maniphest.
- Viewed Applications.
- Viewed Paste.
- Viewed People.
- Viewed Phulux.
- Viewed Pholio.
- Viewed Phame (blog, post).
- Viewed Phortune (account, product).
- Viewed Ponder (questions, answers, comments).
- Viewed Releeph.
- Viewed Projects.
- Viewed Slowvote.
NOTE: Images in Files aren't on a black background anymore -- I assume that's on purpose?
NOTE: Some jankiness in Phortune, I'll clean that up when I get back to it. Not related to this diff.
Reviewers: chad
Reviewed By: chad
CC: aran
Differential Revision: https://secure.phabricator.com/D7174
2013-09-30 18:36:04 +02:00
|
|
|
->appendChild($content);
|
2011-01-24 22:18:41 +01:00
|
|
|
}
|
2012-01-24 09:37:50 +01:00
|
|
|
|
2013-04-16 20:02:04 +02:00
|
|
|
private function renderRename($display_file, $other_file, $arrow) {
|
|
|
|
$old = explode('/', $display_file);
|
|
|
|
$new = explode('/', $other_file);
|
|
|
|
|
|
|
|
$start = count($old);
|
|
|
|
foreach ($old as $index => $part) {
|
|
|
|
if (!isset($new[$index]) || $part != $new[$index]) {
|
|
|
|
$start = $index;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$end = count($old);
|
|
|
|
foreach (array_reverse($old) as $from_end => $part) {
|
|
|
|
$index = count($new) - $from_end - 1;
|
|
|
|
if (!isset($new[$index]) || $part != $new[$index]) {
|
|
|
|
$end = $from_end;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$rename =
|
|
|
|
'{'.
|
|
|
|
implode('/', array_slice($old, $start, count($old) - $end - $start)).
|
|
|
|
' '.$arrow.' '.
|
|
|
|
implode('/', array_slice($new, $start, count($new) - $end - $start)).
|
|
|
|
'}';
|
|
|
|
|
|
|
|
array_splice($new, $start, count($new) - $end - $start, $rename);
|
|
|
|
return implode('/', $new);
|
|
|
|
}
|
|
|
|
|
2012-03-13 01:06:55 +01:00
|
|
|
private function renderCoverage(array $coverage, $file) {
|
|
|
|
$info = idx($coverage, $file);
|
|
|
|
if (!$info) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$not_covered = substr_count($info, 'U');
|
|
|
|
$covered = substr_count($info, 'C');
|
|
|
|
|
|
|
|
if (!$not_covered && !$covered) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sprintf('%d%%', 100 * ($covered / ($covered + $not_covered)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-16 20:02:04 +02:00
|
|
|
private function renderChangesetLink(
|
|
|
|
DifferentialChangeset $changeset,
|
|
|
|
$ref,
|
|
|
|
$display_file) {
|
2012-01-24 09:37:50 +01:00
|
|
|
|
2013-01-25 21:57:17 +01:00
|
|
|
return javelin_tag(
|
2012-01-24 09:37:50 +01:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '#'.$changeset->getAnchorName(),
|
2012-05-01 21:09:50 +02:00
|
|
|
'meta' => array(
|
|
|
|
'id' => 'diff-'.$changeset->getAnchorName(),
|
|
|
|
'ref' => $ref,
|
|
|
|
),
|
|
|
|
'sigil' => 'differential-load',
|
2012-01-24 09:37:50 +01:00
|
|
|
),
|
2013-01-25 21:57:17 +01:00
|
|
|
$display_file);
|
2012-01-24 09:37:50 +01:00
|
|
|
}
|
2012-03-30 19:13:08 +02:00
|
|
|
|
2011-01-24 22:18:41 +01:00
|
|
|
}
|