@@ -46,6 +46,16 @@ OPTIONS
`$GIT_URL/info/refs?service=git-receive-pack` requests. See
`--http-backend-info-refs` in linkgit:git-upload-pack[1].
+--show-service::
+ Output the "# service=git-receive-pack" pktline and the
+ "0000" flush pktline firstly. Since the git client needs
+ the git server to send the first pktline
+ "# service=$servicename", this option allows the git
+ server to delegate the functionality of sending this pktline
+ to `git-receive-pack`.
+ Note that this option can only be used together with
+ `--http-backend-info-refs`.
+
PRE-RECEIVE HOOK
----------------
Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists
@@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git-upload-pack' [--[no-]strict] [--timeout=<n>] [--stateless-rpc]
- [--advertise-refs] <directory>
+ [--advertise-refs] [--show-service] <directory>
DESCRIPTION
-----------
@@ -44,6 +44,17 @@ OPTIONS
documentation. Also understood by
linkgit:git-receive-pack[1].
+--show-service::
+ Output the "# service=git-upload-pack" pktline and the
+ "0000" flush pktline firstly. Since the git client needs
+ the git server to send the first pktline
+ "# service=$servicename", this option allows the git
+ server to delegate the functionality of sending this pktline
+ to `git-upload-pack`.
+ Note that this option can only be used together with
+ `--http-backend-info-refs` and it is not applicable when
+ using protocol v2.
+
<directory>::
The repository to sync from.
@@ -2485,6 +2485,7 @@ static int delete_only(struct command *commands)
int cmd_receive_pack(int argc, const char **argv, const char *prefix)
{
int advertise_refs = 0;
+ int show_service = 0;
struct command *commands;
struct oid_array shallow = OID_ARRAY_INIT;
struct oid_array ref = OID_ARRAY_INIT;
@@ -2497,8 +2498,10 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
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_BOOL(0, "show-service", &show_service, N_("show service information")),
OPT_END()
};
+ enum protocol_version version = determine_protocol_version_server();
packet_trace_identity("receive-pack");
@@ -2525,7 +2528,16 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
else if (0 <= receive_unpack_limit)
unpack_limit = receive_unpack_limit;
- switch (determine_protocol_version_server()) {
+ if (show_service) {
+ if (!advertise_refs)
+ die(_("options '%s' and '%s' should be used together"), "--show-service", "--http-backend-info-refs");
+ if (version != protocol_v2) {
+ packet_write_fmt(1, "# service=git-receive-pack\n");
+ packet_flush(1);
+ }
+ }
+
+ switch (version) {
case protocol_v2:
/*
* push support for protocol v2 has not been implemented yet,
@@ -11,7 +11,7 @@
static const char * const upload_pack_usage[] = {
N_("git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n"
- " [--advertise-refs] <directory>"),
+ " [--advertise-refs] [--show-service] <directory>"),
NULL
};
@@ -22,6 +22,7 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)
int advertise_refs = 0;
int stateless_rpc = 0;
int timeout = 0;
+ int show_service = 0;
struct option options[] = {
OPT_BOOL(0, "stateless-rpc", &stateless_rpc,
N_("quit after a single request/response exchange")),
@@ -32,8 +33,10 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)
N_("do not try <directory>/.git/ if <directory> is no Git directory")),
OPT_INTEGER(0, "timeout", &timeout,
N_("interrupt transfer after <n> seconds of inactivity")),
+ OPT_BOOL(0, "show-service", &show_service, N_("show service information")),
OPT_END()
};
+ enum protocol_version version = determine_protocol_version_server();
packet_trace_identity("upload-pack");
read_replace_refs = 0;
@@ -50,7 +53,17 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)
if (!enter_repo(dir, strict))
die("'%s' does not appear to be a git repository", dir);
- switch (determine_protocol_version_server()) {
+
+ if (show_service) {
+ if (!advertise_refs)
+ die(_("options '%s' and '%s' should be used together"), "--show-service", "--http-backend-info-refs");
+ if (version != protocol_v2) {
+ packet_write_fmt(1, "# service=git-upload-pack\n");
+ packet_flush(1);
+ }
+ }
+
+ switch (version) {
case protocol_v2:
if (advertise_refs)
protocol_v2_advertise_capabilities();
@@ -539,6 +539,7 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
if (service_name) {
const char *argv[] = {NULL /* service name */,
"--http-backend-info-refs",
+ "--show-service",
".", NULL};
struct rpc_service *svc = select_service(hdr, service_name);
@@ -547,12 +548,6 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
hdr_str(hdr, content_type, buf.buf);
end_headers(hdr);
-
- if (determine_protocol_version_server() != protocol_v2) {
- packet_write_fmt(1, "# service=git-%s\n", svc->name);
- packet_flush(1);
- }
-
argv[0] = svc->name;
run_service(argv, 0);
@@ -159,4 +159,124 @@ test_expect_success 'git receive-pack --advertise-refs: v2' '
test_cmp actual expect
'
+test_expect_success 'git upload-pack --advertise-refs --show-service: v0' '
+ # With no specified protocol
+ cat >expect <<-EOF &&
+ # service=git-upload-pack
+ 0000
+ $(git rev-parse HEAD) HEAD
+ $(git rev-parse HEAD) $(git symbolic-ref HEAD)
+ 0000
+ EOF
+
+ git upload-pack --advertise-refs --show-service . >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 --show-service . >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 --show-service: v0' '
+ # With no specified protocol
+ cat >expect <<-EOF &&
+ # service=git-receive-pack
+ 0000
+ $(git rev-parse HEAD) $(git symbolic-ref HEAD)
+ 0000
+ EOF
+
+ git receive-pack --advertise-refs --show-service . >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 --show-service . >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 --show-service: v1' '
+ # With no specified protocol
+ cat >expect <<-EOF &&
+ # service=git-upload-pack
+ 0000
+ 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 --show-service . >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 --show-service: v1' '
+ # With no specified protocol
+ cat >expect <<-EOF &&
+ # service=git-receive-pack
+ 0000
+ version 1
+ $(git rev-parse HEAD) $(git symbolic-ref HEAD)
+ 0000
+ EOF
+
+ GIT_PROTOCOL=version=1 \
+ git receive-pack --advertise-refs --show-service . >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 --show-service: 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 --show-service . >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 --show-service: 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 --show-service . >out 2>err &&
+
+ test-tool pkt-line unpack <out >actual &&
+ test_must_be_empty err &&
+ test_cmp actual expect
+'
+
test_done