2011-01-27 23:55:52 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright 2011 Facebook, Inc.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class DifferentialRevisionViewController extends DifferentialController {
|
|
|
|
|
|
|
|
private $revisionID;
|
|
|
|
|
|
|
|
public function willProcessRequest(array $data) {
|
|
|
|
$this->revisionID = $data['id'];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function processRequest() {
|
|
|
|
|
|
|
|
$request = $this->getRequest();
|
2011-02-06 01:57:21 +01:00
|
|
|
$user = $request->getUser();
|
2011-01-27 23:55:52 +01:00
|
|
|
|
|
|
|
$revision = id(new DifferentialRevision())->load($this->revisionID);
|
|
|
|
if (!$revision) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
|
|
|
|
$revision->loadRelationships();
|
|
|
|
|
|
|
|
$diffs = $revision->loadDiffs();
|
|
|
|
|
2011-03-25 05:32:26 +01:00
|
|
|
if (!$diffs) {
|
|
|
|
throw new Exception(
|
|
|
|
"This revision has no diffs. Something has gone quite wrong.");
|
|
|
|
}
|
|
|
|
|
2011-02-04 00:41:58 +01:00
|
|
|
$diff_vs = $request->getInt('vs');
|
2011-04-11 21:32:08 +02:00
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
$target = end($diffs);
|
2011-04-11 21:32:08 +02:00
|
|
|
$target_id = $request->getInt('id');
|
|
|
|
if ($target_id) {
|
|
|
|
if (isset($diffs[$target_id])) {
|
|
|
|
$target = $diffs[$target_id];
|
|
|
|
}
|
|
|
|
}
|
2011-01-27 23:55:52 +01:00
|
|
|
|
2011-02-04 00:41:58 +01:00
|
|
|
$diffs = mpull($diffs, null, 'getID');
|
|
|
|
if (empty($diffs[$diff_vs])) {
|
|
|
|
$diff_vs = null;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
list($changesets, $vs_map, $rendering_references) =
|
2011-02-04 00:41:58 +01:00
|
|
|
$this->loadChangesetsAndVsMap($diffs, $diff_vs, $target);
|
2011-01-27 23:55:52 +01:00
|
|
|
|
2011-01-30 19:37:36 +01:00
|
|
|
$comments = $revision->loadComments();
|
|
|
|
$comments = array_merge(
|
|
|
|
$this->getImplicitComments($revision),
|
|
|
|
$comments);
|
|
|
|
|
2011-03-08 07:01:33 +01:00
|
|
|
$all_changesets = $changesets;
|
|
|
|
$inlines = $this->loadInlineComments($comments, $all_changesets);
|
2011-02-03 04:38:43 +01:00
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
$object_phids = array_merge(
|
|
|
|
$revision->getReviewers(),
|
|
|
|
$revision->getCCPHIDs(),
|
2011-04-08 06:59:42 +02:00
|
|
|
$revision->loadCommitPHIDs(),
|
2011-01-27 23:55:52 +01:00
|
|
|
array(
|
2011-01-30 19:37:36 +01:00
|
|
|
$revision->getAuthorPHID(),
|
2011-02-06 01:57:21 +01:00
|
|
|
$user->getPHID(),
|
2011-01-30 19:37:36 +01:00
|
|
|
),
|
|
|
|
mpull($comments, 'getAuthorPHID'));
|
2011-06-01 20:19:55 +02:00
|
|
|
|
|
|
|
foreach ($comments as $comment) {
|
|
|
|
$metadata = $comment->getMetadata();
|
|
|
|
$added_reviewers = idx(
|
|
|
|
$metadata,
|
|
|
|
DifferentialComment::METADATA_ADDED_REVIEWERS);
|
|
|
|
if ($added_reviewers) {
|
|
|
|
foreach ($added_reviewers as $phid) {
|
|
|
|
$object_phids[] = $phid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-17 23:32:01 +01:00
|
|
|
foreach ($revision->getAttached() as $type => $phids) {
|
|
|
|
foreach ($phids as $phid => $info) {
|
|
|
|
$object_phids[] = $phid;
|
|
|
|
}
|
|
|
|
}
|
2011-02-03 04:38:43 +01:00
|
|
|
$object_phids = array_unique($object_phids);
|
2011-01-27 23:55:52 +01:00
|
|
|
|
|
|
|
$handles = id(new PhabricatorObjectHandleData($object_phids))
|
|
|
|
->loadHandles();
|
|
|
|
|
2011-02-06 01:43:28 +01:00
|
|
|
$request_uri = $request->getRequestURI();
|
|
|
|
|
|
|
|
$limit = 100;
|
|
|
|
$large = $request->getStr('large');
|
|
|
|
if (count($changesets) > $limit && !$large) {
|
|
|
|
$count = number_format(count($changesets));
|
|
|
|
$warning = new AphrontErrorView();
|
|
|
|
$warning->setTitle('Very Large Diff');
|
|
|
|
$warning->setSeverity(AphrontErrorView::SEVERITY_WARNING);
|
|
|
|
$warning->setWidth(AphrontErrorView::WIDTH_WIDE);
|
|
|
|
$warning->appendChild(
|
2011-04-15 23:25:23 +02:00
|
|
|
"<p>This diff is very large and affects {$count} files. Use ".
|
|
|
|
"Table of Contents to open files in a standalone view. ".
|
2011-02-06 01:43:28 +01:00
|
|
|
"<strong>".
|
|
|
|
phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $request_uri->alter('large', 'true'),
|
|
|
|
),
|
2011-04-15 23:25:23 +02:00
|
|
|
'Show All Files Inline').
|
2011-02-06 01:43:28 +01:00
|
|
|
"</strong>");
|
|
|
|
$warning = $warning->render();
|
|
|
|
|
2011-04-15 23:25:23 +02:00
|
|
|
$visible_changesets = array();
|
2011-02-06 01:43:28 +01:00
|
|
|
} else {
|
|
|
|
$warning = null;
|
|
|
|
$visible_changesets = $changesets;
|
|
|
|
}
|
|
|
|
|
2011-04-11 00:50:26 +02:00
|
|
|
$diff_properties = id(new DifferentialDiffProperty())->loadAllWhere(
|
|
|
|
'diffID = %d AND name IN (%Ls)',
|
|
|
|
$target->getID(),
|
|
|
|
array(
|
|
|
|
'arc:lint',
|
|
|
|
'arc:unit',
|
|
|
|
));
|
|
|
|
$diff_properties = mpull($diff_properties, 'getData', 'getName');
|
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
$revision_detail = new DifferentialRevisionDetailView();
|
|
|
|
$revision_detail->setRevision($revision);
|
|
|
|
|
2011-04-13 00:57:29 +02:00
|
|
|
$custom_renderer_class = PhabricatorEnv::getEnvConfig(
|
|
|
|
'differential.revision-custom-detail-renderer');
|
|
|
|
if ($custom_renderer_class) {
|
|
|
|
PhutilSymbolLoader::loadClass($custom_renderer_class);
|
|
|
|
$custom_renderer =
|
|
|
|
newv($custom_renderer_class, array());
|
2011-04-30 05:15:16 +02:00
|
|
|
} else {
|
|
|
|
$custom_renderer = null;
|
2011-04-13 00:57:29 +02:00
|
|
|
}
|
|
|
|
|
2011-04-11 00:50:26 +02:00
|
|
|
$properties = $this->getRevisionProperties(
|
|
|
|
$revision,
|
|
|
|
$target,
|
|
|
|
$handles,
|
|
|
|
$diff_properties);
|
2011-04-13 00:57:29 +02:00
|
|
|
if ($custom_renderer) {
|
|
|
|
$properties = array_merge(
|
|
|
|
$properties,
|
|
|
|
$custom_renderer->generateProperties($revision, $target));
|
|
|
|
}
|
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
$revision_detail->setProperties($properties);
|
|
|
|
|
|
|
|
$actions = $this->getRevisionActions($revision);
|
2011-04-13 00:57:29 +02:00
|
|
|
if ($custom_renderer) {
|
|
|
|
$actions = array_merge(
|
|
|
|
$actions,
|
|
|
|
$custom_renderer->generateActionLinks($revision, $target));
|
|
|
|
}
|
|
|
|
|
2011-04-28 06:16:35 +02:00
|
|
|
$whitespace = $request->getStr(
|
|
|
|
'whitespace',
|
2011-05-05 16:14:45 +02:00
|
|
|
DifferentialChangesetParser::WHITESPACE_IGNORE_ALL
|
2011-04-28 06:16:35 +02:00
|
|
|
);
|
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
$revision_detail->setActions($actions);
|
|
|
|
|
2011-04-13 03:17:43 +02:00
|
|
|
$revision_detail->setUser($user);
|
|
|
|
|
2011-01-30 19:37:36 +01:00
|
|
|
$comment_view = new DifferentialRevisionCommentListView();
|
|
|
|
$comment_view->setComments($comments);
|
|
|
|
$comment_view->setHandles($handles);
|
2011-02-03 04:38:43 +01:00
|
|
|
$comment_view->setInlineComments($inlines);
|
2011-03-08 07:01:33 +01:00
|
|
|
$comment_view->setChangesets($all_changesets);
|
2011-02-06 01:57:21 +01:00
|
|
|
$comment_view->setUser($user);
|
2011-04-15 02:22:57 +02:00
|
|
|
$comment_view->setTargetDiff($target);
|
2011-01-30 19:37:36 +01:00
|
|
|
|
2011-04-28 01:19:31 +02:00
|
|
|
$changeset_view = new DifferentialChangesetListView();
|
|
|
|
$changeset_view->setChangesets($visible_changesets);
|
|
|
|
$changeset_view->setEditable(true);
|
2011-05-06 21:58:53 +02:00
|
|
|
$changeset_view->setStandaloneViews(true);
|
2011-04-28 01:19:31 +02:00
|
|
|
$changeset_view->setRevision($revision);
|
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
|
|
|
$changeset_view->setRenderingReferences($rendering_references);
|
2011-04-28 06:16:35 +02:00
|
|
|
$changeset_view->setWhitespace($whitespace);
|
2011-04-28 01:19:31 +02:00
|
|
|
|
2011-01-30 19:37:36 +01:00
|
|
|
$diff_history = new DifferentialRevisionUpdateHistoryView();
|
|
|
|
$diff_history->setDiffs($diffs);
|
2011-02-03 22:20:43 +01:00
|
|
|
$diff_history->setSelectedVersusDiffID($diff_vs);
|
|
|
|
$diff_history->setSelectedDiffID($target->getID());
|
2011-04-28 06:16:35 +02:00
|
|
|
$diff_history->setSelectedWhitespace($whitespace);
|
2011-01-30 19:37:36 +01:00
|
|
|
|
|
|
|
$toc_view = new DifferentialDiffTableOfContentsView();
|
|
|
|
$toc_view->setChangesets($changesets);
|
2011-04-15 23:25:23 +02:00
|
|
|
$toc_view->setStandaloneViewLink(empty($visible_changesets));
|
|
|
|
$toc_view->setVsMap($vs_map);
|
|
|
|
$toc_view->setRevisionID($revision->getID());
|
2011-04-28 06:16:35 +02:00
|
|
|
$toc_view->setWhitespace($whitespace);
|
2011-01-30 19:37:36 +01:00
|
|
|
|
|
|
|
|
2011-02-06 01:57:21 +01:00
|
|
|
$draft = id(new PhabricatorDraft())->loadOneWhere(
|
|
|
|
'authorPHID = %s AND draftKey = %s',
|
|
|
|
$user->getPHID(),
|
|
|
|
'differential-comment-'.$revision->getID());
|
|
|
|
if ($draft) {
|
|
|
|
$draft = $draft->getDraft();
|
|
|
|
} else {
|
|
|
|
$draft = null;
|
|
|
|
}
|
|
|
|
|
2011-01-30 20:02:22 +01:00
|
|
|
$comment_form = new DifferentialAddCommentView();
|
|
|
|
$comment_form->setRevision($revision);
|
|
|
|
$comment_form->setActions($this->getRevisionCommentActions($revision));
|
2011-01-30 21:08:40 +01:00
|
|
|
$comment_form->setActionURI('/differential/comment/save/');
|
2011-02-06 01:57:21 +01:00
|
|
|
$comment_form->setUser($user);
|
|
|
|
$comment_form->setDraft($draft);
|
2011-01-30 20:02:22 +01:00
|
|
|
|
Differential Updates View
Summary:
This adds a new view to differential called Updates.
The high-level goal of Updates is to enabled differential to be
effectively used without email notifications. I've tried doing things
like automatically deleting differential emails where I'm in the 'to'
line since they show up on the main diffential page but then there's
always the chance an important diff flies by without me seeing it. Also,
sometimes someone comments on a diff post-commit but differential
doesn't surface those diffs.
I re-created a test db on my devserver using mysqldump to get data on
revs > 230000 so I would have some test data. We need to add a simple
viewtime table but I didn't want to do that in production. Here's the
table:
CREATE TABLE differential_viewtime (
viewerPHID varchar(64) not null,
objectPHID varchar(64) not null,
viewTime int unsigned not null,
PRIMARY KEY (viewerPHID, objectPHID)
);
Issues:
-Once we turn this on, all diffs will be 'unviewed'. What do you think
about a 'Clear All' button or something?
-Maybe we should add a pager
This feature would be insanely useful, let me know what you think.
Test Plan:
Loaded Updates in my sandbox
http://phabricator.dev1577.snc6.facebook.com/differential/filter/updates/
Clicked a diff, then went back, made sure diff disappeared from Updates
list
Reviewed By: tuomaspelkonen
Reviewers: epriestley, jungejason, tuomaspelkonen
Commenters: epriestley
CC: epriestley, elynde, tuomaspelkonen
Differential Revision: 169
2011-04-27 10:27:06 +02:00
|
|
|
$this->updateViewTime($user->getPHID(), $revision->getPHID());
|
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
return $this->buildStandardPageResponse(
|
2011-06-08 21:39:03 +02:00
|
|
|
id(new DifferentialPrimaryPaneView())
|
|
|
|
->setLineWidthFromChangesets($changesets)
|
|
|
|
->appendChild(
|
|
|
|
$revision_detail->render().
|
|
|
|
$comment_view->render().
|
|
|
|
$diff_history->render().
|
|
|
|
$warning.
|
|
|
|
$toc_view->render().
|
|
|
|
$changeset_view->render().
|
|
|
|
$comment_form->render()),
|
2011-01-27 23:55:52 +01:00
|
|
|
array(
|
2011-06-14 21:53:52 +02:00
|
|
|
'title' => 'D'.$revision->getID().' '.$revision->getTitle(),
|
2011-01-27 23:55:52 +01:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2011-01-30 19:37:36 +01:00
|
|
|
private function getImplicitComments(DifferentialRevision $revision) {
|
|
|
|
|
|
|
|
$template = new DifferentialComment();
|
|
|
|
$template->setAuthorPHID($revision->getAuthorPHID());
|
|
|
|
$template->setRevisionID($revision->getID());
|
|
|
|
$template->setDateCreated($revision->getDateCreated());
|
|
|
|
|
|
|
|
$comments = array();
|
|
|
|
|
|
|
|
if (strlen($revision->getSummary())) {
|
|
|
|
$summary_comment = clone $template;
|
|
|
|
$summary_comment->setContent($revision->getSummary());
|
|
|
|
$summary_comment->setAction(DifferentialAction::ACTION_SUMMARIZE);
|
|
|
|
$comments[] = $summary_comment;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strlen($revision->getTestPlan())) {
|
|
|
|
$testplan_comment = clone $template;
|
|
|
|
$testplan_comment->setContent($revision->getTestPlan());
|
|
|
|
$testplan_comment->setAction(DifferentialAction::ACTION_TESTPLAN);
|
|
|
|
$comments[] = $testplan_comment;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $comments;
|
|
|
|
}
|
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
private function getRevisionProperties(
|
|
|
|
DifferentialRevision $revision,
|
|
|
|
DifferentialDiff $diff,
|
2011-04-11 00:50:26 +02:00
|
|
|
array $handles,
|
|
|
|
array $diff_properties) {
|
2011-01-27 23:55:52 +01:00
|
|
|
|
|
|
|
$properties = array();
|
|
|
|
|
|
|
|
$status = $revision->getStatus();
|
2011-05-06 21:34:34 +02:00
|
|
|
$next_step = null;
|
|
|
|
if ($status == DifferentialRevisionStatus::ACCEPTED) {
|
|
|
|
switch ($diff->getSourceControlSystem()) {
|
|
|
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
|
|
|
|
$next_step = 'arc amend --revision '.$revision->getID();
|
|
|
|
break;
|
|
|
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
|
|
|
|
$next_step = 'arc commit --revision '.$revision->getID();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ($next_step) {
|
|
|
|
$next_step =
|
|
|
|
' · '.
|
|
|
|
'Next step: <tt>'.phutil_escape_html($next_step).'</tt>';
|
|
|
|
}
|
|
|
|
}
|
2011-01-27 23:55:52 +01:00
|
|
|
$status = DifferentialRevisionStatus::getNameForRevisionStatus($status);
|
2011-05-06 21:34:34 +02:00
|
|
|
$properties['Revision Status'] = '<strong>'.$status.'</strong>'.$next_step;
|
2011-01-27 23:55:52 +01:00
|
|
|
|
2011-01-30 19:37:36 +01:00
|
|
|
$author = $handles[$revision->getAuthorPHID()];
|
2011-01-27 23:55:52 +01:00
|
|
|
$properties['Author'] = $author->renderLink();
|
|
|
|
|
|
|
|
$properties['Reviewers'] = $this->renderHandleLinkList(
|
|
|
|
array_select_keys(
|
|
|
|
$handles,
|
|
|
|
$revision->getReviewers()));
|
|
|
|
|
|
|
|
$properties['CCs'] = $this->renderHandleLinkList(
|
|
|
|
array_select_keys(
|
|
|
|
$handles,
|
|
|
|
$revision->getCCPHIDs()));
|
|
|
|
|
2011-02-05 02:53:14 +01:00
|
|
|
$host = $diff->getSourceMachine();
|
|
|
|
if ($host) {
|
|
|
|
$properties['Host'] = phutil_escape_html($host);
|
|
|
|
}
|
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
$path = $diff->getSourcePath();
|
|
|
|
if ($path) {
|
2011-02-05 02:53:14 +01:00
|
|
|
$branch = $diff->getBranch() ? ' ('.$diff->getBranch().')' : '';
|
|
|
|
$properties['Path'] = phutil_escape_html("{$path} {$branch}");
|
2011-01-27 23:55:52 +01:00
|
|
|
}
|
|
|
|
|
2011-02-05 02:53:14 +01:00
|
|
|
$lstar = DifferentialRevisionUpdateHistoryView::renderDiffLintStar($diff);
|
|
|
|
$lmsg = DifferentialRevisionUpdateHistoryView::getDiffLintMessage($diff);
|
2011-04-11 00:50:26 +02:00
|
|
|
$ldata = idx($diff_properties, 'arc:lint');
|
|
|
|
$ltail = null;
|
|
|
|
if ($ldata) {
|
|
|
|
$ldata = igroup($ldata, 'path');
|
|
|
|
$lint_messages = array();
|
|
|
|
foreach ($ldata as $path => $messages) {
|
|
|
|
$message_markup = array();
|
|
|
|
foreach ($messages as $message) {
|
|
|
|
$path = idx($message, 'path');
|
|
|
|
$line = idx($message, 'line');
|
|
|
|
|
|
|
|
$code = idx($message, 'code');
|
|
|
|
$severity = idx($message, 'severity');
|
|
|
|
|
|
|
|
$name = idx($message, 'name');
|
|
|
|
$description = idx($message, 'description');
|
|
|
|
|
|
|
|
$message_markup[] =
|
|
|
|
'<li>'.
|
|
|
|
'<span class="lint-severity-'.phutil_escape_html($severity).'">'.
|
|
|
|
phutil_escape_html(ucwords($severity)).
|
|
|
|
'</span>'.
|
|
|
|
' '.
|
|
|
|
'('.phutil_escape_html($code).') '.
|
|
|
|
phutil_escape_html($name).
|
|
|
|
' at line '.phutil_escape_html($line).
|
|
|
|
'<p>'.phutil_escape_html($description).'</p>'.
|
|
|
|
'</li>';
|
|
|
|
}
|
|
|
|
$lint_messages[] =
|
|
|
|
'<li class="lint-file-block">'.
|
|
|
|
'Lint for <strong>'.phutil_escape_html($path).'</strong>'.
|
|
|
|
'<ul>'.implode("\n", $message_markup).'</ul>'.
|
|
|
|
'</li>';
|
|
|
|
}
|
|
|
|
$ltail =
|
|
|
|
'<div class="differential-lint-block">'.
|
|
|
|
'<ul>'.
|
|
|
|
implode("\n", $lint_messages).
|
|
|
|
'</ul>'.
|
|
|
|
'</div>';
|
|
|
|
}
|
|
|
|
|
|
|
|
$properties['Lint'] = $lstar.' '.$lmsg.$ltail;
|
2011-01-27 23:55:52 +01:00
|
|
|
|
2011-02-05 02:53:14 +01:00
|
|
|
$ustar = DifferentialRevisionUpdateHistoryView::renderDiffUnitStar($diff);
|
|
|
|
$umsg = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff);
|
2011-04-11 00:50:26 +02:00
|
|
|
|
2011-06-09 01:16:59 +02:00
|
|
|
$postponed_count = 0;
|
2011-04-11 00:50:26 +02:00
|
|
|
$udata = idx($diff_properties, 'arc:unit');
|
|
|
|
$utail = null;
|
|
|
|
if ($udata) {
|
|
|
|
$unit_messages = array();
|
|
|
|
foreach ($udata as $test) {
|
|
|
|
$name = phutil_escape_html(idx($test, 'name'));
|
|
|
|
$result = phutil_escape_html(idx($test, 'result'));
|
2011-06-09 01:16:59 +02:00
|
|
|
|
|
|
|
if ($result != DifferentialUnitTestResult::RESULT_POSTPONED &&
|
|
|
|
$result != DifferentialUnitTestResult::RESULT_PASS) {
|
|
|
|
$userdata = phutil_escape_html(idx($test, 'userdata'));
|
|
|
|
if (strlen($userdata) > 256) {
|
|
|
|
$userdata = substr($userdata, 0, 256).'...';
|
|
|
|
}
|
|
|
|
$userdata = str_replace("\n", '<br />', $userdata);
|
|
|
|
$unit_messages[] =
|
|
|
|
'<tr>'.
|
2011-04-11 00:50:26 +02:00
|
|
|
'<th>'.$name.'</th>'.
|
2011-04-11 02:47:47 +02:00
|
|
|
'<th class="unit-test-result">'.
|
2011-06-09 01:16:59 +02:00
|
|
|
'<div class="result-'.$result.'">'.
|
|
|
|
strtoupper($result).
|
|
|
|
'</div>'.
|
2011-04-11 00:50:26 +02:00
|
|
|
'</th>'.
|
|
|
|
'<td>'.$userdata.'</td>'.
|
2011-06-09 01:16:59 +02:00
|
|
|
'</tr>';
|
2011-04-11 00:50:26 +02:00
|
|
|
|
2011-06-09 01:16:59 +02:00
|
|
|
$utail =
|
|
|
|
'<div class="differential-unit-block">'.
|
|
|
|
'<table class="differential-unit-table">'.
|
2011-04-11 00:50:26 +02:00
|
|
|
implode("\n", $unit_messages).
|
2011-06-09 01:16:59 +02:00
|
|
|
'</table>'.
|
|
|
|
'</div>';
|
|
|
|
} else if ($result == DifferentialUnitTestResult::RESULT_POSTPONED) {
|
|
|
|
$postponed_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($postponed_count > 0 &&
|
|
|
|
$diff->getUnitStatus() == DifferentialUnitStatus::UNIT_POSTPONED) {
|
|
|
|
$umsg = $postponed_count.' '.$umsg;
|
2011-04-11 00:50:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$properties['Unit'] = $ustar.' '.$umsg.$utail;
|
2011-01-27 23:55:52 +01:00
|
|
|
|
2011-04-13 21:12:02 +02:00
|
|
|
if (PhabricatorEnv::getEnvConfig('maniphest.enabled')) {
|
|
|
|
$tasks = $revision->getAttachedPHIDs(
|
|
|
|
PhabricatorPHIDConstants::PHID_TYPE_TASK);
|
|
|
|
if ($tasks) {
|
|
|
|
$links = array();
|
|
|
|
foreach ($tasks as $task_phid) {
|
|
|
|
$links[] = $handles[$task_phid]->renderLink();
|
|
|
|
}
|
|
|
|
$properties['Maniphest Tasks'] = implode('<br />', $links);
|
2011-02-17 23:32:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-08 06:59:42 +02:00
|
|
|
$commit_phids = $revision->getCommitPHIDs();
|
|
|
|
if ($commit_phids) {
|
|
|
|
$links = array();
|
|
|
|
foreach ($commit_phids as $commit_phid) {
|
|
|
|
$links[] = $handles[$commit_phid]->renderLink();
|
|
|
|
}
|
|
|
|
$properties['Commits'] = implode('<br />', $links);
|
|
|
|
}
|
|
|
|
|
2011-05-06 21:34:34 +02:00
|
|
|
$properties['Apply Patch'] =
|
|
|
|
'<tt>arc patch D'.$revision->getID().'</tt>';
|
|
|
|
$properties['Export Patch'] =
|
|
|
|
'<tt>arc export --revision '.$revision->getID().'</tt>';
|
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
return $properties;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getRevisionActions(DifferentialRevision $revision) {
|
|
|
|
$viewer_phid = $this->getRequest()->getUser()->getPHID();
|
2011-01-30 19:37:36 +01:00
|
|
|
$viewer_is_owner = ($revision->getAuthorPHID() == $viewer_phid);
|
2011-01-27 23:55:52 +01:00
|
|
|
$viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers());
|
|
|
|
$viewer_is_cc = in_array($viewer_phid, $revision->getCCPHIDs());
|
|
|
|
$status = $revision->getStatus();
|
|
|
|
$revision_id = $revision->getID();
|
|
|
|
$revision_phid = $revision->getPHID();
|
|
|
|
|
|
|
|
$links = array();
|
|
|
|
|
|
|
|
if ($viewer_is_owner) {
|
|
|
|
$links[] = array(
|
|
|
|
'class' => 'revision-edit',
|
|
|
|
'href' => "/differential/revision/edit/{$revision_id}/",
|
|
|
|
'name' => 'Edit Revision',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$viewer_is_owner && !$viewer_is_reviewer) {
|
|
|
|
$action = $viewer_is_cc ? 'rem' : 'add';
|
|
|
|
$links[] = array(
|
2011-04-13 03:17:43 +02:00
|
|
|
'class' => $viewer_is_cc ? 'subscribe-rem' : 'subscribe-add',
|
|
|
|
'href' => "/differential/subscribe/{$action}/{$revision_id}/",
|
|
|
|
'name' => $viewer_is_cc ? 'Unsubscribe' : 'Subscribe',
|
|
|
|
'instant' => true,
|
2011-01-27 23:55:52 +01:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
$links[] = array(
|
|
|
|
'class' => 'subscribe-rem unavailable',
|
|
|
|
'name' => 'Automatically Subscribed',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2011-02-17 23:32:01 +01:00
|
|
|
require_celerity_resource('phabricator-object-selector-css');
|
|
|
|
require_celerity_resource('javelin-behavior-phabricator-object-selector');
|
|
|
|
|
2011-04-13 21:12:02 +02:00
|
|
|
if (PhabricatorEnv::getEnvConfig('maniphest.enabled')) {
|
|
|
|
$links[] = array(
|
|
|
|
'class' => 'attach-maniphest',
|
|
|
|
'name' => 'Edit Maniphest Tasks',
|
2011-05-16 20:43:39 +02:00
|
|
|
'href' => "/search/attach/{$revision_phid}/TASK/",
|
2011-04-13 21:12:02 +02:00
|
|
|
'sigil' => 'workflow',
|
|
|
|
);
|
|
|
|
}
|
2011-02-17 23:32:01 +01:00
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
$links[] = array(
|
|
|
|
'class' => 'transcripts-metamta',
|
|
|
|
'name' => 'MetaMTA Transcripts',
|
|
|
|
'href' => "/mail/?phid={$revision_phid}",
|
|
|
|
);
|
|
|
|
|
2011-04-07 23:24:54 +02:00
|
|
|
$links[] = array(
|
|
|
|
'class' => 'transcripts-herald',
|
|
|
|
'name' => 'Herald Transcripts',
|
|
|
|
'href' => "/herald/transcript/?phid={$revision_phid}",
|
|
|
|
);
|
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
return $links;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function renderHandleLinkList(array $list) {
|
|
|
|
if (empty($list)) {
|
|
|
|
return '<em>None</em>';
|
|
|
|
}
|
|
|
|
return implode(', ', mpull($list, 'renderLink'));
|
|
|
|
}
|
|
|
|
|
2011-01-30 20:02:22 +01:00
|
|
|
private function getRevisionCommentActions(DifferentialRevision $revision) {
|
|
|
|
|
|
|
|
$actions = array(
|
|
|
|
DifferentialAction::ACTION_COMMENT => true,
|
|
|
|
);
|
|
|
|
|
|
|
|
$viewer_phid = $this->getRequest()->getUser()->getPHID();
|
|
|
|
$viewer_is_owner = ($viewer_phid == $revision->getAuthorPHID());
|
2011-04-11 19:38:10 +02:00
|
|
|
$viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers());
|
2011-01-30 20:02:22 +01:00
|
|
|
|
|
|
|
if ($viewer_is_owner) {
|
|
|
|
switch ($revision->getStatus()) {
|
|
|
|
case DifferentialRevisionStatus::NEEDS_REVIEW:
|
|
|
|
$actions[DifferentialAction::ACTION_ABANDON] = true;
|
2011-04-14 01:10:54 +02:00
|
|
|
$actions[DifferentialAction::ACTION_RETHINK] = true;
|
2011-01-30 20:02:22 +01:00
|
|
|
break;
|
|
|
|
case DifferentialRevisionStatus::NEEDS_REVISION:
|
2011-04-14 01:10:54 +02:00
|
|
|
$actions[DifferentialAction::ACTION_ABANDON] = true;
|
|
|
|
$actions[DifferentialAction::ACTION_REQUEST] = true;
|
|
|
|
break;
|
2011-01-30 20:02:22 +01:00
|
|
|
case DifferentialRevisionStatus::ACCEPTED:
|
|
|
|
$actions[DifferentialAction::ACTION_ABANDON] = true;
|
|
|
|
$actions[DifferentialAction::ACTION_REQUEST] = true;
|
2011-04-14 01:10:54 +02:00
|
|
|
$actions[DifferentialAction::ACTION_RETHINK] = true;
|
2011-01-30 20:02:22 +01:00
|
|
|
break;
|
|
|
|
case DifferentialRevisionStatus::COMMITTED:
|
|
|
|
break;
|
|
|
|
case DifferentialRevisionStatus::ABANDONED:
|
|
|
|
$actions[DifferentialAction::ACTION_RECLAIM] = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch ($revision->getStatus()) {
|
|
|
|
case DifferentialRevisionStatus::NEEDS_REVIEW:
|
|
|
|
$actions[DifferentialAction::ACTION_ACCEPT] = true;
|
|
|
|
$actions[DifferentialAction::ACTION_REJECT] = true;
|
2011-04-11 19:38:10 +02:00
|
|
|
$actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
|
2011-01-30 20:02:22 +01:00
|
|
|
break;
|
|
|
|
case DifferentialRevisionStatus::NEEDS_REVISION:
|
|
|
|
$actions[DifferentialAction::ACTION_ACCEPT] = true;
|
2011-04-11 19:38:10 +02:00
|
|
|
$actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer;
|
2011-01-30 20:02:22 +01:00
|
|
|
break;
|
|
|
|
case DifferentialRevisionStatus::ACCEPTED:
|
|
|
|
$actions[DifferentialAction::ACTION_REJECT] = true;
|
|
|
|
break;
|
|
|
|
case DifferentialRevisionStatus::COMMITTED:
|
|
|
|
case DifferentialRevisionStatus::ABANDONED:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$actions[DifferentialAction::ACTION_ADDREVIEWERS] = true;
|
|
|
|
|
2011-04-15 00:10:51 +02:00
|
|
|
return array_keys(array_filter($actions));
|
2011-01-30 20:02:22 +01:00
|
|
|
}
|
|
|
|
|
2011-02-03 04:38:43 +01:00
|
|
|
private function loadInlineComments(array $comments, array &$changesets) {
|
|
|
|
|
|
|
|
$inline_comments = array();
|
|
|
|
|
|
|
|
$comment_ids = array_filter(mpull($comments, 'getID'));
|
|
|
|
if (!$comment_ids) {
|
|
|
|
return $inline_comments;
|
|
|
|
}
|
|
|
|
|
|
|
|
$inline_comments = id(new DifferentialInlineComment())
|
|
|
|
->loadAllWhere(
|
|
|
|
'commentID in (%Ld)',
|
|
|
|
$comment_ids);
|
|
|
|
|
|
|
|
$load_changesets = array();
|
|
|
|
foreach ($inline_comments as $inline) {
|
|
|
|
$changeset_id = $inline->getChangesetID();
|
|
|
|
if (isset($changesets[$changeset_id])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$load_changesets[$changeset_id] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$more_changesets = array();
|
|
|
|
if ($load_changesets) {
|
|
|
|
$changeset_ids = array_keys($load_changesets);
|
|
|
|
$more_changesets += id(new DifferentialChangeset())
|
|
|
|
->loadAllWhere(
|
|
|
|
'id IN (%Ld)',
|
|
|
|
$changeset_ids);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($more_changesets) {
|
|
|
|
$changesets += $more_changesets;
|
|
|
|
$changesets = msort($changesets, 'getSortKey');
|
|
|
|
}
|
|
|
|
|
|
|
|
return $inline_comments;
|
|
|
|
}
|
|
|
|
|
2011-02-04 00:41:58 +01:00
|
|
|
private function loadChangesetsAndVsMap(array $diffs, $diff_vs, $target) {
|
|
|
|
$load_ids = array();
|
|
|
|
if ($diff_vs) {
|
|
|
|
$load_ids[] = $diff_vs;
|
|
|
|
}
|
|
|
|
$load_ids[] = $target->getID();
|
|
|
|
|
|
|
|
$raw_changesets = id(new DifferentialChangeset())
|
|
|
|
->loadAllWhere(
|
|
|
|
'diffID IN (%Ld)',
|
|
|
|
$load_ids);
|
|
|
|
$changeset_groups = mgroup($raw_changesets, 'getDiffID');
|
|
|
|
|
|
|
|
$changesets = idx($changeset_groups, $target->getID(), array());
|
|
|
|
$changesets = mpull($changesets, null, 'getID');
|
|
|
|
|
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
|
|
|
$refs = array();
|
|
|
|
foreach ($changesets as $changeset) {
|
|
|
|
$refs[$changeset->getID()] = $changeset->getID();
|
|
|
|
}
|
|
|
|
|
2011-02-04 00:41:58 +01:00
|
|
|
$vs_map = array();
|
|
|
|
if ($diff_vs) {
|
|
|
|
$vs_changesets = idx($changeset_groups, $diff_vs, array());
|
|
|
|
$vs_changesets = mpull($vs_changesets, null, 'getFilename');
|
|
|
|
foreach ($changesets as $key => $changeset) {
|
|
|
|
$file = $changeset->getFilename();
|
|
|
|
if (isset($vs_changesets[$file])) {
|
|
|
|
$vs_map[$changeset->getID()] = $vs_changesets[$file]->getID();
|
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
|
|
|
$refs[$changeset->getID()] =
|
|
|
|
$changeset->getID().'/'.$vs_changesets[$file]->getID();
|
2011-02-04 00:41:58 +01:00
|
|
|
unset($vs_changesets[$file]);
|
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
|
|
|
} else {
|
|
|
|
$refs[$changeset->getID()] = $changeset->getID();
|
2011-02-04 00:41:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach ($vs_changesets as $changeset) {
|
|
|
|
$changesets[$changeset->getID()] = $changeset;
|
|
|
|
$vs_map[$changeset->getID()] = -1;
|
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
|
|
|
$refs[$changeset->getID()] = $changeset->getID().'/-1';
|
2011-02-04 00:41:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$changesets = msort($changesets, 'getSortKey');
|
|
|
|
|
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
|
|
|
return array($changesets, $vs_map, $refs);
|
2011-02-04 00:41:58 +01:00
|
|
|
}
|
|
|
|
|
Differential Updates View
Summary:
This adds a new view to differential called Updates.
The high-level goal of Updates is to enabled differential to be
effectively used without email notifications. I've tried doing things
like automatically deleting differential emails where I'm in the 'to'
line since they show up on the main diffential page but then there's
always the chance an important diff flies by without me seeing it. Also,
sometimes someone comments on a diff post-commit but differential
doesn't surface those diffs.
I re-created a test db on my devserver using mysqldump to get data on
revs > 230000 so I would have some test data. We need to add a simple
viewtime table but I didn't want to do that in production. Here's the
table:
CREATE TABLE differential_viewtime (
viewerPHID varchar(64) not null,
objectPHID varchar(64) not null,
viewTime int unsigned not null,
PRIMARY KEY (viewerPHID, objectPHID)
);
Issues:
-Once we turn this on, all diffs will be 'unviewed'. What do you think
about a 'Clear All' button or something?
-Maybe we should add a pager
This feature would be insanely useful, let me know what you think.
Test Plan:
Loaded Updates in my sandbox
http://phabricator.dev1577.snc6.facebook.com/differential/filter/updates/
Clicked a diff, then went back, made sure diff disappeared from Updates
list
Reviewed By: tuomaspelkonen
Reviewers: epriestley, jungejason, tuomaspelkonen
Commenters: epriestley
CC: epriestley, elynde, tuomaspelkonen
Differential Revision: 169
2011-04-27 10:27:06 +02:00
|
|
|
private function updateViewTime($user_phid, $revision_phid) {
|
|
|
|
$view_time =
|
|
|
|
id(new DifferentialViewTime())
|
|
|
|
->setViewerPHID($user_phid)
|
|
|
|
->setObjectPHID($revision_phid)
|
|
|
|
->setViewTime(time())
|
|
|
|
->replace();
|
|
|
|
}
|
2011-01-27 23:55:52 +01:00
|
|
|
}
|