private function markReachable(PhabricatorRepository $repository) { if (!$repository->isGit()) { throw new PhutilArgumentUsageException(pht('Only Git repositories are supported, this repository ("%s") is ' . 'not a Git repository.', $repository->getDisplayName())); } $viewer = $this->getViewer(); $commits = id(new DiffusionCommitQuery())->setViewer($viewer)->withRepository($repository)->execute(); $flag = PhabricatorRepositoryCommit::IMPORTED_UNREACHABLE; $graph = new PhabricatorGitGraphStream($repository); foreach ($commits as $commit) { $identifier = $commit->getCommitIdentifier(); try { $graph->getCommitDate($identifier); $unreachable = false; } catch (Exception $ex) { $unreachable = true; } // The commit has proper reachability, so do nothing. if ($commit->isUnreachable() === $unreachable) { $this->untouchedCount++; continue; } if ($unreachable) { echo tsprintf("%s: %s\n", $commit->getMonogram(), pht('Marking commit unreachable.')); $commit->writeImportStatusFlag($flag); } else { echo tsprintf("%s: %s\n", $commit->getMonogram(), pht('Marking commit reachable.')); $commit->clearImportStatusFlag($flag); } } }
private function pushRepositoryToMirror(PhabricatorRepository $repository, PhabricatorRepositoryURI $mirror_uri) { $this->log(pht('Pushing to remote "%s"...', $mirror_uri->getEffectiveURI())); if ($repository->isGit()) { $this->pushToGitRepository($repository, $mirror_uri); } else { if ($repository->isHg()) { $this->pushToHgRepository($repository, $mirror_uri); } else { throw new Exception(pht('Unsupported VCS!')); } } }
private function getRequestDirectoryPath(PhabricatorRepository $repository) { $request = $this->getRequest(); $request_path = $request->getRequestURI()->getPath(); $base_path = preg_replace('@^/diffusion/[A-Z]+@', '', $request_path); // For Git repositories, strip an optional directory component if it // isn't the name of a known Git resource. This allows users to clone // repositories as "/diffusion/X/anything.git", for example. if ($repository->isGit()) { $known = array('info', 'git-upload-pack', 'git-receive-pack'); foreach ($known as $key => $path) { $known[$key] = preg_quote($path, '@'); } $known = implode('|', $known); if (preg_match('@^/([^/]+)/(' . $known . ')(/|$)@', $base_path)) { $base_path = preg_replace('@^/([^/]+)@', '', $base_path); } } return $base_path; }
private function markUnreachableCommits(PhabricatorRepository $repository) { // For now, this is only supported for Git. if (!$repository->isGit()) { return; } // Find older versions of refs which we haven't processed yet. We're going // to make sure their commits are still reachable. $old_refs = id(new PhabricatorRepositoryOldRef())->loadAllWhere('repositoryPHID = %s', $repository->getPHID()); // We can share a single graph stream across all the checks we need to do. $stream = new PhabricatorGitGraphStream($repository); foreach ($old_refs as $old_ref) { $identifier = $old_ref->getCommitIdentifier(); $this->markUnreachableFrom($repository, $stream, $identifier); // If nothing threw an exception, we're all done with this ref. $old_ref->delete(); } }
private function rebuildRepository(PhabricatorRepository $repo) { $console = PhutilConsole::getConsole(); $console->writeOut("%s\n", pht('Rebuilding "%s"...', $repo->getMonogram())); $refs = id(new PhabricatorRepositoryRefCursorQuery())->setViewer($this->getViewer())->withRefTypes(array(PhabricatorRepositoryRefCursor::TYPE_BRANCH))->withRepositoryPHIDs(array($repo->getPHID()))->execute(); $graph = array(); foreach ($refs as $ref) { if (!$repo->shouldTrackBranch($ref->getRefName())) { continue; } $console->writeOut("%s\n", pht('Rebuilding branch "%s"...', $ref->getRefName())); $commit = $ref->getCommitIdentifier(); if ($repo->isGit()) { $stream = new PhabricatorGitGraphStream($repo, $commit); } else { $stream = new PhabricatorMercurialGraphStream($repo, $commit); } $discover = array($commit); while ($discover) { $target = array_pop($discover); if (isset($graph[$target])) { continue; } $graph[$target] = $stream->getParents($target); foreach ($graph[$target] as $parent) { $discover[] = $parent; } } } $console->writeOut("%s\n", pht('Found %s total commit(s); updating...', phutil_count($graph))); $commit_table = id(new PhabricatorRepositoryCommit()); $commit_table_name = $commit_table->getTableName(); $conn_w = $commit_table->establishConnection('w'); $bar = id(new PhutilConsoleProgressBar())->setTotal(count($graph)); $need = array(); foreach ($graph as $child => $parents) { foreach ($parents as $parent) { $need[$parent] = $parent; } $need[$child] = $child; } $map = array(); foreach (array_chunk($need, 2048) as $chunk) { $rows = queryfx_all($conn_w, 'SELECT id, commitIdentifier FROM %T WHERE commitIdentifier IN (%Ls) AND repositoryID = %d', $commit_table_name, $chunk, $repo->getID()); foreach ($rows as $row) { $map[$row['commitIdentifier']] = $row['id']; } } $insert_sql = array(); $delete_sql = array(); foreach ($graph as $child => $parents) { $names = $parents; $names[] = $child; foreach ($names as $name) { if (empty($map[$name])) { throw new Exception(pht('Unknown commit "%s"!', $name)); } } if (!$parents) { // Write an explicit 0 to indicate "no parents" instead of "no data". $insert_sql[] = qsprintf($conn_w, '(%d, 0)', $map[$child]); } else { foreach ($parents as $parent) { $insert_sql[] = qsprintf($conn_w, '(%d, %d)', $map[$child], $map[$parent]); } } $delete_sql[] = $map[$child]; $bar->update(1); } $commit_table->openTransaction(); foreach (PhabricatorLiskDAO::chunkSQL($delete_sql) as $chunk) { queryfx($conn_w, 'DELETE FROM %T WHERE childCommitID IN (%Q)', PhabricatorRepository::TABLE_PARENTS, $chunk); } foreach (PhabricatorLiskDAO::chunkSQL($insert_sql) as $chunk) { queryfx($conn_w, 'INSERT INTO %T (childCommitID, parentCommitID) VALUES %Q', PhabricatorRepository::TABLE_PARENTS, $chunk); } $commit_table->saveTransaction(); $bar->done(); }
public function shouldEnableForRepository(PhabricatorRepository $repository) { return $repository->isGit(); }
protected function canBuildForRepository(PhabricatorRepository $repository) { return $repository->isGit(); }
private function getObservedVersion(PhabricatorRepository $repository) { if ($repository->isHosted()) { return null; } if ($repository->isGit()) { return $this->getGitObservedVersion($repository); } return null; }
private function markUnreachableCommits(PhabricatorRepository $repository) { // For now, this is only supported for Git. if (!$repository->isGit()) { return; } // Find older versions of refs which we haven't processed yet. We're going // to make sure their commits are still reachable. $old_refs = id(new PhabricatorRepositoryOldRef())->loadAllWhere('repositoryPHID = %s', $repository->getPHID()); // If we don't have any refs to update, bail out before building a graph // stream. In particular, this improves behavior in empty repositories, // where `git log` exits with an error. if (!$old_refs) { return; } // We can share a single graph stream across all the checks we need to do. $stream = new PhabricatorGitGraphStream($repository); foreach ($old_refs as $old_ref) { $identifier = $old_ref->getCommitIdentifier(); $this->markUnreachableFrom($repository, $stream, $identifier); // If nothing threw an exception, we're all done with this ref. $old_ref->delete(); } }