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;
|
|
|
|
}
|
|
|
|
|
2011-08-30 20:34:07 +02:00
|
|
|
list($aux_fields, $props) = $this->loadAuxiliaryFieldsAndProperties(
|
|
|
|
$revision,
|
|
|
|
$target,
|
|
|
|
array(
|
|
|
|
'local:commits',
|
|
|
|
));
|
2011-08-14 20:29:56 +02: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
|
|
|
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-06-24 21:21:48 +02:00
|
|
|
$added_ccs = idx(
|
|
|
|
$metadata,
|
|
|
|
DifferentialComment::METADATA_ADDED_CCS);
|
|
|
|
if ($added_ccs) {
|
|
|
|
foreach ($added_ccs as $phid) {
|
|
|
|
$object_phids[] = $phid;
|
|
|
|
}
|
|
|
|
}
|
2011-06-01 20:19:55 +02:00
|
|
|
}
|
|
|
|
|
2011-02-17 23:32:01 +01:00
|
|
|
foreach ($revision->getAttached() as $type => $phids) {
|
|
|
|
foreach ($phids as $phid => $info) {
|
|
|
|
$object_phids[] = $phid;
|
|
|
|
}
|
|
|
|
}
|
2011-08-14 21:33:54 +02:00
|
|
|
|
|
|
|
$aux_phids = array();
|
|
|
|
foreach ($aux_fields as $key => $aux_field) {
|
|
|
|
$aux_phids[$key] = $aux_field->getRequiredHandlePHIDsForRevisionView();
|
|
|
|
}
|
|
|
|
$object_phids = array_merge($object_phids, array_mergev($aux_phids));
|
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-08-14 21:33:54 +02:00
|
|
|
foreach ($aux_fields as $key => $aux_field) {
|
|
|
|
// Make sure each field only has access to handles it specifically
|
|
|
|
// requested, not all handles. Otherwise you can get a field which works
|
|
|
|
// only in the presence of other fields.
|
|
|
|
$aux_field->setHandles(array_select_keys($handles, $aux_phids[$key]));
|
|
|
|
}
|
|
|
|
|
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-01-27 23:55:52 +01:00
|
|
|
$revision_detail = new DifferentialRevisionDetailView();
|
|
|
|
$revision_detail->setRevision($revision);
|
2011-08-10 22:46:01 +02:00
|
|
|
$revision_detail->setAuxiliaryFields($aux_fields);
|
2011-01-27 23:55:52 +01:00
|
|
|
|
2011-08-14 22:55:30 +02:00
|
|
|
$actions = $this->getRevisionActions($revision);
|
|
|
|
|
2011-04-13 00:57:29 +02:00
|
|
|
$custom_renderer_class = PhabricatorEnv::getEnvConfig(
|
|
|
|
'differential.revision-custom-detail-renderer');
|
|
|
|
if ($custom_renderer_class) {
|
2011-08-14 22:55:30 +02:00
|
|
|
|
2011-08-18 09:17:50 +02:00
|
|
|
// TODO: build a better version of the action links and deprecate the
|
|
|
|
// whole DifferentialRevisionDetailRenderer class.
|
2011-04-13 00:57:29 +02:00
|
|
|
PhutilSymbolLoader::loadClass($custom_renderer_class);
|
|
|
|
$custom_renderer =
|
|
|
|
newv($custom_renderer_class, array());
|
|
|
|
$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
|
|
|
|
2011-08-30 20:34:07 +02:00
|
|
|
$local_view = new DifferentialLocalCommitsView();
|
|
|
|
$local_view->setUser($user);
|
|
|
|
$local_view->setLocalCommits(idx($props, 'local:commits'));
|
|
|
|
|
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-07-08 22:00:30 +02:00
|
|
|
$pane_id = celerity_generate_unique_node_id();
|
|
|
|
Javelin::initBehavior(
|
|
|
|
'differential-keyboard-navigation',
|
|
|
|
array(
|
|
|
|
'haunt' => $pane_id,
|
|
|
|
));
|
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
return $this->buildStandardPageResponse(
|
2011-06-08 21:39:03 +02:00
|
|
|
id(new DifferentialPrimaryPaneView())
|
|
|
|
->setLineWidthFromChangesets($changesets)
|
2011-07-08 22:00:30 +02:00
|
|
|
->setID($pane_id)
|
2011-06-08 21:39:03 +02:00
|
|
|
->appendChild(
|
|
|
|
$revision_detail->render().
|
|
|
|
$comment_view->render().
|
|
|
|
$diff_history->render().
|
|
|
|
$warning.
|
2011-08-30 20:34:07 +02:00
|
|
|
$local_view->render().
|
2011-06-08 21:39:03 +02:00
|
|
|
$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 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-07-05 22:18:47 +02:00
|
|
|
$links[] = array(
|
|
|
|
'class' => 'action-dependencies',
|
|
|
|
'name' => 'Edit Dependencies',
|
|
|
|
'href' => "/search/attach/{$revision_phid}/DREV/dependencies/",
|
|
|
|
'sigil' => 'workflow',
|
|
|
|
);
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
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-06-24 21:21:48 +02:00
|
|
|
$actions[DifferentialAction::ACTION_ADDCCS] = true;
|
2011-01-30 20:02:22 +01:00
|
|
|
|
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) {
|
2011-08-16 22:50:47 +02:00
|
|
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
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
|
|
|
$view_time =
|
|
|
|
id(new DifferentialViewTime())
|
|
|
|
->setViewerPHID($user_phid)
|
|
|
|
->setObjectPHID($revision_phid)
|
|
|
|
->setViewTime(time())
|
|
|
|
->replace();
|
|
|
|
}
|
2011-08-10 22:46:01 +02:00
|
|
|
|
2011-08-30 20:34:07 +02:00
|
|
|
private function loadAuxiliaryFieldsAndProperties(
|
2011-08-14 22:55:30 +02:00
|
|
|
DifferentialRevision $revision,
|
2011-08-30 20:34:07 +02:00
|
|
|
DifferentialDiff $diff,
|
|
|
|
array $special_properties) {
|
|
|
|
|
2011-08-10 22:46:01 +02:00
|
|
|
$aux_fields = DifferentialFieldSelector::newSelector()
|
|
|
|
->getFieldSpecifications();
|
|
|
|
foreach ($aux_fields as $key => $aux_field) {
|
|
|
|
if (!$aux_field->shouldAppearOnRevisionView()) {
|
|
|
|
unset($aux_fields[$key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-14 22:55:30 +02:00
|
|
|
$aux_fields = DifferentialAuxiliaryField::loadFromStorage(
|
2011-08-10 22:46:01 +02:00
|
|
|
$revision,
|
|
|
|
$aux_fields);
|
2011-08-14 22:55:30 +02:00
|
|
|
|
|
|
|
$aux_props = array();
|
|
|
|
foreach ($aux_fields as $key => $aux_field) {
|
|
|
|
$aux_field->setDiff($diff);
|
|
|
|
$aux_props[$key] = $aux_field->getRequiredDiffProperties();
|
|
|
|
}
|
|
|
|
|
|
|
|
$required_properties = array_mergev($aux_props);
|
2011-08-30 20:34:07 +02:00
|
|
|
$required_properties = array_merge(
|
|
|
|
$required_properties,
|
|
|
|
$special_properties);
|
|
|
|
|
2011-08-14 22:55:30 +02:00
|
|
|
$property_map = array();
|
|
|
|
if ($required_properties) {
|
|
|
|
$properties = id(new DifferentialDiffProperty())->loadAllWhere(
|
|
|
|
'diffID = %d AND name IN (%Ls)',
|
|
|
|
$diff->getID(),
|
|
|
|
$required_properties);
|
|
|
|
$property_map = mpull($properties, 'getData', 'getName');
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($aux_fields as $key => $aux_field) {
|
|
|
|
// Give each field only the properties it specifically required, and
|
|
|
|
// set 'null' for each requested key which we didn't actually load a
|
|
|
|
// value for (otherwise, getDiffProperty() will throw).
|
|
|
|
if ($aux_props[$key]) {
|
|
|
|
$props = array_select_keys($property_map, $aux_props[$key]) +
|
|
|
|
array_fill_keys($aux_props[$key], null);
|
|
|
|
} else {
|
|
|
|
$props = array();
|
|
|
|
}
|
|
|
|
|
|
|
|
$aux_field->setDiffProperties($props);
|
|
|
|
}
|
|
|
|
|
2011-08-30 20:34:07 +02:00
|
|
|
return array(
|
|
|
|
$aux_fields,
|
|
|
|
array_select_keys(
|
|
|
|
$property_map,
|
|
|
|
$special_properties));
|
2011-08-10 22:46:01 +02:00
|
|
|
}
|
|
|
|
|
2011-08-14 22:55:30 +02:00
|
|
|
|
2011-01-27 23:55:52 +01:00
|
|
|
}
|