Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F82873
D7421.diff
All Users
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D7421.diff
View Options
diff --git a/scripts/ssh/ssh-exec.php b/scripts/ssh/ssh-exec.php
--- a/scripts/ssh/ssh-exec.php
+++ b/scripts/ssh/ssh-exec.php
@@ -61,6 +61,8 @@
$workflows = array(
new ConduitSSHWorkflow(),
+
+ new DiffusionSSHGitUploadPackWorkflow(),
);
$workflow_names = mpull($workflows, 'getName', 'getName');
@@ -81,16 +83,24 @@
throw new Exception("Unable to open stdout.");
}
+ $sock_stderr = fopen('php://stderr', 'w');
+ if (!$sock_stderr) {
+ throw new Exception("Unable to open stderr.");
+ }
+
$socket_channel = new PhutilSocketChannel(
$sock_stdin,
$sock_stdout);
+ $error_channel = new PhutilSocketChannel(null, $sock_stderr);
$metrics_channel = new PhutilMetricsChannel($socket_channel);
$workflow->setIOChannel($metrics_channel);
+ $workflow->setErrorChannel($error_channel);
$err = $workflow->execute($original_args);
$metrics_channel->flush();
+ $error_channel->flush();
} catch (Exception $ex) {
- echo "phabricator-ssh-exec: ".$ex->getMessage()."\n";
+ fwrite(STDERR, "phabricator-ssh-exec: ".$ex->getMessage()."\n");
exit(1);
}
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -526,6 +526,9 @@
'DiffusionRepositoryPath' => 'applications/diffusion/data/DiffusionRepositoryPath.php',
'DiffusionRepositoryTag' => 'applications/diffusion/data/DiffusionRepositoryTag.php',
'DiffusionRequest' => 'applications/diffusion/request/DiffusionRequest.php',
+ 'DiffusionSSHGitUploadPackWorkflow' => 'applications/diffusion/ssh/DiffusionSSHGitUploadPackWorkflow.php',
+ 'DiffusionSSHGitWorkflow' => 'applications/diffusion/ssh/DiffusionSSHGitWorkflow.php',
+ 'DiffusionSSHWorkflow' => 'applications/diffusion/ssh/DiffusionSSHWorkflow.php',
'DiffusionSetupException' => 'applications/diffusion/exception/DiffusionSetupException.php',
'DiffusionStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionStableCommitNameQuery.php',
'DiffusionSvnCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionSvnCommitParentsQuery.php',
@@ -2711,6 +2714,9 @@
0 => 'DiffusionController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
+ 'DiffusionSSHGitUploadPackWorkflow' => 'DiffusionSSHGitWorkflow',
+ 'DiffusionSSHGitWorkflow' => 'DiffusionSSHWorkflow',
+ 'DiffusionSSHWorkflow' => 'PhabricatorSSHWorkflow',
'DiffusionSetupException' => 'AphrontUsageException',
'DiffusionStableCommitNameQuery' => 'DiffusionQuery',
'DiffusionSvnCommitParentsQuery' => 'DiffusionCommitParentsQuery',
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryEditHostingController.php b/src/applications/diffusion/controller/DiffusionRepositoryEditHostingController.php
--- a/src/applications/diffusion/controller/DiffusionRepositoryEditHostingController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryEditHostingController.php
@@ -134,7 +134,7 @@
if ($request->isFormPost()) {
$v_http_mode = $request->getStr('http');
- $v_ssh_mode = PhabricatorRepository::SERVE_OFF;
+ $v_ssh_mode = $request->getStr('ssh');
$xactions = array();
$template = id(new PhabricatorRepositoryTransaction());
@@ -176,6 +176,29 @@
'writes.');
}
+ $ssh_control =
+ id(new AphrontFormRadioButtonControl())
+ ->setName('ssh')
+ ->setLabel(pht('SSH'))
+ ->setValue($v_ssh_mode)
+ ->addButton(
+ PhabricatorRepository::SERVE_OFF,
+ PhabricatorRepository::getProtocolAvailabilityName(
+ PhabricatorRepository::SERVE_OFF),
+ pht('Phabricator will not serve this repository.'))
+ ->addButton(
+ PhabricatorRepository::SERVE_READONLY,
+ PhabricatorRepository::getProtocolAvailabilityName(
+ PhabricatorRepository::SERVE_READONLY),
+ pht('Phabricator will serve a read-only copy of this repository.'))
+ ->addButton(
+ PhabricatorRepository::SERVE_READWRITE,
+ PhabricatorRepository::getProtocolAvailabilityName(
+ PhabricatorRepository::SERVE_READWRITE),
+ $rw_message,
+ $repository->isHosted() ? null : 'disabled',
+ $repository->isHosted() ? null : true);
+
$http_control =
id(new AphrontFormRadioButtonControl())
->setName('http')
@@ -205,6 +228,7 @@
pht(
'Phabricator can serve repositories over various protocols. You can '.
'configure server protocols here.'))
+ ->appendChild($ssh_control)
->appendChild($http_control)
->appendChild(
id(new AphrontFormSubmitControl())
diff --git a/src/applications/diffusion/ssh/DiffusionSSHGitUploadPackWorkflow.php b/src/applications/diffusion/ssh/DiffusionSSHGitUploadPackWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/ssh/DiffusionSSHGitUploadPackWorkflow.php
@@ -0,0 +1,26 @@
+<?php
+
+final class DiffusionSSHGitUploadPackWorkflow
+ extends DiffusionSSHGitWorkflow {
+
+ public function didConstruct() {
+ $this->setName('git-upload-pack');
+ $this->setArguments(
+ array(
+ array(
+ 'name' => 'dir',
+ 'wildcard' => true,
+ ),
+ ));
+ }
+
+ public function isReadOnly() {
+ return true;
+ }
+
+ public function getRequestPath() {
+ $args = $this->getArgs();
+ return head($args->getArg('dir'));
+ }
+
+}
diff --git a/src/applications/diffusion/ssh/DiffusionSSHGitWorkflow.php b/src/applications/diffusion/ssh/DiffusionSSHGitWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/ssh/DiffusionSSHGitWorkflow.php
@@ -0,0 +1,10 @@
+<?php
+
+abstract class DiffusionSSHGitWorkflow extends DiffusionSSHWorkflow {
+
+ protected function writeError($message) {
+ // Git assumes we'll add our own newlines.
+ return parent::writeError($message."\n");
+ }
+
+}
diff --git a/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php b/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
@@ -0,0 +1,90 @@
+<?php
+
+abstract class DiffusionSSHWorkflow extends PhabricatorSSHWorkflow {
+
+ private $args;
+
+ public function getArgs() {
+ return $this->args;
+ }
+
+ abstract protected function isReadOnly();
+ abstract protected function getRequestPath();
+ protected function writeError($message) {
+ $this->getErrorChannel()->write($message);
+ return $this;
+ }
+
+ final public function execute(PhutilArgumentParser $args) {
+ $this->args = $args;
+
+ try {
+ $repository = $this->loadRepository();
+
+ throw new Exception("TODO: Implement serve over SSH.");
+
+ } catch (Exception $ex) {
+ $this->writeError(get_class($ex).': '.$ex->getMessage());
+ return 1;
+ }
+
+ return 0;
+ }
+
+ private function loadRepository() {
+ $viewer = $this->getUser();
+ $path = $this->getRequestPath();
+
+ $regex = '@^/?diffusion/(?P<callsign>[A-Z]+)(?:/|$)@';
+ $matches = null;
+ if (!preg_match($regex, $path, $matches)) {
+ throw new Exception(
+ pht(
+ 'Unrecognized repository path "%s". Expected a path like '.
+ '"%s".',
+ $path,
+ "/diffusion/X/"));
+ }
+
+ $callsign = $matches[1];
+ $repository = id(new PhabricatorRepositoryQuery())
+ ->setViewer($viewer)
+ ->withCallsigns(array($callsign))
+ ->executeOne();
+
+ if (!$repository) {
+ throw new Exception(
+ pht('No repository "%s" exists!', $callsign));
+ }
+
+ $is_push = !$this->isReadOnly();
+
+ switch ($repository->getServeOverSSH()) {
+ case PhabricatorRepository::SERVE_READONLY:
+ if ($is_push) {
+ throw new Exception(
+ pht('This repository is read-only over SSH.'));
+ }
+ break;
+ case PhabricatorRepository::SERVE_READWRITE:
+ if ($is_push) {
+ $can_push = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $repository,
+ DiffusionCapabilityPush::CAPABILITY);
+ if (!$can_push) {
+ throw new Exception(
+ pht('You do not have permission to push to this repository.'));
+ }
+ }
+ break;
+ case PhabricatorRepository::SERVE_OFF:
+ default:
+ throw new Exception(
+ pht('This repository is not available over SSH.'));
+ }
+
+ return $repository;
+ }
+
+}
diff --git a/src/infrastructure/ssh/PhabricatorSSHWorkflow.php b/src/infrastructure/ssh/PhabricatorSSHWorkflow.php
--- a/src/infrastructure/ssh/PhabricatorSSHWorkflow.php
+++ b/src/infrastructure/ssh/PhabricatorSSHWorkflow.php
@@ -4,6 +4,16 @@
private $user;
private $iochannel;
+ private $errorChannel;
+
+ public function setErrorChannel(PhutilChannel $error_channel) {
+ $this->errorChannel = $error_channel;
+ return $this;
+ }
+
+ public function getErrorChannel() {
+ return $this->errorChannel;
+ }
public function setUser(PhabricatorUser $user) {
$this->user = $user;
@@ -38,4 +48,9 @@
return $channel->read();
}
+ public function writeIO($data) {
+ $this->getIOChannel()->write($data);
+ return $this;
+ }
+
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/du/jj/3wekjxk6sty6427r
Default Alt Text
D7421.diff (9 KB)
Attached To
Mode
D7421: Route some VCS connections over SSH
Attached
Detach File
Event Timeline
Log In to Comment