@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move repository URIs to a dedicated index

Summary:
Ref T4705 (there are also some other adjacent related tasks dealing with URIs).

Currently, we issue a "get repositories matching URIs: ..." query by loading every possible repository and then checking their URIs in PHP.

Instead, put URIs in a separate table. I plan for each repository to potentially have multiple URIs soon, so this prepares for that.

Test Plan:
- Ran migrations.
- Looked at index table, made sure it appeared sensible.
- Ran some queries by `uri` to find repositories, found the repositories I expected.
- Updated the remote URI of a repository, saw queries / index update appropriately.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4705

Differential Revision: https://secure.phabricator.com/D15005

+175 -30
+7
resources/sql/autopatches/20160112.repo.01.uri.sql
··· 1 + CREATE TABLE {$NAMESPACE}_repository.repository_uriindex ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + repositoryPHID VARBINARY(64) NOT NULL, 4 + repositoryURI LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}, 5 + KEY `key_repository` (repositoryPHID), 6 + KEY `key_uri` (repositoryURI(128)) 7 + ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+7
resources/sql/autopatches/20160112.repo.02.uri.index.php
··· 1 + <?php 2 + 3 + $table = new PhabricatorRepository(); 4 + 5 + foreach (new LiskMigrationIterator($table) as $repo) { 6 + $repo->updateURIIndex(); 7 + }
+4
src/__phutil_library_map__.php
··· 734 734 'DiffusionRepositorySymbolsController' => 'applications/diffusion/controller/DiffusionRepositorySymbolsController.php', 735 735 'DiffusionRepositoryTag' => 'applications/diffusion/data/DiffusionRepositoryTag.php', 736 736 'DiffusionRepositoryTestAutomationController' => 'applications/diffusion/controller/DiffusionRepositoryTestAutomationController.php', 737 + 'DiffusionRepositoryURIsIndexEngineExtension' => 'applications/diffusion/engineextension/DiffusionRepositoryURIsIndexEngineExtension.php', 737 738 'DiffusionRequest' => 'applications/diffusion/request/DiffusionRequest.php', 738 739 'DiffusionResolveRefsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionResolveRefsConduitAPIMethod.php', 739 740 'DiffusionResolveUserQuery' => 'applications/diffusion/query/DiffusionResolveUserQuery.php', ··· 3009 3010 'PhabricatorRepositoryTransaction' => 'applications/repository/storage/PhabricatorRepositoryTransaction.php', 3010 3011 'PhabricatorRepositoryTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryTransactionQuery.php', 3011 3012 'PhabricatorRepositoryType' => 'applications/repository/constants/PhabricatorRepositoryType.php', 3013 + 'PhabricatorRepositoryURIIndex' => 'applications/repository/storage/PhabricatorRepositoryURIIndex.php', 3012 3014 'PhabricatorRepositoryURINormalizer' => 'applications/repository/data/PhabricatorRepositoryURINormalizer.php', 3013 3015 'PhabricatorRepositoryURINormalizerTestCase' => 'applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php', 3014 3016 'PhabricatorRepositoryURITestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryURITestCase.php', ··· 4707 4709 'DiffusionRepositorySymbolsController' => 'DiffusionRepositoryEditController', 4708 4710 'DiffusionRepositoryTag' => 'Phobject', 4709 4711 'DiffusionRepositoryTestAutomationController' => 'DiffusionRepositoryEditController', 4712 + 'DiffusionRepositoryURIsIndexEngineExtension' => 'PhabricatorIndexEngineExtension', 4710 4713 'DiffusionRequest' => 'Phobject', 4711 4714 'DiffusionResolveRefsConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 4712 4715 'DiffusionResolveUserQuery' => 'Phobject', ··· 7415 7418 'PhabricatorRepositoryTransaction' => 'PhabricatorApplicationTransaction', 7416 7419 'PhabricatorRepositoryTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 7417 7420 'PhabricatorRepositoryType' => 'Phobject', 7421 + 'PhabricatorRepositoryURIIndex' => 'PhabricatorRepositoryDAO', 7418 7422 'PhabricatorRepositoryURINormalizer' => 'Phobject', 7419 7423 'PhabricatorRepositoryURINormalizerTestCase' => 'PhabricatorTestCase', 7420 7424 'PhabricatorRepositoryURITestCase' => 'PhabricatorTestCase',
+1 -1
src/applications/diffusion/DiffusionLintSaveRunner.php
··· 71 71 } else if ($uuid) { 72 72 $repository_query->withUUIDs(array($uuid)); 73 73 } else if ($remote_uri) { 74 - $repository_query->withRemoteURIs(array($remote_uri)); 74 + $repository_query->withURIs(array($remote_uri)); 75 75 } 76 76 77 77 $repository = $repository_query->executeOne();
+22
src/applications/diffusion/engineextension/DiffusionRepositoryURIsIndexEngineExtension.php
··· 1 + <?php 2 + 3 + final class DiffusionRepositoryURIsIndexEngineExtension 4 + extends PhabricatorIndexEngineExtension { 5 + 6 + const EXTENSIONKEY = 'diffusion.repositories.uri'; 7 + 8 + public function getExtensionName() { 9 + return pht('Repository URIs'); 10 + } 11 + 12 + public function shouldIndexObject($object) { 13 + return ($object instanceof PhabricatorRepository); 14 + } 15 + 16 + public function indexObject( 17 + PhabricatorIndexEngine $engine, 18 + $object) { 19 + $object->updateURIIndex(); 20 + } 21 + 22 + }
+1 -1
src/applications/repository/conduit/RepositoryQueryConduitAPIMethod.php
··· 63 63 64 64 $remote_uris = $request->getValue('remoteURIs', array()); 65 65 if ($remote_uris) { 66 - $query->withRemoteURIs($remote_uris); 66 + $query->withURIs($remote_uris); 67 67 } 68 68 69 69 $uuids = $request->getValue('uuids', array());
+4
src/applications/repository/editor/PhabricatorRepositoryEditor.php
··· 518 518 throw new PhabricatorApplicationTransactionValidationException($errors); 519 519 } 520 520 521 + protected function supportsSearch() { 522 + return true; 523 + } 524 + 521 525 }
+36 -16
src/applications/repository/query/PhabricatorRepositoryQuery.php
··· 9 9 private $types; 10 10 private $uuids; 11 11 private $nameContains; 12 - private $remoteURIs; 12 + private $uris; 13 13 private $datasourceQuery; 14 14 private $slugs; 15 15 ··· 118 118 return $this; 119 119 } 120 120 121 - public function withRemoteURIs(array $uris) { 122 - $this->remoteURIs = $uris; 121 + public function withURIs(array $uris) { 122 + $this->uris = $uris; 123 123 return $this; 124 124 } 125 125 ··· 263 263 } 264 264 } 265 265 266 - // TODO: Denormalize this, too. 267 - if ($this->remoteURIs) { 268 - $try_uris = $this->getNormalizedPaths(); 269 - $try_uris = array_fuse($try_uris); 270 - foreach ($repositories as $key => $repository) { 271 - if (!isset($try_uris[$repository->getNormalizedPath()])) { 272 - unset($repositories[$key]); 273 - } 274 - } 275 - } 276 - 277 266 // Build the identifierMap 278 267 if ($this->numericIdentifiers) { 279 268 foreach ($this->numericIdentifiers as $id) { ··· 445 434 protected function buildSelectClauseParts(AphrontDatabaseConnection $conn) { 446 435 $parts = parent::buildSelectClauseParts($conn); 447 436 437 + $parts[] = 'r.*'; 438 + 448 439 if ($this->shouldJoinSummaryTable()) { 449 440 $parts[] = 's.*'; 450 441 } ··· 460 451 $conn, 461 452 'LEFT JOIN %T s ON r.id = s.repositoryID', 462 453 PhabricatorRepository::TABLE_SUMMARY); 454 + } 455 + 456 + if ($this->shouldJoinURITable()) { 457 + $joins[] = qsprintf( 458 + $conn, 459 + 'LEFT JOIN %T uri ON r.phid = uri.repositoryPHID', 460 + id(new PhabricatorRepositoryURIIndex())->getTableName()); 463 461 } 464 462 465 463 return $joins; 466 464 } 467 465 466 + protected function shouldGroupQueryResultRows() { 467 + if ($this->shouldJoinURITable()) { 468 + return true; 469 + } 470 + 471 + return parent::shouldGroupQueryResultRows(); 472 + } 473 + 474 + private function shouldJoinURITable() { 475 + return ($this->uris !== null); 476 + } 477 + 468 478 private function shouldJoinSummaryTable() { 469 479 if ($this->needCommitCounts) { 470 480 return true; ··· 592 602 if (strlen($this->nameContains)) { 593 603 $where[] = qsprintf( 594 604 $conn, 595 - 'name LIKE %~', 605 + 'r.name LIKE %~', 596 606 $this->nameContains); 597 607 } 598 608 ··· 619 629 $this->slugs); 620 630 } 621 631 632 + if ($this->uris !== null) { 633 + $try_uris = $this->getNormalizedPaths(); 634 + $try_uris = array_fuse($try_uris); 635 + 636 + $where[] = qsprintf( 637 + $conn, 638 + 'uri.repositoryURI IN (%Ls)', 639 + $try_uris); 640 + } 641 + 622 642 return $where; 623 643 } 624 644 ··· 635 655 // or an `svn+ssh` URI, we could deduce how to normalize it. However, this 636 656 // would be more complicated and it's not clear if it matters in practice. 637 657 638 - foreach ($this->remoteURIs as $uri) { 658 + foreach ($this->uris as $uri) { 639 659 $normalized_uris[] = new PhabricatorRepositoryURINormalizer( 640 660 PhabricatorRepositoryURINormalizer::TYPE_GIT, 641 661 $uri);
+26 -12
src/applications/repository/storage/PhabricatorRepository.php
··· 823 823 return $uri; 824 824 } 825 825 826 - public function getNormalizedPath() { 827 - $uri = (string)$this->getCloneURIObject(); 826 + public function updateURIIndex() { 827 + $uris = array( 828 + (string)$this->getCloneURIObject(), 829 + ); 830 + 831 + foreach ($uris as $key => $uri) { 832 + $uris[$key] = $this->getNormalizedURI($uri) 833 + ->getNormalizedPath(); 834 + } 835 + 836 + PhabricatorRepositoryURIIndex::updateRepositoryURIs( 837 + $this->getPHID(), 838 + $uris); 828 839 840 + return $this; 841 + } 842 + 843 + private function getNormalizedURI($uri) { 829 844 switch ($this->getVersionControlSystem()) { 830 845 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 831 - $normalized_uri = new PhabricatorRepositoryURINormalizer( 846 + return new PhabricatorRepositoryURINormalizer( 832 847 PhabricatorRepositoryURINormalizer::TYPE_GIT, 833 848 $uri); 834 - break; 835 849 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 836 - $normalized_uri = new PhabricatorRepositoryURINormalizer( 850 + return new PhabricatorRepositoryURINormalizer( 837 851 PhabricatorRepositoryURINormalizer::TYPE_SVN, 838 852 $uri); 839 - break; 840 853 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 841 - $normalized_uri = new PhabricatorRepositoryURINormalizer( 854 + return new PhabricatorRepositoryURINormalizer( 842 855 PhabricatorRepositoryURINormalizer::TYPE_MERCURIAL, 843 856 $uri); 844 - break; 845 857 default: 846 858 throw new Exception(pht('Unrecognized version control system.')); 847 859 } 848 - 849 - return $normalized_uri->getNormalizedPath(); 850 860 } 851 861 852 862 public function isTracked() { ··· 2231 2241 public function destroyObjectPermanently( 2232 2242 PhabricatorDestructionEngine $engine) { 2233 2243 2244 + $phid = $this->getPHID(); 2245 + 2234 2246 $this->openTransaction(); 2235 2247 2236 2248 $this->delete(); 2249 + 2250 + PhabricatorRepositoryURIIndex::updateRepositoryURIs($phid, array()); 2237 2251 2238 2252 $books = id(new DivinerBookQuery()) 2239 2253 ->setViewer($engine->getViewer()) 2240 - ->withRepositoryPHIDs(array($this->getPHID())) 2254 + ->withRepositoryPHIDs(array($phid)) 2241 2255 ->execute(); 2242 2256 foreach ($books as $book) { 2243 2257 $engine->destroyObject($book); ··· 2245 2259 2246 2260 $atoms = id(new DivinerAtomQuery()) 2247 2261 ->setViewer($engine->getViewer()) 2248 - ->withRepositoryPHIDs(array($this->getPHID())) 2262 + ->withRepositoryPHIDs(array($phid)) 2249 2263 ->execute(); 2250 2264 foreach ($atoms as $atom) { 2251 2265 $engine->destroyObject($atom);
+67
src/applications/repository/storage/PhabricatorRepositoryURIIndex.php
··· 1 + <?php 2 + 3 + final class PhabricatorRepositoryURIIndex 4 + extends PhabricatorRepositoryDAO { 5 + 6 + protected $repositoryPHID; 7 + protected $repositoryURI; 8 + 9 + protected function getConfiguration() { 10 + return array( 11 + self::CONFIG_TIMESTAMPS => false, 12 + self::CONFIG_COLUMN_SCHEMA => array( 13 + 'repositoryURI' => 'text', 14 + ), 15 + self::CONFIG_KEY_SCHEMA => array( 16 + 'key_repository' => array( 17 + 'columns' => array('repositoryPHID'), 18 + ), 19 + 'key_uri' => array( 20 + 'columns' => array('repositoryURI(128)'), 21 + ), 22 + ), 23 + ) + parent::getConfiguration(); 24 + } 25 + 26 + public static function updateRepositoryURIs( 27 + $repository_phid, 28 + array $uris) { 29 + 30 + $table = new self(); 31 + $conn_w = $table->establishConnection('w'); 32 + 33 + $sql = array(); 34 + foreach ($uris as $key => $uri) { 35 + if (!strlen($uri)) { 36 + unset($uris[$key]); 37 + continue; 38 + } 39 + 40 + $sql[] = qsprintf( 41 + $conn_w, 42 + '(%s, %s)', 43 + $repository_phid, 44 + $uri); 45 + } 46 + 47 + $table->openTransaction(); 48 + 49 + queryfx( 50 + $conn_w, 51 + 'DELETE FROM %T WHERE repositoryPHID = %s', 52 + $table->getTableName(), 53 + $repository_phid); 54 + 55 + if ($sql) { 56 + queryfx( 57 + $conn_w, 58 + 'INSERT INTO %T (repositoryPHID, repositoryURI) VALUES %Q', 59 + $table->getTableName(), 60 + implode(', ', $sql)); 61 + } 62 + 63 + $table->saveTransaction(); 64 + 65 + } 66 + 67 + }