Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/diffusion/conduit/ConduitAPI_diffusion_diffquery_Method.php b/src/applications/diffusion/conduit/ConduitAPI_diffusion_diffquery_Method.php
index 35cb59854e..6becde1908 100644
--- a/src/applications/diffusion/conduit/ConduitAPI_diffusion_diffquery_Method.php
+++ b/src/applications/diffusion/conduit/ConduitAPI_diffusion_diffquery_Method.php
@@ -1,241 +1,235 @@
<?php
/**
* @group conduit
*/
final class ConduitAPI_diffusion_diffquery_Method
extends ConduitAPI_diffusion_abstractquery_Method {
private $effectiveCommit;
public function getMethodDescription() {
return
'Get diff information from a repository for a specific path at an '.
'(optional) commit.';
}
public function defineReturnType() {
return 'array';
}
protected function defineCustomParamTypes() {
return array(
'path' => 'required string',
'commit' => 'optional string',
);
}
protected function getResult(ConduitAPIRequest $request) {
$result = parent::getResult($request);
return array(
'changes' => mpull($result, 'toDictionary'),
- 'effectiveCommit' => $this->getEffectiveCommit($request));
+ 'effectiveCommit' => $this->getEffectiveCommit($request),
+ );
}
protected function getGitResult(ConduitAPIRequest $request) {
return $this->getGitOrMercurialResult($request);
}
protected function getMercurialResult(ConduitAPIRequest $request) {
return $this->getGitOrMercurialResult($request);
}
/**
* NOTE: We have to work particularly hard for SVN as compared to other VCS.
* That's okay but means this shares little code with the other VCS.
*/
protected function getSVNResult(ConduitAPIRequest $request) {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$effective_commit = $this->getEffectiveCommit($request);
if (!$effective_commit) {
return $this->getEmptyResult();
}
$drequest = clone $drequest;
$drequest->setCommit($effective_commit);
$path_change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
$drequest);
$path_changes = $path_change_query->loadChanges();
$path = null;
foreach ($path_changes as $change) {
if ($change->getPath() == $drequest->getPath()) {
$path = $change;
}
}
if (!$path) {
return $this->getEmptyResult();
}
$change_type = $path->getChangeType();
switch ($change_type) {
case DifferentialChangeType::TYPE_MULTICOPY:
case DifferentialChangeType::TYPE_DELETE:
if ($path->getTargetPath()) {
$old = array(
$path->getTargetPath(),
$path->getTargetCommitIdentifier());
} else {
$old = array($path->getPath(), $path->getCommitIdentifier() - 1);
}
$old_name = $path->getPath();
$new_name = '';
$new = null;
break;
case DifferentialChangeType::TYPE_ADD:
$old = null;
$new = array($path->getPath(), $path->getCommitIdentifier());
$old_name = '';
$new_name = $path->getPath();
break;
case DifferentialChangeType::TYPE_MOVE_HERE:
case DifferentialChangeType::TYPE_COPY_HERE:
$old = array(
$path->getTargetPath(),
$path->getTargetCommitIdentifier());
$new = array($path->getPath(), $path->getCommitIdentifier());
$old_name = $path->getTargetPath();
$new_name = $path->getPath();
break;
case DifferentialChangeType::TYPE_MOVE_AWAY:
$old = array(
$path->getPath(),
$path->getCommitIdentifier() - 1);
$old_name = $path->getPath();
$new_name = null;
$new = null;
break;
default:
$old = array($path->getPath(), $path->getCommitIdentifier() - 1);
$new = array($path->getPath(), $path->getCommitIdentifier());
$old_name = $path->getPath();
$new_name = $path->getPath();
break;
}
$futures = array(
'old' => $this->buildSVNContentFuture($old),
'new' => $this->buildSVNContentFuture($new),
);
$futures = array_filter($futures);
foreach (Futures($futures) as $key => $future) {
$stdout = '';
try {
list($stdout) = $future->resolvex();
} catch (CommandException $e) {
if ($path->getFileType() != DifferentialChangeType::FILE_DIRECTORY) {
throw $e;
}
}
$futures[$key] = $stdout;
}
$old_data = idx($futures, 'old', '');
$new_data = idx($futures, 'new', '');
$engine = new PhabricatorDifferenceEngine();
$engine->setOldName($old_name);
$engine->setNewName($new_name);
$raw_diff = $engine->generateRawDiffFromFileContent($old_data, $new_data);
$arcanist_changes = DiffusionPathChange::convertToArcanistChanges(
$path_changes);
$parser = $this->getDefaultParser();
$parser->setChanges($arcanist_changes);
$parser->forcePath($path->getPath());
$changes = $parser->parseDiff($raw_diff);
$change = $changes[$path->getPath()];
return array($change);
}
private function getEffectiveCommit(ConduitAPIRequest $request) {
if ($this->effectiveCommit === null) {
$drequest = $this->getDiffusionRequest();
- $user = $request->getUser();
- $commit = null;
- $conduit_result = DiffusionQuery::callConduitWithDiffusionRequest(
- $user,
+ $path = $drequest->getPath();
+ $result = DiffusionQuery::callConduitWithDiffusionRequest(
+ $request->getUser(),
$drequest,
'diffusion.lastmodifiedquery',
array(
- 'commit' => $drequest->getCommit(),
- 'path' => $drequest->getPath()));
- $c_dict = $conduit_result['commit'];
- if ($c_dict) {
- $commit = PhabricatorRepositoryCommit::newFromDictionary($c_dict);
- }
- if (!$commit) {
- // TODO: Improve error messages here.
- return null;
- }
- $this->effectiveCommit = $commit->getCommitIdentifier();
+ 'paths' => array($path => $drequest->getCommit()),
+ ));
+
+ $this->effectiveCommit = idx($result, $path);
}
+
return $this->effectiveCommit;
}
private function buildSVNContentFuture($spec) {
if (!$spec) {
return null;
}
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
list($ref, $rev) = $spec;
return $repository->getRemoteCommandFuture(
'cat %s',
$repository->getSubversionPathURI($ref, $rev));
}
private function getGitOrMercurialResult(ConduitAPIRequest $request) {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$effective_commit = $this->getEffectiveCommit($request);
if (!$effective_commit) {
return $this->getEmptyResult(1);
}
// TODO: This side effect is kind of sketchy.
$drequest->setCommit($effective_commit);
$raw_query = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest);
$raw_diff = $raw_query->loadRawDiff();
if (!$raw_diff) {
return $this->getEmptyResult(2);
}
$parser = $this->getDefaultParser();
$changes = $parser->parseDiff($raw_diff);
return $changes;
}
private function getDefaultParser() {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$parser = new ArcanistDiffParser();
$try_encoding = $repository->getDetail('encoding');
if ($try_encoding) {
$parser->setTryEncoding($try_encoding);
}
$parser->setDetectBinaryFiles(true);
return $parser;
}
private function getEmptyResult() {
return array();
}
}
diff --git a/src/applications/diffusion/conduit/ConduitAPI_diffusion_lastmodifiedquery_Method.php b/src/applications/diffusion/conduit/ConduitAPI_diffusion_lastmodifiedquery_Method.php
index 8cfa1f6f55..d0101c4b15 100644
--- a/src/applications/diffusion/conduit/ConduitAPI_diffusion_lastmodifiedquery_Method.php
+++ b/src/applications/diffusion/conduit/ConduitAPI_diffusion_lastmodifiedquery_Method.php
@@ -1,115 +1,84 @@
<?php
-/**
- * @group conduit
- */
final class ConduitAPI_diffusion_lastmodifiedquery_Method
extends ConduitAPI_diffusion_abstractquery_Method {
public function getMethodDescription() {
- return
- 'Get last modified information from a repository for a specific commit '.
- 'at a specific path.';
+ return pht('Get the commits at which paths were last modified.');
}
public function defineReturnType() {
- return 'array';
+ return 'map<string, string>';
}
protected function defineCustomParamTypes() {
return array(
- 'commit' => 'required string',
- 'path' => 'required string',
+ 'paths' => 'required map<string, string>',
);
}
- protected function getResult(ConduitAPIRequest $request) {
- list($commit, $commit_data) = parent::getResult($request);
- if ($commit) {
- $commit = $commit->toDictionary();
- }
- if ($commit_data) {
- $commit_data = $commit_data->toDictionary();
- }
- return array(
- 'commit' => $commit,
- 'commitData' => $commit_data);
- }
-
protected function getGitResult(ConduitAPIRequest $request) {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
- list($hash) = $repository->execxLocalCommand(
- 'log -n1 --format=%%H %s -- %s',
- $drequest->getCommit(),
- $drequest->getPath());
- $hash = trim($hash);
+ $result = array();
+ foreach ($request->getValue('paths') as $path => $commit) {
+ list($hash) = $repository->execxLocalCommand(
+ 'log -n1 --format=%%H %s -- %s',
+ $commit,
+ $path);
+ $result[$path] = trim($hash);
+ }
- return $this->loadDataFromHash($hash);
+ return $result;
}
protected function getSVNResult(ConduitAPIRequest $request) {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
- $path = $drequest->getPath();
-
- $history_result = DiffusionQuery::callConduitWithDiffusionRequest(
- $request->getUser(),
- $drequest,
- 'diffusion.historyquery',
- array(
- 'commit' => $drequest->getCommit(),
- 'path' => $path,
- 'limit' => 1,
- 'offset' => 0,
- 'needDirectChanges' => true,
- 'needChildChanges' => true));
- $history_array = DiffusionPathChange::newFromConduit(
- $history_result['pathChanges']);
-
- if (!$history_array) {
- return array(array(), array());
+ $result = array();
+ foreach ($request->getValue('paths') as $path => $commit) {
+ $history_result = DiffusionQuery::callConduitWithDiffusionRequest(
+ $request->getUser(),
+ $drequest,
+ 'diffusion.historyquery',
+ array(
+ 'commit' => $commit,
+ 'path' => $path,
+ 'limit' => 1,
+ 'offset' => 0,
+ 'needDirectChanges' => true,
+ 'needChildChanges' => true,
+ ));
+
+ $history_array = DiffusionPathChange::newFromConduit(
+ $history_result['pathChanges']);
+ if ($history_array) {
+ $result[$path] = head($history_array)
+ ->getCommit()
+ ->getCommitIdentifier();
+ }
}
- $history = reset($history_array);
-
- return array($history->getCommit(), $history->getCommitData());
+ return $result;
}
protected function getMercurialResult(ConduitAPIRequest $request) {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
- $path = $drequest->getPath();
-
- list($hash) = $repository->execxLocalCommand(
- 'log --template %s --limit 1 --removed --rev %s -- %s',
- '{node}',
- hgsprintf('reverse(ancestors(%s))', $drequest->getCommit()),
- nonempty(ltrim($path, '/'), '.'));
-
- return $this->loadDataFromHash($hash);
- }
-
- private function loadDataFromHash($hash) {
- $drequest = $this->getDiffusionRequest();
- $repository = $drequest->getRepository();
-
- $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere(
- 'repositoryID = %d AND commitIdentifier = %s',
- $repository->getID(),
- $hash);
-
- if ($commit) {
- $commit_data = $commit->loadCommitData();
- } else {
- $commit = array();
- $commit_data = array();
+ $result = array();
+ foreach ($request->getValue('paths') as $path => $commit) {
+ list($hash) = $repository->execxLocalCommand(
+ 'log --template %s --limit 1 --removed --rev %s -- %s',
+ '{node}',
+ hgsprintf('reverse(ancestors(%s))', $commit),
+ nonempty(ltrim($path, '/'), '.'));
+ $result[$path] = trim($hash);
}
- return array($commit, $commit_data);
+ return $result;
}
}
diff --git a/src/applications/diffusion/controller/DiffusionLastModifiedController.php b/src/applications/diffusion/controller/DiffusionLastModifiedController.php
index fd10082af6..7b96f6ab7f 100644
--- a/src/applications/diffusion/controller/DiffusionLastModifiedController.php
+++ b/src/applications/diffusion/controller/DiffusionLastModifiedController.php
@@ -1,155 +1,158 @@
<?php
final class DiffusionLastModifiedController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
public function processRequest() {
$drequest = $this->getDiffusionRequest();
$request = $this->getRequest();
+ $viewer = $request->getUser();
$paths = $request->getStr('paths');
$paths = json_decode($paths, true);
if (!is_array($paths)) {
return new Aphront400Response();
}
+ $modified_map = $this->callConduitWithDiffusionRequest(
+ 'diffusion.lastmodifiedquery',
+ array(
+ 'paths' => array_fill_keys($paths, $drequest->getCommit()),
+ ));
+
+ if ($modified_map) {
+ $commit_map = id(new DiffusionCommitQuery())
+ ->setViewer($viewer)
+ ->withRepository($drequest->getRepository())
+ ->withIdentifiers(array_values($modified_map))
+ ->needCommitData(true)
+ ->execute();
+ $commit_map = mpull($commit_map, null, 'getCommitIdentifier');
+ } else {
+ $commit_map = array();
+ }
+
$commits = array();
foreach ($paths as $path) {
- $prequest = clone $drequest;
- $prequest->setPath($path);
-
- $conduit_result = $this->callConduitWithDiffusionRequest(
- 'diffusion.lastmodifiedquery',
- array(
- 'commit' => $prequest->getCommit(),
- 'path' => $prequest->getPath(),
- ));
-
- $commit = PhabricatorRepositoryCommit::newFromDictionary(
- $conduit_result['commit']);
-
- $commit_data = PhabricatorRepositoryCommitData::newFromDictionary(
- $conduit_result['commitData']);
-
- $commit->attachCommitData($commit_data);
-
- $phids = array();
- if ($commit_data) {
- if ($commit_data->getCommitDetail('authorPHID')) {
- $phids[$commit_data->getCommitDetail('authorPHID')] = true;
- }
- if ($commit_data->getCommitDetail('committerPHID')) {
- $phids[$commit_data->getCommitDetail('committerPHID')] = true;
+ $modified_at = idx($modified_map, $path);
+ if ($modified_at) {
+ $commit = idx($commit_map, $modified_at);
+ if ($commit) {
+ $commits[$path] = $commit;
}
}
-
- $commits[$path] = $commit;
}
- $phids = array_keys($phids);
+ $phids = array();
+ foreach ($commits as $commit) {
+ $data = $commit->getCommitData();
+ $phids[] = $data->getCommitDetail('authorPHID');
+ $phids[] = $data->getCommitDetail('committerPHID');
+ }
+ $phids = array_filter($phids);
$handles = $this->loadViewerHandles($phids);
$branch = $drequest->loadBranch();
- if ($branch) {
+ if ($branch && $commits) {
$lint_query = id(new DiffusionLintCountQuery())
->withBranchIDs(array($branch->getID()))
->withPaths(array_keys($commits));
if ($drequest->getLint()) {
$lint_query->withCodes(array($drequest->getLint()));
}
$lint = $lint_query->execute();
} else {
$lint = array();
}
$output = array();
foreach ($commits as $path => $commit) {
$prequest = clone $drequest;
$prequest->setPath($path);
$output[$path] = $this->renderColumns(
$prequest,
$handles,
$commit,
idx($lint, $path));
}
return id(new AphrontAjaxResponse())->setContent($output);
}
private function renderColumns(
DiffusionRequest $drequest,
array $handles,
PhabricatorRepositoryCommit $commit = null,
$lint = null) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$viewer = $this->getRequest()->getUser();
if ($commit) {
$epoch = $commit->getEpoch();
$modified = DiffusionView::linkCommit(
$drequest->getRepository(),
$commit->getCommitIdentifier());
$date = phabricator_date($epoch, $viewer);
$time = phabricator_time($epoch, $viewer);
} else {
$modified = '';
$date = '';
$time = '';
}
$data = $commit->getCommitData();
if ($data) {
$author_phid = $data->getCommitDetail('authorPHID');
if ($author_phid && isset($handles[$author_phid])) {
$author = $handles[$author_phid]->renderLink();
} else {
$author = DiffusionView::renderName($data->getAuthorName());
}
$committer = $data->getCommitDetail('committer');
if ($committer) {
$committer_phid = $data->getCommitDetail('committerPHID');
if ($committer_phid && isset($handles[$committer_phid])) {
$committer = $handles[$committer_phid]->renderLink();
} else {
$committer = DiffusionView::renderName($committer);
}
if ($author != $committer) {
$author = hsprintf('%s/%s', $author, $committer);
}
}
$details = AphrontTableView::renderSingleDisplayLine($data->getSummary());
} else {
$author = '';
$details = '';
}
$return = array(
'commit' => $modified,
'date' => $date,
'time' => $time,
'author' => $author,
'details' => $details,
);
if ($lint !== null) {
$return['lint'] = phutil_tag(
'a',
array('href' => $drequest->generateURI(array(
'action' => 'lint',
'lint' => null,
))),
number_format($lint));
}
return $return;
}
}
diff --git a/src/applications/diffusion/query/DiffusionCommitQuery.php b/src/applications/diffusion/query/DiffusionCommitQuery.php
index 0b8d9cc523..1b7b90d706 100644
--- a/src/applications/diffusion/query/DiffusionCommitQuery.php
+++ b/src/applications/diffusion/query/DiffusionCommitQuery.php
@@ -1,512 +1,515 @@
<?php
final class DiffusionCommitQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $defaultRepository;
private $identifiers;
private $repositoryIDs;
private $identifierMap;
private $needAuditRequests;
private $auditIDs;
private $auditorPHIDs;
private $auditAwaitingUser;
private $auditStatus;
const AUDIT_STATUS_ANY = 'audit-status-any';
const AUDIT_STATUS_OPEN = 'audit-status-open';
const AUDIT_STATUS_CONCERN = 'audit-status-concern';
private $loadAuditIds;
private $needCommitData;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
/**
* Load commits by partial or full identifiers, e.g. "rXab82393", "rX1234",
* or "a9caf12". When an identifier matches multiple commits, they will all
* be returned; callers should be prepared to deal with more results than
* they queried for.
*/
public function withIdentifiers(array $identifiers) {
$this->identifiers = $identifiers;
return $this;
}
/**
* Look up commits in a specific repository. This is a shorthand for calling
* @{method:withDefaultRepository} and @{method:withRepositoryIDs}.
*/
public function withRepository(PhabricatorRepository $repository) {
$this->withDefaultRepository($repository);
$this->withRepositoryIDs(array($repository->getID()));
return $this;
}
/**
* If a default repository is provided, ambiguous commit identifiers will
* be assumed to belong to the default repository.
*
* For example, "r123" appearing in a commit message in repository X is
* likely to be unambiguously "rX123". Normally the reference would be
* considered ambiguous, but if you provide a default repository it will
* be correctly resolved.
*/
public function withDefaultRepository(PhabricatorRepository $repository) {
$this->defaultRepository = $repository;
return $this;
}
public function withRepositoryIDs(array $repository_ids) {
$this->repositoryIDs = $repository_ids;
return $this;
}
public function needCommitData($need) {
$this->needCommitData = $need;
return $this;
}
public function needAuditRequests($need) {
$this->needAuditRequests = $need;
return $this;
}
/**
* Retuns true if we should join the audit table, either because we're
* interested in the information if it's available or because matching
* rows must always have it.
*/
private function shouldJoinAudits() {
return
$this->needAuditRequests ||
$this->auditStatus ||
$this->rowsMustHaveAudits();
}
/**
* Return true if we should `JOIN` (vs `LEFT JOIN`) the audit table, because
* matching commits will always have audit rows.
*/
private function rowsMustHaveAudits() {
return
$this->auditIDs ||
$this->auditorPHIDs ||
$this->auditAwaitingUser;
}
public function withAuditIDs(array $ids) {
$this->auditIDs = $ids;
return $this;
}
public function withAuditorPHIDs(array $auditor_phids) {
$this->auditorPHIDs = $auditor_phids;
return $this;
}
public function withAuditAwaitingUser(PhabricatorUser $user) {
$this->auditAwaitingUser = $user;
return $this;
}
public function withAuditStatus($status) {
$this->auditStatus = $status;
return $this;
}
public function getIdentifierMap() {
if ($this->identifierMap === null) {
throw new Exception(
"You must execute() the query before accessing the identifier map.");
}
return $this->identifierMap;
}
protected function getPagingColumn() {
return 'commit.id';
}
protected function willExecute() {
if ($this->identifierMap === null) {
$this->identifierMap = array();
}
}
protected function loadPage() {
$table = new PhabricatorRepositoryCommit();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT commit.* %Q FROM %T commit %Q %Q %Q %Q',
$this->buildAuditSelect($conn_r),
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
if ($this->shouldJoinAudits()) {
$this->loadAuditIds = ipull($data, 'audit_id');
}
return $table->loadAllFromArray($data);
}
private function buildAuditSelect($conn_r) {
if ($this->shouldJoinAudits()) {
return qsprintf(
$conn_r,
', audit.id as audit_id');
}
return '';
}
protected function willFilterPage(array $commits) {
$repository_ids = mpull($commits, 'getRepositoryID', 'getRepositoryID');
$repos = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withIDs($repository_ids)
->execute();
foreach ($commits as $key => $commit) {
$repo = idx($repos, $commit->getRepositoryID());
if ($repo) {
$commit->attachRepository($repo);
} else {
unset($commits[$key]);
}
}
if ($this->identifiers !== null) {
$ids = array_fuse($this->identifiers);
$min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
$result = array();
foreach ($commits as $commit) {
$prefix = 'r'.$commit->getRepository()->getCallsign();
$suffix = $commit->getCommitIdentifier();
if ($commit->getRepository()->isSVN()) {
if (isset($ids[$prefix.$suffix])) {
$result[$prefix.$suffix][] = $commit;
}
} else {
// This awkward contruction is so we can link the commits up in O(N)
// time instead of O(N^2).
for ($ii = $min_qualified; $ii <= strlen($suffix); $ii++) {
$part = substr($suffix, 0, $ii);
if (isset($ids[$prefix.$part])) {
$result[$prefix.$part][] = $commit;
}
if (isset($ids[$part])) {
$result[$part][] = $commit;
}
}
}
}
foreach ($result as $identifier => $matching_commits) {
if (count($matching_commits) == 1) {
$result[$identifier] = head($matching_commits);
} else {
// This reference is ambiguous (it matches more than one commit) so
// don't link it
unset($result[$identifier]);
}
}
$this->identifierMap += $result;
}
return $commits;
}
protected function didFilterPage(array $commits) {
if ($this->needCommitData) {
$data = id(new PhabricatorRepositoryCommitData())->loadAllWhere(
'commitID in (%Ld)',
mpull($commits, 'getID'));
$data = mpull($data, null, 'getCommitID');
foreach ($commits as $commit) {
$commit_data = idx($data, $commit->getID());
+ if (!$commit_data) {
+ $commit_data = new PhabricatorRepositoryCommitData();
+ }
$commit->attachCommitData($commit_data);
}
}
if ($this->shouldJoinAudits()) {
$load_ids = array_filter($this->loadAuditIds);
if ($load_ids) {
$requests = id(new PhabricatorRepositoryAuditRequest())
->loadAllWhere('id IN (%Ld)', $this->loadAuditIds);
} else {
$requests = array();
}
$requests = mgroup($requests, 'getCommitPHID');
foreach ($commits as $commit) {
$audit_requests = idx($requests, $commit->getPHID(), array());
$commit->attachAudits($audit_requests);
foreach ($audit_requests as $audit_request) {
$audit_request->attachCommit($commit);
}
}
}
return $commits;
}
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'commit.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'commit.phid IN (%Ls)',
$this->phids);
}
if ($this->repositoryIDs !== null) {
$where[] = qsprintf(
$conn_r,
'commit.repositoryID IN (%Ld)',
$this->repositoryIDs);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'commit.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->identifiers !== null) {
$min_unqualified = PhabricatorRepository::MINIMUM_UNQUALIFIED_HASH;
$min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
$refs = array();
$bare = array();
foreach ($this->identifiers as $identifier) {
$matches = null;
preg_match('/^(?:r([A-Z]+))?(.*)$/', $identifier, $matches);
$repo = nonempty($matches[1], null);
$identifier = nonempty($matches[2], null);
if ($repo === null) {
if ($this->defaultRepository) {
$repo = $this->defaultRepository->getCallsign();
}
}
if ($repo === null) {
if (strlen($identifier) < $min_unqualified) {
continue;
}
$bare[] = $identifier;
} else {
$refs[] = array(
'callsign' => $repo,
'identifier' => $identifier,
);
}
}
$sql = array();
foreach ($bare as $identifier) {
$sql[] = qsprintf(
$conn_r,
'(commit.commitIdentifier LIKE %> AND '.
'LENGTH(commit.commitIdentifier) = 40)',
$identifier);
}
if ($refs) {
$callsigns = ipull($refs, 'callsign');
$repos = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withCallsigns($callsigns)
->execute();
$repos = mpull($repos, null, 'getCallsign');
foreach ($refs as $key => $ref) {
$repo = idx($repos, $ref['callsign']);
if (!$repo) {
continue;
}
if ($repo->isSVN()) {
if (!ctype_digit($ref['identifier'])) {
continue;
}
$sql[] = qsprintf(
$conn_r,
'(commit.repositoryID = %d AND commit.commitIdentifier = %s)',
$repo->getID(),
// NOTE: Because the 'commitIdentifier' column is a string, MySQL
// ignores the index if we hand it an integer. Hand it a string.
// See T3377.
(int)$ref['identifier']);
} else {
if (strlen($ref['identifier']) < $min_qualified) {
continue;
}
$sql[] = qsprintf(
$conn_r,
'(commit.repositoryID = %d AND commit.commitIdentifier LIKE %>)',
$repo->getID(),
$ref['identifier']);
}
}
}
if (!$sql) {
// If we discarded all possible identifiers (e.g., they all referenced
// bogus repositories or were all too short), make sure the query finds
// nothing.
throw new PhabricatorEmptyQueryException(
pht('No commit identifiers.'));
}
$where[] = '('.implode(' OR ', $sql).')';
}
if ($this->auditIDs !== null) {
$where[] = qsprintf(
$conn_r,
'audit.id IN (%Ld)',
$this->auditIDs);
}
if ($this->auditorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'audit.auditorPHID IN (%Ls)',
$this->auditorPHIDs);
}
if ($this->auditAwaitingUser) {
$awaiting_user_phid = $this->auditAwaitingUser->getPHID();
// Exclude package and project audits associated with commits where
// the user is the author.
$where[] = qsprintf(
$conn_r,
'(commit.authorPHID IS NULL OR commit.authorPHID != %s)
OR (audit.auditorPHID = %s)',
$awaiting_user_phid,
$awaiting_user_phid);
}
$status = $this->auditStatus;
if ($status !== null) {
switch ($status) {
case self::AUDIT_STATUS_CONCERN:
$where[] = qsprintf(
$conn_r,
'audit.auditStatus = %s',
PhabricatorAuditStatusConstants::CONCERNED);
break;
case self::AUDIT_STATUS_OPEN:
$where[] = qsprintf(
$conn_r,
'audit.auditStatus in (%Ls)',
PhabricatorAuditStatusConstants::getOpenStatusConstants());
if ($this->auditAwaitingUser) {
$where[] = qsprintf(
$conn_r,
'awaiting.auditStatus IS NULL OR awaiting.auditStatus != %s',
PhabricatorAuditStatusConstants::RESIGNED);
}
break;
case self::AUDIT_STATUS_ANY:
break;
default:
$valid = array(
self::AUDIT_STATUS_ANY,
self::AUDIT_STATUS_OPEN,
self::AUDIT_STATUS_CONCERN,
);
throw new Exception(
"Unknown audit status '{$status}'! Valid statuses are: ".
implode(', ', $valid));
}
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function didFilterResults(array $filtered) {
if ($this->identifierMap) {
foreach ($this->identifierMap as $name => $commit) {
if (isset($filtered[$commit->getPHID()])) {
unset($this->identifierMap[$name]);
}
}
}
}
private function buildJoinClause($conn_r) {
$joins = array();
$audit_request = new PhabricatorRepositoryAuditRequest();
if ($this->shouldJoinAudits()) {
$joins[] = qsprintf(
$conn_r,
'%Q %T audit ON commit.phid = audit.commitPHID',
($this->rowsMustHaveAudits() ? 'JOIN' : 'LEFT JOIN'),
$audit_request->getTableName());
}
if ($this->auditAwaitingUser) {
// Join the request table on the awaiting user's requests, so we can
// filter out package and project requests which the user has resigned
// from.
$joins[] = qsprintf(
$conn_r,
'LEFT JOIN %T awaiting ON audit.commitPHID = awaiting.commitPHID AND
awaiting.auditorPHID = %s',
$audit_request->getTableName(),
$this->auditAwaitingUser->getPHID());
}
if ($joins) {
return implode(' ', $joins);
} else {
return '';
}
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationDiffusion';
}
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Aug 15, 7:09 AM (6 d, 3 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
201442
Default Alt Text
(33 KB)

Event Timeline