connect: add function to parse multiple v1 capability values

In a capability response, we can have multiple symref entries.  In the
future, we will also allow for multiple hash algorithms to be specified.
To avoid duplication, expand the parse_feature_value function to take an
optional offset where the parsing should begin next time.  Add a wrapper
function that allows us to query the next server feature value, and use
it in the existing symref parsing code.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
brian m. carlson 2020-05-25 19:58:52 +00:00 коммит произвёл Junio C Hamano
Родитель bf30dbf826
Коммит 2c6a403d96
1 изменённых файлов: 21 добавлений и 9 удалений

Просмотреть файл

@ -18,7 +18,8 @@
static char *server_capabilities_v1; static char *server_capabilities_v1;
static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT; static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT;
static const char *parse_feature_value(const char *, const char *, int *); static const char *parse_feature_value(const char *, const char *, int *, int *);
static const char *next_server_feature_value(const char *feature, int *len, int *offset);
static int check_ref(const char *name, unsigned int flags) static int check_ref(const char *name, unsigned int flags)
{ {
@ -180,17 +181,16 @@ reject:
static void annotate_refs_with_symref_info(struct ref *ref) static void annotate_refs_with_symref_info(struct ref *ref)
{ {
struct string_list symref = STRING_LIST_INIT_DUP; struct string_list symref = STRING_LIST_INIT_DUP;
const char *feature_list = server_capabilities_v1; int offset = 0;
while (feature_list) { while (1) {
int len; int len;
const char *val; const char *val;
val = parse_feature_value(feature_list, "symref", &len); val = next_server_feature_value("symref", &len, &offset);
if (!val) if (!val)
break; break;
parse_one_symref_info(&symref, val, len); parse_one_symref_info(&symref, val, len);
feature_list = val + 1;
} }
string_list_sort(&symref); string_list_sort(&symref);
@ -452,7 +452,7 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
return list; return list;
} }
static const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp) static const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset)
{ {
int len; int len;
@ -460,6 +460,8 @@ static const char *parse_feature_value(const char *feature_list, const char *fea
return NULL; return NULL;
len = strlen(feature); len = strlen(feature);
if (offset)
feature_list += *offset;
while (*feature_list) { while (*feature_list) {
const char *found = strstr(feature_list, feature); const char *found = strstr(feature_list, feature);
if (!found) if (!found)
@ -474,9 +476,14 @@ static const char *parse_feature_value(const char *feature_list, const char *fea
} }
/* feature with a value (e.g., "agent=git/1.2.3") */ /* feature with a value (e.g., "agent=git/1.2.3") */
else if (*value == '=') { else if (*value == '=') {
int end;
value++; value++;
end = strcspn(value, " \t\n");
if (lenp) if (lenp)
*lenp = strcspn(value, " \t\n"); *lenp = end;
if (offset)
*offset = value + end - feature_list;
return value; return value;
} }
/* /*
@ -491,12 +498,17 @@ static const char *parse_feature_value(const char *feature_list, const char *fea
int parse_feature_request(const char *feature_list, const char *feature) int parse_feature_request(const char *feature_list, const char *feature)
{ {
return !!parse_feature_value(feature_list, feature, NULL); return !!parse_feature_value(feature_list, feature, NULL, NULL);
}
static const char *next_server_feature_value(const char *feature, int *len, int *offset)
{
return parse_feature_value(server_capabilities_v1, feature, len, offset);
} }
const char *server_feature_value(const char *feature, int *len) const char *server_feature_value(const char *feature, int *len)
{ {
return parse_feature_value(server_capabilities_v1, feature, len); return parse_feature_value(server_capabilities_v1, feature, len, NULL);
} }
int server_supports(const char *feature) int server_supports(const char *feature)