2011-01-25 00:52:35 +01:00
|
|
|
<?php
|
|
|
|
|
2012-03-10 00:46:25 +01:00
|
|
|
final class DifferentialChangesetViewController extends DifferentialController {
|
2011-01-25 00:52:35 +01:00
|
|
|
|
2011-10-24 21:27:16 +02:00
|
|
|
public function shouldRequireLogin() {
|
|
|
|
return !$this->allowsAnonymousAccess();
|
|
|
|
}
|
|
|
|
|
2011-01-25 00:52:35 +01:00
|
|
|
public function processRequest() {
|
2011-02-01 05:38:13 +01:00
|
|
|
$request = $this->getRequest();
|
|
|
|
|
2011-02-02 01:42:36 +01:00
|
|
|
$author_phid = $request->getUser()->getPHID();
|
2011-02-01 05:38:13 +01:00
|
|
|
|
Move "Rendering References" to the DifferentialChangesetParser level
Summary:
Separates changeset IDs from rendering. Now each changeset has a "rendering
reference" which is basically a description of what the ajax endpoint should
render. For Differential, it's in the form "id/vs". For Diffusion,
"branch/path;commit".
I believe this fixes pretty much all of the bugs related to "show more" breaking
in various obscure ways, although I never got a great repro for T153.
Test Plan:
Clicked "show more" in diffusion change and commit views and differential diff,
diff-of-diff, standalone-diff, standalone-diff-of-diff views. Verified refs and
'whitespace' were always sent correctly.
Made inline comments on diffs and diffs-of-diffs. Used "Reply".
Reviewed By: tuomaspelkonen
Reviewers: tuomaspelkonen, jungejason, aran
CC: aran, tuomaspelkonen, epriestley
Differential Revision: 274
2011-05-12 06:46:29 +02:00
|
|
|
$rendering_reference = $request->getStr('ref');
|
|
|
|
$parts = explode('/', $rendering_reference);
|
|
|
|
if (count($parts) == 2) {
|
|
|
|
list($id, $vs) = $parts;
|
|
|
|
} else {
|
|
|
|
$id = $parts[0];
|
|
|
|
$vs = 0;
|
|
|
|
}
|
2011-02-04 00:41:58 +01:00
|
|
|
|
Move "Rendering References" to the DifferentialChangesetParser level
Summary:
Separates changeset IDs from rendering. Now each changeset has a "rendering
reference" which is basically a description of what the ajax endpoint should
render. For Differential, it's in the form "id/vs". For Diffusion,
"branch/path;commit".
I believe this fixes pretty much all of the bugs related to "show more" breaking
in various obscure ways, although I never got a great repro for T153.
Test Plan:
Clicked "show more" in diffusion change and commit views and differential diff,
diff-of-diff, standalone-diff, standalone-diff-of-diff views. Verified refs and
'whitespace' were always sent correctly.
Made inline comments on diffs and diffs-of-diffs. Used "Reply".
Reviewed By: tuomaspelkonen
Reviewers: tuomaspelkonen, jungejason, aran
CC: aran, tuomaspelkonen, epriestley
Differential Revision: 274
2011-05-12 06:46:29 +02:00
|
|
|
$id = (int)$id;
|
|
|
|
$vs = (int)$vs;
|
2011-02-04 00:41:58 +01:00
|
|
|
|
2011-02-01 05:38:13 +01:00
|
|
|
$changeset = id(new DifferentialChangeset())->load($id);
|
2011-01-25 00:52:35 +01:00
|
|
|
if (!$changeset) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
|
2011-05-06 21:58:53 +02:00
|
|
|
$view = $request->getStr('view');
|
|
|
|
if ($view) {
|
|
|
|
$changeset->attachHunks($changeset->loadHunks());
|
2012-02-06 20:58:21 +01:00
|
|
|
$phid = idx($changeset->getMetadata(), "$view:binary-phid");
|
|
|
|
if ($phid) {
|
|
|
|
return id(new AphrontRedirectResponse())->setURI("/file/info/$phid/");
|
|
|
|
}
|
|
|
|
switch ($view) {
|
|
|
|
case 'new':
|
2012-02-15 02:00:20 +01:00
|
|
|
return $this->buildRawFileResponse($changeset, $is_new = true);
|
2012-02-06 20:58:21 +01:00
|
|
|
case 'old':
|
2012-08-08 03:53:22 +02:00
|
|
|
if ($vs && ($vs != -1)) {
|
|
|
|
$vs_changeset = id(new DifferentialChangeset())->load($vs);
|
|
|
|
if ($vs_changeset) {
|
|
|
|
$vs_changeset->attachHunks($vs_changeset->loadHunks());
|
|
|
|
return $this->buildRawFileResponse($vs_changeset, $is_new = true);
|
|
|
|
}
|
|
|
|
}
|
2012-02-15 02:00:20 +01:00
|
|
|
return $this->buildRawFileResponse($changeset, $is_new = false);
|
2012-02-06 20:58:21 +01:00
|
|
|
default:
|
|
|
|
return new Aphront400Response();
|
2011-05-06 21:58:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-04 00:41:58 +01:00
|
|
|
if ($vs && ($vs != -1)) {
|
|
|
|
$vs_changeset = id(new DifferentialChangeset())->load($vs);
|
|
|
|
if (!$vs_changeset) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$vs) {
|
|
|
|
$right = $changeset;
|
|
|
|
$left = null;
|
|
|
|
|
|
|
|
$right_source = $right->getID();
|
|
|
|
$right_new = true;
|
|
|
|
$left_source = $right->getID();
|
|
|
|
$left_new = false;
|
2011-05-05 16:08:10 +02:00
|
|
|
|
|
|
|
$render_cache_key = $right->getID();
|
2011-02-04 00:41:58 +01:00
|
|
|
} else if ($vs == -1) {
|
|
|
|
$right = null;
|
|
|
|
$left = $changeset;
|
|
|
|
|
|
|
|
$right_source = $left->getID();
|
|
|
|
$right_new = false;
|
|
|
|
$left_source = $left->getID();
|
|
|
|
$left_new = true;
|
2011-05-05 16:08:10 +02:00
|
|
|
|
|
|
|
$render_cache_key = null;
|
2011-02-04 00:41:58 +01:00
|
|
|
} else {
|
|
|
|
$right = $changeset;
|
|
|
|
$left = $vs_changeset;
|
|
|
|
|
|
|
|
$right_source = $right->getID();
|
|
|
|
$right_new = true;
|
|
|
|
$left_source = $left->getID();
|
|
|
|
$left_new = true;
|
2011-05-05 16:08:10 +02:00
|
|
|
|
|
|
|
$render_cache_key = null;
|
2011-02-04 00:41:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($left) {
|
|
|
|
$left->attachHunks($left->loadHunks());
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($right) {
|
|
|
|
$right->attachHunks($right->loadHunks());
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($left) {
|
|
|
|
|
|
|
|
$left_data = $left->makeNewFile();
|
|
|
|
if ($right) {
|
|
|
|
$right_data = $right->makeNewFile();
|
|
|
|
} else {
|
|
|
|
$right_data = $left->makeOldFile();
|
|
|
|
}
|
|
|
|
|
2011-07-17 20:06:02 +02:00
|
|
|
$engine = new PhabricatorDifferenceEngine();
|
|
|
|
$synthetic = $engine->generateChangesetFromFileContent(
|
|
|
|
$left_data,
|
|
|
|
$right_data);
|
2011-02-04 00:41:58 +01:00
|
|
|
|
2012-06-15 09:53:26 +02:00
|
|
|
$choice = clone nonempty($left, $right);
|
2011-07-17 20:06:02 +02:00
|
|
|
$choice->attachHunks($synthetic->getHunks());
|
2011-02-04 00:41:58 +01:00
|
|
|
|
|
|
|
$changeset = $choice;
|
|
|
|
}
|
2011-01-25 00:52:35 +01:00
|
|
|
|
Show coverage information in Differential
Summary:
Render coverage information in the right gutter, if available.
We could render some kind of summary report deal too but this seems like a good
start.
Test Plan:
- Looked at diffs with coverage.
- Looked at diffs without coverage.
- Used inline comments, diff-of-diff, "show more", "show entire file", "show
generated file", "undo". Nothing seemed disrupted by the addition of a 5th
column.
Reviewers: btrahan, tuomaspelkonen, jungejason
Reviewed By: btrahan
CC: zeeg, aran, epriestley
Maniphest Tasks: T140
Differential Revision: https://secure.phabricator.com/D1527
2012-01-31 21:07:47 +01:00
|
|
|
$coverage = null;
|
2012-03-02 02:57:19 +01:00
|
|
|
if ($right && $right->getDiffID()) {
|
Show coverage information in Differential
Summary:
Render coverage information in the right gutter, if available.
We could render some kind of summary report deal too but this seems like a good
start.
Test Plan:
- Looked at diffs with coverage.
- Looked at diffs without coverage.
- Used inline comments, diff-of-diff, "show more", "show entire file", "show
generated file", "undo". Nothing seemed disrupted by the addition of a 5th
column.
Reviewers: btrahan, tuomaspelkonen, jungejason
Reviewed By: btrahan
CC: zeeg, aran, epriestley
Maniphest Tasks: T140
Differential Revision: https://secure.phabricator.com/D1527
2012-01-31 21:07:47 +01:00
|
|
|
$unit = id(new DifferentialDiffProperty())->loadOneWhere(
|
|
|
|
'diffID = %d AND name = %s',
|
|
|
|
$right->getDiffID(),
|
|
|
|
'arc:unit');
|
|
|
|
|
|
|
|
if ($unit) {
|
|
|
|
$coverage = array();
|
|
|
|
foreach ($unit->getData() as $result) {
|
|
|
|
$result_coverage = idx($result, 'coverage');
|
|
|
|
if (!$result_coverage) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$file_coverage = idx($result_coverage, $right->getFileName());
|
|
|
|
if (!$file_coverage) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$coverage[] = $file_coverage;
|
|
|
|
}
|
|
|
|
|
|
|
|
$coverage = ArcanistUnitTestResult::mergeCoverage($coverage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-17 20:06:02 +02:00
|
|
|
$spec = $request->getStr('range');
|
|
|
|
list($range_s, $range_e, $mask) =
|
|
|
|
DifferentialChangesetParser::parseRangeSpecification($spec);
|
2011-02-01 05:38:13 +01:00
|
|
|
|
2011-01-25 00:52:35 +01:00
|
|
|
$parser = new DifferentialChangesetParser();
|
Show coverage information in Differential
Summary:
Render coverage information in the right gutter, if available.
We could render some kind of summary report deal too but this seems like a good
start.
Test Plan:
- Looked at diffs with coverage.
- Looked at diffs without coverage.
- Used inline comments, diff-of-diff, "show more", "show entire file", "show
generated file", "undo". Nothing seemed disrupted by the addition of a 5th
column.
Reviewers: btrahan, tuomaspelkonen, jungejason
Reviewed By: btrahan
CC: zeeg, aran, epriestley
Maniphest Tasks: T140
Differential Revision: https://secure.phabricator.com/D1527
2012-01-31 21:07:47 +01:00
|
|
|
$parser->setCoverage($coverage);
|
2011-01-25 00:52:35 +01:00
|
|
|
$parser->setChangeset($changeset);
|
Move "Rendering References" to the DifferentialChangesetParser level
Summary:
Separates changeset IDs from rendering. Now each changeset has a "rendering
reference" which is basically a description of what the ajax endpoint should
render. For Differential, it's in the form "id/vs". For Diffusion,
"branch/path;commit".
I believe this fixes pretty much all of the bugs related to "show more" breaking
in various obscure ways, although I never got a great repro for T153.
Test Plan:
Clicked "show more" in diffusion change and commit views and differential diff,
diff-of-diff, standalone-diff, standalone-diff-of-diff views. Verified refs and
'whitespace' were always sent correctly.
Made inline comments on diffs and diffs-of-diffs. Used "Reply".
Reviewed By: tuomaspelkonen
Reviewers: tuomaspelkonen, jungejason, aran
CC: aran, tuomaspelkonen, epriestley
Differential Revision: 274
2011-05-12 06:46:29 +02:00
|
|
|
$parser->setRenderingReference($rendering_reference);
|
2011-05-05 16:08:10 +02:00
|
|
|
$parser->setRenderCacheKey($render_cache_key);
|
2011-02-04 00:41:58 +01:00
|
|
|
$parser->setRightSideCommentMapping($right_source, $right_new);
|
|
|
|
$parser->setLeftSideCommentMapping($left_source, $left_new);
|
2011-04-18 22:38:54 +02:00
|
|
|
$parser->setWhitespaceMode($request->getStr('whitespace'));
|
2011-02-02 22:48:52 +01:00
|
|
|
|
2013-01-14 23:20:35 +01:00
|
|
|
if ($request->getStr('renderer') == '1up') {
|
|
|
|
$parser->setRenderer(new DifferentialChangesetOneUpRenderer());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-15 09:53:26 +02:00
|
|
|
if ($left && $right) {
|
|
|
|
$parser->setOriginals($left, $right);
|
|
|
|
}
|
|
|
|
|
2011-05-09 06:22:25 +02:00
|
|
|
// Load both left-side and right-side inline comments.
|
|
|
|
$inlines = $this->loadInlineComments(
|
|
|
|
array($left_source, $right_source),
|
|
|
|
$author_phid);
|
|
|
|
|
2012-01-04 18:10:37 +01:00
|
|
|
if ($left_new) {
|
|
|
|
$inlines = array_merge(
|
|
|
|
$inlines,
|
|
|
|
$this->buildLintInlineComments($left));
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($right_new) {
|
|
|
|
$inlines = array_merge(
|
|
|
|
$inlines,
|
|
|
|
$this->buildLintInlineComments($right));
|
|
|
|
}
|
|
|
|
|
2011-02-02 01:42:36 +01:00
|
|
|
$phids = array();
|
|
|
|
foreach ($inlines as $inline) {
|
|
|
|
$parser->parseInlineComment($inline);
|
2012-01-04 18:10:37 +01:00
|
|
|
if ($inline->getAuthorPHID()) {
|
|
|
|
$phids[$inline->getAuthorPHID()] = true;
|
|
|
|
}
|
2011-02-02 01:42:36 +01:00
|
|
|
}
|
|
|
|
$phids = array_keys($phids);
|
2011-02-02 22:48:52 +01:00
|
|
|
|
2012-09-05 04:02:56 +02:00
|
|
|
$handles = $this->loadViewerHandles($phids);
|
2011-02-02 01:42:36 +01:00
|
|
|
$parser->setHandles($handles);
|
2011-02-02 22:48:52 +01:00
|
|
|
|
2012-10-24 02:33:58 +02:00
|
|
|
$engine = new PhabricatorMarkupEngine();
|
|
|
|
$engine->setViewer($request->getUser());
|
|
|
|
|
|
|
|
foreach ($inlines as $inline) {
|
|
|
|
$engine->addObject(
|
|
|
|
$inline,
|
|
|
|
PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY);
|
|
|
|
}
|
|
|
|
|
|
|
|
$engine->process();
|
2011-02-02 01:42:36 +01:00
|
|
|
$parser->setMarkupEngine($engine);
|
2011-01-25 00:52:35 +01:00
|
|
|
|
2011-02-02 19:10:25 +01:00
|
|
|
if ($request->isAjax()) {
|
|
|
|
// TODO: This is sort of lazy, the effect is just to not render "Edit"
|
2012-04-18 06:18:30 +02:00
|
|
|
// and "Reply" links on the "standalone view".
|
2011-02-02 19:10:25 +01:00
|
|
|
$parser->setUser($request->getUser());
|
|
|
|
}
|
|
|
|
|
|
|
|
$output = $parser->render($range_s, $range_e, $mask);
|
2011-01-25 00:52:35 +01:00
|
|
|
|
2012-03-13 01:06:55 +01:00
|
|
|
$mcov = $parser->renderModifiedCoverage();
|
|
|
|
|
2011-01-25 20:57:47 +01:00
|
|
|
if ($request->isAjax()) {
|
2012-03-13 05:39:05 +01:00
|
|
|
$coverage = array(
|
|
|
|
'differential-mcoverage-'.md5($changeset->getFilename()) => $mcov,
|
2012-03-13 01:06:55 +01:00
|
|
|
);
|
2012-03-13 05:39:05 +01:00
|
|
|
|
|
|
|
return id(new PhabricatorChangesetResponse())
|
|
|
|
->setRenderedChangeset($output)
|
|
|
|
->setCoverage($coverage);
|
2011-01-25 20:57:47 +01:00
|
|
|
}
|
|
|
|
|
2011-02-01 05:38:13 +01:00
|
|
|
Javelin::initBehavior('differential-show-more', array(
|
|
|
|
'uri' => '/differential/changeset/',
|
2011-05-11 02:36:06 +02:00
|
|
|
'whitespace' => $request->getStr('whitespace'),
|
2011-02-01 05:38:13 +01:00
|
|
|
));
|
|
|
|
|
2011-05-11 21:25:29 +02:00
|
|
|
Javelin::initBehavior('differential-comment-jump', array());
|
|
|
|
|
2011-01-25 20:57:47 +01:00
|
|
|
$detail = new DifferentialChangesetDetailView();
|
|
|
|
$detail->setChangeset($changeset);
|
|
|
|
$detail->appendChild($output);
|
2012-04-07 19:01:14 +02:00
|
|
|
$detail->setVsChangesetID($left_source);
|
2011-05-06 21:58:53 +02:00
|
|
|
|
2012-12-06 20:33:04 +01:00
|
|
|
$panel = new DifferentialPrimaryPaneView();
|
2012-11-01 21:30:37 +01:00
|
|
|
$panel->appendChild(phutil_render_tag('div',
|
|
|
|
array(
|
|
|
|
'class' => 'differential-review-stage',
|
|
|
|
'id' => 'differential-review-stage',
|
|
|
|
), $detail->render())
|
|
|
|
);
|
2011-01-25 00:52:35 +01:00
|
|
|
|
|
|
|
return $this->buildStandardPageResponse(
|
|
|
|
array(
|
2012-11-01 21:30:37 +01:00
|
|
|
$panel
|
2011-01-25 00:52:35 +01:00
|
|
|
),
|
|
|
|
array(
|
|
|
|
'title' => 'Changeset View',
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2011-05-09 06:22:25 +02:00
|
|
|
private function loadInlineComments(array $changeset_ids, $author_phid) {
|
|
|
|
$changeset_ids = array_unique(array_filter($changeset_ids));
|
|
|
|
if (!$changeset_ids) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-02-02 01:42:36 +01:00
|
|
|
return id(new DifferentialInlineComment())->loadAllWhere(
|
2011-05-09 06:22:25 +02:00
|
|
|
'changesetID IN (%Ld) AND (commentID IS NOT NULL OR authorPHID = %s)',
|
|
|
|
$changeset_ids,
|
2011-02-02 01:42:36 +01:00
|
|
|
$author_phid);
|
|
|
|
}
|
|
|
|
|
2012-02-15 02:00:20 +01:00
|
|
|
private function buildRawFileResponse(
|
|
|
|
DifferentialChangeset $changeset,
|
|
|
|
$is_new) {
|
|
|
|
|
|
|
|
if ($is_new) {
|
|
|
|
$key = 'raw:new:phid';
|
|
|
|
} else {
|
|
|
|
$key = 'raw:old:phid';
|
|
|
|
}
|
|
|
|
|
|
|
|
$metadata = $changeset->getMetadata();
|
|
|
|
|
|
|
|
$file = null;
|
|
|
|
$phid = idx($metadata, $key);
|
|
|
|
if ($phid) {
|
|
|
|
$file = id(new PhabricatorFile())->loadOneWhere(
|
|
|
|
'phid = %s',
|
|
|
|
$phid);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$file) {
|
|
|
|
// This is just building a cache of the changeset content in the file
|
|
|
|
// tool, and is safe to run on a read pathway.
|
|
|
|
$unguard = AphrontWriteGuard::beginScopedUnguardedWrites();
|
|
|
|
|
|
|
|
if ($is_new) {
|
|
|
|
$data = $changeset->makeNewFile();
|
|
|
|
} else {
|
|
|
|
$data = $changeset->makeOldFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
$file = PhabricatorFile::newFromFileData(
|
|
|
|
$data,
|
|
|
|
array(
|
|
|
|
'name' => $changeset->getFilename(),
|
|
|
|
'mime-type' => 'text/plain',
|
|
|
|
));
|
|
|
|
|
|
|
|
$metadata[$key] = $file->getPHID();
|
|
|
|
$changeset->setMetadata($metadata);
|
|
|
|
$changeset->save();
|
|
|
|
|
|
|
|
unset($unguard);
|
|
|
|
}
|
|
|
|
|
|
|
|
return id(new AphrontRedirectResponse())
|
|
|
|
->setURI($file->getBestURI());
|
2011-05-06 21:58:53 +02:00
|
|
|
}
|
2011-02-02 01:42:36 +01:00
|
|
|
|
2012-01-04 18:10:37 +01:00
|
|
|
private function buildLintInlineComments($changeset) {
|
|
|
|
$lint = id(new DifferentialDiffProperty())->loadOneWhere(
|
|
|
|
'diffID = %d AND name = %s',
|
|
|
|
$changeset->getDiffID(),
|
|
|
|
'arc:lint');
|
|
|
|
if (!$lint) {
|
2012-01-05 18:11:49 +01:00
|
|
|
return array();
|
2012-01-04 18:10:37 +01:00
|
|
|
}
|
|
|
|
$lint = $lint->getData();
|
|
|
|
|
|
|
|
$inlines = array();
|
|
|
|
foreach ($lint as $msg) {
|
2012-01-17 08:05:44 +01:00
|
|
|
if ($msg['path'] != $changeset->getFilename()) {
|
2012-01-04 18:10:37 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$inline = new DifferentialInlineComment();
|
|
|
|
$inline->setChangesetID($changeset->getID());
|
|
|
|
$inline->setIsNewFile(true);
|
|
|
|
$inline->setSyntheticAuthor('Lint: '.$msg['name']);
|
|
|
|
$inline->setLineNumber($msg['line']);
|
|
|
|
$inline->setLineLength(0);
|
|
|
|
|
|
|
|
$inline->setContent('%%%'.$msg['description'].'%%%');
|
|
|
|
|
|
|
|
$inlines[] = $inline;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $inlines;
|
|
|
|
}
|
|
|
|
|
2011-01-25 00:52:35 +01:00
|
|
|
}
|