Page MenuHomePhabricator

D7387.diff

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
@@ -51,6 +51,7 @@
'AphrontFormToggleButtonsControl' => 'view/form/control/AphrontFormToggleButtonsControl.php',
'AphrontFormTokenizerControl' => 'view/form/control/AphrontFormTokenizerControl.php',
'AphrontFormView' => 'view/form/AphrontFormView.php',
+ 'AphrontGitResponse' => 'aphront/response/AphrontGitResponse.php',
'AphrontGlyphBarView' => 'view/widget/bars/AphrontGlyphBarView.php',
'AphrontHTMLResponse' => 'aphront/response/AphrontHTMLResponse.php',
'AphrontHTTPSink' => 'aphront/sink/AphrontHTTPSink.php',
@@ -475,6 +476,7 @@
'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php',
'DiffusionGitRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionGitRawDiffQuery.php',
'DiffusionGitRequest' => 'applications/diffusion/request/DiffusionGitRequest.php',
+ 'DiffusionGitServeController' => 'applications/diffusion/controller/DiffusionGitServeController.php',
'DiffusionGitStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionGitStableCommitNameQuery.php',
'DiffusionHistoryController' => 'applications/diffusion/controller/DiffusionHistoryController.php',
'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php',
@@ -619,6 +621,7 @@
'FileCreateMailReceiver' => 'applications/files/mail/FileCreateMailReceiver.php',
'FileMailReceiver' => 'applications/files/mail/FileMailReceiver.php',
'FileReplyHandler' => 'applications/files/mail/FileReplyHandler.php',
+ 'GitHTTPServer' => 'infrastructure/git/GitHTTPServer.php',
'HarbormasterBuild' => 'applications/harbormaster/storage/build/HarbormasterBuild.php',
'HarbormasterBuildArtifact' => 'applications/harbormaster/storage/build/HarbormasterBuildArtifact.php',
'HarbormasterBuildItem' => 'applications/harbormaster/storage/build/HarbormasterBuildItem.php',
@@ -2234,6 +2237,7 @@
'AphrontFormToggleButtonsControl' => 'AphrontFormControl',
'AphrontFormTokenizerControl' => 'AphrontFormControl',
'AphrontFormView' => 'AphrontView',
+ 'AphrontGitResponse' => 'AphrontResponse',
'AphrontGlyphBarView' => 'AphrontBarView',
'AphrontHTMLResponse' => 'AphrontResponse',
'AphrontHTTPSinkTestCase' => 'PhabricatorTestCase',
@@ -2646,6 +2650,7 @@
'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionGitRawDiffQuery' => 'DiffusionRawDiffQuery',
'DiffusionGitRequest' => 'DiffusionRequest',
+ 'DiffusionGitServeController' => 'DiffusionController',
'DiffusionGitStableCommitNameQuery' => 'DiffusionStableCommitNameQuery',
'DiffusionHistoryController' => 'DiffusionController',
'DiffusionHistoryTableView' => 'DiffusionView',
diff --git a/src/aphront/response/AphrontGitResponse.php b/src/aphront/response/AphrontGitResponse.php
new file mode 100644
--- /dev/null
+++ b/src/aphront/response/AphrontGitResponse.php
@@ -0,0 +1,47 @@
+<?php
+
+final class AphrontGitResponse extends AphrontResponse {
+
+ private $httpCode;
+ private $headers;
+ private $response;
+
+ public function setGitData($data) {
+ // We have to parse lines up until the HTTP double newline. First
+ // split on \r\n\r\n to get the headers and content as separate entries.
+ $headeridx = strpos($data, "\r\n\r\n");
+ $this->response = substr($data, $headeridx + 4);
+
+ // Now parse the headers, the CGI command can potentially output "Status:"
+ // to change the HTTP status code.
+ $lines = explode("\r\n", substr($data, 0, $headeridx));
+
+ $this->headers = array();
+ if (substr($lines[0], 0, 7) === "Status:") {
+ $this->httpCode = substr($lines[0], 8, 3);
+ } else {
+ $this->httpCode = 200;
+ }
+ for ($i = 1; $i < count($lines); $i++) {
+ $this->headers[] = explode(": ", $lines[$i]);
+ }
+ }
+
+ public function buildResponseString() {
+ return $this->response;
+ }
+
+ public function getHeaders() {
+ return $this->headers;
+ }
+
+ public function getCacheHeaders() {
+ return array();
+ }
+
+ public function getHTTPResponseCode() {
+ return $this->httpCode;
+ }
+
+}
+
diff --git a/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php b/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
--- a/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
+++ b/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
@@ -44,6 +44,7 @@
'(?:query/(?P<queryKey>[^/]+)/)?'
=> 'DiffusionRepositoryListController',
'create/' => 'DiffusionRepositoryCreateController',
+ 'git/(?P<callsign>[A-Z]+)(?<url>.+)' => 'DiffusionGitServeController',
'(?P<callsign>[A-Z]+)/' => array(
'' => 'DiffusionRepositoryController',
diff --git a/src/applications/diffusion/controller/DiffusionGitServeController.php b/src/applications/diffusion/controller/DiffusionGitServeController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/controller/DiffusionGitServeController.php
@@ -0,0 +1,45 @@
+<?php
+
+final class DiffusionGitServeController extends DiffusionController {
+
+ private $callsign;
+ private $url;
+
+ public function willProcessRequest(array $data) {
+ $this->callsign = idx($data, 'callsign');
+ $this->url = idx($data, 'url');
+ }
+
+ // TODO: We can't just throw the login page at a Git client, so this probably
+ // needs to be handled by presenting HTTP basic auth if Phabricator basic
+ // registration is enabled.
+
+ public function shouldRequireLogin() {
+ return false;
+ }
+
+ public function shouldRequireAdmin() {
+ return false;
+ }
+
+ public function shouldRequireEnabledUser() {
+ return false;
+ }
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function processRequest() {
+ $server = new GitHTTPServer();
+ // FIXME: Change the project root based on the data in Phabricator
+ $server->setProjectRoot("/home/james/git/test");
+ $data = $server->acceptRequest($this->url);
+
+ $response = new AphrontGitResponse();
+ $response->setGitData($data);
+ return $response;
+ }
+
+}
+
diff --git a/src/infrastructure/git/GitHTTPServer.php b/src/infrastructure/git/GitHTTPServer.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/git/GitHTTPServer.php
@@ -0,0 +1,40 @@
+<?php
+
+final class GitHTTPServer {
+
+ private $path;
+ private $projectRoot;
+
+ public function __construct($path = null) {
+ $this->path = $path;
+ if ($this->path === null) {
+ $this->path = "/usr/lib/git/git-http-backend";
+ }
+ }
+
+ public function setProjectRoot($root) {
+ $this->projectRoot = $root;
+ }
+
+ /**
+ * Accepts an Aphront request and returns the
+ * HTTP result from git-http-backend.
+ */
+ public function acceptRequest($url) {
+ // Set project root and HTTP export.
+ putenv("REQUEST_METHOD=".$_SERVER['REQUEST_METHOD']);
+ putenv("GIT_PROJECT_ROOT=".$this->projectRoot);
+ putenv("GIT_HTTP_EXPORT_ALL=1");
+ putenv("PATH_INFO=".$url);
+
+ // Execute git-http-backend.
+ list($err, $stdout, $strerr) = exec_manual($this->path);
+
+ // Returns the output of git-http-backend, which
+ // is the direct HTTP response we should return (including
+ // HTTP headers).
+ return $stdout;
+ }
+
+}
+

File Metadata

Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/4p/ur/cw2ycddvy55wdywi
Default Alt Text
D7387.diff (7 KB)

Event Timeline