Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/audit/management/PhabricatorAuditManagementDeleteWorkflow.php b/src/applications/audit/management/PhabricatorAuditManagementDeleteWorkflow.php
index 7d14df7239..cd621ce821 100644
--- a/src/applications/audit/management/PhabricatorAuditManagementDeleteWorkflow.php
+++ b/src/applications/audit/management/PhabricatorAuditManagementDeleteWorkflow.php
@@ -1,321 +1,331 @@
<?php
final class PhabricatorAuditManagementDeleteWorkflow
extends PhabricatorAuditManagementWorkflow {
protected function didConstruct() {
$this
->setName('delete')
->setExamples('**delete** [--dry-run] ...')
->setSynopsis(pht('Delete audit requests matching parameters.'))
->setArguments(
array(
array(
'name' => 'dry-run',
'help' => pht(
'Show what would be deleted, but do not actually delete '.
'anything.'),
),
array(
'name' => 'users',
'param' => 'names',
'help' => pht('Select only audits by a given list of users.'),
),
array(
'name' => 'repositories',
'param' => 'repos',
'help' => pht(
'Select only audits in a given list of repositories.'),
),
array(
'name' => 'commits',
'param' => 'commits',
'help' => pht('Select only audits for the given commits.'),
),
array(
'name' => 'min-commit-date',
'param' => 'date',
'help' => pht(
'Select only audits for commits on or after the given date.'),
),
array(
'name' => 'max-commit-date',
'param' => 'date',
'help' => pht(
'Select only audits for commits on or before the given date.'),
),
array(
'name' => 'status',
'param' => 'status',
'help' => pht(
'Select only audits in the given status. By default, '.
'only open audits are selected.'),
),
array(
'name' => 'ids',
'param' => 'ids',
'help' => pht('Select only audits with the given IDs.'),
),
));
}
public function execute(PhutilArgumentParser $args) {
$viewer = $this->getViewer();
$users = $this->loadUsers($args->getArg('users'));
$repos = $this->loadRepos($args->getArg('repositories'));
$commits = $this->loadCommits($args->getArg('commits'));
$ids = $this->parseList($args->getArg('ids'));
$status = $args->getArg('status');
$min_date = $this->loadDate($args->getArg('min-commit-date'));
$max_date = $this->loadDate($args->getArg('max-commit-date'));
if ($min_date && $max_date && ($min_date > $max_date)) {
throw new PhutilArgumentUsageException(
pht('Specified maximum date must come after specified minimum date.'));
}
$is_dry_run = $args->getArg('dry-run');
$query = id(new DiffusionCommitQuery())
->setViewer($this->getViewer())
->needAuditRequests(true);
if ($status) {
$query->withStatuses(array($status));
}
$id_map = array();
if ($ids) {
$id_map = array_fuse($ids);
$query->withAuditIDs($ids);
}
if ($repos) {
$query->withRepositoryIDs(mpull($repos, 'getID'));
+
+ // See T13457. If we're iterating over commits in a single large
+ // repository, the lack of a "<repositoryID, [id]>" key can slow things
+ // down. Iterate in a specific order to use a key which is present
+ // on the table ("<repositoryID, epoch, [id]>").
+ $query->setOrderVector(array('-epoch', '-id'));
}
$auditor_map = array();
if ($users) {
$auditor_map = array_fuse(mpull($users, 'getPHID'));
$query->withAuditorPHIDs($auditor_map);
}
if ($commits) {
$query->withPHIDs(mpull($commits, 'getPHID'));
}
- $commit_iterator = new PhabricatorQueryIterator($query);
+ $commit_iterator = id(new PhabricatorQueryIterator($query));
+
+ // See T13457. We may be examining many commits; each commit is small so
+ // we can safely increase the page size to improve performance a bit.
+ $commit_iterator->setPageSize(1000);
$audits = array();
foreach ($commit_iterator as $commit) {
$commit_audits = $commit->getAudits();
foreach ($commit_audits as $key => $audit) {
if ($id_map && empty($id_map[$audit->getID()])) {
unset($commit_audits[$key]);
continue;
}
if ($auditor_map && empty($auditor_map[$audit->getAuditorPHID()])) {
unset($commit_audits[$key]);
continue;
}
if ($min_date && $commit->getEpoch() < $min_date) {
unset($commit_audits[$key]);
continue;
}
if ($max_date && $commit->getEpoch() > $max_date) {
unset($commit_audits[$key]);
continue;
}
}
if (!$commit_audits) {
continue;
}
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(mpull($commit_audits, 'getAuditorPHID'))
->execute();
foreach ($commit_audits as $audit) {
$audit_id = $audit->getID();
$description = sprintf(
'%10d %-16s %-16s %s: %s',
$audit_id,
$handles[$audit->getAuditorPHID()]->getName(),
PhabricatorAuditStatusConstants::getStatusName(
$audit->getAuditStatus()),
$commit->getRepository()->formatCommitName(
$commit->getCommitIdentifier()),
trim($commit->getSummary()));
$audits[] = array(
'auditID' => $audit_id,
'commitPHID' => $commit->getPHID(),
'description' => $description,
);
}
}
if (!$audits) {
echo tsprintf(
"%s\n",
pht('No audits match the query.'));
return 0;
}
foreach ($audits as $audit_spec) {
echo tsprintf(
"%s\n",
$audit_spec['description']);
}
if ($is_dry_run) {
echo tsprintf(
"%s\n",
pht('This is a dry run, so no changes will be made.'));
return 0;
}
$message = pht(
'Really delete these %s audit(s)? They will be permanently deleted '.
'and can not be recovered.',
phutil_count($audits));
if (!phutil_console_confirm($message)) {
echo tsprintf(
"%s\n",
pht('User aborted the workflow.'));
return 1;
}
$audits_by_commit = igroup($audits, 'commitPHID');
foreach ($audits_by_commit as $commit_phid => $audit_specs) {
$audit_ids = ipull($audit_specs, 'auditID');
$audits = id(new PhabricatorRepositoryAuditRequest())->loadAllWhere(
'id IN (%Ld)',
$audit_ids);
foreach ($audits as $audit) {
$id = $audit->getID();
echo tsprintf(
"%s\n",
pht('Deleting audit %d...', $id));
$audit->delete();
}
$this->synchronizeCommitAuditState($commit_phid);
}
return 0;
}
private function loadUsers($users) {
$users = $this->parseList($users);
if (!$users) {
return null;
}
$objects = id(new PhabricatorPeopleQuery())
->setViewer($this->getViewer())
->withUsernames($users)
->execute();
$objects = mpull($objects, null, 'getUsername');
foreach ($users as $name) {
if (empty($objects[$name])) {
throw new PhutilArgumentUsageException(
pht('No such user with username "%s"!', $name));
}
}
return $objects;
}
private function parseList($list) {
$list = preg_split('/\s*,\s*/', $list);
foreach ($list as $key => $item) {
$list[$key] = trim($item);
}
foreach ($list as $key => $item) {
if (!strlen($item)) {
unset($list[$key]);
}
}
return $list;
}
private function loadRepos($identifiers) {
$identifiers = $this->parseList($identifiers);
if (!$identifiers) {
return null;
}
$query = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withIdentifiers($identifiers);
$repos = $query->execute();
$map = $query->getIdentifierMap();
foreach ($identifiers as $identifier) {
if (empty($map[$identifier])) {
throw new PhutilArgumentUsageException(
pht('No repository "%s" exists!', $identifier));
}
}
return $repos;
}
private function loadDate($date) {
if (!$date) {
return null;
}
$epoch = strtotime($date);
if (!$epoch || $epoch < 1) {
throw new PhutilArgumentUsageException(
pht(
'Unable to parse date "%s". Use a format like "%s".',
$date,
'2000-01-01'));
}
return $epoch;
}
private function loadCommits($commits) {
$names = $this->parseList($commits);
if (!$names) {
return null;
}
$query = id(new DiffusionCommitQuery())
->setViewer($this->getViewer())
->withIdentifiers($names);
$commits = $query->execute();
$map = $query->getIdentifierMap();
foreach ($names as $name) {
if (empty($map[$name])) {
throw new PhutilArgumentUsageException(
pht('No such commit "%s"!', $name));
}
}
return $commits;
}
}
diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementRebuildIdentitiesWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementRebuildIdentitiesWorkflow.php
index c1f92e8371..513d7a3805 100644
--- a/src/applications/repository/management/PhabricatorRepositoryManagementRebuildIdentitiesWorkflow.php
+++ b/src/applications/repository/management/PhabricatorRepositoryManagementRebuildIdentitiesWorkflow.php
@@ -1,383 +1,388 @@
<?php
final class PhabricatorRepositoryManagementRebuildIdentitiesWorkflow
extends PhabricatorRepositoryManagementWorkflow {
private $identityCache = array();
protected function didConstruct() {
$this
->setName('rebuild-identities')
->setExamples(
'**rebuild-identities** [__options__] __repository__')
->setSynopsis(pht('Rebuild repository identities from commits.'))
->setArguments(
array(
array(
'name' => 'all-repositories',
'help' => pht('Rebuild identities across all repositories.'),
),
array(
'name' => 'all-identities',
'help' => pht('Rebuild all currently-known identities.'),
),
array(
'name' => 'repository',
'param' => 'repository',
'repeat' => true,
'help' => pht('Rebuild identities in a repository.'),
),
array(
'name' => 'commit',
'param' => 'commit',
'repeat' => true,
'help' => pht('Rebuild identities for a commit.'),
),
array(
'name' => 'user',
'param' => 'user',
'repeat' => true,
'help' => pht('Rebuild identities for a user.'),
),
array(
'name' => 'email',
'param' => 'email',
'repeat' => true,
'help' => pht('Rebuild identities for an email address.'),
),
array(
'name' => 'raw',
'param' => 'raw',
'repeat' => true,
'help' => pht('Rebuild identities for a raw commit string.'),
),
));
}
public function execute(PhutilArgumentParser $args) {
$viewer = $this->getViewer();
$rebuilt_anything = false;
$all_repositories = $args->getArg('all-repositories');
$repositories = $args->getArg('repository');
if ($all_repositories && $repositories) {
throw new PhutilArgumentUsageException(
pht(
'Flags "--all-repositories" and "--repository" are not '.
'compatible.'));
}
$all_identities = $args->getArg('all-identities');
$raw = $args->getArg('raw');
if ($all_identities && $raw) {
throw new PhutilArgumentUsageException(
pht(
'Flags "--all-identities" and "--raw" are not '.
'compatible.'));
}
if ($all_repositories || $repositories) {
$rebuilt_anything = true;
if ($repositories) {
$repository_list = $this->loadRepositories($args, 'repository');
} else {
$repository_query = id(new PhabricatorRepositoryQuery())
->setViewer($viewer);
$repository_list = new PhabricatorQueryIterator($repository_query);
}
foreach ($repository_list as $repository) {
$commit_query = id(new DiffusionCommitQuery())
->setViewer($viewer)
->needCommitData(true)
->withRepositoryIDs(array($repository->getID()));
- $commit_iterator = new PhabricatorQueryIterator($commit_query);
+ // See T13457. Adjust ordering to hit keys better and tweak page size
+ // to improve performance slightly, since these records are small.
+ $commit_query->setOrderVector(array('-epoch', '-id'));
+
+ $commit_iterator = id(new PhabricatorQueryIterator($commit_query))
+ ->setPageSize(1000);
$this->rebuildCommits($commit_iterator);
}
}
$commits = $args->getArg('commit');
if ($commits) {
$rebuilt_anything = true;
$commit_list = $this->loadCommits($args, 'commit');
// Reload commits to get commit data.
$commit_list = id(new DiffusionCommitQuery())
->setViewer($viewer)
->needCommitData(true)
->withIDs(mpull($commit_list, 'getID'))
->execute();
$this->rebuildCommits($commit_list);
}
$users = $args->getArg('user');
if ($users) {
$rebuilt_anything = true;
$user_list = $this->loadUsersFromArguments($users);
$this->rebuildUsers($user_list);
}
$emails = $args->getArg('email');
if ($emails) {
$rebuilt_anything = true;
$this->rebuildEmails($emails);
}
if ($all_identities || $raw) {
$rebuilt_anything = true;
if ($raw) {
$identities = id(new PhabricatorRepositoryIdentityQuery())
->setViewer($viewer)
->withIdentityNames($raw)
->execute();
$identities = mpull($identities, null, 'getIdentityNameRaw');
foreach ($raw as $raw_identity) {
if (!isset($identities[$raw_identity])) {
throw new PhutilArgumentUsageException(
pht(
'No identity "%s" exists. When selecting identities with '.
'"--raw", the entire identity must match exactly.',
$raw_identity));
}
}
$identity_list = $identities;
} else {
$identity_query = id(new PhabricatorRepositoryIdentityQuery())
->setViewer($viewer);
$identity_list = new PhabricatorQueryIterator($identity_query);
$this->logInfo(
pht('REBUILD'),
pht('Rebuilding all existing identities.'));
}
$this->rebuildIdentities($identity_list);
}
if (!$rebuilt_anything) {
throw new PhutilArgumentUsageException(
pht(
'Nothing specified to rebuild. Use flags to choose which '.
'identities to rebuild, or "--help" for help.'));
}
return 0;
}
private function rebuildCommits($commits) {
foreach ($commits as $commit) {
$needs_update = false;
$data = $commit->getCommitData();
$author_name = $data->getAuthorName();
$author_identity = $this->getIdentityForCommit(
$commit,
$author_name);
$author_phid = $commit->getAuthorIdentityPHID();
$identity_phid = $author_identity->getPHID();
$aidentity_phid = $identity_phid;
if ($author_phid !== $identity_phid) {
$commit->setAuthorIdentityPHID($identity_phid);
$data->setCommitDetail('authorIdentityPHID', $identity_phid);
$needs_update = true;
}
$committer_name = $data->getCommitDetail('committer', null);
$committer_phid = $commit->getCommitterIdentityPHID();
if (strlen($committer_name)) {
$committer_identity = $this->getIdentityForCommit(
$commit,
$committer_name);
$identity_phid = $committer_identity->getPHID();
} else {
$identity_phid = null;
}
if ($committer_phid !== $identity_phid) {
$commit->setCommitterIdentityPHID($identity_phid);
$data->setCommitDetail('committerIdentityPHID', $identity_phid);
$needs_update = true;
}
if ($needs_update) {
$commit->save();
$data->save();
$this->logInfo(
pht('COMMIT'),
pht(
'Rebuilt identities for "%s".',
$commit->getDisplayName()));
} else {
$this->logInfo(
pht('SKIP'),
pht(
'No changes for commit "%s".',
$commit->getDisplayName()));
}
}
}
private function getIdentityForCommit(
PhabricatorRepositoryCommit $commit,
$raw_identity) {
if (!isset($this->identityCache[$raw_identity])) {
$viewer = $this->getViewer();
$identity = id(new DiffusionRepositoryIdentityEngine())
->setViewer($viewer)
->setSourcePHID($commit->getPHID())
->newResolvedIdentity($raw_identity);
$this->identityCache[$raw_identity] = $identity;
}
return $this->identityCache[$raw_identity];
}
private function rebuildUsers($users) {
$viewer = $this->getViewer();
foreach ($users as $user) {
$this->logInfo(
pht('USER'),
pht(
'Rebuilding identities for user "%s".',
$user->getMonogram()));
$emails = id(new PhabricatorUserEmail())->loadAllWhere(
'userPHID = %s',
$user->getPHID());
if ($emails) {
$this->rebuildEmails(mpull($emails, 'getAddress'));
}
$identities = id(new PhabricatorRepositoryIdentityQuery())
->setViewer($viewer)
->withRelatedPHIDs(array($user->getPHID()))
->execute();
if (!$identities) {
$this->logWarn(
pht('NO IDENTITIES'),
pht('Found no identities directly related to user.'));
continue;
}
$this->rebuildIdentities($identities);
}
}
private function rebuildEmails($emails) {
$viewer = $this->getViewer();
foreach ($emails as $email) {
$this->logInfo(
pht('EMAIL'),
pht('Rebuilding identities for email address "%s".', $email));
$identities = id(new PhabricatorRepositoryIdentityQuery())
->setViewer($viewer)
->withEmailAddresses(array($email))
->execute();
if (!$identities) {
$this->logWarn(
pht('NO IDENTITIES'),
pht('Found no identities for email address "%s".', $email));
continue;
}
$this->rebuildIdentities($identities);
}
}
private function rebuildIdentities($identities) {
$viewer = $this->getViewer();
foreach ($identities as $identity) {
$raw_identity = $identity->getIdentityName();
if (isset($this->identityCache[$raw_identity])) {
$this->logInfo(
pht('SKIP'),
pht(
'Identity "%s" has already been rebuilt.',
$raw_identity));
continue;
}
$this->logInfo(
pht('IDENTITY'),
pht(
'Rebuilding identity "%s".',
$raw_identity));
$old_auto = $identity->getAutomaticGuessedUserPHID();
$old_assign = $identity->getManuallySetUserPHID();
$identity = id(new DiffusionRepositoryIdentityEngine())
->setViewer($viewer)
->newUpdatedIdentity($identity);
$this->identityCache[$raw_identity] = $identity;
$new_auto = $identity->getAutomaticGuessedUserPHID();
$new_assign = $identity->getManuallySetUserPHID();
$same_auto = ($old_auto === $new_auto);
$same_assign = ($old_assign === $new_assign);
if ($same_auto && $same_assign) {
$this->logInfo(
pht('UNCHANGED'),
pht('No changes to identity.'));
} else {
if (!$same_auto) {
$this->logWarn(
pht('AUTOMATIC PHID'),
pht(
'Automatic user updated from "%s" to "%s".',
$this->renderPHID($old_auto),
$this->renderPHID($new_auto)));
}
if (!$same_assign) {
$this->logWarn(
pht('ASSIGNED PHID'),
pht(
'Assigned user updated from "%s" to "%s".',
$this->renderPHID($old_assign),
$this->renderPHID($new_assign)));
}
}
}
}
private function renderPHID($phid) {
if ($phid == null) {
return pht('NULL');
} else {
return $phid;
}
}
}
diff --git a/src/infrastructure/storage/lisk/PhabricatorQueryIterator.php b/src/infrastructure/storage/lisk/PhabricatorQueryIterator.php
index 648b83863a..cc88678cdf 100644
--- a/src/infrastructure/storage/lisk/PhabricatorQueryIterator.php
+++ b/src/infrastructure/storage/lisk/PhabricatorQueryIterator.php
@@ -1,43 +1,48 @@
<?php
final class PhabricatorQueryIterator extends PhutilBufferedIterator {
private $query;
private $pager;
public function __construct(PhabricatorCursorPagedPolicyAwareQuery $query) {
$this->query = $query;
}
protected function didRewind() {
- $this->pager = new AphrontCursorPagerView();
+ $pager = new AphrontCursorPagerView();
+
+ $page_size = $this->getPageSize();
+ $pager->setPageSize($page_size);
+
+ $this->pager = $pager;
}
public function key() {
return $this->current()->getID();
}
protected function loadPage() {
if (!$this->pager) {
return array();
}
$pager = clone $this->pager;
$query = clone $this->query;
$query->setDisableOverheating(true);
$results = $query->executeWithCursorPager($pager);
// If we got less than a full page of results, this was the last set of
// results. Throw away the pager so we end iteration.
if (!$pager->getHasMoreResults()) {
$this->pager = null;
} else {
$this->pager->setAfterID($pager->getNextPageID());
}
return $results;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jul 27, 2:36 PM (1 w, 6 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
185020
Default Alt Text
(22 KB)

Event Timeline