Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2890574
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
74 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/applications/diffusion/controller/DiffusionBranchTableController.php b/src/applications/diffusion/controller/DiffusionBranchTableController.php
index 388eb9d568..4f0c494110 100644
--- a/src/applications/diffusion/controller/DiffusionBranchTableController.php
+++ b/src/applications/diffusion/controller/DiffusionBranchTableController.php
@@ -1,74 +1,74 @@
<?php
final class DiffusionBranchTableController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
protected function processDiffusionRequest(AphrontRequest $request) {
$drequest = $this->getDiffusionRequest();
$viewer = $request->getUser();
$repository = $drequest->getRepository();
$pager = new AphrontPagerView();
$pager->setURI($request->getRequestURI(), 'offset');
$pager->setOffset($request->getInt('offset'));
// TODO: Add support for branches that contain commit
$branches = $this->callConduitWithDiffusionRequest(
'diffusion.branchquery',
array(
'offset' => $pager->getOffset(),
'limit' => $pager->getPageSize() + 1,
));
$branches = $pager->sliceResults($branches);
$branches = DiffusionRepositoryRef::loadAllFromDictionaries($branches);
$content = null;
if (!$branches) {
$content = $this->renderStatusMessage(
pht('No Branches'),
pht('This repository has no branches.'));
} else {
$commits = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withIdentifiers(mpull($branches, 'getCommitIdentifier'))
->withRepository($repository)
->execute();
$view = id(new DiffusionBranchTableView())
->setUser($viewer)
->setBranches($branches)
->setCommits($commits)
->setDiffusionRequest($drequest);
- $panel = id(new AphrontPanelView())
- ->setNoBackground(true)
- ->appendChild($view)
- ->appendChild($pager);
+ $panel = id(new PHUIObjectBoxView())
+ ->setHeaderText(pht('Branches'))
+ ->appendChild($view);
$content = $panel;
}
$crumbs = $this->buildCrumbs(
array(
'branches' => true,
));
return $this->buildApplicationPage(
array(
$crumbs,
$content,
+ $pager,
),
array(
'title' => array(
pht('Branches'),
'r'.$repository->getCallsign(),
),
));
}
}
diff --git a/src/applications/diffusion/controller/DiffusionBrowseDirectoryController.php b/src/applications/diffusion/controller/DiffusionBrowseDirectoryController.php
index 2be77a134e..833e108648 100644
--- a/src/applications/diffusion/controller/DiffusionBrowseDirectoryController.php
+++ b/src/applications/diffusion/controller/DiffusionBrowseDirectoryController.php
@@ -1,106 +1,106 @@
<?php
final class DiffusionBrowseDirectoryController
extends DiffusionBrowseController {
private $browseQueryResults;
public function setBrowseQueryResults(DiffusionBrowseResultSet $results) {
$this->browseQueryResults = $results;
return $this;
}
public function getBrowseQueryResults() {
return $this->browseQueryResults;
}
protected function processDiffusionRequest(AphrontRequest $request) {
$drequest = $this->diffusionRequest;
$results = $this->getBrowseQueryResults();
$reason = $results->getReasonForEmptyResultSet();
$content = array();
$actions = $this->buildActionView($drequest);
$properties = $this->buildPropertyView($drequest, $actions);
$object_box = id(new PHUIObjectBoxView())
->setHeader($this->buildHeaderView($drequest))
->addPropertyList($properties);
$content[] = $object_box;
$content[] = $this->renderSearchForm($collapsed = true);
if (!$results->isValidResults()) {
$empty_result = new DiffusionEmptyResultView();
$empty_result->setDiffusionRequest($drequest);
$empty_result->setDiffusionBrowseResultSet($results);
$empty_result->setView($request->getStr('view'));
$content[] = $empty_result;
} else {
$phids = array();
foreach ($results->getPaths() as $result) {
$data = $result->getLastCommitData();
if ($data) {
if ($data->getCommitDetail('authorPHID')) {
$phids[$data->getCommitDetail('authorPHID')] = true;
}
}
}
$phids = array_keys($phids);
$handles = $this->loadViewerHandles($phids);
$browse_table = new DiffusionBrowseTableView();
$browse_table->setDiffusionRequest($drequest);
$browse_table->setHandles($handles);
$browse_table->setPaths($results->getPaths());
$browse_table->setUser($request->getUser());
- $browse_panel = new AphrontPanelView();
+ $browse_panel = new PHUIObjectBoxView();
+ $browse_panel->setHeaderText($drequest->getPath(), '/');
$browse_panel->appendChild($browse_table);
- $browse_panel->setNoBackground();
$content[] = $browse_panel;
}
$content[] = $this->buildOpenRevisions();
$readme_path = $results->getReadmePath();
if ($readme_path) {
$readme_content = $this->callConduitWithDiffusionRequest(
'diffusion.filecontentquery',
array(
'path' => $readme_path,
'commit' => $drequest->getStableCommit(),
));
if ($readme_content) {
$content[] = id(new DiffusionReadmeView())
->setUser($this->getViewer())
->setPath($readme_path)
->setContent($readme_content['corpus']);
}
}
$crumbs = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'browse',
));
return $this->buildApplicationPage(
array(
$crumbs,
$content,
),
array(
'title' => array(
nonempty(basename($drequest->getPath()), '/'),
$drequest->getRepository()->getCallsign().' Repository',
),
));
}
}
diff --git a/src/applications/diffusion/controller/DiffusionCommitController.php b/src/applications/diffusion/controller/DiffusionCommitController.php
index 01a96a6456..d55fdfbdf4 100644
--- a/src/applications/diffusion/controller/DiffusionCommitController.php
+++ b/src/applications/diffusion/controller/DiffusionCommitController.php
@@ -1,1081 +1,1084 @@
<?php
final class DiffusionCommitController extends DiffusionController {
const CHANGES_LIMIT = 100;
private $auditAuthorityPHIDs;
private $highlightedAudits;
public function shouldAllowPublic() {
return true;
}
protected function shouldLoadDiffusionRequest() {
return false;
}
protected function processDiffusionRequest(AphrontRequest $request) {
$user = $request->getUser();
// This controller doesn't use blob/path stuff, just pass the dictionary
// in directly instead of using the AphrontRequest parsing mechanism.
$data = $request->getURIMap();
$data['user'] = $user;
$drequest = DiffusionRequest::newFromDictionary($data);
$this->diffusionRequest = $drequest;
if ($request->getStr('diff')) {
return $this->buildRawDiffResponse($drequest);
}
$repository = $drequest->getRepository();
$callsign = $repository->getCallsign();
$content = array();
$commit = id(new DiffusionCommitQuery())
->setViewer($request->getUser())
->withRepository($repository)
->withIdentifiers(array($drequest->getCommit()))
->needCommitData(true)
->needAuditRequests(true)
->executeOne();
$crumbs = $this->buildCrumbs(array(
'commit' => true,
));
if (!$commit) {
$exists = $this->callConduitWithDiffusionRequest(
'diffusion.existsquery',
array('commit' => $drequest->getCommit()));
if (!$exists) {
return new Aphront404Response();
}
$error = id(new PHUIInfoView())
->setTitle(pht('Commit Still Parsing'))
->appendChild(
pht(
'Failed to load the commit because the commit has not been '.
'parsed yet.'));
return $this->buildApplicationPage(
array(
$crumbs,
$error,
),
array(
'title' => pht('Commit Still Parsing'),
));
}
$audit_requests = $commit->getAudits();
$this->auditAuthorityPHIDs =
PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
$commit_data = $commit->getCommitData();
$is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
$changesets = null;
if ($is_foreign) {
$subpath = $commit_data->getCommitDetail('svn-subpath');
$error_panel = new PHUIInfoView();
$error_panel->setTitle(pht('Commit Not Tracked'));
$error_panel->setSeverity(PHUIInfoView::SEVERITY_WARNING);
$error_panel->appendChild(
pht("This Diffusion repository is configured to track only one ".
"subdirectory of the entire Subversion repository, and this commit ".
"didn't affect the tracked subdirectory ('%s'), so no ".
"information is available.", $subpath));
$content[] = $error_panel;
} else {
$engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
$engine->setConfig('viewer', $user);
require_celerity_resource('phabricator-remarkup-css');
$parents = $this->callConduitWithDiffusionRequest(
'diffusion.commitparentsquery',
array('commit' => $drequest->getCommit()));
if ($parents) {
$parents = id(new DiffusionCommitQuery())
->setViewer($user)
->withRepository($repository)
->withIdentifiers($parents)
->execute();
}
$headsup_view = id(new PHUIHeaderView())
->setHeader(nonempty($commit->getSummary(), pht('Commit Detail')));
$headsup_actions = $this->renderHeadsupActionList($commit, $repository);
$commit_properties = $this->loadCommitProperties(
$commit,
$commit_data,
$parents,
$audit_requests);
$property_list = id(new PHUIPropertyListView())
->setHasKeyboardShortcuts(true)
->setUser($user)
->setObject($commit);
foreach ($commit_properties as $key => $value) {
$property_list->addProperty($key, $value);
}
$message = $commit_data->getCommitMessage();
$revision = $commit->getCommitIdentifier();
$message = $this->linkBugtraq($message);
$message = $engine->markupText($message);
$property_list->invokeWillRenderEvent();
$property_list->setActionList($headsup_actions);
$detail_list = new PHUIPropertyListView();
$detail_list->addSectionHeader(
pht('Description'),
PHUIPropertyListView::ICON_SUMMARY);
$detail_list->addTextContent(
phutil_tag(
'div',
array(
'class' => 'diffusion-commit-message phabricator-remarkup',
),
$message));
$object_box = id(new PHUIObjectBoxView())
->setHeader($headsup_view)
->addPropertyList($property_list)
->addPropertyList($detail_list);
$content[] = $object_box;
}
$content[] = $this->buildComments($commit);
$hard_limit = 1000;
if ($commit->isImported()) {
$change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
$drequest);
$change_query->setLimit($hard_limit + 1);
$changes = $change_query->loadChanges();
} else {
$changes = array();
}
$was_limited = (count($changes) > $hard_limit);
if ($was_limited) {
$changes = array_slice($changes, 0, $hard_limit);
}
$content[] = $this->buildMergesTable($commit);
$highlighted_audits = $commit->getAuthorityAudits(
$user,
$this->auditAuthorityPHIDs);
$owners_paths = array();
if ($highlighted_audits) {
$packages = id(new PhabricatorOwnersPackage())->loadAllWhere(
'phid IN (%Ls)',
mpull($highlighted_audits, 'getAuditorPHID'));
if ($packages) {
$owners_paths = id(new PhabricatorOwnersPath())->loadAllWhere(
'repositoryPHID = %s AND packageID IN (%Ld)',
$repository->getPHID(),
mpull($packages, 'getID'));
}
}
$change_table = new DiffusionCommitChangeTableView();
$change_table->setDiffusionRequest($drequest);
$change_table->setPathChanges($changes);
$change_table->setOwnersPaths($owners_paths);
$count = count($changes);
$bad_commit = null;
if ($count == 0) {
$bad_commit = queryfx_one(
id(new PhabricatorRepository())->establishConnection('r'),
'SELECT * FROM %T WHERE fullCommitName = %s',
PhabricatorRepository::TABLE_BADCOMMIT,
'r'.$callsign.$commit->getCommitIdentifier());
}
if ($bad_commit) {
$content[] = $this->renderStatusMessage(
pht('Bad Commit'),
$bad_commit['description']);
} else if ($is_foreign) {
// Don't render anything else.
} else if (!$commit->isImported()) {
$content[] = $this->renderStatusMessage(
pht('Still Importing...'),
pht(
'This commit is still importing. Changes will be visible once '.
'the import finishes.'));
} else if (!count($changes)) {
$content[] = $this->renderStatusMessage(
pht('Empty Commit'),
pht(
'This commit is empty and does not affect any paths.'));
} else if ($was_limited) {
$content[] = $this->renderStatusMessage(
pht('Enormous Commit'),
pht(
'This commit is enormous, and affects more than %d files. '.
'Changes are not shown.',
$hard_limit));
} else {
// The user has clicked "Show All Changes", and we should show all the
// changes inline even if there are more than the soft limit.
$show_all_details = $request->getBool('show_all');
$change_panel = new PHUIObjectBoxView();
$header = new PHUIHeaderView();
$header->setHeader('Changes ('.number_format($count).')');
$change_panel->setID('toc');
if ($count > self::CHANGES_LIMIT && !$show_all_details) {
$icon = id(new PHUIIconView())
->setIconFont('fa-files-o');
$button = id(new PHUIButtonView())
->setText(pht('Show All Changes'))
->setHref('?show_all=true')
->setTag('a')
->setIcon($icon);
$warning_view = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
->setTitle('Very Large Commit')
->appendChild(
pht('This commit is very large. Load each file individually.'));
$change_panel->setErrorView($warning_view);
$header->addActionLink($button);
}
$change_panel->appendChild($change_table);
$change_panel->setHeader($header);
$content[] = $change_panel;
$changesets = DiffusionPathChange::convertToDifferentialChangesets(
$user,
$changes);
$vcs = $repository->getVersionControlSystem();
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$vcs_supports_directory_changes = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$vcs_supports_directory_changes = false;
break;
default:
throw new Exception('Unknown VCS.');
}
$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;
}
}
$references[$key] = $drequest->generateURI(
array(
'action' => 'rendering-ref',
'path' => $changeset->getFilename(),
));
}
// TODO: Some parts of the views still rely on properties of the
// 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).
$path_ids = array_flip(mpull($changes, 'getPath'));
foreach ($changesets as $changeset) {
$changeset->makeEphemeral();
$changeset->setID($path_ids[$changeset->getFilename()]);
}
if ($count <= self::CHANGES_LIMIT || $show_all_details) {
$visible_changesets = $changesets;
} else {
$visible_changesets = array();
$inlines = PhabricatorAuditInlineComment::loadDraftAndPublishedComments(
$user,
$commit->getPHID());
$path_ids = mpull($inlines, null, 'getPathID');
foreach ($changesets as $key => $changeset) {
if (array_key_exists($changeset->getID(), $path_ids)) {
$visible_changesets[$key] = $changeset;
}
}
}
$change_list_title = DiffusionView::nameCommit(
$repository,
$commit->getCommitIdentifier());
$change_list = new DifferentialChangesetListView();
$change_list->setTitle($change_list_title);
$change_list->setChangesets($changesets);
$change_list->setVisibleChangesets($visible_changesets);
$change_list->setRenderingReferences($references);
$change_list->setRenderURI('/diffusion/'.$callsign.'/diff/');
$change_list->setRepository($repository);
$change_list->setUser($user);
// TODO: Try to setBranch() to something reasonable here?
$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');
$change_list->setInlineCommentControllerURI(
'/diffusion/inline/edit/'.phutil_escape_uri($commit->getPHID()).'/');
$change_references = array();
foreach ($changesets as $key => $changeset) {
$change_references[$changeset->getID()] = $references[$key];
}
$change_table->setRenderingReferences($change_references);
$content[] = $change_list->render();
}
$content[] = $this->renderAddCommentPanel($commit, $audit_requests);
$commit_id = 'r'.$callsign.$commit->getCommitIdentifier();
$short_name = DiffusionView::nameCommit(
$repository,
$commit->getCommitIdentifier());
$prefs = $user->loadPreferences();
$pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE;
$pref_collapse = PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED;
$show_filetree = $prefs->getPreference($pref_filetree);
$collapsed = $prefs->getPreference($pref_collapse);
if ($changesets && $show_filetree) {
$nav = id(new DifferentialChangesetFileTreeSideNavBuilder())
->setTitle($short_name)
->setBaseURI(new PhutilURI('/'.$commit_id))
->build($changesets)
->setCrumbs($crumbs)
->setCollapsed((bool)$collapsed)
->appendChild($content);
$content = $nav;
} else {
$content = array($crumbs, $content);
}
return $this->buildApplicationPage(
$content,
array(
'title' => $commit_id,
'pageObjects' => array($commit->getPHID()),
));
}
private function loadCommitProperties(
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $data,
array $parents,
array $audit_requests) {
assert_instances_of($parents, 'PhabricatorRepositoryCommit');
$viewer = $this->getRequest()->getUser();
$commit_phid = $commit->getPHID();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array($commit_phid))
->withEdgeTypes(array(
DiffusionCommitHasTaskEdgeType::EDGECONST,
DiffusionCommitHasRevisionEdgeType::EDGECONST,
DiffusionCommitRevertsCommitEdgeType::EDGECONST,
DiffusionCommitRevertedByCommitEdgeType::EDGECONST,
));
$edges = $edge_query->execute();
$task_phids = array_keys(
$edges[$commit_phid][DiffusionCommitHasTaskEdgeType::EDGECONST]);
$revision_phid = key(
$edges[$commit_phid][DiffusionCommitHasRevisionEdgeType::EDGECONST]);
$reverts_phids = array_keys(
$edges[$commit_phid][DiffusionCommitRevertsCommitEdgeType::EDGECONST]);
$reverted_by_phids = array_keys(
$edges[$commit_phid][DiffusionCommitRevertedByCommitEdgeType::EDGECONST]);
$phids = $edge_query->getDestinationPHIDs(array($commit_phid));
if ($data->getCommitDetail('authorPHID')) {
$phids[] = $data->getCommitDetail('authorPHID');
}
if ($data->getCommitDetail('reviewerPHID')) {
$phids[] = $data->getCommitDetail('reviewerPHID');
}
if ($data->getCommitDetail('committerPHID')) {
$phids[] = $data->getCommitDetail('committerPHID');
}
if ($parents) {
foreach ($parents as $parent) {
$phids[] = $parent->getPHID();
}
}
// NOTE: We should never normally have more than a single push log, but
// it can occur naturally if a commit is pushed, then the branch it was
// on is deleted, then the commit is pushed again (or through other similar
// chains of events). This should be rare, but does not indicate a bug
// or data issue.
// NOTE: We never query push logs in SVN because the commiter is always
// the pusher and the commit time is always the push time; the push log
// is redundant and we save a query by skipping it.
$push_logs = array();
if ($repository->isHosted() && !$repository->isSVN()) {
$push_logs = id(new PhabricatorRepositoryPushLogQuery())
->setViewer($viewer)
->withRepositoryPHIDs(array($repository->getPHID()))
->withNewRefs(array($commit->getCommitIdentifier()))
->withRefTypes(array(PhabricatorRepositoryPushLog::REFTYPE_COMMIT))
->execute();
foreach ($push_logs as $log) {
$phids[] = $log->getPusherPHID();
}
}
$handles = array();
if ($phids) {
$handles = $this->loadViewerHandles($phids);
}
$props = array();
if ($commit->getAuditStatus()) {
$status = PhabricatorAuditCommitStatusConstants::getStatusName(
$commit->getAuditStatus());
$tag = id(new PHUITagView())
->setType(PHUITagView::TYPE_STATE)
->setName($status);
switch ($commit->getAuditStatus()) {
case PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT:
$tag->setBackgroundColor(PHUITagView::COLOR_ORANGE);
break;
case PhabricatorAuditCommitStatusConstants::CONCERN_RAISED:
$tag->setBackgroundColor(PHUITagView::COLOR_RED);
break;
case PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED:
$tag->setBackgroundColor(PHUITagView::COLOR_BLUE);
break;
case PhabricatorAuditCommitStatusConstants::FULLY_AUDITED:
$tag->setBackgroundColor(PHUITagView::COLOR_GREEN);
break;
}
$props['Status'] = $tag;
}
if ($audit_requests) {
$user_requests = array();
$other_requests = array();
foreach ($audit_requests as $audit_request) {
if ($audit_request->isUser()) {
$user_requests[] = $audit_request;
} else {
$other_requests[] = $audit_request;
}
}
if ($user_requests) {
$props['Auditors'] = $this->renderAuditStatusView(
$user_requests);
}
if ($other_requests) {
$props['Project/Package Auditors'] = $this->renderAuditStatusView(
$other_requests);
}
}
$author_phid = $data->getCommitDetail('authorPHID');
$author_name = $data->getAuthorName();
if (!$repository->isSVN()) {
$authored_info = id(new PHUIStatusItemView());
// TODO: In Git, a distinct authorship date is available. When present,
// we should show it here.
if ($author_phid) {
$authored_info->setTarget($handles[$author_phid]->renderLink());
} else if (strlen($author_name)) {
$authored_info->setTarget($author_name);
}
$props['Authored'] = id(new PHUIStatusListView())
->addItem($authored_info);
}
$committed_info = id(new PHUIStatusItemView())
->setNote(phabricator_datetime($commit->getEpoch(), $viewer));
$committer_phid = $data->getCommitDetail('committerPHID');
$committer_name = $data->getCommitDetail('committer');
if ($committer_phid) {
$committed_info->setTarget($handles[$committer_phid]->renderLink());
} else if (strlen($committer_name)) {
$committed_info->setTarget($committer_name);
} else if ($author_phid) {
$committed_info->setTarget($handles[$author_phid]->renderLink());
} else if (strlen($author_name)) {
$committed_info->setTarget($author_name);
}
$props['Committed'] = id(new PHUIStatusListView())
->addItem($committed_info);
if ($push_logs) {
$pushed_list = new PHUIStatusListView();
foreach ($push_logs as $push_log) {
$pushed_item = id(new PHUIStatusItemView())
->setTarget($handles[$push_log->getPusherPHID()]->renderLink())
->setNote(phabricator_datetime($push_log->getEpoch(), $viewer));
$pushed_list->addItem($pushed_item);
}
$props['Pushed'] = $pushed_list;
}
$reviewer_phid = $data->getCommitDetail('reviewerPHID');
if ($reviewer_phid) {
$props['Reviewer'] = $handles[$reviewer_phid]->renderLink();
}
if ($revision_phid) {
$props['Differential Revision'] = $handles[$revision_phid]->renderLink();
}
if ($parents) {
$parent_links = array();
foreach ($parents as $parent) {
$parent_links[] = $handles[$parent->getPHID()]->renderLink();
}
$props['Parents'] = phutil_implode_html(" \xC2\xB7 ", $parent_links);
}
$props['Branches'] = phutil_tag(
'span',
array(
'id' => 'commit-branches',
),
pht('Unknown'));
$props['Tags'] = phutil_tag(
'span',
array(
'id' => 'commit-tags',
),
pht('Unknown'));
$callsign = $repository->getCallsign();
$root = '/diffusion/'.$callsign.'/commit/'.$commit->getCommitIdentifier();
Javelin::initBehavior(
'diffusion-commit-branches',
array(
$root.'/branches/' => 'commit-branches',
$root.'/tags/' => 'commit-tags',
));
$refs = $this->buildRefs($drequest);
if ($refs) {
$props['References'] = $refs;
}
if ($reverts_phids) {
$this->loadHandles($reverts_phids);
$props[pht('Reverts')] = $this->renderHandlesForPHIDs($reverts_phids);
}
if ($reverted_by_phids) {
$this->loadHandles($reverted_by_phids);
$props[pht('Reverted By')] = $this->renderHandlesForPHIDs(
$reverted_by_phids);
}
if ($task_phids) {
$task_list = array();
foreach ($task_phids as $phid) {
$task_list[] = $handles[$phid]->renderLink();
}
$task_list = phutil_implode_html(phutil_tag('br'), $task_list);
$props['Tasks'] = $task_list;
}
return $props;
}
private function buildComments(PhabricatorRepositoryCommit $commit) {
$timeline = $this->buildTransactionTimeline(
$commit,
new PhabricatorAuditTransactionQuery());
$commit->willRenderTimeline($timeline, $this->getRequest());
return $timeline;
}
private function renderAddCommentPanel(
PhabricatorRepositoryCommit $commit,
array $audit_requests) {
assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
$request = $this->getRequest();
$user = $request->getUser();
if (!$user->isLoggedIn()) {
return id(new PhabricatorApplicationTransactionCommentView())
->setUser($user)
->setRequestURI($request->getRequestURI());
}
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
$pane_id = celerity_generate_unique_node_id();
Javelin::initBehavior(
'differential-keyboard-navigation',
array(
'haunt' => $pane_id,
));
$draft = id(new PhabricatorDraft())->loadOneWhere(
'authorPHID = %s AND draftKey = %s',
$user->getPHID(),
'diffusion-audit-'.$commit->getID());
if ($draft) {
$draft = $draft->getDraft();
} else {
$draft = null;
}
$actions = $this->getAuditActions($commit, $audit_requests);
$form = id(new AphrontFormView())
->setUser($user)
->setAction('/audit/addcomment/')
->addHiddenInput('commit', $commit->getPHID())
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Action'))
->setName('action')
->setID('audit-action')
->setOptions($actions))
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Add Auditors'))
->setName('auditors')
->setControlID('add-auditors')
->setControlStyle('display: none')
->setID('add-auditors-tokenizer')
->setDisableBehavior(true))
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Add CCs'))
->setName('ccs')
->setControlID('add-ccs')
->setControlStyle('display: none')
->setID('add-ccs-tokenizer')
->setDisableBehavior(true))
->appendChild(
id(new PhabricatorRemarkupControl())
->setLabel(pht('Comments'))
->setName('content')
->setValue($draft)
->setID('audit-content')
->setUser($user))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Submit')));
$header = new PHUIHeaderView();
$header->setHeader(
$is_serious ? pht('Audit Commit') : pht('Creative Accounting'));
require_celerity_resource('phabricator-transaction-view-css');
$mailable_source = new PhabricatorMetaMTAMailableDatasource();
$auditor_source = new DiffusionAuditorDatasource();
Javelin::initBehavior(
'differential-add-reviewers-and-ccs',
array(
'dynamic' => array(
'add-auditors-tokenizer' => array(
'actions' => array('add_auditors' => 1),
'src' => $auditor_source->getDatasourceURI(),
'row' => 'add-auditors',
'placeholder' => $auditor_source->getPlaceholderText(),
),
'add-ccs-tokenizer' => array(
'actions' => array('add_ccs' => 1),
'src' => $mailable_source->getDatasourceURI(),
'row' => 'add-ccs',
'placeholder' => $mailable_source->getPlaceholderText(),
),
),
'select' => 'audit-action',
));
Javelin::initBehavior('differential-feedback-preview', array(
'uri' => '/audit/preview/'.$commit->getID().'/',
'preview' => 'audit-preview',
'content' => 'audit-content',
'action' => 'audit-action',
'previewTokenizers' => array(
'auditors' => 'add-auditors-tokenizer',
'ccs' => 'add-ccs-tokenizer',
),
'inline' => 'inline-comment-preview',
'inlineuri' => '/diffusion/inline/preview/'.$commit->getPHID().'/',
));
$loading = phutil_tag_div(
'aphront-panel-preview-loading-text',
pht('Loading preview...'));
$preview_panel = phutil_tag_div(
'aphront-panel-preview aphront-panel-flush',
array(
phutil_tag('div', array('id' => 'audit-preview'), $loading),
phutil_tag('div', array('id' => 'inline-comment-preview')),
));
// TODO: This is pretty awkward, unify the CSS between Diffusion and
// Differential better.
require_celerity_resource('differential-core-view-css');
$anchor = id(new PhabricatorAnchorView())
->setAnchorName('comment')
->setNavigationMarker(true)
->render();
$comment_box = id(new PHUIObjectBoxView())
->setHeader($header)
->appendChild($form);
return phutil_tag(
'div',
array(
'id' => $pane_id,
),
phutil_tag_div(
'differential-add-comment-panel',
array($anchor, $comment_box, $preview_panel)));
}
/**
* 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) {
assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
$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;
$actions[PhabricatorAuditActionConstants::ADD_CCS] = true;
$actions[PhabricatorAuditActionConstants::ADD_AUDITORS] = true;
// 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;
$authority_map = array_fill_keys($this->auditAuthorityPHIDs, true);
foreach ($audit_requests as $request) {
if (empty($authority_map[$request->getAuditorPHID()])) {
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);
$can_close_option = PhabricatorEnv::getEnvConfig(
'audit.can-author-close-audit');
if ($can_close_option && $user_is_author && $concern_raised) {
$actions[PhabricatorAuditActionConstants::CLOSE] = true;
}
foreach ($actions as $constant => $ignored) {
$actions[$constant] =
PhabricatorAuditActionConstants::getActionName($constant);
}
return $actions;
}
private function buildMergesTable(PhabricatorRepositoryCommit $commit) {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$vcs = $repository->getVersionControlSystem();
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
// These aren't supported under SVN.
return null;
}
$limit = 50;
$merges = $this->callConduitWithDiffusionRequest(
'diffusion.mergedcommitsquery',
array(
'commit' => $drequest->getCommit(),
'limit' => $limit + 1,
));
if (!$merges) {
return null;
}
$merges = DiffusionPathChange::newFromConduit($merges);
$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.";
+ $caption = new PHUIInfoView();
+ $caption->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
+ $caption->appendChild(
+ pht('This commit merges more than %d changes. Only the first '.
+ '%d are shown.', $limit));
}
$history_table = new DiffusionHistoryTableView();
$history_table->setUser($this->getRequest()->getUser());
$history_table->setDiffusionRequest($drequest);
$history_table->setHistory($merges);
$history_table->loadRevisions();
$phids = $history_table->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$history_table->setHandles($handles);
- $panel = new AphrontPanelView();
- $panel->setHeader(pht('Merged Changes'));
- $panel->setCaption($caption);
+ $panel = new PHUIObjectBoxView();
+ $panel->setHeaderText(pht('Merged Changes'));
$panel->appendChild($history_table);
- $panel->setNoBackground();
+ if ($caption) {
+ $panel->setErrorView($caption);
+ }
return $panel;
}
private function renderHeadsupActionList(
PhabricatorRepositoryCommit $commit,
PhabricatorRepository $repository) {
$request = $this->getRequest();
$user = $request->getUser();
$actions = id(new PhabricatorActionListView())
->setUser($user)
->setObject($commit)
->setObjectURI($request->getRequestURI());
$can_edit = PhabricatorPolicyFilter::hasCapability(
$user,
$commit,
PhabricatorPolicyCapability::CAN_EDIT);
$uri = '/diffusion/'.$repository->getCallsign().'/commit/'.
$commit->getCommitIdentifier().'/edit/';
$action = id(new PhabricatorActionView())
->setName(pht('Edit Commit'))
->setHref($uri)
->setIcon('fa-pencil')
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit);
$actions->addAction($action);
require_celerity_resource('phabricator-object-selector-css');
require_celerity_resource('javelin-behavior-phabricator-object-selector');
$maniphest = 'PhabricatorManiphestApplication';
if (PhabricatorApplication::isClassInstalled($maniphest)) {
$action = id(new PhabricatorActionView())
->setName(pht('Edit Maniphest Tasks'))
->setIcon('fa-anchor')
->setHref('/search/attach/'.$commit->getPHID().'/TASK/edge/')
->setWorkflow(true)
->setDisabled(!$can_edit);
$actions->addAction($action);
}
$action = id(new PhabricatorActionView())
->setName(pht('Download Raw Diff'))
->setHref($request->getRequestURI()->alter('diff', true))
->setIcon('fa-download');
$actions->addAction($action);
return $actions;
}
private function buildRefs(DiffusionRequest $request) {
// this is git-only, so save a conduit round trip and just get out of
// here if the repository isn't git
$type_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
$repository = $request->getRepository();
if ($repository->getVersionControlSystem() != $type_git) {
return null;
}
$results = $this->callConduitWithDiffusionRequest(
'diffusion.refsquery',
array('commit' => $request->getCommit()));
$ref_links = array();
foreach ($results as $ref_data) {
$ref_links[] = phutil_tag('a',
array('href' => $ref_data['href']),
$ref_data['ref']);
}
return phutil_implode_html(', ', $ref_links);
}
private function buildRawDiffResponse(DiffusionRequest $drequest) {
$raw_diff = $this->callConduitWithDiffusionRequest(
'diffusion.rawdiffquery',
array(
'commit' => $drequest->getCommit(),
'path' => $drequest->getPath(),
));
$file = PhabricatorFile::buildFromFileDataOrHash(
$raw_diff,
array(
'name' => $drequest->getCommit().'.diff',
'ttl' => (60 * 60 * 24),
'viewPolicy' => PhabricatorPolicies::POLICY_NOONE,
));
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$file->attachToObject($drequest->getRepository()->getPHID());
unset($unguarded);
return $file->getRedirectResponse();
}
private function renderAuditStatusView(array $audit_requests) {
assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
$phids = mpull($audit_requests, 'getAuditorPHID');
$this->loadHandles($phids);
$authority_map = array_fill_keys($this->auditAuthorityPHIDs, true);
$view = new PHUIStatusListView();
foreach ($audit_requests as $request) {
$code = $request->getAuditStatus();
$item = new PHUIStatusItemView();
$item->setIcon(
PhabricatorAuditStatusConstants::getStatusIcon($code),
PhabricatorAuditStatusConstants::getStatusColor($code),
PhabricatorAuditStatusConstants::getStatusName($code));
$note = array();
foreach ($request->getAuditReasons() as $reason) {
$note[] = phutil_tag('div', array(), $reason);
}
$item->setNote($note);
$auditor_phid = $request->getAuditorPHID();
$target = $this->getHandle($auditor_phid)->renderLink();
$item->setTarget($target);
if (isset($authority_map[$auditor_phid])) {
$item->setHighlighted(true);
}
$view->addItem($item);
}
return $view;
}
private function linkBugtraq($corpus) {
$url = PhabricatorEnv::getEnvConfig('bugtraq.url');
if (!strlen($url)) {
return $corpus;
}
$regexes = PhabricatorEnv::getEnvConfig('bugtraq.logregex');
if (!$regexes) {
return $corpus;
}
$parser = id(new PhutilBugtraqParser())
->setBugtraqPattern("[[ {$url} | %BUGID% ]]")
->setBugtraqCaptureExpression(array_shift($regexes));
$select = array_shift($regexes);
if ($select) {
$parser->setBugtraqSelectExpression($select);
}
return $parser->processCorpus($corpus);
}
}
diff --git a/src/applications/diffusion/controller/DiffusionExternalController.php b/src/applications/diffusion/controller/DiffusionExternalController.php
index fdffd91da4..228cc53e3e 100644
--- a/src/applications/diffusion/controller/DiffusionExternalController.php
+++ b/src/applications/diffusion/controller/DiffusionExternalController.php
@@ -1,141 +1,145 @@
<?php
final class DiffusionExternalController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
protected function shouldLoadDiffusionRequest() {
return false;
}
protected function processDiffusionRequest(AphrontRequest $request) {
$uri = $request->getStr('uri');
$id = $request->getStr('id');
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($request->getUser())
->execute();
if ($uri) {
$uri_path = id(new PhutilURI($uri))->getPath();
$matches = array();
// Try to figure out which tracked repository this external lives in by
// comparing repository metadata. We look for an exact match, but accept
// a partial match.
foreach ($repositories as $key => $repository) {
$remote_uri = new PhutilURI($repository->getRemoteURI());
if ($remote_uri->getPath() == $uri_path) {
$matches[$key] = 1;
}
if ($repository->getPublicCloneURI() == $uri) {
$matches[$key] = 2;
}
if ($repository->getRemoteURI() == $uri) {
$matches[$key] = 3;
}
}
arsort($matches);
$best_match = head_key($matches);
if ($best_match) {
$repository = $repositories[$best_match];
$redirect = DiffusionRequest::generateDiffusionURI(
array(
'action' => 'browse',
'callsign' => $repository->getCallsign(),
'branch' => $repository->getDefaultBranch(),
'commit' => $id,
));
return id(new AphrontRedirectResponse())->setURI($redirect);
}
}
// TODO: This is a rare query but does a table scan, add a key?
$commits = id(new PhabricatorRepositoryCommit())->loadAllWhere(
'commitIdentifier = %s',
$id);
if (empty($commits)) {
$desc = null;
if ($uri) {
$desc = $uri.', at ';
}
$desc .= $id;
$content = id(new PHUIInfoView())
->setTitle(pht('Unknown External'))
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
->appendChild(phutil_tag(
'p',
array(),
pht('This external (%s) does not appear in any tracked '.
'repository. It may exist in an untracked repository that '.
'Diffusion does not know about.', $desc)));
} else if (count($commits) == 1) {
$commit = head($commits);
$repo = $repositories[$commit->getRepositoryID()];
$redirect = DiffusionRequest::generateDiffusionURI(
array(
'action' => 'browse',
'callsign' => $repo->getCallsign(),
'branch' => $repo->getDefaultBranch(),
'commit' => $commit->getCommitIdentifier(),
));
return id(new AphrontRedirectResponse())->setURI($redirect);
} else {
$rows = array();
foreach ($commits as $commit) {
$repo = $repositories[$commit->getRepositoryID()];
$href = DiffusionRequest::generateDiffusionURI(
array(
'action' => 'browse',
'callsign' => $repo->getCallsign(),
'branch' => $repo->getDefaultBranch(),
'commit' => $commit->getCommitIdentifier(),
));
$rows[] = array(
phutil_tag(
'a',
array(
'href' => $href,
),
'r'.$repo->getCallsign().$commit->getCommitIdentifier()),
$commit->loadCommitData()->getSummary(),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
pht('Commit'),
pht('Description'),
));
$table->setColumnClasses(
array(
'pri',
'wide',
));
- $content = new AphrontPanelView();
- $content->setHeader(pht('Multiple Matching Commits'));
- $content->setCaption(
- pht('This external reference matches multiple known commits.'));
+ $caption = id(new PHUIInfoView())
+ ->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
+ ->appendChild(
+ pht('This external reference matches multiple known commits.'));
+
+ $content = new PHUIObjectBoxView();
+ $content->setHeaderText(pht('Multiple Matching Commits'));
+ $content->setErrorView($caption);
$content->appendChild($table);
}
return $this->buildApplicationPage(
$content,
array(
'title' => pht('Unresolvable External'),
));
}
}
diff --git a/src/applications/diffusion/controller/DiffusionHistoryController.php b/src/applications/diffusion/controller/DiffusionHistoryController.php
index 2ac87542f5..36667c5dfe 100644
--- a/src/applications/diffusion/controller/DiffusionHistoryController.php
+++ b/src/applications/diffusion/controller/DiffusionHistoryController.php
@@ -1,173 +1,173 @@
<?php
final class DiffusionHistoryController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
protected function processDiffusionRequest(AphrontRequest $request) {
$drequest = $this->diffusionRequest;
$viewer = $request->getUser();
$repository = $drequest->getRepository();
$page_size = $request->getInt('pagesize', 100);
$offset = $request->getInt('offset', 0);
$params = array(
'commit' => $drequest->getCommit(),
'path' => $drequest->getPath(),
'offset' => $offset,
'limit' => $page_size + 1,
);
if (!$request->getBool('copies')) {
$params['needDirectChanges'] = true;
$params['needChildChanges'] = true;
}
$history_results = $this->callConduitWithDiffusionRequest(
'diffusion.historyquery',
$params);
$history = DiffusionPathChange::newFromConduit(
$history_results['pathChanges']);
$pager = new AphrontPagerView();
$pager->setPageSize($page_size);
$pager->setOffset($offset);
$history = $pager->sliceResults($history);
$pager->setURI($request->getRequestURI(), 'offset');
$show_graph = !strlen($drequest->getPath());
$content = array();
$history_table = new DiffusionHistoryTableView();
$history_table->setUser($request->getUser());
$history_table->setDiffusionRequest($drequest);
$history_table->setHistory($history);
$history_table->loadRevisions();
$phids = $history_table->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$history_table->setHandles($handles);
if ($show_graph) {
$history_table->setParents($history_results['parents']);
$history_table->setIsHead($offset == 0);
}
- $history_panel = new AphrontPanelView();
+ $history_panel = new PHUIObjectBoxView();
+ $history_panel->setHeaderText(pht('History'));
$history_panel->appendChild($history_table);
- $history_panel->appendChild($pager);
- $history_panel->setNoBackground();
$content[] = $history_panel;
$header = id(new PHUIHeaderView())
->setUser($viewer)
->setPolicyObject($repository)
->setHeader($this->renderPathLinks($drequest, $mode = 'history'));
$actions = $this->buildActionView($drequest);
$properties = $this->buildPropertyView($drequest, $actions);
$object_box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
$crumbs = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'history',
));
return $this->buildApplicationPage(
array(
$crumbs,
$object_box,
$content,
+ $pager,
),
array(
'title' => array(
pht('History'),
pht('%s Repository', $drequest->getRepository()->getCallsign()),
),
));
}
private function buildActionView(DiffusionRequest $drequest) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setUser($viewer);
$browse_uri = $drequest->generateURI(
array(
'action' => 'browse',
));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Browse Content'))
->setHref($browse_uri)
->setIcon('fa-files-o'));
// TODO: Sometimes we do have a change view, we need to look at the most
// recent history entry to figure it out.
$request = $this->getRequest();
if ($request->getBool('copies')) {
$branch_name = pht('Hide Copies/Branches');
$branch_uri = $request->getRequestURI()
->alter('offset', null)
->alter('copies', null);
} else {
$branch_name = pht('Show Copies/Branches');
$branch_uri = $request->getRequestURI()
->alter('offset', null)
->alter('copies', true);
}
$view->addAction(
id(new PhabricatorActionView())
->setName($branch_name)
->setIcon('fa-code-fork')
->setHref($branch_uri));
return $view;
}
protected function buildPropertyView(
DiffusionRequest $drequest,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions);
$stable_commit = $drequest->getStableCommit();
$callsign = $drequest->getRepository()->getCallsign();
$view->addProperty(
pht('Commit'),
phutil_tag(
'a',
array(
'href' => $drequest->generateURI(
array(
'action' => 'commit',
'commit' => $stable_commit,
)),
),
$drequest->getRepository()->formatCommitName($stable_commit)));
return $view;
}
}
diff --git a/src/applications/diffusion/controller/DiffusionLintController.php b/src/applications/diffusion/controller/DiffusionLintController.php
index 8e00727729..5f51d31fe7 100644
--- a/src/applications/diffusion/controller/DiffusionLintController.php
+++ b/src/applications/diffusion/controller/DiffusionLintController.php
@@ -1,344 +1,342 @@
<?php
final class DiffusionLintController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
protected function processDiffusionRequest(AphrontRequest $request) {
$user = $request->getUser();
$drequest = $this->diffusionRequest;
if ($request->getStr('lint') !== null) {
$controller = new DiffusionLintDetailsController();
$controller->setDiffusionRequest($drequest);
$controller->setCurrentApplication($this->getCurrentApplication());
return $this->delegateToController($controller);
}
$owners = array();
if (!$drequest) {
if (!$request->getArr('owner')) {
$owners = array($user->getPHID());
} else {
$owners = array(head($request->getArr('owner')));
}
$owner_handles = $this->loadViewerHandles($owners);
}
$codes = $this->loadLintCodes($owners);
if ($codes && !$drequest) {
// TODO: Build some real Query classes for this stuff.
$branches = id(new PhabricatorRepositoryBranch())->loadAllWhere(
'id IN (%Ld)',
array_unique(ipull($codes, 'branchID')));
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($user)
->withIDs(mpull($branches, 'getRepositoryID'))
->execute();
$drequests = array();
foreach ($branches as $id => $branch) {
if (empty($repositories[$branch->getRepositoryID()])) {
continue;
}
$drequests[$id] = DiffusionRequest::newFromDictionary(array(
'user' => $user,
'repository' => $repositories[$branch->getRepositoryID()],
'branch' => $branch->getName(),
));
}
}
$rows = array();
$total = 0;
foreach ($codes as $code) {
if (!$this->diffusionRequest) {
$drequest = idx($drequests, $code['branchID']);
}
if (!$drequest) {
continue;
}
$total += $code['n'];
$href_lint = $drequest->generateURI(array(
'action' => 'lint',
'lint' => $code['code'],
));
$href_browse = $drequest->generateURI(array(
'action' => 'browse',
'lint' => $code['code'],
));
$href_repo = $drequest->generateURI(array('action' => 'lint'));
$rows[] = array(
phutil_tag('a', array('href' => $href_lint), $code['n']),
phutil_tag('a', array('href' => $href_browse), $code['files']),
phutil_tag('a', array('href' => $href_repo), $drequest->getCallsign()),
ArcanistLintSeverity::getStringForSeverity($code['maxSeverity']),
$code['code'],
$code['maxName'],
$code['maxDescription'],
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(array(
pht('Problems'),
pht('Files'),
pht('Repository'),
pht('Severity'),
pht('Code'),
pht('Name'),
pht('Example'),
))
->setColumnVisibility(array(true, true, !$this->diffusionRequest))
->setColumnClasses(array('n', 'n', '', '', 'pri', '', ''));
$content = array();
- $link = null;
if (!$this->diffusionRequest) {
$form = id(new AphrontFormView())
->setUser($user)
->setMethod('GET')
->appendChild(
id(new AphrontFormTokenizerControl())
->setDatasource(new PhabricatorPeopleDatasource())
->setLimit(1)
->setName('owner')
->setLabel(pht('Owner'))
->setValue($owner_handles))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Filter'));
$content[] = id(new AphrontListFilterView())->appendChild($form);
}
- $content[] = id(new AphrontPanelView())
- ->setNoBackground(true)
- ->setCaption($link)
+ $content[] = id(new PHUIObjectBoxView())
+ ->setHeaderText(pht('Lint'))
->appendChild($table);
$title = array('Lint');
$crumbs = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'lint',
));
if ($this->diffusionRequest) {
$title[] = $drequest->getCallsign();
} else {
$crumbs->addTextCrumb(pht('All Lint'));
}
if ($this->diffusionRequest) {
$branch = $drequest->loadBranch();
$header = id(new PHUIHeaderView())
->setHeader($this->renderPathLinks($drequest, 'lint'))
->setUser($user)
->setPolicyObject($drequest->getRepository());
$actions = $this->buildActionView($drequest);
$properties = $this->buildPropertyView(
$drequest,
$branch,
$total,
$actions);
$object_box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
} else {
$object_box = null;
}
return $this->buildApplicationPage(
array(
$crumbs,
$object_box,
$content,
),
array(
'title' => $title,
));
}
private function loadLintCodes(array $owner_phids) {
$drequest = $this->diffusionRequest;
$conn = id(new PhabricatorRepository())->establishConnection('r');
$where = array('1 = 1');
if ($drequest) {
$branch = $drequest->loadBranch();
if (!$branch) {
return array();
}
$where[] = qsprintf($conn, 'branchID = %d', $branch->getID());
if ($drequest->getPath() != '') {
$path = '/'.$drequest->getPath();
$is_dir = (substr($path, -1) == '/');
$where[] = ($is_dir
? qsprintf($conn, 'path LIKE %>', $path)
: qsprintf($conn, 'path = %s', $path));
}
}
if ($owner_phids) {
$or = array();
$or[] = qsprintf($conn, 'authorPHID IN (%Ls)', $owner_phids);
$paths = array();
$packages = id(new PhabricatorOwnersOwner())
->loadAllWhere('userPHID IN (%Ls)', $owner_phids);
if ($packages) {
$paths = id(new PhabricatorOwnersPath())->loadAllWhere(
'packageID IN (%Ld)',
mpull($packages, 'getPackageID'));
}
if ($paths) {
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getRequest()->getUser())
->withPHIDs(mpull($paths, 'getRepositoryPHID'))
->execute();
$repositories = mpull($repositories, 'getID', 'getPHID');
$branches = id(new PhabricatorRepositoryBranch())->loadAllWhere(
'repositoryID IN (%Ld)',
$repositories);
$branches = mgroup($branches, 'getRepositoryID');
}
foreach ($paths as $path) {
$branch = idx(
$branches,
idx(
$repositories,
$path->getRepositoryPHID()));
if ($branch) {
$condition = qsprintf(
$conn,
'(branchID IN (%Ld) AND path LIKE %>)',
array_keys($branch),
$path->getPath());
if ($path->getExcluded()) {
$where[] = 'NOT '.$condition;
} else {
$or[] = $condition;
}
}
}
$where[] = '('.implode(' OR ', $or).')';
}
return queryfx_all(
$conn,
'SELECT
branchID,
code,
MAX(severity) AS maxSeverity,
MAX(name) AS maxName,
MAX(description) AS maxDescription,
COUNT(DISTINCT path) AS files,
COUNT(*) AS n
FROM %T
WHERE %Q
GROUP BY branchID, code
ORDER BY n DESC',
PhabricatorRepository::TABLE_LINTMESSAGE,
implode(' AND ', $where));
}
protected function buildActionView(DiffusionRequest $drequest) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setUser($viewer);
$list_uri = $drequest->generateURI(
array(
'action' => 'lint',
'lint' => '',
));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('View As List'))
->setHref($list_uri)
->setIcon('fa-list'));
$history_uri = $drequest->generateURI(
array(
'action' => 'history',
));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('View History'))
->setHref($history_uri)
->setIcon('fa-clock-o'));
$browse_uri = $drequest->generateURI(
array(
'action' => 'browse',
));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Browse Content'))
->setHref($browse_uri)
->setIcon('fa-files-o'));
return $view;
}
protected function buildPropertyView(
DiffusionRequest $drequest,
PhabricatorRepositoryBranch $branch,
$total,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions);
$callsign = $drequest->getRepository()->getCallsign();
$lint_commit = $branch->getLintCommit();
$view->addProperty(
pht('Lint Commit'),
phutil_tag(
'a',
array(
'href' => $drequest->generateURI(
array(
'action' => 'commit',
'commit' => $lint_commit,
)),
),
$drequest->getRepository()->formatCommitName($lint_commit)));
$view->addProperty(
pht('Total Messages'),
pht('%s', new PhutilNumber($total)));
return $view;
}
}
diff --git a/src/applications/diffusion/controller/DiffusionLintDetailsController.php b/src/applications/diffusion/controller/DiffusionLintDetailsController.php
index 255b9e55cd..ba1a1dcbaf 100644
--- a/src/applications/diffusion/controller/DiffusionLintDetailsController.php
+++ b/src/applications/diffusion/controller/DiffusionLintDetailsController.php
@@ -1,144 +1,144 @@
<?php
final class DiffusionLintDetailsController extends DiffusionController {
protected function processDiffusionRequest(AphrontRequest $request) {
$limit = 500;
$offset = $request->getInt('offset', 0);
$drequest = $this->getDiffusionRequest();
$branch = $drequest->loadBranch();
$messages = $this->loadLintMessages($branch, $limit, $offset);
$is_dir = (substr('/'.$drequest->getPath(), -1) == '/');
$authors = $this->loadViewerHandles(ipull($messages, 'authorPHID'));
$rows = array();
foreach ($messages as $message) {
$path = phutil_tag(
'a',
array(
'href' => $drequest->generateURI(array(
'action' => 'lint',
'path' => $message['path'],
)),
),
substr($message['path'], strlen($drequest->getPath()) + 1));
$line = phutil_tag(
'a',
array(
'href' => $drequest->generateURI(array(
'action' => 'browse',
'path' => $message['path'],
'line' => $message['line'],
'commit' => $branch->getLintCommit(),
)),
),
$message['line']);
$author = $message['authorPHID'];
if ($author && $authors[$author]) {
$author = $authors[$author]->renderLink();
}
$rows[] = array(
$path,
$line,
$author,
ArcanistLintSeverity::getStringForSeverity($message['severity']),
$message['name'],
$message['description'],
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(array(
pht('Path'),
pht('Line'),
pht('Author'),
pht('Severity'),
pht('Name'),
pht('Description'),
))
->setColumnClasses(array('', 'n'))
->setColumnVisibility(array($is_dir));
$content = array();
$pager = id(new AphrontPagerView())
->setPageSize($limit)
->setOffset($offset)
->setHasMorePages(count($messages) >= $limit)
->setURI($request->getRequestURI(), 'offset');
- $content[] = id(new AphrontPanelView())
- ->setNoBackground(true)
- ->appendChild($table)
- ->appendChild($pager);
+ $content[] = id(new PHUIObjectBoxView())
+ ->setHeaderText(pht('Lint Details'))
+ ->appendChild($table);
$crumbs = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'lint',
));
return $this->buildApplicationPage(
array(
$crumbs,
$content,
+ $pager,
),
array(
'title' =>
array(
pht('Lint'),
$drequest->getRepository()->getCallsign(),
),
));
}
private function loadLintMessages(
PhabricatorRepositoryBranch $branch,
$limit,
$offset) {
$drequest = $this->getDiffusionRequest();
if (!$branch) {
return array();
}
$conn = $branch->establishConnection('r');
$where = array(
qsprintf($conn, 'branchID = %d', $branch->getID()),
);
if ($drequest->getPath() != '') {
$path = '/'.$drequest->getPath();
$is_dir = (substr($path, -1) == '/');
$where[] = ($is_dir
? qsprintf($conn, 'path LIKE %>', $path)
: qsprintf($conn, 'path = %s', $path));
}
if ($drequest->getLint() != '') {
$where[] = qsprintf(
$conn,
'code = %s',
$drequest->getLint());
}
return queryfx_all(
$conn,
'SELECT *
FROM %T
WHERE %Q
ORDER BY path, code, line LIMIT %d OFFSET %d',
PhabricatorRepository::TABLE_LINTMESSAGE,
implode(' AND ', $where),
$limit,
$offset);
}
}
diff --git a/src/applications/diffusion/controller/DiffusionSymbolController.php b/src/applications/diffusion/controller/DiffusionSymbolController.php
index 104b9fc515..34a291a8cd 100644
--- a/src/applications/diffusion/controller/DiffusionSymbolController.php
+++ b/src/applications/diffusion/controller/DiffusionSymbolController.php
@@ -1,153 +1,151 @@
<?php
final class DiffusionSymbolController extends DiffusionController {
private $name;
protected function processDiffusionRequest(AphrontRequest $request) {
$user = $request->getUser();
$this->name = $request->getURIData('name');
$query = id(new DiffusionSymbolQuery())
->setViewer($user)
->setName($this->name);
if ($request->getStr('context') !== null) {
$query->setContext($request->getStr('context'));
}
if ($request->getStr('type')) {
$query->setType($request->getStr('type'));
}
if ($request->getStr('lang')) {
$query->setLanguage($request->getStr('lang'));
}
if ($request->getStr('projects')) {
$phids = $request->getStr('projects');
$phids = explode(',', $phids);
$phids = array_filter($phids);
if ($phids) {
$projects = id(new PhabricatorRepositoryArcanistProject())
->loadAllWhere(
'phid IN (%Ls)',
$phids);
$projects = mpull($projects, 'getID');
if ($projects) {
$query->setProjectIDs($projects);
}
}
}
$query->needPaths(true);
$query->needArcanistProjects(true);
$query->needRepositories(true);
$symbols = $query->execute();
// For PHP builtins, jump to php.net documentation.
if ($request->getBool('jump') && count($symbols) == 0) {
if ($request->getStr('lang', 'php') == 'php') {
if ($request->getStr('type', 'function') == 'function') {
$functions = get_defined_functions();
if (in_array($this->name, $functions['internal'])) {
return id(new AphrontRedirectResponse())
->setIsExternal(true)
->setURI('http://www.php.net/function.'.$this->name);
}
}
if ($request->getStr('type', 'class') == 'class') {
if (class_exists($this->name, false) ||
interface_exists($this->name, false)) {
if (id(new ReflectionClass($this->name))->isInternal()) {
return id(new AphrontRedirectResponse())
->setIsExternal(true)
->setURI('http://www.php.net/class.'.$this->name);
}
}
}
}
}
$rows = array();
foreach ($symbols as $symbol) {
$project = $symbol->getArcanistProject();
if ($project) {
$project_name = $project->getName();
} else {
$project_name = '-';
}
$file = $symbol->getPath();
$line = $symbol->getLineNumber();
$repo = $symbol->getRepository();
if ($repo) {
$href = $symbol->getURI();
if ($request->getBool('jump') && count($symbols) == 1) {
// If this is a clickthrough from Differential, just jump them
// straight to the target if we got a single hit.
return id(new AphrontRedirectResponse())->setURI($href);
}
$location = phutil_tag(
'a',
array(
'href' => $href,
),
$file.':'.$line);
} else if ($file) {
$location = $file.':'.$line;
} else {
$location = '?';
}
$rows[] = array(
$symbol->getSymbolType(),
$symbol->getSymbolContext(),
$symbol->getSymbolName(),
$symbol->getSymbolLanguage(),
$project_name,
$location,
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
pht('Type'),
pht('Context'),
pht('Name'),
pht('Language'),
pht('Project'),
pht('File'),
));
$table->setColumnClasses(
array(
'',
'',
'pri',
'',
'',
'',
));
$table->setNoDataString(
pht('No matching symbol could be found in any indexed project.'));
- $panel = new AphrontPanelView();
- $panel->setHeader(pht('Similar Symbols'));
+ $panel = new PHUIObjectBoxView();
+ $panel->setHeaderText(pht('Similar Symbols'));
$panel->appendChild($table);
return $this->buildApplicationPage(
- array(
- $panel,
- ),
+ $panel,
array(
'title' => pht('Find Symbol'),
));
}
}
diff --git a/src/applications/diffusion/controller/DiffusionTagListController.php b/src/applications/diffusion/controller/DiffusionTagListController.php
index bf2c2f84ce..349df62520 100644
--- a/src/applications/diffusion/controller/DiffusionTagListController.php
+++ b/src/applications/diffusion/controller/DiffusionTagListController.php
@@ -1,96 +1,96 @@
<?php
final class DiffusionTagListController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
protected function processDiffusionRequest(AphrontRequest $request) {
$drequest = $this->getDiffusionRequest();
$viewer = $request->getUser();
$repository = $drequest->getRepository();
$pager = new AphrontPagerView();
$pager->setURI($request->getRequestURI(), 'offset');
$pager->setOffset($request->getInt('offset'));
$params = array(
'limit' => $pager->getPageSize() + 1,
'offset' => $pager->getOffset(),
);
if ($drequest->getSymbolicCommit()) {
$is_commit = true;
$params['commit'] = $drequest->getSymbolicCommit();
} else {
$is_commit = false;
}
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$tags = array();
break;
default:
$conduit_result = $this->callConduitWithDiffusionRequest(
'diffusion.tagsquery',
$params);
$tags = DiffusionRepositoryTag::newFromConduit($conduit_result);
break;
}
$tags = $pager->sliceResults($tags);
$content = null;
if (!$tags) {
$content = $this->renderStatusMessage(
pht('No Tags'),
$is_commit
? pht('This commit has no tags.')
: pht('This repository has no tags.'));
} else {
$commits = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withRepository($repository)
->withIdentifiers(mpull($tags, 'getCommitIdentifier'))
->needCommitData(true)
->execute();
$view = id(new DiffusionTagListView())
->setTags($tags)
->setUser($viewer)
->setCommits($commits)
->setDiffusionRequest($drequest);
$phids = $view->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$view->setHandles($handles);
- $panel = id(new AphrontPanelView())
- ->setNoBackground(true)
- ->appendChild($view)
- ->appendChild($pager);
+ $panel = id(new PHUIObjectBoxView())
+ ->setHeaderText(pht('Tags'))
+ ->appendChild($view);
$content = $panel;
}
$crumbs = $this->buildCrumbs(
array(
'tags' => true,
'commit' => $drequest->getSymbolicCommit(),
));
return $this->buildApplicationPage(
array(
$crumbs,
$content,
+ $pager,
),
array(
'title' => array(
pht('Tags'),
pht('%s Repository', $repository->getCallsign()),
),
));
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 13:47 (3 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1125209
Default Alt Text
(74 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment