From dd944f7d833b88dfa6ee968ddac4722d327737c3 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 25 Jan 2014 14:01:58 -0800 Subject: [PATCH] Separate repository mirroring into an Engine and provide `bin/repository mirror` Summary: Ref T4338. Currently, there's no diagnostic command to execute mirroring (so I can't give users an easy command to run), and it's roughly the last piece of real logic left in the PullLocal daemon. Separate mirroring out, and provide `bin/repository mirror`. Test Plan: - Ran `bin/repository mirror` to mirror a repository. - Ran PullLocalDaemon and verified it also continued mirroring normally. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T4338 Differential Revision: https://secure.phabricator.com/D8066 --- src/__phutil_library_map__.php | 4 ++ .../PhabricatorRepositoryPullLocalDaemon.php | 53 ++++--------------- .../engine/PhabricatorRepositoryEngine.php | 5 ++ .../PhabricatorRepositoryMirrorEngine.php | 51 ++++++++++++++++++ ...atorRepositoryManagementMirrorWorkflow.php | 52 ++++++++++++++++++ 5 files changed, 121 insertions(+), 44 deletions(-) create mode 100644 src/applications/repository/engine/PhabricatorRepositoryMirrorEngine.php create mode 100644 src/applications/repository/management/PhabricatorRepositoryManagementMirrorWorkflow.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index e3747346d6..42c34e6f5f 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1860,12 +1860,14 @@ phutil_register_library_map(array( 'PhabricatorRepositoryManagementListWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListWorkflow.php', 'PhabricatorRepositoryManagementLookupUsersWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementLookupUsersWorkflow.php', 'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMarkImportedWorkflow.php', + 'PhabricatorRepositoryManagementMirrorWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMirrorWorkflow.php', 'PhabricatorRepositoryManagementPullWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementPullWorkflow.php', 'PhabricatorRepositoryManagementRefsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementRefsWorkflow.php', 'PhabricatorRepositoryManagementWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementWorkflow.php', 'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryMercurialCommitChangeParserWorker.php', 'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryMercurialCommitMessageParserWorker.php', 'PhabricatorRepositoryMirror' => 'applications/repository/storage/PhabricatorRepositoryMirror.php', + 'PhabricatorRepositoryMirrorEngine' => 'applications/repository/engine/PhabricatorRepositoryMirrorEngine.php', 'PhabricatorRepositoryMirrorQuery' => 'applications/repository/query/PhabricatorRepositoryMirrorQuery.php', 'PhabricatorRepositoryPHIDTypeArcanistProject' => 'applications/repository/phid/PhabricatorRepositoryPHIDTypeArcanistProject.php', 'PhabricatorRepositoryPHIDTypeCommit' => 'applications/repository/phid/PhabricatorRepositoryPHIDTypeCommit.php', @@ -4539,6 +4541,7 @@ phutil_register_library_map(array( 'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementLookupUsersWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'PhabricatorRepositoryManagementWorkflow', + 'PhabricatorRepositoryManagementMirrorWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementPullWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementRefsWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementWorkflow' => 'PhabricatorManagementWorkflow', @@ -4549,6 +4552,7 @@ phutil_register_library_map(array( 0 => 'PhabricatorRepositoryDAO', 1 => 'PhabricatorPolicyInterface', ), + 'PhabricatorRepositoryMirrorEngine' => 'PhabricatorRepositoryEngine', 'PhabricatorRepositoryMirrorQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryPHIDTypeArcanistProject' => 'PhabricatorPHIDType', 'PhabricatorRepositoryPHIDTypeCommit' => 'PhabricatorPHIDType', diff --git a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php index 9d68f661bb..484e70a519 100644 --- a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php +++ b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php @@ -141,6 +141,7 @@ final class PhabricatorRepositoryPullLocalDaemon null); $this->discoverRepository($repository); $this->updateRepositoryRefs($repository); + $this->mirrorRepository($repository); $repository->writeStatusMessage( PhabricatorRepositoryStatusMessage::TYPE_FETCH, PhabricatorRepositoryStatusMessage::CODE_OKAY); @@ -229,21 +230,25 @@ final class PhabricatorRepositoryPullLocalDaemon $this->checkIfRepositoryIsFullyImported($repository); + return (bool)count($refs); + } + + private function mirrorRepository(PhabricatorRepository $repository) { try { - $this->pushToMirrors($repository); + id(new PhabricatorRepositoryMirrorEngine()) + ->setRepository($repository) + ->pushToMirrors(); } catch (Exception $ex) { // TODO: We should report these into the UI properly, but for // now just complain. These errors are much less severe than // pull errors. $proxy = new PhutilProxyException( pht( - 'Error while pushing "%s" repository to a mirror.', + 'Error while pushing "%s" repository to mirrors.', $repository->getCallsign()), $ex); phlog($proxy); } - - return (bool)count($refs); } private function updateRepositoryRefs(PhabricatorRepository $repository) { @@ -299,44 +304,4 @@ final class PhabricatorRepositoryPullLocalDaemon $repository->saveTransaction(); } - - private function pushToMirrors(PhabricatorRepository $repository) { - if (!$repository->canMirror()) { - return; - } - - $mirrors = id(new PhabricatorRepositoryMirrorQuery()) - ->setViewer($this->getViewer()) - ->withRepositoryPHIDs(array($repository->getPHID())) - ->execute(); - - // TODO: This is a little bit janky, but we don't have first-class - // infrastructure for running remote commands against an arbitrary remote - // right now. Just make an emphemeral copy of the repository and muck with - // it a little bit. In the medium term, we should pull this command stuff - // out and use it here and for "Land to ...". - - $proxy = clone $repository; - $proxy->makeEphemeral(); - - $proxy->setDetail('hosting-enabled', false); - foreach ($mirrors as $mirror) { - $proxy->setDetail('remote-uri', $mirror->getRemoteURI()); - $proxy->setCredentialPHID($mirror->getCredentialPHID()); - - $this->log(pht('Pushing to remote "%s"...', $mirror->getRemoteURI())); - - if (!$proxy->isGit()) { - throw new Exception('Unsupported VCS!'); - } - - $future = $proxy->getRemoteCommandFuture( - 'push --verbose --mirror -- %P', - $proxy->getRemoteURIEnvelope()); - - $future - ->setCWD($proxy->getLocalPath()) - ->resolvex(); - } - } } diff --git a/src/applications/repository/engine/PhabricatorRepositoryEngine.php b/src/applications/repository/engine/PhabricatorRepositoryEngine.php index 9c304af4c5..ce8fb183a8 100644 --- a/src/applications/repository/engine/PhabricatorRepositoryEngine.php +++ b/src/applications/repository/engine/PhabricatorRepositoryEngine.php @@ -47,6 +47,11 @@ abstract class PhabricatorRepositoryEngine { } + public function getViewer() { + return PhabricatorUser::getOmnipotentUser(); + } + + /** * @task internal */ diff --git a/src/applications/repository/engine/PhabricatorRepositoryMirrorEngine.php b/src/applications/repository/engine/PhabricatorRepositoryMirrorEngine.php new file mode 100644 index 0000000000..058ef3f1f8 --- /dev/null +++ b/src/applications/repository/engine/PhabricatorRepositoryMirrorEngine.php @@ -0,0 +1,51 @@ +getRepository(); + + if (!$repository->canMirror()) { + return; + } + + $mirrors = id(new PhabricatorRepositoryMirrorQuery()) + ->setViewer($this->getViewer()) + ->withRepositoryPHIDs(array($repository->getPHID())) + ->execute(); + + // TODO: This is a little bit janky, but we don't have first-class + // infrastructure for running remote commands against an arbitrary remote + // right now. Just make an emphemeral copy of the repository and muck with + // it a little bit. In the medium term, we should pull this command stuff + // out and use it here and for "Land to ...". + + $proxy = clone $repository; + $proxy->makeEphemeral(); + + $proxy->setDetail('hosting-enabled', false); + foreach ($mirrors as $mirror) { + $proxy->setDetail('remote-uri', $mirror->getRemoteURI()); + $proxy->setCredentialPHID($mirror->getCredentialPHID()); + + $this->log(pht('Pushing to remote "%s"...', $mirror->getRemoteURI())); + + if (!$proxy->isGit()) { + throw new Exception('Unsupported VCS!'); + } + + $future = $proxy->getRemoteCommandFuture( + 'push --verbose --mirror -- %P', + $proxy->getRemoteURIEnvelope()); + + $future + ->setCWD($proxy->getLocalPath()) + ->resolvex(); + } + } + +} diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementMirrorWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementMirrorWorkflow.php new file mode 100644 index 0000000000..16c72effed --- /dev/null +++ b/src/applications/repository/management/PhabricatorRepositoryManagementMirrorWorkflow.php @@ -0,0 +1,52 @@ +setName('mirror') + ->setExamples('**mirror** [__options__] __repository__ ...') + ->setSynopsis( + pht('Push __repository__, named by callsign, to mirrors.')) + ->setArguments( + array( + array( + 'name' => 'verbose', + 'help' => pht('Show additional debugging information.'), + ), + array( + 'name' => 'repos', + 'wildcard' => true, + ), + )); + } + + public function execute(PhutilArgumentParser $args) { + $repos = $this->loadRepositories($args, 'repos'); + + if (!$repos) { + throw new PhutilArgumentUsageException( + pht( + "Specify one or more repositories to push to mirrors, by ". + "callsign.")); + } + + $console = PhutilConsole::getConsole(); + foreach ($repos as $repo) { + $console->writeOut( + "%s\n", + pht('Pushing "%s" to mirrors...', $repo->getCallsign())); + + $engine = id(new PhabricatorRepositoryMirrorEngine()) + ->setRepository($repo) + ->setVerbose($args->getArg('verbose')) + ->pushToMirrors(); + } + + $console->writeOut("Done.\n"); + + return 0; + } + +}