serve: add "receive" method for v2 capabilities table

We have a capabilities table that tells us what we should tell the
client we are capable of, and what to do when a client gives us a
particular command (e.g., "command=ls-refs"). But it doesn't tell us
what to do when the client sends us back a capability (e.g.,
"object-format=sha256"). We just collect them all in a strvec and hope
somebody can use them later.

Instead, let's provide a function pointer in the table to act on these.
This will eventually help us avoid collecting the strings, which will be
more efficient and less prone to mischief.

Using the new method is optional, which helps in two ways:

  - we can move existing capabilities over to this new system gradually
    in individual commits

  - some capabilities we don't actually do anything with anyway. For
    example, the client is free to say "agent=git/1.2.3" to us, but we
    do not act on the information in any way.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2021-09-14 11:31:07 -04:00 committed by Junio C Hamano
parent 5ef260d2d1
commit e56e53067f

21
serve.c
View File

@ -70,6 +70,16 @@ struct protocol_capability {
* This field should be NULL for capabilities which are not commands.
*/
int (*command)(struct repository *r, struct packet_reader *request);
/*
* Function called when a client requests the capability as a
* non-command. This may be NULL if the capability does nothing.
*
* For a capability of the form "foo=bar", the value string points to
* the content after the "=" (i.e., "bar"). For simple capabilities
* (just "foo"), it is NULL.
*/
void (*receive)(struct repository *r, const char *value);
};
static struct protocol_capability capabilities[] = {
@ -164,12 +174,17 @@ static struct protocol_capability *get_capability(const char *key, const char **
return NULL;
}
static int is_valid_capability(const char *key)
static int receive_client_capability(const char *key)
{
const char *value;
const struct protocol_capability *c = get_capability(key, &value);
return c && c->advertise(the_repository, NULL);
if (!c || !c->advertise(the_repository, NULL))
return 0;
if (c->receive)
c->receive(the_repository, value);
return 1;
}
static int parse_command(const char *key, struct protocol_capability **command)
@ -262,7 +277,7 @@ static int process_request(void)
case PACKET_READ_NORMAL:
/* collect request; a sequence of keys and values */
if (parse_command(reader.line, &command) ||
is_valid_capability(reader.line))
receive_client_capability(reader.line))
strvec_push(&keys, reader.line);
else
die("unknown capability '%s'", reader.line);