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 <sbel...@google.com>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to