@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Serve Git reads over SSH

Summary: Like D7423, but for SSH.

Test Plan: Ran `git clone ssh://...`, got a clone.

Reviewers: btrahan

Reviewed By: btrahan

CC: hach-que, aran

Maniphest Tasks: T2230

Differential Revision: https://secure.phabricator.com/D7424

+65 -5
+8
src/applications/diffusion/ssh/DiffusionSSHGitUploadPackWorkflow.php
··· 23 23 return head($args->getArg('dir')); 24 24 } 25 25 26 + protected function executeRepositoryOperations( 27 + PhabricatorRepository $repository) { 28 + 29 + $future = new ExecFuture('git-upload-pack %s', $repository->getLocalPath()); 30 + 31 + return $this->passthruIO($future); 32 + } 33 + 26 34 }
+4 -5
src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
··· 10 10 11 11 abstract protected function isReadOnly(); 12 12 abstract protected function getRequestPath(); 13 + abstract protected function executeRepositoryOperations( 14 + PhabricatorRepository $repository); 15 + 13 16 protected function writeError($message) { 14 17 $this->getErrorChannel()->write($message); 15 18 return $this; ··· 20 23 21 24 try { 22 25 $repository = $this->loadRepository(); 23 - 24 - throw new Exception("TODO: Implement serve over SSH."); 25 - 26 + return $this->executeRepositoryOperations($repository); 26 27 } catch (Exception $ex) { 27 28 $this->writeError(get_class($ex).': '.$ex->getMessage()); 28 29 return 1; 29 30 } 30 - 31 - return 0; 32 31 } 33 32 34 33 private function loadRepository() {
+53
src/infrastructure/ssh/PhabricatorSSHWorkflow.php
··· 37 37 return $this->iochannel; 38 38 } 39 39 40 + public function passthruIO(ExecFuture $future) { 41 + $exec_channel = new PhutilExecChannel($future); 42 + $exec_channel->setStderrHandler(array($this, 'writeErrorIOCallback')); 43 + 44 + $io_channel = $this->getIOChannel(); 45 + $error_channel = $this->getErrorChannel(); 46 + 47 + $channels = array($exec_channel, $io_channel, $error_channel); 48 + 49 + while (true) { 50 + PhutilChannel::waitForAny($channels); 51 + 52 + $io_channel->update(); 53 + $exec_channel->update(); 54 + $error_channel->update(); 55 + 56 + $done = !$exec_channel->isOpen(); 57 + 58 + $data = $io_channel->read(); 59 + if (strlen($data)) { 60 + $exec_channel->write($data); 61 + } 62 + 63 + $data = $exec_channel->read(); 64 + if (strlen($data)) { 65 + $io_channel->write($data); 66 + } 67 + 68 + // If we have nothing left on stdin, close stdin on the subprocess. 69 + if (!$io_channel->isOpenForReading()) { 70 + // TODO: This should probably be part of PhutilExecChannel? 71 + $future->write(''); 72 + } 73 + 74 + if ($done) { 75 + break; 76 + } 77 + } 78 + 79 + list($err) = $future->resolve(); 80 + 81 + return $err; 82 + } 83 + 40 84 public function readAllInput() { 41 85 $channel = $this->getIOChannel(); 42 86 while ($channel->update()) { ··· 51 95 public function writeIO($data) { 52 96 $this->getIOChannel()->write($data); 53 97 return $this; 98 + } 99 + 100 + public function writeErrorIO($data) { 101 + $this->getErrorChannel()->write($data); 102 + return $this; 103 + } 104 + 105 + public function writeErrorIOCallback(PhutilChannel $channel, $data) { 106 + $this->writeErrorIO($data); 54 107 } 55 108 56 109 }