1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-25 08:12:40 +01:00

Move "Affected Path" index updates to a separate class

Summary:
Ref T13639. Move operations related to updating the "AffectedPath" index to a dedicated class.

This change has no functional effect and only moves code.

Test Plan: Used an external script to rebuild every revision index; destroyed a revision with `bin/remove destroy`.

Maniphest Tasks: T13639

Differential Revision: https://secure.phabricator.com/D21616
This commit is contained in:
epriestley 2021-03-15 09:59:40 -07:00
parent e919b4c35a
commit 38ef910da8
4 changed files with 148 additions and 97 deletions

View file

@ -450,6 +450,7 @@ phutil_register_library_map(array(
'DifferentialActionEmailCommand' => 'applications/differential/command/DifferentialActionEmailCommand.php',
'DifferentialAdjustmentMapTestCase' => 'applications/differential/storage/__tests__/DifferentialAdjustmentMapTestCase.php',
'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php',
'DifferentialAffectedPathEngine' => 'applications/differential/engine/DifferentialAffectedPathEngine.php',
'DifferentialAsanaRepresentationField' => 'applications/differential/customfield/DifferentialAsanaRepresentationField.php',
'DifferentialAuditorsCommitMessageField' => 'applications/differential/field/DifferentialAuditorsCommitMessageField.php',
'DifferentialAuditorsField' => 'applications/differential/customfield/DifferentialAuditorsField.php',
@ -6533,6 +6534,7 @@ phutil_register_library_map(array(
'DifferentialActionEmailCommand' => 'MetaMTAEmailTransactionCommand',
'DifferentialAdjustmentMapTestCase' => 'PhabricatorTestCase',
'DifferentialAffectedPath' => 'DifferentialDAO',
'DifferentialAffectedPathEngine' => 'Phobject',
'DifferentialAsanaRepresentationField' => 'DifferentialCustomField',
'DifferentialAuditorsCommitMessageField' => 'DifferentialCommitMessageCustomField',
'DifferentialAuditorsField' => 'DifferentialStoredCustomField',

View file

@ -356,7 +356,12 @@ final class DifferentialTransactionEditor
// diff to a revision.
$this->updateRevisionHashTable($object, $diff);
$this->updateAffectedPathTable($object, $diff);
id(new DifferentialAffectedPathEngine())
->setRevision($object)
->setDiff($diff)
->updateAffectedPaths();
break;
}
}
@ -1258,92 +1263,6 @@ final class DifferentialTransactionEditor
return $adapter;
}
/**
* Update the table which links Differential revisions to paths they affect,
* so Diffusion can efficiently find pending revisions for a given file.
*/
private function updateAffectedPathTable(
DifferentialRevision $revision,
DifferentialDiff $diff) {
$repository = $revision->getRepository();
if (!$repository) {
// The repository where the code lives is untracked.
return;
}
$path_prefix = null;
$local_root = $diff->getSourceControlPath();
if ($local_root) {
// We're in a working copy which supports subdirectory checkouts (e.g.,
// SVN) so we need to figure out what prefix we should add to each path
// (e.g., trunk/projects/example/) to get the absolute path from the
// root of the repository. DVCS systems like Git and Mercurial are not
// affected.
// Normalize both paths and check if the repository root is a prefix of
// the local root. If so, throw it away. Note that this correctly handles
// the case where the remote path is "/".
$local_root = id(new PhutilURI($local_root))->getPath();
$local_root = rtrim($local_root, '/');
$repo_root = id(new PhutilURI($repository->getRemoteURI()))->getPath();
$repo_root = rtrim($repo_root, '/');
if (!strncmp($repo_root, $local_root, strlen($repo_root))) {
$path_prefix = substr($local_root, strlen($repo_root));
}
}
$changesets = $diff->getChangesets();
$paths = array();
foreach ($changesets as $changeset) {
$paths[] = $path_prefix.'/'.$changeset->getFilename();
}
// Mark this as also touching all parent paths, so you can see all pending
// changes to any file within a directory.
$all_paths = array();
foreach ($paths as $local) {
foreach (DiffusionPathIDQuery::expandPathToRoot($local) as $path) {
$all_paths[$path] = true;
}
}
$all_paths = array_keys($all_paths);
$path_ids =
PhabricatorRepositoryCommitChangeParserWorker::lookupOrCreatePaths(
$all_paths);
$table = new DifferentialAffectedPath();
$conn_w = $table->establishConnection('w');
$sql = array();
foreach ($path_ids as $path_id) {
$sql[] = qsprintf(
$conn_w,
'(%d, %d, %d, %d)',
$repository->getID(),
$path_id,
time(),
$revision->getID());
}
queryfx(
$conn_w,
'DELETE FROM %T WHERE revisionID = %d',
$table->getTableName(),
$revision->getID());
foreach (array_chunk($sql, 256) as $chunk) {
queryfx(
$conn_w,
'INSERT INTO %T (repositoryID, pathID, epoch, revisionID) VALUES %LQ',
$table->getTableName(),
$chunk);
}
}
/**
* Update the table connecting revisions to DVCS local hashes, so we can
* identify revisions by commit/tree hashes.

View file

@ -0,0 +1,137 @@
<?php
final class DifferentialAffectedPathEngine
extends Phobject {
private $revision;
private $diff;
public function setRevision(DifferentialRevision $revision) {
$this->revision = $revision;
return $this;
}
public function getRevision() {
return $this->revision;
}
public function setDiff(DifferentialDiff $diff) {
$this->diff = $diff;
return $this;
}
public function getDiff() {
return $this->diff;
}
public function updateAffectedPaths() {
$revision = $this->getRevision();
$diff = $this->getDiff();
$repository = $revision->getRepository();
if ($repository) {
$repository_id = $repository->getID();
} else {
return;
}
$paths = $this->getAffectedPaths();
$path_ids =
PhabricatorRepositoryCommitChangeParserWorker::lookupOrCreatePaths(
$paths);
$table = new DifferentialAffectedPath();
$conn = $table->establishConnection('w');
$sql = array();
foreach ($path_ids as $path_id) {
$sql[] = qsprintf(
$conn,
'(%d, %d, %d, %d)',
$repository_id,
$path_id,
PhabricatorTime::getNow(),
$revision->getID());
}
queryfx(
$conn,
'DELETE FROM %R WHERE revisionID = %d',
$table,
$revision->getID());
if ($sql) {
foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) {
queryfx(
$conn,
'INSERT INTO %R (repositoryID, pathID, epoch, revisionID) VALUES %LQ',
$table,
$chunk);
}
}
}
public function destroyAffectedPaths() {
$revision = $this->getRevision();
$table = new DifferentialAffectedPath();
$conn = $table->establishConnection('w');
queryfx(
$conn,
'DELETE FROM %R WHERE revisionID = %d',
$table,
$revision->getID());
}
public function getAffectedPaths() {
$revision = $this->getRevision();
$diff = $this->getDiff();
$repository = $revision->getRepository();
$path_prefix = null;
if ($repository) {
$local_root = $diff->getSourceControlPath();
if ($local_root) {
// We're in a working copy which supports subdirectory checkouts (e.g.,
// SVN) so we need to figure out what prefix we should add to each path
// (e.g., trunk/projects/example/) to get the absolute path from the
// root of the repository. DVCS systems like Git and Mercurial are not
// affected.
// Normalize both paths and check if the repository root is a prefix of
// the local root. If so, throw it away. Note that this correctly
// handles the case where the remote path is "/".
$local_root = id(new PhutilURI($local_root))->getPath();
$local_root = rtrim($local_root, '/');
$repo_root = id(new PhutilURI($repository->getRemoteURI()))->getPath();
$repo_root = rtrim($repo_root, '/');
if (!strncmp($repo_root, $local_root, strlen($repo_root))) {
$path_prefix = substr($local_root, strlen($repo_root));
}
}
}
$changesets = $diff->getChangesets();
$paths = array();
foreach ($changesets as $changeset) {
$paths[] = $path_prefix.'/'.$changeset->getFilename();
}
// Mark this as also touching all parent paths, so you can see all pending
// changes to any file within a directory.
$all_paths = array();
foreach ($paths as $local) {
foreach (DiffusionPathIDQuery::expandPathToRoot($local) as $path) {
$all_paths[$path] = true;
}
}
$all_paths = array_keys($all_paths);
return $all_paths;
}
}

View file

@ -1022,16 +1022,9 @@ final class DifferentialRevision extends DifferentialDAO
$engine->destroyObject($diff);
}
$conn_w = $this->establishConnection('w');
// we have to do paths a little differently as they do not have
// an id or phid column for delete() to act on
$dummy_path = new DifferentialAffectedPath();
queryfx(
$conn_w,
'DELETE FROM %T WHERE revisionID = %d',
$dummy_path->getTableName(),
$this->getID());
id(new DifferentialAffectedPathEngine())
->setRevision($this)
->destroyAffectedPaths();
$viewstate_query = id(new DifferentialViewStateQuery())
->setViewer($viewer)