]> git.ipfire.org Git - thirdparty/git.git/blobdiff - serve.c
Fifth batch
[thirdparty/git.git] / serve.c
diff --git a/serve.c b/serve.c
index c046926ba141c76fc2a6b6fb1db80e31c1c28e8c..f6341206c4e30122c3cb819ef8c01f6d2be06d22 100644 (file)
--- a/serve.c
+++ b/serve.c
@@ -3,7 +3,7 @@
 #include "config.h"
 #include "pkt-line.h"
 #include "version.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "ls-refs.h"
 #include "serve.h"
 #include "upload-pack.h"
@@ -22,6 +22,14 @@ static int agent_advertise(struct repository *r,
        return 1;
 }
 
+static int object_format_advertise(struct repository *r,
+                                  struct strbuf *value)
+{
+       if (value)
+               strbuf_addstr(value, r->hash_algo->name);
+       return 1;
+}
+
 struct protocol_capability {
        /*
         * The name of the capability.  The server uses this name when
@@ -48,7 +56,7 @@ struct protocol_capability {
         * This field should be NULL for capabilities which are not commands.
         */
        int (*command)(struct repository *r,
-                      struct argv_array *keys,
+                      struct strvec *keys,
                       struct packet_reader *request);
 };
 
@@ -57,6 +65,7 @@ static struct protocol_capability capabilities[] = {
        { "ls-refs", always_advertise, ls_refs },
        { "fetch", upload_pack_advertise, upload_pack_v2 },
        { "server-option", always_advertise, NULL },
+       { "object-format", object_format_advertise, NULL },
 };
 
 static void advertise_capabilities(void)
@@ -133,13 +142,13 @@ static int is_command(const char *key, struct protocol_capability **command)
        return 0;
 }
 
-int has_capability(const struct argv_array *keys, const char *capability,
+int has_capability(const struct strvec *keys, const char *capability,
                   const char **value)
 {
        int i;
-       for (i = 0; i < keys->argc; i++) {
+       for (i = 0; i < keys->nr; i++) {
                const char *out;
-               if (skip_prefix(keys->argv[i], capability, &out) &&
+               if (skip_prefix(keys->v[i], capability, &out) &&
                    (!*out || *out == '=')) {
                        if (value) {
                                if (*out == '=')
@@ -153,6 +162,22 @@ int has_capability(const struct argv_array *keys, const char *capability,
        return 0;
 }
 
+static void check_algorithm(struct repository *r, struct strvec *keys)
+{
+       int client = GIT_HASH_SHA1, server = hash_algo_by_ptr(r->hash_algo);
+       const char *algo_name;
+
+       if (has_capability(keys, "object-format", &algo_name)) {
+               client = hash_algo_by_name(algo_name);
+               if (client == GIT_HASH_UNKNOWN)
+                       die("unknown object format '%s'", algo_name);
+       }
+
+       if (client != server)
+               die("mismatched object format: server %s; client %s\n",
+                   r->hash_algo->name, hash_algos[client].name);
+}
+
 enum request_state {
        PROCESS_REQUEST_KEYS,
        PROCESS_REQUEST_DONE,
@@ -162,7 +187,7 @@ static int process_request(void)
 {
        enum request_state state = PROCESS_REQUEST_KEYS;
        struct packet_reader reader;
-       struct argv_array keys = ARGV_ARRAY_INIT;
+       struct strvec keys = STRVEC_INIT;
        struct protocol_capability *command = NULL;
 
        packet_reader_init(&reader, 0, NULL, 0,
@@ -186,7 +211,7 @@ static int process_request(void)
                        /* collect request; a sequence of keys and values */
                        if (is_command(reader.line, &command) ||
                            is_valid_capability(reader.line))
-                               argv_array_push(&keys, reader.line);
+                               strvec_push(&keys, reader.line);
                        else
                                die("unknown capability '%s'", reader.line);
 
@@ -198,7 +223,7 @@ static int process_request(void)
                         * If no command and no keys were given then the client
                         * wanted to terminate the connection.
                         */
-                       if (!keys.argc)
+                       if (!keys.nr)
                                return 1;
 
                        /*
@@ -225,9 +250,11 @@ static int process_request(void)
        if (!command)
                die("no command requested");
 
+       check_algorithm(the_repository, &keys);
+
        command->command(the_repository, &keys, &reader);
 
-       argv_array_clear(&keys);
+       strvec_clear(&keys);
        return 0;
 }