diff --git a/resources/sql/patches/006.repository.sql b/resources/sql/patches/006.repository.sql index 6ea9ee3f5f..29ce4aa76e 100644 --- a/resources/sql/patches/006.repository.sql +++ b/resources/sql/patches/006.repository.sql @@ -1,44 +1,54 @@ create table phabricator_repository.repository_commitdata ( id int unsigned not null auto_increment primary key, commitID int unsigned not null, authorName varchar(255) not null, commitMessage longblob not null, unique key (commitID), key (authorName) ); ALTER TABLE phabricator_worker.worker_task drop priority; ALTER TABLE phabricator_worker.worker_task drop key leaseOwner; ALTER TABLE phabricator_worker.worker_task drop key (leaseOwner(16)); create table phabricator_repository.repository_path ( id int unsigned not null auto_increment primary key, path varchar(512) binary not null, unique key (path) ); create table phabricator_repository.repository_pathchange ( repositoryID int unsigned NOT NULL, pathID int unsigned NOT NULL, commitID int unsigned NOT NULL, targetPathID int unsigned, targetCommitID int unsigned, changeType int unsigned NOT NULL, fileType int unsigned NOT NULL, isDirect bool NOT NULL, commitSequence int unsigned NOT NULL, primary key (commitID, pathID), key (repositoryID, pathID, commitSequence) ); create table phabricator_repository.repository_filesystem ( repositoryID int unsigned not null, parentID int unsigned not null, svnCommit int unsigned not null, pathID int unsigned not null, existed bool not null, fileType int unsigned not null, primary key (repositoryID, parentID, svnCommit, pathID) ); -alter table repository_filesystem add key (repositoryID, svnCommit); \ No newline at end of file +alter table repository_filesystem add key (repositoryID, svnCommit); + +truncate phabricator_repository.repository_commit; +alter table phabricator_repository.repository_commit + change repositoryPHID repositoryID int unsigned not null; +alter table phabricator_repository.repository_commit drop key repositoryPHID; +alter table phabricator_repository.repository_commit add unique key + (repositoryID, commitIdentifier(16)); +alter table phabricator_repository.repository_commit add key + (repositoryID, epoch); + diff --git a/src/applications/diffusion/controller/home/DiffusionHomeController.php b/src/applications/diffusion/controller/home/DiffusionHomeController.php index 9989cb3b66..c51c034e89 100644 --- a/src/applications/diffusion/controller/home/DiffusionHomeController.php +++ b/src/applications/diffusion/controller/home/DiffusionHomeController.php @@ -1,96 +1,128 @@ loadAll(); $commit = new PhabricatorRepositoryCommit(); $conn_r = $commit->establishConnection('r'); - // TODO: Both these queries are basically bogus and have total trash for - // query plans, and don't return the right results. Build a cache instead. - // These are just pulling data with approximately the right look to it. - $commits = $commit->loadAllWhere( - '1 = 1 GROUP BY repositoryPHID'); - $commits = mpull($commits, null, 'getRepositoryPHID'); - - $commit_counts = queryfx_all( - $conn_r, - 'SELECT repositoryPHID, count(*) N FROM %T - GROUP BY repositoryPHID', + // TODO: These queries are pretty bogus. + + $commits = array(); + $commit_counts = array(); + + $max_epoch = queryfx_all( + $commit->establishConnection('r'), + 'SELECT repositoryID, MAX(epoch) maxEpoch FROM %T GROUP BY repositoryID', $commit->getTableName()); - $commit_counts = ipull($commit_counts, 'N', 'repositoryPHID'); + + if ($max_epoch) { + $sql = array(); + foreach ($max_epoch as $head) { + $sql[] = '('.(int)$head['repositoryID'].', '.(int)$head['maxEpoch'].')'; + } + + // NOTE: It's possible we'll pull multiple commits for some repository + // here but it reduces query cost around 3x to unique them in PHP rather + // than apply GROUP BY in MySQL. + $commits = $commit->loadAllWhere( + '(repositoryID, epoch) IN (%Q)', + implode(', ', $sql)); + $commits = mpull($commits, null, 'getRepositoryID'); + + $commit_counts = queryfx_all( + $conn_r, + 'SELECT repositoryID, count(*) N FROM %T + GROUP BY repositoryID', + $commit->getTableName()); + $commit_counts = ipull($commit_counts, 'N', 'repositoryID'); + } $rows = array(); foreach ($repositories as $repository) { - $phid = $repository->getPHID(); - $commit = idx($commits, $phid); + $id = $repository->getID(); + $commit = idx($commits, $id); + $date = null; + $time = null; + if ($commit) { + $date = date('M j, Y', $commit->getEpoch()); + $time = date('g:i A', $commit->getEpoch()); + } + $rows[] = array( phutil_render_tag( 'a', array( 'href' => '/diffusion/'.$repository->getCallsign().'/', ), phutil_escape_html($repository->getName())), $repository->getVersionControlSystem(), - idx($commit_counts, $phid, 0), - $commit - ? $commit->getCommitIdentifier() - : null, // TODO: Link/format + idx($commit_counts, $id, 0), $commit - ? phabricator_format_timestamp($commit->getEpoch()) + ? DiffusionView::linkCommit( + $repository, + $commit->getCommitIdentifier()) : null, + $date, + $time, ); } $table = new AphrontTableView($rows); $table->setHeaders( array( 'Repository', 'VCS', 'Size', 'Last', - 'Committed', + 'Date', + 'Time', )); $table->setColumnClasses( array( 'wide', + '', + 'n', + 'n', + '', + 'right', )); $panel = new AphrontPanelView(); $panel->setHeader('Browse Repositories'); $panel->appendChild($table); $crumbs = $this->buildCrumbs(); return $this->buildStandardPageResponse( array( $crumbs, $panel, ), array( 'title' => 'Diffusion', )); } } diff --git a/src/applications/diffusion/controller/repository/DiffusionRepositoryController.php b/src/applications/diffusion/controller/repository/DiffusionRepositoryController.php index 7b14ccdd24..b62b3fd11d 100644 --- a/src/applications/diffusion/controller/repository/DiffusionRepositoryController.php +++ b/src/applications/diffusion/controller/repository/DiffusionRepositoryController.php @@ -1,79 +1,87 @@ diffusionRequest; $content = array(); $crumbs = $this->buildCrumbs(); $content[] = $crumbs; $history_query = DiffusionHistoryQuery::newFromDiffusionRequest( $drequest); $history_query->setLimit(15); $history = $history_query->loadHistory(); $history_table = new DiffusionHistoryTableView(); $history_table->setDiffusionRequest($drequest); $history_table->setHistory($history); + $callsign = $drequest->getRepository()->getCallsign(); + $all = phutil_render_tag( + 'a', + array( + 'href' => "/diffusion/{$callsign}/history/", + ), + 'View Full Commit History'); + $panel = new AphrontPanelView(); - $panel->setHeader('Recent Commits'); + $panel->setHeader("Recent Commits · {$all}"); $panel->appendChild($history_table); $content[] = $panel; $browse_query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest); $results = $browse_query->loadPaths(); $browse_table = new DiffusionBrowseTableView(); $browse_table->setDiffusionRequest($drequest); $browse_table->setPaths($results); $browse_panel = new AphrontPanelView(); $browse_panel->setHeader('Browse Repository'); $browse_panel->appendChild($browse_table); $content[] = $browse_panel; if ($drequest->getBranch() !== null) { $branch_query = DiffusionBranchQuery::newFromDiffusionRequest($drequest); $branches = $branch_query->loadBranches(); $branch_table = new DiffusionBranchTableView(); $branch_table->setDiffusionRequest($drequest); $branch_table->setBranches($branches); $branch_panel = new AphrontPanelView(); $branch_panel->setHeader('Branches'); $branch_panel->appendChild($branch_table); $content[] = $branch_panel; } return $this->buildStandardPageResponse( $content, array( 'title' => 'Diffusion', )); } } diff --git a/src/applications/diffusion/data/pathchange/DiffusionPathChange.php b/src/applications/diffusion/data/pathchange/DiffusionPathChange.php index 652ab82d08..ebd38224ef 100644 --- a/src/applications/diffusion/data/pathchange/DiffusionPathChange.php +++ b/src/applications/diffusion/data/pathchange/DiffusionPathChange.php @@ -1,33 +1,79 @@ commitIdentifier = $commit; return $this; } final public function getCommitIdentifier() { return $this->commitIdentifier; } + final public function setCommit($commit) { + $this->commit = $commit; + return $this; + } + + final public function getCommit() { + return $this->commit; + } + + final public function setCommitData($commit_data) { + $this->commitData = $commit_data; + return $this; + } + + final public function getCommitData() { + return $this->commitData; + } + + + final public function getEpoch() { + if ($this->getCommit()) { + return $this->getCommit()->getEpoch(); + } + return null; + } + + final public function getAuthorName() { + if ($this->getCommitData()) { + return $this->getCommitData()->getAuthorName(); + } + return null; + } + + final public function getSummary() { + if (!$this->getCommitData()) { + return null; + } + $message = $this->getCommitData()->getCommitMessage(); + $first = idx(explode("\n", $message), 0); + return substr($first, 0, 80); + } + + + } diff --git a/src/applications/diffusion/data/pathchange/__init__.php b/src/applications/diffusion/data/pathchange/__init__.php index 1e0dcbd347..0256f567bf 100644 --- a/src/applications/diffusion/data/pathchange/__init__.php +++ b/src/applications/diffusion/data/pathchange/__init__.php @@ -1,10 +1,12 @@ getRequest(); $repository = $drequest->getRepository(); $path = $drequest->getPath(); $commit = $drequest->getCommit(); $path_normal = '/'.trim($path, '/'); $conn_r = $repository->establishConnection('r'); $paths = queryfx_all( $conn_r, 'SELECT id, path FROM %T WHERE path IN (%Ls)', PhabricatorRepository::TABLE_PATH, array($path_normal)); $paths = ipull($paths, 'id', 'path'); $path_id = $paths[$path_normal]; + if ($commit) { + $slice_clause = 'AND svnCommit <= '.(int)$commit; + } else { + $slice_clause = ''; + } + $index = queryfx_all( $conn_r, 'SELECT pathID, max(svnCommit) maxCommit FROM %T WHERE repositoryID = %d AND parentID = %d %Q GROUP BY pathID', PhabricatorRepository::TABLE_FILESYSTEM, $repository->getID(), $path_id, - ''); + $slice_clause); if (!$index) { // TODO: ! return false; } $sql = array(); foreach ($index as $row) { $sql[] = '('.(int)$row['pathID'].', '.(int)$row['maxCommit'].')'; } $browse = queryfx_all( $conn_r, 'SELECT *, p.path pathName FROM %T f JOIN %T p ON f.pathID = p.id WHERE repositoryID = %d AND parentID = %d AND existed = 1 AND (pathID, svnCommit) in (%Q) ORDER BY pathName', PhabricatorRepository::TABLE_FILESYSTEM, PhabricatorRepository::TABLE_PATH, $repository->getID(), $path_id, implode(', ', $sql)); $results = array(); foreach ($browse as $file) { $file_path = $file['pathName']; $file_path = ltrim(substr($file_path, strlen($path_normal)), '/'); $result = new DiffusionRepositoryPath(); $result->setPath($file_path); // $result->setHash($hash); $result->setFileType($file['fileType']); // $result->setFileSize($size); $results[] = $result; } return $results; } } diff --git a/src/applications/diffusion/query/history/base/DiffusionHistoryQuery.php b/src/applications/diffusion/query/history/base/DiffusionHistoryQuery.php index 15e33280ff..8cb1c1d719 100644 --- a/src/applications/diffusion/query/history/base/DiffusionHistoryQuery.php +++ b/src/applications/diffusion/query/history/base/DiffusionHistoryQuery.php @@ -1,70 +1,80 @@ } final public static function newFromDiffusionRequest( DiffusionRequest $request) { $repository = $request->getRepository(); switch ($repository->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $class = 'DiffusionGitHistoryQuery'; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $class = 'DiffusionSvnHistoryQuery'; break; default: throw new Exception("Unsupported VCS!"); } PhutilSymbolLoader::loadClass($class); $query = new $class(); $query->request = $request; return $query; } final protected function getRequest() { return $this->request; } final public function loadHistory() { return $this->executeQuery(); } final public function setLimit($limit) { $this->limit = $limit; return $this; } final public function getLimit() { return $this->limit; } + final public function setOffset($offset) { + $this->offset = $offset; + return $this; + } + + final public function getOffset() { + return $this->offset; + } + abstract protected function executeQuery(); } diff --git a/src/applications/diffusion/query/history/git/DiffusionGitHistoryQuery.php b/src/applications/diffusion/query/history/git/DiffusionGitHistoryQuery.php index 9226d98069..a30ce88f25 100644 --- a/src/applications/diffusion/query/history/git/DiffusionGitHistoryQuery.php +++ b/src/applications/diffusion/query/history/git/DiffusionGitHistoryQuery.php @@ -1,66 +1,84 @@ getRequest(); $repository = $drequest->getRepository(); $path = $drequest->getPath(); - $commit = $drequest->getCommit(); + $commit_hash = $drequest->getCommit(); $local_path = $repository->getDetail('local-path'); $git = $drequest->getPathToGitBinary(); list($stdout) = execx( '(cd %s && %s log '. '--skip=%d '. '-n %d '. - '-M '. - '-C '. - '-B '. - '--find-copies-harder '. - '--raw '. '-t '. '--abbrev=40 '. - '--pretty=format:%%x1c%%H%%x1d '. + '--pretty=format:%%H '. '%s -- %s)', $local_path, $git, - $offset = 0, + $this->getOffset(), $this->getLimit(), - $commit, + $commit_hash, $path); - $commits = explode("\x1c", $stdout); - array_shift($commits); // \x1c character is first, remove empty record + $hashes = explode("\n", $stdout); + $hashes = array_filter($hashes); - $history = array(); - foreach ($commits as $commit) { - list($hash, $raw) = explode("\x1d", $commit); + $commits = array(); + $commit_data = array(); + + if ($hashes) { + $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere( + 'repositoryID = %d AND commitIdentifier IN (%Ls)', + $repository->getID(), + $hashes); + $commits = mpull($commits, null, 'getCommitIdentifier'); + if ($commits) { + $commit_data = id(new PhabricatorRepositoryCommitData())->loadAllWhere( + 'commitID in (%Ld)', + mpull($commits, 'getID')); + $commit_data = mpull($commit_data, null, 'getCommitID'); + } + } + $history = array(); + foreach ($hashes as $hash) { $item = new DiffusionPathChange(); $item->setCommitIdentifier($hash); + $commit = idx($commits, $hash); + if ($commit) { + $item->setCommit($commit); + $data = idx($commit_data, $commit->getID()); + if ($data) { + $item->setCommitData($data); + } + } $history[] = $item; } return $history; } } diff --git a/src/applications/diffusion/query/history/git/__init__.php b/src/applications/diffusion/query/history/git/__init__.php index c2a505f6df..a1f26cd3ff 100644 --- a/src/applications/diffusion/query/history/git/__init__.php +++ b/src/applications/diffusion/query/history/git/__init__.php @@ -1,15 +1,18 @@ getRequest(); $repository = $drequest->getRepository(); $path = $drequest->getPath(); $commit = $drequest->getCommit(); $conn_r = $repository->establishConnection('r'); $paths = queryfx_all( $conn_r, 'SELECT id, path FROM %T WHERE path IN (%Ls)', PhabricatorRepository::TABLE_PATH, array('/'.trim($path, '/'))); $paths = ipull($paths, 'id', 'path'); $path_id = $paths['/'.trim($path, '/')]; $history_data = queryfx_all( $conn_r, 'SELECT * FROM %T WHERE repositoryID = %d AND pathID = %d AND commitSequence <= %d ORDER BY commitSequence DESC LIMIT %d', PhabricatorRepository::TABLE_PATHCHANGE, $repository->getID(), $path_id, $commit ? $commit : 0x7FFFFFFF, $this->getLimit()); + $commits = array(); + $commit_data = array(); + + $commit_ids = ipull($history_data, 'commitID'); + if ($commit_ids) { + $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere( + 'id IN (%Ld)', + $commit_ids); + if ($commits) { + $commit_data = id(new PhabricatorRepositoryCommitData())->loadAllWhere( + 'commitID in (%Ld)', + $commit_ids); + $commit_data = mpull($commit_data, null, 'getCommitID'); + } + } + + + $history = array(); foreach ($history_data as $row) { $item = new DiffusionPathChange(); - $item->setCommitIdentifier($row['commitID']); + $commit = idx($commits, $row['commitID']); + if ($commit) { + $item->setCommit($commit); + $item->setCommitIdentifier($commit->getCommitIdentifier()); + $data = idx($commit_data, $commit->getID()); + if ($data) { + $item->setCommitData($data); + } + } $history[] = $item; } return $history; } } diff --git a/src/applications/diffusion/view/historytable/DiffusionHistoryTableView.php b/src/applications/diffusion/view/historytable/DiffusionHistoryTableView.php index c1960a7403..bf31331419 100644 --- a/src/applications/diffusion/view/historytable/DiffusionHistoryTableView.php +++ b/src/applications/diffusion/view/historytable/DiffusionHistoryTableView.php @@ -1,72 +1,85 @@ history = $history; return $this; } public function render() { $drequest = $this->getDiffusionRequest(); $rows = array(); foreach ($this->history as $history) { + $epoch = $history->getEpoch(); + + if ($epoch) { + $date = date('M j, Y', $epoch); + $time = date('g:i A', $epoch); + } else { + $date = null; + $time = null; + } + $rows[] = array( $this->linkBrowse( $drequest->getPath(), array( 'commit' => $history->getCommitIdentifier(), )), self::linkCommit( $drequest->getRepository(), $history->getCommitIdentifier()), - '?', - '?', - '', - '', + '-', + $date, + $time, + phutil_escape_html($history->getAuthorName()), + phutil_escape_html($history->getSummary()), // TODO: etc etc ); } $view = new AphrontTableView($rows); $view->setHeaders( array( 'Browse', 'Commit', 'Change', 'Date', + 'Time', 'Author', 'Details', )); $view->setColumnClasses( array( '', 'n', '', '', + 'right', '', 'wide wrap', )); return $view->render(); } } diff --git a/src/applications/diffusion/view/historytable/__init__.php b/src/applications/diffusion/view/historytable/__init__.php index f6e0c07164..5607901c5f 100644 --- a/src/applications/diffusion/view/historytable/__init__.php +++ b/src/applications/diffusion/view/historytable/__init__.php @@ -1,13 +1,16 @@ repository; } final public function run() { $this->repository = $this->loadRepository(); $sleep = 15; while (true) { $found = $this->discoverCommits(); if ($found) { $sleep = 15; } else { $sleep = min($sleep + 15, 60 * 15); } $this->sleep($sleep); } } protected function isKnownCommit($target) { if (isset($this->commitCache[$target])) { return true; } $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere( - 'repositoryPHID = %s AND commitIdentifier = %s', - $this->getRepository()->getPHID(), + 'repositoryID = %s AND commitIdentifier = %s', + $this->getRepository()->getID(), $target); if (!$commit) { return false; } $this->commitCache[$target] = true; while (count($this->commitCache) > 16) { array_shift($this->commitCache); } return true; } protected function recordCommit($commit_identifier, $epoch) { $repository = $this->getRepository(); $commit = new PhabricatorRepositoryCommit(); - $commit->setRepositoryPHID($repository->getPHID()); + $commit->setRepositoryID($repository->getID()); $commit->setCommitIdentifier($commit_identifier); $commit->setEpoch($epoch); try { $commit->save(); $event = new PhabricatorTimelineEvent( 'cmit', array( 'id' => $commit->getID(), )); $event->recordEvent(); $this->commitCache[$commit_identifier] = true; } catch (AphrontQueryDuplicateKeyException $ex) { // Ignore. This can happen because we discover the same new commit // more than once when looking at history, or because of races or // data inconsistency or cosmic radiation; in any case, we're still // in a good state if we ignore the failure. } $this->stillWorking(); } abstract protected function discoverCommits(); } diff --git a/src/applications/repository/daemon/committask/PhabricatorRepositoryCommitTaskDaemon.php b/src/applications/repository/daemon/committask/PhabricatorRepositoryCommitTaskDaemon.php index 65874fed0f..9e0aab76cc 100644 --- a/src/applications/repository/daemon/committask/PhabricatorRepositoryCommitTaskDaemon.php +++ b/src/applications/repository/daemon/committask/PhabricatorRepositoryCommitTaskDaemon.php @@ -1,72 +1,71 @@ getData(); if (!$data) { // TODO: This event can't be processed, provide some way to // communicate that? continue; } $commit = id(new PhabricatorRepositoryCommit())->load($data['id']); if (!$commit) { // TODO: Same as above. continue; } // TODO: Cache these. - $repository = id(new PhabricatorRepository())->loadOneWhere( - 'phid = %s', - $commit->getRepositoryPHID()); + $repository = id(new PhabricatorRepository())->load( + $commit->getRepositoryID()); $vcs = $repository->getVersionControlSystem(); switch ($vcs) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $class = 'PhabricatorRepositoryGitCommitMessageParserWorker'; $task = new PhabricatorWorkerTask(); $task->setTaskClass($class); $task->setData($commit->getID()); $task->save(); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $class = 'PhabricatorRepositorySvnCommitMessageParserWorker'; $task = new PhabricatorWorkerTask(); $task->setTaskClass($class); $task->setData($commit->getID()); $task->save(); break; default: throw new Exception("Unknown repository type."); } $this->stillWorking(); } sleep(1); $this->stillWorking(); } while (true); } } diff --git a/src/applications/repository/storage/commit/PhabricatorRepositoryCommit.php b/src/applications/repository/storage/commit/PhabricatorRepositoryCommit.php index b0efefaf63..b3dce63f0d 100644 --- a/src/applications/repository/storage/commit/PhabricatorRepositoryCommit.php +++ b/src/applications/repository/storage/commit/PhabricatorRepositoryCommit.php @@ -1,38 +1,38 @@ true, self::CONFIG_TIMESTAMPS => false, ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorPHIDConstants::PHID_TYPE_CMIT); } } diff --git a/src/applications/repository/worker/base/PhabricatorRepositoryCommitParserWorker.php b/src/applications/repository/worker/base/PhabricatorRepositoryCommitParserWorker.php index 04043e5e77..822c612246 100644 --- a/src/applications/repository/worker/base/PhabricatorRepositoryCommitParserWorker.php +++ b/src/applications/repository/worker/base/PhabricatorRepositoryCommitParserWorker.php @@ -1,54 +1,53 @@ getTaskData(); if (!$commit_id) { return; } $commit = id(new PhabricatorRepositoryCommit())->load($commit_id); if (!$commit) { // TODO: Communicate permanent failure? return; } $this->commit = $commit; - $repository = id(new PhabricatorRepository())->loadOneWhere( - 'phid = %s', - $commit->getRepositoryPHID()); + $repository = id(new PhabricatorRepository())->load( + $commit->getRepositoryID()); if (!$repository) { return; } return $this->parseCommit($repository, $commit); } abstract protected function parseCommit( PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit); } diff --git a/src/applications/repository/worker/commitchangeparser/base/PhabricatorRepositoryCommitChangeParserWorker.php b/src/applications/repository/worker/commitchangeparser/base/PhabricatorRepositoryCommitChangeParserWorker.php index c61250990b..e9e871c94f 100644 --- a/src/applications/repository/worker/commitchangeparser/base/PhabricatorRepositoryCommitChangeParserWorker.php +++ b/src/applications/repository/worker/commitchangeparser/base/PhabricatorRepositoryCommitChangeParserWorker.php @@ -1,69 +1,75 @@ establishConnection('w'); $result_map = $this->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)', $path); } queryfx( $conn_w, - 'INSERT INTO %T (path) VALUES %Q', + 'INSERT IGNORE INTO %T (path) VALUES %Q', PhabricatorRepository::TABLE_PATH, implode(', ', $sql)); } $result_map += $this->lookupPaths($missing_paths); } return $result_map; } private 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 path IN (%Ls)', PhabricatorRepository::TABLE_PATH, $path_chunk); foreach ($chunk_map as $row) { $result_map[$row['path']] = $row['id']; } } return $result_map; } }