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 validateGitLFSRequest(PhabricatorRepository $repository, PhabricatorUser $viewer)
 {
     if (!$this->getIsGitLFSRequest()) {
         return null;
     }
     if (!$repository->canUseGitLFS()) {
         return new PhabricatorVCSResponse(403, pht('The requested repository ("%s") does not support Git LFS.', $repository->getDisplayName()));
     }
     // If this is using an LFS token, sanity check that we're using it on the
     // correct repository. This shouldn't really matter since the user could
     // just request a proper token anyway, but it suspicious and should not
     // be permitted.
     $token = $this->getGitLFSToken();
     if ($token) {
         $resource = $token->getTokenResource();
         if ($resource !== $repository->getPHID()) {
             return new PhabricatorVCSResponse(403, pht('The authentication token provided in the request is bound to ' . 'a different repository than the requested repository ("%s").', $repository->getDisplayName()));
         }
     }
     return null;
 }
 private function expectChanges(PhabricatorRepository $repository, array $commits, array $expect)
 {
     foreach ($commits as $commit) {
         $commit_identifier = $commit->getCommitIdentifier();
         $expect_changes = idx($expect, $commit_identifier);
         if ($expect_changes === null) {
             $this->assertEqual($commit_identifier, null, pht('No test entry for commit "%s" in repository "%s"!', $commit_identifier, $repository->getDisplayName()));
         }
         $changes = $this->parseCommit($repository, $commit);
         $path_map = id(new DiffusionPathQuery())->withPathIDs(mpull($changes, 'getPathID'))->execute();
         $path_map = ipull($path_map, 'path');
         $target_commits = array_filter(mpull($changes, 'getTargetCommitID'));
         if ($target_commits) {
             $commits = id(new DiffusionCommitQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withIDs($target_commits)->execute();
             $target_commits = mpull($commits, 'getCommitIdentifier', 'getID');
         }
         $dicts = array();
         foreach ($changes as $key => $change) {
             $target_path = idx($path_map, $change->getTargetPathID());
             $target_commit = idx($target_commits, $change->getTargetCommitID());
             $dicts[$key] = array($path_map[(int) $change->getPathID()], $target_path, $target_commit ? (string) $target_commit : null, (int) $change->getChangeType(), (int) $change->getFileType(), (int) $change->getIsDirect(), (int) $change->getCommitSequence());
         }
         $dicts = ipull($dicts, null, 0);
         $expect_changes = ipull($expect_changes, null, 0);
         ksort($dicts);
         ksort($expect_changes);
         $this->assertEqual($expect_changes, $dicts, pht('Commit %s', $commit_identifier));
     }
 }
 private function verifySubversionRoot(PhabricatorRepository $repository)
 {
     list($xml) = $repository->execxRemoteCommand('info --xml %s', $repository->getSubversionPathURI());
     $xml = phutil_utf8ize($xml);
     $xml = new SimpleXMLElement($xml);
     $remote_root = (string) $xml->entry[0]->repository[0]->root[0];
     $expect_root = $repository->getSubversionPathURI();
     $normal_type_svn = PhabricatorRepositoryURINormalizer::TYPE_SVN;
     $remote_normal = id(new PhabricatorRepositoryURINormalizer($normal_type_svn, $remote_root))->getNormalizedPath();
     $expect_normal = id(new PhabricatorRepositoryURINormalizer($normal_type_svn, $expect_root))->getNormalizedPath();
     if ($remote_normal != $expect_normal) {
         throw new Exception(pht('Repository "%s" does not have a correctly configured remote URI. ' . 'The remote URI for a Subversion repository MUST point at the ' . 'repository root. The root for this repository is "%s", but the ' . 'configured URI is "%s". To resolve this error, set the remote URI ' . 'to point at the repository root. If you want to import only part ' . 'of a Subversion repository, use the "Import Only" option.', $repository->getDisplayName(), $remote_root, $expect_root));
     }
 }
 private function isCommitOnBranch(PhabricatorRepository $repo, PhabricatorRepositoryCommit $commit, ReleephBranch $releeph_branch)
 {
     switch ($repo->getVersionControlSystem()) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             list($output) = $repo->execxLocalCommand('branch --all --no-color --contains %s', $commit->getCommitIdentifier());
             $remote_prefix = 'remotes/origin/';
             $branches = array();
             foreach (array_filter(explode("\n", $output)) as $line) {
                 $tokens = explode(' ', $line);
                 $ref = last($tokens);
                 if (strncmp($ref, $remote_prefix, strlen($remote_prefix)) === 0) {
                     $branch = substr($ref, strlen($remote_prefix));
                     $branches[$branch] = $branch;
                 }
             }
             return idx($branches, $releeph_branch->getName());
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(DiffusionRequest::newFromDictionary(array('user' => $this->getUser(), 'repository' => $repo, 'commit' => $commit->getCommitIdentifier())));
             $path_changes = $change_query->loadChanges();
             $commit_paths = mpull($path_changes, 'getPath');
             $branch_path = $releeph_branch->getName();
             $in_branch = array();
             $ex_branch = array();
             foreach ($commit_paths as $path) {
                 if (strncmp($path, $branch_path, strlen($branch_path)) === 0) {
                     $in_branch[] = $path;
                 } else {
                     $ex_branch[] = $path;
                 }
             }
             if ($in_branch && $ex_branch) {
                 $error = pht('CONFUSION: commit %s in %s contains %d path change(s) that were ' . 'part of a Releeph branch, but also has %d path change(s) not ' . 'part of a Releeph branch!', $commit->getCommitIdentifier(), $repo->getDisplayName(), count($in_branch), count($ex_branch));
                 phlog($error);
             }
             return !empty($in_branch);
             break;
     }
 }
 /**
  * @task pull
  */
 private function resolveUpdateFuture(PhabricatorRepository $repository, ExecFuture $future, $min_sleep)
 {
     $display_name = $repository->getDisplayName();
     $this->log(pht('Resolving update for "%s".', $display_name));
     try {
         list($stdout, $stderr) = $future->resolvex();
     } catch (Exception $ex) {
         $proxy = new PhutilProxyException(pht('Error while updating the "%s" repository.', $display_name), $ex);
         phlog($proxy);
         $smart_wait = $repository->loadUpdateInterval($min_sleep);
         return PhabricatorTime::getNow() + $smart_wait;
     }
     if (strlen($stderr)) {
         $stderr_msg = pht('Unexpected output while updating repository "%s": %s', $display_name, $stderr);
         phlog($stderr_msg);
     }
     $smart_wait = $repository->loadUpdateInterval($min_sleep);
     $this->log(pht('Based on activity in repository "%s", considering a wait of %s ' . 'seconds before update.', $display_name, new PhutilNumber($smart_wait)));
     return PhabricatorTime::getNow() + $smart_wait;
 }