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 markUnreachableFrom(PhabricatorRepository $repository, PhabricatorGitGraphStream $stream, $identifier) { $unreachable = array(); $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere('repositoryID = %s AND commitIdentifier = %s', $repository->getID(), $identifier); if (!$commit) { return; } $look = array($commit); $seen = array(); while ($look) { $target = array_pop($look); // If we've already checked this commit (for example, because history // branches and then merges) we don't need to check it again. $target_identifier = $target->getCommitIdentifier(); if (isset($seen[$target_identifier])) { continue; } $seen[$target_identifier] = true; try { $stream->getCommitDate($target_identifier); $reachable = true; } catch (Exception $ex) { $reachable = false; } if ($reachable) { // This commit is reachable, so we don't need to go any further // down this road. continue; } $unreachable[] = $target; // Find the commit's parents and check them for reachability, too. We // have to look in the database since we no may longer have the commit // in the repository. $rows = queryfx_all($commit->establishConnection('w'), 'SELECT commit.* FROM %T commit JOIN %T parents ON commit.id = parents.parentCommitID WHERE parents.childCommitID = %d', $commit->getTableName(), PhabricatorRepository::TABLE_PARENTS, $target->getID()); if (!$rows) { continue; } $parents = id(new PhabricatorRepositoryCommit())->loadAllFromArray($rows); foreach ($parents as $parent) { $look[] = $parent; } } $unreachable = array_reverse($unreachable); $flag = PhabricatorRepositoryCommit::IMPORTED_UNREACHABLE; foreach ($unreachable as $unreachable_commit) { $unreachable_commit->writeImportStatusFlag($flag); } // If anything was unreachable, just rebuild the whole summary table. // We can't really update it incrementally when a commit becomes // unreachable. if ($unreachable) { $this->rebuildSummaryTable($repository); } }
/** * @task git */ private function executeGitDiscoverCommit(PhabricatorRepository $repository, $commit, $branch, $autoclose) { $discover = array($commit); $insert = array($commit); $seen_parent = array(); $stream = new PhabricatorGitGraphStream($repository, $commit); while (true) { $target = array_pop($discover); $parents = $stream->getParents($target); foreach ($parents as $parent) { if (isset($seen_parent[$parent])) { // We end up in a loop here somehow when we parse Arcanist if we // don't do this. TODO: Figure out why and draw a pretty diagram // since it's not evident how parsing a DAG with this causes the // loop to stop terminating. continue; } $seen_parent[$parent] = true; if ($autoclose) { $known = $this->isKnownCommitOnAnyAutocloseBranch($repository, $parent); } else { $known = $this->isKnownCommit($repository, $parent); } if (!$known) { $this->log("Discovered commit '{$parent}'."); $discover[] = $parent; $insert[] = $parent; } } if (empty($discover)) { break; } } $n = count($insert); if ($autoclose) { $this->log("Found {$n} new autoclose commits on branch '{$branch}'."); } else { $this->log("Found {$n} new commits on branch '{$branch}'."); } while (true) { $target = array_pop($insert); $epoch = $stream->getCommitDate($target); $epoch = trim($epoch); if ($autoclose) { $this->updateCommit($repository, $target, $branch); } else { $this->recordCommit($repository, $target, $epoch, $branch); } if (empty($insert)) { break; } } }