2011-03-11 18:34:22 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
2012-01-19 20:49:51 +01:00
|
|
|
* Copyright 2012 Facebook, Inc.
|
2011-03-11 18:34:22 +01:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2012-03-10 00:46:25 +01:00
|
|
|
final class DiffusionCommitController extends DiffusionController {
|
2011-03-11 18:34:22 +01:00
|
|
|
|
2011-04-07 23:55:06 +02:00
|
|
|
const CHANGES_LIMIT = 100;
|
|
|
|
|
2012-03-26 18:44:06 +02:00
|
|
|
private $auditAuthorityPHIDs;
|
|
|
|
|
Fix many encoding and architecture problems in Diffusion request and URI handling
Summary:
Diffusion request/uri handling is currently a big, hastily ported mess. In particular, it has:
- Tons and tons of duplicated code.
- Bugs with handling unusual branch and file names.
- An excessively large (and yet insufficiently expressive) API on DiffusionRequest, including a nonsensical concrete base class.
- Other tools were doing hacky things like passing ":" branch names.
This diff attempts to fix these issues.
- Make the base class abstract (it was concrete ONLY for "/diffusion/").
- Move all URI generation to DiffusionRequest. Make the core static. Add unit tests.
- Delete the 300 copies of URI generation code throughout Diffusion.
- Move all URI parsing to DiffusionRequest. Make the core static. Add unit tests.
- Add an appropriate static initializer for other callers.
- Convert all code calling `newFromAphrontRequestDictionary` outside of Diffusion to the new `newFromDictionary` API.
- Refactor static initializers to be sensibly-sized.
- Refactor derived DiffusionRequest classes to remove duplicated code.
- Properly encode branch names (fixes branches with "/", see <https://github.com/facebook/phabricator/issues/100>).
- Properly encode path names (fixes issues in D1742).
- Properly escape delimiter characters ";" and "$" in path names so files like "$100" are not interpreted as "line 100".
- Fix a couple warnings.
- Fix a couple lint issues.
- Fix a bug where we would not parse filenames with spaces in them correctly in the Git browse query.
- Fix a bug where Git change queries would fail unnecessarily.
- Provide or improve some documentation.
This thing is pretty gigantic but also kind of hard to split up. If it's unreasonably difficult to review, let me know and I can take a stab at it though.
This supplants D1742.
Test Plan:
- Used home, repository, branch, browse, change, history, diff (ajax), lastmodified (ajax) views of Diffusion.
- Used Owners typeaheads and search.
- Used diffusion.getrecentcommitsbypath method.
- Pushed a change to an absurdly-named file on an absurdly-named branch, everything worked properly.
{F9185}
Reviewers: nh, vrana, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1921
2012-03-20 03:52:14 +01:00
|
|
|
public function willProcessRequest(array $data) {
|
|
|
|
// This controller doesn't use blob/path stuff, just pass the dictionary
|
|
|
|
// in directly instead of using the AphrontRequest parsing mechanism.
|
|
|
|
$drequest = DiffusionRequest::newFromDictionary($data);
|
|
|
|
$this->diffusionRequest = $drequest;
|
|
|
|
}
|
|
|
|
|
2011-03-11 18:34:22 +01:00
|
|
|
public function processRequest() {
|
2011-03-14 00:19:39 +01:00
|
|
|
$drequest = $this->getDiffusionRequest();
|
2011-04-07 23:55:06 +02:00
|
|
|
$request = $this->getRequest();
|
2011-06-18 22:07:02 +02:00
|
|
|
$user = $request->getUser();
|
2011-03-11 18:34:22 +01:00
|
|
|
|
2012-05-02 22:43:45 +02:00
|
|
|
if ($request->getStr('diff')) {
|
|
|
|
return $this->buildRawDiffResponse($drequest);
|
|
|
|
}
|
|
|
|
|
2011-03-31 04:22:11 +02:00
|
|
|
$callsign = $drequest->getRepository()->getCallsign();
|
|
|
|
|
2011-03-14 00:19:39 +01:00
|
|
|
$content = array();
|
|
|
|
$content[] = $this->buildCrumbs(array(
|
|
|
|
'commit' => true,
|
|
|
|
));
|
2011-03-11 18:34:22 +01:00
|
|
|
|
2011-03-14 04:12:17 +01:00
|
|
|
$repository = $drequest->getRepository();
|
|
|
|
$commit = $drequest->loadCommit();
|
2011-03-27 08:52:09 +02:00
|
|
|
|
|
|
|
if (!$commit) {
|
|
|
|
// TODO: Make more user-friendly.
|
|
|
|
throw new Exception('This commit has not parsed yet.');
|
|
|
|
}
|
|
|
|
|
2011-03-14 04:12:17 +01:00
|
|
|
$commit_data = $drequest->loadCommitData();
|
2012-03-26 18:44:06 +02:00
|
|
|
$commit->attachCommitData($commit_data);
|
2011-03-14 04:12:17 +01:00
|
|
|
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
$is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
|
|
|
|
if ($is_foreign) {
|
|
|
|
$subpath = $commit_data->getCommitDetail('svn-subpath');
|
|
|
|
|
|
|
|
$error_panel = new AphrontErrorView();
|
|
|
|
$error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
|
|
|
|
$error_panel->setTitle('Commit Not Tracked');
|
|
|
|
$error_panel->setSeverity(AphrontErrorView::SEVERITY_WARNING);
|
|
|
|
$error_panel->appendChild(
|
|
|
|
"This Diffusion repository is configured to track only one ".
|
|
|
|
"subdirectory of the entire Subversion repository, and this commit ".
|
|
|
|
"didn't affect the tracked subdirectory ('".
|
|
|
|
phutil_escape_html($subpath)."'), so no information is available.");
|
|
|
|
$content[] = $error_panel;
|
|
|
|
} else {
|
|
|
|
$engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
|
|
|
|
|
|
|
|
require_celerity_resource('diffusion-commit-view-css');
|
|
|
|
require_celerity_resource('phabricator-remarkup-css');
|
|
|
|
|
2012-03-26 21:21:48 +02:00
|
|
|
$parent_query = DiffusionCommitParentsQuery::newFromDiffusionRequest(
|
|
|
|
$drequest);
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
|
2012-03-30 23:12:10 +02:00
|
|
|
$headsup_panel = new AphrontHeadsupView();
|
|
|
|
$headsup_panel->setHeader('Commit Detail');
|
|
|
|
$headsup_panel->setActionList(
|
|
|
|
$this->renderHeadsupActionList($commit));
|
|
|
|
$headsup_panel->setProperties(
|
|
|
|
$this->getCommitProperties(
|
|
|
|
$commit,
|
|
|
|
$commit_data,
|
|
|
|
$parent_query->loadParents()));
|
|
|
|
|
|
|
|
$headsup_panel->appendChild(
|
|
|
|
'<div class="diffusion-commit-message phabricator-remarkup">'.
|
|
|
|
$engine->markupText($commit_data->getCommitMessage()).
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
'</div>');
|
2011-03-11 18:34:22 +01:00
|
|
|
|
2012-03-30 23:12:10 +02:00
|
|
|
$content[] = $headsup_panel;
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
}
|
2011-03-14 00:19:39 +01:00
|
|
|
|
2012-03-26 18:44:06 +02:00
|
|
|
$query = new PhabricatorAuditQuery();
|
|
|
|
$query->withCommitPHIDs(array($commit->getPHID()));
|
|
|
|
$audit_requests = $query->execute();
|
|
|
|
|
|
|
|
$this->auditAuthorityPHIDs =
|
|
|
|
PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
|
|
|
|
|
|
|
|
$content[] = $this->buildAuditTable($commit, $audit_requests);
|
2012-02-24 23:14:39 +01:00
|
|
|
$content[] = $this->buildComments($commit);
|
2012-02-24 22:02:14 +01:00
|
|
|
|
2011-03-14 00:19:39 +01:00
|
|
|
$change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
|
|
|
|
$drequest);
|
|
|
|
$changes = $change_query->loadChanges();
|
|
|
|
|
2012-03-23 23:32:26 +01:00
|
|
|
$content[] = $this->buildMergesTable($commit);
|
|
|
|
|
2011-04-07 23:55:06 +02:00
|
|
|
$original_changes_count = count($changes);
|
|
|
|
if ($request->getStr('show_all') !== 'true' &&
|
|
|
|
$original_changes_count > self::CHANGES_LIMIT) {
|
|
|
|
$changes = array_slice($changes, 0, self::CHANGES_LIMIT);
|
|
|
|
}
|
|
|
|
|
2011-03-11 18:34:22 +01:00
|
|
|
$change_table = new DiffusionCommitChangeTableView();
|
|
|
|
$change_table->setDiffusionRequest($drequest);
|
2011-03-14 00:19:39 +01:00
|
|
|
$change_table->setPathChanges($changes);
|
2011-03-11 18:34:22 +01:00
|
|
|
|
2011-04-07 23:55:06 +02:00
|
|
|
$count = count($changes);
|
2011-03-19 22:38:50 +01:00
|
|
|
|
2011-03-27 08:52:09 +02:00
|
|
|
$bad_commit = null;
|
|
|
|
if ($count == 0) {
|
|
|
|
$bad_commit = queryfx_one(
|
|
|
|
id(new PhabricatorRepository())->establishConnection('r'),
|
|
|
|
'SELECT * FROM %T WHERE fullCommitName = %s',
|
|
|
|
PhabricatorRepository::TABLE_BADCOMMIT,
|
2011-03-31 04:22:11 +02:00
|
|
|
'r'.$callsign.$commit->getCommitIdentifier());
|
2011-03-27 08:52:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($bad_commit) {
|
|
|
|
$error_panel = new AphrontErrorView();
|
|
|
|
$error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
|
|
|
|
$error_panel->setTitle('Bad Commit');
|
|
|
|
$error_panel->appendChild(
|
|
|
|
phutil_escape_html($bad_commit['description']));
|
|
|
|
|
|
|
|
$content[] = $error_panel;
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
} else if ($is_foreign) {
|
|
|
|
// Don't render anything else.
|
|
|
|
} else if (!count($changes)) {
|
|
|
|
$no_changes = new AphrontErrorView();
|
|
|
|
$no_changes->setWidth(AphrontErrorView::WIDTH_WIDE);
|
|
|
|
$no_changes->setSeverity(AphrontErrorView::SEVERITY_WARNING);
|
|
|
|
$no_changes->setTitle('Not Yet Parsed');
|
|
|
|
// TODO: This can also happen with weird SVN changes that don't do
|
|
|
|
// anything (or only alter properties?), although the real no-changes case
|
|
|
|
// is extremely rare and might be impossible to produce organically. We
|
|
|
|
// should probably write some kind of "Nothing Happened!" change into the
|
|
|
|
// DB once we parse these changes so we can distinguish between
|
|
|
|
// "not parsed yet" and "no changes".
|
|
|
|
$no_changes->appendChild(
|
|
|
|
"This commit hasn't been fully parsed yet (or doesn't affect any ".
|
|
|
|
"paths).");
|
|
|
|
$content[] = $no_changes;
|
2011-03-27 08:52:09 +02:00
|
|
|
} else {
|
|
|
|
$change_panel = new AphrontPanelView();
|
2011-04-07 23:55:06 +02:00
|
|
|
$change_panel->setHeader("Changes (".number_format($count).")");
|
2012-06-18 20:09:25 +02:00
|
|
|
$change_panel->setID('differential-review-toc');
|
2011-04-07 23:55:06 +02:00
|
|
|
|
|
|
|
if ($count !== $original_changes_count) {
|
|
|
|
$show_all_button = phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'class' => 'button green',
|
|
|
|
'href' => '?show_all=true',
|
|
|
|
),
|
|
|
|
phutil_escape_html('Show All Changes'));
|
|
|
|
$warning_view = id(new AphrontErrorView())
|
|
|
|
->setSeverity(AphrontErrorView::SEVERITY_WARNING)
|
|
|
|
->setTitle(sprintf(
|
|
|
|
"Showing only the first %d changes out of %s!",
|
|
|
|
self::CHANGES_LIMIT,
|
|
|
|
number_format($original_changes_count)));
|
|
|
|
|
|
|
|
$change_panel->appendChild($warning_view);
|
|
|
|
$change_panel->addButton($show_all_button);
|
|
|
|
}
|
|
|
|
|
2011-03-27 08:52:09 +02:00
|
|
|
$change_panel->appendChild($change_table);
|
|
|
|
|
|
|
|
$content[] = $change_panel;
|
|
|
|
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
$changesets = DiffusionPathChange::convertToDifferentialChangesets(
|
|
|
|
$changes);
|
|
|
|
|
|
|
|
$vcs = $repository->getVersionControlSystem();
|
|
|
|
switch ($vcs) {
|
|
|
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
|
|
|
|
$vcs_supports_directory_changes = true;
|
|
|
|
break;
|
|
|
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
|
Basic support for Mercurial in Diffusion
Summary: Change import script plus almost all the view stuff. Still some rough
edges but this seems to mostly work. Blame is currently unsupported but I think
everything else works properly.
Test Plan:
Imported the hg repository itself. It doesn't immediately seem completely
broken. Here are some screens:
https://secure.phabricator.com/file/view/PHID-FILE-1438b71cc7c4a2eb4569/
https://secure.phabricator.com/file/view/PHID-FILE-3cec4f72f39e7de2d041/
https://secure.phabricator.com/file/view/PHID-FILE-2ea4883f160e8e5098f9/
https://secure.phabricator.com/file/view/PHID-FILE-35f751a36ebf65399ade/
All the parsers were able to churn through it without errors.
Ran the new "reparse.php" script in various one-commit and repository modes.
Browsed/imported some git repos for good measure.
NOTE: The hg repository is only 15,000 commits and around 1,000 files.
Performance is okay but hg doesn't provide performant, native APIs to get some
data efficiently so we have to do some dumb stuff. If some of these interfaces
are cripplingly slow or whatever, let me know and we can start bundling some
Mercurial extensions with Arcanist.
Reviewers: Makinde, jungejason, nh, tuomaspelkonen, aran
Reviewed By: Makinde
CC: aran, Makinde, epriestley
Differential Revision: 960
2011-09-26 20:07:38 +02:00
|
|
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
$vcs_supports_directory_changes = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new Exception("Unknown VCS.");
|
|
|
|
}
|
2011-03-31 07:08:41 +02:00
|
|
|
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
$references = array();
|
|
|
|
foreach ($changesets as $key => $changeset) {
|
|
|
|
$file_type = $changeset->getFileType();
|
|
|
|
if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
|
|
|
|
if (!$vcs_supports_directory_changes) {
|
|
|
|
unset($changesets[$key]);
|
|
|
|
continue;
|
2011-03-31 07:08:41 +02:00
|
|
|
}
|
2011-03-31 04:22:11 +02:00
|
|
|
}
|
|
|
|
|
Fix many encoding and architecture problems in Diffusion request and URI handling
Summary:
Diffusion request/uri handling is currently a big, hastily ported mess. In particular, it has:
- Tons and tons of duplicated code.
- Bugs with handling unusual branch and file names.
- An excessively large (and yet insufficiently expressive) API on DiffusionRequest, including a nonsensical concrete base class.
- Other tools were doing hacky things like passing ":" branch names.
This diff attempts to fix these issues.
- Make the base class abstract (it was concrete ONLY for "/diffusion/").
- Move all URI generation to DiffusionRequest. Make the core static. Add unit tests.
- Delete the 300 copies of URI generation code throughout Diffusion.
- Move all URI parsing to DiffusionRequest. Make the core static. Add unit tests.
- Add an appropriate static initializer for other callers.
- Convert all code calling `newFromAphrontRequestDictionary` outside of Diffusion to the new `newFromDictionary` API.
- Refactor static initializers to be sensibly-sized.
- Refactor derived DiffusionRequest classes to remove duplicated code.
- Properly encode branch names (fixes branches with "/", see <https://github.com/facebook/phabricator/issues/100>).
- Properly encode path names (fixes issues in D1742).
- Properly escape delimiter characters ";" and "$" in path names so files like "$100" are not interpreted as "line 100".
- Fix a couple warnings.
- Fix a couple lint issues.
- Fix a bug where we would not parse filenames with spaces in them correctly in the Git browse query.
- Fix a bug where Git change queries would fail unnecessarily.
- Provide or improve some documentation.
This thing is pretty gigantic but also kind of hard to split up. If it's unreasonably difficult to review, let me know and I can take a stab at it though.
This supplants D1742.
Test Plan:
- Used home, repository, branch, browse, change, history, diff (ajax), lastmodified (ajax) views of Diffusion.
- Used Owners typeaheads and search.
- Used diffusion.getrecentcommitsbypath method.
- Pushed a change to an absurdly-named file on an absurdly-named branch, everything worked properly.
{F9185}
Reviewers: nh, vrana, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1921
2012-03-20 03:52:14 +01:00
|
|
|
$references[$key] = $drequest->generateURI(
|
|
|
|
array(
|
|
|
|
'action' => 'rendering-ref',
|
|
|
|
'path' => $changeset->getFilename(),
|
|
|
|
));
|
2011-03-31 04:22:11 +02:00
|
|
|
}
|
2011-03-27 08:52:09 +02:00
|
|
|
|
2012-04-07 20:45:31 +02:00
|
|
|
// TODO: Some parts of the views still rely on properties of the
|
Add inline comments to Diffusion/Audit
Summary:
- Add inline comments to Audits, like Differential.
- Creates new storage for the comments in the Audits database.
- Creates a new PhabricatorAuditInlineComment class, similar to DifferentialInlineComment.
- Defines an Interface which Differential and Audit comments conform to.
- Makes consumers of DifferentialInlineComments consume objects which implement that interface instead.
- Adds save
NOTE: Some features are still missing! Wanted to cut this off before it got crazy:
- Inline comments aren't shown in the main comment list.
- Inline comments aren't shown in the emails.
- Inline comments aren't previewed.
I'll followup with those but this was getting pretty big.
@vrana, does the SQL change look correct?
Test Plan:
- Created, edited, deleted, replied to, reloaded and saved inline comments in Diffusion, on the left and right side of diffs.
- Created, edited, deleted, replied to, reloaded and saved inline comments in Differentila, on the left and right side of primary and diff-versus-diff diffs.
Reviewers: btrahan, vrana
Reviewed By: btrahan
CC: aran, epriestley
Maniphest Tasks: T904
Differential Revision: https://secure.phabricator.com/D1898
2012-03-14 20:56:01 +01:00
|
|
|
// DifferentialChangeset. Make the objects ephemeral to make sure we don't
|
|
|
|
// accidentally save them, and then set their ID to the appropriate ID for
|
|
|
|
// this application (the path IDs).
|
|
|
|
$pquery = new DiffusionPathIDQuery(mpull($changesets, 'getFilename'));
|
|
|
|
$path_ids = $pquery->loadPathIDs();
|
|
|
|
foreach ($changesets as $changeset) {
|
|
|
|
$changeset->makeEphemeral();
|
|
|
|
$changeset->setID($path_ids[$changeset->getFilename()]);
|
|
|
|
}
|
|
|
|
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
$change_list = new DifferentialChangesetListView();
|
|
|
|
$change_list->setChangesets($changesets);
|
2012-05-01 21:09:50 +02:00
|
|
|
$change_list->setVisibleChangesets($changesets);
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
$change_list->setRenderingReferences($references);
|
|
|
|
$change_list->setRenderURI('/diffusion/'.$callsign.'/diff/');
|
2012-04-10 08:42:12 +02:00
|
|
|
$change_list->setRepository($repository);
|
2012-01-16 20:08:54 +01:00
|
|
|
$change_list->setUser($user);
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
|
2012-03-20 03:57:41 +01:00
|
|
|
$change_list->setStandaloneURI(
|
|
|
|
'/diffusion/'.$callsign.'/diff/');
|
|
|
|
$change_list->setRawFileURIs(
|
|
|
|
// TODO: Implement this, somewhat tricky if there's an octopus merge
|
|
|
|
// or whatever?
|
|
|
|
null,
|
|
|
|
'/diffusion/'.$callsign.'/diff/?view=r');
|
|
|
|
|
Add inline comments to Diffusion/Audit
Summary:
- Add inline comments to Audits, like Differential.
- Creates new storage for the comments in the Audits database.
- Creates a new PhabricatorAuditInlineComment class, similar to DifferentialInlineComment.
- Defines an Interface which Differential and Audit comments conform to.
- Makes consumers of DifferentialInlineComments consume objects which implement that interface instead.
- Adds save
NOTE: Some features are still missing! Wanted to cut this off before it got crazy:
- Inline comments aren't shown in the main comment list.
- Inline comments aren't shown in the emails.
- Inline comments aren't previewed.
I'll followup with those but this was getting pretty big.
@vrana, does the SQL change look correct?
Test Plan:
- Created, edited, deleted, replied to, reloaded and saved inline comments in Diffusion, on the left and right side of diffs.
- Created, edited, deleted, replied to, reloaded and saved inline comments in Differentila, on the left and right side of primary and diff-versus-diff diffs.
Reviewers: btrahan, vrana
Reviewed By: btrahan
CC: aran, epriestley
Maniphest Tasks: T904
Differential Revision: https://secure.phabricator.com/D1898
2012-03-14 20:56:01 +01:00
|
|
|
$change_list->setInlineCommentControllerURI(
|
|
|
|
'/diffusion/inline/'.phutil_escape_uri($commit->getPHID()).'/');
|
|
|
|
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
// TODO: This is pretty awkward, unify the CSS between Diffusion and
|
|
|
|
// Differential better.
|
|
|
|
require_celerity_resource('differential-core-view-css');
|
|
|
|
$change_list =
|
|
|
|
'<div class="differential-primary-pane">'.
|
|
|
|
$change_list->render().
|
|
|
|
'</div>';
|
|
|
|
|
2011-03-27 08:52:09 +02:00
|
|
|
$content[] = $change_list;
|
|
|
|
}
|
2011-03-14 00:19:39 +01:00
|
|
|
|
2012-03-26 18:44:06 +02:00
|
|
|
$content[] = $this->buildAddCommentView($commit, $audit_requests);
|
2012-02-25 00:04:53 +01:00
|
|
|
|
2011-03-11 18:34:22 +01:00
|
|
|
return $this->buildStandardPageResponse(
|
2011-03-14 00:19:39 +01:00
|
|
|
$content,
|
2011-03-11 18:34:22 +01:00
|
|
|
array(
|
2012-01-20 22:27:32 +01:00
|
|
|
'title' => 'r'.$callsign.$commit->getCommitIdentifier(),
|
2011-03-11 18:34:22 +01:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2012-03-30 23:12:10 +02:00
|
|
|
private function getCommitProperties(
|
2011-04-02 02:11:05 +02:00
|
|
|
PhabricatorRepositoryCommit $commit,
|
2012-03-26 21:21:48 +02:00
|
|
|
PhabricatorRepositoryCommitData $data,
|
|
|
|
array $parents) {
|
2012-04-04 01:22:31 +02:00
|
|
|
assert_instances_of($parents, 'PhabricatorRepositoryCommit');
|
2012-03-30 23:12:10 +02:00
|
|
|
$user = $this->getRequest()->getUser();
|
2011-04-02 02:11:05 +02:00
|
|
|
|
2012-04-05 02:34:25 +02:00
|
|
|
$task_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
|
|
|
|
$commit->getPHID(),
|
|
|
|
PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK);
|
|
|
|
|
|
|
|
$phids = $task_phids;
|
2011-04-02 02:11:05 +02:00
|
|
|
if ($data->getCommitDetail('authorPHID')) {
|
|
|
|
$phids[] = $data->getCommitDetail('authorPHID');
|
|
|
|
}
|
|
|
|
if ($data->getCommitDetail('reviewerPHID')) {
|
|
|
|
$phids[] = $data->getCommitDetail('reviewerPHID');
|
|
|
|
}
|
2012-05-23 17:34:36 +02:00
|
|
|
if ($data->getCommitDetail('committerPHID')) {
|
|
|
|
$phids[] = $data->getCommitDetail('committerPHID');
|
|
|
|
}
|
2011-04-02 02:11:05 +02:00
|
|
|
if ($data->getCommitDetail('differential.revisionPHID')) {
|
|
|
|
$phids[] = $data->getCommitDetail('differential.revisionPHID');
|
|
|
|
}
|
2012-03-26 21:21:48 +02:00
|
|
|
if ($parents) {
|
|
|
|
foreach ($parents as $parent) {
|
|
|
|
$phids[] = $parent->getPHID();
|
|
|
|
}
|
|
|
|
}
|
2011-04-02 02:11:05 +02:00
|
|
|
|
|
|
|
$handles = array();
|
|
|
|
if ($phids) {
|
|
|
|
$handles = id(new PhabricatorObjectHandleData($phids))
|
|
|
|
->loadHandles();
|
|
|
|
}
|
|
|
|
|
|
|
|
$props = array();
|
|
|
|
|
2012-03-30 23:12:10 +02:00
|
|
|
if ($commit->getAuditStatus()) {
|
|
|
|
$status = PhabricatorAuditCommitStatusConstants::getStatusName(
|
|
|
|
$commit->getAuditStatus());
|
|
|
|
$props['Status'] = phutil_render_tag(
|
|
|
|
'strong',
|
|
|
|
array(),
|
|
|
|
phutil_escape_html($status));
|
|
|
|
}
|
|
|
|
|
|
|
|
$props['Committed'] = phabricator_datetime($commit->getEpoch(), $user);
|
|
|
|
|
2011-04-02 02:11:05 +02:00
|
|
|
$author_phid = $data->getCommitDetail('authorPHID');
|
|
|
|
if ($data->getCommitDetail('authorPHID')) {
|
|
|
|
$props['Author'] = $handles[$author_phid]->renderLink();
|
|
|
|
} else {
|
|
|
|
$props['Author'] = phutil_escape_html($data->getAuthorName());
|
|
|
|
}
|
|
|
|
|
|
|
|
$reviewer_phid = $data->getCommitDetail('reviewerPHID');
|
|
|
|
$reviewer_name = $data->getCommitDetail('reviewerName');
|
|
|
|
if ($reviewer_phid) {
|
|
|
|
$props['Reviewer'] = $handles[$reviewer_phid]->renderLink();
|
|
|
|
} else if ($reviewer_name) {
|
|
|
|
$props['Reviewer'] = phutil_escape_html($reviewer_name);
|
|
|
|
}
|
|
|
|
|
2012-05-23 17:34:36 +02:00
|
|
|
$committer = $data->getCommitDetail('committer');
|
|
|
|
if ($committer) {
|
|
|
|
$committer_phid = $data->getCommitDetail('committerPHID');
|
|
|
|
if ($data->getCommitDetail('committerPHID')) {
|
|
|
|
$props['Committer'] = $handles[$committer_phid]->renderLink();
|
|
|
|
} else {
|
|
|
|
$props['Committer'] = phutil_escape_html($committer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-02 02:11:05 +02:00
|
|
|
$revision_phid = $data->getCommitDetail('differential.revisionPHID');
|
|
|
|
if ($revision_phid) {
|
|
|
|
$props['Differential Revision'] = $handles[$revision_phid]->renderLink();
|
|
|
|
}
|
|
|
|
|
2012-03-26 21:21:48 +02:00
|
|
|
if ($parents) {
|
|
|
|
$parent_links = array();
|
|
|
|
foreach ($parents as $parent) {
|
|
|
|
$parent_links[] = $handles[$parent->getPHID()]->renderLink();
|
|
|
|
}
|
|
|
|
$props['Parents'] = implode(' · ', $parent_links);
|
|
|
|
}
|
|
|
|
|
2012-04-05 02:34:25 +02:00
|
|
|
|
2012-01-19 20:49:51 +01:00
|
|
|
$request = $this->getDiffusionRequest();
|
|
|
|
|
2012-06-29 23:14:02 +02:00
|
|
|
$branches = $this->buildBranches($request);
|
2012-01-19 20:49:51 +01:00
|
|
|
if ($branches) {
|
|
|
|
$props['Branches'] = $branches;
|
|
|
|
}
|
|
|
|
|
2012-04-25 16:21:03 +02:00
|
|
|
$tags = $this->buildTags($request);
|
2012-04-24 03:36:25 +02:00
|
|
|
if ($tags) {
|
|
|
|
$props['Tags'] = $tags;
|
|
|
|
}
|
|
|
|
|
2012-04-25 16:21:03 +02:00
|
|
|
$refs = $this->buildRefs($request);
|
|
|
|
if ($refs) {
|
2012-06-29 23:14:02 +02:00
|
|
|
$props['References'] = $refs;
|
2012-04-25 16:21:03 +02:00
|
|
|
}
|
|
|
|
|
2012-04-05 02:34:25 +02:00
|
|
|
if ($task_phids) {
|
|
|
|
$task_list = array();
|
|
|
|
foreach ($task_phids as $phid) {
|
|
|
|
$task_list[] = $handles[$phid]->renderLink();
|
|
|
|
}
|
|
|
|
$task_list = implode('<br />', $task_list);
|
|
|
|
$props['Tasks'] = $task_list;
|
|
|
|
}
|
|
|
|
|
2012-03-30 23:12:10 +02:00
|
|
|
return $props;
|
2011-04-02 02:11:05 +02:00
|
|
|
}
|
|
|
|
|
2012-04-04 01:22:31 +02:00
|
|
|
private function buildAuditTable(
|
|
|
|
PhabricatorRepositoryCommit $commit,
|
|
|
|
array $audits) {
|
|
|
|
assert_instances_of($audits, 'PhabricatorRepositoryAuditRequest');
|
Allow Herald to trigger audits for users or projects
Summary:
Allows you to write a commit rule that triggers an audit by a user (personal
rules) or a project (global rules).
Mostly this is trying to make auditing more lightweight and accessible in
environments where setting up Owners packages doesn't make sense.
For instance, Disqus wants a rule like "trigger an audit for everything that
didn't have a Differential revision". While not necessarily scalable, this is a
perfectly reasonable rule for a small company, but a lot of work to implement
with Owners (and you'll get a lot of collateral damage if you don't make every
committer a project owner).
Instead, they can create a project called 'Unreviewed Commits' and write a rule
like:
- When: Differential revision does not exist
- Action: Trigger an Audit for project: "Unreviewed Commits"
Then whoever cares can join that project and they'll see those audits in their
queue, and when they approve/raise on commits their actions will affect the
project audit.
Similarly, if I want to look at all commits that match some other rule (say,
XSS) but only want to do it like once a month, I can just set up an audit rule
and go through the queue when I feel like it.
NOTE: This abuses the 'packagePHID' field to also store user and project PHIDs.
Through the magic of handles, this (apparently) works fine for now; I'll do a
big schema patch soon but have several other edits I want to make at the same
time.
Also:
- Adds an "active" fiew for /audit/, eventually this will be like the
Differential "active" view (stuff that is relevant to you right now).
- On commits, highlight triggered audits you are responsible for.
Test Plan: Added personal and global audit triggers to Herald, reparsed some
commits with --herald, got audits. Browsed all audit interfaces to make sure
nothing exploded. Viewed a commit where I was responsible for only some audits.
Performed audits and made sure the triggers I am supposed to be responsible for
updated properly.
Reviewers: btrahan, jungejason
Reviewed By: jungejason
CC: aran, epriestley
Maniphest Tasks: T904
Differential Revision: https://secure.phabricator.com/D1690
2012-02-27 18:36:30 +01:00
|
|
|
$user = $this->getRequest()->getUser();
|
|
|
|
|
2012-02-24 22:02:14 +01:00
|
|
|
$view = new PhabricatorAuditListView();
|
|
|
|
$view->setAudits($audits);
|
2012-03-26 18:44:06 +02:00
|
|
|
$view->setCommits(array($commit));
|
|
|
|
$view->setUser($user);
|
|
|
|
$view->setShowDescriptions(false);
|
2012-02-24 22:02:14 +01:00
|
|
|
|
|
|
|
$phids = $view->getRequiredHandlePHIDs();
|
|
|
|
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
|
|
|
$view->setHandles($handles);
|
2012-03-26 18:44:06 +02:00
|
|
|
$view->setAuthorityPHIDs($this->auditAuthorityPHIDs);
|
2012-02-24 22:02:14 +01:00
|
|
|
|
|
|
|
$panel = new AphrontPanelView();
|
|
|
|
$panel->setHeader('Audits');
|
2012-03-30 23:12:10 +02:00
|
|
|
$panel->setCaption('Audits you are responsible for are highlighted.');
|
2012-02-24 22:02:14 +01:00
|
|
|
$panel->appendChild($view);
|
|
|
|
|
|
|
|
return $panel;
|
|
|
|
}
|
|
|
|
|
2012-04-04 01:22:31 +02:00
|
|
|
private function buildComments(PhabricatorRepositoryCommit $commit) {
|
2012-02-24 23:14:39 +01:00
|
|
|
$user = $this->getRequest()->getUser();
|
|
|
|
$comments = id(new PhabricatorAuditComment())->loadAllWhere(
|
|
|
|
'targetPHID = %s ORDER BY dateCreated ASC',
|
|
|
|
$commit->getPHID());
|
|
|
|
|
2012-03-20 03:56:06 +01:00
|
|
|
$inlines = id(new PhabricatorAuditInlineComment())->loadAllWhere(
|
|
|
|
'commitPHID = %s AND auditCommentID IS NOT NULL',
|
|
|
|
$commit->getPHID());
|
|
|
|
|
|
|
|
$path_ids = mpull($inlines, 'getPathID');
|
|
|
|
|
|
|
|
$path_map = array();
|
|
|
|
if ($path_ids) {
|
|
|
|
$path_map = id(new DiffusionPathQuery())
|
|
|
|
->withPathIDs($path_ids)
|
|
|
|
->execute();
|
|
|
|
$path_map = ipull($path_map, 'path', 'id');
|
|
|
|
}
|
|
|
|
|
2012-02-24 23:14:39 +01:00
|
|
|
$view = new DiffusionCommentListView();
|
|
|
|
$view->setUser($user);
|
|
|
|
$view->setComments($comments);
|
2012-03-20 03:56:06 +01:00
|
|
|
$view->setInlineComments($inlines);
|
|
|
|
$view->setPathMap($path_map);
|
2012-02-24 23:14:39 +01:00
|
|
|
|
|
|
|
$phids = $view->getRequiredHandlePHIDs();
|
|
|
|
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
|
|
|
$view->setHandles($handles);
|
|
|
|
|
|
|
|
return $view;
|
|
|
|
}
|
|
|
|
|
2012-04-04 01:22:31 +02:00
|
|
|
private function buildAddCommentView(
|
|
|
|
PhabricatorRepositoryCommit $commit,
|
|
|
|
array $audit_requests) {
|
|
|
|
assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
|
2012-02-25 00:04:53 +01:00
|
|
|
$user = $this->getRequest()->getUser();
|
|
|
|
|
|
|
|
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
|
|
|
|
2012-03-19 03:44:28 +01:00
|
|
|
Javelin::initBehavior(
|
|
|
|
'differential-keyboard-navigation',
|
|
|
|
array(
|
|
|
|
// TODO: Make this comment panel hauntable
|
|
|
|
'haunt' => null,
|
|
|
|
));
|
|
|
|
|
2012-02-27 22:00:23 +01:00
|
|
|
$draft = id(new PhabricatorDraft())->loadOneWhere(
|
|
|
|
'authorPHID = %s AND draftKey = %s',
|
|
|
|
$user->getPHID(),
|
|
|
|
'diffusion-audit-'.$commit->getID());
|
|
|
|
if ($draft) {
|
|
|
|
$draft = $draft->getDraft();
|
|
|
|
} else {
|
|
|
|
$draft = null;
|
|
|
|
}
|
|
|
|
|
2012-03-26 18:44:06 +02:00
|
|
|
$actions = $this->getAuditActions($commit, $audit_requests);
|
|
|
|
|
2012-02-25 00:04:53 +01:00
|
|
|
$form = id(new AphrontFormView())
|
|
|
|
->setUser($user)
|
|
|
|
->setAction('/audit/addcomment/')
|
|
|
|
->addHiddenInput('commit', $commit->getPHID())
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSelectControl())
|
|
|
|
->setLabel('Action')
|
|
|
|
->setName('action')
|
2012-02-27 22:00:23 +01:00
|
|
|
->setID('audit-action')
|
2012-03-26 18:44:06 +02:00
|
|
|
->setOptions($actions))
|
2012-04-23 22:50:04 +02:00
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormTokenizerControl())
|
|
|
|
->setLabel('Add Auditors')
|
|
|
|
->setName('auditors')
|
|
|
|
->setControlID('add-auditors')
|
|
|
|
->setControlStyle('display: none')
|
|
|
|
->setID('add-auditors-tokenizer')
|
|
|
|
->setDisableBehavior(true))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormTokenizerControl())
|
|
|
|
->setLabel('Add CCs')
|
|
|
|
->setName('ccs')
|
|
|
|
->setControlID('add-ccs')
|
|
|
|
->setControlStyle('display: none')
|
|
|
|
->setID('add-ccs-tokenizer')
|
|
|
|
->setDisableBehavior(true))
|
2012-02-25 00:04:53 +01:00
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormTextAreaControl())
|
|
|
|
->setLabel('Comments')
|
|
|
|
->setName('content')
|
2012-02-27 22:00:23 +01:00
|
|
|
->setValue($draft)
|
|
|
|
->setID('audit-content')
|
2012-02-25 00:04:53 +01:00
|
|
|
->setCaption(phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => PhabricatorEnv::getDoclink(
|
|
|
|
'article/Remarkup_Reference.html'),
|
|
|
|
'tabindex' => '-1',
|
|
|
|
'target' => '_blank',
|
|
|
|
),
|
|
|
|
'Formatting Reference')))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSubmitControl())
|
|
|
|
->setValue($is_serious ? 'Submit' : 'Cook the Books'));
|
|
|
|
|
|
|
|
$panel = new AphrontPanelView();
|
|
|
|
$panel->setHeader($is_serious ? 'Audit Commit' : 'Creative Accounting');
|
|
|
|
$panel->appendChild($form);
|
|
|
|
|
2012-02-27 22:00:23 +01:00
|
|
|
require_celerity_resource('phabricator-transaction-view-css');
|
|
|
|
|
2012-04-23 22:50:04 +02:00
|
|
|
Javelin::initBehavior(
|
|
|
|
'differential-add-reviewers-and-ccs',
|
|
|
|
array(
|
|
|
|
'dynamic' => array(
|
|
|
|
'add-auditors-tokenizer' => array(
|
|
|
|
'actions' => array('add_auditors' => 1),
|
|
|
|
'src' => '/typeahead/common/users/',
|
|
|
|
'row' => 'add-auditors',
|
|
|
|
'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'),
|
|
|
|
'placeholder' => 'Type a user name...',
|
|
|
|
),
|
|
|
|
'add-ccs-tokenizer' => array(
|
|
|
|
'actions' => array('add_ccs' => 1),
|
|
|
|
'src' => '/typeahead/common/mailable/',
|
|
|
|
'row' => 'add-ccs',
|
|
|
|
'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'),
|
|
|
|
'placeholder' => 'Type a user or mailing list...',
|
|
|
|
),
|
|
|
|
),
|
|
|
|
'select' => 'audit-action',
|
|
|
|
));
|
|
|
|
|
|
|
|
Javelin::initBehavior('differential-feedback-preview', array(
|
2012-02-27 22:00:23 +01:00
|
|
|
'uri' => '/audit/preview/'.$commit->getID().'/',
|
|
|
|
'preview' => 'audit-preview',
|
|
|
|
'content' => 'audit-content',
|
|
|
|
'action' => 'audit-action',
|
2012-04-23 22:50:04 +02:00
|
|
|
'previewTokenizers' => array(
|
|
|
|
'auditors' => 'add-auditors-tokenizer',
|
|
|
|
'ccs' => 'add-ccs-tokenizer',
|
|
|
|
),
|
2012-02-27 22:00:23 +01:00
|
|
|
));
|
|
|
|
|
|
|
|
$preview_panel =
|
|
|
|
'<div class="aphront-panel-preview">
|
|
|
|
<div id="audit-preview">
|
|
|
|
<div class="aphront-panel-preview-loading-text">
|
|
|
|
Loading preview...
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>';
|
|
|
|
|
|
|
|
$view = new AphrontNullView();
|
|
|
|
$view->appendChild($panel);
|
|
|
|
$view->appendChild($preview_panel);
|
|
|
|
return $view;
|
2012-02-25 00:04:53 +01:00
|
|
|
}
|
|
|
|
|
2012-03-26 18:44:06 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a map of available audit actions for rendering into a <select />.
|
|
|
|
* This shows the user valid actions, and does not show nonsense/invalid
|
|
|
|
* actions (like closing an already-closed commit, or resigning from a commit
|
|
|
|
* you have no association with).
|
|
|
|
*/
|
|
|
|
private function getAuditActions(
|
|
|
|
PhabricatorRepositoryCommit $commit,
|
|
|
|
array $audit_requests) {
|
2012-04-04 01:22:31 +02:00
|
|
|
assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
|
2012-03-26 18:44:06 +02:00
|
|
|
$user = $this->getRequest()->getUser();
|
|
|
|
|
|
|
|
$user_is_author = ($commit->getAuthorPHID() == $user->getPHID());
|
|
|
|
|
|
|
|
$user_request = null;
|
|
|
|
foreach ($audit_requests as $audit_request) {
|
|
|
|
if ($audit_request->getAuditorPHID() == $user->getPHID()) {
|
|
|
|
$user_request = $audit_request;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$actions = array();
|
|
|
|
$actions[PhabricatorAuditActionConstants::COMMENT] = true;
|
2012-04-23 22:50:04 +02:00
|
|
|
$actions[PhabricatorAuditActionConstants::ADD_CCS] = true;
|
|
|
|
$actions[PhabricatorAuditActionConstants::ADD_AUDITORS] = true;
|
2012-03-26 18:44:06 +02:00
|
|
|
|
|
|
|
// We allow you to accept your own commits. A use case here is that you
|
|
|
|
// notice an issue with your own commit and "Raise Concern" as an indicator
|
|
|
|
// to other auditors that you're on top of the issue, then later resolve it
|
|
|
|
// and "Accept". You can not accept on behalf of projects or packages,
|
|
|
|
// however.
|
|
|
|
$actions[PhabricatorAuditActionConstants::ACCEPT] = true;
|
|
|
|
$actions[PhabricatorAuditActionConstants::CONCERN] = true;
|
|
|
|
|
|
|
|
|
|
|
|
// To resign, a user must have authority on some request and not be the
|
|
|
|
// commit's author.
|
|
|
|
if (!$user_is_author) {
|
|
|
|
$may_resign = false;
|
2012-05-07 22:37:41 +02:00
|
|
|
|
|
|
|
$authority_map = array_fill_keys($this->auditAuthorityPHIDs, true);
|
2012-03-26 18:44:06 +02:00
|
|
|
foreach ($audit_requests as $request) {
|
2012-05-07 22:37:41 +02:00
|
|
|
if (empty($authority_map[$request->getAuditorPHID()])) {
|
2012-03-26 18:44:06 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$may_resign = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the user has already resigned, don't show "Resign...".
|
|
|
|
$status_resigned = PhabricatorAuditStatusConstants::RESIGNED;
|
|
|
|
if ($user_request) {
|
|
|
|
if ($user_request->getAuditStatus() == $status_resigned) {
|
|
|
|
$may_resign = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($may_resign) {
|
|
|
|
$actions[PhabricatorAuditActionConstants::RESIGN] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$status_concern = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
|
|
|
|
$concern_raised = ($commit->getAuditStatus() == $status_concern);
|
|
|
|
|
|
|
|
if ($user_is_author && $concern_raised) {
|
|
|
|
$actions[PhabricatorAuditActionConstants::CLOSE] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($actions as $constant => $ignored) {
|
|
|
|
$actions[$constant] =
|
|
|
|
PhabricatorAuditActionConstants::getActionName($constant);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $actions;
|
|
|
|
}
|
|
|
|
|
2012-03-23 23:32:26 +01:00
|
|
|
private function buildMergesTable(PhabricatorRepositoryCommit $commit) {
|
|
|
|
$drequest = $this->getDiffusionRequest();
|
|
|
|
|
|
|
|
$limit = 50;
|
|
|
|
|
|
|
|
$merge_query = DiffusionMergedCommitsQuery::newFromDiffusionRequest(
|
|
|
|
$drequest);
|
|
|
|
$merge_query->setLimit($limit + 1);
|
|
|
|
$merges = $merge_query->loadMergedCommits();
|
|
|
|
|
|
|
|
if (!$merges) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$caption = null;
|
|
|
|
if (count($merges) > $limit) {
|
|
|
|
$merges = array_slice($merges, 0, $limit);
|
|
|
|
$caption =
|
|
|
|
"This commit merges more than {$limit} changes. Only the first ".
|
|
|
|
"{$limit} are shown.";
|
|
|
|
}
|
|
|
|
|
|
|
|
$history_table = new DiffusionHistoryTableView();
|
|
|
|
$history_table->setDiffusionRequest($drequest);
|
|
|
|
$history_table->setHistory($merges);
|
2012-06-23 01:52:08 +02:00
|
|
|
$history_table->loadRevisions();
|
2012-03-23 23:32:26 +01:00
|
|
|
|
|
|
|
$phids = $history_table->getRequiredHandlePHIDs();
|
|
|
|
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
|
|
|
$history_table->setHandles($handles);
|
|
|
|
|
|
|
|
$panel = new AphrontPanelView();
|
|
|
|
$panel->setHeader('Merged Changes');
|
|
|
|
$panel->setCaption($caption);
|
|
|
|
$panel->appendChild($history_table);
|
|
|
|
|
|
|
|
return $panel;
|
|
|
|
}
|
|
|
|
|
2012-03-30 23:12:10 +02:00
|
|
|
private function renderHeadsupActionList(
|
|
|
|
PhabricatorRepositoryCommit $commit) {
|
|
|
|
|
2012-05-02 22:43:45 +02:00
|
|
|
$request = $this->getRequest();
|
|
|
|
$user = $request->getUser();
|
2012-03-30 23:12:10 +02:00
|
|
|
|
|
|
|
$actions = array();
|
|
|
|
|
|
|
|
require_celerity_resource('phabricator-flag-css');
|
|
|
|
$flag = PhabricatorFlagQuery::loadUserFlag($user, $commit->getPHID());
|
|
|
|
if ($flag) {
|
|
|
|
$class = PhabricatorFlagColor::getCSSClass($flag->getColor());
|
|
|
|
$color = PhabricatorFlagColor::getColorName($flag->getColor());
|
|
|
|
|
|
|
|
$action = new AphrontHeadsupActionView();
|
|
|
|
$action->setClass('flag-clear '.$class);
|
|
|
|
$action->setURI('/flag/delete/'.$flag->getID().'/');
|
|
|
|
$action->setName('Remove '.$color.' Flag');
|
|
|
|
$action->setWorkflow(true);
|
|
|
|
$actions[] = $action;
|
|
|
|
} else {
|
|
|
|
$action = new AphrontHeadsupActionView();
|
|
|
|
$action->setClass('phabricator-flag-ghost');
|
|
|
|
$action->setURI('/flag/edit/'.$commit->getPHID().'/');
|
|
|
|
$action->setName('Flag Commit');
|
|
|
|
$action->setWorkflow(true);
|
|
|
|
$actions[] = $action;
|
|
|
|
}
|
|
|
|
|
|
|
|
require_celerity_resource('phabricator-object-selector-css');
|
|
|
|
require_celerity_resource('javelin-behavior-phabricator-object-selector');
|
|
|
|
|
|
|
|
$action = new AphrontHeadsupActionView();
|
|
|
|
$action->setName('Edit Maniphest Tasks');
|
2012-04-05 02:34:25 +02:00
|
|
|
$action->setURI('/search/attach/'.$commit->getPHID().'/TASK/edge/');
|
2012-03-30 23:12:10 +02:00
|
|
|
$action->setWorkflow(true);
|
|
|
|
$action->setClass('attach-maniphest');
|
|
|
|
$actions[] = $action;
|
|
|
|
|
|
|
|
if ($user->getIsAdmin()) {
|
|
|
|
$action = new AphrontHeadsupActionView();
|
|
|
|
$action->setName('MetaMTA Transcripts');
|
|
|
|
$action->setURI('/mail/?phid='.$commit->getPHID());
|
|
|
|
$action->setClass('transcripts-metamta');
|
|
|
|
$actions[] = $action;
|
|
|
|
}
|
|
|
|
|
|
|
|
$action = new AphrontHeadsupActionView();
|
|
|
|
$action->setName('Herald Transcripts');
|
|
|
|
$action->setURI('/herald/transcript/?phid='.$commit->getPHID());
|
|
|
|
$action->setClass('transcripts-herald');
|
|
|
|
$actions[] = $action;
|
|
|
|
|
2012-05-02 22:43:45 +02:00
|
|
|
$action = new AphrontHeadsupActionView();
|
|
|
|
$action->setName('Download Raw Diff');
|
|
|
|
$action->setURI($request->getRequestURI()->alter('diff', true));
|
|
|
|
$action->setClass('action-download');
|
|
|
|
$actions[] = $action;
|
|
|
|
|
2012-03-30 23:12:10 +02:00
|
|
|
$action_list = new AphrontHeadsupActionListView();
|
|
|
|
$action_list->setActions($actions);
|
|
|
|
|
|
|
|
return $action_list;
|
|
|
|
}
|
|
|
|
|
2012-06-29 23:14:02 +02:00
|
|
|
private function buildBranches(DiffusionRequest $request) {
|
|
|
|
|
|
|
|
$branch_query = DiffusionContainsQuery::newFromDiffusionRequest($request);
|
|
|
|
$branches = $branch_query->loadContainingBranches();
|
|
|
|
|
|
|
|
if (!$branches) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$branch_links = array();
|
|
|
|
foreach ($branches as $branch => $commit) {
|
|
|
|
$branch_links[] = phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $request->generateURI(
|
|
|
|
array(
|
|
|
|
'action' => 'browse',
|
|
|
|
'branch' => $branch,
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
phutil_escape_html($branch));
|
|
|
|
}
|
|
|
|
$branch_links = implode(', ', $branch_links);
|
|
|
|
return $branch_links;
|
|
|
|
}
|
|
|
|
|
2012-04-25 16:21:03 +02:00
|
|
|
private function buildTags(DiffusionRequest $request) {
|
2012-04-24 03:36:25 +02:00
|
|
|
$tag_limit = 10;
|
|
|
|
|
|
|
|
$tag_query = DiffusionCommitTagsQuery::newFromDiffusionRequest($request);
|
|
|
|
$tag_query->setLimit($tag_limit + 1);
|
|
|
|
$tags = $tag_query->loadTags();
|
|
|
|
|
|
|
|
if (!$tags) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$has_more_tags = (count($tags) > $tag_limit);
|
|
|
|
$tags = array_slice($tags, 0, $tag_limit);
|
|
|
|
|
|
|
|
$tag_links = array();
|
|
|
|
foreach ($tags as $tag) {
|
|
|
|
$tag_links[] = phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $request->generateURI(
|
|
|
|
array(
|
|
|
|
'action' => 'browse',
|
|
|
|
'commit' => $tag->getName(),
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
phutil_escape_html($tag->getName()));
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($has_more_tags) {
|
|
|
|
$tag_links[] = phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $request->generateURI(
|
|
|
|
array(
|
|
|
|
'action' => 'tags',
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
"More tags\xE2\x80\xA6");
|
|
|
|
}
|
|
|
|
|
|
|
|
$tag_links = implode(', ', $tag_links);
|
|
|
|
|
|
|
|
return $tag_links;
|
|
|
|
}
|
2012-03-23 23:32:26 +01:00
|
|
|
|
2012-04-25 16:21:03 +02:00
|
|
|
private function buildRefs(DiffusionRequest $request) {
|
|
|
|
// Not turning this into a proper Query class since it's pretty simple,
|
|
|
|
// one-off, and Git-specific.
|
|
|
|
|
|
|
|
$type_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
|
|
|
|
|
|
|
|
$repository = $request->getRepository();
|
|
|
|
if ($repository->getVersionControlSystem() != $type_git) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
list($stdout) = $repository->execxLocalCommand(
|
|
|
|
'log --format=%s -n 1 %s --',
|
|
|
|
'%d',
|
|
|
|
$request->getCommit());
|
|
|
|
|
2012-06-29 23:14:02 +02:00
|
|
|
// %d, gives a weird output format
|
|
|
|
// similar to (remote/one, remote/two, remote/three)
|
|
|
|
$refs = trim($stdout, "() \n");
|
|
|
|
$refs = explode(',', $refs);
|
|
|
|
$refs = array_map('trim', $refs);
|
|
|
|
|
|
|
|
$ref_links = array();
|
|
|
|
foreach ($refs as $ref) {
|
|
|
|
$ref_links[] = phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $request->generateURI(
|
|
|
|
array(
|
|
|
|
'action' => 'browse',
|
|
|
|
'branch' => $ref,
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
phutil_escape_html($ref));
|
|
|
|
}
|
|
|
|
$ref_links = implode(', ', $ref_links);
|
|
|
|
return $ref_links;
|
2012-04-25 16:21:03 +02:00
|
|
|
}
|
|
|
|
|
2012-05-02 22:43:45 +02:00
|
|
|
private function buildRawDiffResponse(DiffusionRequest $drequest) {
|
|
|
|
$raw_query = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest);
|
|
|
|
$raw_diff = $raw_query->loadRawDiff();
|
|
|
|
|
|
|
|
$hash = PhabricatorHash::digest($raw_diff);
|
|
|
|
|
|
|
|
$file = id(new PhabricatorFile())->loadOneWhere(
|
|
|
|
'contentHash = %s LIMIT 1',
|
|
|
|
$hash);
|
|
|
|
if (!$file) {
|
|
|
|
// We're just caching the data; this is always safe.
|
|
|
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
|
|
|
|
|
|
|
$file = PhabricatorFile::newFromFileData(
|
|
|
|
$raw_diff,
|
|
|
|
array(
|
|
|
|
'name' => $drequest->getCommit().'.diff',
|
|
|
|
));
|
|
|
|
|
|
|
|
unset($unguarded);
|
|
|
|
}
|
|
|
|
|
|
|
|
return id(new AphrontRedirectResponse())->setURI($file->getBestURI());
|
|
|
|
}
|
|
|
|
|
2011-03-11 18:34:22 +01:00
|
|
|
}
|