Instead of calling get_remote_heads as a first command during the protocol exchange, we need to have fine grained control over the capability negotiation in version 2 of the protocol. Introduce get_remote_capabilities, which will just listen to capabilities of the remote and request_capabilities which will tell the selection of capabilities to the remote. Signed-off-by: Stefan Beller <sbeller@xxxxxxxxxx> --- connect.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ remote.h | 3 +++ 2 files changed, 62 insertions(+) diff --git a/connect.c b/connect.c index 79505fb..1ba9a0f 100644 --- a/connect.c +++ b/connect.c @@ -10,6 +10,7 @@ #include "string-list.h" #include "sha1-array.h" #include "transport.h" +#include "version.h" struct string_list server_capabilities = STRING_LIST_INIT_DUP; static const char *parse_feature_value(struct string_list *, const char *, int *); @@ -106,6 +107,64 @@ static void annotate_refs_with_symref_info(struct ref *ref) string_list_clear(&symref, 0); } +const char *known_capabilities[] = { + "multi_ack", + "thin-pack", + "side-band", + "side-band-64k", + "ofs-delta", + "shallow", + "no-progress", + "include-tag", + "multi_ack_detailed", + "allow-tip-sha1-in-want", + "allow-reachable-sha1-in-want", + "no-done", +}; + +static int keep_capability(char *line) +{ + int i; + for (i = 0; i < ARRAY_SIZE(known_capabilities); i++) + if (starts_with(line, known_capabilities[i])) + return 1; + return 0; +} + +void get_remote_capabilities(int in, char *src_buf, size_t src_len) +{ + for (;;) { + int len; + char *line = packet_buffer; + + len = packet_read(in, &src_buf, &src_len, + packet_buffer, sizeof(packet_buffer), + PACKET_READ_GENTLE_ON_EOF | + PACKET_READ_CHOMP_NEWLINE); + if (len < 0) + die_initial_contact(0); + + if (!len) + break; + + /* + * We need to ignore and drop unknown capabilities as they + * may be huge. + */ + if (keep_capability(line)) + string_list_append(&server_capabilities, line); + } +} + + +void request_capabilities(int out, struct string_list *list) +{ + struct string_list_item *item; + for_each_string_list_item(item, list) + packet_write(out, "%s\n", item->string); + packet_flush(out); +} + /* * Read all the refs from the other end */ diff --git a/remote.h b/remote.h index cdb25d0..534282b 100644 --- a/remote.h +++ b/remote.h @@ -153,6 +153,9 @@ extern struct ref **get_remote_heads(int in, char *src_buf, size_t src_len, struct sha1_array *extra_have, struct sha1_array *shallow); +extern void get_remote_capabilities(int in, char *src_buf, size_t src_len); +extern void request_capabilities(int out, struct string_list*); + int resolve_remote_symref(struct ref *ref, struct ref *list); int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid); -- 2.8.0.32.g71f8beb.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html