]> git.ipfire.org Git - thirdparty/git.git/commitdiff
serve: provide "receive" function for object-format capability
authorJeff King <peff@peff.net>
Tue, 14 Sep 2021 23:51:27 +0000 (19:51 -0400)
committerJunio C Hamano <gitster@pobox.com>
Wed, 15 Sep 2021 00:12:05 +0000 (17:12 -0700)
We get any "object-format" specified by the client by searching for it
in the collected list of capabilities the client sent. We can instead
just handle it as soon as they send it. This is slightly more efficient,
and gets us one step closer to dropping that collected list.

Note that we do still have to do our final hash check after receiving
all capabilities (because they might not have sent an object-format line
at all, and we still have to check that the default matches our
repository algorithm). Since the check_algorithm() function would now be
down to a single if() statement, I've just inlined it in its only
caller.

There should be no change of behavior here, except for two
broken-protocol cases:

  - if the client sends multiple conflicting object-format capabilities
    (which they should not), we'll now choose the last one rather than
    the first. We could also detect and complain about the duplicates
    quite easily now, which we could not before, but I didn't do so
    here.

  - if the client sends a bogus "object-format" with no equals sign,
    we'll now say so, rather than "unknown object format: ''"

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
serve.c

diff --git a/serve.c b/serve.c
index a161189984b6ba17e3291a694f4082fc4f3255dc..f6ea2953eb12f5b68dfcdbee24c6080e97f0c802 100644 (file)
--- a/serve.c
+++ b/serve.c
@@ -10,6 +10,7 @@
 #include "upload-pack.h"
 
 static int advertise_sid = -1;
+static int client_hash_algo = GIT_HASH_SHA1;
 
 static int always_advertise(struct repository *r,
                            struct strbuf *value)
@@ -33,6 +34,17 @@ static int object_format_advertise(struct repository *r,
        return 1;
 }
 
+static void object_format_receive(struct repository *r,
+                                 const char *algo_name)
+{
+       if (!algo_name)
+               die("object-format capability requires an argument");
+
+       client_hash_algo = hash_algo_by_name(algo_name);
+       if (client_hash_algo == GIT_HASH_UNKNOWN)
+               die("unknown object format '%s'", algo_name);
+}
+
 static int session_id_advertise(struct repository *r, struct strbuf *value)
 {
        if (advertise_sid == -1 &&
@@ -104,6 +116,7 @@ static struct protocol_capability capabilities[] = {
        {
                .name = "object-format",
                .advertise = object_format_advertise,
+               .receive = object_format_receive,
        },
        {
                .name = "session-id",
@@ -228,22 +241,6 @@ static int has_capability(const struct strvec *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,
@@ -317,7 +314,10 @@ static int process_request(void)
        if (!command)
                die("no command requested");
 
-       check_algorithm(the_repository, &keys);
+       if (client_hash_algo != hash_algo_by_ptr(the_repository->hash_algo))
+               die("mismatched object format: server %s; client %s\n",
+                   the_repository->hash_algo->name,
+                   hash_algos[client_hash_algo].name);
 
        if (has_capability(&keys, "session-id", &client_sid))
                trace2_data_string("transfer", NULL, "client-sid", client_sid);