mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-28 08:20:57 +01:00
Add a basic view for repository pull logs
Summary: Depends on D18912. Ref T13046. Add a UI to browse the existing pull log table. The actual log still has some significant flaws, but get the basics working. Test Plan: {F5391909} Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13046 Differential Revision: https://secure.phabricator.com/D18914
This commit is contained in:
parent
2914613444
commit
e6a9db56a9
11 changed files with 304 additions and 25 deletions
|
@ -764,6 +764,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionLintCountQuery' => 'applications/diffusion/query/DiffusionLintCountQuery.php',
|
||||
'DiffusionLintSaveRunner' => 'applications/diffusion/DiffusionLintSaveRunner.php',
|
||||
'DiffusionLocalRepositoryFilter' => 'applications/diffusion/data/DiffusionLocalRepositoryFilter.php',
|
||||
'DiffusionLogController' => 'applications/diffusion/controller/DiffusionLogController.php',
|
||||
'DiffusionLookSoonConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionLookSoonConduitAPIMethod.php',
|
||||
'DiffusionLowLevelCommitFieldsQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelCommitFieldsQuery.php',
|
||||
'DiffusionLowLevelCommitQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelCommitQuery.php',
|
||||
|
@ -831,9 +832,11 @@ phutil_register_library_map(array(
|
|||
'DiffusionPreCommitRefTypeHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefTypeHeraldField.php',
|
||||
'DiffusionPreCommitUsesGitLFSHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitUsesGitLFSHeraldField.php',
|
||||
'DiffusionPullEventGarbageCollector' => 'applications/diffusion/garbagecollector/DiffusionPullEventGarbageCollector.php',
|
||||
'DiffusionPullLogListController' => 'applications/diffusion/controller/DiffusionPullLogListController.php',
|
||||
'DiffusionPullLogListView' => 'applications/diffusion/view/DiffusionPullLogListView.php',
|
||||
'DiffusionPullLogSearchEngine' => 'applications/diffusion/query/DiffusionPullLogSearchEngine.php',
|
||||
'DiffusionPushCapability' => 'applications/diffusion/capability/DiffusionPushCapability.php',
|
||||
'DiffusionPushEventViewController' => 'applications/diffusion/controller/DiffusionPushEventViewController.php',
|
||||
'DiffusionPushLogController' => 'applications/diffusion/controller/DiffusionPushLogController.php',
|
||||
'DiffusionPushLogListController' => 'applications/diffusion/controller/DiffusionPushLogListController.php',
|
||||
'DiffusionPushLogListView' => 'applications/diffusion/view/DiffusionPushLogListView.php',
|
||||
'DiffusionPythonExternalSymbolsSource' => 'applications/diffusion/symbol/DiffusionPythonExternalSymbolsSource.php',
|
||||
|
@ -5864,6 +5867,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionLintCountQuery' => 'PhabricatorQuery',
|
||||
'DiffusionLintSaveRunner' => 'Phobject',
|
||||
'DiffusionLocalRepositoryFilter' => 'Phobject',
|
||||
'DiffusionLogController' => 'DiffusionController',
|
||||
'DiffusionLookSoonConduitAPIMethod' => 'DiffusionConduitAPIMethod',
|
||||
'DiffusionLowLevelCommitFieldsQuery' => 'DiffusionLowLevelQuery',
|
||||
'DiffusionLowLevelCommitQuery' => 'DiffusionLowLevelQuery',
|
||||
|
@ -5931,10 +5935,12 @@ phutil_register_library_map(array(
|
|||
'DiffusionPreCommitRefTypeHeraldField' => 'DiffusionPreCommitRefHeraldField',
|
||||
'DiffusionPreCommitUsesGitLFSHeraldField' => 'DiffusionPreCommitContentHeraldField',
|
||||
'DiffusionPullEventGarbageCollector' => 'PhabricatorGarbageCollector',
|
||||
'DiffusionPullLogListController' => 'DiffusionLogController',
|
||||
'DiffusionPullLogListView' => 'AphrontView',
|
||||
'DiffusionPullLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'DiffusionPushCapability' => 'PhabricatorPolicyCapability',
|
||||
'DiffusionPushEventViewController' => 'DiffusionPushLogController',
|
||||
'DiffusionPushLogController' => 'DiffusionController',
|
||||
'DiffusionPushLogListController' => 'DiffusionPushLogController',
|
||||
'DiffusionPushEventViewController' => 'DiffusionLogController',
|
||||
'DiffusionPushLogListController' => 'DiffusionLogController',
|
||||
'DiffusionPushLogListView' => 'AphrontView',
|
||||
'DiffusionPythonExternalSymbolsSource' => 'DiffusionExternalSymbolsSource',
|
||||
'DiffusionQuery' => 'PhabricatorQuery',
|
||||
|
|
|
@ -124,6 +124,9 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
|
|||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'DiffusionPushLogListController',
|
||||
'view/(?P<id>\d+)/' => 'DiffusionPushEventViewController',
|
||||
),
|
||||
'pulllog/' => array(
|
||||
$this->getQueryRoutePattern() => 'DiffusionPullLogListController',
|
||||
),
|
||||
'(?P<repositoryCallsign>[A-Z]+)' => $repository_routes,
|
||||
'(?P<repositoryID>[1-9]\d*)' => $repository_routes,
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
abstract class DiffusionPushLogController extends DiffusionController {
|
||||
abstract class DiffusionLogController extends DiffusionController {
|
||||
|
||||
protected function shouldLoadDiffusionRequest() {
|
||||
return false;
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionPullLogListController
|
||||
extends DiffusionLogController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
return id(new DiffusionPullLogSearchEngine())
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionPushEventViewController
|
||||
extends DiffusionPushLogController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
extends DiffusionLogController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionPushLogListController extends DiffusionPushLogController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
final class DiffusionPushLogListController
|
||||
extends DiffusionLogController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
return id(new PhabricatorRepositoryPushLogSearchEngine())
|
||||
|
|
|
@ -365,7 +365,7 @@ final class DiffusionRepositoryController extends DiffusionController {
|
|||
|
||||
if ($repository->isHosted()) {
|
||||
$push_uri = $this->getApplicationURI(
|
||||
'pushlog/?repositories='.$repository->getMonogram());
|
||||
'pushlog/?repositories='.$repository->getPHID());
|
||||
|
||||
$action_view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
|
@ -374,6 +374,15 @@ final class DiffusionRepositoryController extends DiffusionController {
|
|||
->setHref($push_uri));
|
||||
}
|
||||
|
||||
$pull_uri = $this->getApplicationURI(
|
||||
'pulllog/?repositories='.$repository->getPHID());
|
||||
|
||||
$action_view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('View Pull Logs'))
|
||||
->setIcon('fa-list-alt')
|
||||
->setHref($pull_uri));
|
||||
|
||||
return $action_view;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionPullLogSearchEngine
|
||||
extends PhabricatorApplicationSearchEngine {
|
||||
|
||||
public function getResultTypeDescription() {
|
||||
return pht('Pull Logs');
|
||||
}
|
||||
|
||||
public function getApplicationClassName() {
|
||||
return 'PhabricatorDiffusionApplication';
|
||||
}
|
||||
|
||||
public function newQuery() {
|
||||
return new PhabricatorRepositoryPullEventQuery();
|
||||
}
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
$query = $this->newQuery();
|
||||
|
||||
if ($map['repositoryPHIDs']) {
|
||||
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
|
||||
}
|
||||
|
||||
if ($map['pullerPHIDs']) {
|
||||
$query->withPullerPHIDs($map['pullerPHIDs']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function buildCustomSearchFields() {
|
||||
return array(
|
||||
id(new PhabricatorSearchDatasourceField())
|
||||
->setDatasource(new DiffusionRepositoryDatasource())
|
||||
->setKey('repositoryPHIDs')
|
||||
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
|
||||
->setLabel(pht('Repositories'))
|
||||
->setDescription(
|
||||
pht('Search for pull logs for specific repositories.')),
|
||||
id(new PhabricatorUsersSearchField())
|
||||
->setKey('pullerPHIDs')
|
||||
->setAliases(array('puller', 'pullers', 'pullerPHID'))
|
||||
->setLabel(pht('Pullers'))
|
||||
->setDescription(
|
||||
pht('Search for pull logs by specific users.')),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getURI($path) {
|
||||
return '/diffusion/pulllog/'.$path;
|
||||
}
|
||||
|
||||
protected function getBuiltinQueryNames() {
|
||||
return array(
|
||||
'all' => pht('All Pull Logs'),
|
||||
);
|
||||
}
|
||||
|
||||
public function buildSavedQueryFromBuiltin($query_key) {
|
||||
$query = $this->newSavedQuery();
|
||||
$query->setQueryKey($query_key);
|
||||
|
||||
switch ($query_key) {
|
||||
case 'all':
|
||||
return $query;
|
||||
}
|
||||
|
||||
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||
}
|
||||
|
||||
protected function renderResultList(
|
||||
array $logs,
|
||||
PhabricatorSavedQuery $query,
|
||||
array $handles) {
|
||||
|
||||
$table = id(new DiffusionPullLogListView())
|
||||
->setViewer($this->requireViewer())
|
||||
->setLogs($logs);
|
||||
|
||||
return id(new PhabricatorApplicationSearchResultView())
|
||||
->setTable($table);
|
||||
}
|
||||
|
||||
}
|
115
src/applications/diffusion/view/DiffusionPullLogListView.php
Normal file
115
src/applications/diffusion/view/DiffusionPullLogListView.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionPullLogListView extends AphrontView {
|
||||
|
||||
private $logs;
|
||||
|
||||
public function setLogs(array $logs) {
|
||||
assert_instances_of($logs, 'PhabricatorRepositoryPullEvent');
|
||||
$this->logs = $logs;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$events = $this->logs;
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$handle_phids = array();
|
||||
foreach ($events as $event) {
|
||||
if ($event->getPullerPHID()) {
|
||||
$handle_phids[] = $event->getPullerPHID();
|
||||
}
|
||||
}
|
||||
$handles = $viewer->loadHandles($handle_phids);
|
||||
|
||||
// Figure out which repositories are editable. We only let you see remote
|
||||
// IPs if you have edit capability on a repository.
|
||||
$editable_repos = array();
|
||||
if ($events) {
|
||||
$editable_repos = id(new PhabricatorRepositoryQuery())
|
||||
->setViewer($viewer)
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->withPHIDs(mpull($events, 'getRepositoryPHID'))
|
||||
->execute();
|
||||
$editable_repos = mpull($editable_repos, null, 'getPHID');
|
||||
}
|
||||
|
||||
$rows = array();
|
||||
$any_host = false;
|
||||
foreach ($events as $event) {
|
||||
if ($event->getRepositoryPHID()) {
|
||||
$repository = $event->getRepository();
|
||||
} else {
|
||||
$repository = null;
|
||||
}
|
||||
|
||||
// Reveal this if it's valid and the user can edit the repository. For
|
||||
// invalid requests you currently have to go fishing in the database.
|
||||
$remote_address = '-';
|
||||
if ($repository) {
|
||||
if (isset($editable_repos[$event->getRepositoryPHID()])) {
|
||||
$remote_address = $event->getRemoteAddress();
|
||||
}
|
||||
}
|
||||
|
||||
$event_id = $event->getID();
|
||||
|
||||
$repository_link = null;
|
||||
if ($repository) {
|
||||
$repository_link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $repository->getURI(),
|
||||
),
|
||||
$repository->getDisplayName());
|
||||
}
|
||||
|
||||
$puller_link = null;
|
||||
if ($event->getPullerPHID()) {
|
||||
$puller_link = $viewer->renderHandle($event->getPullerPHID());
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
$event_id,
|
||||
$repository_link,
|
||||
$puller_link,
|
||||
$remote_address,
|
||||
$event->getRemoteProtocolDisplayName(),
|
||||
$event->newResultIcon(),
|
||||
$event->getResultCode(),
|
||||
phabricator_datetime($event->getEpoch(), $viewer),
|
||||
);
|
||||
}
|
||||
|
||||
$table = id(new AphrontTableView($rows))
|
||||
->setHeaders(
|
||||
array(
|
||||
pht('Pull'),
|
||||
pht('Repository'),
|
||||
pht('Puller'),
|
||||
pht('From'),
|
||||
pht('Via'),
|
||||
null,
|
||||
pht('Error'),
|
||||
pht('Date'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'n',
|
||||
'',
|
||||
'',
|
||||
'n',
|
||||
'wide',
|
||||
'',
|
||||
'n',
|
||||
'right',
|
||||
));
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
}
|
|
@ -37,19 +37,35 @@ final class PhabricatorRepositoryPullEventQuery
|
|||
}
|
||||
|
||||
protected function willFilterPage(array $events) {
|
||||
// If a pull targets an invalid repository or fails before authenticating,
|
||||
// it may not have an associated repository.
|
||||
|
||||
$repository_phids = mpull($events, 'getRepositoryPHID');
|
||||
$repositories = id(new PhabricatorRepositoryQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($repository_phids)
|
||||
->execute();
|
||||
$repositories = mpull($repositories, null, 'getPHID');
|
||||
$repository_phids = array_filter($repository_phids);
|
||||
|
||||
if ($repository_phids) {
|
||||
$repositories = id(new PhabricatorRepositoryQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($repository_phids)
|
||||
->execute();
|
||||
$repositories = mpull($repositories, null, 'getPHID');
|
||||
} else {
|
||||
$repositories = array();
|
||||
}
|
||||
|
||||
foreach ($events as $key => $event) {
|
||||
$phid = $event->getRepositoryPHID();
|
||||
if (empty($repositories[$phid])) {
|
||||
unset($events[$key]);
|
||||
if (!$phid) {
|
||||
$event->attachRepository(null);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($repositories[$phid])) {
|
||||
unset($events[$key]);
|
||||
$this->didRejectResult($event);
|
||||
continue;
|
||||
}
|
||||
|
||||
$event->attachRepository($repositories[$phid]);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ final class PhabricatorRepositoryPullEvent
|
|||
PhabricatorRepositoryPullEventPHIDType::TYPECONST);
|
||||
}
|
||||
|
||||
public function attachRepository(PhabricatorRepository $repository) {
|
||||
public function attachRepository(PhabricatorRepository $repository = null) {
|
||||
$this->repository = $repository;
|
||||
return $this;
|
||||
}
|
||||
|
@ -60,6 +60,38 @@ final class PhabricatorRepositoryPullEvent
|
|||
return $this->assertAttached($this->repository);
|
||||
}
|
||||
|
||||
public function getRemoteProtocolDisplayName() {
|
||||
$map = array(
|
||||
'ssh' => pht('SSH'),
|
||||
'http' => pht('HTTP'),
|
||||
);
|
||||
|
||||
$protocol = $this->getRemoteProtocol();
|
||||
|
||||
return idx($map, $protocol, $protocol);
|
||||
}
|
||||
|
||||
public function newResultIcon() {
|
||||
$icon = new PHUIIconView();
|
||||
$type = $this->getResultType();
|
||||
|
||||
switch ($type) {
|
||||
case 'wild':
|
||||
$icon
|
||||
->setIcon('fa-question indigo')
|
||||
->setTooltip(pht('Unknown ("%s")', $type));
|
||||
break;
|
||||
case 'pull':
|
||||
$icon
|
||||
->setIcon('fa-download green')
|
||||
->setTooltip(pht('Pull'));
|
||||
break;
|
||||
}
|
||||
|
||||
return $icon;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
@ -71,10 +103,18 @@ final class PhabricatorRepositoryPullEvent
|
|||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
return $this->getRepository()->getPolicy($capability);
|
||||
if ($this->getRepository()) {
|
||||
return $this->getRepository()->getPolicy($capability);
|
||||
}
|
||||
|
||||
return PhabricatorPolicies::POLICY_ADMIN;
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
if (!$this->getRepository()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getRepository()->hasAutomaticCapability($capability, $viewer);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue