Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13993368
D7423.id16716.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
D7423.id16716.diff
View Options
Index: src/__phutil_library_map__.php
===================================================================
--- src/__phutil_library_map__.php
+++ src/__phutil_library_map__.php
@@ -480,6 +480,7 @@
'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php',
'DiffusionGitRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionGitRawDiffQuery.php',
'DiffusionGitRequest' => 'applications/diffusion/request/DiffusionGitRequest.php',
+ 'DiffusionGitResponse' => 'applications/diffusion/response/DiffusionGitResponse.php',
'DiffusionGitStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionGitStableCommitNameQuery.php',
'DiffusionHistoryController' => 'applications/diffusion/controller/DiffusionHistoryController.php',
'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php',
@@ -2672,6 +2673,7 @@
'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionGitRawDiffQuery' => 'DiffusionRawDiffQuery',
'DiffusionGitRequest' => 'DiffusionRequest',
+ 'DiffusionGitResponse' => 'AphrontResponse',
'DiffusionGitStableCommitNameQuery' => 'DiffusionStableCommitNameQuery',
'DiffusionHistoryController' => 'DiffusionController',
'DiffusionHistoryTableView' => 'DiffusionView',
Index: src/applications/diffusion/controller/DiffusionController.php
===================================================================
--- src/applications/diffusion/controller/DiffusionController.php
+++ src/applications/diffusion/controller/DiffusionController.php
@@ -17,6 +17,8 @@
if (preg_match($regex, (string)$uri, $matches)) {
$vcs = null;
+ $content_type = $request->getHTTPHeader('Content-Type');
+
if ($request->getExists('__vcs__')) {
// This is magic to make it easier for us to debug stuff by telling
// users to run:
@@ -26,8 +28,13 @@
// ...to get a human-readable error.
$vcs = $request->getExists('__vcs__');
} else if ($request->getExists('service')) {
+ $service = $request->getStr('service');
+ // We get this initially for `info/refs`.
// Git also gives us a User-Agent like "git/1.8.2.3".
$vcs = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
+ } else if ($content_type == 'application/x-git-upload-pack-request') {
+ // We get this for `git-upload-pack`.
+ $vcs = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
} else if ($request->getExists('cmd')) {
// Mercurial also sends an Accept header like
// "application/mercurial-0.1", and a User-Agent like
@@ -125,6 +132,13 @@
pht('This repository is not available over HTTP.'));
}
+ switch ($repository->getVersionControlSystem()) {
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
+ return $this->serveGitRequest($repository);
+ default:
+ break;
+ }
+
return new PhabricatorVCSResponse(
999,
pht('TODO: Implement meaningful responses.'));
@@ -133,22 +147,28 @@
private function isReadOnlyRequest(
PhabricatorRepository $repository) {
$request = $this->getRequest();
+ $method = $_SERVER['REQUEST_METHOD'];
// TODO: This implementation is safe by default, but very incomplete.
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$service = $request->getStr('service');
+ $path = $this->getRequestDirectoryPath();
// NOTE: Service names are the reverse of what you might expect, as they
// are from the point of view of the server. The main read service is
// "git-upload-pack", and the main write service is "git-receive-pack".
- switch ($service) {
- case 'git-upload-pack':
- return true;
- case 'git-receive-pack':
- default:
- return false;
+
+ if ($method == 'GET' &&
+ $path == '/info/refs' &&
+ $service == 'git-upload-pack') {
+ return true;
+ }
+
+ if ($path == '/git-upload-pack') {
+ return true;
}
+
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$cmd = $request->getStr('cmd');
@@ -375,5 +395,52 @@
return $links;
}
+ /**
+ * @phutil-external-symbol class PhabricatorStartup
+ */
+ private function serveGitRequest(PhabricatorRepository $repository) {
+ $request = $this->getRequest();
+
+ $request_path = $this->getRequestDirectoryPath();
+ $repository_root = $repository->getLocalPath();
+
+ // Rebuild the query string to strip `__magic__` parameters and prevent
+ // issues where we might interpret inputs like "service=read&service=write"
+ // differently than the server does and pass it an unsafe command.
+ $query_data = $request->getPassthroughRequestParameters();
+ $query_string = http_build_query($query_data, '', '&');
+
+ // We're about to wipe out PATH with the rest of the environment, so
+ // resolve the binary first.
+ $bin = Filesystem::resolveBinary('git-http-backend');
+ if (!$bin) {
+ throw new Exception("Unable to find `git-http-backend` in PATH!");
+ }
+
+ $env = array(
+ 'REQUEST_METHOD' => $_SERVER['REQUEST_METHOD'],
+ 'QUERY_STRING' => $query_string,
+ 'CONTENT_TYPE' => $_SERVER['CONTENT_TYPE'],
+ 'REMOTE_USER' => '',
+ 'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'],
+ 'GIT_PROJECT_ROOT' => $repository_root,
+ 'GIT_HTTP_EXPORT_ALL' => '1',
+ 'PATH_INFO' => $request_path,
+ );
+
+ list($stdout) = id(new ExecFuture('%s', $bin))
+ ->setEnv($env, true)
+ ->write(PhabricatorStartup::getRawInput())
+ ->resolvex();
+
+ return id(new DiffusionGitResponse())->setGitData($stdout);
+ }
+
+ private function getRequestDirectoryPath() {
+ $request = $this->getRequest();
+ $request_path = $request->getRequestURI()->getPath();
+ return preg_replace('@^/diffusion/[A-Z]+@', '', $request_path);
+ }
+
}
Index: src/applications/diffusion/response/DiffusionGitResponse.php
===================================================================
--- /dev/null
+++ src/applications/diffusion/response/DiffusionGitResponse.php
@@ -0,0 +1,44 @@
+<?php
+
+final class DiffusionGitResponse extends AphrontResponse {
+
+ private $httpCode;
+ private $headers = array();
+ private $response;
+
+ public function setGitData($data) {
+ list($headers, $body) = explode("\r\n\r\n", $data, 2);
+ $this->response = $body;
+ $headers = explode("\r\n", $headers);
+
+ $matches = null;
+ $this->httpCode = 200;
+ $this->headers = array();
+ foreach ($headers as $header) {
+ if (preg_match('/^Status:\s*(\d+)/i', $header, $matches)) {
+ $this->httpCode = (int)$matches[1];
+ } else {
+ $this->headers[] = explode(': ', $header, 2);
+ }
+ }
+
+ return $this;
+ }
+
+ public function buildResponseString() {
+ return $this->response;
+ }
+
+ public function getHeaders() {
+ return $this->headers;
+ }
+
+ public function getCacheHeaders() {
+ return array();
+ }
+
+ public function getHTTPResponseCode() {
+ return $this->httpCode;
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Oct 23, 10:26 PM (2 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6745304
Default Alt Text
D7423.id16716.diff (7 KB)
Attached To
Mode
D7423: Serve Git reads over HTTP
Attached
Detach File
Event Timeline
Log In to Comment