Signed-off-by: Stefan Beller <sbeller@xxxxxxxxxx> --- builtin/receive-pack.c | 13 +++++---- connect.c | 79 ++++++++++++++++++++++---------------------------- connect.h | 2 +- upload-pack.c | 11 +++++-- 4 files changed, 51 insertions(+), 54 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index d2ec52b..518ce85 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1391,16 +1391,19 @@ static struct command *read_head_info(struct sha1_array *shallow) linelen = strlen(line); if (linelen < len) { - const char *feature_list = line + linelen + 1; - if (parse_feature_request(feature_list, "report-status")) + struct string_list feature_list = STRING_LIST_INIT_DUP; + from_space_separated_string(&feature_list, line + linelen + 1); + if (parse_feature_request(&feature_list, "report-status")) report_status = 1; - if (parse_feature_request(feature_list, "side-band-64k")) + if (parse_feature_request(&feature_list, "side-band-64k")) use_sideband = LARGE_PACKET_MAX; - if (parse_feature_request(feature_list, "quiet")) + if (parse_feature_request(&feature_list, "quiet")) quiet = 1; if (advertise_atomic_push - && parse_feature_request(feature_list, "atomic")) + && parse_feature_request(&feature_list, "atomic")) use_atomic = 1; + + string_list_clear(&feature_list, 1); } if (!strcmp(line, "push-cert")) { diff --git a/connect.c b/connect.c index c0144d8..4295ba1 100644 --- a/connect.c +++ b/connect.c @@ -10,8 +10,8 @@ #include "string-list.h" #include "sha1-array.h" -static char *server_capabilities; -static const char *parse_feature_value(const char *, const char *, int *); +struct string_list server_capabilities = STRING_LIST_INIT_DUP; +static const char *parse_feature_value(struct string_list *, const char *, int *); static int check_ref(const char *name, unsigned int flags) { @@ -80,18 +80,18 @@ reject: static void annotate_refs_with_symref_info(struct ref *ref) { + struct string_list_item *item; struct string_list symref = STRING_LIST_INIT_DUP; - const char *feature_list = server_capabilities; - while (feature_list) { - int len; + for_each_string_list_item(item, &server_capabilities) { const char *val; - val = parse_feature_value(feature_list, "symref", &len); - if (!val) - break; - parse_one_symref_info(&symref, val, len); - feature_list = val + 1; + if (skip_prefix(item->string, "symref", &val)) { + if (!val) + continue; + val++; /* skip the = */ + parse_one_symref_info(&symref, val, strlen(val)); + } } string_list_sort(&symref); @@ -153,8 +153,8 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t src_len, name_len = strlen(name); if (len != name_len + 41) { - free(server_capabilities); - server_capabilities = xstrdup(name + name_len + 1); + string_list_clear(&server_capabilities, 1); + from_space_separated_string(&server_capabilities, name + name_len + 1); } if (extra_have && !strcmp(name, ".have")) { @@ -176,51 +176,40 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t src_len, return list; } -static const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp) +static const char *parse_feature_value(struct string_list *feature_list, const char *feature, int *lenp) { - int len; - - if (!feature_list) - return NULL; - - len = strlen(feature); - while (*feature_list) { - const char *found = strstr(feature_list, feature); - if (!found) - return NULL; - if (feature_list == found || isspace(found[-1])) { - const char *value = found + len; - /* feature with no value (e.g., "thin-pack") */ - if (!*value || isspace(*value)) { - if (lenp) - *lenp = 0; - return value; - } - /* feature with a value (e.g., "agent=git/1.2.3") */ - else if (*value == '=') { - value++; - if (lenp) - *lenp = strcspn(value, " \t\n"); - return value; - } - /* - * otherwise we matched a substring of another feature; - * keep looking - */ + const char *value; + struct string_list_item *item; + + for_each_string_list_item(item, feature_list) { + if (!skip_prefix(item->string, feature, &value)) + continue; + + /* feature with no value (e.g., "thin-pack") */ + if (!*value) { + if (lenp) + *lenp = 0; + return value; + } + /* feature with a value (e.g., "agent=git/1.2.3") */ + else if (*value == '=') { + value++; + if (lenp) + *lenp = strlen(value); + return value; } - feature_list = found + 1; } return NULL; } -int parse_feature_request(const char *feature_list, const char *feature) +int parse_feature_request(struct string_list *feature_list, const char *feature) { return !!parse_feature_value(feature_list, feature, NULL); } const char *server_feature_value(const char *feature, int *len) { - return parse_feature_value(server_capabilities, feature, len); + return parse_feature_value(&server_capabilities, feature, len); } int server_supports(const char *feature) diff --git a/connect.h b/connect.h index c41a685..47492e5 100644 --- a/connect.h +++ b/connect.h @@ -7,7 +7,7 @@ extern struct child_process *git_connect(int fd[2], const char *url, const char extern int finish_connect(struct child_process *conn); extern int git_connection_is_socket(struct child_process *conn); extern int server_supports(const char *feature); -extern int parse_feature_request(const char *features, const char *feature); +extern int parse_feature_request(struct string_list *, const char *feature); extern const char *server_feature_value(const char *feature, int *len_ret); extern int url_is_local_not_ssh(const char *url); diff --git a/upload-pack.c b/upload-pack.c index 5449ff7..2493964 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -531,7 +531,7 @@ error: } } -static void parse_features(const char *features) +static void parse_features(struct string_list *features) { if (parse_feature_request(features, "multi_ack_detailed")) multi_ack = 2; @@ -563,7 +563,10 @@ static void receive_needs(void) for (;;) { struct object *o; unsigned char sha1_buf[20]; - char *line = packet_read_line(0, NULL); + int pkt_len; + struct string_list list = STRING_LIST_INIT_DUP; + char *line = packet_read_line(0, &pkt_len); + reset_timeout(); if (!line) break; @@ -596,7 +599,9 @@ static void receive_needs(void) die("git upload-pack: protocol error, " "expected to get sha, not '%s'", line); - parse_features(line + 45); + from_space_separated_string(&list, xstrdup(line + 45)); + parse_features(&list); + string_list_clear(&list, 1); o = parse_object(sha1_buf); if (!o) -- 2.4.1.345.gab207b6.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html