Skip to content

Commit

Permalink
transport-helper: introduce stateless-connect
Browse files Browse the repository at this point in the history
Introduce the transport-helper capability 'stateless-connect'.  This
capability indicates that the transport-helper can be requested to run
the 'stateless-connect' command which should attempt to make a
stateless connection with a remote end.  Once established, the
connection can be used by the git client to communicate with
the remote end natively in a stateless-rpc manner as supported by
protocol v2.  This means that the client must send everything the server
needs in a single request as the client must not assume any
state-storing on the part of the server or transport.

If a stateless connection cannot be established then the remote-helper
will respond in the same manner as the 'connect' command indicating that
the client should fallback to using the dumb remote-helper commands.

A future patch will implement the 'stateless-connect' capability in our
http remote-helper (remote-curl) so that protocol v2 can be used using
the http transport.

Signed-off-by: Brandon Williams <bmwill@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
bmwill authored and gitster committed Mar 15, 2018
1 parent 176e85c commit edc9caf
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 0 deletions.
32 changes: 32 additions & 0 deletions Documentation/gitremote-helpers.txt
Expand Up @@ -102,6 +102,14 @@ Capabilities for Pushing
+
Supported commands: 'connect'.

'stateless-connect'::
Experimental; for internal use only.
Can attempt to connect to a remote server for communication
using git's wire-protocol version 2. See the documentation
for the stateless-connect command for more information.
+
Supported commands: 'stateless-connect'.

'push'::
Can discover remote refs and push local commits and the
history leading up to them to new or existing remote refs.
Expand Down Expand Up @@ -136,6 +144,14 @@ Capabilities for Fetching
+
Supported commands: 'connect'.

'stateless-connect'::
Experimental; for internal use only.
Can attempt to connect to a remote server for communication
using git's wire-protocol version 2. See the documentation
for the stateless-connect command for more information.
+
Supported commands: 'stateless-connect'.

'fetch'::
Can discover remote refs and transfer objects reachable from
them to the local object store.
Expand Down Expand Up @@ -375,6 +391,22 @@ Supported if the helper has the "export" capability.
+
Supported if the helper has the "connect" capability.

'stateless-connect' <service>::
Experimental; for internal use only.
Connects to the given remote service for communication using
git's wire-protocol version 2. Valid replies to this command
are empty line (connection established), 'fallback' (no smart
transport support, fall back to dumb transports) and just
exiting with error message printed (can't connect, don't bother
trying to fall back). After line feed terminating the positive
(empty) response, the output of the service starts. Messages
(both request and response) must consist of zero or more
PKT-LINEs, terminating in a flush packet. The client must not
expect the server to store any state in between request-response
pairs. After the connection ends, the remote helper exits.
+
Supported if the helper has the "stateless-connect" capability.

If a fatal error occurs, the program writes the error message to
stderr and exits. The caller should expect that a suitable error
message has been printed if the child closes the connection without
Expand Down
11 changes: 11 additions & 0 deletions transport-helper.c
Expand Up @@ -12,6 +12,7 @@
#include "argv-array.h"
#include "refs.h"
#include "transport-internal.h"
#include "protocol.h"

static int debug;

Expand All @@ -26,6 +27,7 @@ struct helper_data {
option : 1,
push : 1,
connect : 1,
stateless_connect : 1,
signed_tags : 1,
check_connectivity : 1,
no_disconnect_req : 1,
Expand Down Expand Up @@ -188,6 +190,8 @@ static struct child_process *get_helper(struct transport *transport)
refspecs[refspec_nr++] = xstrdup(arg);
} else if (!strcmp(capname, "connect")) {
data->connect = 1;
} else if (!strcmp(capname, "stateless-connect")) {
data->stateless_connect = 1;
} else if (!strcmp(capname, "signed-tags")) {
data->signed_tags = 1;
} else if (skip_prefix(capname, "export-marks ", &arg)) {
Expand Down Expand Up @@ -612,6 +616,13 @@ static int process_connect_service(struct transport *transport,
if (data->connect) {
strbuf_addf(&cmdbuf, "connect %s\n", name);
ret = run_connect(transport, &cmdbuf);
} else if (data->stateless_connect &&
(get_protocol_version_config() == protocol_v2) &&
!strcmp("git-upload-pack", name)) {
strbuf_addf(&cmdbuf, "stateless-connect %s\n", name);
ret = run_connect(transport, &cmdbuf);
if (ret)
transport->stateless_rpc = 1;
}

strbuf_release(&cmdbuf);
Expand Down
1 change: 1 addition & 0 deletions transport.c
Expand Up @@ -252,6 +252,7 @@ static int fetch_refs_via_pack(struct transport *transport,
data->options.check_self_contained_and_connected;
args.cloning = transport->cloning;
args.update_shallow = data->options.update_shallow;
args.stateless_rpc = transport->stateless_rpc;

if (!data->got_remote_heads)
refs_tmp = get_refs_via_connect(transport, 0, NULL);
Expand Down
6 changes: 6 additions & 0 deletions transport.h
Expand Up @@ -55,6 +55,12 @@ struct transport {
*/
unsigned cloning : 1;

/*
* Indicates that the transport is connected via a half-duplex
* connection and should operate in stateless-rpc mode.
*/
unsigned stateless_rpc : 1;

/*
* These strings will be passed to the {pre, post}-receive hook,
* on the remote side, if both sides support the push options capability.
Expand Down

0 comments on commit edc9caf

Please sign in to comment.