Merge branch 'ab/serve-cleanup' into jk/reduce-malloc-in-v2-servers
* ab/serve-cleanup: upload-pack: document and rename --advertise-refs serve.[ch]: remove "serve_options", split up --advertise-refs code {upload,receive}-pack tests: add --advertise-refs tests serve.c: move version line to advertise_capabilities() serve: move transfer.advertiseSID check into session_id_advertise() serve.[ch]: don't pass "struct strvec *keys" to commands serve: use designated initializers transport: use designated initializers transport: rename "fetch" in transport_vtable to "fetch_refs" serve: mark has_capability() as static
This commit is contained in:
commit
0057847208
@ -41,6 +41,11 @@ OPTIONS
|
|||||||
<directory>::
|
<directory>::
|
||||||
The repository to sync into.
|
The repository to sync into.
|
||||||
|
|
||||||
|
--http-backend-info-refs::
|
||||||
|
Used by linkgit:git-http-backend[1] to serve up
|
||||||
|
`$GIT_URL/info/refs?service=git-receive-pack` requests. See
|
||||||
|
`--http-backend-info-refs` in linkgit:git-upload-pack[1].
|
||||||
|
|
||||||
PRE-RECEIVE HOOK
|
PRE-RECEIVE HOOK
|
||||||
----------------
|
----------------
|
||||||
Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists
|
Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists
|
||||||
|
@ -36,10 +36,14 @@ OPTIONS
|
|||||||
This fits with the HTTP POST request processing model where
|
This fits with the HTTP POST request processing model where
|
||||||
a program may read the request, write a response, and must exit.
|
a program may read the request, write a response, and must exit.
|
||||||
|
|
||||||
--advertise-refs::
|
--http-backend-info-refs::
|
||||||
Only the initial ref advertisement is output, and the program exits
|
Used by linkgit:git-http-backend[1] to serve up
|
||||||
immediately. This fits with the HTTP GET request model, where
|
`$GIT_URL/info/refs?service=git-upload-pack` requests. See
|
||||||
no request content is received but a response must be produced.
|
"Smart Clients" in link:technical/http-protocol.html[the HTTP
|
||||||
|
transfer protocols] documentation and "HTTP Transport" in
|
||||||
|
link:technical/protocol-v2.html[the Git Wire Protocol, Version
|
||||||
|
2] documentation. Also understood by
|
||||||
|
linkgit:git-receive-pack[1].
|
||||||
|
|
||||||
<directory>::
|
<directory>::
|
||||||
The repository to sync from.
|
The repository to sync from.
|
||||||
|
@ -225,6 +225,9 @@ The client may send Extra Parameters (see
|
|||||||
Documentation/technical/pack-protocol.txt) as a colon-separated string
|
Documentation/technical/pack-protocol.txt) as a colon-separated string
|
||||||
in the Git-Protocol HTTP header.
|
in the Git-Protocol HTTP header.
|
||||||
|
|
||||||
|
Uses the `--http-backend-info-refs` option to
|
||||||
|
linkgit:git-upload-pack[1].
|
||||||
|
|
||||||
Dumb Server Response
|
Dumb Server Response
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
Dumb servers MUST respond with the dumb server reply format.
|
Dumb servers MUST respond with the dumb server reply format.
|
||||||
|
@ -81,6 +81,9 @@ A v2 server would reply:
|
|||||||
Subsequent requests are then made directly to the service
|
Subsequent requests are then made directly to the service
|
||||||
`$GIT_URL/git-upload-pack`. (This works the same for git-receive-pack).
|
`$GIT_URL/git-upload-pack`. (This works the same for git-receive-pack).
|
||||||
|
|
||||||
|
Uses the `--http-backend-info-refs` option to
|
||||||
|
linkgit:git-upload-pack[1].
|
||||||
|
|
||||||
Capability Advertisement
|
Capability Advertisement
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
@ -2477,7 +2477,8 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
|
|||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT__QUIET(&quiet, N_("quiet")),
|
OPT__QUIET(&quiet, N_("quiet")),
|
||||||
OPT_HIDDEN_BOOL(0, "stateless-rpc", &stateless_rpc, NULL),
|
OPT_HIDDEN_BOOL(0, "stateless-rpc", &stateless_rpc, NULL),
|
||||||
OPT_HIDDEN_BOOL(0, "advertise-refs", &advertise_refs, NULL),
|
OPT_HIDDEN_BOOL(0, "http-backend-info-refs", &advertise_refs, NULL),
|
||||||
|
OPT_ALIAS(0, "advertise-refs", "http-backend-info-refs"),
|
||||||
OPT_HIDDEN_BOOL(0, "reject-thin-pack-for-testing", &reject_thin, NULL),
|
OPT_HIDDEN_BOOL(0, "reject-thin-pack-for-testing", &reject_thin, NULL),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
@ -16,16 +16,18 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)
|
|||||||
{
|
{
|
||||||
const char *dir;
|
const char *dir;
|
||||||
int strict = 0;
|
int strict = 0;
|
||||||
struct upload_pack_options opts = { 0 };
|
int advertise_refs = 0;
|
||||||
struct serve_options serve_opts = SERVE_OPTIONS_INIT;
|
int stateless_rpc = 0;
|
||||||
|
int timeout = 0;
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOL(0, "stateless-rpc", &opts.stateless_rpc,
|
OPT_BOOL(0, "stateless-rpc", &stateless_rpc,
|
||||||
N_("quit after a single request/response exchange")),
|
N_("quit after a single request/response exchange")),
|
||||||
OPT_BOOL(0, "advertise-refs", &opts.advertise_refs,
|
OPT_HIDDEN_BOOL(0, "http-backend-info-refs", &advertise_refs,
|
||||||
N_("exit immediately after initial ref advertisement")),
|
N_("serve up the info/refs for git-http-backend")),
|
||||||
|
OPT_ALIAS(0, "advertise-refs", "http-backend-info-refs"),
|
||||||
OPT_BOOL(0, "strict", &strict,
|
OPT_BOOL(0, "strict", &strict,
|
||||||
N_("do not try <directory>/.git/ if <directory> is no Git directory")),
|
N_("do not try <directory>/.git/ if <directory> is no Git directory")),
|
||||||
OPT_INTEGER(0, "timeout", &opts.timeout,
|
OPT_INTEGER(0, "timeout", &timeout,
|
||||||
N_("interrupt transfer after <n> seconds of inactivity")),
|
N_("interrupt transfer after <n> seconds of inactivity")),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
@ -38,9 +40,6 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)
|
|||||||
if (argc != 1)
|
if (argc != 1)
|
||||||
usage_with_options(upload_pack_usage, options);
|
usage_with_options(upload_pack_usage, options);
|
||||||
|
|
||||||
if (opts.timeout)
|
|
||||||
opts.daemon_mode = 1;
|
|
||||||
|
|
||||||
setup_path();
|
setup_path();
|
||||||
|
|
||||||
dir = argv[0];
|
dir = argv[0];
|
||||||
@ -50,21 +49,22 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
switch (determine_protocol_version_server()) {
|
switch (determine_protocol_version_server()) {
|
||||||
case protocol_v2:
|
case protocol_v2:
|
||||||
serve_opts.advertise_capabilities = opts.advertise_refs;
|
if (advertise_refs)
|
||||||
serve_opts.stateless_rpc = opts.stateless_rpc;
|
protocol_v2_advertise_capabilities();
|
||||||
serve(&serve_opts);
|
else
|
||||||
|
protocol_v2_serve_loop(stateless_rpc);
|
||||||
break;
|
break;
|
||||||
case protocol_v1:
|
case protocol_v1:
|
||||||
/*
|
/*
|
||||||
* v1 is just the original protocol with a version string,
|
* v1 is just the original protocol with a version string,
|
||||||
* so just fall through after writing the version string.
|
* so just fall through after writing the version string.
|
||||||
*/
|
*/
|
||||||
if (opts.advertise_refs || !opts.stateless_rpc)
|
if (advertise_refs || !stateless_rpc)
|
||||||
packet_write_fmt(1, "version 1\n");
|
packet_write_fmt(1, "version 1\n");
|
||||||
|
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case protocol_v0:
|
case protocol_v0:
|
||||||
upload_pack(&opts);
|
upload_pack(advertise_refs, stateless_rpc, timeout);
|
||||||
break;
|
break;
|
||||||
case protocol_unknown_version:
|
case protocol_unknown_version:
|
||||||
BUG("unknown protocol version");
|
BUG("unknown protocol version");
|
||||||
|
@ -534,7 +534,7 @@ static void get_info_refs(struct strbuf *hdr, char *arg)
|
|||||||
|
|
||||||
if (service_name) {
|
if (service_name) {
|
||||||
const char *argv[] = {NULL /* service name */,
|
const char *argv[] = {NULL /* service name */,
|
||||||
"--stateless-rpc", "--advertise-refs",
|
"--http-backend-info-refs",
|
||||||
".", NULL};
|
".", NULL};
|
||||||
struct rpc_service *svc = select_service(hdr, service_name);
|
struct rpc_service *svc = select_service(hdr, service_name);
|
||||||
|
|
||||||
|
@ -139,8 +139,7 @@ static int ls_refs_config(const char *var, const char *value, void *data)
|
|||||||
return parse_hide_refs_config(var, value, "uploadpack");
|
return parse_hide_refs_config(var, value, "uploadpack");
|
||||||
}
|
}
|
||||||
|
|
||||||
int ls_refs(struct repository *r, struct strvec *keys,
|
int ls_refs(struct repository *r, struct packet_reader *request)
|
||||||
struct packet_reader *request)
|
|
||||||
{
|
{
|
||||||
struct ls_refs_data data;
|
struct ls_refs_data data;
|
||||||
|
|
||||||
|
@ -2,10 +2,8 @@
|
|||||||
#define LS_REFS_H
|
#define LS_REFS_H
|
||||||
|
|
||||||
struct repository;
|
struct repository;
|
||||||
struct strvec;
|
|
||||||
struct packet_reader;
|
struct packet_reader;
|
||||||
int ls_refs(struct repository *r, struct strvec *keys,
|
int ls_refs(struct repository *r, struct packet_reader *request);
|
||||||
struct packet_reader *request);
|
|
||||||
int ls_refs_advertise(struct repository *r, struct strbuf *value);
|
int ls_refs_advertise(struct repository *r, struct strbuf *value);
|
||||||
|
|
||||||
#endif /* LS_REFS_H */
|
#endif /* LS_REFS_H */
|
||||||
|
@ -75,8 +75,7 @@ static void send_info(struct repository *r, struct packet_writer *writer,
|
|||||||
strbuf_release(&send_buffer);
|
strbuf_release(&send_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cap_object_info(struct repository *r, struct strvec *keys,
|
int cap_object_info(struct repository *r, struct packet_reader *request)
|
||||||
struct packet_reader *request)
|
|
||||||
{
|
{
|
||||||
struct requested_info info;
|
struct requested_info info;
|
||||||
struct packet_writer writer;
|
struct packet_writer writer;
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
#define PROTOCOL_CAPS_H
|
#define PROTOCOL_CAPS_H
|
||||||
|
|
||||||
struct repository;
|
struct repository;
|
||||||
struct strvec;
|
|
||||||
struct packet_reader;
|
struct packet_reader;
|
||||||
int cap_object_info(struct repository *r, struct strvec *keys,
|
int cap_object_info(struct repository *r, struct packet_reader *request);
|
||||||
struct packet_reader *request);
|
|
||||||
|
|
||||||
#endif /* PROTOCOL_CAPS_H */
|
#endif /* PROTOCOL_CAPS_H */
|
||||||
|
82
serve.c
82
serve.c
@ -9,7 +9,7 @@
|
|||||||
#include "serve.h"
|
#include "serve.h"
|
||||||
#include "upload-pack.h"
|
#include "upload-pack.h"
|
||||||
|
|
||||||
static int advertise_sid;
|
static int advertise_sid = -1;
|
||||||
|
|
||||||
static int always_advertise(struct repository *r,
|
static int always_advertise(struct repository *r,
|
||||||
struct strbuf *value)
|
struct strbuf *value)
|
||||||
@ -35,6 +35,9 @@ static int object_format_advertise(struct repository *r,
|
|||||||
|
|
||||||
static int session_id_advertise(struct repository *r, struct strbuf *value)
|
static int session_id_advertise(struct repository *r, struct strbuf *value)
|
||||||
{
|
{
|
||||||
|
if (advertise_sid == -1 &&
|
||||||
|
git_config_get_bool("transfer.advertisesid", &advertise_sid))
|
||||||
|
advertise_sid = 0;
|
||||||
if (!advertise_sid)
|
if (!advertise_sid)
|
||||||
return 0;
|
return 0;
|
||||||
if (value)
|
if (value)
|
||||||
@ -60,34 +63,58 @@ struct protocol_capability {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Function called when a client requests the capability as a command.
|
* Function called when a client requests the capability as a command.
|
||||||
* The function will be provided the capabilities requested via 'keys'
|
* Will be provided a struct packet_reader 'request' which it should
|
||||||
* as well as a struct packet_reader 'request' which the command should
|
|
||||||
* use to read the command specific part of the request. Every command
|
* use to read the command specific part of the request. Every command
|
||||||
* MUST read until a flush packet is seen before sending a response.
|
* MUST read until a flush packet is seen before sending a response.
|
||||||
*
|
*
|
||||||
* This field should be NULL for capabilities which are not commands.
|
* This field should be NULL for capabilities which are not commands.
|
||||||
*/
|
*/
|
||||||
int (*command)(struct repository *r,
|
int (*command)(struct repository *r, struct packet_reader *request);
|
||||||
struct strvec *keys,
|
|
||||||
struct packet_reader *request);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct protocol_capability capabilities[] = {
|
static struct protocol_capability capabilities[] = {
|
||||||
{ "agent", agent_advertise, NULL },
|
{
|
||||||
{ "ls-refs", ls_refs_advertise, ls_refs },
|
.name = "agent",
|
||||||
{ "fetch", upload_pack_advertise, upload_pack_v2 },
|
.advertise = agent_advertise,
|
||||||
{ "server-option", always_advertise, NULL },
|
},
|
||||||
{ "object-format", object_format_advertise, NULL },
|
{
|
||||||
{ "session-id", session_id_advertise, NULL },
|
.name = "ls-refs",
|
||||||
{ "object-info", always_advertise, cap_object_info },
|
.advertise = ls_refs_advertise,
|
||||||
|
.command = ls_refs,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "fetch",
|
||||||
|
.advertise = upload_pack_advertise,
|
||||||
|
.command = upload_pack_v2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "server-option",
|
||||||
|
.advertise = always_advertise,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "object-format",
|
||||||
|
.advertise = object_format_advertise,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "session-id",
|
||||||
|
.advertise = session_id_advertise,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "object-info",
|
||||||
|
.advertise = always_advertise,
|
||||||
|
.command = cap_object_info,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void advertise_capabilities(void)
|
void protocol_v2_advertise_capabilities(void)
|
||||||
{
|
{
|
||||||
struct strbuf capability = STRBUF_INIT;
|
struct strbuf capability = STRBUF_INIT;
|
||||||
struct strbuf value = STRBUF_INIT;
|
struct strbuf value = STRBUF_INIT;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* serve by default supports v2 */
|
||||||
|
packet_write_fmt(1, "version 2\n");
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
|
for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
|
||||||
struct protocol_capability *c = &capabilities[i];
|
struct protocol_capability *c = &capabilities[i];
|
||||||
|
|
||||||
@ -156,8 +183,8 @@ static int is_command(const char *key, struct protocol_capability **command)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int has_capability(const struct strvec *keys, const char *capability,
|
static int has_capability(const struct strvec *keys, const char *capability,
|
||||||
const char **value)
|
const char **value)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < keys->nr; i++) {
|
for (i = 0; i < keys->nr; i++) {
|
||||||
@ -270,35 +297,22 @@ static int process_request(void)
|
|||||||
if (has_capability(&keys, "session-id", &client_sid))
|
if (has_capability(&keys, "session-id", &client_sid))
|
||||||
trace2_data_string("transfer", NULL, "client-sid", client_sid);
|
trace2_data_string("transfer", NULL, "client-sid", client_sid);
|
||||||
|
|
||||||
command->command(the_repository, &keys, &reader);
|
command->command(the_repository, &reader);
|
||||||
|
|
||||||
strvec_clear(&keys);
|
strvec_clear(&keys);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Main serve loop for protocol version 2 */
|
void protocol_v2_serve_loop(int stateless_rpc)
|
||||||
void serve(struct serve_options *options)
|
|
||||||
{
|
{
|
||||||
git_config_get_bool("transfer.advertisesid", &advertise_sid);
|
if (!stateless_rpc)
|
||||||
|
protocol_v2_advertise_capabilities();
|
||||||
if (options->advertise_capabilities || !options->stateless_rpc) {
|
|
||||||
/* serve by default supports v2 */
|
|
||||||
packet_write_fmt(1, "version 2\n");
|
|
||||||
|
|
||||||
advertise_capabilities();
|
|
||||||
/*
|
|
||||||
* If only the list of capabilities was requested exit
|
|
||||||
* immediately after advertising capabilities
|
|
||||||
*/
|
|
||||||
if (options->advertise_capabilities)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If stateless-rpc was requested then exit after
|
* If stateless-rpc was requested then exit after
|
||||||
* a single request/response exchange
|
* a single request/response exchange
|
||||||
*/
|
*/
|
||||||
if (options->stateless_rpc) {
|
if (stateless_rpc) {
|
||||||
process_request();
|
process_request();
|
||||||
} else {
|
} else {
|
||||||
for (;;)
|
for (;;)
|
||||||
|
12
serve.h
12
serve.h
@ -1,15 +1,7 @@
|
|||||||
#ifndef SERVE_H
|
#ifndef SERVE_H
|
||||||
#define SERVE_H
|
#define SERVE_H
|
||||||
|
|
||||||
struct strvec;
|
void protocol_v2_advertise_capabilities(void);
|
||||||
int has_capability(const struct strvec *keys, const char *capability,
|
void protocol_v2_serve_loop(int stateless_rpc);
|
||||||
const char **value);
|
|
||||||
|
|
||||||
struct serve_options {
|
|
||||||
unsigned advertise_capabilities;
|
|
||||||
unsigned stateless_rpc;
|
|
||||||
};
|
|
||||||
#define SERVE_OPTIONS_INIT { 0 }
|
|
||||||
void serve(struct serve_options *options);
|
|
||||||
|
|
||||||
#endif /* SERVE_H */
|
#endif /* SERVE_H */
|
||||||
|
@ -10,12 +10,12 @@ static char const * const serve_usage[] = {
|
|||||||
|
|
||||||
int cmd__serve_v2(int argc, const char **argv)
|
int cmd__serve_v2(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
struct serve_options opts = SERVE_OPTIONS_INIT;
|
int stateless_rpc = 0;
|
||||||
|
int advertise_capabilities = 0;
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOL(0, "stateless-rpc", &opts.stateless_rpc,
|
OPT_BOOL(0, "stateless-rpc", &stateless_rpc,
|
||||||
N_("quit after a single request/response exchange")),
|
N_("quit after a single request/response exchange")),
|
||||||
OPT_BOOL(0, "advertise-capabilities", &opts.advertise_capabilities,
|
OPT_BOOL(0, "advertise-capabilities", &advertise_capabilities,
|
||||||
N_("exit immediately after advertising capabilities")),
|
N_("exit immediately after advertising capabilities")),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
@ -25,7 +25,11 @@ int cmd__serve_v2(int argc, const char **argv)
|
|||||||
argc = parse_options(argc, argv, prefix, options, serve_usage,
|
argc = parse_options(argc, argv, prefix, options, serve_usage,
|
||||||
PARSE_OPT_KEEP_DASHDASH |
|
PARSE_OPT_KEEP_DASHDASH |
|
||||||
PARSE_OPT_KEEP_UNKNOWN);
|
PARSE_OPT_KEEP_UNKNOWN);
|
||||||
serve(&opts);
|
|
||||||
|
if (advertise_capabilities)
|
||||||
|
protocol_v2_advertise_capabilities();
|
||||||
|
else
|
||||||
|
protocol_v2_serve_loop(stateless_rpc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
161
t/t5555-http-smart-common.sh
Executable file
161
t/t5555-http-smart-common.sh
Executable file
@ -0,0 +1,161 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='test functionality common to smart fetch & push'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
test_expect_success 'setup' '
|
||||||
|
test_commit --no-tag initial
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git upload-pack --http-backend-info-refs and --advertise-refs are aliased' '
|
||||||
|
git upload-pack --http-backend-info-refs . >expected 2>err.expected &&
|
||||||
|
git upload-pack --advertise-refs . >actual 2>err.actual &&
|
||||||
|
test_cmp err.expected err.actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git receive-pack --http-backend-info-refs and --advertise-refs are aliased' '
|
||||||
|
git receive-pack --http-backend-info-refs . >expected 2>err.expected &&
|
||||||
|
git receive-pack --advertise-refs . >actual 2>err.actual &&
|
||||||
|
test_cmp err.expected err.actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git upload-pack --advertise-refs' '
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
$(git rev-parse HEAD) HEAD
|
||||||
|
$(git rev-parse HEAD) $(git symbolic-ref HEAD)
|
||||||
|
0000
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# We only care about GIT_PROTOCOL, not GIT_TEST_PROTOCOL_VERSION
|
||||||
|
sane_unset GIT_PROTOCOL &&
|
||||||
|
GIT_TEST_PROTOCOL_VERSION=2 \
|
||||||
|
git upload-pack --advertise-refs . >out 2>err &&
|
||||||
|
|
||||||
|
test-tool pkt-line unpack <out >actual &&
|
||||||
|
test_must_be_empty err &&
|
||||||
|
test_cmp actual expect &&
|
||||||
|
|
||||||
|
# The --advertise-refs alias works
|
||||||
|
git upload-pack --advertise-refs . >out 2>err &&
|
||||||
|
|
||||||
|
test-tool pkt-line unpack <out >actual &&
|
||||||
|
test_must_be_empty err &&
|
||||||
|
test_cmp actual expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git upload-pack --advertise-refs: v0' '
|
||||||
|
# With no specified protocol
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
$(git rev-parse HEAD) HEAD
|
||||||
|
$(git rev-parse HEAD) $(git symbolic-ref HEAD)
|
||||||
|
0000
|
||||||
|
EOF
|
||||||
|
|
||||||
|
git upload-pack --advertise-refs . >out 2>err &&
|
||||||
|
test-tool pkt-line unpack <out >actual &&
|
||||||
|
test_must_be_empty err &&
|
||||||
|
test_cmp actual expect &&
|
||||||
|
|
||||||
|
# With explicit v0
|
||||||
|
GIT_PROTOCOL=version=0 \
|
||||||
|
git upload-pack --advertise-refs . >out 2>err &&
|
||||||
|
test-tool pkt-line unpack <out >actual 2>err &&
|
||||||
|
test_must_be_empty err &&
|
||||||
|
test_cmp actual expect
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git receive-pack --advertise-refs: v0' '
|
||||||
|
# With no specified protocol
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
$(git rev-parse HEAD) $(git symbolic-ref HEAD)
|
||||||
|
0000
|
||||||
|
EOF
|
||||||
|
|
||||||
|
git receive-pack --advertise-refs . >out 2>err &&
|
||||||
|
test-tool pkt-line unpack <out >actual &&
|
||||||
|
test_must_be_empty err &&
|
||||||
|
test_cmp actual expect &&
|
||||||
|
|
||||||
|
# With explicit v0
|
||||||
|
GIT_PROTOCOL=version=0 \
|
||||||
|
git receive-pack --advertise-refs . >out 2>err &&
|
||||||
|
test-tool pkt-line unpack <out >actual 2>err &&
|
||||||
|
test_must_be_empty err &&
|
||||||
|
test_cmp actual expect
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git upload-pack --advertise-refs: v1' '
|
||||||
|
# With no specified protocol
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
version 1
|
||||||
|
$(git rev-parse HEAD) HEAD
|
||||||
|
$(git rev-parse HEAD) $(git symbolic-ref HEAD)
|
||||||
|
0000
|
||||||
|
EOF
|
||||||
|
|
||||||
|
GIT_PROTOCOL=version=1 \
|
||||||
|
git upload-pack --advertise-refs . >out &&
|
||||||
|
|
||||||
|
test-tool pkt-line unpack <out >actual 2>err &&
|
||||||
|
test_must_be_empty err &&
|
||||||
|
test_cmp actual expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git receive-pack --advertise-refs: v1' '
|
||||||
|
# With no specified protocol
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
version 1
|
||||||
|
$(git rev-parse HEAD) $(git symbolic-ref HEAD)
|
||||||
|
0000
|
||||||
|
EOF
|
||||||
|
|
||||||
|
GIT_PROTOCOL=version=1 \
|
||||||
|
git receive-pack --advertise-refs . >out &&
|
||||||
|
|
||||||
|
test-tool pkt-line unpack <out >actual 2>err &&
|
||||||
|
test_must_be_empty err &&
|
||||||
|
test_cmp actual expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git upload-pack --advertise-refs: v2' '
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
version 2
|
||||||
|
agent=FAKE
|
||||||
|
ls-refs=unborn
|
||||||
|
fetch=shallow wait-for-done
|
||||||
|
server-option
|
||||||
|
object-format=$(test_oid algo)
|
||||||
|
object-info
|
||||||
|
0000
|
||||||
|
EOF
|
||||||
|
|
||||||
|
GIT_PROTOCOL=version=2 \
|
||||||
|
GIT_USER_AGENT=FAKE \
|
||||||
|
git upload-pack --advertise-refs . >out 2>err &&
|
||||||
|
|
||||||
|
test-tool pkt-line unpack <out >actual &&
|
||||||
|
test_must_be_empty err &&
|
||||||
|
test_cmp actual expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git receive-pack --advertise-refs: v2' '
|
||||||
|
# There is no v2 yet for receive-pack, implicit v0
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
$(git rev-parse HEAD) $(git symbolic-ref HEAD)
|
||||||
|
0000
|
||||||
|
EOF
|
||||||
|
|
||||||
|
GIT_PROTOCOL=version=2 \
|
||||||
|
git receive-pack --advertise-refs . >out 2>err &&
|
||||||
|
|
||||||
|
test-tool pkt-line unpack <out >actual &&
|
||||||
|
test_must_be_empty err &&
|
||||||
|
test_cmp actual expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
@ -671,8 +671,8 @@ static int connect_helper(struct transport *transport, const char *name,
|
|||||||
static struct ref *get_refs_list_using_list(struct transport *transport,
|
static struct ref *get_refs_list_using_list(struct transport *transport,
|
||||||
int for_push);
|
int for_push);
|
||||||
|
|
||||||
static int fetch(struct transport *transport,
|
static int fetch_refs(struct transport *transport,
|
||||||
int nr_heads, struct ref **to_fetch)
|
int nr_heads, struct ref **to_fetch)
|
||||||
{
|
{
|
||||||
struct helper_data *data = transport->data;
|
struct helper_data *data = transport->data;
|
||||||
int i, count;
|
int i, count;
|
||||||
@ -681,7 +681,7 @@ static int fetch(struct transport *transport,
|
|||||||
|
|
||||||
if (process_connect(transport, 0)) {
|
if (process_connect(transport, 0)) {
|
||||||
do_take_over(transport);
|
do_take_over(transport);
|
||||||
return transport->vtable->fetch(transport, nr_heads, to_fetch);
|
return transport->vtable->fetch_refs(transport, nr_heads, to_fetch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1261,12 +1261,12 @@ static struct ref *get_refs_list_using_list(struct transport *transport,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct transport_vtable vtable = {
|
static struct transport_vtable vtable = {
|
||||||
set_helper_option,
|
.set_option = set_helper_option,
|
||||||
get_refs_list,
|
.get_refs_list = get_refs_list,
|
||||||
fetch,
|
.fetch_refs = fetch_refs,
|
||||||
push_refs,
|
.push_refs = push_refs,
|
||||||
connect_helper,
|
.connect = connect_helper,
|
||||||
release_helper
|
.disconnect = release_helper
|
||||||
};
|
};
|
||||||
|
|
||||||
int transport_helper_init(struct transport *transport, const char *name)
|
int transport_helper_init(struct transport *transport, const char *name)
|
||||||
|
@ -34,7 +34,7 @@ struct transport_vtable {
|
|||||||
* get_refs_list(), it should set the old_sha1 fields in the
|
* get_refs_list(), it should set the old_sha1 fields in the
|
||||||
* provided refs now.
|
* provided refs now.
|
||||||
**/
|
**/
|
||||||
int (*fetch)(struct transport *transport, int refs_nr, struct ref **refs);
|
int (*fetch_refs)(struct transport *transport, int refs_nr, struct ref **refs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push the objects and refs. Send the necessary objects, and
|
* Push the objects and refs. Send the necessary objects, and
|
||||||
|
32
transport.c
32
transport.c
@ -883,12 +883,10 @@ static int disconnect_git(struct transport *transport)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct transport_vtable taken_over_vtable = {
|
static struct transport_vtable taken_over_vtable = {
|
||||||
NULL,
|
.get_refs_list = get_refs_via_connect,
|
||||||
get_refs_via_connect,
|
.fetch_refs = fetch_refs_via_pack,
|
||||||
fetch_refs_via_pack,
|
.push_refs = git_transport_push,
|
||||||
git_transport_push,
|
.disconnect = disconnect_git
|
||||||
NULL,
|
|
||||||
disconnect_git
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void transport_take_over(struct transport *transport,
|
void transport_take_over(struct transport *transport,
|
||||||
@ -1032,21 +1030,17 @@ void transport_check_allowed(const char *type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct transport_vtable bundle_vtable = {
|
static struct transport_vtable bundle_vtable = {
|
||||||
NULL,
|
.get_refs_list = get_refs_from_bundle,
|
||||||
get_refs_from_bundle,
|
.fetch_refs = fetch_refs_from_bundle,
|
||||||
fetch_refs_from_bundle,
|
.disconnect = close_bundle
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
close_bundle
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct transport_vtable builtin_smart_vtable = {
|
static struct transport_vtable builtin_smart_vtable = {
|
||||||
NULL,
|
.get_refs_list = get_refs_via_connect,
|
||||||
get_refs_via_connect,
|
.fetch_refs = fetch_refs_via_pack,
|
||||||
fetch_refs_via_pack,
|
.push_refs = git_transport_push,
|
||||||
git_transport_push,
|
.connect = connect_git,
|
||||||
connect_git,
|
.disconnect = disconnect_git
|
||||||
disconnect_git
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct transport *transport_get(struct remote *remote, const char *url)
|
struct transport *transport_get(struct remote *remote, const char *url)
|
||||||
@ -1453,7 +1447,7 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
|
|||||||
heads[nr_heads++] = rm;
|
heads[nr_heads++] = rm;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = transport->vtable->fetch(transport, nr_heads, heads);
|
rc = transport->vtable->fetch_refs(transport, nr_heads, heads);
|
||||||
|
|
||||||
free(heads);
|
free(heads);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -1214,7 +1214,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
|
|||||||
" allow-tip-sha1-in-want" : "",
|
" allow-tip-sha1-in-want" : "",
|
||||||
(data->allow_uor & ALLOW_REACHABLE_SHA1) ?
|
(data->allow_uor & ALLOW_REACHABLE_SHA1) ?
|
||||||
" allow-reachable-sha1-in-want" : "",
|
" allow-reachable-sha1-in-want" : "",
|
||||||
data->stateless_rpc ? " no-done" : "",
|
data->no_done ? " no-done" : "",
|
||||||
symref_info.buf,
|
symref_info.buf,
|
||||||
data->allow_filter ? " filter" : "",
|
data->allow_filter ? " filter" : "",
|
||||||
session_id.buf,
|
session_id.buf,
|
||||||
@ -1329,7 +1329,8 @@ static int upload_pack_config(const char *var, const char *value, void *cb_data)
|
|||||||
return parse_hide_refs_config(var, value, "uploadpack");
|
return parse_hide_refs_config(var, value, "uploadpack");
|
||||||
}
|
}
|
||||||
|
|
||||||
void upload_pack(struct upload_pack_options *options)
|
void upload_pack(const int advertise_refs, const int stateless_rpc,
|
||||||
|
const int timeout)
|
||||||
{
|
{
|
||||||
struct packet_reader reader;
|
struct packet_reader reader;
|
||||||
struct upload_pack_data data;
|
struct upload_pack_data data;
|
||||||
@ -1338,14 +1339,17 @@ void upload_pack(struct upload_pack_options *options)
|
|||||||
|
|
||||||
git_config(upload_pack_config, &data);
|
git_config(upload_pack_config, &data);
|
||||||
|
|
||||||
data.stateless_rpc = options->stateless_rpc;
|
data.stateless_rpc = stateless_rpc;
|
||||||
data.daemon_mode = options->daemon_mode;
|
data.timeout = timeout;
|
||||||
data.timeout = options->timeout;
|
if (data.timeout)
|
||||||
|
data.daemon_mode = 1;
|
||||||
|
|
||||||
head_ref_namespaced(find_symref, &data.symref);
|
head_ref_namespaced(find_symref, &data.symref);
|
||||||
|
|
||||||
if (options->advertise_refs || !data.stateless_rpc) {
|
if (advertise_refs || !data.stateless_rpc) {
|
||||||
reset_timeout(data.timeout);
|
reset_timeout(data.timeout);
|
||||||
|
if (advertise_refs)
|
||||||
|
data.no_done = 1;
|
||||||
head_ref_namespaced(send_ref, &data);
|
head_ref_namespaced(send_ref, &data);
|
||||||
for_each_namespaced_ref(send_ref, &data);
|
for_each_namespaced_ref(send_ref, &data);
|
||||||
advertise_shallow_grafts(1);
|
advertise_shallow_grafts(1);
|
||||||
@ -1355,7 +1359,7 @@ void upload_pack(struct upload_pack_options *options)
|
|||||||
for_each_namespaced_ref(check_ref, NULL);
|
for_each_namespaced_ref(check_ref, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options->advertise_refs) {
|
if (!advertise_refs) {
|
||||||
packet_reader_init(&reader, 0, NULL, 0,
|
packet_reader_init(&reader, 0, NULL, 0,
|
||||||
PACKET_READ_CHOMP_NEWLINE |
|
PACKET_READ_CHOMP_NEWLINE |
|
||||||
PACKET_READ_DIE_ON_ERR_PACKET);
|
PACKET_READ_DIE_ON_ERR_PACKET);
|
||||||
@ -1659,8 +1663,7 @@ enum fetch_state {
|
|||||||
FETCH_DONE,
|
FETCH_DONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
int upload_pack_v2(struct repository *r, struct strvec *keys,
|
int upload_pack_v2(struct repository *r, struct packet_reader *request)
|
||||||
struct packet_reader *request)
|
|
||||||
{
|
{
|
||||||
enum fetch_state state = FETCH_PROCESS_ARGS;
|
enum fetch_state state = FETCH_PROCESS_ARGS;
|
||||||
struct upload_pack_data data;
|
struct upload_pack_data data;
|
||||||
|
@ -1,20 +1,12 @@
|
|||||||
#ifndef UPLOAD_PACK_H
|
#ifndef UPLOAD_PACK_H
|
||||||
#define UPLOAD_PACK_H
|
#define UPLOAD_PACK_H
|
||||||
|
|
||||||
struct upload_pack_options {
|
void upload_pack(const int advertise_refs, const int stateless_rpc,
|
||||||
int stateless_rpc;
|
const int timeout);
|
||||||
int advertise_refs;
|
|
||||||
unsigned int timeout;
|
|
||||||
int daemon_mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
void upload_pack(struct upload_pack_options *options);
|
|
||||||
|
|
||||||
struct repository;
|
struct repository;
|
||||||
struct strvec;
|
|
||||||
struct packet_reader;
|
struct packet_reader;
|
||||||
int upload_pack_v2(struct repository *r, struct strvec *keys,
|
int upload_pack_v2(struct repository *r, struct packet_reader *request);
|
||||||
struct packet_reader *request);
|
|
||||||
|
|
||||||
struct strbuf;
|
struct strbuf;
|
||||||
int upload_pack_advertise(struct repository *r,
|
int upload_pack_advertise(struct repository *r,
|
||||||
|
Loading…
Reference in New Issue
Block a user