clone: request the 'bundle-uri' command when available
Set up all the needed client parts of the 'bundle-uri' protocol v2 command, without actually doing anything with the bundle URIs. If the server says it supports 'bundle-uri' teach Git to issue the 'bundle-uri' command after the 'ls-refs' during 'git clone'. The returned key=value pairs are passed to the bundle list code which is tested using a different ingest mechanism in t5750-bundle-uri-parse.sh. At this point, Git does nothing with that bundle list. It will not download any of the bundles. That will come in a later change after these protocol bits are finalized. The no-op client is initially used only by 'git clone' to test the basic functionality, and eventually will bootstrap the initial download of Git objects during a fresh clone. The bundle URI client will not be integrated into other fetches until a mechanism is created to select a subset of bundles for download. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
8f788eb8b7
commit
0cfde740f0
@ -1271,6 +1271,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||||||
if (refs)
|
if (refs)
|
||||||
mapped_refs = wanted_peer_refs(refs, &remote->fetch);
|
mapped_refs = wanted_peer_refs(refs, &remote->fetch);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Populate transport->got_remote_bundle_uri and
|
||||||
|
* transport->bundle_uri. We might get nothing.
|
||||||
|
*/
|
||||||
|
transport_get_remote_bundle_uri(transport);
|
||||||
|
|
||||||
if (mapped_refs) {
|
if (mapped_refs) {
|
||||||
int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
|
int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
|
||||||
|
|
||||||
|
44
connect.c
44
connect.c
@ -15,6 +15,7 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "alias.h"
|
#include "alias.h"
|
||||||
|
#include "bundle-uri.h"
|
||||||
|
|
||||||
static char *server_capabilities_v1;
|
static char *server_capabilities_v1;
|
||||||
static struct strvec server_capabilities_v2 = STRVEC_INIT;
|
static struct strvec server_capabilities_v2 = STRVEC_INIT;
|
||||||
@ -491,6 +492,49 @@ static void send_capabilities(int fd_out, struct packet_reader *reader)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_remote_bundle_uri(int fd_out, struct packet_reader *reader,
|
||||||
|
struct bundle_list *bundles, int stateless_rpc)
|
||||||
|
{
|
||||||
|
int line_nr = 1;
|
||||||
|
|
||||||
|
/* Assert bundle-uri support */
|
||||||
|
server_supports_v2("bundle-uri", 1);
|
||||||
|
|
||||||
|
/* (Re-)send capabilities */
|
||||||
|
send_capabilities(fd_out, reader);
|
||||||
|
|
||||||
|
/* Send command */
|
||||||
|
packet_write_fmt(fd_out, "command=bundle-uri\n");
|
||||||
|
packet_delim(fd_out);
|
||||||
|
|
||||||
|
packet_flush(fd_out);
|
||||||
|
|
||||||
|
/* Process response from server */
|
||||||
|
while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
|
||||||
|
const char *line = reader->line;
|
||||||
|
line_nr++;
|
||||||
|
|
||||||
|
if (!bundle_uri_parse_line(bundles, line))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return error(_("error on bundle-uri response line %d: %s"),
|
||||||
|
line_nr, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader->status != PACKET_READ_FLUSH)
|
||||||
|
return error(_("expected flush after bundle-uri listing"));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Might die(), but obscure enough that that's OK, e.g. in
|
||||||
|
* serve.c we'll call BUG() on its equivalent (the
|
||||||
|
* PACKET_READ_RESPONSE_END check).
|
||||||
|
*/
|
||||||
|
check_stateless_delimiter(stateless_rpc, reader,
|
||||||
|
_("expected response end packet after ref listing"));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
|
struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
|
||||||
struct ref **list, int for_push,
|
struct ref **list, int for_push,
|
||||||
struct transport_ls_refs_options *transport_options,
|
struct transport_ls_refs_options *transport_options,
|
||||||
|
5
remote.h
5
remote.h
@ -234,6 +234,11 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
|
|||||||
const struct string_list *server_options,
|
const struct string_list *server_options,
|
||||||
int stateless_rpc);
|
int stateless_rpc);
|
||||||
|
|
||||||
|
/* Used for protocol v2 in order to retrieve refs from a remote */
|
||||||
|
struct bundle_list;
|
||||||
|
int get_remote_bundle_uri(int fd_out, struct packet_reader *reader,
|
||||||
|
struct bundle_list *bundles, int stateless_rpc);
|
||||||
|
|
||||||
int resolve_remote_symref(struct ref *ref, struct ref *list);
|
int resolve_remote_symref(struct ref *ref, struct ref *list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -83,3 +83,22 @@ test_expect_success "connect with $BUNDLE_URI_PROTOCOL:// using protocol v2: hav
|
|||||||
# Server advertised bundle-uri capability
|
# Server advertised bundle-uri capability
|
||||||
grep "< bundle-uri" log
|
grep "< bundle-uri" log
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success "clone with $BUNDLE_URI_PROTOCOL:// using protocol v2: request bundle-uris" '
|
||||||
|
test_when_finished "rm -rf log cloned" &&
|
||||||
|
|
||||||
|
GIT_TRACE_PACKET="$PWD/log" \
|
||||||
|
git \
|
||||||
|
-c protocol.version=2 \
|
||||||
|
clone "$BUNDLE_URI_REPO_URI" cloned \
|
||||||
|
>actual 2>err &&
|
||||||
|
|
||||||
|
# Server responded using protocol v2
|
||||||
|
grep "< version 2" log &&
|
||||||
|
|
||||||
|
# Server advertised bundle-uri capability
|
||||||
|
grep "< bundle-uri" log &&
|
||||||
|
|
||||||
|
# Client issued bundle-uri command
|
||||||
|
grep "> command=bundle-uri" log
|
||||||
|
'
|
||||||
|
@ -1267,9 +1267,22 @@ static struct ref *get_refs_list_using_list(struct transport *transport,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_bundle_uri(struct transport *transport)
|
||||||
|
{
|
||||||
|
get_helper(transport);
|
||||||
|
|
||||||
|
if (process_connect(transport, 0)) {
|
||||||
|
do_take_over(transport);
|
||||||
|
return transport->vtable->get_bundle_uri(transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static struct transport_vtable vtable = {
|
static struct transport_vtable vtable = {
|
||||||
.set_option = set_helper_option,
|
.set_option = set_helper_option,
|
||||||
.get_refs_list = get_refs_list,
|
.get_refs_list = get_refs_list,
|
||||||
|
.get_bundle_uri = get_bundle_uri,
|
||||||
.fetch_refs = fetch_refs,
|
.fetch_refs = fetch_refs,
|
||||||
.push_refs = push_refs,
|
.push_refs = push_refs,
|
||||||
.connect = connect_helper,
|
.connect = connect_helper,
|
||||||
|
@ -26,6 +26,13 @@ struct transport_vtable {
|
|||||||
struct ref *(*get_refs_list)(struct transport *transport, int for_push,
|
struct ref *(*get_refs_list)(struct transport *transport, int for_push,
|
||||||
struct transport_ls_refs_options *transport_options);
|
struct transport_ls_refs_options *transport_options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the remote side's bundle-uri under protocol v2,
|
||||||
|
* if the "bundle-uri" capability was advertised. Returns 0 if
|
||||||
|
* OK, negative values on error.
|
||||||
|
*/
|
||||||
|
int (*get_bundle_uri)(struct transport *transport);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the objects for the given refs. Note that this gets
|
* Fetch the objects for the given refs. Note that this gets
|
||||||
* an array, and should ignore the list structure.
|
* an array, and should ignore the list structure.
|
||||||
|
51
transport.c
51
transport.c
@ -22,6 +22,7 @@
|
|||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "object-store.h"
|
#include "object-store.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
#include "bundle-uri.h"
|
||||||
|
|
||||||
static int transport_use_color = -1;
|
static int transport_use_color = -1;
|
||||||
static char transport_colors[][COLOR_MAXLEN] = {
|
static char transport_colors[][COLOR_MAXLEN] = {
|
||||||
@ -359,6 +360,32 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
|
|||||||
return handshake(transport, for_push, options, 1);
|
return handshake(transport, for_push, options, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_bundle_uri(struct transport *transport)
|
||||||
|
{
|
||||||
|
struct git_transport_data *data = transport->data;
|
||||||
|
struct packet_reader reader;
|
||||||
|
int stateless_rpc = transport->stateless_rpc;
|
||||||
|
|
||||||
|
if (!transport->bundles) {
|
||||||
|
CALLOC_ARRAY(transport->bundles, 1);
|
||||||
|
init_bundle_list(transport->bundles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "Support" protocol v0 and v2 without bundle-uri support by
|
||||||
|
* silently degrading to a NOOP.
|
||||||
|
*/
|
||||||
|
if (!server_supports_v2("bundle-uri", 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
packet_reader_init(&reader, data->fd[0], NULL, 0,
|
||||||
|
PACKET_READ_CHOMP_NEWLINE |
|
||||||
|
PACKET_READ_GENTLE_ON_EOF);
|
||||||
|
|
||||||
|
return get_remote_bundle_uri(data->fd[1], &reader,
|
||||||
|
transport->bundles, stateless_rpc);
|
||||||
|
}
|
||||||
|
|
||||||
static int fetch_refs_via_pack(struct transport *transport,
|
static int fetch_refs_via_pack(struct transport *transport,
|
||||||
int nr_heads, struct ref **to_fetch)
|
int nr_heads, struct ref **to_fetch)
|
||||||
{
|
{
|
||||||
@ -902,6 +929,7 @@ static int disconnect_git(struct transport *transport)
|
|||||||
|
|
||||||
static struct transport_vtable taken_over_vtable = {
|
static struct transport_vtable taken_over_vtable = {
|
||||||
.get_refs_list = get_refs_via_connect,
|
.get_refs_list = get_refs_via_connect,
|
||||||
|
.get_bundle_uri = get_bundle_uri,
|
||||||
.fetch_refs = fetch_refs_via_pack,
|
.fetch_refs = fetch_refs_via_pack,
|
||||||
.push_refs = git_transport_push,
|
.push_refs = git_transport_push,
|
||||||
.disconnect = disconnect_git
|
.disconnect = disconnect_git
|
||||||
@ -1054,6 +1082,7 @@ static struct transport_vtable bundle_vtable = {
|
|||||||
|
|
||||||
static struct transport_vtable builtin_smart_vtable = {
|
static struct transport_vtable builtin_smart_vtable = {
|
||||||
.get_refs_list = get_refs_via_connect,
|
.get_refs_list = get_refs_via_connect,
|
||||||
|
.get_bundle_uri = get_bundle_uri,
|
||||||
.fetch_refs = fetch_refs_via_pack,
|
.fetch_refs = fetch_refs_via_pack,
|
||||||
.push_refs = git_transport_push,
|
.push_refs = git_transport_push,
|
||||||
.connect = connect_git,
|
.connect = connect_git,
|
||||||
@ -1068,6 +1097,9 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
|||||||
ret->progress = isatty(2);
|
ret->progress = isatty(2);
|
||||||
string_list_init_dup(&ret->pack_lockfiles);
|
string_list_init_dup(&ret->pack_lockfiles);
|
||||||
|
|
||||||
|
CALLOC_ARRAY(ret->bundles, 1);
|
||||||
|
init_bundle_list(ret->bundles);
|
||||||
|
|
||||||
if (!remote)
|
if (!remote)
|
||||||
BUG("No remote provided to transport_get()");
|
BUG("No remote provided to transport_get()");
|
||||||
|
|
||||||
@ -1482,6 +1514,23 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int transport_get_remote_bundle_uri(struct transport *transport)
|
||||||
|
{
|
||||||
|
const struct transport_vtable *vtable = transport->vtable;
|
||||||
|
|
||||||
|
/* Check config only once. */
|
||||||
|
if (transport->got_remote_bundle_uri)
|
||||||
|
return 0;
|
||||||
|
transport->got_remote_bundle_uri = 1;
|
||||||
|
|
||||||
|
if (!vtable->get_bundle_uri)
|
||||||
|
return error(_("bundle-uri operation not supported by protocol"));
|
||||||
|
|
||||||
|
if (vtable->get_bundle_uri(transport) < 0)
|
||||||
|
return error(_("could not retrieve server-advertised bundle-uri list"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void transport_unlock_pack(struct transport *transport, unsigned int flags)
|
void transport_unlock_pack(struct transport *transport, unsigned int flags)
|
||||||
{
|
{
|
||||||
int in_signal_handler = !!(flags & TRANSPORT_UNLOCK_PACK_IN_SIGNAL_HANDLER);
|
int in_signal_handler = !!(flags & TRANSPORT_UNLOCK_PACK_IN_SIGNAL_HANDLER);
|
||||||
@ -1512,6 +1561,8 @@ int transport_disconnect(struct transport *transport)
|
|||||||
ret = transport->vtable->disconnect(transport);
|
ret = transport->vtable->disconnect(transport);
|
||||||
if (transport->got_remote_refs)
|
if (transport->got_remote_refs)
|
||||||
free_refs((void *)transport->remote_refs);
|
free_refs((void *)transport->remote_refs);
|
||||||
|
clear_bundle_list(transport->bundles);
|
||||||
|
free(transport->bundles);
|
||||||
free(transport);
|
free(transport);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
19
transport.h
19
transport.h
@ -62,6 +62,7 @@ enum transport_family {
|
|||||||
TRANSPORT_FAMILY_IPV6
|
TRANSPORT_FAMILY_IPV6
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bundle_list;
|
||||||
struct transport {
|
struct transport {
|
||||||
const struct transport_vtable *vtable;
|
const struct transport_vtable *vtable;
|
||||||
|
|
||||||
@ -76,6 +77,18 @@ struct transport {
|
|||||||
*/
|
*/
|
||||||
unsigned got_remote_refs : 1;
|
unsigned got_remote_refs : 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether we already called get_bundle_uri_list(); set by
|
||||||
|
* transport.c::transport_get_remote_bundle_uri().
|
||||||
|
*/
|
||||||
|
unsigned got_remote_bundle_uri : 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The results of "command=bundle-uri", if both sides support
|
||||||
|
* the "bundle-uri" capability.
|
||||||
|
*/
|
||||||
|
struct bundle_list *bundles;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Transports that call take-over destroys the data specific to
|
* Transports that call take-over destroys the data specific to
|
||||||
* the transport type while doing so, and cannot be reused.
|
* the transport type while doing so, and cannot be reused.
|
||||||
@ -281,6 +294,12 @@ void transport_ls_refs_options_release(struct transport_ls_refs_options *opts);
|
|||||||
const struct ref *transport_get_remote_refs(struct transport *transport,
|
const struct ref *transport_get_remote_refs(struct transport *transport,
|
||||||
struct transport_ls_refs_options *transport_options);
|
struct transport_ls_refs_options *transport_options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve bundle URI(s) from a remote. Populates "struct
|
||||||
|
* transport"'s "bundle_uri" and "got_remote_bundle_uri".
|
||||||
|
*/
|
||||||
|
int transport_get_remote_bundle_uri(struct transport *transport);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch the hash algorithm used by a remote.
|
* Fetch the hash algorithm used by a remote.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user