summaryrefslogtreecommitdiff
path: root/transport-helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'transport-helper.c')
-rw-r--r--transport-helper.c135
1 files changed, 84 insertions, 51 deletions
diff --git a/transport-helper.c b/transport-helper.c
index c948d5215c..11f1055b47 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -11,6 +11,8 @@
#include "sigchain.h"
#include "argv-array.h"
#include "refs.h"
+#include "transport-internal.h"
+#include "protocol.h"
static int debug;
@@ -25,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,
@@ -48,7 +51,7 @@ static void sendline(struct helper_data *helper, struct strbuf *buffer)
die_errno("Full write to remote helper failed");
}
-static int recvline_fh(FILE *helper, struct strbuf *buffer, const char *name)
+static int recvline_fh(FILE *helper, struct strbuf *buffer)
{
strbuf_reset(buffer);
if (debug)
@@ -66,7 +69,7 @@ static int recvline_fh(FILE *helper, struct strbuf *buffer, const char *name)
static int recvline(struct helper_data *helper, struct strbuf *buffer)
{
- return recvline_fh(helper->out, buffer, helper->name);
+ return recvline_fh(helper->out, buffer);
}
static void write_constant(int fd, const char *str)
@@ -187,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)) {
@@ -535,7 +540,7 @@ static int fetch_with_import(struct transport *transport,
else
private = xstrdup(name);
if (private) {
- if (read_ref(private, posn->old_oid.hash) < 0)
+ if (read_ref(private, &posn->old_oid) < 0)
die("Could not read ref %s", private);
free(private);
}
@@ -544,14 +549,13 @@ static int fetch_with_import(struct transport *transport,
return 0;
}
-static int process_connect_service(struct transport *transport,
- const char *name, const char *exec)
+static int run_connect(struct transport *transport, struct strbuf *cmdbuf)
{
struct helper_data *data = transport->data;
- struct strbuf cmdbuf = STRBUF_INIT;
- struct child_process *helper;
- int r, duped, ret = 0;
+ int ret = 0;
+ int duped;
FILE *input;
+ struct child_process *helper;
helper = get_helper(transport);
@@ -567,44 +571,61 @@ static int process_connect_service(struct transport *transport,
input = xfdopen(duped, "r");
setvbuf(input, NULL, _IONBF, 0);
+ sendline(data, cmdbuf);
+ if (recvline_fh(input, cmdbuf))
+ exit(128);
+
+ if (!strcmp(cmdbuf->buf, "")) {
+ data->no_disconnect_req = 1;
+ if (debug)
+ fprintf(stderr, "Debug: Smart transport connection "
+ "ready.\n");
+ ret = 1;
+ } else if (!strcmp(cmdbuf->buf, "fallback")) {
+ if (debug)
+ fprintf(stderr, "Debug: Falling back to dumb "
+ "transport.\n");
+ } else {
+ die("Unknown response to connect: %s",
+ cmdbuf->buf);
+ }
+
+ fclose(input);
+ return ret;
+}
+
+static int process_connect_service(struct transport *transport,
+ const char *name, const char *exec)
+{
+ struct helper_data *data = transport->data;
+ struct strbuf cmdbuf = STRBUF_INIT;
+ int ret = 0;
+
/*
* Handle --upload-pack and friends. This is fire and forget...
* just warn if it fails.
*/
if (strcmp(name, exec)) {
- r = set_helper_option(transport, "servpath", exec);
+ int r = set_helper_option(transport, "servpath", exec);
if (r > 0)
warning("Setting remote service path not supported by protocol.");
else if (r < 0)
warning("Invalid remote service path.");
}
- if (data->connect)
+ if (data->connect) {
strbuf_addf(&cmdbuf, "connect %s\n", name);
- else
- goto exit;
-
- sendline(data, &cmdbuf);
- if (recvline_fh(input, &cmdbuf, name))
- exit(128);
-
- if (!strcmp(cmdbuf.buf, "")) {
- data->no_disconnect_req = 1;
- if (debug)
- fprintf(stderr, "Debug: Smart transport connection "
- "ready.\n");
- ret = 1;
- } else if (!strcmp(cmdbuf.buf, "fallback")) {
- if (debug)
- fprintf(stderr, "Debug: Falling back to dumb "
- "transport.\n");
- } else
- die("Unknown response to connect: %s",
- cmdbuf.buf);
+ 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;
+ }
-exit:
strbuf_release(&cmdbuf);
- fclose(input);
return ret;
}
@@ -650,7 +671,7 @@ static int fetch(struct transport *transport,
if (process_connect(transport, 0)) {
do_take_over(transport);
- return transport->fetch(transport, nr_heads, to_fetch);
+ return transport->vtable->fetch(transport, nr_heads, to_fetch);
}
count = 0;
@@ -671,6 +692,11 @@ static int fetch(struct transport *transport,
if (data->transport_options.update_shallow)
set_helper_option(transport, "update-shallow", "true");
+ if (data->transport_options.filter_options.choice)
+ set_helper_option(
+ transport, "filter",
+ data->transport_options.filter_options.filter_spec);
+
if (data->fetch)
return fetch_with_fetch(transport, nr_heads, to_fetch);
@@ -795,7 +821,8 @@ static int push_update_refs_status(struct helper_data *data,
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
if (!private)
continue;
- update_ref("update by helper", private, ref->new_oid.hash, NULL, 0, 0);
+ update_ref("update by helper", private, &ref->new_oid, NULL,
+ 0, 0);
free(private);
}
strbuf_release(&buf);
@@ -881,7 +908,8 @@ static int push_refs_with_push(struct transport *transport,
struct strbuf cas = STRBUF_INIT;
strbuf_addf(&cas, "%s:%s",
ref->name, oid_to_hex(&ref->old_oid_expect));
- string_list_append(&cas_options, strbuf_detach(&cas, NULL));
+ string_list_append_nodup(&cas_options,
+ strbuf_detach(&cas, NULL));
}
}
if (buf.len == 0) {
@@ -896,6 +924,7 @@ static int push_refs_with_push(struct transport *transport,
strbuf_addch(&buf, '\n');
sendline(data, &buf);
strbuf_release(&buf);
+ string_list_clear(&cas_options, 0);
return push_update_refs_status(data, remote_refs, flags);
}
@@ -929,7 +958,8 @@ static int push_refs_with_export(struct transport *transport,
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
if (private && !get_oid(private, &oid)) {
strbuf_addf(&buf, "^%s", private);
- string_list_append(&revlist_args, strbuf_detach(&buf, NULL));
+ string_list_append_nodup(&revlist_args,
+ strbuf_detach(&buf, NULL));
oidcpy(&ref->old_oid, &oid);
}
free(private);
@@ -941,10 +971,9 @@ static int push_refs_with_export(struct transport *transport,
int flag;
/* Follow symbolic refs (mainly for HEAD). */
- name = resolve_ref_unsafe(
- ref->peer_ref->name,
- RESOLVE_REF_READING,
- oid.hash, &flag);
+ name = resolve_ref_unsafe(ref->peer_ref->name,
+ RESOLVE_REF_READING,
+ &oid, &flag);
if (!name || !(flag & REF_ISSYMREF))
name = ref->peer_ref->name;
@@ -987,7 +1016,7 @@ static int push_refs(struct transport *transport,
if (process_connect(transport, 1)) {
do_take_over(transport);
- return transport->push_refs(transport, remote_refs, flags);
+ return transport->vtable->push_refs(transport, remote_refs, flags);
}
if (!remote_refs) {
@@ -1022,7 +1051,8 @@ static int has_attribute(const char *attrs, const char *attr) {
}
}
-static struct ref *get_refs_list(struct transport *transport, int for_push)
+static struct ref *get_refs_list(struct transport *transport, int for_push,
+ const struct argv_array *ref_prefixes)
{
struct helper_data *data = transport->data;
struct child_process *helper;
@@ -1035,7 +1065,7 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
if (process_connect(transport, for_push)) {
do_take_over(transport);
- return transport->get_refs_list(transport, for_push);
+ return transport->vtable->get_refs_list(transport, for_push, ref_prefixes);
}
if (data->push && for_push)
@@ -1066,8 +1096,7 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
if (eon) {
if (has_attribute(eon + 1, "unchanged")) {
(*tail)->status |= REF_STATUS_UPTODATE;
- if (read_ref((*tail)->name,
- (*tail)->old_oid.hash) < 0)
+ if (read_ref((*tail)->name, &(*tail)->old_oid) < 0)
die(_("Could not read ref %s"),
(*tail)->name);
}
@@ -1084,6 +1113,15 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
return ret;
}
+static struct transport_vtable vtable = {
+ set_helper_option,
+ get_refs_list,
+ fetch,
+ push_refs,
+ connect_helper,
+ release_helper
+};
+
int transport_helper_init(struct transport *transport, const char *name)
{
struct helper_data *data = xcalloc(1, sizeof(*data));
@@ -1095,12 +1133,7 @@ int transport_helper_init(struct transport *transport, const char *name)
debug = 1;
transport->data = data;
- transport->set_option = set_helper_option;
- transport->get_refs_list = get_refs_list;
- transport->fetch = fetch;
- transport->push_refs = push_refs;
- transport->disconnect = release_helper;
- transport->connect = connect_helper;
+ transport->vtable = &vtable;
transport->smart_options = &(data->transport_options);
return 0;
}