mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-01 09:28:22 +01:00
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
This commit is contained in:
parent
7d9dfb561d
commit
9a2e45ef12
3 changed files with 65 additions and 5 deletions
|
@ -23,4 +23,12 @@ final class DiffusionSSHGitUploadPackWorkflow
|
|||
return head($args->getArg('dir'));
|
||||
}
|
||||
|
||||
protected function executeRepositoryOperations(
|
||||
PhabricatorRepository $repository) {
|
||||
|
||||
$future = new ExecFuture('git-upload-pack %s', $repository->getLocalPath());
|
||||
|
||||
return $this->passthruIO($future);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@ abstract class DiffusionSSHWorkflow extends PhabricatorSSHWorkflow {
|
|||
|
||||
abstract protected function isReadOnly();
|
||||
abstract protected function getRequestPath();
|
||||
abstract protected function executeRepositoryOperations(
|
||||
PhabricatorRepository $repository);
|
||||
|
||||
protected function writeError($message) {
|
||||
$this->getErrorChannel()->write($message);
|
||||
return $this;
|
||||
|
@ -20,15 +23,11 @@ abstract class DiffusionSSHWorkflow extends PhabricatorSSHWorkflow {
|
|||
|
||||
try {
|
||||
$repository = $this->loadRepository();
|
||||
|
||||
throw new Exception("TODO: Implement serve over SSH.");
|
||||
|
||||
return $this->executeRepositoryOperations($repository);
|
||||
} catch (Exception $ex) {
|
||||
$this->writeError(get_class($ex).': '.$ex->getMessage());
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function loadRepository() {
|
||||
|
|
|
@ -37,6 +37,50 @@ abstract class PhabricatorSSHWorkflow extends PhutilArgumentWorkflow {
|
|||
return $this->iochannel;
|
||||
}
|
||||
|
||||
public function passthruIO(ExecFuture $future) {
|
||||
$exec_channel = new PhutilExecChannel($future);
|
||||
$exec_channel->setStderrHandler(array($this, 'writeErrorIOCallback'));
|
||||
|
||||
$io_channel = $this->getIOChannel();
|
||||
$error_channel = $this->getErrorChannel();
|
||||
|
||||
$channels = array($exec_channel, $io_channel, $error_channel);
|
||||
|
||||
while (true) {
|
||||
PhutilChannel::waitForAny($channels);
|
||||
|
||||
$io_channel->update();
|
||||
$exec_channel->update();
|
||||
$error_channel->update();
|
||||
|
||||
$done = !$exec_channel->isOpen();
|
||||
|
||||
$data = $io_channel->read();
|
||||
if (strlen($data)) {
|
||||
$exec_channel->write($data);
|
||||
}
|
||||
|
||||
$data = $exec_channel->read();
|
||||
if (strlen($data)) {
|
||||
$io_channel->write($data);
|
||||
}
|
||||
|
||||
// If we have nothing left on stdin, close stdin on the subprocess.
|
||||
if (!$io_channel->isOpenForReading()) {
|
||||
// TODO: This should probably be part of PhutilExecChannel?
|
||||
$future->write('');
|
||||
}
|
||||
|
||||
if ($done) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list($err) = $future->resolve();
|
||||
|
||||
return $err;
|
||||
}
|
||||
|
||||
public function readAllInput() {
|
||||
$channel = $this->getIOChannel();
|
||||
while ($channel->update()) {
|
||||
|
@ -53,4 +97,13 @@ abstract class PhabricatorSSHWorkflow extends PhutilArgumentWorkflow {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function writeErrorIO($data) {
|
||||
$this->getErrorChannel()->write($data);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function writeErrorIOCallback(PhutilChannel $channel, $data) {
|
||||
$this->writeErrorIO($data);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue