When using server_supports() to match a given "feature" against the server capabilities, follow these rules: - "feature" must appear at the beginning of server_capabilities, or the byte immediately before the matched location in server_capabilities must be a SP; and - if "feature" does not end with an equal sign, it does not expect a value. The byte after the matched location in server_capabilities must be either the end of string or a SP. A feature that expects a value is checked with 'server_supports("feature=")' and the matched location in server_capabilities can be followed by anything (i.e. if at the end of string or a SP, it gets an empty string as the value, and otherwise it will get the stretch of bytes after the '=' up to the next SP). Given the server_capabilities string "foo=ab bar=froboz boz", this patch should make it behave as follows: server_supports("foo=") matches "foo=ab", returns "ab"; server_supports("ab") does not match anything; server_supports("bar") does not match anything; server_supports("boz") matches (and returns "boz"), without failing at the end of bar=froboz that comes earlier. Suggested-by: Junio C Hamano <gitster@xxxxxxxxx> Signed-off-by: Johan Herland <johan@xxxxxxxxxxx> --- cache.h | 2 +- connect.c | 30 +++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/cache.h b/cache.h index 009b365..1a9338f 100644 --- a/cache.h +++ b/cache.h @@ -995,7 +995,7 @@ struct extra_have_objects { unsigned char (*array)[20]; }; extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags, struct extra_have_objects *); -extern int server_supports(const char *feature); +extern const char *server_supports(const char *feature); extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path); diff --git a/connect.c b/connect.c index 2119c3f..3c0a706 100644 --- a/connect.c +++ b/connect.c @@ -8,6 +8,7 @@ #include "url.h" static char *server_capabilities; +static size_t server_capabilities_len; static int check_ref(const char *name, int len, unsigned int flags) { @@ -80,8 +81,16 @@ struct ref **get_remote_heads(int in, struct ref **list, name_len = strlen(name); if (len != name_len + 41) { + char *p; free(server_capabilities); server_capabilities = xstrdup(name + name_len + 1); + server_capabilities_len = strlen(server_capabilities); + /* split capabilities on SP */ + for (p = server_capabilities; + p < server_capabilities + server_capabilities_len; + p++) + if (*p == ' ') + *p = '\0'; } if (extra_have && @@ -102,10 +111,25 @@ struct ref **get_remote_heads(int in, struct ref **list, return list; } -int server_supports(const char *feature) +const char *server_supports(const char *feature) { - return server_capabilities && - strstr(server_capabilities, feature) != NULL; + const char *p = server_capabilities; + size_t feature_len = strlen(feature); + int need_value = feature[feature_len - 1] == '='; + + if (!server_capabilities) + return NULL; + + for (p = server_capabilities; + p < server_capabilities + server_capabilities_len; + p += strlen(p) + 1) { + if (need_value) { + if (!strncmp(p, feature, feature_len)) + return p + feature_len; + } else if (!strcmp(p, feature)) + return p; + } + return NULL; } int path_match(const char *path, int nr, char **match) -- 1.7.5.rc1.3.g4d7b -- 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