test-gvfs-protocol: also serve smart protocol

This comes in handy, as we want to verify that `scalar clone` also works
against a GVFS-enabled remote repository.

Note that we have to set `MSYS2_ENV_CONV_EXCL` to prevent MSYS2 from
mangling `PATH_TRANSLATED`: The value _does_ look like a Unix-style
path, but no, MSYS2 must not be allowed to convert that into a Windows
path: `http-backend` needs it in the unmodified form. (The MSYS2 runtime
comes in when `git` is run via `bin-wrappers/git`, which is a shell
script.)

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin 2021-04-16 19:47:05 +02:00
Родитель a2b0d56115
Коммит ce509f679a
1 изменённых файлов: 50 добавлений и 0 удалений

Просмотреть файл

@ -1,5 +1,6 @@
#include "git-compat-util.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "alloc.h"
#include "setup.h"
@ -1490,6 +1491,8 @@ done:
static enum worker_result dispatch(struct req *req)
{
static regex_t *smart_http_regex;
static int initialized;
const char *method;
enum worker_result wr;
@ -1538,6 +1541,53 @@ static enum worker_result dispatch(struct req *req)
return do__gvfs_prefetch__get(req);
}
if (!initialized) {
smart_http_regex = xmalloc(sizeof(*smart_http_regex));
if (regcomp(smart_http_regex, "^/(HEAD|info/refs|"
"objects/info/[^/]+|git-(upload|receive)-pack)$",
REG_EXTENDED)) {
warning("could not compile smart HTTP regex");
smart_http_regex = NULL;
}
initialized = 1;
}
if (smart_http_regex &&
!regexec(smart_http_regex, req->uri_base.buf, 0, NULL, 0)) {
const char *ok = "HTTP/1.1 200 OK\r\n";
struct child_process cp = CHILD_PROCESS_INIT;
int i, res;
if (write(1, ok, strlen(ok)) < 0)
return error(_("could not send '%s'"), ok);
strvec_pushf(&cp.env, "REQUEST_METHOD=%s", method);
strvec_pushf(&cp.env, "PATH_TRANSLATED=%s",
req->uri_base.buf);
/* Prevent MSYS2 from "converting to a Windows path" */
strvec_pushf(&cp.env,
"MSYS2_ENV_CONV_EXCL=PATH_TRANSLATED");
strvec_push(&cp.env, "SERVER_PROTOCOL=HTTP/1.1");
if (req->quest_args.len)
strvec_pushf(&cp.env, "QUERY_STRING=%s",
req->quest_args.buf);
for (i = 0; i < req->header_list.nr; i++) {
const char *header = req->header_list.items[i].string;
if (!strncasecmp("Content-Type: ", header, 14))
strvec_pushf(&cp.env, "CONTENT_TYPE=%s",
header + 14);
else if (!strncasecmp("Content-Length: ", header, 16))
strvec_pushf(&cp.env, "CONTENT_LENGTH=%s",
header + 16);
}
cp.git_cmd = 1;
strvec_push(&cp.args, "http-backend");
res = run_command(&cp);
close(1);
close(0);
return !!res;
}
return send_http_error(1, 501, "Not Implemented", -1,
WR_OK | WR_HANGUP);
}