Merge branch 'bw/protocol-v2'
The beginning of the next-gen transfer protocol. * bw/protocol-v2: (35 commits) remote-curl: don't request v2 when pushing remote-curl: implement stateless-connect command http: eliminate "# service" line when using protocol v2 http: don't always add Git-Protocol header http: allow providing extra headers for http requests remote-curl: store the protocol version the server responded with remote-curl: create copy of the service name pkt-line: add packet_buf_write_len function transport-helper: introduce stateless-connect transport-helper: refactor process_connect_service transport-helper: remove name parameter connect: don't request v2 when pushing connect: refactor git_connect to only get the protocol version once fetch-pack: support shallow requests fetch-pack: perform a fetch using v2 upload-pack: introduce fetch server command push: pass ref prefixes when pushing fetch: pass ref prefixes when fetching ls-remote: pass ref prefixes when requesting a remote's refs transport: convert transport_get_remote_refs to take a list of ref prefixes ...
This commit is contained in:
130
transport.c
130
transport.c
@ -18,6 +18,7 @@
|
||||
#include "sha1-array.h"
|
||||
#include "sigchain.h"
|
||||
#include "transport-internal.h"
|
||||
#include "protocol.h"
|
||||
#include "object-store.h"
|
||||
|
||||
static void set_upstreams(struct transport *transport, struct ref *refs,
|
||||
@ -72,7 +73,9 @@ struct bundle_transport_data {
|
||||
struct bundle_header header;
|
||||
};
|
||||
|
||||
static struct ref *get_refs_from_bundle(struct transport *transport, int for_push)
|
||||
static struct ref *get_refs_from_bundle(struct transport *transport,
|
||||
int for_push,
|
||||
const struct argv_array *ref_prefixes)
|
||||
{
|
||||
struct bundle_transport_data *data = transport->data;
|
||||
struct ref *result = NULL;
|
||||
@ -118,6 +121,7 @@ struct git_transport_data {
|
||||
struct child_process *conn;
|
||||
int fd[2];
|
||||
unsigned got_remote_heads : 1;
|
||||
enum protocol_version version;
|
||||
struct oid_array extra_have;
|
||||
struct oid_array shallow;
|
||||
};
|
||||
@ -197,16 +201,35 @@ static int connect_setup(struct transport *transport, int for_push)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ref *get_refs_via_connect(struct transport *transport, int for_push)
|
||||
static struct ref *get_refs_via_connect(struct transport *transport, int for_push,
|
||||
const struct argv_array *ref_prefixes)
|
||||
{
|
||||
struct git_transport_data *data = transport->data;
|
||||
struct ref *refs;
|
||||
struct ref *refs = NULL;
|
||||
struct packet_reader reader;
|
||||
|
||||
connect_setup(transport, for_push);
|
||||
get_remote_heads(data->fd[0], NULL, 0, &refs,
|
||||
for_push ? REF_NORMAL : 0,
|
||||
&data->extra_have,
|
||||
&data->shallow);
|
||||
|
||||
packet_reader_init(&reader, data->fd[0], NULL, 0,
|
||||
PACKET_READ_CHOMP_NEWLINE |
|
||||
PACKET_READ_GENTLE_ON_EOF);
|
||||
|
||||
data->version = discover_version(&reader);
|
||||
switch (data->version) {
|
||||
case protocol_v2:
|
||||
get_remote_refs(data->fd[1], &reader, &refs, for_push,
|
||||
ref_prefixes);
|
||||
break;
|
||||
case protocol_v1:
|
||||
case protocol_v0:
|
||||
get_remote_heads(&reader, &refs,
|
||||
for_push ? REF_NORMAL : 0,
|
||||
&data->extra_have,
|
||||
&data->shallow);
|
||||
break;
|
||||
case protocol_unknown_version:
|
||||
BUG("unknown protocol version");
|
||||
}
|
||||
data->got_remote_heads = 1;
|
||||
|
||||
return refs;
|
||||
@ -217,7 +240,7 @@ static int fetch_refs_via_pack(struct transport *transport,
|
||||
{
|
||||
int ret = 0;
|
||||
struct git_transport_data *data = transport->data;
|
||||
struct ref *refs;
|
||||
struct ref *refs = NULL;
|
||||
char *dest = xstrdup(transport->url);
|
||||
struct fetch_pack_args args;
|
||||
struct ref *refs_tmp = NULL;
|
||||
@ -242,18 +265,29 @@ static int fetch_refs_via_pack(struct transport *transport,
|
||||
args.from_promisor = data->options.from_promisor;
|
||||
args.no_dependents = data->options.no_dependents;
|
||||
args.filter_options = data->options.filter_options;
|
||||
args.stateless_rpc = transport->stateless_rpc;
|
||||
|
||||
if (!data->got_remote_heads) {
|
||||
connect_setup(transport, 0);
|
||||
get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0,
|
||||
NULL, &data->shallow);
|
||||
data->got_remote_heads = 1;
|
||||
if (!data->got_remote_heads)
|
||||
refs_tmp = get_refs_via_connect(transport, 0, NULL);
|
||||
|
||||
switch (data->version) {
|
||||
case protocol_v2:
|
||||
refs = fetch_pack(&args, data->fd, data->conn,
|
||||
refs_tmp ? refs_tmp : transport->remote_refs,
|
||||
dest, to_fetch, nr_heads, &data->shallow,
|
||||
&transport->pack_lockfile, data->version);
|
||||
break;
|
||||
case protocol_v1:
|
||||
case protocol_v0:
|
||||
refs = fetch_pack(&args, data->fd, data->conn,
|
||||
refs_tmp ? refs_tmp : transport->remote_refs,
|
||||
dest, to_fetch, nr_heads, &data->shallow,
|
||||
&transport->pack_lockfile, data->version);
|
||||
break;
|
||||
case protocol_unknown_version:
|
||||
BUG("unknown protocol version");
|
||||
}
|
||||
|
||||
refs = fetch_pack(&args, data->fd, data->conn,
|
||||
refs_tmp ? refs_tmp : transport->remote_refs,
|
||||
dest, to_fetch, nr_heads, &data->shallow,
|
||||
&transport->pack_lockfile);
|
||||
close(data->fd[0]);
|
||||
close(data->fd[1]);
|
||||
if (finish_connect(data->conn))
|
||||
@ -552,16 +586,10 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
|
||||
{
|
||||
struct git_transport_data *data = transport->data;
|
||||
struct send_pack_args args;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (!data->got_remote_heads) {
|
||||
struct ref *tmp_refs;
|
||||
connect_setup(transport, 1);
|
||||
|
||||
get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL,
|
||||
NULL, &data->shallow);
|
||||
data->got_remote_heads = 1;
|
||||
}
|
||||
if (!data->got_remote_heads)
|
||||
get_refs_via_connect(transport, 1, NULL);
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
|
||||
@ -583,8 +611,18 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
|
||||
else
|
||||
args.push_cert = SEND_PACK_PUSH_CERT_NEVER;
|
||||
|
||||
ret = send_pack(&args, data->fd, data->conn, remote_refs,
|
||||
&data->extra_have);
|
||||
switch (data->version) {
|
||||
case protocol_v2:
|
||||
die("support for protocol v2 not implemented yet");
|
||||
break;
|
||||
case protocol_v1:
|
||||
case protocol_v0:
|
||||
ret = send_pack(&args, data->fd, data->conn, remote_refs,
|
||||
&data->extra_have);
|
||||
break;
|
||||
case protocol_unknown_version:
|
||||
BUG("unknown protocol version");
|
||||
}
|
||||
|
||||
close(data->fd[1]);
|
||||
close(data->fd[0]);
|
||||
@ -1007,11 +1045,38 @@ int transport_push(struct transport *transport,
|
||||
int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
|
||||
int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
|
||||
int push_ret, ret, err;
|
||||
struct refspec *tmp_rs;
|
||||
struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
|
||||
int i;
|
||||
|
||||
if (check_push_refs(local_refs, refspec_nr, refspec) < 0)
|
||||
return -1;
|
||||
|
||||
remote_refs = transport->vtable->get_refs_list(transport, 1);
|
||||
tmp_rs = parse_push_refspec(refspec_nr, refspec);
|
||||
for (i = 0; i < refspec_nr; i++) {
|
||||
const char *prefix = NULL;
|
||||
|
||||
if (tmp_rs[i].dst)
|
||||
prefix = tmp_rs[i].dst;
|
||||
else if (tmp_rs[i].src && !tmp_rs[i].exact_sha1)
|
||||
prefix = tmp_rs[i].src;
|
||||
|
||||
if (prefix) {
|
||||
const char *glob = strchr(prefix, '*');
|
||||
if (glob)
|
||||
argv_array_pushf(&ref_prefixes, "%.*s",
|
||||
(int)(glob - prefix),
|
||||
prefix);
|
||||
else
|
||||
expand_ref_prefix(&ref_prefixes, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
remote_refs = transport->vtable->get_refs_list(transport, 1,
|
||||
&ref_prefixes);
|
||||
|
||||
argv_array_clear(&ref_prefixes);
|
||||
free_refspec(refspec_nr, tmp_rs);
|
||||
|
||||
if (flags & TRANSPORT_PUSH_ALL)
|
||||
match_flags |= MATCH_REFS_ALL;
|
||||
@ -1117,10 +1182,13 @@ int transport_push(struct transport *transport,
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct ref *transport_get_remote_refs(struct transport *transport)
|
||||
const struct ref *transport_get_remote_refs(struct transport *transport,
|
||||
const struct argv_array *ref_prefixes)
|
||||
{
|
||||
if (!transport->got_remote_refs) {
|
||||
transport->remote_refs = transport->vtable->get_refs_list(transport, 0);
|
||||
transport->remote_refs =
|
||||
transport->vtable->get_refs_list(transport, 0,
|
||||
ref_prefixes);
|
||||
transport->got_remote_refs = 1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user