Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/repository/query/PhabricatorRepositoryQuery.php b/src/applications/repository/query/PhabricatorRepositoryQuery.php
index 92d8b95adf..327fe36ba8 100644
--- a/src/applications/repository/query/PhabricatorRepositoryQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryQuery.php
@@ -1,325 +1,338 @@
<?php
final class PhabricatorRepositoryQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $callsigns;
private $types;
private $uuids;
+ private $nameContains;
const STATUS_OPEN = 'status-open';
const STATUS_CLOSED = 'status-closed';
const STATUS_ALL = 'status-all';
private $status = self::STATUS_ALL;
const ORDER_CREATED = 'order-created';
const ORDER_COMMITTED = 'order-committed';
const ORDER_CALLSIGN = 'order-callsign';
const ORDER_NAME = 'order-name';
private $order = self::ORDER_CREATED;
private $needMostRecentCommits;
private $needCommitCounts;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCallsigns(array $callsigns) {
$this->callsigns = $callsigns;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withTypes(array $types) {
$this->types = $types;
return $this;
}
public function withUUIDs(array $uuids) {
$this->uuids = $uuids;
return $this;
}
+ public function withNameContains($contains) {
+ $this->nameContains = $contains;
+ return $this;
+ }
+
public function needCommitCounts($need_counts) {
$this->needCommitCounts = $need_counts;
return $this;
}
public function needMostRecentCommits($need_commits) {
$this->needMostRecentCommits = $need_commits;
return $this;
}
public function setOrder($order) {
$this->order = $order;
return $this;
}
protected function loadPage() {
$table = new PhabricatorRepository();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T r %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinsClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$repositories = $table->loadAllFromArray($data);
if ($this->needCommitCounts) {
$sizes = ipull($data, 'size', 'id');
foreach ($repositories as $id => $repository) {
$repository->attachCommitCount(nonempty($sizes[$id], 0));
}
}
if ($this->needMostRecentCommits) {
$commit_ids = ipull($data, 'lastCommitID', 'id');
$commit_ids = array_filter($commit_ids);
if ($commit_ids) {
$commits = id(new DiffusionCommitQuery())
->setViewer($this->getViewer())
->withIDs($commit_ids)
->execute();
} else {
$commits = array();
}
foreach ($repositories as $id => $repository) {
$commit = null;
if (idx($commit_ids, $id)) {
$commit = idx($commits, $commit_ids[$id]);
}
$repository->attachMostRecentCommit($commit);
}
}
return $repositories;
}
public function willFilterPage(array $repositories) {
assert_instances_of($repositories, 'PhabricatorRepository');
// TODO: Denormalize repository status into the PhabricatorRepository
// table so we can do this filtering in the database.
foreach ($repositories as $key => $repo) {
$status = $this->status;
switch ($status) {
case self::STATUS_OPEN:
if (!$repo->isTracked()) {
unset($repositories[$key]);
}
break;
case self::STATUS_CLOSED:
if ($repo->isTracked()) {
unset($repositories[$key]);
}
break;
case self::STATUS_ALL:
break;
default:
throw new Exception("Unknown status '{$status}'!");
}
}
return $repositories;
}
public function getReversePaging() {
switch ($this->order) {
case self::ORDER_CALLSIGN:
case self::ORDER_NAME:
return true;
}
return false;
}
protected function getPagingColumn() {
$order = $this->order;
switch ($order) {
case self::ORDER_CREATED:
return 'r.id';
case self::ORDER_COMMITTED:
return 's.epoch';
case self::ORDER_CALLSIGN:
return 'r.callsign';
case self::ORDER_NAME:
return 'r.name';
default:
throw new Exception("Unknown order '{$order}!'");
}
}
private function loadCursorObject($id) {
$query = id(new PhabricatorRepositoryQuery())
->setViewer($this->getPagingViewer())
->withIDs(array((int)$id));
if ($this->order == self::ORDER_COMMITTED) {
$query->needMostRecentCommits(true);
}
$results = $query->execute();
return head($results);
}
protected function buildPagingClause(AphrontDatabaseConnection $conn_r) {
$default = parent::buildPagingClause($conn_r);
$before_id = $this->getBeforeID();
$after_id = $this->getAfterID();
if (!$before_id && !$after_id) {
return $default;
}
$order = $this->order;
if ($order == self::ORDER_CREATED) {
return $default;
}
if ($before_id) {
$cursor = $this->loadCursorObject($before_id);
} else {
$cursor = $this->loadCursorObject($after_id);
}
if (!$cursor) {
return null;
}
$id_column = array(
'name' => 'r.id',
'type' => 'int',
'value' => $cursor->getID(),
);
$columns = array();
switch ($order) {
case self::ORDER_COMMITTED:
$commit = $cursor->getMostRecentCommit();
if (!$commit) {
return null;
}
$columns[] = array(
'name' => 's.epoch',
'type' => 'int',
'value' => $commit->getEpoch(),
);
$columns[] = $id_column;
break;
case self::ORDER_CALLSIGN:
$columns[] = array(
'name' => 'r.callsign',
'type' => 'string',
'value' => $cursor->getCallsign(),
'reverse' => true,
);
break;
case self::ORDER_NAME:
$columns[] = array(
'name' => 'r.name',
'type' => 'string',
'value' => $cursor->getName(),
'reverse' => true,
);
$columns[] = $id_column;
break;
default:
throw new Exception("Unknown order '{$order}'!");
}
return $this->buildPagingClauseFromMultipleColumns(
$conn_r,
$columns,
array(
// TODO: Clean up the column ordering stuff and then make this
// depend on getReversePaging().
'reversed' => (bool)($before_id),
));
}
private function buildJoinsClause(AphrontDatabaseConnection $conn_r) {
$joins = array();
$join_summary_table = $this->needCommitCounts ||
$this->needMostRecentCommits ||
($this->order == self::ORDER_COMMITTED);
if ($join_summary_table) {
$joins[] = qsprintf(
$conn_r,
'LEFT JOIN %T s ON r.id = s.repositoryID',
PhabricatorRepository::TABLE_SUMMARY);
}
return implode(' ', $joins);
}
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'r.id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'r.phid IN (%Ls)',
$this->phids);
}
if ($this->callsigns) {
$where[] = qsprintf(
$conn_r,
'r.callsign IN (%Ls)',
$this->callsigns);
}
if ($this->types) {
$where[] = qsprintf(
$conn_r,
'r.versionControlSystem IN (%Ls)',
$this->types);
}
if ($this->uuids) {
$where[] = qsprintf(
$conn_r,
'r.uuid IN (%Ls)',
$this->uuids);
}
+ if (strlen($this->nameContains)) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'name LIKE %~',
+ $this->nameContains);
+ }
+
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationDiffusion';
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositorySearchEngine.php b/src/applications/repository/query/PhabricatorRepositorySearchEngine.php
index 5c6595426a..41dff1056e 100644
--- a/src/applications/repository/query/PhabricatorRepositorySearchEngine.php
+++ b/src/applications/repository/query/PhabricatorRepositorySearchEngine.php
@@ -1,155 +1,167 @@
<?php
final class PhabricatorRepositorySearchEngine
extends PhabricatorApplicationSearchEngine {
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter('callsigns', $request->getStrList('callsigns'));
$saved->setParameter('status', $request->getStr('status'));
$saved->setParameter('order', $request->getStr('order'));
$saved->setParameter('types', $request->getArr('types'));
+ $saved->setParameter('name', $request->getStr('name'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorRepositoryQuery())
->needCommitCounts(true)
->needMostRecentCommits(true);
$callsigns = $saved->getParameter('callsigns');
if ($callsigns) {
$query->withCallsigns($callsigns);
}
$status = $saved->getParameter('status');
$status = idx($this->getStatusValues(), $status);
if ($status) {
$query->withStatus($status);
}
$order = $saved->getParameter('order');
$order = idx($this->getOrderValues(), $order);
if ($order) {
$query->setOrder($order);
} else {
$query->setOrder(head($this->getOrderValues()));
}
$types = $saved->getParameter('types');
if ($types) {
$query->withTypes($types);
}
+ $name = $saved->getParameter('name');
+ if (strlen($name)) {
+ $query->withNameContains($name);
+ }
+
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {
$callsigns = $saved_query->getParameter('callsigns', array());
$types = $saved_query->getParameter('types', array());
$types = array_fuse($types);
+ $name = $saved_query->getParameter('name');
$form
->appendChild(
id(new AphrontFormTextControl())
->setName('callsigns')
->setLabel(pht('Callsigns'))
->setValue(implode(', ', $callsigns)))
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setName('name')
+ ->setLabel(pht('Name Contains'))
+ ->setValue($name))
->appendChild(
id(new AphrontFormSelectControl())
->setName('status')
->setLabel(pht('Status'))
->setValue($saved_query->getParameter('status'))
->setOptions($this->getStatusOptions()));
$type_control = id(new AphrontFormCheckboxControl())
->setLabel(pht('Types'));
$all_types = PhabricatorRepositoryType::getAllRepositoryTypes();
foreach ($all_types as $key => $name) {
$type_control->addCheckbox(
'types[]',
$key,
$name,
isset($types[$key]));
}
$form
->appendChild($type_control)
->appendChild(
id(new AphrontFormSelectControl())
->setName('order')
->setLabel(pht('Order'))
->setValue($saved_query->getParameter('order'))
->setOptions($this->getOrderOptions()));
}
protected function getURI($path) {
return '/diffusion/'.$path;
}
public function getBuiltinQueryNames() {
$names = array(
'active' => pht('Active Repositories'),
'all' => pht('All Repositories'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
return $query->setParameter('status', 'open');
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
private function getStatusOptions() {
return array(
'' => pht('Active and Inactive Repositories'),
'open' => pht('Active Repositories'),
'closed' => pht('Inactive Repositories'),
);
}
private function getStatusValues() {
return array(
'' => PhabricatorRepositoryQuery::STATUS_ALL,
'open' => PhabricatorRepositoryQuery::STATUS_OPEN,
'closed' => PhabricatorRepositoryQuery::STATUS_CLOSED,
);
}
private function getOrderOptions() {
return array(
'committed' => pht('Most Recent Commit'),
'name' => pht('Name'),
'callsign' => pht('Callsign'),
'created' => pht('Date Created'),
);
}
private function getOrderValues() {
return array(
'committed' => PhabricatorRepositoryQuery::ORDER_COMMITTED,
'name' => PhabricatorRepositoryQuery::ORDER_NAME,
'callsign' => PhabricatorRepositoryQuery::ORDER_CALLSIGN,
'created' => PhabricatorRepositoryQuery::ORDER_CREATED,
);
}
}
diff --git a/src/applications/search/engine/PhabricatorJumpNavHandler.php b/src/applications/search/engine/PhabricatorJumpNavHandler.php
index b0e80962f0..e3081dfebd 100644
--- a/src/applications/search/engine/PhabricatorJumpNavHandler.php
+++ b/src/applications/search/engine/PhabricatorJumpNavHandler.php
@@ -1,111 +1,126 @@
<?php
final class PhabricatorJumpNavHandler {
public static function getJumpResponse(PhabricatorUser $viewer, $jump) {
$jump = trim($jump);
$help_href = PhabricatorEnv::getDocLink('article/Jump_Nav_User_Guide.html');
$patterns = array(
'/^help/i' => 'uri:'.$help_href,
'/^a$/i' => 'uri:/audit/',
'/^f$/i' => 'uri:/feed/',
'/^d$/i' => 'uri:/differential/',
'/^r$/i' => 'uri:/diffusion/',
'/^t$/i' => 'uri:/maniphest/',
'/^p$/i' => 'uri:/project/',
'/^u$/i' => 'uri:/people/',
'/^p\s+(.+)$/i' => 'project',
'/^#(.+)$/i' => 'project',
'/^u\s+(\S+)$/i' => 'user',
'/^@(.+)$/i' => 'user',
'/^task:\s*(.+)/i' => 'create-task',
'/^(?:s|symbol)\s+(\S+)/i' => 'find-symbol',
+ '/^r\s+(.+)$/i' => 'find-repository',
);
foreach ($patterns as $pattern => $effect) {
$matches = null;
if (preg_match($pattern, $jump, $matches)) {
if (!strncmp($effect, 'uri:', 4)) {
return id(new AphrontRedirectResponse())
->setURI(substr($effect, 4));
} else {
switch ($effect) {
case 'user':
return id(new AphrontRedirectResponse())
->setURI('/p/'.$matches[1].'/');
case 'project':
$project = self::findCloselyNamedProject($matches[1]);
if ($project) {
return id(new AphrontRedirectResponse())
->setURI('/project/view/'.$project->getID().'/');
} else {
$jump = $matches[1];
}
break;
case 'find-symbol':
$context = '';
$symbol = $matches[1];
$parts = array();
if (preg_match('/(.*)(?:\\.|::|->)(.*)/', $symbol, $parts)) {
$context = '&context='.phutil_escape_uri($parts[1]);
$symbol = $parts[2];
}
return id(new AphrontRedirectResponse())
->setURI("/diffusion/symbol/$symbol/?jump=true$context");
+ case 'find-repository':
+ $name = $matches[1];
+ $repositories = id(new PhabricatorRepositoryQuery())
+ ->setViewer($viewer)
+ ->withNameContains($name)
+ ->execute();
+ if (count($repositories) == 1) {
+ // Just one match, jump to repository.
+ $uri = '/diffusion/'.head($repositories)->getCallsign().'/';
+ } else {
+ // More than one match, jump to search.
+ $uri = urisprintf('/diffusion/?order=name&name=%s', $name);
+ }
+ return id(new AphrontRedirectResponse())->setURI($uri);
case 'create-task':
return id(new AphrontRedirectResponse())
->setURI('/maniphest/task/create/?title='
.phutil_escape_uri($matches[1]));
default:
throw new Exception("Unknown jump effect '{$effect}'!");
}
}
}
}
// If none of the patterns matched, look for an object by name.
$objects = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withNames(array($jump))
->execute();
if (count($objects) == 1) {
$handle = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(mpull($objects, 'getPHID'))
->executeOne();
return id(new AphrontRedirectResponse())->setURI($handle->getURI());
}
return null;
}
private static function findCloselyNamedProject($name) {
$project = id(new PhabricatorProject())->loadOneWhere(
'name = %s',
$name);
if ($project) {
return $project;
} else { // no exact match, try a fuzzy match
$projects = id(new PhabricatorProject())->loadAllWhere(
'name LIKE %~',
$name);
if ($projects) {
$min_name_length = PHP_INT_MAX;
$best_project = null;
foreach ($projects as $project) {
$name_length = strlen($project->getName());
if ($name_length <= $min_name_length) {
$min_name_length = $name_length;
$best_project = $project;
}
}
return $best_project;
} else {
return null;
}
}
}
}
diff --git a/src/docs/user/userguide/jump.diviner b/src/docs/user/userguide/jump.diviner
index 06b1e4fa9d..5910484760 100644
--- a/src/docs/user/userguide/jump.diviner
+++ b/src/docs/user/userguide/jump.diviner
@@ -1,28 +1,29 @@
@title Jump Nav User Guide
@group userguide
Command reference for the jump nav.
= Overview =
The jump nav provides a quick way to navigate to tools and objects: just type
a navigational command into the box and press return.
= Supported Commands =
- **help** - Jump to this document.
- **T** - Jump to Maniphest.
- **T123** - Jump to Maniphest Task 123.
- **D** - Jump to Differential.
- **D123** - Jump to Differential Revision 123.
- **r** - Jump to Diffusion.
- **rXYZ** - Jump to Diffusion Repository XYZ.
- **rXYZabcdef** - Jump to Diffusion Commit rXYZabcdef.
+ - **r <name>** - Search for repositories by name.
- **u** - Jump to People
- **u username** - Jump to username's Profile
- **p** - Jump to Project
- **p Some Project** - Jump to Project: Some Project
- **s SymbolName** - Jump to Symbol SymbolName
- **task: (new title)** - Jumps to Task Creation Page with pre-filled
title.
- **(default)** - Search for input.

File Metadata

Mime Type
text/x-diff
Expires
Wed, Apr 30, 11:33 PM (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
108808
Default Alt Text
(19 KB)

Event Timeline