diff --git a/src/applications/repository/worker/commitchangeparser/PhabricatorOwnersPackagePathValidator.php b/src/applications/repository/worker/commitchangeparser/PhabricatorOwnersPackagePathValidator.php index d007b0b206..55b34e7fef 100644 --- a/src/applications/repository/worker/commitchangeparser/PhabricatorOwnersPackagePathValidator.php +++ b/src/applications/repository/worker/commitchangeparser/PhabricatorOwnersPackagePathValidator.php @@ -1,98 +1,108 @@ setViewer($actor) + ->withIDs(array($commit->getRepositoryID())) + ->executeOne(); + if (!$repository) { + return; + } + $changes = self::loadDiffusionChangesForCommit( + $repository, + $commit, + $actor); if (!$changes) { return; } - // TODO: (T603) This should be policy-aware. - $repository = - id(new PhabricatorRepository())->load($commit->getRepositoryID()); $move_map = array(); foreach ($changes as $change) { if ($change->getChangeType() == DifferentialChangeType::TYPE_MOVE_HERE) { $from_path = '/'.$change->getTargetPath(); $to_path = '/'.$change->getPath(); if ($change->getFileType() == DifferentialChangeType::FILE_DIRECTORY) { $to_path = $to_path.'/'; $from_path = $from_path.'/'; } $move_map[$from_path] = $to_path; } } if ($move_map) { self::updateAffectedPackages($repository, $move_map); } } private static function updateAffectedPackages($repository, array $move_map) { $paths = array_keys($move_map); if ($paths) { $packages = PhabricatorOwnersPackage::loadAffectedPackages($repository, $paths); foreach ($packages as $package) { self::updatePackagePaths($package, $move_map); } } } private static function updatePackagePaths($package, array $move_map) { $paths = array_keys($move_map); $pkg_paths = $package->loadPaths(); $new_paths = array(); foreach ($pkg_paths as $pkg_path) { $path_changed = false; foreach ($paths as $old_path) { if (strncmp($pkg_path->getPath(), $old_path, strlen($old_path)) === 0) { $new_paths[] = array ( 'packageID' => $package->getID(), 'repositoryPHID' => $pkg_path->getRepositoryPHID(), 'path' => str_replace($pkg_path->getPath(), $old_path, $move_map[$old_path]), ); $path_changed = true; } } if (!$path_changed) { $new_paths[] = array ( 'packageID' => $package->getID(), 'repositoryPHID' => $pkg_path->getRepositoryPHID(), 'path' => $pkg_path->getPath(), ); } } if ($new_paths) { $package->attachOldPrimaryOwnerPHID($package->getPrimaryOwnerPHID()); $package->attachUnsavedPaths($new_paths); $package->save(); // save the changes and notify the owners. } } - private static function loadDiffusionChangesForCommit($commit) { - $repository = - id(new PhabricatorRepository())->load($commit->getRepositoryID()); + private static function loadDiffusionChangesForCommit( + PhabricatorRepository $repository, + PhabricatorRepositoryCommit $commit, + PhabricatorUser $actor) { $data = array( - 'user' => PhabricatorUser::getOmnipotentUser(), + 'user' => $actor, 'repository' => $repository, 'commit' => $commit->getCommitIdentifier(), ); $drequest = DiffusionRequest::newFromDictionary($data); $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest($drequest); return $change_query->loadChanges(); } } diff --git a/src/applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php b/src/applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php index 5aedbf74dc..ffcb78435e 100644 --- a/src/applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php +++ b/src/applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php @@ -1,157 +1,159 @@ getCommitIdentifier(); $callsign = $repository->getCallsign(); $full_name = 'r'.$callsign.$identifier; $this->log("Parsing %s...\n", $full_name); if ($this->isBadCommit($full_name)) { $this->log('This commit is marked bad!'); return; } $results = $this->parseCommitChanges($repository, $commit); if ($results) { $this->writeCommitChanges($repository, $commit, $results); } $this->finishParse(); } public function parseChangesForUnitTest( PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit) { return $this->parseCommitChanges($repository, $commit); } public static function lookupOrCreatePaths(array $paths) { $repository = new PhabricatorRepository(); $conn_w = $repository->establishConnection('w'); $result_map = self::lookupPaths($paths); $missing_paths = array_fill_keys($paths, true); $missing_paths = array_diff_key($missing_paths, $result_map); $missing_paths = array_keys($missing_paths); if ($missing_paths) { foreach (array_chunk($missing_paths, 128) as $path_chunk) { $sql = array(); foreach ($path_chunk as $path) { $sql[] = qsprintf($conn_w, '(%s, %s)', $path, md5($path)); } queryfx( $conn_w, 'INSERT IGNORE INTO %T (path, pathHash) VALUES %Q', PhabricatorRepository::TABLE_PATH, implode(', ', $sql)); } $result_map += self::lookupPaths($missing_paths); } return $result_map; } private static function lookupPaths(array $paths) { $repository = new PhabricatorRepository(); $conn_w = $repository->establishConnection('w'); $result_map = array(); foreach (array_chunk($paths, 128) as $path_chunk) { $chunk_map = queryfx_all( $conn_w, 'SELECT path, id FROM %T WHERE pathHash IN (%Ls)', PhabricatorRepository::TABLE_PATH, array_map('md5', $path_chunk)); foreach ($chunk_map as $row) { $result_map[$row['path']] = $row['id']; } } return $result_map; } protected function finishParse() { $commit = $this->commit; $commit->writeImportStatusFlag( PhabricatorRepositoryCommit::IMPORTED_CHANGE); id(new PhabricatorSearchIndexer()) ->queueDocumentForIndexing($commit->getPHID()); - PhabricatorOwnersPackagePathValidator::updateOwnersPackagePaths($commit); + PhabricatorOwnersPackagePathValidator::updateOwnersPackagePaths( + $commit, + PhabricatorUser::getOmnipotentUser()); if ($this->shouldQueueFollowupTasks()) { $this->queueTask( 'PhabricatorRepositoryCommitOwnersWorker', array( 'commitID' => $commit->getID(), )); } } private function writeCommitChanges( PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit, array $changes) { $repository_id = (int)$repository->getID(); $commit_id = (int)$commit->getID(); // NOTE: This SQL is being built manually instead of with qsprintf() // because some SVN changes affect an enormous number of paths (millions) // and this showed up as significantly slow on a profile at some point. $changes_sql = array(); foreach ($changes as $change) { $values = array( $repository_id, (int)$change->getPathID(), $commit_id, nonempty((int)$change->getTargetPathID(), 'null'), nonempty((int)$change->getTargetCommitID(), 'null'), (int)$change->getChangeType(), (int)$change->getFileType(), (int)$change->getIsDirect(), (int)$change->getCommitSequence(), ); $changes_sql[] = '('.implode(', ', $values).')'; } $conn_w = $repository->establishConnection('w'); queryfx( $conn_w, 'DELETE FROM %T WHERE commitID = %d', PhabricatorRepository::TABLE_PATHCHANGE, $commit_id); foreach (PhabricatorLiskDAO::chunkSQL($changes_sql) as $chunk) { queryfx( $conn_w, 'INSERT INTO %T (repositoryID, pathID, commitID, targetPathID, targetCommitID, changeType, fileType, isDirect, commitSequence) VALUES %Q', PhabricatorRepository::TABLE_PATHCHANGE, $chunk); } } }