diff --git a/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php b/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php index cb097fae2f..d4734f61e6 100644 --- a/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php +++ b/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php @@ -1,159 +1,199 @@ ids = $ids; return $this; } public function withPHIDs(array $phids) { $this->phids = $phids; return $this; } public function withRepositoryPHIDs(array $repository_phids) { $this->repositoryPHIDs = $repository_phids; return $this; } public function withPusherPHIDs(array $pusher_phids) { $this->pusherPHIDs = $pusher_phids; return $this; } public function withRefTypes(array $ref_types) { $this->refTypes = $ref_types; return $this; } public function withNewRefs(array $new_refs) { $this->newRefs = $new_refs; return $this; } public function withPushEventPHIDs(array $phids) { $this->pushEventPHIDs = $phids; return $this; } public function withEpochBetween($min, $max) { $this->epochMin = $min; $this->epochMax = $max; return $this; } + public function withBlockingHeraldRulePHIDs(array $phids) { + $this->blockingHeraldRulePHIDs = $phids; + return $this; + } + public function newResultObject() { return new PhabricatorRepositoryPushLog(); } protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } protected function willFilterPage(array $logs) { $event_phids = mpull($logs, 'getPushEventPHID'); $events = id(new PhabricatorObjectQuery()) ->setParentQuery($this) ->setViewer($this->getViewer()) ->withPHIDs($event_phids) ->execute(); $events = mpull($events, null, 'getPHID'); foreach ($logs as $key => $log) { $event = idx($events, $log->getPushEventPHID()); if (!$event) { unset($logs[$key]); continue; } $log->attachPushEvent($event); } return $logs; } protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); if ($this->ids !== null) { $where[] = qsprintf( $conn, - 'id IN (%Ld)', + 'log.id IN (%Ld)', $this->ids); } if ($this->phids !== null) { $where[] = qsprintf( $conn, - 'phid IN (%Ls)', + 'log.phid IN (%Ls)', $this->phids); } if ($this->repositoryPHIDs !== null) { $where[] = qsprintf( $conn, - 'repositoryPHID IN (%Ls)', + 'log.repositoryPHID IN (%Ls)', $this->repositoryPHIDs); } if ($this->pusherPHIDs !== null) { $where[] = qsprintf( $conn, - 'pusherPHID in (%Ls)', + 'log.pusherPHID in (%Ls)', $this->pusherPHIDs); } if ($this->pushEventPHIDs !== null) { $where[] = qsprintf( $conn, - 'pushEventPHID in (%Ls)', + 'log.pushEventPHID in (%Ls)', $this->pushEventPHIDs); } if ($this->refTypes !== null) { $where[] = qsprintf( $conn, - 'refType IN (%Ls)', + 'log.refType IN (%Ls)', $this->refTypes); } if ($this->newRefs !== null) { $where[] = qsprintf( $conn, - 'refNew IN (%Ls)', + 'log.refNew IN (%Ls)', $this->newRefs); } if ($this->epochMin !== null) { $where[] = qsprintf( $conn, - 'epoch >= %d', + 'log.epoch >= %d', $this->epochMin); } if ($this->epochMax !== null) { $where[] = qsprintf( $conn, - 'epoch <= %d', + 'log.epoch <= %d', $this->epochMax); } + if ($this->blockingHeraldRulePHIDs !== null) { + $where[] = qsprintf( + $conn, + '(event.rejectCode = %d AND event.rejectDetails IN (%Ls))', + PhabricatorRepositoryPushLog::REJECT_HERALD, + $this->blockingHeraldRulePHIDs); + } + return $where; } + protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) { + $joins = parent::buildJoinClauseParts($conn); + + if ($this->shouldJoinPushEventTable()) { + $joins[] = qsprintf( + $conn, + 'JOIN %T event ON event.phid = log.pushEventPHID', + id(new PhabricatorRepositoryPushEvent())->getTableName()); + } + + return $joins; + } + + private function shouldJoinPushEventTable() { + if ($this->blockingHeraldRulePHIDs !== null) { + return true; + } + + return false; + } + public function getQueryApplicationClass() { return 'PhabricatorDiffusionApplication'; } + protected function getPrimaryTableAlias() { + return 'log'; + } + + } diff --git a/src/applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php b/src/applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php index eb2bc6b45b..87b2e44740 100644 --- a/src/applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php +++ b/src/applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php @@ -1,259 +1,269 @@ newQuery(); if ($map['repositoryPHIDs']) { $query->withRepositoryPHIDs($map['repositoryPHIDs']); } if ($map['pusherPHIDs']) { $query->withPusherPHIDs($map['pusherPHIDs']); } if ($map['createdStart'] || $map['createdEnd']) { $query->withEpochBetween( $map['createdStart'], $map['createdEnd']); } + if ($map['blockingHeraldRulePHIDs']) { + $query->withBlockingHeraldRulePHIDs($map['blockingHeraldRulePHIDs']); + } + 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.')), + pht('Search for push logs for specific repositories.')), id(new PhabricatorUsersSearchField()) ->setKey('pusherPHIDs') ->setAliases(array('pusher', 'pushers', 'pusherPHID')) ->setLabel(pht('Pushers')) ->setDescription( - pht('Search for pull logs by specific users.')), + pht('Search for push logs by specific users.')), + id(new PhabricatorSearchDatasourceField()) + ->setDatasource(new HeraldRuleDatasource()) + ->setKey('blockingHeraldRulePHIDs') + ->setLabel(pht('Blocked By')) + ->setDescription( + pht('Search for pushes blocked by particular Herald rules.')), id(new PhabricatorSearchDateField()) ->setLabel(pht('Created After')) ->setKey('createdStart'), id(new PhabricatorSearchDateField()) ->setLabel(pht('Created Before')) ->setKey('createdEnd'), ); } protected function getURI($path) { return '/diffusion/pushlog/'.$path; } protected function getBuiltinQueryNames() { return array( 'all' => pht('All Push 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 DiffusionPushLogListView()) ->setViewer($this->requireViewer()) ->setLogs($logs); return id(new PhabricatorApplicationSearchResultView()) ->setTable($table); } protected function newExportFields() { $viewer = $this->requireViewer(); $fields = array( id(new PhabricatorIDExportField()) ->setKey('pushID') ->setLabel(pht('Push ID')), id(new PhabricatorStringExportField()) ->setKey('unique') ->setLabel(pht('Unique')), id(new PhabricatorStringExportField()) ->setKey('protocol') ->setLabel(pht('Protocol')), id(new PhabricatorPHIDExportField()) ->setKey('repositoryPHID') ->setLabel(pht('Repository PHID')), id(new PhabricatorStringExportField()) ->setKey('repository') ->setLabel(pht('Repository')), id(new PhabricatorPHIDExportField()) ->setKey('pusherPHID') ->setLabel(pht('Pusher PHID')), id(new PhabricatorStringExportField()) ->setKey('pusher') ->setLabel(pht('Pusher')), id(new PhabricatorPHIDExportField()) ->setKey('devicePHID') ->setLabel(pht('Device PHID')), id(new PhabricatorStringExportField()) ->setKey('device') ->setLabel(pht('Device')), id(new PhabricatorStringExportField()) ->setKey('type') ->setLabel(pht('Ref Type')), id(new PhabricatorStringExportField()) ->setKey('name') ->setLabel(pht('Ref Name')), id(new PhabricatorStringExportField()) ->setKey('old') ->setLabel(pht('Ref Old')), id(new PhabricatorStringExportField()) ->setKey('new') ->setLabel(pht('Ref New')), id(new PhabricatorIntExportField()) ->setKey('flags') ->setLabel(pht('Flags')), id(new PhabricatorStringListExportField()) ->setKey('flagNames') ->setLabel(pht('Flag Names')), id(new PhabricatorIntExportField()) ->setKey('result') ->setLabel(pht('Result')), id(new PhabricatorStringExportField()) ->setKey('resultName') ->setLabel(pht('Result Name')), id(new PhabricatorStringExportField()) ->setKey('resultDetails') ->setLabel(pht('Result Details')), id(new PhabricatorIntExportField()) ->setKey('writeWait') ->setLabel(pht('Write Wait (us)')), id(new PhabricatorIntExportField()) ->setKey('readWait') ->setLabel(pht('Read Wait (us)')), id(new PhabricatorIntExportField()) ->setKey('hostWait') ->setLabel(pht('Host Wait (us)')), ); if ($viewer->getIsAdmin()) { $fields[] = id(new PhabricatorStringExportField()) ->setKey('remoteAddress') ->setLabel(pht('Remote Address')); } return $fields; } protected function newExportData(array $logs) { $viewer = $this->requireViewer(); $phids = array(); foreach ($logs as $log) { $phids[] = $log->getPusherPHID(); $phids[] = $log->getDevicePHID(); $phids[] = $log->getPushEvent()->getRepositoryPHID(); } $handles = $viewer->loadHandles($phids); $flag_map = PhabricatorRepositoryPushLog::getFlagDisplayNames(); $reject_map = PhabricatorRepositoryPushLog::getRejectCodeDisplayNames(); $export = array(); foreach ($logs as $log) { $event = $log->getPushEvent(); $repository_phid = $event->getRepositoryPHID(); if ($repository_phid) { $repository_name = $handles[$repository_phid]->getName(); } else { $repository_name = null; } $pusher_phid = $log->getPusherPHID(); if ($pusher_phid) { $pusher_name = $handles[$pusher_phid]->getName(); } else { $pusher_name = null; } $device_phid = $log->getDevicePHID(); if ($device_phid) { $device_name = $handles[$device_phid]->getName(); } else { $device_name = null; } $flags = $log->getChangeFlags(); $flag_names = array(); foreach ($flag_map as $flag_key => $flag_name) { if (($flags & $flag_key) === $flag_key) { $flag_names[] = $flag_name; } } $result = $event->getRejectCode(); $result_name = idx($reject_map, $result, pht('Unknown ("%s")', $result)); $map = array( 'pushID' => $event->getID(), 'unique' => $event->getRequestIdentifier(), 'protocol' => $event->getRemoteProtocol(), 'repositoryPHID' => $repository_phid, 'repository' => $repository_name, 'pusherPHID' => $pusher_phid, 'pusher' => $pusher_name, 'devicePHID' => $device_phid, 'device' => $device_name, 'type' => $log->getRefType(), 'name' => $log->getRefName(), 'old' => $log->getRefOld(), 'new' => $log->getRefNew(), 'flags' => $flags, 'flagNames' => $flag_names, 'result' => $result, 'resultName' => $result_name, 'resultDetails' => $event->getRejectDetails(), 'writeWait' => $event->getWriteWait(), 'readWait' => $event->getReadWait(), 'hostWait' => $event->getHostWait(), ); if ($viewer->getIsAdmin()) { $map['remoteAddress'] = $event->getRemoteAddress(); } $export[] = $map; } return $export; } } diff --git a/src/applications/repository/storage/PhabricatorRepositoryPushEvent.php b/src/applications/repository/storage/PhabricatorRepositoryPushEvent.php index e44f99df4d..682b367926 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryPushEvent.php +++ b/src/applications/repository/storage/PhabricatorRepositoryPushEvent.php @@ -1,103 +1,106 @@ setPusherPHID($viewer->getPHID()); } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_TIMESTAMPS => false, self::CONFIG_COLUMN_SCHEMA => array( 'requestIdentifier' => 'bytes12?', 'remoteAddress' => 'ipaddress?', 'remoteProtocol' => 'text32?', 'rejectCode' => 'uint32', 'rejectDetails' => 'text64?', 'writeWait' => 'uint64?', 'readWait' => 'uint64?', 'hostWait' => 'uint64?', ), self::CONFIG_KEY_SCHEMA => array( 'key_repository' => array( 'columns' => array('repositoryPHID'), ), 'key_identifier' => array( 'columns' => array('requestIdentifier'), ), + 'key_reject' => array( + 'columns' => array('rejectCode', 'rejectDetails'), + ), ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorRepositoryPushEventPHIDType::TYPECONST); } public function attachRepository(PhabricatorRepository $repository) { $this->repository = $repository; return $this; } public function getRepository() { return $this->assertAttached($this->repository); } public function attachLogs(array $logs) { $this->logs = $logs; return $this; } public function getLogs() { return $this->assertAttached($this->logs); } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, ); } public function getPolicy($capability) { return $this->getRepository()->getPolicy($capability); } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return $this->getRepository()->hasAutomaticCapability($capability, $viewer); } public function describeAutomaticCapability($capability) { return pht( "A repository's push events are visible to users who can see the ". "repository."); } }